Browse Source

extension

jqh 4 years ago
parent
commit
2dc9705299

+ 37 - 0
database/migrations/2020_09_07_090635_create_admin_settings_table.php

@@ -0,0 +1,37 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateAdminSettingsTable extends Migration
+{
+    public function getConnection()
+    {
+        return config('database.connection') ?: config('database.default');
+    }
+
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('admin_settings', function (Blueprint $table) {
+            $table->string('slug', 100)->primary();
+            $table->text('value');
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('admin_settings');
+    }
+}

+ 21 - 92
src/Admin.php

@@ -10,6 +10,7 @@ use Dcat\Admin\Layout\Menu;
 use Dcat\Admin\Layout\Navbar;
 use Dcat\Admin\Layout\SectionManager;
 use Dcat\Admin\Repositories\EloquentRepository;
+use Dcat\Admin\Support\Composer;
 use Dcat\Admin\Support\Helper;
 use Dcat\Admin\Traits\HasAssets;
 use Dcat\Admin\Traits\HasPermissions;
@@ -36,16 +37,6 @@ class Admin
      */
     const VERSION = '1.7.1';
 
-    /**
-     * @var array
-     */
-    protected static $extensions = [];
-
-    /**
-     * @var array
-     */
-    protected static $availableExtensions;
-
     /**
      * @var string
      */
@@ -320,88 +311,6 @@ class Admin
         return app('admin.app');
     }
 
-    /**
-     * 获取所有已注册的扩展.
-     *
-     * @return array
-     */
-    public static function extensions()
-    {
-        return static::$extensions;
-    }
-
-    /**
-     * 获取所有可用扩展.
-     *
-     * @return Extension[]
-     */
-    public static function availableExtensions()
-    {
-        if (static::$availableExtensions !== null) {
-            return static::$availableExtensions;
-        }
-
-        static::$availableExtensions = [];
-        foreach (static::$extensions as $k => $extension) {
-            if (! config("admin-extensions.{$k}.enable")) {
-                continue;
-            }
-
-            static::$availableExtensions[$k] = $extension::make();
-        }
-
-        return static::$availableExtensions;
-    }
-
-    /**
-     * 注册扩展.
-     *
-     * @param string $class
-     *
-     * @return void
-     */
-    public static function extend(string $class)
-    {
-        static::$extensions[$class::NAME] = $class;
-    }
-
-    /**
-     * 启用扩展.
-     *
-     * @param string $class
-     * @param bool   $enable
-     *
-     * @return bool
-     */
-    public static function enableExtenstion(string $class, bool $enable = true)
-    {
-        if (! $class || ! is_subclass_of($class, Extension::class)) {
-            return false;
-        }
-
-        $name = $class::NAME;
-
-        $config = (array) config('admin-extensions');
-
-        $config[$name] = (array) ($config[$name] ?? []);
-
-        $config[$name]['enable'] = $enable;
-
-        return Helper::updateExtensionConfig($config);
-    }
-
-    /**
-     * 禁用扩展.
-     *
-     * @param string $class
-     *
-     * @return bool
-     */
-    public static function disableExtenstion(string $class)
-    {
-        return static::enableExtenstion($class, false);
-    }
-
     /**
      * @return Handler
      */
@@ -474,6 +383,26 @@ class Admin
         return static::context()->ignoreQueries ?? [];
     }
 
