PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/library/Dojo/Data.php

https://github.com/kervin/kyzstudio
PHP | 563 lines | 255 code | 57 blank | 251 comment | 36 complexity | 8933e961b9c3cfdfde8258c2d8e9a759 MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Dojo
  17. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @license http://framework.zend.com/license/new-bsd New BSD License
  19. * @version $Id: Data.php 20096 2010-01-06 02:05:09Z bkarwin $
  20. */
  21. /**
  22. * dojo.data support for Zend Framework
  23. *
  24. * @uses ArrayAccess
  25. * @uses Iterator
  26. * @uses Countable
  27. * @package Zend_Dojo
  28. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  29. * @license http://framework.zend.com/license/new-bsd New BSD License
  30. */
  31. class Zend_Dojo_Data implements ArrayAccess,Iterator,Countable
  32. {
  33. /**
  34. * Identifier field of item
  35. * @var string|int
  36. */
  37. protected $_identifier;
  38. /**
  39. * Collected items
  40. * @var array
  41. */
  42. protected $_items = array();
  43. /**
  44. * Label field of item
  45. * @var string
  46. */
  47. protected $_label;
  48. /**
  49. * Data container metadata
  50. * @var array
  51. */
  52. protected $_metadata = array();
  53. /**
  54. * Constructor
  55. *
  56. * @param string|null $identifier
  57. * @param array|Traversable|null $items
  58. * @param string|null $label
  59. * @return void
  60. */
  61. public function __construct($identifier = null, $items = null, $label = null)
  62. {
  63. if (null !== $identifier) {
  64. $this->setIdentifier($identifier);
  65. }
  66. if (null !== $items) {
  67. $this->setItems($items);
  68. }
  69. if (null !== $label) {
  70. $this->setLabel($label);
  71. }
  72. }
  73. /**
  74. * Set the items to collect
  75. *
  76. * @param array|Traversable $items
  77. * @return Zend_Dojo_Data
  78. */
  79. public function setItems($items)
  80. {
  81. $this->clearItems();
  82. return $this->addItems($items);
  83. }
  84. /**
  85. * Set an individual item, optionally by identifier (overwrites)
  86. *
  87. * @param array|object $item
  88. * @param string|null $identifier
  89. * @return Zend_Dojo_Data
  90. */
  91. public function setItem($item, $id = null)
  92. {
  93. $item = $this->_normalizeItem($item, $id);
  94. $this->_items[$item['id']] = $item['data'];
  95. return $this;
  96. }
  97. /**
  98. * Add an individual item, optionally by identifier
  99. *
  100. * @param array|object $item
  101. * @param string|null $id
  102. * @return Zend_Dojo_Data
  103. */
  104. public function addItem($item, $id = null)
  105. {
  106. $item = $this->_normalizeItem($item, $id);
  107. if ($this->hasItem($item['id'])) {
  108. #require_once 'Zend/Dojo/Exception.php';
  109. throw new Zend_Dojo_Exception('Overwriting items using addItem() is not allowed');
  110. }
  111. $this->_items[$item['id']] = $item['data'];
  112. return $this;
  113. }
  114. /**
  115. * Add multiple items at once
  116. *
  117. * @param array|Traversable $items
  118. * @return Zend_Dojo_Data
  119. */
  120. public function addItems($items)
  121. {
  122. if (!is_array($items) && (!is_object($items) || !($items instanceof Traversable))) {
  123. #require_once 'Zend/Dojo/Exception.php';
  124. throw new Zend_Dojo_Exception('Only arrays and Traversable objects may be added to ' . __CLASS__);
  125. }
  126. foreach ($items as $item) {
  127. $this->addItem($item);
  128. }
  129. return $this;
  130. }
  131. /**
  132. * Get all items as an array
  133. *
  134. * Serializes items to arrays.
  135. *
  136. * @return array
  137. */
  138. public function getItems()
  139. {
  140. return $this->_items;
  141. }
  142. /**
  143. * Does an item with the given identifier exist?
  144. *
  145. * @param string|int $id
  146. * @return bool
  147. */
  148. public function hasItem($id)
  149. {
  150. return array_key_exists($id, $this->_items);
  151. }
  152. /**
  153. * Retrieve an item by identifier
  154. *
  155. * Item retrieved will be flattened to an array.
  156. *
  157. * @param string $id
  158. * @return array
  159. */
  160. public function getItem($id)
  161. {
  162. if (!$this->hasItem($id)) {
  163. return null;
  164. }
  165. return $this->_items[$id];
  166. }
  167. /**
  168. * Remove item by identifier
  169. *
  170. * @param string $id
  171. * @return Zend_Dojo_Data
  172. */
  173. public function removeItem($id)
  174. {
  175. if ($this->hasItem($id)) {
  176. unset($this->_items[$id]);
  177. }
  178. return $this;
  179. }
  180. /**
  181. * Remove all items at once
  182. *
  183. * @return Zend_Dojo_Data
  184. */
  185. public function clearItems()
  186. {
  187. $this->_items = array();
  188. return $this;
  189. }
  190. /**
  191. * Set identifier for item lookups
  192. *
  193. * @param string|int|null $identifier
  194. * @return Zend_Dojo_Data
  195. */
  196. public function setIdentifier($identifier)
  197. {
  198. if (null === $identifier) {
  199. $this->_identifier = null;
  200. } elseif (is_string($identifier)) {
  201. $this->_identifier = $identifier;
  202. } elseif (is_numeric($identifier)) {
  203. $this->_identifier = (int) $identifier;
  204. } else {
  205. #require_once 'Zend/Dojo/Exception.php';
  206. throw new Zend_Dojo_Exception('Invalid identifier; please use a string or integer');
  207. }
  208. return $this;
  209. }
  210. /**
  211. * Retrieve current item identifier
  212. *
  213. * @return string|int|null
  214. */
  215. public function getIdentifier()
  216. {
  217. return $this->_identifier;
  218. }
  219. /**
  220. * Set label to use for displaying item associations
  221. *
  222. * @param string|null $label
  223. * @return Zend_Dojo_Data
  224. */
  225. public function setLabel($label)
  226. {
  227. if (null === $label) {
  228. $this->_label = null;
  229. } else {
  230. $this->_label = (string) $label;
  231. }
  232. return $this;
  233. }
  234. /**
  235. * Retrieve item association label
  236. *
  237. * @return string|null
  238. */
  239. public function getLabel()
  240. {
  241. return $this->_label;
  242. }
  243. /**
  244. * Set metadata by key or en masse
  245. *
  246. * @param string|array $spec
  247. * @param mixed $value
  248. * @return Zend_Dojo_Data
  249. */
  250. public function setMetadata($spec, $value = null)
  251. {
  252. if (is_string($spec) && (null !== $value)) {
  253. $this->_metadata[$spec] = $value;
  254. } elseif (is_array($spec)) {
  255. foreach ($spec as $key => $value) {
  256. $this->setMetadata($key, $value);
  257. }
  258. }
  259. return $this;
  260. }
  261. /**
  262. * Get metadata item or all metadata
  263. *
  264. * @param null|string $key Metadata key when pulling single metadata item
  265. * @return mixed
  266. */
  267. public function getMetadata($key = null)
  268. {
  269. if (null === $key) {
  270. return $this->_metadata;
  271. }
  272. if (array_key_exists($key, $this->_metadata)) {
  273. return $this->_metadata[$key];
  274. }
  275. return null;
  276. }
  277. /**
  278. * Clear individual or all metadata item(s)
  279. *
  280. * @param null|string $key
  281. * @return Zend_Dojo_Data
  282. */
  283. public function clearMetadata($key = null)
  284. {
  285. if (null === $key) {
  286. $this->_metadata = array();
  287. } elseif (array_key_exists($key, $this->_metadata)) {
  288. unset($this->_metadata[$key]);
  289. }
  290. return $this;
  291. }
  292. /**
  293. * Load object from array
  294. *
  295. * @param array $data
  296. * @return Zend_Dojo_Data
  297. */
  298. public function fromArray(array $data)
  299. {
  300. if (array_key_exists('identifier', $data)) {
  301. $this->setIdentifier($data['identifier']);
  302. }
  303. if (array_key_exists('label', $data)) {
  304. $this->setLabel($data['label']);
  305. }
  306. if (array_key_exists('items', $data) && is_array($data['items'])) {
  307. $this->setItems($data['items']);
  308. } else {
  309. $this->clearItems();
  310. }
  311. return $this;
  312. }
  313. /**
  314. * Load object from JSON
  315. *
  316. * @param string $json
  317. * @return Zend_Dojo_Data
  318. */
  319. public function fromJson($json)
  320. {
  321. if (!is_string($json)) {
  322. #require_once 'Zend/Dojo/Exception.php';
  323. throw new Zend_Dojo_Exception('fromJson() expects JSON input');
  324. }
  325. #require_once 'Zend/Json.php';
  326. $data = Zend_Json::decode($json);
  327. return $this->fromArray($data);
  328. }
  329. /**
  330. * Seralize entire data structure, including identifier and label, to array
  331. *
  332. * @return array
  333. */
  334. public function toArray()
  335. {
  336. if (null === ($identifier = $this->getIdentifier())) {
  337. #require_once 'Zend/Dojo/Exception.php';
  338. throw new Zend_Dojo_Exception('Serialization requires that an identifier be present in the object; first call setIdentifier()');
  339. }
  340. $array = array(
  341. 'identifier' => $identifier,
  342. 'items' => array_values($this->getItems()),
  343. );
  344. $metadata = $this->getMetadata();
  345. if (!empty($metadata)) {
  346. foreach ($metadata as $key => $value) {
  347. $array[$key] = $value;
  348. }
  349. }
  350. if (null !== ($label = $this->getLabel())) {
  351. $array['label'] = $label;
  352. }
  353. return $array;
  354. }
  355. /**
  356. * Serialize to JSON (dojo.data format)
  357. *
  358. * @return string
  359. */
  360. public function toJson()
  361. {
  362. #require_once 'Zend/Json.php';
  363. return Zend_Json::encode($this->toArray());
  364. }
  365. /**
  366. * Serialize to string (proxy to {@link toJson()})
  367. *
  368. * @return string
  369. */
  370. public function __toString()
  371. {
  372. return $this->toJson();
  373. }
  374. /**
  375. * ArrayAccess: does offset exist?
  376. *
  377. * @param string|int $offset
  378. * @return bool
  379. */
  380. public function offsetExists($offset)
  381. {
  382. return (null !== $this->getItem($offset));
  383. }
  384. /**
  385. * ArrayAccess: retrieve by offset
  386. *
  387. * @param string|int $offset
  388. * @return array
  389. */
  390. public function offsetGet($offset)
  391. {
  392. return $this->getItem($offset);
  393. }
  394. /**
  395. * ArrayAccess: set value by offset
  396. *
  397. * @param string $offset
  398. * @param array|object|null $value
  399. * @return void
  400. */
  401. public function offsetSet($offset, $value)
  402. {
  403. $this->setItem($value, $offset);
  404. }
  405. /**
  406. * ArrayAccess: unset value by offset
  407. *
  408. * @param string $offset
  409. * @return void
  410. */
  411. public function offsetUnset($offset)
  412. {
  413. $this->removeItem($offset);
  414. }
  415. /**
  416. * Iterator: get current value
  417. *
  418. * @return array
  419. */
  420. public function current()
  421. {
  422. return current($this->_items);
  423. }
  424. /**
  425. * Iterator: get current key
  426. *
  427. * @return string|int
  428. */
  429. public function key()
  430. {
  431. return key($this->_items);
  432. }
  433. /**
  434. * Iterator: get next item
  435. *
  436. * @return void
  437. */
  438. public function next()
  439. {
  440. return next($this->_items);
  441. }
  442. /**
  443. * Iterator: rewind to first value in collection
  444. *
  445. * @return void
  446. */
  447. public function rewind()
  448. {
  449. return reset($this->_items);
  450. }
  451. /**
  452. * Iterator: is item valid?
  453. *
  454. * @return bool
  455. */
  456. public function valid()
  457. {
  458. return (bool) $this->current();
  459. }
  460. /**
  461. * Countable: how many items are present
  462. *
  463. * @return int
  464. */
  465. public function count()
  466. {
  467. return count($this->_items);
  468. }
  469. /**
  470. * Normalize an item to attach to the collection
  471. *
  472. * @param array|object $item
  473. * @param string|int|null $id
  474. * @return array
  475. */
  476. protected function _normalizeItem($item, $id)
  477. {
  478. if (null === ($identifier = $this->getIdentifier())) {
  479. #require_once 'Zend/Dojo/Exception.php';
  480. throw new Zend_Dojo_Exception('You must set an identifier prior to adding items');
  481. }
  482. if (!is_object($item) && !is_array($item)) {
  483. #require_once 'Zend/Dojo/Exception.php';
  484. throw new Zend_Dojo_Exception('Only arrays and objects may be attached');
  485. }
  486. if (is_object($item)) {
  487. if (method_exists($item, 'toArray')) {
  488. $item = $item->toArray();
  489. } else {
  490. $item = get_object_vars($item);
  491. }
  492. }
  493. if ((null === $id) && !array_key_exists($identifier, $item)) {
  494. #require_once 'Zend/Dojo/Exception.php';
  495. throw new Zend_Dojo_Exception('Item must contain a column matching the currently set identifier');
  496. } elseif (null === $id) {
  497. $id = $item[$identifier];
  498. } else {
  499. $item[$identifier] = $id;
  500. }
  501. return array(
  502. 'id' => $id,
  503. 'data' => $item,
  504. );
  505. }
  506. }