You are here

class CliService in CMS Content Sync 8

Same name in this branch
  1. 8 src/Cli/CliService.php \Drupal\cms_content_sync\Cli\CliService
  2. 8 modules/cms_content_sync_developer/src/Cli/CliService.php \Drupal\cms_content_sync_developer\Cli\CliService
Same name and namespace in other branches
  1. 2.1.x src/Cli/CliService.php \Drupal\cms_content_sync\Cli\CliService
  2. 2.0.x src/Cli/CliService.php \Drupal\cms_content_sync\Cli\CliService

Hierarchy

Expanded class hierarchy of CliService

1 file declares its use of CliService
CMSContentSyncCommands.php in src/Commands/CMSContentSyncCommands.php
1 string reference to 'CliService'
cms_content_sync.services.yml in ./cms_content_sync.services.yml
cms_content_sync.services.yml
1 service uses CliService
cms_content_sync.cli in ./cms_content_sync.services.yml
Drupal\cms_content_sync\Cli\CliService

File

src/Cli/CliService.php, line 19

Namespace

Drupal\cms_content_sync\Cli
View source
class CliService {

  /**
   * Export the configuration to the Sync Core.
   *
   * @param ICLIIO $io
   *                        The CLI service which allows interoperability
   * @param array  $options
   *                        An array containing the option parameters provided by Drush
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   * @throws \EdgeBox\SyncCore\Exception\SyncCoreException
   * @throws \Exception
   */
  public function configuration_export($io, $options) {
    $io
      ->text('Validating Pools...');
    foreach (Pool::getAll() as $pool) {
      if (!PoolExport::validateBaseUrl($pool)) {
        throw new \Exception('The site does not have a valid base url. The base url must not contain "localhost" and is not allowed to be an IP address. The base url of the site can be configured at the CMS Content Sync settings page.');
      }
      $exporter = new SyncCorePoolExport($pool);
      $sites = $exporter
        ->verifySiteId();
      if (!$options['force'] && $sites && count($sites)) {
        throw new \Exception('Another site with id ' . array_keys($sites)[0] . ' and base url ' . array_values($sites)[0] . ' already exists for the pool "' . $pool->id . '"');
      }
    }
    $io
      ->text('Finished validating Pools.');
    $io
      ->text('Starting Flow export...');
    $count = 0;
    foreach (Flow::getAll() as $flow) {
      $io
        ->text('> Exporting Flow ' . $flow
        ->label() . '...');
      $exporter = new SyncCoreFlowExport($flow);
      $batch = $exporter
        ->prepareBatch($options['force']);
      $io
        ->text('>> Executing ' . $batch
        ->count() . ' operations...');
      $batch
        ->executeAll();
      ++$count;
    }
    $io
      ->text('Finished export of ' . $count . ' Flow(s).');
    $io
      ->success('Export completed.');
  }

  /**
   * Kindly ask the Sync Core to login again.
   *
   * @param ICLIIO $io
   *                   The CLI service which allows interoperability
   *
   * @throws \EdgeBox\SyncCore\Exception\SyncCoreException
   */
  public function sync_core_login($io) {
    $io
      ->text('Asking all connected Sync Cores to refresh the login to this site...');
    $cores = SyncCoreFactory::getAllSyncCores();
    foreach ($cores as $host => $core) {
      if ($core
        ->getSyndicationService()
        ->refreshAuthentication()) {
        $io
          ->text('SUCCESS login from Sync Core at ' . $host);
      }
      else {
        $io
          ->error('FAILED to login from Sync Core at ' . $host);
      }
    }
    $io
      ->success('Done.');
  }

