diff --git a/composer.json b/composer.json index d84889e1841de013a80316c5c295b2fa6aefe881..40aabbd2b2dd6a9c4caa35a2759b10f1e8216741 100644 --- a/composer.json +++ b/composer.json @@ -125,7 +125,7 @@ "drupal/file_browser": "1.3", "drupal/focal_point": "1.5", "drupal/google_analytics": "^4.0", - "drupal/google_tag": "1.4", + "drupal/google_tag": "1.5", "drupal/honeypot": "2.1.2", "drupal/inline_entity_form": "1.0-rc9", "drupal/libraries": "3.0-beta1", diff --git a/composer.lock b/composer.lock index 52bbed877f75930e2c73f1bf940227249b6bf33b..f998128d73170008d1f1f9ba78381962e65f4597 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "9dc87a1389d83c78b818424bc14b49fd", + "content-hash": "d0832e6942d51f5d5aed796afae2f395", "packages": [ { "name": "alchemy/zippy", @@ -4631,17 +4631,17 @@ }, { "name": "drupal/google_tag", - "version": "1.4.0", + "version": "1.5.0", "source": { "type": "git", "url": "https://git.drupalcode.org/project/google_tag.git", - "reference": "8.x-1.4" + "reference": "8.x-1.5" }, "dist": { "type": "zip", - "url": "https://ftp.drupal.org/files/projects/google_tag-8.x-1.4.zip", - "reference": "8.x-1.4", - "shasum": "1bdc6f93d1c79c27738320597f2185f5de37432f" + "url": "https://ftp.drupal.org/files/projects/google_tag-8.x-1.5.zip", + "reference": "8.x-1.5", + "shasum": "b2929a517cc86bb3e54dded127556f18236a8628" }, "require": { "drupal/core": "^8.8 || ^9" @@ -4649,8 +4649,8 @@ "type": "drupal-module", "extra": { "drupal": { - "version": "8.x-1.4", - "datestamp": "1593179846", + "version": "8.x-1.5", + "datestamp": "1648569365", "security-coverage": { "status": "covered", "message": "Covered by Drupal's security advisory policy" diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 8b1b270136c1ebec852c0480c7d18c3d3ba149fe..60f3654b284108f9f9af0595ff65a40ca07799fd 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -4784,18 +4784,18 @@ }, { "name": "drupal/google_tag", - "version": "1.4.0", - "version_normalized": "1.4.0.0", + "version": "1.5.0", + "version_normalized": "1.5.0.0", "source": { "type": "git", "url": "https://git.drupalcode.org/project/google_tag.git", - "reference": "8.x-1.4" + "reference": "8.x-1.5" }, "dist": { "type": "zip", - "url": "https://ftp.drupal.org/files/projects/google_tag-8.x-1.4.zip", - "reference": "8.x-1.4", - "shasum": "1bdc6f93d1c79c27738320597f2185f5de37432f" + "url": "https://ftp.drupal.org/files/projects/google_tag-8.x-1.5.zip", + "reference": "8.x-1.5", + "shasum": "b2929a517cc86bb3e54dded127556f18236a8628" }, "require": { "drupal/core": "^8.8 || ^9" @@ -4803,8 +4803,8 @@ "type": "drupal-module", "extra": { "drupal": { - "version": "8.x-1.4", - "datestamp": "1591383264", + "version": "8.x-1.5", + "datestamp": "1648569365", "security-coverage": { "status": "covered", "message": "Covered by Drupal's security advisory policy" diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index 39935a758fb11e52f335ffa0788f0f6934536af9..59e1e947277df6824e0cfc700d441876acc0b2a1 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -3,7 +3,7 @@ 'name' => 'osu-asc-webservices/d8-upstream', 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => '94cc3b822d657cc885a015bf9c535fc1673b5084', + 'reference' => 'f81c67fdbbb087e73b37cf6229e1b5f65363f729', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -839,9 +839,9 @@ 'dev_requirement' => false, ), 'drupal/google_tag' => array( - 'pretty_version' => '1.4.0', - 'version' => '1.4.0.0', - 'reference' => '8.x-1.4', + 'pretty_version' => '1.5.0', + 'version' => '1.5.0.0', + 'reference' => '8.x-1.5', 'type' => 'drupal-module', 'install_path' => __DIR__ . '/../../web/modules/google_tag', 'aliases' => array(), @@ -1594,7 +1594,7 @@ 'osu-asc-webservices/d8-upstream' => array( 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => '94cc3b822d657cc885a015bf9c535fc1673b5084', + 'reference' => 'f81c67fdbbb087e73b37cf6229e1b5f65363f729', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), diff --git a/web/modules/google_tag/google_tag.info.yml b/web/modules/google_tag/google_tag.info.yml index 9b15fbf6a8a9f3c86caa05d172259f525323f272..032639ce7ebf5943b7b88643583c308e7395e174 100644 --- a/web/modules/google_tag/google_tag.info.yml +++ b/web/modules/google_tag/google_tag.info.yml @@ -5,7 +5,7 @@ package: 'Statistics' core_version_requirement: ^8.8 || ^9 configure: google_tag.settings_form -# Information added by Drupal.org packaging script on 2020-06-05 -version: '8.x-1.4' +# Information added by Drupal.org packaging script on 2022-03-29 +version: '8.x-1.5' project: 'google_tag' -datestamp: 1591383266 +datestamp: 1648569368 diff --git a/web/modules/google_tag/google_tag.services.yml b/web/modules/google_tag/google_tag.services.yml index b0b7d42701c9b0e195323b510a10d92807c512df..b5b5251962cc2d9172e0f53a980115e5fc58bc19 100644 --- a/web/modules/google_tag/google_tag.services.yml +++ b/web/modules/google_tag/google_tag.services.yml @@ -1,4 +1,4 @@ services: google_tag.container_manager: class: Drupal\google_tag\Entity\ContainerManager - arguments: ['@entity_type.manager', '@module_handler', '@file_system', '@messenger', '@logger.factory'] + arguments: ['@entity_type.manager', '@config.factory', '@file_system', '@cache.data', '@messenger', '@logger.factory'] diff --git a/web/modules/google_tag/src/Entity/Container.php b/web/modules/google_tag/src/Entity/Container.php index 8b5f113674d81c7ac774175dea09379cb5bcdd38..5ab83755fb899feaa68f9bf250c9d71a5e4d3e4e 100644 --- a/web/modules/google_tag/src/Entity/Container.php +++ b/web/modules/google_tag/src/Entity/Container.php @@ -256,7 +256,6 @@ public function snippets() { */ protected function scriptSnippet() { // Gather data. - $compact = \Drupal::config('google_tag.settings')->get('compact_snippet'); $container_id = $this->variableClean('container_id'); $data_layer = $this->variableClean('data_layer'); $query = $this->environmentQuery(); @@ -264,7 +263,6 @@ protected function scriptSnippet() { // Build script snippet. $script = <<<EOS (function(w,d,s,l,i){ - w[l]=w[l]||[]; w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'}); var f=d.getElementsByTagName(s)[0]; @@ -273,13 +271,9 @@ protected function scriptSnippet() { j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl+'$query'; j.async=true; f.parentNode.insertBefore(j,f); - })(window,document,'script','$data_layer','$container_id'); EOS; - if ($compact) { - $script = str_replace(["\n", ' '], '', $script); - } - return $script; + return $this->compactSnippet($script); } /** @@ -290,7 +284,6 @@ protected function scriptSnippet() { */ protected function noscriptSnippet() { // Gather data. - $compact = \Drupal::config('google_tag.settings')->get('compact_snippet'); $container_id = $this->variableClean('container_id'); $query = $this->environmentQuery(); @@ -299,10 +292,7 @@ protected function noscriptSnippet() { <noscript aria-hidden="true"><iframe src="https://www.googletagmanager.com/ns.html?id=$container_id$query" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript> EOS; - if ($compact) { - $noscript = str_replace("\n", '', $noscript); - } - return $noscript; + return $this->compactSnippet($noscript, ["\n"]); } /** @@ -333,8 +323,14 @@ protected function dataLayerSnippet() { if ($classes) { // Build data layer snippet. - $script = "var $data_layer = [" . json_encode($classes) . '];'; - return $script; + $classes = json_encode($classes); + $script = <<<EOS +(function(w,l){ + w[l]=w[l]||[]; + w[l].push($classes); +})(window,'$data_layer'); +EOS; + return $this->compactSnippet($script); } } @@ -370,6 +366,22 @@ public function variableClean($variable) { return trim(json_encode($this->get($variable)), '"'); } + /** + * Returns the compacted snippet. + * + * @param string $snippet + * The JavaScript snippet. + * @param array $search + * The array of strings to replace with blank. + * + * @return string + * The compacted snippet. + */ + protected function compactSnippet($snippet, array $search = ["\n", ' ']) { + $compact = \Drupal::config('google_tag.settings')->get('compact_snippet'); + return $compact ? str_replace($search, '', $snippet) : $snippet; + } + /** * Determines whether to insert the snippet on the response. * @@ -517,6 +529,19 @@ public function snippetURI($type) { return $this->snippetDirectory() . "/google_tag.$type.js"; } + /** + * Returns the snippet cache ID for a snippet type. + * + * @param string $type + * The snippet type. + * + * @return string + * The snippet cache ID. + */ + public function snippetCid($type) { + return "google_tag:$type:{$this->id()}"; + } + /** * Returns tag array for the snippet type. * @@ -530,7 +555,14 @@ public function snippetURI($type) { */ public function fileTag($type, $weight) { $uri = $this->snippetURI($type); - $url = file_url_transform_relative(file_create_url($uri)); + // Remove the if-else when core_version_requirement >= 9.3 for this module. + if (\Drupal::hasService('file_url_generator')) { + $generator = \Drupal::service('file_url_generator'); + $url = $generator->transformRelative($generator->generateAbsoluteString($uri)); + } + else { + $url = file_url_transform_relative(file_create_url($uri)); + } $query_string = \Drupal::state()->get('system.css_js_query_string') ?: '0'; $attachment = [ [ @@ -556,9 +588,7 @@ public function fileTag($type, $weight) { * The tag array. */ public function inlineTag($type, $weight) { - $uri = $this->snippetURI($type); - $url = \Drupal::service('file_system')->realpath($uri); - $contents = @file_get_contents($url); + $contents = $this->getSnippetContents($type); $attachment = [ $contents ? [ '#type' => 'html_tag', @@ -594,9 +624,7 @@ public function noscriptTag($type = 'noscript', $weight = -10) { // As markup, core removes the 'style' attribute from the noscript snippet. // With the inline template type, core does not alter the noscript snippet. - $uri = $this->snippetURI($type); - $url = \Drupal::service('file_system')->realpath($uri); - $contents = @file_get_contents($url); + $contents = $this->getSnippetContents($type); $attachment = $contents ? [ "google_tag_{$type}_tag__{$this->id()}" => [ '#type' => 'inline_template', @@ -607,6 +635,20 @@ public function noscriptTag($type = 'noscript', $weight = -10) { return $attachment; } + /** + * Returns the snippet contents for the snippet type. + * + * @param string $type + * The snippet type. + * + * @return string + * The snippet contents. + */ + public function getSnippetContents($type) { + $cache = \Drupal::service('cache.data')->get($this->snippetCid($type)); + return $cache ? $cache->data : ''; + } + /** * {@inheritdoc} */ diff --git a/web/modules/google_tag/src/Entity/ContainerManager.php b/web/modules/google_tag/src/Entity/ContainerManager.php index f266d285ccfd4d0a0142d308bec5c95b5411ccf0..80fe83e30d7f62edda633e555c3bc85ec6c7d610 100644 --- a/web/modules/google_tag/src/Entity/ContainerManager.php +++ b/web/modules/google_tag/src/Entity/ContainerManager.php @@ -3,9 +3,10 @@ namespace Drupal\google_tag\Entity; // use Drupal\google_tag\Entity\ContainerManagerInterface; +use Drupal\Core\Cache\CacheBackendInterface; +use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Config\Entity\ConfigEntityInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; -use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\File\FileSystemInterface; use Drupal\Core\Logger\LoggerChannelFactoryInterface; use Drupal\Core\Messenger\MessengerInterface; @@ -26,11 +27,11 @@ class ContainerManager implements ContainerManagerInterface { protected $entityTypeManager; /** - * The module handler. + * The module configuration. * - * @var \Drupal\Core\Extension\ModuleHandlerInterface + * @var \Drupal\Core\Config\ConfigFactoryInterface */ - protected $moduleHandler; + protected $config; /** * The file system. @@ -39,6 +40,13 @@ class ContainerManager implements ContainerManagerInterface { */ protected $fileSystem; + /** + * The cache backend. + * + * @var \Drupal\Core\Cache\CacheBackendInterface + */ + protected $cache; + /** * The messenger. * @@ -56,10 +64,11 @@ class ContainerManager implements ContainerManagerInterface { /** * {@inheritdoc} */ - public function __construct(EntityTypeManagerInterface $entity_type_manager, ModuleHandlerInterface $module_handler, FileSystemInterface $file_system, MessengerInterface $messenger, LoggerChannelFactoryInterface $logger_factory) { + public function __construct(EntityTypeManagerInterface $entity_type_manager, ConfigFactoryInterface $config_factory, FileSystemInterface $file_system, CacheBackendInterface $cache, MessengerInterface $messenger, LoggerChannelFactoryInterface $logger_factory) { $this->entityTypeManager = $entity_type_manager; - $this->moduleHandler = $module_handler; + $this->config = $config_factory->get('google_tag.settings'); $this->fileSystem = $file_system; + $this->cache = $cache; $this->messenger = $messenger; $this->logger = $logger_factory->get('google_tag'); } @@ -68,6 +77,11 @@ public function __construct(EntityTypeManagerInterface $entity_type_manager, Mod * {@inheritdoc} */ public function createAssets(ConfigEntityInterface $container) { + $include_script_as_file = $this->config->get('include_file'); + if (!$include_script_as_file) { + return $this->saveSnippets($container); + } + $result = TRUE; $directory = $container->snippetDirectory(); if (!is_dir($directory) || !_google_tag_is_writable($directory) || !_google_tag_is_executable($directory)) { @@ -89,13 +103,22 @@ public function createAssets(ConfigEntityInterface $container) { * {@inheritdoc} */ public function saveSnippets(ConfigEntityInterface $container) { + $include_script_as_file = $this->config->get('include_file'); // Save the altered snippets after hook_google_tag_snippets_alter(). $result = TRUE; $snippets = $container->snippets(); foreach ($snippets as $type => $snippet) { - $uri = $container->snippetURI($type); - $path = $this->fileSystem->saveData($snippet, $uri, FileSystemInterface::EXISTS_REPLACE); - $result = !$path ? FALSE : $result; + if ($include_script_as_file && $type != 'noscript') { + // Write to file. + $uri = $container->snippetURI($type); + $path = $this->fileSystem->saveData($snippet, $uri, FileSystemInterface::EXISTS_REPLACE); + $result = !$path ? FALSE : $result; + } + else { + // Write to cache (noscript is always inline). + $cid = $container->snippetCid($type); + $this->cache->set($cid, $snippet, CacheBackendInterface::CACHE_PERMANENT, $container->getCacheTags()); + } } $args = ['@count' => count($snippets), '%container' => $container->get('label')]; if (!$result) { @@ -161,7 +184,7 @@ public function getScriptAttachments(array &$attachments) { } static $weight = 9; - $include_script_as_file = \Drupal::config('google_tag.settings')->get('include_file'); + $include_script_as_file = $this->config->get('include_file'); $include_classes = $container->get('include_classes'); // @todo Only want one data_layer snippet even with multiple containers. // If user sorts containers such that the first does not define the data @@ -170,20 +193,9 @@ public function getScriptAttachments(array &$attachments) { $types = $include_classes ? ['data_layer', 'script'] : ['script']; // Add data_layer and script snippets to head (no longer by default). - if ($include_script_as_file) { - foreach ($types as $type) { - // @todo Will it matter if file is empty? - // @todo Check config for the whitelist and blacklist classes before adding. - $attachments['#attached']['html_head'][] = $container->fileTag($type, $weight++); - } - } - else { - foreach ($types as $type) { - // @see drupal_get_js() in 7.x core. - // For inline JavaScript to validate as XHTML, all JavaScript containing - // XHTML needs to be wrapped in CDATA. - $attachments['#attached']['html_head'][] = $container->inlineTag($type, $weight++); - } + $function = $include_script_as_file ? 'fileTag' : 'inlineTag'; + foreach ($types as $type) { + $attachments['#attached']['html_head'][] = $container->$function($type, $weight++); } } } @@ -224,8 +236,8 @@ public function createAllAssets() { * {@inheritdoc} */ public function deleteAllAssets() { - if (\Drupal::config('google_tag.settings')->get('flush_snippets')) { - $directory = \Drupal::config('google_tag.settings')->get('uri'); + if ($this->config->get('flush_snippets')) { + $directory = $this->config->get('uri'); if (!empty($directory)) { // Remove any stale files (e.g. module update or machine name change). return $this->fileSystem->deleteRecursive($directory . '/google_tag'); @@ -252,7 +264,10 @@ public function deleteAssets(ConfigEntityInterface $container) { $include_classes = $container->get('include_classes'); $types = $include_classes ? ['data_layer', 'script', 'noscript'] : ['script', 'noscript']; $directory = $container->snippetDirectory(); - $result = $this->fileSystem->deleteRecursive($directory); + $result = TRUE; + if (!empty($directory) && is_dir($directory)) { + $result = $this->fileSystem->deleteRecursive($directory); + } $args = ['@count' => count($types), '%container' => $container->get('label')]; if (!$result) { @@ -275,14 +290,24 @@ public function deleteAssets(ConfigEntityInterface $container) { * {@inheritdoc} */ public function findAssets(ConfigEntityInterface $container) { + $include_script_as_file = $this->config->get('include_file'); $include_classes = $container->get('include_classes'); $types = $include_classes ? ['data_layer', 'script', 'noscript'] : ['script', 'noscript']; - $result = TRUE; + foreach ($types as $type) { - $uri = $container->snippetURI($type); - $result = !is_file($uri) ? FALSE : $result; + if ($include_script_as_file && $type != 'noscript') { + $uri = $container->snippetURI($type); + if (!is_file($uri)) { + return FALSE; + } + } + else { + if (!$cache = $this->cache->get($container->snippetCid($type))) { + return FALSE; + } + } } - return $result; + return TRUE; } } diff --git a/web/modules/google_tag/src/Entity/ContainerManagerInterface.php b/web/modules/google_tag/src/Entity/ContainerManagerInterface.php index 0dd0ec0b7d28ad3f3410ba8170efb979077dda33..6068cb992d0c0eda5cd55f1516fd85f052f488c5 100644 --- a/web/modules/google_tag/src/Entity/ContainerManagerInterface.php +++ b/web/modules/google_tag/src/Entity/ContainerManagerInterface.php @@ -2,9 +2,10 @@ namespace Drupal\google_tag\Entity; +use Drupal\Core\Cache\CacheBackendInterface; +use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Config\Entity\ConfigEntityInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; -use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\File\FileSystemInterface; use Drupal\Core\Logger\LoggerChannelFactoryInterface; use Drupal\Core\Messenger\MessengerInterface; @@ -19,16 +20,18 @@ interface ContainerManagerInterface { * * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager * The entity type manager. - * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler - * The module handler. + * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory + * The config factory. * @param \Drupal\Core\File\FileSystemInterface $file_system * The file system. + * @param \Drupal\Core\Cache\CacheBackendInterface $cache + * The cache backend. * @param \Drupal\Core\Messenger\MessengerInterface $messenger * The messenger. * @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $logger_factory * The logger factory. */ - public function __construct(EntityTypeManagerInterface $entity_type_manager, ModuleHandlerInterface $module_handler, FileSystemInterface $file_system, MessengerInterface $messenger, LoggerChannelFactoryInterface $logger_factory); + public function __construct(EntityTypeManagerInterface $entity_type_manager, ConfigFactoryInterface $config_factory, FileSystemInterface $file_system, CacheBackendInterface $cache, MessengerInterface $messenger, LoggerChannelFactoryInterface $logger_factory); /** * Prepares directory for and saves snippet files for a container. diff --git a/web/modules/google_tag/src/Form/ContainerForm.php b/web/modules/google_tag/src/Form/ContainerForm.php index 5b5a5964661e1e0875c41fb80ee7057b16b3b6bb..446a42c8db2bf8665e07f539e8b1da643453a9c9 100644 --- a/web/modules/google_tag/src/Form/ContainerForm.php +++ b/web/modules/google_tag/src/Form/ContainerForm.php @@ -82,7 +82,7 @@ public function form(array $form, FormStateInterface $form_state) { // Build form elements. $form['label'] = [ '#type' => 'textfield', - '#title' => 'Label', + '#title' => $this->t('Label'), '#default_value' => $container->label(), '#required' => TRUE, ]; @@ -160,7 +160,7 @@ public function generalFieldset(FormStateInterface &$form_state) { $fieldset['weight'] = [ '#type' => 'weight', - '#title' => 'Weight', + '#title' => $this->t('Weight'), '#default_value' => $container->get('weight'), ]; diff --git a/web/modules/google_tag/tests/src/Functional/GTMMultipleTest.php b/web/modules/google_tag/tests/src/Functional/GTMMultipleTest.php index ce03c5fcbf6c789138488017cd9f2521cc7c5164..6acd621b286d9582fdeaf90c9bef84460bb3deb5 100644 --- a/web/modules/google_tag/tests/src/Functional/GTMMultipleTest.php +++ b/web/modules/google_tag/tests/src/Functional/GTMMultipleTest.php @@ -49,13 +49,13 @@ protected function createData() { /** * {@inheritdoc} */ - protected function checkSnippetFiles() { + protected function checkSnippetContents() { foreach ($this->variables as $key => $variables) { $message = "Start on container $key"; parent::assertTrue(TRUE, $message); foreach ($this->types as $type) { - $url = "$this->basePath/google_tag/{$key}/google_tag.$type.js"; - $contents = @file_get_contents($url); + $function = $type == 'noscript' ? 'getSnippetFromCache' : 'getSnippetFromFile'; + $contents = $this->$function($key, $type); $function = "verify{$type}Snippet"; $this->$function($contents, $this->variables[$key]); } @@ -68,17 +68,48 @@ protected function checkSnippetFiles() { protected function checkPageResponse() { parent::checkPageResponse(); + $include_file = $this->config('google_tag.settings')->get('include_file'); + $include_file ? $this->checkPageResponseFile() : $this->checkPageResponseInline(); + } + + /** + * Inspect the page response (based on file source). + */ + protected function checkPageResponseFile() { foreach ($this->variables as $key => $variables) { $this->drupalGet(''); $message = "Start on container $key"; parent::assertTrue(TRUE, $message); foreach ($this->types as $type) { $uri = "$this->basePath/google_tag/{$key}/google_tag.$type.js"; - $url = file_url_transform_relative(file_create_url($uri)); + // Remove the if-else when core_version_requirement >= 9.3 for this module. + if (\Drupal::hasService('file_url_generator')) { + $generator = \Drupal::service('file_url_generator'); + $url = $generator->transformRelative($generator->generateAbsoluteString($uri)); + } + else { + $url = file_url_transform_relative(file_create_url($uri)); + } $function = "verify{$type}Tag"; $this->$function($url, $this->variables[$key]); } } } + /** + * Inspect the page response (based on inline snippet). + */ + protected function checkPageResponseInline() { + foreach ($this->variables as $key => $variables) { + $this->drupalGet(''); + $message = "Start on container $key"; + parent::assertTrue(TRUE, $message); + foreach ($this->types as $type) { + $contents = $this->getSnippetFromCache($key, $type); + $function = "verify{$type}TagInline"; + $this->$function($this->variables[$key], $contents); + } + } + } + } diff --git a/web/modules/google_tag/tests/src/Functional/GTMTestBase.php b/web/modules/google_tag/tests/src/Functional/GTMTestBase.php index 3743f9995f12d0c3ce446b53d202e8c22f79eb55..22e5a130934d4931264da9e39b8b3061cc8461ec 100644 --- a/web/modules/google_tag/tests/src/Functional/GTMTestBase.php +++ b/web/modules/google_tag/tests/src/Functional/GTMTestBase.php @@ -77,13 +77,16 @@ public function testModule() { // Create containers in code. $this->createData(); $this->saveContainers(); - $this->checkSnippetFiles(); + $this->checkSnippetContents(); $this->checkPageResponse(); // Delete containers. $this->deleteContainers(); // Create containers in user interface. $this->submitContainers(); - $this->checkSnippetFiles(); + $this->checkSnippetContents(); + $this->checkPageResponse(); + // Switch to inline snippets. + $this->modifySettings(FALSE); $this->checkPageResponse(); } catch (\Exception $e) { @@ -97,13 +100,17 @@ public function testModule() { /** * Modify settings for test purposes. + * + * @param bool $include_file + * The include_file module setting. */ - protected function modifySettings() { + protected function modifySettings($include_file = TRUE) { // Modify default settings. // These should propagate to each container created in test. $config = $this->config('google_tag.settings'); $settings = $config->get(); unset($settings['_core']); + $settings['include_file'] = $include_file; $settings['flush_snippets'] = 1; $settings['debug_output'] = 1; $settings['_default_container']['role_toggle'] = 'include listed'; @@ -183,7 +190,7 @@ protected function deleteContainers() { // Confirm no snippet files. $message = 'No snippet files found after delete'; - parent::assertTrue(!is_dir($directory . '/google_tag'), $message); + parent::assertDirectoryNotExists($directory . '/google_tag', $message); } /** @@ -194,7 +201,8 @@ protected function submitContainers() { foreach ($this->variables as $key => $variables) { $edit = (array) $variables; - $this->drupalPostForm('/admin/config/system/google-tag/add', $edit, 'Save'); + $this->drupalGet('/admin/config/system/google-tag/add'); + $this->submitForm($edit, 'Save'); $text = 'Created @count snippet files for %container container based on configuration.'; $args = ['@count' => 3, '%container' => $variables->label]; @@ -209,9 +217,26 @@ protected function submitContainers() { } /** - * Inspect the snippet files. + * Returns the snippet contents. + */ + protected function getSnippetFromFile($key, $type) { + $url = "$this->basePath/google_tag/{$key}/google_tag.$type.js"; + return @file_get_contents($url); + } + + /** + * Returns the snippet contents. + */ + protected function getSnippetFromCache($key, $type) { + $cid = "google_tag:$type:$key"; + $cache = $this->container->get('cache.data')->get($cid); + return $cache ? $cache->data : ''; + } + + /** + * Inspect the snippet contents. */ - protected function checkSnippetFiles() { + protected function checkSnippetContents() { } /** @@ -232,19 +257,19 @@ protected function verifyScriptSnippet($contents, $variables) { } /** - * Verify the snippet file contents. + * Verify the snippet cache contents. */ protected function verifyNoScriptSnippet($contents, $variables) { $status = strpos($contents, "id=$variables->container_id") !== FALSE; - $message = 'Found in noscript snippet file: container_id'; + $message = 'Found in noscript snippet cache: container_id'; parent::assertTrue($status, $message); $status = strpos($contents, "gtm_preview=$variables->environment_id") !== FALSE; - $message = 'Found in noscript snippet file: environment_id'; + $message = 'Found in noscript snippet cache: environment_id'; parent::assertTrue($status, $message); $status = strpos($contents, "gtm_auth=$variables->environment_token") !== FALSE; - $message = 'Found in noscript snippet file: environment_token'; + $message = 'Found in noscript snippet cache: environment_token'; parent::assertTrue($status, $message); } @@ -279,7 +304,38 @@ protected function verifyScriptTag($realpath) { /** * Verify the tag in page response. */ - protected function verifyNoScriptTag($realpath, $variables) { + protected function verifyScriptTagInline($variables, $cache) { + $id = $variables->container_id; + $xpath = "//script[contains(text(), '$id')]"; + $elements = $this->xpath($xpath); + if (!is_array($elements) || count($elements) > 1) { + $message = 'Found only one script tag'; + parent::assertFalse($status, $message); + return; + } + + $contents = $elements[0]->getHtml(); + + $status = strpos($contents, "(window,document,'script','dataLayer','$id')") !== FALSE; + $message = 'Found in script tag: container_id and data data_layer'; + parent::assertTrue($status, $message); + + $status = strpos($contents, "gtm_preview=$variables->environment_id") !== FALSE; + $message = 'Found in script tag: environment_id'; + parent::assertTrue($status, $message); + + $status = strpos($contents, "gtm_auth=$variables->environment_token") !== FALSE; + $message = 'Found in script tag: environment_token'; + parent::assertTrue($status, $message); + + $message = 'Contents of script tag matches cache'; + parent::assertTrue($contents == $cache, $message); + } + + /** + * Verify the tag in page response. + */ + protected function verifyNoScriptTag($realpath, $variables, $cache = '') { // The tags are sorted by weight. $index = isset($variables->weight) ? $variables->weight - 1 : 0; $xpath = '//noscript//iframe'; @@ -297,6 +353,18 @@ protected function verifyNoScriptTag($realpath, $variables) { $status = strpos($contents, "gtm_auth=$variables->environment_token") !== FALSE; $message = 'Found in noscript tag: environment_token'; parent::assertTrue($status, $message); + + if ($cache) { + $message = 'Contents of noscript tag matches cache'; + parent::assertTrue(strpos($cache, $contents) !== FALSE, $message); + } + } + + /** + * Verify the tag in page response. + */ + protected function verifyNoScriptTagInline($variables, $cache) { + $this->verifyNoScriptTag('', $variables, $cache); } }