+    /**
+     * 插件管理.
+     *
+     * @return \Dcat\Admin\Extend\Manager
+     */
+    public static function extensions()
+    {
+        return app('admin.extend');
+    }
+
+    /**
+     * 类自动加载器.
+     *
+     * @return \Composer\Autoload\ClassLoader
+     */
+    public static function classLoader()
+    {
+        return Composer::loader();
+    }
+
     /**
      * 获取js配置.
      *

+ 8 - 13
src/AdminServiceProvider.php

@@ -7,6 +7,7 @@ use Dcat\Admin\Layout\Content;
 use Dcat\Admin\Layout\Menu;
 use Dcat\Admin\Layout\Navbar;
 use Dcat\Admin\Layout\SectionManager;
+use Dcat\Admin\Extend\Manager;
 use Dcat\Admin\Support\WebUploader;
 use Illuminate\Support\Arr;
 use Illuminate\Support\Facades\Blade;
@@ -87,10 +88,10 @@ class AdminServiceProvider extends ServiceProvider
         require_once __DIR__.'/Support/AdminSection.php';
 
         $this->aliasAdmin();
-        $this->registerExtensionProviders();
         $this->loadAdminAuthConfig();
         $this->registerRouteMiddleware();
         $this->registerServices();
+        $this->loadExtensions();
 
         $this->commands($this->commands);
 
@@ -160,18 +161,6 @@ class AdminServiceProvider extends ServiceProvider
         }
     }
 
-    /**
-     * 扩展注册.
-     */
-    public function registerExtensionProviders()
-    {
-        foreach (Admin::availableExtensions() as $extension) {
-            if ($provider = $extension->serviceProvider()) {
-                $this->app->register($provider);
-            }
-        }
-    }
-
     /**
      * 设置 auth 配置.
      *
@@ -217,12 +206,18 @@ class AdminServiceProvider extends ServiceProvider
         $this->app->singleton('admin.asset', Asset::class);
         $this->app->singleton('admin.color', Color::class);
         $this->app->singleton('admin.sections', SectionManager::class);
+        $this->app->singleton('admin.extend', Manager::class);
         $this->app->singleton('admin.navbar', Navbar::class);
         $this->app->singleton('admin.menu', Menu::class);
         $this->app->singleton('admin.context', Fluent::class);
         $this->app->singleton('admin.web-uploader', WebUploader::class);
     }
 
+    protected function loadExtensions()
+    {
+        Admin::extensions()->load();
+    }
+
     /**
      * 路由中间件注册.
      *

+ 31 - 0
src/Extend/Manager.php

@@ -0,0 +1,31 @@
+<?php
+
+namespace Dcat\Admin\Extend;
+
+class Manager
+{
+    /**
+     * 加载扩展,注册自动加载规则.
+     *
+     * @return void
+     */
+    public function load()
+    {
+    }
+
+    /**
+     * 注册扩展.
+     *
+     * @return void
+     */
+    public function register()
+    {
+    }
+
+    /**
+     * @return array
+     */
+    public function getPluginNamespaces()
+    {
+    }
+}

+ 353 - 0
src/Extend/ServiceProvider.php

