mirror of
https://github.com/Sylius/Sylius.git
synced 2026-07-14 09:02:12 +00:00
[Product Reviews API] - add API for product reviews
This commit is contained in:
parent
127382f6ee
commit
aca53a4b11
18 changed files with 1681 additions and 0 deletions
|
|
@ -20,7 +20,9 @@ The REST API Reference
|
|||
payments
|
||||
product_attributes
|
||||
product_options
|
||||
product_reviews
|
||||
product_variants
|
||||
product_reviews
|
||||
products
|
||||
promotion_coupons
|
||||
promotions
|
||||
|
|
|
|||
|
|
@ -14,7 +14,9 @@
|
|||
* :doc:`/api/payments`
|
||||
* :doc:`/api/product_attributes`
|
||||
* :doc:`/api/product_options`
|
||||
* :doc:`/api/product_reviews`
|
||||
* :doc:`/api/product_variants`
|
||||
* :doc:`/api/product_reviews`
|
||||
* :doc:`/api/products`
|
||||
* :doc:`/api/promotion_coupons`
|
||||
* :doc:`/api/promotions`
|
||||
|
|
|
|||
635
docs/api/product_reviews.rst
Normal file
635
docs/api/product_reviews.rst
Normal file
|
|
@ -0,0 +1,635 @@
|
|||
Product Reviews API
|
||||
====================
|
||||
|
||||
These endpoints will allow you to easily manage product reviews. Base URI is `/api/v1/products/{productCode}/reviews/`.
|
||||
|
||||
Product Reviews API response structure
|
||||
--------------------------------------
|
||||
|
||||
When you get a collection of resources, you will receive objects with the following fields:
|
||||
|
||||
+------------------+------------------------------------------------------------------------------------------------+
|
||||
| Field | Description |
|
||||
+==================+================================================================================================+
|
||||
| id | Id of product review |
|
||||
+------------------+------------------------------------------------------------------------------------------------+
|
||||
| title | Title of product review |
|
||||
+------------------+------------------------------------------------------------------------------------------------+
|
||||
| comment | Comment of product review |
|
||||
+------------------+------------------------------------------------------------------------------------------------+
|
||||
| author | Customer author for product review (This is customer that added the |
|
||||
| | product review; this will contain customer resource information) |
|
||||
+------------------+------------------------------------------------------------------------------------------------+
|
||||
| status | Status of product review (New, Accepted, Rejected) |
|
||||
+------------------+------------------------------------------------------------------------------------------------+
|
||||
| reviewSubject | This is the review subject for the product review. For this case of the product review, this |
|
||||
| | will contain a product resource |
|
||||
+------------------+------------------------------------------------------------------------------------------------+
|
||||
|
||||
.. note::
|
||||
|
||||
Read more about :doc:`ProductReviews docs</book/products/product_reviews>`.
|
||||
|
||||
Creating a Product Review
|
||||
--------------------------
|
||||
|
||||
To create a new product review you will need to call the ``/api/v1/products/{productCode}/reviews/`` endpoint with the ``POST`` method.
|
||||
|
||||
Definition
|
||||
^^^^^^^^^^
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
POST /api/v1/products/{productCode}/reviews/
|
||||
|
||||
+---------------+----------------+----------------------------------------------------------+
|
||||
| Parameter | Parameter type | Description |
|
||||
+===============+================+==========================================================+
|
||||
| Authorization | header | Token received during authentication |
|
||||
+---------------+----------------+----------------------------------------------------------+
|
||||
| productCode | url attribute | Code of product for which the reviews should be created |
|
||||
+---------------+----------------+----------------------------------------------------------+
|
||||
| title | request | Product review title |
|
||||
+---------------+----------------+----------------------------------------------------------+
|
||||
| comment | request | Product review comment |
|
||||
+---------------+----------------+----------------------------------------------------------+
|
||||
| rating | request | Product review rating (1..5) |
|
||||
+---------------+----------------+----------------------------------------------------------+
|
||||
| author | request | Product review author |
|
||||
+---------------+----------------+----------------------------------------------------------+
|
||||
|
||||
Example
|
||||
^^^^^^^
|
||||
|
||||
To create a new product review for the product with ``code = MUG-TH`` use the below method.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ curl http://demo.sylius.org/api/v1/products/MUG-TH/reviews/ \
|
||||
-H "Authorization: Bearer SampleToken" \
|
||||
-H "Content-Type: application/json" \
|
||||
-X POST \
|
||||
--data '
|
||||
{
|
||||
"title": "A product review",
|
||||
"rating": "3",
|
||||
"comment": "This is a comment review",
|
||||
"author": {
|
||||
"email": "test@example.com"
|
||||
}
|
||||
}
|
||||
'
|
||||
|
||||
Exemplary Response
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
STATUS: 201 Created
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"id": 4,
|
||||
"title": "A product review",
|
||||
"rating": 3,
|
||||
"comment": "This is a comment review",
|
||||
"author": {
|
||||
"id": 2,
|
||||
"email": "test@example.com",
|
||||
"emailCanonical": "test@example.com",
|
||||
"gender": "u",
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "/api/v1/customers/2"
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": "new",
|
||||
"reviewSubject": {
|
||||
"id": 1,
|
||||
"name": "MUG-TH",
|
||||
"code": "MUG-TH",
|
||||
"attributes": [],
|
||||
"options": [],
|
||||
"associations": [],
|
||||
"translations": []
|
||||
}
|
||||
}
|
||||
|
||||
.. warning::
|
||||
|
||||
If you try to create a resource without title, rating, comment or author, you will receive a ``400 Bad Request`` error.
|
||||
|
||||
Example
|
||||
^^^^^^^
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ curl http://demo.sylius.org/api/v1/products/MUG-TH/reviews/ \
|
||||
-H "Authorization: Bearer SampleToken" \
|
||||
-H "Content-Type: application/json" \
|
||||
-X POST
|
||||
|
||||
Exemplary Response
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
STATUS: 400 Bad Request
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"code": 400,
|
||||
"message": "Validation Failed",
|
||||
"errors": {
|
||||
"children": {
|
||||
"rating": {
|
||||
"errors": [
|
||||
"You must check review rating."
|
||||
],
|
||||
"children": [
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
]
|
||||
},
|
||||
"title": {
|
||||
"errors": [
|
||||
"Review title should not be blank."
|
||||
]
|
||||
},
|
||||
"comment": {
|
||||
"errors": [
|
||||
"Review comment should not be blank."
|
||||
]
|
||||
},
|
||||
"author": {
|
||||
"children": {
|
||||
"email": {
|
||||
"errors": [
|
||||
"Please enter your email."
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Getting a Single Product Review
|
||||
--------------------------------
|
||||
|
||||
To retrieve the details of a product review you will need to call the ``/api/v1/products/{productCode}/reviews/{id}`` endpoint with the ``GET`` method.
|
||||
|
||||
Definition
|
||||
^^^^^^^^^^
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
GET /api/v1/products/{productCode}/reviews/{id}
|
||||
|
||||
+---------------+----------------+-----------------------------------------------------------+
|
||||
| Parameter | Parameter type | Description |
|
||||
+===============+================+===========================================================+
|
||||
| Authorization | header | Token received during authentication |
|
||||
+---------------+----------------+-----------------------------------------------------------+
|
||||
| id | url attribute | Identifier of the product review |
|
||||
+---------------+----------------+-----------------------------------------------------------+
|
||||
| productCode | url attribute | Code of product for which the reviews should be displayed |
|
||||
+---------------+----------------+-----------------------------------------------------------+
|
||||
|
||||
Example
|
||||
^^^^^^^
|
||||
|
||||
To see the details of the product review with ``id = 1``, which is defined for the product with ``code = MUG-TH`` use the below method.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ curl http://demo.sylius.org/api/v1/products/MUG-TH/reviews/1 \
|
||||
-H "Authorization: Bearer SampleToken" \
|
||||
-H "Accept: application/json"
|
||||
|
||||
Exemplary Response
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
STATUS: 200 OK
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"title": "A product review",
|
||||
"rating": 3,
|
||||
"comment": "This is a comment review",
|
||||
"author": {
|
||||
"id": 2,
|
||||
"email": "test@example.com",
|
||||
"emailCanonical": "test@example.com",
|
||||
"gender": "u",
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "/api/v1/customers/2"
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": "new",
|
||||
"reviewSubject": {
|
||||
"id": 1,
|
||||
"name": "MUG-TH",
|
||||
"code": "MUG-TH",
|
||||
"attributes": [],
|
||||
"options": [],
|
||||
"associations": [],
|
||||
"translations": []
|
||||
}
|
||||
}
|
||||
|
||||
Collection of Product Reviews
|
||||
------------------------------
|
||||
|
||||
To retrieve a paginated list of reviews for a selected product you will need to call the ``/api/v1/products/{productCode}/reviews/`` endpoint with the ``GET`` method.
|
||||
|
||||
Definition
|
||||
^^^^^^^^^^
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
GET /api/v1/products/{productCode}/reviews/
|
||||
|
||||
+-------------------------------------+----------------+------------------------------------------------------------+
|
||||
| Parameter | Parameter type | Description |
|
||||
+=====================================+================+============================================================+
|
||||
| Authorization | header | Token received during authentication |
|
||||
+-------------------------------------+----------------+------------------------------------------------------------+
|
||||
| productCode | url attribute | Code of product for which the reviews should be displayed |
|
||||
+-------------------------------------+----------------+------------------------------------------------------------+
|
||||
| limit | query | *(optional)* Number of items to display per page, |
|
||||
| | | by default = 10 |
|
||||
+-------------------------------------+----------------+------------------------------------------------------------+
|
||||
| sorting['nameOfField']['direction'] | query | *(optional)* Field and direction of sorting, |
|
||||
| | | by default 'desc' and 'createdAt' |
|
||||
+-------------------------------------+----------------+------------------------------------------------------------+
|
||||
|
||||
Example
|
||||
^^^^^^^
|
||||
|
||||
To see the first page of all product reviews for the product with ``code = MUG-TH`` use the method below.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ curl http://demo.sylius.org/api/v1/products/MUG-TH/reviews/ \
|
||||
-H "Authorization: Bearer SampleToken" \
|
||||
-H "Accept: application/json"
|
||||
|
||||
Exemplary Response
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
STATUS: 200 OK
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"page": 1,
|
||||
"limit": 10,
|
||||
"pages": 1,
|
||||
"total": 3,
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "/api/v1/products/MUG-TH/reviews/?page=1&limit=10"
|
||||
},
|
||||
"first": {
|
||||
"href": "/api/v1/products/MUG-TH/reviews/?page=1&limit=10"
|
||||
},
|
||||
"last": {
|
||||
"href": "/api/v1/products/MUG-TH/reviews/?page=1&limit=10"
|
||||
}
|
||||
},
|
||||
"_embedded": {
|
||||
"items": [
|
||||
{
|
||||
"id": 4,
|
||||
"title": "A product review",
|
||||
"rating": 3,
|
||||
"comment": "This is a comment review",
|
||||
"author": {
|
||||
"id": 2,
|
||||
"email": "test@example.com",
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "/api/v1/customers/2"
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": "new",
|
||||
"reviewSubject": {
|
||||
"id": 1,
|
||||
"name": "MUG-TH",
|
||||
"code": "MUG-TH",
|
||||
"options": [],
|
||||
"averageRating": 0,
|
||||
"images": [],
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "/api/v1/products/MUG-TH"
|
||||
}
|
||||
}
|
||||
},
|
||||
"createdAt": "2017-10-04T20:19:06+03:00",
|
||||
"updatedAt": "2017-10-04T20:19:06+03:00"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"title": "A product review 2",
|
||||
"rating": 5,
|
||||
"comment": "This is a comment review 2",
|
||||
"author": {
|
||||
"id": 1,
|
||||
"email": "onetest@example.com",
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "/api/v1/customers/1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": "new",
|
||||
"reviewSubject": {
|
||||
"id": 1,
|
||||
"name": "MUG-TH",
|
||||
"code": "MUG-TH",
|
||||
"options": [],
|
||||
"averageRating": 0,
|
||||
"images": [],
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "/api/v1/products/MUG-TH"
|
||||
}
|
||||
}
|
||||
},
|
||||
"createdAt": "2017-10-04T18:23:56+03:00",
|
||||
"updatedAt": "2017-10-04T18:44:08+03:00"
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"title": "Test review 3",
|
||||
"rating": 4,
|
||||
"comment": "This is a comment review 3",
|
||||
"author": {
|
||||
"id": 1,
|
||||
"email": "onetest@example.com",
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "/api/v1/customers/1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": "accepted",
|
||||
"reviewSubject": {
|
||||
"id": 1,
|
||||
"name": "MUG-TH",
|
||||
"code": "MUG-TH",
|
||||
"options": [],
|
||||
"averageRating": 0,
|
||||
"images": [],
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "/api/v1/products/MUG-TH"
|
||||
}
|
||||
}
|
||||
},
|
||||
"createdAt": "2017-10-03T23:53:24+03:00",
|
||||
"updatedAt": "2017-10-04T19:18:00+03:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Updating Product Review
|
||||
------------------------
|
||||
|
||||
To fully update a product review you will need to call the ``/api/v1/products/{productCode}/reviews/{id}`` endpoint with the ``PUT`` method.
|
||||
|
||||
Definition
|
||||
^^^^^^^^^^
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
PUT /api/v1/products/{productCode}/reviews/{id}
|
||||
|
||||
+---------------+----------------+----------------------------------------------------------+
|
||||
| Parameter | Parameter type | Description |
|
||||
+===============+================+==========================================================+
|
||||
| Authorization | header | Token received during authentication |
|
||||
+---------------+----------------+----------------------------------------------------------+
|
||||
| id | url attribute | Product review id |
|
||||
+---------------+----------------+----------------------------------------------------------+
|
||||
| productCode | url attribute | Code of product for which the reviews should be updated |
|
||||
+---------------+----------------+----------------------------------------------------------+
|
||||
| title | request | Product review title |
|
||||
+---------------+----------------+----------------------------------------------------------+
|
||||
| comment | request | Product review comment |
|
||||
+---------------+----------------+----------------------------------------------------------+
|
||||
| rating | request | Product review rating (1..5) |
|
||||
+---------------+----------------+----------------------------------------------------------+
|
||||
|
||||
Example
|
||||
^^^^^^^
|
||||
|
||||
To fully update the product review with ``id = 1`` for the product with ``code = MUG-TH`` use the below method.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ curl http://demo.sylius.org/api/v1/products/MUG-TH/reviews/1 \
|
||||
-H "Authorization: Bearer SampleToken" \
|
||||
-H "Content-Type: application/json" \
|
||||
-X PUT \
|
||||
--data '
|
||||
{
|
||||
"title": "A product review",
|
||||
"rating": "4",
|
||||
"comment": "This is a comment for review"
|
||||
}
|
||||
'
|
||||
|
||||
Exemplary Response
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
STATUS: 204 No Content
|
||||
|
||||
To partially update a product review you will need to call the ``/api/v1/products/{productCode}/reviews/{id}`` endpoint with the ``PATCH`` method.
|
||||
|
||||
Definition
|
||||
^^^^^^^^^^
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
PATCH /api/v1/products/{productCode}/reviews/{id}
|
||||
|
||||
+------------------------------------+----------------+-----------------------------------------------------------+
|
||||
| Parameter | Parameter type | Description |
|
||||
+====================================+================+===========================================================+
|
||||
| Authorization | header | Token received during authentication |
|
||||
+------------------------------------+----------------+-----------------------------------------------------------+
|
||||
| id | url attribute | Identifier of the product review |
|
||||
+------------------------------------+----------------+-----------------------------------------------------------+
|
||||
| productCode | url attribute | Code of product for which the reviews should be updated |
|
||||
+------------------------------------+----------------+-----------------------------------------------------------+
|
||||
| title | request | Product review title |
|
||||
+------------------------------------+----------------+-----------------------------------------------------------+
|
||||
|
||||
Example
|
||||
^^^^^^^
|
||||
|
||||
To partially update the product review with ``id = 1`` for the product with ``code = MUG-TH`` use the below method.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ curl http://demo.sylius.org/api/v1/products/MUG-TH/reviews/1 \
|
||||
-H "Authorization: Bearer SampleToken" \
|
||||
-H "Content-Type: application/json" \
|
||||
-X PATCH \
|
||||
--data '
|
||||
{
|
||||
"title": "This is an another title for the review"
|
||||
}
|
||||
'
|
||||
|
||||
Exemplary Response
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
STATUS: 204 No Content
|
||||
|
||||
Deleting a Product Review
|
||||
--------------------------
|
||||
|
||||
To delete a product review you will need to call the ``/api/v1/products/{productCode}/reviews/{id}`` endpoint with the ``DELETE`` method.
|
||||
|
||||
Definition
|
||||
^^^^^^^^^^
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
DELETE /api/v1/products/{productCode}/reviews/{id}
|
||||
|
||||
+---------------+----------------+-----------------------------------------------------------+
|
||||
| Parameter | Parameter type | Description |
|
||||
+===============+================+===========================================================+
|
||||
| Authorization | header | Token received during authentication |
|
||||
+---------------+----------------+-----------------------------------------------------------+
|
||||
| id | url attribute | Identifier of the product review |
|
||||
+---------------+----------------+-----------------------------------------------------------+
|
||||
| productCode | url attribute | Code of product for which the reviews should be deleted |
|
||||
+---------------+----------------+-----------------------------------------------------------+
|
||||
|
||||
Example
|
||||
^^^^^^^
|
||||
|
||||
To delete the product review with ``id = 1`` from the product with ``code = MUG-TH`` use the below method.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ curl http://demo.sylius.org/api/v1/products/MUG-TH/reviews/1 \
|
||||
-H "Authorization: Bearer SampleToken" \
|
||||
-H "Accept: application/json" \
|
||||
-X DELETE
|
||||
|
||||
Exemplary Response
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
STATUS: 204 No Content
|
||||
|
||||
Accept a Product Review
|
||||
--------------------------
|
||||
|
||||
To accept a product review you will need to call the ``/api/v1/products/{productCode}/reviews/{id}/accept`` endpoint with the ``POST``, ``PUT`` or ``PATCH`` method.
|
||||
|
||||
Definition
|
||||
^^^^^^^^^^
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
POST /api/v1/products/{productCode}/reviews/{id}/accept
|
||||
|
||||
+---------------+----------------+-----------------------------------------------------------+
|
||||
| Parameter | Parameter type | Description |
|
||||
+===============+================+===========================================================+
|
||||
| Authorization | header | Token received during authentication |
|
||||
+---------------+----------------+-----------------------------------------------------------+
|
||||
| id | url attribute | Identifier of the product review |
|
||||
+---------------+----------------+-----------------------------------------------------------+
|
||||
| productCode | url attribute | Code of product for which the reviews should be accepted |
|
||||
+---------------+----------------+-----------------------------------------------------------+
|
||||
|
||||
Example
|
||||
^^^^^^^
|
||||
|
||||
To accept the product review with ``id = 1`` from the product with ``code = MUG-TH`` use the below method.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ curl http://demo.sylius.org/api/v1/products/MUG-TH/reviews/1/accept \
|
||||
-H "Authorization: Bearer SampleToken" \
|
||||
-H "Accept: application/json" \
|
||||
-X POST
|
||||
|
||||
Exemplary Response
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
STATUS: 204 No Content
|
||||
|
||||
Reject a Product Review
|
||||
--------------------------
|
||||
|
||||
To reject a product review you will need to call the ``/api/v1/products/{productCode}/reviews/{id}/reject`` endpoint with the ``POST``, ``PUT`` or ``PATCH`` method.
|
||||
|
||||
Definition
|
||||
^^^^^^^^^^
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
POST /api/v1/products/{productCode}/reviews/{id}/reject
|
||||
|
||||
+---------------+----------------+-----------------------------------------------------------+
|
||||
| Parameter | Parameter type | Description |
|
||||
+===============+================+===========================================================+
|
||||
| Authorization | header | Token received during authentication |
|
||||
+---------------+----------------+-----------------------------------------------------------+
|
||||
| id | url attribute | Identifier of the product review |
|
||||
+---------------+----------------+-----------------------------------------------------------+
|
||||
| productCode | url attribute | Code of product for which the reviews should be rejected |
|
||||
+---------------+----------------+-----------------------------------------------------------+
|
||||
|
||||
Example
|
||||
^^^^^^^
|
||||
|
||||
To reject the product review with ``id = 1`` from the product with ``code = MUG-TH`` use the below method.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ curl http://demo.sylius.org/api/v1/products/MUG-TH/reviews/1/reject \
|
||||
-H "Authorization: Bearer SampleToken" \
|
||||
-H "Accept: application/json" \
|
||||
-X POST
|
||||
|
||||
Exemplary Response
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
STATUS: 204 No Content
|
||||
|
||||
|
|
@ -7,6 +7,7 @@ imports:
|
|||
- { resource: "@SyliusAdminApiBundle/Resources/config/grids/cart.yml" }
|
||||
- { resource: "@SyliusAdminApiBundle/Resources/config/grids/payments.yml" }
|
||||
- { resource: "@SyliusAdminApiBundle/Resources/config/grids/product.yml" }
|
||||
- { resource: "@SyliusAdminApiBundle/Resources/config/grids/product_review.yml" }
|
||||
- { resource: "@SyliusAdminApiBundle/Resources/config/grids/product_variant.yml" }
|
||||
- { resource: "@SyliusAdminApiBundle/Resources/config/grids/promotion.yml" }
|
||||
- { resource: "@SyliusAdminApiBundle/Resources/config/grids/shipments.yml" }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
# This file is part of the Sylius package.
|
||||
# (c) Paweł Jędrzejewski
|
||||
|
||||
sylius_grid:
|
||||
grids:
|
||||
sylius_admin_api_product_review:
|
||||
driver:
|
||||
name: doctrine/orm
|
||||
options:
|
||||
class: "%sylius.model.product_review.class%"
|
||||
repository:
|
||||
method: createQueryBuilderByProductCode
|
||||
arguments: ["%locale%", $productCode]
|
||||
sorting:
|
||||
date: desc
|
||||
fields:
|
||||
date:
|
||||
type: datetime
|
||||
label: sylius.ui.date
|
||||
path: createdAt
|
||||
sortable: createdAt
|
||||
options:
|
||||
format: d-m-Y H:i:s
|
||||
title:
|
||||
type: string
|
||||
label: sylius.ui.title
|
||||
sortable: ~
|
||||
rating:
|
||||
type: string
|
||||
label: sylius.ui.rating
|
||||
sortable: ~
|
||||
status:
|
||||
type: twig
|
||||
label: sylius.ui.status
|
||||
reviewSubject:
|
||||
type: string
|
||||
label: sylius.ui.product
|
||||
author:
|
||||
type: string
|
||||
label: sylius.ui.customer
|
||||
filters:
|
||||
title:
|
||||
type: string
|
||||
label: sylius.ui.title
|
||||
|
|
@ -60,6 +60,10 @@ sylius_api_product_association_type:
|
|||
sylius_api_product_option:
|
||||
resource: "@SyliusAdminApiBundle/Resources/config/routing/product_option.yml"
|
||||
|
||||
sylius_api_product_review:
|
||||
resource: "@SyliusAdminApiBundle/Resources/config/routing/product_review.yml"
|
||||
prefix: /products/{productCode}
|
||||
|
||||
sylius_api_product_taxon_position:
|
||||
resource: "@SyliusAdminApiBundle/Resources/config/routing/product_taxon_position.yml"
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,90 @@
|
|||
# This file is part of the Sylius package.
|
||||
# (c) Paweł Jędrzejewski
|
||||
|
||||
sylius_admin_api_product_review:
|
||||
resource: |
|
||||
path: 'reviews'
|
||||
grid: sylius_admin_api_product_review
|
||||
alias: sylius.product_review
|
||||
section: admin_api
|
||||
only: ['index']
|
||||
serialization_version: $version
|
||||
vars:
|
||||
route:
|
||||
parameters:
|
||||
productCode: $productCode
|
||||
type: sylius.resource_api
|
||||
|
||||
sylius_admin_api_product_review_create:
|
||||
path: /reviews/
|
||||
methods: [POST]
|
||||
defaults:
|
||||
_controller: sylius.controller.product_review:createAction
|
||||
_sylius:
|
||||
serialization_groups: [Default, Detailed]
|
||||
serialization_version: $version
|
||||
section: admin_api
|
||||
form: Sylius\Bundle\CoreBundle\Form\Type\Product\ProductReviewType
|
||||
factory:
|
||||
method: createForSubject
|
||||
arguments:
|
||||
- expr:notFoundOnNull(service('sylius.repository.product').findOneByCode($productCode))
|
||||
|
||||
sylius_admin_api_product_review_update:
|
||||
path: /reviews/{id}
|
||||
methods: [PUT, PATCH]
|
||||
defaults:
|
||||
_controller: sylius.controller.product_review:updateAction
|
||||
_sylius:
|
||||
serialization_version: $version
|
||||
section: admin_api
|
||||
form: Sylius\Bundle\CoreBundle\Form\Type\Product\ProductReviewType
|
||||
repository:
|
||||
method: findOneByIdAndProductCode
|
||||
arguments: [$id, $productCode]
|
||||
|
||||
sylius_admin_api_product_review_delete:
|
||||
path: /reviews/{id}
|
||||
methods: [DELETE]
|
||||
defaults:
|
||||
_controller: sylius.controller.product_review:deleteAction
|
||||
_sylius:
|
||||
serialization_version: $version
|
||||
section: admin_api
|
||||
repository:
|
||||
method: findOneByIdAndProductCode
|
||||
arguments: [$id, $productCode]
|
||||
csrf_protection: false
|
||||
|
||||
sylius_admin_api_product_review_show:
|
||||
path: /reviews/{code}
|
||||
methods: [GET]
|
||||
defaults:
|
||||
_controller: sylius.controller.product_review:showAction
|
||||
_sylius:
|
||||
serialization_version: $version
|
||||
section: admin_api
|
||||
serialization_groups: [Default, Detailed]
|
||||
repository:
|
||||
method: findOneByIdAndProductCode
|
||||
arguments: [$code, $productCode]
|
||||
|
||||
sylius_admin_api_product_review_accept:
|
||||
path: /reviews/{id}/accept
|
||||
methods: [POST, PUT, PATCH]
|
||||
defaults:
|
||||
_controller: sylius.controller.product_review:applyStateMachineTransitionAction
|
||||
_sylius:
|
||||
state_machine:
|
||||
graph: sylius_product_review
|
||||
transition: accept
|
||||
|
||||
sylius_admin_api_product_review_reject:
|
||||
path: /reviews/{id}/reject
|
||||
methods: [POST, PUT, PATCH]
|
||||
defaults:
|
||||
_controller: sylius.controller.product_review:applyStateMachineTransitionAction
|
||||
_sylius:
|
||||
state_machine:
|
||||
graph: sylius_product_review
|
||||
transition: reject
|
||||
|
|
@ -13,6 +13,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace Sylius\Bundle\CoreBundle\Doctrine\ORM;
|
||||
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Sylius\Bundle\ResourceBundle\Doctrine\ORM\EntityRepository;
|
||||
use Sylius\Component\Core\Model\ChannelInterface;
|
||||
use Sylius\Component\Core\Repository\ProductReviewRepositoryInterface;
|
||||
|
|
@ -60,4 +61,35 @@ class ProductReviewRepository extends EntityRepository implements ProductReviewR
|
|||
->getResult()
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function createQueryBuilderByProductCode(string $locale, string $productCode): QueryBuilder
|
||||
{
|
||||
return $this->createQueryBuilder('o')
|
||||
->innerJoin('o.reviewSubject', 'product')
|
||||
->innerJoin('product.translations', 'translation')
|
||||
->andWhere('translation.locale = :locale')
|
||||
->andWhere('product.code = :productCode')
|
||||
->setParameter('locale', $locale)
|
||||
->setParameter('productCode', $productCode)
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function findOneByIdAndProductCode($id, string $productCode): ?ReviewInterface
|
||||
{
|
||||
return $this->createQueryBuilder('o')
|
||||
->innerJoin('o.reviewSubject', 'product')
|
||||
->andWhere('product.code = :productCode')
|
||||
->andWhere('o.id = :id')
|
||||
->setParameter('productCode', $productCode)
|
||||
->setParameter('id', $id)
|
||||
->getQuery()
|
||||
->getOneOrNullResult()
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace Sylius\Component\Core\Repository;
|
||||
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Sylius\Component\Core\Model\ChannelInterface;
|
||||
use Sylius\Component\Resource\Repository\RepositoryInterface;
|
||||
use Sylius\Component\Review\Model\ReviewInterface;
|
||||
|
|
@ -38,4 +39,20 @@ interface ProductReviewRepositoryInterface extends RepositoryInterface
|
|||
* @return array|ReviewInterface[]
|
||||
*/
|
||||
public function findAcceptedByProductSlugAndChannel(string $slug, string $locale, ChannelInterface $channel): array;
|
||||
|
||||
/**
|
||||
* @param string $locale
|
||||
* @param string $productCode
|
||||
*
|
||||
* @return QueryBuilder
|
||||
*/
|
||||
public function createQueryBuilderByProductCode(string $locale, string $productCode): QueryBuilder;
|
||||
|
||||
/**
|
||||
* @param mixed $id
|
||||
* @param string $productCode
|
||||
*
|
||||
* @return ReviewInterface|null
|
||||
*/
|
||||
public function findOneByIdAndProductCode($id, string $productCode): ?ReviewInterface;
|
||||
}
|
||||
|
|
|
|||
359
tests/Controller/ProductReviewApiTest.php
Normal file
359
tests/Controller/ProductReviewApiTest.php
Normal file
|
|
@ -0,0 +1,359 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Paweł Jędrzejewski
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Tests\Controller;
|
||||
|
||||
use Lakion\ApiTestCase\JsonApiTestCase;
|
||||
use Sylius\Component\Core\Model\ProductInterface;
|
||||
use Sylius\Component\Review\Model\ReviewInterface;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* @author Paul Stoica <paul.stoica18@gmail.com>
|
||||
*/
|
||||
final class ProductReviewApiTest extends JsonApiTestCase
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private static $authorizedHeaderWithContentType = [
|
||||
'HTTP_Authorization' => 'Bearer SampleTokenNjZkNjY2MDEwMTAzMDkxMGE0OTlhYzU3NzYyMTE0ZGQ3ODcyMDAwM2EwMDZjNDI5NDlhMDdlMQ',
|
||||
'CONTENT_TYPE' => 'application/json',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private static $authorizedHeaderWithAccept = [
|
||||
'HTTP_Authorization' => 'Bearer SampleTokenNjZkNjY2MDEwMTAzMDkxMGE0OTlhYzU3NzYyMTE0ZGQ3ODcyMDAwM2EwMDZjNDI5NDlhMDdlMQ',
|
||||
'ACCEPT' => 'application/json',
|
||||
];
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_does_not_allow_to_show_product_review_list_when_access_is_denied()
|
||||
{
|
||||
$productReviewsData = $this->loadFixturesFromFile('resources/product_reviews.yml');
|
||||
|
||||
/** @var ProductInterface $product */
|
||||
$product = $productReviewsData['product1'];
|
||||
|
||||
$this->client->request('GET', $this->getReviewListUrl($product));
|
||||
$response = $this->client->getResponse();
|
||||
|
||||
$this->assertResponse($response, 'authentication/access_denied_response', Response::HTTP_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_does_not_allow_to_show_product_review_when_it_does_not_exist()
|
||||
{
|
||||
$productReviewsData = $this->loadFixturesFromFile('resources/product_reviews.yml');
|
||||
$this->loadFixturesFromFile('authentication/api_administrator.yml');
|
||||
|
||||
/** @var ProductInterface $product */
|
||||
$product = $productReviewsData['product1'];
|
||||
|
||||
$this->client->request('GET', $this->getReviewListUrl($product) . '0', [], [], static::$authorizedHeaderWithAccept);
|
||||
$response = $this->client->getResponse();
|
||||
|
||||
$this->assertResponse($response, 'error/not_found_response', Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_allows_showing_product_review()
|
||||
{
|
||||
$this->loadFixturesFromFile('authentication/api_administrator.yml');
|
||||
$productReviewsData = $this->loadFixturesFromFile('resources/product_reviews.yml');
|
||||
|
||||
/** @var ProductInterface $product */
|
||||
$product = $productReviewsData['product1'];
|
||||
|
||||
/** @var ReviewInterface $productReview */
|
||||
$productReview = $productReviewsData['productReview1'];
|
||||
|
||||
$this->client->request('GET', $this->getReviewUrl($product, $productReview), [], [], static::$authorizedHeaderWithAccept);
|
||||
$response = $this->client->getResponse();
|
||||
|
||||
$this->assertResponse($response, 'product_review/show_response', Response::HTTP_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_allows_indexing_product_reviews()
|
||||
{
|
||||
$this->loadFixturesFromFile('authentication/api_administrator.yml');
|
||||
$productReviewsData = $this->loadFixturesFromFile('resources/product_reviews.yml');
|
||||
|
||||
/** @var ProductInterface $product */
|
||||
$product = $productReviewsData['product1'];
|
||||
|
||||
$this->client->request('GET', $this->getReviewListUrl($product), [], [], static::$authorizedHeaderWithAccept);
|
||||
$response = $this->client->getResponse();
|
||||
|
||||
$this->assertResponse($response, 'product_review/index_response', Response::HTTP_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_allows_create_product_review()
|
||||
{
|
||||
$this->loadFixturesFromFile('authentication/api_administrator.yml');
|
||||
$productReviewsData = $this->loadFixturesFromFile('resources/product_reviews.yml');
|
||||
|
||||
/** @var ProductInterface $product */
|
||||
$product = $productReviewsData['product1'];
|
||||
|
||||
$data =
|
||||
<<<EOT
|
||||
{
|
||||
"title": "J_REVIEW",
|
||||
"rating": "3",
|
||||
"comment": "J_REVIEW_COMMENT",
|
||||
"author": {
|
||||
"email": "j@example.com"
|
||||
}
|
||||
}
|
||||
EOT;
|
||||
|
||||
$this->client->request('POST', $this->getReviewListUrl($product), [], [], static::$authorizedHeaderWithContentType, $data);
|
||||
$response = $this->client->getResponse();
|
||||
|
||||
$this->assertResponse($response, 'product_review/create_response', Response::HTTP_CREATED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_does_not_allow_to_create_product_review_without_required_fields()
|
||||
{
|
||||
$this->loadFixturesFromFile('authentication/api_administrator.yml');
|
||||
$productReviewsData = $this->loadFixturesFromFile('resources/product_reviews.yml');
|
||||
|
||||
/** @var ProductInterface $product */
|
||||
$product = $productReviewsData['product1'];
|
||||
|
||||
$this->client->request('POST', $this->getReviewListUrl($product), [], [], static::$authorizedHeaderWithContentType, []);
|
||||
$response = $this->client->getResponse();
|
||||
|
||||
$this->assertResponse($response, 'product_review/create_validation_fail_response', Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_does_not_allow_delete_product_review_if_it_does_not_exist()
|
||||
{
|
||||
$this->loadFixturesFromFile('authentication/api_administrator.yml');
|
||||
$productReviewsData = $this->loadFixturesFromFile('resources/product_reviews.yml');
|
||||
|
||||
/** @var ProductInterface $product */
|
||||
$product = $productReviewsData['product1'];
|
||||
|
||||
$this->client->request('DELETE', $this->getReviewListUrl($product) . '0', [], [], static::$authorizedHeaderWithAccept);
|
||||
$response = $this->client->getResponse();
|
||||
|
||||
$this->assertResponse($response, 'error/not_found_response', Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_allows_delete_product_review()
|
||||
{
|
||||
$this->loadFixturesFromFile('authentication/api_administrator.yml');
|
||||
$productReviewsData = $this->loadFixturesFromFile('resources/product_reviews.yml');
|
||||
|
||||
/** @var ProductInterface $product */
|
||||
$product = $productReviewsData['product1'];
|
||||
|
||||
/** @var ReviewInterface $productReview */
|
||||
$productReview = $productReviewsData['productReview1'];
|
||||
|
||||
$this->client->request('DELETE', $this->getReviewUrl($product, $productReview), [], [], static::$authorizedHeaderWithContentType, []);
|
||||
|
||||
$response = $this->client->getResponse();
|
||||
$this->assertResponseCode($response, Response::HTTP_NO_CONTENT);
|
||||
|
||||
/** @var ProductInterface $product */
|
||||
$product = $productReviewsData['product1'];
|
||||
|
||||
$this->client->request('GET', $this->getReviewUrl($product, $productReview), [], [], static::$authorizedHeaderWithAccept);
|
||||
$response = $this->client->getResponse();
|
||||
|
||||
$this->assertResponse($response, 'error/not_found_response', Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_allows_updating_information_about_product_review()
|
||||
{
|
||||
$this->loadFixturesFromFile('authentication/api_administrator.yml');
|
||||
$productReviewsData = $this->loadFixturesFromFile('resources/product_reviews.yml');
|
||||
|
||||
/** @var ProductInterface $product */
|
||||
$product = $productReviewsData['product1'];
|
||||
|
||||
/** @var ReviewInterface $productReview */
|
||||
$productReview = $productReviewsData['productReview1'];
|
||||
|
||||
$data =
|
||||
<<<EOT
|
||||
{
|
||||
"title": "NEW_REVIEW_TITLE",
|
||||
"rating": "1",
|
||||
"comment": "NEW_REVIEW_COMMENT"
|
||||
}
|
||||
EOT;
|
||||
$this->client->request('PUT', $this->getReviewUrl($product, $productReview), [], [], static::$authorizedHeaderWithContentType, $data);
|
||||
$response = $this->client->getResponse();
|
||||
|
||||
$this->assertResponseCode($response, Response::HTTP_NO_CONTENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_allows_updating_partial_information_about_product_review()
|
||||
{
|
||||
$this->loadFixturesFromFile('authentication/api_administrator.yml');
|
||||
$productReviewsData = $this->loadFixturesFromFile('resources/product_reviews.yml');
|
||||
$this->loadFixturesFromFile('resources/locales.yml');
|
||||
|
||||
/** @var ProductInterface $product */
|
||||
$product = $productReviewsData['product1'];
|
||||
|
||||
/** @var ReviewInterface $productReview */
|
||||
$productReview = $productReviewsData['productReview1'];
|
||||
|
||||
$data =
|
||||
<<<EOT
|
||||
{
|
||||
"comment": "A_NEW_REVIEW_COMMENT"
|
||||
}
|
||||
EOT;
|
||||
|
||||
$this->client->request('PATCH', $this->getReviewUrl($product, $productReview), [], [], static::$authorizedHeaderWithContentType, $data);
|
||||
$response = $this->client->getResponse();
|
||||
|
||||
$this->assertResponseCode($response, Response::HTTP_NO_CONTENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_allows_accept_product_review()
|
||||
{
|
||||
$this->loadFixturesFromFile('authentication/api_administrator.yml');
|
||||
$productReviewsData = $this->loadFixturesFromFile('resources/product_reviews.yml');
|
||||
|
||||
/** @var ProductInterface $product */
|
||||
$product = $productReviewsData['product1'];
|
||||
|
||||
/** @var ReviewInterface $productReview */
|
||||
$productReview = $productReviewsData['productReview1'];
|
||||
|
||||
$this->client->request('PATCH', $this->getReviewUrl($product, $productReview) . '/accept', [], [], static::$authorizedHeaderWithAccept);
|
||||
$response = $this->client->getResponse();
|
||||
|
||||
$this->assertResponse($response, 'product_review/accept_response', Response::HTTP_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_does_not_allows_accept_product_review_if_it_has_not_new_status()
|
||||
{
|
||||
$this->loadFixturesFromFile('authentication/api_administrator.yml');
|
||||
$productReviewsData = $this->loadFixturesFromFile('resources/product_reviews.yml');
|
||||
|
||||
/** @var ProductInterface $product */
|
||||
$product = $productReviewsData['product1'];
|
||||
|
||||
/** @var ReviewInterface $productReview */
|
||||
$productReview = $productReviewsData['productReview3'];
|
||||
|
||||
$this->client->request('POST', $this->getReviewUrl($product, $productReview) . '/accept', [], [], static::$authorizedHeaderWithAccept);
|
||||
$response = $this->client->getResponse();
|
||||
|
||||
$this->assertResponse($response, 'product_review/change_status_fail_response', Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_allows_reject_product_review()
|
||||
{
|
||||
$this->loadFixturesFromFile('authentication/api_administrator.yml');
|
||||
$productReviewsData = $this->loadFixturesFromFile('resources/product_reviews.yml');
|
||||
|
||||
/** @var ProductInterface $product */
|
||||
$product = $productReviewsData['product1'];
|
||||
|
||||
/** @var ReviewInterface $productReview */
|
||||
$productReview = $productReviewsData['productReview1'];
|
||||
|
||||
$this->client->request('PATCH', $this->getReviewUrl($product, $productReview) . '/reject', [], [], static::$authorizedHeaderWithAccept);
|
||||
$response = $this->client->getResponse();
|
||||
|
||||
$this->assertResponse($response, 'product_review/reject_response', Response::HTTP_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_does_not_allows_reject_product_review_if_it_has_not_new_status()
|
||||
{
|
||||
$this->loadFixturesFromFile('authentication/api_administrator.yml');
|
||||
$productReviewsData = $this->loadFixturesFromFile('resources/product_reviews.yml');
|
||||
|
||||
/** @var ProductInterface $product */
|
||||
$product = $productReviewsData['product1'];
|
||||
|
||||
/** @var ReviewInterface $productReview */
|
||||
$productReview = $productReviewsData['productReview3'];
|
||||
|
||||
$this->client->request('POST', $this->getReviewUrl($product, $productReview) . '/accept', [], [], static::$authorizedHeaderWithAccept);
|
||||
$response = $this->client->getResponse();
|
||||
|
||||
$this->assertResponse($response, 'product_review/change_status_fail_response', Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ProductInterface $product
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getReviewListUrl(ProductInterface $product): string
|
||||
{
|
||||
return sprintf('/api/v1/products/%s/reviews/', $product->getCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ProductInterface $product
|
||||
* @param ReviewInterface $productReview
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getReviewUrl(ProductInterface $product, ReviewInterface $productReview): string
|
||||
{
|
||||
return sprintf('%s%s', $this->getReviewListUrl($product), $productReview->getId());
|
||||
}
|
||||
}
|
||||
44
tests/DataFixtures/ORM/resources/product_reviews.yml
Normal file
44
tests/DataFixtures/ORM/resources/product_reviews.yml
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
Sylius\Component\Core\Model\Customer:
|
||||
customer_example1:
|
||||
firstName: Example
|
||||
lastName: Queen
|
||||
email: example.queen@example.com
|
||||
emailCanonical: example.queen@example.com
|
||||
customer_example2:
|
||||
firstName: Example
|
||||
lastName: King
|
||||
email: example.king@example.com
|
||||
emailCanonical: example.king@example.com
|
||||
|
||||
Sylius\Component\Core\Model\Product:
|
||||
product1:
|
||||
fallbackLocale: en_US
|
||||
currentLocale: en
|
||||
code: MUG_REVIEW_BEST
|
||||
product2:
|
||||
fallbackLocale: en_US
|
||||
currentLocale: en
|
||||
code: MUG_REVIEW_GOOD
|
||||
|
||||
Sylius\Component\Core\Model\ProductReview:
|
||||
productReview1:
|
||||
title: mug_review_best
|
||||
rating: 4
|
||||
comment: "mug_review_best_comment"
|
||||
author: "@customer_example1"
|
||||
status: "new"
|
||||
reviewSubject: "@product1"
|
||||
productReview2:
|
||||
title: mug_review_good
|
||||
rating: 3
|
||||
comment: "mug_review_good_comment"
|
||||
author: "@customer_example1"
|
||||
status: "new"
|
||||
reviewSubject: "@product1"
|
||||
productReview3:
|
||||
title: mug_review_bad
|
||||
rating: 1
|
||||
comment: "mug_review_bad_comment"
|
||||
author: "@customer_example1"
|
||||
status: "rejected"
|
||||
reviewSubject: "@product1"
|
||||
92
tests/Responses/Expected/product_review/accept_response.json
Normal file
92
tests/Responses/Expected/product_review/accept_response.json
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
{
|
||||
"id": @integer@,
|
||||
"title": "mug_review_best",
|
||||
"rating": 4,
|
||||
"comment": "mug_review_best_comment",
|
||||
"author": {
|
||||
"id": @integer@,
|
||||
"email": "example.queen@example.com",
|
||||
"emailCanonical": "example.queen@example.com",
|
||||
"firstName": "Example",
|
||||
"lastName": "Queen",
|
||||
"gender": "u",
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": @string@
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": "accepted",
|
||||
"reviewSubject": {
|
||||
"id": @integer@,
|
||||
"code": "MUG_REVIEW_BEST",
|
||||
"attributes": [],
|
||||
"options": [],
|
||||
"associations": [],
|
||||
"translations": {
|
||||
"en": {
|
||||
"locale": "en"
|
||||
}
|
||||
},
|
||||
"productTaxons": [],
|
||||
"channels": [],
|
||||
"reviews": {
|
||||
"1": {
|
||||
"id": @integer@,
|
||||
"title": "mug_review_good",
|
||||
"rating": 3,
|
||||
"comment": "mug_review_good_comment",
|
||||
"author": {
|
||||
"id": @integer@,
|
||||
"email": "example.queen@example.com",
|
||||
"emailCanonical": "example.queen@example.com",
|
||||
"firstName": "Example",
|
||||
"lastName": "Queen",
|
||||
"gender": "u",
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": @string@
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": "new",
|
||||
"createdAt": @string@,
|
||||
"updatedAt": @string@
|
||||
},
|
||||
"2": {
|
||||
"id": @integer@,
|
||||
"title": "mug_review_bad",
|
||||
"rating": 1,
|
||||
"comment": "mug_review_bad_comment",
|
||||
"author": {
|
||||
"id": @integer@,
|
||||
"email": "example.queen@example.com",
|
||||
"emailCanonical": "example.queen@example.com",
|
||||
"firstName": "Example",
|
||||
"lastName": "Queen",
|
||||
"gender": "u",
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": @string@
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": "rejected",
|
||||
"createdAt": @string@,
|
||||
"updatedAt": @string@
|
||||
}
|
||||
},
|
||||
"averageRating": 4,
|
||||
"images": [],
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "/api/v1/products/MUG_REVIEW_BEST"
|
||||
},
|
||||
"variants": {
|
||||
"href": "/api/v1/products/MUG_REVIEW_BEST/variants/"
|
||||
}
|
||||
}
|
||||
},
|
||||
"createdAt": @string@,
|
||||
"updatedAt": @string@
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"code":400,
|
||||
"message":""
|
||||
}
|
||||
112
tests/Responses/Expected/product_review/create_response.json
Normal file
112
tests/Responses/Expected/product_review/create_response.json
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
{
|
||||
"id": @integer@,
|
||||
"title": "J_REVIEW",
|
||||
"rating": 3,
|
||||
"comment": "J_REVIEW_COMMENT",
|
||||
"author": {
|
||||
"id": @integer@,
|
||||
"email": "j@example.com",
|
||||
"emailCanonical": "j@example.com",
|
||||
"gender": "u",
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": @string@
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": "new",
|
||||
"reviewSubject": {
|
||||
"id": @integer@,
|
||||
"code": "MUG_REVIEW_BEST",
|
||||
"attributes": [],
|
||||
"options": [],
|
||||
"associations": [],
|
||||
"translations": {
|
||||
"en": {
|
||||
"locale": "en"
|
||||
}
|
||||
},
|
||||
"productTaxons": [],
|
||||
"channels": [],
|
||||
"reviews": [
|
||||
{
|
||||
"id": @integer@,
|
||||
"title": "mug_review_best",
|
||||
"rating": 4,
|
||||
"comment": "mug_review_best_comment",
|
||||
"author": {
|
||||
"id": @integer@,
|
||||
"email": "example.queen@example.com",
|
||||
"emailCanonical": "example.queen@example.com",
|
||||
"firstName": "Example",
|
||||
"lastName": "Queen",
|
||||
"gender": "u",
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": @string@
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": "new",
|
||||
"createdAt": @string@,
|
||||
"updatedAt": @string@
|
||||
},
|
||||
{
|
||||
"id": @integer@,
|
||||
"title": "mug_review_good",
|
||||
"rating": 3,
|
||||
"comment": "mug_review_good_comment",
|
||||
"author": {
|
||||
"id": @integer@,
|
||||
"email": "example.queen@example.com",
|
||||
"emailCanonical": "example.queen@example.com",
|
||||
"firstName": "Example",
|
||||
"lastName": "Queen",
|
||||
"gender": "u",
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": @string@
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": "new",
|
||||
"createdAt": @string@,
|
||||
"updatedAt": @string@
|
||||
},
|
||||
{
|
||||
"id": @integer@,
|
||||
"title": "mug_review_bad",
|
||||
"rating": 1,
|
||||
"comment": "mug_review_bad_comment",
|
||||
"author": {
|
||||
"id": @integer@,
|
||||
"email": "example.queen@example.com",
|
||||
"emailCanonical": "example.queen@example.com",
|
||||
"firstName": "Example",
|
||||
"lastName": "Queen",
|
||||
"gender": "u",
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": @string@
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": "rejected",
|
||||
"createdAt": @string@,
|
||||
"updatedAt": @string@
|
||||
}
|
||||
],
|
||||
"averageRating": 0,
|
||||
"images": [],
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "\/api\/v1\/products\/MUG_REVIEW_BEST"
|
||||
},
|
||||
"variants": {
|
||||
"href": "\/api\/v1\/products\/MUG_REVIEW_BEST\/variants\/"
|
||||
}
|
||||
}
|
||||
},
|
||||
"createdAt": @string@,
|
||||
"updatedAt": @string@
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"code": 400,
|
||||
"message": "Validation Failed",
|
||||
"errors": {
|
||||
"children": {
|
||||
"rating": {
|
||||
"errors": [
|
||||
"You must check review rating."
|
||||
],
|
||||
"children": [
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
]
|
||||
},
|
||||
"title": {
|
||||
"errors": [
|
||||
"Review title should not be blank."
|
||||
]
|
||||
},
|
||||
"comment": {
|
||||
"errors": [
|
||||
"Review comment should not be blank."
|
||||
]
|
||||
},
|
||||
"author": {
|
||||
"children": {
|
||||
"email": {
|
||||
"errors": [
|
||||
"Please enter your email."
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
20
tests/Responses/Expected/product_review/index_response.json
Normal file
20
tests/Responses/Expected/product_review/index_response.json
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"page": 1,
|
||||
"limit": 10,
|
||||
"pages": 1,
|
||||
"total": 0,
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "\/api\/v1\/products\/MUG_REVIEW_BEST\/reviews\/?page=1&limit=10"
|
||||
},
|
||||
"first": {
|
||||
"href": "\/api\/v1\/products\/MUG_REVIEW_BEST\/reviews\/?page=1&limit=10"
|
||||
},
|
||||
"last": {
|
||||
"href": "\/api\/v1\/products\/MUG_REVIEW_BEST\/reviews\/?page=1&limit=10"
|
||||
}
|
||||
},
|
||||
"_embedded": {
|
||||
"items": []
|
||||
}
|
||||
}
|
||||
92
tests/Responses/Expected/product_review/reject_response.json
Normal file
92
tests/Responses/Expected/product_review/reject_response.json
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
{
|
||||
"id": @integer@,
|
||||
"title": "mug_review_best",
|
||||
"rating": 4,
|
||||
"comment": "mug_review_best_comment",
|
||||
"author": {
|
||||
"id": @integer@,
|
||||
"email": "example.queen@example.com",
|
||||
"emailCanonical": "example.queen@example.com",
|
||||
"firstName": "Example",
|
||||
"lastName": "Queen",
|
||||
"gender": "u",
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": @string@
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": "rejected",
|
||||
"reviewSubject": {
|
||||
"id": @integer@,
|
||||
"code": "MUG_REVIEW_BEST",
|
||||
"attributes": [],
|
||||
"options": [],
|
||||
"associations": [],
|
||||
"translations": {
|
||||
"en": {
|
||||
"locale": "en"
|
||||
}
|
||||
},
|
||||
"productTaxons": [],
|
||||
"channels": [],
|
||||
"reviews": {
|
||||
"1": {
|
||||
"id": @integer@,
|
||||
"title": "mug_review_good",
|
||||
"rating": 3,
|
||||
"comment": "mug_review_good_comment",
|
||||
"author": {
|
||||
"id": @integer@,
|
||||
"email": "example.queen@example.com",
|
||||
"emailCanonical": "example.queen@example.com",
|
||||
"firstName": "Example",
|
||||
"lastName": "Queen",
|
||||
"gender": "u",
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": @string@
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": "new",
|
||||
"createdAt": @string@,
|
||||
"updatedAt": @string@
|
||||
},
|
||||
"2": {
|
||||
"id": @integer@,
|
||||
"title": "mug_review_bad",
|
||||
"rating": 1,
|
||||
"comment": "mug_review_bad_comment",
|
||||
"author": {
|
||||
"id": @integer@,
|
||||
"email": "example.queen@example.com",
|
||||
"emailCanonical": "example.queen@example.com",
|
||||
"firstName": "Example",
|
||||
"lastName": "Queen",
|
||||
"gender": "u",
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": @string@
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": "rejected",
|
||||
"createdAt": @string@,
|
||||
"updatedAt": @string@
|
||||
}
|
||||
},
|
||||
"averageRating": 0,
|
||||
"images": [],
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "/api/v1/products/MUG_REVIEW_BEST"
|
||||
},
|
||||
"variants": {
|
||||
"href": "/api/v1/products/MUG_REVIEW_BEST/variants/"
|
||||
}
|
||||
}
|
||||
},
|
||||
"createdAt": @string@,
|
||||
"updatedAt": @string@
|
||||
}
|
||||
92
tests/Responses/Expected/product_review/show_response.json
Normal file
92
tests/Responses/Expected/product_review/show_response.json
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
{
|
||||
"id": @integer@,
|
||||
"title": "mug_review_best",
|
||||
"rating": 4,
|
||||
"comment": "mug_review_best_comment",
|
||||
"author": {
|
||||
"id": @integer@,
|
||||
"email": "example.queen@example.com",
|
||||
"emailCanonical": "example.queen@example.com",
|
||||
"firstName": "Example",
|
||||
"lastName": "Queen",
|
||||
"gender": "u",
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": @string@
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": "new",
|
||||
"reviewSubject": {
|
||||
"id": @integer@,
|
||||
"code": "MUG_REVIEW_BEST",
|
||||
"attributes": [],
|
||||
"options": [],
|
||||
"associations": [],
|
||||
"translations": {
|
||||
"en": {
|
||||
"locale": "en"
|
||||
}
|
||||
},
|
||||
"productTaxons": [],
|
||||
"channels": [],
|
||||
"reviews": {
|
||||
"1": {
|
||||
"id": @integer@,
|
||||
"title": "mug_review_good",
|
||||
"rating": 3,
|
||||
"comment": "mug_review_good_comment",
|
||||
"author": {
|
||||
"id": @integer@,
|
||||
"email": "example.queen@example.com",
|
||||
"emailCanonical": "example.queen@example.com",
|
||||
"firstName": "Example",
|
||||
"lastName": "Queen",
|
||||
"gender": "u",
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": @string@
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": "new",
|
||||
"createdAt": @string@,
|
||||
"updatedAt": @string@
|
||||
},
|
||||
"2": {
|
||||
"id": @integer@,
|
||||
"title": "mug_review_bad",
|
||||
"rating": 1,
|
||||
"comment": "mug_review_bad_comment",
|
||||
"author": {
|
||||
"id": @integer@,
|
||||
"email": "example.queen@example.com",
|
||||
"emailCanonical": "example.queen@example.com",
|
||||
"firstName": "Example",
|
||||
"lastName": "Queen",
|
||||
"gender": "u",
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": @string@
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": "rejected",
|
||||
"createdAt": @string@,
|
||||
"updatedAt": @string@
|
||||
}
|
||||
},
|
||||
"averageRating": 0,
|
||||
"images": [],
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "\/api\/v1\/products\/MUG_REVIEW_BEST"
|
||||
},
|
||||
"variants": {
|
||||
"href": "\/api\/v1\/products\/MUG_REVIEW_BEST\/variants\/"
|
||||
}
|
||||
}
|
||||
},
|
||||
"createdAt": @string@,
|
||||
"updatedAt": @string@
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue