215 lines
5.1 KiB
PHP
215 lines
5.1 KiB
PHP
<?php
|
|
|
|
namespace Laravel\Nova\Fields;
|
|
|
|
use Illuminate\Support\Str;
|
|
use Laravel\Nova\Http\Requests\NovaRequest;
|
|
use Laravel\Nova\Nova;
|
|
|
|
class KeyValue extends Field
|
|
{
|
|
use SupportsDependentFields;
|
|
|
|
/**
|
|
* The field's component.
|
|
*
|
|
* @var string
|
|
*/
|
|
public $component = 'key-value-field';
|
|
|
|
public function resolve($resource, $attribute = null)
|
|
{
|
|
parent::resolve($resource, $attribute);
|
|
|
|
if ($this->value === '{}') {
|
|
$this->value = null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Indicates if the element should be shown on the index view.
|
|
*
|
|
* @var bool
|
|
*/
|
|
public $showOnIndex = false;
|
|
|
|
/**
|
|
* The label that should be used for the key heading.
|
|
*
|
|
* @var string|null
|
|
*/
|
|
public $keyLabel;
|
|
|
|
/**
|
|
* The label that should be used for the value heading.
|
|
*
|
|
* @var string|null
|
|
*/
|
|
public $valueLabel;
|
|
|
|
/**
|
|
* The label that should be used for the "add row" button.
|
|
*
|
|
* @var string|null
|
|
*/
|
|
public $actionText;
|
|
|
|
/**
|
|
* The callback used to determine if the keys are readonly.
|
|
*
|
|
* @var (callable(\Laravel\Nova\Http\Requests\NovaRequest):(bool))|bool|null
|
|
*/
|
|
public $readonlyKeysCallback;
|
|
|
|
/**
|
|
* Determine if new rows are able to be added.
|
|
*
|
|
* @var bool
|
|
*/
|
|
public $canAddRow = true;
|
|
|
|
/**
|
|
* Determine if rows are able to be deleted.
|
|
*
|
|
* @var bool
|
|
*/
|
|
public $canDeleteRow = true;
|
|
|
|
/**
|
|
* Hydrate the given attribute on the model based on the incoming request.
|
|
*
|
|
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
|
* @param string $requestAttribute
|
|
* @param \Illuminate\Database\Eloquent\Model|\Laravel\Nova\Support\Fluent $model
|
|
* @param string $attribute
|
|
* @return void
|
|
*/
|
|
protected function fillAttributeFromRequest(NovaRequest $request, $requestAttribute, $model, $attribute)
|
|
{
|
|
if ($request->exists($requestAttribute)) {
|
|
// The value for KeyValue fields are serialized on the front-end using `JSON.stringify`,
|
|
// so we need to convert it to an associative array before saving it to the database.
|
|
$this->fillModelWithData($model, json_decode($request[$requestAttribute], true), $attribute);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fill the model's attribute with data.
|
|
*
|
|
* @param \Illuminate\Database\Eloquent\Model|\Laravel\Nova\Support\Fluent $model
|
|
* @param mixed $value
|
|
* @param string $attribute
|
|
* @return void
|
|
*/
|
|
public function fillModelWithData($model, $value, string $attribute)
|
|
{
|
|
$model->forceFill([Str::replace('.', '->', $attribute) => $value]);
|
|
}
|
|
|
|
/**
|
|
* The label that should be used for the key table heading.
|
|
*
|
|
* @param string $label
|
|
* @return $this
|
|
*/
|
|
public function keyLabel($label)
|
|
{
|
|
$this->keyLabel = $label;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* The label that should be used for the value table heading.
|
|
*
|
|
* @param string $label
|
|
* @return $this
|
|
*/
|
|
public function valueLabel($label)
|
|
{
|
|
$this->valueLabel = $label;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* The label that should be used for the add row button.
|
|
*
|
|
* @param string $label
|
|
* @return $this
|
|
*/
|
|
public function actionText($label)
|
|
{
|
|
$this->actionText = $label;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Set the callback used to determine if the keys are readonly.
|
|
*
|
|
* @param (callable(\Laravel\Nova\Http\Requests\NovaRequest):(bool))|bool $callback
|
|
* @return $this
|
|
*/
|
|
public function disableEditingKeys($callback = true)
|
|
{
|
|
$this->readonlyKeysCallback = $callback;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Determine if the keys are readonly.
|
|
*
|
|
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
|
* @return bool
|
|
*/
|
|
public function readonlyKeys(NovaRequest $request)
|
|
{
|
|
return with($this->readonlyKeysCallback, function ($callback) use ($request) {
|
|
return is_callable($callback) ? call_user_func($callback, $request) : ($callback === true);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Disable adding new rows.
|
|
*
|
|
* @return $this
|
|
*/
|
|
public function disableAddingRows()
|
|
{
|
|
$this->canAddRow = false;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Disable deleting rows.
|
|
*
|
|
* @return $this
|
|
*/
|
|
public function disableDeletingRows()
|
|
{
|
|
$this->canDeleteRow = false;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Prepare the field element for JSON serialization.
|
|
*
|
|
* @return array<string, mixed>
|
|
*/
|
|
public function jsonSerialize(): array
|
|
{
|
|
return array_merge(parent::jsonSerialize(), [
|
|
'keyLabel' => $this->keyLabel ?? Nova::__('Key'),
|
|
'valueLabel' => $this->valueLabel ?? Nova::__('Value'),
|
|
'actionText' => $this->actionText ?? Nova::__('Add row'),
|
|
'readonlyKeys' => $this->readonlyKeys(app(NovaRequest::class)),
|
|
'canAddRow' => $this->canAddRow,
|
|
'canDeleteRow' => $this->canDeleteRow,
|
|
]);
|
|
}
|
|
}
|