mirror of
https://github.com/flarum/framework.git
synced 2024-12-04 08:13:39 +08:00
Implemented extensions as an object, usable by backend and frontend.
This commit is contained in:
parent
10f3846646
commit
b11b952aff
|
@ -11,7 +11,6 @@ import listItems from 'flarum/helpers/listItems';
|
||||||
|
|
||||||
export default class ExtensionsPage extends Component {
|
export default class ExtensionsPage extends Component {
|
||||||
view() {
|
view() {
|
||||||
const extensions = Object.keys(app.extensions).map(id => app.extensions[id]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="ExtensionsPage">
|
<div className="ExtensionsPage">
|
||||||
|
@ -29,15 +28,15 @@ export default class ExtensionsPage extends Component {
|
||||||
<div className="ExtensionsPage-list">
|
<div className="ExtensionsPage-list">
|
||||||
<div className="container">
|
<div className="container">
|
||||||
<ul className="ExtensionList">
|
<ul className="ExtensionList">
|
||||||
{extensions
|
{Object.keys(app.extensions)
|
||||||
.sort((a, b) => a.extra['flarum-extension'].title.localeCompare(b.extra['flarum-extension'].title))
|
.map(id => {
|
||||||
.map(extension => {
|
const extension = app.extensions[id];
|
||||||
const controls = this.controlItems(extension.id).toArray();
|
const controls = this.controlItems(extension.id).toArray();
|
||||||
|
|
||||||
return <li className={'ExtensionListItem ' + (!this.isEnabled(extension.id) ? 'disabled' : '')}>
|
return <li className={'ExtensionListItem ' + (!this.isEnabled(extension.id) ? 'disabled' : '')}>
|
||||||
<div className="ExtensionListItem-content">
|
<div className="ExtensionListItem-content">
|
||||||
<span className="ExtensionListItem-icon ExtensionIcon" style={extension.extra['flarum-extension'].icon}>
|
<span className="ExtensionListItem-icon ExtensionIcon" style={extension.icon}>
|
||||||
{extension.extra['flarum-extension'].icon ? icon(extension.extra['flarum-extension'].icon.name) : ''}
|
{extension.icon ? icon(extension.icon.name) : ''}
|
||||||
</span>
|
</span>
|
||||||
{controls.length ? (
|
{controls.length ? (
|
||||||
<Dropdown
|
<Dropdown
|
||||||
|
|
|
@ -72,7 +72,7 @@ class ClientController extends BaseClientController
|
||||||
|
|
||||||
$view->setVariable('settings', $settings);
|
$view->setVariable('settings', $settings);
|
||||||
$view->setVariable('permissions', Permission::map());
|
$view->setVariable('permissions', Permission::map());
|
||||||
$view->setVariable('extensions', $this->extensions->getInfo());
|
$view->setVariable('extensions', $this->extensions->getExtensions()->toArray());
|
||||||
|
|
||||||
return $view;
|
return $view;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,6 @@ class DatabaseMigrationRepository implements MigrationRepositoryInterface
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Database\ConnectionResolverInterface $resolver
|
* @param \Illuminate\Database\ConnectionResolverInterface $resolver
|
||||||
* @param string $table
|
* @param string $table
|
||||||
* @return void
|
|
||||||
*/
|
*/
|
||||||
public function __construct(Resolver $resolver, $table)
|
public function __construct(Resolver $resolver, $table)
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
namespace Flarum\Database;
|
namespace Flarum\Database;
|
||||||
|
|
||||||
|
use Flarum\Extension\Extension;
|
||||||
use Illuminate\Database\ConnectionResolverInterface as Resolver;
|
use Illuminate\Database\ConnectionResolverInterface as Resolver;
|
||||||
use Illuminate\Filesystem\Filesystem;
|
use Illuminate\Filesystem\Filesystem;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
@ -58,7 +59,6 @@ class Migrator
|
||||||
* @param \Flarum\Database\MigrationRepositoryInterface $repository
|
* @param \Flarum\Database\MigrationRepositoryInterface $repository
|
||||||
* @param \Illuminate\Database\ConnectionResolverInterface $resolver
|
* @param \Illuminate\Database\ConnectionResolverInterface $resolver
|
||||||
* @param \Illuminate\Filesystem\Filesystem $files
|
* @param \Illuminate\Filesystem\Filesystem $files
|
||||||
* @return void
|
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
MigrationRepositoryInterface $repository,
|
MigrationRepositoryInterface $repository,
|
||||||
|
@ -74,16 +74,16 @@ class Migrator
|
||||||
* Run the outstanding migrations at a given path.
|
* Run the outstanding migrations at a given path.
|
||||||
*
|
*
|
||||||
* @param string $path
|
* @param string $path
|
||||||
* @param string $extension
|
* @param Extension $extension
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function run($path, $extension = null)
|
public function run($path, Extension $extension = null)
|
||||||
{
|
{
|
||||||
$this->notes = [];
|
$this->notes = [];
|
||||||
|
|
||||||
$files = $this->getMigrationFiles($path);
|
$files = $this->getMigrationFiles($path);
|
||||||
|
|
||||||
$ran = $this->repository->getRan($extension);
|
$ran = $this->repository->getRan($extension ? $extension->getId() : null);
|
||||||
|
|
||||||
$migrations = array_diff($files, $ran);
|
$migrations = array_diff($files, $ran);
|
||||||
|
|
||||||
|
@ -96,10 +96,9 @@ class Migrator
|
||||||
* Run an array of migrations.
|
* Run an array of migrations.
|
||||||
*
|
*
|
||||||
* @param array $migrations
|
* @param array $migrations
|
||||||
* @param bool $pretend
|
* @param Extension $extension
|
||||||
* @return void
|
|
||||||
*/
|
*/
|
||||||
public function runMigrationList($migrations, $extension)
|
public function runMigrationList($migrations, Extension $extension = null)
|
||||||
{
|
{
|
||||||
// First we will just make sure that there are any migrations to run. If there
|
// First we will just make sure that there are any migrations to run. If there
|
||||||
// aren't, we will just make a note of it to the developer so they're aware
|
// aren't, we will just make a note of it to the developer so they're aware
|
||||||
|
@ -122,10 +121,10 @@ class Migrator
|
||||||
* Run "up" a migration instance.
|
* Run "up" a migration instance.
|
||||||
*
|
*
|
||||||
* @param string $file
|
* @param string $file
|
||||||
* @param string $extension
|
* @param Extension $extension
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected function runUp($file, $extension)
|
protected function runUp($file, Extension $extension = null)
|
||||||
{
|
{
|
||||||
// First we will resolve a "real" instance of the migration class from this
|
// First we will resolve a "real" instance of the migration class from this
|
||||||
// migration file name. Once we have the instances we can run the actual
|
// migration file name. Once we have the instances we can run the actual
|
||||||
|
@ -137,7 +136,7 @@ class Migrator
|
||||||
// Once we have run a migrations class, we will log that it was run in this
|
// Once we have run a migrations class, we will log that it was run in this
|
||||||
// repository so that we don't try to run it next time we do a migration
|
// repository so that we don't try to run it next time we do a migration
|
||||||
// in the application. A migration repository keeps the migrate order.
|
// in the application. A migration repository keeps the migrate order.
|
||||||
$this->repository->log($file, $extension);
|
$this->repository->log($file, $extension ? $extension->getId() : null);
|
||||||
|
|
||||||
$this->note("<info>Migrated:</info> $file");
|
$this->note("<info>Migrated:</info> $file");
|
||||||
}
|
}
|
||||||
|
@ -145,14 +144,15 @@ class Migrator
|
||||||
/**
|
/**
|
||||||
* Rolls all of the currently applied migrations back.
|
* Rolls all of the currently applied migrations back.
|
||||||
*
|
*
|
||||||
* @param bool $pretend
|
* @param string $path
|
||||||
|
* @param Extension $extension
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function reset($path, $extension = null)
|
public function reset($path, Extension $extension = null)
|
||||||
{
|
{
|
||||||
$this->notes = [];
|
$this->notes = [];
|
||||||
|
|
||||||
$migrations = array_reverse($this->repository->getRan($extension));
|
$migrations = array_reverse($this->repository->getRan($extension->getId()));
|
||||||
|
|
||||||
$this->requireFiles($path, $migrations);
|
$this->requireFiles($path, $migrations);
|
||||||
|
|
||||||
|
@ -173,10 +173,10 @@ class Migrator
|
||||||
* Run "down" a migration instance.
|
* Run "down" a migration instance.
|
||||||
*
|
*
|
||||||
* @param string $file
|
* @param string $file
|
||||||
* @param string $extension
|
* @param Extension $extension
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected function runDown($file, $extension = null)
|
protected function runDown($file, Extension $extension = null)
|
||||||
{
|
{
|
||||||
// First we will get the file name of the migration so we can resolve out an
|
// First we will get the file name of the migration so we can resolve out an
|
||||||
// instance of the migration. Once we get an instance we can either run a
|
// instance of the migration. Once we get an instance we can either run a
|
||||||
|
@ -188,7 +188,7 @@ class Migrator
|
||||||
// Once we have successfully run the migration "down" we will remove it from
|
// Once we have successfully run the migration "down" we will remove it from
|
||||||
// the migration repository so it will be considered to have not been run
|
// the migration repository so it will be considered to have not been run
|
||||||
// by the application then will be able to fire by any later operation.
|
// by the application then will be able to fire by any later operation.
|
||||||
$this->repository->delete($file, $extension);
|
$this->repository->delete($file, $extension ? $extension->getId() : null);
|
||||||
|
|
||||||
$this->note("<info>Rolled back:</info> $file");
|
$this->note("<info>Rolled back:</info> $file");
|
||||||
}
|
}
|
||||||
|
@ -201,7 +201,7 @@ class Migrator
|
||||||
*/
|
*/
|
||||||
public function getMigrationFiles($path)
|
public function getMigrationFiles($path)
|
||||||
{
|
{
|
||||||
$files = $this->files->glob($path.'/*_*.php');
|
$files = $this->files->glob($path . '/*_*.php');
|
||||||
|
|
||||||
// Once we have the array of files in the directory we will just remove the
|
// Once we have the array of files in the directory we will just remove the
|
||||||
// extension and take the basename of the file which is all we need when
|
// extension and take the basename of the file which is all we need when
|
||||||
|
@ -232,7 +232,7 @@ class Migrator
|
||||||
public function requireFiles($path, array $files)
|
public function requireFiles($path, array $files)
|
||||||
{
|
{
|
||||||
foreach ($files as $file) {
|
foreach ($files as $file) {
|
||||||
$this->files->requireOnce($path.'/'.$file.'.php');
|
$this->files->requireOnce($path . '/' . $file . '.php');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,13 +240,21 @@ class Migrator
|
||||||
* Resolve a migration instance from a file.
|
* Resolve a migration instance from a file.
|
||||||
*
|
*
|
||||||
* @param string $file
|
* @param string $file
|
||||||
|
* @param Extension $extension
|
||||||
* @return object
|
* @return object
|
||||||
*/
|
*/
|
||||||
public function resolve($file, $extension = null)
|
public function resolve($file, Extension $extension = null)
|
||||||
{
|
{
|
||||||
$file = implode('_', array_slice(explode('_', $file), 4));
|
$file = implode('_', array_slice(explode('_', $file), 4));
|
||||||
|
|
||||||
$class = ($extension ? str_replace('-', '\\', $extension) : 'Flarum\\Core') . '\\Migration\\';
|
// flagrow/image-upload
|
||||||
|
if ($extension) {
|
||||||
|
$class = str_replace('/', '\\', $extension->name);
|
||||||
|
} else {
|
||||||
|
$class = 'Flarum\\Core';
|
||||||
|
}
|
||||||
|
|
||||||
|
$class .= '\\Migration\\';
|
||||||
|
|
||||||
$class .= Str::studly($file);
|
$class .= Str::studly($file);
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
|
|
||||||
namespace Flarum\Event;
|
namespace Flarum\Event;
|
||||||
|
|
||||||
|
use Flarum\Extension\Extension;
|
||||||
|
|
||||||
class ExtensionWasDisabled
|
class ExtensionWasDisabled
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -18,9 +20,9 @@ class ExtensionWasDisabled
|
||||||
protected $extension;
|
protected $extension;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $extension
|
* @param Extension $extension
|
||||||
*/
|
*/
|
||||||
public function __construct($extension)
|
public function __construct(Extension $extension)
|
||||||
{
|
{
|
||||||
$this->extension = $extension;
|
$this->extension = $extension;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
|
|
||||||
namespace Flarum\Event;
|
namespace Flarum\Event;
|
||||||
|
|
||||||
|
use Flarum\Extension\Extension;
|
||||||
|
|
||||||
class ExtensionWasEnabled
|
class ExtensionWasEnabled
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -18,9 +20,9 @@ class ExtensionWasEnabled
|
||||||
protected $extension;
|
protected $extension;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $extension
|
* @param Extension $extension
|
||||||
*/
|
*/
|
||||||
public function __construct($extension)
|
public function __construct(Extension $extension)
|
||||||
{
|
{
|
||||||
$this->extension = $extension;
|
$this->extension = $extension;
|
||||||
}
|
}
|
||||||
|
|
252
framework/core/src/Extension/Extension.php
Normal file
252
framework/core/src/Extension/Extension.php
Normal file
|
@ -0,0 +1,252 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* This file is part of Flarum.
|
||||||
|
*
|
||||||
|
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Flarum\Extension;
|
||||||
|
|
||||||
|
use Illuminate\Contracts\Support\Arrayable;
|
||||||
|
use Illuminate\Support\Arr;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property string $name
|
||||||
|
* @property string $description
|
||||||
|
* @property string $type
|
||||||
|
* @property array $keywords
|
||||||
|
* @property string $homepage
|
||||||
|
* @property string $time
|
||||||
|
* @property string $license
|
||||||
|
* @property array $authors
|
||||||
|
* @property array $support
|
||||||
|
* @property array $require
|
||||||
|
* @property array $requireDev
|
||||||
|
* @property array $autoload
|
||||||
|
* @property array $autoloadDev
|
||||||
|
* @property array $conflict
|
||||||
|
* @property array $replace
|
||||||
|
* @property array $provide
|
||||||
|
* @property array $suggest
|
||||||
|
* @property array $extra
|
||||||
|
*/
|
||||||
|
class Extension implements Arrayable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Unique Id of the extension.
|
||||||
|
*
|
||||||
|
* @info Identical to the directory in the extensions directory.
|
||||||
|
* @example flarum_suspend
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $id;
|
||||||
|
/**
|
||||||
|
* The directory of this extension.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $path;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Composer json of the package.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $composerJson;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the extension is installed.
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $installed = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The installed version of the extension.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the extension is enabled.
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $enabled = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $path
|
||||||
|
* @param array $composerJson
|
||||||
|
*/
|
||||||
|
public function __construct($path, $composerJson)
|
||||||
|
{
|
||||||
|
$this->id = end(explode('/', $path));
|
||||||
|
$this->path = $path;
|
||||||
|
$this->composerJson = $composerJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function __get($name)
|
||||||
|
{
|
||||||
|
return $this->composerJsonAttribute(Str::snake($name, '-'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function __isset($name)
|
||||||
|
{
|
||||||
|
return isset($this->{$name}) || $this->composerJsonAttribute(Str::snake($name, '-'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dot notation getter for composer.json attributes.
|
||||||
|
*
|
||||||
|
* @see https://laravel.com/docs/5.1/helpers#arrays
|
||||||
|
*
|
||||||
|
* @param $name
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function composerJsonAttribute($name)
|
||||||
|
{
|
||||||
|
return Arr::get($this->composerJson, $name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param boolean $installed
|
||||||
|
* @return Extension
|
||||||
|
*/
|
||||||
|
public function setInstalled($installed)
|
||||||
|
{
|
||||||
|
$this->installed = $installed;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function isInstalled()
|
||||||
|
{
|
||||||
|
return $this->installed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $version
|
||||||
|
* @return Extension
|
||||||
|
*/
|
||||||
|
public function setVersion($version)
|
||||||
|
{
|
||||||
|
$this->version = $version;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getVersion()
|
||||||
|
{
|
||||||
|
return $this->version;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the icon information from the composer.json.
|
||||||
|
*
|
||||||
|
* @return array|null
|
||||||
|
*/
|
||||||
|
public function getIcon()
|
||||||
|
{
|
||||||
|
if (($icon = $this->composerJsonAttribute('extra.flarum-extension.icon'))) {
|
||||||
|
if ($file = Arr::get($icon, 'image')) {
|
||||||
|
$file = $this->path . '/' . $file;
|
||||||
|
|
||||||
|
if (file_exists($file)) {
|
||||||
|
$mimetype = pathinfo($file, PATHINFO_EXTENSION) === 'svg'
|
||||||
|
? 'image/svg+xml'
|
||||||
|
: finfo_file(finfo_open(FILEINFO_MIME_TYPE), $file);
|
||||||
|
$data = file_get_contents($file);
|
||||||
|
|
||||||
|
$icon['backgroundImage'] = 'url(\'data:' . $mimetype . ';base64,' . base64_encode($data) . '\')';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $icon;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param boolean $enabled
|
||||||
|
* @return Extension
|
||||||
|
*/
|
||||||
|
public function setEnabled($enabled)
|
||||||
|
{
|
||||||
|
$this->enabled = $enabled;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function isEnabled()
|
||||||
|
{
|
||||||
|
return $this->enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The raw path of the directory under extensions.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getId()
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests whether the extension has assets.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasAssets()
|
||||||
|
{
|
||||||
|
return realpath($this->path . '/assets/') !== false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests whether the extension has migrations.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasMigrations()
|
||||||
|
{
|
||||||
|
return realpath($this->path . '/migrations/') !== false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an array result for the object.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function toArray()
|
||||||
|
{
|
||||||
|
return (array) array_merge([
|
||||||
|
'id' => $this->getId(),
|
||||||
|
'version' => $this->getVersion(),
|
||||||
|
'path' => $this->path,
|
||||||
|
'icon' => $this->getIcon(),
|
||||||
|
'hasAssets' => $this->hasAssets(),
|
||||||
|
'hasMigrations' => $this->hasMigrations(),
|
||||||
|
], $this->composerJson);
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,6 +19,8 @@ use Flarum\Foundation\Application;
|
||||||
use Flarum\Settings\SettingsRepositoryInterface;
|
use Flarum\Settings\SettingsRepositoryInterface;
|
||||||
use Illuminate\Contracts\Events\Dispatcher;
|
use Illuminate\Contracts\Events\Dispatcher;
|
||||||
use Illuminate\Filesystem\Filesystem;
|
use Illuminate\Filesystem\Filesystem;
|
||||||
|
use Illuminate\Support\Arr;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
class ExtensionManager
|
class ExtensionManager
|
||||||
{
|
{
|
||||||
|
@ -38,8 +40,13 @@ class ExtensionManager
|
||||||
*/
|
*/
|
||||||
protected $filesystem;
|
protected $filesystem;
|
||||||
|
|
||||||
public function __construct(SettingsRepositoryInterface $config, Application $app, Migrator $migrator, Dispatcher $dispatcher, Filesystem $filesystem)
|
public function __construct(
|
||||||
{
|
SettingsRepositoryInterface $config,
|
||||||
|
Application $app,
|
||||||
|
Migrator $migrator,
|
||||||
|
Dispatcher $dispatcher,
|
||||||
|
Filesystem $filesystem
|
||||||
|
) {
|
||||||
$this->config = $config;
|
$this->config = $config;
|
||||||
$this->app = $app;
|
$this->app = $app;
|
||||||
$this->migrator = $migrator;
|
$this->migrator = $migrator;
|
||||||
|
@ -47,61 +54,70 @@ class ExtensionManager
|
||||||
$this->filesystem = $filesystem;
|
$this->filesystem = $filesystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getInfo()
|
/**
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public function getExtensions()
|
||||||
{
|
{
|
||||||
$extensionsDir = $this->getExtensionsDir();
|
$extensionsDir = $this->getExtensionsDir();
|
||||||
|
|
||||||
$dirs = array_diff(scandir($extensionsDir), ['.', '..']);
|
$dirs = array_diff(scandir($extensionsDir), ['.', '..']);
|
||||||
$extensions = [];
|
$extensions = new Collection();
|
||||||
|
|
||||||
$installed = json_decode(file_get_contents(public_path('vendor/composer/installed.json')), true);
|
$installed = json_decode(file_get_contents(public_path('vendor/composer/installed.json')), true);
|
||||||
|
|
||||||
foreach ($dirs as $dir) {
|
foreach ($dirs as $dir) {
|
||||||
if (file_exists($manifest = $extensionsDir . '/' . $dir . '/composer.json')) {
|
if (file_exists($manifest = $extensionsDir . '/' . $dir . '/composer.json')) {
|
||||||
$extension = json_decode(file_get_contents($manifest), true);
|
$extension = new Extension(
|
||||||
|
$extensionsDir . '/' . $dir,
|
||||||
|
json_decode(file_get_contents($manifest), true)
|
||||||
|
);
|
||||||
|
|
||||||
if (empty($extension['name'])) {
|
if (empty($extension->name)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($extension['extra']['flarum-extension']['icon'])) {
|
|
||||||
$icon = &$extension['extra']['flarum-extension']['icon'];
|
|
||||||
|
|
||||||
if ($file = array_get($icon, 'image')) {
|
|
||||||
$file = $extensionsDir . '/' . $dir . '/' . $file;
|
|
||||||
|
|
||||||
if (file_exists($file)) {
|
|
||||||
$mimetype = pathinfo($file, PATHINFO_EXTENSION) === 'svg'
|
|
||||||
? 'image/svg+xml'
|
|
||||||
: finfo_file(finfo_open(FILEINFO_MIME_TYPE), $file);
|
|
||||||
$data = file_get_contents($file);
|
|
||||||
|
|
||||||
$icon['backgroundImage'] = 'url(\'data:' . $mimetype . ';base64,' . base64_encode($data) . '\')';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($installed as $package) {
|
foreach ($installed as $package) {
|
||||||
if ($package['name'] === $extension['name']) {
|
if ($package['name'] === $extension->name) {
|
||||||
$extension['version'] = $package['version'];
|
$extension->setInstalled(true);
|
||||||
|
$extension->setVersion($package['version']);
|
||||||
|
$extension->setEnabled($this->isEnabled($dir));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$extension['id'] = $dir;
|
$extensions->put($dir, $extension);
|
||||||
|
|
||||||
$extensions[$dir] = $extension;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $extensions;
|
return $extensions->sortBy(function ($extension, $name) {
|
||||||
|
return $extension->composerJsonAttribute('extra.flarum-extension.title');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function enable($extension)
|
/**
|
||||||
|
* Loads an Extension with all information.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @return Extension|null
|
||||||
|
*/
|
||||||
|
public function getExtension($name)
|
||||||
{
|
{
|
||||||
if (! $this->isEnabled($extension)) {
|
return $this->getExtensions()->get($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables the extension.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
*/
|
||||||
|
public function enable($name)
|
||||||
|
{
|
||||||
|
if (!$this->isEnabled($name)) {
|
||||||
|
$extension = $this->getExtension($name);
|
||||||
|
|
||||||
$enabled = $this->getEnabled();
|
$enabled = $this->getEnabled();
|
||||||
|
|
||||||
$enabled[] = $extension;
|
$enabled[] = $name;
|
||||||
|
|
||||||
$this->migrate($extension);
|
$this->migrate($extension);
|
||||||
|
|
||||||
|
@ -109,72 +125,101 @@ class ExtensionManager
|
||||||
|
|
||||||
$this->setEnabled($enabled);
|
$this->setEnabled($enabled);
|
||||||
|
|
||||||
|
$extension->setEnabled(true);
|
||||||
|
|
||||||
$this->dispatcher->fire(new ExtensionWasEnabled($extension));
|
$this->dispatcher->fire(new ExtensionWasEnabled($extension));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function disable($extension)
|
/**
|
||||||
|
* Disables an extension.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
*/
|
||||||
|
public function disable($name)
|
||||||
{
|
{
|
||||||
$enabled = $this->getEnabled();
|
$enabled = $this->getEnabled();
|
||||||
|
|
||||||
if (($k = array_search($extension, $enabled)) !== false) {
|
if (($k = array_search($name, $enabled)) !== false) {
|
||||||
unset($enabled[$k]);
|
unset($enabled[$k]);
|
||||||
|
|
||||||
|
$extension = $this->getExtension($name);
|
||||||
|
|
||||||
$this->setEnabled($enabled);
|
$this->setEnabled($enabled);
|
||||||
|
|
||||||
|
$extension->setEnabled(false);
|
||||||
|
|
||||||
$this->dispatcher->fire(new ExtensionWasDisabled($extension));
|
$this->dispatcher->fire(new ExtensionWasDisabled($extension));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function uninstall($extension)
|
/**
|
||||||
|
* Uninstalls an extension.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
*/
|
||||||
|
public function uninstall($name)
|
||||||
{
|
{
|
||||||
$this->disable($extension);
|
$extension = $this->getExtension($name);
|
||||||
|
|
||||||
|
$this->disable($name);
|
||||||
|
|
||||||
$this->migrateDown($extension);
|
$this->migrateDown($extension);
|
||||||
|
|
||||||
$this->unpublishAssets($extension);
|
$this->unpublishAssets($extension);
|
||||||
|
|
||||||
|
$extension->setInstalled(false);
|
||||||
|
|
||||||
$this->dispatcher->fire(new ExtensionWasUninstalled($extension));
|
$this->dispatcher->fire(new ExtensionWasUninstalled($extension));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy the assets from an extension's assets directory into public view.
|
* Copy the assets from an extension's assets directory into public view.
|
||||||
*
|
*
|
||||||
* @param string $extension
|
* @param Extension $extension
|
||||||
*/
|
*/
|
||||||
protected function publishAssets($extension)
|
protected function publishAssets(Extension $extension)
|
||||||
{
|
{
|
||||||
|
if ($extension->hasAssets()) {
|
||||||
$this->filesystem->copyDirectory(
|
$this->filesystem->copyDirectory(
|
||||||
$this->app->basePath().'/extensions/'.$extension.'/assets',
|
$this->app->basePath() . '/extensions/' . $extension->getId() . '/assets',
|
||||||
$this->app->basePath().'/assets/extensions/'.$extension
|
$this->app->basePath() . '/assets/extensions/' . $extension->getId()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete an extension's assets from public view.
|
* Delete an extension's assets from public view.
|
||||||
*
|
*
|
||||||
* @param string $extension
|
* @param Extension $extension
|
||||||
*/
|
*/
|
||||||
protected function unpublishAssets($extension)
|
protected function unpublishAssets(Extension $extension)
|
||||||
{
|
{
|
||||||
$this->filesystem->deleteDirectory($this->app->basePath().'/assets/extensions/'.$extension);
|
$this->filesystem->deleteDirectory($this->app->basePath() . '/assets/extensions/' . $extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the path to an extension's published asset.
|
* Get the path to an extension's published asset.
|
||||||
*
|
*
|
||||||
* @param string $extension
|
* @param Extension $extension
|
||||||
* @param string $path
|
* @param string $path
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getAsset($extension, $path)
|
public function getAsset(Extension $extension, $path)
|
||||||
{
|
{
|
||||||
return $this->app->basePath().'/assets/extensions/'.$extension.$path;
|
return $this->app->basePath() . '/assets/extensions/' . $extension->getId() . $path;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function migrate($extension, $up = true)
|
/**
|
||||||
|
* Runs the database migrations for the extension.
|
||||||
|
*
|
||||||
|
* @param Extension $extension
|
||||||
|
* @param bool|true $up
|
||||||
|
*/
|
||||||
|
public function migrate(Extension $extension, $up = true)
|
||||||
{
|
{
|
||||||
$migrationDir = public_path('extensions/' . $extension . '/migrations');
|
if ($extension->hasMigrations()) {
|
||||||
|
$migrationDir = public_path('extensions/' . $extension->getId() . '/migrations');
|
||||||
|
|
||||||
$this->app->bind('Illuminate\Database\Schema\Builder', function ($container) {
|
$this->app->bind('Illuminate\Database\Schema\Builder', function ($container) {
|
||||||
return $container->make('Illuminate\Database\ConnectionInterface')->getSchemaBuilder();
|
return $container->make('Illuminate\Database\ConnectionInterface')->getSchemaBuilder();
|
||||||
|
@ -186,10 +231,16 @@ class ExtensionManager
|
||||||
$this->migrator->reset($migrationDir, $extension);
|
$this->migrator->reset($migrationDir, $extension);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function migrateDown($extension)
|
/**
|
||||||
|
* Runs the database migrations to reset the database to its old state.
|
||||||
|
*
|
||||||
|
* @param Extension $extension
|
||||||
|
*/
|
||||||
|
public function migrateDown(Extension $extension)
|
||||||
{
|
{
|
||||||
$this->migrate($extension, false);
|
$this->migrate($extension->getId(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getMigrator()
|
public function getMigrator()
|
||||||
|
|
|
@ -343,7 +343,7 @@ class InstallCommand extends AbstractCommand
|
||||||
'flarum-pusher',
|
'flarum-pusher',
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach ($extensions->getInfo() as $name => $extension) {
|
foreach ($extensions->getExtensions() as $name => $extension) {
|
||||||
if (in_array($name, $disabled)) {
|
if (in_array($name, $disabled)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,8 +74,8 @@ class MigrateCommand extends AbstractCommand
|
||||||
|
|
||||||
$migrator = $extensions->getMigrator();
|
$migrator = $extensions->getMigrator();
|
||||||
|
|
||||||
foreach ($extensions->getInfo() as $name => $extension) {
|
foreach ($extensions->getExtensions() as $name => $extension) {
|
||||||
if (! $extensions->isEnabled($name)) {
|
if (! $extension->isEnabled()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user