Написание CMS на Kohana 3.2 — 4 статья

Здравствуйте, сегодня мы продолжим работу над нашей cms.
В прошлой статьи мы не успели организовать вывод ошибок ,да и сама авторизация с регистрацией нуждается в доработке. Также напишу об одном возможном баге при работе с авторизацией.

1. Организация вывода ошибок и сообщений
2. Добавление модуля Captcha
3. Доработка авторизации и регистрации

1. Организация вывода ошибок и сообщений
Для этого мы напишем статические функции которые будут находиться в нашем базовом контроллере.

// Пример
page::error('Текст ошибки или массив с ошибками(любой вложенности)');
page::message('Текст ошибки или массив с сообщениями(одномерный)');


При этом мы сделаем также чтобы если в качестве параметра функции передается массив(любой вложенности) он разбивался на множество строк и только в таком виде мы будем передавать его в файлы вида. Где мы будем перебирать строки через цикл и выводить их пользователю.
Также заодно внесем попутные изменения в базовый контроллер — Page

<?php defined('SYSPATH') or die('No direct script access.');
abstract class Page extends Controller_Template {
    public $template = 'default';
	public $error=array();
	public $message=array();
    public $main_config;
	public $session;
	public $title;
	public $keywords;
	public $description;
	public $auth;
	public $user;
    public function before()
    {
	/**
	* Идентификация пользователя
	*/
	$this->session = Session::instance();
	$this->auth = Auth::instance();
	$this->user = $this->auth->get_user();
	/**
	* Получение основных настроек
	**/
	$this->main_config = Kohana::$config->load('main');
    Kohana::add_path('themes/'.$this->main_config->get('web_theme').'/');
    parent::before();
	$this->template->styles = array('main');
	//$this->template->scripts = '';
    }
	public function error($error) {
	  if (is_array($error)) {
	   foreach ($error as $errors) {
	    if (is_array($errors)) {
	    return self::error($errors);
	    }
	   $this->error[]=$errors;
	   }
	  } else {
	  return $this->error[]=$error;
	  }
	}
	public function message($message) {
	  if (is_array($message)) {
	   foreach ($message as $messages) {
	   $this->message[]=$messages;
	   }
	  } else {
	  return $this->message[]=$message;
	  }
	}
	public function after()
	{
	View::set_global(array(
    'title' => !isset($this->title)?$this->main_config->get('title'):$this->title,
	'keywords' => !isset($this->keywords)?$this->main_config->get('keywords'):$this->keywords,
    'description' => !isset($this->description)?$this->main_config->get('description'):$this->description,
	'session' => $this->session,
	'user' => $this->user,
	'error' => $this->error,
	'message' => $this->message,
	'view_captcha' => Captcha::instance()->render()
    ));
	parent::after();
	}
}

Теперь нужно внести изменения в файлы видов.
Базовый файл вида — default.php

<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8" />
  <title><?php echo $title ?></title>
  <meta name="keywords" content="<?php echo $keywords ?>" />
  <meta name="description" content="<?php echo $description ?>" />
  <?php
  foreach($styles as $style) {
   echo HTML::style('themes/default/css/'.$style.'.css');
  }
  /*
  foreach($scripts as $script) {
   echo HTML::script('themes/default/css/'.$script.'.js');
  }
  */
  ?>
 </head>
 <body>
 <div id="container">
  <header>
  <div id="header">
		<h1>PEGAS <span>CMS</span></h1>
		<p>Based on framework Kohana 3.2</p>
		<div id="topmenu">
		<ul>
			<li><?php echo HTML::anchor('/#', 'Главная'); ?></li>
			<li><?php echo HTML::anchor('/about/', 'О Pegas CMS'); ?></li>
		</ul>
		</div>
  </div>
  </header>
 <div id="contentcontainer">
		<div id="content">
		<!-- ### Post Entry Begin ###  -->
		<div class="post">
		<?php
		echo View::factory('/main/error');
		echo View::factory('/main/message');
		if(!empty($content))echo $content;
		?>
		</div>
		</div>
		<!-- ### Sidebar Begin ### -->
		<?php echo View::factory('/main/sidebar'); ?>
		<!-- ### Sidebar End ### -->
	</div>
 </div>
  <footer>
  <div id="footer">
    &copy; Pegas CMS 2011-<?php echo date('Y'); ?> г
  </div>
  </footer>
 </body>
