Completed
Pull Request — master (#195)
by Tim
04:13 queued 02:30
created

DebugUtil   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 241
Duplicated Lines 8.3 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 17
lcom 1
cbo 5
dl 20
loc 241
ccs 0
cts 95
cp 0
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 1
A getRegistryProcessor() 0 4 1
A getConfiguration() 0 4 1
A getApplication() 0 4 1
A getRenderer() 0 4 1
B extractArchive() 0 61 6
A prepareDump() 20 20 2
A createDump() 0 41 4

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
/**
4
 * TechDivision\Import\Utils\DebugUtil
5
 *
6
 * NOTICE OF LICENSE
7
 *
8
 * This source file is subject to the Open Software License (OSL 3.0)
9
 * that is available through the world-wide-web at this URL:
10
 * http://opensource.org/licenses/osl-3.0.php
11
 *
12
 * PHP version 5
13
 *
14
 * @author    Tim Wagner <[email protected]>
15
 * @copyright 2020 TechDivision GmbH <[email protected]>
16
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
17
 * @link      https://github.com/techdivision/import-cli
18
 * @link      http://www.techdivision.com
19
 */
20
21
namespace TechDivision\Import\Utils;
22
23
use Doctrine\Common\Collections\Collection;
24
use TechDivision\Import\SystemLoggerTrait;
25
use TechDivision\Import\ApplicationInterface;
26
use TechDivision\Import\Services\RegistryProcessorInterface;
27
use TechDivision\Import\Configuration\ConfigurationInterface;
28
use TechDivision\Import\Listeners\Renderer\RendererInterface;
29
30
/**
31
 * A utility class to create cache keys.
32
 *
33
 * @author    Tim Wagner <[email protected]>
34
 * @copyright 2020 TechDivision GmbH <[email protected]>
35
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
36
 * @link      https://github.com/techdivision/import-cli
37
 * @link      http://www.techdivision.com
38
 */
39
class DebugUtil implements DebugUtilInterface
40
{
41
42
    /**
43
     * The trait that provides basic system logger functionality.
44
     *
45
     * @var \TechDivision\Import\SystemLoggerTrait
46
     */
47
    use SystemLoggerTrait;
48
49
    /**
50
     * The import processor instance.
51
     *
52
     * @var \TechDivision\Import\Services\RegistryProcessorInterface
53
     */
54
    private $registryProcessor;
55
56
    /**
57
     * The configuration instance.
58
     *
59
     * @var \TechDivision\Import\Configuration\ConfigurationInterface
60
     */
61
    private $configuration;
62
63
    /**
64
     * The debug dump renderer.
65
     *
66
     * @var \TechDivision\Import\Listeners\Renderer\RendererInterface
67
     */
68
    private $renderer;
69
70
    /**
71
     * Initializes the plugin with the application instance.
72
     *
73
     * @param \TechDivision\Import\Services\RegistryProcessorInterface  $registryProcessor The registry processor instance
74
     * @param \TechDivision\Import\Configuration\ConfigurationInterface $configuration     The configuration instance
75
     * @param \Doctrine\Common\Collections\Collection                   $systemLoggers     The array with the system loggers instances
76
     * @param \TechDivision\Import\Listeners\Renderer\RendererInterface $renderer          The debug dump renderer instance
77
     */
78
    public function __construct(
79
        RegistryProcessorInterface $registryProcessor,
80
        ConfigurationInterface $configuration,
81
        Collection $systemLoggers,
82
        RendererInterface $renderer
83
    ) {
84
        $this->registryProcessor = $registryProcessor;
85
        $this->configuration = $configuration;
86
        $this->systemLoggers = $systemLoggers;
0 ignored issues
show
Documentation Bug introduced by
It seems like $systemLoggers of type object<Doctrine\Common\Collections\Collection> is incompatible with the declared type array of property $systemLoggers.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
87
        $this->renderer = $renderer;
88
    }
89
90
    /**
91
     * Return's the registry processor instance.
92
     *
93
     * @return \TechDivision\Import\Services\RegistryProcessorInterface The registry processor instance
94
     */
95
    private function getRegistryProcessor() : RegistryProcessorInterface
96
    {
97
        return $this->registryProcessor;
98
    }
99
100
    /**
101
     * Return's the configuration instance.
102
     *
103
     * @return \TechDivision\Import\Configuration\ConfigurationInterface The configuration instance
104
     */
105
    private function getConfiguration() : ConfigurationInterface
106
    {
107
        return $this->configuration;
108
    }
109
110
    /**
111
     * Return's the application instance.
112
     *
113
     * @return \TechDivision\Import\ApplicationInterface The application instance
114
     */
115
    private function getApplication() : ApplicationInterface
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
116
    {
117
        return $this->application;
0 ignored issues
show
Bug introduced by
The property application does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
118
    }
119
120
    /**
121
     * Return's the debug dump renderer instance.
122
     *
123
     * @return \TechDivision\Import\Listeners\Renderer\RendererInterface The debug dump renderer instance
124
     */
125
    private function getRenderer() : RendererInterface
126
    {
127
        return $this->renderer;
128
    }
129
130
    /**
131
     * The method to extract an archive that has already been created by a previous
132
     * import back into the source directory.
133
     *
134
     * @param string $serial The serial of the archive to extract
135
     *
136
     * @return void
137
     * @throws \Exception Is thrown, if the archive can not be extracted back into the source directory
138
     */
139
    public function extractArchive(string $serial) : void
140
    {
141
142
        // clear the filecache
143
        clearstatcache();
144
145
        // load the actual status
146
        $status = $this->getRegistryProcessor()->getAttribute(RegistryKeys::STATUS);
147
148
        // query whether or not the configured source directory is available
149
        if (isset($status[RegistryKeys::SOURCE_DIRECTORY])) {
150
            $sourceDir = $status[RegistryKeys::SOURCE_DIRECTORY];
151
        } else {
152
            throw new \Exception('Source directory is not available!');
153
        }
154
155
        // try to load the archive directory
156
        $archiveDir = $this->getConfiguration()->getArchiveDir();
157
158
        // query whether or not the specified archive directory already exists
159
        if ($archiveDir === null) {
160
            $archiveDir = sprintf('var/import_history');
161
        }
162
163
        // initialize the ZIP instance
164
        $zip = new \ZipArchive();
165
166
        // prepare the archive filename
167
        $archiveFile = sprintf('%s/%s.zip', $archiveDir, $serial);
168
169
        // query whether or not the directory already exists
170
        if (is_dir($sourceDir)) {
171
            // log a warning and stop extracting the files
172
            $this->getSystemLogger()->warning(
173
                sprintf(
174
                    'Won\'t extract artefacts of "%s" for serial "%s" to directory "%s", because directory already exists',
175
                    $archiveFile,
176
                    $serial,
177
                    $sourceDir
178
                )
179
            );
180
181
            // stop prcessing the file extraction of the ZIP file
182
            return;
183
        }
184
185
        // try to open and extract the ZIP archive
186
        if (is_file($archiveFile)) {
187
            if ($zip->open($archiveFile) === true) {
188
                $zip->extractTo($sourceDir);
189
                $zip->close();
190
            } else {
191
                throw new \Exception(sprintf('Can\'t extract archive "%s" back into source directory', $archiveFile));
192
            }
193
        } else {
194
            $this->getSystemLogger()->debug(sprintf('"%s" is not available and can not be extracted therefore', $archiveFile));
195
        }
196
197
        // log a message that the file has successfully been extracted
198
        $this->getSystemLogger()->info(sprintf('Successfully extracted artefacts for serial "%s" to directory', $serial, $sourceDir));
199
    }
200
201
    /**
202
     * The method to create the debugging artefacts in the apropriate directory.
203
     *
204
     * @param string $serial The serial to prepare the dump for
205
     *
206
     * @return void
207
     * @throws \Exception Is thrown, if the configuration can not be dumped
208
     */
209 View Code Duplication
    public function prepareDump(string $serial) : void
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
210
    {
211
212
        // load the actual status
213
        $status = $this->getRegistryProcessor()->getAttribute(RegistryKeys::STATUS);
214
215
        // clear the filecache
216
        clearstatcache();
217
218
        // query whether or not the configured source directory is available
219
        if (!is_dir($sourceDir = $status[RegistryKeys::SOURCE_DIRECTORY])) {
220
            throw new \Exception(sprintf('Configured source directory %s is not available!', $sourceDir));
221
        }
222
223
        // render the debug artefacts
224
        $this->getRenderer()->render($serial);
0 ignored issues
show
Unused Code introduced by
The call to RendererInterface::render() has too many arguments starting with $serial.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
225
226
        // log a message that the debug artefacts has successfully been rendered
227
        $this->getSystemLogger()->info(sprintf('Successfully rendered the debug artefacts for serial "%s"', $serial));
228
    }
229
230
    /**
231
     * The method to create the debug dump with all artefacts and reports.
232
     *
233
     * @param string $serial The serial to create the dump for
234
     *
235
     * @return string $filename The name of the dumpfile
236
     * @throws \InvalidArgumentException Is thrown, if the passed serial has no matching import to create the dump for
237
     */
238
    public function createDump(string $serial) : string
239
    {
240
241
        // initialize the dump filename
242
        $dumpFile = null;
0 ignored issues
show
Unused Code introduced by
$dumpFile is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
243
244
        // load the actual status
245
        $status = $this->getRegistryProcessor()->getAttribute(RegistryKeys::STATUS);
246
247
        // clear the filecache
248
        clearstatcache();
249
250
        // query whether or not the configured source directory is available
251
        if (!is_dir($sourceDir = $status[RegistryKeys::SOURCE_DIRECTORY])) {
252
            throw new \Exception(sprintf('Configured source directory %s is not available!', $sourceDir));
253
        }
254
255
        // create the ZIP archive
256
        $dumpFile = new \ZipArchive();
257
        $dumpFile->open($dumpFilename = sprintf('%s/%s.zip', sys_get_temp_dir(), $serial), \ZipArchive::CREATE);
258
259
        // init file iterator on source directory
260
        $fileIterator = new \FilesystemIterator($sourceDir);
261
262
        // iterate through all files and add them to the ZIP archive
263
        /** @var \SplFileInfo $filename */
264
        foreach ($fileIterator as $filename) {
265
            if ($filename->isFile()) {
266
                $dumpFile->addFile($filename, basename($filename));
267
            }
268
        }
269
270
        // save the ZIP archive
271
        $dumpFile->close();
272
273
        // log a message that the dump has succesfully been created
274
        $this->getSystemLogger()->info(sprintf('Successfully created dump "%s" with artefacts for serial "%s"', $dumpFilename, $serial));
275
276
        // return the filename of the dump
277
        return $dumpFilename;
278
    }
279
}
280