| 180 | } |
| 181 | |
| 182 | private function validateRanges(string $rangeList): ?string { |
| 183 | $ranges = str_getcsv($rangeList); |
| 184 | $totalCells = 0; |
| 185 | foreach ($ranges as $range) { |
| 186 | $range = strtoupper(trim($range)); |
| 187 | if ($range === '') { |
| 188 | return $this->l10n->t('Invalid spreadsheet range'); |
| 189 | } |
| 190 | |
| 191 | if (preg_match('/^(?<startColumn>[A-Z]{1,3})(?<startRow>[1-9][0-9]*)(?::(?<endColumn>[A-Z]{1,3})(?<endRow>[1-9][0-9]*))?$/', $range, $matches) !== 1) { |
| 192 | return $this->l10n->t('Invalid spreadsheet range'); |
| 193 | } |
| 194 | |
| 195 | $endColumn = ($matches['endColumn'] ?? '') !== '' ? $matches['endColumn'] : $matches['startColumn']; |
| 196 | $endRow = ($matches['endRow'] ?? '') !== '' ? $matches['endRow'] : $matches['startRow']; |
| 197 | $rows = abs((int)$endRow - (int)$matches['startRow']) + 1; |
| 198 | if ($rows > self::MAX_RANGE_ROWS) { |
| 199 | return $this->l10n->t('Spreadsheet range is too large'); |
| 200 | } |
| 201 | |
| 202 | try { |
| 203 | [$startColumn] = Coordinate::coordinateFromString($matches['startColumn'] . $matches['startRow']); |
| 204 | [$validatedEndColumn] = Coordinate::coordinateFromString($endColumn . $endRow); |
| 205 | $columns = abs(Coordinate::columnIndexFromString($validatedEndColumn) - Coordinate::columnIndexFromString($startColumn)) + 1; |
| 206 | } catch (\PhpOffice\PhpSpreadsheet\Exception $e) { |
| 207 | return $this->l10n->t('Invalid spreadsheet range'); |
| 208 | } |
| 209 | $totalCells += $columns * $rows; |
| 210 | |
| 211 | if ($totalCells > self::MAX_RANGE_CELLS) { |
| 212 | return $this->l10n->t('Spreadsheet range is too large'); |
| 213 | } |
| 214 | } |
| 215 | |
| 216 | return null; |
| 217 | } |
| 218 | |
| 219 | private function removeNullColumns(array $data): array { |
| 220 | // Transpose the data to work with columns as rows |