diff --git a/framework/core/src/Event/AbstractConfigureRoutes.php b/framework/core/src/Event/AbstractConfigureRoutes.php index 3ce06cf61..5474c40f1 100644 --- a/framework/core/src/Event/AbstractConfigureRoutes.php +++ b/framework/core/src/Event/AbstractConfigureRoutes.php @@ -14,6 +14,9 @@ namespace Flarum\Event; use Flarum\Http\RouteCollection; use Flarum\Http\RouteHandlerFactory; +/** + * @deprecated + */ abstract class AbstractConfigureRoutes { /** diff --git a/framework/core/src/Event/ConfigureApiRoutes.php b/framework/core/src/Event/ConfigureApiRoutes.php index 47727c913..1bcadbfb5 100644 --- a/framework/core/src/Event/ConfigureApiRoutes.php +++ b/framework/core/src/Event/ConfigureApiRoutes.php @@ -12,9 +12,7 @@ namespace Flarum\Event; /** - * Configure API routes. - * - * This event is fired when API routes are being registered. + * @deprecated */ class ConfigureApiRoutes extends AbstractConfigureRoutes { diff --git a/framework/core/src/Event/ConfigureForumRoutes.php b/framework/core/src/Event/ConfigureForumRoutes.php index 934f27a48..cc64464fd 100644 --- a/framework/core/src/Event/ConfigureForumRoutes.php +++ b/framework/core/src/Event/ConfigureForumRoutes.php @@ -14,9 +14,7 @@ namespace Flarum\Event; use Flarum\Forum\Controller\FrontendController; /** - * Configure forum routes. - * - * This event is fired when routes for the forum client are being registered. + * @deprecated */ class ConfigureForumRoutes extends AbstractConfigureRoutes { diff --git a/framework/core/src/Event/ConfigureLocales.php b/framework/core/src/Event/ConfigureLocales.php index 11a412537..1fb373155 100644 --- a/framework/core/src/Event/ConfigureLocales.php +++ b/framework/core/src/Event/ConfigureLocales.php @@ -15,6 +15,9 @@ use DirectoryIterator; use Flarum\Locale\LocaleManager; use RuntimeException; +/** + * @deprecated + */ class ConfigureLocales { /** diff --git a/framework/core/src/Event/ConfigureMiddleware.php b/framework/core/src/Event/ConfigureMiddleware.php index e602d5532..1581bfdbd 100644 --- a/framework/core/src/Event/ConfigureMiddleware.php +++ b/framework/core/src/Event/ConfigureMiddleware.php @@ -13,6 +13,9 @@ namespace Flarum\Event; use Zend\Stratigility\MiddlewarePipe; +/** + * @deprecated + */ class ConfigureMiddleware { /** diff --git a/framework/core/src/Extend/Assets.php b/framework/core/src/Extend/Assets.php new file mode 100644 index 000000000..6fb52dbd7 --- /dev/null +++ b/framework/core/src/Extend/Assets.php @@ -0,0 +1,81 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Flarum\Extend; + +use Flarum\Frontend\Event\Rendering; +use Illuminate\Contracts\Container\Container; +use Illuminate\Events\Dispatcher; + +class Assets implements Extender +{ + protected $appName; + + protected $assets = []; + protected $bootstrapper; + + public function __construct($appName) + { + $this->appName = $appName; + } + + public function defaultAssets($baseDir) + { + $this->asset("$baseDir/js/{$this->appName}/dist/extension.js"); + $this->asset("$baseDir/less/{$this->appName}/extension.less"); + + return $this; + } + + public function asset($path) + { + $this->assets[] = $path; + + return $this; + } + + public function bootstrapper($name) + { + $this->bootstrapper = $name; + + return $this; + } + + public function apply(Container $container) + { + $container->make(Dispatcher::class)->listen( + Rendering::class, + function (Rendering $event) { + if (! $this->matches($event)) { + return; + } + + $event->addAssets($this->assets); + + if ($this->bootstrapper) { + $event->addBootstrapper($this->bootstrapper); + } + } + ); + } + + private function matches(Rendering $event) + { + switch ($this->appName) { + case 'admin': + return $event->isAdmin(); + case 'forum': + return $event->isForum(); + default: + return false; + } + } +} diff --git a/framework/core/src/Extend/Compat.php b/framework/core/src/Extend/Compat.php new file mode 100644 index 000000000..3678f2a84 --- /dev/null +++ b/framework/core/src/Extend/Compat.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Flarum\Extend; + +use Illuminate\Contracts\Container\Container; + +/** + * This class is used to wrap old bootstrap.php closures (as used in versions up + * to 0.1.0-beta7) in the new Extender format. + * + * This gives extensions the chance to work with the new API without making any + * changes, and have some time to convert to the pure usage of extenders. + * + * @deprecated + */ +class Compat implements Extender +{ + protected $callback; + + public function __construct($callback) + { + $this->callback = $callback; + } + + public function apply(Container $container) + { + $container->call($this->callback); + } +} diff --git a/framework/core/src/Extend/Extender.php b/framework/core/src/Extend/Extender.php new file mode 100644 index 000000000..71274391e --- /dev/null +++ b/framework/core/src/Extend/Extender.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Flarum\Extend; + +use Illuminate\Contracts\Container\Container; + +interface Extender +{ + public function apply(Container $container); +} diff --git a/framework/core/src/Extend/FormatterConfiguration.php b/framework/core/src/Extend/FormatterConfiguration.php new file mode 100644 index 000000000..1608a35fd --- /dev/null +++ b/framework/core/src/Extend/FormatterConfiguration.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Flarum\Extend; + +use Flarum\Formatter\Event\Configuring; +use Illuminate\Contracts\Container\Container; +use Illuminate\Events\Dispatcher; + +class FormatterConfiguration implements Extender +{ + protected $callback; + + public function __construct(callable $callback) + { + $this->callback = $callback; + } + + public function apply(Container $container) + { + $container->make(Dispatcher::class)->listen( + Configuring::class, + function (Configuring $event) { + call_user_func($this->callback, $event->configurator); + } + ); + } +} diff --git a/framework/core/src/Extend/Locale.php b/framework/core/src/Extend/Locale.php new file mode 100644 index 000000000..08e126b41 --- /dev/null +++ b/framework/core/src/Extend/Locale.php @@ -0,0 +1,75 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Flarum\Extend; + +use DirectoryIterator; +use Flarum\Locale\LocaleManager; +use Illuminate\Contracts\Container\Container; +use RuntimeException; + +class Locale implements Extender +{ + protected $directory; + + public function __construct($directory) + { + $this->directory = $directory; + } + + public function apply(Container $container) + { + $this->loadLanguagePackFrom( + $this->directory, + $container->make(LocaleManager::class) + ); + } + + private function loadLanguagePackFrom($directory, LocaleManager $locales) + { + $name = $title = basename($directory); + + if (file_exists($manifest = $directory.'/composer.json')) { + $json = json_decode(file_get_contents($manifest), true); + + if (empty($json)) { + throw new RuntimeException("Error parsing composer.json in $name: ".json_last_error_msg()); + } + + $locale = array_get($json, 'extra.flarum-locale.code'); + $title = array_get($json, 'extra.flarum-locale.title', $title); + } + + if (! isset($locale)) { + throw new RuntimeException("Language pack $name must define \"extra.flarum-locale.code\" in composer.json."); + } + + $locales->addLocale($locale, $title); + + if (! is_dir($localeDir = $directory.'/locale')) { + throw new RuntimeException("Language pack $name must have a \"locale\" subdirectory."); + } + + if (file_exists($file = $localeDir.'/config.js')) { + $locales->addJsFile($locale, $file); + } + + if (file_exists($file = $localeDir.'/config.css')) { + $locales->addCssFile($locale, $file); + } + + foreach (new DirectoryIterator($localeDir) as $file) { + if ($file->isFile() && in_array($file->getExtension(), ['yml', 'yaml'])) { + $locales->addTranslations($locale, $file->getPathname()); + } + } + } +} diff --git a/framework/core/src/Extend/Route.php b/framework/core/src/Extend/Route.php new file mode 100644 index 000000000..260bb37a5 --- /dev/null +++ b/framework/core/src/Extend/Route.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Flarum\Extend; + +use Flarum\Http\RouteCollection; +use Flarum\Http\RouteHandlerFactory; +use Illuminate\Contracts\Container\Container; + +class Route implements Extender +{ + protected $appName; + protected $name; + protected $httpMethod; + protected $path; + protected $handler; + + public function __construct($appName, $name, $httpMethod, $path, $handler) + { + $this->appName = $appName; + $this->name = $name; + $this->httpMethod = $httpMethod; + $this->path = $path; + $this->handler = $handler; + } + + public function apply(Container $container) + { + /** @var RouteCollection $routes */ + $collection = $container->make("flarum.{$this->appName}.routes"); + + /** @var RouteHandlerFactory $factory */ + $factory = $container->make(RouteHandlerFactory::class); + + $collection->{$this->httpMethod}( + $this->path, + $this->name, + $factory->toController($this->handler) + ); + } +} diff --git a/framework/core/src/Extension/Extension.php b/framework/core/src/Extension/Extension.php index 1abb6febe..255a7c6df 100644 --- a/framework/core/src/Extension/Extension.php +++ b/framework/core/src/Extension/Extension.php @@ -231,6 +231,11 @@ class Extension implements Arrayable return $this->path; } + public function getBootstrapperPath() + { + return "{$this->path}/bootstrap.php"; + } + /** * Tests whether the extension has assets. * diff --git a/framework/core/src/Extension/ExtensionManager.php b/framework/core/src/Extension/ExtensionManager.php index 404638fd5..ad0df4278 100644 --- a/framework/core/src/Extension/ExtensionManager.php +++ b/framework/core/src/Extension/ExtensionManager.php @@ -12,6 +12,7 @@ namespace Flarum\Extension; use Flarum\Database\Migrator; +use Flarum\Extend\Compat; use Flarum\Extension\Event\Disabled; use Flarum\Extension\Event\Disabling; use Flarum\Extension\Event\Enabled; @@ -273,21 +274,30 @@ class ExtensionManager } /** - * Loads all bootstrap.php files of the enabled extensions. + * Retrieve all extender instances of all enabled extensions. * * @return Collection */ - public function getEnabledBootstrappers() + public function getActiveExtenders() { - $bootstrappers = new Collection; + return $this->getEnabledExtensions() + ->flatMap(function (Extension $extension) { + $bootstrapper = $extension->getBootstrapperPath(); + if ($this->filesystem->exists($bootstrapper)) { + $extenders = require $bootstrapper; - foreach ($this->getEnabledExtensions() as $extension) { - if ($this->filesystem->exists($file = $extension->getPath().'/bootstrap.php')) { - $bootstrappers->push($file); - } - } + if (is_array($extenders)) { + return $extenders; + } - return $bootstrappers; + // Assume that the extension has not yet switched to the new + // bootstrap.php format, and wrap the callback in a Compat + // extender. + return [new Compat($extenders)]; + } else { + return []; + } + }); } /** diff --git a/framework/core/src/Extension/ExtensionServiceProvider.php b/framework/core/src/Extension/ExtensionServiceProvider.php index 77b88d3e5..78b8be201 100644 --- a/framework/core/src/Extension/ExtensionServiceProvider.php +++ b/framework/core/src/Extension/ExtensionServiceProvider.php @@ -12,6 +12,7 @@ namespace Flarum\Extension; use Flarum\Foundation\AbstractServiceProvider; +use Illuminate\Contracts\Container\Container; class ExtensionServiceProvider extends AbstractServiceProvider { @@ -22,13 +23,14 @@ class ExtensionServiceProvider extends AbstractServiceProvider { $this->app->bind('flarum.extensions', ExtensionManager::class); - $bootstrappers = $this->app->make('flarum.extensions')->getEnabledBootstrappers(); + $this->app->booting(function (Container $app) { + /** @var \Flarum\Extend\Extender[] $extenders */ + $extenders = $app->make('flarum.extensions')->getActiveExtenders(); - foreach ($bootstrappers as $file) { - $bootstrapper = require $file; - - $this->app->call($bootstrapper); - } + foreach ($extenders as $extender) { + $extender->apply($app); + } + }); } /**