class LongLivedSandboxSubscriber
Same name and namespace in other branches
- 11.x core/modules/package_manager/src/EventSubscriber/LongLivedSandboxSubscriber.php \Drupal\package_manager\EventSubscriber\LongLivedSandboxSubscriber
Maintains state for the long-lived sandbox directory.
- Records the timestamp when a sandbox is created (used by cron to determine when a sandbox is stale and can be removed).
- Deletes the sandbox directory when the `include_unknown_files_in_project_root` setting is changed to FALSE, because the rsync flags used to sync changes won't delete files that are now excluded from the source directory.
This subscriber intentionally injects only the container to avoid resolving the heavy ComposerStager dependency tree (Beginner, Stager, Committer and their precondition chains) at construction time. Those services are resolved lazily inside onConfigSave() only when the setting actually changes.
@internal This is an internal part of Package Manager and may be changed or removed at any time without warning. External code should not interact with this class.
Hierarchy
- class \Drupal\package_manager\EventSubscriber\LongLivedSandboxSubscriber implements \Symfony\Component\EventDispatcher\EventSubscriberInterface
Expanded class hierarchy of LongLivedSandboxSubscriber
2 files declare their use of LongLivedSandboxSubscriber
- CronHook.php in core/
modules/ package_manager/ src/ Hook/ CronHook.php - SandboxManagerBaseTest.php in core/
modules/ package_manager/ tests/ src/ Kernel/ SandboxManagerBaseTest.php
File
-
core/
modules/ package_manager/ src/ EventSubscriber/ LongLivedSandboxSubscriber.php, line 46
Namespace
Drupal\package_manager\EventSubscriberView source
final class LongLivedSandboxSubscriber implements EventSubscriberInterface {
/**
* The state key which holds the last time a create event ran.
*
* @var string
*/
public const STATE_KEY = 'package_manager.last_create_event';
public function __construct(private readonly StateInterface $state, private readonly TimeInterface $time, private readonly ContainerInterface $container) {
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() : array {
return [
ConfigEvents::SAVE => 'onConfigSave',
PostCreateEvent::class => 'updateLastCreatedTime',
];
}
/**
* Updates state with the last time a create event ran.
*
* @param \Drupal\package_manager\Event\PostCreateEvent $event
* The event being handled.
*/
public function updateLastCreatedTime(PostCreateEvent $event) : void {
$this->state
->set(static::STATE_KEY, $this->time
->getCurrentTime());
}
/**
* Reacts when config is saved.
*
* @param \Drupal\Core\Config\ConfigCrudEvent $event
* The event object.
*/
public function onConfigSave(ConfigCrudEvent $event) : void {
$config = $event->getConfig();
if ($config->getName() !== 'package_manager.settings' || !$event->isChanged('include_unknown_files_in_project_root')) {
return;
}
// Skip initial module install where the original value is NULL, no sandbox
// directory exists yet to clean up. Removing this guard will cause test
// failures (e.g., SymlinkValidatorTest) where the subscriber's side effects
// during module install are unexpected.
if ($config->getOriginal('include_unknown_files_in_project_root') === NULL) {
return;
}
// Ensure the sandbox directory is deleted when unknown files setting is
// changed to FALSE, as the rsync flags won't delete unknown files if they
// still exist in the source directory.
// @see \PhpTuf\ComposerStager\Internal\FileSyncer\Service\FileSyncer::buildCommand
if ($config->get('include_unknown_files_in_project_root') === FALSE) {
$sandbox_manager = new class ($this->container
->get(PathLocator::class), $this->container
->get(BeginnerInterface::class), $this->container
->get(StagerInterface::class), $this->container
->get(CommitterInterface::class), $this->container
->get(QueueFactory::class), $this->container
->get(EventDispatcherInterface::class), $this->container
->get(SharedTempStoreFactory::class), $this->container
->get(TimeInterface::class), $this->container
->get(PathFactoryInterface::class), $this->container
->get(FailureMarker::class)) extends SandboxManagerBase {
};
// In direct-write mode, getSandboxDirectory() returns the project root.
// There is no separate sandbox directory to delete.
if ($sandbox_manager->isDirectWrite()) {
return;
}
$is_available = $sandbox_manager->isAvailable();
$sandbox_dir = $sandbox_manager->getSandboxDirectory();
if (file_exists($sandbox_dir) && $is_available) {
/** @var \Drupal\Core\File\FileSystemInterface $file_system */
$file_system = $this->container
->get(FileSystemInterface::class);
$file_system->deleteRecursive($sandbox_dir, function (string $path) use ($file_system) : void {
$file_system->chmod($path, is_dir($path) ? 0700 : 0600);
});
$this->container
->get(StateInterface::class)
->delete(static::STATE_KEY);
}
}
}
}
Members
| Title Sort descending | Modifiers | Object type | Summary |
|---|---|---|---|
| LongLivedSandboxSubscriber::getSubscribedEvents | public static | function | |
| LongLivedSandboxSubscriber::onConfigSave | public | function | Reacts when config is saved. |
| LongLivedSandboxSubscriber::STATE_KEY | public | constant | The state key which holds the last time a create event ran. |
| LongLivedSandboxSubscriber::updateLastCreatedTime | public | function | Updates state with the last time a create event ran. |
| LongLivedSandboxSubscriber::__construct | public | function |
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.