Completed
Push — master ( 1de9b7...830752 )
by Kristof
38:46 queued 24:09
created

Configuration/NodePagesConfiguration.php (7 issues)

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');
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->container->getPar...r('analyzer_languages') of type * is incompatible with the declared type array of property $analyzerLanguages.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
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) {
240
            if ($this->indexNodeTranslation($nodeTranslation)) {
241
                $this->indexChildren($node, $lang);
242
            }
243
        }
244
    }
245
246
    /**
247
     * Index all children of the specified node (only for the specified
248
     * language)
249
     *
250
     * @param Node   $node
251
     * @param string $lang
252
     */
253
    public function indexChildren(Node $node, $lang)
254
    {
255
        foreach ($node->getChildren() as $childNode) {
256
            $this->indexNode($childNode, $lang);
257
        }
258
    }
259
260
    /**
261
     * Index a node translation
262
     *
263
     * @param NodeTranslation $nodeTranslation
264
     * @param bool            $add             Add node immediately to index?
265
     *
266
     * @return bool Return true if the document has been indexed
267
     */
268
    public function indexNodeTranslation(NodeTranslation $nodeTranslation, $add = false)
269
    {
270
        // Retrieve the public NodeVersion
271
        $publicNodeVersion = $nodeTranslation->getPublicNodeVersion();
272
        if (is_null($publicNodeVersion)) {
273
            return false;
274
        }
275
276
        $refPage = $this->getNodeRefPage($publicNodeVersion);
277
        if ($refPage->isStructureNode()) {
278
            return true;
279
        }
280
281
        // Only index online NodeTranslations
282
        if (!$nodeTranslation->isOnline()) {
283
            return false;
284
        }
285
286
        $node = $nodeTranslation->getNode();
287
        if ($this->isIndexable($refPage)) {
288
            // Retrieve the referenced entity from the public NodeVersion
289
            $page = $publicNodeVersion->getRef($this->em);
290
291
            $this->addPageToIndex($nodeTranslation, $node, $publicNodeVersion, $page);
0 ignored issues
show
It seems like $page defined by $publicNodeVersion->getRef($this->em) on line 289 can be null; however, Kunstmaan\NodeSearchBund...ation::addPageToIndex() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
292
            if ($add) {
293
                $this->searchProvider->addDocuments($this->documents);
294
                $this->documents = [];
295
            }
296
        }
297
298
        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)
299
    }
300
301
    /**
302
     * Return if the page is indexable - by default all pages are indexable,
303
     * you can override this by implementing the IndexableInterface on your
304
     * page entity and returning false in the isIndexable method.
305
     *
306
     * @param HasNodeInterface $page
307
     *
308
     * @return bool
309
     */
310
    protected function isIndexable(HasNodeInterface $page)
311
    {
312
        return $this->container->get('kunstmaan_node.pages_configuration')->isIndexable($page);
313
    }
314
315
    /**
316
     * Remove the specified node translation from the index
317
     *
318
     * @param NodeTranslation $nodeTranslation
319
     */
320
    public function deleteNodeTranslation(NodeTranslation $nodeTranslation)
321
    {
322
        $uid = 'nodetranslation_' . $nodeTranslation->getId();
323
        $indexName = $this->indexName . '_' . $nodeTranslation->getLang();
324
        $this->searchProvider->deleteDocument($indexName, $this->indexType, $uid);
325
    }
326
327
    /**
328
     * Delete the specified index
329
     */
330
    public function deleteIndex()
331
    {
332
        foreach ($this->locales as $locale) {
333
            $this->searchProvider->deleteIndex($this->indexName . '_' . $locale);
334
        }
335
    }
336
337
    /**
338
     * Apply the analysis factory to the index
339
     *
340
     * @param Index                    $index
341
     * @param AnalysisFactoryInterface $analysis
342
     */
343
    public function setAnalysis(Index $index, AnalysisFactoryInterface $analysis)
344
    {
345
        $index->create(
346
            array(
347
                'number_of_shards' => $this->numberOfShards,
348
                'number_of_replicas' => $this->numberOfReplicas,
349
                'analysis' => $analysis->build(),
350
            )
351
        );
352
    }
353
354
    /**
355
     * Return default search fields mapping for node translations
356
     *
357
     * @param Index  $index
358
     * @param string $lang
359
     *
360
     * @return Mapping
361
     */
