Друзья, продолжаем реализацию намеченных планов. Сегодня речь пойдет о создании шестеренки инвайтов, которая позволит ограничить регистрацию на сайте или же вовсе закрыть доступ для нежелательных гостей.Реализация, предложенная мною, обеспечивает только базовый функционал шестеренки. При наличии желания вы можете добавить собственный функционал.
Файловая структура
Как обычно, создадим каркас шестеренки.
Файл конфигурации
Все стандартно, без особых новшеств. Добавим только лишь параметр, позволяющий закрыть доступ для неавторизированных пользователей.;==================================================
; Invites config
;==================================================
title = Invites
description = Access to site or register via invite only
core = 1.0
group = modules
position = 1
enabled = FALSE
access_mode = FALSE
База данных
Создадим дамп таблицы, который будет исполнен при установке шестеренки./gears/invites/install.sql:
CREATE TABLE IF NOT EXISTS `invites` (
`id` int(10) unsigned NOT NULL auto_increment,
`from` int(10) unsigned NOT NULL default '1',
`to` int(10) unsigned default NULL,
`invite` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
KEY `from` (`from`),
KEY `to` (`to`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
Интернационализация
Создадим файл с языковыми переменными./gears/invites/lang/ru.lng:
[gears]
invites = "Инвайты"
invites_description = "Регистрация только по приглашениям."
[invites]
gift = "Раздача приглашений"
title = "Доступ только для участников сообщества"
invite = "Приглашение"
invites = "Приглашения"
invite_description = "Регистрация только по приглашениям.";
invited = "Приглашенные"
no_such_invite = "Такого приглашения не существует или оно уже было использовано!"
;--------------------------------------------------
; Control Panel
;--------------------------------------------------
total_invited = "Зарегистрировавшихся по приглашению"
total_invites = "Общее количество свободных приглашений"
users = "Кто получит приглашения?"
users_description = "Вы можете ввести имена пользователей через запятую или же поставить знак <strong>*</strong>, чтобы приглашения получили все пользователи.";
count = "Количество приглашений";
added = "Приглашения отправлены";
grab = "Отобрать приглашения?";
grab_description = "Все с точностью да наоборот.";
grabbed = "Приглашения отобраны";
access_mode = "Ограничение доступа к сайту"
access_mode_description = "Пользователь без авторизации не сможет увидеть содержимое сайта."
Хуки
Итак, нам потребуются хуки для следующих действий:- Переадресация на страницу авторизации для незарегистрированных пользователей, в случае, если в настройках включен соответствующий параметр.
- Добавление поля ввода для инвайта в форму регистрации.
- Сохранение id пользователя в таблице инвайтов после регистрации (для завершения цепочки «пригласивший — приглашенный»).
- Проверка правильности инвайта в форме регистрации.
- Добавление списка кодов инвайтов в профиль пользователя.
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* CoGear
*
* Content management system based on CodeIgniter
*
* @package CoGear
* @author CodeMotion, Dmitriy Belyaev
* @copyright Copyright © 2009, CodeMotion
* @license http://cogear.ru/license.html
* @link http://cogear.ru
* @since Version 1.0
* @filesource
*/
// ------------------------------------------------------------------------
/**
* Invites hooks
*
* @package CoGear
* @subpackage Invites
* @category Gears hooks
* @author CodeMotion, Dmitriy Belyaev
* @link http://cogear.ru/user_guide/
*/
/**
* Redirect to login form if 'access_mode' param is enabled and user is not registered
*
* @param object
* @return void
*/
function invites_header($CI){
if($CI->gears->invites->access_mode && !$CI->user->get('id')){
if($CI->name != 'user' && !in_array('ajax',$CI->uri->segments)){
redirect('/user/login');
}
else {
title(t('invites title'),TRUE,TRUE);
}
}
}
// ------------------------------------------------------------------------
/**
* Add invite field into register form
*
* @param object
* @return void
*/
function invites_form_result_($Form){
$CI =& get_instance();
if($Form->name == 'register' && !$CI->user->get('id')){
d('invites');
$Form->input('invite',array('validation'=>'required|check_invite','js_validation'=>'required|length[5,-1]'),6);
d();
}
}
// ------------------------------------------------------------------------
/**
* Add user id to invites table after registration is complete
*
* @param object
* @param array
* @return void
*/
function invites_form_save_after_($Form,$result){
if($Form->name == 'register'){
$CI->db->update('invites',array('to'=>$Form->insert_id),array('invite'=>$result['invite'],'to'=>NULL));
}
}
/**
* Check for invite
*
* @param string
* @return boolean
*/
function check_invite($invite){
$CI =& get_instance();
$CI->form_validation->set_message('check_invite', t('!invites no_such_invite'));
return $CI->db->get_where('invites',array('invite'=>$invite,'to'=>NULL))->row() ? TRUE : FALSE;
}
// ------------------------------------------------------------------------
/**
* Show user invites in profile
*
* @param object
* @return void
*/
function invites_panel_compile_($Panel){
if($Panel->name == 'userinfo_profile'){
$CI =& get_instance();
$item['type'] = 'line';
if($CI->user->get('id') == $Panel->data->id){
$item['left'] = fc_t('!invites invites');
$query = $CI->db->select('invite')->get_where('invites',array('from'=>$CI->user->get('id'),'to'=>NULL))->result_array();
if($query){
foreach($query as $invite){
$invites[] = $invite['invite'];
}
$item['right'] = isset($invites) ? $CI->builder->div(implode('
',$invites),'hide-show') : t('!invites no_invites');
$Panel->add($item,6);
$item['left'] = fc_t('!invites invited');
$query = $CI->db->select('users.name,users.url_name')->join('users','users.id = invites.to','inner')->get_where('invites',array('from'=>$CI->user->get('id'),'to'=>'IS NOT NULL'))->result_array();
}
if($query){
foreach($query as $invite){
$invited[] = $CI->builder->a($user['name'],l('/user/'.$user['url_name']),'user '.($CI->buddy->check($user['name']) !== FALSE ? 'buddy' : FALSE));
}
$item['right'] = isset($invited) ? implode(', ',$invited) : t('!invites no_invited');
$Panel->add($item,7);
}
}
}
}
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
Панель управления
Дает возможность раздавать инвайты пользователям, а также редактировать настройки шестеренки./gears/invites/_admin.php:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* CoGear
*
* Content management system based on CodeIgniter
*
* @package CoGear
* @author CodeMotion, Dmitriy Belyaev
* @copyright Copyright © 2009, CodeMotion
* @license http://cogear.ru/license.html
* @link http://cogear.ru
* @since Version 1.0
* @filesource
*/
// ------------------------------------------------------------------------
/**
* Invites CP controller
*
* @package CoGear
* @subpackage Invites
* @category Gears controllers
* @author CodeMotion, Dmitriy Belyaev
* @link http://cogear.ru/user_guide/
*/
class _Admin extends Controller{
/**
* Constructor
*
* @return void
*/
function _Admin(){
parent::Controller();
d('invites');
$this->invites_tabs = new Panel('invites_tabs',FALSE,FALSE,'tabs');
$this->invites_tabs->set_title = TRUE;
$this->invites_tabs->links_base = '/admin/invites/';
$this->invites_tabs->add(array('name'=>'index','text'=>fc_t('%settings'),'index'=>TRUE));
$this->invites_tabs->add(array('name'=>'gift','text'=>fc_t('gift')));
$this->invites_tabs->set_active(empty($this->uri->segments['3']) ? 'index' : $this->uri->segments['3']);
$this->invites_tabs->compile(12);
}
// ------------------------------------------------------------------------
/**
* Index method
*
* @return
*/
function index(){
$this->form->set('admin/invites')
->checkbox('access_mode')
->buttons('save')
->set_values($this->gears->invites);
if($result = $this->form->result(TRUE)){
$this->info->set(GEARS.'invites/invites')->change('access_mode',$result['access_mode'])->compile();
msg(t('form saved'));
$this->form->set_values($result);
}
$this->form->compile();
}
/**
* Show invites statistics, create invites
*
* @return void
*/
function gift(){
$this->form->set('invites')
->input('users',array('validation'=>'required'))
->input('count',array('validation'=>'required|is_natural_no_zero','js_validation'=>'required|digit'))
->checkbox('grab')
->buttons('create');
if($result = $this->form->result(TRUE)){
if(trim($result['users']) == '*'){
$users = array4key($this->db->select('url_name')->order_by('id','asc')->get('users')->result_array(),FALSE,'url_name');
}
else $users = explode(',',$result['users']);
$this->load->library('encrypt');
foreach($users as $user){
if($user = $this->user->info(url_name($user))){
if($result['grab']){
$this->db->limit($result['count'])->delete('invites',array('invites.from'=>$user->id,'invites.to'=>NULL));
} else {
for($i = 0; $i < $result['count']; $i++){
$data = array(
'datetime'=>date('H:i:s d.m.Y'),
'username'=>$user->name,
'count'=>$i
);
$invite = $this->encrypt->sha1(serialize($data));
$this->db->insert('invites',array('invites.from'=>$user->id,'invite'=>$invite));
}
}
}
}
msg(t('!invites '.(isset($result['grab']) ? 'grabbed' : 'added')),TRUE);
}
$this->form->compile();
$total_invited = $this->db->where('invites.to IS NOT NULL')->count_all_results('invites');
$this->builder->div(TRUE,'line',TRUE);
$this->builder->div(t('total_invited'),'left',TRUE);
$this->builder->div($total_invited,'right',TRUE);
$this->builder->div(FALSE,'line',TRUE);
$total_invites = $this->db->where('invites.to IS NULL')->count_all_results('invites');
$this->builder->div(TRUE,'line',TRUE);
$this->builder->div(t('total_invites'),'left',TRUE);
$this->builder->div($total_invites,'right',TRUE);
$this->builder->div(FALSE,'line',TRUE);
$this->builder->div('','clear',TRUE);
d();
}
// ------------------------------------------------------------------------
}
// ------------------------------------------------------------------------
Заключение
Не забудьте активировать шестеренку в панели управления.


Только бы вот времени где достать свободного. Впрочем чего жаловаться. Я слежу за развитием этого движка и честно рад за то, что Дима его продолжается развивать в лучшую сторону. А так я конечно бы и сам написал сайт на этом движке, как только доберусь до плотного изучения движка.
P.S. Я не робот :-)