From 0605e18d14ffea87204c3cf08cef704414b166ee Mon Sep 17 00:00:00 2001 From: Eileen McNaughton Date: Mon, 20 Mar 2023 13:07:10 +1300 Subject: [PATCH] Add handling of usage to DAO generator --- CRM/Core/CodeGen/Specification.php | 35 ++-- CRM/Core/DAO/Address.php | 176 ++++++++++++++++++++- tests/phpunit/CRM/Contact/SelectorTest.php | 8 +- xml/schema/Core/Address.xml | 5 + xml/templates/dao.tpl | 14 +- 5 files changed, 218 insertions(+), 20 deletions(-) diff --git a/CRM/Core/CodeGen/Specification.php b/CRM/Core/CodeGen/Specification.php index 9f3aaea737..c26671270e 100644 --- a/CRM/Core/CodeGen/Specification.php +++ b/CRM/Core/CodeGen/Specification.php @@ -23,7 +23,7 @@ class CRM_Core_CodeGen_Specification { $this->buildVersion = $buildVersion; if ($verbose) { - echo "Parsing schema description " . $schemaPath . "\n"; + echo 'Parsing schema description ' . $schemaPath . "\n"; } $dbXML = CRM_Core_CodeGen_Util_Xml::parse($schemaPath); @@ -45,13 +45,13 @@ class CRM_Core_CodeGen_Specification { // add archive tables here foreach ($this->tables as $name => $table) { - if ($table['archive'] == 'true') { + if ($table['archive'] === 'true') { $name = 'archive_' . $table['name']; $table['name'] = $name; $table['archive'] = 'false'; if (isset($table['foreignKey'])) { foreach ($table['foreignKey'] as $fkName => $fkValue) { - if ($this->tables[$fkValue['table']]['archive'] == 'true') { + if ($this->tables[$fkValue['table']]['archive'] === 'true') { $table['foreignKey'][$fkName]['table'] = 'archive_' . $table['foreignKey'][$fkName]['table']; $table['foreignKey'][$fkName]['uniqName'] = str_replace('FK_', 'FK_archive_', $table['foreignKey'][$fkName]['uniqName']); @@ -355,7 +355,7 @@ class CRM_Core_CodeGen_Specification { default: $field['sqlType'] = $type; - if ($type == 'int unsigned' || $type == 'tinyint') { + if ($type === 'int unsigned' || $type === 'tinyint') { $field['crmType'] = 'CRM_Utils_Type::T_INT'; } else { @@ -372,13 +372,28 @@ class CRM_Core_CodeGen_Specification { $field['comment'] = $this->value('comment', $fieldXML); $field['deprecated'] = $this->value('deprecated', $fieldXML, FALSE); $field['default'] = $this->value('default', $fieldXML); - $field['import'] = $this->value('import', $fieldXML); - if ($this->value('export', $fieldXML)) { - $field['export'] = $this->value('export', $fieldXML); + $import = $this->value('import', $fieldXML) ? strtoupper($this->value('import', $fieldXML)) : 'FALSE'; + $export = $this->value('export', $fieldXML) ? strtoupper($this->value('export', $fieldXML)) : NULL; + if (!isset($fieldXML->usage)) { + $usage = [ + 'import' => $import, + 'export' => $export ?? $import, + ]; } else { - $field['export'] = $this->value('import', $fieldXML); - } + $usage = []; + foreach ($fieldXML->usage->children() as $usedFor => $isUsed) { + $usage[$usedFor] = strtoupper((string) $isUsed); + } + $import = $usage['import'] ?? $import; + } + // Ensure all keys are populated. Import is the historical de-facto default. + $field['usage'] = array_merge(array_fill_keys(['import', 'export', 'duplicate_matching'], $import), $usage); + // Usage for tokens has not historically been in the metadata so we can default to FALSE. + // historically hard-coded lists have been used. + $field['usage']['token'] = $field['usage']['token'] ?? 'FALSE'; + $field['import'] = $field['usage']['import']; + $field['export'] = $export ?? $import; $field['rule'] = $this->value('rule', $fieldXML); $field['title'] = $this->value('title', $fieldXML); if (!$field['title']) { @@ -730,7 +745,7 @@ class CRM_Core_CodeGen_Specification { * @param $object * @param null $default * - * @return null|string + * @return null|string|\SimpleXMLElement */ protected function value($key, &$object, $default = NULL) { if (isset($object->$key)) { diff --git a/CRM/Core/DAO/Address.php b/CRM/Core/DAO/Address.php index c1d7e448b9..d6daae7227 100644 --- a/CRM/Core/DAO/Address.php +++ b/CRM/Core/DAO/Address.php @@ -6,7 +6,7 @@ * * Generated from xml/schema/CRM/Core/Address.xml * DO NOT EDIT. Generated by CRM_Core_CodeGen - * (GenCodeChecksum:d528ca80d405aaf51c9868b4a491329d) + * (GenCodeChecksum:93cff77485ca748e88906bcb5d61bf22) */ /** @@ -350,6 +350,12 @@ class CRM_Core_DAO_Address extends CRM_Core_DAO { 'title' => ts('Address ID'), 'description' => ts('Unique Address ID'), 'required' => TRUE, + 'usage' => [ + 'import' => FALSE, + 'export' => TRUE, + 'duplicate_matching' => FALSE, + 'token' => FALSE, + ], 'where' => 'civicrm_address.id', 'export' => TRUE, 'table_name' => 'civicrm_address', @@ -367,6 +373,12 @@ class CRM_Core_DAO_Address extends CRM_Core_DAO { 'type' => CRM_Utils_Type::T_INT, 'title' => ts('Contact ID'), 'description' => ts('FK to Contact ID'), + 'usage' => [ + 'import' => FALSE, + 'export' => FALSE, + 'duplicate_matching' => FALSE, + 'token' => FALSE, + ], 'where' => 'civicrm_address.contact_id', 'table_name' => 'civicrm_address', 'entity' => 'Address', @@ -383,6 +395,12 @@ class CRM_Core_DAO_Address extends CRM_Core_DAO { 'type' => CRM_Utils_Type::T_INT, 'title' => ts('Address Location Type'), 'description' => ts('Which Location does this address belong to.'), + 'usage' => [ + 'import' => FALSE, + 'export' => FALSE, + 'duplicate_matching' => FALSE, + 'token' => FALSE, + ], 'where' => 'civicrm_address.location_type_id', 'table_name' => 'civicrm_address', 'entity' => 'Address', @@ -404,6 +422,12 @@ class CRM_Core_DAO_Address extends CRM_Core_DAO { 'title' => ts('Is Primary'), 'description' => ts('Is this the primary address.'), 'required' => TRUE, + 'usage' => [ + 'import' => FALSE, + 'export' => FALSE, + 'duplicate_matching' => FALSE, + 'token' => FALSE, + ], 'where' => 'civicrm_address.is_primary', 'default' => '0', 'table_name' => 'civicrm_address', @@ -421,6 +445,12 @@ class CRM_Core_DAO_Address extends CRM_Core_DAO { 'title' => ts('Is Billing Address'), 'description' => ts('Is this the billing address.'), 'required' => TRUE, + 'usage' => [ + 'import' => FALSE, + 'export' => FALSE, + 'duplicate_matching' => FALSE, + 'token' => FALSE, + ], 'where' => 'civicrm_address.is_billing', 'default' => '0', 'table_name' => 'civicrm_address', @@ -441,6 +471,12 @@ class CRM_Core_DAO_Address extends CRM_Core_DAO { delivery, etc.).'), 'maxlength' => 96, 'size' => CRM_Utils_Type::HUGE, + 'usage' => [ + 'import' => TRUE, + 'export' => TRUE, + 'duplicate_matching' => TRUE, + 'token' => FALSE, + ], 'import' => TRUE, 'where' => 'civicrm_address.street_address', 'headerPattern' => '/(street|address)/i', @@ -460,6 +496,12 @@ class CRM_Core_DAO_Address extends CRM_Core_DAO { 'type' => CRM_Utils_Type::T_INT, 'title' => ts('Street Number'), 'description' => ts('Numeric portion of address number on the street, e.g. For 112A Main St, the street_number = 112.'), + 'usage' => [ + 'import' => FALSE, + 'export' => TRUE, + 'duplicate_matching' => FALSE, + 'token' => FALSE, + ], 'where' => 'civicrm_address.street_number', 'export' => TRUE, 'table_name' => 'civicrm_address', @@ -478,6 +520,12 @@ class CRM_Core_DAO_Address extends CRM_Core_DAO { 'description' => ts('Non-numeric portion of address number on the street, e.g. For 112A Main St, the street_number_suffix = A'), 'maxlength' => 8, 'size' => CRM_Utils_Type::EIGHT, + 'usage' => [ + 'import' => FALSE, + 'export' => TRUE, + 'duplicate_matching' => FALSE, + 'token' => FALSE, + ], 'where' => 'civicrm_address.street_number_suffix', 'export' => TRUE, 'table_name' => 'civicrm_address', @@ -496,6 +544,12 @@ class CRM_Core_DAO_Address extends CRM_Core_DAO { 'description' => ts('Directional prefix, e.g. SE Main St, SE is the prefix.'), 'maxlength' => 8, 'size' => CRM_Utils_Type::EIGHT, + 'usage' => [ + 'import' => FALSE, + 'export' => FALSE, + 'duplicate_matching' => FALSE, + 'token' => FALSE, + ], 'where' => 'civicrm_address.street_number_predirectional', 'table_name' => 'civicrm_address', 'entity' => 'Address', @@ -513,6 +567,12 @@ class CRM_Core_DAO_Address extends CRM_Core_DAO { 'description' => ts('Actual street name, excluding St, Dr, Rd, Ave, e.g. For 112 Main St, the street_name = Main.'), 'maxlength' => 64, 'size' => CRM_Utils_Type::BIG, + 'usage' => [ + 'import' => FALSE, + 'export' => TRUE, + 'duplicate_matching' => FALSE, + 'token' => FALSE, + ], 'where' => 'civicrm_address.street_name', 'export' => TRUE, 'table_name' => 'civicrm_address', @@ -531,6 +591,12 @@ class CRM_Core_DAO_Address extends CRM_Core_DAO { 'description' => ts('St, Rd, Dr, etc.'), 'maxlength' => 8, 'size' => CRM_Utils_Type::EIGHT, + 'usage' => [ + 'import' => FALSE, + 'export' => FALSE, + 'duplicate_matching' => FALSE, + 'token' => FALSE, + ], 'where' => 'civicrm_address.street_type', 'table_name' => 'civicrm_address', 'entity' => 'Address', @@ -548,6 +614,12 @@ class CRM_Core_DAO_Address extends CRM_Core_DAO { 'description' => ts('Directional prefix, e.g. Main St S, S is the suffix.'), 'maxlength' => 8, 'size' => CRM_Utils_Type::EIGHT, + 'usage' => [ + 'import' => FALSE, + 'export' => FALSE, + 'duplicate_matching' => FALSE, + 'token' => FALSE, + ], 'where' => 'civicrm_address.street_number_postdirectional', 'table_name' => 'civicrm_address', 'entity' => 'Address', @@ -565,6 +637,12 @@ class CRM_Core_DAO_Address extends CRM_Core_DAO { 'description' => ts('Secondary unit designator, e.g. Apt 3 or Unit # 14, or Bldg 1200'), 'maxlength' => 16, 'size' => CRM_Utils_Type::TWELVE, + 'usage' => [ + 'import' => FALSE, + 'export' => TRUE, + 'duplicate_matching' => FALSE, + 'token' => FALSE, + ], 'where' => 'civicrm_address.street_unit', 'export' => TRUE, 'table_name' => 'civicrm_address', @@ -583,6 +661,12 @@ class CRM_Core_DAO_Address extends CRM_Core_DAO { 'description' => ts('Supplemental Address Information, Line 1'), 'maxlength' => 96, 'size' => CRM_Utils_Type::HUGE, + 'usage' => [ + 'import' => TRUE, + 'export' => TRUE, + 'duplicate_matching' => TRUE, + 'token' => FALSE, + ], 'import' => TRUE, 'where' => 'civicrm_address.supplemental_address_1', 'headerPattern' => '/(supplemental(\s)?)?address(\s\d+)?/i', @@ -604,6 +688,12 @@ class CRM_Core_DAO_Address extends CRM_Core_DAO { 'description' => ts('Supplemental Address Information, Line 2'), 'maxlength' => 96, 'size' => CRM_Utils_Type::HUGE, + 'usage' => [ + 'import' => TRUE, + 'export' => TRUE, + 'duplicate_matching' => TRUE, + 'token' => FALSE, + ], 'import' => TRUE, 'where' => 'civicrm_address.supplemental_address_2', 'headerPattern' => '/(supplemental(\s)?)?address(\s\d+)?/i', @@ -625,6 +715,12 @@ class CRM_Core_DAO_Address extends CRM_Core_DAO { 'description' => ts('Supplemental Address Information, Line 3'), 'maxlength' => 96, 'size' => CRM_Utils_Type::HUGE, + 'usage' => [ + 'import' => TRUE, + 'export' => TRUE, + 'duplicate_matching' => TRUE, + 'token' => FALSE, + ], 'import' => TRUE, 'where' => 'civicrm_address.supplemental_address_3', 'headerPattern' => '/(supplemental(\s)?)?address(\s\d+)?/i', @@ -646,6 +742,12 @@ class CRM_Core_DAO_Address extends CRM_Core_DAO { 'description' => ts('City, Town or Village Name.'), 'maxlength' => 64, 'size' => CRM_Utils_Type::BIG, + 'usage' => [ + 'import' => TRUE, + 'export' => TRUE, + 'duplicate_matching' => TRUE, + 'token' => FALSE, + ], 'import' => TRUE, 'where' => 'civicrm_address.city', 'headerPattern' => '/city/i', @@ -665,6 +767,12 @@ class CRM_Core_DAO_Address extends CRM_Core_DAO { 'type' => CRM_Utils_Type::T_INT, 'title' => ts('County ID'), 'description' => ts('Which County does this address belong to.'), + 'usage' => [ + 'import' => FALSE, + 'export' => FALSE, + 'duplicate_matching' => FALSE, + 'token' => FALSE, + ], 'where' => 'civicrm_address.county_id', 'table_name' => 'civicrm_address', 'entity' => 'Address', @@ -689,6 +797,12 @@ class CRM_Core_DAO_Address extends CRM_Core_DAO { 'type' => CRM_Utils_Type::T_INT, 'title' => ts('State/Province ID'), 'description' => ts('Which State_Province does this address belong to.'), + 'usage' => [ + 'import' => FALSE, + 'export' => FALSE, + 'duplicate_matching' => FALSE, + 'token' => FALSE, + ], 'where' => 'civicrm_address.state_province_id', 'table_name' => 'civicrm_address', 'entity' => 'Address', @@ -716,6 +830,12 @@ class CRM_Core_DAO_Address extends CRM_Core_DAO { 'description' => ts('Store the suffix, like the +4 part in the USPS system.'), 'maxlength' => 12, 'size' => 3, + 'usage' => [ + 'import' => TRUE, + 'export' => TRUE, + 'duplicate_matching' => TRUE, + 'token' => FALSE, + ], 'import' => TRUE, 'where' => 'civicrm_address.postal_code_suffix', 'headerPattern' => '/p(ostal)\sc(ode)\ss(uffix)/i', @@ -737,6 +857,12 @@ class CRM_Core_DAO_Address extends CRM_Core_DAO { 'description' => ts('Store both US (zip5) AND international postal codes. App is responsible for country/region appropriate validation.'), 'maxlength' => 64, 'size' => 6, + 'usage' => [ + 'import' => TRUE, + 'export' => TRUE, + 'duplicate_matching' => TRUE, + 'token' => FALSE, + ], 'import' => TRUE, 'where' => 'civicrm_address.postal_code', 'headerPattern' => '/postal|zip/i', @@ -758,6 +884,12 @@ class CRM_Core_DAO_Address extends CRM_Core_DAO { 'description' => ts('USPS Bulk mailing code.'), 'maxlength' => 32, 'size' => CRM_Utils_Type::MEDIUM, + 'usage' => [ + 'import' => FALSE, + 'export' => FALSE, + 'duplicate_matching' => FALSE, + 'token' => FALSE, + ], 'where' => 'civicrm_address.usps_adc', 'table_name' => 'civicrm_address', 'entity' => 'Address', @@ -771,6 +903,12 @@ class CRM_Core_DAO_Address extends CRM_Core_DAO { 'type' => CRM_Utils_Type::T_INT, 'title' => ts('Country ID'), 'description' => ts('Which Country does this address belong to.'), + 'usage' => [ + 'import' => FALSE, + 'export' => FALSE, + 'duplicate_matching' => FALSE, + 'token' => FALSE, + ], 'where' => 'civicrm_address.country_id', 'table_name' => 'civicrm_address', 'entity' => 'Address', @@ -796,6 +934,12 @@ class CRM_Core_DAO_Address extends CRM_Core_DAO { 'type' => CRM_Utils_Type::T_FLOAT, 'title' => ts('Latitude'), 'description' => ts('Latitude'), + 'usage' => [ + 'import' => TRUE, + 'export' => TRUE, + 'duplicate_matching' => TRUE, + 'token' => FALSE, + ], 'import' => TRUE, 'where' => 'civicrm_address.geo_code_1', 'headerPattern' => '/geo/i', @@ -814,6 +958,12 @@ class CRM_Core_DAO_Address extends CRM_Core_DAO { 'type' => CRM_Utils_Type::T_FLOAT, 'title' => ts('Longitude'), 'description' => ts('Longitude'), + 'usage' => [ + 'import' => TRUE, + 'export' => TRUE, + 'duplicate_matching' => TRUE, + 'token' => FALSE, + ], 'import' => TRUE, 'where' => 'civicrm_address.geo_code_2', 'headerPattern' => '/geo/i', @@ -833,6 +983,12 @@ class CRM_Core_DAO_Address extends CRM_Core_DAO { 'title' => ts('Is Manually Geocoded'), 'description' => ts('Is this a manually entered geo code'), 'required' => TRUE, + 'usage' => [ + 'import' => FALSE, + 'export' => TRUE, + 'duplicate_matching' => FALSE, + 'token' => FALSE, + ], 'where' => 'civicrm_address.manual_geo_code', 'export' => TRUE, 'default' => '0', @@ -852,6 +1008,12 @@ class CRM_Core_DAO_Address extends CRM_Core_DAO { 'description' => ts('Timezone expressed as a UTC offset - e.g. United States CST would be written as "UTC-6".'), 'maxlength' => 8, 'size' => CRM_Utils_Type::EIGHT, + 'usage' => [ + 'import' => FALSE, + 'export' => FALSE, + 'duplicate_matching' => FALSE, + 'token' => FALSE, + ], 'where' => 'civicrm_address.timezone', 'table_name' => 'civicrm_address', 'entity' => 'Address', @@ -868,6 +1030,12 @@ class CRM_Core_DAO_Address extends CRM_Core_DAO { 'title' => ts('Address Name'), 'maxlength' => 255, 'size' => CRM_Utils_Type::HUGE, + 'usage' => [ + 'import' => TRUE, + 'export' => TRUE, + 'duplicate_matching' => TRUE, + 'token' => FALSE, + ], 'import' => TRUE, 'where' => 'civicrm_address.name', 'headerPattern' => '/^location|(l(ocation\s)?name)$/i', @@ -887,6 +1055,12 @@ class CRM_Core_DAO_Address extends CRM_Core_DAO { 'type' => CRM_Utils_Type::T_INT, 'title' => ts('Master Address ID'), 'description' => ts('FK to Address ID'), + 'usage' => [ + 'import' => TRUE, + 'export' => TRUE, + 'duplicate_matching' => TRUE, + 'token' => FALSE, + ], 'import' => TRUE, 'where' => 'civicrm_address.master_id', 'export' => TRUE, diff --git a/tests/phpunit/CRM/Contact/SelectorTest.php b/tests/phpunit/CRM/Contact/SelectorTest.php index d436e5273c..f1b5423e8e 100644 --- a/tests/phpunit/CRM/Contact/SelectorTest.php +++ b/tests/phpunit/CRM/Contact/SelectorTest.php @@ -27,13 +27,15 @@ class CRM_Contact_SelectorTest extends CiviUnitTestCase { } /** - * Test the query from the selector class is consistent with the dataset expectation. + * Test the query from the selector class is consistent with the dataset + * expectation. * * @param array $dataSet - * The data set to be tested. Note that when adding new datasets often only form_values and expected where - * clause will need changing. + * The data set to be tested. Note that when adding new datasets often only + * form_values and expected where clause will need changing. * * @dataProvider querySets + * @throws \Civi\Core\Exception\DBQueryException */ public function testSelectorQuery(array $dataSet): void { $tag = $this->callAPISuccess('Tag', 'create', [ diff --git a/xml/schema/Core/Address.xml b/xml/schema/Core/Address.xml index 9937b31a5c..f9f06ed27c 100644 --- a/xml/schema/Core/Address.xml +++ b/xml/schema/Core/Address.xml @@ -13,6 +13,11 @@ address_id int unsigned true + + false + true + false + Address ID true Unique Address ID diff --git a/xml/templates/dao.tpl b/xml/templates/dao.tpl index 904aefbb8f..d56d62fcec 100644 --- a/xml/templates/dao.tpl +++ b/xml/templates/dao.tpl @@ -184,17 +184,19 @@ class {$table.className} extends CRM_Core_DAO {ldelim} {if isset($field.cols)} 'cols' => {$field.cols}, {/if} {* field.cols *} - -{if $field.import} - 'import' => {$field.import|strtoupper}, + 'usage' => array( + {foreach from=$field.usage key=usage item=isUsed}'{$usage}' => {$isUsed}, + {/foreach}), +{if $field.import === 'TRUE'} + 'import' => TRUE, {/if} {* field.import *} 'where' => '{$table.name}.{$field.name}', {if $field.headerPattern}'headerPattern' => '{$field.headerPattern}',{/if} {if $field.dataPattern}'dataPattern' => '{$field.dataPattern}',{/if} -{if $field.export} - 'export' => {$field.export|strtoupper}, -{/if} {* field.export *} +{if $field.export === 'TRUE' || ($field.export === 'FALSE' && $field.import === 'TRUE')} + 'export' => {$field.export}, +{/if} {* field.export - only show if meaningful, deprecated for usage *} {if $field.contactType} 'contactType' => {if $field.contactType == 'null'}NULL{else}'{$field.contactType}'{/if}, {/if} -- 2.25.1