1
0
Fork 0
mirror of https://github.com/Oreolek/kangana.git synced 2024-06-26 03:40:56 +03:00

Renamed subscriptions to courses. Added a test.

This commit is contained in:
Alexander Yakovlev 2014-02-05 15:10:05 +07:00
parent e1433eedf1
commit ee62fd61b2
19 changed files with 221 additions and 73 deletions

3
.gitmodules vendored
View file

@ -31,3 +31,6 @@
[submodule "modules/cache"] [submodule "modules/cache"]
path = modules/cache path = modules/cache
url = git@github.com:Oreolek/cache.git url = git@github.com:Oreolek/cache.git
[submodule "modules/unittest"]
path = modules/unittest
url = git@github.com:kohana/unittest.git

View file

@ -1,9 +1,9 @@
<?php defined('SYSPATH') or die('No direct script access.'); <?php defined('SYSPATH') or die('No direct script access.');
/** /**
* Subscription controller. * Course controller.
**/ **/
class Controller_Subscription extends Controller_Layout { class Controller_Course extends Controller_Layout {
protected $secure_actions = array( protected $secure_actions = array(
'index','create', 'edit', 'delete', 'view' 'index','create', 'edit', 'delete', 'view'
); );
@ -16,9 +16,9 @@ class Controller_Subscription extends Controller_Layout {
public function action_index() public function action_index()
{ {
$this->template = new View_Subscription_Index; $this->template = new View_Course_Index;
$this->template->title = __('Subscription index'); $this->template->title = __('Course index');
$this->template->items = ORM::factory('Subscription') $this->template->items = ORM::factory('Course')
->filter_by_page($this->request->param('page')) ->filter_by_page($this->request->param('page'))
->find_all(); ->find_all();
} }
@ -26,17 +26,17 @@ class Controller_Subscription extends Controller_Layout {
public function action_create() public function action_create()
{ {
$this->template = new View_Edit; $this->template = new View_Edit;
$this->template->model = ORM::factory('Subscription'); $this->template->model = ORM::factory('Course');
$this->template->title = __('New subscription'); $this->template->title = __('New course');
$this->_edit($this->template->model); $this->_edit($this->template->model);
} }
public function action_edit() public function action_edit()
{ {
$this->template = new View_Edit; $this->template = new View_Edit;
$this->template->title = __('Edit subscription'); $this->template->title = __('Edit course');
$id = $this->request->param('id'); $id = $this->request->param('id');
$model = ORM::factory('Subscription', $id); $model = ORM::factory('Course', $id);
if (!$model->loaded()) if (!$model->loaded())
{ {
$this->redirect('error/404'); $this->redirect('error/404');
@ -48,12 +48,12 @@ class Controller_Subscription extends Controller_Layout {
{ {
$this->template = new View_Delete; $this->template = new View_Delete;
$id = $this->request->param('id'); $id = $this->request->param('id');
$model = ORM::factory('Subscription', $id); $model = ORM::factory('Course', $id);
if (!$model->loaded()) if (!$model->loaded())
{ {
$this->redirect('error/404'); $this->redirect('error/404');
} }
$this->template->title = __('Delete subscription'); $this->template->title = __('Delete course');
$this->template->content_title = $model->title; $this->template->content_title = $model->title;
$this->template->content = $model->description; $this->template->content = $model->description;
@ -67,13 +67,13 @@ class Controller_Subscription extends Controller_Layout {
{ {
$this->template = new View_Letter_Index; $this->template = new View_Letter_Index;
$id = $this->request->param('id'); $id = $this->request->param('id');
$model = ORM::factory('Subscription', $id)->with('letters'); $model = ORM::factory('Course', $id)->with('letters');
if (!$model->loaded()) if (!$model->loaded())
{ {
$this->redirect('error/404'); $this->redirect('error/404');
} }
$this->template->title = __('Subscription').' '.$model->title; $this->template->title = __('Course').' '.$model->title;
$this->template->subscription_id = $id; $this->template->course_id = $id;
$this->template->items = $model->letters $this->template->items = $model->letters
->filter_by_page($this->request->param('page')) ->filter_by_page($this->request->param('page'))
->order_by('order') ->order_by('order')
@ -82,14 +82,14 @@ class Controller_Subscription extends Controller_Layout {
public function action_subscribe() public function action_subscribe()
{ {
$this->template = new View_Subscription_Subscribe; $this->template = new View_Course_Subscribe;
$id = $this->request->param('id'); $id = $this->request->param('id');
$subscription = ORM::factory('Subscription', $id); $course = ORM::factory('Course', $id);
if (!$subscription->loaded()) if (!$course->loaded())
{ {
$this->redirect('error/404'); $this->redirect('error/404');
} }
$this->template->title = __('Subscribe to ').$subscription->title; $this->template->title = __('Subscribe to ').$course->title;
$controls = array( $controls = array(
'name' => 'input', 'name' => 'input',
'email' => 'input' 'email' => 'input'
@ -108,9 +108,9 @@ class Controller_Subscription extends Controller_Layout {
if ($validation->check()) if ($validation->check())
{ {
$model->save(); $model->save();
$model->add('subscription', $subscription); $model->add('course', $course);
$task = ORM::factory('Task'); $task = ORM::factory('Task');
$letter = $subscription->next_letter(); $letter = $course->next_letter();
$task->letter_id = $letter->id; $task->letter_id = $letter->id;
$task->client_id = $model->id; $task->client_id = $model->id;
// now we break the abstraction to speed things up // now we break the abstraction to speed things up

View file

@ -16,12 +16,12 @@ class Controller_Letter extends Controller_Layout {
{ {
$this->template = new View_Edit; $this->template = new View_Edit;
$id = $this->request->param('id'); $id = $this->request->param('id');
if (!Model_Subscription::exists($id)) if (!Model_Course::exists($id))
{ {
$this->redirect('error/500'); $this->redirect('error/500');
} }
$this->template->model = ORM::factory('Letter'); $this->template->model = ORM::factory('Letter');
$this->template->model->subscription_id = $id; $this->template->model->course_id = $id;
$this->template->title = __('New letter'); $this->template->title = __('New letter');
$this->_edit($this->template->model); $this->_edit($this->template->model);
} }

View file

@ -1,16 +1,16 @@
<?php defined('SYSPATH') OR die('No direct access allowed.'); <?php defined('SYSPATH') OR die('No direct access allowed.');
/** /**
* Subscription model. * Course model.
* Subscription is an ordered collection of letters. * Course is an ordered collection of letters.
* It has a period in days. Every <period> days a client receives a letter from the collection. * It has a period in days. Every <period> days a client receives a letter from the collection.
* @package Models * @package Models
* @author Oreolek * @author Oreolek
**/ **/
class Model_Subscription extends ORM { class Model_Course extends ORM {
protected $_has_many = array( protected $_has_many = array(
'client' => array( 'client' => array(
'model' => 'Client', 'model' => 'Client',
'through' => 'clients_subscriptions' 'through' => 'clients_courses'
), ),
'letters' => array( 'letters' => array(
'model' => 'Letter' 'model' => 'Letter'
@ -62,7 +62,7 @@ class Model_Subscription extends ORM {
public static function count_letters($id) public static function count_letters($id)
{ {
return DB::select(array(DB::expr('COUNT(*)'), 'cnt'))->from('letters')->where('subscription_id', '=', $id)->execute()->get('cnt'); return DB::select(array(DB::expr('COUNT(*)'), 'cnt'))->from('letters')->where('course_id', '=', $id)->execute()->get('cnt');
} }
/** /**
@ -70,55 +70,55 @@ class Model_Subscription extends ORM {
**/ **/
public function count_clients() public function count_clients()
{ {
return DB::select(array(DB::expr('COUNT(client_id)'), 'cnt'))->from('clients_subscriptions')->where('subscription_id', '=', $this->id)->execute()->get('cnt'); return DB::select(array(DB::expr('COUNT(client_id)'), 'cnt'))->from('clients_courses')->where('course_id', '=', $this->id)->execute()->get('cnt');
} }
public static function exists($id) public static function exists($id)
{ {
$count = DB::select(array(DB::expr('COUNT(*)'), 'cnt'))->from('subscriptions')->where('id', '=', $id)->execute()->get('cnt'); $count = DB::select(array(DB::expr('COUNT(*)'), 'cnt'))->from('courses')->where('id', '=', $id)->execute()->get('cnt');
return ($count == 1); return ($count == 1);
} }
public static function get_ids() public static function get_ids()
{ {
return DB::select('id')->from('subscriptions')->execute()->get('id'); return DB::select('id')->from('courses')->execute()->get('id');
} }
public static function get_period($subscription_id) public static function get_period($course_id)
{ {
return DB::select('period') return DB::select('period')
->from('subscriptions') ->from('courses')
->where('subscription_id', '=', $subscription_id) ->where('course_id', '=', $course_id)
->execute() ->execute()
->get('period'); ->get('period');
} }
public static function get_letter_ids($subscription_id) public static function get_letter_ids($course_id)
{ {
return DB::select('id') return DB::select('id')
->from('letters') ->from('letters')
->where('subscription_id', '=', $subscription_id) ->where('course_id', '=', $course_id)
->order_by('order') ->order_by('order')
->execute() ->execute()
->get('id'); ->get('id');
} }
public static function get_client_ids($subscription_id) public static function get_client_ids($course_id)
{ {
return DB::select('client_id') return DB::select('client_id')
->from('clients_subscriptions') ->from('clients_courses')
->where('subscription_id', '=', $subscription_id) ->where('course_id', '=', $course_id)
->execute() ->execute()
->get('client_id'); ->get('client_id');
} }
/** /**
* Get next letter in subscription * Get next letter in course
* @param int $offset search offset (typically number of already sent letters) * @param int $offset search offset (typically number of already sent letters)
**/ **/
public function next_letter($offset = 0) public function next_letter($offset = 0)
{ {
return ORM::factory('Letter') return ORM::factory('Letter')
->where('subscription_id', '=', $this->id) ->where('course_id', '=', $this->id)
->order_by('order', 'ASC') ->order_by('order', 'ASC')
->limit(1) ->limit(1)
->offset($offset) ->offset($offset)
@ -139,10 +139,10 @@ class Model_Subscription extends ORM {
} }
$query->execute(); $query->execute();
DB::delete('letters') DB::delete('letters')
->where('subscription_id', '=', $this->id) ->where('course_id', '=', $this->id)
->execute(); ->execute();
DB::delete('clients_subscriptions') DB::delete('clients_courses')
->where('subscription_id', '=', $this->id) ->where('course_id', '=', $this->id)
->execute(); ->execute();
return parent::delete(); return parent::delete();
} }

View file

@ -7,7 +7,7 @@
**/ **/
class Model_Letter extends ORM { class Model_Letter extends ORM {
protected $belongs_to = array( protected $belongs_to = array(
'subscription' 'course'
); );
/** /**
@ -44,7 +44,7 @@ class Model_Letter extends ORM {
{ {
if(empty($this->order)) if(empty($this->order))
{ {
$this->order = Model_Subscription::count_letters($this->subscription_id) + 1; $this->order = Model_Course::count_letters($this->course_id) + 1;
} }
} }
@ -62,7 +62,7 @@ class Model_Letter extends ORM {
* @param $address string or array of strings - email addresses * @param $address string or array of strings - email addresses
* @param $text message body * @param $text message body
* @param $subject message subject * @param $subject message subject
* @param $token user subscription token * @param $token user course token
**/ **/
public static function _send($address, $text, $subject, $token = '') public static function _send($address, $text, $subject, $token = '')
{ {

View file

@ -10,16 +10,16 @@ class Task_Prepare extends Minion_Task
{ {
protected $_options = array(); protected $_options = array();
/** /**
* @param int $subscription subscription ID * @param int $course course ID
**/ **/
protected function prepare_subscription($subscription) protected function prepare_course($course)
{ {
$count = Model_Subscription::count_letters($subscription); $count = Model_Course::count_letters($course);
if ($count == 0) if ($count == 0)
return; return;
$period = Model_Subscription::get_period($subscription); $period = Model_Course::get_period($course);
$clients = Model_Subscription::get_client_ids($subscription, $period); $clients = Model_Course::get_client_ids($course, $period);
$letters = Model_Subscription::get_letter_ids($subscription); $letters = Model_Course::get_letter_ids($course);
if (!is_array($clients)) if (!is_array($clients))
{ {
$this->prepare_letters($clients, $letters, $period); $this->prepare_letters($clients, $letters, $period);
@ -47,7 +47,7 @@ class Task_Prepare extends Minion_Task
/** /**
* Prepare letters to be sent out. * Prepare letters to be sent out.
* If a client received less letters from subscription than there is in subscription, * If a client received less letters from course than there is in course,
* a task is formed. * a task is formed.
* *
* @return null * @return null
@ -58,17 +58,16 @@ class Task_Prepare extends Minion_Task
$db->begin(); $db->begin();
try try
{ {
$subscriptions = Model_Subscription::get_ids(); $courses = Model_Course::get_ids();
echo __('Total subscription count').': '.count($subscriptions)."\n"; if (!is_array($courses))
if (!is_array($subscriptions))
{ {
$this->prepare_subscription($subscriptions); $this->prepare_course($courses);
} }
else else
{ {
foreach ($subscriptions as $subscription) foreach ($courses as $course)
{ {
$this->prepare_subscription($subscription); $this->prepare_course($course);
} }
} }
$db->commit(); $db->commit();

View file

@ -1,11 +1,11 @@
<?php defined('SYSPATH') OR die('No direct script access.'); <?php defined('SYSPATH') OR die('No direct script access.');
/** /**
* Subscription index view controller. * Course index view controller.
* @package Views * @package Views
* @author Oreolek * @author Oreolek
**/ **/
class View_Subscription_Index extends View_Index { class View_Course_Index extends View_Index {
protected $is_admin = TRUE; // admin only view protected $is_admin = TRUE; // admin only view
public $show_date = FALSE; public $show_date = FALSE;
public function get_header() public function get_header()

View file

@ -1,8 +1,8 @@
<?php defined('SYSPATH') or die('No direct script access.'); <?php defined('SYSPATH') or die('No direct script access.');
/** /**
* Subscription form view controller * Course subscription form view controller
**/ **/
class View_Subscription_Subscribe extends View_Edit { class View_Course_Subscribe extends View_Edit {
public $_layout = 'empty'; public $_layout = 'empty';
} }

View file

@ -77,7 +77,7 @@ class View_Layout {
else else
{ {
$navigation = array_merge($navigation, array( $navigation = array_merge($navigation, array(
__('Subscriptions') => 'subscription/index', __('Courses') => 'course/index',
'Клиенты' => 'client/index', 'Клиенты' => 'client/index',
'Поиск клиентов' => 'client/search', 'Поиск клиентов' => 'client/search',
)); ));

View file

@ -28,18 +28,15 @@ return array
'caching' => TRUE, 'caching' => TRUE,
'profiling' => FALSE, 'profiling' => FALSE,
), ),
'sphinx' => array( 'test' => array(
'type' => 'MySQLi', 'type' => 'MySQL',
'connection' => array( 'connection' => array(
'hostname' => 'localhost:9306', 'hostname' => 'localhost',
'database' => 'oreolek', // index name from sphinx config 'database' => 'oreolek',
'username' => '', 'username' => '',
'password' => '', 'password' => '',
'persistent' => FALSE, 'persistent' => FALSE,
), )
'charset' => 'utf8', )
'caching' => TRUE,
'profiling' => FALSE,
),
); );

View file

@ -16,6 +16,7 @@ return array(
'Mailing date' => 'Дата отправки', 'Mailing date' => 'Дата отправки',
'Status' => 'Статус', 'Status' => 'Статус',
'Subscriptions' => 'Рассылки', 'Subscriptions' => 'Рассылки',
'Courses' => 'Курсы',
'No objects found to show' => 'Не найдено объектов для отображения.', 'No objects found to show' => 'Не найдено объектов для отображения.',
'Add' => 'Добавить', 'Add' => 'Добавить',
'Edit' => 'Редактировать', 'Edit' => 'Редактировать',
@ -27,6 +28,11 @@ return array(
'Edit subscription' => 'Редактировать рассылку', 'Edit subscription' => 'Редактировать рассылку',
'Subscribe to ' => 'Подписка на ', 'Subscribe to ' => 'Подписка на ',
'Subscription' => 'Рассылка', 'Subscription' => 'Рассылка',
'Course' => 'Курс',
'New course' => 'Новый курс',
'Course index' => 'Список курсов',
'Delete course' => 'Удалить курс',
'Edit course' => 'Редактировать курс',
'Name' => 'Имя', 'Name' => 'Имя',
'You were subscribed. A welcome email has been sent to you. Please check your inbox.' => 'Вы были подписаны. Вам было выслано вступительное письмо; пожалуйста, проверьте входящие сообщения.', 'You were subscribed. A welcome email has been sent to you. Please check your inbox.' => 'Вы были подписаны. Вам было выслано вступительное письмо; пожалуйста, проверьте входящие сообщения.',
'New letter' => 'Новое письмо', 'New letter' => 'Новое письмо',
@ -36,6 +42,7 @@ return array(
'Message subject' => 'Тема письма', 'Message subject' => 'Тема письма',
'The password was successfully changed.' => 'Пароль был успешно изменён.', 'The password was successfully changed.' => 'Пароль был успешно изменён.',
'Total subscription count' => 'Всего подписок', 'Total subscription count' => 'Всего подписок',
'Total course count' => 'Всего курсов',
'Sending letter with subject "%subject" to address %address' => 'Отсылаю письмо с темой %subject на адрес %address', 'Sending letter with subject "%subject" to address %address' => 'Отсылаю письмо с темой %subject на адрес %address',
'Clients' => 'Клиенты', 'Clients' => 'Клиенты',
'Description' => 'Описание', 'Description' => 'Описание',

View file

@ -0,0 +1,50 @@
<?php
/**
* Test for course workflow.
* @category Tests
* @author Oreolek
* @license AGPL
**/
class CoursesTest extends Unittest_Database_TestCase
{
protected $_database_connection = 'test';
protected function getdataset()
{
return $this->createXMLDataSet(Kohana::find_file('tests', 'test_data/courses', 'xml'));
}
public function getSetUpOperation() {
// whether you want cascading truncates
// set false if unsure
$cascadeTruncates = false;
return new PHPUnit_Extensions_Database_Operation_Composite(array(
new PHPUnit_Extensions_Database_Operation_MySQL55Truncate($cascadeTruncates),
PHPUnit_Extensions_Database_Operation_Factory::INSERT()
));
}
/**
* @group Mail
**/
function testPrepareCourse()
{
Minion_Task::factory(array('task' => 'prepare'))->execute();
$status = DB::select('status')->from('tasks')->where('letter_id', '=', '1')->and_where('client_id','=','1')->execute()->get('status');
$this->assertEquals(Model_Task::STATUS_PENDING, $status);
}
function testSendCourse()
{
$status = DB::select('status')->from('tasks')->where('letter_id', '=', '1')->and_where('client_id','=','1')->execute()->get('status');
if (is_null($status))
{
DB::insert('tasks', array('letter_id', 'client_id', 'date', 'status'))->values(array('1','1',date('Y-m-d'), Model_Task::STATUS_PENDING))->execute();
}
Minion_Task::factory(array('task' => 'send'))->execute();
$status = DB::select('status')->from('tasks')->where('letter_id', '=', '1')->and_where('client_id','=','1')->execute()->get('status');
$this->assertEquals(Model_Task::STATUS_SENT, $status);
}
}

View file

@ -0,0 +1,11 @@
<?php
require_once '../../modules/unittest/bootstrap.php';
class PHPUnit_Extensions_Database_Operation_MySQL55Truncate extends PHPUnit_Extensions_Database_Operation_Truncate
{
public function execute(PHPUnit_Extensions_Database_DB_IDatabaseConnection $connection, PHPUnit_Extensions_Database_DataSet_IDataSet $dataSet) {
$connection->getConnection()->query("SET @PHAKE_PREV_foreign_key_checks = @@foreign_key_checks");
$connection->getConnection()->query("SET foreign_key_checks = 0");
parent::execute($connection, $dataSet);
$connection->getConnection()->query("SET foreign_key_checks = @PHAKE_PREV_foreign_key_checks");
}
}

View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit colors="true" bootstrap="./bootstrap.php">
<testsuites>
<testsuite name="Application Tests">
<file>../../modules/unittest/tests.php</file>
</testsuite>
</testsuites>
<groups>
<exclude>
<group>kohana</group>
</exclude>
</groups>
</phpunit>

View file

@ -0,0 +1,67 @@
<?xml version="1.0" ?>
<dataset>
<table name="courses">
<column>id</column>
<column>title</column>
<column>description</column>
<column>period</column>
<column>price</column>
<row>
<value>1</value>
<value>Test course</value>
<value>Application testing purposes</value>
<value>1</value>
<value>0</value>
</row>
</table>
<table name="clients">
<column>id</column>
<column>email</column>
<column>name</column>
<column>token</column>
<row>
<value>1</value>
<value>test@example.com</value>
<value>Test User</value>
<value></value><!-- empty token -->
</row>
</table>
<table name="clients_courses">
<column>id</column>
<column>client_id</column>
<column>course_id</column>
<row>
<value>1</value>
<value>1</value>
<value>1</value>
</row>
</table>
<table name="letters">
<column>id</column>
<column>text</column>
<column>course_id</column>
<column>order</column>
<column>subject</column>
<row>
<value>1</value>
<value>This is a test message. Please ignore it.</value>
<value>1</value>
<value>0</value>
<value>Test message #1</value>
</row>
<row>
<value>2</value>
<value>This is a test message number two. Please ignore it.</value>
<value>1</value>
<value>1</value>
<value>Test message #2</value>
</row>
</table>
<table name="tasks">
<column>id</column>
<column>letter_id</column>
<column>client_id</column>
<column>date</column>
<column>status</column>
</table>
</dataset>

BIN
model.mwb

Binary file not shown.

1
modules/unittest Submodule

@ -0,0 +1 @@
Subproject commit 8db01f00d6d94781e0e8750cc7d586221e771cc7