Xsd.php 9.3 KB

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