Load   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 115
Duplicated Lines 0 %

Test Coverage

Coverage 91.43%

Importance

Changes 0
Metric Value
eloc 64
dl 0
loc 115
ccs 64
cts 70
cp 0.9143
rs 10
c 0
b 0
f 0
wmc 16

4 Methods

Rating   Name   Duplication   Size   Complexity  
A init() 0 4 3
B process() 0 74 10
A getName() 0 3 1
A pathToArray() 0 7 2
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\Data;
15
16
use Cecil\Collection\Page\PrefixSuffix;
17
use Cecil\Step\AbstractStep;
18
use Cecil\Util;
19
use Symfony\Component\Finder\Finder;
20
use Symfony\Component\Serializer\Encoder\CsvEncoder;
21
use Symfony\Component\Serializer\Encoder\JsonEncoder;
22
use Symfony\Component\Serializer\Encoder\XmlEncoder;
23
use Symfony\Component\Serializer\Encoder\YamlEncoder;
24
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
25
use Symfony\Component\Serializer\Serializer;
26
27
/**
28
 * Load step class.
29
 *
30
 * This class is responsible for loading data files from a specified directory,
31
 * decoding their contents based on the file extension, and merging the data
32
 * into the builder's data collection. It supports various file formats such as
33
 * YAML, JSON, CSV, and XML. The loaded data is organized into a nested array
34
 * structure based on the file paths and language suffixes.
35
 */
36
class Load extends AbstractStep
37
{
38
    /**
39
     * {@inheritdoc}
40
     */
41 1
    public function getName(): string
42
    {
43 1
        return 'Loading data';
44
    }
45
46
    /**
47
     * {@inheritdoc}
48
     */
49 1
    public function init(array $options): void
50
    {
51 1
        if (is_dir($this->config->getDataPath()) && $this->config->isEnabled('data.load')) {
52 1
            $this->canProcess = true;
53
        }
54
    }
55
56
    /**
57
     * {@inheritdoc}
58
     */
59 1
    public function process(): void
60
    {
61 1
        $files = Finder::create()
62 1
            ->files()
63 1
            ->in($this->config->getDataPath())
64 1
            ->name('/\.(' . implode('|', (array) $this->config->get('data.ext')) . ')$/')
65 1
            ->sortByName(true);
66 1
        $total = \count($files);
67
68 1
        if ($total < 1) {
69
            $message = 'No files';
70
            $this->builder->getLogger()->info($message);
71
72
            return;
73
        }
74
75 1
        $serializerYaml = new Serializer([new ObjectNormalizer()], [new YamlEncoder()]);
76 1
        $serializerJson = new Serializer([new ObjectNormalizer()], [new JsonEncoder()]);
77 1
        $serializerCsv = new Serializer([new ObjectNormalizer()], [new CsvEncoder()]);
78 1
        $serializerXml = new Serializer([new ObjectNormalizer()], [new XmlEncoder()]);
79 1
        $count = 0;
80
81
        /** @var \Symfony\Component\Finder\SplFileInfo $file */
82 1
        foreach ($files as $file) {
83 1
            $count++;
84 1
            set_error_handler(
85 1
                function ($severity, $message, $file, $line) {
86
                    throw new \ErrorException($message, 0, $severity, $file, $line, null);
87 1
                }
88 1
            );
89 1
            $data = $file->getContents();
90 1
            restore_error_handler();
91
92 1
            switch ($file->getExtension()) {
93 1
                case 'yml':
94 1
                case 'yaml':
95 1
                    $dataAsArray = $serializerYaml->decode($data, 'yaml');
96 1
                    break;
97 1
                case 'json':
98 1
                    $dataAsArray = $serializerJson->decode($data, 'json');
99 1
                    break;
100 1
                case 'csv':
101 1
                    $dataAsArray = $serializerCsv->decode($data, 'csv');
102 1
                    break;
103 1
                case 'xml':
104 1
                    $dataAsArray = $serializerXml->decode($data, 'xml');
105 1
                    break;
106
                default:
107
                    return;
108
            }
109
110 1
            $lang = $this->config->getLanguageDefault();
111 1
            if (PrefixSuffix::hasSuffix($file->getBasename('.' . $file->getExtension()))) {
112
                $lang = PrefixSuffix::getSuffix($file->getBasename('.' . $file->getExtension()));
113
            }
114 1
            $basename = $file->getBasename('.' . $file->getExtension());
115 1
            $subpath = \Cecil\Util\File::getFS()->makePathRelative(
116 1
                $file->getPath(),
117 1
                $this->config->getDataPath()
118 1
            );
119 1
            $subpath = trim($subpath, './');
120 1
            $array = [];
121 1
            $path = !empty($subpath) ? Util::joinFile($subpath, $basename) : $basename;
122 1
            $localizedPath = Util::joinFile((string) $lang, PrefixSuffix::sub($path));
123 1
            $this->pathToArray($array, $localizedPath, $dataAsArray);
124
125 1
            $dataAsArray = array_merge_recursive(
126 1
                $this->builder->getData(),
127 1
                $array
128 1
            );
129 1
            $this->builder->setData($dataAsArray);
130
131 1
            $message = \sprintf('File "%s.%s" loaded', Util::joinFile($path), $file->getExtension());
132 1
            $this->builder->getLogger()->info($message, ['progress' => [$count, $total]]);
133
        }
134
    }
135
136
    /**
137
     * Puts a path/value couple into an array.
138
     *
139
     * @param array  $arr       Target array
140
     * @param string $path      Source path
141
     * @param array  $value     Source values
142
     * @param string $separator Path separator (ie: '/')
143
     */
144 1
    private function pathToArray(array &$arr, string $path, array $value, string $separator = DIRECTORY_SEPARATOR): void
145
    {
146 1
        $keys = explode($separator, $path);
147 1
        foreach ($keys as $key) {
148 1
            $arr = &$arr[$key];
149
        }
150 1
        $arr = $value;
151
    }
152
}
153