'NHibernate C# DO', self::HANDLER_NHIBERNATE_XML => 'NHibernate XML', ]; private const HANDLER_NHIBERNATE_CS = 0; private const HANDLER_NHIBERNATE_XML = 1; /** @var self::HANDLER_NHIBERNATE_* */ private int $format = self::HANDLER_NHIBERNATE_CS; /** @psalm-return non-empty-lowercase-string */ public function getName(): string { return 'codegen'; } protected function setProperties(): ExportPluginProperties { $exportPluginProperties = new ExportPluginProperties(); $exportPluginProperties->setText('CodeGen'); $exportPluginProperties->setExtension('cs'); $exportPluginProperties->setMimeType('text/cs'); // create the root group that will be the options field for // $exportPluginProperties // this will be shown as "Format specific options" $exportSpecificOptions = new OptionsPropertyRootGroup('Format Specific Options'); // general options main group $generalOptions = new OptionsPropertyMainGroup('codegen_general_opts'); // create primary items and add them to the group $leaf = new HiddenPropertyItem('codegen_structure_or_data'); $generalOptions->addProperty($leaf); $leaf = new SelectPropertyItem( 'codegen_format', __('Format:'), ); $leaf->setValues(self::CODEGEN_FORMATS); $generalOptions->addProperty($leaf); // add the main group to the root group $exportSpecificOptions->addProperty($generalOptions); // set the options for the export plugin property item $exportPluginProperties->setOptions($exportSpecificOptions); return $exportPluginProperties; } /** * Outputs the content of a table in NHibernate format * * @param string $db database name * @param string $table table name * @param string $sqlQuery SQL query for obtaining data * @param mixed[] $aliases Aliases of db/table/columns */ public function exportData( string $db, string $table, string $sqlQuery, array $aliases = [], ): void { if ($this->format === self::HANDLER_NHIBERNATE_XML) { $this->outputHandler->addLine($this->handleNHibernateXMLBody($db, $table, $aliases)); return; } $this->outputHandler->addLine($this->handleNHibernateCSBody($db, $table, $aliases)); } /** * Used to make identifiers (from table or database names) * * @param string $str name to be converted * @param bool $ucfirst whether to make the first character uppercase * * @return string identifier */ public static function cgMakeIdentifier(string $str, bool $ucfirst = true): string { // remove unsafe characters $str = (string) preg_replace('/[^\p{L}\p{Nl}_]/u', '', $str); // make sure first character is a letter or _ if (preg_match('/^\pL/u', $str) !== 1) { $str = '_' . $str; } if ($ucfirst) { return ucfirst($str); } return $str; } /** * C# Handler * * @param string $db database name * @param string $table table name * @param mixed[] $aliases Aliases of db/table/columns * * @return string containing C# code lines, separated by "\n" */ private function handleNHibernateCSBody(string $db, string $table, array $aliases = []): string { $dbAlias = $this->getDbAlias($aliases, $db); $tableAlias = $this->getTableAlias($aliases, $db, $table); $result = $this->dbi->query(sprintf('DESC %s.%s', Util::backquote($db), Util::backquote($table))); /** @var TableProperty[] $tableProperties */ $tableProperties = []; while ($row = $result->fetchRow()) { $row[0] = $this->getColumnAlias($aliases, $db, $table, $row[0]); $tableProperties[] = new TableProperty($row); } unset($result); $lines = []; $lines[] = 'using System;'; $lines[] = 'using System.Collections;'; $lines[] = 'using System.Collections.Generic;'; $lines[] = 'using System.Text;'; $lines[] = 'namespace ' . self::cgMakeIdentifier($dbAlias); $lines[] = '{'; $lines[] = ' #region ' . self::cgMakeIdentifier($tableAlias); $lines[] = ' public class ' . self::cgMakeIdentifier($tableAlias); $lines[] = ' {'; $lines[] = ' #region Member Variables'; foreach ($tableProperties as $tableProperty) { $lines[] = $tableProperty->formatCs(' protected #dotNetPrimitiveType# _#name#;'); } $lines[] = ' #endregion'; $lines[] = ' #region Constructors'; $lines[] = ' public ' . self::cgMakeIdentifier($tableAlias) . '() { }'; $temp = []; foreach ($tableProperties as $tableProperty) { if ($tableProperty->isPK()) { continue; } $temp[] = $tableProperty->formatCs('#dotNetPrimitiveType# #name#'); } $lines[] = ' public ' . self::cgMakeIdentifier($tableAlias) . '(' . implode(', ', $temp) . ')'; $lines[] = ' {'; foreach ($tableProperties as $tableProperty) { if ($tableProperty->isPK()) { continue; } $lines[] = $tableProperty->formatCs(' this._#name#=#name#;'); } $lines[] = ' }'; $lines[] = ' #endregion'; $lines[] = ' #region Public Properties'; foreach ($tableProperties as $tableProperty) { $lines[] = $tableProperty->formatCs( ' public virtual #dotNetPrimitiveType# #ucfirstName#' . "\n" . ' {' . "\n" . ' get {return _#name#;}' . "\n" . ' set {_#name#=value;}' . "\n" . ' }', ); } $lines[] = ' #endregion'; $lines[] = ' }'; $lines[] = ' #endregion'; $lines[] = '}'; return implode("\n", $lines); } /** * XML Handler * * @param string $db database name * @param string $table table name * @param mixed[] $aliases Aliases of db/table/columns * * @return string containing XML code lines, separated by "\n" */ private function handleNHibernateXMLBody( string $db, string $table, array $aliases = [], ): string { $dbAlias = $this->getDbAlias($aliases, $db); $tableAlias = $this->getTableAlias($aliases, $db, $table); $lines = []; $lines[] = ''; $lines[] = ''; $lines[] = ' '; $result = $this->dbi->query(sprintf('DESC %s.%s', Util::backquote($db), Util::backquote($table))); while ($row = $result->fetchRow()) { $row[0] = $this->getColumnAlias($aliases, $db, $table, $row[0]); $tableProperty = new TableProperty($row); if ($tableProperty->isPK()) { $lines[] = $tableProperty->formatXml( ' ' . "\n" . ' ' . "\n" . ' ' . "\n" . ' ', ); } else { $lines[] = $tableProperty->formatXml( ' ' . "\n" . ' ' . "\n" . ' ', ); } } $lines[] = ' '; $lines[] = ''; return implode("\n", $lines); } public function setExportOptions(ServerRequest $request, Export $exportConfig): void { // phpcs:disable Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps $this->structureOrData = $this->setStructureOrData( $request->getParsedBodyParam('codegen_structure_or_data'), $exportConfig->codegen_structure_or_data, StructureOrData::Data, ); $this->format = $this->setFormat( $request->getParsedBodyParam('codegen_format'), $exportConfig->codegen_format, ); // phpcs:enable Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps } /** @return self::HANDLER_NHIBERNATE_* */ private function setFormat(mixed $fromRequest, mixed $fromConfig): int { $value = self::HANDLER_NHIBERNATE_CS; if (is_numeric($fromRequest)) { $value = (int) $fromRequest; } elseif (is_numeric($fromConfig)) { $value = (int) $fromConfig; } return $value === self::HANDLER_NHIBERNATE_XML ? self::HANDLER_NHIBERNATE_XML : self::HANDLER_NHIBERNATE_CS; } }