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

/src/lib/Views/DoctrineJsonView.php

https://gitlab.com/gothcon/cthulhu
PHP | 347 lines | 239 code | 45 blank | 63 comment | 45 complexity | 611f53cec79f330a9e18cfa8d45c28af MD5 | raw file
  1. <?php
  2. require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR."../Views/HtmlView.php");
  3. class DoctrineJsonView extends View{
  4. public function init(){
  5. }
  6. public function render(){
  7. header('Cache-Control: no-cache, must-revalidate');
  8. header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
  9. header('Content-Type: application/json; charset=utf-8');
  10. $jsonData= $this->getModel()->getJsonData();
  11. echo json_encode(DoctrineEntitySerializer::Serialize($jsonData,10));
  12. }
  13. }
  14. class Serializor {
  15. /**
  16. * @param object $object The Object (Typically a Doctrine Entity) to convert to an array
  17. * @param integer $depth The Depth of the object graph to pursue
  18. * @param array $whitelist List of entity=>array(parameters) to convert
  19. * @param array $blacklist List of entity=>array(parameters) to skip
  20. * @return NULL|Array
  21. */
  22. public static function toArray($object, $depth = 1,$whitelist=array(), $blacklist=array()){
  23. // If we drop below depth 0, just return NULL
  24. if ($depth < 0){
  25. return NULL;
  26. }
  27. // If this is an array, we need to loop through the values
  28. if (is_array($object)){
  29. // Somthing to Hold Return Values
  30. $anArray = array();
  31. // The Loop
  32. foreach ($object as $value){
  33. // Store the results
  34. $anArray[] = Serializor::toArray($value, $depth, $whitelist, $blacklist);
  35. }
  36. // Return it
  37. return $anArray;
  38. }else{
  39. // Just return it
  40. return Serializor::arrayizor($object, $depth, $whitelist, $blacklist);
  41. }
  42. }
  43. /**
  44. * This does all the heavy lifting of actually converting to an array
  45. *
  46. * @param object $object The Object (Typically a Doctrine Entity) to convert to an array
  47. * @param integer $depth The Depth of the object graph to pursue
  48. * @param array $whitelist List of entity=>array(parameters) to convert
  49. * @param array $blacklist List of entity=>array(parameters) to skip
  50. * @return NULL|Array
  51. */
  52. private static function arrayizor($anObject, $depth, $whitelist=array(), $blacklist=array(), $parentObject = null){
  53. // Determine the next depth to use
  54. $nextDepth = $depth - 1;
  55. // Lets get our Class Name
  56. // @TODO: Making some assumptions that only objects get passed in, need error checking
  57. $clazzName = get_class($anObject);
  58. // Now get our reflection class for this class name
  59. $reflectionClass = new \ReflectionClass($clazzName);
  60. // Then grap the class properites
  61. $clazzProps = $reflectionClass->getProperties();
  62. $em = GothConEntityManager::getInstance();
  63. $metadata = $em->getClassMetadata(get_class($anObject));
  64. if (is_a($anObject, 'Doctrine\ORM\Proxy\Proxy')){
  65. return null;
  66. $parent = $reflectionClass->getParentClass();
  67. $clazzName = $parent->getName();
  68. $clazzProps = $parent->getProperties();
  69. }
  70. // If this is a entity, get the metadata
  71. // A new array to hold things for us
  72. $anArray = array();
  73. // Lets loop through those class properties now
  74. $propertyNames =$metadata->fieldNames;
  75. foreach($metadata->associationMappings as $propertyName => $mappingInformation){
  76. array_push($propertyNames,$propertyName);
  77. }
  78. foreach ($propertyNames as $propName){
  79. // If a Whitelist exists
  80. if (@count($whitelist[$clazzName]) > 0)
  81. {
  82. // And this class property is not in it
  83. if (! @in_array($propName, $whitelist[$clazzName])){
  84. // lets skip it.
  85. continue;
  86. }
  87. // Otherwise, if a blacklist exists
  88. }
  89. elseif (@count($blacklist) > 0)
  90. {
  91. // And this class property is in it
  92. if (@in_array($propName, $blacklist)){
  93. // lets skip it.
  94. continue;
  95. }
  96. }
  97. // We know the property, lets craft a getProperty method
  98. $method_name = 'get' . ucfirst($propName) ;
  99. // And check to see that it exists for this object
  100. if (! method_exists($anObject, $method_name)){
  101. continue;
  102. }
  103. // It did, so lets call it!
  104. $aValue = $anObject->$method_name();
  105. // If it is an object, we need to handle that
  106. if (is_object($aValue)){
  107. if (get_class($aValue) === 'DateTime'){
  108. // If it is a datetime, lets make it a string
  109. $anArray[$propName] = $aValue->format('Y-m-d H:i:s');
  110. }
  111. else{
  112. // If it is a Doctrine Collection, we need to loop through it
  113. if(isset($metadata->associationMappings[$propName])){
  114. if($metadata->associationMappings[$propName]["mappedBy"] != null){
  115. $_blacklist = array($metadata->associationMappings[$propName]["mappedBy"]);
  116. }
  117. else if($metadata->associationMappings[$propName]["inversedBy"] != null) {
  118. $_blacklist = array($metadata->associationMappings[$propName]["inversedBy"]);
  119. }
  120. else{
  121. $_blacklist = array();
  122. }
  123. }
  124. if(get_class($aValue) ==='Doctrine\ORM\PersistentCollection'){
  125. if($aValue->isInitialized()){
  126. $collect = array();
  127. foreach ($aValue as $val){
  128. $collect[] = Serializor::toArray($val, $nextDepth, $whitelist, $_blacklist);
  129. }
  130. $anArray[$propName] = $collect;
  131. }else{
  132. $anArray[$propName] = null;
  133. }
  134. // Otherwise, we can simply make it an array
  135. }else{
  136. $anArray[$propName] = Serializor::toArray($aValue, $nextDepth, $whitelist, $_blacklist);
  137. }
  138. }
  139. // Otherwise, we just use the base value
  140. }else{
  141. $anArray[$propName] = $aValue;
  142. }
  143. }
  144. // All done, send it back!
  145. return $anArray;
  146. }
  147. }
  148. class DoctrineEntitySerializer{
  149. private static function propertyIsWhitelisted($propertyName, $className,$whitelist){
  150. if(!isset($whitelist[$className]) || count($whitelist[$className]) == 0){
  151. return true;
  152. }
  153. return in_array($propertyName, $whitelist[$className]);
  154. }
  155. private static function propertyIsBlacklisted($propertyName, $className, $blacklist){
  156. if(count($blacklist) == 0){
  157. return false;
  158. }
  159. if(!isset($blacklist[$className])){
  160. return false;
  161. }
  162. return in_array($propertyName, $blacklist[$className]);
  163. }
  164. private static function _serialize($entity, $depth, $whitelist, $blacklist){
  165. if($depth < 0 || is_a($entity, 'Doctrine\ORM\Proxy\Proxy')){
  166. return null;
  167. }
  168. else if (is_a($entity, 'DateTime')){
  169. // If it is a datetime, lets make it a string
  170. return $entity->format('Y-m-d H:i:s');
  171. }
  172. else if(is_array($entity)){
  173. return static::_serializeArray($entity, $depth, $whitelist, $blacklist);
  174. }
  175. else if(is_object($entity)){
  176. return static::_serializeObject($entity, $depth, $whitelist, $blacklist);
  177. }else{
  178. return $entity;
  179. }
  180. return null;
  181. }
  182. /**
  183. *
  184. * @param Doctrine\ORM\PersistentCollection $collection
  185. * @param int $depth
  186. * @param array $whitelist
  187. * @param array $blacklist
  188. * @return type
  189. */
  190. private static function _serializeCollection($collection,$depth,$whitelist,$blacklist){
  191. if(!$collection->isInitialized()){
  192. return null;
  193. }
  194. $serializableArray = array();
  195. $items = $collection->getValues();
  196. foreach($items as $item){
  197. $serializableArray[] = DoctrineEntitySerializer::_serialize($item,$depth-1,$whitelist,$blacklist);
  198. }
  199. return $serializableArray;
  200. }
  201. private static function _serializeStandardObject($entity,$depth,$whitelist,$blacklist){
  202. $reflectionClass = new \ReflectionClass($entity);
  203. $serializableObject = array();
  204. $properties = $reflectionClass->getProperties();
  205. foreach($properties as $property){
  206. $value = $property->getValue($entity);
  207. if (is_a($value, 'DateTime')){
  208. // If it is a datetime, lets make it a string
  209. $value = $value->format('Y-m-d H:i:s');
  210. }
  211. $serializableObject[$property->name] = DoctrineEntitySerializer::_serialize($value, $depth, $whitelist, $blacklist);
  212. }
  213. return $serializableObject;
  214. }
  215. private static function _serializeObject($entity,$depth,$whitelist,$blacklist){
  216. $reflectionClass = new \ReflectionClass($entity);
  217. $serializableObject = array();
  218. $em = GothConEntityManager::getInstance();
  219. try{
  220. $metadata = $em->getClassMetadata(get_class($entity));
  221. }
  222. catch (Exception $em){
  223. return DoctrineEntitySerializer::_serializeStandardObject($entity, $depth, $whitelist, $blacklist);
  224. }
  225. foreach($metadata->fieldNames as $propertyName){
  226. if (!static::propertyIsWhitelisted($propertyName, $reflectionClass->getName(), $whitelist)){
  227. // the whitelist is defined and the property is not in it
  228. continue;
  229. }
  230. elseif (static::propertyIsBlacklisted($propertyName, $reflectionClass->getName(), $blacklist))
  231. {
  232. // the blacklist is defined and the property is in it
  233. continue;
  234. }
  235. if(!$reflectionClass->hasMethod("get" . $propertyName )){
  236. continue;
  237. }
  238. $method = $reflectionClass->getMethod("get" . $propertyName);
  239. $value = $method->invoke($entity);
  240. if (is_a($value, 'DateTime')){
  241. // If it is a datetime, lets make it a string
  242. $value = $value->format('Y-m-d H:i:s');
  243. }
  244. $serializableObject[$propertyName] = $value;
  245. }
  246. foreach($metadata->associationMappings as $propertyName => $mappingData){
  247. $_blacklist = array();
  248. if(!$reflectionClass->hasProperty($propertyName)){
  249. continue;
  250. }
  251. if (!static::propertyIsWhitelisted($propertyName, $reflectionClass->getName(), $whitelist)){
  252. // the whitelist is defined and the property is not in it
  253. continue;
  254. }
  255. else if (static::propertyIsBlacklisted($propertyName, $reflectionClass->getName(),$blacklist))
  256. {
  257. // the blacklist is defined and the property is in it
  258. continue;
  259. }
  260. // if($mappingData["isOwningSide"]){
  261. $_blacklist[$mappingData["targetEntity"]] = array($mappingData["mappedBy"]);
  262. // }
  263. $property = $reflectionClass->getProperty($propertyName);
  264. $property->setAccessible(true);
  265. $associationItem = $property->getValue($entity);
  266. if( get_class($associationItem) === 'Doctrine\ORM\PersistentCollection'){
  267. $serializableObject[$propertyName] = DoctrineEntitySerializer::_serializeCollection($associationItem, $depth, $whitelist, $_blacklist);
  268. }
  269. else if( get_class($associationItem) === 'Doctrine\Common\Collections\ArrayCollection'){
  270. $serializableObject[$propertyName] = DoctrineEntitySerializer::_serializeArray($associationItem->getValues(), $depth, $whitelist, $_blacklist);
  271. }else{
  272. $serializableObject[$propertyName] = DoctrineEntitySerializer::_serialize($associationItem,$depth-1,$whitelist,$_blacklist);
  273. }
  274. }
  275. return $serializableObject;
  276. }
  277. private static function _isArrayCollection($entity){
  278. $class = get_class($entity);
  279. if($class === 'Doctrine\ORM\PersistentCollection'){
  280. return true;
  281. }
  282. if($class ==='Doctrine\Common\Collections\ArrayCollection'){
  283. return true;
  284. }
  285. return false;
  286. }
  287. private static function _serializeArray($items,$depth,$whitelist,$blacklist){
  288. $serializableArray = array();
  289. foreach($items as $key => $item){
  290. $serializableArray[$key] = DoctrineEntitySerializer::_serialize($item,$depth-1,$whitelist,$blacklist);
  291. }
  292. return $serializableArray;
  293. }
  294. public static function Serialize($entity, $depth = 6, $whitelist=array(), $blacklist=array()){
  295. try {
  296. $serializableEntity = static::_serialize($entity, $depth, $whitelist, $blacklist);
  297. } catch (Exception $e){
  298. $foo = $e;
  299. }
  300. return $serializableEntity;
  301. }
  302. }