cms_content_sync-3.0.x-dev/src/SyncCoreInterface/DrupalApplication.php

src/SyncCoreInterface/DrupalApplication.php
<?php

namespace Drupal\cms_content_sync\SyncCoreInterface;

use Drupal\cms_content_sync\Controller\AuthenticationByUser;
use Drupal\cms_content_sync\Controller\ContentSyncSettings;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Url;
use EdgeBox\SyncCore\Interfaces\Embed\IEmbedService;
use EdgeBox\SyncCore\Interfaces\IApplicationInterface;

/**
 * Class DrupalApplication.
 *
 * Implement the ApplicationInterface to provide basic information about this site to the Sync Core. Must be provided
 * to all client instances to communicate with the Sync Core.
 */
class DrupalApplication implements IApplicationInterface {
  /**
   * @var string APPLICATION_ID Unique ID to identify the kind of application
   */
  public const APPLICATION_ID = 'drupal';

  /**
   * @var DrupalApplication
   */
  protected static $instance;

  /**
   * @return DrupalApplication
   */
  public static function get() {
    if (!empty(self::$instance)) {
      return self::$instance;
    }

    return self::$instance = new DrupalApplication();
  }

  /**
   * {@inheritdoc}
   */
  public function getSiteBaseUrl() {
    return ContentSyncSettings::getInstance()->getSiteBaseUrl();
  }

  /**
   * {@inheritdoc}
   */
  public function getAuthentication() {
    $type = ContentSyncSettings::getInstance()->getAuthenticationType();
    $authentication_provider = AuthenticationByUser::getInstance();

    return [
      'type' => $type,
      'username' => $authentication_provider->getUsername(),
      'password' => $authentication_provider->getPassword(),
    ];
  }

  /**
   * Apply the required _format query parameter and fix issues with the base URL
   * and languages interfering.
   *
   * @param string $url
   *
   * @return string
   */
  protected function processUrl(string $url) {
    // Always request JSON as the format. Drupal doesn't support Accept headers, so we have to pass it as a query parameter.
    $url .= (strpos($url, '?') === FALSE ? '?' : '&') . '_format=json';

    // When users migrate from v1, their base URL will include e.g. the site name or the language suffix.
    // As above's Url::fromRoute() will append that, too, it would be included twice in the resulting URL.
    // So we have to cut it off from the path to allow v1 users to continue with their existing base URL.
    $base_url = $this->getSiteBaseUrl();
    $base_url_path = parse_url($base_url, PHP_URL_PATH);
    $base_url_path_parts = array_slice(explode('/', $base_url_path ?? ''), 1);

    $url_parts = array_slice(explode('/', $url), 1);

    // If the start of the path is equal to the end of the base URL, we have to
    // cut it off here so that it doesn't result in two language prefixes in the url.
    // e.g. https://example.com/en + /en/rest/... would result in https://example.com/en/en/rest/...
    // instead of https://example.com/en/rest/...
    if (count($base_url_path_parts) && $url_parts[0] === $base_url_path_parts[count($base_url_path_parts) - 1]) {
      $url = '/' . implode('/', array_slice($url_parts, 1));
    }
    // When using the UI, Drupal may prepend the site's path to the route when using multisite (but not when using Drush).
    // So we check if the path of the base URL is the prefix of the provided route path.
    // Otherwise this would result in URLs like https://example.com/sub-site/sub-site/... instead of https://example.com/sub-site/...
    // or https://example.com/sub-site/en/sub-site/en/... instead of https://example.com/sub-site/en/...
    elseif ($base_url_path && mb_substr($url, 0, mb_strlen($base_url_path)) === $base_url_path) {
      $url = mb_substr($url, mb_strlen($base_url_path));
    }

    return $url;
  }

  /**
   * {@inheritdoc}
   */
  public function getRelativeReferenceForSiteRestCall(string $action) {
    if (IApplicationInterface::REST_ACTION_SITE_STATUS === $action) {
      $url = Url::fromRoute('rest.cms_content_sync_sync_core_site_status.GET')->toString();
    }
    elseif (IApplicationInterface::REST_ACTION_SITE_CONFIG === $action) {
      $url = Url::fromRoute('rest.cms_content_sync_sync_core_site_config.GET')->toString();
    }
    else {
      return NULL;
    }

    $url = $this->processUrl($url);

    return $url;
  }

  /**
   * {@inheritdoc}
   */
  public function getRelativeReferenceForRestCall(string $flow_machine_name, string $action) {
    if (IApplicationInterface::REST_ACTION_LIST_ENTITIES === $action) {
      $url = Url::fromRoute('rest.cms_content_sync_sync_core_entity_list.GET', ['flow_id' => $flow_machine_name])->toString();
    }
    elseif (in_array($action, [
      IApplicationInterface::REST_ACTION_CREATE_ENTITY,
      IApplicationInterface::REST_ACTION_DELETE_ENTITY,
      IApplicationInterface::REST_ACTION_RETRIEVE_ENTITY,
    ])) {
      $url = Url::fromRoute('rest.cms_content_sync_sync_core_entity_item.GET', [
        'flow_id' => $flow_machine_name,
        'entity_type' => '[type.namespaceMachineName]',
        'entity_bundle' => '[type.machineName]',
            // When retrieving the entity we require the UUID as we're only saving
            // the UUID at status entities.
        'shared_entity_id' => IApplicationInterface::REST_ACTION_RETRIEVE_ENTITY === $action ? '[entity.uuid]' : '[entity.sharedId]',
      ])->toString();
    }
    else {
      return NULL;
    }

    // Drupal will url encode the passed arguments, so turn the [] brackets into %.. characters. So we reverse that here as these are placeholders and must be actual brackets.
    $url = preg_replace('@%5B([a-zA-Z0-9.]+)%5D@', '[$1]', $url);

    // Ask for additional localization parameters to be passed as query parameters when requesting a specific entity.
    if (IApplicationInterface::REST_ACTION_LIST_ENTITIES !== $action) {
      $url .= '?language=[entity.language]';
      $url .= '&isTranslationRoot=[entity.isTranslationRoot]';
      $url .= '&individualTranslation=[entity.individualTranslation]';
    }

    $url = $this->processUrl($url);

    return $url;
  }