362
    protected function createDefaultSearchFieldsMapping(Index $index, $lang = 'en')
363
    {
364
        $mapping = new Mapping();
365
        $mapping->setType($index->getType($this->indexType));
366
367
        $mapping->setProperties($this->properties);
368
369
        return $mapping;
370
    }
371
372
    /**
373
     * Initialize the index with the default search fields mapping
374
     *
375
     * @param Index  $index
376
     * @param string $lang
377
     */
378
    protected function setMapping(Index $index, $lang = 'en')
379
    {
380
        $mapping = $this->createDefaultSearchFieldsMapping($index, $lang);
381
        $mapping->send();
382
        $index->refresh();
383
    }
384
385
    /**
386
     * Create a search document for a page
387
     *
388
     * @param NodeTranslation  $nodeTranslation
389
     * @param Node             $node
390
     * @param NodeVersion      $publicNodeVersion
391
     * @param HasNodeInterface $page
392
     */
393
    protected function addPageToIndex(
394
        NodeTranslation $nodeTranslation,
395
        Node $node,
396
        NodeVersion $publicNodeVersion,
397
        HasNodeInterface $page
398
    ) {
399
        $rootNode = $this->currentTopNode;
400
        if (!$rootNode) {
401
            // Fetch main parent of current node...
402
            $rootNode = $this->em->getRepository('KunstmaanNodeBundle:Node')->getRootNodeFor(
403
                $node,
404
                $nodeTranslation->getLang()
405
            );
406
        }
407
408
        $doc = array(
409
            'root_id' => $rootNode->getId(),
410
            'node_id' => $node->getId(),
411
            'node_translation_id' => $nodeTranslation->getId(),
412
            'node_version_id' => $publicNodeVersion->getId(),
413
            'title' => $nodeTranslation->getTitle(),
414
            'slug' => $nodeTranslation->getFullSlug(),
415
            'page_class' => ClassLookup::getClass($page),
416
            'created' => $this->getUTCDateTime(
417
                $nodeTranslation->getCreated()
418
            )->format(\DateTime::ISO8601),
419
            'updated' => $this->getUTCDateTime(
420
                $nodeTranslation->getUpdated()
421
            )->format(\DateTime::ISO8601),
422
        );
423
        if ($this->logger) {
424
            $this->logger->info('Indexing document : ' . implode(', ', $doc));
425
        }
426
427
        // Permissions
428
        $this->addPermissions($node, $doc);
429
430
        // Search type
431
        $this->addSearchType($page, $doc);
432
433
        // Parent and Ancestors
434
        $this->addParentAndAncestors($node, $doc);
435
436
        // Content
437
        $this->addPageContent($nodeTranslation, $page, $doc);
438
439
        // Add document to index
440
        $uid = 'nodetranslation_' . $nodeTranslation->getId();
441
442
        $this->addCustomData($page, $doc);
443
444
        $this->documents[] = $this->searchProvider->createDocument(
445
            $uid,
446
            $doc,
0 ignored issues
show
$doc is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
447
            $this->indexName . '_' . $nodeTranslation->getLang(),
448
            $this->indexType
449
        );
450
    }
451
452
    /**
453
     * Add view permissions to the index document
454
     *
455
     * @param Node  $node
456
     * @param array $doc
457
     *
458
     * @return array
0 ignored issues
show
Should the return type not be array|null? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
459
     */
460
    protected function addPermissions(Node $node, &$doc)
461
    {
462
        if (!is_null($this->aclProvider)) {
463
            $roles = $this->getAclPermissions($node);
464
        } else {
465
            // Fallback when no ACL available / assume everything is accessible...
466
            $roles = array('IS_AUTHENTICATED_ANONYMOUSLY');
467
        }
468
        $doc['view_roles'] = $roles;
469
    }
470
471
    /**
472
     * Add type to the index document
473
     *
474
     * @param object $page
475
     * @param array  $doc
476
     *
477
     * @return array
0 ignored issues
show
Should the return type not be array|null? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
478
     */
479
    protected function addSearchType($page, &$doc)
480
    {
481
        $doc['type'] = $this->container->get('kunstmaan_node.pages_configuration')->getSearchType($page);
482
    }
