<?php
namespace WebBundle\Service;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityRepository;
use Exception;
use SoapClient;
use SoapFault;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use WebBundle\Entity\Factory;
use WebBundle\Entity\ListCountry;
use WebBundle\Entity\ProductReviewsCache;
use WebBundle\Helper\App;
use WebBundle\Helper\SoapHelper;
use WebBundle\Helper\StrHelper;
use WebBundle\Helper\TrustpilotHelper;
use WebBundle\Repository\ListCountryRepository;
use WebBundle\Repository\ProductReviewsCacheRepository;
use WebBundle\Repository\ReviewsCacheRepository;
use WebBundle\Repository\ReviewsTotalCacheRepository;
class ReviewsService
{
/** @required */
public ProductReviewsCacheRepository $productReviewsCacheRepository;
/** @required */
public ReviewsCacheRepository $reviewsCacheRepository;
/** @required */
public ListCountryRepository $listCountryRepository;
protected EntityManager $em;
protected ContainerInterface $container;
/**
* Хранится репозиторий суммарных дынных отзывов
* @var null
*/
protected $repoSummaries = null;
/**
* Хранится репозиторий отзывов
* @var null
*/
protected $repoReviews = null;
private array $totals = [];
private array $reviews = [];
private string $serviceType = 'trustpilot';
private string $reviewsType = 'service';
/**
* @param ContainerInterface $container
* @param EntityManager $entityManager
*/
public function __construct(ContainerInterface $container, EntityManager $entityManager)
{
$this->container = $container;
$this->em = $entityManager;
}
/**
* @return string
*/
public function getServiceType()
{
return $this->serviceType;
}
/**
* @param string $serviceType
* @return ReviewsService
*/
public function setServiceType(string $serviceType)
{
$this->serviceType = $serviceType;
return $this;
}
/**
* @return string
*/
public function getReviewsType()
{
return $this->reviewsType;
}
/**
* @param string $reviewsType
* @return ReviewsService
*/
public function setReviewsType(string $reviewsType)
{
$this->reviewsType = $reviewsType;
return $this;
}
/**
* Получить суммарные данные из Интерета
* @param array $options
* @return bool|null|array
* @throws Exception
*/
public function getSummariesFromInternet(array $options)
{
if ($this->serviceType === 'trustpilot') {
if ($this->reviewsType === 'service') {
// Получаем данные из интернета
return $this->totals['new'] = TrustpilotHelper::getInstance()->getTotal();
} elseif ($this->reviewsType === 'product') {
if (isset($options['sku']) && !empty($options['sku'])) {
return $this->totals['new'] = TrustpilotHelper::getInstance()->getProductTotal([
'sku' => $options['sku'],
]);
}
return $this->totals['new'] = TrustpilotHelper::getInstance()->getProductTotalList();
}
}
return null;
}
/**
* Получить сумарные данные по отзывам из БД
* @param array $options
* @return array|null
*/
public function getSummariesToDB(array $options): ?array
{
if ($this->serviceType === 'trustpilot') {
if ($this->reviewsType === 'service') {
/** @var ReviewsTotalCacheRepository $repoReviews */
$repoReviews = $this->getRepoSummaries();
if ($options['hash'] ?? null) {
return $this->totals['db'] = $repoReviews->findBy([
'hash' => $options['hash'],
]);
}
return $this->totals['db'] = $repoReviews->getTotal();
} elseif ($this->reviewsType === 'product') {
/** @var ProductReviewsCacheRepository $repoService */
$repoService = $this->getRepoSummaries();
if (!empty($param['sku'])) {
return $this->totals['db'] = $repoService->getReviews([
'sku' => $options['sku'],
]);
}
return $this->totals['db'] = $repoService->getReviews();
}
}
return null;
}
/**
* Возвращает отзывы суммарной информации отзывов
* @return mixed
*/
public function getRepoSummaries(): EntityRepository
{
$repoSummaries = $this->repoSummaries;
if ($this->serviceType === 'trustpilot') {
if ($this->reviewsType === 'service') {
/** @var ReviewsTotalCacheRepository $repoSummaries */
$repoSummaries = $this->em
->getRepository('WebBundle:ReviewsTotalCache');
} elseif ($this->reviewsType === 'product') {
$repoSummaries = $this->productReviewsCacheRepository;
}
$this->repoSummaries = $repoSummaries;
}
return $this->repoSummaries;
}
/**
* Получить данные отзывов из Интерета
* @param array $options
* @return bool|null|array
* @throws Exception
*/
public function getReviewsFromInternet(array $options)
{
if ($this->serviceType === 'trustpilot') {
if ($this->reviewsType === 'service') {
// Получаем данные из интернета
return $this->reviews['new'] = TrustpilotHelper::getInstance()->getReviews();
} elseif ($this->reviewsType === 'product') {
$this->reviews['new'] = TrustpilotHelper::getInstance()->getProductReviews();
return $this->reviews['new'];
}
}
return null;
}
/**
* Получить список отзывов из БД
* @param array $options
* @return array|bool|null
*/
public function getListReviewsToDB(array $options)
{
if ($this->serviceType === 'trustpilot') {
if ($this->reviewsType === 'service') {
// Если установлены лимиты
if (isset($options['current'])) {
$options['start_with'] = $options['current'];
}
$reviews = $this->getRepoReviews()->getReviews($options);
// https://te2.remote.team/discus/D5467D43-C08A-85DB-AF3F-6BED74D781DA
array_walk($reviews,
static fn (array &$item) => $item['url'] = str_replace('#', '/', $item['url'])
);
return $this->reviews['db'] = $reviews;
} elseif ($this->reviewsType === 'product') {
$params = [];
if (!empty($options['sku'])) {
$params = [
'sku' => $options['sku'],
];
}
$res = $this->getRepoReviews()->getReviews($params);
return $this->reviews['db'] = $res;
}
}
return null;
}
/**
* Возвращает репозитории отзывов
* @return mixed
*/
public function getRepoReviews(): EntityRepository
{
$repoReviews = $this->repoReviews;
if ($this->serviceType === 'trustpilot') {
if ($this->reviewsType === 'service') {
$repoReviews = $this->reviewsCacheRepository;
} elseif ($this->reviewsType === 'product') {
$repoReviews = $this->productReviewsCacheRepository;
}
$this->repoReviews = $repoReviews;
}
return $this->repoReviews;
}
/**
* Получает страну
* @param $id
* @return string|null
* @throws SoapFault|Exception
*/
public function getCountryReview($id)
{
/** @var SoapClient $client */
$client = SoapHelper::client(App::getContainer()->getParameter('orderApi_wsdl'));
if (!$client) {
return null;
}
$response = $client->GetCountryOrder(['Number' => $id]);
if (is_string($response->return)) {
$result = json_decode($response->return, true);
if (isset($result['Code'])) {
return StrHelper::toUpper($result['Code']);
}
} else {
// Вторая попытка
$response = $client->GetCountryOrder(['Number' => $id]);
if (is_string($response->return)) {
$result = json_decode($response->return, true);
if (isset($result['Code'])) {
return StrHelper::toUpper($result['Code']);
}
}
}
return null;
}
public function getReviewsByCollectionId(int $collectionId): array
{
$reviewsData = $this->productReviewsCacheRepository->findBy(['collection' => $collectionId], ['id' => 'DESC']);
$reviewsDataArr = [];
/** @var ProductReviewsCache $review */
foreach ($reviewsData as $review) {
if ($review->isAnonymous) {
$review->setUsername('');
}
if (!$review->getCountry()) {
// if ($review->getOrder() && $review->getOrder()->getDeliveryCountry()) {
// $countryEntity = $this->listCountryRepository->find($review->getOrder()->getDeliveryCountry());
// /** @var ListCountry $countryEntity */
// if ($countryEntity) {
// $review->countryFromOrder = $countryEntity->getCode();
// }
// }
}
$reviewsDataArr[] = $review->toArray();
}
return $this->getRevData($reviewsDataArr);
}
public function getReviewByCollection($code): array // старый вариант - в будущем будет удален
{
$reviewsData = $this->productReviewsCacheRepository->getReviews(['sku' => $code]);
return $this->getRevData($reviewsData);
}
/**
* @param array $codes
* @return array
*/
function getReviewForFactory(array $codes): array
{
$reviewsData = $this->productReviewsCacheRepository->getReviews(['sku' => array_keys($codes)]);
$data = [
'prcCount' => 0,
'prcVote' => 0,
'list' => [],
];
foreach ($reviewsData as $row) {
if (empty($codes[ $row['sku'] ])) {
continue;
}
//App::dumpExit($row);
if (empty($data[ $row['sku'] ])) {
$data[ $row['sku'] ] = [
'prcCount' => 0,
'prcVote' => 0,
];
}
$data['list'][] = [
'star' => 5,
'date' => date('Y-d-m H:i:s', 1479934546),
'content' => 'répond aux attentes, pas de commentaire.',
'username' => 'Delmoitié',
];
$data['prcCount']++;
$data['prcVote'] += $row['star'];
$data[ $row['sku'] ]['prcCount']++;
$data[ $row['sku'] ]['prcVote'] += $row['star'];
$data[ $row['sku'] ]['name'] = $codes[ $row['sku'] ]['name'];
$data[ $row['sku'] ]['url'] = $codes[ $row['sku'] ]['url'];
}
return $data;
}
/**
* @param array $reviewsData
* @return array
* @throws Exception
*/
public function getRevData(array $reviewsData): array
{
$percent = [
'1' => 0,
'2' => 0,
'3' => 0,
'4' => 0,
'5' => 0,
'all' => 0,
'd' => 0,
];
$starsCount = [
1 => 0,
2 => 0,
3 => 0,
4 => 0,
5 => 0
];
foreach ($reviewsData as $row) {
$percent['all']++;
$percent[$row['star']]++;
$percent['d'] = $percent['d'] + $row['star'];
}
$starsCount = $percent;
unset($starsCount['all']);
unset($starsCount['d']);
$data = [
'list' => $reviewsData,
'count' => $percent['all'],
'percent' => [
'1' => 0,
'2' => 0,
'3' => 0,
'4' => 0,
'5' => 0,
'd' => 0
],
'starsDistribution' => $starsCount,
// новая версия
'stars' => [
0 => 0,
1 => 0,
2 => 0,
3 => 0,
4 => 0
],
'common' => 0
];
if ($percent['all'] > 0) {
$data['percent'] = [
'1' => (100 / $percent['all'] * $percent[1]),
'2' => (100 / $percent['all'] * $percent[2]),
'3' => (100 / $percent['all'] * $percent[3]),
'4' => (100 / $percent['all'] * $percent[4]),
'5' => (100 / $percent['all'] * $percent[5]),
'd' => round($percent['d'] / $percent['all'], 1)
];
$data['stars'] = [
0 => (100 / $percent['all'] * $percent[1]),
1 => (100 / $percent['all'] * $percent[2]),
2 => (100 / $percent['all'] * $percent[3]),
3 => (100 / $percent['all'] * $percent[4]),
4 => (100 / $percent['all'] * $percent[5]),
];
$data['common'] = round($percent['d'] / $percent['all'], 1);
}
foreach ($data['list'] as &$review) {
$review['replyUrl'] = App::generateUrl('app_product_review_reply', ['id' => $review['id']]);
}
$percentRound = $data['percent'];
unset($percentRound['d']);
foreach ($percentRound as $key => $value) {
$percentRound[$key] = round($value, 2);
}
$data['percentRound'] = $percentRound;
return $data;
}
public function getReviewsByFactory(Factory $factory)
{
$collections = App::getRepository('WebBundle:Collection')->findBy(['factory' => $factory->getId()]);
$reviews = $this->productReviewsCacheRepository->findBy(['collection' => $collections]);
$reviewsByCollections = [];
foreach ($reviews as $review) {
/** @var ProductReviewsCache $review */
$reviewsByCollections[$review->getCollection()->getId()]['collectionName'] = $review->getCollection()->getName();
$reviewsByCollections[$review->getCollection()->getId()]['collectionId'] = $review->getCollection()->getId();
$reviewsByCollections[$review->getCollection()->getId()]['collection_url'] = App::generateUrl(
'app_collection',
[
'collectionUrl' => $review->getCollection()->getUrl(),
'factoryUrl' => $review->getCollection()->getFactoryUrl(),
],
UrlGeneratorInterface::ABSOLUTE_URL
);
$reviewsByCollections[$review->getCollection()->getId()]['reviews'][] = $review->toArray();
}
return $reviewsByCollections;
}
}