diff --git a/app/Http/Controllers/AdminController.php b/app/Http/Controllers/AdminController.php index 28f0a536..1c8c189f 100644 --- a/app/Http/Controllers/AdminController.php +++ b/app/Http/Controllers/AdminController.php @@ -26,54 +26,71 @@ class AdminController extends Controller { $form->text('home_pic_url', '首页图片地址')->hint('相对于首页的路径或者完整的 URL'); - $form->select('copyright_prefer', '程序版权信息', function($options) { - $options->add('0', 'Powered with ❤ by Blessing Skin Server.'); - $options->add('1', 'Powered by Blessing Skin Server.'); - $options->add('2', '由 Blessing Skin Server 强力驱动.'); - $options->add('3', '自豪地采用 Blessing Skin Server.'); - })->setSelected(Option::get('copyright_prefer', 0, false)); + $form->select('copyright_prefer', '程序版权信息') + ->option('0', 'Powered with ❤ by Blessing Skin Server.') + ->option('1', 'Powered by Blessing Skin Server.') + ->option('2', '由 Blessing Skin Server 强力驱动.') + ->option('3', '自豪地采用 Blessing Skin Server.'); - $form->textarea('copyright_text', '自定义版权文字', function($textarea) { - $textarea->setRows(6); - $textarea->setDescription('自定义版权文字内可使用占位符,{site_name} 将会被自动替换为站点名称,{site_url} 会被替换为站点地址。'); - }); + $form->textarea('copyright_text', '自定义版权文字')->rows(6) + ->description('自定义版权文字内可使用占位符,{site_name} 将会被自动替换为站点名称,{site_url} 会被替换为站点地址。'); })->handle(); - return view('admin.customize', compact('homepage')); + $customJsCss = Option::form('customJsCss', '自定义 CSS/JavaScript', function($form) + { + $form->textarea('custom_css', 'CSS')->rows(6); + $form->textarea('custom_js', 'JavaScript')->rows(6); + })->addMessage(' + 内容将会被追加至每个页面的 <style> 和 <script> 标签中。
+ - 这里有一些有用的示例:「自定义 CSS JavaScript」功能的一些实例@GitHub WiKi + ')->handle(); + + return view('admin.customize', ['forms' => compact('homepage', 'customJsCss')]); } public function score() { $rate = Option::form('rate', '积分换算', function($form) { - $form->group('score_per_storage', '存储', function($group) { - $group->text('score_per_storage'); - $group->addon('积分 = 1 KB'); - }); + $form->group('score_per_storage', '存储')->text('score_per_storage')->addon('积分 = 1 KB'); - $form->group('private_score_per_storage', '私密材质存储', function($group) { - $group->text('private_score_per_storage'); - $group->addon('积分 = 1 KB'); - })->hint('上传私密材质将消耗更多积分'); + $form->group('private_score_per_storage', '私密材质存储') + ->text('private_score_per_storage')->addon('积分 = 1 KB') + ->hint('上传私密材质将消耗更多积分'); - $form->group('score_per_closet_item', '收藏消耗积分', function($group) { - $group->text('score_per_closet_item'); - $group->addon('积分 = 一个衣柜物品'); - }); + $form->group('score_per_closet_item', '收藏消耗积分') + ->text('score_per_closet_item')->addon('积分 = 一个衣柜物品'); - $form->checkbox('return_score', '积分返还', '用户删除角色/材质/收藏时返还积分'); + $form->checkbox('return_score', '积分返还')->label('用户删除角色/材质/收藏时返还积分'); - $form->group('score_per_player', '角色', function($group) { - $group->text('score_per_player'); - $group->addon('积分 = 一个角色'); - }); + $form->group('score_per_player', '角色')->text('score_per_player')->addon('积分 = 一个角色'); $form->text('user_initial_score', '新用户默认积分'); })->handle(); - return view('admin.score', compact('rate')); + $signIn = Option::form('sign_in', '签到配置', function($form) + { + $form->group('sign_score', '签到获得积分') + ->text('sign_score_from')->addon('积分 ~ ')->text('sign_score_to')->addon('积分'); + + $form->group('sign_gap_time', '签到间隔时间')->text('sign_gap_time')->addon('小时'); + + $form->checkbox('sign_after_zero', '签到时间')->label('每天零点后可签到') + ->hint('勾选后将无视上一条,每天零时后均可签到'); + })->handle(function() { + $sign_score = $_POST['sign_score_from'].','.$_POST['sign_score_to']; + Option::set('sign_score', $sign_score); + + unset($_POST['sign_score_from']); + unset($_POST['sign_score_to']); + })->with([ + 'sign_score_from' => @explode(',', option('sign_score'))[0], + 'sign_score_to' => @explode(',', option('sign_score'))[1] + ]); + + return view('admin.score', ['forms' => compact('rate', 'signIn')]); } public function options() diff --git a/app/Services/OptionForm.php b/app/Services/OptionForm.php index 978a91d4..10f0aef8 100644 --- a/app/Services/OptionForm.php +++ b/app/Services/OptionForm.php @@ -3,8 +3,10 @@ namespace App\Services; use Option; +use ReflectionClass; use Illuminate\Support\Arr; use Illuminate\Support\Str; +use BadMethodCallException; class OptionForm { @@ -12,11 +14,12 @@ class OptionForm protected $title; protected $hint; - protected $type = 'primary'; - protected $items; + protected $type = 'primary'; + protected $items = []; - protected $values; + protected $values = []; + protected $buttons = []; protected $messages = []; protected $alwaysCallback = null; @@ -24,26 +27,48 @@ class OptionForm protected $renderWithOutTable = false; protected $renderInputTagsOnly = false; + /** + * Create a new option form instance. + * + * @param string $id + * @param string $title + * @return void + */ public function __construct($id, $title) { $this->id = $id; $this->title = $title; } - public function __call($name, $arguments) + /** + * Add option item to the form dynamically. + * + * @param string $method + * @param array $parameters + * @return OptionItem + * + * @throws \BadMethodCallException + */ + public function __call($method, $parameters) { - if (!in_array($name, ['text', 'checkbox', 'textarea', 'select', 'group'])) { - throw new \InvalidArgumentException("No such item for option form.", 1); + if (!in_array($method, ['text', 'checkbox', 'textarea', 'select', 'group'])) { + throw new BadMethodCallException("Method [$method] does not exist on option form."); } - $class = new \ReflectionClass('App\Services\OptionForm'.Str::title($name)); + $class = new ReflectionClass('App\Services\OptionForm'.Str::title($method)); // use ReflectionClass to create a new OptionFormItem instance - $item = $class->newInstanceArgs($arguments); + $item = $class->newInstanceArgs($parameters); $this->items[] = $item; return $item; } + /** + * Set the box type of option form. + * + * @param string $type + * @return $this + */ public function type($type) { $this->type = $type; @@ -51,17 +76,30 @@ class OptionForm return $this; } - public function hint($hint_content) + /** + * Add a hint to option form. + * + * @param array $info + * @return $this + */ + public function hint($hintContent) { - $this->hint = view('vendor.option-form.hint')->with('hint', $hint_content)->render(); + $this->hint = view('vendor.option-form.hint')->with('hint', $hintContent)->render(); return $this; } + /** + * Add a piece of data to the option form. + * + * @param string|array $key + * @param mixed $value + * @return $this + */ public function with($key, $value = null) { if (is_array($key)) { - $this->values = array_merge($this->values, $values); + $this->values = array_merge($this->values, $key); } else { $this->values[$key] = $value; } @@ -69,22 +107,69 @@ class OptionForm return $this; } - public function addMessage($msg, $type = "info") + /** + * Add a button at the footer of option form. + * + * @param array $info + * @return $this + */ + public function addButton(array $info) { - $this->messages[] = "
$msg
"; + $info = array_merge([ + 'style' => 'default', + 'class' => [], + 'href' => '', + 'text' => 'BUTTON', + 'type' => 'button', + 'name' => '' + ], $info); + + $classes = "btn btn-{$info['style']} ".implode(' ', (array) Arr::get($info, 'class')); + + if ($info['href']) { + $this->buttons[] = "{$info['text']}"; + } else { + $this->buttons[] = ""; + } + + return $this; } - public function always($callback) + /** + * Add a message to the top of option form. + * + * @param string $msg + * @param string $style + * @return $this + */ + public function addMessage($msg, $style = "info") + { + $this->messages[] = "
$msg
"; + + return $this; + } + + /** + * Add callback which will be always executed. + * + * @param callable $callback + * @return $this + */ + public function always(callable $callback) { $this->alwaysCallback = $callback; return $this; } + /** + * Parse id formatted as *[*]. Return id & offset when succeed. + * + * @param string $id + * @return bool|array + */ 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])) { @@ -97,34 +182,54 @@ class OptionForm return false; } - public function handle($callback = null) + /** + * Handle the HTTP post request and update modified options. + * + * @param callable $callback + * @return $this + */ + public function handle(callable $callback = null) { if (Arr::get($_POST, 'option') == $this->id) { if (!is_null($callback)) { call_user_func($callback, $this); } - $arrayOptionCache = []; + $postOptionQueue = []; + $arrayOptionQueue = []; foreach ($this->items as $item) { + if ($item instanceof OptionFormGroup) { + foreach ($item->items as $innerItem) { + if ($innerItem['type'] == "text") { + $postOptionQueue[] = new OptionFormText($innerItem['id']); + } + } + continue; + } + // push item to the queue + $postOptionQueue[] = $item; + } + + foreach ($postOptionQueue as $item) { if ($item instanceof OptionFormCheckbox && !isset($_POST[$item->id])) { // preset value for checkboxes which are not checked - $_POST[$item->id] = "0"; + $_POST[$item->id] = "false"; } // 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]; + $arrayOptionQueue[$result['id']][$result['offset']] = $_POST[$item->id]; continue; } - if ($_POST[$item->id] != option($item->id, null, false)) { - Option::set($item->id, $_POST[$item->id]); + if (($data = Arr::get($_POST, $item->id)) != option($item->id, null, false)) { + Option::set($item->id, $data); } } - foreach ($arrayOptionCache as $key => $value) { + foreach ($arrayOptionQueue as $key => $value) { Option::set($key, serialize($value)); } @@ -135,7 +240,7 @@ class OptionForm } /** - * Load value from $this->values & options. + * Load value from $this->values & options by given id. * * @param string $id * @return mixed @@ -143,7 +248,7 @@ class OptionForm protected function getValueById($id) { if (false === ($result = $this->parseIdWithOffset($id))) { - return option($id); + return Arr::get($this->values, $id, option($id, null, false)); } else { $option = Arr::get( $this->values, @@ -156,6 +261,11 @@ class OptionForm } } + /** + * Assign value for option items whose value haven't been set. + * + * @return void + */ protected function assignValues() { if (!is_null($this->alwaysCallback)) { @@ -165,7 +275,7 @@ class OptionForm // load values for items if not set manually foreach ($this->items as $item) { if ($item instanceof OptionFormGroup) { - foreach ($item->items as $groupItem) { + foreach ($item->items as &$groupItem) { if ($groupItem['id'] && is_null($groupItem['value'])) { $groupItem['value'] = $this->getValueById($groupItem['id']); } @@ -193,12 +303,27 @@ class OptionForm return $this; } + /** + * Get the string contents of the option form. + * + * @return string + */ public function render() { $this->assignValues(); return view('vendor.option-form.main')->with(array_merge(get_object_vars($this)))->render(); } + + /** + * Get the string contents of the option form. + * + * @return string + */ + public function __toString() + { + return $this->render(); + } } class OptionFormItem diff --git a/app/helpers.php b/app/helpers.php index dcadb863..c17d4c0a 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -221,7 +221,15 @@ if (! function_exists('bs_nickname')) { } if (! function_exists('option')) { - + /** + * Get / set the specified option value. + * + * If an array is passed as the key, we will assume you want to set an array of values. + * + * @param array|string $key + * @param mixed $default + * @return mixed + */ function option($key = null, $default = null, $bool = true) { $options = app('options'); diff --git a/resources/views/admin/customize.tpl b/resources/views/admin/customize.tpl index c38b017e..479bd6b5 100644 --- a/resources/views/admin/customize.tpl +++ b/resources/views/admin/customize.tpl @@ -86,55 +86,12 @@ -
- {!! $homepage->render() !!} + {!! $forms['homepage']->render() !!} -
-
-

自定义 CSS/JavaScript - -

-
-
- -
- 设置已保存。
'; - } else { ?> -
- 内容将会被追加至每个页面的 <style> 和 <script> 标签中。
- - 这里有一些有用的示例:「自定义 CSS JavaScript」功能的一些实例@GitHub WiKi -
- - - - - - - - - - - - - -
CSS - -
JavaScript - -
-
- - -
+ {!! $forms['customJsCss']->render() !!} diff --git a/resources/views/admin/score.tpl b/resources/views/admin/score.tpl index 610f1160..9cd34b06 100644 --- a/resources/views/admin/score.tpl +++ b/resources/views/admin/score.tpl @@ -18,69 +18,11 @@
- {!! $rate->render() !!} + {!! $forms['rate']->render() !!}
-
-
-

签到配置

-
-
- -
- 设置已保存。
'; - } ?> - - - - - - - - - - - - - - - - - -
签到获得积分 -
- - 积分 ~ - - 积分 -
- -
签到间隔时间 -
- - 小时 -
- -
签到时间 - - - -
-
- - -
+ {!! $forms['signIn']->render() !!}
diff --git a/resources/views/vendor/option-form/checkbox.tpl b/resources/views/vendor/option-form/checkbox.tpl index 07068495..ba91f33d 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 new file mode 100644 index 00000000..c7c678fd --- /dev/null +++ b/resources/views/vendor/option-form/item.tpl @@ -0,0 +1,5 @@ +{!! $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 960f5c9d..98bf181b 100644 --- a/resources/views/vendor/option-form/main.tpl +++ b/resources/views/vendor/option-form/main.tpl @@ -6,43 +6,37 @@
- @if (!empty($messages)) - @foreach($messages as $msg) - {!! $msg !!} - @endforeach - @endif + @foreach($messages as $msg) + {!! $msg !!} + @endforeach + @if ($renderWithOutTable) + @each('vendor.option-form.item', $items, 'item') + @else @foreach($items as $item) - - - @unless ($renderWithOutTable) @unless ($renderInputTagsOnly) @endunless - @endunless - @endforeach
{{ $item->name }} {!! $item->hint or '' !!} - @endunless - - {!! $item->render() !!} - - @if ($item->description) -

{!! $item->description !!}

- @endif - - @unless ($renderWithOutTable) + @include('vendor.option-form.item', compact('item'))
+ @endif +