From bcd554f60d56f387cd574f60708ffa9918e40fba Mon Sep 17 00:00:00 2001 From: Oreolek Date: Fri, 31 Jan 2014 15:15:50 +0700 Subject: [PATCH] DAR-13: planning task --- application/classes/Model/Letter.php | 16 ++++- application/classes/Model/Subscription.php | 23 +++++++ application/classes/Model/Task.php | 62 +++++++++++++++++ application/classes/Task/Password.php | 3 +- application/classes/Task/Prepare.php | 77 ++++++++++++++++++++++ application/classes/Task/Send.php | 54 +++++++++++++++ application/config/auth.php.example | 2 +- application/i18n/ru.php | 3 +- 8 files changed, 233 insertions(+), 7 deletions(-) create mode 100644 application/classes/Task/Prepare.php create mode 100644 application/classes/Task/Send.php diff --git a/application/classes/Model/Letter.php b/application/classes/Model/Letter.php index 24b8e60..34b45bd 100644 --- a/application/classes/Model/Letter.php +++ b/application/classes/Model/Letter.php @@ -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(); } diff --git a/application/classes/Model/Subscription.php b/application/classes/Model/Subscription.php index 51b2162..2318920 100644 --- a/application/classes/Model/Subscription.php +++ b/application/classes/Model/Subscription.php @@ -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) diff --git a/application/classes/Model/Task.php b/application/classes/Model/Task.php index 27d6cb0..8b705c5 100644 --- a/application/classes/Model/Task.php +++ b/application/classes/Model/Task.php @@ -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(); + } } diff --git a/application/classes/Task/Password.php b/application/classes/Task/Password.php index 610ca23..4329a74 100644 --- a/application/classes/Task/Password.php +++ b/application/classes/Task/Password.php @@ -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.'); diff --git a/application/classes/Task/Prepare.php b/application/classes/Task/Prepare.php new file mode 100644 index 0000000..a53baf1 --- /dev/null +++ b/application/classes/Task/Prepare.php @@ -0,0 +1,77 @@ +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(); + } + } +} diff --git a/application/classes/Task/Send.php b/application/classes/Task/Send.php new file mode 100644 index 0000000..30bf001 --- /dev/null +++ b/application/classes/Task/Send.php @@ -0,0 +1,54 @@ +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(); + } + } +} diff --git a/application/config/auth.php.example b/application/config/auth.php.example index e129c4f..5915897 100644 --- a/application/config/auth.php.example +++ b/application/config/auth.php.example @@ -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', diff --git a/application/i18n/ru.php b/application/i18n/ru.php index 0671b5f..2aa7517 100644 --- a/application/i18n/ru.php +++ b/application/i18n/ru.php @@ -34,5 +34,6 @@ return array( 'Delete letter' => 'Удалить письмо', 'View' => 'Просмотреть', 'Message subject' => 'Тема письма', - 'The password was successfully changed.' => 'Пароль был успешно изменён.' + 'The password was successfully changed.' => 'Пароль был успешно изменён.', + 'Total subscription count' => 'Всего подписок' );