483
484
    /**
485
     * Add parent nodes to the index document
486
     *
487
     * @param Node  $node
488
     * @param array $doc
489
     *
490
     * @return array
0 ignored issues
show
Should the return type not be array|null? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
491
     */
492
    protected function addParentAndAncestors($node, &$doc)
493
    {
494
        $parent = $node->getParent();
495
496
        if ($parent) {
497
            $doc['parent'] = $parent->getId();
498
            $ancestors = [];
499
            do {
500
                $ancestors[] = $parent->getId();
501
                $parent = $parent->getParent();
502
            } while ($parent);
503
            $doc['ancestors'] = $ancestors;
504
        }
505
    }
506
507
    /**
508
     * Add page content to the index document
509
     *
510
     * @param NodeTranslation  $nodeTranslation
511
     * @param HasNodeInterface $page
512
     * @param array            $doc
513
     */
514
    protected function addPageContent(NodeTranslation $nodeTranslation, $page, &$doc)
515
    {
516
        $this->enterRequestScope($nodeTranslation->getLang());
517
        if ($this->logger) {
518
            $this->logger->debug(
519
                sprintf(
520
                    'Indexing page "%s" / lang : %s / type : %s / id : %d / node id : %d',
521
                    $page->getTitle(),
522
                    $nodeTranslation->getLang(),
523
                    get_class($page),
524
                    $page->getId(),
525
                    $nodeTranslation->getNode()->getId()
526
                )
527
            );
528
        }
529
530
        $renderer = $this->container->get('templating');
531
        $doc['content'] = '';
532
533
        if ($page instanceof SearchViewTemplateInterface) {
534
            $doc['content'] = $this->renderCustomSearchView($nodeTranslation, $page, $renderer);
535
536
            return null;
537
        }
538
539
        if ($page instanceof HasPagePartsInterface) {
540
            $doc['content'] = $this->renderDefaultSearchView($nodeTranslation, $page, $renderer);
541
542
            return null;
543
        }
544
    }
545
546
    /**
547
     * Enter request scope if it is not active yet...
548
     *
549
     * @param string $lang
550
     */
551
    protected function enterRequestScope($lang)
552
    {
553
        $requestStack = $this->container->get('request_stack');
554
        // If there already is a request, get the locale from it.
555
        if ($requestStack->getCurrentRequest()) {
556
            $locale = $requestStack->getCurrentRequest()->getLocale();
557
        }
558
        // If we don't have a request or the current request locale is different from the node langauge
559
        if (!$requestStack->getCurrentRequest() || ($locale && $locale !== $lang)) {
560
            $request = new Request();
561
            $request->setLocale($lang);
562
563
            $context = $this->container->get('router')->getContext();
564
            $context->setParameter('_locale', $lang);
565
566
            $requestStack->push($request);
567
        }
568
    }
569
570
    /**
571
     * Render a custom search view
572
     *
573
     * @param NodeTranslation             $nodeTranslation
574
     * @param SearchViewTemplateInterface $page
575
     * @param EngineInterface             $renderer
576
     *
577
     * @return string
578
     */
579
    protected function renderCustomSearchView(
580
        NodeTranslation $nodeTranslation,
581
        SearchViewTemplateInterface $page,
582
        EngineInterface $renderer
583
    ) {
584
        $view = $page->getSearchView();
585
        $renderContext = new RenderContext([
586
            'locale' => $nodeTranslation->getLang(),
587
            'page' => $page,
588
            'indexMode' => true,
589
            'nodetranslation' => $nodeTranslation,
590
        ]);
591
592
        if ($page instanceof PageInterface) {
593
            $request = $this->container->get('request_stack')->getCurrentRequest();
594
            $page->service($this->container, $request, $renderContext);
595
        }
596
597
        $content = $this->removeHtml(
598
            $renderer->render(
599
                $view,
600
                $renderContext->getArrayCopy()
601
            )
602
        );
603
604
        return $content;
605
    }
606
607
    /**
608
     * Render default search view (all indexable pageparts in the main context
609
     * of the page)
610
     *
611
     * @param NodeTranslation       $nodeTranslation
612
     * @param HasPagePartsInterface $page
613
     * @param EngineInterface       $renderer
614
     *
615
     * @return string
616
     */
