PageRenderTime 47ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/t/upfront/library/class_upfront_model.php

https://bitbucket.org/matthewselby/wpdev
PHP | 491 lines | 174 code | 56 blank | 261 comment | 16 complexity | b908ed1ea08a3efecafc1c74e27c4c15 MD5 | raw file
Possible License(s): Apache-2.0, GPL-2.0, LGPL-3.0, LGPL-2.1, AGPL-1.0, BSD-3-Clause, MIT, GPL-3.0, MPL-2.0-no-copyleft-exception
  1. <?php
  2. /**
  3. * Upfront model abstraction
  4. */
  5. abstract class Upfront_Model {
  6. const STORAGE_KEY = 'upfront';
  7. /**
  8. * Storage key
  9. *
  10. * @var string
  11. */
  12. protected static $storage_key = self::STORAGE_KEY;
  13. /**
  14. * Model name
  15. *
  16. * @var string
  17. */
  18. protected $_name;
  19. /**
  20. * Internal data
  21. *
  22. * @var array
  23. */
  24. protected $_data;
  25. /**
  26. * Initializes the model
  27. */
  28. abstract public function initialize ();
  29. /**
  30. * Persists the model data
  31. */
  32. abstract public function save ();
  33. /**
  34. * Removes the model data
  35. */
  36. abstract public function delete ();
  37. /**
  38. * Resolves model name to an ID fragment
  39. *
  40. * @return string
  41. */
  42. protected function _name_to_id () {
  43. $name = preg_replace('/[^-_a-z0-9]/', '-', strtolower($this->_name));
  44. return $name;
  45. }
  46. /**
  47. * Gets model name
  48. *
  49. * @return string
  50. */
  51. public function get_name () {
  52. return $this->_name;
  53. }
  54. /**
  55. * Resolves and gets the model fully qualified ID
  56. *
  57. * Will try to go through the data in resolution first,
  58. * and will fall back to name-to-id convention
  59. *
  60. * Fully resolved ID will also include the storage key
  61. *
  62. * @return string
  63. */
  64. public function get_id () {
  65. if (!empty($this->_data['preferred_layout'])) {
  66. $id = $this->_data['preferred_layout'];
  67. } else if (!empty($this->_data['current_layout'])) {
  68. $id = $this->_data['current_layout'];
  69. } else if (!empty($this->_data['layout']['item']) && 'single-page' === $this->_data['layout']['item'] && !empty($this->_data['layout']['specificity'])) {
  70. $id = $this->_data['layout']['specificity'];
  71. } else {
  72. $id = !empty($this->_data['layout']['item'])
  73. ? $this->_data['layout']['item']
  74. : $this->_name_to_id()
  75. ;
  76. }
  77. $storage_key = self::get_storage_key();
  78. return $storage_key . '-' . $id;
  79. }
  80. /**
  81. * Compacts a fully resolved ID to an ID fragment
  82. *
  83. * @param string $id Fully resolved ID
  84. *
  85. * @return string Collapsed ID fragment
  86. */
  87. public static function id_to_type ($id) {
  88. $storage_key = self::get_storage_key();
  89. return preg_replace('/^' . preg_quote($storage_key, '/') . '-/', '', $id);
  90. }
  91. /**
  92. * Sets new internal storage key
  93. *
  94. * Resets the internal storage key to default if the
  95. * argument is empty
  96. *
  97. * @param string $storage_key New storage key to use
  98. */
  99. public static function set_storage_key ($storage_key) {
  100. if (!empty($storage_key)) {
  101. self::$storage_key = $storage_key;
  102. } else {
  103. // restore to default if empty
  104. self::$storage_key = self::STORAGE_KEY;
  105. }
  106. }
  107. /**
  108. * Gets the current storage key
  109. *
  110. * Passes the value through the filter first
  111. *
  112. * @return string
  113. */
  114. public static function get_storage_key() {
  115. return apply_filters('upfront-storage-key', self::$storage_key);
  116. }
  117. /**
  118. * Sets a keyed value to the internal data storage
  119. *
  120. * @param string $key Key to use
  121. * @param mixed $value Value to set
  122. */
  123. public function set ($key, $value) {
  124. $this->_data[$key] = $value;
  125. }
  126. /**
  127. * Gets a value from internal data storage
  128. *
  129. * @param string $key Key to get
  130. *
  131. * @return mixed Value, or (bool)false if it hasn't been set
  132. */
  133. public function get ($key) {
  134. return isset($this->_data[$key]) ? $this->_data[$key] : false;
  135. }
  136. /**
  137. * Gets a property value from internal data storage
  138. *
  139. * @see upfront_get_property_value
  140. *
  141. * @param string $prop Property key
  142. *
  143. * @return mixed
  144. */
  145. public function get_property_value ($prop) {
  146. return upfront_get_property_value($prop, $this->_data);
  147. }
  148. /**
  149. * Sets a property value to internal data storage
  150. *
  151. * @see upfront_set_property_value
  152. *
  153. * @param string $prop Property key
  154. * @param mixed $value Value to set
  155. */
  156. public function set_property_value ($prop, $value) {
  157. $this->_data = upfront_set_property_value($prop, $value, $this->_data);
  158. }
  159. /**
  160. * Checks if internal data storage is empty
  161. *
  162. * @return bool
  163. */
  164. public function is_empty () {
  165. return empty($this->_data);
  166. }
  167. }
  168. /**
  169. * Cache key class
  170. */
  171. class Upfront_Cache_Key {
  172. /**
  173. * Cache key type
  174. *
  175. * @var string
  176. */
  177. private $_type;
  178. /**
  179. * Cache key unique identifier
  180. *
  181. * @var mixed
  182. */
  183. private $_identifier;
  184. /**
  185. * Compiled identifier hash
  186. *
  187. * @var string
  188. */
  189. private $_hash;
  190. /**
  191. * Spawns a key instance, never to the outside world
  192. *
  193. * @param string $type Key type
  194. * @param mixed $identifier Unique identifier
  195. */
  196. protected function __construct ($type, $identifier=false) {
  197. $this->_type = $type;
  198. $this->_identifier = $identifier;
  199. $this->_hash = !empty($this->_identifier) ? $this->get_serialized_identifier() : false;
  200. }
  201. /**
  202. * Spawns a new cache key instance for the outsiders
  203. *
  204. * @param string $type Key type
  205. * @param mixed $identifier Unique identifier
  206. *
  207. * @return Upfront_Cache_Key instance
  208. */
  209. public static function spawn ($type, $identifier=false) {
  210. return new self($type, $identifier);
  211. }
  212. /**
  213. * Gets key type
  214. *
  215. * Falls back to 'upfront'
  216. *
  217. * @return string
  218. */
  219. public function get_type () {
  220. return !empty($this->_type)
  221. ? $this->_type
  222. : 'upfront'
  223. ;
  224. }
  225. /**
  226. * Gets key identifier
  227. *
  228. * @return mixed
  229. */
  230. public function get_identifier () {
  231. return !empty($this->_identifier)
  232. ? $this->_identifier
  233. : rand()
  234. ;
  235. }
  236. /**
  237. * Gets the compiled identifier hash
  238. *
  239. * @return string
  240. */
  241. public function get_hash () {
  242. if (!empty($this->_hash)) return $this->_hash;
  243. $this->_hash = $this->get_serialized_identifier();
  244. return $this->_hash;
  245. }
  246. /**
  247. * Sets hash to a new value
  248. *
  249. * @param string $hash New hash
  250. *
  251. * @return string New hash (side-effect)
  252. */
  253. public function set_hash ($hash) {
  254. return $this->_hash = $hash;
  255. }
  256. /**
  257. * Gets typed hash
  258. *
  259. * @return string
  260. */
  261. public function get () {
  262. return $this->get_typed_hash();
  263. }
  264. /**
  265. * Gets typed hash
  266. *
  267. * @return string
  268. */
  269. public function get_typed_hash () {
  270. $type = preg_replace('/^[^a-z]$/', '', $this->get_type());
  271. $hash = preg_replace('/^[a-f0-9]$/', '', $this->get_hash());
  272. return substr("{$type}_uf_{$hash}", 0, 45);
  273. }
  274. /**
  275. * Hashes the internal identifier
  276. *
  277. * @return string Hash
  278. */
  279. public function get_serialized_identifier () {
  280. return md5(serialize($this->get_identifier()));
  281. }
  282. }
  283. /**
  284. * Main cache class abstraction
  285. */
  286. abstract class Upfront_Cache_Abstract {
  287. /**
  288. * Creates cache key instance
  289. *
  290. * Accepts variable parameters, that will be passed to
  291. * the key instance creation
  292. *
  293. * @return object Upfront_Cache_Key instance
  294. */
  295. public function key () {
  296. $func_args = func_get_args();
  297. return call_user_func_array(array('Upfront_Cache_Key', 'spawn'), $func_args);
  298. }
  299. /**
  300. * Gets cache expiration
  301. *
  302. * @param bool $context Optional context
  303. *
  304. * @return number Expiration timespan in seconds
  305. */
  306. public function get_expiration ($context=false) {
  307. return DAY_IN_SECONDS;
  308. }
  309. /**
  310. * Gets a cached value
  311. *
  312. * @param mixed $key_or_type Cache key object, or type string to create a key from
  313. * @param mixed $identifier Identifier is optional if the cache key object is used as the first argument
  314. *
  315. * @return mixed
  316. */
  317. public function get ($key_or_type, $identifier=false) {
  318. $key = $key_or_type instanceof Upfront_Cache_Key
  319. ? $key_or_type
  320. : $this->key($key_or_type, $identifier)
  321. ;
  322. return $this->_get_from_key($key);
  323. }
  324. /**
  325. * Sets a cached value
  326. *
  327. * @param mixed $key_or_type Cache key object, or type string to create a key from
  328. * @param mixed $identifier_or_value Identifier is optional if the cache key object is used as the first argument
  329. * @param mixed $value Optional value to set (2nd param will be used if key is 1st)
  330. */
  331. public function set ($key_or_type, $identifier_or_value=false, $value=false) {
  332. $key = false;
  333. if ($key_or_type instanceof Upfront_Cache_Key) { // 2 args
  334. $key = $key_or_type;
  335. $value = $identifier_or_value;
  336. } else { // 3 args
  337. $key = $this->key($key_or_type, $identifier_or_value);
  338. }
  339. return $this->_set_for_key($key, $value);
  340. }
  341. /**
  342. * Gets a cached value
  343. *
  344. * Just an interface
  345. *
  346. * @param Upfront_Cache_Key $key Key to check
  347. *
  348. * @return bool
  349. */
  350. protected function _get_from_key (Upfront_Cache_Key $key) {
  351. return false;
  352. }
  353. /**
  354. * Sets a cached value
  355. *
  356. * Just an interface
  357. *
  358. * @param Upfront_Cache_Key $key Key to use
  359. * @param mixed $value Value to set
  360. *
  361. * @return bool
  362. */
  363. protected function _set_for_key (Upfront_Cache_Key $key, $value) {
  364. return false;
  365. }
  366. }
  367. /**
  368. * Transient cache implementation
  369. */
  370. class Upfront_Cache_Transient extends Upfront_Cache_Abstract {
  371. /**
  372. * Gets a cached value
  373. *
  374. * @param Upfront_Cache_Key $key Key to check
  375. *
  376. * @return bool
  377. */
  378. protected function _get_from_key (Upfront_Cache_Key $key) {
  379. return get_transient($key->get());
  380. }
  381. /**
  382. * Sets a cached value
  383. *
  384. * @param Upfront_Cache_Key $key Key to use
  385. * @param mixed $value Value to set
  386. *
  387. * @return bool
  388. */
  389. protected function _set_for_key (Upfront_Cache_Key $key, $value) {
  390. return set_transient($key->get(), $value, $this->get_expiration());
  391. }
  392. }
  393. /**
  394. * Cache factory class
  395. */
  396. abstract class Upfront_Cache {
  397. const TYPE_LONG_TERM = 'longterm';
  398. const TYPE_DEFAULT = 'default';
  399. /**
  400. * Internal instances array
  401. *
  402. * @var array
  403. */
  404. private static $_instances = array();
  405. /**
  406. * Factory method
  407. *
  408. * @param string $type Cache type (optional)
  409. *
  410. * @return Upfront_Cache_Abstract Cache instance
  411. */
  412. public static function get_instance ($type=false) {
  413. $type = empty($type) ? $type : self::TYPE_DEFAULT;
  414. if (!empty(self::$_instances[$type])) return self::$_instances[$type];
  415. if (self::TYPE_LONG_TERM === $type) {
  416. self::$_instances[$type] = new Upfront_Cache_Transient;
  417. return self::$_instances[$type];
  418. }
  419. if (self::TYPE_DEFAULT === $type) {
  420. self::$_instances[$type] = new Upfront_Cache_Transient;
  421. return self::$_instances[$type];
  422. }
  423. return self::get_instance(self::TYPE_DEFAULT);
  424. }
  425. }
  426. require_once('models/class_upfront_entity_resolver.php');
  427. require_once('models/class_upfront_json_model.php');
  428. require_once('models/class_upfront_layout.php');
  429. require_once('models/class_upfront_post_model.php');
  430. require_once('models/class_upfront_postmeta_model.php');
  431. require_once('models/class_upfront_layout_revisions.php');
  432. require_once('models/class_upfront_page_template.php');
  433. require_once('models/class_upfront_page_layout.php');
  434. require_once('models/class_upfront_model_google_fonts.php');
  435. require_once('models/class_upfront_api_keys_model.php');