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

Здравствуйте дорогие читатели сегодня после довольно продолжительного периода простоя мы продолжаем работу над нашей cms =)

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

Первым делом начнем с регистрации ,в предыдущем уроке я допустил XSS — уязвимость ,логин нужно было очищать от html тегов. Каюсь ,пропустил =)
Также мы добавим новое правило валидации для логина. Согласно этому правилу логин не должен в себе содержать смешивание латиницы и кириллицы ,не допускается использование пробелов в начале и конце.

Для этого откроем нашу модель — /application/classes/model/user.php и добавим правило.

<?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',
			'password'         => 'password',
			'password_confirm'         => 'password_confirm',
			'captcha'          => 'captcha',
		);
	}
	public static function captcha_valid($captcha)
	{
	  return (bool)Captcha::valid($captcha);
	}
	public static function login_valid($login)
	{
		 // проверка на длину логина и возможные символы
		 if (!preg_match("#^[a-zа-яё][a-zа-яё0-9\-\_\ ]{2,32}$#ui", $login))return false;
		 // запрещаем одновременное использование русского и английского алфавилов
		 if (preg_match("#[a-z]+#ui", $login) && preg_match("#[а-яё]+#ui", $login))return false;
		 // пробелы вначале или конце ника недопустимы
		 if (preg_match("#(^\ )|(\ $)#ui", $login))return false;
		return true;
	}
} // End User Model

Теперь нужно это правило указать в нашем контроллере регистрации пользователей. +Исправить нашу маленькую уязвимость связанную с логином )

<?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'],
			   'username' => $data['username']));
         $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')
						  ->rule('username' , 'Model_User::login_valid');
         try {
         $user->save($extra_validation);
         $user->add('roles', ORM::factory('role')->where('name', '=', 'login')->find());
		 $this->auth->login($data['username'], $data['password'], TRUE);
         $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

Наши ошибки валидации выходят на английском языке ,а для некоторых правил выводится вообще только название функции. Нужно это немедленно исправить, негоже нам лицезреть буржуйские названия =)
Для этого скопируем файл с сообщениями — /system/messages/validation.php в аналогичную папку нашего приложения.
Теперь многие могут ринуться и переименовывать сообщения валидации ,предупрежу моих суровых товарищей это не совсем по феншую.
По феншую нужно создать файл перевода и уже в нем все переводить.
Создадим папку ru в — /application/i18n/ и файл с переводами ru.php

<?php defined('SYSPATH') or die('No direct script access.');
return array(
 ':field must contain only letters'                     => ':field должно содержать только буквы',
 ':field must contain only numbers, letters and dashes' => ':field должно содержать только буквы, цифры и подчеркивания',
 ':field must contain only letters and numbers'         => ':field должно содержать только буквы и цифры',
 ':field must be a color'                               => ':field должно быть кодом цвета',
 ':field must be a credit card number'                  => ':field должно быть номером кредитной карты',
 ':field must be a date'                                => ':field должно быть датой',
 ':field must be a decimal with :param2 places'  => ':field должно быть десятичным числом с :param2 количеством цифр',
 ':field must be a digit'                               => ':field должно быть целым числом',
 ':field must be a email address'                       => ':field должно быть адресом электронной почты',
 ':field must contain a valid email domain'        => ':field должно быть существующим адресом электронной почты',
 ':field must equal :param2'                            => ':field должно быть идентичным :param2',
 ':field must be exactly :param2 characters long'       => ':field должно быть длиной :param2 символов',
 ':field must be one of the available options'          => ':field должно быть одним из параметров',
 ':field must be an ip address'                         => ':field должно быть ip-адресом',
 ':field must be the same as :param2'                   => ':field должно равняться :param2',
 ':field must be at least :param2 characters long'      => ':field не должно быть короче :param2 символов',
 ':field must not exceed :param2 characters long'       => ':field не должно быть длиннее :param2 символов',
 ':field must not be empty'                             => ':field не должно быть пустым',
 ':field must be numeric'                               => ':field должно быть числом',
 ':field must be a phone number'                        => ':field должно быть номером телефона',
 ':field must be within the range of :param2 to :param3'=> ':field должно находиться между :param2 и :param3',
 ':field does not match the required format'            => ':field не соответствует требуемому формату',
 ':field must be a url'                                 => ':field должно быть URL-адресом',
 ':field incorrect login' 								=> ':field неккоректен',
 ':field incorrect captcha' 							=> ':field неправильно введен код',
 ':filed repeat'										=> ':field уже есть в базе',
 'username'                                             => 'Поле Юзер',
 'email'                                             	=> 'Поле E-mail',
 'password'                                             => 'Поле Пароль',
 'password_confirm'                                     => 'Поле Повторение пароля',
 'captcha'                                              => 'Поле Captcha',
);

