TestXsd.php 14 KB

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