Skip to content

Commit

Permalink
Merge pull request #18 from bcgov/v3-searchapi-upgrade-GDXDSD-6008
Browse files Browse the repository at this point in the history
V3.1.0 Upgrades
  • Loading branch information
ozdemirozcelik authored Mar 7, 2024
2 parents 378f8ad + d293cf8 commit 1a6fc64
Show file tree
Hide file tree
Showing 7 changed files with 186 additions and 80 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.php
22 changes: 10 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@
## GDX-Analytics-Drupal-Snowplow

The GDX Analytics Drupal Snowplow module installs and runs Snowplow
Javascript web trackers, and provides an interface to configure them.
Javascript web trackers and provides an interface to configure them.

## Requirements

This module requires Drupal 10. Backwards compatibilty tests are also conducted for Drupal 9 & 8.
This module requires Drupal 10. Backwards compatibility tests are also conducted for Drupal 9.

## Project Status

This project is currently under development and actively supported by the GDX Analytics Team.

This 3.0 version reverts to using Drupal standard search. If you are currently using the 2.0 version with Search API, do not upgrade to 3.0. A future version of the 3.x will resolve this issue.
This version (3.1.0) now allows the use of GDX Analytics Drupal Snowplow module with other search modules, including Drupal Search API.

## Relevant Repositories
[GDX-Analytics/](https://github.com/bcgov/GDX-Analytics/)
Expand All @@ -21,21 +21,19 @@ This is the central repository for work by the GDX Analytics Team.

## Installation

Install as you would normally install a contributed Drupal module. Visit:
https://www.drupal.org/docs/extending-drupal/installing-modules
for further information.
Install as you would normally install a contributed Drupal module. Visit: https://www.drupal.org/docs/extending-drupal/installing-modules for further information.

In your drupal installation, change directories to your sites/modules/custom folder.
Change directories to your sites/modules/custom folder in your drupal installation.

Clone the project from github: https://github.com/bcgov/GDX-Analytics-Drupal-Snowplow.
Clone the project from github: https://github.com/bcgov/GDX-Analytics-Drupal-Snowplow.

Install the module in Administration » Extend. Select the module; then scroll down and click Install.
Install the module in Administration » Extend. Select the modul, then scroll down and click Install.

## Configuration

Configure settings in Administration » Configuration » GDX Analytics Drupal Snowplow settings.
Configure settings in Administration » Configuration » GDX Analytics Drupal Snowplow settings.

Use this Configuration page to set the collector environment, tracking script URI, and app ID.
Use this Configuration page to set the collector environment, tracking script URI, app ID and search path.

## Getting Help or Reporting an Issue

Expand All @@ -47,7 +45,7 @@ The GDX Analytics Team are the main contributors to this project and maintain th

## How to Contribute

If you would like to contribute, please see our [CONTRIBUTING](CONTRIBUTING.md) guideleines.
If you would like to contribute, please see our [CONTRIBUTING](CONTRIBUTING.md) guidelines.

Please note that this project is released with a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms.

Expand Down
3 changes: 2 additions & 1 deletion config/install/gdx_analytics_drupal_snowplow.settings.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
gdx_collector_mode:
gdx_analytics_snowplow_version:
gdx_analytics_snowplow_script_uri:
gdx_analytics_app_id:
gdx_analytics_app_id:
gdx_analytics_search_path: /search # default search path for standard search
2 changes: 1 addition & 1 deletion gdx_analytics_drupal_snowplow.info.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ description: 'Configures the Javascript tracker for the BC Government GDX Analyt
core: 8.x
core_version_requirement: ^8 || ^9 || ^10
package: 'Analytics'
version: '3.0.0'
version: '3.1.0'
4 changes: 2 additions & 2 deletions gdx_analytics_drupal_snowplow.libraries.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
gdx_analytics_drupal_snowplow.webtracker:
version: 3.0.0
version: 3.1.0
header: true
js:
js/SnowplowInlineCode.js: {}
dependencies:
- core/drupalSettings

gdx_analytics_drupal_snowplow.webtracker_search:
version: 3.0.0
version: 3.1.0
header: true
js:
js/SnowplowInlineCodeSearch.js: {}
Expand Down
172 changes: 120 additions & 52 deletions gdx_analytics_drupal_snowplow.module
Original file line number Diff line number Diff line change
Expand Up @@ -5,80 +5,148 @@
* Contains gdx_analytics_drupal_snowplow.module.
*/

use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Link;
use Drupal\Core\Url;

// Define constants for route names.
define('GDX_ANALYTICS_SETTINGS_FORM_ROUTE', 'gdx_analytics_drupal_snowplow.gdx_analytics_drupal_snowplow_settings_form');
define('GDX_ANALYTICS_HELP_PAGE_ROUTE', 'help.page.gdx_analytics_drupal_snowplow');

// Define constant for tracker versions.
define('GDX_ANALYTICS_WEBTRACKER', 'gdx_analytics_drupal_snowplow/gdx_analytics_drupal_snowplow.webtracker');
define('GDX_ANALYTICS_WEBTRACKER_WITH_SEARCH', 'gdx_analytics_drupal_snowplow/gdx_analytics_drupal_snowplow.webtracker_search');

// Define constant for configuration name.
define('GDX_ANALYTICS_CONFIG_NAME', 'gdx_analytics_drupal_snowplow.settings');

// Define constant for warning message about incomplete configuration.
define('GDX_ANALYTICS_WARNING_CONFIG', t('Please Configure Your GDX Analytics Drupal Snowplow Module.<br>For assistance with filling out this form, contact the GDX Analytics Team.'));

// Define constant for warning message about configuring the module.
define('GDX_ANALYTICS_WARNING_CONFIG_LINK', 'Please click here to configure your GDX Analytics Drupal Snowplow module.');

// Define constant for the module description.
define('GDX_ANALYTICS_MODULE_DESCRIPTION', t('This is the GDX Analytics Drupal Snowplow module.'));


/**
* Implements hook_help().
*/
function gdx_analytics_drupal_snowplow_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
// Main module help for the gdx_analytics_drupal_snowplow module.
case 'help.page.gdx_analytics_drupal_snowplow':
$output = '';
$output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('This is the GDX Analytics Drupal Snowplow module.') . '</p>';
return $output;

default:
function gdx_analytics_drupal_snowplow_help($route_name) {
// Help text for the module. $route_name is as part of Drupal routing system
if ($route_name === GDX_ANALYTICS_HELP_PAGE_ROUTE) {
return '<h3>' . t('About') . '</h3><p>' . GDX_ANALYTICS_MODULE_DESCRIPTION . '</p>';
}
}

/**
* Implements hook_page_attachments().
*/
function gdx_analytics_drupal_snowplow_page_attachments(array &$page) {
//config file for default setting - current empty - gets updated when form is used
$config = \Drupal::config('gdx_analytics_drupal_snowplow.settings');
//we set collector, script uri, app_id, and snowplow_version from the config file
$collector = $config->getRawData()['gdx_collector_mode'];
$script_uri = $config->getRawData()['gdx_analytics_snowplow_script_uri'];
$app_id = $config->getRawData()['gdx_analytics_app_id'];
$snowplow_version = $config->getRawData()['gdx_analytics_snowplow_version'];

$page['#attached']['drupalSettings']['gdx_collector'] = $collector;
$page['#attached']['drupalSettings']['app_id'] = $app_id;
$page['#attached']['drupalSettings']['snowplow_version'] = $snowplow_version;
// Initialize variables.
$admin_context = \Drupal::service('router.admin_context');
$messenger = \Drupal::messenger();
$logger = \Drupal::logger('gdx_analytics_drupal_snowplow');

// Get route info and set up link to settings form.
// This warning shows after module has been installed but no configurations are set
$curr_route_name = \Drupal::routeMatch()->getRouteName();
$form_route = Url::fromRoute('gdx_analytics_drupal_snowplow.gdx_analytics_drupal_snowplow_settings_form');
$link = Link::fromTextAndUrl('Please configure your GDX Analytics Drupal Snowplow module', $form_route);
// Check if the current route is an administrative route.
if ($admin_context->isAdminRoute()) {
// Handle administrative routes.
handleAdminRoutes($logger, $messenger);
} else {
// Handle non-administrative routes.
handleNonAdminRoutes($page, $logger);
}
}

/**
* Handle logic for administrative routes.
*/
function handleAdminRoutes($logger, $messenger) {
// Create link for configuration.
$link = Link::fromTextAndUrl(GDX_ANALYTICS_WARNING_CONFIG_LINK, Url::fromRoute(GDX_ANALYTICS_SETTINGS_FORM_ROUTE));

// Look for standard search default route and enable search event.
if($curr_route_name == 'search.view_node_search') {
$page['#attached']['drupalSettings']['search'] = true;
// Check if configuration is incomplete and display appropriate message.
if (isConfigurationIncomplete($logger, $messenger)) {
if ($route_name === GDX_ANALYTICS_SETTINGS_FORM_ROUTE) {
$messenger->addWarning(GDX_ANALYTICS_WARNING_CONFIG);
} else {
$messenger->addWarning($link);
}
}
}

$messenger = \Drupal::messenger();
/**
* Handle logic for non-administrative routes.
*/
function handleNonAdminRoutes(&$page, $logger) {
try {

// Set admin message if settings form not complete.
if($admin_context->isAdminRoute()){
// Check that the Module has been configured; if there are fields missing, set a warning.
if(empty($collector) || empty($script_uri) || empty($app_id)){
if($curr_route_name == 'gdx_analytics_drupal_snowplow.gdx_analytics_drupal_snowplow_settings_form') {
$messenger->addWarning(t('Please Configure Your GDX Analytics Drupal Snowplow Module.<br>'
. 'For assistance with filling out this form, contact the GDX Analytics Team.'));
}else {
$messenger->addWarning($link);
}
// Get configuration settings.
$settings = \Drupal::config(GDX_ANALYTICS_CONFIG_NAME)->getRawData();

// Set collector, script uri, app_id, snowplow_version and search path.
$page['#attached']['drupalSettings'] = [
'gdx_collector' => $settings['gdx_collector_mode'],
'app_id' => $settings['gdx_analytics_app_id'],
'snowplow_version' => $settings['gdx_analytics_snowplow_version'],
'search_path' => $settings['gdx_analytics_search_path'],
];

// Attach the main tracking code url.
$page['#attached']['drupalSettings']['script_uri'] = $settings['gdx_analytics_snowplow_script_uri'];

// Handle version-specific logic.
if ($settings['gdx_analytics_snowplow_version'] == 1) {
// Handle Web tracker WITH search function
handleTrackerWithSearch($page, $settings);
} elseif ($settings['gdx_analytics_snowplow_version'] == 0) {
// Handle Web tracker WITHOUT search function
$page['#attached']['library'][] = GDX_ANALYTICS_WEBTRACKER;
}

} catch (\Exception $e) {
// Log the exception and display a message
$logger->error('Error processing non-admin routes: @message', ['@message' => $e->getMessage()]);
}
}

// Attach the tracking code to front-end pages based on the configuration
if(!$admin_context->isAdminRoute()){
$page['#attached']['drupalSettings']['script_uri'] = $script_uri;
if($snowplow_version == 1) {
$std_key = Drupal::request()->query->get('keys');
if(!empty($std_key)) {
$page['#attached']['drupalSettings']['search_terms'] = explode(' ', $std_key);
}
$page['#attached']['library'][] = 'gdx_analytics_drupal_snowplow/gdx_analytics_drupal_snowplow.webtracker_search';
} elseif ($snowplow_version == 0) {
$page['#attached']['library'][] = 'gdx_analytics_drupal_snowplow/gdx_analytics_drupal_snowplow.webtracker';
/**
* Handle Web tracker WITH search function
*/
function handleTrackerWithSearch(&$page, $settings) {
// Check if the URI contains the search path (default path is '/search' for Drupal Standard Search).
$curr_uri = \Drupal::request()->getRequestUri();

if (strpos($curr_uri, $settings['gdx_analytics_search_path']) !== false) {
// Retrieve the search query parameters (first value of an array) key value pairs passed to the current script via the URL parameters.
$search_terms = reset($_GET);
if (!empty($search_terms)) {
$page['#attached']['drupalSettings']['search'] = true;
// Assign the array of individual search terms (spaces as delimiters).
$page['#attached']['drupalSettings']['search_terms'] = explode(' ', $search_terms);
}
}
// Attach the tracking code to front-end pages if search toggle is enabled.
$page['#attached']['library'][] = GDX_ANALYTICS_WEBTRACKER_WITH_SEARCH;
}

/**
* Check if configuration settings are incomplete.
*/
function isConfigurationIncomplete($logger, $messenger) {
try {

// Get configuration settings.
$config = \Drupal::config(GDX_ANALYTICS_CONFIG_NAME);
// Retrieve raw data.
$settings = $config->getRawData();

// Check if any setting is empty.
return in_array('', $settings);
} catch (\Exception $e) {
// Log the exception and display a message
$logger->error('Error retrieving configuration: @message', ['@message' => $e->getMessage()]);
$messenger->addError(t('An error occurred while processing the configuration.'));
return false;
}
}
62 changes: 50 additions & 12 deletions src/Form/SettingsForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {

$form['gdx_collector_mode'] = [
'#type' => 'textfield',
'#title' => $this->t('Enter Collector Environment'),
'#title' => $this->t('Collector Environment'),
'#default_value' => $config->get('gdx_collector_mode'),
'#description' => $this->t('Enter the value for the Snowplow endpoint as provided to you. Do not include "https://" or "http://"'),
'#maxlength' => 128,
Expand All @@ -43,7 +43,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
];
$form['gdx_analytics_snowplow_script_uri'] = [
'#type' => 'textfield',
'#title' => $this->t('Enter Snowplow tracking script URI'),
'#title' => $this->t('Snowplow tracking script URI'),
'#default_value' => $config->get('gdx_analytics_snowplow_script_uri'),
'#description' => $this->t('Enter the URL of the Snowplow Library as provided to you. This should be a full URL including "https://" or "http://"'),
'#maxlength' => 256,
Expand All @@ -52,18 +52,27 @@ public function buildForm(array $form, FormStateInterface $form_state) {
];
$form['gdx_analytics_app_id'] = [
'#type' => 'textfield',
'#title' => $this->t('Enter App ID'),
'#title' => $this->t('App ID'),
'#default_value' => $config->get('gdx_analytics_app_id'),
'#description' => $this->t('Enter the value of the App ID for your site as provided to you.'),
'#maxlength' => 256,
'#size' => 60,
'#required' => true,
];
$form['gdx_analytics_search_path'] = [
'#type' => 'textfield',
'#title' => $this->t('Search Path'),
'#default_value' => $config->get('gdx_analytics_search_path'),
'#description' => $this->t('If you are using a search module other than Standard Search, change this search path to the path you require.'),
'#maxlength' => 256,
'#size' => 60,
'#required' => true,
];
$form['gdx_analytics_snowplow_version'] = [
'#type' => 'checkbox',
'#title' => $this->t('Snowplow Search on/off'),
'#title' => $this->t('Snowplow Search Event'),
'#default_value' => $config->get('gdx_analytics_snowplow_version'),
'#description' => $this->t('If checked, Snowplow will track searches made using the Drupal search module.'),
'#description' => $this->t('If checked, Snowplow will track the searches performed on the website.'),
'#size' => 60,
];
return parent::buildForm($form, $form_state);
Expand All @@ -74,6 +83,25 @@ public function buildForm(array $form, FormStateInterface $form_state) {
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
parent::validateForm($form, $form_state);

// Validate the search path to ensure it starts with '/'.
$search_path = $form_state->getValue('gdx_analytics_search_path');
if (!empty($search_path) && substr($search_path, 0, 1) !== '/') {
$form_state->setErrorByName('gdx_analytics_search_path', $this->t('The Search Route must start with "/".'));
}

// Validate the Snowplow tracking script URI to ensure it's a complete URL with 'http://' or 'https://'.
$script_uri = $form_state->getValue('gdx_analytics_snowplow_script_uri');
if (!empty($script_uri) && !filter_var($script_uri, FILTER_VALIDATE_URL) && substr($script_uri, 0, 1) !== 'http') {
$form_state->setErrorByName('gdx_analytics_snowplow_script_uri', $this->t('The Snowplow tracking script URI must be a complete URL starting with "http://" or "https://".'));
}

// Validate the collector mode to ensure it doesn't start with 'http://' or 'https://'.
$collector_mode = $form_state->getValue('gdx_collector_mode');
if (!empty($collector_mode) && (strpos($collector_mode, 'http://') === 0 || strpos($collector_mode, 'https://') === 0)) {
$form_state->setErrorByName('gdx_collector_mode', $this->t('The Collector Environment should not include "http://" or "https://".'));
}

}

/**
Expand All @@ -82,12 +110,22 @@ public function validateForm(array &$form, FormStateInterface $form_state) {
public function submitForm(array &$form, FormStateInterface $form_state) {
parent::submitForm($form, $form_state);

$this->config('gdx_analytics_drupal_snowplow.settings')
->set('gdx_collector_mode', $form_state->getValue('gdx_collector_mode'))
->set('gdx_analytics_snowplow_version', $form_state->getValue('gdx_analytics_snowplow_version'))
->set('gdx_analytics_snowplow_script_uri', $form_state->getValue('gdx_analytics_snowplow_script_uri'))
->set('gdx_analytics_app_id', $form_state->getValue('gdx_analytics_app_id'))
->save();
}
try {
// Save the form values to configuration.
$this->config('gdx_analytics_drupal_snowplow.settings')
->set('gdx_collector_mode', $form_state->getValue('gdx_collector_mode'))
->set('gdx_analytics_snowplow_version', $form_state->getValue('gdx_analytics_snowplow_version'))
->set('gdx_analytics_snowplow_script_uri', $form_state->getValue('gdx_analytics_snowplow_script_uri'))
->set('gdx_analytics_app_id', $form_state->getValue('gdx_analytics_app_id'))
->set('gdx_analytics_search_path', $form_state->getValue('gdx_analytics_search_path'))
->save();

// Drupal will provide "The configuration options have been saved." message

} catch (\Exception $e) {
// Log the exception and display a message
\Drupal::logger('gdx_analytics_drupal_snowplow')->error('An error occurred while saving settings: @message', ['@message' => $e->getMessage()]);
$this->messenger()->addError($this->t('An error occurred while saving settings.'));
}
}
}

0 comments on commit 1a6fc64

Please sign in to comment.