Completed
Push — feature-output-formats ( 05a544...77af1f )
by Arnaud
02:05
created

PagesRender::getOutputFormats()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 20
rs 9.6
c 0
b 0
f 0
cc 4
nc 6
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\Step;
10
11
use Cecil\Collection\Page\Page;
12
use Cecil\Exception\Exception;
13
use Cecil\Renderer\Layout;
14
use Cecil\Renderer\Twig;
15
16
/**
17
 * Pages rendering.
18
 */
19
class PagesRender extends AbstractStep
20
{
21
    /**
22
     * {@inheritdoc}
23
     *
24
     * @throws Exception
25
     */
26
    public function init($options)
27
    {
28
        if (!is_dir($this->config->getLayoutsPath()) && !$this->config->hasTheme()) {
29
            throw new Exception(sprintf(
30
                "'%s' is not a valid layouts directory",
31
                $this->config->getLayoutsPath()
32
            ));
33
        }
34
35
        $this->process = true;
36
    }
37
38
    /**
39
     * {@inheritdoc}
40
     *
41
     * @throws Exception
42
     */
43
    public function process()
44
    {
45
        // prepares renderer
46
        $this->builder->setRenderer(new Twig($this->getAllLayoutsPaths(), $this->builder));
47
48
        // add globals variables
49
        $this->addGlobals();
50
51
        call_user_func_array($this->builder->getMessageCb(), ['RENDER', 'Rendering pages']);
52
53
        // collect published pages
54
        /* @var $page Page */
55
        $filteredPages = $this->builder->getPages()->filter(function (Page $page) {
56
            return !empty($page->getVariable('published'));
57
        });
58
        $max = count($filteredPages);
59
60
        // render each page
61
        $count = 0;
62
        /* @var $page Page */
63
        foreach ($filteredPages as $page) {
64
            $count++;
65
            $formats = ['html'];
0 ignored issues
show
Unused Code introduced by
$formats is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
66
            $rendered = null;
67
            $alternates = [];
0 ignored issues
show
Unused Code introduced by
$alternates is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
68
69
            // get page's output formats
70
            $formats = $this->getOutputFormats($page);
71
            $page->setVariable('output', $formats);
72
73
            // get alternates links
74
            $alternates = $this->getAlternates($formats);
75
            $page->setVariable('alternates', $alternates);
76
77
            // render each output format
78
            foreach ($formats as $format) {
79
                // exclude pages with specific variable(s)
80
                if ($exclude = $this->config->get("site.output.formats.$format.exclude")) {
81
                    // ie: 'exclude' => ['paginated'],
82
                    foreach ($exclude as $variable) {
83
                        if ($page->hasVariable($variable)) {
84
                            continue 2;
85
                        }
86
                    }
87
                }
88
                // search for the template
89
                $layout = Layout::finder($page, $format, $this->config);
90
                // render with Twig
91
                $rendered[$format]['output'] = $this->builder->getRenderer()->render(
92
                    $layout,
93
                    ['page' => $page]
94
                );
95
                $rendered[$format]['template'] = $layout;
96
            }
97
            $page->setVariable('rendered', $rendered);
98
            $this->builder->getPages()->replace($page->getId(), $page);
99
100
            $layouts = implode(', ', array_column($rendered, 'template'));
101
            $message = sprintf('%s (%s)', ($page->getId() ?: 'index'), $layouts);
102
            call_user_func_array($this->builder->getMessageCb(), ['RENDER_PROGRESS', $message, $count, $max]);
103
        }
104
    }
105
106
    /**
107
     * Return an array of layouts directories.
108
     *
109
     * @return array
110
     */
111
    protected function getAllLayoutsPaths(): array
112
    {
113
        $paths = [];
114
115
        // layouts/
116
        if (is_dir($this->config->getLayoutsPath())) {
117
            $paths[] = $this->config->getLayoutsPath();
118
        }
119
        // <theme>/layouts/
120
        if ($this->config->hasTheme()) {
121
            $themes = $this->config->getTheme();
122
            foreach ($themes as $theme) {
123
                $paths[] = $this->config->getThemeDirPath($theme);
124
            }
125
        }
126
        // res/layouts/
127
        if (is_dir($this->config->getInternalLayoutsPath())) {
128
            $paths[] = $this->config->getInternalLayoutsPath();
129
        }
130
131
        return $paths;
132
    }
133
134
    /**
135
     * Add globals variables.
136
     */
137
    protected function addGlobals()
138
    {
139
        // adds global variables
140
        $this->builder->getRenderer()->addGlobal('site', array_merge(
141
            $this->config->get('site'),
142
            ['menus' => $this->builder->getMenus()],
143
            ['pages' => $this->builder->getPages()->filter(function (Page $page) {
144
                return $page->getVariable('published');
145
            })],
146
            ['time' => time()]
147
        ));
148
        $this->builder->getRenderer()->addGlobal('cecil', [
149
            'url'       => sprintf('https://cecil.app/#%s', $this->builder->getVersion()),
150
            'version'   => $this->builder->getVersion(),
151
            'poweredby' => sprintf('Cecil v%s', $this->builder->getVersion()),
152
        ]);
153
    }
154
155
    /**
156
     * Get available output formats.
157
     *
158
     * @param Page $page
159
     *
160
     * @return array
161
     */
162
    protected function getOutputFormats(Page $page): array
163
    {
164
        $formats = [];
165
166
        // get available output formats for the page type
167
        // ie: "'page' => ['html', 'json']"
168
        if (\is_array($this->config->get('site.output.pagetypeformats.'.$page->getType()))) {
169
            $formats = $this->config->get('site.output.pagetypeformats.'.$page->getType());
170
        }
171
        // Get page output format(s).
172
        // ie: "output: txt"
173
        if ($page->getVariable('output')) {
174
            $formats = $page->getVariable('output');
175
            if (!\is_array($formats)) {
176
                $formats = [$formats];
177
            }
178
        }
179
180
        return $formats;
181
    }
182
183
    /**
184
     * Get alternates.
185
     *
186
     * @param array $formats
187
     *
188
     * @return array
189
     */
190
    protected function getAlternates(array $formats): array
191
    {
192
        $alternates = [];
193
194
        if (count($formats) > 1 && in_array('html', $formats)) {
195
            foreach ($formats as $format) {
196
                $format == 'html' ? $rel = 'canonical' : $rel = 'alternate';
197
                $alternates[] = [
198
                    'rel'    => $rel,
199
                    'type'   => $this->config->get("site.output.formats.$format.mediatype"),
200
                    'title'  => strtoupper($format),
201
                    'format' => $format,
202
                ];
203
            }
204
        }
205
206
        return $alternates;
207
    }
208
}
209