PageRenderTime 63ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/patchwork/class/agent/pForm/entity.php

https://github.com/nicolas-grekas/Patchwork-Doctrine
PHP | 372 lines | 282 code | 72 blank | 18 comment | 46 complexity | a7c74bec7f281433ff11cb1b91efdb6a MD5 | raw file
  1. <?php // vi: set fenc=utf-8 ts=4 sw=4 et:
  2. /*
  3. * Copyright (C) 2012 Nicolas Grekas - p@tchwork.com
  4. *
  5. * This library is free software; you can redistribute it and/or modify it
  6. * under the terms of the (at your option):
  7. * Apache License v2.0 (http://apache.org/licenses/LICENSE-2.0.txt), or
  8. * GNU General Public License v2.0 (http://gnu.org/licenses/gpl-2.0.txt).
  9. */
  10. abstract class agent_pForm_entity extends agent_pForm
  11. {
  12. public $get = array(
  13. '__1__:i:1' => 0
  14. );
  15. static protected $entityNs = 'Entities';
  16. protected $entityUrl;
  17. protected $entityClass;
  18. protected $entity;
  19. protected $entityIsNew = false;
  20. protected $entityIdentifier = array();
  21. protected function getRepository()
  22. {
  23. return EM()->getRepository($this->entityClass);
  24. }
  25. public static function getEntityMetadata($entityClass)
  26. {
  27. return EM()->getClassMetadata($entityClass);
  28. }
  29. function control()
  30. {
  31. parent::control();
  32. if ($this->entity) return;
  33. $u = empty($this->entityUrl)
  34. ? explode('_', substr(get_class($this), 6))
  35. : explode('/', $this->entityUrl);
  36. if ('new' === end($u))
  37. {
  38. $this->entityIsNew = true;
  39. array_pop($u);
  40. }
  41. $this->entityUrl = implode('/', $u);
  42. $this->entityClass = self::$entityNs . "\\";
  43. foreach ($u as $u)
  44. {
  45. $this->entityClass .= ucfirst($u); //TODO: Ugly
  46. }
  47. if ($this->entityIsNew)
  48. {
  49. $this->entity = new $this->entityClass;
  50. }
  51. else if (!empty($this->get->__1__))
  52. {
  53. // Use this to manage composite primary keys
  54. $id = !empty($this->entityIdentifier)
  55. ? $this->entityIdentifier
  56. : $this->get->__1__;
  57. $this->entity = EM()->find($this->entityClass, $id);
  58. $this->entity || Patchwork::forbidden();
  59. }
  60. else if ($this instanceof agent_pForm_entity_indexable)
  61. {
  62. $this->template = $this->entityUrl . '/index';
  63. }
  64. else
  65. {
  66. Patchwork::forbidden();
  67. }
  68. }
  69. ////////////////////////////////////////////////////////////////////////////////
  70. // Entity data
  71. ////////////////////////////////////////////////////////////////////////////////
  72. protected function getEntityData($entity = null, $stringify_dates = true)
  73. {
  74. $entity || $entity = $this->entity;
  75. return self::getEntityDataService($entity, $stringify_dates);
  76. }
  77. public static function getEntityDataService($entity, $stringify_dates = true)
  78. {
  79. if (!$entity) throw new Exception('Null entity supplied.');
  80. $data = array();
  81. $p = self::getEntityMetadata(get_class($entity))->getColumnNames();
  82. foreach ($p as $p)
  83. {
  84. $getProp = 'get' . Doctrine\Common\Util\Inflector::classify($p);
  85. if (method_exists($entity, $getProp))
  86. {
  87. $data[$p] = $entity->$getProp();
  88. if ($stringify_dates && $data[$p] instanceof DateTime)
  89. {
  90. $data[$p . '_timestamp'] = $data[$p]->format('U');
  91. $data[$p] = $data[$p]->format('c');
  92. }
  93. }
  94. }
  95. return $data;
  96. }
  97. protected function setEntityData($data, $entity = null)
  98. {
  99. if (!$entity) $entity = $this->entity;
  100. return self::setEntityDataService($data, $entity);
  101. }
  102. public static function setEntityDataService($data, $entity)
  103. {
  104. if (!$entity) throw new Exception('Null entity supplied.');
  105. $meta = self::getEntityMetadata(get_class($entity));
  106. $id = $meta->getIdentifierFieldNames();
  107. foreach ($data as $f => $v)
  108. {
  109. $repoSetter = 'setEntity' . Doctrine\Common\Util\Inflector::classify($f);
  110. if (method_exists($meta->customRepositoryClassName, $repoSetter))
  111. {
  112. $repo = EM()->getRepository($meta->name);
  113. $repo->$repoSetter($entity, $v);
  114. }
  115. else if (in_array($f, $meta->fieldNames) && !in_array($f, $id))
  116. {
  117. $setter = 'set' . Doctrine\Common\Util\Inflector::classify($f);
  118. $entity->$setter($v);
  119. }
  120. else if (isset($meta->associationMappings[$f]))
  121. {
  122. $v || $v = null;
  123. $setter = 'set' . Doctrine\Common\Util\Inflector::classify($f);
  124. $entity->$setter($v);
  125. }
  126. }
  127. return $entity;
  128. }
  129. ////////////////////////////////////////////////////////////////////////////////
  130. // Save & load
  131. ////////////////////////////////////////////////////////////////////////////////
  132. protected function save($data)
  133. {
  134. $this->setEntityData($data);
  135. $this->entityIsNew && EM()->persist($this->entity);
  136. EM()->flush();
  137. $id = self::getEntityMetadata($this->entityClass);
  138. $id = $id->getSingleIdentifierFieldName();
  139. $id = 'get' . Doctrine\Common\Util\Inflector::classify($id);
  140. return $this->entityUrl . '/' . $this->entity->$id();
  141. }
  142. public static function persist($data, $entity, $flush = true)
  143. {
  144. if (!$data) throw new Exception('Null data supplied.');
  145. if (!$entity) throw new Exception('Null entity supplied.');
  146. EM()->persist(self::setEntityDataService($data, $entity));
  147. if ($flush) EM()->flush();
  148. return $entity;
  149. }
  150. public function loadEntity($o, $entity, $prefix)
  151. {
  152. if ($entity)
  153. {
  154. $meta = self::getEntityMetadata(get_class($entity));
  155. $data = $this->getEntityData($entity);
  156. foreach ($data as $k => $v)
  157. {
  158. if (0 === strpos($k, $prefix . '_'))
  159. {
  160. $k = substr($k, strlen($prefix) + 1);
  161. }
  162. $o->{"{$prefix}_{$k}"} = $v;
  163. }
  164. if (!$meta->isIdentifierComposite)
  165. {
  166. $o->{$prefix} = $this->data[$prefix] = $data[$meta->getSingleIdentifierColumnName()];
  167. }
  168. }
  169. return $o;
  170. }
  171. ////////////////////////////////////////////////////////////////////////////////
  172. // Compose & filters
  173. ////////////////////////////////////////////////////////////////////////////////
  174. function compose($o)
  175. {
  176. if (empty($this->entity))
  177. {
  178. return $this->composeIndex($o);
  179. }
  180. else
  181. {
  182. if (!$this->entityIsNew)
  183. {
  184. $this->data += $this->getEntityData();
  185. foreach ($this->data as $k => $v)
  186. {
  187. $o->$k = $v;
  188. }
  189. }
  190. if ($this instanceof agent_pForm_entity_indexable)
  191. {
  192. $o = $this->composeEntity($o);
  193. }
  194. return parent::compose($o);
  195. }
  196. }
  197. public function loopify(\Doctrine\Common\Collections\ArrayCollection $collection)
  198. {
  199. return new loop_array($collection->toArray(), array($this, 'filterArrayCollection'));
  200. }
  201. public function loadCollectionLoop($o, $entity, $collection)
  202. {
  203. $data = array();
  204. $filter = 'filterPersistentCollection';
  205. if ($entity)
  206. {
  207. $meta = self::getEntityMetadata(get_class($entity));
  208. $params = func_get_args();
  209. unset($params[0], $params[2]);
  210. $repoGetColl = 'getEntity' . Doctrine\Common\Util\Inflector::classify($collection);
  211. $getColl = 'get' . Doctrine\Common\Util\Inflector::classify($collection);
  212. if (method_exists($meta->customRepositoryClassName, $repoGetColl))
  213. {
  214. $repo = EM()->getRepository($meta->name);
  215. $coll = call_user_func_array(array($repo, $repoGetColl), $params);
  216. $data = $coll->toArray();
  217. }
  218. else if (method_exists($entity, $getColl))
  219. {
  220. $coll = call_user_func_array(array($entity, $getColl), $params);
  221. $data = $coll->toArray();
  222. }
  223. else
  224. {
  225. throw new \InvalidArgumentException("The getter : {$getColl} does not exists in {$meta->name} or {$meta->customRepositoryClassName}");
  226. }
  227. if ($coll instanceof \Doctrine\Common\Collections\ArrayCollection)
  228. {
  229. $filter = 'filterArrayCollection';
  230. }
  231. else if ($coll instanceof \Doctrine\ORM\PersistentCollection)
  232. {
  233. $filter = 'filterPersistentCollection';
  234. }
  235. }
  236. $o->{$collection} = new loop_array($data, array($this, $filter));
  237. return $o;
  238. }
  239. function getQueryLoop(Doctrine\ORM\Query $query)
  240. {
  241. return new loop_array($query->getArrayResult(), 'filter_rawArray');
  242. }
  243. function filterPersistentCollection($o)
  244. {
  245. if (is_object($o->VALUE))
  246. $o = (object) $this->getEntityData($o->VALUE);
  247. return $o;
  248. }
  249. function filterArrayCollection($o)
  250. {
  251. $o = $o->VALUE;
  252. if (isset($o[0]))
  253. {
  254. foreach ($o[0] as $k => $v)
  255. {
  256. $o[$k] = $v;
  257. }
  258. unset($o[0]);
  259. }
  260. foreach ($o as $key => $value)
  261. {
  262. if (is_array($value))
  263. {
  264. foreach ($value as $k => $v)
  265. {
  266. if (0 === strpos($k, $key . '_'))
  267. {
  268. $k = substr($k, strlen($key) + 1);
  269. }
  270. $o[$key . '_' . $k] = $v;
  271. unset($o[$key]);
  272. }
  273. }
  274. }
  275. $o = (object) $o;
  276. return $this->filterDateTime($o);
  277. }
  278. function filterDateTime($o)
  279. {
  280. foreach ($o as $k => &$v)
  281. {
  282. if ($v instanceof DateTime)
  283. {
  284. $k .= '_timestamp';
  285. $o->$k = $v->format('U');
  286. $v = $v->format('c');
  287. }
  288. else if (is_array($v))
  289. {
  290. $v = $this->filterDateTime($v);
  291. }
  292. }
  293. return $o;
  294. }
  295. }
  296. interface agent_pForm_entity_indexable
  297. {
  298. function composeIndex($o);
  299. function composeEntity($o);
  300. }