Skip to content
Snippets Groups Projects

feat: remove compilation command

Open Bartek Jaskulski requested to merge v0.10 into main
2 files
+ 3
8
Compare changes
  • Side-by-side
  • Inline

Files

  • e4b6d594
    Previously stoppable binder was working for all binders, although it
    only supported to signal stop execution with class-based binders. This
    changes the behavior, as having all binders wrapped in stoppable binder
    resulted in execution of all collection binders, without regard for the
    stop signal.
    
    This is convoluted and gets even worse, so this part of the API should
    be rewritten. The side effect of this change is that any callable based
    binder (e.g. database migrations) will not be stopped, no matter what
    happens. This is a serious quirk, and may be better to remove other
    kinds of binders than hookable or rethink the stoppable binder.
    
    Signed-off-by: default avatarBart Jaskulski <bjaskulski@protonmail.com>
+ 65
29
@@ -10,7 +10,10 @@ use WPDesk\Init\Binding\Binder\CallableBinder;
use WPDesk\Init\Binding\Binder\CompositeBinder;
use WPDesk\Init\Binding\Binder\HookableBinder;
use WPDesk\Init\Binding\Binder\StoppableBinder;
use WPDesk\Init\Binding\Loader\ClusteredLoader;
use WPDesk\Init\Binding\Loader\CompositeBindingLoader;
use WPDesk\Init\Binding\Loader\DebugBindingLoader;
use WPDesk\Init\Binding\Loader\OrderedBindingLoader;
use WPDesk\Init\Configuration\Configuration;
use WPDesk\Init\DependencyInjection\ContainerBuilder;
use WPDesk\Init\Extension\ExtensionsSet;
@@ -18,6 +21,7 @@ use WPDesk\Init\HookDriver\CompositeDriver;
use WPDesk\Init\HookDriver\GenericDriver;
use WPDesk\Init\HookDriver\HookDriver;
use WPDesk\Init\HookDriver\LegacyDriver;
use WPDesk\Init\Util\PhpFileDumper;
use WPDesk\Init\Util\PhpFileLoader;
use WPDesk\Init\Plugin\Header;
use WPDesk\Init\Util\Path;
@@ -28,19 +32,17 @@ use WPDesk\Init\Plugin\Plugin;
final class Kernel {
/** @var string|null Plugin filename. */
private $filename;
private ?string $filename;
/** @var Configuration */
private $config;
private Configuration $config;
/** @var PhpFileLoader */
private $loader;
private PhpFileLoader $loader;
/** @var HeaderParser */
private $parser;
private HeaderParser $parser;
/** @var ExtensionsSet */
private $extensions;
private ExtensionsSet $extensions;
private PhpFileDumper $dumper;
public function __construct(
string $filename,
@@ -52,6 +54,7 @@ final class Kernel {
$this->extensions = $extensions;
$this->loader = new PhpFileLoader();
$this->parser = new DefaultHeaderParser();
$this->dumper = new PhpFileDumper();
}
public function boot(): void {
@@ -59,11 +62,16 @@ final class Kernel {
try {
$plugin_data = $this->loader->load( $cache_path );
} catch ( \Exception $e ) {
// If cache not found, load data from memory.
// Avoid writing files on host environment.
// Generate cache with command instead.
try {
$this->dumper->dump(
$this->parser->parse( $this->filename ),
$cache_path
);
$plugin_data = $this->loader->load( $cache_path );
} catch ( \Exception $e ) {
$plugin_data = $this->parser->parse( $this->filename );
}
}
$plugin = new Plugin( $this->filename, new Header( $plugin_data ) );
@@ -71,7 +79,7 @@ final class Kernel {
$container->set( Plugin::class, $plugin );
$container->set( Configuration::class, $this->config );
$this->prepare_driver( $container )->register_hooks();
$this->prepare_driver( $container, $plugin )->register_hooks();
}
private function get_cache_path( string $path = '' ): string {
@@ -80,50 +88,70 @@ final class Kernel {
);
}
/**
* Container name in scheme: `<slug>_<version>_container`.
*
* Container is compiled in client environment, so in order to allow graceful upgrade, include version name to the container. Compiled container class is also autoloaded, so it is necessary that name is unique enough to avoid clash with other plugins.
*/
private function get_container_name( Plugin $plugin ): string {
return str_replace( '-', '_', $plugin->get_slug() ) . '_container';
return preg_replace( '/[^\w_]/', '_', implode( '_', [ $plugin->get_slug(), $plugin->get_version(), 'container' ] ) );
}
private function initialize_container( Plugin $plugin ): Container {
private function initialize_container( Plugin $plugin, bool $use_cache = true ): Container {
$original_builder = new DiBuilder();
// If there's a cache file, use it as we are in production environment.
// Otherwise, build the container from scratch and use live version, without compilation.
if ( file_exists( $this->get_cache_path( $this->get_container_name( $plugin ) . '.php' ) ) ) {
if ( $this->is_prod( $plugin ) && $use_cache ) {
$original_builder->enableCompilation(
$this->get_cache_path(),
$this->get_container_name( $plugin )
);
return $original_builder->build();
}
$builder = new ContainerBuilder( $original_builder );
if ( ! function_exists( 'WPDesk\Init\DI\create' ) ) {
require __DIR__ . '/di-functions.php';
}
foreach ( $this->extensions as $extension ) {
$extension->build( $builder, $plugin, $this->config );
}
try {
return $builder->build();
} catch ( \InvalidArgumentException $e ) {
if ( $use_cache === false ) {
// It means, that saving to disk was not an issue.
throw $e;
}
return $this->initialize_container( $plugin, false );
}
}
private function prepare_driver( ContainerInterface $container ): HookDriver {
private function prepare_driver( ContainerInterface $container, Plugin $plugin ): HookDriver {
$loader = new CompositeBindingLoader();
foreach ( $this->extensions as $extension ) {
$loader->add( $extension->bindings( $container ) );
}
$loader = new OrderedBindingLoader(
new ClusteredLoader( $loader )
);
if ( $this->is_dev( $plugin ) ) {
$loader = new DebugBindingLoader( $loader );
}
$driver = new GenericDriver(
$loader,
new StoppableBinder(
new CompositeBinder(
new HookableBinder( $container ),
new StoppableBinder( new HookableBinder( $container ), $container ),
new CallableBinder( $container )
),
$container
)
);
if ( class_exists( \WPDesk_Plugin_Info::class ) ) {
if ( $this->config->get( 'legacy', false ) ) {
$driver = new CompositeDriver(
$driver,
new LegacyDriver( $container )
@@ -132,4 +160,12 @@ final class Kernel {
return $driver;
}
private function is_dev( Plugin $plugin ): bool {
return $this->config->get( 'debug', false ) || wp_get_environment_type() === 'development' || str_contains( $plugin->get_version(), 'dev' );
}
private function is_prod( Plugin $plugin ): bool {
return $this->is_dev( $plugin ) === false;
}
}
Loading