Completed
Pull Request — master (#3)
by David
02:00
created

Page::fromFile()   B

Complexity

Conditions 8
Paths 8

Size

Total Lines 53
Code Lines 37

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 37
nc 8
nop 1
dl 0
loc 53
rs 7.1199
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
    /**
67
     * @param string[]|null $menu
68
     */
69
    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 = [])
70
    {
71
        $this->id = $id;
72
        $this->title = $title;
73
        $this->content = $content;
74
        $this->url = $url;
75
        $this->lang = $lang;
76
        $this->website = $website;
77
        $this->menu = $menu;
78
        $this->menuOrder = $menuOrder;
79
        $this->menuCssClass = $menuCssClass;
80
        $this->metaTitle = $metaTitle;
81
        $this->metaDescription = $metaDescription;
82
        $this->theme = $theme;
83
        $this->template = $template;
84
        $this->context = $context;
85
    }
86
87
    public static function fromFile(string $file): self
88
    {
89
        if (!is_readable($file)) {
90
            throw new UnableToLoadFileException('Cannot read file '.$file);
91
        }
92
93
        $extension = strtolower(pathinfo($file, PATHINFO_EXTENSION));
94
95
        switch ($extension) {
96
            case 'md':
97
                $parseMarkDown = true;
98
                break;
99
            case 'html':
100
                $parseMarkDown = false;
101
                break;
102
            default:
103
                throw new InvalidExtensionException(sprintf('Invalid extension for block %s. Valid extensions are .md and .html', $file));
104
        }
105
106
        $parser = new Parser();
107
108
        $document = $parser->parse(file_get_contents($file), $parseMarkDown);
109
110
        $yaml = $document->getYAML();
111
112
        if (isset($yaml['inherits'])) {
113
            $baseYaml = self::loadBaseYamlFile(dirname($file).'/'.$yaml['inherits']);
114
            $yaml = self::mergeYaml($baseYaml, $yaml, dirname($file).'/'.$yaml['inherits']);
115
        }
116
117
        $compulsoryFields = ['title', 'url', 'lang'];
118
119
        foreach ($compulsoryFields as $field) {
120
            if (!isset($yaml[$field])) {
121
                throw new UnableToLoadFileException('Missing field '.$field.' in YAML front matter of file '.$file);
122
            }
123
        }
124
125
        return new self(
126
            $yaml['id'] ?? null,
127
            $yaml['title'],
128
            $document->getContent(),
129
            '/'.ltrim($yaml['url'], '/'),
130
            $yaml['lang'],
131
            $yaml['website'] ?? null,
132
            isset($yaml['menu']) ? array_map('trim', explode('/', $yaml['menu'])) : null,
133
            $yaml['menu_order'] ?? null,
134
            $yaml['menu_css_class'] ?? null,
135
            $yaml['meta_title'] ?? null,
136
            $yaml['meta_description'] ?? null,
137
            $yaml['theme'] ?? null,
138
            $yaml['template'] ?? null,
139
            $yaml['context'] ?? []
140
        );
141
    }
142
143
    private static function loadBaseYamlFile(string $path): array
144
    {
145
        if (!is_readable($path)) {
146
            throw new UnableToLoadFileException('Cannot read base page '.$path.' (used in "inherits" option)');
147
        }
148
149
        return Yaml::parse(file_get_contents($path));
150
    }
151
152
    private static function mergeYaml(array $baseYaml, array $yaml, string $file): array
153
    {
154
        if (isset($baseYaml['inherits'])) {
155
            $baseYaml2 = self::loadBaseYamlFile(dirname($file).'/'.$baseYaml['inherits']);
156
            $baseYaml = self::mergeYaml($baseYaml2, $baseYaml, dirname($file).'/'.$baseYaml['inherits']);
157
        }
158
159
        $arrayMerger = new YamlUtils();
160
        return $arrayMerger->mergeArrays($baseYaml, $yaml, [
161
            'title' => YamlUtils::OVERRIDE,
162
            'lang' => YamlUtils::OVERRIDE,
163
            'website' => YamlUtils::OVERRIDE,
164
            'menu_css_class' => YamlUtils::OVERRIDE,
165
            'meta_title' => YamlUtils::OVERRIDE,
166
            'meta_description' => YamlUtils::OVERRIDE,
167
            'theme' => YamlUtils::OVERRIDE,
168
            'template' => YamlUtils::OVERRIDE,
169
            'context' => YamlUtils::MERGE_ARRAY,
170
        ]);
171
    }
172
173
    /**
174
     * @return null|string
175
     */
176
    public function getId(): ?string
177
    {
178
        return $this->id;
179
    }
180
181
    /**
182
     * @return string
183
     */
184
    public function getTitle(): string
185
    {
186
        return $this->title;
187
    }
188
189
    /**
190
     * @return string
191
     */
192
    public function getContent(): string
193
    {
194
        return $this->content;
195
    }
196
197
    /**
198
     * @return string
199
     */
200
    public function getUrl(): string
201
    {
202
        return $this->url;
203
    }
204
205
    /**
206
     * @return string
207
     */
208
    public function getLang(): string
209
    {
210
        return $this->lang;
211
    }
212
213
    /**
214
     * @return string|null
215
     */
216
    public function getWebsite(): ?string
217
    {
218
        return $this->website;
219
    }
220
221
    /**
222
     * @return null|string[]
223
     */
224
    public function getMenu(): ?array
225
    {
226
        return $this->menu;
227
    }
228
229
    /**
230
     * @return int
231
     */
232
    public function getMenuOrder(): int
233
    {
234
        return $this->menuOrder ?? 0;
235
    }
236
237
    /**
238
     * @return null|string
239
     */
240
    public function getMenuCssClass(): ?string
241
    {
242
        return $this->menuCssClass;
243
    }
244
245
    /**
246
     * @return null|string
247
     */
248
    public function getMetaTitle(): ?string
249
    {
250
        return $this->metaTitle;
251
    }
252
253
    /**
254
     * @return null|string
255
     */
256
    public function getMetaDescription(): ?string
257
    {
258
        return $this->metaDescription;
259
    }
260
261
    /**
262
     * @return null|string
263
     */
264
    public function getTheme(): ?string
265
    {
266
        return $this->theme;
267
    }
268
269
    /**
270
     * @return null|string
271
     */
272
    public function getTemplate(): ?string
273
    {
274
        return $this->template;
275
    }
276
277
    /**
278
     * @return array
279
     */
280
    public function getContext(): array
281
    {
282
        return $this->context;
283
    }
284
}
285