Completed
Push — master ( 1a117b...43f8bd )
by Mikael
11:04
created

src/Content/FileBasedContent.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 Anax\Content;
4
5
use Anax\Commons\ContainerInjectableInterface;
6
use Anax\Commons\ContainerInjectableTrait;
7
8
/**
9
 * Pages based on file content.
10
 */
11
class FileBasedContent implements ContainerInjectableInterface
12
{
13
    use ContainerInjectableTrait,
14
        FBCBreadcrumbTrait,
15
        FBCLoadAdditionalContentTrait,
16
        FBCUtilitiesTrait;
17
18
19
20
    /**
21
     * All routes.
22
     */
23
    private $index = null;
24
25
    /**
26
     * All authors.
27
     */
28
    private $author = null;
29
30
    /**
31
     * All categories.
32
     */
33
    private $category = null;
34
35
    /**
36
     * All routes having meta.
37
     */
38
    private $meta = null;
39
40
    /**
41
     * This is the base route.
42
     */
43
    private $baseRoute = null;
44
45
    /**
46
     * This is the extendede meta route, if any.
47
     */
48
    private $metaRoute = null;
49
50
    /**
51
     * This is the current page, to supply pagination, if used.
52
     */
53
    private $currentPage = null;
54
55
    /**
56
     * Use cache or recreate each time.
57
     */
58
    private $ignoreCache = false;
59
    
60
    /**
61
     * File name pattern, all files must match this pattern and the first
62
     * numbered part is optional, the second part becomes the route.
63
     */
64
    private $filenamePattern = "#^(\d*)_*([^\.]+)\.md$#";
65
66
    /**
67
     * Internal routes that is marked as internal content routes and not
68
     * exposed as public routes.
69
     */
70
    private $internalRouteDirPattern = [
71
        "#block/#",
72
    ];
73
74
    private $internalRouteFilePattern = [
75
        "#^block[_-]{1}#",
76
        "#^_#",
77
    ];
78
79
    /**
80
     * Routes that should be used in toc.
81
     */
82
    private $allowedInTocPattern = "([\d]+_(\w)+)";
83
84
85
86
    /**
87
     * Set default values from configuration.
88
     *
89
     * @param array $config the configuration to use.
90
     *
91
     * @return void
92
     */
93 1
    public function configure(array $config) : void
94
    {
95 1
        $this->config = $config;
0 ignored issues
show
The property config does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
96 1
        $this->setDefaultsFromConfiguration();
97 1
    }
98
99
100
101
    /**
102
     * Set default values from configuration.
103
     *
104
     * @return this.
105
     */
106 1
    private function setDefaultsFromConfiguration()
107
    {
108 1
        $this->ignoreCache = isset($this->config["ignoreCache"])
109 1
            ? $this->config["ignoreCache"]
110
            : $this->ignoreCache;
111
112 1
        return $this;
113
    }
114
115
116
117
    /**
118
     * Should the cache be used or ignored.
119
     *
120
     * @param boolean $use true to use the cache or false to ignore the cache
121
     *
122
     * @return this.
123
     */
124
    public function useCache($use)
125
    {
126
        $this->ignoreCache = !$use;
127
128
        return $this;
129
    }
130
131
132
133
    /**
134
     * Create the index of all content into an array.
135
     *
136
     * @param string $type of index to load.
137
     *
138
     * @return void.
139
     */
140
    private function load($type)
141
    {
142
        $index = $this->$type;
143
        if ($index) {
144
            return;
145
        }
146
147
        $cache = $this->di->get("cache");
148
        $key = $cache->createKey(__CLASS__, $type);
149
        $index = $cache->get($key);
150
151
        if (is_null($index) || $this->ignoreCache) {
152
            $createMethod = "create$type";
153
            $index = $this->$createMethod();
154
            $cache->set($key, $index);
155
        }
156
157
        $this->$type = $index;
158
    }
159
160
161
162
163
    // = Create and manage index ==================================
164
165
    /**
166
     * Generate an index from the directory structure.
167
     *
168
     * @return array as index for all content files.
169
     */
170
    private function createIndex()
171
    {
172
        $basepath   = $this->config["basePath"];
173
        $pattern    = $this->config["pattern"];
174
        $path       = "$basepath/$pattern";
175
176
        $index = [];
177
        foreach (glob_recursive($path) as $file) {
178
            $filepath = substr($file, strlen($basepath) + 1);
179
180
            // Find content files
181
            $matches = [];
182
            preg_match($this->filenamePattern, basename($filepath), $matches);
183
            $dirpart = dirname($filepath) . "/";
184
            if ($dirpart === "./") {
185
                $dirpart = null;
186
            }
187
            $key = $dirpart . $matches[2];
188
            
189
            // Create level depending on the file id
190
            // TODO ciamge doc, can be replaced by __toc__ in meta?
191
            $id = (int) $matches[1];
192
            $level = 2;
193
            if ($id % 100 === 0) {
194
                $level = 0;
195
            } elseif ($id % 10 === 0) {
196
                $level = 1;
197
            }
198
199
            $index[$key] = [
200
                "file"     => $filepath,
201
                "section"  => $matches[1],
202
                "level"    => $level,  // TODO ?
203
                "internal" => $this->isInternalRoute($filepath),
204
                "tocable"  => $this->allowInToc($filepath),
205
            ];
206
        }
207
208
        return $index;
209
    }
210
211
212
213
    /**
214
     * Check if a filename is to be marked as an internal route..
215
     *
216
     * @param string $filepath as the basepath (routepart) to the file.
217
     *
218
     * @return boolean true if the route content is internal, else false
219
     */
220
    private function isInternalRoute($filepath)
221
    {
222
        foreach ($this->internalRouteDirPattern as $pattern) {
223
            if (preg_match($pattern, $filepath)) {
224
                return true;
225
            }
226
        }
227
228
        $filename = basename($filepath);
229
        foreach ($this->internalRouteFilePattern as $pattern) {
230
            if (preg_match($pattern, $filename)) {
231
                return true;
232
            }
233
        }
234
235
        return false;
236
    }
237
238
239
240
    /**
241
     * Check if filepath should be used as part of toc.
242
     *
243
     * @param string $filepath as the basepath (routepart) to the file.
244
     *
245
     * @return boolean true if the route content shoul dbe in toc, else false
246
     */
247
    private function allowInToc($filepath)
248
    {
249
        return (boolean) preg_match($this->allowedInTocPattern, $filepath);
250
    }
251
252
253
254
    // = Create and manage meta ==================================
255
256
    /**
257
     * Generate an index for meta files.
258
     *
259
     * @return array as meta index.
260
     */
261
    private function createMeta()
262
    {
263
        $basepath = $this->config["basePath"];
264
        $filter   = $this->config["textfilter-frontmatter"];
265
        $pattern  = $this->config["meta"];
266
        $path     = "$basepath/$pattern";
267
        $textfilter = $this->di->get("textfilter");
268
269
        $index = [];
270
        foreach (glob_recursive($path) as $file) {
271
            // The key entry to index
272
            $key = dirname(substr($file, strlen($basepath) + 1));
273
274
            // Get info from base document
275
            $src = file_get_contents($file);
276
            $filtered = $textfilter->parse($src, $filter);
277
            $index[$key] = $filtered->frontmatter;
278
279
            // Add Toc to the data array
280
            $index[$key]["__toc__"] = $this->createBaseRouteToc($key);
281
        }
282
283
        // Add author details
284
        $this->meta = $index;
285
        $this->createAuthor();
286
        $this->createCategory();
287
288
        return $this->meta;
289
    }
290
291
292
293
    /**
294
     * Get a reference to meta data for specific route.
295
     *
296
     * @param string $route current route used to access page.
297
     *
298
     * @return array as table of content.
299
     */
300
    private function getMetaForRoute($route)
301
    {
302
        $base = dirname($route);
303
        return isset($this->meta[$base])
304
            ? $this->meta[$base]
305
            : [];
306
    }
307
308
309
310
    /**
311
     * Create a table of content for routes at particular level.
312
     *
313
     * @param string $route base route to use.
314
     *
315
     * @return array as the toc.
316
     */
317
    private function createBaseRouteToc($route)
318
    {
319
        $toc = [];
320
        $len = strlen($route);
321
322
        foreach ($this->index as $key => $value) {
323
            if (substr($key, 0, $len + 1) === "$route/") {
324
                if ($value["internal"] === false
325
                    && $value["tocable"] === true) {
326
                    $toc[$key] = $value;
327
                    
328
                    $frontm = $this->getFrontmatter($value["file"]);
329
                    $toc[$key]["title"] = $frontm["title"];
330
                    $toc[$key]["publishTime"] = $this->getPublishTime($frontm);
331
                    $toc[$key]["sectionHeader"] = isset($frontm["sectionHeader"])
332
                        ? $frontm["sectionHeader"]
333
                        : null;
334
                    $toc[$key]["linkable"] = isset($frontm["linkable"])
335
                        ? $frontm["linkable"]
336
                        : null;
337
                }
338
            }
339
        };
340
341
        return $toc;
342
    }
343
344
345
346
    // = Deal with authors ====================================
347
    
348
    /**
349
     * Generate a lookup index for authors that maps into the meta entry
350
     * for the author.
351
     *
352
     * @return void.
353
     */
354
    private function createAuthor()
355
    {
356
        $pattern = $this->config["author"];
357
358
        $index = [];
359
        $matches = [];
360
        foreach ($this->meta as $key => $entry) {
361
            if (preg_match($pattern, $key, $matches)) {
362
                $acronym = $matches[1];
363
                $index[$acronym] = $key;
364
                $this->meta[$key]["acronym"] = $acronym;
365
                $this->meta[$key]["url"] = $key;
366
                unset($this->meta[$key]["__toc__"]);
367
368
                // Get content for byline
369
                $route = "$key/byline";
370
                $data = $this->getDataForAdditionalRoute($route);
371
                $byline = isset($data["data"]["content"]) ? $data["data"]["content"] : null;
372
                $this->meta[$key]["byline"] = $byline;
373
            }
374
        }
375
376
        return $index;
377
    }
378
379
380
381
    /**
382
     * Load details for the author.
383
     *
384
     * @param array|string $author with details on the author(s).
385
     *
386
     * @return array with more details on the authors(s).
387
     */
388 View Code Duplication
    private function loadAuthorDetails($author)
389
    {
390
        if (is_array($author) && is_array(array_values($author)[0])) {
391
            return $author;
392
        }
393
394
        if (!is_array($author)) {
395
            $tmp = $author;
396
            $author = [];
397
            $author[] = $tmp;
398
        }
399
400
        $authors = [];
401
        foreach ($author as $acronym) {
402
            if (isset($this->author[$acronym])) {
403
                $key = $this->author[$acronym];
404
                $authors[$acronym] = $this->meta[$key];
405
            } else {
406
                $authors[$acronym]["acronym"] = $acronym;
407
            }
408
        }
409
410
        return $authors;
411
    }
412
413
414
415
    // = Deal with categories ====================================
416
    
417
    /**
418
     * Generate a lookup index for categories that maps into the meta entry
419
     * for the category.
420
     *
421
     * @return void.
422
     */
423
    private function createCategory()
424
    {
425
        $pattern = $this->config["category"];
426
427
        $index = [];
428
        $matches = [];
429
        foreach ($this->meta as $key => $entry) {
430
            if (preg_match($pattern, $key, $matches)) {
431
                $catKey = $matches[1];
432
                $index[$catKey] = $key;
433
                $this->meta[$key]["key"] = $catKey;
434
                $this->meta[$key]["url"] = $key;
435
                unset($this->meta[$key]["__toc__"]);
436
            }
437
        }
438
439
        return $index;
440
    }
441
442
443
444
    /**
445
     * Find next and previous links of current content.
446
     *
447
     * @param array|string $author with details on the category(s).
448
     *
449
     * @return array with more details on the category(s).
450
     */
451 View Code Duplication
    private function loadCategoryDetails($category)
452
    {
453
        if (is_array($category) && is_array(array_values($category)[0])) {
454
            return $category;
455
        }
456
457
        if (!is_array($category)) {
458
            $tmp = $category;
459
            $category = [];
460
            $category[] = $tmp;
461
        }
462
463
        $categorys = [];
464
        foreach ($category as $catKey) {
465
            if (isset($this->category[$catKey])) {
466
                $key = $this->category[$catKey];
467
                $categorys[$catKey] = $this->meta[$key];
468
            } else {
469
                $categorys[$catKey]["key"] = $catKey;
470
            }
471
        }
472
473
        return $categorys;
474
    }
475
476
477
478
479
    // == Used by meta and breadcrumb (to get title) ===========================
480
    // TODO REFACTOR THIS?
481
    // Support getting only frontmatter.
482
    // Merge with function that retrieves whole filtered since getting
483
    // frontmatter will involve full parsing of document.
484
    // Title is retrieved from the HTML code.
485
    // Also do cacheing of each retrieved and parsed document
486
    // in this cycle, to gather code that loads and parses a individual
487
    // document.
488
    
489
    /**
490
     * Get the frontmatter of a document.
491
     *
492
     * @param string $file to get frontmatter from.
493
     *
494
     * @return array as frontmatter.
495
     */
496
    private function getFrontmatter($file)
497
    {
498
        $basepath = $this->config["basePath"];
499
        $filter1  = $this->config["textfilter-frontmatter"];
500
        $filter2  = $this->config["textfilter-title"];
501
        $filter = array_merge($filter1, $filter2);
502
        
503
        $path = $basepath . "/" . $file;
504
        $src = file_get_contents($path);
505
        $filtered = $this->di->get("textfilter")->parse($src, $filter);
506
        return $filtered->frontmatter;
507
    }
508
509
510
511
    // == Look up route in index ===================================
512
    
513
    /**
514
     * Check if currrent route is a supported meta route.
515
     *
516
     * @param string $route current route used to access page.
517
     *
518
     * @return string as route.
519
     */
520
    private function checkForMetaRoute($route)
521
    {
522
        $this->baseRoute = $route;
523
        $this->metaRoute = null;
524
525
        // If route exits in index, use it
526
        if ($this->mapRoute2IndexKey($route)) {
527
            return $route;
528
        }
529
530
        // Check for pagination
531
        $pagination = $this->config["pagination"];
532
        $matches = [];
533
        $pattern = "/(.*?)\/($pagination)\/(\d+)$/";
534
        if (preg_match($pattern, $route, $matches)) {
535
            $this->baseRoute = $matches[1];
536
            $this->metaRoute = $route;
537
            $this->currentPage = $matches[3];
538
        }
539
540
        return $this->baseRoute;
541
    }
542
543
544
545
    /**
546
     * Map the route to the correct key in the index.
547
     *
548
     * @param string $route current route used to access page.
549
     *
550
     * @return string as key or false if no match.
551
     */
552
    private function mapRoute2IndexKey($route)
553
    {
554
        $route = rtrim($route, "/");
555
556
        if (key_exists($route, $this->index)) {
557
            return $route;
558
        } elseif (empty($route) && key_exists("index", $this->index)) {
559
            return "index";
560
        } elseif (key_exists($route . "/index", $this->index)) {
561
            return "$route/index";
562
        }
563
564
        return false;
565
    }
566
567
568
569
    /**
570
     * Map the route to the correct entry in the index.
571
     *
572
     * @param string $route current route used to access page.
573
     *
574
     * @return array as the matched route.
575
     */
576
    private function mapRoute2Index($route)
577
    {
578
        $routeIndex = $this->mapRoute2IndexKey($route);
579
580
        if ($routeIndex) {
581
            return [$routeIndex, $this->index[$routeIndex]];
582
        }
583
584
        $msg = t("The route '!ROUTE' does not exists in the index.", [
585
            "!ROUTE" => $route
586
        ]);
587
        throw new \Anax\Exception\NotFoundException($msg);
588
    }
589
590
591
592
    // = Get view data by merging from meta and current frontmatter =========
593
    
594
    /**
595
     * Get view by mergin information from meta and frontmatter.
596
     *
597
     * @param string $route       current route used to access page.
598
     * @param array  $frontmatter for the content.
599
     * @param string $key         for the view to retrive.
600
     *
601
     * @return array with data to add as view.
602
     */
603
    private function getView($route, $frontmatter, $key)
604
    {
605
        $view = [];
606
607
        // From meta frontmatter
608
        $meta = $this->getMetaForRoute($route);
609
        if (isset($meta[$key])) {
610
            $view = $meta[$key];
611
        }
612
613
        // From document frontmatter
614
        if (isset($frontmatter[$key])) {
615
            $view = array_merge_recursive_distinct($view, $frontmatter[$key]);
616
            //$view = array_merge($view, $frontmatter[$key]);
617
        }
618
619
        return $view;
620
    }
621
622
623
624
    /**
625
     * Get details on extra views.
626
     *
627
     * @param string $route       current route used to access page.
628
     * @param array  $frontmatter for the content.
629
     *
630
     * @return array with page data to send to view.
631
     */
632
    private function getViews($route, $frontmatter)
633
    {
634
        // Arrange data into views
635
        $views = $this->getView($route, $frontmatter, "views", true);
636
637
        // Set defaults
638
        if (!isset($views["main"]["template"])) {
639
            $views["main"]["template"] = $this->config["template"];
640
        }
641
        if (!isset($views["main"]["data"])) {
642
            $views["main"]["data"] = [];
643
        }
644
645
        // Merge remaining frontmatter into view main data.
646
        $data = $this->getMetaForRoute($route);
647
        unset($data["__toc__"]);
648
        unset($data["views"]);
649
        unset($frontmatter["views"]);
650
651
        if ($frontmatter) {
652
            $data = array_merge_recursive_distinct($data, $frontmatter);
653
        }
654
        $views["main"]["data"] = array_merge_recursive_distinct($views["main"]["data"], $data);
655
656
        return $views;
657
    }
658
659
660
661
    // == Create and load content ===================================
662
663
    /**
664
     * Map url to content, even internal content, if such mapping can be done.
665
     *
666
     * @param string $route route to look up.
667
     *
668
     * @return object with content and filtered version.
669
     */
670
    private function createContentForInternalRoute($route)
671
    {
672
        // Load index and map route to content
673
        $this->load("index");
674
        $this->load("meta");
675
        $this->load("author");
676
        $this->load("category");
677
        
678
        // Match the route
679
        $route = rtrim($route, "/");
680
        $route = $this->checkForMetaRoute($route);
681
        list($routeIndex, $content, $filtered) = $this->mapRoute2Content($route);
682
683
        // Create and arrange the content as views, merge with .meta,
684
        // frontmatter is complete.
685
        $content["views"] = $this->getViews($routeIndex, $filtered->frontmatter);
686
687
        // Do process content step two when all frontmatter is included.
688
        $this->processMainContentPhaseTwo($content, $filtered);
689
        
690
        // Set details of content
691
        $content["views"]["main"]["data"]["content"] = $filtered->text;
692
        $content["views"]["main"]["data"]["excerpt"] = $filtered->excerpt;
693
        $this->loadAdditionalContent($content["views"], $route, $routeIndex);
694
695
        // TODO Should not supply all frontmatter to theme, only the
696
        // parts valid to the index template. Separate that data into own
697
        // holder in frontmatter. Do not include whole frontmatter? Only
698
        // on debg?
699
        $content["frontmatter"] = $filtered->frontmatter;
700
701
        return (object) $content;
702
    }
703
704
705
706
    /**
707
     * Look up the route in the index and use that to retrieve the filtered
708
     * content.
709
     *
710
     * @param string $route to look up.
711
     *
712
     * @return array with content and filtered version.
713
     */
714
    private function mapRoute2Content($route)
715
    {
716
        // Look it up in the index
717
        list($keyIndex, $content) = $this->mapRoute2Index($route);
718
        $filtered = $this->loadFileContentPhaseOne($keyIndex);
719
720
        return [$keyIndex, $content, $filtered];
721
    }
722
723
724
725
    /**
726
     * Load content file and frontmatter, this is the first time we process
727
     * the content.
728
     *
729
     * @param string $key     to index with details on the route.
730
     *
731
     * @throws NotFoundException when mapping can not be done.
732
     *
733
     * @return void.
734
     */
735
    private function loadFileContentPhaseOne($key)
736
    {
737
        // Settings from config
738
        $basepath = $this->config["basePath"];
739
        $filter   = $this->config["textfilter-frontmatter"];
740
741
        // Whole path to file
742
        $path = $basepath . "/" . $this->index[$key]["file"];
743
744
        // Load content from file
745
        if (!is_file($path)) {
746
            $msg = t("The content '!ROUTE' does not exists as a file '!FILE'.", ["!ROUTE" => $key, "!FILE" => $path]);
747
            throw new \Anax\Exception\NotFoundException($msg);
748
        }
749
750
        // Get filtered content
751
        $src = file_get_contents($path);
752
        $filtered = $this->di->get("textfilter")->parse($src, $filter);
753
754
        return $filtered;
755
    }
756
757
758
759
    // == Process content phase 2 ===================================
760
    // TODO REFACTOR THIS?
761
    
762
    /**
763
     * Look up the route in the index and use that to retrieve the filtered
764
     * content.
765
     *
766
     * @param array  &$content   to process.
767
     * @param object &$filtered to use for settings.
768
     *
769
     * @return array with content and filtered version.
770
     */
771
    private function processMainContentPhaseTwo(&$content, &$filtered)
772
    {
773
        // From configuration
774
        $filter = $this->config["textfilter"];
775
        $revisionStart = $this->config["revision-history"]["start"];
776
        $revisionEnd   = $this->config["revision-history"]["end"];
777
        $revisionClass = $this->config["revision-history"]["class"];
778
        $revisionSource = isset($this->config["revision-history"]["source"])
779
            ? $this->config["revision-history"]["source"]
780
            : null;
781
782
        $textFilter = $this->di->get("textfilter");
783
        $text = $filtered->text;
784
785
        // Check if revision history is to be included
786
        if (isset($content["views"]["main"]["data"]["revision"])) {
787
            $text = $textFilter->addRevisionHistory(
788
                $text,
789
                $content["views"]["main"]["data"]["revision"],
790
                $revisionStart,
791
                $revisionEnd,
792
                $revisionClass,
793
                $revisionSource . "/" . $content["file"]
794
            );
795
        }
796
797
        // Get new filtered content (and updated frontmatter)
798
        // Title in frontmatter overwrites title found in content
799
        $new = $textFilter->parse($text, $filter);
800
        $filtered->text = $new->text;
801
         
802
        // Keep title if defined in frontmatter
803
        $title = isset($filtered->frontmatter["title"])
804
          ? $filtered->frontmatter["title"]
805
          : null;
806
807
        $filtered->frontmatter = array_merge_recursive_distinct(
808
            $filtered->frontmatter,
809
            $new->frontmatter
810
        );
811
812
        if ($title) {
813
            $filtered->frontmatter["title"] = $title;
814
        }
815
816
        // Main data is
817
        $data = &$content["views"]["main"]["data"];
818
819
        // Update all anchor urls to use baseurl, needs info about baseurl
820
        // from merged frontmatter
821
        $baseurl = isset($data["baseurl"])
822
          ? $data["baseurl"]
823
          : null;
824
        $this->addBaseurl2AnchorUrls($filtered, $baseurl);
825
        $this->addBaseurl2ImageSource($filtered, $baseurl);
826
827
        // Add excerpt and hasMore, if available
828
        $textFilter->addExcerpt($filtered);
829
830
        // Load details on author, if set.
831
        if (isset($data["author"])) {
832
            $data["author"] = $this->loadAuthorDetails($data["author"]);
833
        }
834
835
        // Load details on category, if set.
836
        if (isset($data["category"])) {
837
            $data["category"] = $this->loadCategoryDetails($data["category"]);
838
        }
839
    }
840
841
842
843
    // == Public methods ============================================
844
    
845
    /**
846
     * Map url to content, even internal content, if such mapping can be done.
847
     *
848
     * @param string $route optional route to look up.
849
     *
850
     * @return object with content and filtered version.
851
     */
852
    public function contentForInternalRoute($route = null)
853
    {
854
        // Get the route
855
        if (is_null($route)) {
856
            $route = $this->di->get("request")->getRoute();
857
        }
858
859
        // Check cache for content or create cached version of content
860
        $cache = $this->di->get("cache");
861
        $slug = $this->di->get("url")->slugify($route);
862
        $key = $cache->createKey(__CLASS__, "route-$slug");
863
        $content = $cache->get($key);
864
865
        if (!$content || $this->ignoreCache) {
866
            $content = $this->createContentForInternalRoute($route);
867
            $cache->set($key, $content);
868
        }
869
870
        return $content;
871
    }
872
873
874
875
    /**
876
     * Map url to content if such mapping can be done, exclude internal routes.
877
     *
878
     * @param string $route optional route to look up.
879
     *
880
     * @return object with content and filtered version.
881
     */
882
    public function contentForRoute($route = null)
883
    {
884
        $content = $this->contentForInternalRoute($route);
885
        if ($content->internal === true) {
886
            $msg = t("The content '!ROUTE' does not exists as a public route.", ["!ROUTE" => $route]);
887
            throw new \Anax\Exception\NotFoundException($msg);
888
        }
889
890
        return $content;
891
    }
892
}
893