  /**
   * Kindly ask the Sync Core to pull all entities for a specific flow, or to
   * force pull one specific entity.
   *
   * @param ICLIIO $io
   *                        The CLI service which allows interoperability
   * @param string $flow_id
   *                        The flow the entities should be pulled from
   * @param array  $options
   *                        An array containing the option parameters provided by Drush
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   * @throws \EdgeBox\SyncCore\Exception\SyncCoreException
   */
  public function pull($io, $flow_id, $options) {
    $force = $options['force'];
    $entity_type = $options['entity_type'];
    $entity_uuid = $options['entity_uuid'];
    if ('' != $entity_uuid && null == $entity_type) {
      $io
        ->error('If a specific entity_uuid should be pulled, the entity_type also has to be set.');
      return;
    }

    // @todo Allow pulling of all entities of a specific type for one specific flow.
    if ('' != $entity_type && null == $entity_uuid) {
      $io
        ->error('If the entity_type option is set, the entity_uuid to be pulled also has to be specified.');
      return;
    }
    if (!is_null($entity_uuid) && !is_null($entity_uuid)) {
      if (UUID::isValid($entity_uuid)) {

        // Pull a single entity.
        // @todo Allow pull for single entities which have not been pulled before.
        FlowPull::force_pull_entity($flow_id, $entity_type, $entity_uuid);
      }
      else {
        $io
          ->error('The specified entity_uuid is invalid.');
      }
    }
    else {

      // Pull all entities for the specified flow.
      $flows = Flow::getAll();
      foreach ($flows as $id => $flow) {
        if ($flow_id && $id != $flow_id) {
          continue;
        }
        $result = FlowPull::pullAll($flow, $force);
        if (empty($result)) {
          $io
            ->text('No automated pull configured for Flow: ' . $flow
            ->label());
          continue;
        }
        $io
          ->text('Started pulling for Flow: ' . $flow
          ->label());
        foreach ($result as $operation) {
          $operation
            ->execute();
          if (!($goal = $operation
            ->total())) {
            $io
              ->text('> Nothing to do for: ' . $operation
              ->getTypeMachineName() . '.' . $operation
              ->getBundleMachineName() . ' from ' . $operation
              ->getPoolMachineName());
            continue;
          }
          $progress = 0;
          while ($progress < $goal) {
            if ($progress > 0) {
              sleep(5);
            }
            try {
              $progress = $operation
                ->progress();
            } catch (TimeoutException $e) {
              $io
                ->text('> Timeout when asking the Sync Core to report on the progress of pulling ' . $goal . ' ' . $operation
                ->getTypeMachineName() . '.' . $operation
                ->getBundleMachineName() . ' from ' . $operation
                ->getPoolMachineName() . '. Will try again in 15 seconds...');
              sleep(15);
              continue;
            }
            if ($progress == $goal) {
              $io
                ->text('> Pulled ' . $goal . ' ' . $operation
                ->getTypeMachineName() . '.' . $operation
                ->getBundleMachineName() . ' from ' . $operation
                ->getPoolMachineName());
            }
            elseif (0 == $progress) {
              sleep(5);
            }
            else {
              $io
                ->text('> Pulled ' . $progress . ' of ' . $goal . ' ' . $operation
                ->getTypeMachineName() . '.' . $operation
                ->getBundleMachineName() . ' from ' . $operation
                ->getPoolMachineName() . ': ' . floor($progress / $goal * 100) . '%');
            }
          }
        }
      }
    }
  }

