From ab5d2efacd21ed01899c066b88abff03aac850f0 Mon Sep 17 00:00:00 2001 From: Alexander Yakovlev Date: Tue, 11 Oct 2016 12:12:01 +0700 Subject: [PATCH] Group CRUD --- application/classes/Controller/Client.php | 38 +++-- application/classes/Controller/Group.php | 99 +++++++++++++ application/classes/Form.php | 14 +- application/classes/Model/Client.php | 11 ++ application/classes/Model/Group.php | 10 +- application/classes/View/Client/Index.php | 21 +++ application/classes/View/Index.php | 16 ++- application/classes/View/Layout.php | 7 +- application/i18n/ru.php | 5 +- application/scss/layout.scss | 12 ++ application/templates/client/index.mustache | 22 ++- application/templates/form/select.mustache | 2 +- application/templates/index.mustache | 26 ++-- composer.json | 3 +- composer.lock | 147 ++++++++++++++++++-- 15 files changed, 360 insertions(+), 73 deletions(-) create mode 100644 application/classes/Controller/Group.php diff --git a/application/classes/Controller/Client.php b/application/classes/Controller/Client.php index 5666d4c..d124316 100644 --- a/application/classes/Controller/Client.php +++ b/application/classes/Controller/Client.php @@ -6,7 +6,6 @@ class Controller_Client extends Controller_Layout { protected $secure_actions = array( 'index', - 'group', 'create', 'edit', 'delete', @@ -21,18 +20,22 @@ class Controller_Client extends Controller_Layout { { $this->template = new View_Client_Index; $this->template->title = __('Clients'); - $this->template->items = ORM::factory('Client') - ->filter_by_page($this->request->param('page')) - ->find_all(); - } - - public function action_group() - { - $this->template = new View_Client_Index; - $this->template->title = __('Clients'); - $this->template->items = ORM::factory('Client') - ->filter_by_page($this->request->param('page')) - ->find_by_group($this->request->param('group_id')); + $group_id = $this->request->post('group_id'); + if ($group_id) { + $group = ORM::factory('Group', $group_id); + if (!$group->loaded()) { + $this->redirect('error/404'); + } + $this->template->title .= ' - ' . $group->name; + $this->template->items = $group + ->clients + ->filter_by_page($this->request->param('page')) + ->find_all(); + } else { + $this->template->items = ORM::factory('Client') + ->filter_by_page($this->request->param('page')) + ->find_all(); + } } /** @@ -74,7 +77,7 @@ class Controller_Client extends Controller_Layout { $confirmation = $this->request->post('confirmation'); if ($confirmation === 'yes') { - $post->delete(); + $model->delete(); $this->redirect('/'); } } @@ -93,11 +96,4 @@ class Controller_Client extends Controller_Layout { ->filter_by_page($this->request->param('page')) ->find_all(); } - - /** - * Unsubscription link action. - **/ - public function action_unsubscribe() - { - } } diff --git a/application/classes/Controller/Group.php b/application/classes/Controller/Group.php new file mode 100644 index 0000000..a21bd7c --- /dev/null +++ b/application/classes/Controller/Group.php @@ -0,0 +1,99 @@ + 'input', + ); + public function action_index() + { + $this->template = new View_Index; + $this->template->title = __('Groups'); + $this->template->header = [ + __('Group name'), + __('Edit'), + __('Delete'), + ]; + $this->template->items = ORM::factory('Group') + ->filter_by_page($this->request->param('page')) + ->find_all(); + } + + /** + * Manually add a group. + **/ + public function action_create() + { + $this->template = new View_Edit; + $this->template->model = ORM::factory('Group'); + $this->template->title = __('New group'); + $this->_edit($this->template->model); + } + + public function action_edit() + { + $this->template = new View_Edit; + $this->template->title = __('Edit group info'); + $id = $this->request->param('id'); + $model = ORM::factory('Group', $id); + if (!$model->loaded()) + { + $this->redirect('error/404'); + } + $this->_edit($model); + } + + public function action_delete() + { + $this->template = new View_Delete; + $id = $this->request->param('id'); + $model = ORM::factory('Group', $id); + if (!$model->loaded()) + { + $this->redirect('error/404'); + } + $this->template->title = __('Delete group'); + $this->template->content_title = $model->name; + // $this->template->content = $model->email; + // TODO - display a list of subscribers in group + + $confirmation = $this->request->post('confirmation'); + if ($confirmation === 'yes') { + $model->delete(); + $this->redirect('/'); + } + } + + /** + * Group view. + **/ + public function action_view() + { + $this->redirect('client/index?group_id='.$this->request->param('id')); + } + + /** + * Search groups. + **/ + public function action_search() + { + $this->template = new View_Client_Index; + $this->template->show_create = FALSE; + $this->template->title = __('Groups'); + $query = $this->request->post('query'); + $this->template->items = ORM::factory('Group') + ->search($query) + ->filter_by_page($this->request->param('page')) + ->find_all(); + } +} diff --git a/application/classes/Form.php b/application/classes/Form.php index 544bca2..333e4ac 100644 --- a/application/classes/Form.php +++ b/application/classes/Form.php @@ -1,10 +1,10 @@ -name = $name; $template->label = __(Arr::get($attributes, 'label')); $template->options = array(); - foreach ($options as $name => $value) + foreach ($options as $value => $text) { $template->options[] = array( - 'name' => $name, 'value' => $value, - 'is_selected' => ($name == $selected) + 'text' => $text, + 'is_selected' => ($value == $selected) ); } return self::render_control($template); @@ -214,7 +214,7 @@ class Form extends Kohana_Form { { return self::btn('submit', __($text), 'primary', 'submit'); } - + protected static function render_control($template) { $renderer = Kostache_Layout::factory('form/control'); diff --git a/application/classes/Model/Client.php b/application/classes/Model/Client.php index fe38916..536f65d 100644 --- a/application/classes/Model/Client.php +++ b/application/classes/Model/Client.php @@ -65,4 +65,15 @@ class Model_Client extends ORM { ->or_where(DB::expr('LOWER(email)'), 'LIKE', strtolower($query)); } + /** + * A function to search by group ID + * @param int $group_id + */ + public function find_by_group($group_id) { + return $this + ->with('groups') + ->find() + ->where('groups.id', '=', (int) $group_id); + } + } diff --git a/application/classes/Model/Group.php b/application/classes/Model/Group.php index f639990..88c9027 100644 --- a/application/classes/Model/Group.php +++ b/application/classes/Model/Group.php @@ -19,10 +19,10 @@ class Model_Group extends ORM { public function rules() { return array( - 'title' => array( - array('not_empty'), - array('min_length', array(':value', 4)), - array('max_length', array(':value', 255)), + 'name' => array( + array('not_empty'), + array('min_length', array(':value', 4)), + array('max_length', array(':value', 255)), ), ); } @@ -32,7 +32,7 @@ class Model_Group extends ORM { * Used in forms. **/ protected $_labels = array( - 'title' => 'Title', + 'name' => 'Name', ); public static function count($id) diff --git a/application/classes/View/Client/Index.php b/application/classes/View/Client/Index.php index 3ddbdfe..3a6fcdb 100644 --- a/application/classes/View/Client/Index.php +++ b/application/classes/View/Client/Index.php @@ -9,6 +9,27 @@ class View_Client_Index extends View_Index { protected $is_admin = TRUE; // admin only view public $show_date = FALSE; public $subscription_id; + public $group; + public function get_header() + { + return array( + __('Name'), + __('Email'), + __('Edit'), + __('Delete') + ); + } + + /** + * Group search field + */ + public function groups() { + return Form::open() + . Form::select('group_id', ORM::factory('Group')->find_all()->as_array('id', 'name')) + . Form::submit('s', __('Submit')) + . Form::close(); + } + /** * An internal function to prepare item data. **/ diff --git a/application/classes/View/Index.php b/application/classes/View/Index.php index bfa56d3..646bc21 100644 --- a/application/classes/View/Index.php +++ b/application/classes/View/Index.php @@ -22,6 +22,10 @@ class View_Index extends View_Layout { * Index description **/ public $content = ''; + /** + * Table header + */ + public $header = NULL; protected $is_admin; @@ -51,6 +55,14 @@ class View_Index extends View_Layout { return $output; } + /** + * Table header + */ + public function get_header() + { + return $this->header; + } + public function get_items() { $result = array(); @@ -87,10 +99,6 @@ class View_Index extends View_Layout { $output = array( 'view_link' => HTML::anchor(Route::url('default', array('controller' => Request::current()->controller(), 'action' => 'view','id' => $item->id)), $item->name, array('class' => 'link_view')), ); - if ($this->show_date) - { - $output['date'] = $item->posted_at; - } if ($this->is_admin and $this->show_edit) { $output['edit_link'] = HTML::anchor(Route::url('default', array('controller' => Request::current()->controller(), 'action' => 'edit','id' => $item->id)), __('Edit'), array('class' => 'link_edit')); diff --git a/application/classes/View/Layout.php b/application/classes/View/Layout.php index a4da51d..ea53fea 100644 --- a/application/classes/View/Layout.php +++ b/application/classes/View/Layout.php @@ -11,12 +11,12 @@ class View_Layout { public $base_scripts = array( ); public $errors; - + /** * Inherited paging function **/ public function get_paging() {} - + public function has_errors() { return !empty($this->errors); @@ -80,6 +80,7 @@ class View_Layout { __('Courses') => 'course/index', __('Subscriptions') => 'subscription/index', __('Clients') => 'client/index', + __('Groups') => 'group/index', )); } @@ -121,7 +122,7 @@ class View_Layout { return array( 'button_text' => __('Submit'), 'input_text' => __('Search'), - 'action' => Route::url('default', array('controller' => 'Client', 'action' => 'search')) + 'action' => Route::url('default', array('controller' => 'Client', 'action' => 'search')) ); } } diff --git a/application/i18n/ru.php b/application/i18n/ru.php index 88f0c9b..6c9fa5c 100644 --- a/application/i18n/ru.php +++ b/application/i18n/ru.php @@ -73,5 +73,8 @@ return array( 'Your e-mail' => 'Ваш адрес электронной почты', 'Tired of receiving these emails? Click this link to unsubscribe.' => 'Устали получать эти письма? Нажмите на эту ссылку для отписки.', 'Client not found. Possible subscription token problem.' => 'Клиент не найден. Возможна проблема с токеном подписки.', - 'You have been successfully unsubscribed from course %s' => 'Вы были успешно отписаны от курса %s' + 'You have been successfully unsubscribed from course %s' => 'Вы были успешно отписаны от курса %s', + 'Groups' => 'Группы', + 'Group name' => 'Название группы', + 'Delete group' => 'Удалить группу', ); diff --git a/application/scss/layout.scss b/application/scss/layout.scss index 35a6cb0..ac0bd6c 100644 --- a/application/scss/layout.scss +++ b/application/scss/layout.scss @@ -56,3 +56,15 @@ footer { } } } +.groupform { + margin-top: -3em; + float: right; + width: 50%; + .form-group { + width: 50%; + display: inline-block; + } + input { + margin-right: 1em; + } +} diff --git a/application/templates/client/index.mustache b/application/templates/client/index.mustache index c0e63f9..4df5834 100644 --- a/application/templates/client/index.mustache +++ b/application/templates/client/index.mustache @@ -1,10 +1,21 @@ -{{#show_create}} - {{{link_new}}} -{{/show_create}} -
- {{{content}}} +
+ {{{groups}}}
+{{#show_create}} +

{{{link_new}}}

+{{/show_create}} +{{#content}} +
+ {{{.}}} +
+{{/content}} + +{{#get_header}} + +{{/get_header}} + + {{#get_items}} @@ -15,4 +26,5 @@ {{/edit_link}} {{/get_items}} +
{{.}}
{{{view_link}}}
diff --git a/application/templates/form/select.mustache b/application/templates/form/select.mustache index 45b244f..d34c620 100644 --- a/application/templates/form/select.mustache +++ b/application/templates/form/select.mustache @@ -1,5 +1,5 @@ diff --git a/application/templates/index.mustache b/application/templates/index.mustache index c36d142..a5db106 100644 --- a/application/templates/index.mustache +++ b/application/templates/index.mustache @@ -4,17 +4,23 @@
{{{content}}}
-
+ + +{{#get_header}} + +{{/get_header}} + + {{#get_items}} -
- {{#date}} -
{{date}}
- {{/date}} -
{{{view_link}}}
+
+ {{#edit_link}} -
{{{edit_link}}}
-
{{{delete_link}}}
+ + {{/edit_link}} - + {{/get_items}} - + +
+ {{.}} +
{{{view_link}}}{{{edit_link}}}{{{delete_link}}}
diff --git a/composer.json b/composer.json index 4e6b06e..a4e3fa5 100644 --- a/composer.json +++ b/composer.json @@ -42,7 +42,8 @@ "require-dev": { "phing/phing": "dev-master", "kohana/unittest": "3.4.*", - "kohana/userguide": "3.4.*" + "kohana/userguide": "3.4.*", + "kohana/coding-standards": "*" }, "minimum-stability": "dev", "extra": { diff --git a/composer.lock b/composer.lock index b8074a0..7115f8a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "370816fa629c0856ac1c68ef503cd333", - "content-hash": "37236e1d636299186f13be656b62c8fa", + "hash": "cdd5d55f92469dea3bcd533ffcd17fde", + "content-hash": "05d74ec93f60bdb8b4c933cbc4b857f6", "packages": [ { "name": "composer/installers", @@ -637,12 +637,12 @@ "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "607ce1d4005af32dd866c4a402459494c168d555" + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/607ce1d4005af32dd866c4a402459494c168d555", - "reference": "607ce1d4005af32dd866c4a402459494c168d555", + "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", "shasum": "" }, "require": { @@ -676,7 +676,7 @@ "psr", "psr-3" ], - "time": "2016-09-25 13:41:54" + "time": "2016-10-10 12:19:37" }, { "name": "swiftmailer/swiftmailer", @@ -989,6 +989,48 @@ ], "time": "2016-03-31 10:24:22" }, + { + "name": "kohana/coding-standards", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/kohana/coding-standards.git", + "reference": "5cbecdfce7f238c59d3eeb12fd5d4457e1b05c30" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/kohana/coding-standards/zipball/5cbecdfce7f238c59d3eeb12fd5d4457e1b05c30", + "reference": "5cbecdfce7f238c59d3eeb12fd5d4457e1b05c30", + "shasum": "" + }, + "require": { + "squizlabs/php_codesniffer": "1.*" + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kohana Team", + "email": "team@kohanaframework.org", + "homepage": "http://www.kohanaframework.org", + "role": "Maintainer" + } + ], + "description": "PHP_CodeSniffer rules for the Kohana Framework coding style", + "homepage": "https://github.com/kohana/coding-standards", + "keywords": [ + "Code style", + "code standard", + "coding stanards", + "kohana", + "phpcs", + "standards" + ], + "time": "2014-05-27 16:40:02" + }, { "name": "kohana/unittest", "version": "dev-3.4/develop", @@ -1156,12 +1198,12 @@ "source": { "type": "git", "url": "https://github.com/phingofficial/phing.git", - "reference": "ea5617995882f0e0f90e5ba94dc4d1948c84388a" + "reference": "74af0362988dfd6c53eaf7f6ade823d8e7d40348" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phingofficial/phing/zipball/ea5617995882f0e0f90e5ba94dc4d1948c84388a", - "reference": "ea5617995882f0e0f90e5ba94dc4d1948c84388a", + "url": "https://api.github.com/repos/phingofficial/phing/zipball/74af0362988dfd6c53eaf7f6ade823d8e7d40348", + "reference": "74af0362988dfd6c53eaf7f6ade823d8e7d40348", "shasum": "" }, "require": { @@ -1208,7 +1250,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.15.x-dev" + "dev-master": "2.16.x-dev" } }, "autoload": { @@ -1241,7 +1283,7 @@ "task", "tool" ], - "time": "2016-10-04 15:20:11" + "time": "2016-10-10 11:51:22" }, { "name": "phpdocumentor/reflection-common", @@ -2195,6 +2237,81 @@ "homepage": "https://github.com/sebastianbergmann/version", "time": "2015-06-21 13:59:46" }, + { + "name": "squizlabs/php_codesniffer", + "version": "1.5.x-dev", + "source": { + "type": "git", + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "6f3e42d311b882b25b4d409d23a289f4d3b803d5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/6f3e42d311b882b25b4d409d23a289f4d3b803d5", + "reference": "6f3e42d311b882b25b4d409d23a289f4d3b803d5", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=5.1.2" + }, + "suggest": { + "phpunit/php-timer": "dev-master" + }, + "bin": [ + "scripts/phpcs" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-phpcs-fixer": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "CodeSniffer.php", + "CodeSniffer/CLI.php", + "CodeSniffer/Exception.php", + "CodeSniffer/File.php", + "CodeSniffer/Report.php", + "CodeSniffer/Reporting.php", + "CodeSniffer/Sniff.php", + "CodeSniffer/Tokens.php", + "CodeSniffer/Reports/", + "CodeSniffer/CommentParser/", + "CodeSniffer/Tokenizers/", + "CodeSniffer/DocGenerators/", + "CodeSniffer/Standards/AbstractPatternSniff.php", + "CodeSniffer/Standards/AbstractScopeSniff.php", + "CodeSniffer/Standards/AbstractVariableSniff.php", + "CodeSniffer/Standards/IncorrectPatternException.php", + "CodeSniffer/Standards/Generic/Sniffs/", + "CodeSniffer/Standards/MySource/Sniffs/", + "CodeSniffer/Standards/PEAR/Sniffs/", + "CodeSniffer/Standards/PSR1/Sniffs/", + "CodeSniffer/Standards/PSR2/Sniffs/", + "CodeSniffer/Standards/Squiz/Sniffs/", + "CodeSniffer/Standards/Zend/Sniffs/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "lead" + } + ], + "description": "PHP_CodeSniffer tokenises PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "http://www.squizlabs.com/php-codesniffer", + "keywords": [ + "phpcs", + "standards" + ], + "time": "2014-12-04 22:32:15" + }, { "name": "symfony/yaml", "version": "dev-master", @@ -2256,12 +2373,12 @@ "source": { "type": "git", "url": "https://github.com/webmozart/assert.git", - "reference": "8444f2ac9f86342665cdae47b6d3ea6e07794456" + "reference": "1a6cc8d09dd675802ca93de290ac483c10ef95e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/8444f2ac9f86342665cdae47b6d3ea6e07794456", - "reference": "8444f2ac9f86342665cdae47b6d3ea6e07794456", + "url": "https://api.github.com/repos/webmozart/assert/zipball/1a6cc8d09dd675802ca93de290ac483c10ef95e0", + "reference": "1a6cc8d09dd675802ca93de290ac483c10ef95e0", "shasum": "" }, "require": { @@ -2298,7 +2415,7 @@ "check", "validate" ], - "time": "2016-08-18 09:30:53" + "time": "2016-10-10 07:45:47" } ], "aliases": [],