From cf957fc06831d3eb00bf50b04723817a9465126b Mon Sep 17 00:00:00 2001 From: colemanw Date: Sat, 24 Jun 2023 08:46:42 -0700 Subject: [PATCH] REF - Auto-generate links for CRM_Core_Page_Basic Instead of hard-coding an array of links in every page, we can auto-generate the list based on the 'paths' metadata in the DAO. As a POC this converts one page (ACLs). Future conversions are simply a matter of ensuring 'paths' is defined then deleting the links function and $_links variable. --- CRM/ACL/Page/ACL.php | 46 --------- CRM/Core/Action.php | 205 +++++++++++++++++++++++++++++++++++----- CRM/Core/Page/Basic.php | 48 ++++++++-- 3 files changed, 221 insertions(+), 78 deletions(-) diff --git a/CRM/ACL/Page/ACL.php b/CRM/ACL/Page/ACL.php index 4bffecf133..da80cd79df 100644 --- a/CRM/ACL/Page/ACL.php +++ b/CRM/ACL/Page/ACL.php @@ -18,13 +18,6 @@ class CRM_ACL_Page_ACL extends CRM_Core_Page_Basic { public $useLivePageJS = TRUE; - /** - * The action links that we need to display for the browse screen. - * - * @var array - */ - public static $_links = NULL; - /** * Get BAO Name. * @@ -35,45 +28,6 @@ class CRM_ACL_Page_ACL extends CRM_Core_Page_Basic { return 'CRM_ACL_BAO_ACL'; } - /** - * Get action Links. - * - * @return array - * (reference) of action links - */ - public function &links() { - if (!(self::$_links)) { - self::$_links = [ - CRM_Core_Action::UPDATE => [ - 'name' => ts('Edit'), - 'url' => 'civicrm/acl/edit', - 'qs' => 'reset=1&action=update&id=%%id%%', - 'title' => ts('Edit ACL'), - ], - CRM_Core_Action::DISABLE => [ - 'name' => ts('Disable'), - 'ref' => 'crm-enable-disable', - 'title' => ts('Disable ACL'), - 'weight' => 40, - ], - CRM_Core_Action::ENABLE => [ - 'name' => ts('Enable'), - 'ref' => 'crm-enable-disable', - 'title' => ts('Enable ACL'), - 'weight' => 30, - ], - CRM_Core_Action::DELETE => [ - 'name' => ts('Delete'), - 'url' => 'civicrm/acl/delete', - 'qs' => 'reset=1&action=delete&id=%%id%%', - 'title' => ts('Delete ACL'), - 'weight' => 100, - ], - ]; - } - return self::$_links; - } - /** * Run the page. * diff --git a/CRM/Core/Action.php b/CRM/Core/Action.php index d23bd256a4..284f7b7de0 100644 --- a/CRM/Core/Action.php +++ b/CRM/Core/Action.php @@ -79,12 +79,96 @@ class CRM_Core_Action { 'reopen' => self::REOPEN, ]; - /** - * The flipped version of the names array, initialized when used - * - * @var array - */ - public static $_description; + private static function getInfo(): array { + Civi::$statics[__CLASS__ . 'Info'] = Civi::$statics[__CLASS__ . 'Info'] ?? [ + self::ADD => [ + 'name' => 'add', + 'label' => ts('Add'), + 'weight' => 0, + ], + self::UPDATE => [ + 'name' => 'update', + 'label' => ts('Edit'), + 'weight' => -10, + ], + self::VIEW => [ + 'name' => 'view', + 'label' => ts('View'), + 'weight' => -20, + ], + self::DELETE => [ + 'name' => 'delete', + 'label' => ts('Delete'), + 'weight' => 100, + ], + self::BROWSE => [ + 'name' => 'browse', + 'label' => ts('Browse'), + 'weight' => 0, + ], + self::ENABLE => [ + 'name' => 'enable', + 'label' => ts('Enable'), + 'weight' => 40, + ], + self::DISABLE => [ + 'name' => 'disable', + 'label' => ts('Disable'), + 'weight' => 40, + ], + self::EXPORT => [ + 'name' => 'export', + 'label' => ts('Export'), + 'weight' => 0, + ], + self::PREVIEW => [ + 'name' => 'preview', + 'label' => ts('Preview'), + 'weight' => 0, + ], + self::MAP => [ + 'name' => 'map', + 'label' => ts('Map'), + 'weight' => 0, + ], + self::COPY => [ + 'name' => 'copy', + 'label' => ts('Copy'), + 'weight' => 20, + ], + self::PROFILE => [ + 'name' => 'profile', + 'label' => ts('Profile'), + 'weight' => 0, + ], + self::RENEW => [ + 'name' => 'renew', + 'label' => ts('Renew'), + 'weight' => 10, + ], + self::DETACH => [ + 'name' => 'detach', + 'label' => ts('Detach'), + 'weight' => 0, + ], + self::REVERT => [ + 'name' => 'revert', + 'label' => ts('Revert'), + 'weight' => 0, + ], + self::CLOSE => [ + 'name' => 'close', + 'label' => ts('Close'), + 'weight' => 0, + ], + self::REOPEN => [ + 'name' => 'reopen', + 'label' => ts('Reopen'), + 'weight' => 0, + ], + ]; + return Civi::$statics[__CLASS__ . 'Info']; + } /** * Called by the request object to translate a string into a mask. @@ -129,35 +213,31 @@ class CRM_Core_Action { } /** - * Given a string determine the bitmask for this specific string. + * Given a string lookup the bitmask for the action name. + * e.g. "add" returns self::ADD. * - * @param string $item - * The input action to process. + * @param string $name * * @return int - * the action mask corresponding to the input string */ - public static function mapItem($item) { - $mask = self::$_names[trim($item)] ?? NULL; - return $mask ? $mask : 0; + public static function mapItem($name) { + foreach (self::getInfo() as $mask => $info) { + if ($info['name'] === $name) { + return $mask; + } + } + return self::NONE; } /** - * - * Given an action mask, find the corresponding description + * Given an action mask, get the name which describes it, + * e.g. self::ADD returns 'add'. * * @param int $mask - * The action mask. - * * @return string - * the corresponding action description */ public static function description($mask) { - if (!isset(self::$_description)) { - self::$_description = array_flip(self::$_names); - } - - return CRM_Utils_Array::value($mask, self::$_description, 'NO DESCRIPTION SET'); + return self::getInfo()[$mask]['name'] ?? 'NO DESCRIPTION SET'; } /** @@ -412,4 +492,83 @@ class CRM_Core_Action { return $mask; } + /** + * @param int $mask + * @return string|null + */ + public static function getLabel(int $mask): ?string { + return self::getInfo()[$mask]['label'] ?? NULL; + } + + /** + * @param int $mask + * @return int|null + */ + public static function getWeight(int $mask): ?string { + return self::getInfo()[$mask]['weight'] ?? NULL; + } + + /** + * Builds a title based on action and entity title, e.g. "Update Contact" + * + * @param int $action + * @param string $entityTitle + * @return string|null + */ + public static function getTitle(int $action, string $entityTitle): ?string { + switch ($action) { + case self::ADD: + return ts('Add %1', [1 => $entityTitle]); + + case self::UPDATE: + return ts('Update %1', [1 => $entityTitle]); + + case self::VIEW: + return ts('View %1', [1 => $entityTitle]); + + case self::DELETE: + return ts('Delete %1', [1 => $entityTitle]); + + case self::BROWSE: + return ts('Browse %1', [1 => $entityTitle]); + + case self::ENABLE: + return ts('Enable %1', [1 => $entityTitle]); + + case self::DISABLE: + return ts('Disable %1', [1 => $entityTitle]); + + case self::EXPORT: + return ts('Export %1', [1 => $entityTitle]); + + case self::PREVIEW: + return ts('Preview %1', [1 => $entityTitle]); + + case self::MAP: + return ts('Map %1', [1 => $entityTitle]); + + case self::COPY: + return ts('Copy %1', [1 => $entityTitle]); + + case self::PROFILE: + return ts('Profile %1', [1 => $entityTitle]); + + case self::RENEW: + return ts('Renew %1', [1 => $entityTitle]); + + case self::DETACH: + return ts('Detach %1', [1 => $entityTitle]); + + case self::REVERT: + return ts('Revert %1', [1 => $entityTitle]); + + case self::CLOSE: + return ts('Close %1', [1 => $entityTitle]); + + case self::REOPEN: + return ts('Reopen %1', [1 => $entityTitle]); + } + return NULL; + } + } diff --git a/CRM/Core/Page/Basic.php b/CRM/Core/Page/Basic.php index 52730c05d0..366f16e332 100644 --- a/CRM/Core/Page/Basic.php +++ b/CRM/Core/Page/Basic.php @@ -18,24 +18,54 @@ abstract class CRM_Core_Page_Basic extends CRM_Core_Page { protected $_action; - /** - * Define all the abstract functions here. - */ - /** * Name of the BAO to perform various DB manipulations. * - * @return string + * @return CRM_Core_DAO|string */ abstract protected function getBAOName(); /** - * An array of action links. + * Get array of action links for the "browse" page. * - * @return array - * (reference) + * Transforms from the 'paths' in metadata to the + * format expected by basic pages. + * + * @return array[] */ - abstract protected function &links(); + public function &links() { + $baoName = $this->getBAOName(); + if (!isset(Civi::$statics[$baoName]['actionLinks'])) { + Civi::$statics[$baoName]['actionLinks'] = []; + $title = $baoName::getEntityTitle(); + $paths = $baoName::getEntityPaths(); + unset($paths['add']); + foreach ($paths as $action => $path) { + $actionKey = CRM_Core_Action::map($action); + if ($actionKey) { + [$path, $query] = array_pad(explode('?', $path), 2, ''); + Civi::$statics[$baoName]['actionLinks'][$actionKey] = [ + 'name' => CRM_Core_Action::getLabel($actionKey), + 'title' => CRM_Core_Action::getTitle($actionKey, $title), + 'url' => $path, + 'qs' => str_replace(['[', ']'], '%%', $query), + 'weight' => CRM_Core_Action::getWeight($actionKey), + ]; + } + } + if (isset($baoName::getSupportedFields()['is_active'])) { + foreach ([CRM_Core_Action::DISABLE, CRM_Core_Action::ENABLE] as $actionKey) { + Civi::$statics[$baoName]['actionLinks'][$actionKey] = [ + 'name' => CRM_Core_Action::getLabel($actionKey), + 'title' => CRM_Core_Action::getTitle($actionKey, $title), + 'ref' => 'crm-enable-disable', + 'weight' => CRM_Core_Action::getWeight($actionKey), + ]; + } + } + } + return Civi::$statics[$baoName]['actionLinks']; + } /** * Name of the edit form class. -- 2.25.1