View source
<?php
declare (strict_types=1);
namespace Drupal\entity_share_cron;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Queue\QueueFactory;
use Drupal\Component\Serialization\Json;
use Drupal\entity_share\EntityShareUtility;
use Drupal\entity_share_client\Entity\Remote;
use Drupal\entity_share_client\Service\JsonapiHelperInterface;
use Drupal\entity_share_client\Service\RemoteManagerInterface;
class EntityShareCronService implements EntityShareCronServiceInterface {
protected $config;
protected $remoteManager;
protected $jsonapiHelper;
protected $queueFactory;
protected $entityTypeManager;
public function __construct(ConfigFactoryInterface $config_factory, RemoteManagerInterface $remote_manager, JsonapiHelperInterface $jsonapi_helper, QueueFactory $queue_factory, EntityTypeManagerInterface $entity_type_manager) {
$this->config = $config_factory
->get('entity_share_cron.settings');
$this->remoteManager = $remote_manager;
$this->jsonapiHelper = $jsonapi_helper;
$this->queueFactory = $queue_factory;
$this->entityTypeManager = $entity_type_manager;
}
public function enqueue($remote_id, $channel_id, array $channel_info) {
$queue_name = EntityShareCronServiceInterface::PENDING_QUEUE_NAME;
$queue = $this->queueFactory
->get($queue_name);
$item = [
'remote_id' => $remote_id,
'channel_id' => $channel_id,
'channel_info' => $channel_info,
];
$queue
->createItem($item);
}
public function sync($remote_id, $channel_id, array $channel_info, $page_limit = 0) {
$data_to_import = [];
$next_page = 1;
$url = $channel_info['url'];
while ($url) {
$page_data = $this
->getPage($remote_id, $channel_id, $url);
$data_to_import = array_merge($data_to_import, $page_data['data']);
$next_page++;
$url = $page_data['next'];
if ($url) {
if ($page_limit != 0 && $next_page > $page_limit) {
$next_info = $channel_info;
$next_info['url'] = $url;
$this
->enqueue($remote_id, $channel_id, $next_info);
$url = FALSE;
}
}
}
$channel_config = $this
->getChannelConfig($remote_id, $channel_id);
if (empty($channel_config['operations']['create'])) {
$this
->filterDataToImport($data_to_import);
}
if (empty($channel_config['operations']['update'])) {
$this
->filterDataToImport($data_to_import, FALSE);
}
return $this->jsonapiHelper
->importEntityListData($data_to_import);
}
protected function getPage($remote_id, $channel_id, $url) {
$data = [
'data' => [],
'next' => FALSE,
];
$remote = Remote::load($remote_id);
if ($remote) {
$this->jsonapiHelper
->setRemote($remote);
$http_client = $this->remoteManager
->prepareJsonApiClient($remote);
$json_response = $http_client
->get($url)
->getBody()
->getContents();
$json = Json::decode($json_response);
$data['data'] = EntityShareUtility::prepareData($json['data']);
$data['next'] = !empty($json['links']['next']['href']) ? $json['links']['next']['href'] : FALSE;
}
return $data;
}
protected function filterDataToImport(array &$data, $keep_existing = TRUE) {
$uuid_by_type = [];
foreach ($data as $entity_data) {
$parsed_type = explode('--', $entity_data['type']);
$entity_type = $parsed_type[0];
$uuid = $entity_data['id'];
$uuid_by_type[$entity_type][] = $uuid;
}
$existing_uuids = [];
foreach ($uuid_by_type as $entity_type => $uuids) {
$definition = $this->entityTypeManager
->getDefinition($entity_type);
$uuid_property = $definition
->getKey('uuid');
$storage = $this->entityTypeManager
->getStorage($entity_type);
$existing_entities = $storage
->loadByProperties([
$uuid_property => $uuids,
]);
foreach ($existing_entities as $entity) {
$uuid = $entity
->uuid();
$existing_uuids[$uuid] = $uuid;
}
}
$data_updated = [];
foreach ($data as $entity_data) {
$uuid = $entity_data['id'];
if ($keep_existing && !empty($existing_uuids[$uuid])) {
$data_updated[] = $entity_data;
}
elseif (!$keep_existing && empty($existing_uuids[$uuid])) {
$data_updated[] = $entity_data;
}
}
$data = $data_updated;
}
protected function getChannelConfig($remote_id, $channel_id) {
$settings = [];
$remotes = $this->config
->get('remotes');
if (!empty($remotes[$remote_id]['channels'][$channel_id])) {
$settings = $remotes[$remote_id]['channels'][$channel_id];
}
return $settings;
}
}