Failed Conditions
Pull Request — master (#3528)
by Owen
15:06 queued 35s
created

CellReferenceHelper::updateColumnReference()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 5
rs 10
c 0
b 0
f 0
ccs 3
cts 3
cp 1
cc 1
nc 1
nop 2
crap 1
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet;
4
5
use PhpOffice\PhpSpreadsheet\Cell\AddressRange;
6
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
7
8
class CellReferenceHelper
9
{
10
    protected string $beforeCellAddress;
11
12
    protected int $beforeColumn;
13
14
    protected bool $beforeColumnAbsolute = false;
15
16
    protected string $beforeColumnString;
17
18
    protected int $beforeRow;
19
20
    protected bool $beforeRowAbsolute = false;
21
22
    protected int $numberOfColumns;
23
24
    protected int $numberOfRows;
25
26 436
    public function __construct(string $beforeCellAddress = 'A1', int $numberOfColumns = 0, int $numberOfRows = 0)
27
    {
28 436
        $this->beforeColumnAbsolute = $beforeCellAddress[0] === '$';
29 436
        $this->beforeRowAbsolute = strpos($beforeCellAddress, '$', 1) !== false;
30 436
        $this->beforeCellAddress = str_replace('$', '', $beforeCellAddress);
31 436
        $this->numberOfColumns = $numberOfColumns;
32 436
        $this->numberOfRows = $numberOfRows;
33
34
        // Get coordinate of $beforeCellAddress
35 436
        [$beforeColumn, $beforeRow] = Coordinate::coordinateFromString($beforeCellAddress);
36 436
        $this->beforeColumnString = $beforeColumn;
37 436
        $this->beforeColumn = (int) Coordinate::columnIndexFromString($beforeColumn);
38 436
        $this->beforeRow = (int) $beforeRow;
39
    }
40
41 4
    public function beforeCellAddress(): string
42
    {
43 4
        return $this->beforeCellAddress;
44
    }
45
46 339
    public function refreshRequired(string $beforeCellAddress, int $numberOfColumns, int $numberOfRows): bool
47
    {
48 339
        return $this->beforeCellAddress !== $beforeCellAddress
49 339
            || $this->numberOfColumns !== $numberOfColumns
50 339
            || $this->numberOfRows !== $numberOfRows;
51
    }
52
53 426
    public function updateCellReference(string $cellReference = 'A1', bool $includeAbsoluteReferences = false, bool $onlyAbsoluteReferences = false, ?bool $topLeft = null): string
54
    {
55 426
        if (Coordinate::coordinateIsRange($cellReference)) {
56 1
            throw new Exception('Only single cell references may be passed to this method.');
57
        }
58
59
        // Get coordinate of $cellReference
60 425
        [$newColumn, $newRow] = Coordinate::coordinateFromString($cellReference);
61 425
        $newColumnIndex = Coordinate::columnIndexFromString(str_replace('$', '', $newColumn));
62 425
        $newRowIndex = (int) str_replace('$', '', $newRow);
63
64 425
        $absoluteColumn = $newColumn[0] === '$' ? '$' : '';
65 425
        $absoluteRow = $newRow[0] === '$' ? '$' : '';
66
        // Verify which parts should be updated
67 425
        if ($onlyAbsoluteReferences === true) {
68 5
            $updateColumn = (($absoluteColumn === '$') && $newColumnIndex >= $this->beforeColumn);
69 5
            $updateRow = (($absoluteRow === '$') && $newRowIndex >= $this->beforeRow);
70 421
        } elseif ($includeAbsoluteReferences === false) {
71 357
            $updateColumn = (($absoluteColumn !== '$') && $newColumnIndex >= $this->beforeColumn);
72 357
            $updateRow = (($absoluteRow !== '$') && $newRowIndex >= $this->beforeRow);
73
        } else {
74
            // A special case is removing the left/top or bottom/right edge of a range
75
            // $topLeft is null if we aren't adjusting a range at all.
76
            if (
77 95
                $topLeft !== null
78 95
                && $this->numberOfColumns < 0
79 95
                && $newColumnIndex >= $this->beforeColumn + $this->numberOfColumns
80 95
                && $newColumnIndex <= $this->beforeColumn - 1
81
            ) {
82 1
                if ($topLeft) {
83
                    $newColumnIndex = $this->beforeColumn + $this->numberOfColumns;
84
                } else {
85 1
                    $newColumnIndex = $this->beforeColumn + $this->numberOfColumns - 1;
86
                }
87 95
            } elseif ($newColumnIndex >= $this->beforeColumn) {
88
                // Create new column reference
89 86
                $newColumnIndex += $this->numberOfColumns;
90
            }
91 95
            $newColumn = $absoluteColumn . Coordinate::stringFromColumnIndex($newColumnIndex);
92
            //$updateColumn = ($newColumnIndex >= $this->beforeColumn);
93 95
            $updateColumn = false;
94
            // A special case is removing the left/top or bottom/right edge of a range
95
            // $topLeft is null if we aren't adjusting a range at all.
96
            if (
97 95
                $topLeft !== null
98 95
                && $this->numberOfRows < 0
99 95
                && $newRowIndex >= $this->beforeRow + $this->numberOfRows
100 95
                && $newRowIndex <= $this->beforeRow - 1
101
            ) {
102 2
                if ($topLeft) {
103 2
                    $newRowIndex = $this->beforeRow + $this->numberOfRows;
104
                } else {
105
                    $newRowIndex = $this->beforeRow + $this->numberOfRows - 1;
106
                }
107 95
            } elseif ($newRowIndex >= $this->beforeRow) {
108 88
                $newRowIndex = $newRowIndex + $this->numberOfRows;
109
            }
110 95
            $newRow = $absoluteRow . $newRowIndex;
111
            //$updateRow = ($newRowIndex >= $this->beforeRow);
112 95
            $updateRow = false;
113
        }
114
115
        // Create new column reference
116 425
        if ($updateColumn) {
117 321
            $newColumn = $this->updateColumnReference($newColumnIndex, $absoluteColumn);
118
        }
119
120
        // Create new row reference
121 425
        if ($updateRow) {
122 317
            $newRow = $this->updateRowReference($newRowIndex, $absoluteRow);
123
        }
124
125
        // Return new reference
126 425
        return "{$newColumn}{$newRow}";
127
    }
128
129 28
    public function cellAddressInDeleteRange(string $cellAddress): bool
130
    {
131 28
        [$cellColumn, $cellRow] = Coordinate::coordinateFromString($cellAddress);
132 28
        $cellColumnIndex = Coordinate::columnIndexFromString($cellColumn);
133
        //    Is cell within the range of rows/columns if we're deleting
134
        if (
135 28
            $this->numberOfRows < 0
136 28
            && ($cellRow >= ($this->beforeRow + $this->numberOfRows))
137 28
            && ($cellRow < $this->beforeRow)
138
        ) {
139 1
            return true;
140
        } elseif (
141 28
            $this->numberOfColumns < 0
142 28
            && ($cellColumnIndex >= ($this->beforeColumn + $this->numberOfColumns))
143 28
            && ($cellColumnIndex < $this->beforeColumn)
144
        ) {
145 1
            return true;
146
        }
147
148 27
        return false;
149
    }
150
151 321
    protected function updateColumnReference(int $newColumnIndex, string $absoluteColumn): string
152
    {
153 321
        $newColumn = Coordinate::stringFromColumnIndex(min($newColumnIndex + $this->numberOfColumns, AddressRange::MAX_COLUMN_INT));
154
155 321
        return "{$absoluteColumn}{$newColumn}";
156
    }
157
158 317
    protected function updateRowReference(int $newRowIndex, string $absoluteRow): string
159
    {
160 317
        $newRow = $newRowIndex + $this->numberOfRows;
161 317
        $newRow = ($newRow > AddressRange::MAX_ROW) ? AddressRange::MAX_ROW : $newRow;
162
163 317
        return "{$absoluteRow}{$newRow}";
164
    }
165
}
166