1<?php 2 3declare(strict_types=1); 4 5namespace PhpMyAdmin\Query; 6 7use PhpMyAdmin\Util; 8use function array_shift; 9use function count; 10use function is_array; 11 12/** 13 * Handles caching results 14 */ 15class Cache 16{ 17 /** @var array Table data cache */ 18 private $tableCache = []; 19 20 /** 21 * Caches table data so Table does not require to issue 22 * SHOW TABLE STATUS again 23 * 24 * @param array $tables information for tables of some databases 25 * @param string|bool $table table name 26 */ 27 public function cacheTableData(array $tables, $table): void 28 { 29 // Note: I don't see why we would need array_merge_recursive() here, 30 // as it creates double entries for the same table (for example a double 31 // entry for Comment when changing the storage engine in Operations) 32 // Note 2: Instead of array_merge(), simply use the + operator because 33 // array_merge() renumbers numeric keys starting with 0, therefore 34 // we would lose a db name that consists only of numbers 35 36 foreach ($tables as $one_database => $_) { 37 if (isset($this->tableCache[$one_database])) { 38 // the + operator does not do the intended effect 39 // when the cache for one table already exists 40 if ($table 41 && isset($this->tableCache[$one_database][$table]) 42 ) { 43 unset($this->tableCache[$one_database][$table]); 44 } 45 $this->tableCache[$one_database] 46 += $tables[$one_database]; 47 } else { 48 $this->tableCache[$one_database] = $tables[$one_database]; 49 } 50 } 51 } 52 53 /** 54 * Set an item in table cache using dot notation. 55 * 56 * @param array|null $contentPath Array with the target path 57 * @param mixed $value Target value 58 */ 59 public function cacheTableContent(?array $contentPath, $value): void 60 { 61 $loc = &$this->tableCache; 62 63 if (! isset($contentPath)) { 64 $loc = $value; 65 66 return; 67 } 68 69 while (count($contentPath) > 1) { 70 $key = array_shift($contentPath); 71 72 // If the key doesn't exist at this depth, we will just create an empty 73 // array to hold the next value, allowing us to create the arrays to hold 74 // final values at the correct depth. Then we'll keep digging into the 75 // array. 76 if (! isset($loc[$key]) || ! is_array($loc[$key])) { 77 $loc[$key] = []; 78 } 79 $loc = &$loc[$key]; 80 } 81 82 $loc[array_shift($contentPath)] = $value; 83 } 84 85 /** 86 * Get a cached value from table cache. 87 * 88 * @param array $contentPath Array of the name of the target value 89 * @param mixed $default Return value on cache miss 90 * 91 * @return mixed cached value or default 92 */ 93 public function getCachedTableContent(array $contentPath, $default = null) 94 { 95 return Util::getValueByKey($this->tableCache, $contentPath, $default); 96 } 97 98 public function getCache(): array 99 { 100 return $this->tableCache; 101 } 102 103 public function clearTableCache(): void 104 { 105 $this->tableCache = []; 106 } 107} 108