media_acquiadam-8.x-1.46/src/Plugin/QueueWorker/AssetRefresh.php
src/Plugin/QueueWorker/AssetRefresh.php
<?php namespace Drupal\media_acquiadam\Plugin\QueueWorker; use Drupal\Component\Datetime\TimeInterface; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Queue\DelayedRequeueException; use Drupal\Core\Queue\QueueWorkerBase; use Drupal\Core\Queue\RequeueException; use Drupal\Core\Queue\SuspendQueueException; use Drupal\media\MediaInterface; use Drupal\media_acquiadam\Service\AssetMediaFactory; use GuzzleHttp\Exception\ClientException; use GuzzleHttp\Exception\ConnectException; use GuzzleHttp\Exception\ServerException; use Psr\Log\LoggerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Updates Acquia DAM assets. * * To reduce duplicate queue items, install `queue_unique` and register this * queue worker. * * @link https://www.drupal.org/project/queue_unique * * @QueueWorker ( * id = "media_acquiadam_asset_refresh", * title = @Translation("Acquia DAM Asset Refresh"), * cron = {"time" = 30} * ) */ class AssetRefresh extends QueueWorkerBase implements ContainerFactoryPluginInterface { /** * Drupal logger channel service. * * @var \Psr\Log\LoggerInterface */ protected $loggerChannel; /** * Drupal entity type manager service. * * @var \Drupal\Core\Entity\EntityTypeManagerInterface */ protected $entityTypeManager; /** * Acquia DAM Asset Media Factory service. * * @var \Drupal\media_acquiadam\Service\AssetMediaFactory */ protected $assetMediaFactory; /** * The config factory service. * * @var \Drupal\Core\Config\ConfigFactoryInterface */ protected $configFactory; /** * The time. * * @var \Drupal\Component\Datetime\TimeInterface */ protected $time; /** * {@inheritdoc} */ public function __construct(array $configuration, $plugin_id, $plugin_definition, LoggerInterface $loggerChannel, EntityTypeManagerInterface $entityTypeManager, AssetMediaFactory $assetMediaFactory, ConfigFactoryInterface $config_factory, TimeInterface $time) { parent::__construct($configuration, $plugin_id, $plugin_definition); $this->loggerChannel = $loggerChannel; $this->entityTypeManager = $entityTypeManager; $this->assetMediaFactory = $assetMediaFactory; $this->configFactory = $config_factory; $this->time = $time; } /** * {@inheritdoc} */ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { return new static( $configuration, $plugin_id, $plugin_definition, $container->get('logger.factory')->get('media_acquiadam'), $container->get('entity_type.manager'), $container->get('media_acquiadam.asset_media.factory'), $container->get('config.factory'), $container->get('datetime.time') ); } /** * {@inheritdoc} * * @return bool * TRUE if a media entity was updated successfully, FALSE - otherwise. * * @phpstan-param array{media_id: string} $data */ public function processItem($data) { if (empty($data['media_id'])) { return FALSE; } $entity = $this->entityTypeManager->getStorage('media')->load( $data['media_id'] ); if (!$entity instanceof MediaInterface) { $this->loggerChannel->error( 'Unable to load media entity @media_id in order to refresh the associated asset. Was the media entity deleted within Drupal?', ['@media_id' => $data['media_id']] ); return FALSE; } $wrapped_media = $this->assetMediaFactory->get($entity); $assetID = $wrapped_media->getAssetId(); if (empty($assetID)) { $this->loggerChannel->error( 'Unable to load asset ID from media entity @media_id. This might mean that the DAM and Drupal relationship has been broken. Please check the media entity.', ['@media_id' => $data['media_id']] ); return FALSE; } try { $asset = $wrapped_media->getAsset(); } catch (ServerException $exception) { // If there is a server exception, suspend the queue. throw new SuspendQueueException( $exception->getMessage(), $exception->getCode(), $exception ); } catch (ConnectException $exception) { throw new SuspendQueueException( 'Could not create connection to DAM, possible local network issue', $exception->getCode(), $exception ); } catch (ClientException $exception) { $response = $exception->getResponse(); if ($response === NULL) { throw new RequeueException(); } if ($response->getStatusCode() === 401) { throw new SuspendQueueException('Unable to process queue due to authorization errors', 401, $exception); } // If 404 response, the asset has been removed. Allow processing to // determine if it should be deleted. if ($response->getStatusCode() === 404) { $asset = NULL; } elseif ($response->getStatusCode() === 408) { throw new DelayedRequeueException(60, 'Timed out loading asset, trying again later.', 408, $exception); } else { // Try again for unknown 4xx responses. throw new RequeueException(); } } catch (\Exception $x) { $this->loggerChannel->error( 'Error trying to check asset from media entity @media_id', ['@media_id' => $data['media_id']] ); return FALSE; } // If the asset is expired/deleted in Acquia DAM and is unpublished in // Drupal, we delete it. $perform_delete = $this->configFactory->get('media_acquiadam.settings')->get('sync_perform_delete'); if (($asset === NULL || !$asset->released_and_not_expired) && $perform_delete && !$entity->isPublished()) { $entity->delete(); $this->loggerChannel->warning( 'Deleted media entity @media_id with asset id @assetID.', [ '@media_id' => $data['media_id'], '@assetID' => $assetID, ] ); return TRUE; } // If the asset is expired/deleted in Acquia DAM but is published in // Drupal, we log it because we can't delete it. if ($asset !== NULL && !$asset->released_and_not_expired && $entity->isPublished()) { $this->loggerChannel->warning( 'Unable to delete media entity @media_id because it is published. This warning will continue to appear until the media entity has been deleted or unpublished.', [ '@media_id' => $data['media_id'], ] ); } // If the asset does not exist anymore in Acquia DAM, log the information // for visibility. if ($asset === NULL) { $this->loggerChannel->warning( 'Unable to update media entity @media_id with information from asset @assetID because the asset was missing. This warning will continue to appear until the media entity has been deleted.', [ '@media_id' => $data['media_id'], '@assetID' => $assetID, ] ); return FALSE; } try { // Re-save the entity, prompting the clearing and redownloading of // metadata and asset file. We always modify the changed time to help // indicate the last time this media entity had a refresh performed. $entity->setChangedTime($this->time->getCurrentTime()); $entity->save(); } catch (\Exception $x) { // Something within `media_acquiadam_media_presave` caused a failure that // we cannot detect. Provide verbose logging and let its lock expire // before re-processing. $this->loggerChannel->error( 'Error when saving media to sync data with DAM for media entity @media_id and asset ID @asset_id. Leaving in queue for retry. %exception_type: %error', [ '@media_id' => $data['media_id'], '@asset_id' => $assetID, '%exception_type' => get_class($x), '%error' => $x->getMessage(), ] ); return FALSE; } return TRUE; } }