Skip to content
Open
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
89 changes: 2 additions & 87 deletions basic-scaffold.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,26 +25,6 @@
* License: MIT
* License URI: https://opensource.org/licenses/MIT
*/

declare( strict_types=1 );

namespace MWPD\BasicScaffold;

/*
* This is the plugin's bootstrap file. It serves three main purposes:
* 1. Provide the plugin meta information that WordPress needs;
* 2. Prepare the environment so that it is ready to execute our OOP code;
* 3. Instantiate and kick off our "composition root" (our 'Plugin' class).
*
* The bootstrap file should not do anything else, so that we have a clean
* separation between a.) code that needs to be run sequentially and produces
* side-effects and b.) declarations that can be taken out of contexts for
* testing and reuse and have no side-effects.
*
* Anything past this bootstrap file should be autoloadable classes, interfaces
* or traits without any side-effects.
*/

/*
* As this is the only PHP file having side effects, we need to provide a
* safeguard, so we want to make sure this file is only run from within
Expand All @@ -54,71 +34,6 @@
die();
}

require_once __DIR__ . '/src/boot.php';


/*------------------------------------------------------------------------------
*-- 2. Prepare the environment so that it is ready to execute our OOP code. --
*----------------------------------------------------------------------------*/

/*
* We try to load the Composer if it exists.
* If it doesn't exist, we fall back to a basic bundled autoloader
* implementation. This allows us to just use the plugin as-is without requirin
* the 'composer install' step.
* Note: If you use Composer not only for autoloading, but also including
* dependencies needed in production, the 'composer install' becomes mandatory
* and the fallback autoloader should probably be removed.
*/
$composer_autoloader = __DIR__ . '/vendor/autoload.php';

if ( is_readable ( $composer_autoloader ) ) {
require $composer_autoloader;
}

if ( ! class_exists( __NAMESPACE__ . '\\PluginFactory' ) ) {
// Composer autoloader apparently was not found, so fall back to our bundled
// autoloader.
require_once __DIR__ . '/src/Infrastructure/Autoloader.php';

( new Infrastructure\Autoloader() )
->add_namespace( __NAMESPACE__, __DIR__ . '/src' )
->register();
}



/*------------------------------------------------------------------------------
*-- 3. Instantiate and kick off our "composition root" (our "Plugin" class). --
*----------------------------------------------------------------------------*/

/*
* We use a factory to instantiate the actual plugin.
*
* The factory keeps the object as a shared instance, so that you can also
* get outside access to that same plugin instance through the factory.
*
* This is similar to a Singleton, but without all the drawbacks the Singleton
* anti-pattern brings along.
*
* For more information on why to avoid a Singleton,
* @see https://www.alainschlesser.com/singletons-shared-instances/
*/
$plugin = BasicScaffoldPluginFactory::create();

/*
* We register activation and deactivation hooks by using closures, as these
* need static access to work correctly.
*/
\register_activation_hook( __FILE__, function () use ( $plugin ) {
$plugin->activate();
} );

\register_deactivation_hook( __FILE__, function () use ( $plugin ) {
$plugin->deactivate();
} );

/*
* Finally, we run the plugin's register method to Hook the plugin into the
* WordPress request lifecycle.
*/
$plugin->register();
\MWPD\BasicScaffold\boot(__DIR__);
5 changes: 5 additions & 0 deletions configs/providers.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php

return [
\MWPD\BasicScaffold\SampleSubsystem\Provider::class,
];
140 changes: 75 additions & 65 deletions src/BasicScaffoldPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,7 @@

use MWPD\BasicScaffold\SampleSubsystem\SampleBackendService;
use MWPD\BasicScaffold\SampleSubsystem\SampleLoopService;
use MWPD\BasicScaffold\Infrastructure\{
ServiceBasedPlugin,
View\TemplatedViewFactory,
ViewFactory
};
use MWPD\BasicScaffold\Infrastructure\{Provider, ServiceBasedPlugin, View\TemplatedViewFactory, ViewFactory};

/**
* The BasicScaffoldPlugin class is the composition root of the plugin.
Expand All @@ -29,6 +25,11 @@
* can hook themselves into the WordPress lifecycle.
*/
final class BasicScaffoldPlugin extends ServiceBasedPlugin {

protected $providers = [];



/*
* --------------------------------------------------------------------------
* -- 1. Define the services that make up this plugin. --
Expand All @@ -43,6 +44,12 @@ final class BasicScaffoldPlugin extends ServiceBasedPlugin {
* what makes up the actual plugin, and they provide self-contained pieces
* of code that can work independently.
*/
/**
* @param array $providers
*/
public function __construct(array $providers ) {
$this->providers = $providers;
}

/**
* Get the list of services to register.
Expand All @@ -55,12 +62,21 @@ final class BasicScaffoldPlugin extends ServiceBasedPlugin {
* names or callables.
*/
protected function get_service_classes(): array {
return [
self::SAMPLE_BACKEND_SERVICE_ID => SampleBackendService::class,
self::SAMPLE_LOOP_SERVICE_ID => SampleLoopService::class,

// Add your service definitions here.
];
$services = [];

foreach ($this->providers as $provider) {
/**
* @var Provider $provider
*/
$provider = new $provider();
$services = array_merge(
$services,
$provider->get_service_classes(),
);
}

return $services;
}

/*
Expand Down Expand Up @@ -88,12 +104,20 @@ protected function get_service_classes(): array {
* callables.
*/
protected function get_bindings(): array {
return [
// Map the ViewFactory interface to a concrete implementation.
ViewFactory::class => TemplatedViewFactory::class,
$bindings = [];

// Add your bindings here.
];
foreach ($this->providers as $provider) {
/**
* @var Provider $provider
*/
$provider = new $provider();
$bindings = array_merge(
$bindings,
$provider->get_bindings(),
);
}

return $bindings;
}

/**
Expand All @@ -108,15 +132,20 @@ protected function get_bindings(): array {
* argument names to argument values.
*/
protected function get_arguments(): array {
return [
$arguments = [];

/*
* Example - add a scalar value to an argument for SampleService:
* SampleService::class => [ 'argument_name' => 'value' ],
foreach ($this->providers as $provider) {
/**
* @var Provider $provider
*/

// Add your argument mappings here.
];
$provider = new $provider();
$arguments = array_merge(
$arguments,
$provider->get_arguments(),
);
}

return $arguments;
}

