TestXsd.php 13 KB

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