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

365 lines
8.1 KiB
PHP
Raw Normal View History

2016-11-12 23:50:41 +08:00
<?php
namespace App\Services;
use Option;
use Illuminate\Support\Arr;
2016-11-18 21:57:47 +08:00
use Illuminate\Support\Str;
2016-11-12 23:50:41 +08:00
class OptionForm
{
protected $id;
protected $title;
2016-11-12 23:50:41 +08:00
protected $hint;
2016-12-28 23:28:15 +08:00
protected $type = 'primary';
2016-11-12 23:50:41 +08:00
protected $items;
2016-12-28 23:28:15 +08:00
protected $values;
2016-11-12 23:50:41 +08:00
protected $messages = [];
protected $alwaysCallback = null;
protected $renderWithOutTable = false;
protected $renderInputTagsOnly = false;
2016-11-12 23:50:41 +08:00
public function __construct($id, $title)
{
$this->id = $id;
$this->title = $title;
}
2016-12-28 23:28:15 +08:00
public function __call($name, $arguments)
2016-11-12 23:50:41 +08:00
{
2016-12-28 23:28:15 +08:00
if (!in_array($name, ['text', 'checkbox', 'textarea', 'select', 'group'])) {
throw new \InvalidArgumentException("No such item for option form.", 1);
}
2016-11-12 23:50:41 +08:00
2016-12-28 23:28:15 +08:00
$class = new \ReflectionClass('App\Services\OptionForm'.Str::title($name));
// use ReflectionClass to create a new OptionFormItem instance
$item = $class->newInstanceArgs($arguments);
$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
}
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
}
2016-12-28 23:28:15 +08:00
public function hint($hint_content)
2016-11-12 23:50:41 +08:00
{
2016-12-28 23:28:15 +08:00
$this->hint = view('vendor.option-form.hint')->with('hint', $hint_content)->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
}
public function with($key, $value = null)
2016-11-12 23:50:41 +08:00
{
if (is_array($key)) {
$this->values = array_merge($this->values, $values);
} else {
$this->values[$key] = $value;
}
2016-11-12 23:50:41 +08:00
return $this;
}
public function addMessage($msg, $type = "info")
{
$this->messages[] = "<div class='callout callout-$type'>$msg</div>";
}
public function always($callback)
{
$this->alwaysCallback = $callback;
return $this;
}
protected function parseIdWithOffset($id)
{
// detect if id is formatted as *[*]
// array option is stored as unserialized string
preg_match('/(.*)\[(.*)\]/', $id, $matches);
if (isset($matches[2])) {
return [
'id' => $matches[1],
'offset' => $matches[2]
];
}
return false;
}
2016-11-12 23:50:41 +08:00
public function handle($callback = null)
{
if (Arr::get($_POST, 'option') == $this->id) {
if (!is_null($callback)) {
call_user_func($callback, $this);
2016-11-12 23:50:41 +08:00
}
2016-12-28 23:28:15 +08:00
$arrayOptionCache = [];
2016-11-12 23:50:41 +08:00
foreach ($this->items as $item) {
2016-12-28 23:28:15 +08:00
if ($item instanceof OptionFormCheckbox && !isset($_POST[$item->id])) {
2016-11-18 21:57:47 +08:00
// preset value for checkboxes which are not checked
2016-11-12 23:50:41 +08:00
$_POST[$item->id] = "0";
}
2016-12-28 23:28:15 +08:00
// Str::is('*[*]', $item->id)
if (false !== ($result = $this->parseIdWithOffset($item->id))) {
// push array option value to cache
$arrayOptionCache[$result['id']][$result['offset']] = $_POST[$item->id];
2016-11-18 21:57:47 +08:00
continue;
2016-12-28 23:28:15 +08:00
}
2016-11-18 21:57:47 +08:00
if ($_POST[$item->id] != option($item->id, null, false)) {
2016-11-12 23:50:41 +08:00
Option::set($item->id, $_POST[$item->id]);
}
}
2016-12-28 23:28:15 +08:00
foreach ($arrayOptionCache as $key => $value) {
Option::set($key, serialize($value));
}
$this->addMessage('设置已保存。', '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.
*
* @param string $id
* @return mixed
*/
protected function getValueById($id)
2016-12-28 23:28:15 +08:00
{
if (false === ($result = $this->parseIdWithOffset($id))) {
return option($id);
} else {
$option = Arr::get(
$this->values,
$result['id'],
// fallback to load from options
@unserialize(option($result['id']))
);
return Arr::get($option, $result['offset']);
}
}
protected function assignValues()
2016-11-12 23:50:41 +08:00
{
if (!is_null($this->alwaysCallback)) {
call_user_func($this->alwaysCallback, $this);
}
2016-12-28 23:28:15 +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) {
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
}
}
}
public function renderWithOutTable()
{
$this->renderWithOutTable = true;
2016-11-12 23:50:41 +08:00
return $this;
}
public function renderInputTagsOnly()
{
$this->renderInputTagsOnly = true;
return $this;
}
public function render()
{
$this->assignValues();
return view('vendor.option-form.main')->with(array_merge(get_object_vars($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;
public $value = null;
2016-12-28 23:28:15 +08:00
public $description;
2016-11-12 23:50:41 +08:00
public function __construct($id, $name = null)
2016-11-12 23:50:41 +08:00
{
2016-12-28 23:28:15 +08:00
$this->id = $id;
$this->name = $name;
2016-11-12 23:50:41 +08:00
}
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;
}
2016-12-28 23:28:15 +08:00
public function hint($hintContent)
2016-11-12 23:50:41 +08:00
{
2016-12-28 23:28:15 +08:00
$this->hint = view('vendor.option-form.hint')->with('hint', $hintContent)->render();
2016-11-12 23:50:41 +08:00
return $this;
}
2016-12-28 23:28:15 +08:00
public function description($description)
2016-11-12 23:50:41 +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
}
/**
* Render option item. Should be extended.
*
* @return \Illuminate\View\View|string
*/
2016-12-28 23:28:15 +08:00
public function render()
2016-11-12 23:50:41 +08:00
{
return;
2016-11-12 23:50:41 +08:00
}
2016-12-28 23:28:15 +08:00
}
class OptionFormText extends OptionFormItem
{
2016-11-12 23:50:41 +08:00
public function render()
{
2016-12-28 23:28:15 +08:00
return view('vendor.option-form.text')->with([
'id' => $this->id,
'value' => $this->value
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
2016-12-28 23:28:15 +08:00
public function label($label)
2016-11-12 23:50:41 +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()
{
2016-12-28 23:28:15 +08:00
return view('vendor.option-form.checkbox')->with([
'id' => $this->id,
'value' => $this->value,
'label' => $this->label
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()
{
return view('vendor.option-form.textarea')->with([
2016-12-28 23:28:15 +08:00
'id' => $this->id,
'rows' => $this->rows,
'value' => $this->value
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
{
2016-12-28 23:28:15 +08:00
return view('vendor.option-form.select')->with([
'id' => $this->id,
'options' => $this->options,
'selected' => $this->value
]);
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
2016-12-11 22:26:58 +08:00
public function text($id, $value = null)
2016-11-12 23:50:41 +08:00
{
2016-12-11 22:26:58 +08:00
$this->items[] = ['type' => 'text', 'id' => $id, 'value' => $value];
2016-12-28 23:28:15 +08:00
return $this;
2016-11-12 23:50:41 +08:00
}
public function addon($value)
{
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) {
if ($item['id'] && is_null($item['value'])) {
$item['value'] = option($item['id'], null, false);
2016-12-11 22:26:58 +08:00
}
2016-12-28 23:28:15 +08:00
$rendered[] = view('vendor.option-form.'.$item['type'])->with([
'id' => $item['id'],
'value' => $item['value']
]);
2016-12-11 22:26:58 +08:00
}
return view('vendor.option-form.group')->with('items', $rendered);
2016-11-12 23:50:41 +08:00
}
}