Completed
Push — 15.x ( f4a7f0...f1a10c )
by Tim
02:29
created

ConfigurationManager::getPlugins()   B

Complexity

Conditions 8
Paths 16

Size

Total Lines 53

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 72

Importance

Changes 0
Metric Value
dl 0
loc 53
ccs 0
cts 28
cp 0
rs 7.781
c 0
b 0
f 0
cc 8
nc 16
nop 0
crap 72

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * TechDivision\Import\Execution\ConfigurationManager
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 2019 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
18
 * @link      http://www.techdivision.com
19
 */
20
21
namespace TechDivision\Import\Execution;
22
23
use TechDivision\Import\ConfigurationInterface;
24
use TechDivision\Import\ConfigurationManagerInterface;
25
26
/**
27
 * A simle configuration manager implementation.
28
 *
29
 * @author    Tim Wagner <[email protected]>
30
 * @copyright 2019 TechDivision GmbH <[email protected]>
31
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
32
 * @link      https://github.com/techdivision/import
33
 * @link      http://www.techdivision.com
34
 */
35
class ConfigurationManager implements ConfigurationManagerInterface
36
{
37
38
    /**
39
     * The configuration instance we want to handle.
40
     *
41
     * @var \TechDivision\Import\ConfigurationInterface
42
     */
43
    private $configuration;
44
45
    /**
46
     * Mapping for entity type to edition mapping (for configuration purposes only).
47
     *
48
     * @var array
49
     */
50
    private $entityTypeToEditionMapping = array(
51
        'eav_attribute'                 => 'general',
52
        'eav_attribute_set'             => 'general',
53
        'catalog_product_inventory_msi' => 'general',
54
        'catalog_product_tier_price'    => 'general',
55
        'customer_address'              => 'general',
56
        'customer'                      => 'general'
57
    );
58
59
    /**
60
     * Initializes the manager with the configuration instance.
61
     *
62
     * @param \TechDivision\Import\ConfigurationInterface $configuration The configuration instance
63
     */
64
    public function __construct(ConfigurationInterface $configuration)
65
    {
66
        $this->configuration = $configuration;
67
    }
68
69
    /**
70
     * Return's the managed configuration instance.
71
     *
72
     * @return \TechDivision\Import\ConfigurationInterface The configuration instance
73
     */
74
    public function getConfiguration()
75
    {
76
        return $this->configuration;
77
    }
78
79
    /**
80
     * Return's an array with the configurations of the operations that has to be executed.
81
     *
82
     * @return \TechDivision\Import\Configuration\OperationConfigurationInterface[] The operation configurations
83
     */
84
    public function getOperations()
85
    {
86
87
        // load the configuration instance
88
        $configuration = $this->getConfiguration();
89
90
        // initialize the array for the operations that has to be executed
91
        $execute = array();
92
93
        // load the shortcuts from the configuration
94
        $shortcuts = $configuration->getShortcuts();
95
96
        // query whether or not a shortcut has been passed
97
        if ($shortcut = $configuration->getShortcut()) {
98
            // load the entity type code and map it to the Magento edition
99
            $magentoEdition = $this->mapEntityTypeToMagentoEdition($entityTypeCode = $configuration->getEntityTypeCode());
100
            // load the operation names from the shorcuts
101
            foreach ($shortcuts[$magentoEdition][$entityTypeCode] as $shortcutName => $opNames) {
102
                // query whether or not the operation has to be executed or not
103
                if ($shortcutName === $shortcut) {
104
                    foreach ($opNames as $opName) {
105
                        $configuration->addOperationName($opName);
106
                    }
107
                }
108
            }
109
        }
110
111
        // load the operation names that has to be executed
112
        $operationNames = $configuration->getOperationNames();
113
114
        // load and initialize the operations by their name
115
        foreach ($operationNames as $operationName) {
116
            $execute[] = $this->getOperation($operationName);
117
        }
118
119
        // return the array with the operations
120
        return $execute;
121
    }
122
123
    /**
124
     * Return's the array with the configurations of the plugins that has to be executed.
125
     *
126
     * @return \TechDivision\Import\Configuration\PluginConfigurationInterface[] The plugin configurations
127
     * @throws \Exception Is thrown, if no plugins are available for the actual operation
128
     */
129
    public function getPlugins()
130
    {
131
132
        // initialize the array with the plugins that have to be executed
133
        $plugins = array();
134
135
        // load the operations that has to be executed
136
        $operations = $this->getOperations();
137
138
        // load the configuration instance
139
        $configuration = $this->getConfiguration();
140
141
        // initialize the plugin configurations of the selected operations
142
        foreach ($operations as $operation) {
143
            // iterate over the operation's plugins and initialize their configuration
144
            /** @var \TechDivision\Import\Configuration\PluginConfigurationInterface $plugin */
145
            foreach ($operation->getPlugins() as $plugin) {
146
                // pass the operation configuration instance to the plugin configuration
147
                $plugin->setConfiguration($configuration);
148
                $plugin->setOperationConfiguration($operation);
149
                // if NO prefix for the move files subject has been set, we use the prefix from the first plugin's subject
150
                if ($configuration->getMoveFilesPrefix() === null) {
0 ignored issues
show
Bug introduced by
The method getMoveFilesPrefix() does not seem to exist on object<TechDivision\Impo...ConfigurationInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
151
                    // use the prefix of the first subject
152
                    /** @var \TechDivision\Import\Configuration\SubjectConfigurationInterface $subject */
153
                    foreach ($plugin->getSubjects() as $subject) {
154
                        $configuration->setMoveFilesPrefix($subject->getFileResolver()->getPrefix());
0 ignored issues
show
Bug introduced by
The method setMoveFilesPrefix() does not seem to exist on object<TechDivision\Impo...ConfigurationInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
155
                        break;
156
                    }
157
                }
158
159
                // query whether or not the plugin has subjects configured
160
                if ($subjects = $plugin->getSubjects()) {
161
                    // extend the plugin's subjects with the main configuration instance
162
                    /** @var \TechDivision\Import\Cli\Configuration\Subject $subject */
163
                    foreach ($subjects as $subject) {
164
                        // set the configuration instance on the subject
165
                        $subject->setConfiguration($configuration);
166
                    }
167
                }
168
169
                // finally append the plugin
170
                $plugins[] = $plugin;
171
            }
172
        }
173
174
        // query whether or not we've at least ONE plugin to be executed
175
        if (sizeof($plugins) > 0) {
176
            return $plugins;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $plugins; (array) is incompatible with the return type declared by the interface TechDivision\Import\Conf...erInterface::getPlugins of type Doctrine\Common\Collections\ArrayCollection.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
177
        }
178
179
        // throw an exception if no plugins are available
180
        throw new \Exception(sprintf('Can\'t find any plugins for operation(s) %s', implode(' > ', $configuration->getOperationNames())));
181
    }
182
183
    /**
184
     * Return's the operation with the given name.
185
     *
186
     * @param string $operationName The name of the operation to return
187
     *
188
     * @return \TechDivision\Import\Configuration\OperationConfigurationInterface The operation instance
189
     * @throws \Exception Is thrown if the operation with the given name is not available
190
     */
191
    protected function getOperation($operationName)
192
    {
193
194
        // explode the shortcut to get Magento Edition, Entity Type Code and Operation Name
195
        list($edition, $type, $name) = explode('/', $operationName);
196
197
        // load the operations from the configuration
198
        $operations = $this->getConfiguration()->getOperations();
199
200
        // query whether or not operations for the Magento edition + entity type code are available
201
        if (isset($operations[$edition][$type])) {
202
            // initialize the execution context with the Magento edition + entity type code
203
            $executionContext = new ExecutionContext($edition, $type);
204
            // iterate over the operations, initialize them for execution
205
            foreach ($operations[$edition][$type] as $op) {
206
                // query whether or not the operation is in the array of operation that has to be executed
207
                if ($op->getName() === $name) {
208
                    // pass the execution context to the operation configuration
209
                    $op->setExecutionContext($executionContext);
210
                    // finally add the operation to the array
211
                    return $op;
212
                }
213
            }
214
        }
215
216
        // throw an exception if the operation is not available
217
        throw new \Exception(sprintf('Operation "%s" is not available in scope "%s/%s"', $name, $edition, $type));
218
    }
219
220
    /**
221
     * Return's the Entity Type to the configuration specific Magento Edition.
222
     *
223
     * @param string $entityType The Entity Type fot map
224
     *
225
     * @return string The mapped configuration specific Magento Edition
226
     */
227
    protected function mapEntityTypeToMagentoEdition($entityType)
228
    {
229
230
        // load the actual Magento Edition
231
        $magentoEdition = strtolower($this->getConfiguration()->getMagentoEdition());
232
233
        // map the Entity Type to the configuration specific Magento Edition
234
        if (isset($this->entityTypeToEditionMapping[$entityType])) {
235
            $magentoEdition = $this->entityTypeToEditionMapping[$entityType];
236
        }
237
238
        // return the Magento Edition
239
        return $magentoEdition;
240
    }
241
}
242