Save::process()   A
last analyzed

Complexity

Conditions 6
Paths 6

Size

Total Lines 29
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 18
nc 6
nop 0
dl 0
loc 29
rs 9.0444
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * This file is part of Cecil.
5
 *
6
 * (c) Arnaud Ligny <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Cecil\Step\Pages;
15
16
use Cecil\Collection\Page\Page;
17
use Cecil\Exception\RuntimeException;
18
use Cecil\Renderer\Page as PageRenderer;
19
use Cecil\Step\AbstractStep;
20
use Cecil\Util;
21
22
/**
23
 * Save step.
24
 *
25
 * This step is responsible for saving the rendered pages to the output directory.
26
 * It iterates through the pages, checks if they have been rendered, and saves
27
 * the output in the specified format. The saved files are logged, and the
28
 * output directory is created if it does not exist. If the `dry-run` option is
29
 * enabled, the step will not perform any file operations but will still log
30
 * the intended actions.
31
 */
32
class Save extends AbstractStep
33
{
34
    /**
35
     * {@inheritdoc}
36
     */
37
    public function getName(): string
38
    {
39
        return 'Saving pages';
40
    }
41
42
    /**
43
     * {@inheritdoc}
44
     */
45
    public function init(array $options): void
46
    {
47
        if ($options['dry-run']) {
48
            return;
49
        }
50
51
        Util\File::getFS()->mkdir($this->config->getOutputPath());
52
53
        $this->canProcess = true;
54
    }
55
56
    /**
57
     * {@inheritdoc}
58
     *
59
     * @throws RuntimeException
60
     */
61
    public function process(): void
62
    {
63
        $filteredPages = $this->builder->getPages()->filter(function (Page $page) {
64
            return !empty($page->getRendered());
65
        });
66
        $total = \count($filteredPages);
67
68
        $count = 0;
69
        foreach ($filteredPages as $page) {
70
            $count++;
71
            $files = [];
72
73
            foreach ($page->getRendered() as $format => $rendered) {
74
                if (false === $pathname = (new PageRenderer($this->builder, $page))->getOutputFilePath($format)) {
75
                    throw new RuntimeException(\sprintf("Unable to get pathname of page '%s' (format: '%s').", $page->getId(), $format));
76
                }
77
                $pathname = $this->cleanPath(Util::joinFile($this->config->getOutputPath(), $pathname));
78
79
                try {
80
                    Util\File::getFS()->dumpFile($pathname, $rendered['output']);
81
                } catch (\Symfony\Component\Filesystem\Exception\IOException $e) {
82
                    throw new RuntimeException($e->getMessage());
83
                }
84
85
                $files[] = $this->builder->isDebug() ? $pathname : substr($pathname, \strlen($this->config->getOutputPath()) + 1);
86
            }
87
88
            $message = \sprintf('File(s) "%s" saved', implode(', ', $files));
89
            $this->builder->getLogger()->info($message, ['progress' => [$count, $total]]);
90
        }
91
    }
92
93
    /**
94
     * Removes unnecessary directory separators.
95
     */
96
    private function cleanPath(string $pathname): string
97
    {
98
        if (DIRECTORY_SEPARATOR == '\\') {
99
            $pathname = preg_replace('#\\\\+#', '\\', $pathname);
100
        }
101
102
        return preg_replace('#/+#', '/', $pathname);
103
    }
104
}
105