diff --git a/mixin/lib/civimix-schema@5.80.2/src/SchemaHelper.php b/mixin/lib/civimix-schema@5.80.2/src/SchemaHelper.php deleted file mode 100644 index 8963ed3..0000000 --- a/mixin/lib/civimix-schema@5.80.2/src/SchemaHelper.php +++ /dev/null @@ -1,87 +0,0 @@ -key = $key; - } - - public function install(): void { - $this->runSqls([$this->generateInstallSql()]); - } - - public function uninstall(): void { - $this->runSqls([$this->generateUninstallSql()]); - } - - public function generateInstallSql(): ?string { - return $this->getSqlGenerator()->getCreateTablesSql(); - } - - public function generateUninstallSql(): string { - return $this->getSqlGenerator()->getDropTablesSql(); - } - - public function hasSchema(): bool { - return file_exists($this->getExtensionDir() . '/schema'); - } - - public function arrayToSql(array $entityDefn): string { - $generator = $this->getSqlGenerator(); - return $generator->generateCreateTableWithConstraintSql($entityDefn); - } - - // FIXME: You can add more utility methods here - - // public function addTables(array $names): void { - // throw new \RuntimeException("TODO: Install a single tables"); - // } - // - // public function addColumn(string $table, string $column): void { - // throw new \RuntimeException("TODO: Install a single tables"); - // } - - /** - * @param array $sqls - * List of SQL scripts. - */ - private function runSqls(array $sqls): void { - foreach ($sqls as $sql) { - \CRM_Utils_File::runSqlQuery(CIVICRM_DSN, $sql); - } - } - - protected function getExtensionDir(): string { - if ($this->key === 'civicrm') { - $r = new \ReflectionClass('CRM_Core_ClassLoader'); - return dirname($r->getFileName(), 3); - } - $system = \CRM_Extension_System::singleton(); - return $system->getMapper()->keyToBasePath($this->key); - } - - private function getSqlGenerator() { - if ($this->sqlGenerator === NULL) { - $gen = require __DIR__ . '/SqlGenerator.php'; - $this->sqlGenerator = $gen::createFromFolder($this->key, $this->getExtensionDir() . '/schema', $this->key === 'civicrm'); - } - return $this->sqlGenerator; - } - -}; diff --git a/mixin/lib/civimix-schema@5.80.2/pathload.main.php b/mixin/lib/civimix-schema@5.85.beta1/pathload.main.php similarity index 100% rename from mixin/lib/civimix-schema@5.80.2/pathload.main.php rename to mixin/lib/civimix-schema@5.85.beta1/pathload.main.php diff --git a/mixin/lib/civimix-schema@5.80.2/src/AutomaticUpgrader.php b/mixin/lib/civimix-schema@5.85.beta1/src/AutomaticUpgrader.php similarity index 100% rename from mixin/lib/civimix-schema@5.80.2/src/AutomaticUpgrader.php rename to mixin/lib/civimix-schema@5.85.beta1/src/AutomaticUpgrader.php diff --git a/mixin/lib/civimix-schema@5.80.2/src/CiviMixSchema.php b/mixin/lib/civimix-schema@5.85.beta1/src/CiviMixSchema.php similarity index 100% rename from mixin/lib/civimix-schema@5.80.2/src/CiviMixSchema.php rename to mixin/lib/civimix-schema@5.85.beta1/src/CiviMixSchema.php diff --git a/mixin/lib/civimix-schema@5.80.2/src/DAO.php b/mixin/lib/civimix-schema@5.85.beta1/src/DAO.php similarity index 100% rename from mixin/lib/civimix-schema@5.80.2/src/DAO.php rename to mixin/lib/civimix-schema@5.85.beta1/src/DAO.php diff --git a/mixin/lib/civimix-schema@5.85.beta1/src/SchemaHelper.php b/mixin/lib/civimix-schema@5.85.beta1/src/SchemaHelper.php new file mode 100644 index 0000000..46dc311 --- /dev/null +++ b/mixin/lib/civimix-schema@5.85.beta1/src/SchemaHelper.php @@ -0,0 +1,138 @@ +key = $key; + } + + public function install(): void { + $this->runSqls([$this->generateInstallSql()]); + } + + public function uninstall(): void { + $this->runSqls([$this->generateUninstallSql()]); + } + + public function generateInstallSql(): ?string { + return $this->getSqlGenerator()->getCreateTablesSql(); + } + + public function generateUninstallSql(): string { + return $this->getSqlGenerator()->getDropTablesSql(); + } + + public function hasSchema(): bool { + return file_exists($this->getExtensionDir() . '/schema'); + } + + /** + * Converts an entity or field definition to SQL statement. + * + * @param array $defn + * The definition array, which can either represent + * an entity with fields or a single database column. + * @return string + * The generated SQL statement, which is either an SQL command + * for creating a table with constraints or for defining a single column. + */ + public function arrayToSql(array $defn): string { + $generator = $this->getSqlGenerator(); + // Entity array: generate entire table + if (isset($defn['getFields'])) { + return $generator->generateCreateTableWithConstraintSql($defn); + } + // Field array: generate single column + else { + return $generator->generateFieldSql($defn); + } + } + + /** + * Create table (if not exists) from a given php schema file. + * + * The original entityType.php file should be copied to a directory (e.g. `my_extension/upgrade/schema`) + * and prefixed with the version-added. + * + * @param string $filePath + * Relative path to copied schema file (relative to extension directory). + * @return bool + * @throws \CRM_Core_Exception + */ + public function createEntityTable(string $filePath): bool { + $absolutePath = $this->getExtensionDir() . DIRECTORY_SEPARATOR . $filePath; + $entityDefn = include $absolutePath; + $sql = $this->arrayToSql($entityDefn); + \CRM_Core_DAO::executeQuery($sql, [], TRUE, NULL, FALSE, FALSE); + return TRUE; + } + + /** + * Task to add or change a column definition, based on the php schema spec. + * + * @param string $entityName + * @param string $fieldName + * @param array $fieldSpec + * As definied in the .entityType.php file for $entityName + * @return bool + * @throws \CRM_Core_Exception + */ + public function alterSchemaField(string $entityName, string $fieldName, array $fieldSpec): bool { + $tableName = method_exists('Civi', 'entity') + ? \Civi::entity($entityName)->getMeta('table') + : \CRM_Core_DAO_AllCoreTables::getTableForEntityName($entityName); + $fieldSql = $this->arrayToSql($fieldSpec); + if (\CRM_Core_BAO_SchemaHandler::checkIfFieldExists($tableName, $fieldName, FALSE)) { + $query = "ALTER TABLE `$tableName` CHANGE `$fieldName` `$fieldName` $fieldSql"; + } + else { + $query = "ALTER TABLE `$tableName` ADD COLUMN `$fieldName` $fieldSql"; + } + \CRM_Core_DAO::executeQuery($query, [], TRUE, NULL, FALSE, FALSE); + return TRUE; + } + + /** + * @param array $sqls + * List of SQL scripts. + */ + private function runSqls(array $sqls): void { + foreach ($sqls as $sql) { + \CRM_Utils_File::runSqlQuery(CIVICRM_DSN, $sql); + } + } + + protected function getExtensionDir(): string { + if ($this->key === 'civicrm') { + $r = new \ReflectionClass('CRM_Core_ClassLoader'); + return dirname($r->getFileName(), 3); + } + $system = \CRM_Extension_System::singleton(); + return $system->getMapper()->keyToBasePath($this->key); + } + + private function getSqlGenerator() { + if ($this->sqlGenerator === NULL) { + $gen = require __DIR__ . '/SqlGenerator.php'; + $this->sqlGenerator = $gen::createFromFolder($this->key, $this->getExtensionDir() . '/schema', $this->key === 'civicrm'); + } + return $this->sqlGenerator; + } + +}; diff --git a/mixin/lib/civimix-schema@5.80.2/src/SchemaHelperInterface.php b/mixin/lib/civimix-schema@5.85.beta1/src/SchemaHelperInterface.php similarity index 64% rename from mixin/lib/civimix-schema@5.80.2/src/SchemaHelperInterface.php rename to mixin/lib/civimix-schema@5.85.beta1/src/SchemaHelperInterface.php index e915a80..d14b91c 100644 --- a/mixin/lib/civimix-schema@5.80.2/src/SchemaHelperInterface.php +++ b/mixin/lib/civimix-schema@5.85.beta1/src/SchemaHelperInterface.php @@ -10,16 +10,22 @@ * newer revisions of the library can be loaded, the implementation is an anonymous-class, * and the interface uses soft type-hints. * - * @method bool hasSchema() + * [[ CiviCRM 5.74+ / civimix-schema@5.74+ ]] * + * @method bool hasSchema() * @method void install() * @method void uninstall() - * * @method string generateInstallSql() * @method string generateUninstallSql() * - * TODO: void addTables(string[] $tables) - * TODO: void addColumn(string $table, string $column) + * [[ CiviCRM 5.76+ / civimix-schema@5.76+ ]] + * + * @method string arrayToSql(array $defn) Converts an entity or field definition to SQL statement. + * + * [[ CiviCRM 6.2+ / civimix-schema@5.85+ ]] + * + * @method bool createEntityTable(string $filePath) + * @method bool alterSchemaField(string $entityName, string $fieldName, array $fieldSpec) * * To see the latest implementation: * diff --git a/mixin/lib/civimix-schema@5.80.2/src/SqlGenerator.php b/mixin/lib/civimix-schema@5.85.beta1/src/SqlGenerator.php similarity index 97% rename from mixin/lib/civimix-schema@5.80.2/src/SqlGenerator.php rename to mixin/lib/civimix-schema@5.85.beta1/src/SqlGenerator.php index 8413348..e720aa9 100644 --- a/mixin/lib/civimix-schema@5.80.2/src/SqlGenerator.php +++ b/mixin/lib/civimix-schema@5.85.beta1/src/SqlGenerator.php @@ -145,7 +145,8 @@ private function getTableConstraints(array $entity): array { $constraints = []; foreach ($entity['getFields']() as $fieldName => $field) { if (!empty($field['entity_reference']['entity'])) { - $constraint = "CONSTRAINT `FK_{$entity['table']}_$fieldName` FOREIGN KEY (`$fieldName`)" . + $fkName = \CRM_Core_BAO_SchemaHandler::getIndexName($entity['table'], $fieldName); + $constraint = "CONSTRAINT `FK_$fkName` FOREIGN KEY (`$fieldName`)" . " REFERENCES `" . $this->getTableForEntity($field['entity_reference']['entity']) . "`(`{$field['entity_reference']['key']}`)"; if (!empty($field['entity_reference']['on_delete'])) { $constraint .= " ON DELETE {$field['entity_reference']['on_delete']}"; @@ -156,7 +157,7 @@ private function getTableConstraints(array $entity): array { return $constraints; } - public static function generateFieldSql(array $field) { + public static function generateFieldSql(array $field): string { $fieldSql = $field['sql_type']; if (!empty($field['collate'])) { $fieldSql .= " COLLATE {$field['collate']}";