From 1d7dc13e18b338cf9b6d5caaf4d1e0acb373e04b Mon Sep 17 00:00:00 2001 From: printempw Date: Wed, 28 Dec 2016 23:28:15 +0800 Subject: [PATCH] refactor OptonForm --- app/Http/Controllers/AdminController.php | 35 +- app/Services/OptionForm.php | 382 +++++++++--------- .../views/vendor/option-form/checkbox.tpl | 2 +- resources/views/vendor/option-form/item.tpl | 8 +- resources/views/vendor/option-form/main.tpl | 7 +- resources/views/vendor/option-form/select.tpl | 5 +- .../views/vendor/option-form/textarea.tpl | 4 - 7 files changed, 206 insertions(+), 237 deletions(-) diff --git a/app/Http/Controllers/AdminController.php b/app/Http/Controllers/AdminController.php index abc390db..55ae9870 100644 --- a/app/Http/Controllers/AdminController.php +++ b/app/Http/Controllers/AdminController.php @@ -84,29 +84,24 @@ class AdminController extends Controller $form->text('site_description', '站点描述'); $form->text('site_url', '站点地址(URL)')->hint('以 http(s):// 开头,不要以 / 结尾'); - $form->checkbox('user_can_register', '开放注册', '任何人都可以注册'); + $form->checkbox('user_can_register', '开放注册')->label('任何人都可以注册'); $form->text('regs_per_ip', '每个 IP 限制注册数'); - $form->group('max_upload_file_size', '最大允许上传大小', function($group) { - // main textbox - $group->text('max_upload_file_size'); - $group->addon('KB'); - })->hint('PHP 限制:'.ini_get('post_max_size').',定义在 php.ini 中。'); + $form->group('max_upload_file_size', '最大允许上传大小') + ->text('max_upload_file_size')->addon('KB') + ->hint('PHP 限制:'.ini_get('post_max_size').',定义在 php.ini 中。'); - $form->checkbox('allow_chinese_playername', '角色名', '允许中文角色名'); + $form->checkbox('allow_chinese_playername', '角色名')->label('允许中文角色名'); - $form->select('api_type', '首选 JSON API', function($options) { - $options->add('0', 'CustomSkinLoader API'); - $options->add('1', 'UniversalSkinAPI'); - }); + $form->select('api_type', '首选 JSON API') + ->option('0', 'CustomSkinLoader API') + ->option('1', 'UniversalSkinAPI'); - $form->checkbox('auto_del_invalid_texture', '失效材质', '自动删除失效材质')->hint('自动从皮肤库中删除文件不存在的材质记录'); + $form->checkbox('auto_del_invalid_texture', '失效材质')->label('自动删除失效材质')->hint('自动从皮肤库中删除文件不存在的材质记录'); + + $form->textarea('comment_script', '评论代码')->rows(6)->description('评论代码内可使用占位符,{tid} 将会被自动替换为材质的 id,{name} 会被替换为材质名称,{url} 会被替换为当前页面地址。'); - $form->textarea('comment_script', '评论代码', function($textarea) { - $textarea->setRows(6); - $textarea->setDescription('评论代码内可使用占位符,{tid} 将会被自动替换为材质的 id,{name} 会被替换为材质名称,{url} 会被替换为当前页面地址。'); - }); })->handle(function() { if (substr($_POST['site_url'], -1) == "/") $_POST['site_url'] = substr($_POST['site_url'], 0, -1); @@ -114,13 +109,13 @@ class AdminController extends Controller $cache = Option::form('cache', '资源文件配置', function($form) { - $form->checkbox('force_ssl', '强制 SSL', '强制使用 HTTPS 协议加载资源')->hint('请确认 SSL 可用后再开启'); - $form->checkbox('auto_detect_asset_url', '资源地址', '自动判断资源文件地址')->hint('根据当前 URL 自动加载资源文件,如果关闭则将根据「站点地址」填写的内容加载。如果出现 CDN 回源问题请关闭'); - $form->checkbox('return_200_when_notfound', 'HTTP 响应码', '请求不存在的角色时返回 200 而不是 404'); + $form->checkbox('force_ssl', '强制 SSL')->label('强制使用 HTTPS 协议加载资源')->hint('请确认 SSL 可用后再开启'); + $form->checkbox('auto_detect_asset_url', '资源地址')->label('自动判断资源文件地址')->hint('根据当前 URL 自动加载资源文件,如果关闭则将根据「站点地址」填写的内容加载。如果出现 CDN 回源问题请关闭'); + $form->checkbox('return_200_when_notfound', 'HTTP 响应码')->label('请求不存在的角色时返回 200 而不是 404'); $form->text('cache_expire_time', '缓存失效时间')->hint('秒数,86400 = 一天,31536000 = 一年'); - })->hint('如果启用了 CDN 缓存请适当修改这些配置')->handle(); + })->type('warning')->hint('如果启用了 CDN 缓存请适当修改这些配置')->handle(); return view('admin.options')->with('forms', compact('general', 'cache')); } diff --git a/app/Services/OptionForm.php b/app/Services/OptionForm.php index a9bf14f8..df770ed9 100644 --- a/app/Services/OptionForm.php +++ b/app/Services/OptionForm.php @@ -12,9 +12,10 @@ class OptionForm public $title; protected $hint; + protected $type = 'primary'; protected $items; - protected $success = false; + protected $values; protected $messages = []; @@ -26,66 +27,27 @@ class OptionForm $this->title = $title; } - public function text($id, $name, $value = null) + public function __call($name, $arguments) { - return $this->addItem('text', $id, $name)->set('value', $value); - } - - public function checkbox($id, $name, $label, $checked = null) - { - $checkbox = $this->addItem('checkbox', $id, $name)->set('label', $label); - - return $checkbox; - } - - public function select($id, $name, $callback) - { - $item = $this->addItem('select', $id, $name); - - $select = new OptionFormSelect($id); - - call_user_func($callback, $select); - - $item->set('view', $select); - - return $select; - } - - public function textarea($id, $name, $callback) - { - $item = $this->addItem('textarea', $id, $name); - - $textarea = new OptionFormTextarea($id); - - call_user_func($callback, $textarea); - - $item->set('view', $textarea); - - return $textarea; - } - - public function group($id, $name, $callback) - { - $item = $this->addItem('group', $id, $name); - - $group = new OptionFormGroup($id); - - call_user_func($callback, $group); - - $item->set('view', $group); - - return $item; - } - - public function addItem($type, $id, $name) - { - $item = new OptionFormItem($id, $name, $type); + if (!in_array($name, ['text', 'checkbox', 'textarea', 'select', 'group'])) { + throw new \InvalidArgumentException("No such item for option form.", 1); + } + $class = new \ReflectionClass('App\Services\OptionForm'.Str::title($name)); + // use ReflectionClass to create a new OptionFormItem instance + $item = $class->newInstanceArgs($arguments); $this->items[] = $item; return $item; } + public function type($type) + { + $this->type = $type; + + return $this; + } + public function hint($hint_content) { $this->hint = view('vendor.option-form.hint')->with('hint', $hint_content)->render(); @@ -93,6 +55,13 @@ class OptionForm return $this; } + public function setValues(array $values) + { + $this->values = array_merge($this->values, $values); + + return $this; + } + public function addMessage($msg, $type = "info") { $this->messages[] = "
$msg
"; @@ -105,21 +74,31 @@ class OptionForm call_user_func($callback, $this); } + $arrayOptionCache = []; + foreach ($this->items as $item) { - if ($item->type == "checkbox" && !isset($_POST[$item->id])) { + if ($item instanceof OptionFormCheckbox && !isset($_POST[$item->id])) { // preset value for checkboxes which are not checked $_POST[$item->id] = "0"; } - if (Str::is('*[*]', $item->id)) + // 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]; continue; + } if ($_POST[$item->id] != option($item->id, null, false)) { Option::set($item->id, $_POST[$item->id]); } } - session()->flash($this->id.'.status', 'success'); + foreach ($arrayOptionCache as $key => $value) { + Option::set($key, serialize($value)); + } + + $this->addMessage('设置已保存。', 'success'); } return $this; @@ -132,48 +111,64 @@ class OptionForm 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; + } + + /** + * Load value from $this->values & options. + * + * @param string $id + * @return mixed + */ + protected function loadValueFromId($id) + { + 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']); + } + } + public function render() { if (!is_null($this->alwaysCallback)) { call_user_func($this->alwaysCallback, $this); } + // load values for items if not set manually foreach ($this->items as $item) { - $id = $item->id; - - if (!$value = $item->get('value')) { - preg_match('/(.*)\[(.*)\]/', $id, $matches); - - if (isset($matches[2])) { - $option = @unserialize(option($matches[1])); - - $value = Arr::get($option, $matches[2]); - } else { - $value = option($item->id); + if ($item instanceof OptionFormGroup) { + foreach ($item->items as $groupItem) { + if ($groupItem['id'] && is_null($groupItem['value'])) { + $groupItem['value'] = $this->loadValueFromId($groupItem['id']); + } } + continue; } - switch ($item->type) { - case 'text': - $view = view('vendor.option-form.text')->with(compact('id', 'value')); - break; - - case 'checkbox': - $view = view('vendor.option-form.checkbox')->with([ - 'id' => $id, - 'label' => $item->get('label'), - 'checked' => (bool) $value - ]); - break; - - case 'select': - case 'textarea': - case 'group': - $view = $item->get('view')->render(); - break; + if (is_null($item->value)) { + $item->value = $this->loadValueFromId($item->id); } - - $item->setContent($view->render()); } return view('vendor.option-form.main')->with(get_object_vars($this))->render(); @@ -183,159 +178,139 @@ class OptionForm class OptionFormItem { public $id; - public $type; - public $title; - protected $data; + public $name; - protected $hint; - protected $content; + public $value = null; - public function __construct($id, $title, $type = "") + public $hint; + + public $description; + + public function __construct($id, $name) { - $this->id = $id; - $this->type = $type; - $this->title = $title; + $this->id = $id; + $this->name = $name; } - public function hint($hint_content) + public function value($value) { - $this->hint = view('vendor.option-form.hint')->with('hint', $hint_content)->render(); + $this->value = $value; return $this; } - public function setContent($content) + public function hint($hintContent) { - $this->content = $content; + $this->hint = view('vendor.option-form.hint')->with('hint', $hintContent)->render(); return $this; } - public function set($key, $value) - { - $this->data[$key] = $value; - - return $this; - } - - public function get($key) - { - return Arr::get($this->data, $key); - } - - public function render() - { - return view('vendor.option-form.item')->with([ - 'title' => $this->title, - 'content' => $this->content, - 'hint' => $this->hint - ]); - } - -} - -class OptionFormSelect -{ - protected $id; - - protected $items; - - protected $selected = null; - - public function __construct($id) - { - $this->id = $id; - } - - public function add($id, $name) - { - $this->items[] = [$id, $name]; - } - - public function setSelected($id) - { - $this->selected = $id; - } - - public function render() - { - if (is_null($this->selected)) { - $this->selected = option($this->id); - } - - return view('vendor.option-form.select')->with([ - 'id' => $this->id, - 'items' => $this->items, - 'selected' => $this->selected - ]); - } -} - -class OptionFormTextarea -{ - protected $id; - - protected $value; - - protected $rows = 3; - - protected $description = ""; - - public function __construct($id) - { - $this->id = $id; - } - - public function setContent($content) - { - $this->value = $content; - } - - public function setRows($rows) - { - $this->rows = $rows; - } - - public function setDescription($description) + public function description($description) { $this->description = $description; + + return $this; } public function render() { - if (is_null($this->value)) { - $this->value = option($this->id); - } + // + } - return view('vendor.option-form.textarea')->with([ - 'rows' => $this->rows, - 'id' => $this->id, - 'value' => $this->value, - 'description' => $this->description +} + +class OptionFormText extends OptionFormItem +{ + public function render() + { + return view('vendor.option-form.text')->with([ + 'id' => $this->id, + 'value' => $this->value ]); } } -class OptionFormGroup +class OptionFormCheckbox extends OptionFormItem { - protected $id; + protected $label; - protected $items = []; - - public function __construct($id) + public function label($label) { - $this->id = $id; + $this->label = $label; + + return $this; } + public function render() + { + return view('vendor.option-form.checkbox')->with([ + 'id' => $this->id, + 'value' => $this->value, + 'label' => $this->label + ]); + } +} + +class OptionFormTextarea extends OptionFormItem +{ + protected $rows = 3; + + public function rows($rows) + { + $this->rows = $rows; + + return $this; + } + + public function render() + { + return view('vendor.option-form.textarea')->with([ + 'id' => $this->id, + 'rows' => $this->rows, + 'value' => $this->value + ]); + } +} + +class OptionFormSelect extends OptionFormItem +{ + protected $options; + + public function option($value, $name) + { + $this->options[] = compact('value', 'name'); + + return $this; + } + + public function render() + { + return view('vendor.option-form.select')->with([ + 'id' => $this->id, + 'options' => $this->options, + 'selected' => $this->value + ]); + } +} + +class OptionFormGroup extends OptionFormItem +{ + public $items = []; + public function text($id, $value = null) { $this->items[] = ['type' => 'text', 'id' => $id, 'value' => $value]; + + return $this; } public function addon($value) { $this->items[] = ['type' => 'addon', 'id' => null, 'value' => $value]; + + return $this; } public function render() @@ -347,7 +322,10 @@ class OptionFormGroup $item['value'] = option($item['id'], null, false); } - $rendered[] = view('vendor.option-form.'.$item['type'])->withId($item['id'])->withValue($item['value']); + $rendered[] = view('vendor.option-form.'.$item['type'])->with([ + 'id' => $item['id'], + 'value' => $item['value'] + ]); } return view('vendor.option-form.group')->with('items', $rendered); diff --git a/resources/views/vendor/option-form/checkbox.tpl b/resources/views/vendor/option-form/checkbox.tpl index 7a8455b4..f57babfb 100644 --- a/resources/views/vendor/option-form/checkbox.tpl +++ b/resources/views/vendor/option-form/checkbox.tpl @@ -1,3 +1,3 @@ diff --git a/resources/views/vendor/option-form/item.tpl b/resources/views/vendor/option-form/item.tpl index 3f2b28d2..2dd3818b 100644 --- a/resources/views/vendor/option-form/item.tpl +++ b/resources/views/vendor/option-form/item.tpl @@ -1,6 +1,10 @@ - {{ $title }} {!! $hint or '' !!} + {{ $item->name }} {!! $item->hint or '' !!} - {!! $content !!} + {!! $item->render() !!} + + @if ($item->description != "") +

{!! $item->description !!}

+ @endif diff --git a/resources/views/vendor/option-form/main.tpl b/resources/views/vendor/option-form/main.tpl index 85ace27a..2c37f2df 100644 --- a/resources/views/vendor/option-form/main.tpl +++ b/resources/views/vendor/option-form/main.tpl @@ -1,13 +1,10 @@ -
+

{{ $title }} {!! $hint or '' !!}

- @if (session("$id.status") == 'success') -
设置已保存。
- @endif @if (!empty($messages)) @foreach($messages as $msg) @@ -18,7 +15,7 @@ @foreach($items as $item) - {!! $item->render() !!} + @include('vendor.option-form.item', compact('item')) @endforeach
diff --git a/resources/views/vendor/option-form/select.tpl b/resources/views/vendor/option-form/select.tpl index ad27a4c6..65838ff4 100644 --- a/resources/views/vendor/option-form/select.tpl +++ b/resources/views/vendor/option-form/select.tpl @@ -1,8 +1,7 @@ diff --git a/resources/views/vendor/option-form/textarea.tpl b/resources/views/vendor/option-form/textarea.tpl index 2e4ef1f7..e347ad6e 100644 --- a/resources/views/vendor/option-form/textarea.tpl +++ b/resources/views/vendor/option-form/textarea.tpl @@ -1,5 +1 @@ - -@if ($description != "") -

{!! $description !!}

-@endif