jqh 5 lat temu
rodzic
commit
6e7a468f49

+ 5 - 4
src/Admin.php

@@ -251,16 +251,15 @@ class Admin
     /**
      * Create a repository instance.
      *
-     * @param string|Repository|Model|Builder $class
+     * @param string|Repository|Model|Builder $value
      * @param array                   $args
      *
      * @return Repository
      */
-    public static function repository($class, array $args = [])
+    public static function repository($repository, array $args = [])
     {
-        $repository = $class;
         if (is_string($repository)) {
-            $repository = new $class($args);
+            $repository = new $repository($args);
         }
 
         if ($repository instanceof Model || $repository instanceof Builder) {
@@ -268,6 +267,8 @@ class Admin
         }
 
         if (! $repository instanceof Repository) {
+            $class = is_object($repository) ? get_class($repository) : $repository;
+
             throw new \InvalidArgumentException("The class [{$class}] must be a type of [".Repository::class.'].');
         }
 

+ 67 - 0
src/Contracts/TreeRepository.php

@@ -0,0 +1,67 @@
+<?php
+/*
+ * This file is part of the dcat-admin.
+ *
+ * (c) jqh <841324345@qq.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace Dcat\Admin\Contracts;
+
+use Dcat\Admin\Form;
+use Dcat\Admin\Grid;
+use Dcat\Admin\Show;
+use Illuminate\Support\Collection;
+
+interface TreeRepository
+{
+    /**
+     * @return string
+     */
+    public function getPrimaryKeyColumn();
+
+    /**
+     * @return string
+     */
+    public function getParentColumn();
+
+    /**
+     * Get title column.
+     *
+     * @return string
+     */
+    public function getTitleColumn();
+
+    /**
+     * Get order column name.
+     *
+     * @return string
+     */
+    public function getOrderColumn();
+
+    /**
+     * Save tree order from a tree like array.
+     *
+     * @param array $tree
+     * @param int   $parentId
+     */
+    public function saveOrder($tree = [], $parentId = 0);
+
+    /**
+     * Set query callback to model.
+     *
+     * @param \Closure|null $query
+     *
+     * @return $this
+     */
+    public function withQuery($queryCallback);
+
+    /**
+     * Format data to tree like array.
+     *
+     * @return array
+     */
+    public function toTree();
+}

+ 3 - 1
src/Grid/Filter/AbstractFilter.php

@@ -553,6 +553,8 @@ abstract class AbstractFilter
             return $this->presenter()->{$method}(...$params);
         }
 
-        throw new \Exception('Method "'.$method.'" not exists.');
+        throw new \BadMethodCallException(sprintf(
+            'Call to undefined method %s::%s()', static::class, $method
+        ));
     }
 }

+ 65 - 1
src/Repositories/EloquentRepository.php

@@ -2,6 +2,7 @@
 
 namespace Dcat\Admin\Repositories;
 
+use Dcat\Admin\Contracts\TreeRepository;
 use Dcat\Admin\Form;
 use Dcat\Admin\Grid;
 use Dcat\Admin\Show;
@@ -15,7 +16,7 @@ use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Str;
 use Spatie\EloquentSortable\Sortable;
 
