/src/Midgard/PHPCR/NodeType/NodeTypeDefinition.php

https://github.com/bergie/phpcr-midgard2 · PHP · 286 lines · 237 code · 39 blank · 10 comment · 38 complexity · bc2a4c1ddc348326acc8e289f08ba4d9 MD5 · raw file

  1. <?php
  2. namespace Midgard\PHPCR\NodeType;
  3. use Midgard\PHPCR\Utils\NodeMapper;
  4. use PHPCR\NodeType\NodeTypeDefinitionInterface;
  5. use PHPCR\Version\OnParentVersionAction;
  6. use ReflectionClass;
  7. use \midgard_reflector_object;
  8. use \midgard_reflection_property;
  9. use \midgard_reflection_class;
  10. class NodeTypeDefinition implements NodeTypeDefinitionInterface
  11. {
  12. protected $nodeTypeManager = null;
  13. protected $childNodeDefinitions = null;
  14. protected $propertyDefinitions = null;
  15. protected $supertypeNames = null;
  16. protected $name = null;
  17. protected $primaryItemName = null;
  18. protected $hasOrderableChildNodes = false;
  19. protected $isAbstract = false;
  20. protected $isMixin = false;
  21. protected $isQueryable = false;
  22. protected $midgardInternalProps = array(
  23. 'connection',
  24. 'guid',
  25. 'metadata',
  26. 'action',
  27. 'id',
  28. 'name',
  29. 'parent',
  30. 'parentname',
  31. );
  32. public function __construct($name = null, NodeTypeManager $mgr)
  33. {
  34. $this->name = $name;
  35. $this->nodeTypeManager = $mgr;
  36. }
  37. private function getStringValue($reflector, $name, $property = null)
  38. {
  39. if ($property) {
  40. // Property reflector
  41. return $reflector->get_user_value($property, $name);
  42. }
  43. // Class reflector
  44. return $reflector->get_user_value($name);
  45. }
  46. private function getBooleanValue($reflector, $name, $property = null)
  47. {
  48. $value = $this->getStringValue($reflector, $name, $property);
  49. if ($value == 'true') {
  50. return true;
  51. }
  52. return false;
  53. }
  54. private function createChildNodeDefinition($name, midgard_reflection_class $reflector)
  55. {
  56. $template = $this->nodeTypeManager->createNodeDefinitionTemplate();
  57. $template->setAutoCreated($this->getBooleanValue($reflector, 'isAutoCreated'));
  58. $primaryTypes = $this->getStringValue($reflector, 'RequiredPrimaryTypes');
  59. if ($primaryTypes) {
  60. $primaryTypes = explode(' ', $primaryTypes);
  61. } else {
  62. $primaryTypes = array('nt:base');
  63. }
  64. $template->setRequiredPrimaryTypeNames($primaryTypes);
  65. $defaultPrimary = $this->getStringValue($reflector, 'DefaultPrimaryType');
  66. if (!$defaultPrimary) {
  67. if (in_array($this->getName(), $primaryTypes) || in_array('*', $primaryTypes)) {
  68. $defaultPrimary = $this->getName();
  69. }
  70. }
  71. $template->setDefaultPrimaryTypeName($defaultPrimary);
  72. $template->setMandatory($this->getBooleanValue($reflector, 'isMandatory'));
  73. $template->setName($name);
  74. $template->setAutoCreated($this->getBooleanValue($reflector, 'isAutoCreated'));
  75. $template->setProtected($this->getBooleanValue($reflector, 'isProtected'));
  76. $template->setSameNameSiblings($this->getBooleanValue($reflector, 'SameNameSiblings'));
  77. $opv = $this->getStringValue($reflector, 'OnParentVersion');
  78. if ($opv) {
  79. $template->setOnParentVersion(OnParentVersionAction::valueFromName($opv));
  80. }
  81. return new NodeDefinition($this->getName(), $template, $this->nodeTypeManager);
  82. }
  83. public function getDeclaredChildNodeDefinitions()
  84. {
  85. if (!is_null($this->childNodeDefinitions)) {
  86. return $this->childNodeDefinitions;
  87. }
  88. $this->childNodeDefinitions = array();
  89. $childNames = array();
  90. $midgardName = NodeMapper::getMidgardName($this->name);
  91. try {
  92. $reflector = new midgard_reflection_class($midgardName);
  93. } catch ( \Exception $e) {
  94. return $this->childNodeDefinitions;
  95. }
  96. $childDefs = $this->getStringValue($reflector, 'ChildNodeDefinition');
  97. if (!$childDefs) {
  98. return $this->childNodeDefinitions;
  99. }
  100. $childDefs = explode(' ', $childDefs);
  101. foreach ($childDefs as $childName) {
  102. if (!$childName) {
  103. continue;
  104. }
  105. $this->childNodeDefinitions[$childName] = $this->createChildNodeDefinition($childName, $reflector);
  106. }
  107. return $this->childNodeDefinitions;
  108. }
  109. private function createPropertyDefinition($midgardName, $name, midgard_reflection_property $reflector = null)
  110. {
  111. $template = $this->nodeTypeManager->createPropertyDefinitionTemplate();
  112. $template->setName($name);
  113. if (!$reflector) {
  114. // This is all we know of the property
  115. return new PropertyDefinition($this, $template, $this->nodeTypeManager);
  116. }
  117. $template->setAutoCreated($this->getBooleanValue($reflector, 'isAutoCreated', $midgardName));
  118. $template->setRequiredType(NodeMapper::getPHPCRPropertyType(null, $midgardName, $reflector));
  119. $template->setMandatory($this->getBooleanValue($reflector, 'isMandatory', $midgardName));
  120. $template->setProtected($this->getBooleanValue($reflector, 'isProtected', $midgardName));
  121. $template->setMultiple($this->getBooleanValue($reflector, 'isMultiple', $midgardName));
  122. return new PropertyDefinition($this->getName(), $template, $this->nodeTypeManager);
  123. }
  124. public function getDeclaredPropertyDefinitions()
  125. {
  126. if (!is_null($this->propertyDefinitions)) {
  127. return $this->propertyDefinitions;
  128. }
  129. $this->propertyDefinitions = array();
  130. $midgardName = NodeMapper::getMidgardName($this->name);
  131. $properties = midgard_reflector_object::list_defined_properties($midgardName);
  132. $reflector = $this->getPropertyReflector($midgardName);
  133. if ($reflector == null) {
  134. /* Try mixin derived abstract */
  135. if (class_exists($midgardName . "_abstract")) {
  136. $reflector = new midgard_reflection_property($midgardName . "_abstract");
  137. }
  138. }
  139. foreach ($properties as $property => $value) {
  140. if (in_array($property, $this->midgardInternalProps)) {
  141. continue;
  142. }
  143. $propertyPHPCR = NodeMapper::getPHPCRProperty($property);
  144. if (!$propertyPHPCR) {
  145. continue;
  146. }
  147. $this->propertyDefinitions[$propertyPHPCR] = $this->createPropertyDefinition($property, $propertyPHPCR, $reflector);
  148. }
  149. return $this->propertyDefinitions;
  150. }
  151. private function getPropertyReflector($midgardName)
  152. {
  153. if (is_subclass_of($midgardName, 'MidgardDBObject')) {
  154. return new midgard_reflection_property($midgardName);
  155. }
  156. // Currently mixin types are not reflectable. Get reflector
  157. // from a type using mixin
  158. $nodeTypes = $this->nodeTypeManager->getAllNodeTypes();
  159. foreach ($nodeTypes as $nodeType) {
  160. if ($nodeType->isMixin()) {
  161. continue;
  162. }
  163. if ($nodeType->getName() == $this->getName()) {
  164. continue;
  165. }
  166. if (!$nodeType->isNodeType($this->getName())) {
  167. continue;
  168. }
  169. $midgardName = NodeMapper::getMidgardName($nodeType->getName());
  170. return new midgard_reflection_property($midgardName);
  171. }
  172. return null;
  173. }
  174. public function getDeclaredSupertypeNames()
  175. {
  176. if (!is_null($this->supertypeNames)) {
  177. return $this->supertypeNames;
  178. }
  179. $this->supertypeNames = array();
  180. // Get supertypes based on PHP hierarchy
  181. $midgardName = NodeMapper::getMidgardName($this->name);
  182. $reflector = new ReflectionClass($midgardName);
  183. $parentReflector = $reflector->getParentClass();
  184. if ($parentReflector) {
  185. $crName = NodeMapper::getPHPCRName($parentReflector->getName());
  186. if ($crName) {
  187. $this->supertypeNames[] = $crName;
  188. }
  189. }
  190. $reflector = new midgard_reflection_class($midgardName);
  191. $superTypes = explode(' ', $reflector->get_user_value('Supertypes'));
  192. foreach ($superTypes as $superType) {
  193. if (!$superType || $superType == $this->getName()) {
  194. continue;
  195. }
  196. if (!in_array($superType, $this->supertypeNames)) {
  197. $this->supertypeNames[] = $superType;
  198. }
  199. }
  200. if (!$this->isMixin() && $this->getName() != 'nt:base' && !in_array('nt:base', $this->supertypeNames)) {
  201. // Primary types extend nt:base automatically
  202. // but only if they don't already extend another
  203. // primary type
  204. $extendsPrimary = false;
  205. foreach ($this->supertypeNames as $superTypeName) {
  206. $superType = $this->nodeTypeManager->getNodeType($superTypeName);
  207. if (!$superType->isMixin()) {
  208. $extendsPrimary = true;
  209. }
  210. }
  211. if (!$extendsPrimary) {
  212. $this->supertypeNames[] = 'nt:base';
  213. }
  214. }
  215. return $this->supertypeNames;
  216. }
  217. public function getName()
  218. {
  219. return $this->name;
  220. }
  221. public function getPrimaryItemName()
  222. {
  223. if (!is_null($this->primaryItemName))
  224. {
  225. return $this->primaryItemName;
  226. }
  227. $mgdName = NodeMapper::getMidgardName($this->name);
  228. $this->primaryItemName = midgard_reflector_object::get_schema_value($mgdName, 'PrimaryItemName');
  229. return $this->primaryItemName;
  230. }
  231. public function hasOrderableChildNodes()
  232. {
  233. return $this->hasOrderableChildNodes;
  234. }
  235. public function isAbstract()
  236. {
  237. return $this->isAbstract;
  238. }
  239. public function isMixin()
  240. {
  241. return $this->isMixin;
  242. }
  243. public function isQueryable()
  244. {
  245. return $this->isQueryable;
  246. }
  247. }