  /**
   * Kindly ask the Sync Core to pull all entities for a specific flow.
   *
   * @param ICLIIO $io
   *                        The CLI service which allows interoperability
   * @param string $flow_id
   *                        The flow the entities should be pulled from
   * @param array  $options
   *                        An array containing the option parameters provided by Drush
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   * @throws \EdgeBox\SyncCore\Exception\SyncCoreException
   *
   * @deprecated Function is deprecated and is going to be removed in 2.0, use
   *   pull() instead.
   */
  public function pull_entities($io, $flow_id, $options) {
    $io
      ->warning('Function is deprecated and is going to be removed in 2.0, use "cs-pull" instead.');
    $force = $options['force'];
    $flows = Flow::getAll();
    foreach ($flows as $id => $flow) {
      if ($flow_id && $id != $flow_id) {
        continue;
      }
      $result = FlowPull::pullAll($flow, $force);
      if (empty($result)) {
        $io
          ->text('No automated pull configured for Flow: ' . $flow
          ->label());
        continue;
      }
      $io
        ->text('Started pulling for Flow: ' . $flow
        ->label());
      foreach ($result as $operation) {
        $operation
          ->execute();
        if (!($goal = $operation
          ->total())) {
          $io
            ->text('> Nothing to do for: ' . $operation
            ->getTypeMachineName() . '.' . $operation
            ->getBundleMachineName() . ' from ' . $operation
            ->getPoolMachineName());
          continue;
        }
        $progress = 0;
        while ($progress < $goal) {
          if ($progress > 0) {
            sleep(5);
          }
          try {
            $progress = $operation
              ->progress();
          } catch (TimeoutException $e) {
            $io
              ->text('> Timeout when asking the Sync Core to report on the progress of pulling ' . $goal . ' ' . $operation
              ->getTypeMachineName() . '.' . $operation
              ->getBundleMachineName() . ' from ' . $operation
              ->getPoolMachineName() . '. Will try again in 15 seconds...');
            sleep(15);
            continue;
          }
          if ($progress == $goal) {
            $io
              ->text('> Pulled ' . $goal . ' ' . $operation
              ->getTypeMachineName() . '.' . $operation
              ->getBundleMachineName() . ' from ' . $operation
              ->getPoolMachineName());
          }
          elseif (0 == $progress) {
            sleep(5);
          }
          else {
            $io
              ->text('> Pulled ' . $progress . ' of ' . $goal . ' ' . $operation
              ->getTypeMachineName() . '.' . $operation
              ->getBundleMachineName() . ' from ' . $operation
              ->getPoolMachineName() . ': ' . floor($progress / $goal * 100) . '%');
          }
        }
      }
    }
  }

  /**
   * Kindly ask the Sync Core to force pull a specific entity.
   *
   * @param ICLIIO $io
   *                            The CLI service which allows interoperability
   * @param string $flow_id
   *                            The flow the entities should be pulled from
   * @param string $entity_type
   *                            The type of the entity that should be pulled
   * @param string $entity_uuid
   *                            The uuid of the entity that should be pulled
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   *
   * @deprecated Function is deprecated and is going to be removed in 2.0, use
   *   pull() instead.
   */
  public function force_pull_entity($io, $flow_id, $entity_type, $entity_uuid) {
    $io
      ->warning('Function is deprecated and is going to be removed in 2.0, use "cs-pull" instead.');
    FlowPull::force_pull_entity($flow_id, $entity_type, $entity_uuid);
  }