-class EloquentRepository extends Repository
+class EloquentRepository extends Repository implements TreeRepository
 {
     /**
      * @var string
@@ -390,6 +391,69 @@ class EloquentRepository extends Repository
             ->toArray();
     }
 
+    /**
+     * @return string
+     */
+    public function getParentColumn()
+    {
+        return $this->eloquent()->getParentColumn();
+    }
+
+    /**
+     * Get title column.
+     *
+     * @return string
+     */
+    public function getTitleColumn()
+    {
+        return $this->eloquent()->getTitleColumn();
+    }
+
+    /**
+     * Get order column name.
+     *
+     * @return string
+     */
+    public function getOrderColumn()
+    {
+        return $this->eloquent()->getOrderColumn();
+    }
+
+    /**
+     * Save tree order from a tree like array.
+     *
+     * @param array $tree
+     * @param int   $parentId
+     */
+    public function saveOrder($tree = [], $parentId = 0)
+    {
+        $this->eloquent()->saveOrder($tree, $parentId);
+    }
+
+    /**
+     * Set query callback to model.
+     *
+     * @param \Closure|null $query
+     *
+     * @return $this
+     */
+    public function withQuery($queryCallback)
+    {
+        $this->eloquent()->withQuery($queryCallback);
+
+        return $this;
+    }
+
+    /**
+     * Format data to tree like array.
+     *
+     * @return array
+     */
+    public function toTree()
+    {
+        return $this->eloquent()->toTree();
+    }
+
     /**
      * @return Builder
      */

+ 81 - 9
src/Repositories/Repository.php

@@ -2,13 +2,16 @@
 
 namespace Dcat\Admin\Repositories;
 
+use Dcat\Admin\Contracts\TreeRepository;
 use Dcat\Admin\Form;
 use Dcat\Admin\Grid;
 use Dcat\Admin\Show;
+use Dcat\Admin\Contracts\Repository as RepositoryInterface;
 use Illuminate\Support\Collection;
 use Illuminate\Support\Traits\Macroable;
+use RuntimeException;
 
-abstract class Repository implements \Dcat\Admin\Contracts\Repository
+abstract class Repository implements RepositoryInterface, TreeRepository
 {
     use Macroable;
 
@@ -85,7 +88,7 @@ abstract class Repository implements \Dcat\Admin\Contracts\Repository
      */
     public function get(Grid\Model $model)
     {
-        return [];
+        throw new RuntimeException('This repository does not support "get" method.');
     }
 
     /**
@@ -97,7 +100,7 @@ abstract class Repository implements \Dcat\Admin\Contracts\Repository
      */
     public function edit(Form $form): array
     {
-        return [];
+        throw new RuntimeException('This repository does not support "edit" method.');
     }
 
     /**
@@ -109,7 +112,7 @@ abstract class Repository implements \Dcat\Admin\Contracts\Repository
      */
     public function detail(Show $show): array
     {
-        return [];
+        throw new RuntimeException('This repository does not support "detail" method.');
     }
 
     /**
@@ -121,7 +124,7 @@ abstract class Repository implements \Dcat\Admin\Contracts\Repository
      */
     public function store(Form $form)
     {
-        return false;
+        throw new RuntimeException('This repository does not support "store" method.');
     }
 
     /**
@@ -133,7 +136,7 @@ abstract class Repository implements \Dcat\Admin\Contracts\Repository
      */
     public function getDataWhenUpdating(Form $form): array
     {
-        return [];
+        throw new RuntimeException('This repository does not support "getDataWhenUpdating" method.');
     }
 
     /**
@@ -145,7 +148,7 @@ abstract class Repository implements \Dcat\Admin\Contracts\Repository
      */
     public function update(Form $form)
     {
-        return false;
+        throw new RuntimeException('This repository does not support "update" method.');
     }
 
     /**
@@ -158,7 +161,7 @@ abstract class Repository implements \Dcat\Admin\Contracts\Repository
      */
     public function destroy(Form $form, array $deletingData)
     {
-        return false;
+        throw new RuntimeException('This repository does not support "destroy" method.');
     }
 
     /**
@@ -170,7 +173,76 @@ abstract class Repository implements \Dcat\Admin\Contracts\Repository
      */
     public function getDataWhenDeleting(Form $form): array
     {
-        return [];
+        throw new RuntimeException('This repository does not support "getDataWhenDeleting" method.');
+    }
+
+    /**
+     * @return string
+     */
+    public function getPrimaryKeyColumn()
+    {
+        return $this->getKeyName();
+    }
+
+    /**
+     * @return string
+     */
+    public function getParentColumn()
+    {
+        return 'parent_id';
+    }
+
+    /**
+     * Get title column.
+     *
+     * @return string
+     */
+    public function getTitleColumn()
+    {
+        return 'title';
+    }
+
+    /**
+     * Get order column name.
+     *
+     * @return string
+     */
+    public function getOrderColumn()
+    {
+        return 'order';
+    }
+
+    /**
+     * Save tree order from a tree like array.
+     *
+     * @param array $tree
+     * @param int   $parentId
+     */
+    public function saveOrder($tree = [], $parentId = 0)
+    {
+        throw new RuntimeException('This repository does not support "saveOrder" method.');
+    }
+
+    /**
+     * Set query callback to model.
+     *
+     * @param \Closure|null $query
+     *
+     * @return $this
+     */
+    public function withQuery($queryCallback)
+    {
+        throw new RuntimeException('This repository does not support "withQuery" method.');
+    }
+
+    /**
+     * Format data to tree like array.
+     *
+     * @return array
+     */
+    public function toTree()
+    {
+        throw new RuntimeException('This repository does not support "toTree" method.');
     }
 
     /**

+ 40 - 10
src/Tree.php

@@ -3,11 +3,14 @@
 namespace Dcat\Admin;
 
 use Closure;
+use Dcat\Admin\Contracts\TreeRepository;
+use Dcat\Admin\Repositories\EloquentRepository;
 use Dcat\Admin\Traits\HasBuilderEvents;
 use Dcat\Admin\Tree\AbstractTool;
 use Dcat\Admin\Tree\Tools;
 use Illuminate\Contracts\Support\Htmlable;
 use Illuminate\Contracts\Support\Renderable;
+use Illuminate\Database\Eloquent\Builder;
 use Illuminate\Database\Eloquent\Model;
 use Illuminate\Support\Traits\Macroable;
 
@@ -27,9 +30,9 @@ class Tree implements Renderable
     protected $elementId = 'tree-';
 
     /**
-     * @var Model
+     * @var TreeRepository
      */
-    protected $model;
+    protected $repository;
 
     /**
      * @var \Closure
@@ -126,11 +129,11 @@ class Tree implements Renderable
     /**
      * Menu constructor.
      *
-     * @param Model|null $model
+     * @param Model|TreeRepository|string|null $model
      */
-    public function __construct(Model $model = null, ?\Closure $callback = null)
+    public function __construct($repository = null, ?\Closure $callback = null)
     {
-        $this->model = $model;
+        $this->repository = $this->makeRepository($repository);
         $this->path = $this->path ?: request()->getPathInfo();
         $this->url = url($this->path);
 
@@ -154,6 +157,33 @@ class Tree implements Renderable
         $this->tools = new Tools($this);
     }
 
+    /**
+     * @param $repository
+     *
+     * @return TreeRepository
+     */
+    public function makeRepository($repository)
+    {
+        if (is_string($repository)) {
+            $repository = new $repository();
+        }
+
+        if ($repository instanceof Model || $repository instanceof Builder) {
+            $repository = EloquentRepository::make($repository);
+        }
+
+        if (! $repository instanceof TreeRepository) {
+            $class = get_class($repository);
+
+            throw new \InvalidArgumentException("The class [{$class}] must be a type of [".TreeRepository::class.'].');
+        }
+
+        return $repository;
+    }
+
+    /**
+     * Collect assets.
+     */
     protected function collectAssets()
     {
         Admin::collectComponentAssets('jquery.nestable');
@@ -168,8 +198,8 @@ class Tree implements Renderable
     {
         if (is_null($this->branchCallback)) {
             $this->branchCallback = function ($branch) {
-                $key = $branch[$this->model->getKeyName()];
-                $title = $branch[$this->model->getTitleColumn()];
+                $key = $branch[$this->repository->getPrimaryKeyColumn()];
+                $title = $branch[$this->repository->getTitleColumn()];
 
                 return "$key - $title";
             };
@@ -314,7 +344,7 @@ class Tree implements Renderable
             throw new \InvalidArgumentException(json_last_error_msg());
         }
 
-        $this->model->saveOrder($tree);
+        $this->repository->saveOrder($tree);
 
         return true;
     }
@@ -408,7 +438,7 @@ JS;
      */
     public function getItems()
     {
-        return $this->model->withQuery($this->queryCallback)->toTree();
+        return $this->repository->withQuery($this->queryCallback)->toTree();
     }
 
     /**
@@ -539,7 +569,7 @@ JS;
 
             view()->share([
                 'path'           => $this->url,
-                'keyName'        => $this->model->getKeyName(),
+                'keyName'        => $this->repository->getKeyName(),
                 'branchView'     => $this->view['branch'],
                 'branchCallback' => $this->branchCallback,
             ]);

+ 1 - 1
src/Widgets/Form.php

@@ -557,7 +557,7 @@ HTML;
             return $this->macroCall($method, $arguments);
         }
 
-        throw new \Exception("Field [{$method}] does not exist.");
+        throw new \BadMethodCallException("Field [{$method}] does not exist.");
     }
 
     /**