From 6dc348deb1d22545db77850e4f804f0eddbbbd7d Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Tue, 16 May 2017 02:46:33 -0700 Subject: [PATCH] CRM-20600 - Civi\Angular\Manager - Add hook for modifying partials and dependencies --- CRM/Utils/Hook.php | 22 ++++++++ Civi/Angular/Manager.php | 62 +++++++++++++++++---- tests/phpunit/Civi/Angular/ManagerTest.php | 63 +++++++++++++++++++++- 3 files changed, 136 insertions(+), 11 deletions(-) diff --git a/CRM/Utils/Hook.php b/CRM/Utils/Hook.php index 23e29ef595..2f263a3b79 100644 --- a/CRM/Utils/Hook.php +++ b/CRM/Utils/Hook.php @@ -2107,6 +2107,28 @@ abstract class CRM_Utils_Hook { ); } + /** + * Alter the definition of some Angular HTML partials. + * + * @param \Civi\Angular\Manager $angular + * + * @code + * function example_civicrm_alterAngular($angular) { + * $angular->add(ChangeSet::create('mychanges') + * ->alterHtml('~/crmMailing/EditMailingCtrl/2step.html', function(phpQueryObject $doc) { + * $doc->find('[ng-form="crmMailingSubform"]')->attr('cat-stevens', 'ts(\'wild world\')'); + * }) + * ); + * } + * @endCode + */ + public static function alterAngular($angular) { + $event = \Civi\Core\Event\GenericHookEvent::create(array( + 'angular' => $angular, + )); + Civi::dispatcher()->dispatch('hook_civicrm_alterAngular', $event); + } + /** * This hook is called whenever the system builds a new copy of * semi-static asset. diff --git a/Civi/Angular/Manager.php b/Civi/Angular/Manager.php index 0f19e1dff7..73ae38931c 100644 --- a/Civi/Angular/Manager.php +++ b/Civi/Angular/Manager.php @@ -35,6 +35,12 @@ class Manager { */ protected $cache; + /** + * @var array + * Array(string $name => ChangeSet $change). + */ + protected $changeSets = NULL; + /** * @param \CRM_Core_Resources $res * The resource manager. @@ -143,7 +149,7 @@ class Manager { } /** - * Get the partial HTML documents for a module. + * Get the partial HTML documents for a module (unfiltered). * * @param string $name * Angular module name. @@ -152,12 +158,7 @@ class Manager { * @throws \Exception * Invalid partials configuration. */ - public function getPartials($name) { - $cacheKey = "angular-partials::$name"; - $cacheValue = $this->cache->get($cacheKey); - if ($cacheValue !== NULL) { - return $cacheValue; - } + public function getRawPartials($name) { $module = $this->getModule($name); $result = array(); if (isset($module['partials'])) { @@ -169,12 +170,31 @@ class Manager { $result[$filename] = file_get_contents($partialDir . '/' . $file); } } + return $result; } - - $this->cache->set($cacheKey, $result); return $result; } + /** + * Get the partial HTML documents for a module. + * + * @param string $name + * Angular module name. + * @return array + * Array(string $extFilePath => string $html) + * @throws \Exception + * Invalid partials configuration. + */ + public function getPartials($name) { + $cacheKey = "angular-partials::$name"; + $cacheValue = $this->cache->get($cacheKey); + if ($cacheValue === NULL) { + $cacheValue = ChangeSet::applyResourceFilters($this->getChangeSets(), 'partials', $this->getRawPartials($name)); + $this->cache->set($cacheKey, $cacheValue); + } + return $cacheValue; + } + /** * Get list of translated strings for a module. * @@ -274,7 +294,29 @@ class Manager { } } } - return $result; + + return ChangeSet::applyResourceFilters($this->getChangeSets(), $resType, $result); + } + + /** + * @return array + * Array(string $name => ChangeSet $changeSet). + */ + public function getChangeSets() { + if ($this->changeSets === NULL) { + $this->changeSets = array(); + \CRM_Utils_Hook::alterAngular($this); + } + return $this->changeSets; + } + + /** + * @param ChangeSet $changeSet + * @return \Civi\Angular\Manager + */ + public function add($changeSet) { + $this->changeSets[$changeSet->getName()] = $changeSet; + return $this; } } diff --git a/tests/phpunit/Civi/Angular/ManagerTest.php b/tests/phpunit/Civi/Angular/ManagerTest.php index 3ab7d8939d..51d5ea30d2 100644 --- a/tests/phpunit/Civi/Angular/ManagerTest.php +++ b/tests/phpunit/Civi/Angular/ManagerTest.php @@ -109,7 +109,18 @@ class ManagerTest extends \CiviUnitTestCase { */ public function testGetPartials() { $partials = $this->angular->getPartials('crmMailing'); - $this->assertRegExp('/ng-form="crmMailing/', $partials['~/crmMailing/EditMailingCtrl/2step.html']); + $this->assertRegExp('/ng-form="crmMailingSubform">/', $partials['~/crmMailing/EditMailingCtrl/2step.html']); + // If crmMailing changes, feel free to use a different example. + } + + /** + * Get HTML fragments from an example module. The HTML is modified via hook. + */ + public function testGetPartials_Hooked() { + \CRM_Utils_Hook::singleton()->setHook('civicrm_alterAngular', array($this, 'hook_civicrm_alterAngular')); + + $partials = $this->angular->getPartials('crmMailing'); + $this->assertRegExp('/ng-form="crmMailingSubform" cat-stevens="ts\\(\'wild world\'\\)">/', $partials['~/crmMailing/EditMailingCtrl/2step.html']); // If crmMailing changes, feel free to use a different example. } @@ -119,7 +130,57 @@ class ManagerTest extends \CiviUnitTestCase { public function testGetStrings() { $strings = $this->angular->getStrings('crmMailing'); $this->assertTrue(in_array('Save Draft', $strings)); + $this->assertFalse(in_array('wild world', $strings)); + // If crmMailing changes, feel free to use a different example. + } + + /** + * Get a translatable string from an example module. The HTML is modified via hook. + */ + public function testGetStrings_Hooked() { + \CRM_Utils_Hook::singleton()->setHook('civicrm_alterAngular', array($this, 'hook_civicrm_alterAngular')); + + $strings = $this->angular->getStrings('crmMailing'); + $this->assertTrue(in_array('wild world', $strings)); + // If crmMailing changes, feel free to use a different example. + } + + /** + * Get the list of dependencies for an Angular module. + */ + public function testGetRequires() { + $requires = $this->angular->getResources(array('crmMailing'), 'requires', 'requires'); + $this->assertTrue(in_array('ngRoute', $requires['crmMailing'])); + $this->assertFalse(in_array('crmCatStevens', $requires['crmMailing'])); // If crmMailing changes, feel free to use a different example. } + /** + * Get the list of dependencies for an Angular module. It can be modified via hook. + */ + public function testGetRequires_Hooked() { + \CRM_Utils_Hook::singleton()->setHook('civicrm_alterAngular', array($this, 'hook_civicrm_alterAngular')); + + $requires = $this->angular->getResources(array('crmMailing'), 'requires', 'requires'); + $this->assertTrue(in_array('ngRoute', $requires['crmMailing'])); + $this->assertTrue(in_array('crmCatStevens', $requires['crmMailing'])); + // If crmMailing changes, feel free to use a different example. + } + + /** + * Example hook. Modifies `2step.html` by adding the attribute + * `cat-stevens="ts('wild world')"`. + * + * @param \Civi\Angular\Manager $angular + * @see \CRM_Utils_Hook::alterAngular + */ + public function hook_civicrm_alterAngular($angular) { + $angular->add(ChangeSet::create('cat-stevens') + ->requires('crmMailing', 'crmCatStevens') + ->alterHtml('~/crmMailing/EditMailingCtrl/2step.html', function(\phpQueryObject $doc){ + $doc->find('[ng-form="crmMailingSubform"]')->attr('cat-stevens', 'ts(\'wild world\')'); + }) + ); + } + } -- 2.25.1