/**
Expand All @@ -132,15 +161,20 @@ protected function get_arguments(): array {
* @return array<class-string> Array of fully qualified class names.
*/
protected function get_shared_instances(): array {
return [
$shared_instances = [];

/*
* Example - make SampleService be shared amongst instantiations:
* SampleService::class,
foreach ($this->providers as $provider) {
/**
* @var Provider $provider
*/

// Add your shared instances here.
];
$provider = new $provider();
$shared_instances = array_merge(
$shared_instances,
$provider->get_shared_instances(),
);
}

return $shared_instances;
}

/**
Expand All @@ -155,43 +189,19 @@ protected function get_shared_instances(): array {
* @return array<class-string,callable> Associative array of callables.
*/
protected function get_delegations(): array {
return [
$delegations = [];

/*
* Add a factory for instantiating WP_Post objects:
* \WP_Post::class => function () {
* return \get_post( \get_the_ID() ); },
foreach ($this->providers as $provider) {
/**
* @var Provider $provider
*/

// Add your delegations here.
];
$provider = new $provider();
$delegations = array_merge(
$delegations,
$provider->get_delegations(),
);
}

return $delegations;
}

/*
* --------------------------------------------------------------------------
* -- 3. Define prefixes and identifiers for outside access. --
* --------------------------------------------------------------------------
*/

/*
* Prefixes to use.
*
* These are provided so that if multiple plugins use the same boilerplate
* code, there hooks and service identifiers are scoped and don't clash.
*/
protected const HOOK_PREFIX = 'mwpd.basic_scaffold.';

protected const SERVICE_PREFIX = 'mwpd.basic_scaffold.';

/*
* Service identifiers we know about.
*
* These can be used from outside code as well to directly refer to a
* service when talking to the service container.
*/
public const VIEW_FACTORY_ID = self::SERVICE_PREFIX . 'view-factory';

public const SAMPLE_BACKEND_SERVICE_ID = self::SERVICE_PREFIX . 'sample-subsystem.sample-backend-service';

public const SAMPLE_LOOP_SERVICE_ID = self::SERVICE_PREFIX . 'sample-subsystem.sample-loop-service';
}
4 changes: 2 additions & 2 deletions src/BasicScaffoldPluginFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ final class BasicScaffoldPluginFactory {
*
* @return Plugin Plugin instance.
*/
public static function create(): Plugin {
public static function create(array $providers): Plugin {
/**
* We use a static variable to ensure that the plugin is only instantiated
* once. This is important for performance reasons and to ensure that the
Expand All @@ -49,7 +49,7 @@ public static function create(): Plugin {
static $plugin = null;

if ( null === $plugin ) {
$plugin = new BasicScaffoldPlugin();
$plugin = new BasicScaffoldPlugin( $providers );
}

return $plugin;
Expand Down
15 changes: 15 additions & 0 deletions src/Infrastructure/Provider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace MWPD\BasicScaffold\Infrastructure;

interface Provider {
public function get_bindings(): array;

public function get_arguments(): array;

public function get_shared_instances(): array;

public function get_delegations(): array;

public function get_service_classes(): array;
}
4 changes: 2 additions & 2 deletions src/Infrastructure/ServiceBasedPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@

namespace MWPD\BasicScaffold\Infrastructure;

use MWPD\BasicScaffold\Infrastructure\Injector\SimpleInjector;
use MWPD\BasicScaffold\Infrastructure\ServiceContainer\SimpleServiceContainer;
use MWPD\BasicScaffold\Exception\InvalidArgument;
use MWPD\BasicScaffold\Exception\InvalidConfiguration;
use MWPD\BasicScaffold\Exception\InvalidService;
use MWPD\BasicScaffold\Infrastructure\Injector\SimpleInjector;
use MWPD\BasicScaffold\Infrastructure\ServiceContainer\LazilyInstantiatedService;
use MWPD\BasicScaffold\Infrastructure\ServiceContainer\SimpleServiceContainer;

/**
* This abstract base plugin provides all the boilerplate code for working with
Expand Down
37 changes: 37 additions & 0 deletions src/SampleSubsystem/Provider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

namespace MWPD\BasicScaffold\SampleSubsystem;

class Provider implements \MWPD\BasicScaffold\Infrastructure\Provider {

public function get_bindings(): array {
return [

];
}

public function get_arguments(): array {
return [

];
}

public function get_shared_instances(): array {
return [

];
}

public function get_delegations(): array {
return [

];
}

public function get_service_classes(): array {
return [
'mwpd.basic_scaffold.sample-subsystem.sample-backend-service' => SampleBackendService::class,
'mwpd.basic_scaffold.sample-subsystem.sample-loop-service' => SampleLoopService::class,
];
}
}
Loading