Passed
Pull Request — master (#17)
by
unknown
13:11 queued 03:05
created

ImportConfigDiffCommand   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 167
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 57
dl 0
loc 167
rs 10
c 1
b 0
f 1
wmc 19

7 Methods

Rating   Name   Duplication   Size   Complexity  
A configure() 0 8 1
A getAddedKeys() 0 9 3
A executeSimpleCommand() 0 23 2
A getDeletedKeys() 0 9 3
A getAllDiffs() 0 9 1
A getDataAsFlatArray() 0 14 5
A writeDiffs() 0 19 4
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 = __DIR__ . '/../../config.json.default';
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)
0 ignored issues
show
Bug introduced by
The constant TechDivision\Import\Util...mes::IMPORT_CONFIG_DIFF was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
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
    {
79
        $serializer = $this->createSerializer();
80
        $projectValues = $serializer->serialize($configuration, 'json');
81
        $defaultValues = file_get_contents(self::DEFAULT_FILE);
82
83
        // compare project and default Values
84
        if ($defaultValues !== $projectValues) {
85
            $projectJsonValues = json_decode($projectValues);
86
            $defaultValuesJson = json_decode($defaultValues);
87
            $paths = $this->getDataAsFlatArray($projectJsonValues);
88
            $defaultPaths = $this->getDataAsFlatArray($defaultValuesJson);
89
            $diff = $this->getAllDiffs($defaultPaths, $paths);
90
            $this->writeDiffs($defaultPaths, $paths, $diff, $output);
91
            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...
92
        }
93
94
        $output->writeln('[*] no changes found');
95
        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...
96
    }
97
98
    /**
99
     * @param array $defaultPaths
100
     * @param array $paths
101
     * @return array
102
     */
103
    public function getAllDiffs(array $defaultPaths, array $paths): array
104
    {
105
        $addedKeys = $this->getAddedKeys($defaultPaths, $paths);
106
        $manipulatedKeys = array_diff_assoc($defaultPaths, $paths);
107
        $deletedKeys = $this->getDeletedKeys($defaultPaths, $paths);
108
        return [
109
            self::ADD_KEY => $addedKeys,
110
            self::DELETE_KEY => $deletedKeys,
111
            self::CHANGED_KEY => $manipulatedKeys,
112
        ];
113
    }
114
115
    /**
116
     * @param array $defaultConfig
117
     * @param array $projectConfig
118
     * @param array $diff
119
     * @param OutputInterface $output
120
     * @return void
121
     */
122
    private function writeDiffs(
123
        array $defaultConfig,
124
        array $projectConfig,
125
        array $diff,
126
        OutputInterface $output
127
    ): void
128
    {
129
        $output->writeln('Original | Override');
130
        foreach ($diff[self::DELETE_KEY] as $deletedKey) {
131
            $output->writeln($deletedKey . ':' .
132
                '"' . $defaultConfig[$deletedKey] . '"' . ' | --- key was deleted ---');
133
        }
134
        foreach ($diff[self::ADD_KEY] as $addedKey) {
135
            $output->writeln('--- key was added --- | ' . $addedKey . ':' .
136
                '"' . $projectConfig[$addedKey] . '"');
137
        }
138
        foreach ($diff[self::CHANGED_KEY] as $key => $value) {
139
            $output->writeln($key. ':' .
140
                '"'.$defaultConfig[$key].'"' . ' | ' . $key . ':'. '"'.$projectConfig[$key].'"');
141
        }
142
    }
143
144
    /**
145
     * @param array $default
146
     * @param array $project
147
     * @return array
148
     */
149
    private function getDeletedKeys(array $default, array $project): array
150
    {
151
        $deletedKeys = [];
152
        foreach ($default as $key => $value) {
153
            if (!array_key_exists($key, $project)) {
154
                $deletedKeys[] = $key;
155
            }
156
        }
157
        return $deletedKeys;
158
    }
159
160
    /**
161
     * @param array $default
162
     * @param array $project
163
     * @return array
164
     */
165
    private function getAddedKeys(array $default, array $project): array
166
    {
167
        $addedKeys = [];
168
        foreach ($project as $key => $value) {
169
            if (!array_key_exists($key, $default)) {
170
                $addedKeys[] = $key;
171
            }
172
        }
173
        return $addedKeys;
174
    }
175
176
    /**
177
     * @param $data
178
     * @param string $key
179
     * @param string $path
180
     * @param array $arr
181
     * @return array
182
     */
183
    public function getDataAsFlatArray($data, string $key='', string $path='', array $arr=[]): array
184
    {
185
        if ($path != '') {
186
            $path = $path . '/';
187
        }
188
        $path = $path . $key;
189
        if (is_object($data) || is_array($data)) {
190
            foreach ($data as $key => $value) {
191
                $arr = $this->getDataAsFlatArray($value, $key, $path, $arr);
192
            }
193
        } else {
194
            $arr[$path] = $data;
195
        }
196
        return $arr;
197
    }
198
}
199