ExportCodegen.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * Set of functions used to build NHibernate dumps of tables
  5. *
  6. * @package PhpMyAdmin-Export
  7. * @subpackage CodeGen
  8. */
  9. declare(strict_types=1);
  10. namespace PhpMyAdmin\Plugins\Export;
  11. use PhpMyAdmin\Export;
  12. use PhpMyAdmin\Plugins\Export\Helpers\TableProperty;
  13. use PhpMyAdmin\Plugins\ExportPlugin;
  14. use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyMainGroup;
  15. use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyRootGroup;
  16. use PhpMyAdmin\Properties\Options\Items\HiddenPropertyItem;
  17. use PhpMyAdmin\Properties\Options\Items\SelectPropertyItem;
  18. use PhpMyAdmin\Properties\Plugins\ExportPluginProperties;
  19. use PhpMyAdmin\Util;
  20. /**
  21. * Handles the export for the CodeGen class
  22. *
  23. * @package PhpMyAdmin-Export
  24. * @subpackage CodeGen
  25. */
  26. class ExportCodegen extends ExportPlugin
  27. {
  28. /**
  29. * CodeGen Formats
  30. *
  31. * @var array
  32. */
  33. private $_cgFormats;
  34. /**
  35. * CodeGen Handlers
  36. *
  37. * @var array
  38. */
  39. private $_cgHandlers;
  40. /**
  41. * Constructor
  42. */
  43. public function __construct()
  44. {
  45. parent::__construct();
  46. // initialize the specific export CodeGen variables
  47. $this->initSpecificVariables();
  48. $this->setProperties();
  49. }
  50. /**
  51. * Initialize the local variables that are used for export CodeGen
  52. *
  53. * @return void
  54. */
  55. protected function initSpecificVariables()
  56. {
  57. $this->_setCgFormats(
  58. [
  59. "NHibernate C# DO",
  60. "NHibernate XML",
  61. ]
  62. );
  63. $this->_setCgHandlers(
  64. [
  65. "_handleNHibernateCSBody",
  66. "_handleNHibernateXMLBody",
  67. ]
  68. );
  69. }
  70. /**
  71. * Sets the export CodeGen properties
  72. *
  73. * @return void
  74. */
  75. protected function setProperties()
  76. {
  77. $exportPluginProperties = new ExportPluginProperties();
  78. $exportPluginProperties->setText('CodeGen');
  79. $exportPluginProperties->setExtension('cs');
  80. $exportPluginProperties->setMimeType('text/cs');
  81. $exportPluginProperties->setOptionsText(__('Options'));
  82. // create the root group that will be the options field for
  83. // $exportPluginProperties
  84. // this will be shown as "Format specific options"
  85. $exportSpecificOptions = new OptionsPropertyRootGroup(
  86. "Format Specific Options"
  87. );
  88. // general options main group
  89. $generalOptions = new OptionsPropertyMainGroup("general_opts");
  90. // create primary items and add them to the group
  91. $leaf = new HiddenPropertyItem("structure_or_data");
  92. $generalOptions->addProperty($leaf);
  93. $leaf = new SelectPropertyItem(
  94. "format",
  95. __('Format:')
  96. );
  97. $leaf->setValues($this->_getCgFormats());
  98. $generalOptions->addProperty($leaf);
  99. // add the main group to the root group
  100. $exportSpecificOptions->addProperty($generalOptions);
  101. // set the options for the export plugin property item
  102. $exportPluginProperties->setOptions($exportSpecificOptions);
  103. $this->properties = $exportPluginProperties;
  104. }
  105. /**
  106. * Outputs export header
  107. *
  108. * @return bool Whether it succeeded
  109. */
  110. public function exportHeader()
  111. {
  112. return true;
  113. }
  114. /**
  115. * Outputs export footer
  116. *
  117. * @return bool Whether it succeeded
  118. */
  119. public function exportFooter()
  120. {
  121. return true;
  122. }
  123. /**
  124. * Outputs database header
  125. *
  126. * @param string $db Database name
  127. * @param string $db_alias Aliases of db
  128. *
  129. * @return bool Whether it succeeded
  130. */
  131. public function exportDBHeader($db, $db_alias = '')
  132. {
  133. return true;
  134. }
  135. /**
  136. * Outputs database footer
  137. *
  138. * @param string $db Database name
  139. *
  140. * @return bool Whether it succeeded
  141. */
  142. public function exportDBFooter($db)
  143. {
  144. return true;
  145. }
  146. /**
  147. * Outputs CREATE DATABASE statement
  148. *
  149. * @param string $db Database name
  150. * @param string $export_type 'server', 'database', 'table'
  151. * @param string $db_alias Aliases of db
  152. *
  153. * @return bool Whether it succeeded
  154. */
  155. public function exportDBCreate($db, $export_type, $db_alias = '')
  156. {
  157. return true;
  158. }
  159. /**
  160. * Outputs the content of a table in NHibernate format
  161. *
  162. * @param string $db database name
  163. * @param string $table table name
  164. * @param string $crlf the end of line sequence
  165. * @param string $error_url the url to go back in case of error
  166. * @param string $sql_query SQL query for obtaining data
  167. * @param array $aliases Aliases of db/table/columns
  168. *
  169. * @return bool Whether it succeeded
  170. */
  171. public function exportData(
  172. $db,
  173. $table,
  174. $crlf,
  175. $error_url,
  176. $sql_query,
  177. array $aliases = []
  178. ) {
  179. $CG_FORMATS = $this->_getCgFormats();
  180. $CG_HANDLERS = $this->_getCgHandlers();
  181. $format = $GLOBALS['codegen_format'];
  182. if (isset($CG_FORMATS[$format])) {
  183. $method = $CG_HANDLERS[$format];
  184. return $this->export->outputHandler(
  185. $this->$method($db, $table, $crlf, $aliases)
  186. );
  187. }
  188. return $this->export->outputHandler(sprintf("%s is not supported.", $format));
  189. }
  190. /**
  191. * Used to make identifiers (from table or database names)
  192. *
  193. * @param string $str name to be converted
  194. * @param bool $ucfirst whether to make the first character uppercase
  195. *
  196. * @return string identifier
  197. */
  198. public static function cgMakeIdentifier($str, $ucfirst = true)
  199. {
  200. // remove unsafe characters
  201. $str = preg_replace('/[^\p{L}\p{Nl}_]/u', '', $str);
  202. // make sure first character is a letter or _
  203. if (! preg_match('/^\pL/u', $str)) {
  204. $str = '_' . $str;
  205. }
  206. if ($ucfirst) {
  207. $str = ucfirst($str);
  208. }
  209. return $str;
  210. }
  211. /**
  212. * C# Handler
  213. *
  214. * @param string $db database name
  215. * @param string $table table name
  216. * @param string $crlf line separator
  217. * @param array $aliases Aliases of db/table/columns
  218. *
  219. * @return string containing C# code lines, separated by "\n"
  220. */
  221. private function _handleNHibernateCSBody($db, $table, $crlf, array $aliases = [])
  222. {
  223. $db_alias = $db;
  224. $table_alias = $table;
  225. $this->initAlias($aliases, $db_alias, $table_alias);
  226. $lines = [];
  227. $result = $GLOBALS['dbi']->query(
  228. sprintf(
  229. 'DESC %s.%s',
  230. Util::backquote($db),
  231. Util::backquote($table)
  232. )
  233. );
  234. if ($result) {
  235. /** @var TableProperty[] $tableProperties */
  236. $tableProperties = [];
  237. while ($row = $GLOBALS['dbi']->fetchRow($result)) {
  238. $col_as = $this->getAlias($aliases, $row[0], 'col', $db, $table);
  239. if (! empty($col_as)) {
  240. $row[0] = $col_as;
  241. }
  242. $tableProperties[] = new TableProperty($row);
  243. }
  244. $GLOBALS['dbi']->freeResult($result);
  245. $lines[] = 'using System;';
  246. $lines[] = 'using System.Collections;';
  247. $lines[] = 'using System.Collections.Generic;';
  248. $lines[] = 'using System.Text;';
  249. $lines[] = 'namespace ' . ExportCodegen::cgMakeIdentifier($db_alias);
  250. $lines[] = '{';
  251. $lines[] = ' #region '
  252. . ExportCodegen::cgMakeIdentifier($table_alias);
  253. $lines[] = ' public class '
  254. . ExportCodegen::cgMakeIdentifier($table_alias);
  255. $lines[] = ' {';
  256. $lines[] = ' #region Member Variables';
  257. foreach ($tableProperties as $tableProperty) {
  258. $lines[] = $tableProperty->formatCs(
  259. ' protected #dotNetPrimitiveType# _#name#;'
  260. );
  261. }
  262. $lines[] = ' #endregion';
  263. $lines[] = ' #region Constructors';
  264. $lines[] = ' public '
  265. . ExportCodegen::cgMakeIdentifier($table_alias) . '() { }';
  266. $temp = [];
  267. foreach ($tableProperties as $tableProperty) {
  268. if (! $tableProperty->isPK()) {
  269. $temp[] = $tableProperty->formatCs(
  270. '#dotNetPrimitiveType# #name#'
  271. );
  272. }
  273. }
  274. $lines[] = ' public '
  275. . ExportCodegen::cgMakeIdentifier($table_alias)
  276. . '('
  277. . implode(', ', $temp)
  278. . ')';
  279. $lines[] = ' {';
  280. foreach ($tableProperties as $tableProperty) {
  281. if (! $tableProperty->isPK()) {
  282. $lines[] = $tableProperty->formatCs(
  283. ' this._#name#=#name#;'
  284. );
  285. }
  286. }
  287. $lines[] = ' }';
  288. $lines[] = ' #endregion';
  289. $lines[] = ' #region Public Properties';
  290. foreach ($tableProperties as $tableProperty) {
  291. $lines[] = $tableProperty->formatCs(
  292. ' public virtual #dotNetPrimitiveType# #ucfirstName#'
  293. . "\n"
  294. . ' {' . "\n"
  295. . ' get {return _#name#;}' . "\n"
  296. . ' set {_#name#=value;}' . "\n"
  297. . ' }'
  298. );
  299. }
  300. $lines[] = ' #endregion';
  301. $lines[] = ' }';
  302. $lines[] = ' #endregion';
  303. $lines[] = '}';
  304. }
  305. return implode($crlf, $lines);
  306. }
  307. /**
  308. * XML Handler
  309. *
  310. * @param string $db database name
  311. * @param string $table table name
  312. * @param string $crlf line separator
  313. * @param array $aliases Aliases of db/table/columns
  314. *
  315. * @return string containing XML code lines, separated by "\n"
  316. */
  317. private function _handleNHibernateXMLBody(
  318. $db,
  319. $table,
  320. $crlf,
  321. array $aliases = []
  322. ) {
  323. $db_alias = $db;
  324. $table_alias = $table;
  325. $this->initAlias($aliases, $db_alias, $table_alias);
  326. $lines = [];
  327. $lines[] = '<?xml version="1.0" encoding="utf-8" ?' . '>';
  328. $lines[] = '<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" '
  329. . 'namespace="' . ExportCodegen::cgMakeIdentifier($db_alias) . '" '
  330. . 'assembly="' . ExportCodegen::cgMakeIdentifier($db_alias) . '">';
  331. $lines[] = ' <class '
  332. . 'name="' . ExportCodegen::cgMakeIdentifier($table_alias) . '" '
  333. . 'table="' . ExportCodegen::cgMakeIdentifier($table_alias) . '">';
  334. $result = $GLOBALS['dbi']->query(
  335. sprintf(
  336. "DESC %s.%s",
  337. Util::backquote($db),
  338. Util::backquote($table)
  339. )
  340. );
  341. if ($result) {
  342. while ($row = $GLOBALS['dbi']->fetchRow($result)) {
  343. $col_as = $this->getAlias($aliases, $row[0], 'col', $db, $table);
  344. if (! empty($col_as)) {
  345. $row[0] = $col_as;
  346. }
  347. $tableProperty = new TableProperty($row);
  348. if ($tableProperty->isPK()) {
  349. $lines[] = $tableProperty->formatXml(
  350. ' <id name="#ucfirstName#" type="#dotNetObjectType#"'
  351. . ' unsaved-value="0">' . "\n"
  352. . ' <column name="#name#" sql-type="#type#"'
  353. . ' not-null="#notNull#" unique="#unique#"'
  354. . ' index="PRIMARY"/>' . "\n"
  355. . ' <generator class="native" />' . "\n"
  356. . ' </id>'
  357. );
  358. } else {
  359. $lines[] = $tableProperty->formatXml(
  360. ' <property name="#ucfirstName#"'
  361. . ' type="#dotNetObjectType#">' . "\n"
  362. . ' <column name="#name#" sql-type="#type#"'
  363. . ' not-null="#notNull#" #indexName#/>' . "\n"
  364. . ' </property>'
  365. );
  366. }
  367. }
  368. $GLOBALS['dbi']->freeResult($result);
  369. }
  370. $lines[] = ' </class>';
  371. $lines[] = '</hibernate-mapping>';
  372. return implode($crlf, $lines);
  373. }
  374. /* ~~~~~~~~~~~~~~~~~~~~ Getters and Setters ~~~~~~~~~~~~~~~~~~~~ */
  375. /**
  376. * Getter for CodeGen formats
  377. *
  378. * @return array
  379. */
  380. private function _getCgFormats()
  381. {
  382. return $this->_cgFormats;
  383. }
  384. /**
  385. * Setter for CodeGen formats
  386. *
  387. * @param array $CG_FORMATS contains CodeGen Formats
  388. *
  389. * @return void
  390. */
  391. private function _setCgFormats(array $CG_FORMATS)
  392. {
  393. $this->_cgFormats = $CG_FORMATS;
  394. }
  395. /**
  396. * Getter for CodeGen handlers
  397. *
  398. * @return array
  399. */
  400. private function _getCgHandlers()
  401. {
  402. return $this->_cgHandlers;
  403. }
  404. /**
  405. * Setter for CodeGen handlers
  406. *
  407. * @param array $CG_HANDLERS contains CodeGen handler methods
  408. *
  409. * @return void
  410. */
  411. private function _setCgHandlers(array $CG_HANDLERS)
  412. {
  413. $this->_cgHandlers = $CG_HANDLERS;
  414. }
  415. }