</html>

Файлы вида — error.php и message.php

<?php
if (!empty($error)) {
   foreach ($error as $errors) {
   ?>
   <div class="post_error">
   <span><?php echo $errors; ?></span>
   </div>
   <?php
   }
}
<?php
if (!empty($message)) {
   foreach ($message as $messages) {
   ?>
   <div class="post_message">
   <span><?php echo $messages; ?></span>
   </div>
   <?php
   }
}

Теперь нужно все это дело оформить, для красивого вывода сообщений =)
Добавим в /css/main.css

.post_error {
padding:3px;
font-size:15px;
font-family: Tahoma;
color: #7f0000;
border-left: 2px solid #7f0000;
border-right: 2px solid #7f0000;
border-top: 1px dotted #7f0000;
}
.post_error span {
padding-left:5px;
}
.post_message {
padding: 3px;
font-size:15px;
font-family: Tahoma;
color: #59A84A;
border-left: 2px solid #59A84A;
border-right: 2px solid #59A84A;
border-top: 1px dotted #59A84A;
}
.post_message span {
padding-left:5px;
}

Переходим к следующему пункту.
2. Добавление модуля Captcha
Модуль Captcha мы возьмем уже готовый и внедрим его в наш проект.
Скачать исправленный и вполне работоспособный модуль можно здесь Captcha.
После того как скачали устанавливаем его ,для этого добавляем строку в массив подключаемых модулей — bootstrap.php

'captcha'  => MODPATH.'captcha', //Captcha

Не забываем также закинуть файл настроек с самого модуля в папку /application/config/. Так лучше всего поступать со всеми модулями ,это позволит нам создавать более упорядоченные приложения которым не так страшны обновления модулей.
Теперь после того как мы разобрались с двумя пунктами сегодняшней работы осталось эти изменения внедрить.
3. Доработка авторизации и регистрации
Изменим контроллер — /controller/registration.php. Добавим в него новую проверку — цифровый код (Captcha) — это позволит нам избежать регистрации ботов на сайте. Для этого придется также поработать с моделями и валидацией. Тема — это довольно сложная для понимания. Поэтому рекомендую почитать статьи на данные тематики.

<?php defined('SYSPATH') or die('No direct script access.');
class Controller_Registration extends Page {
	public function action_index()
	{
	$this->title = 'Регистрация';
	$data = array();
	     if ($_POST) {
		 $user = ORM::factory('user');
		 $data = Arr::extract($_POST, array('username', 'email', 'password', 'confirm_password', 'captcha'));
$data['username']=HTML::chars($data['username']);
         $user->values($data,  array('username', 'email', 'password'));
		 $extra_validation = Validation::factory(
         array('password' => $data['password'],
               'password_confirm' => $data['confirm_password'],
			   'captcha' => $data['captcha']));
         $extra_validation->rule('password' , 'not_empty')
                          ->rule('password' , 'min_length', array(':value', 4))
                          ->rule('password' , 'max_length', array(':value', 32))
                          ->rule('password_confirm', 'matches', array(':validation', 'password_confirm', 'password'))
						  ->rule('captcha' , 'not_empty')
						  ->rule('captcha' , 'Model_User::captcha_valid');
         try {
         $user->save($extra_validation);
         $user->add('roles', ORM::factory('role')->where('name', '=', 'login')->find());
		 $this->auth->login($data['username'], $data['password'], 1);
         $this->template->content =  View::factory('registration/ok',$data);
		 return TRUE;
         } catch (ORM_Validation_Exception $e) {
           page::error($e->errors('validation'));
         }
		}
    $this->template->content =  View::factory('registration/main');
	}
} // End Registration

