Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions src/WordPress/Blueprints/Resource/ResourceManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ class ResourceManager {

protected Filesystem $fs;
protected ResourceMap $map;
protected ResourceResolverInterface $resourceResolver;

public function __construct(
protected ResourceResolverInterface $resourceResolver
public function __construct(
ResourceResolverInterface $resourceResolver
) {
$this->fs = new Filesystem();
$this->resourceResolver = $resourceResolver;
$this->fs = new Filesystem();
$this->map = new ResourceMap();
}

Expand Down
81 changes: 55 additions & 26 deletions src/WordPress/Blueprints/Runner/Blueprint/BlueprintRunner.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,48 +11,77 @@

class BlueprintRunner {

public readonly EventDispatcher $events;
public EventDispatcher $events;
protected RuntimeInterface $runtime;
protected $resourceManagerFactory;

public function __construct(
protected RuntimeInterface $runtime,
protected $resourceManagerFactory,
public function __construct(
RuntimeInterface $runtime,
$resourceManagerFactory
) {
$this->events = new EventDispatcher();
$this->resourceManagerFactory = $resourceManagerFactory;
$this->runtime = $runtime;
$this->events = new EventDispatcher();
}

// 1. compile
// 2. DI ?
// 3. handle resources - enqueue not working
// 4. run steps

// 4.b - fail strategies and snapshots, what happens when it failed, what is reverted?
// 4.c how can it be corrected? will a strict error policy not interfere with this?

public function run( CompiledBlueprint $blueprint ) {
$resourceManagerFactory = $this->resourceManagerFactory;
// TODO why factory? java much?
$resourceManager = $resourceManagerFactory();
// this does the resource steps. Why not run in the same way the runCompiledSteps method works?
// and just iterate over it?
// maybe prepareRequiredResources
$resourceManager->enqueue(
$blueprint->compiledResources
);
// TODO initiate fileManager, tracker? something for metrics?
// is the tracker a per step obj or a singleton?
foreach ( $blueprint->compiledSteps as $compiledStep ) {
// TODO set execution context
$compiledStep->runner->setRuntime( $this->runtime );
$compiledStep->runner->setResourceManager( $resourceManager );
}

// Run, store results
$results = [];
foreach ( $blueprint->compiledSteps as $k => $compiledStep ) {
/** @var CompiledStep $compiledStep */
try {
$results[ $k ] = new StepSuccess(
$compiledStep->step,
$compiledStep->runner->run( $compiledStep->step, new Tracker() )
);
} catch ( \Exception $e ) {
$results[ $k ] = $e;
if ( $compiledStep->step->continueOnError !== true ) {
throw new BlueprintRunnerException(
"Error when executing step {$compiledStep->step->step} (number $k on the list)",
0,
$results[ $k ]
);
}
}
}

return $results;
return $this->runCompiledSteps($blueprint);
}

/**
* @param CompiledBlueprint $blueprint
* @return array
* @throws BlueprintRunnerException
*/
public function runCompiledSteps(CompiledBlueprint $blueprint): array
{
$results = [];
foreach ($blueprint->compiledSteps as $k => $compiledStep) {
/** @var CompiledStep $compiledStep */
try {
$results[$k] = new StepSuccess(
$compiledStep->step,
$compiledStep->runner->run($compiledStep->step, new Tracker())
);
// blueprint exeption? all exceptions?
} catch (\Exception $e) {
if ($compiledStep->step->continueOnError !== true) {
throw new BlueprintRunnerException(
//
"Error when executing step {$compiledStep->step->step} (number $k on the list)",
0,
$e
);
}
$results[$k] = $e;
}
}
return $results;
}
}
14 changes: 10 additions & 4 deletions src/WordPress/Blueprints/Runner/Step/BaseStepRunner.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,21 @@

namespace WordPress\Blueprints\Runner\Step;

use WordPress\Blueprints\Context\ExecutionContext;
use WordPress\Blueprints\Resource\ResourceManager;
use WordPress\Blueprints\Runtime\RuntimeInterface;
use WordPress\FileManager\FileManager;

abstract class BaseStepRunner implements StepRunnerInterface {
protected ResourceManager $resourceManager;

protected RuntimeInterface $runtime;

protected FileManager $fileManager;

function __construct(RuntimeInterface $runtime) {
$this->fileManager = new FileManager($runtime);
}

public function setResourceManager( ResourceManager $map ) {
$this->resourceManager = $map;
}
Expand All @@ -19,6 +25,7 @@ protected function getResource( $declaration ) {
return $this->resourceManager->getStream( $declaration );
}

// TODO would advise to set runtime at initialization only
public function setRuntime( RuntimeInterface $runtime ): void {
$this->runtime = $runtime;
}
Expand All @@ -27,8 +34,7 @@ protected function getRuntime(): RuntimeInterface {
return $this->runtime;
}

protected function getDefaultCaption( $input ): string|null {
protected function getDefaultCaption( $input ): ?string {
return null;
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

class DownloadWordPressStepRunner extends InstallAssetStepRunner {

//TODO why is this download and not install?
Copy link
Copy Markdown
Collaborator

@adamziel adamziel Feb 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Installation is a separate step. The developer may not want to run the installation wizard automatically.

public function run(
DownloadWordPressStep $input,
Tracker $progress = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@


class InstallAssetStepRunner extends BaseStepRunner {
// TODO following the github API - this is not an exposed step - maybe it's internals should be used by other steps and not extended?
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had the same thought, just couldn't think of the right names for things.

// especially since it is a functionality primarily focused on unzipping

protected function unzipAssetTo( $zipResource, $targetPath ) {
if ( ! file_exists( $targetPath ) ) {
Expand Down
14 changes: 7 additions & 7 deletions src/WordPress/Blueprints/Runner/Step/MkdirStepRunner.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@

namespace WordPress\Blueprints\Runner\Step;

use Symfony\Component\Filesystem\Exception\IOException;
use WordPress\Blueprints\BlueprintException;
use WordPress\Blueprints\Model\DataClass\MkdirStep;


class MkdirStepRunner extends BaseStepRunner {

function run( MkdirStep $input ) {
// @TODO: Treat $input->path as relative path to the document root (unless it's absolute)
$success = mkdir( $input->path );
if ( ! $success ) {
throw new \Exception( "Failed to create directory at {$input->path}" );
}
function run(MkdirStep $input) {
$path = $input->path;
$this->fileManager->assertNoFileExists($path);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line obscures that $path is relative to the document root and needs to be resolved.

$this->fileManager->mkdir($path);
}
}
}
13 changes: 5 additions & 8 deletions src/WordPress/Blueprints/Runner/Step/MvStepRunner.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
<?php
/**
* @file
*/

namespace WordPress\Blueprints\Runner\Step;

Expand All @@ -13,10 +10,10 @@ class MvStepRunner extends BaseStepRunner {
* @param MvStep $input
*/
function run( MvStep $input ) {
// @TODO: Treat these paths as relative path to the document root (unless it's absolute)
$success = rename( $input->fromPath, $input->toPath );
if ( ! $success ) {
throw new \Exception( "Failed to move the file from {$input->fromPath} at {$input->toPath}" );
}
$fromPath = $input->fromPath;
$toPath = $input->toPath;
$this->fileManager->assertFileExists($fromPath);
$this->fileManager->assertNoFileExists($toPath);
$this->fileManager->rename($fromPath, $toPath);
}
}
8 changes: 6 additions & 2 deletions src/WordPress/Blueprints/Runner/Step/UnzipStepRunner.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@ class UnzipStepRunner extends BaseStepRunner {

public function run(
UnzipStep $input,
Tracker $progress = null
// maybe publish events for tracking instead of passing a variable?
// so that the tracker is a singleton with listeners
Tracker $tracker = null
) {
$progress?->set( 10, 'Unzipping...' );
if (!is_null($tracker)) {
$tracker->set( 10, 'Unzipping...' );
}

// @TODO: Expose a generic helper method for this, e.g. $this->getExecutionContext()->resolvePath($input->extractToPath);
$toPath = $this->getRuntime()->getDocumentRoot() . '/' . $input->extractToPath;
Expand Down
8 changes: 5 additions & 3 deletions src/WordPress/Blueprints/Runtime/NativePHPRuntime.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@
class NativePHPRuntime implements RuntimeInterface {

public Filesystem $fs;
protected string $documentRoot;

public function __construct(
protected string $documentRoot
public function __construct(
string $documentRoot
) {
$this->fs = new Filesystem();
$this->documentRoot = $documentRoot;
$this->fs = new Filesystem();
if ( ! file_exists( $this->getDocumentRoot() ) ) {
$this->fs->mkdir( $this->getDocumentRoot() );
}
Expand Down
65 changes: 65 additions & 0 deletions src/WordPress/FileManager/FileManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

namespace WordPress\FileManager;

use Symfony\Component\Filesystem\Exception\IOException;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Filesystem\Path;
use WordPress\Blueprints\BlueprintException;
use WordPress\Blueprints\Runtime\RuntimeInterface;

class FileManager {

private RuntimeInterface $runtime;

private Filesystem $filesystem;

function __construct(RuntimeInterface $runtime) {
$this->filesystem = new Filesystem();
$this->runtime = $runtime;
}

public function toAbsolutePath(string $path): string {
return Path::makeAbsolute($path, $this->runtime->getDocumentRoot());
}

public function mkdir(string $path): void {
$absolutePath = $this->toAbsolutePath($path);
try {
$this->filesystem->mkdir($absolutePath);
} catch (IOException $exception) {
throw new BlueprintException("Failed to create directory at $absolutePath.", 0, $exception);
}
}

public function assertFileExists($path) {
$absolutePath = $this->toAbsolutePath($path);
if (!file_exists($absolutePath)) {
throw new BlueprintException("Fail. No file at \"$absolutePath\" exists.");
}
}

public function rename(string $fromPath, string $toPath): void {
$absoluteFromPath = $this->toAbsolutePath($fromPath);
$absoluteToPath = $this->toAbsolutePath($toPath);
$isSuccessful = rename($absoluteFromPath, $absoluteToPath);
if (!$isSuccessful) {
throw new BlueprintException( "Failed to move the file from \"$absoluteFromPath\" at \"$absoluteToPath\"." );
}
}

public function assertNoFileExists($path): void {
$absolutePath = $this->toAbsolutePath($path);
if (!file_exists($absolutePath)) {
return;
}
if (is_dir($absolutePath)) {
throw new BlueprintException("Fail. A directory at \"$absolutePath\" exists.");
}
if (is_file($absolutePath)) {
throw new BlueprintException("Fail. A file at \"$absolutePath\" exists.");
}
}


}
16 changes: 8 additions & 8 deletions tests/Unit/CompilerTest.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<?php

use \WordPress\Blueprints\Compiler;

it('Compiler should validate Blueprints', function () {
$c = new Compiler();
$c->compile([
'steps' => []
]);
});
//use \WordPress\Blueprints\Compiler;
//
//it('Compiler should validate Blueprints', function () {
// $c = new Compiler();
// $c->compile([
// 'steps' => []
// ]);
//});
Loading