* @date 02/17/2017 */ namespace AppBundle\Service; use AppBundle\Entity\Page; use AppBundle\Util; use Doctrine\ORM\EntityManager; class KeywordService { protected static $DO_SKIP_KEYWORD_CHECK_BY_DOM_ELEMENT_NAME = ['h1' => true, 'h2' => true, 'h3' => true, 'h4' => true, 'h5' => true, 'h6' => true, 'a' => true, 'audio' => true, 'video' => true, 'object' => true, 'nav' => true, 'form' => true ]; private $entityManager; private $dictByContext = null; private $globalDict = null; /** * KeywordService constructor. * * @param EntityManager $entityManager */ public function __construct(EntityManager $entityManager) { $this->entityManager = $entityManager; } /** * Source: http://78.47.251.156/svn/stern-consulting/sunstarPlugin/branches/1.4/lib/sun.class.php * * @param $html * @param string $classes Space separated values for the "class"-attribute * @return string */ public function addKeywordLinksToHtml($html, $classes = '') { $dict = $this->getKeywordsToLinksDict($classes); $doc = new \DOMDocument('1.0', 'utf-8'); $doc->loadHTML('
'. $html .''); $xp = new \DOMXPath($doc); $rootNodes = $xp->query('//body')->item(0)->childNodes; $this->addKeywordLinksToDomNodes($rootNodes, $dict, $doc); $ret = ''; foreach($rootNodes as $node) { $ret .= $doc->saveHTML($node); } return $ret; } /** * Quelle: http://78.47.251.156/svn/stern-consulting/sunstarPlugin/branches/1.4/lib/sun.class.php * * @param \DOMNodeList|\DOMNode[] &$nodes * @param array &$dict * @param \DOMDocument &$doc */ private function addKeywordLinksToDomNodes(&$nodes, &$dict, &$doc) { // As $nodes is a direct reference to $parentNode->childNodes it will be changed when // replacing text-nodes due to adding keywords. Therefore we loop through this // auxilary array '$originalNodes' which simply contains all nodes to process. $originalNodes = []; foreach ($nodes as $node) { $originalNodes[] = $node; } /** @var \DOMNode $node */ foreach($originalNodes as $node) { if($node->nodeType == XML_TEXT_NODE) { $nodeValue = $node->nodeValue; $foundKeywords = false; foreach($dict as $keyword => $link) { $nodeValue = preg_replace('/(^|\W)'. preg_quote($keyword, '/') .'($|\W)/u', '$1'. $link .'$2', $nodeValue, 1, $count); if($count > 0) { $foundKeywords = true; unset($dict[$keyword]); } } if($foundKeywords) { $newNode = $doc->createDocumentFragment(); $newNode->appendXML($nodeValue); $node->parentNode->replaceChild($newNode, $node); } } elseif($node->nodeType == XML_ELEMENT_NODE && !isset(self::$DO_SKIP_KEYWORD_CHECK_BY_DOM_ELEMENT_NAME[strtolower($node->nodeName)])) { $classAttr = $node->attributes->getNamedItem("class"); if (!(isset($classAttr) && $classAttr->nodeValue && preg_match('/(^|\s)skip-keywords($|\s)/', $classAttr->nodeValue) == 1)) { $this->addKeywordLinksToDomNodes($node->childNodes, $dict, $doc); } } } } /** * Source: http://78.47.251.156/svn/stern-consulting/sunstarPlugin/branches/1.4/lib/sun.class.php * * @param string $classes Space separated values for the "class"-attribute * @return array */ private function getKeywordsToLinksDict($classes = '', $context = null) { if ($context) { if (!isset($this->dictByContext[$context])) { $this->dictByContext[$context] = null; } $dict = &$this->dictByContext[$context]; } else { $dict = &$this->globalDict; } if($dict === null) { $dict = []; /* $keywords = $this->entityManager->getRepository('AppBundle:Keyword')->findAll(); foreach($keywords as $keyword) { if(isset($dict[$keyword->getValue()])) { continue; } $dictEntry = $this->createKeywordDictEntry($keyword->getUrl(), $keyword->getValue(), $classes); if ($dictEntry !== null) { $dict[$keyword->getValue()] = $dictEntry; } } $pages = $this->entityManager->createQueryBuilder() ->from('AppBundle:Page', 'p') ->select('p') ->where('p.keyword IS NOT NULL') ->getQuery() ->execute() ; foreach($pages as $page) { if(isset($dict[$page->getKeyword()])) { continue; } $dictEntry = $this->createKeywordDictEntry($page->getUrlPath(), $page->getKeyword(), $classes); if ($dictEntry !== null) { $dict[$page->getKeyword()] = $dictEntry; } } */ /** @var Page $page */ $keywords = Util::loadFromApi('cms/keywords', ['url'=>'']); foreach($keywords as $keyword => $url) { if(isset($dict[$keyword])) { continue; } $dictEntry = $this->createKeywordDictEntry("/".$url, $keyword, $classes); if ($dictEntry !== null) { $dict[$keyword] = $dictEntry; } } } return $dict; } private function createKeywordDictEntry($url, $keywordValue, $classes) { $port = parse_url($url, PHP_URL_PORT); if($url[0] == '/' || strtolower($_SERVER['HTTP_HOST']) == strtolower(parse_url($url, PHP_URL_HOST) .($port ? ':'. $port : ''))) { // Same host => check if same page $urlPath = parse_url($url, PHP_URL_PATH); if($_SERVER['REQUEST_URI'] == $urlPath || ($_SERVER['REQUEST_URI'] == '/' && $urlPath == '')) { // Yes => we don't want to link to the current URL return null; } // No => setup a JS popup layer $attr = ''; $additional_classes = 'intern-link show-layer '; } else { $additional_classes = ''; $attr = 'target="_blank"'; } return ''. $keywordValue .''; } }