SQLite.php 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. <?php
  2. /**
  3. * 重庆赤晓店信息科技有限公司
  4. * https://www.chixiaodian.com
  5. * Copyright (c) 2023 赤店商城 All rights reserved.
  6. */
  7. class PHPExcel_CachedObjectStorage_SQLite extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache
  8. {
  9. /**
  10. * Database table name
  11. *
  12. * @var string
  13. */
  14. private $TableName = null;
  15. /**
  16. * Database handle
  17. *
  18. * @var resource
  19. */
  20. private $DBHandle = null;
  21. /**
  22. * Store cell data in cache for the current cell object if it's "dirty",
  23. * and the 'nullify' the current cell object
  24. *
  25. * @return void
  26. * @throws PHPExcel_Exception
  27. */
  28. protected function storeData()
  29. {
  30. if ($this->currentCellIsDirty && !empty($this->currentObjectID)) {
  31. $this->currentObject->detach();
  32. if (!$this->DBHandle->queryExec("INSERT OR REPLACE INTO kvp_".$this->TableName." VALUES('".$this->currentObjectID."','".sqlite_escape_string(serialize($this->currentObject))."')")) {
  33. throw new PHPExcel_Exception(sqlite_error_string($this->DBHandle->lastError()));
  34. }
  35. $this->currentCellIsDirty = false;
  36. }
  37. $this->currentObjectID = $this->currentObject = null;
  38. }
  39. /**
  40. * Add or Update a cell in cache identified by coordinate address
  41. *
  42. * @param string $pCoord Coordinate address of the cell to update
  43. * @param PHPExcel_Cell $cell Cell to update
  44. * @return PHPExcel_Cell
  45. * @throws PHPExcel_Exception
  46. */
  47. public function addCacheData($pCoord, PHPExcel_Cell $cell)
  48. {
  49. if (($pCoord !== $this->currentObjectID) && ($this->currentObjectID !== null)) {
  50. $this->storeData();
  51. }
  52. $this->currentObjectID = $pCoord;
  53. $this->currentObject = $cell;
  54. $this->currentCellIsDirty = true;
  55. return $cell;
  56. }
  57. /**
  58. * Get cell at a specific coordinate
  59. *
  60. * @param string $pCoord Coordinate of the cell
  61. * @throws PHPExcel_Exception
  62. * @return PHPExcel_Cell Cell that was found, or null if not found
  63. */
  64. public function getCacheData($pCoord)
  65. {
  66. if ($pCoord === $this->currentObjectID) {
  67. return $this->currentObject;
  68. }
  69. $this->storeData();
  70. $query = "SELECT value FROM kvp_".$this->TableName." WHERE id='".$pCoord."'";
  71. $cellResultSet = $this->DBHandle->query($query, SQLITE_ASSOC);
  72. if ($cellResultSet === false) {
  73. throw new PHPExcel_Exception(sqlite_error_string($this->DBHandle->lastError()));
  74. } elseif ($cellResultSet->numRows() == 0) {
  75. // Return null if requested entry doesn't exist in cache
  76. return null;
  77. }
  78. // Set current entry to the requested entry
  79. $this->currentObjectID = $pCoord;
  80. $cellResult = $cellResultSet->fetchSingle();
  81. $this->currentObject = unserialize($cellResult);
  82. // Re-attach this as the cell's parent
  83. $this->currentObject->attach($this);
  84. // Return requested entry
  85. return $this->currentObject;
  86. }
  87. /**
  88. * Is a value set for an indexed cell?
  89. *
  90. * @param string $pCoord Coordinate address of the cell to check
  91. * @return boolean
  92. */
  93. public function isDataSet($pCoord)
  94. {
  95. if ($pCoord === $this->currentObjectID) {
  96. return true;
  97. }
  98. // Check if the requested entry exists in the cache
  99. $query = "SELECT id FROM kvp_".$this->TableName." WHERE id='".$pCoord."'";
  100. $cellResultSet = $this->DBHandle->query($query, SQLITE_ASSOC);
  101. if ($cellResultSet === false) {
  102. throw new PHPExcel_Exception(sqlite_error_string($this->DBHandle->lastError()));
  103. } elseif ($cellResultSet->numRows() == 0) {
  104. // Return null if requested entry doesn't exist in cache
  105. return false;
  106. }
  107. return true;
  108. }
  109. /**
  110. * Delete a cell in cache identified by coordinate address
  111. *
  112. * @param string $pCoord Coordinate address of the cell to delete
  113. * @throws PHPExcel_Exception
  114. */
  115. public function deleteCacheData($pCoord)
  116. {
  117. if ($pCoord === $this->currentObjectID) {
  118. $this->currentObject->detach();
  119. $this->currentObjectID = $this->currentObject = null;
  120. }
  121. // Check if the requested entry exists in the cache
  122. $query = "DELETE FROM kvp_".$this->TableName." WHERE id='".$pCoord."'";
  123. if (!$this->DBHandle->queryExec($query)) {
  124. throw new PHPExcel_Exception(sqlite_error_string($this->DBHandle->lastError()));
  125. }
  126. $this->currentCellIsDirty = false;
  127. }
  128. /**
  129. * Move a cell object from one address to another
  130. *
  131. * @param string $fromAddress Current address of the cell to move
  132. * @param string $toAddress Destination address of the cell to move
  133. * @return boolean
  134. */
  135. public function moveCell($fromAddress, $toAddress)
  136. {
  137. if ($fromAddress === $this->currentObjectID) {
  138. $this->currentObjectID = $toAddress;
  139. }
  140. $query = "DELETE FROM kvp_".$this->TableName." WHERE id='".$toAddress."'";
  141. $result = $this->DBHandle->exec($query);
  142. if ($result === false) {
  143. throw new PHPExcel_Exception($this->DBHandle->lastErrorMsg());
  144. }
  145. $query = "UPDATE kvp_".$this->TableName." SET id='".$toAddress."' WHERE id='".$fromAddress."'";
  146. $result = $this->DBHandle->exec($query);
  147. if ($result === false) {
  148. throw new PHPExcel_Exception($this->DBHandle->lastErrorMsg());
  149. }
  150. return true;
  151. }
  152. /**
  153. * Get a list of all cell addresses currently held in cache
  154. *
  155. * @return string[]
  156. */
  157. public function getCellList()
  158. {
  159. if ($this->currentObjectID !== null) {
  160. $this->storeData();
  161. }
  162. $query = "SELECT id FROM kvp_".$this->TableName;
  163. $cellIdsResult = $this->DBHandle->unbufferedQuery($query, SQLITE_ASSOC);
  164. if ($cellIdsResult === false) {
  165. throw new PHPExcel_Exception(sqlite_error_string($this->DBHandle->lastError()));
  166. }
  167. $cellKeys = array();
  168. foreach ($cellIdsResult as $row) {
  169. $cellKeys[] = $row['id'];
  170. }
  171. return $cellKeys;
  172. }
  173. /**
  174. * Clone the cell collection
  175. *
  176. * @param PHPExcel_Worksheet $parent The new worksheet
  177. * @return void
  178. */
  179. public function copyCellCollection(PHPExcel_Worksheet $parent)
  180. {
  181. $this->currentCellIsDirty;
  182. $this->storeData();
  183. // Get a new id for the new table name
  184. $tableName = str_replace('.', '_', $this->getUniqueID());
  185. if (!$this->DBHandle->queryExec('CREATE TABLE kvp_'.$tableName.' (id VARCHAR(12) PRIMARY KEY, value BLOB)
  186. AS SELECT * FROM kvp_'.$this->TableName)
  187. ) {
  188. throw new PHPExcel_Exception(sqlite_error_string($this->DBHandle->lastError()));
  189. }
  190. // Copy the existing cell cache file
  191. $this->TableName = $tableName;
  192. }
  193. /**
  194. * Clear the cell collection and disconnect from our parent
  195. *
  196. * @return void
  197. */
  198. public function unsetWorksheetCells()
  199. {
  200. if (!is_null($this->currentObject)) {
  201. $this->currentObject->detach();
  202. $this->currentObject = $this->currentObjectID = null;
  203. }
  204. // detach ourself from the worksheet, so that it can then delete this object successfully
  205. $this->parent = null;
  206. // Close down the temporary cache file
  207. $this->__destruct();
  208. }
  209. /**
  210. * Initialise this new cell collection
  211. *
  212. * @param PHPExcel_Worksheet $parent The worksheet for this cell collection
  213. */
  214. public function __construct(PHPExcel_Worksheet $parent)
  215. {
  216. parent::__construct($parent);
  217. if (is_null($this->DBHandle)) {
  218. $this->TableName = str_replace('.', '_', $this->getUniqueID());
  219. $_DBName = ':memory:';
  220. $this->DBHandle = new SQLiteDatabase($_DBName);
  221. if ($this->DBHandle === false) {
  222. throw new PHPExcel_Exception(sqlite_error_string($this->DBHandle->lastError()));
  223. }
  224. if (!$this->DBHandle->queryExec('CREATE TABLE kvp_'.$this->TableName.' (id VARCHAR(12) PRIMARY KEY, value BLOB)')) {
  225. throw new PHPExcel_Exception(sqlite_error_string($this->DBHandle->lastError()));
  226. }
  227. }
  228. }
  229. /**
  230. * Destroy this cell collection
  231. */
  232. public function __destruct()
  233. {
  234. if (!is_null($this->DBHandle)) {
  235. $this->DBHandle->queryExec('DROP TABLE kvp_'.$this->TableName);
  236. }
  237. $this->DBHandle = null;
  238. }
  239. /**
  240. * Identify whether the caching method is currently available
  241. * Some methods are dependent on the availability of certain extensions being enabled in the PHP build
  242. *
  243. * @return boolean
  244. */
  245. public static function cacheMethodIsAvailable()
  246. {
  247. if (!function_exists('sqlite_open')) {
  248. return false;
  249. }
  250. return true;
  251. }
  252. }