Xsd.php 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. <?php
  2. Lib::loadClass('ApiDataSourceTodo');// TODO: @see Entity/Source/Mysql from feature-schema-install
  3. Lib::loadClass('Data_Source');
  4. class Api_Xsd {
  5. private $_apiUser;
  6. private $_dataSourceName;
  7. private $_tblName;
  8. private $_tblSchema;
  9. public function setUser($user) {
  10. $this->_apiUser = $user;
  11. }
  12. public function execute($request) {
  13. if (!$this->_apiUser->isAdmin()) {
  14. throw new HttpException("Forbidden", 403);
  15. }
  16. 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>';}
  17. if (empty($request->segments) || !is_array($request->segments)) return;
  18. if (count($request->segments) < 1) {
  19. throw new HttpException("Data source and table name not specified", 400);
  20. }
  21. $this->_dataSourceName = array_shift($request->segments);
  22. if ('default_db' == $this->_dataSourceName) {
  23. $db = DB::getDB();
  24. $limit = 1000;
  25. $tbls = array();
  26. $sql = "show full tables";
  27. $res = $db->query($sql);
  28. while ($r = $db->fetch($res)) {
  29. if ('BASE TABLE' == $r->Table_type) {
  30. $tblName = get_object_vars($r);
  31. $tblName = array_values($tblName);
  32. $tblName = reset($tblName);
  33. if ('DEALS_TABLE_2015_03_17_zest_dla_zubryka' == $tblName) {
  34. continue;// fields name 'grup_concat(...'
  35. }
  36. if ('KSIEG_DOKUMENTY' == $tblName) {
  37. continue;// fields name '201_...'
  38. }
  39. if ('KSIEG_DOKUMENTY_HIST' == $tblName) {
  40. continue;// fields name '201_...'
  41. }
  42. if ('Rozdzielcza_rurociag_wsg84' == $tblName) {
  43. continue;// fields name with space ' '
  44. }
  45. $ds = new Data_Source();
  46. $ds->set_table($tblName);
  47. $ds->get_cols();
  48. $tbls[$tblName] = $ds;
  49. if (--$limit < 0) break;
  50. }
  51. }
  52. $xml = <<<XMLEOF
  53. <?xml version="1.0"?>
  54. <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}">
  55. XMLEOF;
  56. Lib::loadClass('TableAcl');
  57. $acl = new TableAcl();
  58. foreach ($tbls as $tblName => $ds) {
  59. $xmlFields = array();
  60. $tblFields = $ds->_col_types;
  61. foreach ($tblFields as $fldName => $colType) {
  62. $minOccurs = 0;
  63. $maxOccurs = 1;
  64. $colDefault = null;
  65. $xsdType = 'string';
  66. //$xsdType = 'token';
  67. //$xsdType = 'integer';
  68. //$xsdType = 'double';
  69. $xsdRestrictions = array();
  70. if (false !== strpos($colType, ';')) {
  71. $colType = explode(';', $colType, 2);
  72. $colDefault = array_pop($colType);
  73. $colType = array_shift($colType);
  74. }
  75. //$xsdRestrictions[] = '<xs:enumeration value="WAITING"/>';
  76. if ($this->isIntegerField($colType)) {
  77. $xsdType = 'integer';
  78. }
  79. else if ($this->isDecimalField($colType)) {
  80. $xsdType = 'double';
  81. }
  82. else if ($this->isStringField($colType)) {
  83. $xsdType = 'string';
  84. $maxLength = (int)str_replace(array(' ','(',')'), '', substr($colType, strpos($colType, '(') + 1, -1));
  85. if ($maxLength > 0) {
  86. $xsdRestrictions[] = '<xs:maxLength value="' . $maxLength . '"/>';
  87. }
  88. }
  89. else if ($this->isTextField($colType)) {
  90. $xsdType = 'string';
  91. }
  92. else if ($this->isDateField($colType)) {
  93. $xsdType = 'token';
  94. $xsdDatePattern = '[0-9]{4}-[0-9]{2}-[0-9]{2}';
  95. $xsdRestrictions[] = '<xs:pattern value="' . $xsdDatePattern . '"/>';
  96. }
  97. else if ($this->isDateTimeField($colType)) {
  98. $xsdType = 'token';
  99. $xsdDatePattern = '[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}';
  100. $xsdRestrictions[] = '<xs:pattern value="' . $xsdDatePattern . '"/>';
  101. }
  102. else if (substr($colType, 0, 4) == 'enum') {
  103. $xsdType = 'string';
  104. $values = explode(',', str_replace(array('(',')',"'",'"'), '', substr($colType, 5)));
  105. foreach ($values as $val) {
  106. $xsdRestrictions[] = '<xs:enumeration value="' . $val . '"/>';
  107. }
  108. }
  109. else if ('polygon' == $colType) {
  110. $xsdType = 'string';
  111. }// Wielokąt
  112. else if ('multipolygon' == $colType) {
  113. $xsdType = 'string';
  114. }// Zbiór wielokątów
  115. else if ('linestring' == $colType) {
  116. $xsdType = 'string';
  117. }// Krzywa z interpolacji liniowej pomiędzy punktami
  118. else if ('point' == $colType) {
  119. $xsdType = 'string';
  120. }// Punkt w przestrzeni 2-wymiarowej
  121. else if ('geometry' == $colType) {
  122. $xsdType = 'string';
  123. }// Typy, które mogą przechowywać geometrię dowolnego typu
  124. else if ('multipoint' == $colType) {
  125. $xsdType = 'string';
  126. }// Zbiór punktów
  127. else if ('multilinestring' == $colType) {
  128. $xsdType = 'string';
  129. }// Zbiór krzywych z interpolacji liniowej pomiędzy punktami
  130. else if ('geometrycollection' == $colType) {
  131. $xsdType = 'string';
  132. }// Zbiór obiektów geometrycznych dowolnego typu
  133. else if ('timestamp' == substr($colType, 0, 9)) {
  134. $xsdType = 'string';
  135. }
  136. else if ('time' == substr($colType, 0, 4)) {
  137. $xsdType = 'token';
  138. $xsdDatePattern = '[0-9]{2}:[0-9]{2}:[0-9]{2}';
  139. $xsdRestrictions[] = '<xs:pattern value="' . $xsdDatePattern . '"/>';
  140. }
  141. else if ('binary' == substr($colType, 0, 6)
  142. || 'varbinary' == substr($colType, 0, 9)) {
  143. $xsdType = 'hexBinary';
  144. }
  145. else if ('blob' == substr($colType, 0, 4)
  146. || 'longblob' == substr($colType, 0, 8)
  147. || 'mediumblob' == substr($colType, 0, 10)
  148. || 'tinyblob' == substr($colType, 0, 8)) {
  149. $xsdType = 'hexBinary';
  150. }
  151. else if (substr($colType, 0, 3) == 'set') {
  152. $xsdType = 'string';
  153. $values = explode(',', str_replace(array('(',')',"'",'"'), '', substr($colType, 4)));
  154. foreach ($values as $val) {
  155. $xsdRestrictions[] = '<xs:enumeration value="' . $val . '"/>';
  156. }
  157. }
  158. else {
  159. $xsdType = 'unknown-Type-'.$colType.'';
  160. }
  161. $xmlFld = '';
  162. $xmlFld .= '<xs:element minOccurs="' . $minOccurs . '" maxOccurs="' . $maxOccurs . '" name="' . $fldName . '">';
  163. $xmlFld .= "\n\t\t\t\t" . '<xs:simpleType>';
  164. if (!empty($xsdRestrictions)) {
  165. $xmlFld .= "\n\t\t\t\t\t" . '<xs:restriction base="xs:' . $xsdType . '">';
  166. $xmlFld .= "\n\t\t\t\t\t\t" . implode("\n\t\t\t\t\t\t", $xsdRestrictions);
  167. $xmlFld .= "\n\t\t\t\t\t" . '</xs:restriction>';
  168. } else {
  169. $xmlFld .= "\n\t\t\t\t\t" . '<xs:restriction base="xs:' . $xsdType . '"/>';
  170. }
  171. $xmlFld .= "\n\t\t\t\t" . '</xs:simpleType>';
  172. $xmlFld .= "\n\t\t\t" . '</xs:element>';
  173. $xmlFields[] = $xmlFld;
  174. }
  175. $xmlFields = implode("\n\t\t\t", $xmlFields);
  176. $xml .= <<<XMLEOF
  177. <xs:element name="{$tblName}" type="{$this->_dataSourceName}:{$tblName}"/>
  178. <xs:complexType name="{$tblName}">
  179. <xs:sequence>
  180. {$xmlFields}
  181. </xs:sequence>
  182. </xs:complexType>
  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. }