Xsd.php 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. <?php
  2. Lib::loadClass('ApiDataSourceTodo');// TODO: @see Entity/Source/Mysql from feature-schema-install
  3. Lib::loadClass('Data_Source');
  4. Lib::loadClass('ApiRouteBase');
  5. class Api_Xsd extends ApiRouteBase {
  6. public $_apiUser;
  7. public $_dataSourceName;
  8. public $_tblName;
  9. public $_tblSchema;
  10. public function execute($request) {
  11. if (!$this->_apiUser->isAdmin()) {
  12. throw new HttpException("Forbidden", 403);
  13. }
  14. session_write_close();
  15. IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">request->segments (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($request->segments);echo'</pre>';}
  16. if (empty($request->segments) || !is_array($request->segments)) return;
  17. if (count($request->segments) < 1) {
  18. throw new HttpException("Data source and table name not specified", 400);
  19. }
  20. $this->_dataSourceName = array_shift($request->segments);
  21. if ('default_db' == $this->_dataSourceName) {
  22. $db = DB::getDB();
  23. $limit = 1000;
  24. $tbls = array();
  25. $sql = "show full tables";
  26. $res = $db->query($sql);
  27. while ($r = $db->fetch($res)) {
  28. if ('BASE TABLE' == $r->Table_type) {
  29. $tblName = get_object_vars($r);
  30. $tblName = array_values($tblName);
  31. $tblName = reset($tblName);
  32. if ('DEALS_TABLE_2015_03_17_zest_dla_zubryka' == $tblName) continue;// fields name 'grup_concat(...'
  33. if (false !== strpos($tblName, '#')) continue;
  34. $ds = new Data_Source();
  35. $ds->set_table($tblName);
  36. $ds->get_cols();
  37. $tbls[$tblName] = $ds;
  38. if (--$limit < 0) break;
  39. }
  40. }
  41. $xml = <<<XMLEOF
  42. <?xml version="1.0"?>
  43. <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:{$this->_dataSourceName}="http://biuro.biall-net.pl/xmlschema_procesy5/{$this->_dataSourceName}" targetNamespace="http://biuro.biall-net.pl/xmlschema_procesy5/{$this->_dataSourceName}">
  44. XMLEOF;
  45. foreach ($tbls as $tblName => $ds) {
  46. $xmlFields = array();
  47. $tblFields = $ds->_col_types;
  48. $xmlTableNamedSimpleTypes = array();
  49. foreach ($tblFields as $fldName => $colType) {
  50. $minOccurs = 0;
  51. $maxOccurs = 1;
  52. $colDefault = null;
  53. $xsdType = 'string';
  54. //$xsdType = 'token';
  55. //$xsdType = 'integer';
  56. //$xsdType = 'double';
  57. $xsdRestrictions = array();
  58. if (false !== strpos($colType, ';')) {
  59. $colType = explode(';', $colType, 2);
  60. $colDefault = array_pop($colType);
  61. $colType = array_shift($colType);
  62. }
  63. //$xsdRestrictions[] = '<xs:enumeration value="WAITING"/>';
  64. if ($this->isIntegerField($colType)) {
  65. $xsdType = 'integer';
  66. }
  67. else if ($this->isDecimalField($colType)) {
  68. $xsdType = 'double';
  69. }
  70. else if ($this->isStringField($colType)) {
  71. $xsdType = 'string';
  72. $maxLength = (int)str_replace(array(' ','(',')'), '', substr($colType, strpos($colType, '(') + 1, -1));
  73. if ($maxLength > 0) {
  74. $xsdRestrictions[] = '<xs:maxLength value="' . $maxLength . '"/>';
  75. }
  76. }
  77. else if ($this->isTextField($colType)) {
  78. $xsdType = 'string';
  79. }
  80. else if ($this->isDateField($colType)) {
  81. $xsdType = 'token';
  82. $xsdDatePattern = '[0-9]{4}-[0-9]{2}-[0-9]{2}';
  83. $xsdRestrictions[] = '<xs:pattern value="' . $xsdDatePattern . '"/>';
  84. }
  85. else if ($this->isDateTimeField($colType)) {
  86. $xsdType = 'token';
  87. $xsdDatePattern = '[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}';
  88. $xsdRestrictions[] = '<xs:pattern value="' . $xsdDatePattern . '"/>';
  89. }
  90. else if (substr($colType, 0, 4) == 'year') {
  91. $xsdType = 'token';
  92. $xsdDatePattern = '[0-9]{4}';
  93. $xsdRestrictions[] = '<xs:pattern value="' . $xsdDatePattern . '"/>';
  94. }
  95. else if (substr($colType, 0, 4) == 'enum') {
  96. $xsdType = 'string';
  97. $values = explode(',', str_replace(array('(',')',"'",'"'), '', substr($colType, 5)));
  98. foreach ($values as $val) {
  99. $xsdRestrictions[] = '<xs:enumeration value="' . $val . '"/>';
  100. }
  101. }
  102. else if ('polygon' == $colType) {
  103. $xsdType = 'string';
  104. }// Wielokąt
  105. else if ('multipolygon' == $colType) {
  106. $xsdType = 'string';
  107. }// Zbiór wielokątów
  108. else if ('linestring' == $colType) {
  109. $xsdType = 'string';
  110. }// Krzywa z interpolacji liniowej pomiędzy punktami
  111. else if ('point' == $colType) {
  112. $xsdType = 'string';
  113. }// Punkt w przestrzeni 2-wymiarowej
  114. else if ('geometry' == $colType) {
  115. $xsdType = 'string';
  116. }// Typy, które mogą przechowywać geometrię dowolnego typu
  117. else if ('multipoint' == $colType) {
  118. $xsdType = 'string';
  119. }// Zbiór punktów
  120. else if ('multilinestring' == $colType) {
  121. $xsdType = 'string';
  122. }// Zbiór krzywych z interpolacji liniowej pomiędzy punktami
  123. else if ('geometrycollection' == $colType) {
  124. $xsdType = 'string';
  125. }// Zbiór obiektów geometrycznych dowolnego typu
  126. else if ('timestamp' == substr($colType, 0, 9)) {
  127. $xsdType = 'string';
  128. }
  129. else if ('time' == substr($colType, 0, 4)) {
  130. $xsdType = 'token';
  131. $xsdDatePattern = '[0-9]{2}:[0-9]{2}:[0-9]{2}';
  132. $xsdRestrictions[] = '<xs:pattern value="' . $xsdDatePattern . '"/>';
  133. }
  134. else if ('binary' == substr($colType, 0, 6)
  135. || 'varbinary' == substr($colType, 0, 9)) {
  136. $xsdType = 'hexBinary';
  137. }
  138. else if ('blob' == substr($colType, 0, 4)
  139. || 'longblob' == substr($colType, 0, 8)
  140. || 'mediumblob' == substr($colType, 0, 10)
  141. || 'tinyblob' == substr($colType, 0, 8)) {
  142. $xsdType = 'hexBinary';
  143. }
  144. else if (substr($colType, 0, 3) == 'set') {
  145. $xsdType = 'string';
  146. $values = explode(',', str_replace(array('(',')',"'",'"'), '', substr($colType, 4)));
  147. foreach ($values as $val) {
  148. $xsdRestrictions[] = '<xs:enumeration value="' . $val . '"/>';
  149. }
  150. }
  151. else {
  152. $xsdType = 'unknown-Type-'.$colType.'';
  153. }
  154. $xmlFld = '';
  155. $xmlFieldTypeName = "{$tblName}__{$fldName}";
  156. $xmlFld .= '<xs:element minOccurs="' . $minOccurs . '" maxOccurs="' . $maxOccurs . '" name="' . $fldName . '" type="' . "{$this->_dataSourceName}:{$xmlFieldTypeName}" . '">';
  157. {
  158. $xmlNamedSimpleType = '';
  159. $xmlNamedSimpleType .= "\n" . '<xs:simpleType name="' . $xmlFieldTypeName . '">';
  160. if (!empty($xsdRestrictions)) {
  161. $xmlNamedSimpleType .= "\n\t" . '<xs:restriction base="xs:' . $xsdType . '">';
  162. $xmlNamedSimpleType .= "\n\t\t" . implode("\n\t\t", $xsdRestrictions);
  163. $xmlNamedSimpleType .= "\n\t" . '</xs:restriction>';
  164. } else {
  165. $xmlNamedSimpleType .= "\n\t" . '<xs:restriction base="xs:' . $xsdType . '"/>';
  166. }
  167. $xmlNamedSimpleType .= "\n" . '</xs:simpleType>';
  168. $xmlTableNamedSimpleTypes[] = $xmlNamedSimpleType;
  169. }
  170. $xmlFld .= "\n\t\t\t" . '</xs:element>';
  171. $xmlFields[] = $xmlFld;
  172. }
  173. $xmlFields = implode("\n\t\t\t", $xmlFields);
  174. $xmlTableNamedSimpleTypes = implode("\n", $xmlTableNamedSimpleTypes);
  175. $xml .= <<<XMLEOF
  176. <xs:element name="{$tblName}" type="{$this->_dataSourceName}:{$tblName}"/>
  177. <xs:complexType name="{$tblName}">
  178. <xs:sequence>
  179. {$xmlFields}
  180. </xs:sequence>
  181. </xs:complexType>
  182. {$xmlTableNamedSimpleTypes}
  183. XMLEOF;
  184. }
  185. $xml .= <<<XMLEOF
  186. </xs:schema>
  187. XMLEOF;
  188. header('Content-Type: text/xml; charset=utf-8');
  189. echo $xml;
  190. exit;
  191. //echo'<pre>';print_r($tbls);echo'</pre>';
  192. }
  193. // return document tree - array of arrays
  194. }
  195. // FROM TableAcl {
  196. public function isIntegerField($type) {
  197. if (substr($type, 0, 3) == 'int'
  198. || substr($type, 0, 7) == 'tinyint'
  199. || substr($type, 0, 8) == 'smallint'
  200. || substr($type, 0, 9) == 'mediumint'
  201. || substr($type, 0, 6) == 'bigint'
  202. ) {
  203. return true;
  204. }
  205. return false;
  206. }
  207. public function isDecimalField($type) {
  208. if (substr($type, 0, 7) == 'decimal'
  209. || substr($type, 0, 7) == 'numeric'
  210. || substr($type, 0, 6) == 'double'
  211. || substr($type, 0, 5) == 'float'
  212. || substr($type, 0, 4) == 'real'
  213. ) {
  214. return true;
  215. }
  216. return false;
  217. }
  218. public function isDateField($type) {
  219. if (substr($type, 0, 4) == 'date' && substr($type, 0, 8) != 'datetime') {
  220. return true;
  221. }
  222. return false;
  223. }
  224. public function isDateTimeField($type) {
  225. if (substr($type, 0, 8) == 'datetime') {
  226. return true;
  227. }
  228. return false;
  229. }
  230. public function isStringField($type) {
  231. if (substr($type, 0, 7) == 'varchar'
  232. || substr($type, 0, 4) == 'char'
  233. ) {
  234. return true;
  235. }
  236. return false;
  237. }
  238. public function isTextField($type) {
  239. if (substr($type, 0, 4) == 'text'
  240. || substr($type, 0, 8) == 'tinytext'
  241. || substr($type, 0, 10) == 'mediumtext'
  242. || substr($type, 0, 8) == 'longtext'
  243. ) {
  244. return true;
  245. }
  246. return false;
  247. }
  248. // FROM } TableAcl
  249. private function getDataSource() {
  250. if (!$this->_dataSource) {
  251. // TODO: get data source from Factory
  252. {
  253. if ('default_db' == $this->_dataSourceName) {
  254. $this->_dataSource = new ApiDataSourceTodo($this->_dataSourceName);
  255. $this->_dataSource->setTable($this->_tblName);
  256. }
  257. else if ('931' == $this->_dataSourceName) {
  258. $this->_dataSource = new ApiDataSourceTodo($this->_dataSourceName);
  259. $this->_dataSource->setTable($this->_tblName);
  260. }
  261. }
  262. }
  263. return $this->_dataSource;
  264. }
  265. }