@@ -0,0 +1,353 @@
+<?php
+
+namespace Dcat\Admin\Plugin;
+
+use Dcat\Admin\Admin;
+use Illuminate\Console\Command;
+use Illuminate\Support\Arr;
+use Illuminate\Support\Facades\Validator;
+use Illuminate\Support\ServiceProvider as LaravelServiceProvider;
+
+abstract class ServiceProvider extends LaravelServiceProvider
+{
+    const NAME = null;
+
+    /**
+     * @var string
+     */
+    protected $assets = '';
+
+    /**
+     * @var string
+     */
+    protected $views = '';
+
+    /**
+     * @var string
+     */
+    protected $lang = '';
+
+    /**
+     * @var string
+     */
+    protected $migrations = '';
+
+    /**
+     * @var array
+     */
+    protected $menu = [];
+
+    /**
+     * @var array
+     */
+    protected $permission = [];
+
+    /**
+     * The menu validation rules.
+     *
+     * @var array
+     */
+    protected $menuValidationRules = [
+        'title' => 'required',
+        'path'  => 'required',
+        'icon'  => 'required',
+    ];
+
+    /**
+     * The permission validation rules.
+     *
+     * @var array
+     */
+    protected $permissionValidationRules = [
+        'name'  => 'required',
+        'slug'  => 'required',
+        'path'  => 'required',
+    ];
+
+    /**
+     * @return string
+     */
+    final public function getName()
+    {
+        return static::NAME;
+    }
+
+    /**
+     * Get the path of assets files.
+     *
+     * @return string
+     */
+    public function assets()
+    {
+        return $this->assets;
+    }
+
+    /**
+     * Get the path of view files.
+     *
+     * @return string
+     */
+    public function views()
+    {
+        return $this->views;
+    }
+
+    /**
+     * Get the path of migration files.
+     *
+     * @return string
+     */
+    public function migrations()
+    {
+        return $this->migrations;
+    }
+
+    /**
+     * @return array
+     */
+    public function menu()
+    {
+        return $this->menu;
+    }
+
+    /**
+     * @return array
+     */
+    public function permission()
+    {
+        return $this->permission;
+    }
+
+    /**
+     * @return string
+     */
+    public function lang()
+    {
+        return $this->lang;
+    }
+
+    /**
+     * Whether the extension is enabled.
+     *
+     * @return bool
+     */
+    final public static function enabled()
+    {
+        return config('admin-extensions.'.static::NAME.'.enable') ? true : false;
+    }
+
+    /**
+     * Whether the extension is disabled.
+     *
+     * @return bool
+     */
+    final public static function disable()
+    {
+        return ! static::enabled();
+    }
+
+    /**
+     * Get config set in config/admin.php.
+     *
+     * @param string $key
+     * @param null   $default
+     *
+     * @return \Illuminate\Config\Repository|mixed
+     */
+    final public function config($key = null, $default = null)
+    {
+        if (is_null($key)) {
+            $key = sprintf('admin.extensions.%s', static::NAME);
+        } else {
+            $key = sprintf('admin.extensions.%s.%s', static::NAME, $key);
+        }
+
+        return config($key, $default);
+    }
+
+    /**
+     * Import menu item and permission to dcat-admin.
+     */
+    public function import(Command $command)
+    {
+        if ($menu = $this->menu()) {
+            if ($this->validateMenu($menu)) {
+                extract($menu);
+
+                if ($this->checkMenuExist($path)) {
+                    $command->warn("Menu [$path] already exists!");
+                } else {
+                    $this->createMenu($title, $path, $icon);
+                    $command->info('Import extension menu succeeded!');
+                }
+            }
+        }
+
+        if ($permission = $this->permission()) {
+            if ($this->validatePermission($permission)) {
+                extract($permission);
+
+                if ($this->checkPermissionExist($slug)) {
+                    $command->warn("Permission [$slug] already exists!");
+                } else {
+                    $this->createPermission($name, $slug, $path);
+                    $command->info('Import extension permission succeeded!');
+                }
+            }
+        }
+    }
+
+    /**
+     * Uninstall the extension.
+     *
+     * @param Command $command
+     */
+    public function uninstall(Command $command)
+    {
+    }
+
+    /**
+     * Validate menu fields.
+     *
+     * @param array $menu
+     *
+     * @throws \Exception
+     *
+     * @return bool
+     */
+    public function validateMenu(array $menu)
+    {
+        /** @var \Illuminate\Validation\Validator $validator */
+        $validator = Validator::make($menu, $this->menuValidationRules);
+
+        if ($validator->passes()) {
+            return true;
+        }
+
+        $message = "Invalid menu:\r\n".implode("\r\n", Arr::flatten($validator->errors()->messages()));
+
+        throw new \Exception($message);
+    }
+
+    /**
+     * @param $path
+     *
+     * @return bool
+     */
+    protected function checkMenuExist($path)
+    {
+        $menuModel = config('admin.database.menu_model');
+
+        /* @var \Illuminate\Database\Eloquent\Builder $query */
+        $query = $menuModel::query();
+
+        $result = $query->where('uri', $path)
+            ->get()
+            ->first();
+
+        return $result ? true : false;
+    }
+
+    /**
+     * Validate permission fields.
+     *
+     * @param array $permission
+     *
+     * @throws \Exception
+     *
+     * @return bool
+     */
+    public function validatePermission(array $permission)
+    {
+        /** @var \Illuminate\Validation\Validator $validator */
+        $validator = Validator::make($permission, $this->permissionValidationRules);
+
+        if ($validator->passes()) {
+            return true;
+        }
+
+        $message = "Invalid permission:\r\n".implode("\r\n", Arr::flatten($validator->errors()->messages()));
+
+        throw new \Exception($message);
+    }
+
+    /**
+     * Create a item in dcat-admin left side menu.
+     *
+     * @param string $title
+     * @param string $uri
+     * @param string $icon
+     * @param int    $parentId
+     */
+    protected function createMenu($title, $uri, $icon = 'fa-bars', $parentId = 0)
+    {
+        $menuModel = config('admin.database.menu_model');
+
+        $lastOrder = $menuModel::max('order');
+
+        $menuModel::create([
+            'parent_id' => $parentId,
+            'order'     => $lastOrder + 1,
+            'title'     => $title,
+            'icon'      => $icon,
+            'uri'       => $uri,
+        ]);
+    }
+
+    /**
+     * @param $slug
+     *
+     * @return bool
+     */
+    protected function checkPermissionExist($slug)
+    {
+        $permissionModel = config('admin.database.permissions_model');
+
+        /* @var \Illuminate\Database\Eloquent\Builder $query */
+        $query = $permissionModel::query();
+
+        $result = $query->where('slug', $slug)
+            ->get()
+            ->first();
+
+        return $result ? true : false;
+    }
+
+    /**
+     * Create a permission for this extension.
+     *
+     * @param $name
+     * @param $slug
+     * @param $path
+     */
+    protected function createPermission($name, $slug, $path)
+    {
+        $permissionModel = config('admin.database.permissions_model');
+
+        $permissionModel::create([
+            'name'      => $name,
+            'slug'      => $slug,
+            'http_path' => '/'.trim($path, '/'),
+        ]);
+    }
+
+    /**
+     * Set routes for this extension.
+     *
+     * @param $callback
+     */
+    public function routes($callback)
+    {
+        Admin::app()->routes(function ($router) use ($callback) {
+            $attributes = array_merge(
+                [
+                    'prefix'     => config('admin.route.prefix'),
+                    'middleware' => config('admin.route.middleware'),
+                ],
+                $this->config('route', [])
+            );
+
+            $router->group($attributes, $callback);
+        });
+    }
+}

