<?php
namespace Schoettler\SteincoProducts\Twig;
use Schoettler\SteincoProducts\Constants;
use Schoettler\SteincoProducts\SharedFunctions;
use Shopware\Core\Content\Product\Aggregate\ProductVisibility\ProductVisibilityDefinition;
use Shopware\Core\Content\Product\ProductRepository;
use Shopware\Core\Content\Property\Aggregate\PropertyGroupOption\PropertyGroupOptionCollection;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\RangeFilter;
use Shopware\Core\Framework\Routing\Annotation\RouteScope;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Core\System\SalesChannel\SalesChannelRepository;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Shopware\Storefront\Page\Product\ProductLoader;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
use Shopware\Core\Content\Seo\SeoUrlPlaceholderHandlerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Shopware\Core\System\SalesChannel\Context\AbstractSalesChannelContextFactory;
use Doctrine\DBAL\Connection;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Shopware\Core\Content\Property\PropertyGroupEntity;
/**
* @RouteScope(scopes={"storefront"})
*/
class SchoettlerTwigFunctions extends AbstractExtension
{
private $systemConfigService;
private $dbConnection;
private $session;
public function __construct(SessionInterface $session,
SystemConfigService $systemConfigService,
Connection $dbConnection)
{
$this->session = $session;
$this->systemConfigService = $systemConfigService;
$this->dbConnection = $dbConnection;
}
public function getFunctions(): array
{
return [
new TwigFunction('shop_url_for_product', [$this, 'getShopUrlForProduct']),
new TwigFunction('remote_ip', [$this, 'getTheRemoteIP']),
new TwigFunction('intersect', [$this, 'hasIntersection']),
new TwigFunction('cat_is_rolle', [$this, 'catIsRolle']),
new TwigFunction('cat_is_rad', [$this, 'catIsRad']),
new TwigFunction('cat_is_zubehoer', [$this, 'catIsZubehoer']),
new TwigFunction('get_tag', [$this, 'getTag']),
new TwigFunction('set_tag', [$this, 'setTag']),
new TwigFunction('get_property', [$this, 'getPropertyByDescription'])
];
}
/**
* Retrieves a PropertyGroupEntity from an array of properties based on its description.
*
* This function iterates through an array of properties and returns the first
* PropertyGroupEntity that matches the given description.
*
* @param array $properties An array of PropertyGroupEntity objects to search through.
* @param string|null $description The description to match against the property descriptions.
*
* @return PropertyGroupEntity|null Returns the matching PropertyGroupEntity if found, or null if not found or if input is invalid.
*/
public function getPropertyByDescription($properties, ?string $description): ?PropertyGroupEntity
{
if (empty($properties) || $description === null || trim($description) === '') {
return null;
}
foreach ($properties as $property) {
if (!($property instanceof PropertyGroupEntity)) {
// Log this error or throw an exception in a development environment
// error_log('Invalid element in property array: ' . gettype($property));
continue;
}
if ($property->getDescription() === $description) {
return $property;
}
}
return null;
}
public function catIsRolle(): bool
{
return $this->getTag() == Constants::TAG_ROLLE;
}
public function catIsRad(): bool
{
return $this->getTag() == Constants::TAG_RAD;
}
public function catIsZubehoer(): bool
{
return $this->getTag() == Constants::TAG_ZUBEHOER;
}
public function getTag(): string
{
return $this->session->get(Constants::TAG_NAME, Constants::TAG_ROLLE);
}
public function setTag(string $value): void
{
$this->session->set(Constants::TAG_NAME, $value);
}
public function getTheRemoteIP(): string
{
return SharedFunctions::getRemoteIP();
}
public function hasIntersection(array $array1, array $array2): bool
{
return ! empty( array_intersect($array1, $array2));
}
public function getShopUrlForProduct(string $productId, ?string $salesChannelId, ?string $languageId): string
{
/* The function returns the SEO URL for the requested product and language
* from the shop sales channel. If there is no corresponding product, an empty
* string will be returned.
*/
// HALLO der Name des Verkaufskanals muss hier ausgewertet werden
if ( $salesChannelId == null || $languageId == null) {
return '';
}
$result = '';
$scShopUUID = $this->systemConfigService->get('SteincoProductsController.config.scShopUUID');
$sql = "SELECT scd.url base_url, TRIM( su.seo_path_info) seo_path"
. " FROM product p, product_visibility pv, sales_channel sc, sales_channel_domain scd, seo_url su, language l"
. " WHERE p.id = UNHEX('" . $productId . "')"
. " AND l.id = UNHEX('" . $languageId . "')"
. " AND p.id = pv.product_id"
. " AND sc.id = UNHEX('" . $salesChannelId . "')"
. " AND scd.sales_channel_id = sc.id"
. " AND scd.language_id = l.id"
. " AND pv.sales_channel_id = sc.id"
. " AND su.sales_channel_id = sc.id"
. " AND su.foreign_key = p.id"
. " AND su.language_id = l.id"
. " AND su.is_canonical = true";
$stmt = $this->dbConnection->executeQuery($sql);
$row = $stmt->fetchAssociative();
if ($row) {
$result = $row['base_url'] . '/' . $row['seo_path'];
}
return $result;
}
}