1
0
Fork 0
mirror of https://github.com/Oreolek/kangana.git synced 2024-06-16 15:01:09 +03:00

DAR-13: planning task

This commit is contained in:
Alexander Yakovlev 2014-01-31 15:15:50 +07:00
parent dce39db44f
commit bcd554f60d
8 changed files with 233 additions and 7 deletions

View file

@ -52,12 +52,22 @@ class Model_Letter extends ORM {
* Function to send a email to a specified address.
* Not suitable for a large-scale use.
* @param email $address email address
* TODO: render text in HTML template
**/
public function send($address)
public function send($address, $token = '')
{
return self::_send($address, $this->text, $this->subject, $token);
}
/**
* @param $address string or array of strings - email addresses
* @param $text message body
* @param $subject message subject
* @param $token user subscription token
**/
public static function _send($address, $text, $subject, $token = '')
{
$sender = Kohana::$config->load('email')->get('sender');
$email = Email::factory($this->subject, $this->text)->to($address)->from($sender);
$email = Email::factory($subject, $text)->to($address)->from($sender);
return $email->send();
}

View file

@ -71,6 +71,29 @@ class Model_Subscription extends ORM {
return ($count == 1);
}
public static function get_ids()
{
return DB::select('id')->from('subscriptions')->execute()->get('id');
}
public static function get_letter_ids($subscription_id)
{
return DB::select('id')
->from('letters')
->where('subscription_id', '=', $subscription_id)
->order_by('order')
->execute()
->get('id');
}
public static function get_client_ids($subscription_id)
{
return DB::select('client_id')
->from('clients_subscriptions')
->where('subscription_id', '=', $subscription_id)
->execute()
->get('client_id');
}
/**
* Get next letter in subscription
* @param int $offset search offset (typically number of already sent letters)

View file

@ -49,4 +49,66 @@ class Model_Task extends ORM {
$this->status = STATUS_SENT;
$this->save();
}
/**
* Get next unsent letter by client. Returns FALSE if there're no letters left to send.
* @param array $letters array of letter IDs (integers) to send
* @param int $client_id client ID
* @return int/bool first unsent letter ID or FALSE
**/
public static function next_unsent($client_id, $letters)
{
$query = DB::select(array(DB::expr('COUNT(*)'), 'cnt'))
->from('tasks');
if (is_array($letters))
{
$query = $query->where('letter_id', 'IN', $letters);
}
else
{
$query = $query->where('letter_id', '=', $letters);
}
$cnt = $query
->and_where('status', '=', self::STATUS_SENT)
->and_where('client_id', '=', $client_id)
->execute()
->get('cnt');
if ($cnt < count($letters))
{
$query = DB::select('letter_id')
->from('tasks');
if (is_array($letters))
{
$query = $query->where('letter_id', 'IN', $letters);
}
else
{
$query = $query->where('letter_id', '=', $letters);
}
$sent_letters = $query
->and_where('status', '=', self::STATUS_SENT)
->and_where('client_id', '=', $client_id)
->execute()
->get('letter_id');
if (is_array($letters))
{
$diff = array_diff($letters, $sent_letters);
return $diff[0];
}
else
{
// count($letters) is > count($sent_letters), $letters is not an array
// so there are no sent letters
return $letters;
}
}
return FALSE;
}
public static function prepare($client_id, $letter_id)
{
return DB::insert('tasks', array('client_id', 'letter_id', 'date', 'status'))
->values(array($client_id, $letter_id, date('Y-m-d'), self::STATUS_PENDING))
->execute();
}
}

View file

@ -29,8 +29,7 @@ class Task_Password extends Minion_Task
$writer = new Config_File_Writer;
Kohana::$config->attach($writer);
$config = Kohana::$config->load('auth');
$hashing_key = $config->get('hash_key');
$hash = hash_hmac('sha256', $params['password'], $hashing_key);
$hash = hash_hmac($config->get('hash_method'), $params['password'], $config->get('hash_key'));
$config->set('users', array($params['user'] => $hash));
Kohana::$config->detach($writer);
echo __('The password was successfully changed.');

