model = $model; $this->builder = $builder; $this->initPanel(); $this->initContents(); if (static::$initCallback instanceof Closure) { call_user_func(static::$initCallback, $this); } } /** * Initialize with user pre-defined default disables, etc. * * @param Closure $callback */ public static function init(Closure $callback = null) { static::$initCallback = $callback; } /** * 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; } /** * Add a model field to show. * * @param string $name * @param string $label * * @return Field */ public function field($name, $label = '') { return $this->addField($name, $label); } /** * Add multiple fields. * * @param array $fields * * @return $this */ public function fields(array $fields = []) { if (!Arr::isAssoc($fields)) { $fields = array_combine($fields, $fields); } foreach ($fields as $field => $label) { $this->field($field, $label); } return $this; } /** * Show all fields. * * @return Show */ public function all() { $fields = array_keys($this->model->getAttributes()); 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); return tap($field, function ($field) { $this->fields->push($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); return tap($relation, function ($relation) { $this->relations->push($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; } ); } /** * Show a divider. */ public function divider() { $this->fields->push(new Divider()); } /** * Set resource path. * * @param string $resource * * @return $this */ public function setResource($resource) { $this->resource = $resource; return $this; } /** * Get resource path. * * @return string */ public function getResourcePath() { if (empty($this->resource)) { $path = request()->path(); $segments = explode('/', $path); array_pop($segments); $this->resource = implode('/', $segments); } return $this->resource; } /** * Set the model instance. * * @param Model $model * * @return $this */ public function setModel($model) { $this->model = $model; return $this; } /** * Get the model instance being queried. * * @return Model */ public function getModel() { return $this->model; } /** * Add field and relation dynamically. * * @param string $method * @param array $arguments * * @return bool|mixed */ public function __call($method, $arguments = []) { $label = isset($arguments[0]) ? $arguments[0] : ucfirst($method); if ($field = $this->handleGetMutatorField($method, $label)) { return $field; } if ($field = $this->handleRelationField($method, $arguments)) { return $field; } if ($field = $this->handleModelField($method, $label)) { return $field; } return $this->addField($method, $label); } /** * Handle the get mutator field. * * @param string $method * @param string $label * * @return bool|Field */ protected function handleGetMutatorField($method, $label) { if (is_null($this->model)) { return false; } if ($this->model->hasGetMutator($method)) { return $this->addField($method, $label); } return false; } /** * Handle relation field. * * @param string $method * @param array $arguments * * @return $this|bool|Relation|Field */ protected function handleRelationField($method, $arguments) { if (!method_exists($this->model, $method)) { return false; } if (!($relation = $this->model->$method()) instanceof EloquentRelation) { return false; } if ($relation instanceof HasOne || $relation instanceof BelongsTo || $relation instanceof MorphOne ) { $this->model->with($method); if (count($arguments) == 1 && $arguments[0] instanceof \Closure) { return $this->addRelation($method, $arguments[0]); } if (count($arguments) == 2 && $arguments[1] instanceof \Closure) { return $this->addRelation($method, $arguments[1], $arguments[0]); } return $this->addField($method, array_get($arguments, 0))->setRelation(snake_case($method)); } if ($relation instanceof HasMany || $relation instanceof MorphMany || $relation instanceof BelongsToMany || $relation instanceof HasManyThrough ) { if (empty($arguments) || (count($arguments) == 1 && is_string($arguments[0]))) { return $this->showRelationAsField($method, $arguments[0] ?? ''); } $this->model->with($method); if (count($arguments) == 1 && is_callable($arguments[0])) { return $this->addRelation($method, $arguments[0]); } elseif (count($arguments) == 2 && is_callable($arguments[1])) { return $this->addRelation($method, $arguments[1], $arguments[0]); } throw new \InvalidArgumentException('Invalid eloquent relation'); } return false; } protected function showRelationAsField($relation = '', $label = '') { return $this->addField($relation, $label); } /** * Handle model field. * * @param string $method * @param string $label * * @return bool|Field */ protected function handleModelField($method, $label) { if (in_array($method, $this->model->getAttributes())) { return $this->addField($method, $label); } return false; } /** * Render the show panels. * * @return string */ public function render() { 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->setValue($this->model); $this->relations->each->setModel($this->model); $data = [ 'panel' => $this->panel->fill($this->fields), 'relations' => $this->relations, ]; return view('admin::show', $data)->render(); } }