'required',
'path' => 'required',
'icon' => 'required',
];
/**
* @var array
*/
protected $permissionValidationRules = [
'name' => 'required',
'slug' => 'required',
'path' => 'required',
];
/**
* @var \Symfony\Component\Console\Output\OutputInterface
*/
public $output;
public function __construct($app)
{
parent::__construct($app);
$this->output = new NullOutput();
}
/**
* {@inheritdoc}
*/
public function boot()
{
if ($views = $this->getViewPath()) {
$this->loadViewsFrom($views, $this->getName());
}
if ($lang = $this->getLangPath()) {
$this->loadTranslationsFrom($lang, $this->getName());
}
if ($routes = $this->getRoutes()) {
return $this->registerRoutes($routes);
}
$this->registerAssets();
}
/**
* 获取扩展名称.
*
* @return string
*/
final public function getName()
{
return $this->name ?: ($this->name = str_replace('/', '.', $this->composerProperty->name));
}
/**
* 获取扩展包路径.
*
* @param string $path
*
* @return string
*
* @throws \ReflectionException
*/
public function path(?string $path = null)
{
if (! $this->path) {
$this->path = realpath(dirname((new \ReflectionClass(static::class))->getFileName()).'/..');
if (! is_dir($this->path)) {
throw new RuntimeException("The {$this->path} is not a directory.");
}
}
$path = ltrim($path, '/');
return $path ? $this->path.'/'.$path : $this->path;
}
/**
* 判断扩展是否启用.
*
* @return bool
*/
final public function enabled()
{
return Admin::extension()->enabled($this->getName());
}
/**
* 判断扩展是否禁用.
*
* @return bool
*/
final public function disabled()
{
return ! $this->enabled();
}
/**
* 获取配置.
*
* @param string $key
* @param null $default
*
* @return \Illuminate\Config\Repository|mixed
*/
final public function config($key = null, $default = null)
{
return Admin::setting()->get($this->name);
}
/**
* 导入扩展.
*/
public function import()
{
$this->importMenus();
$this->importPermissions();
}
/**
* 卸载扩展.
*/
public function uninstall()
{
}
/**
* 注册路由.
*
* @param $callback
*/
public function registerRoutes($callback)
{
Admin::app()->routes(function ($router) use ($callback) {
$attributes = array_merge(
[
'prefix' => config('admin.route.prefix'),
'middleware' => config('admin.route.middleware'),
]
);
$router->group($attributes, $callback);
});
}
/**
* 获取静态资源路径.
*
* @return string
*/
final public function getAssetPath()
{
return $this->path('resources/assets');
}
/**
* 获取视图路径.
*
* @return string
*/
final public function getViewPath()
{
return $this->path('resources/views');
}
/**
* 获取语言包路径.
*
* @return string
*/
final public function getLangPath()
{
return $this->path('resources/lang');
}
/**
* 获取路由地址.
*
* @return string
*
* @throws \ReflectionException
*/
final public function getRoutes()
{
$path = $this->path('src/Http/routes.php');
return is_file($path) ? $path : null;
}
/**
* 获取菜单.
*
* @return array
*/
protected function menu()
{
return $this->menu;
}
/**
* @return array
*/
protected function permission()
{
return $this->permission;
}
/**
* @param ComposerProperty $composerProperty
*
* @return $this
*/
public function withComposerProperty(ComposerProperty $composerProperty)
{
$this->composerProperty = $composerProperty;
return $this;
}
/**
* 导入菜单.
*
* @throws \Exception
*/
protected function importMenus()
{
if (! ($menu = $this->menu()) || ! $this->validateMenu($menu)) {
return;
}
extract($menu);
if ($this->checkMenu($path)) {
$this->output->writeln("Menu [$path] already exists!");
} else {
$this->createMenu($title, $path, $icon);
$this->output->writeln('Import extension menu succeeded!');
}
}
/**
* 导入权限.
*
* @throws \Exception
*/
protected function importPermissions()
{
if (! $this->config('admin.permission.enable')) {
return;
}
if (! ($permission = $this->permission()) || ! $this->validatePermission($permission)) {
return;
}
extract($permission);
if ($this->checkPermission($slug)) {
$this->output->writeln("Permission [$slug] already exists!");
} else {
$this->createPermission($name, $slug, $path);
$this->output->writeln('Import extension permission succeeded!');
}
}
/**
* 注册别名.
*/
protected function registerAssets()
{
if ($this->js || $this->css) {
Admin::asset()->alias($this->getName(), $this->js, $this->css);
}
}
/**
* 验证菜单.
*
* @param array $menu
*
* @throws \Exception
*
* @return bool
*/
protected 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()));
$this->output->writeln("{$message}");
}
/**
* @param $path
*
* @return bool
*/
protected function checkMenu($path)
{
$menuModel = config('admin.database.menu_model');
return $result = $menuModel::where('uri', $path)->exists();
}
/**
* 验证权限.
*
* @param array $permission
*
* @throws \Exception
*
* @return bool
*/
protected 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()));
$this->output->writeln("{$message}");
}
/**
* 创建菜单.
*
* @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 checkPermission($slug)
{
$permissionModel = config('admin.database.permissions_model');
return $permissionModel::where('slug', $slug)->exists();
}
/**
* 创建权限.
*
* @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, '/'),
]);
}
}