Completed
Push — master ( aba493...5356ed )
by Ruud
315:38 queued 305:00
created

Configuration/NodePagesConfiguration.php (1 issue)

Upgrade to new PHP Analysis Engine

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
The variable $locale does not seem to be defined for all execution paths leading up to this point.

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:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

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

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
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