Passed
Push — develop ( 5d4fa7...44e92f )
by Brent
02:52
created

SiteParser::createPageRenderProcess()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 8
nc 2
nop 2
dl 0
loc 14
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace Brendt\Stitcher\Parser\Site;
4
5
use Brendt\Stitcher\Site\Seo\SiteMap;
6
use Pageon\Html\Meta\Meta;
7
use Brendt\Stitcher\Event\Event;
8
use Brendt\Stitcher\Exception\InvalidSiteException;
9
use Brendt\Stitcher\Exception\TemplateNotFoundException;
10
use Brendt\Stitcher\Site\Http\Htaccess;
11
use Brendt\Stitcher\Site\Page;
12
use Brendt\Stitcher\Site\Site;
13
use Pageon\Pcntl\Manager;
14
use Pageon\Pcntl\PageRenderProcess;
15
use Pageon\Pcntl\ProcessCollection;
16
use Symfony\Component\EventDispatcher\EventDispatcher;
17
use Symfony\Component\Finder\Finder;
18
use Symfony\Component\Finder\SplFileInfo;
19
use Symfony\Component\Yaml\Exception\ParseException;
20
use Symfony\Component\Yaml\Yaml;
21
22
class SiteParser
23
{
24
    const EVENT_PARSER_INIT = 'parser.initialised';
25
26
    const EVENT_PAGE_PARSING = 'page.parsing';
27
28
    const EVENT_PAGE_PARSED = 'page.parsed';
29
30
    const TOKEN_REDIRECT = 'redirect';
31
32
    /**
33
     * @var string
34
     */
35
    private $filter;
36
37
    /**
38
     * @var string
39
     */
40
    private $srcDir;
41
42
    /**
43
     * @var array
44
     */
45
    private $metaConfig;
46
47
    /**
48
     * @var EventDispatcher
49
     */
50
    private $eventDispatcher;
51
52
    /**
53
     * @var PageParser
54
     */
55
    private $pageParser;
56
57
    /**
58
     * @var Htaccess
59
     */
60
    private $htaccess;
61
62
    /**
63
     * @var string
64
     */
65
    private $publicDir;
66
67
    /**
68
     * @var bool
69
     */
70
    private $async;
71
72
    /**
73
     * @var string
74
     */
75
    private $environment;
76
77
    /**
78
     * @var SiteMap
79
     */
80
    private $siteMap;
81
82
    /**
83
     * SiteParser constructor.
84
     *
85
     * @param string          $srcDir
86
     * @param string          $publicDir
87
     * @param string          $environment
88
     * @param bool            $async
89
     * @param EventDispatcher $eventDispatcher
90
     * @param PageParser      $pageParser
91
     * @param Htaccess        $htaccess
92
     * @param SiteMap         $siteMap
93
     * @param array           $metaConfig
94
     */
95 View Code Duplication
    public function __construct(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
96
        string $srcDir,
97
        string $publicDir,
98
        string $environment,
99
        bool $async,
100
        EventDispatcher $eventDispatcher,
101
        PageParser $pageParser,
102
        Htaccess $htaccess,
103
        SiteMap $siteMap,
104
        array $metaConfig = []
105
    ) {
106
        $this->srcDir = $srcDir;
107
        $this->publicDir = $publicDir;
108
        $this->eventDispatcher = $eventDispatcher;
109
        $this->pageParser = $pageParser;
110
        $this->htaccess = $htaccess;
111
        $this->metaConfig = $metaConfig;
112
        $this->async = $async;
113
        $this->environment = $environment;
114
        $this->siteMap = $siteMap;
115
    }
116
117
    /**
118
     * Load a site from YAML configuration files in the `directories.src`/site directory.
119
     * All YAML files are loaded and parsed into Page objects and added to a Site collection.
120
     *
121
     * @param array $routes
122
     *
123
     * @return Site
124
     * @throws InvalidSiteException
125
     * @see \Brendt\Stitcher\Site\Page
126
     * @see \Brendt\Stitcher\Site\Site
127
     */
128
    public function loadSite(array $routes = []) : Site {
129
        /** @var SplFileInfo[] $files */
130
        $files = Finder::create()->files()->in("{$this->srcDir}/site")->name('*.yml');
131
        $site = new Site();
132
133
        foreach ($files as $file) {
134
            try {
135
                $fileContents = (array) Yaml::parse($file->getContents());
136
            } catch (ParseException $e) {
137
                throw new InvalidSiteException("{$file->getRelativePathname()}: {$e->getMessage()}");
138
            }
139
140
            foreach ($fileContents as $route => $config) {
141
                if (count($routes) && !in_array($route, $routes)) {
142
                    continue;
143
                }
144
145
                $this->loadPage($site, $route, $config);
146
            }
147
        }
148
149
        return $site;
150
    }
151
152
    /**
153
     * @param Site   $site
154
     * @param string $route
155
     * @param array  $config
156
     */
157
    private function loadPage(Site $site, string $route, array $config) {
158
        if (isset($config[self::TOKEN_REDIRECT])) {
159
            $this->htaccess->addRedirect($route, $config[self::TOKEN_REDIRECT]);
160
161
            return;
162
        }
163
164
        $page = new Page($route, $config, $this->createMeta());
165
        $site->addPage($page);
166
    }
167
168
    /**
169
     * Parse a path into usable data.
170
     *
171
     * @param array  $routes
172
     * @param string $filterValue
173
     *
174
     * @return array
175
     * @throws TemplateNotFoundException
176
     */
177
    public function parse($routes = [], string $filterValue = null) {
178
        $blanket = [];
179
        $manager = extension_loaded('pcntl') && $this->async ? new Manager() : null;
180
        $processCollection = new ProcessCollection();
181
182
        $site = $this->loadSite((array) $routes);
183
        $this->eventDispatcher->dispatch(self::EVENT_PARSER_INIT, Event::create(['site' => $site]));
184
        
185
        foreach ($site as $page) {
186
            $pageRenderProcess = $this->createPageRenderProcess($page, $filterValue);
187
            $this->eventDispatcher->dispatch(self::EVENT_PAGE_PARSING, Event::create(['page' => $page]));
188
189
            if ($manager) {
190
                $pageRenderProcess->setAsync();
191
                $processCollection[] = $manager->async($pageRenderProcess);
192
            } else {
193
                $blanket += $pageRenderProcess->execute();
194
                $pageRenderProcess->triggerSuccess();
195
            }
196
        }
197
198
        if ($manager) {
199
            $manager->wait($processCollection);
200
        }
201
202
        return $blanket;
203
    }
204
205
    /**
206
     * Create a page render process
207
     *
208
     * @param Page        $page
209
     * @param string|null $filterValue
210
     *
211
     * @return PageRenderProcess
212
     */
213
    private function createPageRenderProcess(Page $page, string $filterValue = null) : PageRenderProcess {
214
        $pageRenderProcess = new PageRenderProcess($this->pageParser, $page, $this->publicDir, $filterValue);
215
        $pageRenderProcess->setEnvironment($this->environment);
216
217
        if ($this->siteMap->isEnabled()) {
218
            $pageRenderProcess->setSiteMap($this->siteMap);
219
        }
220
221
        $pageRenderProcess->onSuccess(function () use ($page) {
222
            $this->eventDispatcher->dispatch(SiteParser::EVENT_PAGE_PARSED, Event::create(['pageId' => $page->getId()]));
223
        });
224
225
        return $pageRenderProcess;
226
    }
227
228
    /**
229
     * @param string $filter
230
     *
231
     * @return SiteParser
232
     */
233
    public function setFilter(string $filter) : SiteParser {
234
        $this->filter = $filter;
235
236
        return $this;
237
    }
238
239
    /**
240
     * @return Meta
241
     */
242
    private function createMeta() : Meta {
243
        $meta = new Meta();
244
245
        foreach ($this->metaConfig as $name => $value) {
246
            $meta->name($name, $value);
247
        }
248
249
        return $meta;
250
    }
251
}
252