jingcai-php/vendor/dcat/laravel-admin/src/Show.php

712 lines
14 KiB
PHP
Executable File

<?php
namespace Dcat\Admin;
use Closure;
use Dcat\Admin\Contracts\Repository;
use Dcat\Admin\Show\AbstractTool;
use Dcat\Admin\Show\Divider;
use Dcat\Admin\Show\Field;
use Dcat\Admin\Show\Html;
use Dcat\Admin\Show\Newline;
use Dcat\Admin\Show\Panel;
use Dcat\Admin\Show\Relation;
use Dcat\Admin\Show\Row;
use Dcat\Admin\Show\Tools;
use Dcat\Admin\Traits\HasBuilderEvents;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\Support\Htmlable;
use Illuminate\Contracts\Support\Renderable;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Fluent;
use Illuminate\Support\Traits\Macroable;
class Show implements Renderable
{
use HasBuilderEvents;
use Macroable {
__call as macroCall;
}
/**
* @var string
*/
protected $view = 'admin::show.container';
/**
* @var Repository
*/
protected $repository;
/**
* @var mixed
*/
protected $_id;
/**
* @var string
*/
protected $keyName = 'id';
/**
* @var Fluent
*/
protected $model;
/**
* Show panel builder.
*
* @var callable
*/
protected $builder;
/**
* Resource path for this show page.
*
* @var string
*/
protected $resource;
/**
* Fields to be show.
*
* @var Collection
*/
protected $fields;
/**
* Relations to be show.
*
* @var Collection
*/
protected $relations;
/**
* @var Panel
*/
protected $panel;
/**
* @var \Illuminate\Support\Collection
*/
protected $rows;
/**
* Show constructor.
*
* @param mixed $id $id
* @param Model|Builder|Repository|array|Arrayable $model
* @param \Closure $builder
*/
public function __construct($id = null, $model = null, ?\Closure $builder = null)
{
switch (func_num_args()) {
case 1:
case 2:
if (is_scalar($id)) {
$this->setKey($id);
} else {
$builder = $model;
$model = $id;
}
break;
default:
$this->setKey($id);
}
$this->rows = new Collection();
$this->builder = $builder;
$this->initModel($model);
$this->initPanel();
$this->initContents();
$this->callResolving();
}
protected function initModel($model)
{
if ($model instanceof Repository || $model instanceof Builder) {
$this->repository = Admin::repository($model);
} elseif ($model instanceof Model) {
if ($key = $model->getKey()) {
$this->setKey($key);
$this->setKeyName($model->getKeyName());
$this->model($model);
} else {
$this->repository = Admin::repository($model);
}
} elseif ($model instanceof Arrayable) {
$this->model(new Fluent($model->toArray()));
} elseif (is_array($model)) {
$this->model(new Fluent($model));
} else {
$this->model(new Fluent());
}
if (! $this->model && $this->repository) {
$this->model($this->repository->detail($this));
}
}
/**
* Create a show instance.
*
* @param mixed ...$params
* @return $this
*/
public static function make(...$params)
{
return new static(...$params);
}
/**
* @param string $value
* @return $this
*/
public function setKeyName(string $value)
{
$this->keyName = $value;
return $this;
}
/**
* Get primary key name of model.
*
* @return string
*/
public function getKeyName()
{
if (! $this->repository) {
return $this->keyName;
}
return $this->keyName ?: $this->repository->getKeyName();
}
/**
* @param mixed $id
* @return mixed
*/
public function setKey($id)
{
$this->_id = $id;
return $this;
}
/**
* @return mixed
*/
public function getKey()
{
return $this->_id;
}
/**
* @param Fluent|\Illuminate\Database\Eloquent\Model|null $model
* @return Fluent|$this|\Illuminate\Database\Eloquent\Model
*/
public function model($model = null)
{
if ($model === null) {
return $this->model;
}
if (is_array($model)) {
$model = new Fluent($model);
}
$this->model = $model;
return $this;
}
/**
* Set a view to render.
*
* @param string $view
* @return $this
*/
public function view($view)
{
$this->panel->view($view);
return $this;
}
/**
* Add variables to show view.
*
* @param array $variables
* @return $this
*/
public function with($variables = [])
{
$this->panel->with($variables);
return $this;
}
/**
* @return $this
*/
public function wrap(\Closure $wrapper)
{
$this->panel->wrap($wrapper);
return $this;
}
/**
* Initialize the contents to show.
*/
protected function initContents()
{
$this->fields = new Collection();
$this->relations = new Collection();
}
/**
* Initialize panel.
*/
protected function initPanel()
{
$this->panel = new Panel($this);
}
/**
* Get panel instance.
*
* @return Panel
*/
public function panel()
{
return $this->panel;
}
/**
* @param \Closure|array|AbstractTool|Renderable|Htmlable|string $callback
* @return $this|Tools
*/
public function tools($callback = null)
{
if ($callback === null) {
return $this->panel->tools();
}
if ($callback instanceof \Closure) {
$callback->call($this->model, $this->panel->tools());
return $this;
}
if (! is_array($callback)) {
$callback = [$callback];
}
foreach ($callback as $tool) {
$this->panel->tools()->append($tool);
}
return $this;
}
/**
* Add a model field to show.
*
* @param string $name
* @param string $label
* @return Field
*/
public function field($name, $label = '')
{
return $this->addField($name, $label);
}
/**
* Get fields or add multiple fields.
*
* @param array $fields
* @return $this|Collection
*/
public function fields(array $fields = null)
{
if ($fields === null) {
return $this->fields;
}
if (! Arr::isAssoc($fields)) {
$fields = array_combine($fields, $fields);
}
foreach ($fields as $field => $label) {
$this->field($field, $label);
}
return $this;
}
/**
* @return Collection
*/
public function relations()
{
return $this->relations;
}
/**
* Show all fields.
*
* @return Show
*/
public function all()
{
$fields = array_keys($this->model()->toArray());
return $this->fields($fields);
}
/**
* Add a relation to show.
*
* @param string $name
* @param string|\Closure $label
* @param null|\Closure $builder
* @return Relation
*/
public function relation($name, $label, $builder = null)
{
if (is_null($builder)) {
$builder = $label;
$label = '';
}
return $this->addRelation($name, $builder, $label);
}
/**
* Add a model field to show.
*
* @param string $name
* @param string $label
* @return Field
*/
protected function addField($name, $label = '')
{
$field = new Field($name, $label);
$field->setParent($this);
$this->overwriteExistingField($name);
$this->fields->push($field);
return $field;
}
/**
* Add a relation panel to show.
*
* @param string $name
* @param \Closure $builder
* @param string $label
* @return Relation
*/
protected function addRelation($name, $builder, $label = '')
{
$relation = new Relation($name, $builder, $label);
$relation->setParent($this);
$this->overwriteExistingRelation($name);
$this->relations->push($relation);
return $relation;
}
/**
* Overwrite existing field.
*
* @param string $name
*/
protected function overwriteExistingField($name)
{
if ($this->fields->isEmpty()) {
return;
}
$this->fields = $this->fields->filter(
function (Field $field) use ($name) {
return $field->getName() != $name;
}
);
}
/**
* Overwrite existing relation.
*
* @param string $name
*/
protected function overwriteExistingRelation($name)
{
if ($this->relations->isEmpty()) {
return;
}
$this->relations = $this->relations->filter(
function (Relation $relation) use ($name) {
return $relation->getName() != $name;
}
);
}
/**
* @return Repository
*/
public function repository()
{
return $this->repository;
}
/**
* Show a divider.
*/
public function divider()
{
$this->fields->push(new Divider());
}
/**
* Show a divider.
*/
public function newline()
{
$this->fields->push(new Newline());
}
/**
* Show the content of html.
*
* @param string $html
*/
public function html($html = '')
{
$this->fields->push((new Html($html))->setParent($this));
}
/**
* Disable `list` tool.
*
* @return $this
*/
public function disableListButton(bool $disable = true)
{
$this->panel->tools()->disableList($disable);
return $this;
}
/**
* Disable `delete` tool.
*
* @return $this
*/
public function disableDeleteButton(bool $disable = true)
{
$this->panel->tools()->disableDelete($disable);
return $this;
}
/**
* Disable `edit` tool.
*
* @return $this
*/
public function disableEditButton(bool $disable = true)
{
$this->panel->tools()->disableEdit($disable);
return $this;
}
/**
* Show quick edit tool.
*
* @param null|string $width
* @param null|string $height
* @return $this
*/
public function showQuickEdit(?string $width = null, ?string $height = null)
{
$this->panel->tools()->showQuickEdit($width, $height);
return $this;
}
/**
* Disable quick edit tool.
*
* @return $this
*/
public function disableQuickEdit()
{
$this->panel->tools()->disableQuickEdit();
return $this;
}
/**
* @return string
*/
public function resource()
{
if (empty($this->resource)) {
$path = request()->path();
$segments = explode('/', $path);
array_pop($segments);
$this->resource = url(implode('/', $segments));
}
return $this->resource;
}
/**
* Set resource path.
*
* @param string $path
* @return $this
*/
public function setResource($path)
{
if ($path) {
$this->resource = admin_url($path);
}
return $this;
}
/**
* Add field and relation dynamically.
*
* @param string $method
* @param array $arguments
* @return Field
*/
public function __call($method, $arguments = [])
{
if (static::hasMacro($method)) {
return $this->macroCall($method, $arguments);
}
return $this->call($method, $arguments);
}
/**
* @param $method
* @param array $arguments
* @return bool|Show|Field|Relation
*/
protected function call($method, $arguments = [])
{
$label = isset($arguments[0]) ? $arguments[0] : '';
if ($field = $this->handleRelationField($method, $arguments)) {
return $field;
}
return $this->addField($method, $label);
}
/**
* Handle relation field.
*
* @param string $method
* @param array $arguments
* @return $this|bool|Relation|Field
*/
protected function handleRelationField($method, $arguments)
{
if (count($arguments) == 1 && $arguments[0] instanceof \Closure) {
return $this->addRelation($method, $arguments[0]);
} elseif (count($arguments) == 2 && $arguments[1] instanceof \Closure) {
return $this->addRelation($method, $arguments[1], $arguments[0]);
}
return false;
}
/**
* Render the show panels.
*
* @return string
*/
public function render()
{
$model = $this->model();
if (is_callable($this->builder)) {
call_user_func($this->builder, $this);
}
if ($this->fields->isEmpty()) {
$this->all();
}
if (is_array($this->builder)) {
$this->fields($this->builder);
}
$this->fields->each->fill($model);
$this->relations->each->model($model);
$this->callComposing();
$data = [
'panel' => $this->panel->fill($this->fields),
'relations' => $this->relations,
];
return view($this->view, $data)->render();
}
/**
* Add a row in Show.
*
* @param Closure $callback
* @return $this
*/
public function row(Closure $callback)
{
$this->rows->push(new Row($callback, $this));
return $this;
}
/**
* @return \Illuminate\Support\Collection
*/
public function rows()
{
return $this->rows;
}
/**
* Add a model field to show.
*
* @param string $name
* @return Field|Collection
*/
public function __get($name)
{
return $this->call($name);
}
}