location_selector-8.x-1.x-dev/src/GeoNamesService.php

src/GeoNamesService.php
<?php

namespace Drupal\location_selector;

use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Language\LanguageManagerInterface;

/**
 * Class GeoNamesService.
 */
class GeoNamesService {

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

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

  /**
   * Drupal\Core\Session\AccountProxyInterface definition.
   *
   * @var \Drupal\Core\Session\AccountProxyInterface
   */
  protected $currentUser;

  /**
   * Drupal\Core\Language\LanguageManagerInterface definition.
   *
   * @var \Drupal\Core\Language\LanguageManagerInterface
   */
  protected $languageManager;

  /**
   * Drupal\Core\Cache\CacheBackendInterface definition.
   *
   * @var \Drupal\Core\Cache\CacheBackendInterface
   */
  protected $cache;

  /**
   * Constructs a new GeoNamesService object.
   */
  public function __construct(EntityTypeManagerInterface $entity_type_manager, ConfigFactoryInterface $config_factory, AccountProxyInterface $current_user,LanguageManagerInterface $language_manager,CacheBackendInterface $cache) {
    $this->entityTypeManager = $entity_type_manager;
    $this->configFactory = $config_factory;
    $this->currentUser = $current_user;
    $this->languageManager = $language_manager;
    $this->cache = $cache;
  }

  /**
   * Returns the children or infos from the requestet id's.
   *
   * @param array $ids
   *   Must be the format:
   *   'children' => id
   *   or/and
   *   'parent' => id.
   *
   * @return array|null
   *   The array or null.
   */
  public function getGeoNamesAndIds(array $ids) {
    // Some basic data.
    $infos = NULL;
    $empty_value = t('- Please select -');
    $empty_option = ['val' => 'All', 'text' => $empty_value->render()];

    // Loop trough array and save the API results.
    foreach ($ids as $key1 => $id) {
      // If more than one value, the parent needs to be included.
      if (isset($id['parent'])) {
        if (!empty($data = $this->checkAndSetCaching($id['parent'], 'getInfos', $empty_option))) {
          $result_array[$key1]['parent'] = $data;
        }
      }
      if (isset($id['children'])) {
        if (!empty($data = $this->checkAndSetCaching($id['children'], 'getChildren', $empty_option))) {
          $result_array[$key1]['children'] = $data;
        }
      }
    }
    if (!empty($result_array)) {
      $infos = $result_array;
    }
    return $infos;
  }

  /**
   * Cache handling.
   *
   * @param int|string $api_id
   *   The ids for the select lists.
   * @param string $method
   *   The api method.
   * @param array $empty_option
   *   The empty select option value and text.
   *
   * @return array|null
   *   return select array.
   */
  protected function checkAndSetCaching($api_id, string $method, array $empty_option) {
    $data = NULL;
    $language_id = $this->languageManager->getCurrentLanguage()->getId();
    $cid = 'location_selector:' . $method . ':' . $api_id . ':' . $language_id;
    if ($cache = $this->cache->get($cid)) {
      $data = $cache->data;
    }
    else {
      $data = $this->createSelectArray($api_id, $method, $empty_option);
      if (!empty($data)) {
        // @see createSelectArray()
        if ($data === 'no-children') {
          $data = NULL;
        }
        $this->cache->set($cid, $data, CacheBackendInterface::CACHE_PERMANENT);
      }
    }
    return $data;
  }

  /**
   * Create the select array for select lists.
   *
   * @param int|string $api_id
   *   The ids for the select lists.
   * @param string $method
   *   The api method.
   * @param array $empty_option
   *   The empty select option value and text.
   *
   * @return array|null|string
   *   return select array.
   */
  protected function createSelectArray($api_id, string $method, array $empty_option) {
    $array = NULL;
    switch ($method) {
      case 'getChildren':
        $children = $this->getChildren($api_id);
        if (!empty($children['geonames'])) {
          $results = $children['geonames'];
        }
        elseif (isset($children['geonames'])) {
          // Because ID's without children should be cached too.
          // And the return is not specific empty.
          // @see checkAndSetCaching()
          $array = 'no-children';
        }
        break;

      case 'getInfos':
        $results[] = $this->getInfos($api_id);
        break;
    }
    if (!empty($results)) {
      foreach ($results as $key => $result) {
        $array[$key] = [
          'val' => $result['geonameId'],
          'text' => $result['name'],
        ];
      }
    }
    if (!empty($array) && is_array($array)) {
      array_unshift($array, $empty_option);
    }
    return $array;
  }

