addTableToConfiguration()   B
last analyzed

Complexity

Conditions 8
Paths 80

Size

Total Lines 86

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 86
rs 7.061
c 0
b 0
f 0
cc 8
nc 80
nop 8

How to fix   Long Method    Many Parameters   

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:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
 * @author stev leibelt <[email protected]>
4
 * @since 2014-05-26 
5
 */
6
7
namespace Net\Bazzline\Component\Locator\Configuration\Assembler;
8
9
use Net\Bazzline\Component\Locator\Configuration\Configuration;
10
use Net\Bazzline\Component\Locator\Configuration\Validator\ReadableFilePath;
11
use XMLReader;
12
13
/**
14
 * Class FromPropelSchemaXmlAssembler
15
 * @package Net\Bazzline\Component\Locator\Configuration\Assembler
16
 */
17
class FromPropelSchemaXmlAssembler extends AbstractAssembler
18
{
19
    /**
20
     * @param mixed $data
21
     * @param Configuration $configuration
22
     * @return Configuration
23
     * @throws RuntimeException
24
     */
25
    protected function map($data, Configuration $configuration)
26
    {
27
        //begin of variable definitions
28
        $columnClassMethodBodyBuilder =
29
            (isset($data['column_class_method_body_builder']))
30
                ? $data['column_class_method_body_builder']
31
                : null;
32
33
        $locatorNamespace =
34
            (isset($data['namespace']))
35
                ? $data['namespace']
36
                : '';
37
38
        $methodNameWithoutNamespace =
39
            (isset($data['method_name_without_namespace']))
40
                ? $data['method_name_without_namespace']
41
                : false;
42
43
        $pathToSchemaXml = realpath($data['path_to_schema_xml']);
44
        $queryClassMethodBodyBuilder =
45
            (isset($data['query_class_method_body_builder']))
46
                ? $data['query_class_method_body_builder']
47
                : null;
48
        //end of variable definitions
49
50
        //@todo inject
51
        $validator = new ReadableFilePath();
52
        $validator->validate($pathToSchemaXml);
53
54
        $configuration = $this->mapBooleanProperties(
55
            $data,
56
            $configuration
57
        );
58
        $configuration = $this->mapStringProperties(
59
            $data,
60
            $configuration
61
        );
62
        $configuration = $this->mapSchemaXmlPropertiesToConfiguration(
63
            $pathToSchemaXml,
64
            $configuration,
65
            $columnClassMethodBodyBuilder,
66
            $locatorNamespace,
67
            $queryClassMethodBodyBuilder,
68
            $methodNameWithoutNamespace
69
        );
70
        $configuration = $this->mapArrayPropertiesToConfiguration(
71
            $data,
72
            $configuration
73
        );
74
75
        return $configuration;
76
    }
77
78
    /**
79
     * @param mixed $data
80
     * @throws InvalidArgumentException
81
     */
82 View Code Duplication
    protected function validateData($data)
83
    {
84
        if (!is_array($data)) {
85
            throw new InvalidArgumentException(
86
                'data must be an array'
87
            );
88
        }
89
90
        if (empty($data)) {
91
            throw new InvalidArgumentException(
92
                'data array must contain content'
93
            );
94
        }
95
96
        $mandatoryKeysToExpectedValueTyp = array(
97
            'class_name'            => 'string',
98
            'file_path'             => 'string'
99
        );
100
101
        $this->validateDataWithMandatoryKeysAndExpectedValueType(
102
            $data,
103
            $mandatoryKeysToExpectedValueTyp
104
        );
105
106
        $optionalKeysToExpectedValueTyp = array(
107
            'extends'                       => 'string',
108
            'implements'                    => 'array',
109
            'method_name_without_namespace' => 'boolean',
110
            'namespace'                     => 'string',
111
            'path_to_schema_xml'            => 'string',
112
            'uses'                          => 'array'
113
        );
114
115
        $this->validateDataWithOptionalKeysAndExpectedValueTypeOrSetExpectedValueAsDefault(
116
            $data,
117
            $optionalKeysToExpectedValueTyp
118
        );
119
    }
120
121
    /**
122
     * @param string $pathToSchemaXml
123
     * @param Configuration $configuration
124
     * @param string $columnClassMethodBodyBuilder
125
     * @param string $locatorNamespace
126
     * @param string $queryClassMethodBodyBuilder
127
     * @param boolean $methodNameWithoutNamespace
128
     * @return Configuration
129
     */
130
    private function mapSchemaXmlPropertiesToConfiguration(
131
        $pathToSchemaXml,
132
        Configuration $configuration,
133
        $columnClassMethodBodyBuilder,
134
        $locatorNamespace,
135
        $queryClassMethodBodyBuilder,
136
        $methodNameWithoutNamespace
137
    )
138
    {
139
        //begin of variable definitions
140
        $hasRootNamespace = false;
141
        //@todo inject XMLReader
142
        $reader = new XMLReader();
143
        $reader->open($pathToSchemaXml);
144
        $rootNamespace = '';
145
        //end of variable definitions
146
147
        //begin of xml parsing
148
        while ($reader->read()) {
149
            if ($reader->nodeType === XMLREADER::ELEMENT) {
150
                $nodeIsADatabase    = ($reader->name === 'database');
151
                $nodeIsATable       = ($reader->name === 'table');
152
153
                if ($nodeIsADatabase) {
154
                    $rootNamespace = $reader->getAttribute('namespace');
155
                    if(strlen($rootNamespace) > 0) {
156
                        $hasRootNamespace = true;
157
                    }
158
                }
159
160
                if ($nodeIsATable) {
161
                    $configuration = $this->addTableToConfiguration(
162
                        $reader,
163
                        $hasRootNamespace,
164
                        $rootNamespace,
165
                        $locatorNamespace,
166
                        $configuration,
167
                        $columnClassMethodBodyBuilder,
168
                        $queryClassMethodBodyBuilder,
169
                        $methodNameWithoutNamespace
170
                    );
171
                }
172
            }
173
        }
174
        $reader->close();
175
        //end of xml parsing
176
177
        return $configuration;
178
    }
179
180
    /**
181
     * @param array $data
182
     * @param Configuration $configuration
183
     * @return Configuration
184
     * @throws RuntimeException
185
     */
186 View Code Duplication
    private function mapArrayPropertiesToConfiguration(array $data, Configuration $configuration)
187
    {
188
        if (isset($data['implements'])) {
189
            foreach($data['implements'] as $interfaceName) {
190
                $configuration->addImplements($interfaceName);
191
            }
192
        }
193
194
        if (isset($data['uses'])) {
195
            foreach ($data['uses'] as $key => $uses) {
196
                if (!isset($uses['class_name'])) {
197
                    throw new RuntimeException(
198
                        'use entry with key "' . $key . '" needs to have a key "class_name"'
199
                    );
200
                }
201
202
                $alias      = (isset($uses['alias'])) ? $uses['alias'] : '';
203
                $className  = str_replace('\\\\', '\\', $uses['class_name']);
204
                $configuration->addUses($className, $alias);
205
            }
206
        }
207
208
        return $configuration;
209
    }
210
211
    /**
212
     * @param XMLReader $reader
213
     * @param boolean $hasRootNamespace
214
     * @param string $rootNamespace
215
     * @param string $locatorNamespace
216
     * @param Configuration $configuration
217
     * @param string $columnClassMethodBodyBuilder
218
     * @param string $queryClassMethodBodyBuilder
219
     * @param boolean $methodNameWithoutNamespace
220
     * @return Configuration
221
     */
222
    private function addTableToConfiguration(
223
        XMLReader $reader,
224
        $hasRootNamespace,
225
        $rootNamespace,
226
        $locatorNamespace,
227
        Configuration $configuration,
228
        $columnClassMethodBodyBuilder,
229
        $queryClassMethodBodyBuilder,
230
        $methodNameWithoutNamespace
231
    )
232
    {
233
        //begin of variable definitions
234
        $namespace              = $reader->getAttribute('namespace');
235
        $phpName                = $reader->getAttribute('phpName');
236
        $tableName              = $reader->getAttribute('name');
237
        $tableNamespace         = '';
238
        $hasPhpName             = (strlen($phpName) > 0);
239
        $hasNamespace           = (strlen($namespace) > 0);
240
        //end of variable definitions
241
242
        //begin of class name building
243
        if ($hasRootNamespace) {
244
            $tableNamespace .= '\\' . $rootNamespace . '\\';
245
        }
246
247
        if ($hasNamespace) {
248
            $tableNamespace .= $namespace . '\\';
249
        }
250
251
        $hasDifferentNamespaceThanLocator   = ($locatorNamespace !== $tableNamespace);
252
        $hasTableNamespace                  = (strlen($tableNamespace) > 0);
253
        $fullQualifiedClassName             = $this->createFullQualifiedClassName(
254
            $hasPhpName,
255
            $phpName,
256
            $tableName,
257
            $hasTableNamespace,
258
            $tableNamespace
259
        );
260
261
        $classNameAlias = ($methodNameWithoutNamespace)
262
            ? $this->createClassNameAlias($hasPhpName, $phpName, $tableName)
263
            : null;
264
265
        $queryClassNameAlias =
266
            (!is_null($classNameAlias))
267
                ? $classNameAlias . 'Query'
268
                : null;
269
270
        $fullQualifiedQueryClassName = $fullQualifiedClassName . 'Query';
271
        //end of class name building
272
273
        //begin of configuration adaptation
274
        $configuration->addInstance(
275
            $fullQualifiedClassName,
276
            false,
277
            false,
278
            $fullQualifiedClassName,
279
            $classNameAlias,
280
            $columnClassMethodBodyBuilder
281
        );
282
        $configuration->addInstance(
283
            $fullQualifiedQueryClassName,
284
            false,
285
            false,
286
            $fullQualifiedClassName,
287
            $queryClassNameAlias,
288
            $queryClassMethodBodyBuilder
289
        );
290
291
        if ($hasDifferentNamespaceThanLocator) {
292
            //we have to remove the first "\" if available
293
            $useClassName = ($this->startsWith($fullQualifiedClassName, '\\'))
294
                ? substr($fullQualifiedClassName, 1)
295
                : $fullQualifiedClassName;
296
297
            $useQueryClassName = ($this->startsWith($fullQualifiedQueryClassName, '\\'))
298
                ? substr($fullQualifiedQueryClassName, 1)
299
                : $fullQualifiedQueryClassName;
300
301
            $configuration->addUses($useClassName);
302
            $configuration->addUses($useQueryClassName);
303
        }
304
        //end of configuration adaptation
305
306
        return $configuration;
307
    }
308
309
    /**
310
     * @param string $haystack
311
     * @param string $needle
312
     * @return bool
313
     */
314
    private function startsWith($haystack, $needle)
315
    {
316
        return (strncmp($haystack, $needle, strlen($needle)) === 0);
317
    }
318
319
    /**
320
     * @param boolean $hasPhpName
321
     * @param string $phpName
322
     * @param string $tableName
323
     * @param boolean $hasTableNamespace
324
     * @param string $tableNamespace
325
     * @return mixed|string
326
     */
327
    private function createFullQualifiedClassName($hasPhpName, $phpName, $tableName, $hasTableNamespace, $tableNamespace)
328
    {
329
        $fullQualifiedClassName = '';
330
331
        if ($hasPhpName) {
332
            $fullQualifiedClassName = $phpName;
333
        } else {
334
            $tableNameAsArray = explode('_', $tableName);
335
            array_walk($tableNameAsArray, function (&$value) {
336
                $value = ucfirst($value);
337
            });
338
            $fullQualifiedClassName .= implode('', $tableNameAsArray);
339
        }
340
341
        if ($hasTableNamespace) {
342
            $fullQualifiedClassName = $tableNamespace . '\\' . $fullQualifiedClassName;
343
        }
344
345
        $fullQualifiedClassName = str_replace('\\\\', '\\', $fullQualifiedClassName);
346
347
        return $fullQualifiedClassName;
348
    }
349
350
    /**
351
     * @param boolean $hasPhpName
352
     * @param string $phpName
353
     * @param string $tableName
354
     * @return string
355
     */
356
    private function createClassNameAlias($hasPhpName, $phpName, $tableName)
357
    {
358
        return ($hasPhpName) ? $phpName : $tableName;
359
    }
360
}
361