From 67e37261d585ab73e3416db5fa3a952132d2d39d Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Tue, 13 Oct 2020 18:24:47 -0700 Subject: [PATCH] dev/core#2117 - Resources - Allow each snippet to have `aliases` __Before__: Every snippet/resource has a singular name. If the name ever changes, it becomes a backward-compatibility break. __After__: Every snippet/resource has a singular name, and it may optionally have a list of aliases. If the name ever changes, you can leave an alias for backward-compatibility. --- CRM/Core/Resources/CollectionInterface.php | 1 + CRM/Core/Resources/CollectionTrait.php | 40 +++++++++++++++++-- .../Core/Resources/CollectionTestTrait.php | 39 ++++++++++++++++++ 3 files changed, 77 insertions(+), 3 deletions(-) diff --git a/CRM/Core/Resources/CollectionInterface.php b/CRM/Core/Resources/CollectionInterface.php index e3d1433b71..a81db1cfac 100644 --- a/CRM/Core/Resources/CollectionInterface.php +++ b/CRM/Core/Resources/CollectionInterface.php @@ -50,6 +50,7 @@ * * - type: string (markup, template, callback, script, scriptFile, scriptUrl, jquery, style, styleFile, styleUrl) * - name: string, symbolic identifier for this resource + * - aliases: string[], list of alternative names for this resource * - weight: int, default=1. Lower weights come before higher weights. * (If two resources have the same weight, then a secondary ordering will be * used to ensure reproducibility. However, the secondary ordering is diff --git a/CRM/Core/Resources/CollectionTrait.php b/CRM/Core/Resources/CollectionTrait.php index ec7ef18453..38abdea679 100644 --- a/CRM/Core/Resources/CollectionTrait.php +++ b/CRM/Core/Resources/CollectionTrait.php @@ -122,6 +122,10 @@ trait CRM_Core_Resources_CollectionTrait { $snippet['styleFileUrls'] = $theme->resolveUrls($theme->getActiveThemeKey(), $ext, $file); } + if (isset($snippet['aliases']) && !is_array($snippet['aliases'])) { + $snippet['aliases'] = [$snippet['aliases']]; + } + $this->snippets[$snippet['name']] = $snippet; $this->isSorted = FALSE; return $snippet; @@ -149,8 +153,15 @@ trait CRM_Core_Resources_CollectionTrait { * @see CRM_Core_Resources_CollectionInterface::update() */ public function update($name, $snippet) { - $this->snippets[$name] = array_merge($this->snippets[$name], $snippet); - $this->isSorted = FALSE; + foreach ($this->resolveName($name) as $realName) { + $this->snippets[$realName] = array_merge($this->snippets[$realName], $snippet); + $this->isSorted = FALSE; + return $this; + } + + Civi::log()->warning('Failed to update resource by name ({name})', [ + 'name' => $name, + ]); return $this; } @@ -174,7 +185,12 @@ trait CRM_Core_Resources_CollectionTrait { * @see CRM_Core_Resources_CollectionInterface::get() */ public function &get($name) { - return $this->snippets[$name]; + foreach ($this->resolveName($name) as $realName) { + return $this->snippets[$realName]; + } + + $null = NULL; + return $null; } /** @@ -290,6 +306,24 @@ trait CRM_Core_Resources_CollectionTrait { return $this; } + /** + * @param string $name + * Name or alias. + * return array + * List of real names. + */ + protected function resolveName($name) { + if (isset($this->snippets[$name])) { + return [$name]; + } + foreach ($this->snippets as $snippetName => $snippet) { + if (isset($snippet['aliases']) && in_array($name, $snippet['aliases'])) { + return [$snippetName]; + } + } + return []; + } + /** * @param $a * @param $b diff --git a/tests/phpunit/CRM/Core/Resources/CollectionTestTrait.php b/tests/phpunit/CRM/Core/Resources/CollectionTestTrait.php index 3b1a069cbb..63fad9d198 100644 --- a/tests/phpunit/CRM/Core/Resources/CollectionTestTrait.php +++ b/tests/phpunit/CRM/Core/Resources/CollectionTestTrait.php @@ -222,6 +222,45 @@ trait CRM_Core_Resources_CollectionTestTrait { $this->assertEquals(1, $count, 'Expect one registered snippet'); } + /** + * Create a few resources with aliases. Use a mix of reads+writes on both the + * canonical names and aliased names. + */ + public function testAliases() { + $b = $this->createEmptyCollection(); + $b->add([ + 'styleUrl' => 'https://example.com/foo.css', + 'name' => 'foo', + 'aliases' => ['bar', 'borg'], + ]); + $b->add([ + 'scriptUrl' => 'https://example.com/whiz.js', + 'name' => 'whiz', + 'aliases' => 'bang', + ]); + + $this->assertEquals('foo', $b->get('foo')['name']); + $this->assertEquals('foo', $b->get('bar')['name']); + $this->assertEquals('foo', $b->get('borg')['name']); + $this->assertEquals('whiz', $b->get('whiz')['name']); + $this->assertEquals('whiz', $b->get('bang')['name']); + $this->assertEquals(NULL, $b->get('snafu')); + + // Go back+forth, updating with one name then reading with the other. + + $b->get('borg')['borgify'] = TRUE; + $this->assertEquals(TRUE, $b->get('foo')['borgify']); + + $b->get('foo')['d'] = 'ie'; + $this->assertEquals('ie', $b->get('borg')['d']); + + $b->update('bang', ['b52' => 'love shack']); + $this->assertEquals('love shack', $b->get('whiz')['b52']); + + $b->update('whiz', ['golly' => 'gee']); + $this->assertEquals('gee', $b->get('bang')['golly']); + } + /** * Add some items to a bundle - then clear() all of them. */ -- 2.25.1