Completed
Push — feature-output-formats ( d3bfa5...bfb06f )
by Arnaud
04:51 queued 02:45
created

Page::setPermalink()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
/*
3
 * Copyright (c) Arnaud Ligny <[email protected]>
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
9
namespace Cecil\Collection\Page;
10
11
use Cecil\Collection\Item;
12
use Cecil\Page\Parser;
13
use Cecil\Page\Prefix;
14
use Cecil\Page\Type;
15
use Cecil\Page\VariableTrait;
16
use Cecil\Util;
17
use Cocur\Slugify\Slugify;
18
use Symfony\Component\Finder\SplFileInfo;
19
20
/**
21
 * Class Page.
22
 */
23
class Page extends Item
24
{
25
    use VariableTrait;
26
27
    const SLUGIFY_PATTERN = '/(^\/|[^a-z0-9\/]|-)+/';
28
29
    /**
30
     * @var SplFileInfo
31
     */
32
    protected $file;
33
    /**
34
     * @var string
35
     */
36
    protected $fileExtension;
37
    /**
38
     * @var string
39
     */
40
    protected $filePath;
41
    /**
42
     * @var string
43
     */
44
    protected $fileName;
45
    /**
46
     * @var string
47
     */
48
    protected $filePathname;
49
    /**
50
     * @var bool
51
     */
52
    protected $virtual = false;
53
    /**
54
     * @var string
55
     */
56
    protected $type;
57
    /**
58
     * @var string
59
     */
60
    protected $id;
61
    /**
62
     * @var string
63
     */
64
    protected $pathname;
65
    /**
66
     * @var string
67
     */
68
    protected $path;
69
    /**
70
     * @var string
71
     */
72
    protected $name;
73
    /**
74
     * @var string
75
     */
76
    protected $section;
77
    /**
78
     * @var string
79
     */
80
    protected $frontmatter;
81
    /**
82
     * @var string
83
     */
84
    protected $body;
85
    /**
86
     * @var string
87
     */
88
    protected $html;
89
90
    /**
91
     * Constructor.
92
     *
93
     * @param SplFileInfo|null $file
94
     */
95
    public function __construct(SplFileInfo $file = null)
96
    {
97
        $this->file = $file;
98
99
        // physical page
100
        if ($this->file instanceof SplFileInfo) {
101
            /*
102
             * File path components
103
             */
104
            // ie: content/Blog/Post 1.md
105
            //             |    |      └─ fileExtension
106
            //             |    └─ fileName
107
            //             └─ filePath
108
            $this->fileExtension = pathinfo($this->file, PATHINFO_EXTENSION);
109
            $this->filePath = str_replace(DIRECTORY_SEPARATOR, '/', $this->file->getRelativePath());
110
            $this->fileName = $this->file->getBasename('.'.$this->fileExtension);
111
            // filePathname = filePath + '/' + fileName
112
            // ie: "Blog/Post 1"
113
            $this->filePathname = ($this->filePath ? $this->filePath.'/' : '')
114
                .($this->filePath && $this->fileName == 'index' ? '' : $this->fileName);
115
            /*
116
             * Set properties
117
             */
118
            // ID. ie: "blog/post-1"
119
            $this->id = $this->slugify(Prefix::subPrefix($this->filePathname));
120
            // Path. ie: "blog"
121
            $this->path = $this->slugify($this->filePath);
122
            // Name. ie: "post-1"
123
            $this->name = $this->slugify(Prefix::subPrefix($this->fileName));
124
            // Pathname. ie: "blog/post-1"
125
            $this->pathname = $this->slugify(Prefix::subPrefix($this->filePathname));
126
            /*
127
             * Set variables
128
             */
129
            // Section. ie: "blog"
130
            $this->setSection(explode('/', $this->path)[0]);
131
            /*
132
             * Set variables overridden by front matter
133
             */
134
            // title. ie: "Post 1"
135
            $this->setVariable('title', Prefix::subPrefix($this->fileName));
136
            // date (from file meta)
137
            $this->setVariable('date', filemtime($this->file->getPathname()));
138
            // weight
139
            $this->setVariable('weight', null);
140
            // url
141
            $this->setVariable('url', $this->pathname.'/');
142
            // special case: file has a prefix
143
            if (Prefix::hasPrefix($this->filePathname)) {
144
                // prefix is a valid date?
145
                if (Util::isValidDate(Prefix::getPrefix($this->filePathname))) {
146
                    $this->setVariable('date', (string) Prefix::getPrefix($this->filePathname));
147
                } else {
148
                    // prefix is an integer, use for sorting
149
                    $this->setVariable('weight', (int) Prefix::getPrefix($this->filePathname));
150
                }
151
            }
152
153
            parent::__construct($this->id);
154
        } else {
155
            // virtual page
156
            $this->virtual = true;
157
            // date (current date)
158
            $this->setVariable('date', time());
159
160
            parent::__construct();
161
        }
162
        $this->setType(Type::PAGE);
163
        $this->setVariable('virtual', $this->virtual);
164
        $this->setVariable('published', true);
165
        $this->setVariable('content_template', 'page.content.twig');
166
    }
167
168
    /**
169
     * Turn a path (string) into a slung (URL).
170
     *
171
     * @param string $string
172
     *
173
     * @return string
174
     */
175
    public static function slugify(string $string): string
176
    {
177
        return Slugify::create([
178
            'regexp' => self::SLUGIFY_PATTERN,
179
        ])->slugify($string);
180
    }
181
182
    /**
183
     * Is current page is virtual?
184
     *
185
     * @return bool
186
     */
187
    public function isVirtual(): bool
188
    {
189
        return $this->virtual;
190
    }
191
192
    /**
193
     * Set page type.
194
     *
195
     * @param string $type
196
     *
197
     * @return self
198
     */
199
    public function setType(string $type): self
200
    {
201
        $this->type = new Type($type);
0 ignored issues
show
Documentation Bug introduced by
It seems like new \Cecil\Page\Type($type) of type object<Cecil\Page\Type> is incompatible with the declared type string of property $type.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
202
203
        return $this;
204
    }
205
206
    /**
207
     * Get page type.
208
     *
209
     * @return string|null
210
     */
211
    public function getType(): ?string
212
    {
213
        return $this->type;
214
    }
215
216
    /**
217
     * Parse file content.
218
     *
219
     * @return self
220
     */
221
    public function parse(): self
222
    {
223
        $parser = new Parser($this->file);
224
        $parsed = $parser->parse();
225
        $this->frontmatter = $parsed->getFrontmatter();
226
        $this->body = $parsed->getBody();
227
228
        return $this;
229
    }
230
231
    /**
232
     * Set name.
233
     *
234
     * @param string $name
235
     *
236
     * @return self
237
     */
238
    public function setName(string $name): self
239
    {
240
        $this->name = $name;
241
242
        return $this;
243
    }
244
245
    /**
246
     * Get name.
247
     *
248
     * @return string|null
249
     */
250
    public function getName(): ?string
251
    {
252
        return $this->name;
253
    }
254
255
    /**
256
     * Set path.
257
     *
258
     * @param $path
259
     *
260
     * @return self
261
     */
262
    public function setPath(string $path): self
263
    {
264
        $this->path = $path;
265
266
        return $this;
267
    }
268
269
    /**
270
     * Get path.
271
     *
272
     * @return string
273
     */
274
    public function getPath(): string
275
    {
276
        return $this->path;
277
    }
278
279
    /**
280
     * Set path name.
281
     *
282
     * @param string $pathname
283
     *
284
     * @return self
285
     */
286
    public function setPathname(string $pathname): self
287
    {
288
        $this->pathname = $pathname;
289
290
        return $this;
291
    }
292
293
    /**
294
     * Get path name.
295
     *
296
     * @return string
297
     */
298
    public function getPathname(): string
299
    {
300
        return $this->pathname;
301
    }
302
303
    /**
304
     * Set section.
305
     *
306
     * @param string $section
307
     *
308
     * @return self
309
     */
310
    public function setSection(string $section): self
311
    {
312
        $this->section = $section;
313
314
        return $this;
315
    }
316
317
    /**
318
     * Get section.
319
     *
320
     * @return string|false
321
     */
322
    public function getSection(): ?string
323
    {
324
        if (empty($this->section) && !empty($this->path)) {
325
            $this->setSection(explode('/', $this->path)[0]);
326
        }
327
328
        return $this->section;
329
    }
330
331
    /**
332
     * Get frontmatter.
333
     *
334
     * @return string|null
335
     */
336
    public function getFrontmatter(): ?string
337
    {
338
        return $this->frontmatter;
339
    }
340
341
    /**
342
     * Get body as raw.
343
     *
344
     * @return string
345
     */
346
    public function getBody(): ?string
347
    {
348
        return $this->body;
349
    }
350
351
    /**
352
     * Set body as HTML.
353
     *
354
     * @param string $html
355
     *
356
     * @return self
357
     */
358
    public function setBodyHtml(string $html): self
359
    {
360
        $this->html = $html;
361
362
        return $this;
363
    }
364
365
    /**
366
     * Get body as HTML.
367
     *
368
     * @return string|null
369
     */
370
    public function getBodyHtml(): ?string
371
    {
372
        return $this->html;
373
    }
374
375
    /**
376
     * @see getBodyHtml()
377
     *
378
     * @return string|null
379
     */
380
    public function getContent(): ?string
381
    {
382
        return $this->getBodyHtml();
383
    }
384
}
385