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