Completed
Push — master ( b5c840...3d5461 )
by Marcus
04:46
created

ConfigurationManager   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 239
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 23
lcom 1
cbo 3
dl 0
loc 239
ccs 0
cts 87
cp 0
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A getConfiguration() 0 4 1
B getOperations() 0 41 6
B getPlugins() 0 57 9
A getOperation() 0 24 2
A mapEntityType() 0 11 2
A mapEntityTypeToMagentoEdition() 0 14 2
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\Configuration\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\Configuration\ConfigurationInterface
42
     */
43
    private $configuration;
44
45
    /**
46
     * Mapping for entity type (for configuration purposes only).
47
     *
48
     * @var array
49
     */
50
    private $entityTypeMapping = array('none' => 'general');
51
52
    /**
53
     * Mapping for entity type to edition mapping (for configuration purposes only).
54
     *
55
     * @var array
56
     */
57
    private $entityTypeToEditionMapping = array(
58
        'eav_attribute'                 => 'general',
59
        'eav_attribute_set'             => 'general',
60
        'catalog_product_inventory_msi' => 'general',
61
        'catalog_product_tier_price'    => 'general',
62
        'catalog_product_url'           => 'general',
63
        'customer_address'              => 'general',
64
        'customer'                      => 'general',
65
        'general'                       => 'general',
66
        'none'                          => 'general'
67
    );
68
69
    /**
70
     * Initializes the manager with the configuration instance.
71
     *
72
     * @param \TechDivision\Import\Configuration\ConfigurationInterface $configuration The configuration instance
73
     */
74
    public function __construct(ConfigurationInterface $configuration)
75
    {
76
        $this->configuration = $configuration;
77
    }
78
79
    /**
80
     * Return's the managed configuration instance.
81
     *
82
     * @return \TechDivision\Import\Configuration\ConfigurationInterface The configuration instance
83
     */
84
    public function getConfiguration()
85
    {
86
        return $this->configuration;
87
    }
88
89
    /**
90
     * Return's an array with the configurations of the operations that has to be executed.
91
     *
92
     * @return \TechDivision\Import\Configuration\OperationConfigurationInterface[] The operation configurations
93
     */
94
    public function getOperations()
95
    {
96
97
        // load the configuration instance
98
        $configuration = $this->getConfiguration();
99
100
        // initialize the array for the operations that has to be executed
101
        $execute = array();
102
103
        // load the shortcuts from the configuration
104
        $shortcuts = $configuration->getShortcuts();
105
106
        // map the entity type code, if necessary
107
        $entityTypeCode = $this->mapEntityType($configuration->getEntityTypeCode());
108
109
        // query whether or not a shortcut has been passed
110
        if ($shortcut = $configuration->getShortcut()) {
111
            // load the entity type code and map it to the Magento edition
112
            $magentoEdition = $this->mapEntityTypeToMagentoEdition($entityTypeCode);
113
            // load the operation names from the shorcuts
114
            foreach ($shortcuts[$magentoEdition][$entityTypeCode] as $shortcutName => $opNames) {
115
                // query whether or not the operation has to be executed or not
116
                if ($shortcutName === $shortcut) {
117
                    foreach ($opNames as $opName) {
118
                        $configuration->addOperationName($opName);
119
                    }
120
                }
121
            }
122
        }
123
124
        // load the operation names that has to be executed
125
        $operationNames = $configuration->getOperationNames();
126
127
        // load and initialize the operations by their name
128
        foreach ($operationNames as $operationName) {
129
            $execute[] = $this->getOperation($operationName);
130
        }
131
132
        // return the array with the operations
133
        return $execute;
134
    }
135
136
    /**
137
     * Return's the array with the configurations of the plugins that has to be executed.
138
     *
139
     * @return \TechDivision\Import\Configuration\PluginConfigurationInterface[] The plugin configurations
140
     * @throws \Exception Is thrown, if no plugins are available for the actual operation
141
     */
142
    public function getPlugins()
