/lib/Sirprize/Basecamp/TodoItem/Collection.php

https://github.com/sirprize/basecamp · PHP · 324 lines · 214 code · 48 blank · 62 comment · 17 complexity · ec1a946eaac5757c82fb2d198c376d2d MD5 · raw file

  1. <?php
  2. /*
  3. * This file is part of the Basecamp Classic API Wrapper for PHP 5.3+ package
  4. *
  5. * (c) Christian Hoegl <chrigu@sirprize.me>
  6. */
  7. namespace Sirprize\Basecamp\TodoItem;
  8. use Sirprize\Basecamp\Id;
  9. use Sirprize\Basecamp\Service;
  10. use Sirprize\Basecamp\Response;
  11. use Sirprize\Basecamp\Exception;
  12. use Sirprize\Basecamp\TodoItem\Entity;
  13. use Sirprize\Basecamp\TodoItem\Collection\Observer\Abstrakt;
  14. /**
  15. * Encapsulate a set of persisted todo-item objects and the operations performed over them
  16. */
  17. class Collection extends \SplObjectStorage
  18. {
  19. const _TODO_ITEM = 'todo-item';
  20. protected $_service = null;
  21. protected $_httpClient = null;
  22. protected $_started = false;
  23. protected $_loaded = false;
  24. protected $_response = null;
  25. protected $_observers = array();
  26. public function setService(Service $service)
  27. {
  28. $this->_service = $service;
  29. return $this;
  30. }
  31. public function setHttpClient(\Zend_Http_Client $httpClient)
  32. {
  33. $this->_httpClient = $httpClient;
  34. return $this;
  35. }
  36. /**
  37. * Get response object
  38. *
  39. * @return \Sirprize\Basecamp\Response|null
  40. */
  41. public function getResponse()
  42. {
  43. return $this->_response;
  44. }
  45. /**
  46. * Attach observer object
  47. *
  48. * @return \Sirprize\Basecamp\TodoItem\Collection
  49. */
  50. public function attachObserver(Abstrakt $observer)
  51. {
  52. $exists = false;
  53. foreach(array_keys($this->_observers) as $key)
  54. {
  55. if($observer === $this->_observers[$key])
  56. {
  57. $exists = true;
  58. break;
  59. }
  60. }
  61. if(!$exists)
  62. {
  63. $this->_observers[] = $observer;
  64. }
  65. return $this;
  66. }
  67. /**
  68. * Detach observer object
  69. *
  70. * @return \Sirprize\Basecamp\TodoItem\Collection
  71. */
  72. public function detachObserver(Abstrakt $observer)
  73. {
  74. foreach(array_keys($this->_observers) as $key)
  75. {
  76. if($observer === $this->_observers[$key])
  77. {
  78. unset($this->_observers[$key]);
  79. break;
  80. }
  81. }
  82. return $this;
  83. }
  84. /**
  85. * Instantiate a new todoItem entity
  86. *
  87. * @return \Sirprize\Basecamp\TodoItem\Entity
  88. */
  89. public function getTodoItemInstance()
  90. {
  91. $todoItem = new Entity();
  92. $todoItem
  93. ->setHttpClient($this->_getHttpClient())
  94. ->setService($this->_getService())
  95. ;
  96. return $todoItem;
  97. }
  98. /**
  99. * Defined by \SplObjectStorage
  100. *
  101. * Add todoItem entity
  102. *
  103. * @param \Sirprize\Basecamp\TodoItem\Entity $todoItem
  104. * @throws \Sirprize\Basecamp\Exception
  105. * @return \Sirprize\Basecamp\TodoItem\Collection
  106. */
  107. public function attach($todoItem, $data = null)
  108. {
  109. if(!$todoItem instanceof Entity)
  110. {
  111. throw new Exception('expecting an instance of Entity');
  112. }
  113. parent::attach($todoItem);
  114. return $this;
  115. }
  116. /**
  117. * Fetch todo-items for a given project
  118. *
  119. * @throws \Sirprize\Basecamp\Exception
  120. * @return \Sirprize\Basecamp\TodoItem\Collection
  121. */
  122. public function startAllByTodoListId(Id $todoListId, $force = false)
  123. {
  124. if($this->_started && !$force)
  125. {
  126. return $this;
  127. }
  128. $this->_started = true;
  129. try {
  130. $response = $this->_getHttpClient()
  131. ->setUri($this->_getService()->getBaseUri()."/todo_lists/$todoListId/todo_items.xml")
  132. ->setAuth($this->_getService()->getUsername(), $this->_getService()->getPassword())
  133. ->request('GET')
  134. ;
  135. }
  136. catch(\Exception $exception)
  137. {
  138. try {
  139. // connection error - try again
  140. $response = $this->_getHttpClient()->request('GET');
  141. }
  142. catch(\Exception $exception)
  143. {
  144. $this->_onStartError();
  145. throw new Exception($exception->getMessage());
  146. }
  147. }
  148. $this->_response = new Response($response);
  149. if($this->_response->isError())
  150. {
  151. // service error
  152. $this->_onStartError();
  153. return $this;
  154. }
  155. $this->load($this->_response->getData(), $force);
  156. $this->_onStartSuccess();
  157. return $this;
  158. }
  159. /**
  160. * Fetch todo-item by id
  161. *
  162. * @throws \Sirprize\Basecamp\Exception
  163. * @return null|Entity
  164. */
  165. public function startById(Id $id, $force = false)
  166. {
  167. if($this->_started && !$force)
  168. {
  169. return $this;
  170. }
  171. $this->_started = true;
  172. try {
  173. $response = $this->_getHttpClient()
  174. ->setUri($this->_getService()->getBaseUri()."/todo_items/$id.xml")
  175. ->setAuth($this->_getService()->getUsername(), $this->_getService()->getPassword())
  176. ->request('GET')
  177. ;
  178. }
  179. catch(\Exception $exception)
  180. {
  181. try {
  182. // connection error - try again
  183. $response = $this->_getHttpClient()->request('GET');
  184. }
  185. catch(\Exception $exception)
  186. {
  187. $this->_onStartError();
  188. throw new Exception($exception->getMessage());
  189. }
  190. }
  191. $this->_response = new Response($response);
  192. if($this->_response->isError())
  193. {
  194. // service error
  195. $this->_onStartError();
  196. return null;
  197. }
  198. $this->load($this->_response->getData(), $force);
  199. $this->_onStartSuccess();
  200. $this->rewind();
  201. return $this->current();
  202. }
  203. /**
  204. * Instantiate todo-item objects with api response data
  205. *
  206. * @return \Sirprize\Basecamp\TodoItem\Collection
  207. */
  208. public function load(\SimpleXMLElement $xml, $force = false)
  209. {
  210. if($this->_loaded && !$force)
  211. {
  212. throw new Exception('todo-item collection has already been loaded');
  213. }
  214. $this->_loaded = true;
  215. if(isset($xml->id))
  216. {
  217. // request for a single entity (not supported on todoItems)
  218. $todoItem = $this->getTodoItemInstance();
  219. $todoItem->load($xml, $force);
  220. $this->attach($todoItem);
  221. return $this;
  222. }
  223. $array = (array) $xml;
  224. if(!isset($array[self::_TODO_ITEM]))
  225. {
  226. // list request - 0 items in response
  227. return $this;
  228. }
  229. if(isset($array[self::_TODO_ITEM]->id))
  230. {
  231. // list request - 1 item in response
  232. $todoItem = $this->getTodoItemInstance();
  233. $todoItem->load($array[self::_TODO_ITEM], $force);
  234. $this->attach($todoItem);
  235. return $this;
  236. }
  237. foreach($array[self::_TODO_ITEM] as $row)
  238. {
  239. // list request - 2 or more items in response
  240. $todoItem = $this->getTodoItemInstance();
  241. $todoItem->load($row, $force);
  242. $this->attach($todoItem);
  243. }
  244. return $this;
  245. }
  246. protected function _getService()
  247. {
  248. if($this->_service === null)
  249. {
  250. throw new Exception('call setService() before '.__METHOD__);
  251. }
  252. return $this->_service;
  253. }
  254. protected function _getHttpClient()
  255. {
  256. if($this->_httpClient === null)
  257. {
  258. throw new Exception('call setHttpClient() before '.__METHOD__);
  259. }
  260. return $this->_httpClient;
  261. }
  262. protected function _onStartSuccess()
  263. {
  264. foreach($this->_observers as $observer)
  265. {
  266. $observer->onStartSuccess($this);
  267. }
  268. }
  269. protected function _onStartError()
  270. {
  271. foreach($this->_observers as $observer)
  272. {
  273. $observer->onStartError($this);
  274. }
  275. }
  276. }