  /**
   * Push all entities for a specific flow.
   *
   * @param ICLIIO $io
   *                        The CLI service which allows interoperability
   * @param string $flow_id
   *                        The flow the entities should be pulled from
   * @param array  $options
   *                        An array containing the option parameters provided by Drush
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   * @throws \GuzzleHttp\Exception\GuzzleException
   */
  public function push($io, $flow_id, $options) {
    $push_mode = $options['push_mode'];
    $flows = Flow::getAll();
    if (!is_null($push_mode)) {
      if ('automatic_manual' != $push_mode && 'automatic_manual_force' != $push_mode) {
        $io
          ->error('Invalid value detected for push_mode. Allowed values are: automatic_manual and automatic_manual_force.');
        return;
      }
    }
    foreach ($flows as $id => $flow) {
      if ($flow_id && $id != $flow_id) {
        continue;
      }

      /**
       * @var \Drupal\Core\Entity\EntityTypeManager $entity_type_manager
       */
      $entity_type_manager = \Drupal::service('entity_type.manager');
      foreach ($flow
        ->getEntityTypeConfig(null, null, true) as $config) {
        if ('automatic_manual' == $push_mode || 'automatic_manual_force' == $push_mode) {
          if (PushIntent::PUSH_AUTOMATICALLY != $config['export'] && PushIntent::PUSH_MANUALLY != $config['export']) {
            continue;
          }
        }
        else {
          if (PushIntent::PUSH_AUTOMATICALLY != $config['export']) {
            continue;
          }
        }
        $storage = $entity_type_manager
          ->getStorage($config['entity_type_name']);
        $query = $storage
          ->getQuery();

        // Files don't have bundles, so this would lead to a fatal error then.
        if ($storage
          ->getEntityType()
          ->getKey('bundle')) {
          $query = $query
            ->condition($storage
            ->getEntityType()
            ->getKey('bundle'), $config['bundle_name']);
        }
        $ids = $query
          ->execute();
        $total = count($ids);
        $success = 0;
        $io
          ->text('Starting to push ' . $total . ' entities.');
        foreach ($ids as $id) {
          $entity = $storage
            ->load($id);

          /**
           * @var \Drupal\cms_content_sync\Entity\EntityStatus[] $entity_status
           */
          $entity_status = EntityStatus::getInfosForEntity($entity
            ->getEntityTypeId(), $entity
            ->uuid(), [
            'flow' => $flow
              ->id(),
          ]);
          if ('automatic_manual' == $push_mode && (empty($entity_status) || is_null($entity_status[0]
            ->getLastPush()))) {
            continue;
          }

          /**
           * @var \Drupal\Core\Entity\EntityTypeManager $entity_type_manager
           */
          $entity_type_manager = \Drupal::service('entity_type.manager');
          $entity = $entity_type_manager
            ->getStorage($config['entity_type_name'])
            ->load($id);
          try {
            PushIntent::pushEntity($entity, PushIntent::PUSH_FORCED, SyncIntent::ACTION_CREATE, $flow);
            ++$success;
          } catch (\Exception $exception) {
            \Drupal::logger('cms_content_sync')
              ->notice('Entity could not be pushed, reason: %exception<br>Flow: @flow_id', [
              '%exception' => $exception
                ->getMessage(),
              '@flow_id' => $flow_id,
            ]);
          }
        }
        $io
          ->text('Successfully pushed ' . $success . ' entities.');
        if ($total != $success) {
          $io
            ->text('Failed to push ' . ($total - $success) . ' entities.');
        }
      }
    }
  }

  /**
   * Reset the status entities for a specific or all pool/s.
   *
   * @param ICLIIO $io
   *                        The CLI service which allows interoperability
   * @param array  $options
   *                        An array containing the option parameters provided by Drush
   *
   * @throws \Drush\Exceptions\UserAbortException
   */
  public function reset_status_entities($io, $options = [
    'pool_id' => null,
  ]) {
    $pool_id = empty($options['pool_id']) ? null : $options['pool_id'];
    if (empty($pool_id)) {
      $io
        ->warning(dt('Are you sure you want to reset the status entities for all pools?'));
    }
    else {
      $io
        ->warning(dt('Are you sure you want to reset the status entities for the pool: ' . $pool_id . '?'));
    }
    $io
      ->warning(dt('By resetting the status of all entities, the date of the last pull and the date of the last push date will be reset. The dates will no longer be displayed until the content is pulled or pushed again and all entities will be pushed / pulled again at the next synchronization regardless of whether they have changed or not.'));
    if (!$io
      ->confirm(dt('Do you want to continue?'))) {
      throw new UserAbortException();
    }
    empty($pool_id) ? Pool::resetStatusEntities() : Pool::resetStatusEntities($pool_id);
    $io
      ->success('Status entities have been reset and entity caches are invalidated.');
  }

