Passed
Push — pac-827 ( 14ff5e )
by
unknown
09:22
created

ImportConfigDiffCommand::getAddedKeys()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 5
nc 3
nop 2
dl 0
loc 9
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * TechDivision\Import\Cli\Command\ImportConfigDiffCommand
4
 *
5
 * PHP version 7
6
 *
7
 * @author    [email protected]
8
 * @copyright 2023 TechDivision GmbH <[email protected]>
9
 * @license   https://opensource.org/licenses/MIT
10
 * @link      https://github.com/techdivision/import-cli-simple
11
 * @link      http://www.techdivision.com
12
 */
13
14
namespace TechDivision\Import\Cli\Command;
15
16
use Symfony\Component\Console\Input\InputInterface;
17
use Symfony\Component\Console\Output\OutputInterface;
18
use TechDivision\Import\Configuration\ConfigurationInterface;
19
use TechDivision\Import\Utils\CommandNames;
20
21
/**
22
 * The import command implementation.
23
 *
24
 * @author    [email protected]
25
 * @copyright 2023 TechDivision GmbH <[email protected]>
26
 * @license   https://opensource.org/licenses/MIT
27
 * @link      https://github.com/techdivision/import-cli-simple
28
 * @link      http://www.techdivision.com
29
 */
30
class ImportConfigDiffCommand extends AbstractSimpleImportCommand
31
{
32
    /**
33
     * file where default values are saved
34
     *
35
     * @var string
36
     */
37
    public const DEFAULT_FILE = 'config.json';
38
39
    /** @var string */
40
    public const ADD_KEY = 'added';
41
42
    /** @var string */
43
    public const DELETE_KEY = 'deleted';
44
45
    /** @var string */
46
    public const CHANGED_KEY = 'changed';
47
48
    /**
49
     * Configures the current command.
50
     *
51
     * @return void
52
     * @see \Symfony\Component\Console\Command\Command::configure()
53
     */
54
    protected function configure(): void
55
    {
56
        // initialize the command with the required/optional options
57
        $this->setName(CommandNames::IMPORT_CONFIG_DIFF)
58
            ->setDescription('Shows Diffs between default configuration values and project config');
59
60
        // invoke the parent method
61
        parent::configure();
62
    }
63
64
    /**
65
     * Finally executes the simple command.
66
     *
67
     * @param ConfigurationInterface $configuration The configuration instance
68
     * @param InputInterface         $input         An InputInterface instance
69
     * @param OutputInterface        $output        An OutputInterface instance
70
     *
71
     * @return int
72
     */
73
    protected function executeSimpleCommand(
74
        ConfigurationInterface $configuration,
75
        InputInterface $input,
76
        OutputInterface $output
77
    ): int {
78
        $serializer = $this->createSerializer();
79
        $projectValues = $serializer->serialize($configuration, 'json');
80
        $defaultValues = file_get_contents($this->getFilePathComplete());
81
82
        // compare project and default Values
83
        if ($defaultValues !== $projectValues) {
84
            $projectJsonValues = json_decode($projectValues);
85
            $defaultValuesJson = json_decode($defaultValues);
86
            $paths = $this->getDataAsFlatArray($projectJsonValues);
87
            $defaultPaths = $this->getDataAsFlatArray($defaultValuesJson);
88
            $diff = $this->getAllDiffs($defaultPaths, $paths);
89
            $this->writeDiffs($defaultPaths, $paths, $diff, $output);
90
            return 0;
0 ignored issues
show
Bug Best Practice introduced by
The expression return 0 returns the type integer which is incompatible with the return type mandated by TechDivision\Import\Cli\...:executeSimpleCommand() of void.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
91
        }
92
93
        $output->writeln('[*] no changes found');
94
        return 0;
0 ignored issues
show
Bug Best Practice introduced by
The expression return 0 returns the type integer which is incompatible with the return type mandated by TechDivision\Import\Cli\...:executeSimpleCommand() of void.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
95
    }
96
97
    /**
98
     * @return string
99
     */
100
    public function getFileName(): string
101
    {
102
        return self::DEFAULT_FILE;
103
    }
104
105
    /**
106
     * @return string
107
     */
108
    public function getFilePathComplete(): string
109
    {
110
        return __DIR__ . '/../../' . $this->getFileName() . '.simple';
111
    }
112
113
    /**
114
     * @param array $defaultPaths Default values as flat array
115
     * @param array $paths        Project values as flat array
116
     * @return array
117
     */
118
    public function getAllDiffs(array $defaultPaths, array $paths): array
119
    {
120
        $addedKeys = $this->getAddedKeys($defaultPaths, $paths);
121
        $manipulatedKeys = array_diff_assoc($defaultPaths, $paths);
122
        $deletedKeys = $this->getDeletedKeys($defaultPaths, $paths);
123
        return [
124
            self::ADD_KEY => $addedKeys,
125
            self::DELETE_KEY => $deletedKeys,
126
            self::CHANGED_KEY => $manipulatedKeys,
127
        ];
128
    }
129
130
    /**
131
     * @param array           $defaultConfig Default values as flat array
132
     * @param array           $projectConfig Project values as flat array
133
     * @param array           $diff          Array with all diffs
134
     * @param OutputInterface $output        OutputInterface instance
135
     * @return void
136
     */
137
    private function writeDiffs(
138
        array $defaultConfig,
139
        array $projectConfig,
140
        array $diff,
141
        OutputInterface $output
142
    ): void {
143
        $output->writeln('Original | Override');
144
        foreach ($diff[self::DELETE_KEY] as $deletedKey) {
145
            $output->writeln($deletedKey . ':' .
146
                '"' . $defaultConfig[$deletedKey] . '"' . ' | --- key was deleted ---');
147
        }
148
        foreach ($diff[self::ADD_KEY] as $addedKey) {
149
            $output->writeln('--- key was added --- | ' . $addedKey . ':' .
150
                '"' . $projectConfig[$addedKey] . '"');
151
        }
152
        foreach ($diff[self::CHANGED_KEY] as $key => $value) {
153
            $output->writeln($key. ':' .
154
                '"'.$defaultConfig[$key].'"' . ' | ' . $key . ':'. '"'.$projectConfig[$key].'"');
155
        }
156
    }
157
158
    /**
159
     * @param array $default Default values as flat array
160
     * @param array $project Project values as flat array
161
     * @return array
162
     */
163
    private function getDeletedKeys(array $default, array $project): array
164
    {
165
        $deletedKeys = [];
166
        foreach ($default as $key => $value) {
167
            if (!array_key_exists($key, $project)) {
168
                $deletedKeys[] = $key;
169
            }
170
        }
171
        return $deletedKeys;
172
    }
173
174
    /**
175
     * @param array $default Default values as flat array
176
     * @param array $project Project values as flat array
177
     * @return array
178
     */
179
    private function getAddedKeys(array $default, array $project): array
180
    {
181
        $addedKeys = [];
182
        foreach ($project as $key => $value) {
183
            if (!array_key_exists($key, $default)) {
184
                $addedKeys[] = $key;
185
            }
186
        }
187
        return $addedKeys;
188
    }
189
190
    /**
191
     * @param mixd   $data Data to be converted to flat array
0 ignored issues
show
Bug introduced by
The type TechDivision\Import\Cli\Command\mixd was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
192
     * @param string $key  Key of the data
193
     * @param string $path Path of the data
194
     * @param array  $arr  Array to be filled with data
195
     * @return array
196
     */
197
    public function getDataAsFlatArray($data, string $key = '', string $path = '', array $arr = []): array
198
    {
199
        if ($path != '') {
200
            $path = $path . '/';
201
        }
202
        $path = $path . $key;
203
        if (is_object($data) || is_array($data)) {
204
            foreach ($data as $key => $value) {
205
                $arr = $this->getDataAsFlatArray($value, $key, $path, $arr);
206
            }
207
        } else {
208
            $arr[$path] = $data;
209
        }
210
        return $arr;
211
    }
212
}
213