浏览代码

2017-12-24

Visman 7 年之前
父节点
当前提交
2066bd1790

+ 2 - 1
app/Controllers/Routing.php

@@ -108,11 +108,12 @@ class Routing
         if ($user->isAdmin) {
             $r->add('GET',  '/admin/statistics/info', 'AdminStatistics:info', 'AdminInfo');
             $r->add('GET',  '/admin/groups', 'AdminGroups:view', 'AdminGroups');
-            $r->add('POST', '/admin/groups/new[/{base:[1-9]\d*}]', 'AdminGroups:newPost', 'AdminGroupsNew');
+            $r->add('POST', '/admin/groups/new[/{base:[1-9]\d*}]', 'AdminGroups:editPost', 'AdminGroupsNew');
             $r->add('POST', '/admin/groups/default', 'AdminGroups:defaultPost', 'AdminGroupsDefault');
             $r->add('GET',  '/admin/groups/{id:[1-9]\d*}/edit', 'AdminGroups:edit', 'AdminGroupsEdit');
             $r->add('POST', '/admin/groups/{id:[1-9]\d*}/edit', 'AdminGroups:editPost');
             $r->add('GET',  '/admin/groups/{id:[1-9]\d*}/delete', 'AdminGroups:delete', 'AdminGroupsDelete');
+            $r->add('POST', '/admin/groups/{id:[1-9]\d*}/delete', 'AdminGroups:deletePost');
         }
 
         $uri = $_SERVER['REQUEST_URI'];

+ 1 - 1
app/Models/Forum/Manager.php

@@ -19,7 +19,7 @@ class Manager extends ManagerModel
      * 
      * @param array $attrs
      * 
