cms_content_sync-3.0.x-dev/src/Controller/PushEntities.php
src/Controller/PushEntities.php
<?php
namespace Drupal\cms_content_sync\Controller;
use Drupal\cms_content_sync\Entity\EntityStatus;
use Drupal\cms_content_sync\Entity\Flow;
use Drupal\cms_content_sync\PushIntent;
use Drupal\cms_content_sync\SyncIntent;
use Drupal\Core\Controller\ControllerBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Entity\EntityInterface;
/**
* Pull controller.
*
* Note that this controller is also used by the draggableviews submodule.
*/
class PushEntities extends ControllerBase {
/**
* The operations to perform.
*
* @var null|array
*/
protected $operations = [];
/**
* The title of the entity to be pushed.
*
* @var \Drupal\Core\StringTranslation\TranslatableMarkup
*/
protected $title;
/**
* The push entities batch callback.
*
* @var array|string
*/
protected $callback;
/**
* Show skipped option.
*
* @var bool
*/
protected $showSkipped = FALSE;
/**
* Skip unpushed option.
*
* @var bool
*/
protected $skipUnpushed = FALSE;
/**
* The skipped unpushed entities.
*
* @var array
*/
protected $skippedUnpushed = [];
/**
* The skipped entities due to no matching flow.
*
* @var array
*/
protected $skippedNoFlow = [];
/**
* PushEntities constructor.
*
* @param null|array $existing
* Already existing operations.
*/
public function __construct($existing = NULL) {
$this->operations = $existing;
$this->title = t('Push content');
$this->callback = '\Drupal\cms_content_sync\Controller\PushEntities::batchFinished';
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, $existing = NULL) {
return new PushEntities($existing);
}
/**
* Skip unpushed entities.
*
* @return $this
*/
public function skipUnpushed() {
$this->skipUnpushed = TRUE;
return $this;
}
/**
* Show skipped entities.
*
* @return $this
*/
public function showSkipped() {
if ($count = count($this->skippedNoFlow)) {
$list = [
'#theme' => 'item_list',
'#items' => $this->getSkippedNoFlow(TRUE)
];
\Drupal::messenger()->addWarning(
\Drupal::translation()->translate(
"%count items were not pushed as they're not configured to be pushed: @items",
[
'%count' => $count,
'@items' => \Drupal::service('renderer')->render($list),
]
)
);
}
if ($count = count($this->skippedUnpushed)) {
$list = [
'#theme' => 'item_list',
'#items' => $this->getSkippedUnpushed(TRUE)
];
\Drupal::messenger()->addStatus(
\Drupal::translation()->translate(
"%count items were not pushed as they weren't pushed before: @items",
[
'%count' => $count,
'@items' => \Drupal::service('renderer')->render($list),
]
)
);
}
return $this;
}
/**
* Returns the skipped unpushed entities.
*
* @param bool $labelsOnly
* Return only the labels of the unpushed entities.
*
* @return array
* The skipped unpushed entities.
*/
public function getSkippedUnpushed($labelsOnly = FALSE) {
return $labelsOnly ? $this->getLabels($this->skippedUnpushed) : $this->skippedUnpushed;
}
/**
* Returns the skipped no flow entities.
*
* @param bool $labelsOnly
* Return only the labels of the unpushed entities.
*
* @return array
* The skipped no flow entities.
*/
public function getSkippedNoFlow($labelsOnly = FALSE) {
return $labelsOnly ? $this->getLabels($this->skippedNoFlow) : $this->skippedNoFlow;
}
/**
* Adds an entity to a push operation.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity to be added.
*
* @return $this
*/
public function addEntity(EntityInterface $entity) {
$flows = PushIntent::getFlowsForEntity($entity, PushIntent::PUSH_FORCED, SyncIntent::ACTION_CREATE);
if (!count($flows)) {
$this->skippedNoFlow[] = $entity;
return $this;
}
$flow_id = $flows[0]->id();
/**
* @var \Drupal\cms_content_sync\Entity\EntityStatus[] $entity_status
*/
$entity_status = EntityStatus::getInfosForEntity($entity->getEntityTypeId(), $entity->uuid(), ['flow' => $flow_id]);
if ($this->skipUnpushed) {
if (!count($entity_status) || !$entity_status[0]->getLastPush()) {
$this->skippedUnpushed[] = $entity;
return $this;
}
}
$this->add($flow_id, $entity->getEntityTypeId(), $entity->id());
return $this;
}
/**
* Get the operations that were already added.
*
* You can use them when instantiating this class again later to keep the
* existing operations and add on top of them.
*
* @return null|array
* The operations that were already added.
*/
public function get() {
return $this->operations;
}
/**
* Add entity into push operation.
*
* @param string $flow_id
* The id of the flow.
* @param string $entity_type_id
* The entity type id.
* @param int $entity_id
* The entity id.
*
* @return $this
* The current instance of the operation.
*/
public function add($flow_id, $entity_type_id, $entity_id) {
$this->operations[] = [
'\Drupal\cms_content_sync\Controller\PushEntities::batch',
[$flow_id, $entity_type_id, $entity_id],
];
return $this;
}
/**
* Sets the entity title for the push operation.
*
* @param string $set
* The entity title.
*
* @return $this
* The current instance of the operation.
*/
public function setTitle($set) {
$this->title = $set;
return $this;
}
/**
* Set the callback for the push operation.
*
* @param array|string $set
* The callback to be set.
*
* @return $this
* The current instance of the operation.
*/
public function setCallback($set) {
$this->callback = $set;
return $this;
}
/**
* Start the actual batch operation.
*
* @param null|\Drupal\Core\Url $url
* The URL to return to after the batch operation is finished.
*
* @return null|\Symfony\Component\HttpFoundation\RedirectResponse
* NULL or the RedirectResponse based on the URL.
*/
public function start($url = NULL) {
$batch = [
'title' => $this->title,
'operations' => $this->operations,
'finished' => $this->callback,
];
batch_set($batch);
if ($url) {
return batch_process($url);
}
return NULL;
}
/**
* Check if there actually are any operations to perform now.
*
* @return bool
* TRUE if there are operations to perform, FALSE otherwise.
*/
public function isEmpty() {
return !count($this->operations);
}
/**
* Batch push finished callback.
*
* @param bool $success
* True if the batch operation was successful.
* @param array $results
* The resuluts of the batch operation.
* @param array $operations
* The operations that were already added.
*/
public static function batchFinished($success, array $results, array $operations) {
$succeeded = count(array_filter($results));
\Drupal::messenger()->addMessage(t('%synchronized items have been pushed to your @repository.', [
'@repository' => _cms_content_sync_get_repository_name(),
'%synchronized' => $succeeded
]));
$failed = count($results) - $succeeded;
if ($failed) {
\Drupal::messenger()->addMessage(t('%synchronized items have not been pushed to your @repository.', [
'@repository' => _cms_content_sync_get_repository_name(),
'%synchronized' => $failed
]));
}
}
/**
* The batch push callback.
*
* Batch push callback used by the following operations:
* - Flow: Push All
* - Content overview: Push changes
* - Draggableviews: Push changes.
*
* @param string $flow_id
* The id of the flow.
* @param string $entity_type_id
* The id of the entity type.
* @param int $entity_id
* The id of the entity.
* @param array $context
* The context for the operation.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public static function batch($flow_id, $entity_type_id, $entity_id, array &$context) {
$message = 'Pushing...';
$results = [];
if (isset($context['results'])) {
$results = $context['results'];
}
/**
* @var \Drupal\cms_content_sync\Entity\Flow $flow
*/
$flow = Flow::getAll()[$flow_id];
/**
* @var \Drupal\Core\Entity\EntityTypeManager $entity_type_manager
*/
$entity_type_manager = \Drupal::service('entity_type.manager');
$entity = $entity_type_manager
->getStorage($entity_type_id)
->load($entity_id);
try {
$status = PushIntent::pushEntity($entity, PushIntent::PUSH_FORCED, SyncIntent::ACTION_CREATE, $flow);
}
catch (\Exception $exception) {
\Drupal::messenger()->addWarning(t('Item %label could not be pushed: %exception', [
'%label' => $entity->label(),
'%exception' => $exception->getMessage()
]));
$status = FALSE;
}
$results[] = $status;
$context['message'] = $message;
$context['results'] = $results;
}
/**
* Get the entity labels.
*
* @param array $entities
* The entities to get the labels for.
*
* @return array
* The entity labels.
*/
protected function getLabels(array $entities) {
$result = [];
foreach ($entities as $entity) {
$result[] = $entity->label();
}
return $result;
}
}
