TestXsd.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. <?php
  2. Lib::loadClass('RouteBase');
  3. class Route_Storage_TestXsd extends RouteBase {
  4. public function defaultAction() {
  5. $idStorage = V::get('idStorage', 0, $_REQUEST, 'int');
  6. $storage = DB::getStorage($idStorage);
  7. $tableRealList = $storage->getTableList();
  8. $srvName = $_SERVER['SERVER_NAME'];
  9. $storageZasobId = $storage->getZasobId();
  10. $objNs = "p5_{$storageZasobId}_{$tblName}";
  11. $objNsUri = "https://biuro.biall-net.pl/api/{$storageZasobId}/{$tblName}";
  12. $p5TypePrefix = "p5Type";
  13. $p5TypeNsUri = "http://biuro.biall-net.pl/p5/schema/types";
  14. $p5TypeNsLocation = "http://biuro.biall-net.pl/p5/schema/types.xsd";
  15. header('Content-type: text/plain; charset=utf-8');// TODO: test
  16. //header('Content-type: application/xml; charset=utf-8');
  17. $xmlWriter = new XMLWriter();
  18. $xmlWriter->openUri('php://output');
  19. $xmlWriter->setIndent(true);
  20. if (!$xmlWriter) throw new HttpException("Error no XMLWriter", 404);
  21. $xmlWriter->startDocument('1.0', 'UTF-8');
  22. $xmlWriter->startElement('xs:schema');
  23. $xmlWriter->writeAttribute('xmlns:xs', 'http://www.w3.org/2001/XMLSchema');
  24. $xmlWriter->writeAttribute('xmlns:vc', 'http://www.w3.org/2007/XMLSchema-versioning');
  25. $xmlWriter->writeAttribute("xmlns:{$p5TypePrefix}", $p5TypeNsUri);
  26. $xmlWriter->writeAttribute('elementFormDefault', 'qualified');
  27. $xmlWriter->writeAttribute('targetNamespace', $objNsUri);
  28. $xmlWriter->writeAttribute('vc:minVersion', '1.1');
  29. $xmlWriter->startElement('xs:import');
  30. $xmlWriter->writeAttribute('namespace', $p5TypeNsUri);
  31. $xmlWriter->writeAttribute('schemaLocation', $p5TypeNsLocation);
  32. $xmlWriter->endElement();// xs:import
  33. foreach ($tableRealList as $tbl) {
  34. $tblName = $tbl['table_name'];
  35. $this->tableXsdViewXmlWriter($xmlWriter, $idStorage, $tblName);
  36. }
  37. $xmlWriter->endElement();// xs:schema
  38. $xmlWriter->endDocument();
  39. }
  40. public function tableXsdAction() {
  41. $idStorage = V::get('idStorage', '', $_GET);
  42. $tblName = V::get('table', '', $_GET, 'word');
  43. if (empty($tblName)) die("Wrong table name");
  44. header('Content-type: text/plain; charset=utf-8');// TODO: test
  45. $storage = DB::getStorage($idStorage);
  46. $storageZasobId = $storage->getZasobId();
  47. $objNs = "p5_{$storageZasobId}_{$tblName}";
  48. $objNsUri = "https://biuro.biall-net.pl/api/{$storageZasobId}/{$tblName}";
  49. $p5TypePrefix = "p5Type";
  50. $p5TypeNsUri = "http://biuro.biall-net.pl/p5/schema/types";
  51. $p5TypeNsLocation = "http://biuro.biall-net.pl/p5/schema/types.xsd";
  52. //header('Content-type: application/xml; charset=utf-8');
  53. $xmlWriter = new XMLWriter();
  54. $xmlWriter->openUri('php://output');
  55. $xmlWriter->setIndent(true);
  56. if (!$xmlWriter) throw new HttpException("Error no XMLWriter", 404);
  57. $xmlWriter->startDocument('1.0', 'UTF-8');
  58. $xmlWriter->startElement('xs:schema');
  59. $xmlWriter->writeAttribute('xmlns:xs', 'http://www.w3.org/2001/XMLSchema');
  60. $xmlWriter->writeAttribute('xmlns:vc', 'http://www.w3.org/2007/XMLSchema-versioning');
  61. $xmlWriter->writeAttribute("xmlns:{$p5TypePrefix}", $p5TypeNsUri);
  62. $xmlWriter->writeAttribute('elementFormDefault', 'qualified');
  63. $xmlWriter->writeAttribute('targetNamespace', $objNsUri);
  64. $xmlWriter->writeAttribute('vc:minVersion', '1.1');
  65. $xmlWriter->startElement('xs:import');
  66. $xmlWriter->writeAttribute('namespace', $p5TypeNsUri);
  67. $xmlWriter->writeAttribute('schemaLocation', $p5TypeNsLocation);
  68. $xmlWriter->endElement();// xs:import
  69. $this->tableXsdViewXmlWriter($xmlWriter, $idStorage, $tblName);
  70. $xmlWriter->endElement();// xs:schema
  71. $xmlWriter->endDocument();
  72. }
  73. public function tableXsdViewXmlWriter(&$xmlWriter, $idStorage, $tblName) {
  74. $storage = DB::getStorage($idStorage);
  75. $schema = Schema_TableFactory::build($tblName, $idStorage, $_SERVER['SERVER_NAME']);
  76. $struct = $schema->getStruct();
  77. DBG::_('DBG', '>1', "struct", $struct, __CLASS__, __FUNCTION__, __LINE__);
  78. $typeName = "{$tblName}Type";
  79. $xmlWriter->startElement('xs:complexType');
  80. $xmlWriter->writeAttribute('name', $typeName);
  81. $xmlWriter->startElement('xs:sequence');
  82. $foreignKeys = [];
  83. {
  84. $dbName = DB::getPDO($idStorage)->getDatabaseName();
  85. if ('mysql' === DB::getPDO($idStorage)->getType()) {
  86. $foreignKeys = DB::getPDO($idStorage)->fetchAll("
  87. SELECT i.TABLE_SCHEMA, i.TABLE_NAME, i.CONSTRAINT_TYPE, i.CONSTRAINT_NAME, k.COLUMN_NAME, k.REFERENCED_TABLE_NAME, k.REFERENCED_COLUMN_NAME
  88. FROM information_schema.TABLE_CONSTRAINTS i
  89. LEFT JOIN information_schema.KEY_COLUMN_USAGE k ON i.CONSTRAINT_NAME = k.CONSTRAINT_NAME
  90. WHERE i.TABLE_SCHEMA = :db_name
  91. and i.TABLE_NAME = :tbl_name
  92. and i.CONSTRAINT_TYPE = 'FOREIGN KEY'
  93. ORDER BY i.TABLE_NAME
  94. ", [
  95. ':db_name' => $dbName,
  96. ':tbl_name' => $tblName,
  97. ]);
  98. // if ('CRM_WSKAZNIK' === $tblName) { // @example: CRM_WSKAZNIK.ID_ZASOB => CRM_LISTA_ZASOBOW.ID
  99. // $foreignKeys = [
  100. // [ 'TABLE_SCHEMA' => "SES_USERS2"
  101. // , 'TABLE_NAME' => "CRM_WSKAZNIK"
  102. // , 'CONSTRAINT_TYPE' => "FOREIGN KEY"
  103. // , 'CONSTRAINT_NAME' => "zasob"
  104. // , 'COLUMN_NAME' => "ID_ZASOB"
  105. // , 'REFERENCED_TABLE_NAME' => "CRM_LISTA_ZASOBOW"
  106. // , 'REFERENCED_COLUMN_NAME' => "ID"
  107. // ]
  108. // ];
  109. // }
  110. // $xmlWriter->writeComment("\$foreignKeys: " . var_export($foreignKeys, true));
  111. // TABLE_SCHEMA, TABLE_NAME, CONSTRAINT_TYPE, CONSTRAINT_NAME, COLUMN_NAME, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME
  112. // * * FOREIGN KEY * * * *
  113. }
  114. }
  115. foreach ($struct as $field) {
  116. $xmlWriter->startElement('xs:element');
  117. $xmlWriter->writeAttribute('name', $field['name']);
  118. $xmlWriter->writeAttribute('minOccurs', 0);// TODO: set minOccurs by default, etc.
  119. if ($field['is_nullable']) $xmlWriter->writeAttribute('nillable', 'true');
  120. if (null !== $field['default_value']) {
  121. $xmlWriter->writeAttribute('default', $field['default_value']);
  122. } else if (null === $field['default_value'] && $field['is_nullable']) {
  123. $xmlWriter->writeAttribute('default', $field['default_value']);
  124. } else {
  125. // TODO: Schema BUG?
  126. }
  127. if (empty($field['p5_restrictions'])) {
  128. $xmlWriter->writeAttribute('type', "p5Type:{$field['p5_type']}");
  129. } else {
  130. $xmlWriter->startElement('xs:simpleType');
  131. $xmlWriter->writeAttribute('base', "p5Type:{$field['p5_type']}");
  132. $xmlWriter->startElement('xs:restriction');
  133. if (!empty($field['p5_restrictions']['enumeration'])) {
  134. foreach ($field['p5_restrictions']['enumeration'] as $enumValue) {
  135. $xmlWriter->startElement('xs:enumeration');
  136. $xmlWriter->writeAttribute('value', $enumValue);
  137. $xmlWriter->endElement();// xs:enumeration
  138. }
  139. } else {
  140. // TODO: another restrictions...
  141. }
  142. $xmlWriter->endElement();// xs:restriction
  143. $xmlWriter->endElement();// xs:simpleType
  144. }
  145. $xmlWriter->endElement();// xs:element
  146. }
  147. if (!empty($foreignKeys)) {
  148. foreach ($foreignKeys as $key) {
  149. $xmlWriter->startElement('xs:element');
  150. $refPrefix = (DB::getPDO()->getZasobId() === $idStorage) ? 'p5_default_db' : "p5_zasob_{$idStorage}";
  151. $xmlWriter->writeAttribute('ref', "{$refPrefix}:{$key['REFERENCED_TABLE_NAME']}");
  152. $xmlWriter->startElement('xs:annotation');
  153. $xmlWriter->startElement('xs:appinfo');
  154. $xmlWriter->startElement('system_cache__appinfo:flat_relation_cache');
  155. $xmlWriter->writeAttribute("system_cache__appinfo:name", $key['COLUMN_NAME']);
  156. $xmlWriter->writeAttribute("system_cache__appinfo:xpath", "{$refPrefix}:{$key['REFERENCED_TABLE_NAME']}/{$key['REFERENCED_COLUMN_NAME']}");
  157. $xmlWriter->endElement();// system_cache__appinfo:flat_relation_cache
  158. $xmlWriter->endElement();// xs:appinfo
  159. $xmlWriter->endElement();// xs:annotation
  160. $xmlWriter->endElement();// xs:element
  161. }
  162. }
  163. $xmlWriter->endElement();// xs:sequence
  164. $xmlWriter->endElement();// xs:complexType
  165. return;
  166. // <xs:element maxOccurs="1" minOccurs="0" name="{$fldName}" nillable="true" type="xs:integer"/>
  167. $pKeyField = 'ID';//$storageObject->getPrimaryKeyFieldName();
  168. //DBG::_(true, true, "struct", $struct, __CLASS__, __FUNCTION__, __LINE__);
  169. foreach ($struct as $field) {
  170. $fldName = $vField->getName();
  171. $fldType = $vField->getType();
  172. $xsdType = $fldType->getTypeForXsd();
  173. if ($fldType->hasDefault()) {
  174. $fldDefault = $fldType->getDefault();
  175. if (!empty($fldDefault) || '0' === $fldDefault) {
  176. $elNode->setAttribute('default', $fldDefault);
  177. }
  178. }
  179. $fldRestrictions = $fldType->getRestrictions();
  180. if (empty($fldRestrictions)) {
  181. $elNode->setAttribute('type', "{$p5TypePrefix}:{$xsdType}");
  182. } else {
  183. $sType = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xs:simpleType');
  184. $elNode->appendChild($sType);
  185. $sTypeRes = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xs:restriction');
  186. $sType->appendChild($sTypeRes);
  187. $sTypeRes->setAttribute('base', "{$p5TypePrefix}:{$xsdType}");
  188. $enumList = $fldType->getEnumeration();
  189. if (empty($enumList)) {
  190. foreach ($fldRestrictions as $restricionName => $restrictionValue) {
  191. if ('maxLength' == $restricionName) {
  192. $sTypeResMaxLength = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xs:maxLength');
  193. $sTypeRes->appendChild($sTypeResMaxLength);
  194. $sTypeResMaxLength->setAttribute('value', $restrictionValue);
  195. } else if ('minLength' == $restricionName) {
  196. $sTypeResMinLength = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xs:minLength');
  197. $sTypeRes->appendChild($sTypeResMinLength);
  198. $sTypeResMinLength->setAttribute('value', $restrictionValue);
  199. } else if ('pattern' == $restricionName) {
  200. $sTypeResPattern = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xs:pattern');
  201. $sTypeRes->appendChild($sTypeResPattern);
  202. $sTypeResPattern->setAttribute('value', $restrictionValue);
  203. } else if ('fractionDigits' == $restricionName) {
  204. $sTypeResFractionDigits = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xs:fractionDigits');
  205. $sTypeRes->appendChild($sTypeResFractionDigits);
  206. $sTypeResFractionDigits->setAttribute('value', $restrictionValue);
  207. } else if ('totalDigits' == $restricionName) {
  208. $sTypeResTotalDigits = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xs:totalDigits');
  209. $sTypeRes->appendChild($sTypeResTotalDigits);
  210. $sTypeResTotalDigits->setAttribute('value', $restrictionValue);
  211. } else if ('maxExclusive' == $restricionName) {
  212. $sTypeResMaxExclusive = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xs:maxExclusive');
  213. $sTypeRes->appendChild($sTypeResMaxExclusive);
  214. $sTypeResMaxExclusive->setAttribute('value', $restrictionValue);
  215. } else if ('minExclusive' == $restricionName) {
  216. $sTypeResMinExclusive = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xs:minExclusive');
  217. $sTypeRes->appendChild($sTypeResMinExclusive);
  218. $sTypeResMinExclusive->setAttribute('value', $restrictionValue);
  219. } else if ('maxInclusive' == $restricionName) {
  220. $sTypeResMaxInclusive = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xs:maxInclusive');
  221. $sTypeRes->appendChild($sTypeResMaxInclusive);
  222. $sTypeResMaxInclusive->setAttribute('value', $restrictionValue);
  223. } else if ('minInclusive' == $restricionName) {
  224. $sTypeResMinInclusive = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xs:minInclusive');
  225. $sTypeRes->appendChild($sTypeResMinInclusive);
  226. $sTypeResMinInclusive->setAttribute('value', $restrictionValue);
  227. }
  228. /* TODO: xsd restrictions:
  229. enumeration Defines a list of acceptable values
  230. fractionDigits Specifies the maximum number of decimal places allowed. Must be equal to or greater than zero
  231. length Specifies the exact number of characters or list items allowed. Must be equal to or greater than zero
  232. maxExclusive Specifies the upper bounds for numeric values (the value must be less than this value)
  233. maxInclusive Specifies the upper bounds for numeric values (the value must be less than or equal to this value)
  234. maxLength Specifies the maximum number of characters or list items allowed. Must be equal to or greater than zero
  235. minExclusive Specifies the lower bounds for numeric values (the value must be greater than this value)
  236. minInclusive Specifies the lower bounds for numeric values (the value must be greater than or equal to this value)
  237. minLength Specifies the minimum number of characters or list items allowed. Must be equal to or greater than zero
  238. pattern Defines the exact sequence of characters that are acceptable
  239. totalDigits Specifies the exact number of digits allowed. Must be greater than zero
  240. whiteSpace Specifies how white space (line feeds, tabs, spaces, and carriage returns) is handled
  241. */
  242. }
  243. } else {
  244. foreach ($enumList as $enumValue) {
  245. $sTypeResEnum = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xs:enumeration');
  246. $sTypeRes->appendChild($sTypeResEnum);
  247. $sTypeResEnum->setAttribute('value', $enumValue);
  248. }
  249. }
  250. }
  251. }
  252. $elNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xs:element');
  253. $rootNode->appendChild($elNode);
  254. $elNode->setAttribute('name', $tblName);
  255. $elNode->setAttribute('type', "{$objNs}:{$typeName}");
  256. header('Content-type: application/xml');
  257. echo $dom->saveXML();
  258. exit;
  259. }
  260. }