Completed
Pull Request — master (#27)
by jean-marie
02:29
created

RowIterator::next()   C

Complexity

Conditions 10
Paths 10

Size

Total Lines 47
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 47
rs 5.1578
cc 10
eloc 36
nc 10
nop 0

How to fix   Complexity   

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
namespace Akeneo\Component\SpreadsheetParser\Xlsx;
4
5
/**
6
 * Row iterator for an Excel worksheet
7
 *
8
 * The iterator returns arrays of results.
9
 *
10
 * Empty values are trimed from the right of the rows, and empty rows are skipped.
11
 *
12
 * @author    Antoine Guigan <[email protected]>
13
 * @copyright 2014 Akeneo SAS (http://www.akeneo.com)
14
 * @license   http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
15
 */
16
class RowIterator implements \Iterator
17
{
18
    /**
19
     * @var RowBuilderFactory
20
     */
21
    protected $rowBuilderFactory;
22
23
    /**
24
     * @var ColumnIndexTransformer
25
     */
26
    protected $columnIndexTransformer;
27
28
    /**
29
     * @var ValueTransformer
30
     */
31
    protected $valueTransformer;
32
33
    /**
34
     * @var string
35
     */
36
    protected $path;
37
38
    /**
39
     * @var array
40
     */
41
    protected $options;
42
43
    /**
44
     * @var \XMLReader
45
     */
46
    protected $xml;
47
48
    /**
49
     * @var array
50
     */
51
    protected $currentKey;
52
53
    /**
54
     * @var array
55
     */
56
    protected $currentValue;
57
58
    /**
59
     * @var boolean
60
     */
61
    protected $valid;
62
63
    /**
64
     * Constructor
65
     *
66
     * @param RowBuilderFactory      $rowBuilderFactory
67
     * @param ColumnIndexTransformer $columnIndexTransformer
68
     * @param ValueTransformer       $valueTransformer
69
     * @param string                 $path
70
     * @param array                  $options
71
     */
72
    public function __construct(
73
        RowBuilderFactory $rowBuilderFactory,
74
        ColumnIndexTransformer $columnIndexTransformer,
75
        ValueTransformer $valueTransformer,
76
        $path,
77
        array $options
78
    ) {
79
        $this->rowBuilderFactory = $rowBuilderFactory;
80
        $this->columnIndexTransformer = $columnIndexTransformer;
81
        $this->valueTransformer = $valueTransformer;
82
        $this->path = $path;
83
        $this->options = $options;
84
    }
85
86
    /**
87
     * {@inheritdoc}
88
     */
89
    public function current()
90
    {
91
        return $this->currentValue;
92
    }
93
94
    /**
95
     * {@inheritdoc}
96
     */
97
    public function key()
98
    {
99
        return $this->currentKey;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->currentKey; (array) is incompatible with the return type declared by the interface Iterator::key of type integer|double|string|boolean.

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...
100
    }
101
102
    /**
103
     * {@inheritdoc}
104
     */
105
    public function next()
106
    {
107
        $this->valid = false;
108
109
        $style = null;
110
        $type = null;
111
        $columnIndex = null;
112
        $rowBuilder = null;
113
        $currentKey = null;
114
115
        while ($this->xml->read()) {
116
            if (\XMLReader::ELEMENT === $this->xml->nodeType) {
117
                switch ($this->xml->name) {
118
                    case 'row' :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
119
                        $currentKey = (int)$this->xml->getAttribute('r');
120
                        $rowBuilder = $this->rowBuilderFactory->create();
121
                        break;
122
                    case 'c' :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
123
                        $columnIndex = $this->columnIndexTransformer->transform($this->xml->getAttribute('r'));
124
                        $style = $this->getValue($this->xml->getAttribute('s'));
125
                        $type = $this->getValue($this->xml->getAttribute('t'));
126
                        break;
127
                    case 'v' :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
128
                        $rowBuilder->addValue(
129
                            $columnIndex,
130
                            $this->valueTransformer->transform($this->xml->readString(), $type, $style)
131
                        );
132
                        break;
133
                }
134
            } elseif (\XMLReader::END_ELEMENT === $this->xml->nodeType) {
135
                switch ($this->xml->name) {
136
                    case 'row' :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
137
                        $currentValue = $rowBuilder->getData();
138
                        if (count($currentValue)) {
139
                            $this->currentKey = $currentKey;
0 ignored issues
show
Documentation Bug introduced by
It seems like $currentKey of type null or integer is incompatible with the declared type array of property $currentKey.

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...
140
                            $this->currentValue = $currentValue;
141
                            $this->valid = true;
142
143
                            return;
144
                        }
145
                        break;
146
                    case 'sheetData' :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
147
                        break 2;
148
                }
149
            }
150
        }
151
    }
152
153
    /**
154
     * {@inheritdoc}
155
     */
156
    public function rewind()
157
    {
158
        if ($this->xml) {
159
            $this->xml->close();
160
        }
161
        $this->xml = new \XMLReader();
162
        $this->xml->open($this->path);
163
        $this->next();
164
    }
165
166
    /**
167
     * {@inheritdoc}
168
     */
169
    public function valid()
170
    {
171
        return $this->valid;
172
    }
173
174
    /**
175
     * Returns a normalized attribute value
176
     *
177
     * @param string $value
178
     *
179
     * @return string
180
     */
181
    protected function getValue($value)
182
    {
183
        return null === $value ? '' : $value;
184
    }
185
}
186