-     * @return Topic
+     * @return Forum
      */
     public function create(array $attrs = [])
     {

+ 7 - 8
app/Models/Forum/Save.php

@@ -57,20 +57,19 @@ class Save extends Action
      */
     public function insert(Forum $forum)
     {
-        $modified = $forum->getModified();
-        if (null !== $forum->id || in_array('id', $modified)) {
+        if (null !== $forum->id) {
             throw new RuntimeException('The model has ID');
         }
-        $values = $forum->getAttrs();
+        $attrs  = $forum->getAttrs();
         $fileds = $this->c->dbMap->forums;
         $set = $set2 = $vars = [];
-        foreach ($modified as $name) {
-            if (! isset($fileds[$name])) {
+        foreach ($attrs as $key => $value) {
+            if (! isset($fileds[$key])) {
                 continue;
             }
-            $vars[] = $values[$name];
-            $set[] = $name;
-            $set2[] = '?' . $fileds[$name];
+            $vars[] = $value;
+            $set[]  = $key;
+            $set2[] = '?' . $fileds[$key];
         }
         if (empty($set)) {
             throw new RuntimeException('The model is empty');

+ 90 - 0
app/Models/Group/Manager.php

@@ -0,0 +1,90 @@
+<?php
+
+namespace ForkBB\Models\Group;
+
+use ForkBB\Models\ManagerModel;
+use ForkBB\Models\Group\Model as Group;
+use RuntimeException;
+
+class Manager extends ManagerModel
+{
+    /**
+     * Флаг загрузки групп
+     * @var bool
+     */
+    protected $flag;
+
+    /**
+     * Создает новую модель раздела
+     * 
+     * @param array $attrs
+     * 
+     * @return Group
+     */
+    public function create(array $attrs = [])
+    {
+        return $this->c->GroupModel->setAttrs($attrs);
+    }
+
+    public function getList()
+    {
+        return $this->repository;
+    }
+
+    /**
+     * Загрузка списка групп
+     * 
+     * @return Manager
+     */
+    public function init()
+    {
+        if (empty($this->flag)) {
+            $stmt = $this->c->DB->query('SELECT * FROM ::groups ORDER BY g_id');
+            while ($row = $stmt->fetch()) {
+                $this->set($row['g_id'], $this->create($row));
+            }
+            $this->flag = true;
+        }
+        return $this;
+    }
+
+    /**
+     * Получение модели группы
+     * 
+     * @param int $id
+     * 
+     * @return null|Group
+     */
+    public function get($id)
+    {
+        $group = parent::get($id);
+
+        return $group instanceof Group ? $group : null;
+    }
+
+    /**
+     * Обновляет группу в БД
+     *
+     * @param Group $group
+     * 
+     * @return Group
+     */
+    public function update(Group $group)
+    {
+        return $this->Save->update($group);
+    }
+
+    /**
+     * Добавляет новую группу в БД
+     *
+     * @param Group $group
+     * 
+     * @return int
+     */
+    public function insert(Group $group)
+    {
+        $id = $this->Save->insert($group);
+        $this->set($id, $group);
+        return $id;
+    }
+}

+ 36 - 0
app/Models/Group/Model.php

@@ -0,0 +1,36 @@
+<?php
+
+namespace ForkBB\Models\Group;
+
+use ForkBB\Models\DataModel;
+use RuntimeException;
+use InvalidArgumentException;
+
+class Model extends DataModel
+{
+    protected function getlinkEdit()
+    {
+        return $this->c->Router->link('AdminGroupsEdit', ['id' => $this->g_id]);
+    }
+
+    protected function getcanDelete()
+    {
+        $notDeleted = [
+            $this->c->GROUP_ADMIN, 
+            $this->c->GROUP_MOD, 
+            $this->c->GROUP_GUEST, 
+            $this->c->GROUP_MEMBER
+        ];
+        return ! in_array($this->g_id, $notDeleted) && $this->g_id != $this->c->config->o_default_user_group;
+    }
+
+    protected function getlinkDelete()
+    {
+        return $this->canDelete ? $this->c->Router->link('AdminGroupsDelete', ['id' => $this->g_id]) : null;
+    }
+
+    protected function getgroupGuest()
+    {
+        return $this->g_id === $this->c->GROUP_GUEST;
+    }
+}

+ 83 - 0
app/Models/Group/Save.php

@@ -0,0 +1,83 @@
+<?php
+
+namespace ForkBB\Models\Group;
+
+use ForkBB\Models\Action;
+use ForkBB\Models\Group\Model as Group;
+use RuntimeException;
+
+class Save extends Action
+{
+    /**
+     * Обновляет группу в БД
+     *
+     * @param Group $group
+     * 
+     * @throws RuntimeException
+     * 
+     * @return Group
+     */
+    public function update(Group $group)
+    {
+        if ($group->g_id < 1) {
+            throw new RuntimeException('The model does not have ID');
+        }
+        $modified = $group->getModified();
+        if (empty($modified)) {
+            return $group;
+        }
+        $values = $group->getAttrs();
+        $fileds = $this->c->dbMap->groups;
+        $set = $vars = [];
+        foreach ($modified as $name) {
+            if (! isset($fileds[$name])) {
+                continue;
+            }
+            $vars[] = $values[$name];
+            $set[] = $name . '=?' . $fileds[$name];
+        }
+        if (empty($set)) {
+            return $group;
+        }
+        $vars[] = $group->g_id;
+        $this->c->DB->query('UPDATE ::groups SET ' . implode(', ', $set) . ' WHERE id=?i', $vars);
+        $group->resModified();
+
+        return $group;
+    }
+
+    /**
+     * Добавляет новую группу в БД
+     *
+     * @param Group $group
+     * 
+     * @throws RuntimeException
+     * 
+     * @return int
+     */
+    public function insert(Group $group)
+    {
+        if (null !== $group->g_id) {
+            throw new RuntimeException('The model has ID');
+        }
+        $attrs  = $group->getAttrs();
+        $fileds = $this->c->dbMap->groups;
+        $set = $set2 = $vars = [];
+        foreach ($attrs as $key => $value) {
+            if (! isset($fileds[$key])) {
+                continue;
+            }
+            $vars[] = $value;
+            $set[]  = $key;
+            $set2[] = '?' . $fileds[$key];
+        }
+        if (empty($set)) {
+            throw new RuntimeException('The model is empty');
+        }
+        $this->c->DB->query('INSERT INTO ::groups (' . implode(', ', $set) . ') VALUES (' . implode(', ', $set2) . ')', $vars);
+        $group->g_id = $this->c->DB->lastInsertId();
+        $group->resModified();
+
+        return $group->g_id;
+    }
+}

+ 422 - 337
app/Models/Pages/Admin/Groups.php

@@ -4,129 +4,117 @@ namespace ForkBB\Models\Pages\Admin;
 
 use ForkBB\Core\Container;
 use ForkBB\Core\Validator;
+use ForkBB\Models\Group\Model as Group;
 use ForkBB\Models\Pages\Admin;
 
 class Groups extends Admin
 {
-    /**
-     * Массив групп
-     * @var array
-     */
-    protected $groups;
-
-    /**
-     * Список групп доступных как основа для новой
-     * @var array
-     */
-    protected $grBase = [];
-
-    /**
-     * Список групп доступных для группы по умолчанию
-     * @var array
-     */
-    protected $grDefault = [];
-
-    /**
-     * Список групп доступных для удаления
-     * @var array
-     */
-    protected $grDelete = [];
-
     /**
      * Конструктор
-     * 
+     *
      * @param Container $container
      */
     public function __construct(Container $container)
     {
         parent::__construct($container);
 
-        $this->getGroup();
-        $forBase = [$this->c->GROUP_UNVERIFIED, $this->c->GROUP_ADMIN, $this->c->GROUP_GUEST];
-        $forDelete = [$this->c->GROUP_UNVERIFIED, $this->c->GROUP_ADMIN, $this->c->GROUP_MOD, $this->c->GROUP_GUEST, $this->c->GROUP_MEMBER];
+        $this->c->Lang->load('admin_groups');
 
-        foreach ($this->groups as $key => $cur) {
-            if (! in_array($key, $forBase)) {
-                $this->grBase[$key] = true;
-                if ($cur['g_moderator'] == 0) {
-                    $this->grDefault[$key] = true;
-                }
-                if (! in_array($key, $forDelete)) {
-                    $this->grDelete[$key] = true;
-                }
-            }
-        }
-        $this->aIndex = 'groups';
-    }
+        $groupsList    = [];
+        $groupsNew     = [];
+        $groupsDefault = [];
+        $notForNew     = [$this->c->GROUP_ADMIN];
+        $notForDefault = [$this->c->GROUP_ADMIN, $this->c->GROUP_MOD, $this->c->GROUP_GUEST];
 
-    /**
-     * Создает массив групп
-     */
-    protected function getGroup()
-    {
-        if (empty($this->groups)) {
-            $this->groups = [];
-            $stmt = $this->c->DB->query('SELECT * FROM ::groups ORDER BY g_id');
-            while ($cur = $stmt->fetch()) {
-                $this->groups[$cur['g_id']] = $cur;
+        foreach ($this->c->groups->getList() as $key => $group) {
+            $groupsList[$key] = [$group->g_title, $group->linkEdit, $group->linkDelete];
+
+            if (! in_array($group->g_id, $notForNew)) {
+                $groupsNew[$key] = $group->g_title;
+            }
+            if (! in_array($group->g_id, $notForDefault) && $group->g_moderator == 0) {
+                $groupsDefault[$key] = $group->g_title;
             }
         }
+        $this->groupsList    = $groupsList;
+        $this->groupsNew     = $groupsNew;
+        $this->groupsDefault = $groupsDefault;
+        $this->aIndex        = 'groups';
     }
 
     /**
      * Подготавливает данные для шаблона
-     * 
+     *
      * @return Page
      */
     public function view()
     {
-        $groupsList = [];
-        $groupsNew = [];
-        $groupsDefault = [];
-        foreach ($this->groups as $key => $cur) {
-            $groupsList[] = [
-                $this->c->Router->link('AdminGroupsEdit', ['id' => $key]),
-                $cur['g_title'],
-                isset($this->grDelete[$key]) 
-                    ? $this->c->Router->link('AdminGroupsDelete', ['id' => $key])
-                    : null,
-            ];
-            if (isset($this->grBase[$key])) {
-                $groupsNew[] = [$key, $cur['g_title']];
-            }
-            if (isset($this->grDefault[$key])) {
-                $groupsDefault[] = [$key, $cur['g_title']];
-            }
-        }
-
-        $this->c->Lang->load('admin_groups');
-
-        $this->nameTpl = 'admin/groups';
-        $this->formActionNew     = $this->c->Router->link('AdminGroupsNew');
-        $this->formTokenNew      = $this->c->Csrf->create('AdminGroupsNew');
-        $this->formActionDefault = $this->c->Router->link('AdminGroupsDefault');
-        $this->formTokenDefault  = $this->c->Csrf->create('AdminGroupsDefault');
-        $this->defaultGroup      = $this->c->config->o_default_user_group;
-        $this->groupsNew         = $groupsNew;
-        $this->groupsDefault     = $groupsDefault;
-        $this->groupsList        = $groupsList;
-        $this->tabindex          = 0;
+        $this->nameTpl     = 'admin/groups';
+        $this->formNew     = [
+            'action' => $this->c->Router->link('AdminGroupsNew'),
+            'hidden' => [
+                'token' => $this->c->Csrf->create('AdminGroupsNew'),
+            ],
+            'sets'   => [[
+                'fields' => [
+                    'basegroup' => [
+                        'type'      => 'select',
+                        'options'   => $this->groupsNew,
+                        'value'     => $this->c->config->o_default_user_group,
+                        'title'     => \ForkBB\__('New group label'),
+                        'info'      => \ForkBB\__('New group help'),
+                        'autofocus' => true,
+                    ],
+                ],
+            ]],
+            'btns'   => [
+                'submit'  => [
+                    'type'      => 'submit',
+                    'value'     => \ForkBB\__('Add'),
+                    'accesskey' => 'a',
+                ],
+            ],
+        ];
+        $this->formDefault = [
+            'action' => $this->c->Router->link('AdminGroupsDefault'),
+            'hidden' => [
+                'token' => $this->c->Csrf->create('AdminGroupsDefault'),
+            ],
+            'sets'   => [[
+                'fields' => [
+                    'defaultgroup' => [
+                        'type'    => 'select',
+                        'options' => $this->groupsDefault,
+                        'value'   => $this->c->config->o_default_user_group,
+                        'title'   => \ForkBB\__('Default group label'),
+                        'info'    => \ForkBB\__('Default group help'),
+                    ],
+                ],
+            ]],
+            'btns'   => [
+                'submit'  => [
+                    'type'      => 'submit',
+                    'value'     => \ForkBB\__('Save'),
+                    'accesskey' => 's',
+                ],
+            ],
+        ];
 
         return $this;
     }
 
     /**
      * Устанавливает группу по умолчанию
-     * 
+     *
      * @return Page
      */
     public function defaultPost()
     {
-        $this->c->Lang->load('admin_groups');
-
         $v = $this->c->Validator->setRules([
             'token'        => 'token:AdminGroupsDefault',
-            'defaultgroup' => 'required|integer|in:' . implode(',', array_keys($this->grDefault)),
+            'defaultgroup' => 'required|integer|in:' . implode(',', array_keys($this->groupsDefault)),
+        ])->setMessages([
+            'defaultgroup.in' => 'Invalid default group',
         ]);
 
         if (! $v->validation($_POST)) {
@@ -138,105 +126,107 @@ class Groups extends Admin
         return $this->c->Redirect->page('AdminGroups')->message(\ForkBB\__('Default group redirect'));
     }
 
-    /**
-     * Подготавливает данные для создание группы
-     * Создает новую группу
-     * 
-     * @param array $args
-     * 
-     * @return Page
-     */
-    public function newPost(array $args)
-    {
-        $this->c->Lang->load('admin_groups');
-
-        if (empty($args['base'])) {
-            $v = $this->c->Validator->setRules([
-                'token'     => 'token:AdminGroupsNew',
-                'basegroup' => ['required|integer|in:' . implode(',', array_keys($this->grBase)), \ForkBB\__('New group label')]
-            ]);
-
-            if (! $v->validation($_POST)) {
-                $this->fIswev = $v->getErrors();
-                return $this->view();
-            } else {
-                return $this->edit(['id' => $v->basegroup, '_new' => true]);
-            }
-        } else {
-            return $this->editPost(['id' => $args['base'], '_new' => true]);
-        }
-    }
-
     /**
      * Подготавливает данные для шаблона редактирования группы
-     * 
+     *
      * @param array $args
-     * 
+     *
      * @return Page
      */
     public function edit(array $args)
     {
-        $groups = $this->groups;
+        if (isset($args['base'])) {
+            $group = $this->c->groups->get((int) $args['base']);
+        } else {
+            $group = $this->c->groups->get((int) $args['id']);
+        }
 
-        if (isset($args['_data'])) {
-            $groups[$args['id']] = $args['_data'];
-        } elseif (! isset($groups[$args['id']])) {
+        if (null === $group) {
             return $this->c->Message->message('Bad request');
         }
 
-        if (isset($args['_new'])) {
-            $id = -1;
-            $marker = 'AdminGroupsNew';
-            $vars = ['base' => $args['id']];
-            if (! isset($args['_data'])) {
-                unset($groups[$args['id']]['g_title']);
-            }
+        $group = clone $group;
+
+        if (isset($args['base'])) {
+            $vars            = ['base' => $group->g_id];
+            $group->g_title  = '';
+            $group->g_id     = null;
+            $marker          = 'AdminGroupsNew';
+            $this->titles    = \ForkBB\__('Create new group');
+            $this->titleForm = \ForkBB\__('Create new group');
         } else {
-            $id = (int) $args['id'];
-            $marker = 'AdminGroupsEdit';
-            $vars = ['id' => $id];
+            $vars            = ['id' => $group->g_id];
+            $marker          = 'AdminGroupsEdit';
+            $this->titles    = \ForkBB\__('Edit group');
+            $this->titleForm = \ForkBB\__('Edit group');
         }
 
-        $this->c->Lang->load('admin_groups');
+        if (isset($args['_data'])) {
+            $group->replAttrs($args['_data']);
+        }
 
-        $this->formAction = $this->c->Router->link($marker, $vars);
-        $this->formToken  = $this->c->Csrf->create($marker, $vars);
-        $this->form       = $this->viewForm($id, $groups[$args['id']]);
-        $this->warn       = empty($groups[$args['id']]['g_moderator']) ? null : \ForkBB\__('Moderator info');
-        $this->tabindex   = 0;
+        $this->nameTpl = 'admin/group';
+        $this->form    = $this->viewForm($group, $marker, $vars);
 
         return $this;
     }
 
     /**
+     * Создание новой группы
      * Запись данных по новой/измененной группе
-     * 
+     *
      * @param array $args
-     * 
+     *
      * @return Page
      */
     public function editPost(array $args)
     {
+        // начало создания новой группы
+        if (empty($args['id']) && empty($args['base'])) {
+            $v = $this->c->Validator->setRules([
+                'token'     => 'token:AdminGroupsNew',
+                'basegroup' => 'required|integer|in:' . implode(',', array_keys($this->groupsNew)),
+            ])->setMessages([
+                'basegroup.in' => 'Invalid group to create on base',
+            ]);
+
+            if (! $v->validation($_POST)) {
+                $this->fIswev = $v->getErrors();
+                return $this->view();
+            } else {
+                return $this->edit(['base' => $v->basegroup]);
+            }
+        }
+
+        if (isset($args['base'])) {
+            $group = $this->c->groups->get((int) $args['base']);
+        } else {
+            $group = $this->c->groups->get((int) $args['id']);
+        }
+
+        if (null === $group) {
+            return $this->c->Message->message('Bad request');
+        }
+
+        $group = clone $group;
+
         $next = $this->c->GROUP_ADMIN . ',' . $this->c->GROUP_GUEST;
-        if (isset($args['_new'])) {
-            $id = -1;
-            $marker = 'AdminGroupsNew';
-            $vars = ['base' => $args['id']];
+
+        if (isset($args['base'])) {
+            $marker      = 'AdminGroupsNew';
+            $group->g_id = null;
         } else {
-            $id = (int) $args['id'];
             $marker = 'AdminGroupsEdit';
-            $vars = ['id' => $id];
-            $next .= ',' . $id;
+            $next  .= ',' . $group->g_id;
         }
+
         $reserve = [];
-        foreach ($this->groups as $key => $cur) {
-            if ($key != $id) {
-                $reserve[] = $cur['g_title'];
+        foreach ($this->groupsList as $key => $cur) {
+            if ($group->g_id !== $key) {
+                $reserve[] = $cur[0];
             }
         }
 
-        $this->c->Lang->load('admin_groups');
-
         $v = $this->c->Validator->setRules([
             'token'                  => 'token:' . $marker,
             'g_title'                => 'required|string:trim|max:50|not_in:' . implode(',', $reserve),
@@ -256,6 +246,7 @@ class Groups extends Admin
             'g_edit_posts'           => 'integer|in:0,1',
             'g_delete_posts'         => 'integer|in:0,1',
             'g_delete_topics'        => 'integer|in:0,1',
+            'g_deledit_interval'     => 'integer|min:0|max:999999',
             'g_set_title'            => 'integer|in:0,1',
             'g_post_links'           => 'integer|in:0,1',
             'g_search'               => 'integer|in:0,1',
@@ -266,11 +257,14 @@ class Groups extends Admin
             'g_email_flood'          => 'integer|min:0|max:999999',
             'g_report_flood'         => 'integer|min:0|max:999999',
         ])->setArguments([
-            'token' => $vars,
+            'token' => $args,
+        ])->setMessages([
+            'g_title.required' => 'You must enter a group title',
+            'g_title.not_in'   => 'Title already exists',
         ]);
 
         if (! $v->validation($_POST)) {
-            $this->fIswev = $v->getErrors();
+            $this->fIswev  = $v->getErrors();
             $args['_data'] = $v->getData();
             return $this->edit($args);
         }
@@ -289,283 +283,374 @@ class Groups extends Admin
             $data['g_promote_min_posts']  = 0;
         }
 
-        $fields = [];
-        $sets = [];
-        $vars = [];
-        foreach($data as $key => $value) {
-            if (substr($key, 0, 2) !== 'g_' || $value === null) {
-                continue;
-            } elseif ($key === 'g_user_title' && ! isset($value{0})) {
-                $value = null;
-            }
-            if ($id === -1) {
-                $fields[] = $key;
-                $sets[] = is_int($value) ? '?i' : '?s';
-                $vars[] = $value;
-            } else {
-                if ($id === $this->c->GROUP_ADMIN 
-                    && ! in_array($key, ['g_title', 'g_user_title'])
-                ) {
-                    continue;
-                }
-                $sets[] = $key . '=' . (is_int($value) ? '?i' : '?s');
-                $vars[] = $value;
-            } 
+        foreach ($data as $attr => $value) {
+            $group->$attr = $value;
         }
-        if ($id === -1) {
-            $this->c->DB->exec('INSERT INTO ::groups (' . implode(', ', $fields) . ') VALUES(' . implode(', ', $sets) . ')', $vars);
-            $newId = $this->c->DB->lastInsertId();
 
-            $this->c->DB->exec('INSERT INTO ::forum_perms (group_id, forum_id, read_forum, post_replies, post_topics) SELECT ?i:new, forum_id, read_forum, post_replies, post_topics FROM ::forum_perms WHERE group_id=?i:old', [':new' => $newId, ':old' => $args['id']]);
-        } else {
-            $vars[] = $id;
-            $this->c->DB->exec('UPDATE ::groups SET ' . implode(', ', $sets) . ' WHERE g_id=?i', $vars);
+        $this->c->DB->beginTransaction();
 
+        if (null === $group->g_id) {
+            $message = \ForkBB\__('Group added redirect');
+            $newId   = $this->c->groups->insert($group);
+            //????
+            $this->c->DB->exec('INSERT INTO ::forum_perms (group_id, forum_id, read_forum, post_replies, post_topics) SELECT ?i:new, forum_id, read_forum, post_replies, post_topics FROM ::forum_perms WHERE group_id=?i:old', [':new' => $newId, ':old' => $args['base']]);
+
+        } else {
+            $message = \ForkBB\__('Group edited redirect');
+            $this->c->groups->update($group);
+            //????
             if ($data['g_promote_next_group']) {
-                $vars = [':next' => $data['g_promote_next_group'], ':id' => $id, ':posts' => $data['g_promote_min_posts']];
+                $vars = [':next' => $data['g_promote_next_group'], ':id' => $group->g_id, ':posts' => $data['g_promote_min_posts']];
                 $this->c->DB->exec('UPDATE ::users SET group_id=?i:next WHERE group_id=?i:id AND num_posts>=?i:posts', $vars);
             }
         }
 
+        $this->c->DB->commit();
+
         $this->c->Cache->delete('forums_mark');
 
-        return $this->c->Redirect
-            ->page('AdminGroups')
-            ->message($id === -1 ? \ForkBB\__('Group added redirect') : \ForkBB\__('Group edited redirect'));
+        return $this->c->Redirect->page('AdminGroups')->message($message);
     }
 
     /**
      * Формирует данные для формы редактирования группы
-     * @param int $id
-     * @param array $data
+     *
+     * @param Group $group
+     * @param string $marker
+     * @param array $args
+     *
      * @return array
      */
-    protected function viewForm($id, array $data)
+    protected function viewForm(Group $group, $marker, array $args)
     {
-        $this->nameTpl = 'admin/group';
         $form = [
-            'g_title' => [
-                'type' => 'text',
-                'maxlength' => 50,
-                'value' => isset($data['g_title']) ? $data['g_title'] : '',
-                'title' => \ForkBB\__('Group title label'),
-                'required' => true,
+            'action' => $this->c->Router->link($marker, $args),
+            'hidden' => [
+                'token' => $this->c->Csrf->create($marker, $args),
             ],
-            'g_user_title' => [
-                'type' => 'text',
-                'maxlength' => 50,
-                'value' => isset($data['g_user_title']) ? $data['g_user_title'] : '',
-                'title' => \ForkBB\__('User title label'),
-                'info' => \ForkBB\__('User title help', $id == $this->c->GROUP_GUEST ? \ForkBB\__('Guest') : \ForkBB\__('Member')),
+            'sets'   => [],
+            'btns'   => [
+                'submit'  => [
+                    'type'      => 'submit',
+                    'value'     => \ForkBB\__('Submit'),
+                    'accesskey' => 's',
+                ],
             ],
         ];
 
-        if ($id === $this->c->GROUP_UNVERIFIED || $id === $this->c->GROUP_ADMIN) {
+        $fieldset = [];
+        $fieldset['g_title'] = [
+            'type'      => 'text',
+            'maxlength' => 50,
+            'value'     => $group->g_title,
+            'title'     => \ForkBB\__('Group title label'),
+            'required'  => true,
+            'autofocus' => true,
+        ];
+        $fieldset['g_user_title'] = [
+            'type'      => 'text',
+            'maxlength' => 50,
+            'value'     => $group->g_user_title,
+            'title'     => \ForkBB\__('User title label'),
+            'info'      => \ForkBB\__('User title help', $group->groupGuest ? \ForkBB\__('Guest') : \ForkBB\__('Member')),
+        ];
+
+        if ($group->g_id === $this->c->GROUP_ADMIN) {
+            $form['sets'][] = [
+                'fields' => $fieldset,
+            ];
             return $form;
         }
 
-        if ($id !== $this->c->GROUP_GUEST) {
+        if (! $group->groupGuest) {
             $options = [0 => \ForkBB\__('Disable promotion')];
 
-            foreach ($this->groups as $group) {
-                if ($group['g_id'] == $id || empty($this->grBase[$group['g_id']])) {
+            foreach ($this->groupsNew as $key => $title) {
+                if ($key === $group->g_id || $key === $this->c->GROUP_GUEST) {
                     continue;
                 }
-                $options[$group['g_id']] = $group['g_title'];
+                $options[$key] = $title;
             }
 
-            $form['g_promote_next_group'] = [
-                'type' => 'select',
+            $fieldset['g_promote_next_group'] = [
+                'type'    => 'select',
                 'options' => $options,
-                'value' => isset($data['g_promote_next_group']) ? $data['g_promote_next_group'] : 0,
-                'title' => \ForkBB\__('Promote users label'),
-                'info' => \ForkBB\__('Promote users help', \ForkBB\__('Disable promotion')),
+                'value'   => $group->g_promote_next_group,
+                'title'   => \ForkBB\__('Promote users label'),
+                'info'    => \ForkBB\__('Promote users help', \ForkBB\__('Disable promotion')),
             ];
-            $form['g_promote_min_posts'] = [
-                'type' => 'number',
-                'min' => 0,
-                'max' => 9999999999,
-                'value' => isset($data['g_promote_min_posts']) ? $data['g_promote_min_posts'] : 0,
+            $fieldset['g_promote_min_posts'] = [
+                'type'  => 'number',
+                'min'   => 0,
+                'max'   => 9999999999,
+                'value' => $group->g_promote_min_posts,
                 'title' => \ForkBB\__('Number for promotion label'),
-                'info' => \ForkBB\__('Number for promotion help'),
+                'info'  => \ForkBB\__('Number for promotion help'),
             ];
         }
 
         $y = \ForkBB\__('Yes');
         $n = \ForkBB\__('No');
-        if ($id !== $this->c->GROUP_GUEST && $id != $this->c->config->o_default_user_group) {
-            $form['g_moderator'] = [
-                'type' => 'radio',
-                'value' => isset($data['g_moderator']) ? $data['g_moderator'] : 0,
+
+        if (! $group->groupGuest && $group->g_id != $this->c->config->o_default_user_group) {
+            $fieldset['g_moderator'] = [
+                'type'   => 'radio',
+                'value'  => $group->g_moderator,
                 'values' => [1 => $y, 0 => $n],
-                'title' => \ForkBB\__('Mod privileges label'),
-                'info' => \ForkBB\__('Mod privileges help'),
+                'title'  => \ForkBB\__('Mod privileges label'),
+                'info'   => \ForkBB\__('Mod privileges help'),
             ];
-            $form['g_mod_edit_users'] = [
-                'type' => 'radio',
-                'value' => isset($data['g_mod_edit_users']) ? $data['g_mod_edit_users'] : 0,
+            $fieldset['g_mod_edit_users'] = [
+                'type'   => 'radio',
+                'value'  => $group->g_mod_edit_users,
                 'values' => [1 => $y, 0 => $n],
-                'title' => \ForkBB\__('Edit profile label'),
-                'info' => \ForkBB\__('Edit profile help'),
+                'title'  => \ForkBB\__('Edit profile label'),
+                'info'   => \ForkBB\__('Edit profile help'),
             ];
-            $form['g_mod_rename_users'] = [
-                'type' => 'radio',
-                'value' => isset($data['g_mod_rename_users']) ? $data['g_mod_rename_users'] : 0,
+            $fieldset['g_mod_rename_users'] = [
+                'type'   => 'radio',
+                'value'  => $group->g_mod_rename_users,
                 'values' => [1 => $y, 0 => $n],
-                'title' => \ForkBB\__('Rename users label'),
-                'info' => \ForkBB\__('Rename users help'),
+                'title'  => \ForkBB\__('Rename users label'),
+                'info'   => \ForkBB\__('Rename users help'),
             ];
-            $form['g_mod_change_passwords'] = [
-                'type' => 'radio',
-                'value' => isset($data['g_mod_change_passwords']) ? $data['g_mod_change_passwords'] : 0,
+            $fieldset['g_mod_change_passwords'] = [
+                'type'   => 'radio',
+                'value'  => $group->g_mod_change_passwords,
                 'values' => [1 => $y, 0 => $n],
-                'title' => \ForkBB\__('Change passwords label'),
-                'info' => \ForkBB\__('Change passwords help'),
+                'title'  => \ForkBB\__('Change passwords label'),
+                'info'   => \ForkBB\__('Change passwords help'),
             ];
-            $form['g_mod_promote_users'] = [
-                'type' => 'radio',
-                'value' => isset($data['g_mod_promote_users']) ? $data['g_mod_promote_users'] : 0,
+            $fieldset['g_mod_promote_users'] = [
+                'type'   => 'radio',
+                'value'  => $group->g_mod_promote_users,
                 'values' => [1 => $y, 0 => $n],
-                'title' => \ForkBB\__('Mod promote users label'),
-                'info' => \ForkBB\__('Mod promote users help'),
+                'title'  => \ForkBB\__('Mod promote users label'),
+                'info'   => \ForkBB\__('Mod promote users help'),
             ];
-            $form['g_mod_ban_users'] = [
-                'type' => 'radio',
-                'value' => isset($data['g_mod_ban_users']) ? $data['g_mod_ban_users'] : 0,
+            $fieldset['g_mod_ban_users'] = [
+                'type'   => 'radio',
+                'value'  => $group->g_mod_ban_users,
                 'values' => [1 => $y, 0 => $n],
-                'title' => \ForkBB\__('Ban users label'),
-                'info' => \ForkBB\__('Ban users help'),
+                'title'  => \ForkBB\__('Ban users label'),
+                'info'   => \ForkBB\__('Ban users help'),
             ];
         }
 
-        $form['g_read_board'] = [
-            'type' => 'radio',
-            'value' => isset($data['g_read_board']) ? $data['g_read_board'] : 0,
+        $fieldset['g_read_board'] = [
+            'type'   => 'radio',
+            'value'  => $group->g_read_board,
             'values' => [1 => $y, 0 => $n],
-            'title' => \ForkBB\__('Read board label'),
-            'info' => \ForkBB\__('Read board help'),
+            'title'  => \ForkBB\__('Read board label'),
+            'info'   => \ForkBB\__('Read board help'),
         ];
-        $form['g_view_users'] = [
-            'type' => 'radio',
-            'value' => isset($data['g_view_users']) ? $data['g_view_users'] : 0,
+        $fieldset['g_view_users'] = [
+            'type'   => 'radio',
+            'value'  => $group->g_view_users,
             'values' => [1 => $y, 0 => $n],
-            'title' => \ForkBB\__('View user info label'),
-            'info' => \ForkBB\__('View user info help'),
+            'title'  => \ForkBB\__('View user info label'),
+            'info'   => \ForkBB\__('View user info help'),
         ];
-        $form['g_post_replies'] = [
-            'type' => 'radio',
-            'value' => isset($data['g_post_replies']) ? $data['g_post_replies'] : 0,
+        $fieldset['g_post_replies'] = [
+            'type'   => 'radio',
+            'value'  => $group->g_post_replies,
             'values' => [1 => $y, 0 => $n],
-            'title' => \ForkBB\__('Post replies label'),
-            'info' => \ForkBB\__('Post replies help'),
+            'title'  => \ForkBB\__('Post replies label'),
+            'info'   => \ForkBB\__('Post replies help'),
         ];
-        $form['g_post_topics'] = [
-            'type' => 'radio',
-            'value' => isset($data['g_post_topics']) ? $data['g_post_topics'] : 0,
+        $fieldset['g_post_topics'] = [
+            'type'   => 'radio',
+            'value'  => $group->g_post_topics,
             'values' => [1 => $y, 0 => $n],
-            'title' => \ForkBB\__('Post topics label'),
-            'info' => \ForkBB\__('Post topics help'),
+            'title'  => \ForkBB\__('Post topics label'),
+            'info'   => \ForkBB\__('Post topics help'),
         ];
 
-        if ($id !== $this->c->GROUP_GUEST) {
-            $form['g_edit_posts'] = [
-                'type' => 'radio',
-                'value' => isset($data['g_edit_posts']) ? $data['g_edit_posts'] : 0,
+        if (! $group->groupGuest) {
+            $fieldset['g_edit_posts'] = [
+                'type'   => 'radio',
+                'value'  => $group->g_edit_posts,
                 'values' => [1 => $y, 0 => $n],
-                'title' => \ForkBB\__('Edit posts label'),
-                'info' => \ForkBB\__('Edit posts help'),
+                'title'  => \ForkBB\__('Edit posts label'),
+                'info'   => \ForkBB\__('Edit posts help'),
             ];
-            $form['g_delete_posts'] = [
-                'type' => 'radio',
-                'value' => isset($data['g_delete_posts']) ? $data['g_delete_posts'] : 0,
+            $fieldset['g_delete_posts'] = [
+                'type'   => 'radio',
+                'value'  => $group->g_delete_posts,
                 'values' => [1 => $y, 0 => $n],
-                'title' => \ForkBB\__('Delete posts label'),
-                'info' => \ForkBB\__('Delete posts help'),
+                'title'  => \ForkBB\__('Delete posts label'),
+                'info'   => \ForkBB\__('Delete posts help'),
             ];
-            $form['g_delete_topics'] = [
-                'type' => 'radio',
-                'value' => isset($data['g_delete_topics']) ? $data['g_delete_topics'] : 0,
+            $fieldset['g_delete_topics'] = [
+                'type'   => 'radio',
+                'value'  => $group->g_delete_topics,
                 'values' => [1 => $y, 0 => $n],
-                'title' => \ForkBB\__('Delete topics label'),
-                'info' => \ForkBB\__('Delete topics help'),
+                'title'  => \ForkBB\__('Delete topics label'),
+                'info'   => \ForkBB\__('Delete topics help'),
+            ];
+            $fieldset['g_deledit_interval'] = [
+                'type'  => 'number',
+                'min'   => 0,
+                'max'   => 999999,
+                'value' => $group->g_deledit_interval,
+                'title' => \ForkBB\__('Delete-edit interval label'),
+                'info'  => \ForkBB\__('Delete-edit interval help'),
             ];
-            $form['g_set_title'] = [
-                'type' => 'radio',
-                'value' => isset($data['g_set_title']) ? $data['g_set_title'] : 0,
+            $fieldset['g_set_title'] = [
+                'type'   => 'radio',
+                'value'  => $group->g_set_title,
                 'values' => [1 => $y, 0 => $n],
-                'title' => \ForkBB\__('Set own title label'),
-                'info' => \ForkBB\__('Set own title help'),
+                'title'  => \ForkBB\__('Set own title label'),
+                'info'   => \ForkBB\__('Set own title help'),
             ];
         }
 
-        $form['g_post_links'] = [
-            'type' => 'radio',
-            'value' => isset($data['g_post_links']) ? $data['g_post_links'] : 0,
+        $fieldset['g_post_links'] = [
+            'type'   => 'radio',
+            'value'  => $group->g_post_links,
             'values' => [1 => $y, 0 => $n],
-            'title' => \ForkBB\__('Post links label'),
-            'info' => \ForkBB\__('Post links help'),
+            'title'  => \ForkBB\__('Post links label'),
+            'info'   => \ForkBB\__('Post links help'),
         ];
-        $form['g_search'] = [
-            'type' => 'radio',
-            'value' => isset($data['g_search']) ? $data['g_search'] : 0,
+        $fieldset['g_search'] = [
+            'type'   => 'radio',
+            'value'  => $group->g_search,
             'values' => [1 => $y, 0 => $n],
-            'title' => \ForkBB\__('User search label'),
-            'info' => \ForkBB\__('User search help'),
+            'title'  => \ForkBB\__('User search label'),
+            'info'   => \ForkBB\__('User search help'),
         ];
-        $form['g_search_users'] = [
-            'type' => 'radio',
-            'value' => isset($data['g_search_users']) ? $data['g_search_users'] : 0,
+        $fieldset['g_search_users'] = [
+            'type'   => 'radio',
+            'value'  => $group->g_search_users,
             'values' => [1 => $y, 0 => $n],
-            'title' => \ForkBB\__('User list search label'),
-            'info' => \ForkBB\__('User list search help'),
+            'title'  => \ForkBB\__('User list search label'),
+            'info'   => \ForkBB\__('User list search help'),
         ];
 
-        if ($id !== $this->c->GROUP_GUEST) {
-            $form['g_send_email'] = [
-                'type' => 'radio',
-                'value' => isset($data['g_send_email']) ? $data['g_send_email'] : 0,
+        if (! $group->groupGuest) {
+            $fieldset['g_send_email'] = [
+                'type'   => 'radio',
+                'value'  => $group->g_send_email,
                 'values' => [1 => $y, 0 => $n],
-                'title' => \ForkBB\__('Send e-mails label'),
-                'info' => \ForkBB\__('Send e-mails help'),
+                'title'  => \ForkBB\__('Send e-mails label'),
+                'info'   => \ForkBB\__('Send e-mails help'),
             ];
         }
 
-        $form['g_post_flood'] = [
-            'type' => 'number',
-            'min' => 0,
-            'max' => 999999,
-            'value' => isset($data['g_post_flood']) ? $data['g_post_flood'] : 0,
+        $fieldset['g_post_flood'] = [
+            'type'  => 'number',
+            'min'   => 0,
+            'max'   => 999999,
+            'value' => $group->g_post_flood,
             'title' => \ForkBB\__('Post flood label'),
-            'info' => \ForkBB\__('Post flood help'),
+            'info'  => \ForkBB\__('Post flood help'),
         ];
-        $form['g_search_flood'] = [
-            'type' => 'number',
-            'min' => 0,
-            'max' => 999999,
-            'value' => isset($data['g_search_flood']) ? $data['g_search_flood'] : 0,
+        $fieldset['g_search_flood'] = [
+            'type'  => 'number',
+            'min'   => 0,
+            'max'   => 999999,
+            'value' => $group->g_search_flood,
             'title' => \ForkBB\__('Search flood label'),
-            'info' => \ForkBB\__('Search flood help'),
+            'info'  => \ForkBB\__('Search flood help'),
         ];
 
-        if ($id !== $this->c->GROUP_GUEST) {
-            $form['g_email_flood'] = [
-                'type' => 'number',
-                'min' => 0,
-                'max' => 999999,
-                'value' => isset($data['g_email_flood']) ? $data['g_email_flood'] : 0,
+        if (! $group->groupGuest) {
+            $fieldset['g_email_flood'] = [
+                'type'  => 'number',
+                'min'   => 0,
+                'max'   => 999999,
+                'value' => $group->g_email_flood,
                 'title' => \ForkBB\__('E-mail flood label'),
-                'info' => \ForkBB\__('E-mail flood help'),
+                'info'  => \ForkBB\__('E-mail flood help'),
             ];
-            $form['g_report_flood'] = [
-                'type' => 'number',
-                'min' => 0,
-                'max' => 999999,
-                'value' => isset($data['g_report_flood']) ? $data['g_report_flood'] : 0,
+            $fieldset['g_report_flood'] = [
+                'type'  => 'number',
+                'min'   => 0,
+                'max'   => 999999,
+                'value' => $group->g_report_flood,
                 'title' => \ForkBB\__('Report flood label'),
-                'info' => \ForkBB\__('Report flood help'),
+                'info'  => \ForkBB\__('Report flood help'),
+            ];
+        }
+
+        $form['sets'][] = [
+            'fields' => $fieldset,
+        ];
+
+        if (! empty($group->g_moderator)) {
+            $form['sets'][] = [
+                'info' => [
+                    'info1' => [
+                        'type'  => '', //????
+                        'value' => \ForkBB\__('Moderator info'),
+                    ],
+                ],
             ];
         }
 
         return $form;
     }
+
+    /**
+     * Подготавливает данные для шаблона
+     *
+     * @param array $args
+     * 
+     * @return Page
+     */
+    public function delete(array $args)
+    {
+        $group = $this->c->groups->get((int) $args['id']);
+
+        if (null === $group || ! $group->canDelete) {
+            return $this->c->Message->message('Bad request');
+        }
+
+        $form = [
+            'action' => $this->c->Router->link('AdminGroupsDelete', $args),
+            'hidden' => [
+                'token' => $this->c->Csrf->create('AdminGroupsDelete', $args),
+            ],
+            'sets'   => [],
+            'btns'   => [
+                'delete'  => [
+                    'type'      => 'submit',
+                    'value'     => \ForkBB\__('Delete group'),
+                    'accesskey' => 'd',
+                ],
+            ],
+        ];
+
+        $form['sets'][] = [
+            'info' => [
+                'info1' => [
+                    'type'  => '', //????
+                    'value' => \ForkBB\__('Confirm delete warn'),
+                ],
+#                'info2' => [
+#                    'type'  => '', //????
+#                    'value' => \ForkBB\__('Confirm delete info', $group->g_title),
+#                    'html'  => true,
+#                ],
+            ],
+        ];
+        $form['sets'][] = [
+            'fields' => [
+                'confirm' => [
+#                    'dl'      => 'full',
+                    'title'   => \ForkBB\__('Confirm delete'),
+                    'type'    => 'checkbox',
+                    'label'   => \ForkBB\__('I want to delete this group', $group->g_title),
+                    'value'   => '1',
+                    'checked' => false,
+                ],
+            ],
+        ];
+
+        $this->nameTpl = 'admin/group_delete';
+        $this->titles  = \ForkBB\__('Group delete');
+        $this->form    = $form;
+
+        return $this;
+    }
 }

+ 3 - 3
app/Models/Pages/Auth.php

@@ -193,7 +193,7 @@ class Auth extends Page
             'token' => 'token:Forget',
             'email' => 'required|string:trim,lower|email|check_email',
         ])->setMessages([
-            'email.email' => \ForkBB\__('Invalid email'),
+            'email.email' => 'Invalid email',
         ]);
 
         if (! $v->validation($_POST)) {
@@ -342,8 +342,8 @@ class Auth extends Page
         ])->setArguments([
             'token' => $args,
         ])->setMessages([
-            'password.password'  => \ForkBB\__('Pass format'),
-            'password2.same' => \ForkBB\__('Pass not match'),
+            'password.password'  => 'Pass format',
+            'password2.same'     => 'Pass not match',
         ]);
 
         if (! $v->validation($_POST)) {

+ 10 - 10
app/Models/Pages/Delete.php

@@ -10,9 +10,9 @@ class Delete extends Page
 
     /**
      * Подготовка данных для шаблона удаления сообщения/темы
-     * 
+     *
      * @param array $args
-     * 
+     *
      * @return Page
      */
     public function delete(array $args)
@@ -27,7 +27,7 @@ class Delete extends Page
         $deleteTopic = $post->id === $topic->first_post_id;
 
         $this->c->Lang->load('delete');
-        
+
         $this->nameTpl    = 'post';
         $this->onlinePos  = 'topic-' . $topic->id;
         $this->canonical  = $post->linkDelete;
@@ -68,25 +68,25 @@ class Delete extends Page
             ],
             'btns'   => [
                 'delete'  => [
-                    'type'      => 'submit', 
-                    'value'     => \ForkBB\__($deleteTopic ? 'Delete  topic' : 'Delete  post'), 
+                    'type'      => 'submit',
+                    'value'     => \ForkBB\__($deleteTopic ? 'Delete  topic' : 'Delete  post'),
                     'accesskey' => 'd',
                 ],
                 'cancel'  => [
-                    'type'      => 'submit', 
-                    'value'     => \ForkBB\__('Cancel'), 
+                    'type'      => 'submit',
+                    'value'     => \ForkBB\__('Cancel'),
                 ],
             ],
         ];
-                
+
         return $this;
     }
 
     /**
      * Обработка данных от формы удаления сообщения/темы
-     * 
+     *
      * @param array $args
-     * 
+     *
      * @return Page
      */
     public function deletePost(array $args)

+ 1 - 1
app/Models/Pages/Install.php

@@ -709,7 +709,7 @@ class Install extends Page
         $schema = [
             'FIELDS' => [
                 'id'               => ['SERIAL', false],
-                'group_id'         => ['INT(10) UNSIGNED', false, $this->c->GROUP_UNVERIFIED],
+                'group_id'         => ['INT(10) UNSIGNED', false, 0],
                 'username'         => ['VARCHAR(200)', false, ''],
                 'password'         => ['VARCHAR(255)', false, ''],
                 'email'            => ['VARCHAR(80)', false, ''],

+ 3 - 3
app/Models/Pages/Register.php

@@ -31,8 +31,8 @@ class Register extends Page
         ])->setMessages([
             'agree.required'    => ['cancel', 'cancel'],
             'agree.token'       => [\ForkBB\__('Bad agree', $this->c->Router->link('Register')), 'w'],
-            'password.password' => \ForkBB\__('Pass format'),
-            'username.login'    => \ForkBB\__('Login format'),
+            'password.password' => 'Pass format',
+            'username.login'    => 'Login format',
         ]);
 
         // завершение регистрации
@@ -124,7 +124,7 @@ class Register extends Page
     protected function regEnd(Validator $v)
     {
         if ($this->c->config->o_regs_verify == '1') {
-            $groupId = $this->c->GROUP_UNVERIFIED;
+            $groupId = 0;
             $key = 'w' . $this->c->Secury->randomPass(79);
         } else {
             $groupId = $this->c->config->o_default_user_group;

+ 0 - 1
app/Models/Post/Model.php

@@ -44,7 +44,6 @@ class Model extends DataModel
         $user = $this->c->users->get($this->poster_id);
 
         if (! $user instanceof User) {
-            var_dump($this->poster_id);
             $attrs = $this->a; //????
             $attrs['id'] = $attrs['poster_id'];
 

+ 7 - 8
app/Models/Post/Save.php

@@ -57,20 +57,19 @@ class Save extends Action
      */
     public function insert(Post $post)
     {
-        $modified = $post->getModified();
-        if (null !== $post->id || in_array('id', $modified)) {
+        if (null !== $post->id) {
             throw new RuntimeException('The model has ID');
         }
-        $values = $post->getAttrs();
+        $attrs  = $post->getAttrs();
         $fileds = $this->c->dbMap->posts;
         $set = $set2 = $vars = [];
-        foreach ($modified as $name) {
-            if (! isset($fileds[$name])) {
+        foreach ($attrs as $key => $value) {
+            if (! isset($fileds[$key])) {
                 continue;
             }
-            $vars[] = $values[$name];
-            $set[] = $name;
-            $set2[] = '?' . $fileds[$name];
+            $vars[] = $value;
+            $set[]  = $key;
+            $set2[] = '?' . $fileds[$key];
         }
         if (empty($set)) {
             throw new RuntimeException('The model is empty');

+ 2 - 2
app/Models/Stats/Load.php

@@ -14,8 +14,8 @@ class Load extends Method
      */
     public function load()
     {
-        $total = $this->c->DB->query('SELECT COUNT(id)-1 FROM ::users WHERE group_id!=?i', [$this->c->GROUP_UNVERIFIED])->fetchColumn();
-        $last  = $this->c->DB->query('SELECT id, username FROM ::users WHERE group_id!=?i ORDER BY registered DESC LIMIT 1', [$this->c->GROUP_UNVERIFIED])->fetch();
+        $total = $this->c->DB->query('SELECT COUNT(id)-1 FROM ::users WHERE group_id!=0')->fetchColumn();
+        $last  = $this->c->DB->query('SELECT id, username FROM ::users WHERE group_id!=0 ORDER BY registered DESC LIMIT 1')->fetch();
         $this->model->userTotal = $total;
         $this->model->userLast  = $last;
         $this->c->Cache->set('stats', [

+ 7 - 8
app/Models/Topic/Save.php

@@ -57,20 +57,19 @@ class Save extends Action
      */
     public function insert(Topic $topic)
     {
-        $modified = $topic->getModified();
-        if (null !== $topic->id || in_array('id', $modified)) {
+        if (null !== $topic->id) {
             throw new RuntimeException('The model has ID');
         }
-        $values = $topic->getAttrs();
+        $attrs  = $topic->getAttrs();
         $fileds = $this->c->dbMap->topics;
         $set = $set2 = $vars = [];
-        foreach ($modified as $name) {
-            if (! isset($fileds[$name])) {
+        foreach ($attrs as $key => $value) {
+            if (! isset($fileds[$key])) {
                 continue;
             }
-            $vars[] = $values[$name];
-            $set[] = $name;
-            $set2[] = '?' . $fileds[$name];
+            $vars[] = $value;
+            $set[]  = $key;
+            $set2[] = '?' . $fileds[$key];
         }
         if (empty($set)) {
             throw new RuntimeException('The model is empty');

+ 2 - 2
app/Models/User/Manager.php

@@ -70,8 +70,8 @@ class Manager extends ManagerModel
      */
     public function insert(User $user)
     {
-        $id = $this->Save->insert($topic);
-        $this->set($id, $topic);
+        $id = $this->Save->insert($user);
+        $this->set($id, $user);
         return $id;
     }
 }

+ 2 - 2
app/Models/User/Model.php

@@ -16,7 +16,7 @@ class Model extends DataModel
      */
     protected function getisUnverified()
     {
-        return $this->group_id == $this->c->GROUP_UNVERIFIED;
+        return empty($this->group_id);
     }
 
     /**
@@ -28,7 +28,7 @@ class Model extends DataModel
     {
         return $this->group_id == $this->c->GROUP_GUEST
             || $this->id < 2
-            || $this->group_id == $this->c->GROUP_UNVERIFIED;
+            || empty($this->group_id);
     }
 
     /**

+ 7 - 8
app/Models/User/Save.php

@@ -70,20 +70,19 @@ class Save extends Action
      */
     public function insert(User $user)
     {
-        $modified = $user->getModified();
-        if (null !== $user->id || in_array('id', $modified)) {
+        if (null !== $user->id) {
             throw new RuntimeException('The model has ID');
         }
-        $values = $user->getAttrs();
+        $attrs  = $user->getAttrs();
         $fileds = $this->c->dbMap->users;
         $set = $set2 = $vars = [];
-        foreach ($modified as $name) {
-            if (! isset($fileds[$name])) {
+        foreach ($attrs as $key => $value) {
+            if (! isset($fileds[$key])) {
                 continue;
             }
-            $vars[] = $values[$name];
-            $set[] = $name;
-            $set2[] = '?' . $fileds[$name];
+            $vars[] = $value;
+            $set[]  = $key;
+            $set2[] = '?' . $fileds[$key];
         }
         if (empty($set)) {
             throw new RuntimeException('The model is empty');

+ 0 - 1
app/config/install.php

@@ -3,7 +3,6 @@
 return [
     'BASE_URL'    => 'http://forkbb.local',
     'DEBUG' => 1,
-    'GROUP_UNVERIFIED' => 0,
     'GROUP_ADMIN'      => 1,
     'GROUP_MOD'        => 2,
     'GROUP_GUEST'      => 3,

+ 0 - 1
app/config/main.dist.php

@@ -25,7 +25,6 @@ return [
     'JQUERY_LINK' => '//ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js',
     'DEBUG' => 1,
     'MAINTENANCE_OFF' => false,
-    'GROUP_UNVERIFIED' => 0,
     'GROUP_ADMIN' => 1,
     'GROUP_MOD' => 2,
     'GROUP_GUEST' => 3,

+ 26 - 8
app/lang/English/admin_groups.po

@@ -12,11 +12,11 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Language: en\n"
 
-msgid "Must enter title message"
+msgid "You must enter a group title"
 msgstr "You must enter a group title."
 
-msgid "Title already exists message"
-msgstr "There is already a group with the title <strong>%s</strong>."
+msgid "Title already exists"
+msgstr "There is already a group with this title."
 
 msgid "Default group redirect"
 msgstr "Default group set. Redirecting …"
@@ -69,14 +69,14 @@ msgstr "Edit"
 msgid "Delete link"
 msgstr "Delete"
 
-msgid "Group delete head"
+msgid "Group delete"
 msgstr "Group delete"
 
-msgid "Confirm delete subhead"
-msgstr "Confirm delete group"
+msgid "I want to delete this group"
+msgstr "Yes, I want to delete the group <b>%s</b>"
 
-msgid "Confirm delete info"
-msgstr "Are you sure that you want to delete the group <strong>%s</strong>?"
+msgid "Confirm delete"
+msgstr "Delete group?"
 
 msgid "Confirm delete warn"
 msgstr "WARNING! After you deleted a group you cannot restore it."
@@ -263,3 +263,21 @@ msgstr "Number of seconds that users in this group have to wait between reports.
 
 msgid "Moderator info"
 msgstr "Please note that in order for a user in this group to have moderator abilities, he/she must be assigned to moderate one or more forums. This is done via the user administration page of the user's profile."
+
+msgid "Delete-edit interval label"
+msgstr "Interval for editing/deleting"
+
+msgid "Delete-edit interval help"
+msgstr "Number of seconds to edit (delete) your messages or topics. Set to 0 to disable.<br>Moderators have no restrictions in the zone of responsibility."
+
+msgid "Create new group"
+msgstr "Create new group"
+
+msgid "Edit group"
+msgstr "Edit group"
+
+msgid "Invalid default group"
+msgstr "Invalid default group."
+
+msgid "Invalid group to create on base"
+msgstr "Invalid group to create on base."

+ 26 - 8
app/lang/Russian/admin_groups.po

@@ -12,11 +12,11 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Language: ru\n"
 
-msgid "Must enter title message"
+msgid "You must enter a group title"
 msgstr "Необходимо ввести заголовок группы."
 
-msgid "Title already exists message"
-msgstr "Уже есть группа с заголовком <strong>%s</strong>."
+msgid "Title already exists"
+msgstr "Уже есть группа с таким заголовком."
 
 msgid "Default group redirect"
 msgstr "Установлена группа по умолчанию. Переадресация …"
@@ -69,14 +69,14 @@ msgstr "Править"
 msgid "Delete link"
 msgstr "Удалить"
 
-msgid "Group delete head"
+msgid "Group delete"
 msgstr "Удаление группы"
 
-msgid "Confirm delete subhead"
-msgstr "Подтверждение удаления"
+msgid "I want to delete this group"
+msgstr "Да, я хочу удалить группу <b>%s</b>"
 
-msgid "Confirm delete info"
-msgstr "Вы действительно хотите удалить группу <strong>%s</strong>?"
+msgid "Confirm delete"
+msgstr "Удалить группу?"
 
 msgid "Confirm delete warn"
 msgstr "ВНИМАНИЕ! Удалённую группу невозможно восстановить."
@@ -263,3 +263,21 @@ msgstr "Количество секунд, которые необходимо 
 
 msgid "Moderator info"
 msgstr "Пожалуйста, обратите внимание, что пока пользователь не назначен модератором конкретного раздела, он не сможет реализовать свои модераторские права. Назначение производится в разделе "Модерация" пользовательского профиля."
+
+msgid "Delete-edit interval label"
+msgstr "Интервал для редактирования/удаления"
+
+msgid "Delete-edit interval help"
+msgstr "Количество секунд для редактирования (удаления) своих сообщений или тем. Поставьте 0 чтобы выключить ограничение.<br>Модераторы не имеют ограничений в зоне своей модерации."
+
+msgid "Create new group"
+msgstr "Создание новой группы"
+
+msgid "Edit group"
+msgstr "Редактирование группы"
+
+msgid "Invalid default group"
+msgstr "Недопустимая группа по умолчанию."
+
+msgid "Invalid group to create on base"
+msgstr "Недопустимая группа для создания на основании."

+ 3 - 34
app/templates/admin/group.tpl

@@ -1,40 +1,9 @@
 @extends ('layouts/admin')
       <section class="f-admin">
-        <h2>{!! __('Group settings head') !!}</h2>
+        <h2>{!! $p->titleForm !!}</h2>
         <div class="f-fdiv">
-          <form class="f-form" method="post" action="{!! $p->formAction !!}">
-            <input type="hidden" name="token" value="{!! $p->formToken !!}">
-            <dl>
-@foreach ($p->form as $key => $cur)
-              <dt>{!! $cur['title'] !!}</dt>
-              <dd>
-  @if ($cur['type'] == 'text')
-                <input class="f-ctrl" @if (isset($cur['required'])) required @endif type="text" name="{{ $key }}" maxlength="{!! $cur['maxlength'] !!}" value="{{ $cur['value'] }}" tabindex="{!! ++$p->tabindex !!}">
-  @elseif ($cur['type'] == 'number')
-                <input class="f-ctrl" type="number" name="{{ $key }}" min="{!! $cur['min'] !!}" max="{!! $cur['max'] !!}" value="{{ $cur['value'] }}" tabindex="{!! ++$p->tabindex !!}">
-  @elseif ($cur['type'] == 'select')
-                <select class="f-ctrl" name="{{ $key }}" tabindex="{!! ++$p->tabindex !!}">
-    @foreach ($cur['options'] as $v => $n)
-                  <option value="{{ $v }}" @if ($v == $cur['value']) selected @endif>{{ $n }}</option>
-    @endforeach
-                </select>
-  @elseif ($cur['type'] == 'radio')
-    @foreach ($cur['values'] as $v => $n)
-                <label class="f-label"><input type="radio" name="{{ $key }}" value="{{ $v }}" @if ($v == $cur['value']) checked @endif tabindex="{!! ++$p->tabindex !!}">{{ $n }}</label>
-    @endforeach
-  @endif
-  @if (isset($cur['info']))
-                <span class="f-child4">{!! $cur['info'] !!}</span>
-  @endif
-              </dd>
-@endforeach
-            </dl>
-@if ($p->warn)
-            <p class="f-finfo">{!! $p->warn !!}</p>
+@if ($form = $p->form)
+  @include ('layouts/form')
 @endif
-            <div>
-              <input class="f-btn" type="submit" name="submit" value="{!! __('Save') !!}" tabindex="{!! ++$p->tabindex !!}">
-            </div>
-          </form>
         </div>
       </section>

+ 9 - 0
app/templates/admin/group_delete.tpl

@@ -0,0 +1,9 @@
+@extends ('layouts/admin')
+      <section class="f-admin">
+        <h2>{!! __('Group delete') !!}</h2>
+        <div class="f-fdiv">
+@if ($form = $p->form)
+  @include ('layouts/form')
+@endif
+        </div>
+      </section>

+ 8 - 36
app/templates/admin/groups.tpl

@@ -2,45 +2,17 @@
       <section class="f-admin">
         <h2>{!! __('Add group subhead') !!}</h2>
         <div class="f-fdiv">
-          <form class="f-form" method="post" action="{!! $p->formActionNew !!}">
-            <input type="hidden" name="token" value="{!! $p->formTokenNew !!}">
-            <dl>
-              <dt>{!! __('New group label') !!}</dt>
-              <dd>
-                <select class="f-ctrl" id="id-basegroup" name="basegroup" tabindex="{!! ++$p->tabindex !!}">
-@foreach ($p->groupsNew as $cur)
-                  <option value="{!! $cur[0] !!}" @if ($cur[0] == $p->defaultGroup) selected @endif>{{ $cur[1] }}</option>
-@endforeach
-                </select>
-                <span class="f-child4">{!! __('New group help') !!}</span>
-              </dd>
-            </dl>
-            <div>
-              <input class="f-btn" type="submit" name="submit" value="{!! __('Add') !!}" tabindex="{!! ++$p->tabindex !!}">
-            </div>
-          </form>
+@if ($form = $p->formNew)
+  @include ('layouts/form')
+@endif
         </div>
       </section>
       <section class="f-admin">
         <h2>{!! __('Default group subhead') !!}</h2>
         <div class="f-fdiv">
-          <form class="f-form" method="post" action="{!! $p->formActionDefault !!}">
-            <input type="hidden" name="token" value="{!! $p->formTokenDefault !!}">
-            <dl>
-              <dt>{!! __('Default group label') !!}</dt>
-              <dd>
-                <select class="f-ctrl" id="id-defaultgroup" name="defaultgroup" tabindex="{!! ++$p->tabindex !!}">
-@foreach ($p->groupsDefault as $cur)
-                  <option value="{!! $cur[0] !!}" @if ($cur[0] == $p->defaultGroup) selected @endif>{{ $cur[1] }}</option>
-@endforeach
-                </select>
-                <span class="f-child4">{!! __('Default group help') !!}</span>
-              </dd>
-            </dl>
-            <div>
-              <input class="f-btn" type="submit" name="submit" value="{!! __('Save') !!}" tabindex="{!! ++$p->tabindex !!}">
-            </div>
-          </form>
+@if ($form = $p->formDefault)
+  @include ('layouts/form')
+@endif
         </div>
       </section>
       <section class="f-admin">
@@ -50,9 +22,9 @@
           <ol class="f-grlist">
 @foreach ($p->groupsList as $cur)
             <li>
-              <a href="{!! $cur[0] !!}" tabindex="{!! ++$p->tabindex !!}">{{ $cur[1] }}</a>
+              <a href="{!! $cur[1] !!}">{{ $cur[0] }}</a>
   @if ($cur[2])
-              <a class="f-btn" href="{!! $cur[2] !!}" tabindex="{!! ++$p->tabindex !!}">{!! __('Delete link') !!}</a>
+              <a class="f-btn" href="{!! $cur[2] !!}">{!! __('Delete link') !!}</a>
   @endif
             </li>
 @endforeach

+ 15 - 9
app/templates/admin/index.tpl

@@ -16,14 +16,20 @@
           </ul>
         </div>
         <h2>{!! __('About head') !!}</h2>
-        <div>
-          <dl>
-            <dt>{!! __('ForkBB version label') !!}</dt>
-            <dd>{!! __('ForkBB version data', $p->revision) !!}</dd>
-            <dt>{!! __('Server statistics label') !!}</dt>
-            <dd><a href="{!! $p->linkStat !!}">{!! __('View server statistics') !!}</a></dd>
-            <dt>{!! __('Support label') !!}</dt>
-            <dd><a href="https://github.com/forkbb/forkbb">GitHub</a></dd>
-          </dl>
+        <div class="f-fdiv">
+          <fieldset>
+            <dl>
+              <dt>{!! __('ForkBB version label') !!}</dt>
+              <dd>{!! __('ForkBB version data', $p->revision) !!}</dd>
+            </dl>
+            <dl>
+              <dt>{!! __('Server statistics label') !!}</dt>
+              <dd><a href="{!! $p->linkStat !!}">{!! __('View server statistics') !!}</a></dd>
+            </dl>
+            <dl>
+              <dt>{!! __('Support label') !!}</dt>
+              <dd><a href="https://github.com/forkbb/forkbb">GitHub</a></dd>
+            </dl>
+          </fieldset>
         </div>
       </section>

+ 26 - 20
app/templates/admin/statistics.tpl

@@ -1,36 +1,42 @@
 @extends ('layouts/admin')
       <section class="f-admin">
         <h2>{!! __('Server statistics head') !!}</h2>
-        <div>
-          <dl>
-            <dt>{!! __('Server load label') !!}</dt>
-            <dd>{!! __('Server load data', $p->serverLoad, $p->numOnline) !!}</dd>
+        <div class="f-fdiv">
+          <fieldset>
+            <dl>
+              <dt>{!! __('Server load label') !!}</dt>
+              <dd>{!! __('Server load data', $p->serverLoad, $p->numOnline) !!}</dd>
+            </dl>
 @if ($p->isAdmin)
-            <dt>{!! __('Environment label') !!}</dt>
-            <dd>
-              {!! __('Environment data OS', PHP_OS) !!}<br>
-              {!! __('Environment data version', PHP_VERSION) !!} - <a href="{!! $p->linkInfo !!}">{!! __('Show info') !!}</a><br>
+            <dl>
+              <dt>{!! __('Environment label') !!}</dt>
+              <dd>
+                {!! __('Environment data OS', PHP_OS) !!}<br>
+                {!! __('Environment data version', PHP_VERSION) !!} - <a href="{!! $p->linkInfo !!}">{!! __('Show info') !!}</a><br>
   @if ($p->linkAcc)
-              {!! __('Environment data acc') !!} <a href="{!! $p->linkAcc !!}">{{ $p->accelerator }}</a>
+                {!! __('Environment data acc') !!} <a href="{!! $p->linkAcc !!}">{{ $p->accelerator }}</a>
   @else
-              {!! __('Environment data acc') !!} {{ $p->accelerator }}
+                {!! __('Environment data acc') !!} {{ $p->accelerator }}
   @endif
-            </dd>
-            <dt>{!! __('Database label') !!}</dt>
-            <dd>
-              {{ $p->dbVersion }}
+              </dd>
+            </dl>
+            <dl>
+              <dt>{!! __('Database label') !!}</dt>
+              <dd>
+                {{ $p->dbVersion }}
   @if ($p->tRecords && $p->tSize)
-              <br>{!! __('Database data rows', num($p->tRecords)) !!}
-              <br>{!! __('Database data size', size($p->tSize)) !!}
+                <br>{!! __('Database data rows', num($p->tRecords)) !!}
+                <br>{!! __('Database data size', size($p->tSize)) !!}
   @endif
   @if ($p->tOther)
-              <br><br>{!! __('Other')!!}
+                <br><br>{!! __('Other')!!}
     @foreach ($p->tOther as $key => $value)
-              <br>{{ $key }} = {{ $value }}
+                <br>{{ $key }} = {{ $value }}
     @endforeach
   @endif
-            </dd>
+              </dd>
 @endif
-          </dl>
+            </dl>
+          </fieldset>
         </div>
       </section>

+ 1 - 1
app/templates/change_passphrase.tpl

@@ -19,7 +19,7 @@
               </dd>
             </dl>
           </fieldset>
-          <p>
+          <p class="f-btns">
             <input class="f-btn" type="submit" name="login" value="{!! __('Change passphrase') !!}" tabindex="3">
           </p>
         </form>

+ 16 - 4
app/templates/layouts/form.tpl

@@ -22,7 +22,7 @@
             <dl @if (isset($cur['dl'])) class="f-field-{{ $cur['dl'] }}" @endif>
               <dt> @if (isset($cur['title']))<label class="f-child1 @if (isset($cur['required'])) f-req @endif" for="id-{{ $key }}">{!! $cur['title'] !!}</label> @endif</dt>
               <dd>
-      @if ($cur['type'] === 'textarea')
+      @if ('textarea' === $cur['type'])
                 <textarea @if (isset($cur['required'])) required @endif @if (isset($cur['autofocus'])) autofocus @endif class="f-ctrl" id="id-{{ $key }}" name="{{ $key }}">{{ $cur['value'] or '' }}</textarea>
         @if (isset($cur['bb']))
                 <ul class="f-child5">
@@ -31,10 +31,22 @@
           @endforeach
                 </ul>
         @endif
-      @elseif ($cur['type'] === 'text')
+      @elseif ('select' === $cur['type'])
+                <select @if (isset($cur['required'])) required @endif @if (isset($cur['autofocus'])) autofocus @endif class="f-ctrl" id="id-{{ $key }}" name="{{ $key }}">
+        @foreach ($cur['options'] as $v => $n)
+                  <option value="{{ $v }}" @if ($v == $cur['value']) selected @endif>{{ $n }}</option>
+        @endforeach
+                </select>
+      @elseif ('text' === $cur['type'])
                 <input @if (isset($cur['required'])) required @endif @if (isset($cur['autofocus'])) autofocus @endif class="f-ctrl" id="id-{{ $key }}" name="{{ $key }}" type="text" @if (! empty($cur['maxlength'])) maxlength="{{ $cur['maxlength'] }}" @endif @if (isset($cur['pattern'])) pattern="{{ $cur['pattern'] }}" @endif @if (isset($cur['value'])) value="{{ $cur['value'] }}" @endif>
-      @elseif ($cur['type'] === 'checkbox')
+      @elseif ('number' === $cur['type'])
+                <input @if (isset($cur['required'])) required @endif @if (isset($cur['autofocus'])) autofocus @endif class="f-ctrl" id="id-{{ $key }}" name="{{ $key }}" type="number" min="{{ $cur['min'] }}" max="{{ $cur['max'] }}" @if (isset($cur['value'])) value="{{ $cur['value'] }}" @endif>
+      @elseif ('checkbox' === $cur['type'])
                 <label class="f-child2"><input @if (isset($cur['autofocus'])) autofocus @endif type="checkbox" id="id-{{ $key }}" name="{{ $key }}" value="{{ $cur['value'] or '1' }}" @if (! empty($cur['checked'])) checked @endif>{!! $cur['label'] !!}</label>
+      @elseif ('radio' === $cur['type'])
+        @foreach ($cur['values'] as $v => $n)
+                <label class="f-label"><input @if (isset($cur['autofocus'])) autofocus @endif type="radio" id="id-{{ $key }}-{{ $v }}" name="{{ $key }}" value="{{ $v }}" @if ($v == $cur['value']) checked @endif>{{ $n }}</label>
+        @endforeach
       @endif
       @if (isset($cur['info']))
                 <p class="f-child4">{!! $cur['info'] !!}</p>
@@ -45,7 +57,7 @@
           </fieldset>
   @endif
 @endforeach
-          <p>
+          <p class="f-btns">
 @foreach ($form['btns'] as $key => $cur)
             <input class="f-btn @if(isset($cur['class'])) {{ $cur['class'] }} @endif" type="{{ $cur['type'] }}" name="{{ $key }}" value="{{ $cur['value'] }}" @if (isset($cur['accesskey'])) accesskey="{{ $cur['accesskey'] }}" @endif>
 @endforeach

+ 1 - 1
app/templates/login.tpl

@@ -27,7 +27,7 @@
 @endif
             </dl>
           </fieldset>
-          <p>
+          <p class="f-btns">
             <input class="f-btn" type="submit" name="login" value="{!! __('Sign in') !!}" tabindex="4">
           </p>
         </form>

+ 1 - 1
app/templates/passphrase_reset.tpl

@@ -13,7 +13,7 @@
               </dd>
             </dl>
           </fieldset>
-          <p>
+          <p class="f-btns">
             <input class="f-btn" type="submit" name="submit" value="{!! __('Send email') !!}" tabindex="2">
           </p>
         </form>

+ 1 - 1
app/templates/register.tpl

@@ -29,7 +29,7 @@
               </dd>
             </dl>
           </fieldset>
-          <p>
+          <p class="f-btns">
             <input class="f-btn" type="submit" name="register" value="{!! __('Sign up') !!}" tabindex="4">
           </p>
         </form>

+ 1 - 1
app/templates/rules.tpl

@@ -12,7 +12,7 @@
               <dd><label class="f-child2"><input type="checkbox" name="agree" value="{!! $p->formHash !!}" tabindex="1">{!! __('Agree') !!}</label></dd>
             </dl>
           </fieldset>
-          <p>
+          <p class="f-btns">
             <input class="f-btn" type="submit" name="register" value="{!! __('Register') !!}" tabindex="2">
           </p>
         </form>

+ 93 - 27
public/style/ForkBB/style.css

@@ -94,10 +94,35 @@ html {
 }
 
 h1, h2, h3 {
-  font-family: "Segoe Print", "Flow Ext";
   font-weight: bold;
 }
 
+h2 {
+  font-size: 1.25rem;
+}
+
+h3 {
+  font-size: 1rem;
+}
+
+.f-header h1, 
+.f-category h2, 
+.f-category h3 {
+  font-family: "Segoe Print", "Flow Ext";
+}
+
+.f-header h1 {
+  font-size: 2rem;
+}
+
+.f-category h2 {
+  font-size: 1.5rem
+}
+
+.f-category h3 {
+  font-size: 1.25rem;
+}
+
 .f-wrap {
   padding: 0 0.3125rem;
   max-width: 64rem;
@@ -392,27 +417,31 @@ select {
 }
 
 .f-fdiv h2,
-.f-fdiv .f-form {
-  padding: 0.625rem;
+.f-fdiv fieldset {
+  padding: 0.625rem 0.625rem 0 0.625rem;
 }
 
 .f-fdiv h3 {
   padding: 0.625rem 0.625rem 0 0.625rem;
 }
 
+.f-fdiv dl {
+  padding: 0 0 0.625rem 0;
+}
+
 .f-fdiv .f-ctrl,
 .f-fdiv .f-btn {
   padding: 0.5rem;
   font-size: 1rem;
   display: block;
   width: 100%;
-  margin-bottom: 1rem;
+/*  margin-bottom: 1rem; */
   box-sizing: border-box;
 }
 
 .f-fdiv .f-label {
   font-size: 1rem;
-  margin-bottom: 1rem;
+/*  margin-bottom: 1rem; */
   display: inline-block;
 }
 
@@ -447,8 +476,12 @@ select {
   margin: 0 0.625rem 0 0;
 }
 
+.f-fdiv .f-btns {
+  padding: 0 0.625rem;
+}
+
 .f-fdiv .f-btn {
-  margin: 1rem 0 0.375rem 0;
+  margin: 0.625rem 0;
 }
 
 .f-fdiv .f-child3 {
@@ -459,27 +492,30 @@ select {
 
 .f-fdiv .f-child4 {
   font-size: 0.8125rem;
+  margin-top: 0.3125rem;
   text-align: justify;
 }
 
 .f-fdiv .f-child5 {
-  margin-top: -0.375rem;
-  margin-bottom: 1rem
+/*  margin-top: -0.375rem; */
+/*  margin-bottom: 1rem */
+  padding-top: 0.3125rem;
 }
 
 .f-fdiv .f-finfo {
-  margin: -0.625rem -0.625rem 1rem -0.625rem;
+/*  margin: -0.625rem -0.625rem 1rem -0.625rem; */
   background-color: #AA7939;
   padding: 0.625rem;
   color: #F8F4E3;
+  margin-bottom: 0.625rem;
 }
 
-.f-finfo + .f-finfo {
-  margin-top: -1rem;
+.f-fdiv .f-finfo + .f-finfo {
+  margin-top: -0.625rem;
 }
 
-fieldset + .f-finfo {
-  margin-top: 1rem;
+.f-fdiv fieldset + .f-finfo {
+/*  margin-top: 0.625rem; */
 }
 
 .f-ctrl {
@@ -487,7 +523,7 @@ fieldset + .f-finfo {
 }
 
 .f-ctrl:focus {
-  box-shadow: inset 0px 0px 0.25rem 0 rgba(170,121,57,0.5), 0px 0px 0.25rem 0 rgba(170,121,57,0.5);
+  box-shadow: inset 0 0 0.5rem 0 rgba(170,121,57,0.75), 0 0 0.5rem 0 rgba(170,121,57,0.75); 
 }
 
 .f-ctrl + .f-fhint {
@@ -501,9 +537,10 @@ fieldset + .f-finfo {
 
 .f-ctrl:focus + .f-fhint,
 .f-ctrl:active + .f-fhint {
-  margin-top: -0.375rem;
-  margin-bottom: 1rem;
-  max-height: 1000rem;
+/*  margin-top: 0.3125rem; */
+/*  margin-bottom: -0.625rem; */
+  
+  max-height: 10rem;
 }
 
 /**************/
@@ -750,7 +787,7 @@ fieldset + .f-finfo {
   text-align: center;
   border: 0;
   white-space: nowrap;
-  font-size: 1.125rem;
+/*  font-size: 1.125rem; */
   text-transform: uppercase;
 }
 
@@ -821,20 +858,36 @@ fieldset + .f-finfo {
 }
 
 .f-admin dl {
-  margin: 0 0.625rem 0.625rem 0.625rem;
+/*  margin: 0 0.625rem 0.625rem 0.625rem; */
+  border-bottom: 0.0625rem dotted #AA7939;
+  margin-bottom: 0.625rem;
+}
+
+.f-admin dl:before,
+.f-admin dl:after {
+  content: " ";
+  display: table;
+}
+
+.f-admin dl:after {
+  clear: both;
 }
 
 .f-admin dt {
-  padding-top: 0.625rem;
+/*  padding-top: 0.625rem; */
 }
 
 .f-admin dd {
-  padding: 0.625rem 0;
-  border-bottom: 0.0625rem dotted #AA7939;
+/*  padding: 0.625rem 0; */
+/*  border-bottom: 0.0625rem dotted #AA7939; */
 }
 
 .f-admin .f-fdiv dl {
-  margin: 0;
+/*  margin: 0; */
+}
+
+.f-admin .f-fdiv .f-child2 {
+  font-size: 1rem;
 }
 
 .f-grlist {
@@ -861,9 +914,22 @@ fieldset + .f-finfo {
     float: left;
     width: 14rem;
   }
+
   .f-admin dd {
     padding-left: 14.625rem;
   }
+
+  .f-admin .f-fdiv .f-child1 {
+    font-weight: normal;
+  }
+
+  .f-field-full dt {
+    display: none;
+  }
+
+  .f-field-full dd {
+    padding-left: 0;
+  }
 }
 
 /*********************/
@@ -1139,7 +1205,7 @@ fieldset + .f-finfo {
 }
 
 .f-forum h3 {
-  font-family: Arial, Helvetica, sans-serif;
+/*  font-family: Arial, Helvetica, sans-serif;  */
   font-weight: normal;
   font-size: 1rem;
   position: relative;
@@ -1395,7 +1461,7 @@ li + li .f-btn {
 }
 
 .f-preview > h2 {
-  font-family: Arial, Helvetica, sans-serif;
+/**  font-family: Arial, Helvetica, sans-serif; */
   font-size: 1rem;
   line-height: 1.5;
   padding: 1rem 0.625rem 0.3125rem 0.625rem
@@ -1424,7 +1490,7 @@ li + li .f-btn {
 
 .f-post-form > h2,
 .f-view-posts > h2 {
-  font-family: Arial, Helvetica, sans-serif;
+/**  font-family: Arial, Helvetica, sans-serif; */
   font-size: 1rem;
   padding-right: 0.625rem;
   padding: 1rem 0.625rem 0.3125rem 0.625rem
@@ -1437,7 +1503,7 @@ li + li .f-btn {
 
 .f-post-form legend {
   width: 100%;
-  padding-bottom: 0.625rem;
+  padding: 0.625rem 0 0.3125rem 0;
   margin-bottom: 0.625rem;
   border-bottom: 0.0625rem dotted #AA7939;
   font-weight: bold;