Еще необходимо установить наш язык ,делается это в файл — application/bootstrap.php
Нужно изменить строчку

I18n::lang('en-en');

на

I18n::lang('ru-ru');

Теперь мы будем лицезреть

Приятно =)

Дальше больше.
Для админ-зоны мы создадим отдельную директорию в которой будут храниться наши контроллеры ,также создадим роут для правильной адресации. Доступ к различным страницам будет определяться нашими новыми базовыми контроллерами наследуемые от базового контроллера Page содержащие в себя правила проверки на роль пользователя.

Создадим новый роут ,для этого в файле — /application/bootstrap.php пропишем правила роутинга. Новые роуты нужно прописывать до роута default. Вот так =>

Route::set('apanel', 'apanel(/<controller>(/<action>(/<id>)))')
            ->defaults(array(
            'directory'  => 'apanel',
            'controller' => 'main',
            'action'     => 'index',
            ));
Route::set('default', '(<controller>(/<action>(/<id>)))')
	->defaults(array(
		'controller' => 'main',
		'action'     => 'index',
	));

Перейдем к контроллерам ,создадим директорию — /apanel/ в папке контроллеров — /application/classes/controller/. В директории наш контроллер по умолчанию — main

<?php defined('SYSPATH') or die('No direct script access.');
class Controller_Apanel_Main extends AdminPage {
	public function action_index()
	{
        $this->template->content = View::factory('/apanel/main');
	}
} // End Main

Заметим что мы наследуем наш контроллер уже не от Page ,а от нового базового контроллера AdminPage. О нем чуть попозже. Сейчас же, добавим файлы вида в нем напишем что-нить для примера )

<h3>Админ-панель</h3>
Директория  - <?php echo Request::current()->directory(); ?><br />
Контроллер - <?php echo Request::current()->controller(); ?><br />
Метод - <?php echo Request::current()->action(); ?>

Теперь в папке — /application/classes/ напишем новые базовые контроллеры — GuestPage ,AdminPage,LoginPage.

GuestPage

<?php defined('SYSPATH') or die('No direct script access.');
abstract class GuestPage extends Page {
    public function before()
    {
	if(Auth::instance()->logged_in())  Request::initial()->redirect(URL::site());
    return parent::before();
    }
}

LoginPage

<?php defined('SYSPATH') or die('No direct script access.');
abstract class LoginPage extends Page {
    public function before()
    {
	if(!Auth::instance()->logged_in())  Request::initial()->redirect(URL::site());
    return parent::before();
    }
}

AdminPage

<?php defined('SYSPATH') or die('No direct script access.');
abstract class AdminPage extends Page {
    public function before()
    {
	if(!Auth::instance()->logged_in('admin'))  Request::initial()->redirect(URL::site());
    return parent::before();
    }
}

Теперь почти все готово директория — apanel открыта только для пользователей имеющих роль admin.
Для того чтобы стать админом нужно в базе данных в таблице roles_users добавить новую строку

INSERT INTO `kohanaf2`.`roles_users` (`user_id` ,
`role_id`
)
VALUES ('1', '2'
);

