open-orchestra/open-orchestra-cms-bundle

View on GitHub
Backoffice/Reference/Strategies/AbstractContentReferenceStrategy.php

Summary

Maintainability
A
55 mins
Test Coverage
<?php

namespace OpenOrchestra\Backoffice\Reference\Strategies;

use OpenOrchestra\BBcodeBundle\Parser\BBcodeParserInterface;
use OpenOrchestra\DisplayBundle\BBcode\InternalLinkDefinition;
use OpenOrchestra\ModelInterface\Model\ContentAttributeInterface;
use OpenOrchestra\ModelInterface\Repository\ContentRepositoryInterface;

/**
 * Class AbstractContentReferenceStrategy
 */
abstract class AbstractContentReferenceStrategy implements ReferenceStrategyInterface
{
    protected $contentRepository;
    protected $bbcodeParser;

    /**
     * @param ContentRepositoryInterface $contentRepository
     * @param BBcodeParserInterface      $bbcodeParser
     */
    public function __construct(
        ContentRepositoryInterface $contentRepository,
        BBcodeParserInterface      $bbcodeParser
    ) {
        $this->contentRepository = $contentRepository;
        $this->bbcodeParser = $bbcodeParser;
    }

    /**
     * Recursively extract cont ent ids from elements (bloc, attribute, collection attribute, etc ...)
     *
     * @param mixed $element
     * @param array $references
     *
     * @return array
     */
    protected function extractContentsFromElement($element, array $references = array())
    {
        if ($this->isContentSearchAttribute($element)) {
            $references[] = $element['contentId'];

        } elseif ($this->isEmbeddedContentAttribute($element)) {
            $references[] = $element->getValue()['contentId'];

        } elseif (
            $element instanceof ContentAttributeInterface
            && $element->getType() === 'tinymce'
            && $this->hasInternalLinkBBCode($element->getValue())
        ) {
            $references = array_merge($references, $this->extractContentIdFromBBCode($element->getValue()));

        } elseif (
            is_string($element) &&
            $this->hasInternalLinkBBCode($element)
        ) {
            $references = array_merge($references, $this->extractContentIdFromBBCode($element));

        } elseif (is_array($element)) {
            foreach ($element as $item) {
                $references = array_merge($references, $this->extractContentsFromElement($item));
            }
        }

        return $references;
    }

    /**
     * @param mixed $element
     *
     * @return boolean
     */
    protected function hasInternalLinkBBCode($element)
    {
        $internalLinkBBCode = '/\[' . InternalLinkDefinition::TAG_NAME . '[^]]*].*?\[\/'. InternalLinkDefinition::TAG_NAME . '\]/m';

        return preg_match($internalLinkBBCode, $element) === 1;
    }

    /**
     * @param string $str
     *
     * @return array
     */
    protected function extractContentIdFromBBCode($str)
    {
        $references = array();
        /** @var \OpenOrchestra\BBcodeBundle\Parser\BBcodeParserInterface $parserBBcode */
        $parsedBBcode = $this->bbcodeParser->parse($str);
        $nodeTags = $parsedBBcode->getElementByTagName(InternalLinkDefinition::TAG_NAME);
        /** @var \OpenOrchestra\BBcodeBundle\ElementNode\BBcodeElementNodeInterface $mediaTag */
        foreach ($nodeTags as $nodeTag) {
            $linkAttribute = json_decode(html_entity_decode($nodeTag->getAttribute()['link']), true);
            if (!empty($linkAttribute['contentSearch_contentId'])) {
                $references[] = $linkAttribute['contentSearch_contentId'];
            }
        }

        return $references;
    }

    /**
     * Check if $attributeValue matches with a content search attribute
     *
     * @param mixed $attributeValue
     *
     * @return boolean
     */
    protected function isContentSearchAttribute($attributeValue)
    {
        return is_array($attributeValue)
            && array_key_exists('contentType', $attributeValue)
            && array_key_exists('choiceType', $attributeValue)
            && array_key_exists('keywords', $attributeValue)
            && isset($attributeValue['contentId']);
    }

    /**
     * @param mixed $attributeValue
     *
     * @return bool
     */
    protected function isEmbeddedContentAttribute($attributeValue)
    {
        return $attributeValue instanceof ContentAttributeInterface
            && $attributeValue->getType() === 'embedded_content';
    }
}