Xsd.php 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  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. foreach ($tblFields as $fldName => $colType) {
  58. $minOccurs = 0;
  59. $maxOccurs = 1;
  60. $colDefault = null;
  61. $xsdType = 'string';
  62. //$xsdType = 'token';
  63. //$xsdType = 'integer';
  64. //$xsdType = 'double';
  65. $xsdRestrictions = array();
  66. if (false !== strpos($colType, ';')) {
  67. $colType = explode(';', $colType, 2);
  68. $colDefault = array_pop($colType);
  69. $colType = array_shift($colType);
  70. }
  71. //$xsdRestrictions[] = '<xs:enumeration value="WAITING"/>';
  72. if ($this->isIntegerField($colType)) {
  73. $xsdType = 'integer';
  74. }
  75. else if ($this->isDecimalField($colType)) {
  76. $xsdType = 'double';
  77. }
  78. else if ($this->isStringField($colType)) {
  79. $xsdType = 'string';
  80. $maxLength = (int)str_replace(array(' ','(',')'), '', substr($colType, strpos($colType, '(') + 1, -1));
  81. if ($maxLength > 0) {
  82. $xsdRestrictions[] = '<xs:maxLength value="' . $maxLength . '"/>';
  83. }
  84. }
  85. else if ($this->isTextField($colType)) {
  86. $xsdType = 'string';
  87. }
  88. else if ($this->isDateField($colType)) {
  89. $xsdType = 'token';
  90. $xsdDatePattern = '[0-9]{4}-[0-9]{2}-[0-9]{2}';
  91. $xsdRestrictions[] = '<xs:pattern value="' . $xsdDatePattern . '"/>';
  92. }
  93. else if ($this->isDateTimeField($colType)) {
  94. $xsdType = 'token';
  95. $xsdDatePattern = '[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}';
  96. $xsdRestrictions[] = '<xs:pattern value="' . $xsdDatePattern . '"/>';
  97. }
  98. else if (substr($colType, 0, 4) == 'year') {
  99. $xsdType = 'token';
  100. $xsdDatePattern = '[0-9]{4}';
  101. $xsdRestrictions[] = '<xs:pattern value="' . $xsdDatePattern . '"/>';
  102. }
  103. else if (substr($colType, 0, 4) == 'enum') {
  104. $xsdType = 'string';
  105. $values = explode(',', str_replace(array('(',')',"'",'"'), '', substr($colType, 5)));
  106. foreach ($values as $val) {
  107. $xsdRestrictions[] = '<xs:enumeration value="' . $val . '"/>';
  108. }
  109. }
  110. else if ('polygon' == $colType) {
  111. $xsdType = 'string';
  112. }// Wielokąt
  113. else if ('multipolygon' == $colType) {
  114. $xsdType = 'string';
  115. }// Zbiór wielokątów
  116. else if ('linestring' == $colType) {
  117. $xsdType = 'string';
  118. }// Krzywa z interpolacji liniowej pomiędzy punktami
  119. else if ('point' == $colType) {
  120. $xsdType = 'string';
  121. }// Punkt w przestrzeni 2-wymiarowej
  122. else if ('geometry' == $colType) {
  123. $xsdType = 'string';
  124. }// Typy, które mogą przechowywać geometrię dowolnego typu
  125. else if ('multipoint' == $colType) {
  126. $xsdType = 'string';
  127. }// Zbiór punktów
  128. else if ('multilinestring' == $colType) {
  129. $xsdType = 'string';
  130. }// Zbiór krzywych z interpolacji liniowej pomiędzy punktami
  131. else if ('geometrycollection' == $colType) {
  132. $xsdType = 'string';
  133. }// Zbiór obiektów geometrycznych dowolnego typu
  134. else if ('timestamp' == substr($colType, 0, 9)) {
  135. $xsdType = 'string';
  136. }
  137. else if ('time' == substr($colType, 0, 4)) {
  138. $xsdType = 'token';
  139. $xsdDatePattern = '[0-9]{2}:[0-9]{2}:[0-9]{2}';
  140. $xsdRestrictions[] = '<xs:pattern value="' . $xsdDatePattern . '"/>';
  141. }
  142. else if ('binary' == substr($colType, 0, 6)
  143. || 'varbinary' == substr($colType, 0, 9)) {
  144. $xsdType = 'hexBinary';
  145. }
  146. else if ('blob' == substr($colType, 0, 4)
  147. || 'longblob' == substr($colType, 0, 8)
  148. || 'mediumblob' == substr($colType, 0, 10)
  149. || 'tinyblob' == substr($colType, 0, 8)) {
  150. $xsdType = 'hexBinary';
  151. }
  152. else if (substr($colType, 0, 3) == 'set') {
  153. $xsdType = 'string';
  154. $values = explode(',', str_replace(array('(',')',"'",'"'), '', substr($colType, 4)));
  155. foreach ($values as $val) {
  156. $xsdRestrictions[] = '<xs:enumeration value="' . $val . '"/>';
  157. }
  158. }
  159. else {
  160. $xsdType = 'unknown-Type-'.$colType.'';
  161. }
  162. $xmlFld = '';
  163. $xmlFld .= '<xs:element minOccurs="' . $minOccurs . '" maxOccurs="' . $maxOccurs . '" name="' . $fldName . '">';
  164. $xmlFld .= "\n\t\t\t\t" . '<xs:simpleType>';
  165. if (!empty($xsdRestrictions)) {
  166. $xmlFld .= "\n\t\t\t\t\t" . '<xs:restriction base="xs:' . $xsdType . '">';
  167. $xmlFld .= "\n\t\t\t\t\t\t" . implode("\n\t\t\t\t\t\t", $xsdRestrictions);
  168. $xmlFld .= "\n\t\t\t\t\t" . '</xs:restriction>';
  169. } else {
  170. $xmlFld .= "\n\t\t\t\t\t" . '<xs:restriction base="xs:' . $xsdType . '"/>';
  171. }
  172. $xmlFld .= "\n\t\t\t\t" . '</xs:simpleType>';
  173. $xmlFld .= "\n\t\t\t" . '</xs:element>';
  174. $xmlFields[] = $xmlFld;
  175. }
  176. $xmlFields = implode("\n\t\t\t", $xmlFields);
  177. $xml .= <<<XMLEOF
  178. <xs:element name="{$tblName}" type="{$this->_dataSourceName}:{$tblName}"/>
  179. <xs:complexType name="{$tblName}">
  180. <xs:sequence>
  181. {$xmlFields}
  182. </xs:sequence>
  183. </xs:complexType>
  184. XMLEOF;
  185. }
  186. $xml .= <<<XMLEOF
  187. </xs:schema>
  188. XMLEOF;
  189. header('Content-Type: text/xml; charset=utf-8');
  190. echo $xml;
  191. exit;
  192. //echo'<pre>';print_r($tbls);echo'</pre>';
  193. }
  194. // return document tree - array of arrays
  195. }
  196. // FROM TableAcl {
  197. public function isIntegerField($type) {
  198. if (substr($type, 0, 3) == 'int'
  199. || substr($type, 0, 7) == 'tinyint'
  200. || substr($type, 0, 8) == 'smallint'
  201. || substr($type, 0, 9) == 'mediumint'
  202. || substr($type, 0, 6) == 'bigint'
  203. ) {
  204. return true;
  205. }
  206. return false;
  207. }
  208. public function isDecimalField($type) {
  209. if (substr($type, 0, 7) == 'decimal'
  210. || substr($type, 0, 7) == 'numeric'
  211. || substr($type, 0, 6) == 'double'
  212. || substr($type, 0, 5) == 'float'
  213. || substr($type, 0, 4) == 'real'
  214. ) {
  215. return true;
  216. }
  217. return false;
  218. }
  219. public function isDateField($type) {
  220. if (substr($type, 0, 4) == 'date' && substr($type, 0, 8) != 'datetime') {
  221. return true;
  222. }
  223. return false;
  224. }
  225. public function isDateTimeField($type) {
  226. if (substr($type, 0, 8) == 'datetime') {
  227. return true;
  228. }
  229. return false;
  230. }
  231. public function isStringField($type) {
  232. if (substr($type, 0, 7) == 'varchar'
  233. || substr($type, 0, 4) == 'char'
  234. ) {
  235. return true;
  236. }
  237. return false;
  238. }
  239. public function isTextField($type) {
  240. if (substr($type, 0, 4) == 'text'
  241. || substr($type, 0, 8) == 'tinytext'
  242. || substr($type, 0, 10) == 'mediumtext'
  243. || substr($type, 0, 8) == 'longtext'
  244. ) {
  245. return true;
  246. }
  247. return false;
  248. }
  249. // FROM } TableAcl
  250. private function getDataSource() {
  251. if (!$this->_dataSource) {
  252. // TODO: get data source from Factory
  253. {
  254. if ('default_db' == $this->_dataSourceName) {
  255. $this->_dataSource = new ApiDataSourceTodo($this->_dataSourceName);
  256. $this->_dataSource->setTable($this->_tblName);
  257. }
  258. else if ('931' == $this->_dataSourceName) {
  259. $this->_dataSource = new ApiDataSourceTodo($this->_dataSourceName);
  260. $this->_dataSource->setTable($this->_tblName);
  261. }
  262. }
  263. }
  264. return $this->_dataSource;
  265. }
  266. }