1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Brendt\Stitcher; |
4
|
|
|
|
5
|
|
|
use Brendt\Stitcher\Adapter\Adapter; |
6
|
|
|
use Brendt\Stitcher\Factory\ParserFactory; |
7
|
|
|
use Brendt\Stitcher\Factory\TemplateEngineFactory; |
8
|
|
|
use Brendt\Stitcher\Site\Page; |
9
|
|
|
use Brendt\Stitcher\Site\Site; |
10
|
|
|
use Symfony\Component\Finder\Finder; |
11
|
|
|
use Symfony\Component\Finder\SplFileInfo; |
12
|
|
|
use Symfony\Component\Yaml\Yaml; |
13
|
|
|
|
14
|
|
|
class SiteParser |
15
|
|
|
{ |
16
|
|
|
/** |
17
|
|
|
* @var string |
18
|
|
|
*/ |
19
|
|
|
private $filter; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* @var string |
23
|
|
|
*/ |
24
|
|
|
private $srcDir; |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* @var string |
28
|
|
|
*/ |
29
|
|
|
private $templateDir; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* @var ParserFactory |
33
|
|
|
*/ |
34
|
|
|
private $parserFactory; |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* @var TemplateEngineFactory |
38
|
|
|
*/ |
39
|
|
|
private $templateEngineFactory; |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* SiteParser constructor. |
43
|
|
|
* |
44
|
|
|
* @param string $srcDir |
45
|
|
|
* @param string $templateDir |
46
|
|
|
* @param ParserFactory $parserFactory |
47
|
|
|
* @param TemplateEngineFactory $templateEngineFactory |
48
|
|
|
*/ |
49
|
|
|
public function __construct(string $srcDir, string $templateDir, ParserFactory $parserFactory, TemplateEngineFactory $templateEngineFactory) { |
50
|
|
|
$this->srcDir = $srcDir; |
51
|
|
|
$this->templateDir = $templateDir; |
52
|
|
|
$this->parserFactory = $parserFactory; |
53
|
|
|
$this->templateEngineFactory = $templateEngineFactory; |
54
|
|
|
} |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* Parse a path into usable data. |
58
|
|
|
* |
59
|
|
|
* @param array $routes |
60
|
|
|
* @param string $filterValue |
61
|
|
|
* |
62
|
|
|
* @return mixed |
63
|
|
|
*/ |
64
|
|
|
public function parse($routes = [], string $filterValue = null) : array { |
65
|
|
|
$templateEngine = $this->templateEngineFactory->getDefault(); |
66
|
|
|
$blanket = []; |
67
|
|
|
|
68
|
|
|
$site = $this->loadSite((array) $routes); |
69
|
|
|
$templates = $this->loadTemplates(); |
70
|
|
|
|
71
|
|
|
foreach ($site as $page) { |
72
|
|
|
$templateIsset = isset($templates[$page->getTemplatePath()]); |
73
|
|
|
|
74
|
|
|
if (!$templateIsset) { |
75
|
|
|
if ($template = $page->getTemplatePath()) { |
76
|
|
|
throw new TemplateNotFoundException("Template {$template} not found."); |
77
|
|
|
} else { |
78
|
|
|
throw new TemplateNotFoundException('No template was set.'); |
79
|
|
|
} |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
$pages = $this->parseAdapters($page, $filterValue); |
83
|
|
|
|
84
|
|
|
$pageTemplate = $templates[$page->getTemplatePath()]; |
85
|
|
|
foreach ($pages as $entryPage) { |
86
|
|
|
$entryPage = $this->parseVariables($entryPage); |
87
|
|
|
|
88
|
|
|
// Render each page |
89
|
|
|
$templateEngine->addTemplateVariables($entryPage->getVariables()); |
90
|
|
|
$blanket[$entryPage->getId()] = $templateEngine->renderTemplate($pageTemplate); |
91
|
|
|
$templateEngine->clearTemplateVariables(); |
92
|
|
|
} |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
return $blanket; |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
/** |
99
|
|
|
* Load a site from YAML configuration files in the `directories.src`/site directory. |
100
|
|
|
* All YAML files are loaded and parsed into Page objects and added to a Site collection. |
101
|
|
|
* |
102
|
|
|
* @param array $routes |
103
|
|
|
* |
104
|
|
|
* @return Site |
105
|
|
|
* @throws InvalidSiteException |
106
|
|
|
* @see \Brendt\Stitcher\Site\Page |
107
|
|
|
* @see \Brendt\Stitcher\Site\Site |
108
|
|
|
*/ |
109
|
|
|
public function loadSite(array $routes = []) : Site { |
110
|
|
|
/** @var SplFileInfo[] $files */ |
111
|
|
|
$files = Finder::create()->files()->in("{$this->srcDir}/site")->name('*.yml'); |
112
|
|
|
$site = new Site(); |
113
|
|
|
|
114
|
|
|
foreach ($files as $file) { |
115
|
|
|
try { |
116
|
|
|
$fileContents = (array) Yaml::parse($file->getContents()); |
117
|
|
|
} catch (ParseException $e) { |
|
|
|
|
118
|
|
|
throw new InvalidSiteException("{$file->getRelativePathname()}: {$e->getMessage()}"); |
119
|
|
|
} |
120
|
|
|
|
121
|
|
|
foreach ($fileContents as $route => $data) { |
122
|
|
|
if (count($routes) && !in_array($route, $routes)) { |
123
|
|
|
continue; |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
$page = new Page($route, $data); |
127
|
|
|
$site->addPage($page); |
128
|
|
|
} |
129
|
|
|
} |
130
|
|
|
|
131
|
|
|
return $site; |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
/** |
135
|
|
|
* Load all templates from either the `directories.template` directory. Depending on the configured template |
136
|
|
|
* engine, set with `engines.template`; .html or .tpl files will be loaded. |
137
|
|
|
* |
138
|
|
|
* @return SplFileInfo[] |
139
|
|
|
*/ |
140
|
|
|
public function loadTemplates() { |
141
|
|
|
$templateEngine = $this->templateEngineFactory->getDefault(); |
142
|
|
|
$templateExtension = $templateEngine->getTemplateExtension(); |
143
|
|
|
|
144
|
|
|
/** @var SplFileInfo[] $files */ |
145
|
|
|
$files = Finder::create()->files()->in($this->templateDir)->name("*.{$templateExtension}"); |
146
|
|
|
$templates = []; |
147
|
|
|
|
148
|
|
|
foreach ($files as $file) { |
149
|
|
|
$id = str_replace(".{$templateExtension}", '', $file->getRelativePathname()); |
150
|
|
|
$templates[$id] = $file; |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
return $templates; |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
/** |
157
|
|
|
* This function takes a page and optional entry id. The page's adapters will be loaded and looped. |
158
|
|
|
* An adapter will transform a page's original configuration and variables to one or more pages. |
159
|
|
|
* An entry id can be provided as a filter. This filter can be used in an adapter to skip rendering unnecessary |
160
|
|
|
* pages. The filter parameter is used to render pages on the fly when using the developer controller. |
161
|
|
|
* |
162
|
|
|
* @param Page $page |
163
|
|
|
* @param string $entryId |
164
|
|
|
* |
165
|
|
|
* @return Page[] |
166
|
|
|
* |
167
|
|
|
* @see \Brendt\Stitcher\Adapter\Adapter::transform() |
168
|
|
|
* @see \Brendt\Stitcher\Controller\DevController::run() |
169
|
|
|
*/ |
170
|
|
|
public function parseAdapters(Page $page, $entryId = null) { |
171
|
|
|
if (!$page->getAdapters()) { |
172
|
|
|
return [$page->getId() => $page]; |
|
|
|
|
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
$pages = [$page]; |
176
|
|
|
|
177
|
|
|
foreach ($page->getAdapters() as $type => $adapterConfig) { |
178
|
|
|
/** @var Adapter $adapter */ |
179
|
|
|
// TODO: Work with adapter factory |
180
|
|
|
$adapter = Stitcher::get("adapter.{$type}"); |
181
|
|
|
|
182
|
|
|
if ($entryId !== null) { |
183
|
|
|
$pages = $adapter->transform($pages, $entryId); |
184
|
|
|
} else { |
185
|
|
|
$pages = $adapter->transform($pages); |
186
|
|
|
} |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
return $pages; |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
/** |
193
|
|
|
* This function takes a Page object and parse its variables using a Parser. It will only parse variables which |
194
|
|
|
* weren't parsed already by an adapter. |
195
|
|
|
* |
196
|
|
|
* @param Page $page |
197
|
|
|
* |
198
|
|
|
* @return Page |
199
|
|
|
* |
200
|
|
|
* @see \Brendt\Stitcher\Factory\ParserFactory |
201
|
|
|
* @see \Brendt\Stitcher\Parser\Parser |
202
|
|
|
* @see \Brendt\Stitcher\Site\Page::isParsedVariable() |
203
|
|
|
*/ |
204
|
|
|
public function parseVariables(Page $page) { |
205
|
|
|
foreach ($page->getVariables() as $name => $value) { |
206
|
|
|
if ($page->isParsedVariable($name)) { |
207
|
|
|
continue; |
208
|
|
|
} |
209
|
|
|
|
210
|
|
|
$page |
211
|
|
|
->setVariableValue($name, $this->getData($value)) |
212
|
|
|
->setVariableIsParsed($name); |
213
|
|
|
} |
214
|
|
|
|
215
|
|
|
return $page; |
216
|
|
|
} |
217
|
|
|
|
218
|
|
|
/** |
219
|
|
|
* @param string $filter |
220
|
|
|
* |
221
|
|
|
* @return SiteParser |
222
|
|
|
*/ |
223
|
|
|
public function setFilter(string $filter) : SiteParser { |
224
|
|
|
$this->filter = $filter; |
225
|
|
|
|
226
|
|
|
return $this; |
227
|
|
|
} |
228
|
|
|
|
229
|
|
|
/** |
230
|
|
|
* This function will get the parser based on the value. This value is parsed by the parser, or returned if no |
231
|
|
|
* suitable parser was found. |
232
|
|
|
* |
233
|
|
|
* @param $value |
234
|
|
|
* |
235
|
|
|
* @return mixed |
236
|
|
|
* |
237
|
|
|
* @see \Brendt\Stitcher\Factory\ParserFactory |
238
|
|
|
*/ |
239
|
|
|
private function getData($value) { |
240
|
|
|
$parser = $this->parserFactory->getByFileName($value); |
241
|
|
|
|
242
|
|
|
if (!$parser) { |
243
|
|
|
return $value; |
244
|
|
|
} |
245
|
|
|
|
246
|
|
|
return $parser->parse($value); |
247
|
|
|
} |
248
|
|
|
} |
249
|
|
|
|
Scrutinizer analyzes your
composer.json
/composer.lock
file if available to determine the classes, and functions that are defined by your dependencies.It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.