617
    protected function renderDefaultSearchView(
618
        NodeTranslation $nodeTranslation,
619
        HasPagePartsInterface $page,
620
        EngineInterface $renderer
621
    ) {
622
        $pageparts = $this->indexablePagePartsService->getIndexablePageParts($page);
623
        $view = 'KunstmaanNodeSearchBundle:PagePart:view.html.twig';
624
        $content = $this->removeHtml(
625
            $renderer->render(
626
                $view,
627
                array(
628
                    'locale' => $nodeTranslation->getLang(),
629
                    'page' => $page,
630
                    'pageparts' => $pageparts,
631
                    'indexMode' => true,
632
                )
633
            )
634
        );
635
636
        return $content;
637
    }
638
639
    /**
640
     * Add custom data to index document (you can override to add custom fields
641
     * to the search index)
642
     *
643
     * @param HasNodeInterface $page
644
     * @param array            $doc
645
     */
646
    protected function addCustomData(HasNodeInterface $page, &$doc)
647
    {
648
        $event = new IndexNodeEvent($page, $doc);
649
        $this->container->get('event_dispatcher')->dispatch(IndexNodeEvent::EVENT_INDEX_NODE, $event);
650
651
        $doc = $event->doc;
652
653
        if ($page instanceof HasCustomSearchDataInterface) {
654
            $doc += $page->getCustomSearchData($doc);
655
        }
656
    }
657
658
    /**
659
     * Convert a DateTime to UTC equivalent...
660
     *
661
     * @param \DateTime $dateTime
662
     *
663
     * @return \DateTime
664
     */
665
    protected function getUTCDateTime(\DateTime $dateTime)
666
    {
667
        $result = clone $dateTime;
668
        $result->setTimezone(new \DateTimeZone('UTC'));
669
670
        return $result;
671
    }
672
673
    /**
674
     * Removes all HTML markup & decode HTML entities
675
     *
676
     * @param $text
677
     *
678
     * @return string
679
     */
680
    protected function removeHtml($text)
681
    {
682
        if (!trim($text)) {
683
            return '';
684
        }
685
686
        // Remove Styles and Scripts
687
        $crawler = new Crawler($text);
688
        $crawler->filter('style, script')->each(function (Crawler $crawler) {
689
            foreach ($crawler as $node) {
690
                $node->parentNode->removeChild($node);
691
            }
692
        });
693
        $text = $crawler->html();
694
695
        // Remove HTML markup
696
        $result = strip_tags($text);
697
698
        // Decode HTML entities
699
        $result = trim(html_entity_decode($result, ENT_QUOTES));
700
701
        return $result;
702
    }
703
704
    /**
705
     * Fetch ACL permissions for the specified entity
706
     *
707
     * @param object $object
708
     *
709
     * @return array
710
     */
711
    protected function getAclPermissions($object)
712
    {
713
        $roles = [];
714
715
        try {
716
            $objectIdentity = ObjectIdentity::fromDomainObject($object);
717
718
            /* @var AclInterface $acl */
719
            $acl = $this->aclProvider->findAcl($objectIdentity);
720
            $objectAces = $acl->getObjectAces();
721
722
            /* @var AuditableEntryInterface $ace */
723 View Code Duplication
            foreach ($objectAces as $ace) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
724
                $securityIdentity = $ace->getSecurityIdentity();
725
                if (
726
                    $securityIdentity instanceof RoleSecurityIdentity &&
727
                    ($ace->getMask() & MaskBuilder::MASK_VIEW != 0)
728
                ) {
729
                    $roles[] = $securityIdentity->getRole();
730
                }
731
            }
732
        } catch (AclNotFoundException $e) {
733
            // No ACL found... assume default
734
            $roles = array('IS_AUTHENTICATED_ANONYMOUSLY');
735
        }
736
737
        return $roles;
738
    }
739
740
    /**
741
     * @param $publicNodeVersion
742
     *
743
     * @return mixed
744
     */
745
    private function getNodeRefPage(NodeVersion $publicNodeVersion)
746
    {
747
        $refEntityName = $publicNodeVersion->getRefEntityName();
748
749
        if (!isset($this->nodeRefs[$refEntityName])) {
750
            $this->nodeRefs[$refEntityName] = new $refEntityName();
751
        }
752
753
        return $this->nodeRefs[$refEntityName];
754
    }
755
}
756