From 8da6c9b8aae1cd2ca4474473018a1349061061f7 Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Wed, 24 May 2017 20:40:04 -0700 Subject: [PATCH] CRM-20600 - Civi\Angular\Manager - Add resolveDependencies(), resolveDefaultModules() --- CRM/Utils/Hook.php | 5 ++ Civi/Angular/Manager.php | 58 ++++++++++++++++++++++ tests/phpunit/Civi/Angular/ManagerTest.php | 26 ++++++++++ 3 files changed, 89 insertions(+) diff --git a/CRM/Utils/Hook.php b/CRM/Utils/Hook.php index 9da03b4318..e486374055 100644 --- a/CRM/Utils/Hook.php +++ b/CRM/Utils/Hook.php @@ -2094,6 +2094,10 @@ abstract class CRM_Utils_Hook { * - css: array, list of CSS files or globs. * - partials: array, list of base-dirs containing HTML. * - requires: array, list of required Angular modules. + * - basePages: array, uncondtionally load this module onto the given Angular pages. [v4.7.21+] + * If omitted, default to "array('civicrm/a')" for backward compat. + * For a utility that should only be loaded on-demand, use "array()". + * For a utility that should be loaded in all pages use, "array('*')". * @return null * the return value is ignored * @@ -2109,6 +2113,7 @@ abstract class CRM_Utils_Hook { * 'css' => array('css/myAngularModule.css'), * 'partials' => array('partials/myBigAngularModule'), * 'requires' => array('otherModuleA', 'otherModuleB'), + * 'basePages' => array('civicrm/a'), * ); * } * @endcode diff --git a/Civi/Angular/Manager.php b/Civi/Angular/Manager.php index 73ae38931c..61c2c69c33 100644 --- a/Civi/Angular/Manager.php +++ b/Civi/Angular/Manager.php @@ -97,6 +97,11 @@ class Manager { $angularModules = array_merge($angularModules, $component->getAngularModules()); } \CRM_Utils_Hook::angularModules($angularModules); + foreach (array_keys($angularModules) as $module) { + if (!isset($angularModules[$module]['basePages'])) { + $angularModules[$module]['basePages'] = array('civicrm/a'); + } + } $this->modules = $this->resolvePatterns($angularModules); } @@ -124,6 +129,59 @@ class Manager { return $modules[$name]; } + /** + * Resolve a full list of Angular dependencies. + * + * @param array $names + * List of Angular modules. + * Ex: array('crmMailing'). + * @return array + * List of Angular modules, include all dependencies. + * Ex: array('crmMailing', 'crmUi', 'crmUtil', 'ngRoute'). + */ + public function resolveDependencies($names) { + $allModules = $this->getModules(); + $visited = array(); + $result = $names; + while (($missingModules = array_diff($result, array_keys($visited))) && !empty($missingModules)) { + foreach ($missingModules as $module) { + $visited[$module] = 1; + if (!isset($allModules[$module])) { + \Civi::log()->warning('Unrecognized Angular module {name}. Please ensure that all Angular modules are declared.', array( + 'name' => $module, + 'civi.tag' => 'deprecated', + )); + } + elseif (isset($allModules[$module]['requires'])) { + $result = array_unique(array_merge($result, $allModules[$module]['requires'])); + } + } + } + sort($result); + return $result; + } + + /** + * Get a list of Angular modules that should be loaded on the given + * base-page. + * + * @param string $basePage + * The name of the base-page for which we want a list of moudles. + * @return array + * List of Angular modules. + * Ex: array('crmMailing', 'crmUi', 'crmUtil', 'ngRoute'). + */ + public function resolveDefaultModules($basePage) { + $modules = $this->getModules(); + $result = array(); + foreach ($modules as $moduleName => $module) { + if (in_array($basePage, $module['basePages']) || in_array('*', $module['basePages'])) { + $result[] = $moduleName; + } + } + return $result; + } + /** * Convert any globs in an Angular module to file names. * diff --git a/tests/phpunit/Civi/Angular/ManagerTest.php b/tests/phpunit/Civi/Angular/ManagerTest.php index 51d5ea30d2..3174a35184 100644 --- a/tests/phpunit/Civi/Angular/ManagerTest.php +++ b/tests/phpunit/Civi/Angular/ManagerTest.php @@ -167,6 +167,32 @@ class ManagerTest extends \CiviUnitTestCase { // If crmMailing changes, feel free to use a different example. } + /** + * Get the full, recursive list of dependencies for a set of Angular modules. + */ + public function testResolveDeps() { + // If crmMailing changes, feel free to use a different example. + $expected = array( + 'angularFileUpload', + 'crmAttachment', + 'crmAutosave', + 'crmCxn', + 'crmMailing', + 'crmResource', + 'crmUtil', + 'crmUi', + 'dialogService', + 'ngRoute', + 'ngSanitize', + 'ui.utils', + ); + $input = array('crmMailing', 'crmCxn'); + $actual = $this->angular->resolveDependencies($input); + sort($expected); + sort($actual); + $this->assertEquals($expected, $actual); + } + /** * Example hook. Modifies `2step.html` by adding the attribute * `cat-stevens="ts('wild world')"`. -- 2.25.1