143
    {
144
145
        // initialize the array with the plugins that have to be executed
146
        $plugins = array();
147
148
        // load the operations that has to be executed
149
        $operations = $this->getOperations();
150
151
        // load the configuration instance
152
        $configuration = $this->getConfiguration();
153
154
        // initialize the plugin configurations of the selected operations
155
        foreach ($operations as $operation) {
156
            // iterate over the operation's plugins and initialize their configuration
157
            /** @var \TechDivision\Import\Configuration\PluginConfigurationInterface $plugin */
158
            foreach ($operation->getPlugins() as $plugin) {
159
                // pass the operation configuration instance to the plugin configuration
160
                $plugin->setConfiguration($configuration);
161
                $plugin->setOperationConfiguration($operation);
162
                // if NO prefix for the move files subject has been set, we use the prefix from the first plugin's subject
163
                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...
164
                    // use the prefix of the first subject that needs an .OK file
165
                    /** @var \TechDivision\Import\Configuration\SubjectConfigurationInterface $subject */
166
                    foreach ($plugin->getSubjects() as $subject) {
167
                        // we use the subject with the first file resolver that has a custom
168
                        // prefix set to initialize the prefix for the move files subject for
169
                        if ($subject->getFileResolver()->hasPrefix()) {
170
                            $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...
171
                            break;
172
                        }
173
                    }
174
                }
175
176
                // query whether or not the plugin has subjects configured
177
                if ($subjects = $plugin->getSubjects()) {
178
                    // extend the plugin's subjects with the main configuration instance
179
                    /** @var \TechDivision\Import\Configuration\SubjectConfigurationInterface $subject */
180
                    foreach ($subjects as $subject) {
181
                        // set the configuration instance on the subject
182
                        $subject->setConfiguration($configuration);
183
                    }
184
                }
185
186
                // finally append the plugin
187
                $plugins[] = $plugin;
188
            }
189
        }
190
191
        // query whether or not we've at least ONE plugin to be executed
192
        if (sizeof($plugins) > 0) {
193
            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...
194
        }
195
196
        // throw an exception if no plugins are available
197
        throw new \Exception(sprintf('Can\'t find any plugins for shortcut "%s"', $configuration->getShortcut()));
198
    }
199
200
    /**
201
     * Return's the operation with the given name.
202
     *
203
     * @param string $operationName The name of the operation to return
204
     *
205
     * @return \TechDivision\Import\Configuration\OperationConfigurationInterface The operation instance
206
     * @throws \Exception Is thrown if the operation with the given name is not available
207
     */
208
    protected function getOperation($operationName)
209
    {
210
211
        // explode the shortcut to get Magento Edition, Entity Type Code and Operation Name
212
        list($edition, $type, $name) = explode('/', $operationName);
213
214
        // load the operations from the configuration
215
        $operations = $this->getConfiguration()->getOperations();
216
217
        // query whether or not operations for the Magento edition + entity type code are available
218
        if (isset($operations[$edition][$type][$name])) {
219
            // load the operation
220
            $op = $operations[$edition][$type][$name];
221
            // pass the name to the operation configuration
222
            $op->setName($name);
223
            // initialize and pass the execution context to the operation configuration
224
            $op->setExecutionContext(new ExecutionContext($edition, $type));
225
            // finally add the operation to the array
226
            return $op;
227
        }
228
229
        // throw an exception if the operation is not available
230
        throw new \Exception(sprintf('Operation "%s" is not available in scope "%s/%s"', $name, $edition, $type));
231
    }
232
233
    /**
234
     * Return's the entity type mapping.
235
     *
236
     * @param string $entityType The entity type to map
237
     *
238
     * @return string The mapped entity type
239
     */
240
    protected function mapEntityType($entityType)
241
    {
242
243
        // map the entity type, if a mapping is available
244
        if (isset($this->entityTypeMapping[$entityType])) {
245
            return $this->entityTypeMapping[$entityType];
246
        }
247
248
        // return the entity type
249
        return $entityType;
250
    }
251
252
    /**
253
     * Return's the entity type to the configuration specific Magento edition.
254
     *
255
     * @param string $entityType The entity type to map
256
     *
257
     * @return string The mapped configuration specific Magento edition
258
     */
259
    protected function mapEntityTypeToMagentoEdition($entityType)
260
    {
261
262
        // load the actual Magento edition
263
        $magentoEdition = strtolower($this->getConfiguration()->getMagentoEdition());
264
265
        // map the entity type to the configuration specific Magento edition
266
        if (isset($this->entityTypeToEditionMapping[$entityType])) {
267
            $magentoEdition = $this->entityTypeToEditionMapping[$entityType];
268
        }
269
270
        // return the magento edition
271
        return $magentoEdition;
272
    }
273
}
274