<?php declare(strict_types=1);
namespace TTTrustedShops\Subscriber;
use Shopware\Core\Framework\DataAbstractionLayer\Exception\InconsistentCriteriaIdsException;
use Shopware\Storefront\Page\Product\ProductPageLoadedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use DreiscSeoPro\Subscriber\Installment\RichSnippet\RichSnippetSubscriber;
class TrustedShopsSubscriber implements EventSubscriberInterface
{
private $productReviewsApiUrl = 'https://cdn1.api.trustedshops.com/shops/{{tsId}}/products/public/v1/feed.json';
/**
* @var SystemConfigService
*/
private $systemConfigService;
/**
* @var EntityRepositoryInterface
*/
private $productRepository;
public function __construct(EntityRepositoryInterface $productRepository, SystemConfigService $systemConfigService)
{
$this->productRepository = $productRepository;
$this->systemConfigService = $systemConfigService;
}
public static function getSubscribedEvents()
{
return [
ProductPageLoadedEvent::class => 'addSnippetReviewRating',
];
}
/**
* @param ProductPageLoadedEvent $event
* @throws InconsistentCriteriaIdsException
*/
public function addSnippetReviewRating(ProductPageLoadedEvent $event)
{
$page = $event->getPage();
$product = $page->getProduct();
$richSnippetData = $page->getExtension(RichSnippetSubscriber::DREISC_SEO_INSTALLMENT_RICH_SNIPPET_DATA);
if($richSnippetData) {
$ld = $richSnippetData->getLdJson();
$domain = 'TrustedShops.config.';
$tsId = $this->systemConfigService->get( $domain . 'tsId' );
$apiUrl = str_replace( '{{tsId}}', $tsId, $this->productReviewsApiUrl );
$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Accept: application/json' ] );
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, $apiUrl);
$result = curl_exec($ch);
curl_close($ch);
$shopReviews = json_decode( $result );
if ($shopReviews && $shopReviews->response && $shopReviews->response->data->shop->products) {
foreach ($shopReviews->response->data->shop->products as $_product) {
if ($product->getProductNumber() == $_product->sku) {
$this->addAggregateRatingAndReviews($ld, $_product);
}
}
}
//AM-760 Snippetanpassung für Hauptbild auf den SERPS
$this->fixMediaSnippets($ld, $product);
$richSnippetData->setLdJson($ld);
if(!empty($richSnippetData->getLdJson())) {
$page->addExtension(
RichSnippetSubscriber::DREISC_SEO_INSTALLMENT_RICH_SNIPPET_DATA,
$richSnippetData
);
}
}
}
private function fixMediaSnippets(array &$ld, $_product) {
if(isset($ld[0]['image']) && count($ld[0]['image']) > 1) {
$images = $ld[0]['image'];
//keep only image is a cover of product if product have a cover
foreach($images as $key => $image) {
if(!empty($_product->getCover())) {
if($image != $_product->getCover()->getMedia()->getUrl()) {
unset($ld[0]['image'][$key]);
}
}
}
//keep a first image if product have not a cover
if(count($ld[0]['image']) > 1) {
array_slice($ld[0]['image'],0,1);
}
}
}
private function addAggregateRatingAndReviews(array &$ld, $_product)
{
/** Add the aggregate rating */
$ld[0]['aggregateRating'] = [
'@type' => 'AggregateRating',
'ratingValue' => $_product->qualityIndicators->reviewIndicator->overallMark,
'bestRating' => '5',
'ratingCount' => $_product->qualityIndicators->reviewIndicator->totalReviewCount
];
/** Add the reviews */
$reviews = [];
foreach($_product->productReviews as $productReview) {
$datePublished = $productReview->creationDate;
$review = [
'@type' => 'Review',
'datePublished' => $datePublished,
'name' => $_product->name,
'description' => $productReview->comment,
'author' => [
'@type' => 'Person',
'name' => 'unknown'
]
];
$reviews[] = $review;
}
$ld[0]['review'] = $reviews;
}
}