DatabaseCache.php 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. <?php
  2. namespace ModulesGarden\ProxmoxAddon\Core\Helper;
  3. use \ModulesGarden\ProxmoxAddon\Core\HandlerError\Exceptions\Exception;
  4. use \ModulesGarden\ProxmoxAddon\Core\HandlerError\ErrorCodes\ErrorCodesLib;
  5. use \ModulesGarden\ProxmoxAddon\Core\UI\Traits\RequestObjectHandler;
  6. /**
  7. * Helper for caching data in database
  8. * stores json in the $modelClass
  9. *
  10. * @author inbs
  11. */
  12. class DatabaseCache
  13. {
  14. use RequestObjectHandler;
  15. /**
  16. * @var string
  17. */
  18. protected $modelClass = '\ModulesGarden\ProxmoxAddon\Core\Models\ModuleSettings\Model';
  19. /**
  20. * @var misc
  21. * whatever you need to store
  22. */
  23. protected $data = null;
  24. /**
  25. * @var int
  26. * timestamp of the last update
  27. */
  28. protected $lastDataUpdate = null;
  29. /**
  30. * @var int
  31. * valid period for stored data, after this it will be autoupdated by callback
  32. * in secounds like a timestamp
  33. */
  34. protected $validPeriod = 300;
  35. /**
  36. * @var string
  37. * key for data store
  38. */
  39. protected $dataKey = null;
  40. /**
  41. * @var \ModulesGarden\ProxmoxAddon\Core\Models\ModuleSettings\Model
  42. */
  43. protected $model = null;
  44. /**
  45. * @var callable
  46. * function returning data for the key
  47. */
  48. protected $callback = null;
  49. protected $assocJsonDecode = false;
  50. public function __construct($key, $callback, $timeout = 300, $assoc = false, $forceReload = false)
  51. {
  52. $this->model = sl($this->modelClass);
  53. $this->dataKey = $key;
  54. $this->validPeriod = (int) $timeout;
  55. $this->callback = $callback;
  56. $this->assocJsonDecode = $assoc;
  57. $this->initLoadProcess($forceReload);
  58. }
  59. /**
  60. * wrapper for loading data process
  61. * @param bool $forceReload
  62. */
  63. protected function initLoadProcess($forceReload = false)
  64. {
  65. if ($forceReload)
  66. {
  67. $this->updateRemoteData();
  68. return;
  69. }
  70. $this->loadDataFromDb();
  71. if (!$this->isDataValid())
  72. {
  73. $this->updateRemoteData();
  74. }
  75. }
  76. /**
  77. * loads remote data and updates to local storage
  78. */
  79. protected function updateRemoteData()
  80. {
  81. $data = $this->loadRemoteData();
  82. $time = \time();
  83. $this->updateDbCache($data, $time);
  84. $this->data = $data;
  85. $this->lastDataUpdate = $time;
  86. }
  87. /**
  88. * updates data in database
  89. */
  90. protected function updateDbCache($data, $time)
  91. {
  92. $dbData = $this->model->where('setting', $this->dataKey)->first();
  93. if ($dbData)
  94. {
  95. $dbData->update(['value' => json_encode($data)]);
  96. }
  97. else
  98. {
  99. $this->model->create([
  100. 'setting' => $this->dataKey,
  101. 'value' => json_encode($data)
  102. ]);
  103. }
  104. $dbDataTime = $this->model->where('setting', $this->dataKey . '_lastDataUpdate')->first();
  105. if ($dbDataTime)
  106. {
  107. $dbDataTime->update(['value' => $time]);
  108. }
  109. else
  110. {
  111. $this->model->create([
  112. 'setting' => $this->dataKey . '_lastDataUpdate',
  113. 'value' => $time
  114. ]);
  115. }
  116. }
  117. /**
  118. * using callback function to load data from custom source
  119. */
  120. protected function loadRemoteData()
  121. {
  122. if (!is_callable($this->callback))
  123. {
  124. throw new Exception(ErrorCodesLib::CORE_CDB_000001, ['callback' => $this->callback]);
  125. }
  126. $data = call_user_func_array($this->callback, []);
  127. return $data;
  128. }
  129. /**
  130. * returns loaded data
  131. */
  132. public function getData()
  133. {
  134. return $this->data;
  135. }
  136. /**
  137. * static wrpper for creating instance and retriving data
  138. */
  139. public static function loadData($key, $callback, $timeout = 300, $assoc = false, $forceReload = false)
  140. {
  141. $loader = new DatabaseCache($key, $callback, $timeout, $assoc, $forceReload);
  142. return $loader->getData();
  143. }
  144. /**
  145. * loads data stored in DB
  146. */
  147. protected function loadDataFromDb()
  148. {
  149. $dbData = $this->model->where('setting', $this->dataKey)->first();
  150. if (!$dbData)
  151. {
  152. return false;
  153. }
  154. $this->data = json_decode($dbData->value, $this->assocJsonDecode);
  155. $lastUpdate = $this->model->where('setting', $this->dataKey . '_lastDataUpdate')->first();
  156. if ($lastUpdate)
  157. {
  158. $this->lastDataUpdate = (int) $lastUpdate->value;
  159. }
  160. }
  161. /**
  162. * Check if data is still befeore renewal time
  163. */
  164. protected function isDataValid()
  165. {
  166. if (!$this->data || !$this->lastDataUpdate)
  167. {
  168. return false;
  169. }
  170. if (time() > ($this->lastDataUpdate + $this->validPeriod))
  171. {
  172. return false;
  173. }
  174. return true;
  175. }
  176. }