Skip to content
Snippets Groups Projects
Commit 19f54310 authored by Adam G-H's avatar Adam G-H Committed by Ted Bowman
Browse files

Issue #3232004 by phenaproxima: Move path computation into a Locator service

parent 6bf0d736
No related branches found
No related tags found
1 merge request!32Issue #3232004: Move path computation into a Locator service
...@@ -4,7 +4,7 @@ services: ...@@ -4,7 +4,7 @@ services:
arguments: ['@keyvalue.expirable', '@datetime.time', 24] arguments: ['@keyvalue.expirable', '@datetime.time', 24]
automatic_updates.updater: automatic_updates.updater:
class: Drupal\automatic_updates\Updater class: Drupal\automatic_updates\Updater
arguments: ['@state', '@string_translation','@automatic_updates.beginner', '@automatic_updates.stager', '@automatic_updates.cleaner', '@automatic_updates.committer', '@event_dispatcher', '@config.factory'] arguments: ['@state', '@string_translation','@automatic_updates.beginner', '@automatic_updates.stager', '@automatic_updates.cleaner', '@automatic_updates.committer', '@event_dispatcher', '@automatic_updates.path_locator']
automatic_updates.beginner: automatic_updates.beginner:
class: PhpTuf\ComposerStager\Domain\Beginner class: PhpTuf\ComposerStager\Domain\Beginner
arguments: arguments:
...@@ -73,7 +73,7 @@ services: ...@@ -73,7 +73,7 @@ services:
- { name: event_subscriber } - { name: event_subscriber }
automatic_updates.staged_projects_validator: automatic_updates.staged_projects_validator:
class: Drupal\automatic_updates\Validator\StagedProjectsValidator class: Drupal\automatic_updates\Validator\StagedProjectsValidator
arguments: [ '@string_translation', '@automatic_updates.updater' ] arguments: ['@string_translation', '@automatic_updates.path_locator']
tags: tags:
- { name: event_subscriber } - { name: event_subscriber }
automatic_updates.update_version_validator: automatic_updates.update_version_validator:
...@@ -86,3 +86,7 @@ services: ...@@ -86,3 +86,7 @@ services:
arguments: ['@automatic_updates.exec_finder'] arguments: ['@automatic_updates.exec_finder']
tags: tags:
- { name: event_subscriber } - { name: event_subscriber }
automatic_updates.path_locator:
class: Drupal\automatic_updates\PathLocator
arguments:
- '@config.factory'
<?php
namespace Drupal\automatic_updates;
use Composer\Autoload\ClassLoader;
use Drupal\Component\FileSystem\FileSystem;
use Drupal\Core\Config\ConfigFactoryInterface;
/**
* Computes file system paths that are needed for automatic updates.
*/
class PathLocator {
/**
* The config factory service.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
/**
* Constructs a PathLocator object.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The config factory service.
*/
public function __construct(ConfigFactoryInterface $config_factory) {
$this->configFactory = $config_factory;
}
/**
* Returns the path of the active directory, which should be updated.
*
* @return string
* The absolute path which should be updated.
*/
public function getActiveDirectory(): string {
return $this->getProjectRoot();
}
/**
* Returns the path of the directory where updates should be staged.
*
* @return string
* The absolute path of the directory where updates should be staged.
*/
public function getStageDirectory(): string {
// Append the site ID to the directory in order to support parallel test
// runs, or multiple sites hosted on the same server.
$site_id = $this->configFactory->get('system.site')->get('uuid');
return FileSystem::getOsTemporaryDirectory() . DIRECTORY_SEPARATOR . '.automatic_updates_stage_' . $site_id;
}
/**
* Returns the absolute path of the project root.
*
* This is where the project-level composer.json should normally be found, and
* may or may not be the same path as the Drupal code base.
*
* @return string
* The absolute path of the project root.
*/
public function getProjectRoot(): string {
// Assume that the vendor directory is immediately below the project root.
return realpath($this->getVendorDirectory() . DIRECTORY_SEPARATOR . '..');
}
/**
* Returns the absolute path of the vendor directory.
*
* @return string
* The absolute path of the vendor directory.
*/
public function getVendorDirectory(): string {
$reflector = new \ReflectionClass(ClassLoader::class);
return dirname($reflector->getFileName(), 2);
}
}
...@@ -2,14 +2,11 @@ ...@@ -2,14 +2,11 @@
namespace Drupal\automatic_updates; namespace Drupal\automatic_updates;
use Composer\Autoload\ClassLoader;
use Drupal\automatic_updates\Event\PreCommitEvent; use Drupal\automatic_updates\Event\PreCommitEvent;
use Drupal\automatic_updates\Event\PreStartEvent; use Drupal\automatic_updates\Event\PreStartEvent;
use Drupal\automatic_updates\Event\UpdateEvent; use Drupal\automatic_updates\Event\UpdateEvent;
use Drupal\automatic_updates\Exception\UpdateException; use Drupal\automatic_updates\Exception\UpdateException;
use Drupal\Component\FileSystem\FileSystem;
use Drupal\Component\Serialization\Json; use Drupal\Component\Serialization\Json;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\State\StateInterface; use Drupal\Core\State\StateInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslationInterface; use Drupal\Core\StringTranslation\TranslationInterface;
...@@ -77,11 +74,11 @@ class Updater { ...@@ -77,11 +74,11 @@ class Updater {
protected $eventDispatcher; protected $eventDispatcher;
/** /**
* The config factory service. * The path locator service.
* *
* @var \Drupal\Core\Config\ConfigFactoryInterface * @var \Drupal\automatic_updates\PathLocator
*/ */
protected $configFactory; protected $pathLocator;
/** /**
* Constructs an Updater object. * Constructs an Updater object.
...@@ -100,10 +97,10 @@ class Updater { ...@@ -100,10 +97,10 @@ class Updater {
* The Composer Stager's committer service. * The Composer Stager's committer service.
* @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
* The event dispatcher service. * The event dispatcher service.
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory * @param \Drupal\automatic_updates\PathLocator $path_locator
* The config factory service. * The path locator service.
*/ */
public function __construct(StateInterface $state, TranslationInterface $translation, BeginnerInterface $beginner, StagerInterface $stager, CleanerInterface $cleaner, CommitterInterface $committer, EventDispatcherInterface $event_dispatcher, ConfigFactoryInterface $config_factory) { public function __construct(StateInterface $state, TranslationInterface $translation, BeginnerInterface $beginner, StagerInterface $stager, CleanerInterface $cleaner, CommitterInterface $committer, EventDispatcherInterface $event_dispatcher, PathLocator $path_locator) {
$this->state = $state; $this->state = $state;
$this->beginner = $beginner; $this->beginner = $beginner;
$this->stager = $stager; $this->stager = $stager;
...@@ -111,31 +108,7 @@ class Updater { ...@@ -111,31 +108,7 @@ class Updater {
$this->committer = $committer; $this->committer = $committer;
$this->setStringTranslation($translation); $this->setStringTranslation($translation);
$this->eventDispatcher = $event_dispatcher; $this->eventDispatcher = $event_dispatcher;
$this->configFactory = $config_factory; $this->pathLocator = $path_locator;
}
/**
* Gets the vendor directory.
*
* @return string
* The absolute path for vendor directory.
*/
private static function getVendorDirectory(): string {
$class_loader_reflection = new \ReflectionClass(ClassLoader::class);
return dirname($class_loader_reflection->getFileName(), 2);
}
/**
* Gets the stage directory.
*
* @return string
* The absolute path for stage directory.
*/
public function getStageDirectory(): string {
// Append the site ID to the directory in order to support parallel test
// runs, or multiple sites hosted on the same server.
$site_id = $this->configFactory->get('system.site')->get('uuid');
return FileSystem::getOsTemporaryDirectory() . '/.automatic_updates_stage_' . $site_id;
} }
/** /**
...@@ -145,23 +118,13 @@ class Updater { ...@@ -145,23 +118,13 @@ class Updater {
* TRUE if there is active update, otherwise FALSE. * TRUE if there is active update, otherwise FALSE.
*/ */
public function hasActiveUpdate(): bool { public function hasActiveUpdate(): bool {
$staged_dir = $this->getStageDirectory(); $staged_dir = $this->pathLocator->getStageDirectory();
if (is_dir($staged_dir) || $this->state->get(static::STATE_KEY)) { if (is_dir($staged_dir) || $this->state->get(static::STATE_KEY)) {
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
} }
/**
* Gets the active directory.
*
* @return string
* The absolute path for active directory.
*/
public function getActiveDirectory(): string {
return realpath(static::getVendorDirectory() . '/..');
}
/** /**
* Begins the update. * Begins the update.
* *
...@@ -184,7 +147,7 @@ class Updater { ...@@ -184,7 +147,7 @@ class Updater {
$stage_key = $this->createActiveStage($packages); $stage_key = $this->createActiveStage($packages);
/** @var \Drupal\automatic_updates\Event\PreStartEvent $event */ /** @var \Drupal\automatic_updates\Event\PreStartEvent $event */
$event = $this->dispatchUpdateEvent(new PreStartEvent($packages), AutomaticUpdatesEvents::PRE_START); $event = $this->dispatchUpdateEvent(new PreStartEvent($packages), AutomaticUpdatesEvents::PRE_START);
$this->beginner->begin(static::getActiveDirectory(), static::getStageDirectory(), $this->getExclusions($event)); $this->beginner->begin($this->pathLocator->getActiveDirectory(), $this->pathLocator->getStageDirectory(), $this->getExclusions($event));
return $stage_key; return $stage_key;
} }
...@@ -210,7 +173,7 @@ class Updater { ...@@ -210,7 +173,7 @@ class Updater {
* detecting the core package. * detecting the core package.
*/ */
public function getCorePackageName(): string { public function getCorePackageName(): string {
$composer = realpath(static::getVendorDirectory() . '/../composer.json'); $composer = realpath($this->pathLocator->getProjectRoot() . '/composer.json');
if (empty($composer) || !file_exists($composer)) { if (empty($composer) || !file_exists($composer)) {
throw new \RuntimeException("Could not find project-level composer.json"); throw new \RuntimeException("Could not find project-level composer.json");
...@@ -239,7 +202,7 @@ class Updater { ...@@ -239,7 +202,7 @@ class Updater {
*/ */
private function getExclusions($event): array { private function getExclusions($event): array {
$make_relative = function (string $path): string { $make_relative = function (string $path): string {
return str_replace($this->getActiveDirectory() . '/', '', $path); return str_replace($this->pathLocator->getActiveDirectory() . '/', '', $path);
}; };
return array_map($make_relative, $event->getExcludedPaths()); return array_map($make_relative, $event->getExcludedPaths());
} }
...@@ -270,15 +233,16 @@ class Updater { ...@@ -270,15 +233,16 @@ class Updater {
public function commit(): void { public function commit(): void {
/** @var \Drupal\automatic_updates\Event\PreCommitEvent $event */ /** @var \Drupal\automatic_updates\Event\PreCommitEvent $event */
$event = $this->dispatchUpdateEvent(new PreCommitEvent(), AutomaticUpdatesEvents::PRE_COMMIT); $event = $this->dispatchUpdateEvent(new PreCommitEvent(), AutomaticUpdatesEvents::PRE_COMMIT);
$this->committer->commit($this->getStageDirectory(), static::getActiveDirectory(), $this->getExclusions($event)); $this->committer->commit($this->pathLocator->getStageDirectory(), $this->pathLocator->getActiveDirectory(), $this->getExclusions($event));
} }
/** /**
* Cleans the current update. * Cleans the current update.
*/ */
public function clean(): void { public function clean(): void {
if (is_dir($this->getStageDirectory())) { $stage_dir = $this->pathLocator->getStageDirectory();
$this->cleaner->clean($this->getStageDirectory()); if (is_dir($stage_dir)) {
$this->cleaner->clean($stage_dir);
} }
$this->state->delete(static::STATE_KEY); $this->state->delete(static::STATE_KEY);
} }
...@@ -293,7 +257,7 @@ class Updater { ...@@ -293,7 +257,7 @@ class Updater {
* @see \PhpTuf\ComposerStager\Domain\StagerInterface::stage() * @see \PhpTuf\ComposerStager\Domain\StagerInterface::stage()
*/ */
protected function stageCommand(array $command): void { protected function stageCommand(array $command): void {
$this->stager->stage($command, $this->getStageDirectory()); $this->stager->stage($command, $this->pathLocator->getStageDirectory());
} }
/** /**
......
...@@ -5,7 +5,7 @@ namespace Drupal\automatic_updates\Validator; ...@@ -5,7 +5,7 @@ namespace Drupal\automatic_updates\Validator;
use Drupal\automatic_updates\AutomaticUpdatesEvents; use Drupal\automatic_updates\AutomaticUpdatesEvents;
use Drupal\automatic_updates\Event\UpdateEvent; use Drupal\automatic_updates\Event\UpdateEvent;
use Drupal\automatic_updates\Exception\UpdateException; use Drupal\automatic_updates\Exception\UpdateException;
use Drupal\automatic_updates\Updater; use Drupal\automatic_updates\PathLocator;
use Drupal\automatic_updates\Validation\ValidationResult; use Drupal\automatic_updates\Validation\ValidationResult;
use Drupal\Component\Serialization\Json; use Drupal\Component\Serialization\Json;
use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\StringTranslation\StringTranslationTrait;
...@@ -20,23 +20,23 @@ final class StagedProjectsValidator implements EventSubscriberInterface { ...@@ -20,23 +20,23 @@ final class StagedProjectsValidator implements EventSubscriberInterface {
use StringTranslationTrait; use StringTranslationTrait;
/** /**
* The updater service. * The path locator service.
* *
* @var \Drupal\automatic_updates\Updater * @var \Drupal\automatic_updates\PathLocator
*/ */
protected $updater; protected $pathLocator;
/** /**
* Constructs a StagedProjectsValidation object. * Constructs a StagedProjectsValidation object.
* *
* @param \Drupal\Core\StringTranslation\TranslationInterface $translation * @param \Drupal\Core\StringTranslation\TranslationInterface $translation
* The translation service. * The translation service.
* @param \Drupal\automatic_updates\Updater $updater * @param \Drupal\automatic_updates\PathLocator $path_locator
* The updater service. * The path locator service.
*/ */
public function __construct(TranslationInterface $translation, Updater $updater) { public function __construct(TranslationInterface $translation, PathLocator $path_locator) {
$this->setStringTranslation($translation); $this->setStringTranslation($translation);
$this->updater = $updater; $this->pathLocator = $path_locator;
} }
/** /**
...@@ -87,8 +87,8 @@ final class StagedProjectsValidator implements EventSubscriberInterface { ...@@ -87,8 +87,8 @@ final class StagedProjectsValidator implements EventSubscriberInterface {
*/ */
public function validateStagedProjects(UpdateEvent $event): void { public function validateStagedProjects(UpdateEvent $event): void {
try { try {
$active_packages = $this->getDrupalPackagesFromLockFile($this->updater->getActiveDirectory() . "/composer.lock"); $active_packages = $this->getDrupalPackagesFromLockFile($this->pathLocator->getActiveDirectory() . "/composer.lock");
$staged_packages = $this->getDrupalPackagesFromLockFile($this->updater->getStageDirectory() . "/composer.lock"); $staged_packages = $this->getDrupalPackagesFromLockFile($this->pathLocator->getStageDirectory() . "/composer.lock");
} }
catch (UpdateException $e) { catch (UpdateException $e) {
foreach ($e->getValidationResults() as $result) { foreach ($e->getValidationResults() as $result) {
......
<?php
namespace Drupal\automatic_updates_test;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\DependencyInjection\ServiceProviderBase;
/**
* Modifies service definitions for testing purposes.
*/
class AutomaticUpdatesTestServiceProvider extends ServiceProviderBase {
/**
* {@inheritdoc}
*/
public function alter(ContainerBuilder $container) {
parent::alter($container);
$service = 'automatic_updates.updater';
if ($container->hasDefinition($service)) {
$container->getDefinition($service)->setClass(TestUpdater::class);
}
}
}
<?php
namespace Drupal\automatic_updates_test;
use Drupal\automatic_updates\Updater;
/**
* A testing updater that allows arbitrary active and stage directories.
*/
class TestUpdater extends Updater {
/**
* The active directory to use, if different from the default.
*
* @var string
*/
public $activeDirectory;
/**
* The stage directory to use, if different from the default.
*
* @var string
*/
public $stageDirectory;
/**
* {@inheritdoc}
*/
public function getActiveDirectory(): string {
return $this->activeDirectory ?: parent::getActiveDirectory();
}
/**
* {@inheritdoc}
*/
public function getStageDirectory(): string {
return $this->stageDirectory ?: parent::getStageDirectory();
}
}
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
namespace Drupal\Tests\automatic_updates\Functional; namespace Drupal\Tests\automatic_updates\Functional;
use Drupal\automatic_updates\PathLocator;
use Drupal\automatic_updates\Updater;
use Drupal\Core\Site\Settings; use Drupal\Core\Site\Settings;
use Drupal\Tests\BrowserTestBase; use Drupal\Tests\BrowserTestBase;
...@@ -30,10 +32,22 @@ class ExclusionsTest extends BrowserTestBase { ...@@ -30,10 +32,22 @@ class ExclusionsTest extends BrowserTestBase {
public function testExclusions(): void { public function testExclusions(): void {
$stage_dir = "$this->siteDirectory/stage"; $stage_dir = "$this->siteDirectory/stage";
/** @var \Drupal\automatic_updates_test\TestUpdater $updater */ /** @var \Drupal\automatic_updates\PathLocator|\Prophecy\Prophecy\ObjectProphecy $locator */
$updater = $this->container->get('automatic_updates.updater'); $locator = $this->prophesize(PathLocator::class);
$updater->activeDirectory = __DIR__ . '/../../fixtures/fake-site'; $locator->getActiveDirectory()->willReturn(__DIR__ . '/../../fixtures/fake-site');
$updater->stageDirectory = $stage_dir; $locator->getStageDirectory()->willReturn($stage_dir);
$locator->getProjectRoot()->willReturn($this->getDrupalRoot());
$updater = new Updater(
$this->container->get('state'),
$this->container->get('string_translation'),
$this->container->get('automatic_updates.beginner'),
$this->container->get('automatic_updates.stager'),
$this->container->get('automatic_updates.cleaner'),
$this->container->get('automatic_updates.committer'),
$this->container->get('event_dispatcher'),
$locator->reveal()
);
$settings = Settings::getAll(); $settings = Settings::getAll();
$settings['file_public_path'] = 'files/public'; $settings['file_public_path'] = 'files/public';
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
namespace Drupal\Tests\automatic_updates\Unit; namespace Drupal\Tests\automatic_updates\Unit;
use Drupal\automatic_updates\Event\UpdateEvent; use Drupal\automatic_updates\Event\UpdateEvent;
use Drupal\automatic_updates\Updater; use Drupal\automatic_updates\PathLocator;
use Drupal\automatic_updates\Validator\StagedProjectsValidator; use Drupal\automatic_updates\Validator\StagedProjectsValidator;
use Drupal\Component\FileSystem\FileSystem; use Drupal\Component\FileSystem\FileSystem;
use Drupal\Core\StringTranslation\PluralTranslatableMarkup; use Drupal\Core\StringTranslation\PluralTranslatableMarkup;
...@@ -26,10 +26,10 @@ class StagedProjectsValidatorTest extends UnitTestCase { ...@@ -26,10 +26,10 @@ class StagedProjectsValidatorTest extends UnitTestCase {
$active_dir = uniqid($prefix); $active_dir = uniqid($prefix);
$stage_dir = uniqid($prefix); $stage_dir = uniqid($prefix);
$updater = $this->prophesize(Updater::class); $locator = $this->prophesize(PathLocator::class);
$updater->getActiveDirectory()->willReturn($active_dir); $locator->getActiveDirectory()->willReturn($active_dir);
$updater->getStageDirectory()->willReturn($stage_dir); $locator->getStageDirectory()->willReturn($stage_dir);
$validator = new StagedProjectsValidator(new TestTranslationManager(), $updater->reveal()); $validator = new StagedProjectsValidator(new TestTranslationManager(), $locator->reveal());
$event = new UpdateEvent(); $event = new UpdateEvent();
$validator->validateStagedProjects($event); $validator->validateStagedProjects($event);
...@@ -56,13 +56,13 @@ class StagedProjectsValidatorTest extends UnitTestCase { ...@@ -56,13 +56,13 @@ class StagedProjectsValidatorTest extends UnitTestCase {
* @covers ::validateStagedProjects * @covers ::validateStagedProjects
*/ */
public function testErrors(string $fixtures_dir, string $expected_summary, array $expected_messages): void { public function testErrors(string $fixtures_dir, string $expected_summary, array $expected_messages): void {
$updater = $this->prophesize(Updater::class); $locator = $this->prophesize(PathLocator::class);
$this->assertNotEmpty($fixtures_dir); $this->assertNotEmpty($fixtures_dir);
$this->assertDirectoryExists($fixtures_dir); $this->assertDirectoryExists($fixtures_dir);
$updater->getActiveDirectory()->willReturn("$fixtures_dir/active"); $locator->getActiveDirectory()->willReturn("$fixtures_dir/active");
$updater->getStageDirectory()->willReturn("$fixtures_dir/staged"); $locator->getStageDirectory()->willReturn("$fixtures_dir/staged");
$validator = new StagedProjectsValidator(new TestTranslationManager(), $updater->reveal()); $validator = new StagedProjectsValidator(new TestTranslationManager(), $locator->reveal());
$event = new UpdateEvent(); $event = new UpdateEvent();
$validator->validateStagedProjects($event); $validator->validateStagedProjects($event);
$results = $event->getResults(); $results = $event->getResults();
...@@ -121,10 +121,10 @@ class StagedProjectsValidatorTest extends UnitTestCase { ...@@ -121,10 +121,10 @@ class StagedProjectsValidatorTest extends UnitTestCase {
*/ */
public function testNoErrors(): void { public function testNoErrors(): void {
$fixtures_dir = realpath(__DIR__ . '/../../fixtures/project_staged_validation/no_errors'); $fixtures_dir = realpath(__DIR__ . '/../../fixtures/project_staged_validation/no_errors');
$updater = $this->prophesize(Updater::class); $locator = $this->prophesize(PathLocator::class);
$updater->getActiveDirectory()->willReturn("$fixtures_dir/active"); $locator->getActiveDirectory()->willReturn("$fixtures_dir/active");
$updater->getStageDirectory()->willReturn("$fixtures_dir/staged"); $locator->getStageDirectory()->willReturn("$fixtures_dir/staged");
$validator = new StagedProjectsValidator(new TestTranslationManager(), $updater->reveal()); $validator = new StagedProjectsValidator(new TestTranslationManager(), $locator->reveal());
$event = new UpdateEvent(); $event = new UpdateEvent();
$validator->validateStagedProjects($event); $validator->validateStagedProjects($event);
$results = $event->getResults(); $results = $event->getResults();
...@@ -137,10 +137,10 @@ class StagedProjectsValidatorTest extends UnitTestCase { ...@@ -137,10 +137,10 @@ class StagedProjectsValidatorTest extends UnitTestCase {
*/ */
public function testNoLockFile(): void { public function testNoLockFile(): void {
$fixtures_dir = realpath(__DIR__ . '/../../fixtures/project_staged_validation/no_errors'); $fixtures_dir = realpath(__DIR__ . '/../../fixtures/project_staged_validation/no_errors');
$updater = $this->prophesize(Updater::class); $locator = $this->prophesize(PathLocator::class);
$updater->getActiveDirectory()->willReturn("$fixtures_dir/active"); $locator->getActiveDirectory()->willReturn("$fixtures_dir/active");
$updater->getStageDirectory()->willReturn("$fixtures_dir"); $locator->getStageDirectory()->willReturn("$fixtures_dir");
$validator = new StagedProjectsValidator(new TestTranslationManager(), $updater->reveal()); $validator = new StagedProjectsValidator(new TestTranslationManager(), $locator->reveal());
$event = new UpdateEvent(); $event = new UpdateEvent();
$validator->validateStagedProjects($event); $validator->validateStagedProjects($event);
$results = $event->getResults(); $results = $event->getResults();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment