For God so loved the world, that He gave His only begotten Son, that all who believe in Him should not perish but have everlasting life
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

368 lines
10 KiB

  1. <?php
  2. /**
  3. * PHPExcel_CachedObjectStorage_CacheBase
  4. *
  5. * Copyright (c) 2006 - 2015 PHPExcel
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. * @category PHPExcel
  22. * @package PHPExcel_CachedObjectStorage
  23. * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
  24. * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  25. * @version ##VERSION##, ##DATE##
  26. */
  27. abstract class PHPExcel_CachedObjectStorage_CacheBase
  28. {
  29. /**
  30. * Parent worksheet
  31. *
  32. * @var PHPExcel_Worksheet
  33. */
  34. protected $parent;
  35. /**
  36. * The currently active Cell
  37. *
  38. * @var PHPExcel_Cell
  39. */
  40. protected $currentObject = null;
  41. /**
  42. * Coordinate address of the currently active Cell
  43. *
  44. * @var string
  45. */
  46. protected $currentObjectID = null;
  47. /**
  48. * Flag indicating whether the currently active Cell requires saving
  49. *
  50. * @var boolean
  51. */
  52. protected $currentCellIsDirty = true;
  53. /**
  54. * An array of cells or cell pointers for the worksheet cells held in this cache,
  55. * and indexed by their coordinate address within the worksheet
  56. *
  57. * @var array of mixed
  58. */
  59. protected $cellCache = array();
  60. /**
  61. * Initialise this new cell collection
  62. *
  63. * @param PHPExcel_Worksheet $parent The worksheet for this cell collection
  64. */
  65. public function __construct(PHPExcel_Worksheet $parent)
  66. {
  67. // Set our parent worksheet.
  68. // This is maintained within the cache controller to facilitate re-attaching it to PHPExcel_Cell objects when
  69. // they are woken from a serialized state
  70. $this->parent = $parent;
  71. }
  72. /**
  73. * Return the parent worksheet for this cell collection
  74. *
  75. * @return PHPExcel_Worksheet
  76. */
  77. public function getParent()
  78. {
  79. return $this->parent;
  80. }
  81. /**
  82. * Is a value set in the current PHPExcel_CachedObjectStorage_ICache for an indexed cell?
  83. *
  84. * @param string $pCoord Coordinate address of the cell to check
  85. * @return boolean
  86. */
  87. public function isDataSet($pCoord)
  88. {
  89. if ($pCoord === $this->currentObjectID) {
  90. return true;
  91. }
  92. // Check if the requested entry exists in the cache
  93. return isset($this->cellCache[$pCoord]);
  94. }
  95. /**
  96. * Move a cell object from one address to another
  97. *
  98. * @param string $fromAddress Current address of the cell to move
  99. * @param string $toAddress Destination address of the cell to move
  100. * @return boolean
  101. */
  102. public function moveCell($fromAddress, $toAddress)
  103. {
  104. if ($fromAddress === $this->currentObjectID) {
  105. $this->currentObjectID = $toAddress;
  106. }
  107. $this->currentCellIsDirty = true;
  108. if (isset($this->cellCache[$fromAddress])) {
  109. $this->cellCache[$toAddress] = &$this->cellCache[$fromAddress];
  110. unset($this->cellCache[$fromAddress]);
  111. }
  112. return true;
  113. }
  114. /**
  115. * Add or Update a cell in cache
  116. *
  117. * @param PHPExcel_Cell $cell Cell to update
  118. * @return PHPExcel_Cell
  119. * @throws PHPExcel_Exception
  120. */
  121. public function updateCacheData(PHPExcel_Cell $cell)
  122. {
  123. return $this->addCacheData($cell->getCoordinate(), $cell);
  124. }
  125. /**
  126. * Delete a cell in cache identified by coordinate address
  127. *
  128. * @param string $pCoord Coordinate address of the cell to delete
  129. * @throws PHPExcel_Exception
  130. */
  131. public function deleteCacheData($pCoord)
  132. {
  133. if ($pCoord === $this->currentObjectID && !is_null($this->currentObject)) {
  134. $this->currentObject->detach();
  135. $this->currentObjectID = $this->currentObject = null;
  136. }
  137. if (is_object($this->cellCache[$pCoord])) {
  138. $this->cellCache[$pCoord]->detach();
  139. unset($this->cellCache[$pCoord]);
  140. }
  141. $this->currentCellIsDirty = false;
  142. }
  143. /**
  144. * Get a list of all cell addresses currently held in cache
  145. *
  146. * @return string[]
  147. */
  148. public function getCellList()
  149. {
  150. return array_keys($this->cellCache);
  151. }
  152. /**
  153. * Sort the list of all cell addresses currently held in cache by row and column
  154. *
  155. * @return string[]
  156. */
  157. public function getSortedCellList()
  158. {
  159. $sortKeys = array();
  160. foreach ($this->getCellList() as $coord) {
  161. sscanf($coord, '%[A-Z]%d', $column, $row);
  162. $sortKeys[sprintf('%09d%3s', $row, $column)] = $coord;
  163. }
  164. ksort($sortKeys);
  165. return array_values($sortKeys);
  166. }
  167. /**
  168. * Get highest worksheet column and highest row that have cell records
  169. *
  170. * @return array Highest column name and highest row number
  171. */
  172. public function getHighestRowAndColumn()
  173. {
  174. // Lookup highest column and highest row
  175. $col = array('A' => '1A');
  176. $row = array(1);
  177. foreach ($this->getCellList() as $coord) {
  178. sscanf($coord, '%[A-Z]%d', $c, $r);
  179. $row[$r] = $r;
  180. $col[$c] = strlen($c).$c;
  181. }
  182. if (!empty($row)) {
  183. // Determine highest column and row
  184. $highestRow = max($row);
  185. $highestColumn = substr(max($col), 1);
  186. }
  187. return array(
  188. 'row' => $highestRow,
  189. 'column' => $highestColumn
  190. );
  191. }
  192. /**
  193. * Return the cell address of the currently active cell object
  194. *
  195. * @return string
  196. */
  197. public function getCurrentAddress()
  198. {
  199. return $this->currentObjectID;
  200. }
  201. /**
  202. * Return the column address of the currently active cell object
  203. *
  204. * @return string
  205. */
  206. public function getCurrentColumn()
  207. {
  208. sscanf($this->currentObjectID, '%[A-Z]%d', $column, $row);
  209. return $column;
  210. }
  211. /**
  212. * Return the row address of the currently active cell object
  213. *
  214. * @return integer
  215. */
  216. public function getCurrentRow()
  217. {
  218. sscanf($this->currentObjectID, '%[A-Z]%d', $column, $row);
  219. return (integer) $row;
  220. }
  221. /**
  222. * Get highest worksheet column
  223. *
  224. * @param string $row Return the highest column for the specified row,
  225. * or the highest column of any row if no row number is passed
  226. * @return string Highest column name
  227. */
  228. public function getHighestColumn($row = null)
  229. {
  230. if ($row == null) {
  231. $colRow = $this->getHighestRowAndColumn();
  232. return $colRow['column'];
  233. }
  234. $columnList = array(1);
  235. foreach ($this->getCellList() as $coord) {
  236. sscanf($coord, '%[A-Z]%d', $c, $r);
  237. if ($r != $row) {
  238. continue;
  239. }
  240. $columnList[] = PHPExcel_Cell::columnIndexFromString($c);
  241. }
  242. return PHPExcel_Cell::stringFromColumnIndex(max($columnList) - 1);
  243. }
  244. /**
  245. * Get highest worksheet row
  246. *
  247. * @param string $column Return the highest row for the specified column,
  248. * or the highest row of any column if no column letter is passed
  249. * @return int Highest row number
  250. */
  251. public function getHighestRow($column = null)
  252. {
  253. if ($column == null) {
  254. $colRow = $this->getHighestRowAndColumn();
  255. return $colRow['row'];
  256. }
  257. $rowList = array(0);
  258. foreach ($this->getCellList() as $coord) {
  259. sscanf($coord, '%[A-Z]%d', $c, $r);
  260. if ($c != $column) {
  261. continue;
  262. }
  263. $rowList[] = $r;
  264. }
  265. return max($rowList);
  266. }
  267. /**
  268. * Generate a unique ID for cache referencing
  269. *
  270. * @return string Unique Reference
  271. */
  272. protected function getUniqueID()
  273. {
  274. if (function_exists('posix_getpid')) {
  275. $baseUnique = posix_getpid();
  276. } else {
  277. $baseUnique = mt_rand();
  278. }
  279. return uniqid($baseUnique, true);
  280. }
  281. /**
  282. * Clone the cell collection
  283. *
  284. * @param PHPExcel_Worksheet $parent The new worksheet
  285. * @return void
  286. */
  287. public function copyCellCollection(PHPExcel_Worksheet $parent)
  288. {
  289. $this->currentCellIsDirty;
  290. $this->storeData();
  291. $this->parent = $parent;
  292. if (($this->currentObject !== null) && (is_object($this->currentObject))) {
  293. $this->currentObject->attach($this);
  294. }
  295. } // function copyCellCollection()
  296. /**
  297. * Remove a row, deleting all cells in that row
  298. *
  299. * @param string $row Row number to remove
  300. * @return void
  301. */
  302. public function removeRow($row)
  303. {
  304. foreach ($this->getCellList() as $coord) {
  305. sscanf($coord, '%[A-Z]%d', $c, $r);
  306. if ($r == $row) {
  307. $this->deleteCacheData($coord);
  308. }
  309. }
  310. }
  311. /**
  312. * Remove a column, deleting all cells in that column
  313. *
  314. * @param string $column Column ID to remove
  315. * @return void
  316. */
  317. public function removeColumn($column)
  318. {
  319. foreach ($this->getCellList() as $coord) {
  320. sscanf($coord, '%[A-Z]%d', $c, $r);
  321. if ($c == $column) {
  322. $this->deleteCacheData($coord);
  323. }
  324. }
  325. }
  326. /**
  327. * Identify whether the caching method is currently available
  328. * Some methods are dependent on the availability of certain extensions being enabled in the PHP build
  329. *
  330. * @return boolean
  331. */
  332. public static function cacheMethodIsAvailable()
  333. {
  334. return true;
  335. }
  336. }