diff --git a/ext/afform/admin/Civi/Api4/Action/Afform/LoadAdminData.php b/ext/afform/admin/Civi/Api4/Action/Afform/LoadAdminData.php index 6caa45095252..fa2c2f535a8c 100644 --- a/ext/afform/admin/Civi/Api4/Action/Afform/LoadAdminData.php +++ b/ext/afform/admin/Civi/Api4/Action/Afform/LoadAdminData.php @@ -62,7 +62,7 @@ public function _run(\Civi\Api4\Generic\Result $result) { case 'block': $info['definition'] = $this->definition + [ 'title' => '', - 'block' => $this->entity, + 'entity_type' => $this->entity, 'layout' => [], ]; break; @@ -123,8 +123,8 @@ public function _run(\Civi\Api4\Generic\Result $result) { if ($embeddedForm['type'] === 'block') { $info['blocks'][$blockTag] = $embeddedForm; } - if (!empty($embeddedForm['join'])) { - $entities = array_unique(array_merge($entities, [$embeddedForm['join']])); + if (!empty($embeddedForm['join_entity'])) { + $entities = array_unique(array_merge($entities, [$embeddedForm['join_entity']])); } $scanBlocks($embeddedForm['layout']); } @@ -152,7 +152,7 @@ public function _run(\Civi\Api4\Generic\Result $result) { } if ($info['definition']['type'] === 'block') { - $blockEntity = $info['definition']['join'] ?? $info['definition']['block']; + $blockEntity = $info['definition']['join_entity'] ?? $info['definition']['entity_type']; if ($blockEntity !== '*') { $entities[] = $blockEntity; } @@ -191,7 +191,7 @@ public function _run(\Civi\Api4\Generic\Result $result) { if (!$newForm) { $scanBlocks($info['definition']['layout']); } - $this->loadAvailableBlocks($entities, $info, [['join', 'IS NULL']]); + $this->loadAvailableBlocks($entities, $info, [['join_entity', 'IS NULL']]); } // Optimization - since contact fields are a combination of these three, @@ -237,10 +237,10 @@ private function loadAvailableBlocks($entities, &$info, $where = []) { } if ($entities) { $blockInfo = Afform::get($this->checkPermissions) - ->addSelect('name', 'title', 'block', 'join', 'directive_name', 'repeat') + ->addSelect('name', 'title', 'entity_type', 'join_entity', 'directive_name', 'repeat') ->setWhere($where) ->addWhere('type', '=', 'block') - ->addWhere('block', 'IN', $entities) + ->addWhere('entity_type', 'IN', $entities) ->addWhere('directive_name', 'NOT IN', array_keys($info['blocks'])) ->execute(); $info['blocks'] = array_merge(array_values($info['blocks']), (array) $blockInfo); diff --git a/ext/afform/admin/ang/afGuiEditor/afGuiEditor.component.js b/ext/afform/admin/ang/afGuiEditor/afGuiEditor.component.js index 13a4bbe5ad31..799bcbd327b6 100644 --- a/ext/afform/admin/ang/afGuiEditor/afGuiEditor.component.js +++ b/ext/afform/admin/ang/afGuiEditor/afGuiEditor.component.js @@ -75,7 +75,7 @@ else if (editor.getFormType() === 'block') { editor.layout['#children'] = editor.afform.layout; - editor.blockEntity = editor.afform.join || editor.afform.block; + editor.blockEntity = editor.afform.join_entity || editor.afform.entity_type; $scope.entities[editor.blockEntity] = backfillEntityDefaults({ type: editor.blockEntity, name: editor.blockEntity, diff --git a/ext/afform/admin/ang/afGuiEditor/afGuiEntity.component.js b/ext/afform/admin/ang/afGuiEditor/afGuiEntity.component.js index 6786029542b0..2e6b72c3c5e8 100644 --- a/ext/afform/admin/ang/afGuiEditor/afGuiEntity.component.js +++ b/ext/afform/admin/ang/afGuiEditor/afGuiEntity.component.js @@ -94,12 +94,12 @@ $scope.blockTitles.length = 0; _.each(afGui.meta.blocks, function(block, directive) { if ((!search || _.contains(directive, search) || _.contains(block.name.toLowerCase(), search) || _.contains(block.title.toLowerCase(), search)) && - (block.block === '*' || block.block === ctrl.entity.type || (ctrl.entity.type === 'Contact' && block.block === ctrl.entity.data.contact_type)) && + (block.entity_type === '*' || block.entity_type === ctrl.entity.type || (ctrl.entity.type === 'Contact' && block.entity_type === ctrl.entity.data.contact_type)) && block.name !== ctrl.editor.getAfform().name ) { - var item = {"#tag": block.join ? "div" : directive}; - if (block.join) { - item['af-join'] = block.join; + var item = {"#tag": block.join_entity ? "div" : directive}; + if (block.join_entity) { + item['af-join'] = block.join_entity; item['#children'] = [{"#tag": directive}]; } if (block.repeat) { diff --git a/ext/afform/admin/ang/afGuiEditor/elements/afGuiContainer.component.js b/ext/afform/admin/ang/afGuiEditor/elements/afGuiContainer.component.js index 3cc79a086d6a..539d6b96c2e8 100644 --- a/ext/afform/admin/ang/afGuiEditor/elements/afGuiContainer.component.js +++ b/ext/afform/admin/ang/afGuiEditor/elements/afGuiContainer.component.js @@ -195,7 +195,7 @@ }; _.each(afGui.meta.blocks, function(blockInfo, directive) { - if (directive === ctrl.node['#tag'] || (blockInfo.join && blockInfo.join === ctrl.getFieldEntityType())) { + if (directive === ctrl.node['#tag'] || (blockInfo.join_entity && blockInfo.join_entity === ctrl.getFieldEntityType())) { block.options.push({ id: directive, text: blockInfo.title diff --git a/ext/afform/core/CRM/Afform/AfformScanner.php b/ext/afform/core/CRM/Afform/AfformScanner.php index c7e30aa4d88e..f7a7125f4bee 100644 --- a/ext/afform/core/CRM/Afform/AfformScanner.php +++ b/ext/afform/core/CRM/Afform/AfformScanner.php @@ -231,7 +231,7 @@ private function appendFilePaths(&$formPaths, $parent, $priority) { * @return mixed|string * Ex: '/var/www/sites/default/files/civicrm/afform'. */ - private function getSiteLocalPath() { + public function getSiteLocalPath() { // TODO Allow a setting override. // return Civi::paths()->getPath(Civi::settings()->get('afformPath')); return Civi::paths()->getPath('[civicrm.files]/ang'); diff --git a/ext/afform/core/CRM/Afform/Upgrader.php b/ext/afform/core/CRM/Afform/Upgrader.php new file mode 100644 index 000000000000..2786478f0257 --- /dev/null +++ b/ext/afform/core/CRM/Afform/Upgrader.php @@ -0,0 +1,57 @@ +ctx->log->info('Applying update 1000'); + $scanner = new CRM_Afform_AfformScanner(); + $localDir = $scanner->getSiteLocalPath(); + + // Update form markup with new block directive names + $replacements = [ + 'afjoin-address-default>' => 'afblock-contact-address>', + 'afjoin-email-default>' => 'afblock-contact-email>', + 'afjoin-i-m-default>' => 'afblock-contact-i-m>', + 'afjoin-phone-default>' => 'afblock-contact-phone>', + 'afjoin-website-default>' => 'afblock-contact-website>', + 'afjoin-custom-' => 'afblock-custom-', + ]; + foreach (glob("$localDir/*." . $scanner::LAYOUT_FILE) as $fileName) { + $html = file_get_contents($fileName); + $html = str_replace(array_keys($replacements), array_values($replacements), $html); + file_put_contents($fileName, $html); + } + + // Update form metadata with new block property names + $replacements = [ + 'join' => 'join_entity', + 'block' => 'entity_type', + ]; + foreach (glob("$localDir/*." . $scanner::METADATA_FILE) as $fileName) { + $meta = json_decode(file_get_contents($fileName), TRUE); + foreach ($replacements as $oldKey => $newKey) { + if (isset($meta[$oldKey])) { + $meta[$newKey] = $meta[$oldKey]; + unset($meta[$oldKey]); + } + } + if (!empty($meta['entity_type'])) { + $meta['type'] = 'block'; + } + file_put_contents($fileName, json_encode($meta, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); + } + + return TRUE; + } + +} diff --git a/ext/afform/core/CRM/Afform/Upgrader/Base.php b/ext/afform/core/CRM/Afform/Upgrader/Base.php new file mode 100644 index 000000000000..207520ddd58b --- /dev/null +++ b/ext/afform/core/CRM/Afform/Upgrader/Base.php @@ -0,0 +1,396 @@ +ctx = array_shift($args); + $instance->queue = $instance->ctx->queue; + $method = array_shift($args); + return call_user_func_array([$instance, $method], $args); + } + + /** + * CRM_Afform_Upgrader_Base constructor. + * + * @param $extensionName + * @param $extensionDir + */ + public function __construct($extensionName, $extensionDir) { + $this->extensionName = $extensionName; + $this->extensionDir = $extensionDir; + } + + // ******** Task helpers ******** + + /** + * Run a CustomData file. + * + * @param string $relativePath + * the CustomData XML file path (relative to this extension's dir) + * @return bool + */ + public function executeCustomDataFile($relativePath) { + $xml_file = $this->extensionDir . '/' . $relativePath; + return $this->executeCustomDataFileByAbsPath($xml_file); + } + + /** + * Run a CustomData file + * + * @param string $xml_file + * the CustomData XML file path (absolute path) + * + * @return bool + */ + protected function executeCustomDataFileByAbsPath($xml_file) { + $import = new CRM_Utils_Migrate_Import(); + $import->run($xml_file); + return TRUE; + } + + /** + * Run a SQL file. + * + * @param string $relativePath + * the SQL file path (relative to this extension's dir) + * + * @return bool + */ + public function executeSqlFile($relativePath) { + CRM_Utils_File::sourceSQLFile( + CIVICRM_DSN, + $this->extensionDir . DIRECTORY_SEPARATOR . $relativePath + ); + return TRUE; + } + + /** + * Run the sql commands in the specified file. + * + * @param string $tplFile + * The SQL file path (relative to this extension's dir). + * Ex: "sql/mydata.mysql.tpl". + * + * @return bool + * @throws \CRM_Core_Exception + */ + public function executeSqlTemplate($tplFile) { + // Assign multilingual variable to Smarty. + $upgrade = new CRM_Upgrade_Form(); + + $tplFile = CRM_Utils_File::isAbsolute($tplFile) ? $tplFile : $this->extensionDir . DIRECTORY_SEPARATOR . $tplFile; + $smarty = CRM_Core_Smarty::singleton(); + $smarty->assign('domainID', CRM_Core_Config::domainID()); + CRM_Utils_File::sourceSQLFile( + CIVICRM_DSN, $smarty->fetch($tplFile), NULL, TRUE + ); + return TRUE; + } + + /** + * Run one SQL query. + * + * This is just a wrapper for CRM_Core_DAO::executeSql, but it + * provides syntactic sugar for queueing several tasks that + * run different queries + * + * @return bool + */ + public function executeSql($query, $params = []) { + // FIXME verify that we raise an exception on error + CRM_Core_DAO::executeQuery($query, $params); + return TRUE; + } + + /** + * Syntactic sugar for enqueuing a task which calls a function in this class. + * + * The task is weighted so that it is processed + * as part of the currently-pending revision. + * + * After passing the $funcName, you can also pass parameters that will go to + * the function. Note that all params must be serializable. + */ + public function addTask($title) { + $args = func_get_args(); + $title = array_shift($args); + $task = new CRM_Queue_Task( + [get_class($this), '_queueAdapter'], + $args, + $title + ); + return $this->queue->createItem($task, ['weight' => -1]); + } + + // ******** Revision-tracking helpers ******** + + /** + * Determine if there are any pending revisions. + * + * @return bool + */ + public function hasPendingRevisions() { + $revisions = $this->getRevisions(); + $currentRevision = $this->getCurrentRevision(); + + if (empty($revisions)) { + return FALSE; + } + if (empty($currentRevision)) { + return TRUE; + } + + return ($currentRevision < max($revisions)); + } + + /** + * Add any pending revisions to the queue. + * + * @param CRM_Queue_Queue $queue + */ + public function enqueuePendingRevisions(CRM_Queue_Queue $queue) { + $this->queue = $queue; + + $currentRevision = $this->getCurrentRevision(); + foreach ($this->getRevisions() as $revision) { + if ($revision > $currentRevision) { + $title = E::ts('Upgrade %1 to revision %2', [ + 1 => $this->extensionName, + 2 => $revision, + ]); + + // note: don't use addTask() because it sets weight=-1 + + $task = new CRM_Queue_Task( + [get_class($this), '_queueAdapter'], + ['upgrade_' . $revision], + $title + ); + $this->queue->createItem($task); + + $task = new CRM_Queue_Task( + [get_class($this), '_queueAdapter'], + ['setCurrentRevision', $revision], + $title + ); + $this->queue->createItem($task); + } + } + } + + /** + * Get a list of revisions. + * + * @return array + * revisionNumbers sorted numerically + */ + public function getRevisions() { + if (!is_array($this->revisions)) { + $this->revisions = []; + + $clazz = new ReflectionClass(get_class($this)); + $methods = $clazz->getMethods(); + foreach ($methods as $method) { + if (preg_match('/^upgrade_(.*)/', $method->name, $matches)) { + $this->revisions[] = $matches[1]; + } + } + sort($this->revisions, SORT_NUMERIC); + } + + return $this->revisions; + } + + public function getCurrentRevision() { + $revision = CRM_Core_BAO_Extension::getSchemaVersion($this->extensionName); + if (!$revision) { + $revision = $this->getCurrentRevisionDeprecated(); + } + return $revision; + } + + private function getCurrentRevisionDeprecated() { + $key = $this->extensionName . ':version'; + if ($revision = \Civi::settings()->get($key)) { + $this->revisionStorageIsDeprecated = TRUE; + } + return $revision; + } + + public function setCurrentRevision($revision) { + CRM_Core_BAO_Extension::setSchemaVersion($this->extensionName, $revision); + // clean up legacy schema version store (CRM-19252) + $this->deleteDeprecatedRevision(); + return TRUE; + } + + private function deleteDeprecatedRevision() { + if ($this->revisionStorageIsDeprecated) { + $setting = new CRM_Core_BAO_Setting(); + $setting->name = $this->extensionName . ':version'; + $setting->delete(); + CRM_Core_Error::debug_log_message("Migrated extension schema revision ID for {$this->extensionName} from civicrm_setting (deprecated) to civicrm_extension.\n"); + } + } + + // ******** Hook delegates ******** + + /** + * @see https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_install + */ + public function onInstall() { + $files = glob($this->extensionDir . '/sql/*_install.sql'); + if (is_array($files)) { + foreach ($files as $file) { + CRM_Utils_File::sourceSQLFile(CIVICRM_DSN, $file); + } + } + $files = glob($this->extensionDir . '/sql/*_install.mysql.tpl'); + if (is_array($files)) { + foreach ($files as $file) { + $this->executeSqlTemplate($file); + } + } + $files = glob($this->extensionDir . '/xml/*_install.xml'); + if (is_array($files)) { + foreach ($files as $file) { + $this->executeCustomDataFileByAbsPath($file); + } + } + if (is_callable([$this, 'install'])) { + $this->install(); + } + } + + /** + * @see https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_postInstall + */ + public function onPostInstall() { + $revisions = $this->getRevisions(); + if (!empty($revisions)) { + $this->setCurrentRevision(max($revisions)); + } + if (is_callable([$this, 'postInstall'])) { + $this->postInstall(); + } + } + + /** + * @see https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_uninstall + */ + public function onUninstall() { + $files = glob($this->extensionDir . '/sql/*_uninstall.mysql.tpl'); + if (is_array($files)) { + foreach ($files as $file) { + $this->executeSqlTemplate($file); + } + } + if (is_callable([$this, 'uninstall'])) { + $this->uninstall(); + } + $files = glob($this->extensionDir . '/sql/*_uninstall.sql'); + if (is_array($files)) { + foreach ($files as $file) { + CRM_Utils_File::sourceSQLFile(CIVICRM_DSN, $file); + } + } + } + + /** + * @see https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_enable + */ + public function onEnable() { + // stub for possible future use + if (is_callable([$this, 'enable'])) { + $this->enable(); + } + } + + /** + * @see https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_disable + */ + public function onDisable() { + // stub for possible future use + if (is_callable([$this, 'disable'])) { + $this->disable(); + } + } + + public function onUpgrade($op, CRM_Queue_Queue $queue = NULL) { + switch ($op) { + case 'check': + return [$this->hasPendingRevisions()]; + + case 'enqueue': + return $this->enqueuePendingRevisions($queue); + + default: + } + } + +} diff --git a/ext/afform/core/Civi/Afform/AfformMetadataInjector.php b/ext/afform/core/Civi/Afform/AfformMetadataInjector.php index 418e6cb8abbf..fca28b8694e6 100644 --- a/ext/afform/core/Civi/Afform/AfformMetadataInjector.php +++ b/ext/afform/core/Civi/Afform/AfformMetadataInjector.php @@ -28,12 +28,12 @@ public static function preprocess($e) { ->alterHtml(';\\.aff\\.html$;', function($doc, $path) { try { $module = \Civi::service('angular')->getModule(basename($path, '.aff.html')); - $meta = \Civi\Api4\Afform::get(FALSE)->addWhere('name', '=', $module['_afform'])->setSelect(['join', 'block'])->execute()->first(); + $meta = \Civi\Api4\Afform::get(FALSE)->addWhere('name', '=', $module['_afform'])->setSelect(['join_entity', 'entity_type'])->execute()->first(); } catch (\Exception $e) { } - $blockEntity = $meta['join'] ?? $meta['block'] ?? NULL; + $blockEntity = $meta['join_entity'] ?? $meta['entity_type'] ?? NULL; if (!$blockEntity) { $entities = self::getFormEntities($doc); } diff --git a/ext/afform/core/Civi/Api4/Action/Afform/Get.php b/ext/afform/core/Civi/Api4/Action/Afform/Get.php index 277eaa197469..2d4fa6e86a1d 100644 --- a/ext/afform/core/Civi/Api4/Action/Afform/Get.php +++ b/ext/afform/core/Civi/Api4/Action/Afform/Get.php @@ -43,7 +43,7 @@ public function getRecords() { ]; foreach ($toGet as $key => $get) { if (!in_array($info[$key], $get)) { - continue; + continue 2; } } $record = $scanner->getMeta($name); @@ -90,14 +90,14 @@ protected function checkPermission($name) { protected function getAutoGenerated(&$names, $toGet, $getLayout) { $values = $groupNames = []; foreach ($toGet['name'] ?? [] as $name) { - if (strpos($name, 'afjoinCustom_') === 0 && strlen($name) > 13) { - $groupNames[] = substr($name, 13); + if (strpos($name, 'afblockCustom_') === 0 && strlen($name) > 13) { + $groupNames[] = substr($name, 14); } } // Early return if this api call is fetching afforms by name and those names are not custom-related if ((!empty($toGet['name']) && !$groupNames) - || (!empty($toGet['module_name']) && !strstr(implode(' ', $toGet['module_name']), 'afjoinCustom')) - || (!empty($toGet['directive_name']) && !strstr(implode(' ', $toGet['directive_name']), 'afjoin-custom')) + || (!empty($toGet['module_name']) && !strstr(implode(' ', $toGet['module_name']), 'afblockCustom')) + || (!empty($toGet['directive_name']) && !strstr(implode(' ', $toGet['directive_name']), 'afblock-custom')) ) { return $values; } @@ -119,7 +119,7 @@ protected function getAutoGenerated(&$names, $toGet, $getLayout) { ); } foreach ($customApi->execute() as $custom) { - $name = 'afjoinCustom_' . $custom['name']; + $name = 'afblockCustom_' . $custom['name']; if (!in_array($name, $names)) { $names[] = $name; } @@ -127,14 +127,14 @@ protected function getAutoGenerated(&$names, $toGet, $getLayout) { 'name' => $name, 'type' => 'block', 'requires' => [], - 'title' => E::ts('%1 block (default)', [1 => $custom['title']]), + 'title' => E::ts('%1 block', [1 => $custom['title']]), 'description' => '', 'is_dashlet' => FALSE, 'is_public' => FALSE, 'is_token' => FALSE, 'permission' => 'access CiviCRM', - 'join' => 'Custom_' . $custom['name'], - 'block' => $custom['extends'], + 'join_entity' => 'Custom_' . $custom['name'], + 'entity_type' => $custom['extends'], 'repeat' => $custom['max_multiple'] ?: TRUE, 'has_base' => TRUE, ]; diff --git a/ext/afform/core/Civi/Api4/Afform.php b/ext/afform/core/Civi/Api4/Afform.php index f0450a091b80..6c6f435f08d7 100644 --- a/ext/afform/core/Civi/Api4/Afform.php +++ b/ext/afform/core/Civi/Api4/Afform.php @@ -135,10 +135,12 @@ public static function getFields($checkPermissions = TRUE) { 'data_type' => 'Array', ], [ - 'name' => 'block', + 'name' => 'entity_type', + 'description' => 'Block used for this entity type', ], [ - 'name' => 'join', + 'name' => 'join_entity', + 'description' => 'Used for blocks that join a sub-entity (e.g. Emails for a Contact)', ], [ 'name' => 'title', @@ -183,6 +185,7 @@ public static function getFields($checkPermissions = TRUE) { [ 'name' => 'layout', 'data_type' => 'Array', + 'description' => 'HTML form layout; format is controlled by layoutFormat param', ], ]; // Calculated fields returned by get action diff --git a/ext/afform/core/Civi/Api4/Utils/AfformSaveTrait.php b/ext/afform/core/Civi/Api4/Utils/AfformSaveTrait.php index bee09ea62611..2f4099460a7e 100644 --- a/ext/afform/core/Civi/Api4/Utils/AfformSaveTrait.php +++ b/ext/afform/core/Civi/Api4/Utils/AfformSaveTrait.php @@ -16,7 +16,7 @@ protected function writeRecord($item) { // If no name given, create a unique name based on the title if (empty($item['name'])) { - $prefix = !empty($item['join']) ? "afjoin-{$item['join']}" : (!empty($item['block']) ? ('afblock-' . str_replace('*', 'all', $item['block'])) : 'afform'); + $prefix = 'af' . ($item['type'] ?? ''); $item['name'] = _afform_angular_module_name($prefix . '-' . \CRM_Utils_String::munge($item['title'], '-')); $suffix = ''; while ( diff --git a/ext/afform/core/ang/afjoinAddressDefault.aff.html b/ext/afform/core/ang/afblockContactAddress.aff.html similarity index 100% rename from ext/afform/core/ang/afjoinAddressDefault.aff.html rename to ext/afform/core/ang/afblockContactAddress.aff.html diff --git a/ext/afform/core/ang/afblockContactAddress.aff.json b/ext/afform/core/ang/afblockContactAddress.aff.json new file mode 100644 index 000000000000..41a28494a182 --- /dev/null +++ b/ext/afform/core/ang/afblockContactAddress.aff.json @@ -0,0 +1,7 @@ +{ + "title": "Contact Address(es)", + "type": "block", + "entity_type": "Contact", + "join_entity": "Address", + "repeat": true +} diff --git a/ext/afform/core/ang/afjoinEmailDefault.aff.html b/ext/afform/core/ang/afblockContactEmail.aff.html similarity index 100% rename from ext/afform/core/ang/afjoinEmailDefault.aff.html rename to ext/afform/core/ang/afblockContactEmail.aff.html diff --git a/ext/afform/core/ang/afblockContactEmail.aff.json b/ext/afform/core/ang/afblockContactEmail.aff.json new file mode 100644 index 000000000000..0b8a749a4c21 --- /dev/null +++ b/ext/afform/core/ang/afblockContactEmail.aff.json @@ -0,0 +1,7 @@ +{ + "title": "Contact Email(s)", + "type": "block", + "entity_type": "Contact", + "join_entity": "Email", + "repeat": true +} diff --git a/ext/afform/core/ang/afjoinIMDefault.aff.html b/ext/afform/core/ang/afblockContactIM.aff.html similarity index 100% rename from ext/afform/core/ang/afjoinIMDefault.aff.html rename to ext/afform/core/ang/afblockContactIM.aff.html diff --git a/ext/afform/core/ang/afblockContactIM.aff.json b/ext/afform/core/ang/afblockContactIM.aff.json new file mode 100644 index 000000000000..0d7ea0ff46b7 --- /dev/null +++ b/ext/afform/core/ang/afblockContactIM.aff.json @@ -0,0 +1,7 @@ +{ + "title": "Contact IM(s)", + "type": "block", + "entity_type": "Contact", + "join_entity": "IM", + "repeat": true +} diff --git a/ext/afform/core/ang/afjoinPhoneDefault.aff.html b/ext/afform/core/ang/afblockContactPhone.aff.html similarity index 100% rename from ext/afform/core/ang/afjoinPhoneDefault.aff.html rename to ext/afform/core/ang/afblockContactPhone.aff.html diff --git a/ext/afform/core/ang/afblockContactPhone.aff.json b/ext/afform/core/ang/afblockContactPhone.aff.json new file mode 100644 index 000000000000..fa7cad216868 --- /dev/null +++ b/ext/afform/core/ang/afblockContactPhone.aff.json @@ -0,0 +1,7 @@ +{ + "title": "Contact Phone(s)", + "type": "block", + "entity_type": "Contact", + "join_entity": "Phone", + "repeat": true +} diff --git a/ext/afform/core/ang/afjoinWebsiteDefault.aff.html b/ext/afform/core/ang/afblockContactWebsite.aff.html similarity index 100% rename from ext/afform/core/ang/afjoinWebsiteDefault.aff.html rename to ext/afform/core/ang/afblockContactWebsite.aff.html diff --git a/ext/afform/core/ang/afblockContactWebsite.aff.json b/ext/afform/core/ang/afblockContactWebsite.aff.json new file mode 100644 index 000000000000..3cea837cca6e --- /dev/null +++ b/ext/afform/core/ang/afblockContactWebsite.aff.json @@ -0,0 +1,7 @@ +{ + "title": "Contact Website(s)", + "type": "block", + "entity_type": "Contact", + "join_entity": "Website", + "repeat": true +} diff --git a/ext/afform/core/ang/afblockNameHousehold.aff.json b/ext/afform/core/ang/afblockNameHousehold.aff.json index c4eee679c690..dd665a10ccc4 100644 --- a/ext/afform/core/ang/afblockNameHousehold.aff.json +++ b/ext/afform/core/ang/afblockNameHousehold.aff.json @@ -1,5 +1,5 @@ { - "title": "Household Name (default)", + "title": "Household Name", "type": "block", - "block": "Household" + "entity_type": "Household" } diff --git a/ext/afform/core/ang/afblockNameIndividual.aff.json b/ext/afform/core/ang/afblockNameIndividual.aff.json index 51c4596ea683..1cafdc4be66e 100644 --- a/ext/afform/core/ang/afblockNameIndividual.aff.json +++ b/ext/afform/core/ang/afblockNameIndividual.aff.json @@ -1,5 +1,5 @@ { - "title": "Individual Name (default)", + "title": "Individual Name", "type": "block", - "block": "Individual" + "entity_type": "Individual" } diff --git a/ext/afform/core/ang/afblockNameOrganization.aff.json b/ext/afform/core/ang/afblockNameOrganization.aff.json index e3ac17c246f4..ca44304b5d4f 100644 --- a/ext/afform/core/ang/afblockNameOrganization.aff.json +++ b/ext/afform/core/ang/afblockNameOrganization.aff.json @@ -1,5 +1,5 @@ { - "title": "Organization Name (default)", + "title": "Organization Name", "type": "block", - "block": "Organization" + "entity_type": "Organization" } diff --git a/ext/afform/core/ang/afjoinAddressDefault.aff.json b/ext/afform/core/ang/afjoinAddressDefault.aff.json deleted file mode 100644 index 27775770b667..000000000000 --- a/ext/afform/core/ang/afjoinAddressDefault.aff.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "title": "Address Block (default)", - "type": "block", - "block": "Contact", - "join": "Address", - "repeat": true -} diff --git a/ext/afform/core/ang/afjoinEmailDefault.aff.json b/ext/afform/core/ang/afjoinEmailDefault.aff.json deleted file mode 100644 index 7c50c579dc09..000000000000 --- a/ext/afform/core/ang/afjoinEmailDefault.aff.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "title": "Email (default)", - "type": "block", - "block": "Contact", - "join": "Email", - "repeat": true -} diff --git a/ext/afform/core/ang/afjoinIMDefault.aff.json b/ext/afform/core/ang/afjoinIMDefault.aff.json deleted file mode 100644 index 3ec912975b61..000000000000 --- a/ext/afform/core/ang/afjoinIMDefault.aff.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "title": "IM (default)", - "type": "block", - "block": "Contact", - "join": "IM", - "repeat": true -} diff --git a/ext/afform/core/ang/afjoinPhoneDefault.aff.json b/ext/afform/core/ang/afjoinPhoneDefault.aff.json deleted file mode 100644 index 821d2888408f..000000000000 --- a/ext/afform/core/ang/afjoinPhoneDefault.aff.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "title": "Phone (default)", - "type": "block", - "block": "Contact", - "join": "Phone", - "repeat": true -} diff --git a/ext/afform/core/ang/afjoinWebsiteDefault.aff.json b/ext/afform/core/ang/afjoinWebsiteDefault.aff.json deleted file mode 100644 index b39dd9cd7317..000000000000 --- a/ext/afform/core/ang/afjoinWebsiteDefault.aff.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "title": "Website (default)", - "type": "block", - "block": "Contact", - "join": "Website", - "repeat": true -} diff --git a/ext/afform/mock/tests/phpunit/api/v4/AfformContactUsageTest.php b/ext/afform/mock/tests/phpunit/api/v4/AfformContactUsageTest.php index 45222a343d64..ab9dfde7c0a7 100644 --- a/ext/afform/mock/tests/phpunit/api/v4/AfformContactUsageTest.php +++ b/ext/afform/mock/tests/phpunit/api/v4/AfformContactUsageTest.php @@ -39,7 +39,7 @@ public static function setUpBeforeClass(): void { Individual 1
- +
@@ -49,7 +49,7 @@ public static function setUpBeforeClass(): void {
- +
diff --git a/ext/afform/mock/tests/phpunit/api/v4/AfformCustomFieldUsageTest.php b/ext/afform/mock/tests/phpunit/api/v4/AfformCustomFieldUsageTest.php index 4249d393b057..5ad2aa7255b4 100644 --- a/ext/afform/mock/tests/phpunit/api/v4/AfformCustomFieldUsageTest.php +++ b/ext/afform/mock/tests/phpunit/api/v4/AfformCustomFieldUsageTest.php @@ -17,7 +17,7 @@ public static function setUpBeforeClass(): void { Individual 1
- +
@@ -31,7 +31,7 @@ public static function setUpBeforeClass(): void { * which can be submitted multiple times */ public function testMultiRecordCustomBlock(): void { - $customGroup = \Civi\Api4\CustomGroup::create(FALSE) + \Civi\Api4\CustomGroup::create(FALSE) ->addValue('name', 'MyThings') ->addValue('title', 'My Things') ->addValue('style', 'Tab with table') @@ -49,11 +49,12 @@ public function testMultiRecordCustomBlock(): void { // Creating a custom group should automatically create an afform block $block = \Civi\Api4\Afform::get() - ->addWhere('name', '=', 'afjoinCustom_MyThings') + ->addWhere('name', '=', 'afblockCustom_MyThings') ->setLayoutFormat('shallow') ->setFormatWhitespace(TRUE) - ->execute()->first(); + ->execute()->single(); $this->assertEquals(2, $block['repeat']); + $this->assertEquals('afblock-custom-my-things', $block['directive_name']); $this->assertEquals('my_text', $block['layout'][0]['name']); $this->assertEquals('my_friend', $block['layout'][1]['name']);