From fc4638649f17ef17f577f238e0e2d63b0e078481 Mon Sep 17 00:00:00 2001 From: jhyeon1010 Date: Wed, 24 Apr 2019 15:20:00 +0900 Subject: [PATCH] =?UTF-8?q?=ED=94=8C=EB=9F=AC=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EA=B8=B0=EB=8A=A5=20=EA=B0=9C=EC=84=A0=20?= =?UTF-8?q?=EB=B0=8F=20=EC=84=A4=EC=B9=98=20=EA=B8=B0=EB=8A=A5=20=ED=86=B5?= =?UTF-8?q?=ED=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + app/Console/Commands/ComponentMakeCommand.php | 39 +++++++- app/Console/Commands/ComposerRunTrait.php | 2 + app/Console/Commands/DynamicFieldMake.php | 3 +- app/Console/Commands/DynamicFieldSkinMake.php | 3 +- app/Console/Commands/MakeCommand.php | 20 ++--- app/Console/Commands/PluginCommand.php | 46 ---------- app/Console/Commands/PluginMake.php | 57 ++++++++---- app/Console/Commands/PrivateUpdateCommand.php | 89 +++++++++++++++++++ app/Console/Commands/ShouldOperation.php | 66 ++++++++++++++ app/Console/Commands/SkinMake.php | 3 +- app/Console/Commands/ThemeMake.php | 3 +- app/Console/Commands/XeUpdate.php | 8 -- .../Commands/stubs/plugin/composer.json.stub | 2 +- app/Console/Commands/stubs/skin/skin.stub | 3 - app/Console/Kernel.php | 1 + app/Exceptions/Handler.php | 7 -- app/Http/Controllers/PluginController.php | 47 +++++++++- app/Http/Controllers/SafeModeController.php | 1 - composer.json | 4 + .../Xpressengine/Foundation/Application.php | 11 +++ .../Xpressengine/Plugin/AbstractPlugin.php | 6 +- .../Xpressengine/Plugin/Composer/Composer.php | 2 +- core/src/Xpressengine/Plugin/PluginEntity.php | 30 +++++-- .../src/Xpressengine/Plugin/PluginHandler.php | 27 +----- core/src/Xpressengine/Skin/GenericSkin.php | 5 -- core/src/Xpressengine/Support/helpers.php | 2 +- core/tests/Plugin/PluginEntityTest.php | 1 - resources/lang/common.php | 16 ++++ .../plugin/skins/default/index/item.blade.php | 7 ++ routes/web.php | 7 ++ 31 files changed, 370 insertions(+), 149 deletions(-) create mode 100644 app/Console/Commands/PrivateUpdateCommand.php diff --git a/.gitignore b/.gitignore index 7ecbf3a3ab..fd63748de4 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ composer.user.json *.iml .DS_Store /plugins +/privates node_modules /resources/jsdoc *.map diff --git a/app/Console/Commands/ComponentMakeCommand.php b/app/Console/Commands/ComponentMakeCommand.php index c09f6df471..cba3c9ce24 100644 --- a/app/Console/Commands/ComponentMakeCommand.php +++ b/app/Console/Commands/ComponentMakeCommand.php @@ -17,7 +17,9 @@ use Illuminate\Filesystem\Filesystem; use ReflectionClass; use Symfony\Component\Console\Input\InputOption; +use Xpressengine\Plugin\Composer\ComposerFileWriter; use Xpressengine\Plugin\PluginEntity; +use Xpressengine\Plugin\PluginHandler; /** * Abstract Class ComponentMakeCommand @@ -41,14 +43,22 @@ abstract class ComponentMakeCommand extends MakeCommand */ protected $componentType; + /** + * @var PluginHandler instance + */ + protected $handler; + /** * Create a new component creator command instance. * - * @param \Illuminate\Filesystem\Filesystem $files Filesystem instance + * @param \Illuminate\Filesystem\Filesystem $files Filesystem instance + * @param PluginHandler $handler PluginHandler instance */ - public function __construct(Filesystem $files) + public function __construct(Filesystem $files, ComposerFileWriter $writer, PluginHandler $handler) { - parent::__construct($files); + parent::__construct($files, $writer); + + $this->handler = $handler; $this->addOption('--title', '', InputOption::VALUE_OPTIONAL, 'The title of component'); $this->addOption('--description', '', InputOption::VALUE_OPTIONAL, 'The description of component'); @@ -62,7 +72,7 @@ public function __construct(Filesystem $files) */ protected function getPlugin() { - if(!$plugin = app('xe.plugin')->getPlugin($name = $this->getPluginName())) { + if(!$plugin = $this->handler->getPlugin($name = $this->getPluginName())) { throw new \Exception("Unable to find a plugin to locate the skin file. plugin[$name] is not found."); } @@ -265,6 +275,27 @@ protected function existsAutoload($class, $file) return in_array($file, (array)($autoload->classmap ?? [])); } + /** + * Refresh the given plugin + * + * @param PluginEntity $plugin plugin entity + * @return int + * @throws \Exception + */ + protected function refresh(PluginEntity $plugin) + { + $this->writer->reset()->cleanOperation(); + $this->writer->write(); + + $result = $this->composerDump($plugin->hasVendor() ? $plugin->getPath() : base_path()); + + if (0 !== $result) { + throw new \Exception('Fail to run composer dump'); + } + + return $result; + } + /** * Clean * diff --git a/app/Console/Commands/ComposerRunTrait.php b/app/Console/Commands/ComposerRunTrait.php index 3b03647f14..44336c69cb 100644 --- a/app/Console/Commands/ComposerRunTrait.php +++ b/app/Console/Commands/ComposerRunTrait.php @@ -127,6 +127,8 @@ protected function checkComposerHome() */ protected function runComposer($inputs, $skipPlugin = false, $output = null) { + define('__RUN_IN_ARTISAN__', true); + ini_set('memory_limit', '-1'); if ($skipPlugin) { diff --git a/app/Console/Commands/DynamicFieldMake.php b/app/Console/Commands/DynamicFieldMake.php index 4e7e35fc17..8709a5c348 100644 --- a/app/Console/Commands/DynamicFieldMake.php +++ b/app/Console/Commands/DynamicFieldMake.php @@ -96,6 +96,7 @@ public function handle() try { $this->makeUsable($attr); + $this->info('Generate the dynamic field'); $class = $namespace.'\\'.$className; @@ -106,7 +107,7 @@ public function handle() throw new \Exception('Writing to composer.json file was failed.'); } - $this->runComposerDump($plugin->getPath()); + $this->refresh($plugin); } catch (\Exception $e) { $this->clean($path); throw $e; diff --git a/app/Console/Commands/DynamicFieldSkinMake.php b/app/Console/Commands/DynamicFieldSkinMake.php index 8f9f735d85..749620644f 100644 --- a/app/Console/Commands/DynamicFieldSkinMake.php +++ b/app/Console/Commands/DynamicFieldSkinMake.php @@ -99,13 +99,14 @@ public function handle() try { $this->makeUsable($attr); + $this->info('Generate the dynamic skin'); // composer.json 파일 수정 if ($this->registerComponent($plugin, $id, $namespace.'\\'.$className, $file, ['name' => $title, 'description' => $description]) === false) { throw new \Exception('Writing to composer.json file was failed.'); } - $this->runComposerDump($plugin->getPath()); + $this->refresh($plugin); } catch (\Exception $e) { $this->clean($path); throw $e; diff --git a/app/Console/Commands/MakeCommand.php b/app/Console/Commands/MakeCommand.php index 56aebfec49..2106cd7e1a 100644 --- a/app/Console/Commands/MakeCommand.php +++ b/app/Console/Commands/MakeCommand.php @@ -14,8 +14,8 @@ namespace App\Console\Commands; -use Illuminate\Console\Command; use Illuminate\Filesystem\Filesystem; +use Xpressengine\Plugin\Composer\ComposerFileWriter; /** * Abstract Class MakeCommand @@ -27,10 +27,8 @@ * @license http://www.gnu.org/licenses/lgpl-3.0-standalone.html LGPL * @link http://www.xpressengine.com */ -abstract class MakeCommand extends Command +abstract class MakeCommand extends ShouldOperation { - use ComposerRunTrait; - /** * The filesystem instance. * @@ -41,11 +39,12 @@ abstract class MakeCommand extends Command /** * Create a new component creator command instance. * - * @param \Illuminate\Filesystem\Filesystem $files instance + * @param Filesystem $files Filesystem instance + * @param ComposerFileWriter $writer ComposerFileWriter instance */ - public function __construct(Filesystem $files) + public function __construct(Filesystem $files, ComposerFileWriter $writer) { - parent::__construct(); + parent::__construct($writer); $this->files = $files; } @@ -101,11 +100,6 @@ protected function buildFile($file, array $search, array $replace, $to = null) */ protected function runComposerDump($path) { - $inputs = [ - 'command' => 'dump-autoload', - '--working-dir' => $path, - ]; - - return $this->runComposer($inputs, false); + return $this->composerDump($path); } } diff --git a/app/Console/Commands/PluginCommand.php b/app/Console/Commands/PluginCommand.php index 110937cbff..af23e1662c 100644 --- a/app/Console/Commands/PluginCommand.php +++ b/app/Console/Commands/PluginCommand.php @@ -101,52 +101,6 @@ protected function init( // } - /** - * Execute composer update. - * - * @param array $packages specific package name. no need version - * @return int - * @throws \Exception - * @throws \Throwable - */ - protected function composerUpdate(array $packages) - { - if ($this->isLocked()) { - throw new \Exception('The command is locked. Make sure that another process is running.'); - } - - $this->lock(); - - try { - if (0 !== $this->clearCache(true)) { - throw new \Exception('cache clear fail.. check your system.'); - } - - $this->prepareComposer(); - - $inputs = [ - 'command' => 'update', - "--with-dependencies" => true, - //"--quiet" => true, - '--working-dir' => base_path(), - /*'--verbose' => '3',*/ - 'packages' => $packages - ]; - - $this->writeResult($result = $this->runComposer($inputs, false, $this->output)); - - return $result; - } catch (\Exception $e) { - $this->setFailed($e->getCode()); - throw $e; - } catch (\Throwable $e) { - $this->setFailed($e->getCode()); - throw $e; - } finally { - $this->unlock(); - } - } - /** * Run cache clear. * diff --git a/app/Console/Commands/PluginMake.php b/app/Console/Commands/PluginMake.php index abf5c1c7ac..835ad63c4f 100644 --- a/app/Console/Commands/PluginMake.php +++ b/app/Console/Commands/PluginMake.php @@ -14,6 +14,8 @@ namespace App\Console\Commands; +use Illuminate\Filesystem\Filesystem; +use Xpressengine\Plugin\Composer\ComposerFileWriter; use Xpressengine\Plugin\PluginHandler; /** @@ -47,6 +49,27 @@ class PluginMake extends MakeCommand */ protected $description = 'Create a new plugin of XpressEngine'; + /** + * PluginHandler instance. + * + * @var PluginHandler + */ + protected $handler; + + /** + * PluginMake constructor. + * + * @param Filesystem $files Filesystem instance + * @param ComposerFileWriter $writer ComposerFileWriter instance + * @param PluginHandler $handler PluginHandler instance + */ + public function __construct(Filesystem $files, ComposerFileWriter $writer, PluginHandler $handler) + { + parent::__construct($files, $writer); + + $this->handler = $handler; + } + /** * Execute the console command. * @@ -60,14 +83,23 @@ public function handle() $title = $this->getTitleInput($name); - $this->copyStubDirectory($path = plugins_path($name)); - try { - + $this->copyStubDirectory($path = app('path.privates').DIRECTORY_SEPARATOR.$name); $this->makeUsable($path, $name, $namespace, $title); + $this->info('Generate the plugin'); + + $this->writer->reset()->cleanOperation(); + $this->writer->install($packageName = 'xpressengine-plugin/'.$name, '*'); + $this->writer->write(); + + $this->info('Run composer update command'); + $this->line('> composer update'); - // composer update - $this->runComposerDump($path); + $result = $this->composerUpdate([$packageName]); + + if (0 !== $result) { + throw new \Exception('Fail to run composer update'); + } // plugin activate $this->activatePlugin($name); @@ -77,13 +109,8 @@ public function handle() throw $e; } - // print info - $url = trim(config('app.url'), '/').'/'.config('xe.routing.fixedPrefix').'/'.$name; - $this->info("Plugin is created and activated successfully."); - - $this->info("See ./plugins/$name directory. And open $url in your browser."); - + $this->info("See ./plugins/$name directory."); $this->info("Input and modify your plugin information in ./plugins/$name/composer.json file."); } @@ -217,12 +244,10 @@ protected function makeControllerClass($path, $name, $namespace, $title) */ protected function activatePlugin($name) { - /** @var PluginHandler $handler */ - $handler = app('xe.plugin'); - $handler->getAllPlugins(true); + $this->handler->getAllPlugins(true); - if ($handler->isActivated($name) === false) { - $handler->activatePlugin($name); + if (!$this->handler->isActivated($name)) { + $this->handler->activatePlugin($name); } } diff --git a/app/Console/Commands/PrivateUpdateCommand.php b/app/Console/Commands/PrivateUpdateCommand.php new file mode 100644 index 0000000000..c46899412b --- /dev/null +++ b/app/Console/Commands/PrivateUpdateCommand.php @@ -0,0 +1,89 @@ + + * @copyright 2015 Copyright (C) NAVER Corp. + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPL-2.1 + * @link https://xpressengine.io + */ + +namespace App\Console\Commands; + +use Xpressengine\Plugin\PluginHandler; + +/** + * Class PrivateUpdateCommand + * + * @category Commands + * @package App\Console\Commands + * @author XE Developers + * @copyright 2015 Copyright (C) NAVER Corp. + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPL-2.1 + * @link https://xpressengine.io + */ +class PrivateUpdateCommand extends ShouldOperation +{ + /** + * The name and signature of the console command. + * + * @var string + */ + protected $signature = 'private:update {name : The name of the plugin}'; + + /** + * The console command description. + * + * @var string + */ + protected $description = 'Update the private plugin.'; + + /** + * Execute the console command. + * + * @param PluginHandler $handler plugin handler instance + * @return void + * @throws \Exception + */ + public function handle(PluginHandler $handler) + { + if (!$plugin = $handler->getPlugin($name = $this->argument('name'))) { + throw new \Exception("The plugin[$name] is not found."); + } + + if (!$plugin->isPrivate()) { + throw new \Exception("The plugin[$name] is not private plugin"); + } + + if ($activated = $plugin->isActivated()) { + $handler->deactivatePlugin($name); + } + + $this->info('Unlink plugin'); + $this->output->write(' - Unlinking ... '); + unlink($plugin->getPath()); + $this->info('done'); + + $this->writer->reset()->cleanOperation(); + $this->writer->install($packageName = 'xpressengine-plugin/'.$name, '*'); + $this->writer->write(); + + $this->info('Run composer update command'); + $this->line('> composer update'); + $result = $this->composerUpdate([$packageName]); + + if (0 !== $result) { + throw new \Exception('Fail to run composer update'); + } + + if ($activated) { + $handler->activatePlugin($name); + } + + $this->output->success('Plugin is updated.'); + } +} diff --git a/app/Console/Commands/ShouldOperation.php b/app/Console/Commands/ShouldOperation.php index e093a2c740..5f893f0c55 100644 --- a/app/Console/Commands/ShouldOperation.php +++ b/app/Console/Commands/ShouldOperation.php @@ -21,6 +21,7 @@ use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\StreamOutput; +use Symfony\Component\Debug\Exception\FatalThrowableError; use Xpressengine\Installer\XpressengineInstaller; use Xpressengine\Plugin\Composer\ComposerFileWriter; @@ -81,6 +82,71 @@ public function run(InputInterface $input, OutputInterface $output) return parent::run($input, $output); } + /** + * Execute composer update. + * + * @param array $packages specific package name. no need version + * @return int + * @throws \Exception + * @throws \Throwable + */ + protected function composerUpdate(array $packages) + { + if ($this->isLocked()) { + throw new \Exception('The command is locked. Make sure that another process is running.'); + } + + $this->lock(); + + try { + if (0 !== $this->clearCache(true)) { + throw new \Exception('cache clear fail.. check your system.'); + } + + $this->prepareComposer(); + + $inputs = [ + 'command' => 'update', + "--with-dependencies" => true, + //"--quiet" => true, + '--working-dir' => base_path(), + /*'--verbose' => '3',*/ + 'packages' => $packages + ]; + + $this->writeResult($result = $this->runComposer($inputs, false, $this->output)); + + return $result; + } catch (\Exception $e) { + $this->setFailed($e->getCode()); + throw $e; + } catch (\Throwable $e) { + $this->setFailed($e->getCode()); + throw new FatalThrowableError($e); + } finally { + $this->unlock(); + } + } + + /** + * Run composer dump command. + * + * @param string $path working directory + * @return int + * @throws \Exception + */ + protected function composerDump($path) + { + $inputs = [ + 'command' => 'dump-autoload', + '--working-dir' => $path, + ]; + + $this->writeResult($result = $this->runComposer($inputs, false, $this->output)); + + return $result; + } + /** * Run composer * diff --git a/app/Console/Commands/SkinMake.php b/app/Console/Commands/SkinMake.php index f9823be480..e86bcd3e4e 100644 --- a/app/Console/Commands/SkinMake.php +++ b/app/Console/Commands/SkinMake.php @@ -99,13 +99,14 @@ public function handle() try { $this->makeUsable($attr); + $this->info('Generate the skin'); // composer.json 파일 수정 if ($this->registerComponent($plugin, $id, $namespace.'\\'.$className, $file, ['name' => $title, 'description' => $description]) === false) { throw new \Exception('Writing to composer.json file was failed.'); } - $this->runComposerDump($plugin->getPath()); + $this->refresh($plugin); } catch (\Exception $e) { $this->clean($path); throw $e; diff --git a/app/Console/Commands/ThemeMake.php b/app/Console/Commands/ThemeMake.php index 6583aacd88..5c96997af0 100644 --- a/app/Console/Commands/ThemeMake.php +++ b/app/Console/Commands/ThemeMake.php @@ -97,13 +97,14 @@ public function handle() try { $this->makeUsable($attr); + $this->info('Generate the theme'); // composer.json 파일 수정 if ($this->registerComponent($plugin, $id, $namespace.'\\'.$className, $file, ['name' => $title, 'description' => $description]) === false) { throw new \Exception('Writing to composer.json file was failed.'); } - $this->runComposerDump($plugin->getPath()); + $this->refresh($plugin); } catch (\Exception $e) { $this->clean($path); throw $e; diff --git a/app/Console/Commands/XeUpdate.php b/app/Console/Commands/XeUpdate.php index 77ecf83673..667b313024 100644 --- a/app/Console/Commands/XeUpdate.php +++ b/app/Console/Commands/XeUpdate.php @@ -50,13 +50,6 @@ class XeUpdate extends ShouldOperation */ protected $description = 'Update the XpressEngine'; -// /** -// * ComposerFileWriter instance -// * -// * @var ComposerFileWriter -// */ -// protected $writer; - /** * Filesystem instance * @@ -82,7 +75,6 @@ public function __construct(ComposerFileWriter $writer, ReleaseProvider $release { parent::__construct($writer); -// $this->writer = $writer; $this->filesystem = $filesystem; $this->releaseProvider = $releaseProvider; } diff --git a/app/Console/Commands/stubs/plugin/composer.json.stub b/app/Console/Commands/stubs/plugin/composer.json.stub index f4c5764703..fd8b9ada2f 100644 --- a/app/Console/Commands/stubs/plugin/composer.json.stub +++ b/app/Console/Commands/stubs/plugin/composer.json.stub @@ -5,7 +5,7 @@ "xpressengine", "plugin" ], - "license": "LGPL-2.1", + "license": "LGPL-2.1-or-later", "version": "1.0.0", "type": "xpressengine-plugin", "support": { diff --git a/app/Console/Commands/stubs/skin/skin.stub b/app/Console/Commands/stubs/skin/skin.stub index 108f969f6a..73ba50fb68 100644 --- a/app/Console/Commands/stubs/skin/skin.stub +++ b/app/Console/Commands/stubs/skin/skin.stub @@ -2,11 +2,8 @@ namespace DummyNamespace; use Xpressengine\Skin\GenericSkin; -use Xpressengine\Plugin\SupportInfoTrait; class DummyClass extends GenericSkin { - use SupportInfoTrait; - protected static $path = 'DummyPluginId/DummySkinDirname'; } diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 3b707b9ca5..8ef2d613d7 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -61,6 +61,7 @@ class Kernel extends ConsoleKernel Commands\PluginUpdate::class, Commands\PluginUninstall::class, Commands\PluginComposerSync::class, + Commands\PrivateUpdateCommand::class, Commands\ThemeMake::class, Commands\SkinMake::class, Commands\DynamicFieldMake::class, diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index c8595273e6..6ad404223a 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -84,13 +84,6 @@ public function report(Exception $exception) */ public function render($request, Exception $e) { - if ($e instanceof PluginFileNotFoundException) { - $cache = app('cache'); - Event::fire('cache:clearing', ['plugins']); - $cache->store('plugins')->flush(); - Event::fire('cache:cleared', ['plugins']); - } - if (method_exists($e, 'render') && $response = $e->render($request)) { return Router::toResponse($request, $response); } elseif ($e instanceof Responsable) { diff --git a/app/Http/Controllers/PluginController.php b/app/Http/Controllers/PluginController.php index d4b3f3873a..fc45b84089 100644 --- a/app/Http/Controllers/PluginController.php +++ b/app/Http/Controllers/PluginController.php @@ -588,7 +588,7 @@ public function getMakePlugin() * @param Request $request request * @return \Illuminate\Http\RedirectResponse */ - public function makePlugin(Request $request) + public function makePlugin(Request $request, ComposerFileWriter $writer) { $this->validate($request, [ 'name' => 'required|alpha_dash', @@ -607,9 +607,50 @@ public function makePlugin(Request $request) $parameters['--title'] = $title; } - Artisan::call('make:plugin', $parameters); + $logFile = $this->prepareOperation($writer); - return redirect()->back()->with('alert', ['type' => 'success', 'message' => xe_trans('xe::wasCreated')]); + app()->terminating(function () use ($parameters, $logFile) { + Artisan::call('make:plugin', $parameters, new StreamOutput(fopen(storage_path($logFile), 'a'))); + }); + + return redirect()->back()->with('alert', ['type' => 'success', 'message' => xe_trans('xe::startingOperation')]); + } + + /** + * Renew the plugin + * + * @param PluginHandler $handler plugin handler instance + * @param ComposerFileWriter $writer composer writer instance + * @param string $pluginId plugin name + * @return \Illuminate\Http\RedirectResponse + */ + public function renewPlugin(PluginHandler $handler, ComposerFileWriter $writer, $pluginId) + { + if (!$plugin = $handler->getPlugin($pluginId)) { + return back()->with('alert', [ + 'type' => 'danger', + 'message' => xe_trans('xe::pluginNotFound', ['plugin' => $pluginId]) + ]); + } + + if (!$plugin->isPrivate()) { + return back()->with('alert', [ + 'type' => 'danger', + 'message' => xe_trans('xe::pluginUnableToDependenciesRenew', ['name' => $pluginId]) + ]); + } + + $logFile = $this->prepareOperation($writer); + + app()->terminating(function () use ($pluginId, $logFile) { + Artisan::call( + 'private:update', + ['name' => $pluginId], + new StreamOutput(fopen(storage_path($logFile), 'a')) + ); + }); + + return back()->with('alert', ['type' => 'success', 'message' => xe_trans('xe::startingOperation')]); } /** diff --git a/app/Http/Controllers/SafeModeController.php b/app/Http/Controllers/SafeModeController.php index 7ca44e50f9..f7961c216e 100644 --- a/app/Http/Controllers/SafeModeController.php +++ b/app/Http/Controllers/SafeModeController.php @@ -130,7 +130,6 @@ public function dashboard() public function doCacheClear(CacheManager $cache) { $cache->store('file')->flush(); - $cache->store('plugins')->flush(); $cache->store('schema')->flush(); File::cleanDirectory(storage_path('app/interception')); diff --git a/composer.json b/composer.json index 5ba099f306..2e1e7d4046 100644 --- a/composer.json +++ b/composer.json @@ -50,6 +50,10 @@ { "type": "composer", "url": "https://store.xehub.io" + }, + { + "type": "path", + "url": "./privates/*" } ], "autoload": { diff --git a/core/src/Xpressengine/Foundation/Application.php b/core/src/Xpressengine/Foundation/Application.php index 8f65b2a324..5413619b78 100644 --- a/core/src/Xpressengine/Foundation/Application.php +++ b/core/src/Xpressengine/Foundation/Application.php @@ -70,6 +70,16 @@ public function pluginsPath() return $this->basePath.DIRECTORY_SEPARATOR.'plugins'; } + /** + * Get the path to the private plugins directory. + * + * @return string + */ + public function privatesPath() + { + return $this->basePath.DIRECTORY_SEPARATOR.'privates'; + } + /** * Get the path to the proxies directory. * @@ -90,6 +100,7 @@ protected function bindPathsInContainer() parent::bindPathsInContainer(); $this->instance('path.plugins', $this->pluginsPath()); + $this->instance('path.privates', $this->privatesPath()); $this->instance('path.proxies', $this->proxiesPath()); } diff --git a/core/src/Xpressengine/Plugin/AbstractPlugin.php b/core/src/Xpressengine/Plugin/AbstractPlugin.php index 36a575c8e4..6d61ef1697 100644 --- a/core/src/Xpressengine/Plugin/AbstractPlugin.php +++ b/core/src/Xpressengine/Plugin/AbstractPlugin.php @@ -173,8 +173,7 @@ public function getSettingsURI() */ public static function path($path = '') { - $reflector = new ReflectionClass(static::class); - return dirname($reflector->getFileName()).($path ? DIRECTORY_SEPARATOR.$path : $path); + return plugins_path(static::getId().($path ? DIRECTORY_SEPARATOR.$path : $path)); } /** @@ -187,7 +186,8 @@ public static function path($path = '') */ public static function asset($path, $secure = null) { - $path = 'plugins/'.static::getId().'/'.trim($path, '/'); + $path = str_replace(base_path().DIRECTORY_SEPARATOR, '', static::path(trim($path, '/'))); + return asset($path, $secure); } diff --git a/core/src/Xpressengine/Plugin/Composer/Composer.php b/core/src/Xpressengine/Plugin/Composer/Composer.php index 30cd1081fe..9b09e34a5e 100644 --- a/core/src/Xpressengine/Plugin/Composer/Composer.php +++ b/core/src/Xpressengine/Plugin/Composer/Composer.php @@ -214,7 +214,7 @@ public static function postAutoloadDump(Event $event) */ protected static function clearCompiled() { - $application = new Application(getcwd()); + $application = defined('__RUN_IN_ARTISAN__') ? Application::getInstance() : new Application(getcwd()); if (file_exists($packagesPath = $application->getCachedPackagesPath())) { @unlink($packagesPath); diff --git a/core/src/Xpressengine/Plugin/PluginEntity.php b/core/src/Xpressengine/Plugin/PluginEntity.php index c8a0ec8f24..2bcbd59a07 100644 --- a/core/src/Xpressengine/Plugin/PluginEntity.php +++ b/core/src/Xpressengine/Plugin/PluginEntity.php @@ -735,6 +735,18 @@ public static function setCollection($collection) // } + /** + * vendor 디렉토리를 가지고 있는지 판단한다. + * + * @return bool + */ + public function hasVendor() + { + $vendorDir = dirname($this->pluginFile).'/vendor'; + + return file_exists($vendorDir) && is_dir($vendorDir); + } + /** * 플러그인이 composer autoload 파일을 가지고 있을 경우 autoload를 등록한다. * autoload 파일을 각 플러그인 디렉토리 내에 vendor/autoload.php 파일이다. @@ -774,17 +786,23 @@ public function hasAutoload() } /** - * 직접 설치한 플러그인인지 검사한다. vendor 디렉토리를 가지고 있는지의 유무로 판단한다. + * private 으로 설치되었는지 확인. + * + * @return bool + */ + public function isPrivate() + { + return is_link(dirname($this->pluginFile)); + } + + /** + * 직접 설치한 플러그인인지 검사한다. * * @return bool */ public function isSelfInstalled() { - $vendorDir = dirname($this->pluginFile).'/vendor'; - if (file_exists($vendorDir)) { - return true; - } - return false; + return $this->hasVendor() || $this->isPrivate(); } /** diff --git a/core/src/Xpressengine/Plugin/PluginHandler.php b/core/src/Xpressengine/Plugin/PluginHandler.php index 5752d025f6..adf18c47e1 100644 --- a/core/src/Xpressengine/Plugin/PluginHandler.php +++ b/core/src/Xpressengine/Plugin/PluginHandler.php @@ -758,33 +758,8 @@ public function getOperation(ComposerFileWriter $writer) } } - $ids = array_pluck($targets, 'id'); - $changed = $writer->get('xpressengine-plugin.operation.changed', []); - foreach ($changed as $type) { - foreach ($type as $package => $version) { - list(, $id) = explode('/', $package); - if (!in_array($id, $ids)) { - $ids[] = $id; - } - } - } - $failed = $writer->get('xpressengine-plugin.operation.failed', []); - foreach ($failed as $type) { - foreach ($type as $package => $version) { - list(, $id) = explode('/', $package); - if (!in_array($id, $ids)) { - $ids[] = $id; - } - } - } - - $found = $this->provider->findAll($ids); - $infos = []; - foreach ($found as $info) { - $infos[$info->name] = $info; - } if ($status === ComposerFileWriter::STATUS_RUNNING && $expired === true) { $writer->set('xpressengine-plugin.operation.status', ComposerFileWriter::STATUS_EXPIRED); @@ -803,7 +778,7 @@ public function getOperation(ComposerFileWriter $writer) $locked = $writer->get('xpressengine-plugin.lock', false); - return compact('targets', 'status', 'expired', 'changed', 'failed', 'infos', 'log', 'locked'); + return compact('targets', 'status', 'expired', 'changed', 'failed', 'log', 'locked'); } /** diff --git a/core/src/Xpressengine/Skin/GenericSkin.php b/core/src/Xpressengine/Skin/GenericSkin.php index 98c3c05476..aaf00bac39 100644 --- a/core/src/Xpressengine/Skin/GenericSkin.php +++ b/core/src/Xpressengine/Skin/GenericSkin.php @@ -31,11 +31,6 @@ */ abstract class GenericSkin extends AbstractSkin { - /** - * @deprecated not here, use it in the component in the plugin. - * @todo trait 은 plugin 들을 위한 요소 이나 core에서도 사용되었음. - * 클래스간 역할의 정의, 분리가 적절하게 처리되지 못해 개선이 필요. - */ use SupportInfoTrait; /** diff --git a/core/src/Xpressengine/Support/helpers.php b/core/src/Xpressengine/Support/helpers.php index 924ae1299e..88ec7f2087 100644 --- a/core/src/Xpressengine/Support/helpers.php +++ b/core/src/Xpressengine/Support/helpers.php @@ -692,7 +692,7 @@ function df_edit($group, $columnName, $args) if (function_exists('plugins_path') === false) { /** - * @package Xpressengine\Interception + * @package Xpressengine\Plugin * * @param string $path path * diff --git a/core/tests/Plugin/PluginEntityTest.php b/core/tests/Plugin/PluginEntityTest.php index dacecbaa81..c33dfa5b79 100644 --- a/core/tests/Plugin/PluginEntityTest.php +++ b/core/tests/Plugin/PluginEntityTest.php @@ -139,7 +139,6 @@ public function testGetComponentList($entity) public function testGetters($entity) { $this->assertEquals('title',$entity->getTitle()); - $this->assertEquals(__DIR__.'/plugins/plugin_sample',$entity->getPath()); $this->assertEquals('sample plugin.', $entity->getDescription()); $this->assertCount(6, $entity->getSupport()); $this->assertEquals('xe/plugin_sample', $entity->getName()); diff --git a/resources/lang/common.php b/resources/lang/common.php index cc27c7b2f8..eba6185ad8 100644 --- a/resources/lang/common.php +++ b/resources/lang/common.php @@ -3006,4 +3006,20 @@ 'ko' => '상세보기', 'en' => 'View Details', ], + 'dependencies' => [ + 'ko' => '의존성', + 'en' => 'Dependencies', + ], + 'renew' => [ + 'ko' => '갱신', + 'en' => 'Renew', + ], + 'pluginUnableToDependenciesRenew' => [ + 'ko' => ':name 플러그인은 의존성 갱신을 할 수 없습니다.', + 'en' => 'The :name plugin unable to update dependencies.', + ], + 'startingOperation' => [ + 'ko' => '작업이 시작되었습니다.', + 'en' => 'Starting operation.', + ], ]; diff --git a/resources/views/plugin/skins/default/index/item.blade.php b/resources/views/plugin/skins/default/index/item.blade.php index da946d1405..5782093fce 100644 --- a/resources/views/plugin/skins/default/index/item.blade.php +++ b/resources/views/plugin/skins/default/index/item.blade.php @@ -71,5 +71,12 @@ getId(), $handler->getErrors()) ? 'disabled' : '' }}>{{ xe_trans('xe::activation') }} {{ xe_trans('xe::delete') }} @endif + @if($plugin->isPrivate()) +
+ {{ csrf_field() }} + {{ method_field('PUT') }} + +
+ @endif diff --git a/routes/web.php b/routes/web.php index c35dc19e1e..873a4adb41 100644 --- a/routes/web.php +++ b/routes/web.php @@ -800,6 +800,13 @@ function () { 'uses' => 'PluginController@putUpdatePlugin' ] ); + Route::put( + 'renew', + [ + 'as' => 'settings.plugins.renew', + 'uses' => 'PluginController@renewPlugin' + ] + ); //Route::put( // 'download', // [