vendor/sulu/sulu/src/Sulu/Component/SmartContent/ContentType.php line 291

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of Sulu.
  4.  *
  5.  * (c) Sulu GmbH
  6.  *
  7.  * This source file is subject to the MIT license that is bundled
  8.  * with this source code in the file LICENSE.
  9.  */
  10. namespace Sulu\Component\SmartContent;
  11. use PHPCR\NodeInterface;
  12. use Sulu\Bundle\AudienceTargetingBundle\TargetGroup\TargetGroupStoreInterface;
  13. use Sulu\Bundle\TagBundle\Tag\TagManagerInterface;
  14. use Sulu\Bundle\WebsiteBundle\ReferenceStore\ReferenceStoreInterface;
  15. use Sulu\Component\Category\Request\CategoryRequestHandlerInterface;
  16. use Sulu\Component\Content\Compat\PropertyInterface;
  17. use Sulu\Component\Content\Compat\PropertyParameter;
  18. use Sulu\Component\Content\ComplexContentType;
  19. use Sulu\Component\Content\ContentTypeExportInterface;
  20. use Sulu\Component\Tag\Request\TagRequestHandlerInterface;
  21. use Sulu\Component\Util\ArrayableInterface;
  22. use Sulu\Component\Webspace\Analyzer\RequestAnalyzerInterface;
  23. use Symfony\Component\HttpFoundation\RequestStack;
  24. /**
  25.  * Content type for smart selection.
  26.  */
  27. class ContentType extends ComplexContentType implements ContentTypeExportInterface
  28. {
  29.     /**
  30.      * @var TagManagerInterface
  31.      */
  32.     private $tagManager;
  33.     /**
  34.      * @var DataProviderPoolInterface
  35.      */
  36.     private $dataProviderPool;
  37.     /**
  38.      * @var RequestStack
  39.      */
  40.     private $requestStack;
  41.     /**
  42.      * Contains cached values.
  43.      *
  44.      * @var array
  45.      */
  46.     private $cache = [];
  47.     /**
  48.      * @var TagRequestHandlerInterface
  49.      */
  50.     private $tagRequestHandler;
  51.     /**
  52.      * @var CategoryRequestHandlerInterface
  53.      */
  54.     private $categoryRequestHandler;
  55.     /**
  56.      * @var TargetGroupStoreInterface
  57.      */
  58.     private $targetGroupStore;
  59.     /**
  60.      * @var ReferenceStoreInterface
  61.      */
  62.     private $tagReferenceStore;
  63.     /**
  64.      * @var ReferenceStoreInterface
  65.      */
  66.     private $categoryReferenceStore;
  67.     /**
  68.      * @var RequestAnalyzerInterface
  69.      */
  70.     private $requestAnalyzer;
  71.     public function __construct(
  72.         DataProviderPoolInterface $dataProviderPool,
  73.         TagManagerInterface $tagManager,
  74.         RequestStack $requestStack,
  75.         TagRequestHandlerInterface $tagRequestHandler,
  76.         CategoryRequestHandlerInterface $categoryRequestHandler,
  77.         ReferenceStoreInterface $tagReferenceStore,
  78.         ReferenceStoreInterface $categoryReferenceStore,
  79.         TargetGroupStoreInterface $targetGroupStore null,
  80.         RequestAnalyzerInterface $requestAnalyzer
  81.     ) {
  82.         $this->dataProviderPool $dataProviderPool;
  83.         $this->tagManager $tagManager;
  84.         $this->requestStack $requestStack;
  85.         $this->tagRequestHandler $tagRequestHandler;
  86.         $this->categoryRequestHandler $categoryRequestHandler;
  87.         $this->tagReferenceStore $tagReferenceStore;
  88.         $this->categoryReferenceStore $categoryReferenceStore;
  89.         $this->targetGroupStore $targetGroupStore;
  90.         $this->requestAnalyzer $requestAnalyzer;
  91.     }
  92.     public function read(
  93.         NodeInterface $node,
  94.         PropertyInterface $property,
  95.         $webspaceKey,
  96.         $languageCode,
  97.         $segmentKey
  98.     ) {
  99.         $data $node->getPropertyValueWithDefault($property->getName(), '{}');
  100.         if (\is_string($data)) {
  101.             $data = \json_decode($datatrue);
  102.         }
  103.         if (!empty($data['tags'])) {
  104.             $data['tags'] = $this->tagManager->resolveTagIds($data['tags']);
  105.         }
  106.         $property->setValue($data);
  107.     }
  108.     public function write(
  109.         NodeInterface $node,
  110.         PropertyInterface $property,
  111.         $userId,
  112.         $webspaceKey,
  113.         $languageCode,
  114.         $segmentKey
  115.     ) {
  116.         $value $property->getValue();
  117.         if ($value instanceof ArrayableInterface) {
  118.             $value $value->toArray();
  119.         }
  120.         $this->resolveTags($value'tags');
  121.         $this->resolveTags($value'websiteTags');
  122.         $node->setProperty($property->getName(), \json_encode($value));
  123.     }
  124.     public function remove(
  125.         NodeInterface $node,
  126.         PropertyInterface $property,
  127.         $webspaceKey,
  128.         $languageCode,
  129.         $segmentKey
  130.     ) {
  131.         if ($node->hasProperty($property->getName())) {
  132.             $node->getProperty($property->getName())->remove();
  133.         }
  134.     }
  135.     public function getDefaultParams(PropertyInterface $property null)
  136.     {
  137.         $provider $this->getProvider($property);
  138.         $configuration $provider->getConfiguration();
  139.         $defaults = [
  140.             'provider' => new PropertyParameter('provider''pages'),
  141.             'alias' => null,
  142.             'page_parameter' => new PropertyParameter('page_parameter''p'),
  143.             'tags_parameter' => new PropertyParameter('tags_parameter''tags'),
  144.             'categories_parameter' => new PropertyParameter('categories_parameter''categories'),
  145.             'website_tags_operator' => new PropertyParameter('website_tags_operator''OR'),
  146.             'website_categories_operator' => new PropertyParameter('website_categories_operator''OR'),
  147.             'sorting' => new PropertyParameter('sorting'$configuration->getSorting(), 'collection'),
  148.             'types' => new PropertyParameter('types'$configuration->getTypes(), 'collection'),
  149.             'present_as' => new PropertyParameter('present_as', [], 'collection'),
  150.             'category_root' => new PropertyParameter('category_root'null),
  151.             'display_options' => new PropertyParameter(
  152.                 'display_options',
  153.                 [
  154.                     'tags' => new PropertyParameter('tags'true),
  155.                     'categories' => new PropertyParameter('categories'true),
  156.                     'sorting' => new PropertyParameter('sorting'true),
  157.                     'types' => new PropertyParameter('types'true),
  158.                     'limit' => new PropertyParameter('limit'true),
  159.                     'presentAs' => new PropertyParameter('presentAs'true),
  160.                 ],
  161.                 'collection'
  162.             ),
  163.             'has' => [
  164.                 'datasource' => $configuration->hasDatasource(),
  165.                 'tags' => $configuration->hasTags(),
  166.                 'categories' => $configuration->hasCategories(),
  167.                 'sorting' => $configuration->hasSorting(),
  168.                 'types' => $configuration->hasTypes(),
  169.                 'limit' => $configuration->hasLimit(),
  170.                 'presentAs' => $configuration->hasPresentAs(),
  171.                 'audienceTargeting' => $configuration->hasAudienceTargeting(),
  172.             ],
  173.             'datasourceResourceKey' => $configuration->getDatasourceResourceKey(),
  174.             'datasourceAdapter' => $configuration->getDatasourceAdapter(),
  175.             'exclude_duplicates' => new PropertyParameter('exclude_duplicates'false),
  176.         ];
  177.         if ($provider instanceof DataProviderAliasInterface) {
  178.             $defaults['alias'] = $provider->getAlias();
  179.         }
  180.         return \array_merge(
  181.             parent::getDefaultParams(),
  182.             $defaults,
  183.             $provider->getDefaultPropertyParameter()
  184.         );
  185.     }
  186.     public function getContentData(PropertyInterface $property)
  187.     {
  188.         // check memoize
  189.         $hash = \spl_object_hash($property);
  190.         if (\array_key_exists($hash$this->cache)) {
  191.             return $this->cache[$hash];
  192.         }
  193.         /** @var PropertyParameter[] $params */
  194.         $params = \array_merge(
  195.             $this->getDefaultParams($property),
  196.             $property->getParams()
  197.         );
  198.         // prepare filters
  199.         $filters $property->getValue();
  200.         $filters['excluded'] = [$property->getStructure()->getUuid()];
  201.         // default value of tags/category is an empty array
  202.         if (!\array_key_exists('tags'$filters) || null === $filters['tags']) {
  203.             $filters['tags'] = [];
  204.         }
  205.         if (!\array_key_exists('categories'$filters) || null === $filters['categories']) {
  206.             $filters['categories'] = [];
  207.         }
  208.         // extends selected filter with requested tags
  209.         $filters['websiteTags'] = $this->tagRequestHandler->getTags($params['tags_parameter']->getValue());
  210.         $filters['websiteTagsOperator'] = $params['website_tags_operator']->getValue();
  211.         // extends selected filter with requested categories
  212.         $filters['websiteCategories'] = $this->categoryRequestHandler->getCategories(
  213.             $params['categories_parameter']->getValue()
  214.         );
  215.         $filters['websiteCategoriesOperator'] = $params['website_categories_operator']->getValue();
  216.         if ($this->targetGroupStore && isset($filters['audienceTargeting']) && $filters['audienceTargeting']) {
  217.             $filters['targetGroupId'] = $this->targetGroupStore->getTargetGroupId();
  218.         }
  219.         $segment $this->requestAnalyzer->getSegment();
  220.         if ($segment) {
  221.             $filters['segmentKey'] = $segment->getKey();
  222.         }
  223.         // resolve tags to id
  224.         $this->resolveTags($filters'tags');
  225.         // resolve website tags to id
  226.         $this->resolveTags($filters'websiteTags');
  227.         foreach (\array_merge($filters['tags'], $filters['websiteTags']) as $item) {
  228.             $this->tagReferenceStore->add($item);
  229.         }
  230.         foreach (\array_merge($filters['categories'], $filters['websiteCategories']) as $item) {
  231.             $this->categoryReferenceStore->add($item);
  232.         }
  233.         // get provider
  234.         $provider $this->getProvider($property);
  235.         $configuration $provider->getConfiguration();
  236.         // prepare pagination, limitation and options
  237.         $page 1;
  238.         $limit = (\array_key_exists('limitResult'$filters) && $configuration->hasLimit()) ?
  239.             $filters['limitResult'] : null;
  240.         $options = [
  241.             'webspaceKey' => $this->requestAnalyzer->getWebspace()->getKey(),
  242.             'locale' => $property->getStructure()->getLanguageCode(),
  243.         ];
  244.         if (isset($params['max_per_page']) && $configuration->hasPagination()) {
  245.             // is paginated
  246.             $page $this->getCurrentPage($params['page_parameter']->getValue());
  247.             $pageSize = \intval($params['max_per_page']->getValue());
  248.             // resolve paginated filters
  249.             $data $provider->resolveResourceItems(
  250.                 $filters,
  251.                 $params,
  252.                 $options,
  253.                 !empty($limit) ? \intval($limit) : null,
  254.                 $page,
  255.                 $pageSize
  256.             );
  257.         } else {
  258.             $data $provider->resolveResourceItems(
  259.                 $filters,
  260.                 $params,
  261.                 $options,
  262.                 !empty($limit) ? \intval($limit) : null,
  263.                 1
  264.             );
  265.         }
  266.         // append view data
  267.         $filters['page'] = $page;
  268.         $filters['hasNextPage'] = $data->getHasNextPage();
  269.         $filters['paginated'] = $configuration->hasPagination();
  270.         $property->setValue($filters);
  271.         // save result in cache
  272.         return $this->cache[$hash] = $data->getItems();
  273.     }
  274.     public function getViewData(PropertyInterface $property)
  275.     {
  276.         /** @var PropertyParameter[] $params */
  277.         $params = \array_merge(
  278.             $this->getDefaultParams($property),
  279.             $property->getParams()
  280.         );
  281.         $this->getContentData($property);
  282.         $config $property->getValue();
  283.         $config = \array_merge(
  284.             [
  285.                 'dataSource' => null,
  286.                 'includeSubFolders' => null,
  287.                 'category' => null,
  288.                 'tags' => [],
  289.                 'sortBy' => null,
  290.                 'sortMethod' => null,
  291.                 'presentAs' => null,
  292.                 'limitResult' => null,
  293.                 'page' => null,
  294.                 'hasNextPage' => null,
  295.                 'paginated' => false,
  296.                 'categoryRoot' => $params['category_root']->getValue(),
  297.                 'categoriesParameter' => $params['categories_parameter']->getValue(),
  298.                 'tagsParameter' => $params['tags_parameter']->getValue(),
  299.             ],
  300.             $config
  301.         );
  302.         return $config;
  303.     }
  304.     /**
  305.      * Returns provider for given property.
  306.      *
  307.      * @return DataProviderInterface
  308.      */
  309.     private function getProvider(PropertyInterface $property)
  310.     {
  311.         $params $property->getParams();
  312.         $providerAlias 'pages';
  313.         if (\array_key_exists('provider'$params)) {
  314.             $providerAlias $params['provider']->getValue();
  315.         }
  316.         return $this->dataProviderPool->get($providerAlias);
  317.     }
  318.     /**
  319.      * Determine current page from current request.
  320.      *
  321.      * @param string $pageParameter
  322.      *
  323.      * @return int
  324.      */
  325.     private function getCurrentPage($pageParameter)
  326.     {
  327.         if (null === $this->requestStack->getCurrentRequest()) {
  328.             return 1;
  329.         }
  330.         $page $this->requestStack->getCurrentRequest()->get($pageParameter1);
  331.         if ($page <= 1) {
  332.             $page 1;
  333.         }
  334.         if ($page > \PHP_INT_MAX) {
  335.             return \PHP_INT_MAX;
  336.         }
  337.         return (int) $page;
  338.     }
  339.     public function exportData($propertyValue)
  340.     {
  341.         if (\is_string($propertyValue)) {
  342.             return $propertyValue;
  343.         }
  344.         if (\is_array($propertyValue)) {
  345.             return \json_encode($propertyValue);
  346.         }
  347.         return '';
  348.     }
  349.     public function importData(
  350.         NodeInterface $node,
  351.         PropertyInterface $property,
  352.         $value,
  353.         $userId,
  354.         $webspaceKey,
  355.         $languageCode,
  356.         $segmentKey null
  357.     ) {
  358.         $property->setValue(\json_decode($valuetrue));
  359.         $this->write($node$property$userId$webspaceKey$languageCode$segmentKey);
  360.     }
  361.     /**
  362.      * @param mixed[] $value
  363.      * @param string $key
  364.      */
  365.     protected function resolveTags(&$value$key)
  366.     {
  367.         if (isset($value[$key])) {
  368.             $ids = [];
  369.             $names = [];
  370.             foreach ($value[$key] as $tag) {
  371.                 if (\is_numeric($tag)) {
  372.                     $ids[] = $tag;
  373.                 } else {
  374.                     $names[] = $tag;
  375.                 }
  376.             }
  377.             if (!empty($names)) {
  378.                 foreach ($this->tagManager->resolveTagNames($names) as $id) {
  379.                     $ids[] = $id;
  380.                 }
  381.             }
  382.             $value[$key] = $ids;
  383.         }
  384.     }
  385. }