Skip to content
Snippets Groups Projects
Commit 5058addd authored by hoffismo's avatar hoffismo
Browse files

Initial commit.

parents
Branches
Tags 8.x-1.0-beta1
No related merge requests found
Showing
with 588 additions and 0 deletions
Smart IP Language Detection
redirect: false
smartip_language_detection.smartip_language_mapping.*:
type: config_entity
label: 'Mapping entity config'
mapping:
uuid:
type: string
id:
type: string
label: 'ID'
label:
type: label
label: 'Label'
country:
type: string
label: 'Country'
language:
type: string
label: 'Language'
name: 'Smart IP Language Detection'
description: 'Detects the user''s language by IP'
type: module
core: 8.x
package: Location
dependencies:
- drupal:language
- drupal:locale
- smart_ip:smart_ip
<?php
/**
* @file
* Module maintenance functions for install, uninstall and updates.
*/
use Drupal\smartip_language_detection\Entity\SmartIpLanguageMapping;
/**
* Create Smart IP language mapping entity based on previous configs.
*/
function smartip_language_detection_update_8100() {
$mappings_config = \Drupal::configFactory()->getEditable('smartip_language_detection.mappings');
$config_mappings = $mappings_config->get('detection');
if (empty($config_mappings)) {
return;
}
foreach ($config_mappings as $country => $language) {
$mapping = SmartIpLanguageMapping::create([
'country' => $country,
'language' => $language,
]);
try {
$mapping->save();
}
catch (\Exception $e) {
}
}
$mappings_config->delete();
}
entity.smartip_language_mapping.add_form:
route_name: 'entity.smartip_language_mapping.add_form'
title: 'Add mapping'
appears_on:
- entity.smartip_language_mapping.collection
<?php
/**
* @file
* The Smart IP Language Detection module.
*/
smartip.language_detection:
path: '/admin/config/regional/language/detection/smartip'
defaults:
_title: 'Smart IP Language Detection configuration'
_form: '\Drupal\smartip_language_detection\Form\SmartIpLanguageDetectionForm'
requirements:
_permission: 'administer languages'
<?php
namespace Drupal\smartip_language_detection\Entity;
use Drupal\Core\Config\Entity\ConfigEntityBase;
use Drupal\Core\Entity\EntityMalformedException;
/**
* Defines the Smart IP language mapping entity.
*
* @ConfigEntityType(
* id = "smartip_language_mapping",
* label = @Translation("Smart IP language mapping"),
* handlers = {
* "view_builder" = "Drupal\Core\Entity\EntityViewBuilder",
* "list_builder" = "Drupal\smartip_language_detection\SmartIpLanguageMappingListBuilder",
* "form" = {
* "add" = "Drupal\smartip_language_detection\Form\SmartIpLanguageMappingForm",
* "edit" = "Drupal\smartip_language_detection\Form\SmartIpLanguageMappingForm",
* "delete" = "Drupal\smartip_language_detection\Form\SmartIpLanguageMappingDeleteForm"
* },
* "route_provider" = {
* "html" = "Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider",
* },
* },
* config_prefix = "smartip_language_mapping",
* admin_permission = "administer smartip_language_mapping",
* entity_keys = {
* "id" = "id",
* "label" = "label",
* "uuid" = "uuid"
* },
* links = {
* "canonical" = "/admin/config/regional/language/detection/smartip/{smartip_language_mapping}",
* "add-form" = "/admin/config/regional/language/detection/smartip/add",
* "edit-form" = "/admin/config/regional/language/detection/smartip/{smartip_language_mapping}/edit",
* "delete-form" = "/admin/config/regional/language/detection/smartip/{smartip_language_mapping}/delete",
* "collection" = "/admin/config/regional/language/detection/smartip"
* }
* )
*/
class SmartIpLanguageMapping extends ConfigEntityBase {
/**
* The mapping ID.
*
* @var string
*/
protected $id;
/**
* The mapping label.
*
* @var string
*/
protected $label;
/**
* The mapping country.
*
* @var string
*/
protected $country;
/**
* The mapping language.
*
* @var string
*/
protected $language;
/**
* Get the country of the mapping.
*/
public function getCountry() {
return $this->country;
}
/**
* Get the user friendly name of country.
*
* @return string|null
* The human readable country name.
*/
public function getCountryName() {
if (!$this->country) {
return NULL;
}
$countries = \Drupal::service('country_manager')->getList();
return isset($countries[$this->country]) ? $countries[$this->country] : NULL;
}
/**
* Get the language of the mapping.
*/
public function getLanguage() {
return $this->language;
}
/**
* Get the user friendly name of language.
*
* @return string|null
* The human readable language name.
*/
public function getLanguageName() {
if (!$this->language) {
return NULL;
}
return \Drupal::languageManager()->getLanguageName($this->language);
}
/**
* {@inheritdoc}
*
* @throws \Drupal\Core\Entity\EntityMalformedException
* When attempting to save a Smart IP language mapping with no country.
*/
public function save() {
if (empty($this->country)) {
throw new EntityMalformedException('The Smart IP language mapping does not have a country.');
}
// Auto populate machine name and label.
$this->label = $this->country;
$this->id = 'smartip_language_mapping_' . strtolower($this->country);
parent::save();
}
}
<?php
namespace Drupal\smartip_language_detection\Form;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
/**
* Defines a form for displaying the Smart IP language detection settings.
*/
class SmartIpLanguageDetectionForm extends ConfigFormBase {
/**
* {@inheritdoc}
*/
protected function getEditableConfigNames() {
return [
'smartip_language_detection.settings',
];
}
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'smartip_language_detection_configure_form';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$config = $this->config('smartip_language_detection.settings');
$form['heading'] = [
'#type' => 'html_tag',
'#tag' => 'h2',
'#value' => $this->t('Smart IP language detection settings'),
];
$form['redirect'] = [
'#type' => 'checkbox',
'#title' => 'Redirect to the language path',
'#default_value' => $config->get('redirect'),
];
return parent::buildForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$config = $this->config('smartip_language_detection.settings');
$config->set('redirect', $form_state->getValue('redirect'));
$config->save();
parent::submitForm($form, $form_state);
}
}
<?php
namespace Drupal\smartip_language_detection\Form;
use Drupal\Core\Entity\EntityConfirmFormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
/**
* Builds the form to delete Smart IP language mapping entities.
*/
class SmartIpLanguageMappingDeleteForm extends EntityConfirmFormBase {
/**
* {@inheritdoc}
*/
public function getQuestion() {
return $this->t('Are you sure you want to delete %label mapping?', ['%label' => $this->entity->getCountryName()]);
}
/**
* {@inheritdoc}
*/
public function getCancelUrl() {
return new Url('entity.smartip_language_mapping.collection');
}
/**
* {@inheritdoc}
*/
public function getConfirmText() {
return $this->t('Delete');
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
/** @var \Drupal\smartip_language_detection\Entity\SmartIpLanguageMapping $entity */
$entity = $this->entity;
$entity->delete();
drupal_set_message(
$this->t('Deleted the %label mapping.', ['%label' => $entity->getCountryName()])
);
$form_state->setRedirectUrl($this->getCancelUrl());
}
}
<?php
namespace Drupal\smartip_language_detection\Form;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\smartip_language_detection\Entity\SmartIpLanguageMapping;
/**
* Class SmartIpLanguageMappingForm.
*
* @package Drupal\smartip_language_detection\Form
*/
class SmartIpLanguageMappingForm extends EntityForm {
/**
* {@inheritdoc}
*/
public function form(array $form, FormStateInterface $form_state) {
/** @var \Drupal\smartip_language_detection\Entity\SmartIpLanguageMapping $entity */
$entity = $this->entity;
$form['country'] = [
'#title' => $this->t('Country'),
'#type' => 'select',
'#default_value' => $entity->getCountry(),
'#options' => \Drupal::service('country_manager')->getList(),
'#required' => TRUE,
];
$form['language'] = [
'#title' => $this->t('Language'),
'#type' => 'language_select',
'#default_value' => $entity->getLanguage(),
'#languages' => LanguageInterface::STATE_CONFIGURABLE,
'#required' => TRUE,
];
return parent::form($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
/** @var \Drupal\smartip_language_detection\Entity\SmartIpLanguageMapping $entity */
$entity = $this->entity;
$db_entities = SmartIpLanguageMapping::loadMultiple();
/** @var \Drupal\smartip_language_detection\Entity\SmartIpLanguageMapping $db_entity */
foreach ($db_entities as $db_entity) {
if ($db_entity->id() === $entity->id()) {
continue;
}
if ($db_entity->getCountry() === $entity->getCountry()) {
$form_state->setErrorByName('country', $this->t('The country code %country_code already exists and must be unique.', ['%country_code' => $entity->getCountry()]));
}
elseif ($db_entity->getLanguage() === $entity->getLanguage()) {
$form_state->setErrorByName('language', $this->t('The language code %langcode already exists and must be unique.', ['%langcode' => $entity->getLanguage()]));
}
}
}
/**
* {@inheritdoc}
*/
public function save(array $form, FormStateInterface $form_state) {
/** @var \Drupal\smartip_language_detection\Entity\SmartIpLanguageMapping $entity */
$entity = $this->entity;
$status = $entity->save();
switch ($status) {
case SAVED_NEW:
drupal_set_message($this->t('Created the %label mapping.', [
'%label' => $entity->getCountryName(),
]));
break;
default:
drupal_set_message($this->t('Saved the %label mapping.', [
'%label' => $entity->getCountryName(),
]));
}
$form_state->setRedirectUrl($entity->toUrl('collection'));
}
}
<?php
namespace Drupal\smartip_language_detection\Plugin\LanguageNegotiation;
use Drupal\language\LanguageNegotiationMethodBase;
use Drupal\smart_ip\SmartIp;
use Drupal\smartip_language_detection\Entity\SmartIpLanguageMapping;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\State\StateInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
/**
* Class for identifying language from the IP address.
*
* @LanguageNegotiation(
* id = Drupal\smartip_language_detection\Plugin\LanguageNegotiation\SmartIpLanguageDetection::METHOD_ID,
* weight = -1,
* name = @Translation("IP address"),
* description = @Translation("Uses Smart IP to get language based on visitor's IP address."),
* config_route_name = "smartip.language_detection"
* )
*/
class SmartIpLanguageDetection extends LanguageNegotiationMethodBase implements ContainerFactoryPluginInterface {
/**
* The language negotiation method id.
*/
const METHOD_ID = 'smartip-language-detection';
/**
* The state service.
*
* @var \Drupal\Core\State\StateInterface
*/
protected $state;
/**
* Constructs a new SmartIpLanguageDetection instance.
*
* @param \Drupal\Core\State\StateInterface $state
* The state service.
*/
public function __construct(StateInterface $state) {
$this->state = $state;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$container->get('state')
);
}
/**
* {@inheritdoc}
*/
public function getLangcode(Request $request = NULL) {
$langcode = NULL;
if (!$request || !$this->languageManager) {
return $langcode;
}
\Drupal::service('page_cache_kill_switch')->trigger();
// We can't use the service here because it uses sessions, and they hurt us.
$ip = \Drupal::request()->getClientIp();
$location = SmartIp::query($ip);
// Defensive checking for country code.
if (!isset($location['countryCode'])) {
return $langcode;
}
$country_code = $location['countryCode'];
$mapping_ids = \Drupal::entityQuery('smartip_language_mapping')
->condition('country', $country_code)
->execute();
// No matching country-language is found.
if (empty($mapping_ids)) {
return $langcode;
}
// Update langcode based on mapping values.
$mapping_id = reset($mapping_ids);
$mapping = SmartIpLanguageMapping::load($mapping_id);
$langcode = $mapping->getLanguage();
// Redirect if configure to do so.
$redirect = $this->config->get('smartip_language_detection.settings')->get('redirect') ?? FALSE;
// Don't redirect when the system is in maintenance mode.
if ($redirect === 1 && !$this->state->get('system.maintenance_mode')) {
$this->redirectToLangcodePath($request, $langcode);
}
return $langcode;
}
/**
* Redirect the user to the language path.
*
* @param \Symfony\Component\HttpFoundation\Request $request
* The HTTP request.
* @param string $langcode
* The Drupal language code specified.
*/
private function redirectToLangcodePath(Request $request, $langcode) {
$current_path = \Drupal::service('path.current')->getPath();
$base_path = base_path();
if ($current_path !== $base_path) {
return;
}
$response = new RedirectResponse($base_path . $langcode);
$response->prepare($request);
// Make sure to trigger kernel events.
\Drupal::service('kernel')->terminate($request, $response);
// Tag the language detect and redirect for newrelic.
if (extension_loaded('newrelic')) {
newrelic_name_transaction('smartip_language_detection_redirect');
}
$response->send();
}
}
<?php
namespace Drupal\smartip_language_detection;
use Drupal\Core\Config\Entity\ConfigEntityListBuilder;
use Drupal\Core\Entity\EntityInterface;
use Drupal\smartip_language_detection\Form\SmartIpLanguageDetectionForm;
/**
* Provides a listing of Smart IP language mapping entities.
*/
class SmartIpLanguageMappingListBuilder extends ConfigEntityListBuilder {
/**
* {@inheritdoc}
*/
public function buildHeader() {
$header['country'] = $this->t('Country');
$header['language'] = $this->t('Language');
return $header + parent::buildHeader();
}
/**
* {@inheritdoc}
*
* @var \Drupal\smartip_language_detection\Entity\SmartIpLanguageMapping $entity
*/
public function buildRow(EntityInterface $entity) {
$row['country'] = $entity->getCountryName();
$row['language'] = $entity->getLanguageName();
return $row + parent::buildRow($entity);
}
/**
* {@inheritdoc}
*/
public function render() {
$build = parent::render();
$build['config_form'] = \Drupal::formBuilder()->getForm(SmartIpLanguageDetectionForm::class);
return $build;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment