Passed
Push — master ( ad78b7...4e7b04 )
by Brent
04:37
created

Stitcher   A

Complexity

Total Complexity 30

Size/Duplication

Total Lines 233
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 14

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 233
rs 10
wmc 30
lcom 2
cbo 14

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 12 1
B loadSite() 0 25 5
A loadTemplates() 0 14 3
C stitch() 0 43 8
A parseAdapters() 0 20 4
A parseVariables() 0 13 3
A save() 0 15 4
A getData() 0 9 2
1
<?php
2
3
namespace brendt\stitcher;
4
5
use brendt\stitcher\element\Page;
6
use brendt\stitcher\exception\InvalidSiteException;
7
use brendt\stitcher\exception\TemplateNotFoundException;
8
use brendt\stitcher\factory\AdapterFactory;
9
use brendt\stitcher\factory\ProviderFactory;
10
use brendt\stitcher\factory\TemplateEngineFactory;
11
use Symfony\Component\Filesystem\Filesystem;
12
use Symfony\Component\Finder\Finder;
13
use Symfony\Component\Finder\SplFileInfo;
14
use Symfony\Component\Yaml\Exception\ParseException;
15
use Symfony\Component\Yaml\Yaml;
16
use brendt\stitcher\engine\TemplateEngine;
17
use brendt\stitcher\element\Site;
18
19
class Stitcher {
20
21
    /**
22
     * @var SplFileInfo[]
23
     */
24
    protected $templates;
25
26
    /**
27
     * @var ProviderFactory
28
     */
29
    protected $factory;
30
31
    /**
32
     * @var string
33
     */
34
    private $root;
35
36
    /**
37
     * @var string
38
     */
39
    private $compileDir;
40
41
    /**
42
     * @var string
43
     */
44
    private $publicDir;
45
46
    /**
47
     * @var ProviderFactory
48
     */
49
    private $providerFactory;
50
51
    /**
52
     * @var AdapterFactory
53
     */
54
    private $adapterFactory;
55
56
    /**
57
     * @var TemplateEngine
58
     */
59
    private $templateEngine;
60
61
    /**
62
     * Stitcher constructor.
63
     */
64
    public function __construct() {
65
        $this->root = Config::get('directories.src');
66
        $this->publicDir = Config::get('directories.public');
67
        $this->compileDir = Config::get('directories.cache');
68
69
        $this->providerFactory = Config::getDependency('factory.provider');
70
        $this->adapterFactory = Config::getDependency('factory.adapter');
71
72
        /** @var TemplateEngineFactory $templateEngineFactory */
73
        $templateEngineFactory = Config::getDependency('factory.template.engine');
74
        $this->templateEngine = $templateEngineFactory->getByType(Config::get('engine'));
75
    }
76
77
    /**
78
     * @return Site
79
     * @throws InvalidSiteException
80
     */
81
    public function loadSite() {
82
        $site = new Site();
83
        $finder = new Finder();
84
        $files = $finder->files()->in("{$this->root}/site")->name('*.yml');
85
86
        foreach ($files as $file) {
87
            try {
88
                $fileContents = Yaml::parse($file->getContents());
89
            } catch (ParseException $e) {
90
                throw new InvalidSiteException("{$file->getRelativePathname()}: {$e->getMessage()}");
91
            }
92
93
            if (!is_array($fileContents)) {
94
                continue;
95
            }
96
97
            foreach ($fileContents as $route => $data) {
98
                $page = new Page($route, $data);
99
100
                $site->addPage($page);
101
            }
102
        }
103
104
        return $site;
105
    }
106
107
    /**
108
     * @return SplFileInfo[]
109
     */
110
    public function loadTemplates() {
111
        $finder = new Finder();
112
        $templateExtension = $this->templateEngine->getTemplateExtension();
113
        $templateFolder = Config::get('directories.template') ? Config::get('directories.template') : Config::get('directories.src') . '/template';
114
        $files = $finder->files()->in($templateFolder)->name("*.{$templateExtension}");
115
        $templates = [];
116
117
        foreach ($files as $file) {
118
            $id = str_replace(".{$templateExtension}", '', $file->getRelativePathname());
119
            $templates[$id] = $file;
120
        }
121
122
        return $templates;
123
    }
124
125
    /**
126
     * @param string|array $routes
127
     * @param null         $filterValue
128
     *
129
     * @return array
130
     * @throws TemplateNotFoundException
131
     */
132
    public function stitch($routes = [], $filterValue = null) {
133
        $blanket = [];
134
135
        $site = $this->loadSite();
136
        $templates = $this->loadTemplates();
137
138
        if (is_string($routes)) {
139
            $routes = [$routes];
140
        }
141
142
        foreach ($site as $page) {
143
            $route = $page->getId();
144
145
            $skipRoute = count($routes) && !in_array($route, $routes);
146
            if ($skipRoute) {
147
                continue;
148
            }
149
150
            $templateIsset = isset($templates[$page->getTemplate()]);
151
152
            if (!$templateIsset) {
153
                if (isset($page['template'])) {
154
                    throw new TemplateNotFoundException("Template {$page['template']} not found.");
155
                } else {
156
                    throw new TemplateNotFoundException('No template was set.');
157
                }
158
            }
159
160
            $pages = $this->parseAdapters($page, $filterValue);
161
162
            $pageTemplate = $templates[$page->getTemplate()];
163
            foreach ($pages as $entryPage) {
164
                $entryPage = $this->parseVariables($entryPage);
165
166
                // Render each page
167
                $this->templateEngine->addTemplateVariables($entryPage->getVariables());
168
                $blanket[$entryPage->getId()] = $this->templateEngine->renderTemplate($pageTemplate);
169
                $this->templateEngine->clearTemplateVariables();
170
            }
171
        }
172
173
        return $blanket;
174
    }
175
176
    /**
177
     * @param Page $page
178
     * @param null $entryId
179
     *
180
     * @return Page[]
181
     */
182
    public function parseAdapters(Page $page, $entryId = null) {
183
        $pages = [];
184
185
        // TODO: this will bug with multiple adapters
186
        if (count($page->getAdapters())) {
187
            foreach ($page->getAdapters() as $type => $adapterConfig) {
188
                $adapter = $this->adapterFactory->getByType($type);
189
190
                if ($entryId) {
191
                    $pages = $adapter->transform($page, $entryId);
192
                } else {
193
                    $pages = $adapter->transform($page);
194
                }
195
            }
196
        } else {
197
            $pages = [$page->getId() => $page];
198
        }
199
200
        return $pages;
201
    }
202
203
    /**
204
     * @param Page $page
205
     *
206
     * @return Page
207
     */
208
    public function parseVariables(Page $page) {
209
        foreach ($page->getVariables() as $name => $value) {
210
            if ($page->isParsedField($name)) {
211
                continue;
212
            }
213
214
            $page
215
                ->setVariable($name, $this->getData($value))
216
                ->setParsedField($name);
217
        }
218
219
        return $page;
220
    }
221
222
    /**
223
     * @param array $blanket
224
     */
225
    public function save(array $blanket) {
226
        $fs = new Filesystem();
227
228
        if (!$fs->exists($this->publicDir)) {
229
            $fs->mkdir($this->publicDir);
230
        }
231
232
        foreach ($blanket as $path => $page) {
233
            if ($path === '/') {
234
                $path = 'index';
235
            }
236
237
            $fs->dumpFile($this->publicDir . "/{$path}.html", $page);
238
        }
239
    }
240
241
    private function getData($src) {
242
        $provider = $this->providerFactory->getProvider($src);
243
244
        if (!$provider) {
245
            return $src;
246
        }
247
248
        return $provider->parse($src);
249
    }
250
251
}
252
253
254