From af237f300311691ae1ef410128a03be0bd8ba187 Mon Sep 17 00:00:00 2001 From: voltan Date: Mon, 31 Jul 2017 12:21:03 +0430 Subject: [PATCH] Work on ask module --- asset/css/front.css | 16 ++ config/module.php | 2 +- config/page.php | 6 + sql/mysql.sql | 4 +- src/Api/Project.php | 69 ++++++++ src/Api/Question.php | 13 +- src/Controller/Admin/ProjectController.php | 74 +++++++++ src/Controller/Admin/QuestionController.php | 3 +- src/Controller/Front/AnswerController.php | 4 +- src/Controller/Front/IndexController.php | 44 +++-- src/Controller/Front/ProjectController.php | 58 +++++++ src/Controller/Front/SubmitController.php | 39 ++++- src/Form/ProjectFilter.php | 90 ++++++++++ src/Form/ProjectForm.php | 158 ++++++++++++++++++ src/Model/Project.php | 1 + src/Model/Question.php | 1 + src/Route/Ask.php | 14 +- src/Validator/SlugDuplicate.php | 56 +++++++ template/admin/project-index.phtml | 49 +++++- template/admin/project-update.phtml | 12 +- template/admin/question-index.phtml | 174 ++++++++++---------- template/admin/question-update.phtml | 2 +- template/front/answer_index.phtml | 3 +- template/front/project-list.phtml | 15 ++ template/front/question-list.phtml | 82 +++++++++ template/front/question_index.phtml | 1 + template/front/question_list.phtml | 18 -- template/front/submit-index.phtml | 19 +++ template/front/submit_index.phtml | 28 ---- 29 files changed, 877 insertions(+), 178 deletions(-) create mode 100644 src/Api/Project.php create mode 100644 src/Controller/Front/ProjectController.php create mode 100644 src/Form/ProjectFilter.php create mode 100644 src/Form/ProjectForm.php create mode 100644 src/Validator/SlugDuplicate.php create mode 100644 template/front/project-list.phtml create mode 100644 template/front/question-list.phtml delete mode 100644 template/front/question_list.phtml create mode 100644 template/front/submit-index.phtml delete mode 100644 template/front/submit_index.phtml diff --git a/asset/css/front.css b/asset/css/front.css index e69de29..f0de45a 100644 --- a/asset/css/front.css +++ b/asset/css/front.css @@ -0,0 +1,16 @@ +.question-list { + margin-top: 15px; +} + +.question-single { + padding-bottom: 5px; + margin-bottom: 5px; + border-bottom: 1px solid #ddd; +} + +.question-single .question-single-title h3 { + padding: 5px 0; + margin: 0; +} + +.question-single .question-single-time {} \ No newline at end of file diff --git a/config/module.php b/config/module.php index b2f7b8b..bd8673e 100644 --- a/config/module.php +++ b/config/module.php @@ -14,7 +14,7 @@ 'meta' => array( 'title' => _a('Ask'), 'description' => _a('Ask and Answer'), - 'version' => '0.2.0', + 'version' => '0.2.2', 'license' => 'New BSD', 'logo' => 'image/logo.png', 'readme' => 'docs/readme.txt', diff --git a/config/page.php b/config/page.php index 2365789..864ca8f 100644 --- a/config/page.php +++ b/config/page.php @@ -37,6 +37,12 @@ 'permission' => 'public', 'block' => 1, ), + array( + 'title' => _a('Project page'), + 'controller' => 'project', + 'permission' => 'public', + 'block' => 1, + ), array( 'title' => _a('Answer'), 'controller' => 'answer', diff --git a/sql/mysql.sql b/sql/mysql.sql index 2173ab8..be4c6d1 100644 --- a/sql/mysql.sql +++ b/sql/mysql.sql @@ -51,8 +51,10 @@ CREATE TABLE `{project}` ( `seo_title` VARCHAR(255) NOT NULL DEFAULT '', `seo_keywords` VARCHAR(255) NOT NULL DEFAULT '', `seo_description` VARCHAR(255) NOT NULL DEFAULT '', + `manager` INT(10) UNSIGNED NOT NULL DEFAULT '0', PRIMARY KEY (`id`), KEY `title` (`title`), KEY `status` (`status`), - KEY `time_create` (`time_create`) + KEY `time_create` (`time_create`), + KEY `manager` (`manager`) ); \ No newline at end of file diff --git a/src/Api/Project.php b/src/Api/Project.php new file mode 100644 index 0000000..f2c3202 --- /dev/null +++ b/src/Api/Project.php @@ -0,0 +1,69 @@ + + */ +namespace Module\Ask\Api; + +use Pi; +use Pi\Application\Api\AbstractApi; + +/* + * Pi::api('project', 'ask')->getProject($parameter, $type); + * Pi::api('project', 'ask')->getProjectList(); + * Pi::api('project', 'ask')->canonizeProject($project); + */ + +class Project extends AbstractApi +{ + public function getProject($parameter, $type = 'id') + { + // Get project + $project = Pi::model('project', $this->getModule())->find($parameter, $type); + $project = $this->canonizeProject($project); + return $project; + } + + public function getProjectList() + { + $list = array(); + $where = array('status' => 1); + $order = array('time_create DESC', 'id DESC'); + $select = Pi::model('project', $this->getModule())->select()->where($where)->order($order); + $rowset = Pi::model('project', $this->getModule())->selectWith($select); + foreach ($rowset as $row) { + $list[$row->id] = $this->canonizeProject($row); + } + return $list; + } + + public function canonizeProject($project) + { + // Check + if (empty($project)) { + return ''; + } + // boject to array + $project = $project->toArray(); + // Set times + $project['time_create_view'] = _date($project['time_create']); + $project['time_update_view'] = _date($project['time_update']); + // Set text_description + $project['text_description'] = Pi::service('markup')->render($project['text_description'], 'html', 'html'); + // Set question url + $project['projectUrl'] = Pi::url(Pi::service('url')->assemble('ask', array( + 'module' => $this->getModule(), + 'controller' => 'project', + 'slug' => $project['slug'], + ))); + // return question + return $project; + } +} \ No newline at end of file diff --git a/src/Api/Question.php b/src/Api/Question.php index f696371..8d35ba4 100644 --- a/src/Api/Question.php +++ b/src/Api/Question.php @@ -50,8 +50,6 @@ public function canonizeQuestion($question) if (empty($question)) { return ''; } - // Get config - $config = Pi::service('registry')->config->read($this->getModule()); // boject to array $question = $question->toArray(); // Set times @@ -74,6 +72,17 @@ public function canonizeQuestion($question) } $question['tag'] = $tagList; } + // Set user + $question['user'] = Pi::user()->get($question['uid'], array( + 'id', 'identity', 'name', 'email' + )); + /* $question['user']['avatar'] = Pi::service('user')->avatar($question['user']['id'], 'large', array( + 'alt' => $question['user']['name'], + 'class' => 'img-circle', + )); + $question['user']['profileUrl'] = Pi::url(Pi::service('user')->getUrl('profile', array( + 'id' => $question['user']['id'], + ))); */ // Set info for Q and A switch ($question['type']) { case 'Q': diff --git a/src/Controller/Admin/ProjectController.php b/src/Controller/Admin/ProjectController.php index 22eb1ad..91cf907 100644 --- a/src/Controller/Admin/ProjectController.php +++ b/src/Controller/Admin/ProjectController.php @@ -13,17 +13,91 @@ namespace Module\Ask\Controller\Admin; use Pi; +use Pi\Filter; use Pi\Mvc\Controller\ActionController; +use Module\Ask\Form\ProjectForm; +use Module\Ask\Form\ProjectFilter; class ProjectController extends ActionController { public function indexAction() { + $projects = array(); + // Set info + $order = array('time_create DESC', 'id DESC'); + // Set select + $select = $this->getModel('project')->select()->order($order); + $rowset = $this->getModel('project')->selectWith($select); + // Make list + foreach ($rowset as $row) { + $projects[$row->id] = Pi::api('project', 'ask')->canonizeProject($row); + } + // Set view $this->view()->setTemplate('project-index'); + $this->view()->assign('projects', $projects); } public function updateAction() { + // Get id + $id = $this->params('id'); + // Set form + $form = new ProjectForm('project'); + $form->setAttribute('enctype', 'multipart/form-data'); + if ($this->request->isPost()) { + $data = $this->request->getPost(); + // Set slug + $slug = ($data['slug']) ? $data['slug'] : $data['title']; + $filter = new Filter\Slug; + $data['slug'] = $filter($slug); + // Form filter + $form->setInputFilter(new ProjectFilter); + $form->setData($data); + if ($form->isValid()) { + $values = $form->getData(); + // Set seo_title + $title = ($values['seo_title']) ? $values['seo_title'] : $values['title']; + $filter = new Filter\HeadTitle; + $values['seo_title'] = $filter($title); + // Set seo_keywords + $keywords = ($values['seo_keywords']) ? $values['seo_keywords'] : $values['title']; + $filter = new Filter\HeadKeywords; + $filter->setOptions(array( + 'force_replace_space' => (bool)$this->config('force_replace_space'), + )); + $values['seo_keywords'] = $filter($keywords); + // Set seo_description + $description = ($values['seo_description']) ? $values['seo_description'] : $values['title']; + $filter = new Filter\HeadDescription; + $values['seo_description'] = $filter($description); + // Set if new + if (empty($values['id'])) { + // Set time + $values['time_create'] = time(); + } + // Set time_update + $values['time_update'] = time(); + // Save values + if (!empty($values['id'])) { + $row = $this->getModel('project')->find($values['id']); + } else { + $row = $this->getModel('project')->createRow(); + } + $row->assign($values); + $row->save(); + // jump + $message = __('Project data saved successfully.'); + $this->jump(array('action' => 'index'), $message); + } + } else { + if ($id) { + $project = $this->getModel('project')->find($id)->toArray(); + $form->setData($project); + } + } + // Set view $this->view()->setTemplate('project-update'); + $this->view()->assign('form', $form); + $this->view()->assign('title', __('Add project')); } } \ No newline at end of file diff --git a/src/Controller/Admin/QuestionController.php b/src/Controller/Admin/QuestionController.php index e7fa0c2..289bcda 100644 --- a/src/Controller/Admin/QuestionController.php +++ b/src/Controller/Admin/QuestionController.php @@ -44,7 +44,6 @@ public function indexAction() // Make list foreach ($rowset as $row) { $question[$row->id] = Pi::api('question', 'ask')->canonizeQuestion($row); - } // Set paginator $count = array('count' => new \Zend\Db\Sql\Predicate\Expression('count(*)')); @@ -123,7 +122,7 @@ public function updateAction() } // Set slug $slug = ($values['slug']) ? $values['slug'] : $values['title']; - $slug = $slug . ' ' . $question['time_create']; + $slug = sprintf('%s-%s', $slug, _date($question['time_create'], array('pattern' => 'yyyy MM dd H I'))); $filter = new Filter\Slug; $values['slug'] = $filter($slug); // Set seo_title diff --git a/src/Controller/Front/AnswerController.php b/src/Controller/Front/AnswerController.php index 2aefd26..71fd844 100644 --- a/src/Controller/Front/AnswerController.php +++ b/src/Controller/Front/AnswerController.php @@ -57,7 +57,9 @@ public function indexAction() $values['time_update'] = time(); // Set slug $filter = new Filter\Slug; - $values['slug'] = $filter($values['title'] . ' ' . _date($values['time_create'])); + $slug = sprintf('%s-%s', $values['title'], _date($values['time_create'])); + $values['slug'] = $filter($slug); + // Set seo_title $filter = new Filter\HeadTitle; $values['seo_title'] = $filter($values['title']); diff --git a/src/Controller/Front/IndexController.php b/src/Controller/Front/IndexController.php index f70893b..3c34d0f 100644 --- a/src/Controller/Front/IndexController.php +++ b/src/Controller/Front/IndexController.php @@ -25,23 +25,33 @@ public function indexAction() $module = $this->params('module'); // Get config $config = Pi::service('registry')->config->read($module); - // Set question info - $where = array('status' => 1, 'type' => 'Q'); - // Set paginator info - $template = array( - 'controller' => 'index', - 'action' => 'index', - ); - // Get question List - $questions = $this->askList($where); - // Get paginator - $paginator = $this->askPaginator($template, $where); - // Set view - $this->view()->setTemplate('question_list'); - $this->view()->assign('questions', $questions); - $this->view()->assign('paginator', $paginator); - $this->view()->assign('config', $config); - $this->view()->assign('title', __('List of all questions')); + // Check + if ($config['project_active']) { + $projects = Pi::api('project', 'ask')->getProjectList(); + // Set view + $this->view()->setTemplate('project-list'); + $this->view()->assign('projects', $projects); + $this->view()->assign('config', $config); + $this->view()->assign('title', __('List of all projects')); + } else { + // Set question info + $where = array('status' => 1, 'type' => 'Q'); + // Set paginator info + $template = array( + 'controller' => 'index', + 'action' => 'index', + ); + // Get question List + $questions = $this->askList($where); + // Get paginator + $paginator = $this->askPaginator($template, $where); + // Set view + $this->view()->setTemplate('question-list'); + $this->view()->assign('questions', $questions); + $this->view()->assign('paginator', $paginator); + $this->view()->assign('config', $config); + $this->view()->assign('title', __('List of all questions')); + } } public function askList($where) diff --git a/src/Controller/Front/ProjectController.php b/src/Controller/Front/ProjectController.php new file mode 100644 index 0000000..19fd387 --- /dev/null +++ b/src/Controller/Front/ProjectController.php @@ -0,0 +1,58 @@ + + */ +namespace Module\Ask\Controller\Front; + +use Pi; +use Pi\Mvc\Controller\ActionController; +use Pi\Paginator\Paginator; +use Zend\Db\Sql\Predicate\Expression; + +class ProjectController extends IndexController +{ + public function indexAction() + { + // Get info from url + $module = $this->params('module'); + $slug = $this->params('slug'); + // Get config + $config = Pi::service('registry')->config->read($module); + // Get topic information from model + $project = Pi::api('project', 'ask')->getProject($slug, 'slug'); + // Check slug set + if (empty($project) || $project['status'] != 1) { + $this->getResponse()->setStatusCode(404); + $this->terminate(__('Project not set.'), '', 'error-404'); + $this->view()->setLayout('layout-simple'); + return; + } + // Set question info + $where = array('status' => 1, 'type' => 'Q', 'project_id' => $project['id']); + // Set paginator info + $template = array( + 'controller' => 'index', + 'action' => 'index', + ); + // Get question List + $questions = $this->askList($where); + // Get paginator + $paginator = $this->askPaginator($template, $where); + // Set view + $this->view()->setTemplate('question-list'); + $this->view()->assign('questions', $questions); + $this->view()->assign('paginator', $paginator); + $this->view()->assign('project', $project); + $this->view()->assign('config', $config); + $this->view()->assign('title', __('List of all questions')); + + } +} \ No newline at end of file diff --git a/src/Controller/Front/SubmitController.php b/src/Controller/Front/SubmitController.php index 336485d..c7f50db 100644 --- a/src/Controller/Front/SubmitController.php +++ b/src/Controller/Front/SubmitController.php @@ -25,6 +25,7 @@ public function indexAction() { // Get info from url $module = $this->params('module'); + $slug = $this->params('slug'); // Get config $config = Pi::service('registry')->config->read($module); // Check ask @@ -34,6 +35,22 @@ public function indexAction() } // Check user is login or not Pi::service('authentication')->requireLogin(); + // Check project + if ($config['project_active'] && !empty($slug)) { + // Get topic information from model + $project = Pi::api('project', 'ask')->getProject($slug, 'slug'); + // Check slug set + if (empty($project) || $project['status'] != 1) { + $this->getResponse()->setStatusCode(404); + $this->terminate(__('Project not set.'), '', 'error-404'); + $this->view()->setLayout('layout-simple'); + return; + } + } elseif ($config['project_active'] && empty($slug)) { + $url = array('', 'module' => $module, 'controller' => 'index', 'action' => 'index'); + $this->jump($url, __('Please select project for ask question'), 'error'); + } + // Set form $form = new AskForm('Ask'); if ($this->request->isPost()) { @@ -52,7 +69,8 @@ public function indexAction() $values['time_update'] = time(); // Set slug $filter = new Filter\Slug; - $values['slug'] = $filter($values['title'] . ' ' . _date($values['time_create'])); + $slug = sprintf('%s-%s', $values['title'], _date($values['time_create'], array('pattern' => 'yyyy MM dd H I'))); + $values['slug'] = $filter($slug); // Set seo_title $filter = new Filter\HeadTitle; $values['seo_title'] = $filter($values['title']); @@ -69,6 +87,10 @@ public function indexAction() $values['uid'] = Pi::user()->getId(); $values['status'] = $this->config('auto_approval'); $values['type'] = 'Q'; + // Check project + if (isset($project) && !empty($project)) { + $values['project_id'] = $project['id']; + } // Save values $row = $this->getModel('question')->createRow(); $row->assign($values); @@ -83,12 +105,21 @@ public function indexAction() } else { $message = __('Your ask new question successfully, But it need review and publish by website admin'); } - $url = array('', 'module' => $module, 'controller' => 'index', 'action' => 'index'); + if (isset($project) && !empty($project)) { + $url = array('', 'module' => $module, 'controller' => 'project', 'slug' => $project['slug']); + } else { + $url = array('', 'module' => $module, 'controller' => 'index', 'action' => 'index'); + } $this->jump($url, $message); } } // Set header and title - $title = __('Ask a new Question'); + if (isset($project) && !empty($project)) { + $title = sprintf(__('Ask a new Question on %s project'), $project['title']); + } else { + $title = __('Ask a new Question'); + } + // Set seo_keywords $filter = new Filter\HeadKeywords; $filter->setOptions(array( @@ -99,7 +130,7 @@ public function indexAction() $this->view()->headTitle($title); $this->view()->headDescription($title, 'set'); $this->view()->headKeywords($seoKeywords, 'set'); - $this->view()->setTemplate('submit_index'); + $this->view()->setTemplate('submit-index'); $this->view()->assign('form', $form); $this->view()->assign('title', $title); } diff --git a/src/Form/ProjectFilter.php b/src/Form/ProjectFilter.php new file mode 100644 index 0000000..3c766f9 --- /dev/null +++ b/src/Form/ProjectFilter.php @@ -0,0 +1,90 @@ + + */ + +namespace Module\Ask\Form; + +use Pi; +use Zend\InputFilter\InputFilter; + +class ProjectFilter extends InputFilter +{ + public function __construct() + { + // id + $this->add(array( + 'name' => 'id', + 'required' => false, + )); + // title + $this->add(array( + 'name' => 'title', + 'required' => true, + 'filters' => array( + array( + 'name' => 'StringTrim', + ), + ), + )); + // slug + $this->add(array( + 'name' => 'slug', + 'required' => false, + 'filters' => array( + array( + 'name' => 'StringTrim', + ), + ), + 'validators' => array( + new \Module\Ask\Validator\SlugDuplicate(array( + 'module' => Pi::service('module')->current(), + 'table' => 'project', + )), + ), + )); + // text_description + $this->add(array( + 'name' => 'text_description', + 'required' => true, + 'filters' => array( + array( + 'name' => 'StringTrim', + ), + ), + )); + // status + $this->add(array( + 'name' => 'status', + 'required' => true, + )); + // manager + $this->add(array( + 'name' => 'manager', + 'required' => false, + )); + // seo_title + $this->add(array( + 'name' => 'seo_title', + 'required' => false, + )); + // seo_keywords + $this->add(array( + 'name' => 'seo_keywords', + 'required' => false, + )); + // seo_description + $this->add(array( + 'name' => 'seo_description', + 'required' => false, + )); + } +} \ No newline at end of file diff --git a/src/Form/ProjectForm.php b/src/Form/ProjectForm.php new file mode 100644 index 0000000..9892d6a --- /dev/null +++ b/src/Form/ProjectForm.php @@ -0,0 +1,158 @@ + + */ + +namespace Module\Ask\Form; + +use Pi; +use Pi\Form\Form as BaseForm; + +class ProjectForm extends BaseForm +{ + public function getInputFilter() + { + if (!$this->filter) { + $this->filter = new ProjectFilter; + } + return $this->filter; + } + + public function init() + { + // id + $this->add(array( + 'name' => 'id', + 'attributes' => array( + 'type' => 'hidden', + ), + )); + // title + $this->add(array( + 'name' => 'title', + 'options' => array( + 'label' => __('Title'), + ), + 'attributes' => array( + 'type' => 'text', + 'description' => '', + ) + )); + // slug + $this->add(array( + 'name' => 'slug', + 'options' => array( + 'label' => __('slug'), + ), + 'attributes' => array( + 'type' => 'text', + 'description' => __('Used as story URL value : must be unique, short, and user oriented'), + ) + )); + // text_description + $this->add(array( + 'name' => 'text_description', + 'options' => array( + 'label' => __('Description'), + 'editor' => 'html', + 'set' => '', + ), + 'attributes' => array( + 'type' => 'editor', + 'description' => '', + ) + )); + // status + $this->add(array( + 'name' => 'status', + 'type' => 'select', + 'options' => array( + 'label' => __('Status'), + 'value_options' => array( + 1 => __('Published'), + 2 => __('Pending review'), + 3 => __('Draft'), + 4 => __('Private'), + 5 => __('Remove'), + ), + ), + 'attributes' => array( + 'required' => true, + ), + )); + // manager + $this->add(array( + 'name' => 'manager', + 'options' => array( + 'label' => __('Manager'), + ), + 'attributes' => array( + 'type' => 'text', + 'description' => __('Project manager user id'), + ) + )); + // extra_seo + $this->add(array( + 'name' => 'extra_seo', + 'type' => 'fieldset', + 'options' => array( + 'label' => __('SEO options'), + ), + )); + // seo_title + $this->add(array( + 'name' => 'seo_title', + 'options' => array( + 'label' => __('Meta Title'), + ), + 'attributes' => array( + 'type' => 'textarea', + 'rows' => '2', + 'cols' => '40', + 'description' => __('Displayed in search Engine result pages as Title : between 10 to 70 character. If empty, will be popuated automaticaly by main title value'), + ) + )); + // seo_keywords + $this->add(array( + 'name' => 'seo_keywords', + 'options' => array( + 'label' => __('Meta Keywords'), + ), + 'attributes' => array( + 'type' => 'textarea', + 'rows' => '2', + 'cols' => '40', + 'description' => __('Not used anymore by search engines : between 5 to 12 words / left it empty, it will be automaticaly populated with main title values'), + ) + )); + // seo_description + $this->add(array( + 'name' => 'seo_description', + 'options' => array( + 'label' => __('Meta Description'), + ), + 'attributes' => array( + 'type' => 'textarea', + 'rows' => '3', + 'cols' => '40', + 'description' => __('Displayed in search Engine result pages : quick summary to incitate user to click, between 80 to 160 character'), + ) + )); + // Save + $this->add(array( + 'name' => 'submit', + 'type' => 'submit', + 'attributes' => array( + 'value' => __('Submit'), + ) + )); + } +} \ No newline at end of file diff --git a/src/Model/Project.php b/src/Model/Project.php index f8ab12d..8e4d8d7 100644 --- a/src/Model/Project.php +++ b/src/Model/Project.php @@ -31,5 +31,6 @@ class Project extends Model 'seo_title', 'seo_keywords', 'seo_description', + 'manager', ); } diff --git a/src/Model/Question.php b/src/Model/Question.php index cdc7199..9f4e2ae 100644 --- a/src/Model/Question.php +++ b/src/Model/Question.php @@ -24,6 +24,7 @@ class Question extends Model 'id', 'type', 'question_id', + 'project_id', 'answer', 'uid', 'point', 'count', diff --git a/src/Route/Ask.php b/src/Route/Ask.php index 7633677..86019c7 100644 --- a/src/Route/Ask.php +++ b/src/Route/Ask.php @@ -28,7 +28,7 @@ class Ask extends Standard ); protected $controllerList = array( - 'answer', 'index', 'question', 'submit', 'tag' + 'answer', 'index', 'question', 'submit', 'tag', 'project' ); /** @@ -71,6 +71,18 @@ protected function parse($path) } break; + case 'project': + if (!empty($parts[1])) { + $matches['slug'] = $this->decode($parts[1]); + } + break; + + case 'submit': + if (!empty($parts[1])) { + $matches['slug'] = $this->decode($parts[1]); + } + break; + case 'tag': switch ($parts[1]) { case 'term': diff --git a/src/Validator/SlugDuplicate.php b/src/Validator/SlugDuplicate.php new file mode 100644 index 0000000..eed8dfa --- /dev/null +++ b/src/Validator/SlugDuplicate.php @@ -0,0 +1,56 @@ + + */ +namespace Module\Ask\Validator; + +use Pi; +use Zend\Validator\AbstractValidator; + +class SlugDuplicate extends AbstractValidator +{ + const TAKEN = 'slugExists'; + + /** + * @var array + */ + protected $messageTemplates = array( + self::TAKEN => 'This slug already exists', + ); + + protected $options = array( + 'module', 'table' + ); + + /** + * Slug validate + * + * @param mixed $value + * @param array $context + * @return boolean + */ + public function isValid($value, $context = null) + { + $this->setValue($value); + if (null !== $value) { + $where = array('slug' => $value); + if (!empty($context['id'])) { + $where['id <> ?'] = $context['id']; + } + $rowset = Pi::model($this->options['table'], $this->options['module'])->select($where); + if ($rowset->count()) { + $this->error(static::TAKEN); + return false; + } + } + return true; + } +} \ No newline at end of file diff --git a/template/admin/project-index.phtml b/template/admin/project-index.phtml index c02761d..38ed609 100644 --- a/template/admin/project-index.phtml +++ b/template/admin/project-index.phtml @@ -1,7 +1,42 @@ -css($this->assetModule('css/admin.css')); ?> +
+ +

+ + + + + + + + + + + + + + +
+ + escape($project['id']); ?> + + escape($project['title']); ?> + + +
+

+ + +

+ + + +
\ No newline at end of file diff --git a/template/admin/project-update.phtml b/template/admin/project-update.phtml index c02761d..f1df384 100644 --- a/template/admin/project-update.phtml +++ b/template/admin/project-update.phtml @@ -1,7 +1,5 @@ -css($this->assetModule('css/admin.css')); ?> +
+

escape($title); ?>

+ form($form); ?> +
\ No newline at end of file diff --git a/template/admin/question-index.phtml b/template/admin/question-index.phtml index 5cb9f85..fa784a8 100644 --- a/template/admin/question-index.phtml +++ b/template/admin/question-index.phtml @@ -1,94 +1,94 @@ css(array( - $this->assetModule('css/admin.css'), - $this->assetModule('script/system-ui.css', 'system'), - )); - $this->jQuery(); - $this->js($this->assetModule('script/system-msg.js', 'system')); +$this->css(array( + $this->assetModule('css/admin.css'), + $this->assetModule('script/system-ui.css', 'system'), +)); +$this->jQuery(); +$this->js($this->assetModule('script/system-msg.js', 'system')); ?>
- -

- - - - - - - - - - - - - - - - - - -
escape($question['id']); ?> - - - escape($question['title']); ?> - - - escape($question['title']); ?> - - escape($question['time_create_view']); ?> - - - - - - - -
-
paginationControl($paginator, 'Sliding', 'paginator'); ?>
-

- - -

- - - + +

+ + + + + + + + + + + + + + + + + + +
escape($question['id']); ?> + + + escape($question['title']); ?> + + + escape($question['title']); ?> + + escape($question['time_create_view']); ?> + + + + + + + +
+
paginationControl($paginator, 'Sliding', 'paginator'); ?>
+

+ + +

+ + +
\ No newline at end of file diff --git a/template/admin/question-update.phtml b/template/admin/question-update.phtml index d7d57f7..9737b49 100644 --- a/template/admin/question-update.phtml +++ b/template/admin/question-update.phtml @@ -5,5 +5,5 @@

:

: escape($question['time_create_view']); ?>

- templateComponent('form'); ?> + form($form); ?> \ No newline at end of file diff --git a/template/front/answer_index.phtml b/template/front/answer_index.phtml index 90e4eca..41e1db6 100644 --- a/template/front/answer_index.phtml +++ b/template/front/answer_index.phtml @@ -1,3 +1,4 @@ +css($this->assetModule('css/front.css')); ?>

escape($title); ?>

@@ -5,5 +6,5 @@
- templateComponent('form'); ?> + form($form); ?> \ No newline at end of file diff --git a/template/front/project-list.phtml b/template/front/project-list.phtml new file mode 100644 index 0000000..426ae55 --- /dev/null +++ b/template/front/project-list.phtml @@ -0,0 +1,15 @@ +css($this->assetModule('css/front.css')); ?> +
+ + +
\ No newline at end of file diff --git a/template/front/question-list.phtml b/template/front/question-list.phtml new file mode 100644 index 0000000..20b8693 --- /dev/null +++ b/template/front/question-list.phtml @@ -0,0 +1,82 @@ +css($this->assetModule('css/front.css')); ?> +
+ + +
+ +
+ + + +
+ + +
+
+
+
    +
  • + +
    + +
  • +
  • + +
    + +
  • + +
  • + +
    + +
  • + +
+
+
+
+ +
+
    +
  • +
  • escape($question['time_create_view']); ?>
  • +
  • +
  • escape($question['user']['name']); ?>
  • +
+
+
+
+ +
+
+ paginationControl($paginator, 'Sliding', 'paginator.phtml'); ?> +
+
\ No newline at end of file diff --git a/template/front/question_index.phtml b/template/front/question_index.phtml index 2dfd089..91c3ad8 100644 --- a/template/front/question_index.phtml +++ b/template/front/question_index.phtml @@ -1,3 +1,4 @@ +css($this->assetModule('css/front.css')); ?>