  /**
   * {@inheritdoc}
   */
  public function getEmbedBaseUrl(string $feature) {
    $export_url = $this->getSiteBaseUrl();

    $name = IEmbedService::REGISTER_SITE === $feature || IEmbedService::SITE_REGISTERED === $feature || IEmbedService::MIGRATE === $feature ? 'site' : $feature;

    $url = sprintf(
          '%s/admin/config/services/cms_content_sync/%s',
          $export_url,
          $name
      );

    // If something went wrong and the site needs to be re-registered again forcefully, we add a "force" param.
    if (IEmbedService::REGISTER_SITE === $feature) {
      $url .= '?force=' . IEmbedService::REGISTER_SITE;
    }
    elseif (IEmbedService::MIGRATE === $feature) {
      $url .= '?force=' . IEmbedService::MIGRATE;
    }

    return $url;
  }

  /**
   * {@inheritDoc}
   */
  public function setSyncCoreUrl(string $set) {
    ContentSyncSettings::getInstance()->setSyncCoreUrl($set);
  }

  /**
   * {@inheritDoc}
   */
  public function getSyncCoreUrl() {
    return ContentSyncSettings::getInstance()->getSyncCoreUrl();
  }

  /**
   * {@inheritdoc}
   */
  public function getRestUrl($pool_id, $type_machine_name, $bundle_machine_name, $version_id, $entity_uuid = NULL, $manually = NULL, $as_dependency = NULL) {
    $export_url = $this->getSiteBaseUrl();

    $url = sprintf(
          '%s/rest/cms-content-sync/%s/%s/%s/%s',
          $export_url,
          $pool_id,
          $type_machine_name,
          $bundle_machine_name,
          $version_id
      );

    if ($entity_uuid) {
      $url .= '/' . $entity_uuid;
    }

    $url .= '?_format=json';

    if ($as_dependency) {
      $url .= '&is_dependency=' . $as_dependency;
    }

    if ($manually) {
      $url .= '&is_manual=' . $manually;
    }

    return $url;
  }

  /**
   * {@inheritdoc}
   */
  public function getSiteName() {
    $name = getenv('CMS_CONTENT_SYNC_SITE_NAME') ?? getenv('CONTENT_SYNC_SITE_NAME');
    if ($name) {
      return $name;
    }

    try {
      return ContentSyncSettings::getInstance()->getSiteName();
    }
    // If the site is not registered yet or the Sync Core is unavailable, we return the
    // Drupal site name as default.
    catch (\Exception $e) {
      return \Drupal::config('system.site')->get('name');
    }
  }

  /**
   * {@inheritdoc}
   */
  public function setSiteId($set) {
    ContentSyncSettings::getInstance()->setSiteId($set);
  }

  /**
   * {@inheritdoc}
   */
  public function getSiteId() {
    return ContentSyncSettings::getInstance()->getSiteMachineName();
  }

  /**
   * {@inheritdoc}
   */
  public function getSiteMachineName() {
    return ContentSyncSettings::getInstance()->getSiteMachineName();
  }

  /**
   * {@inheritdoc}
   */
  public function setSiteMachineName($set) {
    ContentSyncSettings::getInstance()->setSiteMachineName($set);
  }

  /**
   * {@inheritdoc}
   */
  public function setSiteUuid(string $set) {
    ContentSyncSettings::getInstance()->setSiteUuid($set);

    // Clear some caches to set the local action buttons to active.
    // @todo Adjust this to just clear the cache tags for the local actions.
    $bins = Cache::getBins();
    $bins['render']->deleteAll();
    $bins['discovery']->deleteAll();
  }

  /**
   * {@inheritdoc}
   */
  public function getSiteUuid() {
    return ContentSyncSettings::getInstance()->getSiteUuid();
  }

  /**
   * {@inheritdoc}
   */
  public function getApplicationId() {
    return self::APPLICATION_ID;
  }

  /**
   * {@inheritdoc}
   */
  public function getApplicationVersion() {
    return \Drupal::VERSION;
  }

  /**
   * {@inheritdoc}
   */
  public function getApplicationModuleVersion() {
    $version = \Drupal::service('extension.list.module')
      ->getExtensionInfo('cms_content_sync')['version'];

    return $version ? $version : 'dev';
  }

  /**
   * {@inheritdoc}
   */
  public function getHttpClient() {
    return \Drupal::httpClient();
  }

  /**
   * {@inheritdoc}
   */
  public function getHttpOptions() {
    $options = [];

    // Allow to set a custom timeout for Sync Core requests.
    global $config;
    $config_name = 'cms_content_sync.sync_core_request_timeout';
    if (!empty($config[$config_name]) && is_int($config[$config_name])) {
      $options['timeout'] = $config[$config_name];
    }

    return $options;
  }

  /**
   *
   */
  public function getFeatureFlags() {
    return [
      'count-entities' => 1,
      'request-per-translation' => 1,
      'request-polling' => \Drupal::service('module_handler')->moduleExists('cms_content_sync_private_environment') ? 1 : 0,
      'site-settings-tab' => 1,
      'skip-unchanged-entities' => 1,
      'skip-unchanged-translations' => 1,
      'prefer-2xx-status-code' => 1,
      'entity-operation' => 1,
      'entity-operation.clear-cache' => 1,
    ];
  }

}

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

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