Skip to content
Snippets Groups Projects
Select Git revision
  • c2d6fbc52a80d5678b06260cf6f522d57a48babc
  • main default protected
  • v0.10
  • 0.10.6
  • 0.10.5
  • 0.10.4
  • 0.10.3
  • 0.10.2
  • 0.10.1
  • 0.10.0
  • 0.9.1
  • 0.9.0
12 results

Kernel.php

Blame
  • Kernel.php 4.41 KiB
    <?php
    declare( strict_types=1 );
    
    namespace WPDesk\Init;
    
    use DI\Container;
    use DI\ContainerBuilder as DiBuilder;
    use Psr\Container\ContainerInterface;
    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;
    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;
    use WPDesk\Init\Plugin\DefaultHeaderParser;
    use WPDesk\Init\Plugin\HeaderParser;
    use WPDesk\Init\Plugin\Plugin;
    
    final class Kernel {
    
    	/** @var string|null Plugin filename. */
    	private ?string $filename;
    
    	private Configuration $config;
    
    	private PhpFileLoader $loader;
    
    	private HeaderParser $parser;
    
    	private ExtensionsSet $extensions;
    
    	private PhpFileDumper $dumper;
    
    	public function __construct(
    		string $filename,
    		Configuration $config,
    		ExtensionsSet $extensions
    	) {
    		$this->filename   = $filename;
    		$this->config     = $config;
    		$this->extensions = $extensions;
    		$this->loader     = new PhpFileLoader();
    		$this->parser     = new DefaultHeaderParser();
    		$this->dumper     = new PhpFileDumper();
    	}
    
    	public function boot(): void {
    		$cache_path = $this->get_cache_path( 'plugin.php' );
    		try {
    			$plugin_data = $this->loader->load( $cache_path );
    		} catch ( \Exception $e ) {
    			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 ) );
    
    		$container = $this->initialize_container( $plugin );
    		$container->set( Plugin::class, $plugin );
    		$container->set( Configuration::class, $this->config );
    
    		$this->prepare_driver( $container )->register_hooks();
    	}
    
    	private function get_cache_path( string $path = '' ): string {
    		return (string) ( new Path( $this->config->get( 'cache_path', 'generated' ) ) )->join( $path )->absolute(
    			rtrim( plugin_dir_path( $this->filename ), '/' ) . '/'
    		);
    	}
    
    	private function get_container_name( Plugin $plugin ): string {
    		return preg_replace( '/[^\w_]/', '_', implode("_", [ $plugin->get_slug(), $plugin->get_version(), 'container' ]) );
    	}
    
    	private function initialize_container( Plugin $plugin, bool $useCache = true ): Container {
    		$original_builder = new DiBuilder();
    
    		if ( $this->is_prod() && $useCache ) {
    			$original_builder->enableCompilation(
    				$this->get_cache_path(),
    				$this->get_container_name( $plugin )
    			);
    		}
    
    		$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 ( \Exception $e ) {
    			return $this->initialize_container( $plugin, false );
    		}
    	}
    
    	private function prepare_driver( ContainerInterface $container ): HookDriver {
    		$loader = new CompositeBindingLoader();
    		foreach ( $this->extensions as $extension ) {
    			$loader->add( $extension->bindings( $container ) );
    		}
    
    		$loader = new OrderedBindingLoader(
    			new ClusteredLoader( $loader )
    		);
    
    		if ( $this->is_dev() ) {
    			$loader = new DebugBindingLoader( $loader );
    		}
    
    		$driver = new GenericDriver(
    			$loader,
    			new CompositeBinder(
    				new StoppableBinder( new HookableBinder( $container ), $container ),
    				new CallableBinder( $container )
    			)
    		);
    
    		if ( $this->config->get( 'legacy', false ) ) {
    			$driver = new CompositeDriver(
    				$driver,
    				new LegacyDriver( $container )
    			);
    		}
    
    		return $driver;
    	}
    
    	private function is_dev(): bool {
    		return $this->config->get( 'debug', false ) || wp_get_environment_type() !== 'development';
    	}
    
    	private function is_prod(): bool {
    		return $this->is_dev() === false;
    	}
    }