Completed
Push — site-variables ( 74af53...a8a6c4 )
by Arnaud
01:55
created

PagesRender::process()   D

Complexity

Conditions 13
Paths 161

Size

Total Lines 102

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 102
rs 4.8865
c 0
b 0
f 0
cc 13
nc 161
nop 0

How to fix   Long Method    Complexity   

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
/*
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\Site;
15
use Cecil\Renderer\Twig;
16
17
/**
18
 * Pages rendering.
19
 */
20
class PagesRender extends AbstractStep
21
{
22
    /**
23
     * {@inheritdoc}
24
     *
25
     * @throws Exception
26
     */
27
    public function init($options)
28
    {
29
        if (!is_dir($this->config->getLayoutsPath()) && !$this->config->hasTheme()) {
30
            throw new Exception(sprintf(
31
                "'%s' is not a valid layouts directory",
32
                $this->config->getLayoutsPath()
33
            ));
34
        }
35
36
        $this->process = true;
37
    }
38
39
    /**
40
     * {@inheritdoc}
41
     *
42
     * @throws Exception
43
     */
44
    public function process()
45
    {
46
        // prepares renderer
47
        $this->builder->setRenderer(new Twig($this->getAllLayoutsPaths(), $this->builder));
48
49
        // add globals variables
50
        $this->addGlobals();
51
52
        call_user_func_array($this->builder->getMessageCb(), ['RENDER', 'Rendering pages']);
53
54
        // collect published pages
55
        /* @var $page Page */
56
        $filteredPages = $this->builder->getPages()->filter(function (Page $page) {
57
            return !empty($page->getVariable('published'));
58
        });
59
        $max = count($filteredPages);
60
61
        // render each page
62
        $count = 0;
63
        /* @var $page Page */
64
        foreach ($filteredPages as $page) {
65
            $count++;
66
            $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...
67
            $rendered = [];
68
69
            // i18n
70
            $pageLang = $page->getVariable('language');
71
            $locale = $this->config->getLanguageProperty('locale', $pageLang);
72
            // The PHP Intl extension is needed to use localized date
73
            if (extension_loaded('intl')) {
74
                \Locale::setDefault($locale);
75
            }
76
            // The PHP Gettext extension is needed to use translation
77
            if (extension_loaded('gettext')) {
78
                $localePath = realpath($this->config->getSourceDir().'/locale');
79
                $domain = 'messages';
80
                putenv("LC_ALL=$locale");
81
                putenv("LANGUAGE=$locale");
82
                setlocale(LC_ALL, "$locale.UTF-8");
83
                bindtextdomain($domain, $localePath);
84
            }
85
86
            // global site variables
87
            $this->builder->getRenderer()
88
                ->addGlobal('site', new Site($this->builder));
89
            // specific language: replace global site variables
90
            if (!empty($pageLang) && $pageLang != $this->config->get('language')) {
91
                $this->builder->getRenderer()
92
                    ->addGlobal('site', new Site($this->builder, $pageLang));
93
            }
94
95
            // get page's output formats
96
            $formats = $this->getOutputFormats($page);
97
            $page->setVariable('output', $formats);
98
99
            // excluded format(s)?
100
            foreach ($formats as $key => $format) {
101
                if ($exclude = $this->config->get("site.output.formats.$format.exclude")) {
102
                    // ie:
103
                    //   formats:
104
                    //     atom:
105
                    //       [...]
106
                    //       exclude: [paginated]
107
                    foreach ($exclude as $variable) {
108
                        if ($page->hasVariable($variable)) {
109
                            unset($formats[$key]);
110
                        }
111
                    }
112
                }
113
            }
114
115
            // get and set alternates links
116
            $page->setVariable('alternates', $this->getAlternates($formats));
117
118
            // render each output format
119
            foreach ($formats as $format) {
120
                // search for the template
121
                $layout = Layout::finder($page, $format, $this->config);
122
                // render with Twig
123
                try {
124
                    $rendered[$format]['output'] = $this->builder->getRenderer()->render(
125
                        $layout,
126
                        ['page' => $page]
127
                    );
128
                    $rendered[$format]['template'] = $layout;
129
                } catch (\Exception $e) {
130
                    throw new Exception(sprintf(
131
                        "Error in template \"%s\" for page \"%s\":\n%s",
132
                        $layout,
133
                        $page->getId(),
134
                        $e->getMessage()
135
                    ));
136
                }
137
            }
138
            $page->setVariable('rendered', $rendered);
139
            $this->builder->getPages()->replace($page->getId(), $page);
140
141
            $layouts = implode(', ', array_column($rendered, 'template'));
142
            $message = sprintf('%s [%s]', ($page->getId() ?: 'index'), $layouts);
143
            call_user_func_array($this->builder->getMessageCb(), ['RENDER_PROGRESS', $message, $count, $max]);
144
        }
145
    }
146
147
    /**
148
     * Return an array of layouts directories.
149
     *
150
     * @return array
151
     */
152
    protected function getAllLayoutsPaths(): array
153
    {
154
        $paths = [];
155
156
        // layouts/
157
        if (is_dir($this->config->getLayoutsPath())) {
158
            $paths[] = $this->config->getLayoutsPath();
159
        }
160
        // <theme>/layouts/
161
        if ($this->config->hasTheme()) {
162
            $themes = $this->config->getTheme();
163
            foreach ($themes as $theme) {
164
                $paths[] = $this->config->getThemeDirPath($theme);
165
            }
166
        }
167
        // res/layouts/
168
        if (is_dir($this->config->getInternalLayoutsPath())) {
169
            $paths[] = $this->config->getInternalLayoutsPath();
170
        }
171
172
        return $paths;
173
    }
174
175
    /**
176
     * Add globals variables.
177
     */
178
    protected function addGlobals()
179
    {
180
        $this->builder->getRenderer()->addGlobal('cecil', [
181
            'url'       => sprintf('https://cecil.app/#%s', $this->builder->getVersion()),
182
            'version'   => $this->builder->getVersion(),
183
            'poweredby' => sprintf('Cecil v%s', $this->builder->getVersion()),
184
        ]);
185
    }
186
187
    /**
188
     * Get available output formats.
189
     *
190
     * @param Page $page
191
     *
192
     * @return array
193
     */
194
    protected function getOutputFormats(Page $page): array
195
    {
196
        $formats = [];
197
198
        // Get available output formats for the page type.
199
        // ie:
200
        //   page: [html, json]
201
        if (\is_array($this->config->get('output.pagetypeformats.'.$page->getType()))) {
202
            $formats = $this->config->get('output.pagetypeformats.'.$page->getType());
203
        }
204
        // Get page output format(s).
205
        // ie:
206
        //   output: txt
207
        if ($page->getVariable('output')) {
208
            $formats = $page->getVariable('output');
209
            if (!\is_array($formats)) {
210
                $formats = [$formats];
211
            }
212
        }
213
214
        return $formats;
215
    }
216
217
    /**
218
     * Get alternates.
219
     *
220
     * @param array $formats
221
     *
222
     * @return array
223
     */
224
    protected function getAlternates(array $formats): array
225
    {
226
        $alternates = [];
227
228
        if (count($formats) > 1 || in_array('html', $formats)) {
229
            foreach ($formats as $format) {
230
                $format == 'html' ? $rel = 'canonical' : $rel = 'alternate';
231
                $alternates[] = [
232
                    'rel'    => $rel,
233
                    'type'   => $this->config->get("site.output.formats.$format.mediatype"),
234
                    'title'  => strtoupper($format),
235
                    'format' => $format,
236
                ];
237
            }
238
        }
239
240
        return $alternates;
241
    }
242
}
243