Осталось для необходимых страниц изменить наследование базового контроллера. К примеру для страницы регистрации можно изменить с Page на GuestPage таким образом доступ к ней будут иметь только незарегистрированные пользователи. Для файлов же админки все файлы будем наследовать от AdminPage.

Все на сегодня =).
Сайт проекта http://cmspegas.ru

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

P.S Есть вопросы => пишем комментарии

Гиламов Данис

Приветствую вас уважаемый посетитель! Меня зовут Данис, на страницах дневника я пишу о том что мне интересно: программирование, саморазвитие, спорт, мои размышления, творчество. Надеюсь вы сможете найди для себя полезную информацию, если вы что-то заметили, захотели обсудить, прошу оставлять комментарии в статьях, в Журнале или Написать мне Для меня - это лучшая награда. Спасибо за внимание :)

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

  • Ставлю систем из ваших исходников и получаю сразу же вот такую ошибку

    ErrorException [ Warning ]: imageftbbox(): Problem loading glyph

    MODPATH\captcha\classes\captcha\alpha.php [ 72 ]
    67 $font = Captcha::$config[‘fontpath’].Captcha::$config[‘fonts’][array_rand(Captcha::$config[‘fonts’])];
    68
    69 $angle = mt_rand(-40, 20);
    70 // Scale the character size on image height
    71 $size = $default_size / 10 * mt_rand(8, 12);
    72 $box = imageftbbox($size, $angle, $font, $this->response[$i]);
    73
    74 // Calculate character starting coordinates
    75 $x = $spacing / 4 + $i * $spacing;
    76 $y = Captcha::$config[‘height’] / 2 + ($box[2] — $box[5]) / 4;
    77

    {PHP internal call} » Kohana_Core::error_handler(arguments)

    MODPATH\captcha\classes\captcha\alpha.php [ 72 ] » imageftbbox(arguments)

    APPPATH\classes\page.php [ 71 ] » Captcha_Alpha->render()

    {PHP internal call} » Page->after()

    SYSPATH\classes\kohana\request\client\internal.php [ 121 ] » ReflectionMethod->invoke(arguments)

    SYSPATH\classes\kohana\request\client.php [ 64 ] » Kohana_Request_Client_Internal->execute_request(arguments)

    SYSPATH\classes\kohana\request.php [ 1138 ] » Kohana_Request_Client->execute(arguments)

    DOCROOT\index.php [ 109 ] » Kohana_Request->execute()

    Что делать????

    • Danis92

      Странно ,у меня все работает ,у вас какой локальный сервер?

  • У меня winginx

  • Поставил на денвере правда все заработало. Очень странно что то…. Кстати проблема с роутами тоже решилась на денвере.

    • Danis92

      я смотрел что вызывает данную ошибку в интернете ,вроде как неправильный путь к библиотеке. Скорей всего в winginx он выглядит по другому чем в Denwer.

      • Да ладно это не страшно. Данис я тебе в аське стукнул ты когда онлайн бываешь. Есть еще несколько вопросов по kohana

        • Danis92

          Я час там редко бываю ,лучше есть вопросы пиши здесь. По вечерам бываю

          • У меня их много))) Слушай я копаясь в коде так и не понял там регистрация рабочая или нет?? Там дампа базы нет, вроде как и запросов в базу тоже нет. А на сайте врое рега работает

  • Danis92

    Dead_Angel, регистрация полностью рабочая ,запросы можно найди здесь modules/orm/.
    Нужно будет помещать в архив с исходниками отдельно ). Правда я об этом писал в одной статей где взять запросы.

  • Игорь Панченко

    У меня такой вопрос. Есть правила валидации, прописанные в модели. Как поступить, если в некоем контроллере мне не нужно чтобы данные форм валидировались? Естественно я говорю о работе с ORM

    • Danis92

      Никогда с подобным не сталкивался ,нужно будет полазить по коду ,возможно есть готовое решение. Пока мне представляется решение переопределить метод rules() в модели ,внести туда проверку