Completed
Push — master ( 155c16...880d18 )
by Kamil
26:05
created

TableManipulator::findRowsWithFields()   C

Complexity

Conditions 11
Paths 8

Size

Total Lines 36
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
dl 0
loc 36
rs 5.2653
c 1
b 0
f 1
cc 11
eloc 20
nc 8
nop 2

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 Sylius\Behat;
4
5
use Behat\Mink\Element\NodeElement;
6
7
/**
8
 * @author Kamil Kokot <[email protected]>
9
 */
10
final class TableManipulator implements TableManipulatorInterface
11
{
12
    /**
13
     * {@inheritdoc}
14
     */
15
    public function getRowWithFields(NodeElement $table, array $fields)
16
    {
17
        try {
18
            return $this->getRowsWithFields($table, $fields)[0];
19
        } catch (\InvalidArgumentException $exception) {
20
            throw new \InvalidArgumentException('Could not find row with given fields', 0, $exception);
21
        }
22
    }
23
24
    /**
25
     * {@inheritdoc}
26
     */
27
    public function getRowsWithFields(NodeElement $table, array $fields)
28
    {
29
        try {
30
            $foundRows = $this->findRowsWithFields($table, $fields);
31
32
            return iterator_to_array($foundRows);
33
        } catch (\InvalidArgumentException $exception) {
34
            throw new \InvalidArgumentException('Could not find any row with given fields', 0, $exception);
35
        }
36
    }
37
38
    /**
39
     * {@inheritdoc}
40
     */
41
    public function getFieldFromRow(NodeElement $table, NodeElement $row, $field)
42
    {
43
        $columnIndex = $this->getColumnIndex($table, $field);
44
45
        $columns = $row->findAll('css', 'td,th');
46
        if (!isset($columns[$columnIndex])) {
47
            throw new \InvalidArgumentException(sprintf('Could not find column with index %d', $columnIndex));
48
        }
49
50
        return $columns[$columnIndex];
51
    }
52
53
    /**
54
     * @param NodeElement $table
55
     * @param array $fields
56
     *
57
     * @return \Generator|NodeElement[]
58
     *
59
     * @throws \InvalidArgumentException If columns or rows were not found
60
     */
61
    private function findRowsWithFields(NodeElement $table, array $fields)
62
    {
63
        $rows = $table->findAll('css', 'tr');
64
65
        if (!isset($rows[0])) {
66
            throw new \InvalidArgumentException('There are no rows!');
67
        }
68
69
        $fields = $this->replaceColumnNamesWithColumnIds($table, $fields);
70
71
        /** @var NodeElement[] $rows */
72
        $rows = $table->findAll('css', 'tr');
73
        foreach ($rows as $row) {
74
            /** @var NodeElement[] $columns */
75
            $columns = $row->findAll('css', 'th,td');
76
            foreach ($fields as $index => $searchedValue) {
77
                if (!isset($columns[$index])) {
78
                    throw new \InvalidArgumentException(sprintf('There is no column with index %d', $index));
79
                }
80
81
                $containing = false;
82
                $searchedValue = trim($searchedValue);
83
                if (0 === strpos($searchedValue, '%') && (strlen($searchedValue) - 1) === strrpos($searchedValue, '%')) {
84
                    $searchedValue = substr($searchedValue, 1, -2);
85
                    $containing = true;
86
                }
87
88
                $position = stripos(trim($columns[$index]->getText()), $searchedValue);
89
                if (($containing && false === $position) || (!$containing && 0 !== $position)) {
90
                    continue 2;
91
                }
92
            }
93
94
            yield $row;
95
        }
96
    }
97
98
    /**
99
     * @param NodeElement $table
100
     * @param string[] $fields
101
     *
102
     * @return string[]
103
     *
104
     * @throws \Exception
105
     */
106
    private function replaceColumnNamesWithColumnIds(NodeElement $table, array $fields)
107
    {
108
        $replacedFields = [];
109
        foreach ($fields as $columnName => $expectedValue) {
110
            $columnIndex = $this->getColumnIndex($table, $columnName);
111
112
            $replacedFields[$columnIndex] = $expectedValue;
113
        }
114
115
        return $replacedFields;
116
    }
117
118
    /**
119
     * @param NodeElement $table
120
     * @param string $columnName
121
     *
122
     * @return int
123
     *
124
     * @throws \Exception If column was not found
125
     */
126
    private function getColumnIndex(NodeElement $table, $columnName)
127
    {
128
        $rows = $table->findAll('css', 'tr');
129
130
        if (!isset($rows[0])) {
131
            throw new \InvalidArgumentException('There are no rows!');
132
        }
133
134
        /** @var NodeElement $firstRow */
135
        $firstRow = $rows[0];
136
        $columns = $firstRow->findAll('css', 'th,td');
137
        foreach ($columns as $index => $column) {
138
            /** @var NodeElement $column */
139
            if (0 === stripos($column->getText(), $columnName)) {
140
                return $index;
141
            }
142
        }
143
144
        throw new \InvalidArgumentException(sprintf('Column with name "%s" not found!', $columnName));
145
    }
146
}
147