From f55f8f1793bccdd8ad9133c0c5e8aca57d4b785a Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Wed, 5 Aug 2020 04:29:59 -0700 Subject: [PATCH] CollectionTrait - Support addSetting(), addSettingsFactory(), ad nauseum --- CRM/Core/Region.php | 2 +- CRM/Core/Resources.php | 105 +++------------ CRM/Core/Resources/CollectionTrait.php | 178 +++++++++++++++++++++++++ 3 files changed, 199 insertions(+), 86 deletions(-) diff --git a/CRM/Core/Region.php b/CRM/Core/Region.php index 6c5da95e10..3f4e1f29d0 100644 --- a/CRM/Core/Region.php +++ b/CRM/Core/Region.php @@ -119,7 +119,7 @@ class CRM_Core_Region { break; case 'settings': - $settingsData = json_encode(Civi::resources()->getSettings($this->_name), JSON_UNESCAPED_SLASHES); + $settingsData = json_encode($this->getSettings(), JSON_UNESCAPED_SLASHES); $js = "(function(vars) { if (window.CRM) CRM.$.extend(true, CRM, vars); else window.CRM = vars; })($settingsData)"; diff --git a/CRM/Core/Resources.php b/CRM/Core/Resources.php index a0d9d0ca99..0871810ccc 100644 --- a/CRM/Core/Resources.php +++ b/CRM/Core/Resources.php @@ -147,19 +147,13 @@ class CRM_Core_Resources { * the client can use this info to make the app more secure; however, * it can produce a better-tuned (non-broken) UI. * - * @param array $permNames + * @param string|iterable $permNames * List of permission names to check/export. * @return CRM_Core_Resources */ public function addPermissions($permNames) { - $permNames = (array) $permNames; - $perms = []; - foreach ($permNames as $permName) { - $perms[$permName] = CRM_Core_Permission::check($permName); - } - return $this->addSetting([ - 'permissions' => $perms, - ]); + $this->getSettingRegion()->addPermissions($permNames); + return $this; } /** @@ -243,11 +237,7 @@ class CRM_Core_Resources { * @return CRM_Core_Resources */ public function addVars($nameSpace, $vars, $region = NULL) { - $s = &$this->findCreateSettingSnippet($region); - $s['settings']['vars'][$nameSpace] = $this->mergeSettings( - $s['settings']['vars'][$nameSpace] ?? [], - $vars - ); + $this->getSettingRegion($region)->addVars($nameSpace, $vars); return $this; } @@ -263,8 +253,7 @@ class CRM_Core_Resources { * @return CRM_Core_Resources */ public function addSetting($settings, $region = NULL) { - $s = &$this->findCreateSettingSnippet($region); - $s['settings'] = $this->mergeSettings($s['settings'], $settings); + $this->getSettingRegion($region)->addSetting($settings); return $this; } @@ -272,68 +261,18 @@ class CRM_Core_Resources { * Add JavaScript variables to the global CRM object via a callback function. * * @param callable $callable - * @param string|NULL $region * @return CRM_Core_Resources */ - public function addSettingsFactory($callable, $region = NULL) { - $s = &$this->findCreateSettingSnippet($region); - $s['settingsFactories'][] = $callable; + public function addSettingsFactory($callable) { + $this->getSettingRegion()->addSettingsFactory($callable); return $this; } /** * Helper fn for addSettingsFactory. - * @deprecated - */ - public function getSettings($region = NULL) { - $s = &$this->findCreateSettingSnippet($region); - $result = $s['settings']; - foreach ($s['settingsFactories'] as $callable) { - $result = $this->mergeSettings($result, $callable()); - } - CRM_Utils_Hook::alterResourceSettings($result); - return $result; - } - - /** - * @param array $settings - * @param array $additions - * @return array - * combination of $settings and $additions */ - protected function mergeSettings($settings, $additions) { - foreach ($additions as $k => $v) { - if (isset($settings[$k]) && is_array($settings[$k]) && is_array($v)) { - $v += $settings[$k]; - } - $settings[$k] = $v; - } - return $settings; - } - - /** - * @param string $regionName - * @return array - */ - private function &findCreateSettingSnippet($regionName) { - if (!$regionName) { - $regionName = self::isAjaxMode() ? 'ajax-snippet' : 'html-header'; - } - - $region = CRM_Core_Region::instance($regionName); - $snippet = &$region->get('settings'); - if ($snippet !== NULL) { - return $snippet; - } - - $region->add([ - 'name' => 'settings', - 'type' => 'settings', - 'settings' => [], - 'settingsFactories' => [], - 'weight' => -100000, - ]); - return $region->get('settings'); + public function getSettings() { + return $this->getSettingRegion()->getSettings(); } /** @@ -367,21 +306,7 @@ class CRM_Core_Resources { * @return CRM_Core_Resources */ public function addString($text, $domain = 'civicrm') { - foreach ((array) $text as $str) { - $translated = ts($str, [ - 'domain' => ($domain == 'civicrm') ? NULL : [$domain, NULL], - 'raw' => TRUE, - ]); - - // We only need to push this string to client if the translation - // is actually different from the original - if ($translated != $str) { - $bucket = $domain == 'civicrm' ? 'strings' : 'strings::' . $domain; - $this->addSetting([ - $bucket => [$str => $translated], - ]); - } - } + $this->getSettingRegion()->addString($text, $domain); return $this; } @@ -953,4 +878,14 @@ class CRM_Core_Resources { return (substr($url, 0, 4) === 'http') || (substr($url, 0, 1) === '/'); } + /** + * @param string|NULL $region + * Optional request for a specific region. If NULL/omitted, use global default. + * @return \CRM_Core_Region + */ + private function getSettingRegion($region = NULL) { + $region = $region ?: (self::isAjaxMode() ? 'ajax-snippet' : 'html-header'); + return CRM_Core_Region::instance($region); + } + } diff --git a/CRM/Core/Resources/CollectionTrait.php b/CRM/Core/Resources/CollectionTrait.php index cdf07da9c6..6532d752a3 100644 --- a/CRM/Core/Resources/CollectionTrait.php +++ b/CRM/Core/Resources/CollectionTrait.php @@ -252,6 +252,31 @@ trait CRM_Core_Resources_CollectionTrait { // ----------------------------------------------- + /** + * Export permission data to the client to enable smarter GUIs. + * + * Note: Application security stems from the server's enforcement + * of the security logic (e.g. in the API permissions). There's no way + * the client can use this info to make the app more secure; however, + * it can produce a better-tuned (non-broken) UI. + * + * @param string|iterable $permNames + * List of permission names to check/export. + * @return static + */ + public function addPermissions($permNames) { + // TODO: Maybe this should be its own resource type to allow smarter management? + $permNames = is_scalar($permNames) ? [$permNames] : $permNames; + + $perms = []; + foreach ($permNames as $permName) { + $perms[$permName] = CRM_Core_Permission::check($permName); + } + return $this->addSetting([ + 'permissions' => $perms, + ]); + } + /** * Add a JavaScript file to the current page using