IPXMLSchema.class.php 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. <?php
  2. /**
  3. * This class helps you creating a valid XMLSchema file
  4. */
  5. class IPXMLSchema {
  6. /** @var domelement reference to the parent domelement */
  7. private $parentElement;
  8. /** @var domelement[] Array with references to all known types in this schema */
  9. private $types = Array();
  10. /** @var boolean True=place array's inline */
  11. private $array_inline = false;
  12. public function __construct(domelement $parentElement){
  13. $this->parentElement = $parentElement;
  14. }
  15. /**
  16. * Ads a complexType tag with xmlschema content to the types tag
  17. * @param string The variable type (Array or class name)
  18. * @param string The variable name
  19. * @param domNode Used when adding an inline complexType
  20. * @return domNode The complexType node
  21. */
  22. public function addComplexType($type, $name = false, $parent = false) {
  23. if(!$parent){//outline element
  24. //check if the complexType doesn't already exists
  25. if(isset($this->types[$name])) return $this->types[$name];
  26. //create the complexType tag beneath the xsd:schema tag
  27. $complexTypeTag=$this->addElement("xsd:complexType", $this->parentElement);
  28. if($name){//might be an anonymous element
  29. $complexTypeTag->setAttribute("name",$name);
  30. $this->types[$name]=$complexTypeTag;
  31. }
  32. }else{//inline element
  33. $complexTypeTag = $this->addElement("xsd:complexType", $parent);
  34. }
  35. //check if its an array
  36. if(strtolower(substr($type,0,6)) == 'array(' || substr($type,-2) == '[]'){
  37. $this->addArray($type,$complexTypeTag);
  38. }else{//it should be an object
  39. $tag=$this->addElement("xsd:all", $complexTypeTag);
  40. //check if it has the name 'object()' (kind of a stdClass)
  41. if(strtolower(substr($type,0,6)) == 'object'){//stdClass
  42. $content = substr($type, 7, (strlen($type)-1));
  43. $properties = explode(",", $content);//split the content into properties
  44. foreach((array)$properties as $property){
  45. if($pos = strpos($property, "=>")){//array with keys (order is important, so use 'sequence' tag)
  46. $keyType = substr($property,6,($pos-6));
  47. $valueType = substr($property,($pos+2), (strlen($property)-7));
  48. $el->$this->addTypeElement($valueType, $keyType, $tag);
  49. }else{
  50. throw new WSDLException("Error creating WSDL: expected \"=>\". When using the object() as type, use it as object(paramname=>paramtype,paramname2=>paramtype2)");
  51. }
  52. }
  53. }else{ //should be a known class
  54. if(!class_exists($name)) throw new WSDLException("Error creating WSDL: no class found with the name '$name' / $type : $parent, so how should we know the structure for this datatype?");
  55. $v = new IPReflectionClass($name);
  56. //TODO: check if the class extends another class?
  57. $properties = $v->getProperties(false, false);//not protected and private properties
  58. foreach((array) $properties as $property){
  59. if(!$property->isPrivate){
  60. $el = $this->addTypeElement($property->type, $property->name, $tag, $property->optional);
  61. }
  62. }
  63. }
  64. }
  65. return $complexTypeTag;
  66. }
  67. /**
  68. * Adds an element tag beneath the parent and takes care
  69. * of the type (XMLSchema type or complexType)
  70. * @param string The datatype
  71. * @param string Name of the element
  72. * @param domNode The parent domNode
  73. * @param boolean If the property is optional
  74. * @return domNode
  75. */
  76. public function addTypeElement($type, $name, $parent, $optional = false) {
  77. $el = $this->addElement("xsd:element", $parent);
  78. $el->setAttribute("name", $name);
  79. if($optional){//if it's an optional property, set minOccur to 0
  80. $el->setAttribute("minOccurs", "0");
  81. $el->setAttribute("maxOccurs", "1");
  82. }
  83. //check if XML Schema datatype
  84. if($t = $this->checkSchemaType(strtolower($type)))
  85. $el->setAttribute("type", "xsd:".$t);
  86. else{//no XML Schema datatype
  87. //if valueType==Array, then create anonymouse inline complexType (within element tag without type attribute)
  88. if(substr($type,-2) == '[]'){
  89. if($this->array_inline){
  90. $this->addComplexType($type, false, $el);
  91. }else{
  92. $name = substr($type, 0, -2)."Array";
  93. $el->setAttribute("type", "tns:".$name);
  94. $this->addComplexType($type, $name, false);
  95. }
  96. }else{//else, new complextype, outline (element with 'ref' attrib)
  97. $el->setAttribute("type", "tns:".$type);
  98. $this->addComplexType($type, $type);
  99. }
  100. }
  101. return $el;
  102. }
  103. /**
  104. * Creates an xmlSchema element for the given array
  105. */
  106. public function addArray($type, $parent) {
  107. $cc = $this->addElement("xsd:complexContent", $parent);
  108. $rs = $this->addElement("xsd:restriction", $cc);
  109. $rs->setAttribute("base", "SOAP-ENC:Array");
  110. $type = (substr($type,-2) == '[]') ? substr($type, 0, (strlen($type)-2)) : substr($type, 6, (strlen($type)-7));
  111. $el = $this->addElement("xsd:attribute", $rs);
  112. $el->setAttribute("ref", "SOAP-ENC:arrayType");
  113. //check if XML Schema datatype
  114. if($t = $this->checkSchemaType(strtolower($type)))
  115. $el->setAttribute("wsdl:arrayType", "xsd:".$t."[]");
  116. else{//no XML Schema datatype
  117. //if valueType==Array, then create anonymouse inline complexType (within element tag without type attribute)
  118. if(substr($type,-2) == '[]'){
  119. $this->addComplexType($type, false, $el);
  120. }else{//else, new complextype, outline (element with 'ref' attrib)
  121. $el->setAttribute("wsdl:arrayType", "tns:".$type."[]");
  122. $this->addComplexType($type, $type);
  123. }
  124. }
  125. return $el;
  126. }
  127. /**
  128. * Checks if the given type is a valid XML Schema type or can be casted to a schema type
  129. * @param string The datatype
  130. * @return string
  131. */
  132. public static function checkSchemaType($type) {
  133. //XML Schema types
  134. $types = Array("string" => "string",
  135. "int" => "int",
  136. "integer" => "int",
  137. "boolean" => "boolean",
  138. "float" => "float");
  139. if(isset($types[$type])) return $types[$type];
  140. else return false;
  141. }
  142. /**
  143. * Adds an child element to the parent
  144. * @param string
  145. * @param domNode
  146. * @return domNode
  147. */
  148. private function addElement($name, $parent = false, $ns = false) {
  149. if($ns)
  150. $el = $parent->ownerDocument->createElementNS($ns, $name);
  151. else
  152. $el = $parent->ownerDocument->createElement($name);
  153. if($parent)
  154. $parent->appendChild($el);
  155. return $el;
  156. }
  157. }
  158. ?>