private function EntityResource::handleIncomingEntity in CMS Content Sync 8
Same name and namespace in other branches
- 2.1.x src/Plugin/rest/resource/EntityResource.php \Drupal\cms_content_sync\Plugin\rest\resource\EntityResource::handleIncomingEntity()
- 2.0.x src/Plugin/rest/resource/EntityResource.php \Drupal\cms_content_sync\Plugin\rest\resource\EntityResource::handleIncomingEntity()
Parameters
string $api: The API {@see Flow}
string $entity_type_name: The entity type of the processed entity
string $entity_bundle: The bundle of the processed entity
string $entity_type_version: The version the config was saved for
array $data: For {@see ::ACTION_CREATE} and {@see ::ACTION_UPDATE}: the data for the entity. Will be passed to {@see SyncIntent}.
string $action: The {@see ::ACTION_*} to be performed on the entity
Return value
\Symfony\Component\HttpFoundation\Response the result (error, ignorance or success)
Throws
\Drupal\cms_content_sync\Exception\SyncException
\Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
\Drupal\Component\Plugin\Exception\PluginNotFoundException
\Drupal\Core\Entity\EntityStorageException
3 calls to EntityResource::handleIncomingEntity()
- EntityResource::delete in src/
Plugin/ rest/ resource/ EntityResource.php - Responds to entity DELETE requests.
- EntityResource::patch in src/
Plugin/ rest/ resource/ EntityResource.php - Responds to entity PATCH requests.
- EntityResource::post in src/
Plugin/ rest/ resource/ EntityResource.php - Responds to entity POST requests.
File
- src/
Plugin/ rest/ resource/ EntityResource.php, line 355
Class
- EntityResource
- Provides entity interfaces for Content Sync, allowing Sync Core to request and manipulate entities.
Namespace
Drupal\cms_content_sync\Plugin\rest\resourceCode
private function handleIncomingEntity($api, $entity_type_name, $entity_bundle, $entity_type_version, array $data, $action) {
if (self::PING_PARAMETER === $api) {
return new ResourceResponse(SyncIntent::ACTION_DELETE === $action ? null : [
'pong' => true,
]);
}
$entity_types = $this->entityTypeBundleInfo
->getAllBundleInfo();
if (empty($entity_types[$entity_type_name])) {
return new ResourceResponse(SyncIntent::ACTION_DELETE == $action ? null : [
'message' => t(self::TYPE_HAS_NOT_BEEN_FOUND)
->render(),
], self::CODE_NOT_FOUND);
}
$is_dependency = isset($_GET['is_dependency']) && 'true' == $_GET['is_dependency'];
$is_manual = isset($_GET['is_manual']) && 'true' == $_GET['is_manual'];
$reason = $is_dependency ? PullIntent::PULL_AS_DEPENDENCY : ($is_manual ? PullIntent::PULL_MANUALLY : PullIntent::PULL_AUTOMATICALLY);
$entity_uuid = null;
$pool = Pool::getAll()[$api];
if (empty($pool)) {
\Drupal::logger('cms_content_sync')
->warning('@not PULL @action @entity_type:@bundle @uuid @reason: @message<br>Flow: @flow_id', [
'@reason' => $reason,
'@action' => $action,
'@entity_type' => $entity_type_name,
'@bundle' => $entity_bundle,
'@uuid' => $entity_uuid,
'@not' => 'NO',
'@flow_id' => $api,
'@message' => t('No pool config matches this request (@api).', [
'@api' => $api,
])
->render(),
]);
$this
->saveFailedPull($api, $entity_type_name, $entity_bundle, $entity_type_version, $entity_uuid, PullIntent::PULL_FAILED_UNKNOWN_POOL, $action, $reason);
return new ResourceResponse(SyncIntent::ACTION_DELETE == $action ? null : [
'message' => t(self::TYPE_HAS_NOT_BEEN_FOUND)
->render(),
], self::CODE_NOT_FOUND);
}
$flow = Flow::getFlowForApiAndEntityType($pool, $entity_type_name, $entity_bundle, $reason, $action);
// Deletion requests will not provide the "is_dependency" query parameter.
if (empty($flow) && SyncIntent::ACTION_DELETE == $action && PullIntent::PULL_AS_DEPENDENCY != $reason) {
$flow = Flow::getFlowForApiAndEntityType($pool, $entity_type_name, $entity_bundle, PullIntent::PULL_AS_DEPENDENCY, $action);
if (!empty($flow)) {
$reason = PullIntent::PULL_AS_DEPENDENCY;
}
}
if (empty($flow)) {
\Drupal::logger('cms_content_sync')
->notice('@not PULL @action @entity_type:@bundle @uuid @reason: @message', [
'@reason' => $reason,
'@action' => $action,
'@entity_type' => $entity_type_name,
'@bundle' => $entity_bundle,
'@uuid' => $entity_uuid,
'@not' => 'NO',
'@message' => t('No synchronization config matches this request (dependency: @dependency, manual: @manual).', [
'@dependency' => $is_dependency ? 'YES' : 'NO',
'@manual' => $is_manual ? 'YES' : 'NO',
])
->render(),
]);
$this
->saveFailedPull($api, $entity_type_name, $entity_bundle, $entity_type_version, $entity_uuid, PullIntent::PULL_FAILED_NO_FLOW, $action, $reason);
return new ResourceResponse(SyncIntent::ACTION_DELETE == $action ? null : [
'message' => t(self::TYPE_HAS_NOT_BEEN_FOUND)
->render(),
], self::CODE_NOT_FOUND);
}
$operation = $pool
->getClient()
->getSyndicationService()
->handlePull($flow->id, $entity_type_name, $entity_bundle, $data);
// DELETE requests only give the ID of the config, not their UUID. So we need to grab the UUID from our local
// database before continuing.
if (SyncIntent::ACTION_DELETE === $action && EntityHandlerPluginManager::isEntityTypeConfiguration($entity_type_name)) {
$entity_uuid = \Drupal::entityTypeManager()
->getStorage($entity_type_name)
->load($operation
->getId())
->uuid();
}
else {
$entity_uuid = $operation
->getUuid();
}
$local_version = Flow::getEntityTypeVersion($entity_type_name, $entity_bundle);
// Allow DELETE requests- when an entity is deleted, the entity type definition may have changed in the meantime
// but this doesn't prevent us from deleting it. The version is only important for creations and updates.
if ($entity_type_version != $local_version && SyncIntent::ACTION_DELETE != $action) {
\Drupal::logger('cms_content_sync')
->warning('@not PULL @action @entity_type:@bundle @uuid @reason: @message<br>Flow: @flow_id | Pool: @pool_id', [
'@reason' => $reason,
'@action' => $action,
'@entity_type' => $entity_type_name,
'@bundle' => $entity_bundle,
'@uuid' => $entity_uuid,
'@not' => 'NO',
'@flow_id' => $api,
'@pool_id' => $pool
->id(),
'@message' => t('The requested entity type version @requested doesn\'t match the local entity type version @local.', [
'@requested' => $entity_type_version,
'@local' => $local_version,
])
->render(),
]);
$this
->saveFailedPull($api, $entity_type_name, $entity_bundle, $entity_type_version, $entity_uuid, PullIntent::PULL_FAILED_DIFFERENT_VERSION, $action, $reason, $flow->id);
return new ResourceResponse([
'message' => t(self::TYPE_HAS_INCOMPATIBLE_VERSION)
->render(),
], self::CODE_NOT_FOUND);
}
try {
$intent = new PullIntent($flow, $pool, $reason, $action, $entity_type_name, $entity_bundle, $operation);
$status = $intent
->execute();
} catch (SyncException $e) {
$message = $e->parentException ? $e->parentException
->getMessage() : ($e->errorCode == $e
->getMessage() ? '' : $e
->getMessage());
if ($message) {
$message = t('Internal error @code: @message', [
'@code' => $e->errorCode,
'@message' => $message,
])
->render();
}
else {
$message = t('Internal error @code', [
'@code' => $e->errorCode,
])
->render();
}
\Drupal::logger('cms_content_sync')
->error('@not PULL @action @entity_type:@bundle @uuid @reason: @message' . "\n" . '@trace' . "\n" . '@request_body<br>Flow: @flow_id | Pool: @pool_id', [
'@reason' => $reason,
'@action' => $action,
'@entity_type' => $entity_type_name,
'@bundle' => $entity_bundle,
'@uuid' => $entity_uuid,
'@not' => 'NO',
'@flow_id' => $api,
'@pool_id' => $pool
->id(),
'@message' => $message,
'@trace' => ($e->parentException ? $e->parentException
->getTraceAsString() . "\n\n\n" : '') . $e
->getTraceAsString(),
'@request_body' => json_encode($data),
]);
$this
->saveFailedPull($api, $entity_type_name, $entity_bundle, $entity_type_version, $entity_uuid, PullIntent::PULL_FAILED_CONTENT_SYNC_ERROR, $action, $reason, $flow->id);
return new ResourceResponse(SyncIntent::ACTION_DELETE == $action ? null : [
'message' => t('SyncException @code: @message', [
'@code' => $e->errorCode,
'@message' => $e
->getMessage(),
])
->render(),
'code' => $e->errorCode,
], 500);
} catch (\Exception $e) {
$message = $e
->getMessage();
\Drupal::logger('cms_content_sync')
->error('@not PULL @action @entity_type:@bundle @uuid @reason: @message' . "\n" . '@trace' . "\n" . '@request_body<br>Flow: @flow_id | Pool: @pool_id', [
'@reason' => $reason,
'@action' => $action,
'@entity_type' => $entity_type_name,
'@bundle' => $entity_bundle,
'@uuid' => $entity_uuid,
'@not' => 'NO',
'@flow_id' => $api,
'@pool_id' => $pool
->id(),
'@message' => $message,
'@trace' => $e
->getTraceAsString(),
'@request_body' => json_encode($data),
]);
$this
->saveFailedPull($api, $entity_type_name, $entity_bundle, $entity_type_version, $entity_uuid, PullIntent::PULL_FAILED_INTERNAL_ERROR, $action, $reason, $flow->id);
return new ResourceResponse(SyncIntent::ACTION_DELETE == $action ? null : [
'message' => t('Unexpected error: @message', [
'@message' => $e
->getMessage(),
])
->render(),
], 500);
}
if (!$status) {
$this
->saveFailedPull($api, $entity_type_name, $entity_bundle, $entity_type_version, $entity_uuid, PullIntent::PULL_FAILED_HANDLER_DENIED, $action, $reason, $flow->id);
}
if ($status) {
$entity = $intent
->getEntity();
$url = null;
if ($entity && $entity
->hasLinkTemplate('canonical')) {
try {
$url = $entity
->toUrl('canonical', [
'absolute' => true,
])
->toString(true)
->getGeneratedUrl();
} catch (\Exception $e) {
throw new SyncException(SyncException::CODE_UNEXPECTED_EXCEPTION, $e);
}
}
$response_body = $operation
->getResponseBody($url);
// If we send data for DELETE requests, the Drupal Serializer will throw
// a random error. So we just leave the body empty then.
return new ModifiedResourceResponse(SyncIntent::ACTION_DELETE == $action ? null : $response_body);
}
return new ResourceResponse(SyncIntent::ACTION_DELETE == $action ? null : [
'message' => t('Entity is not configured to be pulled yet.')
->render(),
], 404);
}