Skip to content

Commit

Permalink
feature #12472 [Api] Visitor and Customer add ProductReview (Tomanhez)
Browse files Browse the repository at this point in the history
This PR was merged into the 1.10-dev branch.

Discussion
----------

| Q               | A
| --------------- | -----
| Branch?         | master
| Bug fix?        | no
| New feature?    | yes
| BC breaks?      | no
| Deprecations?   | no
| License         | MIT

<!--
 - Bug fixes must be submitted against the 1.7 or 1.8 branch (the lowest possible)
 - Features and deprecations must be submitted against the master branch
 - Make sure that the correct base branch is set

 To be sure you are not breaking any Backward Compatibilities, check the documentation:
 https://docs.sylius.com/en/latest/book/organization/backward-compatibility-promise.html
-->


Commits
-------

f11bfb5 Add specs and behat scenarios
bc19b70 Add behat implementation and configuration
2f60dda Add resource configuration and serialization
1900618 Add AddProductReview and AddProductReviewHandler
0cd3da0 AddProductReviewInputDataTransformer
d95297d Add next iteration
  • Loading branch information
GSadee committed Mar 29, 2021
2 parents a5b9405 + d95297d commit 17f8807
Show file tree
Hide file tree
Showing 16 changed files with 570 additions and 25 deletions.
6 changes: 6 additions & 0 deletions UPGRADE-1.10.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,9 @@
### New API

1. API CartShippingMethod key `cost` has been changed to `price`.

1. To have better control over the serialization process, we introduced `shop` and `admin` prefixes to names of serialization groups on `src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/*` and `src/Sylius/Bundle/ApiBundle/Resources/config/serialization/*`.
Several additional serialization groups have been rephrased, to improve readability and predictability of them.
If you are using they on your custom entity `api_resource` configuration or serialization groups, you should check if one of these changes may affect on your app. If yes, change all occurs by this pattern:

- `product_review:update` changed to: `admin:product_review:update` and `shop:product_review:update`
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Feature: Adding product review as a customer
And the store has a product "Necronomicon"
And I am a logged in customer

@ui
@ui @api
Scenario: Adding product reviews as a logged in customer
When I want to review product "Necronomicon"
And I leave a comment "Great book for every advanced sorcerer.", titled "Scary but astonishing"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Feature: Adding product review as a guest
Given the store operates on a single channel in "United States"
And the store has a product "Necronomicon"

@ui
@ui @api
Scenario: Adding product reviews as a guest
When I want to review product "Necronomicon"
And I leave a comment "I'm never gonna read this terrible book again.", titled "Never again" as "castiel@heaven.com"
Expand Down
48 changes: 48 additions & 0 deletions src/Sylius/Behat/Context/Api/Shop/ProductReviewContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use Sylius\Behat\Client\ResponseCheckerInterface;
use Sylius\Behat\Service\SharedStorageInterface;
use Sylius\Component\Product\Model\ProductInterface;
use Sylius\Component\Review\Model\ReviewInterface;
use Webmozart\Assert\Assert;

final class ProductReviewContext implements Context
Expand Down Expand Up @@ -60,6 +61,53 @@ public function iCheckThisProductsReviews(): void
$this->client->filter();
}

/**
* @When I add it
*/
public function iAddIt(): void
{
$this->client->create();
}

/**
* @When I want to review product :product
*/
public function iWantToReviewProduct(ProductInterface $product): void
{
$this->client->buildCreateRequest();
$this->client->addRequestData('productCode', $product->getCode());
}

/**
* @When I leave a comment :comment, titled :title as :email
* @When I leave a comment :comment, titled :title
*/
public function iLeaveACommentTitled(string $comment, string $title, ?string $email = null): void
{
$this->client->addRequestData('title', $title);
$this->client->addRequestData('comment', $comment);
$this->client->addRequestData('email', $email);
}

/**
* @When I rate it with :rating point(s)
*/
public function iRateItWithPoints(int $rating): void
{
$this->client->addRequestData('rating', $rating);
}

/**
* @Then I should be notified that my review is waiting for the acceptation
*/
public function iShouldBeNotifiedThatMyReviewIsWaitingForTheAcceptation(): void
{
Assert::same(
$this->responseChecker->getValue($this->client->getLastResponse(), 'status'),
ReviewInterface::STATUS_NEW
);
}

