diff --git a/CHANGELOG.txt b/CHANGELOG.txt
new file mode 100755
index 0000000..cab8e6b
--- /dev/null
+++ b/CHANGELOG.txt
@@ -0,0 +1,26 @@
+--- version 2.0.0 ---
+ Ported base functions and logic
+ Added libraries
+ Attached JS with behaviour
+ Implemented Drupal coding standards
+
+--- version 1.0.4 ---
+ Added license routing
+ Added license form
+ Added licence number validation
+ Added user login and license number to default configurations
+
+--- version 1.0.3 ---
+ Added configuration
+ Remove configuration on module uninstalling
+
+--- version 1.0.2 ---
+ All defines replaced by const
+ Added settings form
+
+--- version 1.0.1 ---
+ Added permissions
+ Added routing for settings form
+
+--- version 1.0.0 ---
+ Added composer.json with information
diff --git a/README.txt b/README.txt
new file mode 100755
index 0000000..cf74868
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,12 @@
+Installing LiveChat in Drupal:
+1. Upload `livechat` directory to `/sites/all/modules/`.
+2. Open your Drupal website.
+3. Go to "Administration > Modules" and activate `LiveChat`
+module (under `Other` category).
+4. Go to "Administration > Configuration > Services > LiveChat"
+and follow the instructions.
+
+---
+
+For further information, please visit our website:
+www.livechatinc.com
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..0df75c2
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,10 @@
+{
+ "name": "drupal/livechat",
+ "description": "LiveChat integration.",
+ "type": "drupal-module",
+ "homepage": "https://www.drupal.org/project/livechat",
+ "support": {
+ "issues": "https://www.drupal.org/project/issues/livechat"
+ },
+ "license": "GPL-2.0"
+}
diff --git a/config/install/livechat.configuration.yml b/config/install/livechat.configuration.yml
new file mode 100644
index 0000000..9f27425
--- /dev/null
+++ b/config/install/livechat.configuration.yml
@@ -0,0 +1,7 @@
+livechat_visibility: 0
+livechat_pages: "/admin\n/admin/*\n/node/add*\n/node/*/*\n/user/*/*\n"
+livechat_exclude_system_paths: 1
+livechat_group: ''
+livechat_enabled: 1
+livechat_login: ''
+livechat_license: ''
diff --git a/js/livechat.js b/js/livechat.js
new file mode 100755
index 0000000..fbefb16
--- /dev/null
+++ b/js/livechat.js
@@ -0,0 +1,18 @@
+(function ($, Drupal, drupalSettings) {
+ 'use strict';
+
+ Drupal.behaviors.initLiveChat = {
+ attach: function (context, settings) {
+ if (drupalSettings.LiveChat) {
+ $('body').once('initLiveChat').each(function() {
+ window.__lc = drupalSettings.LiveChat || {};
+
+ var lc = document.createElement('script'); lc.type = 'text/javascript'; lc.async = true;
+ lc.src = ('https:' === document.location.protocol ? 'https://' : 'http://') + 'cdn.livechatinc.com/tracking.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(lc, s);
+ });
+ }
+ }
+ };
+
+})(jQuery, Drupal, drupalSettings);
diff --git a/livechat.info.yml b/livechat.info.yml
new file mode 100644
index 0000000..a8a186b
--- /dev/null
+++ b/livechat.info.yml
@@ -0,0 +1,5 @@
+name: LiveChat
+description: LiveChat integration.
+core: 8.x
+type: module
+configure: livechat.settings
\ No newline at end of file
diff --git a/livechat.install b/livechat.install
new file mode 100755
index 0000000..2baa63d
--- /dev/null
+++ b/livechat.install
@@ -0,0 +1,36 @@
+ t('LiveChat'),
+ 'description' => t('A LiveChat license has not been installed. Please go to LiveChat settings.', [
+ '@url' => Url::fromRoute('livechat.license')->toString(),
+ ]),
+ 'severity' => REQUIREMENT_ERROR,
+ 'value' => t('Not configured'),
+ ];
+ }
+ }
+
+ return $requirements;
+}
+
+/**
+ * Implements hook_uninstall().
+ */
+function livechat_uninstall() {
+ $config_factory = \Drupal::configFactory();
+ $config_factory->getEditable('livechat.configuration')->delete();
+}
diff --git a/livechat.libraries.yml b/livechat.libraries.yml
new file mode 100644
index 0000000..74b91ab
--- /dev/null
+++ b/livechat.libraries.yml
@@ -0,0 +1,4 @@
+livechat:
+ version: 1.x
+ js:
+ js/livechat.js: {}
diff --git a/livechat.links.menu.yml b/livechat.links.menu.yml
new file mode 100644
index 0000000..33dde99
--- /dev/null
+++ b/livechat.links.menu.yml
@@ -0,0 +1,5 @@
+livechat.settings:
+ title: LiveChat
+ description: 'Integrate LiveChat with your website.'
+ route_name: livechat.settings
+ parent: system.admin_config_services
diff --git a/livechat.links.task.yml b/livechat.links.task.yml
new file mode 100644
index 0000000..0a1e4ef
--- /dev/null
+++ b/livechat.links.task.yml
@@ -0,0 +1,9 @@
+livechat.settings_tab:
+ route_name: livechat.settings
+ title: 'Settings'
+ base_route: livechat.settings
+
+livechat.license_tab:
+ route_name: livechat.license
+ title: 'License'
+ base_route: livechat.settings
diff --git a/livechat.module b/livechat.module
new file mode 100644
index 0000000..dec4902
--- /dev/null
+++ b/livechat.module
@@ -0,0 +1,176 @@
+get('livechat_enabled'))) {
+ // Validate permissions for current user and visibility for current path.
+ $user = \Drupal::currentUser();
+ if ($user->hasPermission('use livechat') && livechat_check_visibility()) {
+ $license = $configs->get('livechat_license');
+ $group_id = $configs->get('livechat_group');
+ $settings = livechat_attach_js_settings($license, $group_id);
+
+ if (!empty($settings)) {
+ $attachments['#attached']['drupalSettings']['LiveChat'] = $settings;
+ $attachments['#attached']['library'][] = 'livechat/livechat';
+ }
+ }
+ }
+}
+
+/**
+ * Return settings for attaching LiveChat tracking code.
+ *
+ * @param string $license
+ * LiveChat account license number.
+ * @param string $group_id
+ * Id of the website for multi-site.
+ *
+ * @return array
+ */
+function livechat_attach_js_settings($license, $group_id) {
+ $settings = [];
+
+ if (!empty($license)) {
+ // Allow modules to add custom parameters and visitor information.
+ $params = [];
+ $visitor = [];
+ \Drupal::moduleHandler()->alter('livechat', $params, $visitor);
+
+ $settings = [
+ 'license' => $license,
+ 'params' => $params,
+ 'visitor' => $visitor,
+ ];
+
+ // Add in the group id if it has been set.
+ if (!empty($group_id)) {
+ $settings['LiveChat']['group'] = $group_id;
+ }
+ }
+
+ return $settings;
+}
+
+/**
+ * Checks whether LiveChat is correctly set up.
+ *
+ * @return mixed
+ * License number or FALSE.
+ */
+function livechat_is_installed() {
+ $configs = livechat_configs();
+ $license = $configs->get('livechat_license');
+ if (empty($license)) {
+ return FALSE;
+ }
+
+ return livechat_validate_license($license);
+}
+
+/**
+ * Validates a LiveChat license.
+ */
+function livechat_validate_license($license) {
+ if (empty($license)) {
+ return FALSE;
+ }
+
+ return preg_match('/^[0-9]{1,20}$/', $license);
+}
+
+/**
+ * LiveChat configurations.
+ *
+ * @return \Drupal\Core\Config\ImmutableConfig
+ * An immutable configuration object.
+ */
+function livechat_configs() {
+ $configs = \Drupal::config(LIVECHAT_CONFIGURATION_NAME);
+
+ return $configs;
+}
+
+/**
+ * Checks whether LiveChat should be visible on a path, according to settings.
+ *
+ * @param string $path
+ * The raw URI.
+ *
+ * @return bool
+ * Display or not LiveChat popup.
+ */
+function livechat_check_visibility($path = NULL) {
+ $configs = livechat_configs();
+
+ // Default to the current path.
+ if (!isset($path)) {
+ // Important: in Drupal 8 any path returns with trailing slash.
+ // 'currentPath' !== '/currentPath in matchPath result.
+ // Thanks for this pattern with ^.
+ $path = \Drupal::service('path.current')->getPath();
+ }
+
+ // Visibility settings.
+ $visibility = $configs->get('livechat_visibility');
+ $pages = Unicode::strtolower($configs->get('livechat_pages'));
+
+ // If $visibility is set to LIVECHAT_VISIBILITY_NOTLISTED and the setting for
+ // excluding system paths is enabled, add system paths to the list of pages.
+ $exclude_system_paths = $configs->get('livechat_exclude_system_paths');
+ if ($visibility == LIVECHAT_VISIBILITY_NOTLISTED && $exclude_system_paths) {
+ $pages .= "\n" . LIVECHAT_VISIBILITY_SYSTEM_PATHS;
+ }
+
+ // Get the path alias as lowercase.
+ $path_alias = \Drupal::service('path.alias_manager')->getAliasByPath($path);
+ $expanded_path = Unicode::strtolower($path_alias);
+
+ // Compare the lowercase internal and lowercase path alias (if any).
+ $page_match = \Drupal::service('path.matcher')->matchPath($expanded_path, $pages);
+ if ($expanded_path != $path) {
+ $page_match = $page_match || \Drupal::service('path.matcher')->matchPath($path, $pages);
+ }
+
+ // When $visibility has a value of 0 (LIVECHAT_VISIBILITY_NOTLISTED), the
+ // widget should be displayed on all pages except those listed. When set to 1
+ // (LIVECHAT_VISIBILITY_LISTED), it should only be displayed on listed pages.
+ return !($visibility xor $page_match);
+}
diff --git a/livechat.permissions.yml b/livechat.permissions.yml
new file mode 100644
index 0000000..ec9e662
--- /dev/null
+++ b/livechat.permissions.yml
@@ -0,0 +1,7 @@
+use livechat:
+ title: 'Use LiveChat'
+ description: 'Access the LiveChat widget'
+
+administer livechat:
+ title: 'Administer LiveChat'
+ description: 'Administer the LiveChat settings'
diff --git a/livechat.routing.yml b/livechat.routing.yml
new file mode 100644
index 0000000..fd17cb9
--- /dev/null
+++ b/livechat.routing.yml
@@ -0,0 +1,15 @@
+livechat.settings:
+ path: '/admin/config/services/livechat'
+ defaults:
+ _form: 'Drupal\livechat\Form\LiveChatSettingsForm'
+ _title: 'LiveChat'
+ requirements:
+ _permission: 'administer livechat'
+
+livechat.license:
+ path: '/admin/config/services/livechat/license'
+ defaults:
+ _form: 'Drupal\livechat\Form\LiveChatLicenseForm'
+ _title: 'License'
+ requirements:
+ _permission: 'administer livechat'
diff --git a/src/Form/LiveChatLicenseForm.php b/src/Form/LiveChatLicenseForm.php
new file mode 100644
index 0000000..a8e6487
--- /dev/null
+++ b/src/Form/LiveChatLicenseForm.php
@@ -0,0 +1,140 @@
+httpClient = $http_client;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function create(ContainerInterface $container) {
+ return new static(
+ $container->get('config.factory'),
+ $container->get('http_client')
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getFormId() {
+ return 'livechat_license_form';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getEditableConfigNames() {
+ return [
+ LIVECHAT_CONFIGURATION_NAME,
+ ];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function buildForm(array $form, FormStateInterface $form_state) {
+ $config = $this->config(LIVECHAT_CONFIGURATION_NAME);
+
+ $form['account'] = [
+ '#type' => 'details',
+ '#open' => TRUE,
+ '#title' => $this->t('Account details'),
+ ];
+ $form['account']['login'] = [
+ '#type' => 'email',
+ '#title' => $this->t('LiveChat login'),
+ '#description' => $this->t('User account login: my@email.com'),
+ '#default_value' => $config->get('livechat_login'),
+ '#required' => TRUE,
+ ];
+ if (!empty($config->get('livechat_login')) && !empty($config->get('livechat_license'))) {
+ $form['account']['license_number'] = [
+ '#type' => 'textfield',
+ '#title' => $this->t('License number'),
+ '#default_value' => $config->get('livechat_license'),
+ '#required' => TRUE,
+ '#attributes' => [
+ 'disabled' => 'disabled',
+ ],
+ ];
+ }
+
+ return parent::buildForm($form, $form_state);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validateForm(array &$form, FormStateInterface $form_state) {
+ // Validate the license number.
+ $login = $form_state->getValue('login');
+ if (!empty($login)) {
+ try {
+ $license_number_request = LIVECHAT_API_LICENSE_NUMBER . '/' . $login;
+ $response = $this->httpClient->get($license_number_request);
+ $data = $response->getBody()->getContents();
+ if (!empty($data)) {
+ $json = Json::decode($data);
+ if (!empty($json['number'])) {
+ if (livechat_validate_license($json['number'])) {
+ $form_state->setValue('license_number', $json['number']);
+ }
+ else {
+ $form_state->setErrorByName('login', $this->t('LiveChat license number is incorrect.'));
+ }
+ }
+ elseif (!empty($json['error'])) {
+ $form_state->setErrorByName('login', $json['error']);
+ }
+ }
+ }
+ catch (RequestException $e) {
+ watchdog_exception('LiveChat', $e, $e->getMessage(), [], RfcLogLevel::ERROR, $license_number_request);
+ $form_state->setErrorByName('login', $e->getMessage());
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function submitForm(array &$form, FormStateInterface $form_state) {
+ $values = $form_state->getValues();
+ $this->config(LIVECHAT_CONFIGURATION_NAME)
+ ->set('livechat_login', $values['login'])
+ ->set('livechat_license', $values['license_number'])
+ ->save();
+
+ parent::submitForm($form, $form_state);
+ }
+
+}
diff --git a/src/Form/LiveChatSettingsForm.php b/src/Form/LiveChatSettingsForm.php
new file mode 100644
index 0000000..1184aca
--- /dev/null
+++ b/src/Form/LiveChatSettingsForm.php
@@ -0,0 +1,108 @@
+config(LIVECHAT_CONFIGURATION_NAME);
+
+ $form['path'] = [
+ '#type' => 'details',
+ '#title' => $this->t('Visibility'),
+ '#open' => TRUE,
+ ];
+
+ $form['path']['livechat_visibility'] = [
+ '#type' => 'radios',
+ '#title' => $this->t('Show LiveChat on'),
+ '#options' => array(
+ LIVECHAT_VISIBILITY_NOTLISTED => $this->t('All pages except those listed'),
+ LIVECHAT_VISIBILITY_LISTED => $this->t('Only the listed pages'),
+ ),
+ '#default_value' => $config->get('livechat_visibility'),
+ ];
+
+ $form['path']['livechat_pages'] = [
+ '#type' => 'textarea',
+ '#default_value' => $config->get('livechat_pages'),
+ '#description' => $this->t("Specify pages by using their paths. Enter one path per
+ line. The '*' character is a wildcard. Example paths are %blog for the blog
+ page and %blog-wildcard for every personal blog. %front is the
+ front page.", [
+ '%blog' => 'blog',
+ '%blog-wildcard' => 'blog/*',
+ '%front' => '',
+ ]),
+ ];
+
+ $form['path']['livechat_exclude_system_paths'] = [
+ '#type' => 'checkbox',
+ '#title' => $this->t('Disable LiveChat on common system paths (recommended)'),
+ '#description' => $this->t('LiveChat will not trigger on the following paths: %paths', [
+ '%paths' => str_replace("\n", ', ', LIVECHAT_VISIBILITY_SYSTEM_PATHS),
+ ]),
+ '#default_value' => $config->get('livechat_exclude_system_paths'),
+ ];
+
+ $form['livechat_group'] = [
+ '#type' => 'textfield',
+ '#title' => $this->t('Group Id'),
+ '#description' => $this->t('If you are using LiveChat on more than one website,
+ enter the id of the website here'),
+ '#default_value' => $config->get('livechat_group'),
+ ];
+
+ $form['livechat_enabled'] = [
+ '#type' => 'checkbox',
+ '#title' => $this->t('Enable LiveChat'),
+ '#description' => $this->t('Uncheck this box to disable LiveChat.'),
+ '#default_value' => $config->get('livechat_enabled'),
+ ];
+
+
+ return parent::buildForm($form, $form_state);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function submitForm(array &$form, FormStateInterface $form_state) {
+ $values = $form_state->getValues();
+ $this->config(LIVECHAT_CONFIGURATION_NAME)
+ ->set('livechat_visibility', $values['livechat_visibility'])
+ ->set('livechat_pages', $values['livechat_pages'])
+ ->set('livechat_exclude_system_paths', $values['livechat_exclude_system_paths'])
+ ->set('livechat_group', $values['livechat_group'])
+ ->set('livechat_enabled', $values['livechat_enabled'])
+ ->save();
+
+ parent::submitForm($form, $form_state);
+ }
+
+}