Passed
Push — master ( bd792e...df3a06 )
by
unknown
15:51 queued 08:04
created

Matrix   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 159
Duplicated Lines 0 %

Test Coverage

Coverage 92.19%

Importance

Changes 0
Metric Value
wmc 33
eloc 61
c 0
b 0
f 0
dl 0
loc 159
ccs 59
cts 64
cp 0.9219
rs 9.76

5 Methods

Rating   Name   Duplication   Size   Complexity  
A isColumnVector() 0 3 1
A isRowVector() 0 4 3
A extractRowValue() 0 13 3
A transpose() 0 22 5
D index() 0 62 21
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Calculation\LookupRef;
4
5
use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
6
use PhpOffice\PhpSpreadsheet\Calculation\Exception;
7
use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
8
9
class Matrix
10
{
11
    use ArrayEnabled;
12
13
    /**
14
     * Helper function; NOT an implementation of any Excel Function.
15
     *
16
     * @param mixed[] $values
17
     */
18 7
    public static function isColumnVector(array $values): bool
19
    {
20 7
        return count($values, COUNT_RECURSIVE) === (count($values, COUNT_NORMAL) * 2);
21
    }
22
23
    /**
24
     * Helper function; NOT an implementation of any Excel Function.
25
     *
26
     * @param mixed[] $values
27
     */
28 4
    public static function isRowVector(array $values): bool
29
    {
30 4
        return count($values, COUNT_RECURSIVE) > 1
31 4
            && (count($values, COUNT_NORMAL) === 1 || count($values, COUNT_RECURSIVE) === count($values, COUNT_NORMAL));
32
    }
33
34
    /**
35
     * TRANSPOSE.
36
     *
37
     * @param mixed $matrixData A matrix of values
38
     *
39
     * @return mixed[]
40
     */
41 39
    public static function transpose($matrixData): array
42
    {
43 39
        $returnMatrix = [];
44 39
        if (!is_array($matrixData)) {
45 1
            $matrixData = [[$matrixData]];
46
        }
47 39
        if (!is_array(end($matrixData))) {
48 1
            $matrixData = [$matrixData];
49
        }
50
51 39
        $column = 0;
52
        /** @var mixed[][] $matrixData */
53 39
        foreach ($matrixData as $matrixRow) {
54 39
            $row = 0;
55 39
            foreach ($matrixRow as $matrixCell) {
56 39
                $returnMatrix[$row][$column] = $matrixCell;
57 39
                ++$row;
58
            }
59 39
            ++$column;
60
        }
61
62 39
        return $returnMatrix;
63
    }
64
65
    /**
66
     * INDEX.
67
     *
68
     * Uses an index to choose a value from a reference or array
69
     *
70
     * Excel Function:
71
     *        =INDEX(range_array, row_num, [column_num], [area_num])
72
     *
73
     * @param mixed $matrix A range of cells or an array constant
74
     * @param mixed $rowNum The row in the array or range from which to return a value.
75
     *                          If row_num is omitted, column_num is required.
76
     *                      Or can be an array of values
77
     * @param mixed $columnNum The column in the array or range from which to return a value.
78
     *                          If column_num is omitted, row_num is required.
79
     *                      Or can be an array of values
80
     *
81
     * TODO Provide support for area_num, currently not supported
82
     *
83
     * @return mixed the value of a specified cell or array of cells
84
     *         If an array of values is passed as the $rowNum and/or $columnNum arguments, then the returned result
85
     *            will also be an array with the same dimensions
86
     */
87 72
    public static function index(mixed $matrix, mixed $rowNum = 0, mixed $columnNum = null): mixed
88
    {
89 72
        if (is_array($rowNum) || is_array($columnNum)) {
90 20
            return self::evaluateArrayArgumentsSubsetFrom([self::class, __FUNCTION__], 1, $matrix, $rowNum, $columnNum);
91
        }
92
93 72
        $rowNum = $rowNum ?? 0;
94 72
        $columnNum = $columnNum ?? 0;
95 72
        if (is_scalar($matrix)) {
96
            if ($rowNum === 0 || $rowNum === 1) {
97
                if ($columnNum === 0 || $columnNum === 1) {
98
                    if ($columnNum === 1 || $rowNum === 1) {
99
                        return $matrix;
100
                    }
101
                }
102
            }
103
        }
104
105
        try {
106 72
            $rowNum = LookupRefValidations::validatePositiveInt($rowNum);
107 65
            $columnNum = LookupRefValidations::validatePositiveInt($columnNum);
108 14
        } catch (Exception $e) {
109 14
            return $e->getMessage();
110
        }
111
112 58
        if (is_array($matrix) && count($matrix) === 1 && $rowNum > 1) {
113 2
            $matrixKey = array_keys($matrix)[0];
114 2
            if (is_array($matrix[$matrixKey])) {
115 2
                $tempMatrix = [];
116 2
                foreach ($matrix[$matrixKey] as $key => $value) {
117 2
                    $tempMatrix[$key] = [$value];
118
                }
119 2
                $matrix = $tempMatrix;
120
            }
121
        }
122
123 58
        if (!is_array($matrix) || ($rowNum > count($matrix))) {
124 2
            return ExcelError::REF();
125
        }
126
127 56
        $rowKeys = array_keys($matrix);
128 56
        $columnKeys = @array_keys($matrix[$rowKeys[0]]); //* @phpstan-ignore-line
129
130 56
        if ($columnNum > count($columnKeys)) {
131 2
            return ExcelError::REF();
132
        }
133
134 54
        if ($columnNum === 0) {
135 37
            return self::extractRowValue($matrix, $rowKeys, $rowNum);
136
        }
137
138 18
        $columnNum = $columnKeys[--$columnNum];
139 18
        if ($rowNum === 0) {
140 4
            return array_map(
141 4
                fn ($value): array => [$value],
142 4
                array_column($matrix, $columnNum)
143 4
            );
144
        }
145 15
        $rowNum = $rowKeys[--$rowNum];
146
        /** @var mixed[][] $matrix */
147
148 15
        return $matrix[$rowNum][$columnNum];
149
    }
150
151
    /**
152
     * @param mixed[] $matrix
153
     * @param mixed[] $rowKeys
154
     */
155 37
    private static function extractRowValue(array $matrix, array $rowKeys, int $rowNum): mixed
156
    {
157 37
        if ($rowNum === 0) {
158 2
            return $matrix;
159
        }
160
161 35
        $rowNum = $rowKeys[--$rowNum];
162 35
        $row = $matrix[$rowNum];
163 35
        if (is_array($row)) {
164 35
            return [$rowNum => $row];
165
        }
166
167
        return $row;
168
    }
169
}
170