AbstractOptimize::init()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 4.3731

Importance

Changes 0
Metric Value
cc 4
eloc 6
nc 4
nop 1
dl 0
loc 10
ccs 5
cts 7
cp 0.7143
crap 4.3731
rs 10
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\Optimize;
15
16
use Cecil\Cache;
17
use Cecil\Exception\RuntimeException;
18
use Cecil\Step\AbstractStep;
19
use Cecil\Util;
20
use Symfony\Component\Finder\Finder;
21
22
/**
23
 * Abstract class for optimization steps.
24
 *
25
 * This class provides a base implementation for steps that optimize files
26
 * of a specific type (e.g., CSS, JS). It handles the initialization of the
27
 * optimization process, file processing, and caching of optimized files.
28
 */
29
abstract class AbstractOptimize extends AbstractStep
30
{
31
    /** @var string File type (ie: 'css') */
32
    protected $type;
33
34
    /** @var mixed File processor */
35
    protected $processor;
36
37
    /**
38
     * {@inheritdoc}
39
     */
40 1
    public function init(array $options): void
41
    {
42 1
        if ($options['dry-run']) {
43
            return;
44
        }
45 1
        if (!$this->config->isEnabled(\sprintf('optimize.%s', $this->type))) {
46
            return;
47
        }
48 1
        if ($this->config->isEnabled('optimize')) {
49 1
            $this->canProcess = true;
50
        }
51
    }
52
53
    /**
54
     * {@inheritdoc}
55
     *
56
     * @throws RuntimeException
57
     */
58 1
    public function process(): void
59
    {
60 1
        $this->setProcessor();
61
62 1
        $extensions = (array) $this->config->get(\sprintf('optimize.%s.ext', $this->type));
63 1
        if (empty($extensions)) {
64
            throw new RuntimeException(\sprintf('The config key "optimize.%s.ext" is empty.', $this->type));
65
        }
66
67 1
        $files = Finder::create()
68 1
            ->files()
69 1
            ->in($this->config->getOutputPath())
70 1
            ->name('/\.(' . implode('|', $extensions) . ')$/')
71 1
            ->notName('/\.min\.(' . implode('|', $extensions) . ')$/')
72 1
            ->sortByName(true);
73 1
        $max = \count($files);
74
75 1
        if ($max <= 0) {
76
            $this->builder->getLogger()->info('No files');
77
78
            return;
79
        }
80
81 1
        $count = 0;
82 1
        $optimized = 0;
83 1
        $cache = new Cache($this->builder, 'optimized');
84
85
        /** @var \Symfony\Component\Finder\SplFileInfo $file */
86 1
        foreach ($files as $file) {
87 1
            $count++;
88 1
            $sizeBefore = $file->getSize();
89 1
            $message = \sprintf('File "%s" processed', $this->builder->isDebug() ? $file->getPathname() : $file->getRelativePathname());
90
91 1
            $cacheKey = $cache->createKeyFromFile($file);
92 1
            if (!$cache->has($cacheKey)) {
93 1
                $processed = $this->processFile($file);
94 1
                $sizeAfter = \strlen($processed);
95 1
                if ($sizeAfter < $sizeBefore) {
96 1
                    $message = \sprintf(
97 1
                        'File "%s" optimized (%s Ko -> %s Ko)',
98 1
                        $this->builder->isDebug() ? $file->getPathname() : $file->getRelativePathname(),
99 1
                        ceil($sizeBefore / 1000),
100 1
                        ceil($sizeAfter / 1000)
101 1
                    );
102
                }
103 1
                $cache->set($cacheKey, $this->encode($processed));
104 1
                $optimized++;
105
106 1
                $this->builder->getLogger()->info($message, ['progress' => [$count, $max]]);
107
            }
108 1
            $processed = $this->decode($cache->get($cacheKey));
109 1
            Util\File::getFS()->dumpFile($file->getPathname(), $processed);
110
        }
111 1
        if ($optimized == 0) {
112
            $this->builder->getLogger()->info('Nothing to do');
113
        }
114
    }
115
116
    /**
117
     * Set file processor object.
118
     */
119
    abstract public function setProcessor(): void;
120
121
    /**
122
     * Process a file.
123
     */
124
    abstract public function processFile(\Symfony\Component\Finder\SplFileInfo $file): string;
125
126
    /**
127
     * Encode file content.
128
     */
129 1
    public function encode(?string $content = null): ?string
130
    {
131 1
        return $content;
132
    }
133
134
    /**
135
     * Decode file content.
136
     */
137 1
    public function decode(?string $content = null): ?string
138
    {
139 1
        return $content;
140
    }
141
}
142