These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Kunstmaan\NodeSearchBundle\Configuration; |
||
4 | |||
5 | use Doctrine\ORM\EntityManager; |
||
6 | use Elastica\Index; |
||
7 | use Elastica\Type\Mapping; |
||
8 | use Kunstmaan\AdminBundle\Helper\DomainConfigurationInterface; |
||
9 | use Kunstmaan\AdminBundle\Helper\Security\Acl\Permission\MaskBuilder; |
||
10 | use Kunstmaan\NodeBundle\Entity\HasNodeInterface; |
||
11 | use Kunstmaan\NodeBundle\Entity\Node; |
||
12 | use Kunstmaan\NodeBundle\Entity\NodeTranslation; |
||
13 | use Kunstmaan\NodeBundle\Entity\NodeVersion; |
||
14 | use Kunstmaan\NodeBundle\Entity\PageInterface; |
||
15 | use Kunstmaan\NodeBundle\Helper\RenderContext; |
||
16 | use Kunstmaan\NodeSearchBundle\Event\IndexNodeEvent; |
||
17 | use Kunstmaan\NodeSearchBundle\Helper\IndexablePagePartsService; |
||
18 | use Kunstmaan\NodeSearchBundle\Helper\SearchViewTemplateInterface; |
||
19 | use Kunstmaan\PagePartBundle\Helper\HasPagePartsInterface; |
||
20 | use Kunstmaan\SearchBundle\Configuration\SearchConfigurationInterface; |
||
21 | use Kunstmaan\SearchBundle\Provider\SearchProviderInterface; |
||
22 | use Kunstmaan\SearchBundle\Search\AnalysisFactoryInterface; |
||
23 | use Kunstmaan\UtilitiesBundle\Helper\ClassLookup; |
||
24 | use Psr\Log\LoggerInterface; |
||
25 | use Symfony\Component\DependencyInjection\ContainerInterface; |
||
26 | use Symfony\Component\DomCrawler\Crawler; |
||
27 | use Symfony\Component\HttpFoundation\Request; |
||
28 | use Symfony\Component\Security\Acl\Domain\ObjectIdentity; |
||
29 | use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity; |
||
30 | use Symfony\Component\Security\Acl\Exception\AclNotFoundException; |
||
31 | use Symfony\Component\Security\Acl\Model\AclInterface; |
||
32 | use Symfony\Component\Security\Acl\Model\AclProviderInterface; |
||
33 | use Symfony\Component\Security\Acl\Model\AuditableEntryInterface; |
||
34 | use Symfony\Component\Templating\EngineInterface; |
||
35 | |||
36 | class NodePagesConfiguration implements SearchConfigurationInterface |
||
37 | { |
||
38 | /** @var string */ |
||
39 | protected $indexName; |
||
40 | |||
41 | /** @var string */ |
||
42 | protected $indexType; |
||
43 | |||
44 | /** @var SearchProviderInterface */ |
||
45 | protected $searchProvider; |
||
46 | |||
47 | /** @var array */ |
||
48 | protected $locales = []; |
||
49 | |||
50 | /** @var array */ |
||
51 | protected $analyzerLanguages; |
||
52 | |||
53 | /** @var EntityManager */ |
||
54 | protected $em; |
||
55 | |||
56 | /** @var array */ |
||
57 | protected $documents = []; |
||
58 | |||
59 | /** @var ContainerInterface */ |
||
60 | protected $container; |
||
61 | |||
62 | /** @var AclProviderInterface */ |
||
63 | protected $aclProvider = null; |
||
64 | |||
65 | /** @var LoggerInterface */ |
||
66 | protected $logger = null; |
||
67 | |||
68 | /** @var IndexablePagePartsService */ |
||
69 | protected $indexablePagePartsService; |
||
70 | |||
71 | /** @var DomainConfigurationInterface */ |
||
72 | protected $domainConfiguration; |
||
73 | |||
74 | /** @var array */ |
||
75 | protected $properties = []; |
||
76 | |||
77 | /** @var int */ |
||
78 | protected $numberOfShards; |
||
79 | |||
80 | /** @var int */ |
||
81 | protected $numberOfReplicas; |
||
82 | |||
83 | /** @var Node */ |
||
84 | protected $currentTopNode = null; |
||
85 | |||
86 | /** @var array */ |
||
87 | protected $nodeRefs = []; |
||
88 | |||
89 | /** |
||
90 | * @param ContainerInterface $container |
||
91 | * @param SearchProviderInterface $searchProvider |
||
92 | * @param string $name |
||
93 | * @param string $type |
||
94 | */ |
||
95 | public function __construct($container, $searchProvider, $name, $type, $numberOfShards = 1, $numberOfReplicas = 0) |
||
96 | { |
||
97 | $this->container = $container; |
||
98 | $this->indexName = $name; |
||
99 | $this->indexType = $type; |
||
100 | $this->searchProvider = $searchProvider; |
||
101 | $this->domainConfiguration = $this->container->get('kunstmaan_admin.domain_configuration'); |
||
102 | $this->locales = $this->domainConfiguration->getBackendLocales(); |
||
103 | $this->analyzerLanguages = $this->container->getParameter('analyzer_languages'); |
||
104 | $this->em = $this->container->get('doctrine')->getManager(); |
||
105 | $this->numberOfShards = $numberOfShards; |
||
106 | $this->numberOfReplicas = $numberOfReplicas; |
||
107 | } |
||
108 | |||
109 | /** |
||
110 | * @param AclProviderInterface $aclProvider |
||
111 | */ |
||
112 | public function setAclProvider(AclProviderInterface $aclProvider) |
||
113 | { |
||
114 | $this->aclProvider = $aclProvider; |
||
115 | } |
||
116 | |||
117 | /** |
||
118 | * @param IndexablePagePartsService $indexablePagePartsService |
||
119 | */ |
||
120 | public function setIndexablePagePartsService(IndexablePagePartsService $indexablePagePartsService) |
||
121 | { |
||
122 | $this->indexablePagePartsService = $indexablePagePartsService; |
||
123 | } |
||
124 | |||
125 | /** |
||
126 | * @param array $properties |
||
127 | */ |
||
128 | public function setDefaultProperties(array $properties) |
||
129 | { |
||
130 | $this->properties = array_merge($this->properties, $properties); |
||
131 | } |
||
132 | |||
133 | /** |
||
134 | * @param LoggerInterface $logger |
||
135 | */ |
||
136 | public function setLogger(LoggerInterface $logger) |
||
137 | { |
||
138 | $this->logger = $logger; |
||
139 | } |
||
140 | |||
141 | /** |
||
142 | * @return array |
||
143 | */ |
||
144 | public function getLanguagesNotAnalyzed() |
||
145 | { |
||
146 | $notAnalyzed = []; |
||
147 | foreach ($this->locales as $locale) { |
||
148 | if (preg_match('/[a-z]{2}_?+[a-zA-Z]{2}/', $locale)) { |
||
149 | $locale = strtolower($locale); |
||
150 | } |
||
151 | |||
152 | if (false === \array_key_exists($locale, $this->analyzerLanguages)) { |
||
153 | $notAnalyzed[] = $locale; |
||
154 | } |
||
155 | } |
||
156 | |||
157 | return $notAnalyzed; |
||
158 | } |
||
159 | |||
160 | /** |
||
161 | * Create node index |
||
162 | */ |
||
163 | public function createIndex() |
||
164 | { |
||
165 | //create analysis |
||
166 | $analysis = $this->container->get( |
||
167 | 'kunstmaan_search.search.factory.analysis' |
||
168 | ); |
||
169 | |||
170 | foreach ($this->locales as $locale) { |
||
171 | // Multilanguage check |
||
172 | if (preg_match('/[a-z]{2}_?+[a-zA-Z]{2}/', $locale)) { |
||
173 | $locale = strtolower($locale); |
||
174 | } |
||
175 | |||
176 | // Build new index |
||
177 | $index = $this->searchProvider->createIndex($this->indexName . '_' . $locale); |
||
178 | |||
179 | if (\array_key_exists($locale, $this->analyzerLanguages)) { |
||
180 | $localeAnalysis = clone $analysis; |
||
181 | $language = $this->analyzerLanguages[$locale]['analyzer']; |
||
182 | |||
183 | // Create index with analysis |
||
184 | $this->setAnalysis($index, $localeAnalysis->setupLanguage($language)); |
||
185 | } else { |
||
186 | $index->create(); |
||
187 | } |
||
188 | |||
189 | $this->setMapping($index, $locale); |
||
190 | } |
||
191 | } |
||
192 | |||
193 | /** |
||
194 | * Populate node index |
||
195 | */ |
||
196 | public function populateIndex() |
||
197 | { |
||
198 | $nodeRepository = $this->em->getRepository('KunstmaanNodeBundle:Node'); |
||
199 | $nodes = $nodeRepository->getAllTopNodes(); |
||
200 | |||
201 | foreach ($nodes as $node) { |
||
202 | $this->currentTopNode = $node; |
||
203 | foreach ($this->locales as $lang) { |
||
204 | $this->createNodeDocuments($node, $lang); |
||
205 | } |
||
206 | } |
||
207 | |||
208 | if (!empty($this->documents)) { |
||
209 | $this->searchProvider->addDocuments($this->documents); |
||
210 | $this->documents = []; |
||
211 | } |
||
212 | } |
||
213 | |||
214 | /** |
||
215 | * Index a node (including its children) - for the specified language only |
||
216 | * |
||
217 | * @param Node $node |
||
218 | * @param string $lang |
||
219 | */ |
||
220 | public function indexNode(Node $node, $lang) |
||
221 | { |
||
222 | $this->createNodeDocuments($node, $lang); |
||
223 | |||
224 | if (!empty($this->documents)) { |
||
225 | $this->searchProvider->addDocuments($this->documents); |
||
226 | $this->documents = []; |
||
227 | } |
||
228 | } |
||
229 | |||
230 | /** |
||
231 | * Add documents for the node translation (and children) to the index |
||
232 | * |
||
233 | * @param Node $node |
||
234 | * @param string $lang |
||
235 | */ |
||
236 | public function createNodeDocuments(Node $node, $lang) |
||
237 | { |
||
238 | $nodeTranslation = $node->getNodeTranslation($lang, true); |
||
239 | if ($nodeTranslation && $this->indexNodeTranslation($nodeTranslation)) { |
||
240 | $this->indexChildren($node, $lang); |
||
241 | } |
||
242 | } |
||
243 | |||
244 | /** |
||
245 | * Index all children of the specified node (only for the specified |
||
246 | * language) |
||
247 | * |
||
248 | * @param Node $node |
||
249 | * @param string $lang |
||
250 | */ |
||
251 | public function indexChildren(Node $node, $lang) |
||
252 | { |
||
253 | foreach ($node->getChildren() as $childNode) { |
||
254 | $this->indexNode($childNode, $lang); |
||
255 | } |
||
256 | } |
||
257 | |||
258 | /** |
||
259 | * Index a node translation |
||
260 | * |
||
261 | * @param NodeTranslation $nodeTranslation |
||
262 | * @param bool $add Add node immediately to index? |
||
263 | * |
||
264 | * @return bool Return true if the document has been indexed |
||
265 | */ |
||
266 | public function indexNodeTranslation(NodeTranslation $nodeTranslation, $add = false) |
||
267 | { |
||
268 | // Retrieve the public NodeVersion |
||
269 | $publicNodeVersion = $nodeTranslation->getPublicNodeVersion(); |
||
270 | if (\is_null($publicNodeVersion)) { |
||
271 | return false; |
||
272 | } |
||
273 | |||
274 | $refPage = $this->getNodeRefPage($publicNodeVersion); |
||
275 | if ($refPage->isStructureNode()) { |
||
276 | return true; |
||
277 | } |
||
278 | |||
279 | // Only index online NodeTranslations |
||
280 | if (!$nodeTranslation->isOnline()) { |
||
281 | return false; |
||
282 | } |
||
283 | |||
284 | $node = $nodeTranslation->getNode(); |
||
285 | if ($this->isIndexable($refPage)) { |
||
286 | // Retrieve the referenced entity from the public NodeVersion |
||
287 | $page = $publicNodeVersion->getRef($this->em); |
||
288 | |||
289 | $this->addPageToIndex($nodeTranslation, $node, $publicNodeVersion, $page); |
||
290 | if ($add) { |
||
291 | $this->searchProvider->addDocuments($this->documents); |
||
292 | $this->documents = []; |
||
293 | } |
||
294 | } |
||
295 | |||
296 | return true; // return true even if the page itself should not be indexed. This makes sure its children are being processed (i.e. structured nodes) |
||
297 | } |
||
298 | |||
299 | /** |
||
300 | * Return if the page is indexable - by default all pages are indexable, |
||
301 | * you can override this by implementing the IndexableInterface on your |
||
302 | * page entity and returning false in the isIndexable method. |
||
303 | * |
||
304 | * @param HasNodeInterface $page |
||
305 | * |
||
306 | * @return bool |
||
307 | */ |
||
308 | protected function isIndexable(HasNodeInterface $page) |
||
309 | { |
||
310 | return $this->container->get('kunstmaan_node.pages_configuration')->isIndexable($page); |
||
311 | } |
||
312 | |||
313 | /** |
||
314 | * Remove the specified node translation from the index |
||
315 | * |
||
316 | * @param NodeTranslation $nodeTranslation |
||
317 | */ |
||
318 | public function deleteNodeTranslation(NodeTranslation $nodeTranslation) |
||
319 | { |
||
320 | $uid = 'nodetranslation_' . $nodeTranslation->getId(); |
||
321 | $indexName = $this->indexName . '_' . $nodeTranslation->getLang(); |
||
322 | $this->searchProvider->deleteDocument($indexName, $this->indexType, $uid); |
||
323 | } |
||
324 | |||
325 | /** |
||
326 | * Delete the specified index |
||
327 | */ |
||
328 | public function deleteIndex() |
||
329 | { |
||
330 | foreach ($this->locales as $locale) { |
||
331 | $this->searchProvider->deleteIndex($this->indexName . '_' . $locale); |
||
332 | } |
||
333 | } |
||
334 | |||
335 | /** |
||
336 | * Apply the analysis factory to the index |
||
337 | * |
||
338 | * @param Index $index |
||
339 | * @param AnalysisFactoryInterface $analysis |
||
340 | */ |
||
341 | public function setAnalysis(Index $index, AnalysisFactoryInterface $analysis) |
||
342 | { |
||
343 | $index->create( |
||
344 | array( |
||
345 | 'number_of_shards' => $this->numberOfShards, |
||
346 | 'number_of_replicas' => $this->numberOfReplicas, |
||
347 | 'analysis' => $analysis->build(), |
||
348 | ) |
||
349 | ); |
||
350 | } |
||
351 | |||
352 | /** |
||
353 | * Return default search fields mapping for node translations |
||
354 | * |
||
355 | * @param Index $index |
||
356 | * @param string $lang |
||
357 | * |
||
358 | * @return Mapping |
||
359 | */ |
||
360 | protected function createDefaultSearchFieldsMapping(Index $index, $lang = 'en') |
||
361 | { |
||
362 | $mapping = new Mapping(); |
||
363 | $mapping->setType($index->getType($this->indexType)); |
||
364 | |||
365 | $mapping->setProperties($this->properties); |
||
366 | |||
367 | return $mapping; |
||
368 | } |
||
369 | |||
370 | /** |
||
371 | * Initialize the index with the default search fields mapping |
||
372 | * |
||
373 | * @param Index $index |
||
374 | * @param string $lang |
||
375 | */ |
||
376 | protected function setMapping(Index $index, $lang = 'en') |
||
377 | { |
||
378 | $mapping = $this->createDefaultSearchFieldsMapping($index, $lang); |
||
379 | $mapping->send(); |
||
380 | $index->refresh(); |
||
381 | } |
||
382 | |||
383 | /** |
||
384 | * Create a search document for a page |
||
385 | * |
||
386 | * @param NodeTranslation $nodeTranslation |
||
387 | * @param Node $node |
||
388 | * @param NodeVersion $publicNodeVersion |
||
389 | * @param HasNodeInterface $page |
||
390 | */ |
||
391 | protected function addPageToIndex( |
||
392 | NodeTranslation $nodeTranslation, |
||
393 | Node $node, |
||
394 | NodeVersion $publicNodeVersion, |
||
395 | HasNodeInterface $page |
||
396 | ) { |
||
397 | $rootNode = $this->currentTopNode; |
||
398 | if (!$rootNode) { |
||
399 | // Fetch main parent of current node... |
||
400 | $rootNode = $this->em->getRepository('KunstmaanNodeBundle:Node')->getRootNodeFor( |
||
401 | $node, |
||
402 | $nodeTranslation->getLang() |
||
403 | ); |
||
404 | } |
||
405 | |||
406 | $doc = array( |
||
407 | 'root_id' => $rootNode->getId(), |
||
408 | 'node_id' => $node->getId(), |
||
409 | 'node_translation_id' => $nodeTranslation->getId(), |
||
410 | 'node_version_id' => $publicNodeVersion->getId(), |
||
411 | 'title' => $nodeTranslation->getTitle(), |
||
412 | 'slug' => $nodeTranslation->getFullSlug(), |
||
413 | 'page_class' => ClassLookup::getClass($page), |
||
414 | 'created' => $this->getUTCDateTime( |
||
415 | $nodeTranslation->getCreated() |
||
416 | )->format(\DateTime::ISO8601), |
||
417 | 'updated' => $this->getUTCDateTime( |
||
418 | $nodeTranslation->getUpdated() |
||
419 | )->format(\DateTime::ISO8601), |
||
420 | ); |
||
421 | if ($this->logger) { |
||
422 | $this->logger->info('Indexing document : ' . implode(', ', $doc)); |
||
423 | } |
||
424 | |||
425 | // Permissions |
||
426 | $this->addPermissions($node, $doc); |
||
427 | |||
428 | // Search type |
||
429 | $this->addSearchType($page, $doc); |
||
430 | |||
431 | // Parent and Ancestors |
||
432 | $this->addParentAndAncestors($node, $doc); |
||
433 | |||
434 | // Content |
||
435 | $this->addPageContent($nodeTranslation, $page, $doc); |
||
436 | |||
437 | // Add document to index |
||
438 | $uid = 'nodetranslation_' . $nodeTranslation->getId(); |
||
439 | |||
440 | $this->addCustomData($page, $doc); |
||
441 | |||
442 | $this->documents[] = $this->searchProvider->createDocument( |
||
443 | $uid, |
||
444 | $doc, |
||
445 | $this->indexName . '_' . $nodeTranslation->getLang(), |
||
446 | $this->indexType |
||
447 | ); |
||
448 | } |
||
449 | |||
450 | /** |
||
451 | * Add view permissions to the index document |
||
452 | * |
||
453 | * @param Node $node |
||
454 | * @param array $doc |
||
455 | * |
||
456 | * @return array |
||
457 | */ |
||
458 | protected function addPermissions(Node $node, &$doc) |
||
459 | { |
||
460 | if (!\is_null($this->aclProvider)) { |
||
461 | $roles = $this->getAclPermissions($node); |
||
462 | } else { |
||
463 | // Fallback when no ACL available / assume everything is accessible... |
||
464 | $roles = array('IS_AUTHENTICATED_ANONYMOUSLY'); |
||
465 | } |
||
466 | $doc['view_roles'] = $roles; |
||
467 | } |
||
468 | |||
469 | /** |
||
470 | * Add type to the index document |
||
471 | * |
||
472 | * @param object $page |
||
473 | * @param array $doc |
||
474 | * |
||
475 | * @return array |
||
476 | */ |
||
477 | protected function addSearchType($page, &$doc) |
||
478 | { |
||
479 | $doc['type'] = $this->container->get('kunstmaan_node.pages_configuration')->getSearchType($page); |
||
480 | } |
||
481 | |||
482 | /** |
||
483 | * Add parent nodes to the index document |
||
484 | * |
||
485 | * @param Node $node |
||
486 | * @param array $doc |
||
487 | * |
||
488 | * @return array |
||
489 | */ |
||
490 | protected function addParentAndAncestors($node, &$doc) |
||
491 | { |
||
492 | $parent = $node->getParent(); |
||
493 | |||
494 | if ($parent) { |
||
495 | $doc['parent'] = $parent->getId(); |
||
496 | $ancestors = []; |
||
497 | do { |
||
498 | $ancestors[] = $parent->getId(); |
||
499 | $parent = $parent->getParent(); |
||
500 | } while ($parent); |
||
501 | $doc['ancestors'] = $ancestors; |
||
502 | } |
||
503 | } |
||
504 | |||
505 | /** |
||
506 | * Add page content to the index document |
||
507 | * |
||
508 | * @param NodeTranslation $nodeTranslation |
||
509 | * @param HasNodeInterface $page |
||
510 | * @param array $doc |
||
511 | */ |
||
512 | protected function addPageContent(NodeTranslation $nodeTranslation, $page, &$doc) |
||
513 | { |
||
514 | $this->enterRequestScope($nodeTranslation->getLang()); |
||
515 | if ($this->logger) { |
||
516 | $this->logger->debug( |
||
517 | sprintf( |
||
518 | 'Indexing page "%s" / lang : %s / type : %s / id : %d / node id : %d', |
||
519 | $page->getTitle(), |
||
520 | $nodeTranslation->getLang(), |
||
521 | \get_class($page), |
||
522 | $page->getId(), |
||
523 | $nodeTranslation->getNode()->getId() |
||
524 | ) |
||
525 | ); |
||
526 | } |
||
527 | |||
528 | $renderer = $this->container->get('templating'); |
||
529 | $doc['content'] = ''; |
||
530 | |||
531 | if ($page instanceof SearchViewTemplateInterface) { |
||
532 | $doc['content'] = $this->renderCustomSearchView($nodeTranslation, $page, $renderer); |
||
533 | |||
534 | return null; |
||
535 | } |
||
536 | |||
537 | if ($page instanceof HasPagePartsInterface) { |
||
538 | $doc['content'] = $this->renderDefaultSearchView($nodeTranslation, $page, $renderer); |
||
539 | |||
540 | return null; |
||
541 | } |
||
542 | } |
||
543 | |||
544 | /** |
||
545 | * Enter request scope if it is not active yet... |
||
546 | * |
||
547 | * @param string $lang |
||
548 | */ |
||
549 | protected function enterRequestScope($lang) |
||
550 | { |
||
551 | $requestStack = $this->container->get('request_stack'); |
||
552 | // If there already is a request, get the locale from it. |
||
553 | if ($requestStack->getCurrentRequest()) { |
||
554 | $locale = $requestStack->getCurrentRequest()->getLocale(); |
||
555 | } |
||
556 | // If we don't have a request or the current request locale is different from the node langauge |
||
557 | if (!$requestStack->getCurrentRequest() || ($locale && $locale !== $lang)) { |
||
0 ignored issues
–
show
|
|||
558 | $request = new Request(); |
||
559 | $request->setLocale($lang); |
||
560 | |||
561 | $context = $this->container->get('router')->getContext(); |
||
562 | $context->setParameter('_locale', $lang); |
||
563 | |||
564 | $requestStack->push($request); |
||
565 | } |
||
566 | } |
||
567 | |||
568 | /** |
||
569 | * Render a custom search view |
||
570 | * |
||
571 | * @param NodeTranslation $nodeTranslation |
||
572 | * @param SearchViewTemplateInterface $page |
||
573 | * @param EngineInterface $renderer |
||
574 | * |
||
575 | * @return string |
||
576 | */ |
||
577 | protected function renderCustomSearchView( |
||
578 | NodeTranslation $nodeTranslation, |
||
579 | SearchViewTemplateInterface $page, |
||
580 | EngineInterface $renderer |
||
581 | ) { |
||
582 | $view = $page->getSearchView(); |
||
583 | $renderContext = new RenderContext([ |
||
584 | 'locale' => $nodeTranslation->getLang(), |
||
585 | 'page' => $page, |
||
586 | 'indexMode' => true, |
||
587 | 'nodetranslation' => $nodeTranslation, |
||
588 | ]); |
||
589 | |||
590 | if ($page instanceof PageInterface) { |
||
591 | $request = $this->container->get('request_stack')->getCurrentRequest(); |
||
592 | $page->service($this->container, $request, $renderContext); |
||
593 | } |
||
594 | |||
595 | $content = $this->removeHtml( |
||
596 | $renderer->render( |
||
597 | $view, |
||
598 | $renderContext->getArrayCopy() |
||
599 | ) |
||
600 | ); |
||
601 | |||
602 | return $content; |
||
603 | } |
||
604 | |||
605 | /** |
||
606 | * Render default search view (all indexable pageparts in the main context |
||
607 | * of the page) |
||
608 | * |
||
609 | * @param NodeTranslation $nodeTranslation |
||
610 | * @param HasPagePartsInterface $page |
||
611 | * @param EngineInterface $renderer |
||
612 | * |
||
613 | * @return string |
||
614 | */ |
||
615 | protected function renderDefaultSearchView( |
||
616 | NodeTranslation $nodeTranslation, |
||
617 | HasPagePartsInterface $page, |
||
618 | EngineInterface $renderer |
||
619 | ) { |
||
620 | $pageparts = $this->indexablePagePartsService->getIndexablePageParts($page); |
||
621 | $view = 'KunstmaanNodeSearchBundle:PagePart:view.html.twig'; |
||
622 | $content = $this->removeHtml( |
||
623 | $renderer->render( |
||
624 | $view, |
||
625 | array( |
||
626 | 'locale' => $nodeTranslation->getLang(), |
||
627 | 'page' => $page, |
||
628 | 'pageparts' => $pageparts, |
||
629 | 'indexMode' => true, |
||
630 | ) |
||
631 | ) |
||
632 | ); |
||
633 | |||
634 | return $content; |
||
635 | } |
||
636 | |||
637 | /** |
||
638 | * Add custom data to index document (you can override to add custom fields |
||
639 | * to the search index) |
||
640 | * |
||
641 | * @param HasNodeInterface $page |
||
642 | * @param array $doc |
||
643 | */ |
||
644 | protected function addCustomData(HasNodeInterface $page, &$doc) |
||
645 | { |
||
646 | $event = new IndexNodeEvent($page, $doc); |
||
647 | $this->container->get('event_dispatcher')->dispatch(IndexNodeEvent::EVENT_INDEX_NODE, $event); |
||
648 | |||
649 | $doc = $event->doc; |
||
650 | |||
651 | if ($page instanceof HasCustomSearchDataInterface) { |
||
652 | $doc += $page->getCustomSearchData($doc); |
||
653 | } |
||
654 | } |
||
655 | |||
656 | /** |
||
657 | * Convert a DateTime to UTC equivalent... |
||
658 | * |
||
659 | * @param \DateTime $dateTime |
||
660 | * |
||
661 | * @return \DateTime |
||
662 | */ |
||
663 | protected function getUTCDateTime(\DateTime $dateTime) |
||
664 | { |
||
665 | $result = clone $dateTime; |
||
666 | $result->setTimezone(new \DateTimeZone('UTC')); |
||
667 | |||
668 | return $result; |
||
669 | } |
||
670 | |||
671 | /** |
||
672 | * Removes all HTML markup & decode HTML entities |
||
673 | * |
||
674 | * @param $text |
||
675 | * |
||
676 | * @return string |
||
677 | */ |
||
678 | protected function removeHtml($text) |
||
679 | { |
||
680 | if (!trim($text)) { |
||
681 | return ''; |
||
682 | } |
||
683 | |||
684 | // Remove Styles and Scripts |
||
685 | $crawler = new Crawler(); |
||
686 | $crawler->addHtmlContent($text); |
||
687 | $crawler->filter('style, script')->each(function (Crawler $crawler) { |
||
688 | foreach ($crawler as $node) { |
||
689 | $node->parentNode->removeChild($node); |
||
690 | } |
||
691 | }); |
||
692 | $text = $crawler->html(); |
||
693 | |||
694 | // Remove HTML markup |
||
695 | $result = strip_tags($text); |
||
696 | |||
697 | // Decode HTML entities |
||
698 | $result = trim(html_entity_decode($result, ENT_QUOTES)); |
||
699 | |||
700 | return $result; |
||
701 | } |
||
702 | |||
703 | /** |
||
704 | * Fetch ACL permissions for the specified entity |
||
705 | * |
||
706 | * @param object $object |
||
707 | * |
||
708 | * @return array |
||
709 | */ |
||
710 | protected function getAclPermissions($object) |
||
711 | { |
||
712 | $roles = []; |
||
713 | |||
714 | try { |
||
715 | $objectIdentity = ObjectIdentity::fromDomainObject($object); |
||
716 | |||
717 | /* @var AclInterface $acl */ |
||
718 | $acl = $this->aclProvider->findAcl($objectIdentity); |
||
719 | $objectAces = $acl->getObjectAces(); |
||
720 | |||
721 | /* @var AuditableEntryInterface $ace */ |
||
722 | View Code Duplication | foreach ($objectAces as $ace) { |
|
723 | $securityIdentity = $ace->getSecurityIdentity(); |
||
724 | if ( |
||
725 | $securityIdentity instanceof RoleSecurityIdentity && |
||
726 | ($ace->getMask() & MaskBuilder::MASK_VIEW != 0) |
||
727 | ) { |
||
728 | $roles[] = $securityIdentity->getRole(); |
||
729 | } |
||
730 | } |
||
731 | } catch (AclNotFoundException $e) { |
||
732 | // No ACL found... assume default |
||
733 | $roles = array('IS_AUTHENTICATED_ANONYMOUSLY'); |
||
734 | } |
||
735 | |||
736 | return $roles; |
||
737 | } |
||
738 | |||
739 | /** |
||
740 | * @param $publicNodeVersion |
||
741 | * |
||
742 | * @return mixed |
||
743 | */ |
||
744 | private function getNodeRefPage(NodeVersion $publicNodeVersion) |
||
745 | { |
||
746 | $refEntityName = $publicNodeVersion->getRefEntityName(); |
||
747 | |||
748 | if (!isset($this->nodeRefs[$refEntityName])) { |
||
749 | $this->nodeRefs[$refEntityName] = new $refEntityName(); |
||
750 | } |
||
751 | |||
752 | return $this->nodeRefs[$refEntityName]; |
||
753 | } |
||
754 | } |
||
755 |
If you define a variable conditionally, it can happen that it is not defined for all execution paths.
Let’s take a look at an example:
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.
Available Fixes
Check for existence of the variable explicitly:
Define a default value for the variable:
Add a value for the missing path: