/library/Zend/Cache/Storage/Capabilities.php

https://github.com/zucchi/zf2 · PHP · 547 lines · 210 code · 50 blank · 287 comment · 13 complexity · 3f7df340bbc06a312c4d52443b29bd00 MD5 · raw file

  1. <?php
  2. /**
  3. * Zend Framework (http://framework.zend.com/)
  4. *
  5. * @link http://github.com/zendframework/zf2 for the canonical source repository
  6. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  7. * @license http://framework.zend.com/license/new-bsd New BSD License
  8. * @package Zend_Cache
  9. */
  10. namespace Zend\Cache\Storage;
  11. use ArrayObject;
  12. use stdClass;
  13. use Zend\Cache\Exception;
  14. use Zend\EventManager\EventsCapableInterface;
  15. /**
  16. * @category Zend
  17. * @package Zend_Cache
  18. * @subpackage Storage
  19. */
  20. class Capabilities
  21. {
  22. /**
  23. * The storage instance
  24. *
  25. * @var StorageInterface
  26. */
  27. protected $storage;
  28. /**
  29. * A marker to set/change capabilities
  30. *
  31. * @var stdClass
  32. */
  33. protected $marker;
  34. /**
  35. * Base capabilities
  36. *
  37. * @var null|Capabilities
  38. */
  39. protected $baseCapabilities;
  40. /**
  41. * Expire read
  42. *
  43. * If it's NULL the capability isn't set and the getter
  44. * returns the base capability or the default value.
  45. *
  46. * @var null|boolean
  47. */
  48. protected $expiredRead;
  49. /**
  50. * Max. key length
  51. *
  52. * If it's NULL the capability isn't set and the getter
  53. * returns the base capability or the default value.
  54. *
  55. * @var null|int
  56. */
  57. protected $maxKeyLength;
  58. /**
  59. * Min. TTL (0 means items never expire)
  60. *
  61. * If it's NULL the capability isn't set and the getter
  62. * returns the base capability or the default value.
  63. *
  64. * @var null|int
  65. */
  66. protected $minTtl;
  67. /**
  68. * Max. TTL (0 means infinite)
  69. *
  70. * If it's NULL the capability isn't set and the getter
  71. * returns the base capability or the default value.
  72. *
  73. * @var null|int
  74. */
  75. protected $maxTtl;
  76. /**
  77. * Namespace is prefix
  78. *
  79. * If it's NULL the capability isn't set and the getter
  80. * returns the base capability or the default value.
  81. *
  82. * @var null|boolean
  83. */
  84. protected $namespaceIsPrefix;
  85. /**
  86. * Namespace separator
  87. *
  88. * If it's NULL the capability isn't set and the getter
  89. * returns the base capability or the default value.
  90. *
  91. * @var null|string
  92. */
  93. protected $namespaceSeparator;
  94. /**
  95. * Static ttl
  96. *
  97. * If it's NULL the capability isn't set and the getter
  98. * returns the base capability or the default value.
  99. *
  100. * @var null|boolean
  101. */
  102. protected $staticTtl;
  103. /**
  104. * Supported datatypes
  105. *
  106. * If it's NULL the capability isn't set and the getter
  107. * returns the base capability or the default value.
  108. *
  109. * @var null|array
  110. */
  111. protected $supportedDatatypes;
  112. /**
  113. * Supported metdata
  114. *
  115. * If it's NULL the capability isn't set and the getter
  116. * returns the base capability or the default value.
  117. *
  118. * @var null|array
  119. */
  120. protected $supportedMetadata;
  121. /**
  122. * TTL precision
  123. *
  124. * If it's NULL the capability isn't set and the getter
  125. * returns the base capability or the default value.
  126. *
  127. * @var null|int
  128. */
  129. protected $ttlPrecision;
  130. /**
  131. * Use request time
  132. *
  133. * If it's NULL the capability isn't set and the getter
  134. * returns the base capability or the default value.
  135. *
  136. * @var null|boolean
  137. */
  138. protected $useRequestTime;
  139. /**
  140. * Constructor
  141. *
  142. * @param StorageInterface $storage
  143. * @param stdClass $marker
  144. * @param array $capabilities
  145. * @param null|Capabilities $baseCapabilities
  146. */
  147. public function __construct(
  148. StorageInterface $storage,
  149. stdClass $marker,
  150. array $capabilities = array(),
  151. Capabilities $baseCapabilities = null
  152. ) {
  153. $this->storage = $storage;
  154. $this->marker = $marker;
  155. $this->baseCapabilities = $baseCapabilities;
  156. foreach ($capabilities as $name => $value) {
  157. $this->setCapability($marker, $name, $value);
  158. }
  159. }
  160. /**
  161. * Get the storage adapter
  162. *
  163. * @return StorageInterface
  164. */
  165. public function getAdapter()
  166. {
  167. return $this->storage;
  168. }
  169. /**
  170. * Get supported datatypes
  171. *
  172. * @return array
  173. */
  174. public function getSupportedDatatypes()
  175. {
  176. return $this->getCapability('supportedDatatypes', array(
  177. 'NULL' => false,
  178. 'boolean' => false,
  179. 'integer' => false,
  180. 'double' => false,
  181. 'string' => true,
  182. 'array' => false,
  183. 'object' => false,
  184. 'resource' => false,
  185. ));
  186. }
  187. /**
  188. * Set supported datatypes
  189. *
  190. * @param stdClass $marker
  191. * @param array $datatypes
  192. * @throws Exception\InvalidArgumentException
  193. * @return Capabilities Fluent interface
  194. */
  195. public function setSupportedDatatypes(stdClass $marker, array $datatypes)
  196. {
  197. $allTypes = array(
  198. 'array',
  199. 'boolean',
  200. 'double',
  201. 'integer',
  202. 'NULL',
  203. 'object',
  204. 'resource',
  205. 'string',
  206. );
  207. // check/normalize datatype values
  208. foreach ($datatypes as $type => &$toType) {
  209. if (!in_array($type, $allTypes)) {
  210. throw new Exception\InvalidArgumentException("Unknown datatype '{$type}'");
  211. }
  212. if (is_string($toType)) {
  213. $toType = strtolower($toType);
  214. if (!in_array($toType, $allTypes)) {
  215. throw new Exception\InvalidArgumentException("Unknown datatype '{$toType}'");
  216. }
  217. } else {
  218. $toType = (bool) $toType;
  219. }
  220. }
  221. // add missing datatypes as not supported
  222. $missingTypes = array_diff($allTypes, array_keys($datatypes));
  223. foreach ($missingTypes as $type) {
  224. $datatypes[$type] = false;
  225. }
  226. return $this->setCapability($marker, 'supportedDatatypes', $datatypes);
  227. }
  228. /**
  229. * Get supported metadata
  230. *
  231. * @return array
  232. */
  233. public function getSupportedMetadata()
  234. {
  235. return $this->getCapability('supportedMetadata', array());
  236. }
  237. /**
  238. * Set supported metadata
  239. *
  240. * @param stdClass $marker
  241. * @param string[] $metadata
  242. * @throws Exception\InvalidArgumentException
  243. * @return Capabilities Fluent interface
  244. */
  245. public function setSupportedMetadata(stdClass $marker, array $metadata)
  246. {
  247. foreach ($metadata as $name) {
  248. if (!is_string($name)) {
  249. throw new Exception\InvalidArgumentException('$metadata must be an array of strings');
  250. }
  251. }
  252. return $this->setCapability($marker, 'supportedMetadata', $metadata);
  253. }
  254. /**
  255. * Get minimum supported time-to-live
  256. *
  257. * @return int 0 means items never expire
  258. */
  259. public function getMinTtl()
  260. {
  261. return $this->getCapability('minTtl', 0);
  262. }
  263. /**
  264. * Set minimum supported time-to-live
  265. *
  266. * @param stdClass $marker
  267. * @param int $minTtl
  268. * @throws Exception\InvalidArgumentException
  269. * @return Capabilities Fluent interface
  270. */
  271. public function setMinTtl(stdClass $marker, $minTtl)
  272. {
  273. $minTtl = (int) $minTtl;
  274. if ($minTtl < 0) {
  275. throw new Exception\InvalidArgumentException('$minTtl must be greater or equal 0');
  276. }
  277. return $this->setCapability($marker, 'minTtl', $minTtl);
  278. }
  279. /**
  280. * Get maximum supported time-to-live
  281. *
  282. * @return int 0 means infinite
  283. */
  284. public function getMaxTtl()
  285. {
  286. return $this->getCapability('maxTtl', 0);
  287. }
  288. /**
  289. * Set maximum supported time-to-live
  290. *
  291. * @param stdClass $marker
  292. * @param int $maxTtl
  293. * @throws Exception\InvalidArgumentException
  294. * @return Capabilities Fluent interface
  295. */
  296. public function setMaxTtl(stdClass $marker, $maxTtl)
  297. {
  298. $maxTtl = (int) $maxTtl;
  299. if ($maxTtl < 0) {
  300. throw new Exception\InvalidArgumentException('$maxTtl must be greater or equal 0');
  301. }
  302. return $this->setCapability($marker, 'maxTtl', $maxTtl);
  303. }
  304. /**
  305. * Is the time-to-live handled static (on write)
  306. * or dynamic (on read)
  307. *
  308. * @return boolean
  309. */
  310. public function getStaticTtl()
  311. {
  312. return $this->getCapability('staticTtl', false);
  313. }
  314. /**
  315. * Set if the time-to-live handled static (on write) or dynamic (on read)
  316. *
  317. * @param stdClass $marker
  318. * @param boolean $flag
  319. * @return Capabilities Fluent interface
  320. */
  321. public function setStaticTtl(stdClass $marker, $flag)
  322. {
  323. return $this->setCapability($marker, 'staticTtl', (bool)$flag);
  324. }
  325. /**
  326. * Get time-to-live precision
  327. *
  328. * @return float
  329. */
  330. public function getTtlPrecision()
  331. {
  332. return $this->getCapability('ttlPrecision', 1);
  333. }
  334. /**
  335. * Set time-to-live precision
  336. *
  337. * @param stdClass $marker
  338. * @param float $ttlPrecision
  339. * @throws Exception\InvalidArgumentException
  340. * @return Capabilities Fluent interface
  341. */
  342. public function setTtlPrecision(stdClass $marker, $ttlPrecision)
  343. {
  344. $ttlPrecision = (float) $ttlPrecision;
  345. if ($ttlPrecision <= 0) {
  346. throw new Exception\InvalidArgumentException('$ttlPrecision must be greater than 0');
  347. }
  348. return $this->setCapability($marker, 'ttlPrecision', $ttlPrecision);
  349. }
  350. /**
  351. * Get use request time
  352. *
  353. * @return boolean
  354. */
  355. public function getUseRequestTime()
  356. {
  357. return $this->getCapability('useRequestTime', false);
  358. }
  359. /**
  360. * Set use request time
  361. *
  362. * @param stdClass $marker
  363. * @param boolean $flag
  364. * @return Capabilities Fluent interface
  365. */
  366. public function setUseRequestTime(stdClass $marker, $flag)
  367. {
  368. return $this->setCapability($marker, 'useRequestTime', (bool)$flag);
  369. }
  370. /**
  371. * Get if expired items are readable
  372. *
  373. * @return boolean
  374. */
  375. public function getExpiredRead()
  376. {
  377. return $this->getCapability('expiredRead', false);
  378. }
  379. /**
  380. * Set if expired items are readable
  381. *
  382. * @param stdClass $marker
  383. * @param boolean $flag
  384. * @return Capabilities Fluent interface
  385. */
  386. public function setExpiredRead(stdClass $marker, $flag)
  387. {
  388. return $this->setCapability($marker, 'expiredRead', (bool)$flag);
  389. }
  390. /**
  391. * Get maximum key lenth
  392. *
  393. * @return int -1 means unknown, 0 means infinite
  394. */
  395. public function getMaxKeyLength()
  396. {
  397. return $this->getCapability('maxKeyLength', -1);
  398. }
  399. /**
  400. * Set maximum key length
  401. *
  402. * @param stdClass $marker
  403. * @param int $maxKeyLength
  404. * @throws Exception\InvalidArgumentException
  405. * @return Capabilities Fluent interface
  406. */
  407. public function setMaxKeyLength(stdClass $marker, $maxKeyLength)
  408. {
  409. $maxKeyLength = (int) $maxKeyLength;
  410. if ($maxKeyLength < -1) {
  411. throw new Exception\InvalidArgumentException('$maxKeyLength must be greater or equal than -1');
  412. }
  413. return $this->setCapability($marker, 'maxKeyLength', $maxKeyLength);
  414. }
  415. /**
  416. * Get if namespace support is implemented as prefix
  417. *
  418. * @return boolean
  419. */
  420. public function getNamespaceIsPrefix()
  421. {
  422. return $this->getCapability('namespaceIsPrefix', true);
  423. }
  424. /**
  425. * Set if namespace support is implemented as prefix
  426. *
  427. * @param stdClass $marker
  428. * @param boolean $flag
  429. * @return Capabilities Fluent interface
  430. */
  431. public function setNamespaceIsPrefix(stdClass $marker, $flag)
  432. {
  433. return $this->setCapability($marker, 'namespaceIsPrefix', (bool)$flag);
  434. }
  435. /**
  436. * Get namespace separator if namespace is implemented as prefix
  437. *
  438. * @return string
  439. */
  440. public function getNamespaceSeparator()
  441. {
  442. return $this->getCapability('namespaceSeparator', '');
  443. }
  444. /**
  445. * Set the namespace separator if namespace is implemented as prefix
  446. *
  447. * @param stdClass $marker
  448. * @param string $separator
  449. * @return Capabilities Fluent interface
  450. */
  451. public function setNamespaceSeparator(stdClass $marker, $separator)
  452. {
  453. return $this->setCapability($marker, 'namespaceSeparator', (string) $separator);
  454. }
  455. /**
  456. * Get a capability
  457. *
  458. * @param string $property
  459. * @param mixed $default
  460. * @return mixed
  461. */
  462. protected function getCapability($property, $default = null)
  463. {
  464. if ($this->$property !== null) {
  465. return $this->$property;
  466. } elseif ($this->baseCapabilities) {
  467. $getMethod = 'get' . $property;
  468. return $this->baseCapabilities->$getMethod();
  469. }
  470. return $default;
  471. }
  472. /**
  473. * Change a capability
  474. *
  475. * @param stdClass $marker
  476. * @param string $property
  477. * @param mixed $value
  478. * @return Capabilities Fluent interface
  479. * @throws Exception\InvalidArgumentException
  480. */
  481. protected function setCapability(stdClass $marker, $property, $value)
  482. {
  483. if ($this->marker !== $marker) {
  484. throw new Exception\InvalidArgumentException('Invalid marker');
  485. }
  486. if ($this->$property !== $value) {
  487. $this->$property = $value;
  488. // trigger event
  489. if ($this->storage instanceof EventsCapableInterface) {
  490. $this->storage->getEventManager()->trigger('capability', $this->storage, new ArrayObject(array(
  491. $property => $value
  492. )));
  493. }
  494. }
  495. return $this;
  496. }
  497. }