You are here

public function SyncCoreEntityListResource::get in CMS Content Sync 2.0.x

Same name and namespace in other branches
  1. 2.1.x src/Plugin/rest/resource/SyncCoreEntityListResource.php \Drupal\cms_content_sync\Plugin\rest\resource\SyncCoreEntityListResource::get()

File

src/Plugin/rest/resource/SyncCoreEntityListResource.php, line 129

Class

SyncCoreEntityListResource
Provides entity interfaces for Content Sync, allowing Sync Core v2 to list entities.

Namespace

Drupal\cms_content_sync\Plugin\rest\resource

Code

public function get($flow_id) {
  $flow = Flow::getAll()[$flow_id];
  if (empty($flow)) {
    return $this
      ->returnError(t("The flow @flow_id doesn't exist.", [
      '@flow_id' => $flow_id,
    ])
      ->render());
  }
  $query = \Drupal::request()->query
    ->all();
  $queryObject = new RemoteRequestQueryParamsEntityList($query);
  $page = (int) $queryObject
    ->getPage();
  if (!$page) {
    $page = 0;
  }
  $items_per_page = (int) $queryObject
    ->getItemsPerPage();
  if (!$items_per_page) {
    $items_per_page = 0;
  }
  $mode = $queryObject
    ->getMode();
  if (!$mode) {
    return $this
      ->returnError(t('The mode query parameter is required.')
      ->render());
  }

  // Need to convert miliseconds to seconds.
  $changed_after = $queryObject
    ->getChangedAfter() ? floor((int) $queryObject
    ->getChangedAfter() / 1000) : null;
  $entity_type = $queryObject
    ->getNamespaceMachineName();
  $bundle = $queryObject
    ->getMachineName();
  $skip = $page * $items_per_page;
  $database = \Drupal::database();

  /**
   * @var RemoteEntitySummary[] $items
   */
  $items = [];

  // If ALL entities are requested, we can't rely on the status entity.
  // Instead, we query for these entities by their type's table directly.
  if (RemoteEntityListRequestMode::ALL === $mode) {
    if (!$entity_type || !$bundle) {
      return $this
        ->returnError(t("The type and bundle query parameters are required for mode 'all'.")
        ->render());
    }
    $entity_type_storage = \Drupal::entityTypeManager()
      ->getStorage($entity_type);
    $bundle_key = $entity_type_storage
      ->getEntityType()
      ->getKey('bundle');
    $id_key = $entity_type_storage
      ->getEntityType()
      ->getKey('id');
    $base_table = $entity_type_storage
      ->getBaseTable();
    $data_table = $entity_type_storage
      ->getDataTable();
    $definitions = \Drupal::service('entity_field.manager')
      ->getFieldDefinitions($entity_type, $bundle);
    $query = $database
      ->select($base_table, 'bt');
    $query
      ->condition('bt.' . $bundle_key, $bundle)
      ->fields('bt', [
      $id_key,
    ]);
    if (isset($definitions['created'])) {
      $query
        ->join($data_table, 'dt', 'dt.' . $id_key . '= bt.' . $id_key);
      if ($changed_after) {
        $query
          ->condition('dt.created', $changed_after, '>');
      }
      $query
        ->orderBy('dt.created', 'ASC');
    }
    else {
      $query
        ->orderBy('bt.' . $id_key, 'ASC');
    }
    $total_number_of_items = (int) $query
      ->countQuery()
      ->execute()
      ->fetchField();
    if ($total_number_of_items && $items_per_page) {
      $ids = $query
        ->range($skip, $items_per_page)
        ->execute()
        ->fetchAll(PDO::FETCH_COLUMN);
      $entities = $entity_type_storage
        ->loadMultiple($ids);
      foreach ($entities as $entity) {
        $items[] = $this
          ->getItem($flow, $entity, EntityStatus::getInfosForEntity($entity
          ->getEntityTypeId(), $entity
          ->uuid(), [
          'flow' => $flow_id,
        ]));
      }
    }
  }
  else {
    $query = $database
      ->select('cms_content_sync_entity_status', 'cses');
    if ($entity_type && $bundle) {
      $entity_type_storage = \Drupal::entityTypeManager()
        ->getStorage($entity_type);
      $bundle_key = $entity_type_storage
        ->getEntityType()
        ->getKey('bundle');
      $table = $entity_type_storage
        ->getBaseTable();
      $query
        ->join($table, 'bt', 'bt.uuid = cses.entity_uuid');
    }
    $query
      ->condition('cses.flow', $flow_id);
    $changed_field = RemoteEntityListRequestMode::PULLED === $mode ? 'last_import' : 'last_export';
    if ($changed_after) {
      $query
        ->condition('cses.' . $changed_field, $changed_after, '>');
    }
    elseif (RemoteEntityListRequestMode::PULLED === $mode || RemoteEntityListRequestMode::PUSHED === $mode) {
      $query
        ->condition('cses.' . $changed_field, 0, '>');
    }
    if ($entity_type) {
      $query
        ->condition('cses.entity_type', $entity_type);
      if ($bundle) {
        $query
          ->condition('bt.' . $bundle_key, $bundle);
      }
    }
    if (RemoteEntityListRequestMode::PUSH_FAILED === $mode) {
      $query
        ->where('flags&:flag=:flag', [
        ':flag' => EntityStatus::FLAG_PUSH_FAILED,
      ]);
    }
    $query
      ->addExpression('MIN(cses.id)', 'min_id');
    $query
      ->orderBy('min_id', 'ASC')
      ->fields('cses', [
      'entity_type',
      'entity_uuid',
    ]);
    $query
      ->groupBy('cses.entity_type');
    $query
      ->groupBy('cses.entity_uuid');
    $total_number_of_items = (int) $query
      ->countQuery()
      ->execute()
      ->fetchField();
    if ($total_number_of_items && $items_per_page) {
      $query
        ->range($skip, $items_per_page);
      $ids = $query
        ->execute()
        ->fetchAll(PDO::FETCH_ASSOC);
      foreach ($ids as $id) {
        $entity = \Drupal::service('entity.repository')
          ->loadEntityByUuid($id['entity_type'], $id['entity_uuid']);
        $items[] = $this
          ->getItem($flow, $entity, EntityStatus::getInfosForEntity($id['entity_type'], $id['entity_uuid'], [
          'flow' => $flow_id,
        ]));
      }
    }
  }
  if (!$items_per_page) {
    $number_of_pages = $total_number_of_items;
  }
  else {
    $number_of_pages = ceil($total_number_of_items / $items_per_page);
  }
  $result = new RemoteEntityListResponse();
  $result
    ->setPage($page);
  $result
    ->setNumberOfPages($number_of_pages);
  $result
    ->setItemsPerPage($items_per_page);
  $result
    ->setTotalNumberOfItems($total_number_of_items);
  $result
    ->setItems($items);
  $body = $result
    ->jsonSerialize();

  // Turn object into array because Drupal doesn't think stdObject can be
  // serialized the same way.
  return $this
    ->respondWith(json_decode(json_encode($body), true), 200);
}