component_library-1.0.x-dev/modules/component_library_workspaces/src/EventSubscriber/WorkspacePublishingSubscriber.php
modules/component_library_workspaces/src/EventSubscriber/WorkspacePublishingSubscriber.php
<?php
namespace Drupal\component_library_workspaces\EventSubscriber;
use Drupal\Core\Asset\LibraryDiscoveryInterface;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Config\StorageInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\State\StateInterface;
use Drupal\Core\Utility\Error;
use Drupal\workspaces\WorkspaceAssociationInterface;
use Drupal\workspaces\WorkspaceManagerInterface;
use Drupal\wse\Event\WorkspaceEvents;
use Drupal\wse\Event\WorkspacePublishEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Event Subscriber for Workspace pre- and post-publish events.
*/
class WorkspacePublishingSubscriber implements EventSubscriberInterface {
/**
* Prefix used in state.
*/
const COMPONENT_LIBRARY_ASSET_STATE_PREFIX = 'component_library_workspace_published_assets_';
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* The file system service.
*
* @var \Drupal\Core\File\FileSystemInterface
*/
protected $fileSystem;
/**
* The workspace manager service.
*
* @var \Drupal\workspaces\WorkspaceManagerInterface
*/
protected $workspaceManager;
/**
* The workspace association service.
*
* @var \Drupal\workspaces\WorkspaceAssociationInterface
*/
protected $workspaceAssociation;
/**
* The workspaces configuration storage.
*
* @var \Drupal\Core\Config\StorageInterface
*/
protected $configStorage;
/**
* The state key/value store.
*
* @var \Drupal\Core\State\StateInterface
*/
protected $state;
/**
* The configuration factory.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
/**
* The library discovery service.
*
* @var \Drupal\Core\Asset\LibraryDiscoveryInterface
*/
protected $libraryDiscovery;
/**
* Constructs a new WorkspacePublishingSubscriber.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\Core\File\FileSystemInterface $file_system
* The file system service.
* @param \Drupal\workspaces\WorkspaceManagerInterface $workspace_manager
* The workspace manager service.
* @param \Drupal\workspaces\WorkspaceAssociationInterface $workspace_association
* The workspace association service.
* @param \Drupal\Core\Config\StorageInterface $config_storage
* The workspaces configuration storage.
* @param \Drupal\Core\State\StateInterface $state
* The state key/value store.
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The configuration factory.
* @param \Drupal\Core\Asset\LibraryDiscoveryInterface $library_discovery
* The library discovery service.
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager, FileSystemInterface $file_system, WorkspaceManagerInterface $workspace_manager, WorkspaceAssociationInterface $workspace_association, StorageInterface $config_storage, StateInterface $state, ConfigFactoryInterface $config_factory, LibraryDiscoveryInterface $library_discovery) {
$this->entityTypeManager = $entity_type_manager;
$this->fileSystem = $file_system;
$this->workspaceManager = $workspace_manager;
$this->workspaceAssociation = $workspace_association;
$this->configStorage = $config_storage;
$this->state = $state;
$this->configFactory = $config_factory;
$this->libraryDiscovery = $library_discovery;
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
return [
WorkspaceEvents::WORKSPACE_POST_PUBLISH => ['onPostPublish'],
WorkspaceEvents::WORKSPACE_PRE_PUBLISH => ['onPrePublish'],
];
}
/**
* Collects component library assets to be published and puts them into state.
*
* @param \Drupal\wse\Event\WorkspacePublishEvent $event
* The workspace publish event.
*/
public function onPrePublish(WorkspacePublishEvent $event) {
$this->workspaceManager->executeInWorkspace($event->getWorkspace()->id(), function () use ($event) {
$tracked_wse_configs = $this->workspaceAssociation->getTrackedEntities($event->getWorkspace()->id(), 'wse_config');
if (!$tracked_wse_configs) {
return;
}
$wse_config_ids = array_values($tracked_wse_configs['wse_config']);
$wse_configs = $this->entityTypeManager->getStorage('wse_config')
->loadMultiple($wse_config_ids);
$assets_data = [];
foreach ($wse_configs as $wse_config) {
if (mb_strpos($wse_config->get('name')->value, 'component_library.component_library_asset.') === 0) {
$assets_data[] = $this->configStorage->decode($wse_config->get('data')->value);
}
}
$this->state->set(static::COMPONENT_LIBRARY_ASSET_STATE_PREFIX . $event->getWorkspace()->id(), $assets_data);
});
}
/**
* Drops files for component library assets overridden/created in a workspace.
*
* @param \Drupal\wse\Event\WorkspacePublishEvent $event
* The workspace publish event.
*/
public function onPostPublish(WorkspacePublishEvent $event) {
try {
/** @var \Drupal\component_library\Entity\ComponentLibraryAsset[] $published_asset_data */
$asset_entities = $this->entityTypeManager->getStorage('component_library_asset')
->loadMultiple();
$published_asset_data = $this->state->get(static::COMPONENT_LIBRARY_ASSET_STATE_PREFIX . $event->getWorkspace()->id());
if (!$published_asset_data) {
return;
}
foreach ($published_asset_data as $asset_data) {
Cache::invalidateTags(['library_info']);
foreach (['js', 'css'] as $asset_type) {
$aggregation_enabled = $this->configFactory->get('system.performance')->get("$asset_type.preprocess");
if ($aggregation_enabled) {
$this->fileSystem->deleteRecursive('public://' . $asset_type . '/');
}
}
$path = 'public://component_library_assets/' . $asset_data['id'] . '/';
$ws_path = $path . $event->getWorkspace()->id();
$this->fileSystem->deleteRecursive($ws_path);
$ws_path = $path . 'live';
$this->fileSystem->deleteRecursive($ws_path);
foreach ($asset_data['files'] as &$file) {
$code_aware_name = md5($file['code'] . $asset_data['id']);
$file['path'] = sprintf('public://component_library_assets/%s/%s/%s/%s.%s', $asset_data['id'], 'live', $file['type'], $code_aware_name, $file['type']);
$directory = \dirname($file['path']);
$this->fileSystem->prepareDirectory($directory, FileSystemInterface::CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS);
$this->fileSystem->saveData(
$file['code'],
$file['path'],
FileSystemInterface::EXISTS_REPLACE
);
}
if (!empty($asset_entities[$asset_data['id']])) {
$asset_entities[$asset_data['id']]->setFiles($asset_data['files']);
$asset_entities[$asset_data['id']]->save();
}
$this->state->delete(static::COMPONENT_LIBRARY_ASSET_STATE_PREFIX . $event->getWorkspace()->id());
$this->libraryDiscovery->clearCachedDefinitions();
}
}
catch (\Exception $exception) {
$logger = \Drupal::logger('component_library');
Error::logException($logger, $exception, 'Error during deployment of workspace containing component_library_asset data.');
}
}
}