В файле вида /registration/main.php добавим вывод Captcha.

<h2>Регистрация</h2>
<?php echo Form::open('registration')?>
<?php echo Form::label('username', 'Логин (max 32)') ?><br />
<?php echo Form::input('username', HTML::chars(Arr::get($_POST, 'username')))?> <br />
<?php echo Form::label('email', 'E-mail') ?><br />
<?php echo Form::input('email', HTML::chars(Arr::get($_POST, 'email')))?> <br />
<?php echo Form::label('password', 'Пароль (max 64)')?> <br />
<?php echo Form::password('password')?> <br />
<?php echo Form::label('confirm_password', 'Повторите пароль')?> <br />
<?php echo Form::password('confirm_password')?> <br />
<?php echo Form::label('captcha', 'Введите символы с картинки')?> <br />
<?php echo $view_captcha; ?> <br />
<?php echo Form::input('captcha', FALSE,array('size'=>4))?> <br />
<?php echo Form::submit('register','Зарегистрироваться')?> <br /> <br />
&raquo; <?php echo HTML::anchor('/auth', 'Авторизация')?>
<?php echo Form::close()?>

Теперь нам нужно добавить метод проверки кода Captcha в модель — User. Для это мы создадим — /model/user.php наследуемого от базовой модели модуля -Auth.

<?php defined('SYSPATH') or die('No direct access allowed.');
class Model_User extends Model_Auth_User {
	public function labels()
	{
		return array(
			'username'         => 'username',
			'email'            => 'email address',
			'password'         => 'password',
			'captcha'          => 'captcha',
		);
	}
	public static function captcha_valid($captcha)
	{
	  return (bool)Captcha::valid($captcha);
	}
} // End User Model

Перейдем к контроллеру авторизации — /controller/auth.php. Кой-чего подправим =)

<?php defined('SYSPATH') or die('No direct script access.');
class Controller_Auth extends Page {
	public function action_index()
	{
	$this->title = 'Авторизация';
	$data = array();
		if($this->auth->logged_in()) {
			Request::initial()->redirect(URL::site());
		} else {
			if ($_POST) {
			$data = Arr::extract($_POST, array('username', 'password', 'save'));
                 if($this->auth->login($data['username'], $data['password'], (bool)$data['save'])) {
					Request::initial()->redirect(URL::site());
				 } else {
				    page::error('Ошибка авторизации');
				 }
			 }
		}
		$this->template->content=View::factory('auth/main');
	}
	public function action_logout()
	{
	$this->auth->logout();
	Request::initial()->redirect(URL::site());
	}
} // End Auth

В самом начале статьи я писал о возможном интересном нюансе в авторизации при котором используется запоминание пользователя.

$this->auth->login($data['username'], $data['password'], $data['save']);

Вроде все правильно и работать должно ).
Третий параметр функции auth->login принимает булевое значение и отвечает за запоминание пользователя.
Сам я если честно долго сидел и думал почему не работает ))
Проблема разрешилась после того как глянул исходной файл функции auth->login.

// Проверка
if ($remember === TRUE)
{
}

Требуется строгое соблюдение типа! Поэтому нужно обязательно приводить к булевому типу

$this->auth->login($data['username'], $data['password'], (bool)$data['save']);

Вот иногда такая мелочь ,а здорово стопорит работу и ставит в тупик )

Все на сегодня ). В следующей статье мы разберемся с правильным выводом системных сообщений и возможно если получиться и не изменяться планы начнем написание своего первого модуля — гостевой книги.

Пару скринов:

Также напомню вам дорогие мои читатели что все изменения ,внешний вид ,функционал вы можете посмотреть и протестировать на сайте проекта http://cmspegas.ru

Исходники: Скачать исходники pegas_4

P.S По традиции прошу в комментарии при возникновении вопросов или пожеланий ))

Вам также может понравиться ...