+ 3 - 0
src/Extend/UpdateManager.php

@@ -0,0 +1,3 @@
+<?php
+
+//namespace

+ 7 - 0
src/Extend/VersionManager.php

@@ -0,0 +1,7 @@
+<?php
+
+namespace Dcat\Admin\Extend;
+
+class VersionManager
+{
+}

+ 21 - 0
src/Support/Composer.php

@@ -2,6 +2,8 @@
 
 namespace Dcat\Admin\Support;
 
+use Composer\Autoload\ClassLoader;
+
 class Composer
 {
     /**
@@ -9,6 +11,25 @@ class Composer
      */
     protected static $files = [];
 
+    /**
+     * @var ClassLoader
+     */
+    protected static $loader;
+
+    /**
+     * 获取 composer 类加载器.
+     *
+     * @return ClassLoader
+     */
+    public static function loader()
+    {
+        if (! static::$loader) {
+            static::$loader = include base_path().'/vendor/autoload.php';
+        }
+
+        return static::$loader;
+    }
+
     /**
      * @param $path
      *

+ 7 - 0
src/Support/helpers.php

@@ -395,3 +395,10 @@ if (! function_exists('admin_api_route')) {
         return Dcat\Admin\Admin::app()->getCurrentApiRoutePrefix().$path;
     }
 }
+
+if (! function_exists('admin_plugins_path')) {
+    function admin_plugins_path()
+    {
+        return admin_path('/Plugins');
+    }
+}