Page::getLang()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
namespace TheCodingMachine\CMS\StaticRegistry\Loaders;
3
4
use Mni\FrontYAML\Parser;
5
use Symfony\Component\Yaml\Yaml;
6
7
class Page
8
{
9
    /**
10
     * @var string|null
11
     */
12
    private $id;
13
    /**
14
     * @var string
15
     */
16
    private $title;
17
    /**
18
     * @var string
19
     */
20
    private $content;
21
    /**
22
     * @var string
23
     */
24
    private $url;
25
    /**
26
     * @var string
27
     */
28
    private $lang;
29
    /**
30
     * @var null|string
31
     */
32
    private $website;
33
    /**
34
     * @var null|string[]
35
     */
36
    private $menu;
37
    /**
38
     * @var int|null
39
     */
40
    private $menuOrder;
41
    /**
42
     * @var null|string
43
     */
44
    private $metaTitle;
45
    /**
46
     * @var null|string
47
     */
48
    private $metaDescription;
49
    /**
50
     * @var null|string
51
     */
52
    private $theme;
53
    /**
54
     * @var null|string
55
     */
56
    private $menuCssClass;
57
    /**
58
     * @var null|string
59
     */
60
    private $template;
61
    /**
62
     * @var array
63
     */
64
    private $context;
65
    /**
66
     * @var string[]
67
     */
68
    private $tags;
69
70
    /**
71
     * @param string[]|null $menu
72
     * @param mixed[] $context
73
     * @param string[] $tags
74
     */
75
    public function __construct(?string $id, string $title, string $content, string $url, string $lang, ?string $website, ?array $menu, ?int $menuOrder, ?string $menuCssClass, ?string $metaTitle, ?string $metaDescription, ?string $theme, ?string $template, array $context = [], array $tags = [])
76
    {
77
        $this->id = $id;
78
        $this->title = $title;
79
        $this->content = $content;
80
        $this->url = $url;
81
        $this->lang = $lang;
82
        $this->website = $website;
83
        $this->menu = $menu;
84
        $this->menuOrder = $menuOrder;
85
        $this->menuCssClass = $menuCssClass;
86
        $this->metaTitle = $metaTitle;
87
        $this->metaDescription = $metaDescription;
88
        $this->theme = $theme;
89
        $this->template = $template;
90
        $this->context = $context;
91
        $this->tags = $tags;
92
    }
93
94
    public static function fromFile(string $file): self
95
    {
96
        if (!is_readable($file)) {
97
            throw new UnableToLoadFileException('Cannot read file '.$file);
98
        }
99
100
        $extension = strtolower(pathinfo($file, PATHINFO_EXTENSION));
101
102
        switch ($extension) {
103
            case 'md':
104
                $parseMarkDown = true;
105
                break;
106
            case 'html':
107
                $parseMarkDown = false;
108
                break;
109
            default:
110
                throw new InvalidExtensionException(sprintf('Invalid extension for block %s. Valid extensions are .md and .html', $file));
111
        }
112
113
        $parser = new Parser();
114
115
        $document = $parser->parse(file_get_contents($file), $parseMarkDown);
116
117
        $yaml = $document->getYAML();
118
119
        if (isset($yaml['inherits'])) {
120
            $baseYaml = self::loadBaseYamlFile(dirname($file).'/'.$yaml['inherits']);
121
            $yaml = self::mergeYaml($baseYaml, $yaml, dirname($file).'/'.$yaml['inherits']);
122
        }
123
124
        $compulsoryFields = ['title', 'url', 'lang'];
125
126
        foreach ($compulsoryFields as $field) {
127
            if (!isset($yaml[$field])) {
128
                throw new UnableToLoadFileException('Missing field '.$field.' in YAML front matter of file '.$file);
129
            }
130
        }
131
132
        return new self(
133
            $yaml['id'] ?? null,
134
            $yaml['title'],
135
            $document->getContent(),
136
            '/'.ltrim($yaml['url'], '/'),
137
            $yaml['lang'],
138
            $yaml['website'] ?? null,
139
            isset($yaml['menu']) ? array_map('trim', explode('/', $yaml['menu'])) : null,
140
            $yaml['menu_order'] ?? null,
141
            $yaml['menu_css_class'] ?? null,
142
            $yaml['meta_title'] ?? null,
143
            $yaml['meta_description'] ?? null,
144
            $yaml['theme'] ?? null,
145
            $yaml['template'] ?? null,
146
            $yaml['context'] ?? [],
147
            $yaml['tags'] ?? []
148
        );
149
    }
150
151
    /**
152
     * @return mixed[]
153
     * @throws UnableToLoadFileException
154
     */
155
    private static function loadBaseYamlFile(string $path): array
156
    {
157
        if (!is_readable($path)) {
158
            throw new UnableToLoadFileException('Cannot read base page '.$path.' (used in "inherits" option)');
159
        }
160
161
        return Yaml::parse(file_get_contents($path));
162
    }
163
164
    /**
165
     * @param mixed[] $baseYaml
166
     * @param mixed[] $yaml
167
     * @param string $file
168
     * @return mixed[]
169
     */
170
    private static function mergeYaml(array $baseYaml, array $yaml, string $file): array
171
    {
172
        if (isset($baseYaml['inherits'])) {
173
            $baseYaml2 = self::loadBaseYamlFile(dirname($file).'/'.$baseYaml['inherits']);
174
            $baseYaml = self::mergeYaml($baseYaml2, $baseYaml, dirname($file).'/'.$baseYaml['inherits']);
175
        }
176
177
        $arrayMerger = new YamlUtils();
178
        return $arrayMerger->mergeArrays($baseYaml, $yaml, [
179
            'title' => YamlUtils::OVERRIDE,
180
            'lang' => YamlUtils::OVERRIDE,
181
            'website' => YamlUtils::OVERRIDE,
182
            'menu_css_class' => YamlUtils::OVERRIDE,
183
            'meta_title' => YamlUtils::OVERRIDE,
184
            'meta_description' => YamlUtils::OVERRIDE,
185
            'theme' => YamlUtils::OVERRIDE,
186
            'template' => YamlUtils::OVERRIDE,
187
            'context' => YamlUtils::MERGE_ARRAY,
188
            'tags' => YamlUtils::MERGE_ARRAY,
189
        ]);
190
    }
191
192
    /**
193
     * @return null|string
194
     */
195
    public function getId(): ?string
196
    {
197
        return $this->id;
198
    }
199
200
    /**
201
     * @return string
202
     */
203
    public function getTitle(): string
204
    {
205
        return $this->title;
206
    }
207
208
    /**
209
     * @return string
210
     */
211
    public function getContent(): string
212
    {
213
        return $this->content;
214
    }
215
216
    /**
217
     * @return string
218
     */
219
    public function getUrl(): string
220
    {
221
        return $this->url;
222
    }
223
224
    /**
225
     * @return string
226
     */
227
    public function getLang(): string
228
    {
229
        return $this->lang;
230
    }
231
232
    /**
233
     * @return string|null
234
     */
235
    public function getWebsite(): ?string
236
    {
237
        return $this->website;
238
    }
239
240
    /**
241
     * @return null|string[]
242
     */
243
    public function getMenu(): ?array
244
    {
245
        return $this->menu;
246
    }
247
248
    /**
249
     * @return int
250
     */
251
    public function getMenuOrder(): int
252
    {
253
        return $this->menuOrder ?? 0;
254
    }
255
256
    /**
257
     * @return null|string
258
     */
259
    public function getMenuCssClass(): ?string
260
    {
261
        return $this->menuCssClass;
262
    }
263
264
    /**
265
     * @return null|string
266
     */
267
    public function getMetaTitle(): ?string
268
    {
269
        return $this->metaTitle;
270
    }
271
272
    /**
273
     * @return null|string
274
     */
275
    public function getMetaDescription(): ?string
276
    {
277
        return $this->metaDescription;
278
    }
279
280
    /**
281
     * @return null|string
282
     */
283
    public function getTheme(): ?string
284
    {
285
        return $this->theme;
286
    }
287
288
    /**
289
     * @return null|string
290
     */
291
    public function getTemplate(): ?string
292
    {
293
        return $this->template;
294
    }
295
296
    /**
297
     * @return mixed[]
298
     */
299
    public function getContext(): array
300
    {
301
        return $this->context;
302
    }
303
304
    /**
305
     * @return string[]
306
     */
307
    public function getTags(): array
308
    {
309
        return $this->tags;
310
    }
311
}
312