Failed Conditions
Pull Request — master (#4328)
by Owen
15:26 queued 04:43
created

Matrix   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 144
Duplicated Lines 0 %

Test Coverage

Coverage 91.94%

Importance

Changes 0
Metric Value
wmc 32
eloc 59
dl 0
loc 144
ccs 57
cts 62
cp 0.9194
rs 9.84
c 0
b 0
f 0

5 Methods

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