![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/old/app/code/Cnc/Review/Console/ |
<?php /** * Copyright (c) 2020 Kaliop Digital Commerce (https://digitalcommerce.kaliop.com) All Rights Reserved. * https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) * Cnc * Krzysztof Majkowski <[email protected]> */ namespace Cnc\Review\Console; use Magento\Catalog\Model\ResourceModel\Product; use Magento\Framework\App\ResourceConnection; use Magento\Framework\Exception\FileSystemException; use Magento\Framework\Exception\LocalizedException; use Magento\Review\Model\Rating; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Magento\Framework\Setup\SampleData\FixtureManager; use Magento\Framework\Filesystem\Driver\File; use Magento\Review\Model\Review; use Magento\Review\Model\ReviewFactory; use Magento\Review\Model\RatingFactory; use Magento\Customer\Model\Session; use Magento\Review\Model\ResourceModel\Rating\Collection as RatingCollection; use Magento\Review\Model\ResourceModel\Rating\CollectionFactory as RatingCollectionFactory; class ImportReviews extends Command { const FIXTURE_REVIEWS_FILE_PATH = 'Cnc_Review::fixtures/reviews.csv'; const FIXTURE_REVIEWS_DESCRIPTION_FILE_PATH = 'Cnc_Review::fixtures/reviews_description.csv'; const FIXTURE_REVIEWS_DETAILS_FILE_PATH = 'Cnc_Review::fixtures/reviews.csv'; const FIXTURE_PRODUCTS_FILE_PATH = 'Cnc_Catalog::fixtures/products.csv'; /** * @var FixtureManager */ private $fixtureManager; /** * @var File */ private $file; /** * @var ReviewFactory */ private $reviewFactory; /** * @var RatingFactory */ private $ratingFactory; /** * @var Session */ private $customerSession; /** * @var ResourceConnection */ private $resourceConnection; /** * @var OutputInterface */ private $output; /** * @var RatingCollectionFactory */ private $ratingCollectionFactory; /** * @var Product */ private $resourceProduct; /** * @var array */ private $ratings = []; /** * @var array */ private $customersEntityId = []; /** * @var array */ private $productMapping = []; /** * @var array */ private $productsIdToEntityId = []; /** * ImportReviews constructor. * @param FixtureManager $fixtureManager * @param File $file * @param ReviewFactory $reviewFactory * @param RatingFactory $ratingFactory * @param Session $customerSession * @param ResourceConnection $resourceConnection * @param RatingCollectionFactory $ratingCollectionFactory * @param Product $resourceProduct * @param string|null $name */ public function __construct( FixtureManager $fixtureManager, File $file, ReviewFactory $reviewFactory, RatingFactory $ratingFactory, Session $customerSession, ResourceConnection $resourceConnection, RatingCollectionFactory $ratingCollectionFactory, Product $resourceProduct, string $name = null ) { parent::__construct($name); $this->fixtureManager = $fixtureManager; $this->file = $file; $this->reviewFactory = $reviewFactory; $this->ratingFactory = $ratingFactory; $this->customerSession = $customerSession; $this->resourceConnection = $resourceConnection; $this->ratingCollectionFactory = $ratingCollectionFactory; $this->resourceProduct = $resourceProduct; } /** * @inheritDoc */ protected function configure() { $this->setName('reviews:import'); $this->setDescription('Import reviews'); parent::configure(); } /** * CLI command description * * @param InputInterface $input * @param OutputInterface $output * * @return void */ protected function execute(InputInterface $input, OutputInterface $output): void { $this->output = $output; $this->prepareMapping(); $reviews = $this->prepareReviews(); $this->import($reviews); } private function prepareMapping() { $mapping = []; $data = $this->getDataFromFile(self::FIXTURE_PRODUCTS_FILE_PATH); foreach ($data as $row) { $mapping[$row['products_id']] = $row['products_model']; } $this->productMapping = $mapping; } /** * Prepare data. * * @return array * @throws FileSystemException * @throws LocalizedException */ private function prepareReviews() { $reviews = []; $data = $this->getDataFromFile(self::FIXTURE_REVIEWS_FILE_PATH); foreach ($data as $row) { $reviews[$row['reviews_id']] = $row; } $descriptions = $this->getDataFromFile(self::FIXTURE_REVIEWS_DESCRIPTION_FILE_PATH); foreach ($descriptions as $description) { $reviews[$description['reviews_id']] = array_merge($reviews[$description['reviews_id']], $description); } return $reviews; } /** * Do import. * * @param array $reviews * @throws \Exception */ private function import(array $reviews) { $count = count($reviews); foreach ($reviews as $index => $review) { $this->output->writeln(($index + 1) . ' / ' . $count); $reviewObject = $this->reviewFactory->create(); $customerId = isset($review['customers_id']) ? $review['customers_id'] : null; $customerId = ($customerId == 'NULL' ? null : $customerId); if ($customerId !== null) { $customerId = $this->getCustomerEntityId($customerId); } $this->customerSession->setCustomerId($customerId); $productId = $this->getProductId($review['products_id']); if (!$productId) { $this->output->writeln('Product with productsId ' . $review['products_id'] . ' wasnt matched'); continue; } $languagesId = isset($review['languages_id']) ? $review['languages_id'] : 1; $stores = $this->getStores($languagesId); $data = [ 'title' => 'review', 'nickname' => $review['customers_name'], 'detail' => isset($review['reviews_text']) ? $this->prepareForUtf8($review['reviews_text']) : '', 'created_at' => $review['date_added'] ]; $reviewObject->setData($data); $reviewObject->setEntityId($reviewObject->getEntityIdByCode(Review::ENTITY_PRODUCT_CODE)) ->setEntityPkValue($productId) ->setStatusId(Review::STATUS_APPROVED) ->setCustomerId($customerId) ->setStoreId($stores[0]) ->setStores($stores); $reviewObject->save(); /** @var RatingCollection $ratings */ $ratings = $this->getActiveRatings($stores[0]); /** @var Rating $rating */ foreach ($ratings as $rating) { $options = $rating->getOptions(); $optionId = false; foreach ($options as $option) { if ($option->getValue() == $review['reviews_rating']) { $optionId = $option->getData('option_id'); } } if ($optionId) { $this->ratingFactory->create() ->setRatingId($rating->getId()) ->setReviewId($reviewObject->getId()) ->setCustomerId($customerId) ->addOptionVote($optionId, $productId); } } $reviewObject->aggregate(); } $this->customerSession->setCustomerId(null); } /** * Get content of file. * * @param $name * @return array * @throws FileSystemException * @throws LocalizedException */ private function getDataFromFile($name) { $data = []; $fileName = $this->fixtureManager->getFixture($name); $file = $this->file->fileOpen($fileName, "r"); $header = $this->file->fileGetCsv($file, 0, ","); while ($row = $this->file->fileGetCsv($file, 0, ",")) { $data[] = array_filter(array_combine($header, $row)); } return $data; } /** * Get customer entity_id by customer_id. * * @param $customerId * @return string */ private function getCustomerEntityId($customerId) { if (isset($this->customersEntityId[$customerId])) { return $this->customersEntityId[$customerId]; } $sql = 'SELECT entity_id FROM customer_entity WHERE customer_id = ' . $customerId; $this->customersEntityId[$customerId] = $this->resourceConnection->getConnection()->fetchOne($sql); return $this->customersEntityId[$customerId]; } /** * Get entity id by productsId from CSV. * * @param $productsId * @return false|int|mixed */ private function getProductId($productsId) { if (isset($this->productsIdToEntityId[$productsId])) { return $this->productsIdToEntityId[$productsId]; } if (isset($this->productMapping[$productsId])) { $id = $this->resourceProduct->getIdBySku($this->productMapping[$productsId]); if ($id) { //Check if this product is assigned to grouped product. In this case reviews should be saved on grouped. $id = $this->getLinkedGroupedId($id); $this->productsIdToEntityId[$productsId] = $id; return $this->productsIdToEntityId[$productsId]; } } return false; } /** * @param $id * @return string */ private function getLinkedGroupedId($id) { $groupedId = $id; $sql = 'SELECT product_id FROM catalog_product_link WHERE linked_product_id = ' . $id; if ($result = $this->resourceConnection->getConnection()->fetchOne($sql)) { $groupedId = $result; } return $groupedId; } /** * Get active ratings collection for given store * * @param $storeId * @return RatingCollection|mixed */ private function getActiveRatings($storeId) { if (isset($this->ratings[$storeId])) { return $this->ratings[$storeId]; } $collection = $this->ratingCollectionFactory->create(); $collection->setActiveFilter(1)->setStoreFilter($storeId)->load(); $this->ratings[$storeId] = $collection; return $this->ratings[$storeId]; } /** * Convert text to utf8. * * @param $txt * @return string|string[]|null */ private function prepareForUtf8($txt) { return preg_replace( '/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u', ' ', $txt ); } /** * Map languagesId to store id. * * @param $languagesId * @return int[] */ private function getStores($languagesId) { if ($languagesId == 4) { return [1]; } else { return [2, 3, 4]; } } }