  /**
   * Check the flags for an entity.
   *
   * @param ICLIIO $io
   *                            The CLI service which allows interoperability
   * @param string $entity_uuid
   *                            The uuid of the entity the flags should be checked for
   * @param array  $options
   *                            An array containing the option parameters provided by Drush
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  public function check_entity_flags($io, $entity_uuid, $options = [
    'flag' => null,
  ]) {
    $flag = empty($options['flag']) ? null : $options['flag'];

    /**
     * @var \Drupal\cms_content_sync\Entity\EntityStatus[] $entity_status
     */
    $entity_status = \Drupal::entityTypeManager()
      ->getStorage('cms_content_sync_entity_status')
      ->loadByProperties([
      'entity_uuid' => $entity_uuid,
    ]);
    if (empty($entity_status)) {
      $io
        ->text(dt('There is no status entity existent yet for this UUID.'));
    }
    else {
      foreach ($entity_status as $status) {
        $result = '';
        $io
          ->text(dt('Flow: ' . $status
          ->get('flow')->value));
        if (empty($flag)) {
          $result .= 'FLAG_IS_SOURCE_ENTITY: ' . ($status
            ->isSourceEntity() ? 'TRUE' : 'FALSE') . PHP_EOL;
          $result .= 'FLAG_PUSH_ENABLED: ' . ($status
            ->isPushEnabled() ? 'TRUE' : 'FALSE') . PHP_EOL;
          $result .= 'FLAG_PUSHED_AS_DEPENDENCY: ' . ($status
            ->isPushedAsDependency() ? 'TRUE' : 'FALSE') . PHP_EOL;
          $result .= 'FLAG_EDIT_OVERRIDE: ' . ($status
            ->isOverriddenLocally() ? 'TRUE' : 'FALSE') . PHP_EOL;
          $result .= 'FLAG_USER_ENABLED_PUSH: ' . ($status
            ->didUserEnablePush() ? 'TRUE' : 'FALSE') . PHP_EOL;
          $result .= 'FLAG_DELETED: ' . ($status
            ->isDeleted() ? 'TRUE' : 'FALSE') . PHP_EOL;
        }
        else {
          switch ($flag) {
            case 'FLAG_IS_SOURCE_ENTITY':
              $status
                ->isSourceEntity() ? $result .= 'TRUE' : ($result .= 'FALSE');
              break;
            case 'FLAG_PUSH_ENABLED':
              $status
                ->isPushEnabled() ? $result .= 'TRUE' : ($result .= 'FALSE');
              break;
            case 'FLAG_PUSHED_AS_DEPENDENCY':
              $status
                ->isPushedAsDependency() ? $result .= 'TRUE' : ($result .= 'FALSE');
              break;
            case 'FLAG_EDIT_OVERRIDE':
              $status
                ->isOverriddenLocally() ? $result .= 'TRUE' : ($result .= 'FALSE');
              break;
            case 'FLAG_USER_ENABLED_PUSH':
              $status
                ->didUserEnablePush() ? $result .= 'TRUE' : ($result .= 'FALSE');
              break;
            case 'FLAG_DELETED':
              $status
                ->isDeleted() ? $result .= 'TRUE' : ($result .= 'FALSE');
              break;
          }
        }
        $io
          ->text(dt($result));
      }
    }
  }

}

Members

Namesort descending Modifiers Type Description Overrides
CliService::check_entity_flags public function Check the flags for an entity.
CliService::configuration_export public function Export the configuration to the Sync Core.
CliService::force_pull_entity Deprecated public function Kindly ask the Sync Core to force pull a specific entity.
CliService::pull public function Kindly ask the Sync Core to pull all entities for a specific flow, or to force pull one specific entity.
CliService::pull_entities Deprecated public function Kindly ask the Sync Core to pull all entities for a specific flow.
CliService::push public function Push all entities for a specific flow.
CliService::reset_status_entities public function Reset the status entities for a specific or all pool/s.
CliService::sync_core_login public function Kindly ask the Sync Core to login again.