/**
* @Then I should see :amount product reviews in the list
* @Then I should be notified that there are no reviews
Expand Down
1 change: 1 addition & 0 deletions src/Sylius/Behat/Resources/config/suites.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ imports:
- suites/api/locale/managing_locales.yml
- suites/api/order/managing_orders.yml
- suites/api/payment/managing_payments.yml
- suites/api/product/adding_product_review.yml
- suites/api/product/managing_product_association_types.yml
- suites/api/product/managing_product_options.yml
- suites/api/product/managing_product_reviews.yml
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# This file is part of the Sylius package.
# (c) Paweł Jędrzejewski

default:
suites:
api_adding_product_review:
contexts:
- sylius.behat.context.hook.doctrine_orm

- sylius.behat.context.transform.channel
- sylius.behat.context.transform.customer
- sylius.behat.context.transform.lexical
- sylius.behat.context.transform.product
- sylius.behat.context.transform.shared_storage

- sylius.behat.context.setup.channel
- sylius.behat.context.setup.customer
- sylius.behat.context.setup.product
- sylius.behat.context.setup.product_review
- sylius.behat.context.setup.shop_api_security

- sylius.behat.context.api.shop.product
- sylius.behat.context.api.shop.product_review

filters:
tags: "@adding_product_review && @api"
62 changes: 62 additions & 0 deletions src/Sylius/Bundle/ApiBundle/Command/AddProductReview.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?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\Bundle\ApiBundle\Command;

/** @experimental */
class AddProductReview implements CommandAwareDataTransformerInterface
{
/**
* @var string
* @psalm-immutable
*/
public $title;

/**
* @var int
* @psalm-immutable
*/
public $rating;

/**
* @var string
* @psalm-immutable
*/
public $comment;

/**
* @var string
* @psalm-immutable
*/
public $productCode;

/**
* @var string|null
* @psalm-immutable
*/
public $email;

public function __construct(
string $title,
int $rating,
string $comment,
string $productCode,
?string $email = null
) {
$this->title = $title;
$this->rating = $rating;
$this->comment = $comment;
$this->productCode = $productCode;
$this->email = $email;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?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\Bundle\ApiBundle\CommandHandler;

use Sylius\Bundle\AdminApiBundle\Model\UserInterface;
use Sylius\Bundle\ApiBundle\Command\AddProductReview;
use Sylius\Bundle\ApiBundle\Context\UserContextInterface;
use Sylius\Bundle\ApiBundle\Provider\CustomerProviderInterface;
use Sylius\Component\Core\Model\CustomerInterface;
use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Core\Model\ShopUserInterface;
use Sylius\Component\Core\Repository\ProductRepositoryInterface;
use Sylius\Component\Resource\Factory\FactoryInterface;
use Sylius\Component\Resource\Repository\RepositoryInterface;
use Sylius\Component\Review\Model\ReviewInterface;
use Symfony\Component\Messenger\Handler\MessageHandlerInterface;

/** @experimental */
final class AddProductReviewHandler implements MessageHandlerInterface
{
/** @var FactoryInterface */
private $productReviewFactory;

/** @var RepositoryInterface */
private $productReviewRepository;

/** @var ProductRepositoryInterface */
private $productRepository;

/** @var CustomerProviderInterface */
private $customerProvider;

public function __construct(
FactoryInterface $productReviewFactory,
RepositoryInterface $productReviewRepository,
ProductRepositoryInterface $productRepository,
CustomerProviderInterface $customerProvider
) {
$this->productReviewFactory = $productReviewFactory;
$this->productReviewRepository = $productReviewRepository;
$this->productRepository = $productRepository;
$this->customerProvider = $customerProvider;
}

public function __invoke(AddProductReview $addProductReview): ReviewInterface
{
/** @var ProductInterface $product */
$product = $this->productRepository->findOneByCode($addProductReview->productCode);

/** @var string|null $email */
$email = $addProductReview->email;

if ($email === null) {
throw new \InvalidArgumentException('Visitor should provide an email');
}

/** @var CustomerInterface $customer */
$customer = $this->customerProvider->provide($email);

/** @var ReviewInterface $review */
$review = $this->productReviewFactory->createNew();
$review->setTitle($addProductReview->title);
$review->setRating($addProductReview->rating);
$review->setComment($addProductReview->comment);
$review->setReviewSubject($product);
$review->setAuthor($customer);

$product->addReview($review);

$this->productReviewRepository->add($review);

return $review;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?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\Bundle\ApiBundle\DataTransformer;

use Sylius\Bundle\AdminApiBundle\Model\UserInterface;
use Sylius\Bundle\ApiBundle\Command\AddProductReview;
use Sylius\Bundle\ApiBundle\Context\UserContextInterface;
use Sylius\Component\Core\Model\CustomerInterface;
use Sylius\Component\Core\Model\ShopUserInterface;

/** @experimental */
final class LoggedInShopUserEmailAwareCommandDataTransformer implements CommandDataTransformerInterface
{
/** @var UserContextInterface */
private $userContext;

public function __construct(UserContextInterface $userContext)
{
$this->userContext = $userContext;
}

public function transform($object, string $to, array $context = [])
{
/** @var CustomerInterface|null $customer */
$customer = $this->getCustomer();

if ($customer !== null) {
$object->email = $customer->getEmail();
}

return $object;
}

public function supportsTransformation($object): bool
{
return $object instanceof AddProductReview;
}

private function getCustomer(): ?CustomerInterface
{
/** @var UserInterface|null $user */
$user = $this->userContext->getUser();
if ($user !== null && $user instanceof ShopUserInterface) {
return $user->getCustomer();
}

return null;
}
}

0 comments on commit 17f8807

Please sign in to comment.