diff --git a/.gitignore b/.gitignore index 6d538ea9..974885d3 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,3 @@ node_modules/* yarn-error.log _ide_helper.php .phpstorm.meta.php -public/ diff --git a/app/Http/Controllers/MarketController.php b/app/Http/Controllers/MarketController.php index 4c96c626..6f395d9b 100644 --- a/app/Http/Controllers/MarketController.php +++ b/app/Http/Controllers/MarketController.php @@ -121,6 +121,7 @@ class MarketController extends Controller if ($zip->extractTo($plugins_dir) === false) { return json(trans('admin.plugins.market.unzip-failed', ['error' => 'Unable to extract the file.']), 4); } + $manager->copyPluginAssets(plugin($name)); } else { return json(trans('admin.plugins.market.unzip-failed', ['error' => $res]), 4); } diff --git a/app/Http/Controllers/SetupController.php b/app/Http/Controllers/SetupController.php index ac8c11ad..a111036b 100644 --- a/app/Http/Controllers/SetupController.php +++ b/app/Http/Controllers/SetupController.php @@ -41,7 +41,7 @@ class SetupController extends Controller ); } - $content = File::get('.env'); + $content = File::get('..' . DIRECTORY_SEPARATOR . '.env'); $content = str_replace( 'DB_CONNECTION = '.env('DB_CONNECTION'), 'DB_CONNECTION = '.$request->input('type'), @@ -77,7 +77,7 @@ class SetupController extends Controller 'DB_PREFIX = '.$request->input('prefix'), $content ); - File::put('.env', $content); + File::put('..' . DIRECTORY_SEPARATOR . '.env', $content); return redirect('setup/info'); } diff --git a/app/Services/Plugin.php b/app/Services/Plugin.php index 3c7a9a10..1f1d2fed 100644 --- a/app/Services/Plugin.php +++ b/app/Services/Plugin.php @@ -104,7 +104,7 @@ class Plugin implements Arrayable, ArrayAccess public function assets($relativeUri) { - $baseUrl = config('plugins.url') ?: url('plugins'); + $baseUrl = config('plugins.url') ?: url('public/plugins'); return "$baseUrl/{$this->getDirname()}/$relativeUri"; } diff --git a/app/Services/PluginManager.php b/app/Services/PluginManager.php index c15a04bc..f7f97b11 100644 --- a/app/Services/PluginManager.php +++ b/app/Services/PluginManager.php @@ -2,9 +2,11 @@ namespace App\Services; +use Storage; use App\Events; use Composer\Semver\Semver; use Illuminate\Support\Arr; +use Composer\Semver\Comparator; use Illuminate\Support\Collection; use Illuminate\Filesystem\Filesystem; use App\Exceptions\PrettyPageException; @@ -39,6 +41,11 @@ class PluginManager */ protected $plugins; + /** + * @var Collection + */ + protected $enabled; + public function __construct( Application $app, OptionRepository $option, @@ -58,6 +65,7 @@ class PluginManager { if (is_null($this->plugins)) { $plugins = new Collection(); + $enabled = $this->getFullEnabled(); $installed = []; @@ -68,7 +76,7 @@ class PluginManager } // traverse plugins dir - while($filename = @readdir($resource)) { + while ($filename = @readdir($resource)) { if ($filename == '.' || $filename == '..') continue; @@ -106,6 +114,13 @@ class PluginManager } $plugins->put($plugin->name, $plugin); + + if ( + $enabled->has($plugin->name) && + Comparator::notEqualTo($plugin->getVersion(), $enabled->get($plugin->name)) + ) { + $this->copyPluginAssets($plugin); + } } $this->plugins = $plugins->sortBy(function ($plugin, $name) { @@ -134,14 +149,18 @@ class PluginManager */ public function enable($name) { + if (is_null($this->enabled)) { + $this->convertPluginRecord(); + } + if (! $this->isEnabled($name)) { $plugin = $this->getPlugin($name); - $enabled = $this->getEnabled(); - - $enabled[] = $name; - - $this->setEnabled($enabled); + $this->enabled->push([ + 'name' => $name, + 'version' => $plugin->getVersion(), + ]); + $this->saveEnabled(); $plugin->setEnabled(true); @@ -156,17 +175,21 @@ class PluginManager */ public function disable($name) { - $enabled = $this->getEnabled(); + if (is_null($this->enabled)) { + $this->convertPluginRecord(); + } - if (($k = array_search($name, $enabled)) !== false) { - unset($enabled[$k]); + $rejected = $this->enabled->reject(function ($item) use ($name) { + return $item['name'] == $name; + }); + if ($rejected->count() !== $this->enabled->count()) { $plugin = $this->getPlugin($name); - - $this->setEnabled($enabled); - $plugin->setEnabled(false); + $this->enabled = $rejected; + $this->saveEnabled(); + $this->dispatcher->fire(new Events\PluginWasDisabled($plugin)); } } @@ -198,6 +221,10 @@ class PluginManager */ public function getEnabledPlugins() { + if (is_null($this->enabled)) { + $this->convertPluginRecord(); + } + return $this->getPlugins()->only($this->getEnabled()); } @@ -244,19 +271,42 @@ class PluginManager */ public function getEnabled() { - return (array) json_decode($this->option->get('plugins_enabled'), true); + $enabled = collect(json_decode($this->option->get('plugins_enabled'), true)); + + return $enabled->map(function ($item) { + if (is_string($item)) { + return $item; + } else { + return $item['name']; + } + })->values()->toArray(); + } + + /** + * Return enabled plugins with version information. + * + * @return Collection + */ + public function getFullEnabled() + { + $enabled = collect(json_decode($this->option->get('plugins_enabled'), true)); + $ret = collect(); + + $enabled->each(function ($item) use ($ret) { + if (is_array($item)) { + $ret->put($item['name'], $item['version']); + } + }); + + return $ret; } /** * Persist the currently enabled plugins. - * - * @param array $enabled */ - protected function setEnabled(array $enabled) + protected function saveEnabled() { - $enabled = array_values(array_unique($enabled)); - - $this->option->set('plugins_enabled', json_encode($enabled)); + $this->option->set('plugins_enabled', $this->enabled->values()->toJson()); // ensure to save options $this->option->save(); @@ -355,4 +405,49 @@ class PluginManager return config('plugins.directory') ?: base_path('plugins'); } + /** + * Copy plugin assets + * + * @param Plugin $plugin + * + * @return bool + */ + public function copyPluginAssets($plugin) + { + $dir = public_path('plugins/' . $plugin->name . '/assets'); + Storage::deleteDirectory($dir); + + return $this->filesystem->copyDirectory( + $this->getPluginsDir() . DIRECTORY_SEPARATOR . $plugin->name . DIRECTORY_SEPARATOR . 'assets', + $dir + ); + } + + /** + * Convert `plugins_enabled` field for backward compatibility. + * + * @return $this + */ + protected function convertPluginRecord() + { + $list = collect(json_decode($this->option->get('plugins_enabled'), true)); + $this->enabled = $list->map(function ($item) { + if (is_string($item)) { + $plugin = $this->getPlugin($item); + return [ + 'name' => $item, + 'version' => $plugin->getVersion(), + ]; + } else { + $plugin = $this->getPlugin($item['name']); + $item['version'] = $plugin->getVersion(); + return $item; + } + }); + + $this->saveEnabled(); + + return $this; + } + } diff --git a/app/helpers.php b/app/helpers.php index a7d9e0ac..7293465c 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -57,7 +57,7 @@ if (! function_exists('webpack_assets')) { if (app()->environment('development')) { return "http://127.0.0.1:8080/public/$relativeUri"; } else { - return url("public/$relativeUri"); + return url("app/$relativeUri"); } } } diff --git a/bootstrap/chkenv.php b/bootstrap/chkenv.php index 9d3e9842..1e894040 100644 --- a/bootstrap/chkenv.php +++ b/bootstrap/chkenv.php @@ -60,8 +60,8 @@ } } - $autoload = file_get_contents('vendor/autoload.php'); + $autoload = file_get_contents(__DIR__ . '/../vendor/autoload.php'); $lines = explode("\n", $autoload); $lines[1] = '$GLOBALS["env_checked"] = true;'; - file_put_contents('vendor/autoload.php', implode("\n", $lines)); + file_put_contents(__DIR__ . '/../vendor/autoload.php', implode("\n", $lines)); })(); diff --git a/config/options.php b/config/options.php index 544deaad..83031f1e 100644 --- a/config/options.php +++ b/config/options.php @@ -12,7 +12,7 @@ return [ 'api_type' => 'false', 'announcement' => 'Welcome to Blessing Skin {version}!', 'color_scheme' => 'skin-blue', - 'home_pic_url' => './public/bg.jpg', + 'home_pic_url' => './app/bg.jpg', 'custom_css' => '', 'custom_js' => '', 'player_name_rule' => 'official', @@ -42,5 +42,5 @@ return [ 'plugins_enabled' => '', 'copyright_prefer' => '0', 'score_per_closet_item' => '0', - 'favicon_url' => 'public/favicon.ico' + 'favicon_url' => 'app/favicon.ico' ]; diff --git a/package.json b/package.json index 2c0a9131..ffed284b 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "private": true, "scripts": { "dev": "webpack-serve", - "build": "rimraf public && node scripts/build", + "build": "rimraf public/app && node scripts/build", "lint": "eslint --ext=.js,.vue -f=beauty .", "test": "jest", "codecov": "codecov -F js", diff --git a/public/.gitignore b/public/.gitignore new file mode 100644 index 00000000..908f7bbc --- /dev/null +++ b/public/.gitignore @@ -0,0 +1 @@ +app/ diff --git a/.htaccess b/public/.htaccess similarity index 100% rename from .htaccess rename to public/.htaccess diff --git a/index.php b/public/index.php similarity index 52% rename from index.php rename to public/index.php index 812d3d5d..3ce6981e 100755 --- a/index.php +++ b/public/index.php @@ -9,9 +9,9 @@ @ini_set('display_errors', 'on'); -require __DIR__.'/bootstrap/autoload.php'; +require __DIR__.'/../bootstrap/autoload.php'; -if (!isset($GLOBALS['env_checked'])) require __DIR__.'/bootstrap/chkenv.php'; +if (!isset($GLOBALS['env_checked'])) require __DIR__.'/../bootstrap/chkenv.php'; // Process the request -require __DIR__.'/bootstrap/kernel.php'; +require __DIR__.'/../bootstrap/kernel.php'; diff --git a/public/plugins/.gitignore b/public/plugins/.gitignore new file mode 100644 index 00000000..d6b7ef32 --- /dev/null +++ b/public/plugins/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/resources/assets/src/js/public-path.js b/resources/assets/src/js/public-path.js index a8fe193c..67899254 100644 --- a/resources/assets/src/js/public-path.js +++ b/resources/assets/src/js/public-path.js @@ -1,4 +1,4 @@ // eslint-disable-next-line no-undef __webpack_public_path__ = process.env.NODE_ENV === 'development' - ? 'http://127.0.0.1:8080/public/' - : blessing.base_url + '/public/'; + ? 'http://127.0.0.1:8080/' + : blessing.base_url + '/app/'; diff --git a/resources/views/common/dependencies/script.blade.php b/resources/views/common/dependencies/script.blade.php index b763ebf9..d6b4c999 100644 --- a/resources/views/common/dependencies/script.blade.php +++ b/resources/views/common/dependencies/script.blade.php @@ -1,10 +1,10 @@ -@if (file_exists(public_path($path = 'langs/'.config('app.locale').'.js'))) - +@if (file_exists(public_path($path = 'app/langs/'.config('app.locale').'.js'))) + @if (file_exists(resource_path($path = 'lang/overrides/'.config('app.locale').'/locale.js'))) @endif @else - + @if (file_exists(resource_path($path = 'lang/overrides/'.config('app.fallback_locale').'/locale.js'))) @endif diff --git a/resources/views/setup/master.blade.php b/resources/views/setup/master.blade.php index 801d5997..de36739b 100644 --- a/resources/views/setup/master.blade.php +++ b/resources/views/setup/master.blade.php @@ -5,7 +5,7 @@