  /**
   * Get the infos.
   *
   * @param string|int $genames_id
   *   The specific GeoNames ID.
   *
   * @return array|null
   *   return the specific data.
   */
  public function getInfos($genames_id) {
    $data = NULL;
    $language_id = $this->languageManager->getCurrentLanguage()->getId();
    $url = 'http://api.geonames.org/getJSON?&geonameId=' . $genames_id . '&lang=' . $language_id;
    if (!empty($results = $this->geoNamesApiCall('GET', $url))) {
      $data = $results;
    }
    return $data;
  }

  /**
   * Get the children.
   *
   * @param string|int $parent_id
   *   The parent id.
   *
   * @return array|null
   *   return children.
   */
  public function getChildren($parent_id) {
    $data = NULL;
    $language_id = $this->languageManager->getCurrentLanguage()->getId();
    $url = 'http://api.geonames.org/childrenJSON?&geonameId=' . $parent_id . '&lang=' . $language_id;
    if (!empty($results = $this->geoNamesApiCall('GET', $url))) {
      $data = $results;
    }
    return $data;
  }

  /**
   * Make the API call.
   *
   * @param string $method
   *   The method.
   * @param string $url
   *   The url.
   * @param array|bool $data
   *   The data.
   *
   * @see https://stackoverflow.com/questions/9802788/call-a-rest-api-in-php
   * @see http://www.geonames.org/export/ws-overview.html
   *
   * @return array|null
   *   return the result.
   */
  public function geoNamesApiCall($method, $url, $data = FALSE) {
    $result_call = NULL;

    $location_selector_configs = $this->configFactory->get('location_selector.settings');
    if (!empty($username = $location_selector_configs->get('geonames_username'))) {

      $auth_url = substr_replace($url, 'username=' . $username, (strpos($url, '?') + 1), 0);

      // Method: POST, PUT, GET etc.
      // Data: array("param" => "value") ==> index.php?param=value
      $curl = curl_init();
      switch ($method) {
        case "POST":
          curl_setopt($curl, CURLOPT_POST, 1);
          if ($data) {
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
          }
          break;

        case "PUT":
          curl_setopt($curl, CURLOPT_PUT, 1);
          break;

        default:
          if ($data) {
            $auth_url = sprintf("%s?%s", $auth_url, http_build_query($data));
          }
      }

      // Optional Authentication:
      // curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
      // curl_setopt($curl, CURLOPT_USERPWD, "username:password");

      curl_setopt($curl, CURLOPT_URL, $auth_url);
      curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);

      $result = curl_exec($curl);

      curl_close($curl);

      $error = TRUE;
      if (!empty($result)) {
        $json_result = json_decode($result, TRUE);
        if (json_last_error() == JSON_ERROR_NONE) {
          if (!empty($json_result['totalResultsCount']) || !isset($json_result['status'])) {
            $error = FALSE;
          }
        }
      }
      if (!$error && isset($json_result)) {
        $result_call = $json_result;
      }
      else {
        \Drupal::logger('location_selector')->critical(
          'Error with the GeoNames API.
          <br>File: @file<br>Line: @line<br>Function: @function<br>Infos: <pre>@infos</pre>', [
            '@infos' => print_r($result, TRUE),
            '@file' => __FILE__,
            '@line' => __LINE__,
            '@function' => __FUNCTION__,
          ]
        );
      }

    }
    return $result_call;
  }

}

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

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