Completed
Push — collection-position ( 636ee4...426961 )
by Arnaud
02:12
created

PagesRender::process()   C

Complexity

Conditions 9
Paths 21

Size

Total Lines 78

Duplication

Lines 0
Ratio 0 %

Importance

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