blessing-skin-server/app/Services/OptionForm.php

613 lines
14 KiB
PHP
Raw Normal View History

2016-11-12 23:50:41 +08:00
<?php
namespace App\Services;
use BadMethodCallException;
2016-11-12 23:50:41 +08:00
use Illuminate\Support\Arr;
2016-11-18 21:57:47 +08:00
use Illuminate\Support\Str;
2019-12-14 11:10:37 +08:00
use Option;
use ReflectionClass;
2016-11-12 23:50:41 +08:00
class OptionForm
{
2016-12-31 23:28:09 +08:00
/**
* Pass this value to tell generator to
* load text from language files automatically.
*/
const AUTO_DETECT = 0x97ab1;
protected $id;
protected $title;
2016-11-12 23:50:41 +08:00
protected $hint;
protected $type = 'primary';
protected $items = [];
2016-11-12 23:50:41 +08:00
protected $values = [];
2016-11-12 23:50:41 +08:00
protected $buttons = [];
protected $messages = [];
2019-12-05 23:42:51 +08:00
protected $alerts = [];
2017-11-02 16:50:00 +08:00
protected $hookBefore;
protected $hookAfter;
protected $alwaysCallback = null;
2019-08-23 10:59:44 +08:00
protected $renderWithoutTable = false;
protected $renderInputTagsOnly = false;
2019-08-22 17:59:49 +08:00
protected $renderWithoutSubmitButton = false;
/**
* Create a new option form instance.
*
2019-12-14 11:10:37 +08:00
* @param string $id
* @param string $title
*
* @return void
*/
2019-08-23 10:59:44 +08:00
public function __construct($id, $title = self::AUTO_DETECT)
2016-11-12 23:50:41 +08:00
{
2016-12-31 23:28:09 +08:00
$this->id = $id;
if ($title == self::AUTO_DETECT) {
2019-08-23 10:59:44 +08:00
$this->title = trans("options.$id.title");
2016-12-31 23:28:09 +08:00
} else {
$this->title = $title;
}
2016-11-12 23:50:41 +08:00
}
/**
* Add option item to the form dynamically.
*
2019-12-14 11:10:37 +08:00
* @param string $method
* @param array $params
*
* @return OptionItem
*
* @throws \BadMethodCallException
*/
2016-12-31 23:28:09 +08:00
public function __call($method, $params)
2016-11-12 23:50:41 +08:00
{
2019-12-14 11:10:37 +08:00
if (!in_array($method, ['text', 'checkbox', 'textarea', 'select', 'group'])) {
throw new BadMethodCallException("Method [$method] does not exist on option form.");
2016-12-28 23:28:15 +08:00
}
2016-11-12 23:50:41 +08:00
2018-02-16 17:31:04 +08:00
// Assign name for option item
2019-12-14 11:10:37 +08:00
if (!isset($params[1]) || Arr::get($params, 1) == OptionForm::AUTO_DETECT) {
2018-07-13 23:19:59 +08:00
$params[1] = Arr::get(trans("options.$this->id.$params[0]"), 'title', trans("options.$this->id.$params[0]"));
2016-12-31 23:28:09 +08:00
}
$class = new ReflectionClass('App\Services\OptionForm'.Str::title($method));
2018-02-16 17:31:04 +08:00
// Use ReflectionClass to create a new OptionFormItem instance
2016-12-31 23:28:09 +08:00
$item = $class->newInstanceArgs($params);
$item->setParentId($this->id);
2016-12-28 23:28:15 +08:00
$this->items[] = $item;
2016-11-12 23:50:41 +08:00
2016-12-28 23:28:15 +08:00
return $item;
2016-11-12 23:50:41 +08:00
}
/**
* Set the box type of option form.
*
2019-12-14 11:10:37 +08:00
* @param string $type
*
* @return $this
*/
2016-12-28 23:28:15 +08:00
public function type($type)
2016-11-12 23:50:41 +08:00
{
2016-12-28 23:28:15 +08:00
$this->type = $type;
2016-11-12 23:50:41 +08:00
2016-12-28 23:28:15 +08:00
return $this;
2016-11-12 23:50:41 +08:00
}
/**
* Add a hint to option form.
*
2019-12-14 11:10:37 +08:00
* @param array $info
*
* @return $this
*/
public function hint($hintContent = self::AUTO_DETECT)
2016-11-12 23:50:41 +08:00
{
2016-12-31 23:28:09 +08:00
if ($hintContent == self::AUTO_DETECT) {
$hintContent = trans("options.$this->id.hint");
}
2019-12-03 17:03:30 +08:00
$this->hint = view('forms.hint')->with('hint', $hintContent)->render();
2016-11-12 23:50:41 +08:00
2016-12-28 23:28:15 +08:00
return $this;
2016-11-12 23:50:41 +08:00
}
/**
* Add a piece of data to the option form.
*
2019-12-14 11:10:37 +08:00
* @param string|array $key
* @param mixed $value
*
* @return $this
*/
public function with($key, $value = null)
2016-11-12 23:50:41 +08:00
{
if (is_array($key)) {
$this->values = array_merge($this->values, $key);
} else {
$this->values[$key] = $value;
}
2016-11-12 23:50:41 +08:00
return $this;
}
/**
* Add a button at the footer of option form.
*
* @return $this
*/
public function addButton(array $info)
{
$info = array_merge([
'style' => 'default',
'class' => [],
2019-12-14 11:10:37 +08:00
'href' => '',
'text' => 'BUTTON',
'type' => 'button',
'name' => '',
], $info);
2019-12-03 17:03:30 +08:00
$info['class'] = array_merge(
['btn', 'btn-'.$info['style']],
(array) Arr::get($info, 'class')
);
$this->buttons[] = $info;
return $this;
}
/**
* Add a message to the top of option form.
*
2019-12-14 11:10:37 +08:00
* @param string $msg
* @param string $style
*
* @return $this
*/
public function addMessage($msg = self::AUTO_DETECT, $style = 'info')
{
2016-12-31 23:28:09 +08:00
if ($msg == self::AUTO_DETECT) {
$msg = trans("options.$this->id.message");
}
2019-12-03 17:03:30 +08:00
$this->messages[] = ['content' => $msg, 'type' => $style];
return $this;
}
2019-12-05 23:42:51 +08:00
/**
* Add an alert to the top of option form.
*
2019-12-14 11:10:37 +08:00
* @param string $msg
* @param string $style
*
2019-12-05 23:42:51 +08:00
* @return $this
*/
public function addAlert($msg = self::AUTO_DETECT, $style = 'info')
{
if ($msg == self::AUTO_DETECT) {
$msg = trans("options.$this->id.alert");
}
$this->alerts[] = ['content' => $msg, 'type' => $style];
return $this;
}
2017-11-02 16:50:00 +08:00
/**
* Add callback which will be executed before handling options.
2017-11-02 16:50:00 +08:00
*
* @return $this
*/
public function before(callable $callback)
{
$this->hookBefore = $callback;
return $this;
}
/**
* Add callback which will be executed after handling options.
2017-11-02 16:50:00 +08:00
*
* @return $this
*/
public function after(callable $callback)
{
$this->hookAfter = $callback;
return $this;
}
/**
* Add callback which will be always executed.
*
* @return $this
*/
public function always(callable $callback)
{
$this->alwaysCallback = $callback;
return $this;
}
/**
* Handle the HTTP post request and update modified options.
*
2019-12-14 11:10:37 +08:00
* @param callable $callback
*
* @return $this
*/
public function handle(callable $callback = null)
2016-11-12 23:50:41 +08:00
{
2019-08-22 17:59:49 +08:00
$request = request();
2017-11-02 16:50:00 +08:00
$allPostData = $request->all();
if ($request->isMethod('POST') && Arr::get($allPostData, 'option') == $this->id) {
2019-12-14 11:10:37 +08:00
if (!is_null($callback)) {
call_user_func($callback, $this);
2016-11-12 23:50:41 +08:00
}
2019-12-14 11:10:37 +08:00
if (!is_null($this->hookBefore)) {
2017-11-02 16:50:00 +08:00
call_user_func($this->hookBefore, $this);
}
$postOptionQueue = [];
2016-12-28 23:28:15 +08:00
2016-11-12 23:50:41 +08:00
foreach ($this->items as $item) {
if ($item instanceof OptionFormGroup) {
foreach ($item->items as $innerItem) {
if ($innerItem['type'] == 'text') {
$postOptionQueue[] = new OptionFormText($innerItem['id']);
}
}
continue;
}
2018-02-16 17:31:04 +08:00
// Push item to the queue
$postOptionQueue[] = $item;
}
foreach ($postOptionQueue as $item) {
2019-12-14 11:10:37 +08:00
if ($item instanceof OptionFormCheckbox && !isset($allPostData[$item->id])) {
2016-11-18 21:57:47 +08:00
// preset value for checkboxes which are not checked
2019-03-23 15:44:16 +08:00
$allPostData[$item->id] = false;
2016-11-12 23:50:41 +08:00
}
2018-02-16 17:31:04 +08:00
// Compare with raw option value
2017-11-02 16:50:00 +08:00
if (($data = Arr::get($allPostData, $item->id)) != option($item->id, null, true)) {
$formatted = is_null($item->format) ? $data : call_user_func($item->format, $data);
Option::set($item->id, $formatted);
2016-11-12 23:50:41 +08:00
}
}
2019-12-14 11:10:37 +08:00
if (!is_null($this->hookAfter)) {
2017-11-02 16:50:00 +08:00
call_user_func($this->hookAfter, $this);
}
2019-12-05 23:42:51 +08:00
$this->addAlert(trans('options.option-saved'), 'success');
2016-11-12 23:50:41 +08:00
}
return $this;
}
2016-12-28 23:28:15 +08:00
/**
* Load value from $this->values & options by given id.
2016-12-28 23:28:15 +08:00
*
2019-12-14 11:10:37 +08:00
* @param string $id
*
2016-12-28 23:28:15 +08:00
* @return mixed
*/
protected function getValueById($id)
2016-12-28 23:28:15 +08:00
{
2019-08-23 10:59:44 +08:00
return Arr::get($this->values, $id, option_localized($id));
2016-12-28 23:28:15 +08:00
}
/**
* Assign value for option items whose value haven't been set.
*
* @return void
*/
protected function assignValues()
2016-11-12 23:50:41 +08:00
{
2018-02-16 17:31:04 +08:00
// Load values for items if not set manually
2016-11-12 23:50:41 +08:00
foreach ($this->items as $item) {
2016-12-28 23:28:15 +08:00
if ($item instanceof OptionFormGroup) {
foreach ($item->items as &$groupItem) {
2016-12-28 23:28:15 +08:00
if ($groupItem['id'] && is_null($groupItem['value'])) {
$groupItem['value'] = $this->getValueById($groupItem['id']);
2016-12-28 23:28:15 +08:00
}
2016-11-18 21:57:47 +08:00
}
2016-12-28 23:28:15 +08:00
continue;
2016-11-18 21:57:47 +08:00
}
2016-11-12 23:50:41 +08:00
2016-12-28 23:28:15 +08:00
if (is_null($item->value)) {
$item->value = $this->getValueById($item->id);
2016-11-12 23:50:41 +08:00
}
}
}
2019-08-23 10:59:44 +08:00
public function renderWithoutTable()
{
2019-08-23 10:59:44 +08:00
$this->renderWithoutTable = true;
2016-11-12 23:50:41 +08:00
return $this;
}
public function renderInputTagsOnly()
{
$this->renderInputTagsOnly = true;
return $this;
}
2019-08-22 17:59:49 +08:00
public function renderWithoutSubmitButton()
{
2019-08-22 17:59:49 +08:00
$this->renderWithoutSubmitButton = true;
return $this;
}
/**
* Get the string contents of the option form.
*
* @return string
*/
public function render()
{
2019-12-14 11:10:37 +08:00
if (!is_null($this->alwaysCallback)) {
2016-12-30 19:35:07 +08:00
call_user_func($this->alwaysCallback, $this);
}
// attach submit button to the form
2019-12-14 11:10:37 +08:00
if (!$this->renderWithoutSubmitButton) {
$this->addButton([
'style' => 'primary',
2019-12-14 11:10:37 +08:00
'text' => trans('general.submit'),
'type' => 'submit',
'name' => 'submit_'.$this->id,
]);
}
$this->assignValues();
2019-12-03 17:03:30 +08:00
return view('forms.form')
->with(array_merge(get_object_vars($this)))
->render();
2016-11-12 23:50:41 +08:00
}
/**
* Get the string contents of the option form.
*
* @return string
*/
public function __toString()
{
return $this->render();
}
2016-11-12 23:50:41 +08:00
}
class OptionFormItem
{
public $id;
2016-12-28 23:28:15 +08:00
public $name;
2016-11-12 23:50:41 +08:00
2016-12-28 23:28:15 +08:00
public $hint;
2017-11-02 16:50:00 +08:00
public $format;
public $value = null;
public $disabled;
2016-12-28 23:28:15 +08:00
public $description;
2016-11-12 23:50:41 +08:00
protected $parentId;
public function __construct($id, $name = null)
2016-11-12 23:50:41 +08:00
{
$this->id = $id;
2016-12-28 23:28:15 +08:00
$this->name = $name;
2016-11-12 23:50:41 +08:00
}
public function setParentId($id)
{
$this->parentId = $id;
return $this;
}
2016-12-28 23:28:15 +08:00
public function value($value)
2016-11-12 23:50:41 +08:00
{
2016-12-28 23:28:15 +08:00
$this->value = $value;
2016-11-12 23:50:41 +08:00
return $this;
}
public function hint($hintContent = OptionForm::AUTO_DETECT)
2016-11-12 23:50:41 +08:00
{
2016-12-31 23:28:09 +08:00
if ($hintContent == OptionForm::AUTO_DETECT) {
$hintContent = trans("options.$this->parentId.$this->id.hint");
2016-12-31 23:28:09 +08:00
}
2019-12-03 17:03:30 +08:00
$this->hint = view('forms.hint')->with('hint', $hintContent)->render();
2016-11-12 23:50:41 +08:00
return $this;
}
2017-11-02 16:50:00 +08:00
public function format(callable $callback)
{
$this->format = $callback;
return $this;
}
public function disabled($disabled = 'disabled')
{
2019-12-03 17:03:30 +08:00
$this->disabled = $disabled;
return $this;
}
public function description($description = OptionForm::AUTO_DETECT)
2016-11-12 23:50:41 +08:00
{
2016-12-31 23:28:09 +08:00
if ($description == OptionForm::AUTO_DETECT) {
$description = trans("options.$this->parentId.$this->id.description");
2016-12-31 23:28:09 +08:00
}
2016-12-28 23:28:15 +08:00
$this->description = $description;
2016-11-18 21:57:47 +08:00
return $this;
2016-11-12 23:50:41 +08:00
}
2016-12-28 23:28:15 +08:00
}
class OptionFormText extends OptionFormItem
{
protected $placeholder = '';
public function placeholder($placeholder = OptionForm::AUTO_DETECT)
{
if ($placeholder == OptionForm::AUTO_DETECT) {
2018-06-19 12:34:51 +08:00
$key = "options.$this->parentId.$this->id.placeholder";
$placeholder = trans()->has($key) ? trans($key) : '';
}
$this->placeholder = $placeholder;
return $this;
}
2016-11-12 23:50:41 +08:00
public function render()
{
2019-12-03 17:03:30 +08:00
return view('forms.text')->with([
'id' => $this->id,
'value' => $this->value,
'disabled' => $this->disabled,
'placeholder' => $this->placeholder,
2016-11-12 23:50:41 +08:00
]);
}
}
2016-12-28 23:28:15 +08:00
class OptionFormCheckbox extends OptionFormItem
2016-11-12 23:50:41 +08:00
{
2016-12-28 23:28:15 +08:00
protected $label;
2016-11-12 23:50:41 +08:00
public function label($label = OptionForm::AUTO_DETECT)
2016-11-12 23:50:41 +08:00
{
2016-12-31 23:28:09 +08:00
if ($label == OptionForm::AUTO_DETECT) {
$label = trans("options.$this->parentId.$this->id.label");
2016-12-31 23:28:09 +08:00
}
2016-12-28 23:28:15 +08:00
$this->label = $label;
2016-11-12 23:50:41 +08:00
2016-12-28 23:28:15 +08:00
return $this;
2016-11-12 23:50:41 +08:00
}
public function render()
{
2019-12-03 17:03:30 +08:00
return view('forms.checkbox')->with([
2019-12-14 11:10:37 +08:00
'id' => $this->id,
2016-12-28 23:28:15 +08:00
'value' => $this->value,
'label' => $this->label,
'disabled' => $this->disabled,
2016-11-12 23:50:41 +08:00
]);
}
}
2016-12-28 23:28:15 +08:00
class OptionFormTextarea extends OptionFormItem
2016-11-12 23:50:41 +08:00
{
protected $rows = 3;
2016-12-28 23:28:15 +08:00
public function rows($rows)
2016-11-12 23:50:41 +08:00
{
$this->rows = $rows;
2016-12-28 23:28:15 +08:00
return $this;
2016-11-12 23:50:41 +08:00
}
public function render()
{
2019-12-03 17:03:30 +08:00
return view('forms.textarea')->with([
2019-12-14 11:10:37 +08:00
'id' => $this->id,
'rows' => $this->rows,
'value' => $this->value,
'disabled' => $this->disabled,
2016-11-12 23:50:41 +08:00
]);
}
}
2016-12-28 23:28:15 +08:00
class OptionFormSelect extends OptionFormItem
2016-11-12 23:50:41 +08:00
{
2016-12-28 23:28:15 +08:00
protected $options;
public function option($value, $name)
{
$this->options[] = compact('value', 'name');
2016-11-12 23:50:41 +08:00
2016-12-28 23:28:15 +08:00
return $this;
}
2016-11-12 23:50:41 +08:00
2016-12-28 23:28:15 +08:00
public function render()
2016-11-12 23:50:41 +08:00
{
2019-12-03 17:03:30 +08:00
return view('forms.select')->with([
2019-12-14 11:10:37 +08:00
'id' => $this->id,
'options' => (array) $this->options,
'selected' => $this->value,
'disabled' => $this->disabled,
2016-12-28 23:28:15 +08:00
]);
2016-11-12 23:50:41 +08:00
}
2016-12-28 23:28:15 +08:00
}
class OptionFormGroup extends OptionFormItem
{
public $items = [];
2016-11-12 23:50:41 +08:00
public function text($id, $value = null, $placeholder = OptionForm::AUTO_DETECT)
2016-11-12 23:50:41 +08:00
{
if ($placeholder == OptionForm::AUTO_DETECT) {
2018-06-19 12:34:51 +08:00
$key = "options.$this->parentId.$this->id.placeholder";
$placeholder = trans()->has($key) ? trans($key) : '';
}
2019-12-03 17:47:06 +08:00
$this->items[] = [
'type' => 'text',
'id' => $id,
'value' => $value,
2019-12-14 11:10:37 +08:00
'placeholder' => $placeholder,
2019-12-03 17:47:06 +08:00
];
2016-12-28 23:28:15 +08:00
return $this;
2016-11-12 23:50:41 +08:00
}
public function addon($value = OptionForm::AUTO_DETECT)
2016-11-12 23:50:41 +08:00
{
2016-12-31 23:28:09 +08:00
if ($value == OptionForm::AUTO_DETECT) {
$value = trans("options.$this->parentId.$this->id.addon");
2016-12-31 23:28:09 +08:00
}
2016-12-11 22:26:58 +08:00
$this->items[] = ['type' => 'addon', 'id' => null, 'value' => $value];
2016-12-28 23:28:15 +08:00
return $this;
2016-11-12 23:50:41 +08:00
}
public function render()
{
2016-12-11 22:26:58 +08:00
$rendered = [];
foreach ($this->items as $item) {
2019-12-03 17:03:30 +08:00
$rendered[] = view('forms.'.$item['type'])->with([
2019-12-14 11:10:37 +08:00
'id' => $item['id'],
'value' => $item['value'],
'placeholder' => Arr::get($item, 'placeholder'),
2016-12-28 23:28:15 +08:00
]);
2016-12-11 22:26:58 +08:00
}
2019-12-03 17:03:30 +08:00
return view('forms.group')->with('items', $rendered);
2016-11-12 23:50:41 +08:00
}
}