From 7acb5bf1770af87298596c58bfb4f61529785bbf Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Tue, 16 May 2023 12:45:02 -0700 Subject: [PATCH] (REF) Civi/Esm - Use traits --- Civi/Esm/BasicLoaderTrait.php | 139 ++++++++++++++++++++++++++++++++++ Civi/Esm/BrowserLoader.php | 96 +++-------------------- Civi/Esm/ShimLoader.php | 37 ++++----- 3 files changed, 164 insertions(+), 108 deletions(-) create mode 100644 Civi/Esm/BasicLoaderTrait.php diff --git a/Civi/Esm/BasicLoaderTrait.php b/Civi/Esm/BasicLoaderTrait.php new file mode 100644 index 0000000000..c086922e87 --- /dev/null +++ b/Civi/Esm/BasicLoaderTrait.php @@ -0,0 +1,139 @@ + + * { "import": {"civicrm/": "https://example.com/sites/all/modules/civicrm"}} + * + * + * + * + * However, subclasses may use different HTML. + */ +trait BasicLoaderTrait { + + /** + * @return array + */ + public static function getSubscribedEvents() { + return [ + '&civi.esm.useModule' => 'onUseModule', + '&civi.region.render' => 'onRegionRender', + ]; + } + + /** + * @var \Civi\Esm\ImportMap + * @inject esm.import_map + */ + protected $importMap; + + /** + * Do we need to send an import-map for the current page-view? + * + * For the moment, we figure this dynamically -- based on whether any "esm" scripts have + * been added. During the early stages (where ESMs aren't in widespread use), this seems + * safer. However, in the future, we might find some kind of race (e.g. where the system + * renders "" before it decides on a specific "' + */ + abstract protected function renderImportMap(array $importMap): string; + + /** + * @param array $snippet + * The module resource being rendered, as per "CollectionInterface::add()". + * Ex: ['type' => 'scriptUrl', 'scriptUrl' => 'https://example.com/foo.js', 'esm' => TRUE] + * @return string + * HTML + * @see \CRM_Core_Resources_CollectionInterface::add() + */ + public function renderModule(array $snippet): string { + switch ($snippet['type']) { + case 'script': + return $this->renderModuleScript($snippet); + + case 'scriptUrl': + return $this->renderModuleUrl($snippet); + + default: + $class = get_class($this); + Civi::log()->warning($class . ' does not support {type}', ['type' => $snippet['type']]); + return ''; + } + } + + /** + * @param array $snippet + * The module resource being rendered, as per "CollectionInterface::add()". + * Ex: ['type' => 'scriptUrl', 'scriptUrl' => 'https://example.com/foo.js', 'esm' => TRUE] + * @return string + * HTML + * @see \CRM_Core_Resources_CollectionInterface::add() + */ + abstract protected function renderModuleScript(array $snippet): string; + + /** + * @param array $snippet + * The module resource being rendered, as per "CollectionInterface::add()". + * Ex: ['type' => 'scriptUrl', 'scriptUrl' => 'https://example.com/foo.js', 'esm' => TRUE] + * @return string + * HTML + * @see \CRM_Core_Resources_CollectionInterface::add() + */ + abstract protected function renderModuleUrl(array $snippet): string; + +} diff --git a/Civi/Esm/BrowserLoader.php b/Civi/Esm/BrowserLoader.php index 8dedf41b5c..29b9d73bcd 100644 --- a/Civi/Esm/BrowserLoader.php +++ b/Civi/Esm/BrowserLoader.php @@ -28,75 +28,10 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface; */ class BrowserLoader extends \Civi\Core\Service\AutoService implements EventSubscriberInterface { - /** - * @return array - */ - public static function getSubscribedEvents() { - return [ - '&civi.esm.useModule' => 'onUseModule', - '&civi.region.render' => 'onRegionRender', - ]; - } - - /** - * @var \Civi\Esm\ImportMap - * @inject esm.import_map - */ - protected $importMap; - - /** - * Do we need to send an import-map for the current page-view? - * - * For the moment, we figure this dynamically -- based on whether any "esm" scripts have - * been added. During the early stages (where ESMs aren't in widespread use), this seems - * safer. However, in the future, we might find some kind of race (e.g. where the system - * renders "" before it decides on a specific "' + * @inheritDoc */ protected function renderImportMap(array $importMap): string { $flags = JSON_UNESCAPED_SLASHES; @@ -107,26 +42,17 @@ class BrowserLoader extends \Civi\Core\Service\AutoService implements EventSubsc } /** - * @param array $snippet - * The module resource being rendered, as per "CollectionInterface::add()". - * Ex: ['type' => 'scriptUrl', 'scriptUrl' => 'https://example.com/foo.js', 'esm' => TRUE] - * @return string - * HTML - * @see \CRM_Core_Resources_CollectionInterface::add() + * @inheritDoc */ - public function renderModule(array $snippet): string { - switch ($snippet['type']) { - case 'script': - return sprintf("\n", $snippet['script']); - - case 'scriptUrl': - return sprintf("\n", $snippet['scriptUrl']); + protected function renderModuleScript(array $snippet): string { + return sprintf("\n", $snippet['script']); + } - default: - $class = get_class($this); - Civi::log()->warning($class . ' does not support {type}', ['type' => $snippet['type']]); - return ''; - } + /** + * @inheritDoc + */ + protected function renderModuleUrl(array $snippet): string { + return sprintf("\n", $snippet['scriptUrl']); } } diff --git a/Civi/Esm/ShimLoader.php b/Civi/Esm/ShimLoader.php index af7eebdb1d..a7e46d9fa7 100644 --- a/Civi/Esm/ShimLoader.php +++ b/Civi/Esm/ShimLoader.php @@ -3,6 +3,7 @@ namespace Civi\Esm; use Civi; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * The ShimLoader leverages `es-module-shims` for loading ECMAScript Modules (ESM's). @@ -33,15 +34,12 @@ use Civi; * * @service esm.loader.shim */ -class ShimLoader extends BrowserLoader { +class ShimLoader extends \Civi\Core\Service\AutoService implements EventSubscriberInterface { + + use BasicLoaderTrait; /** - * Format the list of imports as an HTML tag. - * - * @param array $importMap - * Ex: ['imports' => ['square/' => 'https://example.com/square/']] - * @return string - * Ex: '' + * @inheritDoc */ protected function renderImportMap(array $importMap): string { $shimUrl = Civi::paths()->getUrl('[civicrm.bower]/es-module-shims/dist/es-module-shims.js'); @@ -55,24 +53,17 @@ class ShimLoader extends BrowserLoader { } /** - * @param array $snippet - * The module resource being rendered, as per "CollectionInterface::add()". - * Ex: ['type' => 'scriptUrl', 'scriptUrl' => 'https://example.com/foo.js', 'esm' => TRUE] - * @return string - * HTML - * @see \CRM_Core_Resources_CollectionInterface::add() + * @inheritDoc */ - public function renderModule(array $snippet): string { - switch ($snippet['type']) { - case 'script': - return sprintf("\n", $snippet['script']); - - case 'scriptUrl': - return sprintf("\n", $snippet['scriptUrl']); + protected function renderModuleScript(array $snippet): string { + return sprintf("\n", $snippet['script']); + } - default: - return parent::renderModule($snippet); - } + /** + * @inheritDoc + */ + protected function renderModuleUrl(array $snippet): string { + return sprintf("\n", $snippet['scriptUrl']); } } -- 2.25.1