View file

@ -0,0 +1,77 @@
<?php defined('SYSPATH') OR die('No direct script access.');
/**
* This is an automated task to create mailing tasks.
* It has no configurable options.
* @category Helpers
* @author Oreolek
* @license AGPL
**/
class Task_Prepare extends Minion_Task
{
protected $_options = array();
/**
* @param int $subscription subscription ID
**/
protected function prepare_subscription($subscription)
{
$count = Model_Subscription::count_letters($subscription);
if ($count == 0)
return;
$clients = Model_Subscription::get_client_ids($subscription);
$letters = Model_Subscription::get_letter_ids($subscription);
if (!is_array($clients))
{
$this->prepare_letters($clients, $letters);
}
else
{
foreach ($clients as $client)
{
$this->prepare_letters($client, $letters);
}
}
}
protected function prepare_letters($client_id, $letter_ids)
{
$letter = Model_Task::next_unsent($client_id, $letter_ids);
if ($letter !== FALSE)
{
Model_Task::prepare($client_id, $letter);
}
}
/**
* Prepare letters to be sent out.
* If a client received less letters from subscription than there is in subscription,
* a task is formed.
*
* @return null
*/
protected function _execute(array $params)
{
$db = Database::instance();
$db->begin();
try
{
$subscriptions = Model_Subscription::get_ids();
echo __('Total subscription count').': '.count($subscriptions)."\n";
if (!is_array($subscriptions))
{
$this->prepare_subscription($subscriptions);
}
else
{
foreach ($subscriptions as $subscription)
{
$this->prepare_subscription($subscription);
}
}
$db->commit();
}
catch(Database_Exception $e)
{
$db->rollback();
}
}
}

View file

@ -0,0 +1,54 @@
<?php defined('SYSPATH') OR die('No direct script access.');
/**
* This is an automated task to send all pending letters.
* It has no configurable options.
* @category Helpers
* @author Oreolek
* @license AGPL
**/
class Task_Send extends Minion_Task
{
protected $_options = array();
/**
* Send all prepared letters.
*
* @return null
* TODO: group by letters and send them using Bcc instead of one at a time
*/
protected function _execute(array $params)
{
$db = Database::instance();
$db->begin();
try
{
$letters = DB::select(
array('letters.text', 'text'),
array('letters.subject', 'subject'),
array('clients.email', 'email'),
array('clients.token', 'token')
)
->from('tasks')
->join('letters', 'LEFT')
->on('tasks.letter_id', '=', 'letters.id')
->join('clients', 'LEFT')
->on('tasks.client_id', '=', 'clients.id')
->where('tasks.status', '=', Model_Task::STATUS_PENDING)
->execute();
foreach ($letters as $letter)
{
Model_Letter::_send($letter['email'], $letter['text'], $letter['subject'], $letter['token']);
}
DB::update('tasks')
->set(array('status' => Model_Task::STATUS_SENT))
->where('status', '=', Model_Task::STATUS_PENDING)
->execute();
$db->commit();
}
catch(Database_Exception $e)
{
$db->rollback();
}
}
}

View file

@ -8,7 +8,7 @@ return array(
'users' => array(
'admin' => 'password-hash'
),
'hash_method' => 'sha256',
'hash_method' => 'sha512',
'hash_key' => "hashing_key",
'lifetime' => 1209600,
'session_key' => 'auth_user',

View file

@ -34,5 +34,6 @@ return array(
'Delete letter' => 'Удалить письмо',
'View' => 'Просмотреть',
'Message subject' => 'Тема письма',
'The password was successfully changed.' => 'Пароль был успешно изменён.'
'The password was successfully changed.' => 'Пароль был успешно изменён.',
'Total subscription count' => 'Всего подписок'
);