taxonomy_place-8.x-1.3/src/TaxonomyPlaceCreator.php

src/TaxonomyPlaceCreator.php
<?php

namespace Drupal\taxonomy_place;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use CommerceGuys\Addressing\Country\CountryRepositoryInterface;
use CommerceGuys\Addressing\Subdivision\SubdivisionRepositoryInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Entity\EntityInterface;

/**
 * Class TaxonomyPlaceCreator.
 *
 * @package Drupal\taxonomy_place
 */
class TaxonomyPlaceCreator {

  /**
   * Config factory.
   *
   * @var Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $configFactory;

  /**
   * Entity Type Manager.
   *
   * @var Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * The country repository.
   *
   * @var \CommerceGuys\Addressing\Country\CountryRepositoryInterface
   */
  protected $countryRepository;

  /**
   * The subdivision repository.
   *
   * @var \CommerceGuys\Addressing\Subdivision\SubdivisionRepositoryInterface
   */
  protected $subdivisionRepository;

  /**
   * The module handler service.
   *
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
   */
  protected $moduleHandler;

  /**
   * Constructs a new TaxonomyPlaceCreator.
   *
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The Config Factory.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The Entity Type Manager.
   * @param \CommerceGuys\Addressing\Country\CountryRepositoryInterface $country_repository
   *   The Country Repository.
   * @param \CommerceGuys\Addressing\Subdivision\SubdivisionRepositoryInterface $subdivision_repository
   *   The Subdivision Repository.
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
   *   The Module Handler.
   */
  public function __construct(ConfigFactoryInterface $config_factory, EntityTypeManagerInterface $entity_type_manager, CountryRepositoryInterface $country_repository, SubdivisionRepositoryInterface $subdivision_repository, ModuleHandlerInterface $module_handler) {
    $this->configFactory = $config_factory;
    $this->entityTypeManager = $entity_type_manager;
    $this->countryRepository = $country_repository;
    $this->subdivisionRepository = $subdivision_repository;
    $this->moduleHandler = $module_handler;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('config.factory'),
      $container->get('entity_type.manager'),
      $container->get('address.country_repository'),
      $container->get('address.subdivision_repository'),
      $container->get('module_handler')
    );
  }

  /**
   * Get settings.
   *
   * @param string $value
   *   The name of the setting to retrieve.
   *
   * @return mixed
   *   The requested setting.
   */
  public function getSettings($value) {
    return $this->configFactory->get('taxonomy_place.settings')->get($value);
  }

  /**
   * A storage object.
   *
   * @return Drupal\Core\Entity\EntityTypeManagerInterface
   *   The storage.
   */
  public function getStorage() {
    return $this->entityTypeManager->getStorage('taxonomy_term');
  }

  /**
   * Create a term for a place.
   *
   * Terms are created only if they don't already exist. Terms are created
   * for each part of the place (country, province, locality), with provinces
   * nested under the country, and localities nested under the province.
   *
   * @param Drupal\Core\Entity\EntityInterface $entity
   *   The entity that contains a field with place information.
   * @param string $field_name
   *   The address field on the entity that contains the place information.
   * @param int $delta
   *   The delta of the field value to use for this term.
   *
   * @return array
   *   Return array of Drupal\taxonomy\TermInterface objects.
   */
  public function createPlaceTerm(EntityInterface $entity, $field_name, $delta = 0) {

    // If the field doesn't exist on this entity, there is nothing to do.
    if (!$entity->get($field_name)) {
      return FALSE;
    }
    // If no vid or address_field have been set, there is nothing to do.
    $vid = $this->getSettings('vid');
    $address_field = $this->getSettings('address_field');

    if (!$vid || !$address_field) {
      return FALSE;
    }

    $place_term = NULL;
    if ($place = $entity->get($field_name)->getValue()) {

      $country_code = $place[$delta]['country_code'];
      $province_code = $place[$delta]['administrative_area'];
      $locality = $place[$delta]['locality'];

      // Create the country term, if it doesn't exist.
      $place = [$country_code, NULL, NULL];
      $country_term = $this->createTermFromValues($place);
      $place_term = $country_term;

      // Create the administrative area term if it doesn't exist.
      if (!empty($province_code) && !empty($country_term)) {
        $place = [$country_code, $province_code, NULL];
        $province_term = $this->createTermFromValues($place);
        if (empty($locality)) {
          $place_term = $province_term;
        }
      }

      // Create the locality term, if it doesn't exist.
      if (!empty($locality)) {
        if (!empty($province_code)) {
          $place = [$country_code, $province_code, $locality];
        }
        else {
          $place = [$country_code, NULL, $locality];
        }
        $locality_term = $this->createTermFromValues($place);
        $place_term = $locality_term;
      }
    }
    return $place_term;
  }

  /**
   * Get the term that matches country, province, and locality.
   *
   * @param array $place
   *   An array of field names and values distinctive to the given term type,
   *   which will be used to find a match:
   *   [$country_code, $province_code, $locality].
   *
   * @return Drupal\taxonomy\TermInterface
   *   Returns term or FALSE if not found.
   */
  public function getPlaceTerm(array $place) {
    $vid = $this->getSettings('vid');
    $address_field = $this->getSettings('address_field');

    $context = ['vid' => $vid];
    $this->moduleHandler->alter('taxonomy_place_get_place', $place, $address_field, $context);

    // If no vid or address_field have been set, there is nothing to do.
    if (!$vid || !$address_field) {
      return FALSE;
    }

    list($country_code, $province_code, $locality) = $place;

    $query = $this->getStorage()->getQuery();
    $query->condition('vid', $vid);
    $query->condition($address_field . '.country_code', $country_code);

    // If this value is empty we have to check for either empty OR NULL.
    if (empty($province_code)) {
      $or = $query->orConditionGroup();
      $or->condition($address_field . '.administrative_area', NULL, 'IS NULL');
      $or->condition($address_field . '.administrative_area', '');
      $query->condition($or);
    }
    else {
      $query->condition($address_field . '.administrative_area', $province_code);
    }

    // If this value is empty we have to check for either empty OR NULL.
    if (empty($locality)) {
      $or = $query->orConditionGroup();
      $or->condition($address_field . '.locality', NULL, 'IS NULL');
      $or->condition($address_field . '.locality', '');
      $query->condition($or);
    }
    else {
      $query->condition($address_field . '.locality', $locality);
    }
    $tids = $query->execute();

    if (count($tids) && $tid = array_shift($tids)) {
      $term = $this->getStorage()->load($tid);
      return $term;
    }
    return FALSE;
  }

  /**
   * Create a term from an array of place information.
   *
   * @param array $place
   *   An array of field names and values distinctive to the given term type,
   *   which will be used to find a match:
   *   [$country_code, $province_code, $locality].
   * @param string $format
   *   The format to use for any long text values.
   *
   * @return Drupal\taxonomy\TermInterface
   *   Returns a term.
   */
  protected function createTermFromValues(array $place, $format = 'basic_html') {
    // If the term already exists, nothing more to do.
    if ($term = $this->getPlaceTerm($place)) {
      return $term;
    }

    list($country_code, $province_code, $locality) = $place;
    $country_name = $this->getCountryName($country_code);
    $province_name = $this->getProvinceName($country_code, $province_code);
    $vid = $this->getSettings('vid');
    $address_field = $this->getSettings('address_field');

    $values = [];
    $values['vid'] = $vid;
    $values['name'] = $this->getPlaceName($place);

    if ($description_field = $this->getSettings('description_field')) {
      $values[$description_field]['value'] = $this->getDescription($place);
      $values[$description_field]['format'] = $format;
    }
    if ($short_name_field = $this->getSettings('short_name_field')) {
      $values[$short_name_field]['value'] = $this->getShortName($place);
    }
    if ($sortable_name_field = $this->getSettings('sortable_name_field')) {
      $values[$sortable_name_field]['value'] = $this->getSortableName($place);
    }

    // A country.
    if (empty($province_code) && empty($locality)) {
      $values['parent'] = [];
    }
    // An administrative area.
    elseif (empty($locality) && !empty($province_code)) {
      if ($country_term = $this->getPlaceTerm([$country_code, NULL, NULL])) {
        $values['parent'] = [$country_term->id()];
      }
    }
    // A locality that is part of an administrative area.
    elseif (!empty($province_code)) {
      if ($province_term = $this->getPlaceTerm([
        $country_code,
        $province_code,
        NULL,
      ])) {
        $values['parent'] = [$province_term->id()];
      }
    }
    // A locality that is directly nested under a country.
    else {
      if ($country_term = $this->getPlaceTerm([$country_code, NULL, NULL])) {
        $values['parent'] = [$country_term->id()];
      }
    }

    $values[$address_field] = [
      'country_code' => $country_code,
      'administrative_area' => $province_code,
      'locality' => $locality,
    ];
    $values['weight'] = 0;
    return $this->createTerm($values);

  }

  /**
   * Create a term from an array of field values.
   *
   * @param array $values
   *   A key/value array of values for the term.
   *
   * @return Drupal\taxonomy\TermInterface
   *   A Term.
   */
  public function createTerm(array $values) {
    $defaults = [
      'vid' => '',
      'name' => '',
    ];
    $values += $defaults;

    // The submitted values must at least have these fields.
    if (empty($values['name']) || empty($values['vid'])) {
      return FALSE;
    }

    $query = $this->getStorage()->getQuery();
    $query->condition('vid', $values['vid']);
    $query->condition('name', $values['name']);
    if ($tids = $query->execute()) {
      $tid = array_shift($tids);
      $term = $this->getStorage()->load($tid);
    }
    else {
      $this->moduleHandler->alter('taxonomy_place_create_term', $values);
      $term = $this->getStorage()->create($values);
      $term->save();
    }
    return $term;
  }

  /**
   * Helper function to get a list of countries.
   *
   * @return array
   *   Array of countries.
   */
  public function getCountries() {
    return $this->countryRepository->getList();
  }

  /**
   * Helper function to get a country name.
   *
   * @param string $country_code
   *   The country code for the country.
   *
   * @return string
   *   The name of the country.
   */
  public function getCountryName($country_code) {
    $countries = $this->getCountries();
    if (array_key_exists($country_code, $countries)) {
      return $countries[$country_code];
    }
    return '';
  }

  /**
   * Helper function to get a list of provinces for a country.
   *
   * @param string $country_code
   *   The country code for the country.
   *
   * @return array
   *   Array of provinces.
   */
  public function getProvinces($country_code) {
    $parents = [$country_code];
    return $this->subdivisionRepository->getList($parents);
  }

  /**
   * Helper function to get a province name.
   *
   * @param string $country_code
   *   The country code for the country.
   * @param string $province_code
   *   The code for the province.
   *
   * @return string
   *   The name of the province.
   */
  public function getProvinceName($country_code, $province_code) {
    $provinces = $this->getProvinces($country_code);
    if (array_key_exists($province_code, $provinces)) {
      return $provinces[$province_code];
    }
    return '';
  }

  /**
   * Helper function to create a place name.
   *
   * @param array $place
   *   An array of field names and values distinctive to the given term type,
   *   which will be used to find a match:
   *   [$country_code, $province_code, $locality].
   *
   * @return string
   *   The name of the place.
   */
  public function getPlaceName(array $place) {
    list($country_code, $province_code, $locality) = $place;
    $country_name = $this->getCountryName($country_code);
    $province_name = $this->getProvinceName($country_code, $province_code);

    // A country.
    if (empty($province_name) && empty($locality)) {
      $name = $country_name;
    }
    // An administrative area.
    elseif (empty($locality) && !empty($province_name)) {
      $name = $province_name;
      if ($country_name != 'United States') {
        $name .= ', ' . $country_name;
      }
    }
    // A locality nested below an administrative area.
    elseif (!empty($province_name)) {
      $name = $locality . ', ' . $province_name;
      if ($country_name != 'United States') {
        $name .= ', ' . $country_name;
      }
    }
    // A locality nested below a country.
    else {
      $name = $locality . ', ' . $country_name;
    }
    return $name;
  }

  /**
   * Helper function to create a short place name.
   *
   * @param array $place
   *   An array of field names and values distinctive to the given term type,
   *   which will be used to find a match:
   *   [$country_code, $province_code, $locality].
   *
   * @return string
   *   The short name of the place.
   */
  public function getShortName(array $place) {
    list($country_code, $province_code, $locality) = $place;
    $country_name = $this->getCountryName($country_code);
    $province_name = $this->getProvinceName($country_code, $province_code);

    if (empty($province_name) && empty($locality)) {
      $name = $country_name;
    }
    elseif (empty($locality)) {
      $name = $province_name;
    }
    else {
      $name = $locality;
    }
    return $name;
  }

  /**
   * Helper function to create a sortable place name.
   *
   * @param array $place
   *   An array of field names and values distinctive to the given term type,
   *   which will be used to find a match:
   *   [$country_code, $province_code, $locality].
   *
   * @return string
   *   The sortable name of the place.
   */
  public function getSortableName(array $place) {
    list($country_code, $province_code, $locality) = $place;
    $country_name = $this->getCountryName($country_code);
    $province_name = $this->getProvinceName($country_code, $province_code);

    if (empty($province_name) && empty($locality)) {
      $name = $country_name;
    }
    elseif (empty($locality)) {
      $name = $country_name . '/ ' . $province_name;
    }
    elseif (!empty($province_name)) {
      $name = $country_name . '/ ' . $province_name . '/ ' . $locality;
    }
    else {
      $name = $country_name . '/' . $locality;
    }
    return $name;
  }

  /**
   * Helper function to create a place description.
   *
   * @param array $place
   *   An array of field names and values distinctive to the given term type,
   *   which will be used to find a match:
   *   [$country_code, $province_code, $locality].
   *
   * @return string
   *   The description of the place.
   */
  public function getDescription(array $place) {

    $description = $this->getPlaceName($place);

    // If the Wikipedia Client module exists, add text from Wikipedia
    // about each place.
    if (\Drupal::moduleHandler()->moduleExists('wikipedia_client')) {
      $wiki_client = \Drupal::service('wikipedia_client.client');
      if ($wiki_data = $wiki_client->getResponse($description)) {
        $description = $wiki_client->getMarkup($wiki_data);
      }
    }

    return $description;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc