| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506 | 
							- <?php
 
- namespace PhpOffice\PhpSpreadsheet\Collection;
 
- use PhpOffice\PhpSpreadsheet\Cell\Cell;
 
- use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
 
- use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
 
- use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
 
- use Psr\SimpleCache\CacheInterface;
 
- class Cells
 
- {
 
-     /**
 
-      * @var \Psr\SimpleCache\CacheInterface
 
-      */
 
-     private $cache;
 
-     /**
 
-      * Parent worksheet.
 
-      *
 
-      * @var Worksheet
 
-      */
 
-     private $parent;
 
-     /**
 
-      * The currently active Cell.
 
-      *
 
-      * @var Cell
 
-      */
 
-     private $currentCell;
 
-     /**
 
-      * Coordinate of the currently active Cell.
 
-      *
 
-      * @var string
 
-      */
 
-     private $currentCoordinate;
 
-     /**
 
-      * Flag indicating whether the currently active Cell requires saving.
 
-      *
 
-      * @var bool
 
-      */
 
-     private $currentCellIsDirty = false;
 
-     /**
 
-      * An index of existing cells. Booleans indexed by their coordinate.
 
-      *
 
-      * @var bool[]
 
-      */
 
-     private $index = [];
 
-     /**
 
-      * Prefix used to uniquely identify cache data for this worksheet.
 
-      *
 
-      * @var string
 
-      */
 
-     private $cachePrefix;
 
-     /**
 
-      * Initialise this new cell collection.
 
-      *
 
-      * @param Worksheet $parent The worksheet for this cell collection
 
-      * @param CacheInterface $cache
 
-      */
 
-     public function __construct(Worksheet $parent, CacheInterface $cache)
 
-     {
 
-         // Set our parent worksheet.
 
-         // This is maintained here to facilitate re-attaching it to Cell objects when
 
-         // they are woken from a serialized state
 
-         $this->parent = $parent;
 
-         $this->cache = $cache;
 
-         $this->cachePrefix = $this->getUniqueID();
 
-     }
 
-     /**
 
-      * Return the parent worksheet for this cell collection.
 
-      *
 
-      * @return Worksheet
 
-      */
 
-     public function getParent()
 
-     {
 
-         return $this->parent;
 
-     }
 
-     /**
 
-      * Whether the collection holds a cell for the given coordinate.
 
-      *
 
-      * @param string $pCoord Coordinate of the cell to check
 
-      *
 
-      * @return bool
 
-      */
 
-     public function has($pCoord)
 
-     {
 
-         if ($pCoord === $this->currentCoordinate) {
 
-             return true;
 
-         }
 
-         // Check if the requested entry exists in the index
 
-         return isset($this->index[$pCoord]);
 
-     }
 
-     /**
 
-      * Add or update a cell in the collection.
 
-      *
 
-      * @param Cell $cell Cell to update
 
-      *
 
-      * @throws PhpSpreadsheetException
 
-      *
 
-      * @return Cell
 
-      */
 
-     public function update(Cell $cell)
 
-     {
 
-         return $this->add($cell->getCoordinate(), $cell);
 
-     }
 
-     /**
 
-      * Delete a cell in cache identified by coordinate.
 
-      *
 
-      * @param string $pCoord Coordinate of the cell to delete
 
-      */
 
-     public function delete($pCoord)
 
-     {
 
-         if ($pCoord === $this->currentCoordinate && $this->currentCell !== null) {
 
-             $this->currentCell->detach();
 
-             $this->currentCoordinate = null;
 
-             $this->currentCell = null;
 
-             $this->currentCellIsDirty = false;
 
-         }
 
-         unset($this->index[$pCoord]);
 
-         // Delete the entry from cache
 
-         $this->cache->delete($this->cachePrefix . $pCoord);
 
-     }
 
-     /**
 
-      * Get a list of all cell coordinates currently held in the collection.
 
-      *
 
-      * @return string[]
 
-      */
 
-     public function getCoordinates()
 
-     {
 
-         return array_keys($this->index);
 
-     }
 
-     /**
 
-      * Get a sorted list of all cell coordinates currently held in the collection by row and column.
 
-      *
 
-      * @return string[]
 
-      */
 
-     public function getSortedCoordinates()
 
-     {
 
-         $sortKeys = [];
 
-         foreach ($this->getCoordinates() as $coord) {
 
-             $column = '';
 
-             $row = 0;
 
-             sscanf($coord, '%[A-Z]%d', $column, $row);
 
-             $sortKeys[sprintf('%09d%3s', $row, $column)] = $coord;
 
-         }
 
-         ksort($sortKeys);
 
-         return array_values($sortKeys);
 
-     }
 
-     /**
 
-      * Get highest worksheet column and highest row that have cell records.
 
-      *
 
-      * @return array Highest column name and highest row number
 
-      */
 
-     public function getHighestRowAndColumn()
 
-     {
 
-         // Lookup highest column and highest row
 
-         $col = ['A' => '1A'];
 
-         $row = [1];
 
-         foreach ($this->getCoordinates() as $coord) {
 
-             $c = '';
 
-             $r = 0;
 
-             sscanf($coord, '%[A-Z]%d', $c, $r);
 
-             $row[$r] = $r;
 
-             $col[$c] = strlen($c) . $c;
 
-         }
 
-         // Determine highest column and row
 
-         $highestRow = max($row);
 
-         $highestColumn = substr(max($col), 1);
 
-         return [
 
-             'row' => $highestRow,
 
-             'column' => $highestColumn,
 
-         ];
 
-     }
 
-     /**
 
-      * Return the cell coordinate of the currently active cell object.
 
-      *
 
-      * @return string
 
-      */
 
-     public function getCurrentCoordinate()
 
-     {
 
-         return $this->currentCoordinate;
 
-     }
 
-     /**
 
-      * Return the column coordinate of the currently active cell object.
 
-      *
 
-      * @return string
 
-      */
 
-     public function getCurrentColumn()
 
-     {
 
-         $column = '';
 
-         $row = 0;
 
-         sscanf($this->currentCoordinate, '%[A-Z]%d', $column, $row);
 
-         return $column;
 
-     }
 
-     /**
 
-      * Return the row coordinate of the currently active cell object.
 
-      *
 
-      * @return int
 
-      */
 
-     public function getCurrentRow()
 
-     {
 
-         $column = '';
 
-         $row = 0;
 
-         sscanf($this->currentCoordinate, '%[A-Z]%d', $column, $row);
 
-         return (int) $row;
 
-     }
 
-     /**
 
-      * Get highest worksheet column.
 
-      *
 
-      * @param string $row Return the highest column for the specified row,
 
-      *                    or the highest column of any row if no row number is passed
 
-      *
 
-      * @return string Highest column name
 
-      */
 
-     public function getHighestColumn($row = null)
 
-     {
 
-         if ($row == null) {
 
-             $colRow = $this->getHighestRowAndColumn();
 
-             return $colRow['column'];
 
-         }
 
-         $columnList = [1];
 
-         foreach ($this->getCoordinates() as $coord) {
 
-             $c = '';
 
-             $r = 0;
 
-             sscanf($coord, '%[A-Z]%d', $c, $r);
 
-             if ($r != $row) {
 
-                 continue;
 
-             }
 
-             $columnList[] = Coordinate::columnIndexFromString($c);
 
-         }
 
-         return Coordinate::stringFromColumnIndex(max($columnList));
 
-     }
 
-     /**
 
-      * Get highest worksheet row.
 
-      *
 
-      * @param string $column Return the highest row for the specified column,
 
-      *                       or the highest row of any column if no column letter is passed
 
-      *
 
-      * @return int Highest row number
 
-      */
 
-     public function getHighestRow($column = null)
 
-     {
 
-         if ($column == null) {
 
-             $colRow = $this->getHighestRowAndColumn();
 
-             return $colRow['row'];
 
-         }
 
-         $rowList = [0];
 
-         foreach ($this->getCoordinates() as $coord) {
 
-             $c = '';
 
-             $r = 0;
 
-             sscanf($coord, '%[A-Z]%d', $c, $r);
 
-             if ($c != $column) {
 
-                 continue;
 
-             }
 
-             $rowList[] = $r;
 
-         }
 
-         return max($rowList);
 
-     }
 
-     /**
 
-      * Generate a unique ID for cache referencing.
 
-      *
 
-      * @return string Unique Reference
 
-      */
 
-     private function getUniqueID()
 
-     {
 
-         return uniqid('phpspreadsheet.', true) . '.';
 
-     }
 
-     /**
 
-      * Clone the cell collection.
 
-      *
 
-      * @param Worksheet $parent The new worksheet that we're copying to
 
-      *
 
-      * @return self
 
-      */
 
-     public function cloneCellCollection(Worksheet $parent)
 
-     {
 
-         $this->storeCurrentCell();
 
-         $newCollection = clone $this;
 
-         $newCollection->parent = $parent;
 
-         if (($newCollection->currentCell !== null) && (is_object($newCollection->currentCell))) {
 
-             $newCollection->currentCell->attach($this);
 
-         }
 
-         // Get old values
 
-         $oldKeys = $newCollection->getAllCacheKeys();
 
-         $oldValues = $newCollection->cache->getMultiple($oldKeys);
 
-         $newValues = [];
 
-         $oldCachePrefix = $newCollection->cachePrefix;
 
-         // Change prefix
 
-         $newCollection->cachePrefix = $newCollection->getUniqueID();
 
-         foreach ($oldValues as $oldKey => $value) {
 
-             $newValues[str_replace($oldCachePrefix, $newCollection->cachePrefix, $oldKey)] = clone $value;
 
-         }
 
-         // Store new values
 
-         $stored = $newCollection->cache->setMultiple($newValues);
 
-         if (!$stored) {
 
-             $newCollection->__destruct();
 
-             throw new PhpSpreadsheetException('Failed to copy cells in cache');
 
-         }
 
-         return $newCollection;
 
-     }
 
-     /**
 
-      * Remove a row, deleting all cells in that row.
 
-      *
 
-      * @param string $row Row number to remove
 
-      */
 
-     public function removeRow($row)
 
-     {
 
-         foreach ($this->getCoordinates() as $coord) {
 
-             $c = '';
 
-             $r = 0;
 
-             sscanf($coord, '%[A-Z]%d', $c, $r);
 
-             if ($r == $row) {
 
-                 $this->delete($coord);
 
-             }
 
-         }
 
-     }
 
-     /**
 
-      * Remove a column, deleting all cells in that column.
 
-      *
 
-      * @param string $column Column ID to remove
 
-      */
 
-     public function removeColumn($column)
 
-     {
 
-         foreach ($this->getCoordinates() as $coord) {
 
-             $c = '';
 
-             $r = 0;
 
-             sscanf($coord, '%[A-Z]%d', $c, $r);
 
-             if ($c == $column) {
 
-                 $this->delete($coord);
 
-             }
 
-         }
 
-     }
 
-     /**
 
-      * Store cell data in cache for the current cell object if it's "dirty",
 
-      * and the 'nullify' the current cell object.
 
-      *
 
-      * @throws PhpSpreadsheetException
 
-      */
 
-     private function storeCurrentCell()
 
-     {
 
-         if ($this->currentCellIsDirty && !empty($this->currentCoordinate)) {
 
-             $this->currentCell->detach();
 
-             $stored = $this->cache->set($this->cachePrefix . $this->currentCoordinate, $this->currentCell);
 
-             if (!$stored) {
 
-                 $this->__destruct();
 
-                 throw new PhpSpreadsheetException("Failed to store cell {$this->currentCoordinate} in cache");
 
-             }
 
-             $this->currentCellIsDirty = false;
 
-         }
 
-         $this->currentCoordinate = null;
 
-         $this->currentCell = null;
 
-     }
 
-     /**
 
-      * Add or update a cell identified by its coordinate into the collection.
 
-      *
 
-      * @param string $pCoord Coordinate of the cell to update
 
-      * @param Cell $cell Cell to update
 
-      *
 
-      * @throws PhpSpreadsheetException
 
-      *
 
-      * @return \PhpOffice\PhpSpreadsheet\Cell\Cell
 
-      */
 
-     public function add($pCoord, Cell $cell)
 
-     {
 
-         if ($pCoord !== $this->currentCoordinate) {
 
-             $this->storeCurrentCell();
 
-         }
 
-         $this->index[$pCoord] = true;
 
-         $this->currentCoordinate = $pCoord;
 
-         $this->currentCell = $cell;
 
-         $this->currentCellIsDirty = true;
 
-         return $cell;
 
-     }
 
-     /**
 
-      * Get cell at a specific coordinate.
 
-      *
 
-      * @param string $pCoord Coordinate of the cell
 
-      *
 
-      * @throws PhpSpreadsheetException
 
-      *
 
-      * @return \PhpOffice\PhpSpreadsheet\Cell\Cell Cell that was found, or null if not found
 
-      */
 
-     public function get($pCoord)
 
-     {
 
-         if ($pCoord === $this->currentCoordinate) {
 
-             return $this->currentCell;
 
-         }
 
-         $this->storeCurrentCell();
 
-         // Return null if requested entry doesn't exist in collection
 
-         if (!$this->has($pCoord)) {
 
-             return null;
 
-         }
 
-         // Check if the entry that has been requested actually exists
 
-         $cell = $this->cache->get($this->cachePrefix . $pCoord);
 
-         if ($cell === null) {
 
-             throw new PhpSpreadsheetException("Cell entry {$pCoord} no longer exists in cache. This probably means that the cache was cleared by someone else.");
 
-         }
 
-         // Set current entry to the requested entry
 
-         $this->currentCoordinate = $pCoord;
 
-         $this->currentCell = $cell;
 
-         // Re-attach this as the cell's parent
 
-         $this->currentCell->attach($this);
 
-         // Return requested entry
 
-         return $this->currentCell;
 
-     }
 
-     /**
 
-      * Clear the cell collection and disconnect from our parent.
 
-      */
 
-     public function unsetWorksheetCells()
 
-     {
 
-         if ($this->currentCell !== null) {
 
-             $this->currentCell->detach();
 
-             $this->currentCell = null;
 
-             $this->currentCoordinate = null;
 
-         }
 
-         // Flush the cache
 
-         $this->__destruct();
 
-         $this->index = [];
 
-         // detach ourself from the worksheet, so that it can then delete this object successfully
 
-         $this->parent = null;
 
-     }
 
-     /**
 
-      * Destroy this cell collection.
 
-      */
 
-     public function __destruct()
 
-     {
 
-         $this->cache->deleteMultiple($this->getAllCacheKeys());
 
-     }
 
-     /**
 
-      * Returns all known cache keys.
 
-      *
 
-      * @return \Generator|string[]
 
-      */
 
-     private function getAllCacheKeys()
 
-     {
 
-         foreach ($this->getCoordinates() as $coordinate) {
 
-             yield $this->cachePrefix . $coordinate;
 
-         }
 
-     }
 
- }
 
 
  |