public function SchedulerManager::publish in Scheduler 2.x
Same name and namespace in other branches
- 8 src/SchedulerManager.php \Drupal\scheduler\SchedulerManager::publish()
Publish scheduled entities.
Return value
bool TRUE if any entity has been published, FALSE otherwise.
Throws
\Drupal\scheduler\Exception\SchedulerEntityTypeNotEnabledException
File
- src/
SchedulerManager.php, line 231
Class
- SchedulerManager
- Defines a scheduler manager.
Namespace
Drupal\schedulerCode
public function publish() {
$result = FALSE;
$process = 'publish';
$plugins = $this
->getPlugins();
foreach ($plugins as $entityTypeId => $plugin) {
// Select all entities of the types for this plugin that are enabled for
// scheduled publishing and where publish_on is less than or equal to the
// current time.
$ids = [];
$scheduler_enabled_types = $this
->getEnabledTypes($entityTypeId, $process);
if (!empty($scheduler_enabled_types)) {
$query = $this->entityTypeManager
->getStorage($entityTypeId)
->getQuery()
->exists('publish_on')
->condition('publish_on', $this->time
->getRequestTime(), '<=')
->condition($plugin
->typeFieldName(), $scheduler_enabled_types, 'IN')
->sort('publish_on');
// Disable access checks for this query.
// @see https://www.drupal.org/node/2700209
$query
->accessCheck(FALSE);
// If the entity type is revisionable then make sure we look for the
// latest revision. This is important for moderated entities.
if ($this->entityTypeManager
->getDefinition($entityTypeId)
->isRevisionable()) {
$query
->latestRevision();
}
$ids = $query
->execute();
}
// Allow other modules to add to the list of entities to be published.
$hook_implementations = $this
->getHookImplementations('list', $entityTypeId);
foreach ($hook_implementations as $function) {
// Cast each hook result as array, to protect from bad implementations.
$ids = array_merge($ids, (array) $function($process, $entityTypeId));
}
// Allow other modules to alter the list of entities to be published.
$hook_implementations = $this
->getHookImplementations('list_alter', $entityTypeId);
foreach ($hook_implementations as $function) {
$function($ids, $process, $entityTypeId);
}
// Finally ensure that there are no duplicates in the list of ids.
$ids = array_unique($ids);
// In 8.x the entity translations are all associated with one entity id
// unlike 7.x where each translation was a separate id. This means that
// the list of ids returned above may have some translations that need
// processing now and others that do not.
/** @var \Drupal\Core\Entity\EntityInterface[] $entities */
$entities = $this
->loadEntities($ids, $entityTypeId);
foreach ($entities as $entity_multilingual) {
// The API calls could return entities of types which are not enabled
// for scheduled publishing, so do not process these. This check can be
// done once as the setting will be the same for all translations.
if (!$this
->getThirdPartySetting($entity_multilingual, 'publish_enable', $this
->setting('default_publish_enable'))) {
$this
->throwSchedulerException($entity_multilingual, 'SchedulerEntityTypeNotEnabledException', $process);
}
$languages = $entity_multilingual
->getTranslationLanguages();
foreach ($languages as $language) {
// The object returned by getTranslation() is a normal $entity.
$entity = $entity_multilingual
->getTranslation($language
->getId());
// If the current translation does not have a publish on value, or it
// is later than the date we are processing then move on to the next.
$publish_on = $entity->publish_on->value;
if (empty($publish_on) || $publish_on > $this->time
->getRequestTime()) {
continue;
}
// Check that other modules allow the process on this entity.
if (!$this
->isAllowed($entity, $process)) {
continue;
}
// Trigger the PRE_PUBLISH Scheduler event so that modules can react
// before the entity is published.
$this
->dispatchSchedulerEvent($entity, 'PRE_PUBLISH');
// Update 'changed' timestamp.
$entity
->setChangedTime($publish_on);
$old_creation_date = $entity
->getCreatedTime();
$msg_extra = '';
// If required, set the created date to match published date.
if ($this
->getThirdPartySetting($entity, 'publish_touch', $this
->setting('default_publish_touch')) || $entity
->getCreatedTime() > $publish_on && $this
->getThirdPartySetting($entity, 'publish_past_date_created', $this
->setting('default_publish_past_date_created'))) {
$entity
->setCreatedTime($publish_on);
$msg_extra = $this
->t('The previous creation date was @old_creation_date, now updated to match the publishing date.', [
'@old_creation_date' => $this->dateFormatter
->format($old_creation_date, 'short'),
]);
}
$create_publishing_revision = $this
->getThirdPartySetting($entity, 'publish_revision', $this
->setting('default_publish_revision'));
if ($create_publishing_revision && $entity
->getEntityType()
->isRevisionable()) {
$entity
->setNewRevision();
// Use a core date format to guarantee a time is included.
$revision_log_message = rtrim($this
->t('Published by Scheduler. The scheduled publishing date was @publish_on.', [
'@publish_on' => $this->dateFormatter
->format($publish_on, 'short'),
]) . ' ' . $msg_extra);
$entity
->setRevisionLogMessage($revision_log_message)
->setRevisionCreationTime($this->time
->getRequestTime());
}
// Unset publish_on so the entity will not get rescheduled by any
// interim calls to $entity->save().
$entity->publish_on->value = NULL;
// Invoke all implementations of hook_scheduler_publish_process() and
// hook_scheduler_{type}_publish_process() to allow other modules to
// do the "publishing" process instead of Scheduler.
$hook_implementations = $this
->getHookImplementations('publish_process', $entity);
$processed = FALSE;
$failed = FALSE;
foreach ($hook_implementations as $function) {
$return = $function($entity);
$processed = $processed || $return === 1;
$failed = $failed || $return === -1;
}
// Create a set of variables for use in the log message.
$entity_type = $this->entityTypeManager
->getStorage($entityTypeId . '_type')
->load($entity
->bundle());
$view_link = $entity
->toLink($this
->t('View @type', [
'@type' => strtolower($entity_type
->label()),
]));
$entity_type_link = $entity_type
->toLink($this
->t('@label settings', [
'@label' => $entity_type
->label(),
]), 'edit-form');
$logger_variables = [
'@type' => $entity_type
->label(),
'%title' => $entity
->label(),
'@hook' => implode(', ', $hook_implementations),
'link' => $view_link
->toString() . ' ' . $entity_type_link
->toString(),
];
if ($failed) {
// At least one hook function returned a failure or exception, so
// stop processing this entity and move on to the next one.
$this->logger
->warning('Publishing failed for %title. Calls to @hook returned a failure code.', $logger_variables);
// Restore the publish_on date to allow another attempt next time.
$entity->publish_on->value = $publish_on;
$entity
->save();
continue;
}
elseif ($processed) {
// The entity was 'published' by a module implementing the hook, so
// we only need to log this result.
$this->logger
->notice('@type: scheduled processing of %title completed by calls to @hook.', $logger_variables);
}
else {
// None of the above hook calls processed the entity and there were
// no errors detected so set the entity to published.
$this->logger
->notice('@type: scheduled publishing of %title.', $logger_variables);
$entity
->setPublished();
}
// Invoke event to tell Rules that Scheduler has published the entity.
if ($this->moduleHandler
->moduleExists('scheduler_rules_integration')) {
_scheduler_rules_integration_dispatch_cron_event($entity, $process);
}
// Trigger the PUBLISH Scheduler event so that modules can react after
// the entity is published.
$this
->dispatchSchedulerEvent($entity, 'PUBLISH');
// Use the standard actions system to publish and save the entity.
$action_id = $plugin
->publishAction();
if ($this->moduleHandler
->moduleExists('workbench_moderation_actions')) {
// workbench_moderation_actions module uses a custom action instead.
$action_id = 'state_change__' . $entityTypeId . '__published';
}
if (!($loaded_action = $this->entityTypeManager
->getStorage('action')
->load($action_id))) {
$this
->missingAction($action_id, $process);
}
$loaded_action
->getPlugin()
->execute($entity);
$result = TRUE;
}
}
}
return $result;
}