Skip to content

Commit

Permalink
Merge pull request #29472 from colemanw/schemaEntity
Browse files Browse the repository at this point in the history
Convert xml schema to new entityType.php format
  • Loading branch information
colemanw authored Apr 19, 2024
2 parents 439fc04 + 12788a9 commit 07e57e8
Show file tree
Hide file tree
Showing 186 changed files with 27,841 additions and 103 deletions.
4 changes: 3 additions & 1 deletion CRM/Core/BAO/SchemaHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
*/
class CRM_Core_BAO_SchemaHandler {

const DEFAULT_COLLATION = 'utf8mb4_unicode_ci';

/**
* Create a CiviCRM-table
*
Expand Down Expand Up @@ -899,7 +901,7 @@ public static function getInUseCollation(): string {
if (!isset(\Civi::$statics[__CLASS__][__FUNCTION__])) {
$dao = CRM_Core_DAO::executeQuery('SHOW TABLE STATUS LIKE \'civicrm_contact\'');
$dao->fetch();
\Civi::$statics[__CLASS__][__FUNCTION__] = $dao->Collation;
\Civi::$statics[__CLASS__][__FUNCTION__] = $dao->Collation ?? self::DEFAULT_COLLATION;
}
return \Civi::$statics[__CLASS__][__FUNCTION__];
}
Expand Down
263 changes: 263 additions & 0 deletions CRM/Core/CRM/Core/DAO/Base.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,263 @@
<?php
/*
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC. All rights reserved. |
| |
| This work is published under the GNU AGPLv3 license with some |
| permitted exceptions and without any warranty. For full license |
| and copyright information, see https://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/

/**
* Base for concrete DAO/BAO classes which are defined with a schema/entityType.php file.
*/
abstract class CRM_Core_DAO_Base extends CRM_Core_DAO {

/**
* @inheritDoc
*/
public function keys(): array {
$keys = [];
foreach (static::getEntityDefinition()['getFields']() as $name => $field) {
if (!empty($field['primary_key'])) {
$keys[] = $name;
}
}
return $keys;
}

public static function getEntityTitle($plural = FALSE) {
$info = static::getEntityInfo();
return ($plural && isset($info['title_plural'])) ? $info['title_plural'] : $info['title'];
}

/**
* @inheritDoc
*/
public static function getEntityPaths(): array {
$definition = static::getEntityDefinition();
if (isset($definition['getPaths'])) {
return $definition['getPaths']();
}
return [];
}

/**
* @inheritDoc
*/
public static function getEntityDescription(): ?string {
return static::getEntityInfo()['description'] ?? NULL;
}

/**
* @inheritDoc
*/
public static function getTableName() {
return static::getEntityDefinition()['table'];
}

/**
* @inheritDoc
*/
public function getLog(): bool {
return static::getEntityInfo()['log'] ?? FALSE;
}

/**
* @inheritDoc
*/
public static function getEntityIcon(string $entityName, int $entityId = NULL): ?string {
return static::getEntityInfo()['icon'] ?? NULL;
}

/**
* @inheritDoc
*/
protected static function getTableAddVersion(): string {
return static::getEntityInfo()['add'] ?? '1.0';
}

/**
* @inheritDoc
*/
public static function getExtensionName(): ?string {
return static::getEntityDefinition()['module'];
}

/**
* @inheritDoc
*/
public static function &fields() {
$fields = [];
foreach (static::getSchemaFields() as $field) {
$key = $field['uniqueName'] ?? $field['name'];
unset($field['uniqueName']);
$fields[$key] = $field;
}
return $fields;
}

private static function getSchemaFields(): array {
return (Civi::$statics[static::class]['fields'] ??= static::loadSchemaFields());
}

private static function loadSchemaFields(): array {
$fields = [];
$entityDef = static::getEntityDefinition();
$baoName = CRM_Core_DAO_AllCoreTables::getBAOClassName(static::class);

foreach ($entityDef['getFields']() as $fieldName => $fieldSpec) {
$field = [
'name' => $fieldName,
'type' => !empty($fieldSpec['data_type']) ? \CRM_Utils_Type::getValidTypes()[$fieldSpec['data_type']] : constant(\CRM_Utils_Schema::getCrmTypeFromSqlType($fieldSpec['sql_type'])),
'title' => $fieldSpec['title'],
'description' => $fieldSpec['description'] ?? NULL,
];
if (!empty($fieldSpec['required'])) {
$field['required'] = TRUE;
}
if (str_starts_with($fieldSpec['sql_type'], 'decimal(')) {
$precision = self::getFieldLength($fieldSpec['sql_type']);
$field['precision'] = explode(',', $precision);
}
foreach (['maxlength', 'size', 'rows', 'cols'] as $attr) {
if (isset($fieldSpec['input_attrs'][$attr])) {
$field[$attr] = $fieldSpec['input_attrs'][$attr];
unset($fieldSpec['input_attrs'][$attr]);
}
}
if (!isset($field['size']) && str_contains($fieldSpec['sql_type'], 'char')) {
$length = self::getFieldLength($fieldSpec['sql_type']);
$field['size'] = constant(CRM_Utils_Schema::getDefaultSize($length));
}
$usage = $fieldSpec['usage'] ?? [];
$field['usage'] = [
'import' => in_array('import', $usage),
'export' => in_array('export', $usage),
'duplicate_matching' => in_array('duplicate_matching', $usage),
'token' => in_array('token', $usage),
];
if ($field['usage']['import']) {
$field['import'] = TRUE;
}
$field['where'] = $entityDef['table'] . '.' . $field['name'];
if ($field['usage']['export'] || (!$field['usage']['export'] && $field['usage']['import'])) {
$field['export'] = $field['usage']['export'];
}
if (!empty($fieldSpec['contact_type'])) {
$field['contactType'] = $fieldSpec['contact_type'];
}
if (!empty($fieldSpec['permission'])) {
$field['permission'] = $fieldSpec['permission'];
}
if (array_key_exists('default', $fieldSpec)) {
$field['default'] = isset($fieldSpec['default']) ? (string) $fieldSpec['default'] : NULL;
if (is_bool($fieldSpec['default'])) {
$field['default'] = $fieldSpec['default'] ? '1' : '0';
}
}
$field['table_name'] = $entityDef['table'];
$field['entity'] = $entityDef['name'];
$field['bao'] = $baoName;
$field['localizable'] = intval($fieldSpec['localizable'] ?? 0);
if (!empty($fieldSpec['localize_context'])) {
$field['localize_context'] = (string) $fieldSpec['localize_context'];
}
if (!empty($fieldSpec['entity_reference'])) {
if (!empty($fieldSpec['entity_reference']['entity'])) {
$field['FKClassName'] = CRM_Core_DAO_AllCoreTables::getDAONameForEntity($fieldSpec['entity_reference']['entity']);
}
if (!empty($fieldSpec['entity_reference']['dynamic_entity'])) {
$field['DFKEntityColumn'] = $fieldSpec['entity_reference']['dynamic_entity'];
}
$field['FKColumnName'] = $fieldSpec['entity_reference']['key'] ?? 'id';
}
if (!empty($fieldSpec['component'])) {
$field['component'] = $fieldSpec['component'];
}
if (!empty($fieldSpec['serialize'])) {
$field['serialize'] = $fieldSpec['serialize'];
}
if (!empty($fieldSpec['unique_name'])) {
$field['uniqueName'] = $fieldSpec['unique_name'];
}
if (!empty($fieldSpec['unique_title'])) {
$field['uniqueTitle'] = $fieldSpec['unique_title'];
}
if (!empty($fieldSpec['deprecated'])) {
$field['deprecated'] = TRUE;
}
if (!empty($fieldSpec['input_attrs'])) {
$field['html'] = CRM_Utils_Array::rekey($fieldSpec['input_attrs'], fn($str) => CRM_Utils_String::convertStringToCamel($str, FALSE));
}
if (!empty($fieldSpec['input_type'])) {
$field['html']['type'] = $fieldSpec['input_type'];
}
if (!empty($fieldSpec['pseudoconstant'])) {
$field['pseudoconstant'] = CRM_Utils_Array::rekey($fieldSpec['pseudoconstant'], fn($str) => CRM_Utils_String::convertStringToCamel($str, FALSE));
if (!isset($field['pseudoconstant']['optionEditPath']) && !empty($field['pseudoconstant']['optionGroupName'])) {
$field['pseudoconstant']['optionEditPath'] = 'civicrm/admin/options/' . $field['pseudoconstant']['optionGroupName'];
}
}
if (!empty($fieldSpec['primary_key']) || !empty($field['readonly'])) {
$field['readonly'] = TRUE;
}
$field['add'] = $fieldSpec['add'] ?? NULL;
$fields[$fieldName] = $field;
}
CRM_Core_DAO_AllCoreTables::invoke(static::class, 'fields_callback', $fields);
return $fields;
}

private static function getFieldLength($sqlType): ?string {
$open = strpos($sqlType, '(');
if ($open) {
return substr($sqlType, $open + 1, -1);
}
return NULL;
}

/**
* @inheritDoc
*/
public static function indices(bool $localize = TRUE): array {
$definition = static::getEntityDefinition();
$indices = [];
if (isset($definition['getIndices'])) {
$fields = $definition['getFields']();
foreach ($definition['getIndices']() as $name => $info) {
$index = [
'name' => $name,
'field' => [],
'localizable' => FALSE,
];
foreach ($info['fields'] as $fieldName => $length) {
if (!empty($fields[$fieldName]['localizable'])) {
$index['localizable'] = TRUE;
}
if (is_int($length)) {
$fieldName .= "($length)";
}
$index['field'][] = $fieldName;
}
if (!empty($info['unique'])) {
$index['unique'] = TRUE;
}
$index['sig'] = ($definition['table']) . '::' . intval($info['unique'] ?? 0) . '::' . implode('::', $index['field']);
$indices[$name] = $index;
}
}
return ($localize && $indices) ? CRM_Core_DAO_AllCoreTables::multilingualize(static::class, $indices) : $indices;
}

private static function getEntityDefinition(): array {
$entityName = CRM_Core_DAO_AllCoreTables::getEntityNameForClass(static::class);
return \Civi\Schema\EntityRepository::getEntity($entityName);
}

private static function getEntityInfo(): array {
return static::getEntityDefinition()['getInfo']();
}

}
4 changes: 4 additions & 0 deletions CRM/Core/ClassLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,10 @@ public function register($prepend = FALSE) {
set_include_path($include_paths . PATH_SEPARATOR . get_include_path());
// @todo Why do we need to load this again?
$this->requireComposerAutoload();

$mixinLib = dirname(__DIR__, 2) . '/mixin/lib';
($GLOBALS['_PathLoad'][0] ?? require "$mixinLib/pathload-0.php");
require_once "$mixinLib/pathload.index.php";
}

/**
Expand Down
2 changes: 1 addition & 1 deletion CRM/Core/CodeGen/Main.php
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ public function getTasks() {
$tasks = [];
$tasks[] = new CRM_Core_CodeGen_Config($this);
$tasks[] = new CRM_Core_CodeGen_Reflection($this);
$tasks[] = new CRM_Core_CodeGen_Schema($this);
$tasks[] = new CRM_Core_CodeGen_PhpSchema($this);
foreach (array_keys($this->tables) as $name) {
$tasks[] = new CRM_Core_CodeGen_DAO($this, $name);
}
Expand Down
Loading

0 comments on commit 07e57e8

Please sign in to comment.