PageRegistry::findPagesByTag()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 10
nc 3
nop 2
dl 0
loc 14
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
4
namespace TheCodingMachine\CMS\StaticRegistry\Registry;
5
6
7
use Psr\Container\ContainerInterface;
8
use Psr\SimpleCache\CacheInterface;
9
use Symfony\Component\Finder\Finder;
10
use TheCodingMachine\CMS\Block\BlockInterface;
11
use TheCodingMachine\CMS\StaticRegistry\Loaders\Page;
12
use TheCodingMachine\CMS\StaticRegistry\Loaders\Page404;
0 ignored issues
show
Bug introduced by
The type TheCodingMachine\CMS\Sta...egistry\Loaders\Page404 was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
13
use TheCodingMachine\CMS\StaticRegistry\Menu\MenuItem;
14
use TheCodingMachine\CMS\StaticRegistry\Menu\MenuRegistry;
15
16
/**
17
 * The page registry can fetch Page objects from the "pages" directory or from the container.
18
 */
19
class PageRegistry
20
{
21
    /**
22
     * @var string
23
     */
24
    private $pageDirectory;
25
    /**
26
     * @var CacheInterface
27
     */
28
    private $cache;
29
30
    /**
31
     * An array of pages indexed by URL.
32
     *
33
     * @var Page[][]
34
     */
35
    private $pages;
36
37
    /**
38
     * @var MenuItem
39
     */
40
    private $rootMenuItem;
41
42
    public function __construct(string $pageDirectory, CacheInterface $cache)
43
    {
44
        $this->pageDirectory = rtrim($pageDirectory, '/\\').'/';
45
        $this->cache = $cache;
46
    }
47
48
    public function getPage(string $url, string $domain): Page
49
    {
50
        $pages = $this->getImportedPagesFromCache();
51
52
        if (isset($pages[$domain][$url])) {
53
            return $pages[$domain][$url];
54
        }
55
        if (isset($pages['<any>'][$url])) {
56
            return $pages['<any>'][$url];
57
        }
58
59
        throw PageNotFoundException::couldNotFindPage($url, $domain);
60
    }
61
62
    /**
63
     * @param string $tag
64
     * @param string|null $domain
65
     * @return Page[]
66
     */
67
    public function findPagesByTag(string $tag, ?string $domain): array
68
    {
69
        $pages = $this->getImportedPagesFromCache();
70
71
        if ($domain === null) {
72
            $pagesArrByTag = [];
73
            foreach ($pages as $domainKey => $pagesPerDomain) {
74
                $pagesArrByTag[] = $this->findPagesByTagAndDomain($pages, $tag, $domainKey);
75
            }
76
            return array_merge(...$pagesArrByTag);
0 ignored issues
show
Bug introduced by
$pagesArrByTag is expanded, but the parameter $array1 of array_merge() does not expect variable arguments. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

76
            return array_merge(/** @scrutinizer ignore-type */ ...$pagesArrByTag);
Loading history...
77
        } else {
78
            $pagesForDomain = $this->findPagesByTagAndDomain($pages, $tag, $domain);
79
            $pagesForAnyDomain = $this->findPagesByTagAndDomain($pages, $tag, '<any>');
80
            return array_merge($pagesForDomain, $pagesForAnyDomain);
81
        }
82
    }
83
84
    /**
85
     * @param Page[][] $pages
86
     * @param string $tag
87
     * @param string $domain
88
     * @return Page[]
89
     */
90
    private function findPagesByTagAndDomain(array $pages, string $tag, string $domain): array
91
    {
92
        $taggedPages = [];
93
        if (isset($pages[$domain])) {
94
            foreach ($pages[$domain] as $page) {
95
                if (in_array($tag, $page->getTags(), true)) {
96
                    $taggedPages[] = $page;
97
                }
98
            }
99
        }
100
        return $taggedPages;
101
    }
102
103
    /**
104
     * @return Page[][]
105
     */
106
    private function getImportedPagesFromCache(): array
107
    {
108
        $key = 'pages';
109
        $pages = $this->cache->get($key);
110
        if ($pages === null) {
111
            $pages = $this->getImportedPages();
112
            $this->cache->set($key, $pages);
113
        }
114
        return $pages;
115
    }
116
117
    /**
118
     * @return Page[][]
119
     * @throws DuplicatePageException
120
     */
121
    private function getImportedPages(): array
122
    {
123
        if ($this->pages === null) {
124
            $this->pages = [];
125
            $fileList = new Finder();
126
127
            $fileList->files()->in($this->pageDirectory)->name('/\.html$|\.md/')->sortByName();
128
129
            foreach ($fileList as $file) {
130
                $importedPage = Page::fromFile($file->getRealPath());
131
132
                if (isset($this->pages[$importedPage->getWebsite() ?? '<any>'][$importedPage->getUrl()])) {
133
                    throw new DuplicatePageException(sprintf('There are 2 pages claiming the URL %s %s', $importedPage->getUrl(), $importedPage->getWebsite() ? ' of website '.$importedPage->getWebsite() : ''));
134
                }
135
                $this->pages[$importedPage->getWebsite() ?? '<any>'][$importedPage->getUrl()] = $importedPage;
136
            }
137
        }
138
        return $this->pages;
139
    }
140
141
    public function getRootMenuItem(): MenuItem
142
    {
143
        $key = 'rootMenuItem';
144
        $rootMenuItem = $this->cache->get($key);
145
        if ($rootMenuItem === null) {
146
            $rootMenuItem = $this->getRootMenuItemWithoutCache();
147
            $this->cache->set($key, $rootMenuItem);
148
        }
149
        return $rootMenuItem;
150
    }
151
152
    private function getRootMenuItemWithoutCache(): MenuItem
153
    {
154
        if ($this->rootMenuItem === null) {
155
            $menuRegistry = new MenuRegistry();
156
            $pages = $this->getImportedPages();
157
            foreach ($pages as $pagesFromWebsite) {
158
                foreach ($pagesFromWebsite as $page) {
159
                    if ($page->getMenu()) {
160
                        $menuRegistry->registerMenuItem(
161
                            $page->getMenu(),
162
                            $page->getUrl(),
163
                            $page->getMenuOrder(),
164
                            $page->getMenuCssClass()
165
                        );
166
                    }
167
                }
168
            }
169
            $this->rootMenuItem = $menuRegistry->getRootMenu();
170
        }
171
        return $this->rootMenuItem;
172
    }
173
}
174