1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Brendt\Stitcher; |
4
|
|
|
|
5
|
|
|
use Brendt\Stitcher\Exception\TemplateNotFoundException; |
6
|
|
|
use Brendt\Stitcher\Parser\Site\SiteParser; |
7
|
|
|
use Brendt\Stitcher\Site\Http\Htaccess; |
8
|
|
|
use Brendt\Stitcher\Site\Seo\SiteMap; |
9
|
|
|
use Brendt\Stitcher\Site\Site; |
10
|
|
|
use Symfony\Component\Filesystem\Filesystem; |
11
|
|
|
|
12
|
|
|
/** |
13
|
|
|
* The Stitcher class is the core compiler of every Stitcher application. This class takes care of all routes, pages, |
14
|
|
|
* templates and data, and "stitches" everything together. |
15
|
|
|
* |
16
|
|
|
* The stitching process is done in several steps, with the final result being a fully rendered website in the |
17
|
|
|
* `directories.public` folder. |
18
|
|
|
*/ |
19
|
|
|
class Stitcher |
20
|
|
|
{ |
21
|
|
|
private $srcDir; |
22
|
|
|
private $publicDir; |
23
|
|
|
private $templateDir; |
24
|
|
|
private $cdn; |
25
|
|
|
private $cdnCache; |
26
|
|
|
private $siteParser; |
27
|
|
|
private $htaccess; |
28
|
|
|
private $siteMap; |
29
|
|
|
|
30
|
|
View Code Duplication |
public function __construct( |
|
|
|
|
31
|
|
|
$srcDir, |
32
|
|
|
$publicDir, |
33
|
|
|
$templateDir, |
34
|
|
|
array $cdn, |
35
|
|
|
bool $cdnCache, |
36
|
|
|
SiteParser $siteParser, |
37
|
|
|
Htaccess $htaccess, |
38
|
|
|
SiteMap $siteMap |
39
|
|
|
) { |
40
|
|
|
$this->srcDir = $srcDir; |
41
|
|
|
$this->publicDir = $publicDir; |
42
|
|
|
$this->templateDir = $templateDir; |
43
|
|
|
$this->cdn = $cdn; |
44
|
|
|
$this->cdnCache = $cdnCache; |
45
|
|
|
$this->siteParser = $siteParser; |
46
|
|
|
$this->htaccess = $htaccess; |
47
|
|
|
$this->siteMap = $siteMap; |
48
|
|
|
} |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* The core stitcher function. This function will compile the configured site and return an array of parsed |
52
|
|
|
* data. |
53
|
|
|
* |
54
|
|
|
* Compiling a site is done in the following steps. |
55
|
|
|
* |
56
|
|
|
* - Load the site configuration @see \Brendt\Stitcher\Stitcher::loadSite() |
57
|
|
|
* - Load all available templates @see \Brendt\Stitcher\Stitcher::loadTemplates() |
58
|
|
|
* - Loop over all pages and transform every page with the configured adapters (in any are set) @see |
59
|
|
|
* \Brendt\Stitcher\Stitcher::parseAdapters() |
60
|
|
|
* - Loop over all transformed pages and parse the variables which weren't parsed by the page's adapters. @see |
61
|
|
|
* \Brendt\Stitcher\Stitcher::parseVariables() |
62
|
|
|
* - Add all variables to the template engine and render the HTML for each page. |
63
|
|
|
* |
64
|
|
|
* This function takes two optional parameters which are used to render pages on the fly when using the |
65
|
|
|
* developer controller. The first one, `routes` will take a string or array of routes which should be rendered, |
66
|
|
|
* instead of all available routes. The second one, `filterValue` is used to provide a filter when the |
67
|
|
|
* CollectionAdapter is used, and only one entry page should be rendered. |
68
|
|
|
* |
69
|
|
|
* @param string|array $routes |
70
|
|
|
* @param string $filterValue |
71
|
|
|
* |
72
|
|
|
* @return array |
73
|
|
|
* @throws TemplateNotFoundException |
74
|
|
|
* |
75
|
|
|
* @see \Brendt\Stitcher\Stitcher::save() |
76
|
|
|
* @see \Brendt\Stitcher\Application\DevController::run() |
77
|
|
|
* @see \Brendt\Stitcher\Adapter\CollectionAdapter::transform() |
78
|
|
|
*/ |
79
|
|
|
public function stitch($routes = [], string $filterValue = null) : array { |
80
|
|
|
if ($filterValue === null) { |
81
|
|
|
$this->htaccess->clearPageBlocks(); |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
$this->saveCdn(); |
85
|
|
|
|
86
|
|
|
return $this->siteParser->parse((array) $routes, $filterValue); |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
public function getSiteMap() : SiteMap { |
90
|
|
|
return $this->siteMap; |
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
public function loadSite(array $routes = []) : Site { |
94
|
|
|
return $this->siteParser->loadSite($routes); |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
/** |
98
|
|
|
* This function will save a stitched output to HTML files in the `directories.public` directory. |
99
|
|
|
* |
100
|
|
|
* @param array $blanket |
101
|
|
|
* |
102
|
|
|
* @see \Brendt\Stitcher\Stitcher::stitch() |
103
|
|
|
*/ |
104
|
|
|
public function save(array $blanket) { |
105
|
|
|
$fs = new Filesystem(); |
106
|
|
|
|
107
|
|
|
foreach ($blanket as $path => $page) { |
108
|
|
|
if ($path === '/') { |
109
|
|
|
$path = 'index'; |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
$fs->dumpFile($this->publicDir . "/{$path}.html", $page); |
113
|
|
|
} |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
public function saveHtaccess() : Stitcher { |
117
|
|
|
$fs = new Filesystem(); |
118
|
|
|
$fs->dumpFile("{$this->publicDir}/.htaccess", $this->htaccess->parse()); |
119
|
|
|
|
120
|
|
|
return $this; |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
public function saveSitemap() : Stitcher { |
124
|
|
|
if (!$this->siteMap->isEnabled()) { |
125
|
|
|
return $this; |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
$fs = new Filesystem(); |
129
|
|
|
$fs->dumpFile("{$this->publicDir}/sitemap.xml", $this->siteMap->render()); |
130
|
|
|
|
131
|
|
|
return $this; |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
public function saveCdn() : Stitcher { |
135
|
|
|
$fs = new Filesystem(); |
136
|
|
|
|
137
|
|
|
foreach ($this->cdn as $resource) { |
138
|
|
|
$resource = trim($resource, '/'); |
139
|
|
|
$publicResourcePath = "{$this->publicDir}/{$resource}"; |
140
|
|
|
|
141
|
|
|
if ($this->cdnCache && $fs->exists($publicResourcePath)) { |
142
|
|
|
continue; |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
$sourceResourcePath = "{$this->srcDir}/{$resource}"; |
146
|
|
|
$this->copyCdnFiles($sourceResourcePath, $publicResourcePath); |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
return $this; |
150
|
|
|
} |
151
|
|
|
|
152
|
|
|
private function copyCdnFiles($sourcePath, $publicPath) { |
153
|
|
|
$fs = new Filesystem(); |
154
|
|
|
|
155
|
|
|
if (is_dir($sourcePath)) { |
156
|
|
|
$fs->mirror($sourcePath, $publicPath); |
157
|
|
|
} else { |
158
|
|
|
$fs->copy($sourcePath, $publicPath, true); |
159
|
|
|
} |
160
|
|
|
} |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
|
164
|
|
|
|
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.