Add email notifications
This commit is contained in:
parent
c539bdc8ab
commit
9eeded33f6
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Controller;
|
||||
|
||||
use Core\Tool;
|
||||
use Core\Registry;
|
||||
use Core\Security;
|
||||
use Core\Translator;
|
||||
|
|
@ -24,6 +25,7 @@ use Model\LastLogin;
|
|||
* @property \Model\GitHub $gitHub
|
||||
* @property \Model\LastLogin $lastLogin
|
||||
* @property \Model\Ldap $ldap
|
||||
* @property \Model\Notification $notification
|
||||
* @property \Model\Project $project
|
||||
* @property \Model\RememberMe $rememberMe
|
||||
* @property \Model\ReverseProxyAuth $reverseProxyAuth
|
||||
|
|
@ -93,9 +95,7 @@ abstract class Base
|
|||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
$class = '\Model\\'.ucfirst($name);
|
||||
$this->registry->$name = new $class($this->registry->shared('db'), $this->registry->shared('event'));
|
||||
return $this->registry->shared($name);
|
||||
return Tool::loadModel($this->registry, $name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -157,6 +157,7 @@ abstract class Base
|
|||
$this->action->attachEvents();
|
||||
$this->project->attachEvents();
|
||||
$this->webhook->attachEvents();
|
||||
$this->notification->attachEvents();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -373,7 +373,7 @@ class Board extends Base
|
|||
}
|
||||
|
||||
if (isset($values['positions'])) {
|
||||
$this->board->saveTasksPosition($values['positions']);
|
||||
$this->board->saveTasksPosition($values['positions'], $values['selected_task_id']);
|
||||
}
|
||||
|
||||
$this->response->html(
|
||||
|
|
|
|||
|
|
@ -20,7 +20,8 @@ class Config extends Base
|
|||
$this->response->html($this->template->layout('config_index', array(
|
||||
'db_size' => $this->config->getDatabaseSize(),
|
||||
'user' => $_SESSION['user'],
|
||||
'projects' => $this->project->getList(),
|
||||
'user_projects' => $this->project->getAvailableList($this->acl->getUserId()),
|
||||
'notifications' => $this->notification->readSettings($this->acl->getUserId()),
|
||||
'languages' => $this->config->getLanguages(),
|
||||
'values' => $this->config->getAll(),
|
||||
'errors' => array(),
|
||||
|
|
@ -32,6 +33,13 @@ class Config extends Base
|
|||
)));
|
||||
}
|
||||
|
||||
public function notifications()
|
||||
{
|
||||
$values = $this->request->getValues();
|
||||
$this->notification->saveSettings($this->acl->getUserId(), $values);
|
||||
$this->response->redirect('?controller=config#notifications');
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate and save settings
|
||||
*
|
||||
|
|
@ -57,7 +65,8 @@ class Config extends Base
|
|||
$this->response->html($this->template->layout('config_index', array(
|
||||
'db_size' => $this->config->getDatabaseSize(),
|
||||
'user' => $_SESSION['user'],
|
||||
'projects' => $this->project->getList(),
|
||||
'user_projects' => $this->project->getAvailableList($this->acl->getUserId()),
|
||||
'notifications' => $this->notification->readSettings($this->acl->getUserId()),
|
||||
'languages' => $this->config->getLanguages(),
|
||||
'values' => $values,
|
||||
'errors' => $errors,
|
||||
|
|
|
|||
|
|
@ -31,4 +31,11 @@ class Tool
|
|||
fclose($fp);
|
||||
}
|
||||
}
|
||||
|
||||
public static function loadModel(Registry $registry, $name)
|
||||
{
|
||||
$class = '\Model\\'.ucfirst($name);
|
||||
$registry->$name = new $class($registry);
|
||||
return $registry->shared($name);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
|
||||
namespace Event;
|
||||
|
||||
use Core\Listener;
|
||||
use Model\Notification;
|
||||
|
||||
/**
|
||||
* Base notification listener
|
||||
*
|
||||
* @package event
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
abstract class BaseNotificationListener implements Listener
|
||||
{
|
||||
/**
|
||||
* Notification model
|
||||
*
|
||||
* @accesss protected
|
||||
* @var Model\Notification
|
||||
*/
|
||||
protected $notification;
|
||||
|
||||
/**
|
||||
* Template name
|
||||
*
|
||||
* @accesss private
|
||||
* @var string
|
||||
*/
|
||||
private $template = '';
|
||||
|
||||
/**
|
||||
* Fetch data for the mail template
|
||||
*
|
||||
* @access public
|
||||
* @param array $data Event data
|
||||
* @return array
|
||||
*/
|
||||
abstract public function getTemplateData(array $data);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @access public
|
||||
* @param \Model\Notification $notification Notification model instance
|
||||
* @param string $template Template name
|
||||
*/
|
||||
public function __construct(Notification $notification, $template)
|
||||
{
|
||||
$this->template = $template;
|
||||
$this->notification = $notification;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the action
|
||||
*
|
||||
* @access public
|
||||
* @param array $data Event data dictionary
|
||||
* @return bool True if the action was executed or false when not executed
|
||||
*/
|
||||
public function execute(array $data)
|
||||
{
|
||||
$values = $this->getTemplateData($data);
|
||||
|
||||
// Get the list of users to be notified
|
||||
$users = $this->notification->getUsersList($values['task']['project_id']);
|
||||
|
||||
// Send notifications
|
||||
if ($users) {
|
||||
$this->notification->sendEmails($this->template, $users, $values);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace Event;
|
||||
|
||||
use Event\BaseNotificationListener;
|
||||
|
||||
/**
|
||||
* Comment notification listener
|
||||
*
|
||||
* @package event
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class CommentNotificationListener extends BaseNotificationListener
|
||||
{
|
||||
/**
|
||||
* Fetch data for the mail template
|
||||
*
|
||||
* @access public
|
||||
* @param array $data Event data
|
||||
* @return array
|
||||
*/
|
||||
public function getTemplateData(array $data)
|
||||
{
|
||||
$values = array();
|
||||
$values['comment'] = $this->notification->comment->getById($data['id']);
|
||||
$values['task'] = $this->notification->task->getById($data['task_id'], true);
|
||||
|
||||
return $values;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace Event;
|
||||
|
||||
use Event\BaseNotificationListener;
|
||||
|
||||
/**
|
||||
* File notification listener
|
||||
*
|
||||
* @package event
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class FileNotificationListener extends BaseNotificationListener
|
||||
{
|
||||
/**
|
||||
* Fetch data for the mail template
|
||||
*
|
||||
* @access public
|
||||
* @param array $data Event data
|
||||
* @return array
|
||||
*/
|
||||
public function getTemplateData(array $data)
|
||||
{
|
||||
$values = array();
|
||||
$values['file'] = $data;
|
||||
$values['task'] = $this->notification->task->getById($data['task_id'], true);
|
||||
|
||||
return $values;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace Event;
|
||||
|
||||
use Event\BaseNotificationListener;
|
||||
|
||||
/**
|
||||
* SubTask notification listener
|
||||
*
|
||||
* @package event
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class SubTaskNotificationListener extends BaseNotificationListener
|
||||
{
|
||||
/**
|
||||
* Fetch data for the mail template
|
||||
*
|
||||
* @access public
|
||||
* @param array $data Event data
|
||||
* @return array
|
||||
*/
|
||||
public function getTemplateData(array $data)
|
||||
{
|
||||
$values = array();
|
||||
$values['subtask'] = $this->notification->subtask->getById($data['id'], true);
|
||||
$values['task'] = $this->notification->task->getById($data['task_id'], true);
|
||||
|
||||
return $values;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace Event;
|
||||
|
||||
use Event\BaseNotificationListener;
|
||||
|
||||
/**
|
||||
* Task notification listener
|
||||
*
|
||||
* @package event
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskNotificationListener extends BaseNotificationListener
|
||||
{
|
||||
/**
|
||||
* Fetch data for the mail template
|
||||
*
|
||||
* @access public
|
||||
* @param array $data Event data
|
||||
* @return array
|
||||
*/
|
||||
public function getTemplateData(array $data)
|
||||
{
|
||||
$values = array();
|
||||
$values['task'] = $this->notification->task->getById($data['task_id'], true);
|
||||
|
||||
return $values;
|
||||
}
|
||||
}
|
||||
|
|
@ -402,4 +402,31 @@ return array(
|
|||
// 'Clone Project' => '',
|
||||
// 'Project cloned successfully.' => '',
|
||||
// 'Unable to clone this project.' => '',
|
||||
// 'Email notifications' => '',
|
||||
// 'Enable email notifications' => '',
|
||||
// 'Task position:' => '',
|
||||
// 'The task #%d have been opened.' => '',
|
||||
// 'The task #%d have been closed.' => '',
|
||||
// 'Sub-task updated' => '',
|
||||
// 'Title:' => '',
|
||||
// 'Status:' => '',
|
||||
// 'Assignee:' => '',
|
||||
// 'Time tracking:' => '',
|
||||
// 'New sub-task' => '',
|
||||
// 'New attachment added "%s"' => '',
|
||||
// 'Comment updated' => '',
|
||||
// 'New comment posted by %s' => '',
|
||||
// 'List of due tasks for the project "%s"' => '',
|
||||
// '[%s][New attachment] %s (#%d)' => '',
|
||||
// '[%s][New comment] %s (#%d)' => '',
|
||||
// '[%s][Comment updated] %s (#%d)' => '',
|
||||
// '[%s][New subtask] %s (#%d)' => '',
|
||||
// '[%s][Subtask updated] %s (#%d)' => '',
|
||||
// '[%s][New task] %s (#%d)' => '',
|
||||
// '[%s][Task updated] %s (#%d)' => '',
|
||||
// '[%s][Task closed] %s (#%d)' => '',
|
||||
// '[%s][Task opened] %s (#%d)' => '',
|
||||
// '[%s][Due tasks]' => '',
|
||||
// '[Kanboard] Notification' => '',
|
||||
// 'I want to receive notifications only for those projects:' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -401,4 +401,31 @@ return array(
|
|||
// 'Clone Project' => '',
|
||||
// 'Project cloned successfully.' => '',
|
||||
// 'Unable to clone this project.' => '',
|
||||
// 'Email notifications' => '',
|
||||
// 'Enable email notifications' => '',
|
||||
// 'Task position:' => '',
|
||||
// 'The task #%d have been opened.' => '',
|
||||
// 'The task #%d have been closed.' => '',
|
||||
// 'Sub-task updated' => '',
|
||||
// 'Title:' => '',
|
||||
// 'Status:' => '',
|
||||
// 'Assignee:' => '',
|
||||
// 'Time tracking:' => '',
|
||||
// 'New sub-task' => '',
|
||||
// 'New attachment added "%s"' => '',
|
||||
// 'Comment updated' => '',
|
||||
// 'New comment posted by %s' => '',
|
||||
// 'List of due tasks for the project "%s"' => '',
|
||||
// '[%s][New attachment] %s (#%d)' => '',
|
||||
// '[%s][New comment] %s (#%d)' => '',
|
||||
// '[%s][Comment updated] %s (#%d)' => '',
|
||||
// '[%s][New subtask] %s (#%d)' => '',
|
||||
// '[%s][Subtask updated] %s (#%d)' => '',
|
||||
// '[%s][New task] %s (#%d)' => '',
|
||||
// '[%s][Task updated] %s (#%d)' => '',
|
||||
// '[%s][Task closed] %s (#%d)' => '',
|
||||
// '[%s][Task opened] %s (#%d)' => '',
|
||||
// '[%s][Due tasks]' => '',
|
||||
// '[Kanboard] Notification' => '',
|
||||
// 'I want to receive notifications only for those projects:' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -401,4 +401,31 @@ return array(
|
|||
// 'Clone Project' => '',
|
||||
// 'Project cloned successfully.' => '',
|
||||
// 'Unable to clone this project.' => '',
|
||||
// 'Email notifications' => '',
|
||||
// 'Enable email notifications' => '',
|
||||
// 'Task position:' => '',
|
||||
// 'The task #%d have been opened.' => '',
|
||||
// 'The task #%d have been closed.' => '',
|
||||
// 'Sub-task updated' => '',
|
||||
// 'Title:' => '',
|
||||
// 'Status:' => '',
|
||||
// 'Assignee:' => '',
|
||||
// 'Time tracking:' => '',
|
||||
// 'New sub-task' => '',
|
||||
// 'New attachment added "%s"' => '',
|
||||
// 'Comment updated' => '',
|
||||
// 'New comment posted by %s' => '',
|
||||
// 'List of due tasks for the project "%s"' => '',
|
||||
// '[%s][New attachment] %s (#%d)' => '',
|
||||
// '[%s][New comment] %s (#%d)' => '',
|
||||
// '[%s][Comment updated] %s (#%d)' => '',
|
||||
// '[%s][New subtask] %s (#%d)' => '',
|
||||
// '[%s][Subtask updated] %s (#%d)' => '',
|
||||
// '[%s][New task] %s (#%d)' => '',
|
||||
// '[%s][Task updated] %s (#%d)' => '',
|
||||
// '[%s][Task closed] %s (#%d)' => '',
|
||||
// '[%s][Task opened] %s (#%d)' => '',
|
||||
// '[%s][Due tasks]' => '',
|
||||
// '[Kanboard] Notification' => '',
|
||||
// 'I want to receive notifications only for those projects:' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -399,4 +399,31 @@ return array(
|
|||
'Clone Project' => 'Cloner le projet',
|
||||
'Project cloned successfully.' => 'Projet cloné avec succès.',
|
||||
'Unable to clone this project.' => 'Impossible de cloner ce projet.',
|
||||
'Email notifications' => 'Notifications par email',
|
||||
'Enable email notifications' => 'Activer les notifications par emails',
|
||||
'Task position:' => 'Position de la tâche :',
|
||||
'The task #%d have been opened.' => 'La tâche #%d a été ouverte.',
|
||||
'The task #%d have been closed.' => 'La tâche #%d a été fermée.',
|
||||
'Sub-task updated' => 'Sous-tâche mise à jour',
|
||||
'Title:' => 'Titre :',
|
||||
'Status:' => 'État :',
|
||||
'Assignee:' => 'Assigné :',
|
||||
'Time tracking:' => 'Gestion du temps :',
|
||||
'New sub-task' => 'Nouvelle sous-tâche',
|
||||
'New attachment added "%s"' => 'Nouvelle pièce-jointe ajoutée « %s »',
|
||||
'Comment updated' => 'Commentaire ajouté',
|
||||
'New comment posted by %s' => 'Nouveau commentaire ajouté par « %s »',
|
||||
'List of due tasks for the project "%s"' => 'Liste des tâches expirées pour le projet « %s »',
|
||||
'[%s][New attachment] %s (#%d)' => '[%s][Pièce-jointe] %s (#%d)',
|
||||
'[%s][New comment] %s (#%d)' => '[%s][Nouveau commentaire] %s (#%d)',
|
||||
'[%s][Comment updated] %s (#%d)' => '[%s][Commentaire mis à jour] %s (#%d)',
|
||||
'[%s][New subtask] %s (#%d)' => '[%s][Nouvelle sous-tâche] %s (#%d)',
|
||||
'[%s][Subtask updated] %s (#%d)' => '[%s][Sous-tâche mise à jour] %s (#%d)',
|
||||
'[%s][New task] %s (#%d)' => '[%s][Nouvelle tâche] %s (#%d)',
|
||||
'[%s][Task updated] %s (#%d)' => '[%s][Tâche mise à jour] %s (#%d)',
|
||||
'[%s][Task closed] %s (#%d)' => '[%s][Tâche fermée] %s (#%d)',
|
||||
'[%s][Task opened] %s (#%d)' => '[%s][Tâche ouverte] %s (#%d)',
|
||||
'[%s][Due tasks]' => '[%s][Tâches expirées]',
|
||||
'[Kanboard] Notification' => '[Kanboard] Notification',
|
||||
'I want to receive notifications only for those projects:' => 'Je souhaite reçevoir les notifications uniquement pour les projets sélectionnés :',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -402,4 +402,31 @@ return array(
|
|||
// 'Clone Project' => '',
|
||||
// 'Project cloned successfully.' => '',
|
||||
// 'Unable to clone this project.' => '',
|
||||
// 'Email notifications' => '',
|
||||
// 'Enable email notifications' => '',
|
||||
// 'Task position:' => '',
|
||||
// 'The task #%d have been opened.' => '',
|
||||
// 'The task #%d have been closed.' => '',
|
||||
// 'Sub-task updated' => '',
|
||||
// 'Title:' => '',
|
||||
// 'Status:' => '',
|
||||
// 'Assignee:' => '',
|
||||
// 'Time tracking:' => '',
|
||||
// 'New sub-task' => '',
|
||||
// 'New attachment added "%s"' => '',
|
||||
// 'Comment updated' => '',
|
||||
// 'New comment posted by %s' => '',
|
||||
// 'List of due tasks for the project "%s"' => '',
|
||||
// '[%s][New attachment] %s (#%d)' => '',
|
||||
// '[%s][New comment] %s (#%d)' => '',
|
||||
// '[%s][Comment updated] %s (#%d)' => '',
|
||||
// '[%s][New subtask] %s (#%d)' => '',
|
||||
// '[%s][Subtask updated] %s (#%d)' => '',
|
||||
// '[%s][New task] %s (#%d)' => '',
|
||||
// '[%s][Task updated] %s (#%d)' => '',
|
||||
// '[%s][Task closed] %s (#%d)' => '',
|
||||
// '[%s][Task opened] %s (#%d)' => '',
|
||||
// '[%s][Due tasks]' => '',
|
||||
// '[Kanboard] Notification' => '',
|
||||
// 'I want to receive notifications only for those projects:' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -404,4 +404,31 @@ return array(
|
|||
'Clone Project' => 'Clonar Projeto',
|
||||
'Project cloned successfully.' => 'Projeto clonado com sucesso.',
|
||||
'Unable to clone this project.' => 'Impossível clonar este projeto.',
|
||||
// 'Email notifications' => '',
|
||||
// 'Enable email notifications' => '',
|
||||
// 'Task position:' => '',
|
||||
// 'The task #%d have been opened.' => '',
|
||||
// 'The task #%d have been closed.' => '',
|
||||
// 'Sub-task updated' => '',
|
||||
// 'Title:' => '',
|
||||
// 'Status:' => '',
|
||||
// 'Assignee:' => '',
|
||||
// 'Time tracking:' => '',
|
||||
// 'New sub-task' => '',
|
||||
// 'New attachment added "%s"' => '',
|
||||
// 'Comment updated' => '',
|
||||
// 'New comment posted by %s' => '',
|
||||
// 'List of due tasks for the project "%s"' => '',
|
||||
// '[%s][New attachment] %s (#%d)' => '',
|
||||
// '[%s][New comment] %s (#%d)' => '',
|
||||
// '[%s][Comment updated] %s (#%d)' => '',
|
||||
// '[%s][New subtask] %s (#%d)' => '',
|
||||
// '[%s][Subtask updated] %s (#%d)' => '',
|
||||
// '[%s][New task] %s (#%d)' => '',
|
||||
// '[%s][Task updated] %s (#%d)' => '',
|
||||
// '[%s][Task closed] %s (#%d)' => '',
|
||||
// '[%s][Task opened] %s (#%d)' => '',
|
||||
// '[%s][Due tasks]' => '',
|
||||
// '[Kanboard] Notification' => '',
|
||||
// 'I want to receive notifications only for those projects:' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -401,4 +401,31 @@ return array(
|
|||
// 'Clone Project' => '',
|
||||
// 'Project cloned successfully.' => '',
|
||||
// 'Unable to clone this project.' => '',
|
||||
// 'Email notifications' => '',
|
||||
// 'Enable email notifications' => '',
|
||||
// 'Task position:' => '',
|
||||
// 'The task #%d have been opened.' => '',
|
||||
// 'The task #%d have been closed.' => '',
|
||||
// 'Sub-task updated' => '',
|
||||
// 'Title:' => '',
|
||||
// 'Status:' => '',
|
||||
// 'Assignee:' => '',
|
||||
// 'Time tracking:' => '',
|
||||
// 'New sub-task' => '',
|
||||
// 'New attachment added "%s"' => '',
|
||||
// 'Comment updated' => '',
|
||||
// 'New comment posted by %s' => '',
|
||||
// 'List of due tasks for the project "%s"' => '',
|
||||
// '[%s][New attachment] %s (#%d)' => '',
|
||||
// '[%s][New comment] %s (#%d)' => '',
|
||||
// '[%s][Comment updated] %s (#%d)' => '',
|
||||
// '[%s][New subtask] %s (#%d)' => '',
|
||||
// '[%s][Subtask updated] %s (#%d)' => '',
|
||||
// '[%s][New task] %s (#%d)' => '',
|
||||
// '[%s][Task updated] %s (#%d)' => '',
|
||||
// '[%s][Task closed] %s (#%d)' => '',
|
||||
// '[%s][Task opened] %s (#%d)' => '',
|
||||
// '[%s][Due tasks]' => '',
|
||||
// '[Kanboard] Notification' => '',
|
||||
// 'I want to receive notifications only for those projects:' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -407,4 +407,30 @@ return array(
|
|||
// 'Clone Project' => '',
|
||||
// 'Project cloned successfully.' => '',
|
||||
// 'Unable to clone this project.' => '',
|
||||
// 'Email notifications' => '',
|
||||
// 'Enable email notifications' => '',
|
||||
// 'Task position:' => '',
|
||||
// 'The task #%d have been opened.' => '',
|
||||
// 'The task #%d have been closed.' => '',
|
||||
// 'Sub-task updated' => '',
|
||||
// 'Title:' => '',
|
||||
// 'Status:' => '',
|
||||
// 'Assignee:' => '',
|
||||
// 'Time tracking:' => '',
|
||||
// 'New sub-task' => '',
|
||||
// 'New attachment added "%s"' => '',
|
||||
// 'Comment updated' => '',
|
||||
// 'New comment posted by %s' => '',
|
||||
// 'List of due tasks for the project "%s"' => '',
|
||||
// '[%s][New attachment] %s (#%d)' => '',
|
||||
// '[%s][New comment] %s (#%d)' => '',
|
||||
// '[%s][Comment updated] %s (#%d)' => '',
|
||||
// '[%s][New subtask] %s (#%d)' => '',
|
||||
// '[%s][Subtask updated] %s (#%d)' => '',
|
||||
// '[%s][New task] %s (#%d)' => '',
|
||||
// '[%s][Task updated] %s (#%d)' => '',
|
||||
// '[%s][Task closed] %s (#%d)' => '',
|
||||
// '[%s][Task opened] %s (#%d)' => '',
|
||||
// '[%s][Due tasks]' => '',
|
||||
// '[Kanboard] Notification' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ class Acl extends Base
|
|||
'board' => array('index', 'show', 'assign', 'assigntask', 'save', 'check'),
|
||||
'project' => array('tasks', 'index', 'forbidden', 'search'),
|
||||
'user' => array('index', 'edit', 'update', 'forbidden', 'logout', 'index', 'unlinkgoogle', 'unlinkgithub'),
|
||||
'config' => array('index', 'removeremembermetoken'),
|
||||
'config' => array('index', 'removeremembermetoken', 'notifications'),
|
||||
'comment' => array('create', 'save', 'confirm', 'remove', 'update', 'edit', 'forbidden'),
|
||||
'file' => array('create', 'save', 'download', 'confirm', 'remove', 'open', 'image'),
|
||||
'subtask' => array('create', 'save', 'edit', 'update', 'confirm', 'remove'),
|
||||
|
|
|
|||
|
|
@ -224,25 +224,25 @@ class Action extends Base
|
|||
switch ($name) {
|
||||
case 'TaskClose':
|
||||
$className = '\Action\TaskClose';
|
||||
return new $className($project_id, new Task($this->db, $this->event));
|
||||
return new $className($project_id, new Task($this->registry));
|
||||
case 'TaskAssignCurrentUser':
|
||||
$className = '\Action\TaskAssignCurrentUser';
|
||||
return new $className($project_id, new Task($this->db, $this->event), new Acl($this->db, $this->event));
|
||||
return new $className($project_id, new Task($this->registry), new Acl($this->registry));
|
||||
case 'TaskAssignSpecificUser':
|
||||
$className = '\Action\TaskAssignSpecificUser';
|
||||
return new $className($project_id, new Task($this->db, $this->event));
|
||||
return new $className($project_id, new Task($this->registry));
|
||||
case 'TaskDuplicateAnotherProject':
|
||||
$className = '\Action\TaskDuplicateAnotherProject';
|
||||
return new $className($project_id, new Task($this->db, $this->event));
|
||||
return new $className($project_id, new Task($this->registry));
|
||||
case 'TaskAssignColorUser':
|
||||
$className = '\Action\TaskAssignColorUser';
|
||||
return new $className($project_id, new Task($this->db, $this->event));
|
||||
return new $className($project_id, new Task($this->registry));
|
||||
case 'TaskAssignColorCategory':
|
||||
$className = '\Action\TaskAssignColorCategory';
|
||||
return new $className($project_id, new Task($this->db, $this->event));
|
||||
return new $className($project_id, new Task($this->registry));
|
||||
case 'TaskAssignCategoryColor':
|
||||
$className = '\Action\TaskAssignCategoryColor';
|
||||
return new $className($project_id, new Task($this->db, $this->event));
|
||||
return new $className($project_id, new Task($this->registry));
|
||||
default:
|
||||
throw new LogicException('Action not found: '.$name);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ require __DIR__.'/../../vendor/SimpleValidator/Validators/Email.php';
|
|||
require __DIR__.'/../../vendor/SimpleValidator/Validators/Numeric.php';
|
||||
|
||||
use Core\Event;
|
||||
use Core\Tool;
|
||||
use Core\Registry;
|
||||
use PicoDb\Database;
|
||||
|
||||
/**
|
||||
|
|
@ -24,6 +26,21 @@ use PicoDb\Database;
|
|||
*
|
||||
* @package model
|
||||
* @author Frederic Guillot
|
||||
*
|
||||
* @property \Model\Acl $acl
|
||||
* @property \Model\Action $action
|
||||
* @property \Model\Board $board
|
||||
* @property \Model\Category $category
|
||||
* @property \Model\Comment $comment
|
||||
* @property \Model\Config $config
|
||||
* @property \Model\File $file
|
||||
* @property \Model\LastLogin $lastLogin
|
||||
* @property \Model\Ldap $ldap
|
||||
* @property \Model\Notification $notification
|
||||
* @property \Model\Project $project
|
||||
* @property \Model\SubTask $subTask
|
||||
* @property \Model\Task $task
|
||||
* @property \Model\User $user
|
||||
*/
|
||||
abstract class Base
|
||||
{
|
||||
|
|
@ -43,16 +60,36 @@ abstract class Base
|
|||
*/
|
||||
protected $event;
|
||||
|
||||
/**
|
||||
* Registry instance
|
||||
*
|
||||
* @access protected
|
||||
* @var \Core\Registry
|
||||
*/
|
||||
protected $registry;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @access public
|
||||
* @param \PicoDb\Database $db Database instance
|
||||
* @param \Core\Event $event Event dispatcher instance
|
||||
* @param \Core\Registry $registry Registry instance
|
||||
*/
|
||||
public function __construct(Database $db, Event $event)
|
||||
public function __construct(Registry $registry)
|
||||
{
|
||||
$this->db = $db;
|
||||
$this->event = $event;
|
||||
$this->registry = $registry;
|
||||
$this->db = $this->registry->shared('db');
|
||||
$this->event = $this->registry->shared('event');
|
||||
}
|
||||
|
||||
/**
|
||||
* Load automatically models
|
||||
*
|
||||
* @access public
|
||||
* @param string $name Model name
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
return Tool::loadModel($this->registry, $name);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,17 +24,18 @@ class Board extends Base
|
|||
* Save task positions for each column
|
||||
*
|
||||
* @access public
|
||||
* @param array $values [['task_id' => X, 'column_id' => X, 'position' => X], ...]
|
||||
* @param array $positions [['task_id' => X, 'column_id' => X, 'position' => X], ...]
|
||||
* @param integer $selected_task_id The selected task id
|
||||
* @return boolean
|
||||
*/
|
||||
public function saveTasksPosition(array $values)
|
||||
public function saveTasksPosition(array $positions, $selected_task_id)
|
||||
{
|
||||
$taskModel = new Task($this->db, $this->event);
|
||||
|
||||
$this->db->startTransaction();
|
||||
|
||||
foreach ($values as $value) {
|
||||
if (! $taskModel->move($value['task_id'], $value['column_id'], $value['position'])) {
|
||||
foreach ($positions as $value) {
|
||||
|
||||
// We trigger events only for the selected task
|
||||
if (! $this->task->move($value['task_id'], $value['column_id'], $value['position'], $value['task_id'] == $selected_task_id)) {
|
||||
$this->db->cancelTransaction();
|
||||
return false;
|
||||
}
|
||||
|
|
@ -201,8 +202,7 @@ class Board extends Base
|
|||
$filters[] = array('column' => 'project_id', 'operator' => 'eq', 'value' => $project_id);
|
||||
$filters[] = array('column' => 'is_active', 'operator' => 'eq', 'value' => Task::STATUS_OPEN);
|
||||
|
||||
$taskModel = new Task($this->db, $this->event);
|
||||
$tasks = $taskModel->find($filters);
|
||||
$tasks = $this->task->find($filters);
|
||||
|
||||
foreach ($columns as &$column) {
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,14 @@ class Comment extends Base
|
|||
*/
|
||||
const TABLE = 'comments';
|
||||
|
||||
/**
|
||||
* Events
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const EVENT_UPDATE = 'comment.update';
|
||||
const EVENT_CREATE = 'comment.create';
|
||||
|
||||
/**
|
||||
* Get all comments for a given task
|
||||
*
|
||||
|
|
@ -95,7 +103,14 @@ class Comment extends Base
|
|||
{
|
||||
$values['date'] = time();
|
||||
|
||||
return $this->db->table(self::TABLE)->save($values);
|
||||
if ($this->db->table(self::TABLE)->save($values)) {
|
||||
|
||||
$values['id'] = $this->db->getConnection()->getLastId();
|
||||
$this->event->trigger(self::EVENT_CREATE, $values);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -107,10 +122,14 @@ class Comment extends Base
|
|||
*/
|
||||
public function update(array $values)
|
||||
{
|
||||
return $this->db
|
||||
$result = $this->db
|
||||
->table(self::TABLE)
|
||||
->eq('id', $values['id'])
|
||||
->update(array('comment' => $values['comment']));
|
||||
|
||||
$this->event->trigger(self::EVENT_UPDATE, $values);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -24,6 +24,13 @@ class File extends Base
|
|||
*/
|
||||
const BASE_PATH = 'data/files/';
|
||||
|
||||
/**
|
||||
* Events
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const EVENT_CREATE = 'file.create';
|
||||
|
||||
/**
|
||||
* Get a file by the id
|
||||
*
|
||||
|
|
@ -82,6 +89,8 @@ class File extends Base
|
|||
*/
|
||||
public function create($task_id, $name, $path, $is_image)
|
||||
{
|
||||
$this->event->trigger(self::EVENT_CREATE, array('task_id' => $task_id, 'name' => $name));
|
||||
|
||||
return $this->db->table(self::TABLE)->save(array(
|
||||
'task_id' => $task_id,
|
||||
'name' => $name,
|
||||
|
|
|
|||
|
|
@ -26,22 +26,19 @@ class GitHub extends Base
|
|||
*/
|
||||
public function authenticate($github_id)
|
||||
{
|
||||
$userModel = new User($this->db, $this->event);
|
||||
|
||||
$user = $userModel->getByGitHubId($github_id);
|
||||
$user = $this->user->getByGitHubId($github_id);
|
||||
|
||||
if ($user) {
|
||||
|
||||
// Create the user session
|
||||
$userModel->updateSession($user);
|
||||
$this->user->updateSession($user);
|
||||
|
||||
// Update login history
|
||||
$lastLogin = new LastLogin($this->db, $this->event);
|
||||
$lastLogin->create(
|
||||
$this->lastLogin->create(
|
||||
LastLogin::AUTH_GITHUB,
|
||||
$user['id'],
|
||||
$userModel->getIpAddress(),
|
||||
$userModel->getUserAgent()
|
||||
$this->user->getIpAddress(),
|
||||
$this->user->getUserAgent()
|
||||
);
|
||||
|
||||
return true;
|
||||
|
|
@ -59,9 +56,7 @@ class GitHub extends Base
|
|||
*/
|
||||
public function unlink($user_id)
|
||||
{
|
||||
$userModel = new User($this->db, $this->event);
|
||||
|
||||
return $userModel->update(array(
|
||||
return $this->user->update(array(
|
||||
'id' => $user_id,
|
||||
'github_id' => '',
|
||||
));
|
||||
|
|
@ -78,9 +73,7 @@ class GitHub extends Base
|
|||
*/
|
||||
public function updateUser($user_id, array $profile)
|
||||
{
|
||||
$userModel = new User($this->db, $this->event);
|
||||
|
||||
return $userModel->update(array(
|
||||
return $this->user->update(array(
|
||||
'id' => $user_id,
|
||||
'github_id' => $profile['id'],
|
||||
'email' => $profile['email'],
|
||||
|
|
@ -141,7 +134,7 @@ class GitHub extends Base
|
|||
try {
|
||||
$gitHubService = $this->getService();
|
||||
$gitHubService->requestAccessToken($code);
|
||||
|
||||
|
||||
return json_decode($gitHubService->request('user'), true);
|
||||
}
|
||||
catch (TokenResponseException $e) {
|
||||
|
|
@ -150,7 +143,7 @@ class GitHub extends Base
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Revokes this user's GitHub tokens for Kanboard
|
||||
*
|
||||
|
|
|
|||
|
|
@ -27,21 +27,19 @@ class Google extends Base
|
|||
*/
|
||||
public function authenticate($google_id)
|
||||
{
|
||||
$userModel = new User($this->db, $this->event);
|
||||
$user = $userModel->getByGoogleId($google_id);
|
||||
$user = $this->user->getByGoogleId($google_id);
|
||||
|
||||
if ($user) {
|
||||
|
||||
// Create the user session
|
||||
$userModel->updateSession($user);
|
||||
$this->user->updateSession($user);
|
||||
|
||||
// Update login history
|
||||
$lastLogin = new LastLogin($this->db, $this->event);
|
||||
$lastLogin->create(
|
||||
$this->lastLogin->create(
|
||||
LastLogin::AUTH_GOOGLE,
|
||||
$user['id'],
|
||||
$userModel->getIpAddress(),
|
||||
$userModel->getUserAgent()
|
||||
$this->user->getIpAddress(),
|
||||
$this->user->getUserAgent()
|
||||
);
|
||||
|
||||
return true;
|
||||
|
|
@ -59,9 +57,7 @@ class Google extends Base
|
|||
*/
|
||||
public function unlink($user_id)
|
||||
{
|
||||
$userModel = new User($this->db, $this->event);
|
||||
|
||||
return $userModel->update(array(
|
||||
return $this->user->update(array(
|
||||
'id' => $user_id,
|
||||
'google_id' => '',
|
||||
));
|
||||
|
|
@ -77,9 +73,7 @@ class Google extends Base
|
|||
*/
|
||||
public function updateUser($user_id, array $profile)
|
||||
{
|
||||
$userModel = new User($this->db, $this->event);
|
||||
|
||||
return $userModel->update(array(
|
||||
return $this->user->update(array(
|
||||
'id' => $user_id,
|
||||
'google_id' => $profile['id'],
|
||||
'email' => $profile['email'],
|
||||
|
|
|
|||
|
|
@ -73,8 +73,7 @@ class Ldap extends Base
|
|||
*/
|
||||
public function create($username, $name, $email)
|
||||
{
|
||||
$userModel = new User($this->db, $this->event);
|
||||
$user = $userModel->getByUsername($username);
|
||||
$user = $this->user->getByUsername($username);
|
||||
|
||||
// There is an existing user account
|
||||
if ($user) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,215 @@
|
|||
<?php
|
||||
|
||||
namespace Model;
|
||||
|
||||
use Core\Template;
|
||||
use Event\TaskNotificationListener;
|
||||
use Event\CommentNotificationListener;
|
||||
use Event\FileNotificationListener;
|
||||
use Event\SubTaskNotificationListener;
|
||||
use Swift_Message;
|
||||
use Swift_Mailer;
|
||||
|
||||
/**
|
||||
* Notification model
|
||||
*
|
||||
* @package model
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Notification extends Base
|
||||
{
|
||||
/**
|
||||
* SQL table name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const TABLE = 'user_has_notifications';
|
||||
|
||||
/**
|
||||
* Get the list of users to send the notification for a given project
|
||||
*
|
||||
* @access public
|
||||
* @param integer $project_id Project id
|
||||
* @return array
|
||||
*/
|
||||
public function getUsersList($project_id)
|
||||
{
|
||||
$users = $this->db->table(User::TABLE)
|
||||
->columns('id', 'username', 'name', 'email')
|
||||
->eq('notifications_enabled', '1')
|
||||
->neq('email', '')
|
||||
->findAll();
|
||||
|
||||
foreach ($users as $index => $user) {
|
||||
|
||||
$projects = $this->db->table(self::TABLE)
|
||||
->eq('user_id', $user['id'])
|
||||
->findAllByColumn('project_id');
|
||||
|
||||
// The user have selected only some projects
|
||||
if (! empty($projects)) {
|
||||
|
||||
// If the user didn't select this project we remove that guy from the list
|
||||
if (! in_array($project_id, $projects)) {
|
||||
unset($users[$index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $users;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach events
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function attachEvents()
|
||||
{
|
||||
$this->event->attach(File::EVENT_CREATE, new FileNotificationListener($this, 'notification_file_creation'));
|
||||
|
||||
$this->event->attach(Comment::EVENT_CREATE, new CommentNotificationListener($this, 'notification_comment_creation'));
|
||||
$this->event->attach(Comment::EVENT_UPDATE, new CommentNotificationListener($this, 'notification_comment_update'));
|
||||
|
||||
$this->event->attach(SubTask::EVENT_CREATE, new SubTaskNotificationListener($this, 'notification_subtask_creation'));
|
||||
$this->event->attach(SubTask::EVENT_UPDATE, new SubTaskNotificationListener($this, 'notification_subtask_update'));
|
||||
|
||||
$this->event->attach(Task::EVENT_CREATE, new TaskNotificationListener($this, 'notification_task_creation'));
|
||||
$this->event->attach(Task::EVENT_UPDATE, new TaskNotificationListener($this, 'notification_task_update'));
|
||||
$this->event->attach(Task::EVENT_CLOSE, new TaskNotificationListener($this, 'notification_task_close'));
|
||||
$this->event->attach(Task::EVENT_OPEN, new TaskNotificationListener($this, 'notification_task_open'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the email notifications
|
||||
*
|
||||
* @access public
|
||||
* @param string $template Template name
|
||||
* @param array $users List of users
|
||||
* @param array $data Template data
|
||||
*/
|
||||
public function sendEmails($template, array $users, array $data)
|
||||
{
|
||||
$transport = $this->registry->shared('mailer');
|
||||
$mailer = Swift_Mailer::newInstance($transport);
|
||||
|
||||
$message = Swift_Message::newInstance()
|
||||
->setSubject($this->getMailSubject($template, $data))
|
||||
->setFrom(array(MAIL_FROM => 'Kanboard'))
|
||||
//->setTo(array($user['email'] => $user['name']))
|
||||
->setBody($this->getMailContent($template, $data), 'text/html');
|
||||
|
||||
foreach ($users as $user) {
|
||||
$message->setTo(array($user['email'] => $user['name'] ?: $user['username']));
|
||||
$mailer->send($message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail subject for a given template name
|
||||
*
|
||||
* @access public
|
||||
* @param string $template Template name
|
||||
* @param array $data Template data
|
||||
*/
|
||||
public function getMailSubject($template, array $data)
|
||||
{
|
||||
switch ($template) {
|
||||
case 'notification_file_creation':
|
||||
return t('[%s][New attachment] %s (#%d)', $data['task']['project_name'], $data['task']['title'], $data['task']['id']);
|
||||
case 'notification_comment_creation':
|
||||
return t('[%s][New comment] %s (#%d)', $data['task']['project_name'], $data['task']['title'], $data['task']['id']);
|
||||
case 'notification_comment_update':
|
||||
return t('[%s][Comment updated] %s (#%d)', $data['task']['project_name'], $data['task']['title'], $data['task']['id']);
|
||||
case 'notification_subtask_creation':
|
||||
return t('[%s][New subtask] %s (#%d)', $data['task']['project_name'], $data['task']['title'], $data['task']['id']);
|
||||
case 'notification_subtask_update':
|
||||
return t('[%s][Subtask updated] %s (#%d)', $data['task']['project_name'], $data['task']['title'], $data['task']['id']);
|
||||
case 'notification_task_creation':
|
||||
return t('[%s][New task] %s (#%d)', $data['task']['project_name'], $data['task']['title'], $data['task']['id']);
|
||||
case 'notification_task_update':
|
||||
return t('[%s][Task updated] %s (#%d)', $data['task']['project_name'], $data['task']['title'], $data['task']['id']);
|
||||
case 'notification_task_close':
|
||||
return t('[%s][Task closed] %s (#%d)', $data['task']['project_name'], $data['task']['title'], $data['task']['id']);
|
||||
case 'notification_task_open':
|
||||
return t('[%s][Task opened] %s (#%d)', $data['task']['project_name'], $data['task']['title'], $data['task']['id']);
|
||||
case 'notification_task_due':
|
||||
return t('[%s][Due tasks]', $data['project']);
|
||||
}
|
||||
|
||||
return t('[Kanboard] Notification');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail content for a given template name
|
||||
*
|
||||
* @access public
|
||||
* @param string $template Template name
|
||||
* @param array $data Template data
|
||||
*/
|
||||
public function getMailContent($template, array $data)
|
||||
{
|
||||
$tpl = new Template;
|
||||
return $tpl->load($template, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save settings for the given user
|
||||
*
|
||||
* @access public
|
||||
* @param integer $user_id User id
|
||||
* @param array $values Form values
|
||||
*/
|
||||
public function saveSettings($user_id, array $values)
|
||||
{
|
||||
// Delete all selected projects
|
||||
$this->db->table(self::TABLE)->eq('user_id', $user_id)->remove();
|
||||
|
||||
if (isset($values['notifications_enabled']) && $values['notifications_enabled'] == 1) {
|
||||
|
||||
// Activate notifications
|
||||
$this->db->table(User::TABLE)->eq('id', $user_id)->update(array(
|
||||
'notifications_enabled' => '1'
|
||||
));
|
||||
|
||||
// Save selected projects
|
||||
if (! empty($values['projects'])) {
|
||||
|
||||
foreach ($values['projects'] as $project_id => $checkbox_value) {
|
||||
$this->db->table(self::TABLE)->insert(array(
|
||||
'user_id' => $user_id,
|
||||
'project_id' => $project_id,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
// Disable notifications
|
||||
$this->db->table(User::TABLE)->eq('id', $user_id)->update(array(
|
||||
'notifications_enabled' => '0'
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read user settings to display the form
|
||||
*
|
||||
* @access public
|
||||
* @param integer $user_id User id
|
||||
* @return array
|
||||
*/
|
||||
public function readSettings($user_id)
|
||||
{
|
||||
$values = array();
|
||||
$values['notifications_enabled'] = $this->db->table(User::TABLE)->eq('id', $user_id)->findOneColumn('notifications_enabled');
|
||||
|
||||
$projects = $this->db->table(self::TABLE)->eq('user_id', $user_id)->findAllByColumn('project_id');
|
||||
|
||||
foreach ($projects as $project_id) {
|
||||
$values['project_'.$project_id] = true;
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
}
|
||||
|
|
@ -55,10 +55,9 @@ class Project extends Base
|
|||
public function getUsersList($project_id, $prepend_unassigned = true, $prepend_everybody = false)
|
||||
{
|
||||
$allowed_users = $this->getAllowedUsers($project_id);
|
||||
$userModel = new User($this->db, $this->event);
|
||||
|
||||
if (empty($allowed_users)) {
|
||||
$allowed_users = $userModel->getList();
|
||||
$allowed_users = $this->user->getList();
|
||||
}
|
||||
|
||||
if ($prepend_unassigned) {
|
||||
|
|
@ -103,8 +102,7 @@ class Project extends Base
|
|||
'not_allowed' => array(),
|
||||
);
|
||||
|
||||
$userModel = new User($this->db, $this->event);
|
||||
$all_users = $userModel->getList();
|
||||
$all_users = $this->user->getList();
|
||||
|
||||
$users['allowed'] = $this->getAllowedUsers($project_id);
|
||||
|
||||
|
|
@ -253,27 +251,23 @@ class Project extends Base
|
|||
->asc('name')
|
||||
->findAll();
|
||||
|
||||
$boardModel = new Board($this->db, $this->event);
|
||||
$taskModel = new Task($this->db, $this->event);
|
||||
$aclModel = new Acl($this->db, $this->event);
|
||||
|
||||
foreach ($projects as $pkey => &$project) {
|
||||
|
||||
if ($check_permissions && ! $this->isUserAllowed($project['id'], $aclModel->getUserId())) {
|
||||
if ($check_permissions && ! $this->isUserAllowed($project['id'], $this->acl->getUserId())) {
|
||||
unset($projects[$pkey]);
|
||||
}
|
||||
else {
|
||||
|
||||
$columns = $boardModel->getcolumns($project['id']);
|
||||
$columns = $this->board->getcolumns($project['id']);
|
||||
$project['nb_active_tasks'] = 0;
|
||||
|
||||
foreach ($columns as &$column) {
|
||||
$column['nb_active_tasks'] = $taskModel->countByColumnId($project['id'], $column['id']);
|
||||
$column['nb_active_tasks'] = $this->task->countByColumnId($project['id'], $column['id']);
|
||||
$project['nb_active_tasks'] += $column['nb_active_tasks'];
|
||||
}
|
||||
|
||||
$project['columns'] = $columns;
|
||||
$project['nb_tasks'] = $taskModel->countByProjectId($project['id']);
|
||||
$project['nb_tasks'] = $this->task->countByProjectId($project['id']);
|
||||
$project['nb_inactive_tasks'] = $project['nb_tasks'] - $project['nb_active_tasks'];
|
||||
}
|
||||
}
|
||||
|
|
@ -416,9 +410,8 @@ class Project extends Base
|
|||
*/
|
||||
public function copyBoardFromAnotherProject($project_from, $project_to)
|
||||
{
|
||||
$boardModel = new Board($this->db, $this->event);
|
||||
$columns = $this->db->table(Board::TABLE)->eq('project_id', $project_from)->asc('position')->findAllByColumn('title');
|
||||
return $boardModel->create($project_to, $columns);
|
||||
return $this->board->create($project_to, $columns);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -431,8 +424,7 @@ class Project extends Base
|
|||
*/
|
||||
public function copyCategoriesFromAnotherProject($project_from, $project_to)
|
||||
{
|
||||
$categoryModel = new Category($this->db, $this->event);
|
||||
$categoriesTemplate = $categoryModel->getAll($project_from);
|
||||
$categoriesTemplate = $this->category->getAll($project_from);
|
||||
|
||||
foreach ($categoriesTemplate as $category) {
|
||||
|
||||
|
|
@ -478,8 +470,7 @@ class Project extends Base
|
|||
*/
|
||||
public function copyActionsFromAnotherProject($project_from, $project_to)
|
||||
{
|
||||
$actionModel = new Action($this->db, $this->event);
|
||||
$actionTemplate = $actionModel->getAllByProject($project_from);
|
||||
$actionTemplate = $this->action->getAllByProject($project_from);
|
||||
|
||||
foreach ($actionTemplate as $action) {
|
||||
|
||||
|
|
@ -522,13 +513,11 @@ class Project extends Base
|
|||
case 'project_id':
|
||||
return $project_to;
|
||||
case 'category_id':
|
||||
$categoryModel = new Category($this->db, $this->event);
|
||||
$categoryTemplate = $categoryModel->getById($param['value']);
|
||||
$categoryTemplate = $this->category->getById($param['value']);
|
||||
$categoryFromNewProject = $this->db->table(Category::TABLE)->eq('project_id', $project_to)->eq('name', $categoryTemplate['name'])->findOne();
|
||||
return $categoryFromNewProject['id'];
|
||||
case 'column_id':
|
||||
$boardModel = new Board($this->db, $this->event);
|
||||
$boardTemplate = $boardModel->getColumn($param['value']);
|
||||
$boardTemplate = $this->board->getColumn($param['value']);
|
||||
$boardFromNewProject = $this->db->table(Board::TABLE)->eq('project_id', $project_to)->eq('title', $boardTemplate['title'])->findOne();
|
||||
return $boardFromNewProject['id'];
|
||||
default:
|
||||
|
|
@ -603,8 +592,7 @@ class Project extends Base
|
|||
|
||||
$project_id = $this->db->getConnection()->getLastId();
|
||||
|
||||
$boardModel = new Board($this->db, $this->event);
|
||||
$boardModel->create($project_id, array(
|
||||
$this->board->create($project_id, array(
|
||||
t('Backlog'),
|
||||
t('Ready'),
|
||||
t('Work in progress'),
|
||||
|
|
|
|||
|
|
@ -92,11 +92,8 @@ class RememberMe extends Base
|
|||
);
|
||||
|
||||
// Create the session
|
||||
$user = new User($this->db, $this->event);
|
||||
$acl = new Acl($this->db, $this->event);
|
||||
|
||||
$user->updateSession($user->getById($record['user_id']));
|
||||
$acl->isRememberMe(true);
|
||||
$this->user->updateSession($this->user->getById($record['user_id']));
|
||||
$this->acl->isRememberMe(true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,24 +23,22 @@ class ReverseProxyAuth extends Base
|
|||
if (isset($_SERVER[REVERSE_PROXY_USER_HEADER])) {
|
||||
|
||||
$login = $_SERVER[REVERSE_PROXY_USER_HEADER];
|
||||
$userModel = new User($this->db, $this->event);
|
||||
$user = $userModel->getByUsername($login);
|
||||
$user = $this->user->getByUsername($login);
|
||||
|
||||
if (! $user) {
|
||||
$this->createUser($login);
|
||||
$user = $userModel->getByUsername($login);
|
||||
$user = $this->user->getByUsername($login);
|
||||
}
|
||||
|
||||
// Create the user session
|
||||
$userModel->updateSession($user);
|
||||
$this->user->updateSession($user);
|
||||
|
||||
// Update login history
|
||||
$lastLogin = new LastLogin($this->db, $this->event);
|
||||
$lastLogin->create(
|
||||
$this->lastLogin->create(
|
||||
LastLogin::AUTH_REVERSE_PROXY,
|
||||
$user['id'],
|
||||
$userModel->getIpAddress(),
|
||||
$userModel->getUserAgent()
|
||||
$this->user->getIpAddress(),
|
||||
$this->user->getUserAgent()
|
||||
);
|
||||
|
||||
return true;
|
||||
|
|
@ -58,9 +56,7 @@ class ReverseProxyAuth extends Base
|
|||
*/
|
||||
private function createUser($login)
|
||||
{
|
||||
$userModel = new User($this->db, $this->event);
|
||||
|
||||
return $userModel->create(array(
|
||||
return $this->user->create(array(
|
||||
'email' => strpos($login, '@') !== false ? $login : '',
|
||||
'username' => $login,
|
||||
'is_admin' => REVERSE_PROXY_DEFAULT_ADMIN === $login,
|
||||
|
|
|
|||
|
|
@ -41,6 +41,14 @@ class SubTask extends Base
|
|||
*/
|
||||
const STATUS_TODO = 0;
|
||||
|
||||
/**
|
||||
* Events
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const EVENT_UPDATE = 'subtask.update';
|
||||
const EVENT_CREATE = 'subtask.create';
|
||||
|
||||
/**
|
||||
* Get available status
|
||||
*
|
||||
|
|
@ -88,10 +96,27 @@ class SubTask extends Base
|
|||
*
|
||||
* @access public
|
||||
* @param integer $subtask_id Subtask id
|
||||
* @param bool $more Fetch more data
|
||||
* @return array
|
||||
*/
|
||||
public function getById($subtask_id)
|
||||
public function getById($subtask_id, $more = false)
|
||||
{
|
||||
if ($more) {
|
||||
|
||||
$subtask = $this->db->table(self::TABLE)
|
||||
->eq(self::TABLE.'.id', $subtask_id)
|
||||
->columns(self::TABLE.'.*', User::TABLE.'.username', User::TABLE.'.name')
|
||||
->join(User::TABLE, 'id', 'user_id')
|
||||
->findOne();
|
||||
|
||||
if ($subtask) {
|
||||
$status = $this->getStatusList();
|
||||
$subtask['status_name'] = $status[$subtask['status']];
|
||||
}
|
||||
|
||||
return $subtask;
|
||||
}
|
||||
|
||||
return $this->db->table(self::TABLE)->eq('id', $subtask_id)->findOne();
|
||||
}
|
||||
|
||||
|
|
@ -116,7 +141,14 @@ class SubTask extends Base
|
|||
$values['time_spent'] = 0;
|
||||
}
|
||||
|
||||
return $this->db->table(self::TABLE)->save($values);
|
||||
$result = $this->db->table(self::TABLE)->save($values);
|
||||
|
||||
if ($result) {
|
||||
$values['id'] = $this->db->getConnection()->getLastId();
|
||||
$this->event->trigger(self::EVENT_CREATE, $values);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -136,7 +168,13 @@ class SubTask extends Base
|
|||
$values['time_spent'] = 0;
|
||||
}
|
||||
|
||||
return $this->db->table(self::TABLE)->eq('id', $values['id'])->save($values);
|
||||
$result = $this->db->table(self::TABLE)->eq('id', $values['id'])->save($values);
|
||||
|
||||
if ($result) {
|
||||
$this->event->trigger(self::EVENT_UPDATE, $values);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -62,6 +62,35 @@ class Task extends Base
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of due tasks for all projects
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getTasksDue()
|
||||
{
|
||||
$tasks = $this->db->table(self::TABLE)
|
||||
->columns(
|
||||
self::TABLE.'.id',
|
||||
self::TABLE.'.title',
|
||||
self::TABLE.'.date_due',
|
||||
self::TABLE.'.project_id',
|
||||
Project::TABLE.'.name AS project_name',
|
||||
User::TABLE.'.username AS assignee_username',
|
||||
User::TABLE.'.name AS assignee_name'
|
||||
)
|
||||
->join(Project::TABLE, 'id', 'project_id')
|
||||
->join(User::TABLE, 'id', 'owner_id')
|
||||
->eq(Project::TABLE.'.is_active', 1)
|
||||
->eq(self::TABLE.'.is_active', 1)
|
||||
->neq(self::TABLE.'.date_due', '')
|
||||
->lte(self::TABLE.'.date_due', mktime(23, 59, 59))
|
||||
->findAll();
|
||||
|
||||
return $tasks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch one task
|
||||
*
|
||||
|
|
@ -182,7 +211,7 @@ class Task extends Base
|
|||
'tasks.category_id',
|
||||
'users.username'
|
||||
)
|
||||
->join('users', 'id', 'owner_id');
|
||||
->join(User::TABLE, 'id', 'owner_id');
|
||||
|
||||
foreach ($filters as $key => $filter) {
|
||||
|
||||
|
|
@ -282,8 +311,6 @@ class Task extends Base
|
|||
{
|
||||
$this->db->startTransaction();
|
||||
|
||||
$boardModel = new Board($this->db, $this->event);
|
||||
|
||||
// Get the original task
|
||||
$task = $this->getById($task_id);
|
||||
|
||||
|
|
@ -296,7 +323,7 @@ class Task extends Base
|
|||
$task['owner_id'] = 0;
|
||||
$task['category_id'] = 0;
|
||||
$task['is_active'] = 1;
|
||||
$task['column_id'] = $boardModel->getFirstColumn($project_id);
|
||||
$task['column_id'] = $this->board->getFirstColumn($project_id);
|
||||
$task['project_id'] = $project_id;
|
||||
$task['position'] = $this->countByColumnId($task['project_id'], $task['column_id']);
|
||||
|
||||
|
|
@ -317,6 +344,32 @@ class Task extends Base
|
|||
return $task_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare data before task creation or modification
|
||||
*
|
||||
* @access public
|
||||
* @param array $values Form values
|
||||
*/
|
||||
public function prepare(array &$values)
|
||||
{
|
||||
if (isset($values['another_task'])) {
|
||||
unset($values['another_task']);
|
||||
}
|
||||
|
||||
if (! empty($values['date_due']) && ! is_numeric($values['date_due'])) {
|
||||
$values['date_due'] = $this->parseDate($values['date_due']);
|
||||
}
|
||||
|
||||
// Force integer fields at 0 (for Postgresql)
|
||||
if (isset($values['date_due']) && empty($values['date_due'])) {
|
||||
$values['date_due'] = 0;
|
||||
}
|
||||
|
||||
if (isset($values['score']) && empty($values['score'])) {
|
||||
$values['score'] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a task
|
||||
*
|
||||
|
|
@ -329,21 +382,7 @@ class Task extends Base
|
|||
$this->db->startTransaction();
|
||||
|
||||
// Prepare data
|
||||
if (isset($values['another_task'])) {
|
||||
unset($values['another_task']);
|
||||
}
|
||||
|
||||
if (! empty($values['date_due']) && ! is_numeric($values['date_due'])) {
|
||||
$values['date_due'] = $this->parseDate($values['date_due']);
|
||||
}
|
||||
else {
|
||||
$values['date_due'] = 0;
|
||||
}
|
||||
|
||||
if (empty($values['score'])) {
|
||||
$values['score'] = 0;
|
||||
}
|
||||
|
||||
$this->prepare($values);
|
||||
$values['date_creation'] = time();
|
||||
$values['position'] = $this->countByColumnId($values['project_id'], $values['column_id']);
|
||||
|
||||
|
|
@ -368,31 +407,21 @@ class Task extends Base
|
|||
* Update a task
|
||||
*
|
||||
* @access public
|
||||
* @param array $values Form values
|
||||
* @param array $values Form values
|
||||
* @param boolean $trigger_events Flag to trigger events
|
||||
* @return boolean
|
||||
*/
|
||||
public function update(array $values)
|
||||
public function update(array $values, $trigger_events = true)
|
||||
{
|
||||
// Prepare data
|
||||
if (! empty($values['date_due']) && ! is_numeric($values['date_due'])) {
|
||||
$values['date_due'] = $this->parseDate($values['date_due']);
|
||||
}
|
||||
|
||||
// Force integer fields at 0 (for Postgresql)
|
||||
if (isset($values['date_due']) && empty($values['date_due'])) {
|
||||
$values['date_due'] = 0;
|
||||
}
|
||||
|
||||
if (isset($values['score']) && empty($values['score'])) {
|
||||
$values['score'] = 0;
|
||||
}
|
||||
|
||||
// Fetch original task
|
||||
$original_task = $this->getById($values['id']);
|
||||
|
||||
if ($original_task === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Prepare data
|
||||
$this->prepare($values);
|
||||
$updated_task = $values;
|
||||
$updated_task['date_modification'] = time();
|
||||
unset($updated_task['id']);
|
||||
|
|
@ -400,31 +429,42 @@ class Task extends Base
|
|||
$result = $this->db->table(self::TABLE)->eq('id', $values['id'])->update($updated_task);
|
||||
|
||||
// Trigger events
|
||||
if ($result) {
|
||||
|
||||
$events = array(
|
||||
self::EVENT_CREATE_UPDATE,
|
||||
self::EVENT_UPDATE,
|
||||
);
|
||||
|
||||
if (isset($values['column_id']) && $original_task['column_id'] != $values['column_id']) {
|
||||
$events[] = self::EVENT_MOVE_COLUMN;
|
||||
}
|
||||
else if (isset($values['position']) && $original_task['position'] != $values['position']) {
|
||||
$events[] = self::EVENT_MOVE_POSITION;
|
||||
}
|
||||
|
||||
$event_data = array_merge($original_task, $values);
|
||||
$event_data['task_id'] = $original_task['id'];
|
||||
|
||||
foreach ($events as $event) {
|
||||
$this->event->trigger($event, $event_data);
|
||||
}
|
||||
if ($result && $trigger_events) {
|
||||
$this->triggerUpdateEvents($original_task, $updated_task);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger events for task modification
|
||||
*
|
||||
* @access public
|
||||
* @param array $original_task Original task data
|
||||
* @param array $updated_task Updated task data
|
||||
*/
|
||||
public function triggerUpdateEvents(array $original_task, array $updated_task)
|
||||
{
|
||||
$events = array(
|
||||
self::EVENT_CREATE_UPDATE,
|
||||
self::EVENT_UPDATE,
|
||||
);
|
||||
|
||||
if (isset($updated_task['column_id']) && $original_task['column_id'] != $updated_task['column_id']) {
|
||||
$events[] = self::EVENT_MOVE_COLUMN;
|
||||
}
|
||||
else if (isset($updated_task['position']) && $original_task['position'] != $updated_task['position']) {
|
||||
$events[] = self::EVENT_MOVE_POSITION;
|
||||
}
|
||||
|
||||
$event_data = array_merge($original_task, $updated_task);
|
||||
$event_data['task_id'] = $original_task['id'];
|
||||
|
||||
foreach ($events as $event) {
|
||||
$this->event->trigger($event, $event_data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark a task closed
|
||||
*
|
||||
|
|
@ -482,8 +522,7 @@ class Task extends Base
|
|||
*/
|
||||
public function remove($task_id)
|
||||
{
|
||||
$file = new File($this->db, $this->event);
|
||||
$file->removeAll($task_id);
|
||||
$this->file->removeAll($task_id);
|
||||
|
||||
return $this->db->table(self::TABLE)->eq('id', $task_id)->remove();
|
||||
}
|
||||
|
|
@ -492,20 +531,23 @@ class Task extends Base
|
|||
* Move a task to another column or to another position
|
||||
*
|
||||
* @access public
|
||||
* @param integer $task_id Task id
|
||||
* @param integer $column_id Column id
|
||||
* @param integer $position Position (must be greater than 1)
|
||||
* @param integer $task_id Task id
|
||||
* @param integer $column_id Column id
|
||||
* @param integer $position Position (must be greater than 1)
|
||||
* @param boolean $trigger_events Flag to trigger events
|
||||
* @return boolean
|
||||
*/
|
||||
public function move($task_id, $column_id, $position)
|
||||
public function move($task_id, $column_id, $position, $trigger_events = true)
|
||||
{
|
||||
$this->event->clearTriggeredEvents();
|
||||
|
||||
return $this->update(array(
|
||||
$values = array(
|
||||
'id' => $task_id,
|
||||
'column_id' => $column_id,
|
||||
'position' => $position,
|
||||
));
|
||||
);
|
||||
|
||||
return $this->update($values, $trigger_events);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -340,8 +340,7 @@ class User extends Base
|
|||
$this->updateSession($user);
|
||||
|
||||
// Update login history
|
||||
$lastLogin = new LastLogin($this->db, $this->event);
|
||||
$lastLogin->create(
|
||||
$this->lastLogin->create(
|
||||
$method,
|
||||
$user['id'],
|
||||
$this->getIpAddress(),
|
||||
|
|
@ -350,9 +349,8 @@ class User extends Base
|
|||
|
||||
// Setup the remember me feature
|
||||
if (! empty($values['remember_me'])) {
|
||||
$rememberMe = new RememberMe($this->db, $this->event);
|
||||
$credentials = $rememberMe->create($user['id'], $this->getIpAddress(), $this->getUserAgent());
|
||||
$rememberMe->writeCookie($credentials['token'], $credentials['sequence'], $credentials['expiration']);
|
||||
$credentials = $this->rememberMe->create($user['id'], $this->getIpAddress(), $this->getUserAgent());
|
||||
$this->rememberMe->writeCookie($credentials['token'], $credentials['sequence'], $credentials['expiration']);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -384,8 +382,7 @@ class User extends Base
|
|||
|
||||
// LDAP authentication
|
||||
if (! $authenticated && LDAP_AUTH) {
|
||||
$ldap = new Ldap($this->db, $this->event);
|
||||
$authenticated = $ldap->authenticate($username, $password);
|
||||
$authenticated = $this->ldap->authenticate($username, $password);
|
||||
$method = LastLogin::AUTH_LDAP;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -64,11 +64,9 @@ class Webhook extends Base
|
|||
*/
|
||||
public function attachEvents()
|
||||
{
|
||||
$config = new Config($this->db, $this->event);
|
||||
|
||||
$this->url_task_creation = $config->get('webhooks_url_task_creation');
|
||||
$this->url_task_modification = $config->get('webhooks_url_task_modification');
|
||||
$this->token = $config->get('webhooks_token');
|
||||
$this->url_task_creation = $this->config->get('webhooks_url_task_creation');
|
||||
$this->url_task_modification = $this->config->get('webhooks_url_task_modification');
|
||||
$this->token = $this->config->get('webhooks_token');
|
||||
|
||||
if ($this->url_task_creation) {
|
||||
$this->attachCreateEvents();
|
||||
|
|
|
|||
|
|
@ -4,7 +4,22 @@ namespace Schema;
|
|||
|
||||
use Core\Security;
|
||||
|
||||
const VERSION = 22;
|
||||
const VERSION = 23;
|
||||
|
||||
function version_23($pdo)
|
||||
{
|
||||
$pdo->exec("ALTER TABLE users ADD COLUMN notifications_enabled TINYINT(1) DEFAULT '0'");
|
||||
|
||||
$pdo->exec("
|
||||
CREATE TABLE user_has_notifications (
|
||||
user_id INT,
|
||||
project_id INT,
|
||||
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
||||
UNIQUE(project_id, user_id)
|
||||
);
|
||||
");
|
||||
}
|
||||
|
||||
function version_22($pdo)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,7 +4,22 @@ namespace Schema;
|
|||
|
||||
use Core\Security;
|
||||
|
||||
const VERSION = 3;
|
||||
const VERSION = 4;
|
||||
|
||||
function version_4($pdo)
|
||||
{
|
||||
$pdo->exec("ALTER TABLE users ADD COLUMN notifications_enabled BOOLEAN DEFAULT '0'");
|
||||
|
||||
$pdo->exec("
|
||||
CREATE TABLE user_has_notifications (
|
||||
user_id INTEGER,
|
||||
project_id INTEGER,
|
||||
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
||||
UNIQUE(project_id, user_id)
|
||||
);
|
||||
");
|
||||
}
|
||||
|
||||
function version_3($pdo)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,7 +4,22 @@ namespace Schema;
|
|||
|
||||
use Core\Security;
|
||||
|
||||
const VERSION = 22;
|
||||
const VERSION = 23;
|
||||
|
||||
function version_23($pdo)
|
||||
{
|
||||
$pdo->exec("ALTER TABLE users ADD COLUMN notifications_enabled INTEGER DEFAULT '0'");
|
||||
|
||||
$pdo->exec("
|
||||
CREATE TABLE user_has_notifications (
|
||||
user_id INTEGER,
|
||||
project_id INTEGER,
|
||||
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
||||
UNIQUE(project_id, user_id)
|
||||
);
|
||||
");
|
||||
}
|
||||
|
||||
function version_22($pdo)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
<?= Helper\form_csrf() ?>
|
||||
<?= Helper\form_hidden('id', $values) ?>
|
||||
<?= Helper\form_hidden('task_id', $values) ?>
|
||||
<?= Helper\form_textarea('comment', $values, $errors, array('autofocus', 'required', 'placeholder="'.t('Leave a comment').'"'), 'comment-textarea') ?><br/>
|
||||
|
||||
<div class="form-actions">
|
||||
|
|
|
|||
|
|
@ -31,14 +31,25 @@
|
|||
<div class="page-header">
|
||||
<h2><?= t('User settings') ?></h2>
|
||||
</div>
|
||||
<section class="settings">
|
||||
<ul>
|
||||
<li>
|
||||
<strong><?= t('My default project:') ?> </strong>
|
||||
<?= (isset($user['default_project_id']) && isset($projects[$user['default_project_id']])) ? Helper\escape($projects[$user['default_project_id']]) : t('None') ?>,
|
||||
<a href="?controller=user&action=edit&user_id=<?= $user['id'] ?>"><?= t('edit') ?></a>
|
||||
</li>
|
||||
</ul>
|
||||
<section>
|
||||
<h3 id="notifications"><?= t('Email notifications') ?></h3>
|
||||
<form method="post" action="?controller=config&action=notifications" autocomplete="off">
|
||||
|
||||
<?= Helper\form_csrf() ?>
|
||||
|
||||
<?= Helper\form_checkbox('notifications_enabled', t('Enable email notifications'), '1', $notifications['notifications_enabled'] == 1) ?><br/>
|
||||
|
||||
<p><?= t('I want to receive notifications only for those projects:') ?><br/><br/></p>
|
||||
|
||||
<div class="form-checkbox-group">
|
||||
<?php foreach ($user_projects as $project_id => $project_name): ?>
|
||||
<?= Helper\form_checkbox('projects['.$project_id.']', $project_name, '1', isset($notifications['project_'.$project_id])) ?>
|
||||
<?php endforeach ?>
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<?php if ($user['is_admin']): ?>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
<h2><?= Helper\escape($task['title']) ?> (#<?= $task['id'] ?>)</h2>
|
||||
|
||||
<h3><?= t('New comment posted by %s', $comment['username']) ?></h3>
|
||||
|
||||
<?= Helper\parse($comment['comment']) ?>
|
||||
|
||||
<hr/>
|
||||
<p>Kanboard</p>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<h2><?= Helper\escape($task['title']) ?> (#<?= $task['id'] ?>)</h2>
|
||||
|
||||
<h3><?= t('Comment updated') ?></h3>
|
||||
|
||||
<?= Helper\parse($comment['comment']) ?>
|
||||
|
||||
<hr/>
|
||||
<p>Kanboard</p>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<h2><?= Helper\escape($task['title']) ?> (#<?= $task['id'] ?>)</h2>
|
||||
|
||||
<h3><?= t('New attachment added "%s"', $file['name']) ?></h3>
|
||||
|
||||
<hr/>
|
||||
<p>Kanboard</p>
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<h2><?= Helper\escape($task['title']) ?> (#<?= $task['id'] ?>)</h2>
|
||||
|
||||
<h3><?= t('New sub-task') ?></h3>
|
||||
|
||||
<ul>
|
||||
<li><?= t('Title:') ?> <?= Helper\escape($subtask['title']) ?></li>
|
||||
<li><?= t('Status:') ?> <?= Helper\escape($subtask['status_name']) ?></li>
|
||||
<li><?= t('Assignee:') ?> <?= Helper\escape($subtask['name'] ?: $subtask['username'] ?: '?') ?></li>
|
||||
<li>
|
||||
<?= t('Time tracking:') ?>
|
||||
<?php if (! empty($subtask['time_estimated'])): ?>
|
||||
<strong><?= Helper\escape($subtask['time_estimated']).'h' ?></strong> <?= t('estimated') ?>
|
||||
<?php endif ?>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<hr/>
|
||||
<p>Kanboard</p>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<h2><?= Helper\escape($task['title']) ?> (#<?= $task['id'] ?>)</h2>
|
||||
|
||||
<h3><?= t('Sub-task updated') ?></h3>
|
||||
|
||||
<ul>
|
||||
<li><?= t('Title:') ?> <?= Helper\escape($subtask['title']) ?></li>
|
||||
<li><?= t('Status:') ?> <?= Helper\escape($subtask['status_name']) ?></li>
|
||||
<li><?= t('Assignee:') ?> <?= Helper\escape($subtask['name'] ?: $subtask['username'] ?: '?') ?></li>
|
||||
<li>
|
||||
<?= t('Time tracking:') ?>
|
||||
<?php if (! empty($subtask['time_spent'])): ?>
|
||||
<strong><?= Helper\escape($subtask['time_spent']).'h' ?></strong> <?= t('spent') ?>
|
||||
<?php endif ?>
|
||||
|
||||
<?php if (! empty($subtask['time_estimated'])): ?>
|
||||
<strong><?= Helper\escape($subtask['time_estimated']).'h' ?></strong> <?= t('estimated') ?>
|
||||
<?php endif ?>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<hr/>
|
||||
<p>Kanboard</p>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<h2><?= Helper\escape($task['title']) ?> (#<?= $task['id'] ?>)</h2>
|
||||
|
||||
<p><?= t('The task #%d have been closed.', $task['id']) ?></p>
|
||||
|
||||
<hr/>
|
||||
<p>Kanboard</p>
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
<h2><?= Helper\escape($task['title']) ?> (#<?= $task['id'] ?>)</h2>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<?= dt('Created on %B %e, %Y at %k:%M %p', $task['date_creation']) ?>
|
||||
</li>
|
||||
<?php if ($task['date_due']): ?>
|
||||
<li>
|
||||
<strong><?= dt('Must be done before %B %e, %Y', $task['date_due']) ?></strong>
|
||||
</li>
|
||||
<?php endif ?>
|
||||
<?php if ($task['creator_username']): ?>
|
||||
<li>
|
||||
<?= t('Created by %s', $task['creator_username']) ?>
|
||||
</li>
|
||||
<?php endif ?>
|
||||
<li>
|
||||
<strong>
|
||||
<?php if ($task['assignee_username']): ?>
|
||||
<?= t('Assigned to %s', $task['assignee_username']) ?>
|
||||
<?php else: ?>
|
||||
<?= t('There is nobody assigned') ?>
|
||||
<?php endif ?>
|
||||
</strong>
|
||||
</li>
|
||||
<li>
|
||||
<?= t('Column on the board:') ?>
|
||||
<strong><?= Helper\escape($task['column_title']) ?></strong>
|
||||
</li>
|
||||
<li><?= t('Task position:').' '.Helper\escape($task['position']) ?></li>
|
||||
<?php if ($task['category_name']): ?>
|
||||
<li>
|
||||
<?= t('Category:') ?> <strong><?= Helper\escape($task['category_name']) ?></strong>
|
||||
</li>
|
||||
<?php endif ?>
|
||||
</ul>
|
||||
|
||||
<?php if (! empty($task['description'])): ?>
|
||||
<h2><?= t('Description') ?></h2>
|
||||
<?= Helper\parse($task['description']) ?>
|
||||
<?php endif ?>
|
||||
|
||||
<hr/>
|
||||
<p>Kanboard</p>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<h2><?= t('List of due tasks for the project "%s"', $project) ?></h2>
|
||||
|
||||
<ul>
|
||||
<?php foreach ($tasks as $task): ?>
|
||||
<li>(<strong>#<?= $task['id'] ?></strong>) <?= Helper\escape($task['title']) ?> (<strong><?= t('Assigned to %s', $task['assignee_name'] ?: $task['assignee_username']) ?></strong>)</li>
|
||||
<?php endforeach ?>
|
||||
</ul>
|
||||
|
||||
<hr/>
|
||||
<p>Kanboard</p>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<h2><?= Helper\escape($task['title']) ?> (#<?= $task['id'] ?>)</h2>
|
||||
|
||||
<p><?= t('The task #%d have been opened.', $task['id']) ?></p>
|
||||
|
||||
<hr/>
|
||||
<p>Kanboard</p>
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
<h2><?= Helper\escape($task['title']) ?> (#<?= $task['id'] ?>)</h2>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<?= dt('Created on %B %e, %Y at %k:%M %p', $task['date_creation']) ?>
|
||||
</li>
|
||||
<?php if ($task['date_due']): ?>
|
||||
<li>
|
||||
<strong><?= dt('Must be done before %B %e, %Y', $task['date_due']) ?></strong>
|
||||
</li>
|
||||
<?php endif ?>
|
||||
<?php if ($task['creator_username']): ?>
|
||||
<li>
|
||||
<?= t('Created by %s', $task['creator_username']) ?>
|
||||
</li>
|
||||
<?php endif ?>
|
||||
<li>
|
||||
<strong>
|
||||
<?php if ($task['assignee_username']): ?>
|
||||
<?= t('Assigned to %s', $task['assignee_username']) ?>
|
||||
<?php else: ?>
|
||||
<?= t('There is nobody assigned') ?>
|
||||
<?php endif ?>
|
||||
</strong>
|
||||
</li>
|
||||
<li>
|
||||
<?= t('Column on the board:') ?>
|
||||
<strong><?= Helper\escape($task['column_title']) ?></strong>
|
||||
</li>
|
||||
<li><?= t('Task position:').' '.Helper\escape($task['position']) ?></li>
|
||||
<?php if ($task['category_name']): ?>
|
||||
<li>
|
||||
<?= t('Category:') ?> <strong><?= Helper\escape($task['category_name']) ?></strong>
|
||||
</li>
|
||||
<?php endif ?>
|
||||
</ul>
|
||||
|
||||
<?php if (! empty($task['description'])): ?>
|
||||
<h2><?= t('Description') ?></h2>
|
||||
<?= Helper\parse($task['description']) ?: t('There is no description.') ?>
|
||||
<?php endif ?>
|
||||
|
||||
<hr/>
|
||||
<p>Kanboard</p>
|
||||
|
|
@ -4,6 +4,8 @@ require __DIR__.'/Core/Loader.php';
|
|||
require __DIR__.'/helpers.php';
|
||||
require __DIR__.'/translator.php';
|
||||
|
||||
require 'vendor/swiftmailer/swift_required.php';
|
||||
|
||||
use Core\Event;
|
||||
use Core\Loader;
|
||||
use Core\Registry;
|
||||
|
|
@ -63,6 +65,15 @@ defined('REVERSE_PROXY_AUTH') or define('REVERSE_PROXY_AUTH', false);
|
|||
defined('REVERSE_PROXY_USER_HEADER') or define('REVERSE_PROXY_USER_HEADER', 'REMOTE_USER');
|
||||
defined('REVERSE_PROXY_DEFAULT_ADMIN') or define('REVERSE_PROXY_DEFAULT_ADMIN', '');
|
||||
|
||||
// Mail configuration
|
||||
defined('MAIL_FROM') or define('MAIL_FROM', 'notifications@kanboard.net');
|
||||
defined('MAIL_TRANSPORT') or define('MAIL_TRANSPORT', 'mail');
|
||||
defined('MAIL_SMTP_HOSTNAME') or define('MAIL_SMTP_HOSTNAME', '');
|
||||
defined('MAIL_SMTP_PORT') or define('MAIL_SMTP_PORT', 25);
|
||||
defined('MAIL_SMTP_USERNAME') or define('MAIL_SMTP_USERNAME', '');
|
||||
defined('MAIL_SMTP_PASSWORD') or define('MAIL_SMTP_PASSWORD', '');
|
||||
defined('MAIL_SENDMAIL_COMMAND') or define('MAIL_SENDMAIL_COMMAND', '/usr/sbin/sendmail -bs');
|
||||
|
||||
$loader = new Loader;
|
||||
$loader->execute();
|
||||
|
||||
|
|
@ -126,3 +137,25 @@ $registry->db = function() use ($registry) {
|
|||
$registry->event = function() use ($registry) {
|
||||
return new Event;
|
||||
};
|
||||
|
||||
$registry->mailer = function() use ($registry) {
|
||||
|
||||
require_once 'vendor/swiftmailer/swift_required.php';
|
||||
|
||||
$transport = null;
|
||||
|
||||
switch (MAIL_TRANSPORT) {
|
||||
case 'smtp':
|
||||
$transport = Swift_SmtpTransport::newInstance(MAIL_SMTP_HOSTNAME, MAIL_SMTP_PORT);
|
||||
$transport->setUsername(MAIL_SMTP_USERNAME);
|
||||
$transport->setPassword(MAIL_SMTP_PASSWORD);
|
||||
break;
|
||||
case 'sendmail':
|
||||
$transport = Swift_SendmailTransport::newInstance(MAIL_SENDMAIL_COMMAND);
|
||||
break;
|
||||
default:
|
||||
$transport = Swift_MailTransport::newInstance();
|
||||
}
|
||||
|
||||
return $transport;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -265,6 +265,10 @@ input.form-date {
|
|||
line-height: 25px;
|
||||
}
|
||||
|
||||
.form-checkbox-group label {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
/* alerts */
|
||||
.alert {
|
||||
padding: 8px 35px 8px 14px;
|
||||
|
|
|
|||
|
|
@ -77,7 +77,8 @@ Kanboard.Board = (function() {
|
|||
connectWith: ".column",
|
||||
placeholder: "draggable-placeholder",
|
||||
stop: function(event, ui) {
|
||||
board_save();
|
||||
var task_id = parseInt(ui.item[0].getAttribute("data-task-id"));
|
||||
board_save(task_id);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -112,7 +113,7 @@ Kanboard.Board = (function() {
|
|||
}
|
||||
|
||||
// Save and refresh the board
|
||||
function board_save()
|
||||
function board_save(selected_task_id)
|
||||
{
|
||||
var data = [];
|
||||
var boardSelector = $("#board");
|
||||
|
|
@ -135,7 +136,7 @@ Kanboard.Board = (function() {
|
|||
$.ajax({
|
||||
cache: false,
|
||||
url: "?controller=board&action=save&project_id=" + projectId,
|
||||
data: {"positions": data, "csrf_token": boardSelector.attr("data-csrf-token")},
|
||||
data: {"positions": data, "csrf_token": boardSelector.attr("data-csrf-token"), "selected_task_id": selected_task_id},
|
||||
type: "POST",
|
||||
success: function(data) {
|
||||
$("#board").remove();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,20 @@
|
|||
<?php
|
||||
|
||||
// E-mail address for the "From" header (notifications)
|
||||
define('MAIL_FROM', 'notifications@kanboard.net');
|
||||
|
||||
// Mail transport to use: "smtp", "sendmail" or "mail" (PHP mail function)
|
||||
define('MAIL_TRANSPORT', 'mail');
|
||||
|
||||
// SMTP configuration to use when the "smtp" transport is chosen
|
||||
define('MAIL_SMTP_HOSTNAME', '');
|
||||
define('MAIL_SMTP_PORT', 25);
|
||||
define('MAIL_SMTP_USERNAME', '');
|
||||
define('MAIL_SMTP_PASSWORD', '');
|
||||
|
||||
// Sendmail command to use when the transport is "sendmail"
|
||||
define('MAIL_SENDMAIL_COMMAND', '/usr/sbin/sendmail -bs');
|
||||
|
||||
// Auto-refresh frequency in seconds for the public board view (60 seconds by default)
|
||||
define('BOARD_PUBLIC_CHECK_INTERVAL', 60);
|
||||
|
||||
|
|
|
|||
28
jsonrpc.php
28
jsonrpc.php
|
|
@ -3,6 +3,7 @@
|
|||
require __DIR__.'/app/common.php';
|
||||
require __DIR__.'/vendor/JsonRPC/Server.php';
|
||||
|
||||
use Core\Translator;
|
||||
use JsonRPC\Server;
|
||||
use Model\Project;
|
||||
use Model\Task;
|
||||
|
|
@ -14,21 +15,28 @@ use Model\SubTask;
|
|||
use Model\Board;
|
||||
use Model\Action;
|
||||
use Model\Webhook;
|
||||
use Model\Notification;
|
||||
|
||||
$config = new Config($registry->shared('db'), $registry->shared('event'));
|
||||
$project = new Project($registry->shared('db'), $registry->shared('event'));
|
||||
$task = new Task($registry->shared('db'), $registry->shared('event'));
|
||||
$user = new User($registry->shared('db'), $registry->shared('event'));
|
||||
$category = new Category($registry->shared('db'), $registry->shared('event'));
|
||||
$comment = new Comment($registry->shared('db'), $registry->shared('event'));
|
||||
$subtask = new SubTask($registry->shared('db'), $registry->shared('event'));
|
||||
$board = new Board($registry->shared('db'), $registry->shared('event'));
|
||||
$action = new Action($registry->shared('db'), $registry->shared('event'));
|
||||
$webhook = new Webhook($registry->shared('db'), $registry->shared('event'));
|
||||
$config = new Config($registry);
|
||||
$project = new Project($registry);
|
||||
$task = new Task($registry);
|
||||
$user = new User($registry);
|
||||
$category = new Category($registry);
|
||||
$comment = new Comment($registry);
|
||||
$subtask = new SubTask($registry);
|
||||
$board = new Board($registry);
|
||||
$action = new Action($registry);
|
||||
$webhook = new Webhook($registry);
|
||||
$notification = new Notification($registry);
|
||||
|
||||
$action->attachEvents();
|
||||
$project->attachEvents();
|
||||
$webhook->attachEvents();
|
||||
$notification->attachEvents();
|
||||
|
||||
// Load translations
|
||||
$language = $config->get('language', 'en_US');
|
||||
if ($language !== 'en_US') Translator::load($language);
|
||||
|
||||
$server = new Server;
|
||||
$server->authentication(array('jsonrpc' => $config->get('api_token')));
|
||||
|
|
|
|||
35
kanboard
35
kanboard
|
|
@ -8,8 +8,9 @@ use Core\Tool;
|
|||
use Core\Translator;
|
||||
use Model\Config;
|
||||
use Model\Task;
|
||||
use Model\Notification;
|
||||
|
||||
$config = new Config($registry->shared('db'), $registry->shared('event'));
|
||||
$config = new Config($registry);
|
||||
|
||||
// Load translations
|
||||
$language = $config->get('language', 'en_US');
|
||||
|
|
@ -25,6 +26,7 @@ $cli = new Cli;
|
|||
$cli->register('help', function() {
|
||||
echo 'Kanboard command line interface'.PHP_EOL.'==============================='.PHP_EOL.PHP_EOL;
|
||||
echo '- Task export to stdout (CSV format): '.$GLOBALS['argv'][0].' export-csv <project_id> <start_date> <end_date>'.PHP_EOL;
|
||||
echo '- Send notifications for tasks due: '.$GLOBALS['argv'][0].' send-notifications-tasks-due'.PHP_EOL;
|
||||
});
|
||||
|
||||
// CSV Export
|
||||
|
|
@ -40,12 +42,39 @@ $cli->register('export-csv', function() use ($cli, $registry) {
|
|||
|
||||
Translator::disableEscaping();
|
||||
|
||||
$task = new Task($registry->shared('db'), $registry->shared('event'));
|
||||
$data = $task->export($project_id, $start_date, $end_date);
|
||||
$taskModel = new Task($registry);
|
||||
$data = $taskModel->export($project_id, $start_date, $end_date);
|
||||
|
||||
if (is_array($data)) {
|
||||
Tool::csv($data);
|
||||
}
|
||||
});
|
||||
|
||||
// Send notification for tasks due
|
||||
$cli->register('send-notifications-tasks-due', function() use ($cli, $registry) {
|
||||
|
||||
$notificationModel = new Notification($registry);
|
||||
$taskModel = new Task($registry);
|
||||
$tasks = $taskModel->getTasksDue();
|
||||
|
||||
// Group tasks by project
|
||||
$projects = array();
|
||||
|
||||
foreach ($tasks as $task) {
|
||||
$projects[$task['project_id']][] = $task;
|
||||
}
|
||||
|
||||
// Send notifications for each project
|
||||
foreach ($projects as $project_id => $project_tasks) {
|
||||
|
||||
$users = $notificationModel->getUsersList($project_id);
|
||||
|
||||
$notificationModel->sendEmails(
|
||||
'notification_task_due',
|
||||
$users,
|
||||
array('tasks' => $project_tasks, 'project' => $project_tasks[0]['project_name'])
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
$cli->execute();
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ class AclTest extends Base
|
|||
'controller1' => array('action1', 'action3'),
|
||||
);
|
||||
|
||||
$acl = new Acl($this->db, $this->event);
|
||||
$acl = new Acl($this->registry);
|
||||
$this->assertTrue($acl->isAllowedAction($acl_rules, 'controller1', 'action1'));
|
||||
$this->assertTrue($acl->isAllowedAction($acl_rules, 'controller1', 'action3'));
|
||||
$this->assertFalse($acl->isAllowedAction($acl_rules, 'controller1', 'action2'));
|
||||
|
|
@ -22,7 +22,7 @@ class AclTest extends Base
|
|||
|
||||
public function testIsAdmin()
|
||||
{
|
||||
$acl = new Acl($this->db, $this->event);
|
||||
$acl = new Acl($this->registry);
|
||||
|
||||
$_SESSION = array();
|
||||
$this->assertFalse($acl->isAdminUser());
|
||||
|
|
@ -45,7 +45,7 @@ class AclTest extends Base
|
|||
|
||||
public function testIsUser()
|
||||
{
|
||||
$acl = new Acl($this->db, $this->event);
|
||||
$acl = new Acl($this->registry);
|
||||
|
||||
$_SESSION = array();
|
||||
$this->assertFalse($acl->isRegularUser());
|
||||
|
|
@ -68,7 +68,7 @@ class AclTest extends Base
|
|||
|
||||
public function testIsPageAllowed()
|
||||
{
|
||||
$acl = new Acl($this->db, $this->event);
|
||||
$acl = new Acl($this->registry);
|
||||
|
||||
// Public access
|
||||
$_SESSION = array();
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ class ActionTaskAssignColorCategory extends Base
|
|||
{
|
||||
public function testBadProject()
|
||||
{
|
||||
$action = new Action\TaskAssignColorCategory(3, new Task($this->db, $this->event));
|
||||
$action = new Action\TaskAssignColorCategory(3, new Task($this->registry));
|
||||
|
||||
$event = array(
|
||||
'project_id' => 2,
|
||||
|
|
@ -24,14 +24,14 @@ class ActionTaskAssignColorCategory extends Base
|
|||
|
||||
public function testExecute()
|
||||
{
|
||||
$action = new Action\TaskAssignColorCategory(1, new Task($this->db, $this->event));
|
||||
$action = new Action\TaskAssignColorCategory(1, new Task($this->registry));
|
||||
$action->setParam('category_id', 1);
|
||||
$action->setParam('color_id', 'blue');
|
||||
|
||||
// We create a task in the first column
|
||||
$t = new Task($this->db, $this->event);
|
||||
$p = new Project($this->db, $this->event);
|
||||
$c = new Category($this->db, $this->event);
|
||||
$t = new Task($this->registry);
|
||||
$p = new Project($this->registry);
|
||||
$c = new Category($this->registry);
|
||||
|
||||
$this->assertEquals(1, $p->create(array('name' => 'test')));
|
||||
$this->assertEquals(1, $c->create(array('name' => 'c1')));
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ class ActionTaskAssignColorUser extends Base
|
|||
{
|
||||
public function testBadProject()
|
||||
{
|
||||
$action = new Action\TaskAssignColorUser(3, new Task($this->db, $this->event));
|
||||
$action = new Action\TaskAssignColorUser(3, new Task($this->registry));
|
||||
|
||||
$event = array(
|
||||
'project_id' => 2,
|
||||
|
|
@ -23,13 +23,13 @@ class ActionTaskAssignColorUser extends Base
|
|||
|
||||
public function testExecute()
|
||||
{
|
||||
$action = new Action\TaskAssignColorUser(1, new Task($this->db, $this->event));
|
||||
$action = new Action\TaskAssignColorUser(1, new Task($this->registry));
|
||||
$action->setParam('user_id', 1);
|
||||
$action->setParam('color_id', 'blue');
|
||||
|
||||
// We create a task in the first column
|
||||
$t = new Task($this->db, $this->event);
|
||||
$p = new Project($this->db, $this->event);
|
||||
$t = new Task($this->registry);
|
||||
$p = new Project($this->registry);
|
||||
$this->assertEquals(1, $p->create(array('name' => 'test')));
|
||||
$this->assertEquals(1, $t->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1, 'color_id' => 'green')));
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ class ActionTaskAssignCurrentUser extends Base
|
|||
{
|
||||
public function testBadProject()
|
||||
{
|
||||
$action = new Action\TaskAssignCurrentUser(3, new Task($this->db, $this->event), new Acl($this->db, $this->event));
|
||||
$action = new Action\TaskAssignCurrentUser(3, new Task($this->registry), new Acl($this->registry));
|
||||
$action->setParam('column_id', 5);
|
||||
|
||||
$event = array(
|
||||
|
|
@ -25,7 +25,7 @@ class ActionTaskAssignCurrentUser extends Base
|
|||
|
||||
public function testBadColumn()
|
||||
{
|
||||
$action = new Action\TaskAssignCurrentUser(3, new Task($this->db, $this->event), new Acl($this->db, $this->event));
|
||||
$action = new Action\TaskAssignCurrentUser(3, new Task($this->registry), new Acl($this->registry));
|
||||
$action->setParam('column_id', 5);
|
||||
|
||||
$event = array(
|
||||
|
|
@ -39,16 +39,16 @@ class ActionTaskAssignCurrentUser extends Base
|
|||
|
||||
public function testExecute()
|
||||
{
|
||||
$action = new Action\TaskAssignCurrentUser(1, new Task($this->db, $this->event), new Acl($this->db, $this->event));
|
||||
$action = new Action\TaskAssignCurrentUser(1, new Task($this->registry), new Acl($this->registry));
|
||||
$action->setParam('column_id', 2);
|
||||
$_SESSION = array(
|
||||
'user' => array('id' => 5)
|
||||
);
|
||||
|
||||
// We create a task in the first column
|
||||
$t = new Task($this->db, $this->event);
|
||||
$p = new Project($this->db, $this->event);
|
||||
$a = new Acl($this->db, $this->event);
|
||||
$t = new Task($this->registry);
|
||||
$p = new Project($this->registry);
|
||||
$a = new Acl($this->registry);
|
||||
|
||||
$this->assertEquals(5, $a->getUserId());
|
||||
$this->assertEquals(1, $p->create(array('name' => 'test')));
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ class ActionTaskAssignSpecificUser extends Base
|
|||
{
|
||||
public function testBadProject()
|
||||
{
|
||||
$action = new Action\TaskAssignSpecificUser(3, new Task($this->db, $this->event));
|
||||
$action = new Action\TaskAssignSpecificUser(3, new Task($this->registry));
|
||||
$action->setParam('column_id', 5);
|
||||
|
||||
$event = array(
|
||||
|
|
@ -24,7 +24,7 @@ class ActionTaskAssignSpecificUser extends Base
|
|||
|
||||
public function testBadColumn()
|
||||
{
|
||||
$action = new Action\TaskAssignSpecificUser(3, new Task($this->db, $this->event));
|
||||
$action = new Action\TaskAssignSpecificUser(3, new Task($this->registry));
|
||||
$action->setParam('column_id', 5);
|
||||
|
||||
$event = array(
|
||||
|
|
@ -38,13 +38,13 @@ class ActionTaskAssignSpecificUser extends Base
|
|||
|
||||
public function testExecute()
|
||||
{
|
||||
$action = new Action\TaskAssignSpecificUser(1, new Task($this->db, $this->event));
|
||||
$action = new Action\TaskAssignSpecificUser(1, new Task($this->registry));
|
||||
$action->setParam('column_id', 2);
|
||||
$action->setParam('user_id', 1);
|
||||
|
||||
// We create a task in the first column
|
||||
$t = new Task($this->db, $this->event);
|
||||
$p = new Project($this->db, $this->event);
|
||||
$t = new Task($this->registry);
|
||||
$p = new Project($this->registry);
|
||||
$this->assertEquals(1, $p->create(array('name' => 'test')));
|
||||
$this->assertEquals(1, $t->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1)));
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ class ActionTaskCloseTest extends Base
|
|||
{
|
||||
public function testBadProject()
|
||||
{
|
||||
$action = new Action\TaskClose(3, new Task($this->db, $this->event));
|
||||
$action = new Action\TaskClose(3, new Task($this->registry));
|
||||
$action->setParam('column_id', 5);
|
||||
|
||||
$event = array(
|
||||
|
|
@ -24,7 +24,7 @@ class ActionTaskCloseTest extends Base
|
|||
|
||||
public function testBadColumn()
|
||||
{
|
||||
$action = new Action\TaskClose(3, new Task($this->db, $this->event));
|
||||
$action = new Action\TaskClose(3, new Task($this->registry));
|
||||
$action->setParam('column_id', 5);
|
||||
|
||||
$event = array(
|
||||
|
|
@ -38,12 +38,12 @@ class ActionTaskCloseTest extends Base
|
|||
|
||||
public function testExecute()
|
||||
{
|
||||
$action = new Action\TaskClose(1, new Task($this->db, $this->event));
|
||||
$action = new Action\TaskClose(1, new Task($this->registry));
|
||||
$action->setParam('column_id', 2);
|
||||
|
||||
// We create a task in the first column
|
||||
$t = new Task($this->db, $this->event);
|
||||
$p = new Project($this->db, $this->event);
|
||||
$t = new Task($this->registry);
|
||||
$p = new Project($this->registry);
|
||||
$this->assertEquals(1, $p->create(array('name' => 'test')));
|
||||
$this->assertEquals(1, $t->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1)));
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ class ActionTaskDuplicateAnotherProject extends Base
|
|||
{
|
||||
public function testBadProject()
|
||||
{
|
||||
$action = new Action\TaskDuplicateAnotherProject(3, new Task($this->db, $this->event));
|
||||
$action = new Action\TaskDuplicateAnotherProject(3, new Task($this->registry));
|
||||
$action->setParam('column_id', 5);
|
||||
|
||||
$event = array(
|
||||
|
|
@ -24,7 +24,7 @@ class ActionTaskDuplicateAnotherProject extends Base
|
|||
|
||||
public function testBadColumn()
|
||||
{
|
||||
$action = new Action\TaskDuplicateAnotherProject(3, new Task($this->db, $this->event));
|
||||
$action = new Action\TaskDuplicateAnotherProject(3, new Task($this->registry));
|
||||
$action->setParam('column_id', 5);
|
||||
|
||||
$event = array(
|
||||
|
|
@ -38,11 +38,11 @@ class ActionTaskDuplicateAnotherProject extends Base
|
|||
|
||||
public function testExecute()
|
||||
{
|
||||
$action = new Action\TaskDuplicateAnotherProject(1, new Task($this->db, $this->event));
|
||||
$action = new Action\TaskDuplicateAnotherProject(1, new Task($this->registry));
|
||||
|
||||
// We create a task in the first column
|
||||
$t = new Task($this->db, $this->event);
|
||||
$p = new Project($this->db, $this->event);
|
||||
$t = new Task($this->registry);
|
||||
$p = new Project($this->registry);
|
||||
$this->assertEquals(1, $p->create(array('name' => 'project 1')));
|
||||
$this->assertEquals(2, $p->create(array('name' => 'project 2')));
|
||||
$this->assertEquals(1, $t->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1)));
|
||||
|
|
|
|||
|
|
@ -12,9 +12,9 @@ class ActionTest extends Base
|
|||
{
|
||||
public function testFetchActions()
|
||||
{
|
||||
$action = new Action($this->db, $this->event);
|
||||
$board = new Board($this->db, $this->event);
|
||||
$project = new Project($this->db, $this->event);
|
||||
$action = new Action($this->registry);
|
||||
$board = new Board($this->registry);
|
||||
$project = new Project($this->registry);
|
||||
|
||||
$this->assertEquals(1, $project->create(array('name' => 'unit_test')));
|
||||
|
||||
|
|
@ -48,10 +48,10 @@ class ActionTest extends Base
|
|||
|
||||
public function testEventMoveColumn()
|
||||
{
|
||||
$task = new Task($this->db, $this->event);
|
||||
$board = new Board($this->db, $this->event);
|
||||
$project = new Project($this->db, $this->event);
|
||||
$action = new Action($this->db, $this->event);
|
||||
$task = new Task($this->registry);
|
||||
$board = new Board($this->registry);
|
||||
$project = new Project($this->registry);
|
||||
$action = new Action($this->registry);
|
||||
|
||||
// We create a project
|
||||
$this->assertEquals(1, $project->create(array('name' => 'unit_test')));
|
||||
|
|
@ -86,8 +86,8 @@ class ActionTest extends Base
|
|||
// We move our task
|
||||
$task->move(1, 4, 1);
|
||||
|
||||
$this->assertTrue($this->event->isEventTriggered(Task::EVENT_MOVE_COLUMN));
|
||||
$this->assertTrue($this->event->isEventTriggered(Task::EVENT_UPDATE));
|
||||
$this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_MOVE_COLUMN));
|
||||
$this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_UPDATE));
|
||||
|
||||
// Our task should be closed
|
||||
$t1 = $task->getById(1);
|
||||
|
|
@ -97,10 +97,10 @@ class ActionTest extends Base
|
|||
|
||||
public function testEventMovePosition()
|
||||
{
|
||||
$task = new Task($this->db, $this->event);
|
||||
$board = new Board($this->db, $this->event);
|
||||
$project = new Project($this->db, $this->event);
|
||||
$action = new Action($this->db, $this->event);
|
||||
$task = new Task($this->registry);
|
||||
$board = new Board($this->registry);
|
||||
$project = new Project($this->registry);
|
||||
$action = new Action($this->registry);
|
||||
|
||||
// We create a project
|
||||
$this->assertEquals(1, $project->create(array('name' => 'unit_test')));
|
||||
|
|
@ -138,7 +138,7 @@ class ActionTest extends Base
|
|||
// We bind events
|
||||
$action->attachEvents();
|
||||
|
||||
$this->assertTrue($this->event->hasListener(Task::EVENT_MOVE_POSITION, 'Action\TaskAssignColorCategory'));
|
||||
$this->assertTrue($this->registry->event->hasListener(Task::EVENT_MOVE_POSITION, 'Action\TaskAssignColorCategory'));
|
||||
|
||||
// Our task should have the color red and position=0
|
||||
$t1 = $task->getById(1);
|
||||
|
|
@ -155,7 +155,7 @@ class ActionTest extends Base
|
|||
$task->move(1, 1, 1); // task #1 to position 1
|
||||
$task->move(2, 1, 0); // task #2 to position 0
|
||||
|
||||
$this->assertTrue($this->event->isEventTriggered(Task::EVENT_MOVE_POSITION));
|
||||
$this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_MOVE_POSITION));
|
||||
|
||||
// Both tasks should be green
|
||||
$t1 = $task->getById(1);
|
||||
|
|
@ -171,10 +171,10 @@ class ActionTest extends Base
|
|||
|
||||
public function testExecuteMultipleActions()
|
||||
{
|
||||
$task = new Task($this->db, $this->event);
|
||||
$board = new Board($this->db, $this->event);
|
||||
$project = new Project($this->db, $this->event);
|
||||
$action = new Action($this->db, $this->event);
|
||||
$task = new Task($this->registry);
|
||||
$board = new Board($this->registry);
|
||||
$project = new Project($this->registry);
|
||||
$action = new Action($this->registry);
|
||||
|
||||
// We create 2 projects
|
||||
$this->assertEquals(1, $project->create(array('name' => 'unit_test1')));
|
||||
|
|
@ -213,8 +213,8 @@ class ActionTest extends Base
|
|||
$action->attachEvents();
|
||||
|
||||
// Events should be attached
|
||||
$this->assertTrue($this->event->hasListener(Task::EVENT_CLOSE, 'Action\TaskDuplicateAnotherProject'));
|
||||
$this->assertTrue($this->event->hasListener(Task::EVENT_MOVE_COLUMN, 'Action\TaskClose'));
|
||||
$this->assertTrue($this->registry->event->hasListener(Task::EVENT_CLOSE, 'Action\TaskDuplicateAnotherProject'));
|
||||
$this->assertTrue($this->registry->event->hasListener(Task::EVENT_MOVE_COLUMN, 'Action\TaskClose'));
|
||||
|
||||
// Our task should be open, linked to the first project and in the first column
|
||||
$t1 = $task->getById(1);
|
||||
|
|
@ -225,8 +225,8 @@ class ActionTest extends Base
|
|||
// We move our task
|
||||
$task->move(1, 4, 1);
|
||||
|
||||
$this->assertTrue($this->event->isEventTriggered(Task::EVENT_CLOSE));
|
||||
$this->assertTrue($this->event->isEventTriggered(Task::EVENT_MOVE_COLUMN));
|
||||
$this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_CLOSE));
|
||||
$this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_MOVE_COLUMN));
|
||||
|
||||
// Our task should be closed
|
||||
$t1 = $task->getById(1);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ require_once __DIR__.'/../../app/Core/Security.php';
|
|||
require_once __DIR__.'/../../vendor/PicoDb/Database.php';
|
||||
require_once __DIR__.'/../../app/Schema/Sqlite.php';
|
||||
|
||||
require_once __DIR__.'/../../app/Core/Registry.php';
|
||||
require_once __DIR__.'/../../app/Core/Tool.php';
|
||||
require_once __DIR__.'/../../app/Core/Listener.php';
|
||||
require_once __DIR__.'/../../app/Core/Event.php';
|
||||
require_once __DIR__.'/../../app/Core/Translator.php';
|
||||
|
|
@ -36,8 +38,9 @@ abstract class Base extends PHPUnit_Framework_TestCase
|
|||
{
|
||||
public function setUp()
|
||||
{
|
||||
$this->db = $this->getDbConnection();
|
||||
$this->event = new \Core\Event;
|
||||
$this->registry = new \Core\Registry;
|
||||
$this->registry->db = $this->getDbConnection();
|
||||
$this->registry->event = new \Core\Event;
|
||||
}
|
||||
|
||||
public function getDbConnection()
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ class BoardTest extends Base
|
|||
{
|
||||
public function testMoveColumns()
|
||||
{
|
||||
$p = new Project($this->db, $this->event);
|
||||
$b = new Board($this->db, $this->event);
|
||||
$p = new Project($this->registry);
|
||||
$b = new Board($this->registry);
|
||||
|
||||
// We create 2 projects
|
||||
$this->assertEquals(1, $p->create(array('name' => 'UnitTest1')));
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@ class CommentTest extends Base
|
|||
{
|
||||
public function testCreate()
|
||||
{
|
||||
$c = new Comment($this->db, $this->event);
|
||||
$t = new Task($this->db, $this->event);
|
||||
$p = new Project($this->db, $this->event);
|
||||
$c = new Comment($this->registry);
|
||||
$t = new Task($this->registry);
|
||||
$p = new Project($this->registry);
|
||||
|
||||
$this->assertEquals(1, $p->create(array('name' => 'test1')));
|
||||
$this->assertEquals(1, $t->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1)));
|
||||
|
|
@ -30,9 +30,9 @@ class CommentTest extends Base
|
|||
|
||||
public function testGetAll()
|
||||
{
|
||||
$c = new Comment($this->db, $this->event);
|
||||
$t = new Task($this->db, $this->event);
|
||||
$p = new Project($this->db, $this->event);
|
||||
$c = new Comment($this->registry);
|
||||
$t = new Task($this->registry);
|
||||
$p = new Project($this->registry);
|
||||
|
||||
$this->assertEquals(1, $p->create(array('name' => 'test1')));
|
||||
$this->assertEquals(1, $t->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1)));
|
||||
|
|
@ -51,9 +51,9 @@ class CommentTest extends Base
|
|||
|
||||
public function testUpdate()
|
||||
{
|
||||
$c = new Comment($this->db, $this->event);
|
||||
$t = new Task($this->db, $this->event);
|
||||
$p = new Project($this->db, $this->event);
|
||||
$c = new Comment($this->registry);
|
||||
$t = new Task($this->registry);
|
||||
$p = new Project($this->registry);
|
||||
|
||||
$this->assertEquals(1, $p->create(array('name' => 'test1')));
|
||||
$this->assertEquals(1, $t->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1)));
|
||||
|
|
@ -67,7 +67,7 @@ class CommentTest extends Base
|
|||
|
||||
public function testValidateCreation()
|
||||
{
|
||||
$c = new Comment($this->db, $this->event);
|
||||
$c = new Comment($this->registry);
|
||||
|
||||
$result = $c->validateCreation(array('user_id' => 1, 'task_id' => 1, 'comment' => 'bla'));
|
||||
$this->assertTrue($result[0]);
|
||||
|
|
@ -96,7 +96,7 @@ class CommentTest extends Base
|
|||
|
||||
public function testValidateModification()
|
||||
{
|
||||
$c = new Comment($this->db, $this->event);
|
||||
$c = new Comment($this->registry);
|
||||
|
||||
$result = $c->validateModification(array('id' => 1, 'comment' => 'bla'));
|
||||
$this->assertTrue($result[0]);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ class ProjectTest extends Base
|
|||
{
|
||||
public function testCreation()
|
||||
{
|
||||
$p = new Project($this->db, $this->event);
|
||||
$p = new Project($this->registry);
|
||||
|
||||
$this->assertEquals(1, $p->create(array('name' => 'UnitTest')));
|
||||
$this->assertNotEmpty($p->getById(1));
|
||||
|
|
@ -21,10 +21,10 @@ class ProjectTest extends Base
|
|||
public function testAllowEverybody()
|
||||
{
|
||||
// We create a regular user
|
||||
$user = new User($this->db, $this->event);
|
||||
$user = new User($this->registry);
|
||||
$user->create(array('username' => 'unittest', 'password' => 'unittest'));
|
||||
|
||||
$p = new Project($this->db, $this->event);
|
||||
$p = new Project($this->registry);
|
||||
$this->assertEmpty($p->getAllowedUsers(1)); // Nobody is specified for the given project
|
||||
$this->assertTrue($p->isUserAllowed(1, 1)); // Everybody should be allowed
|
||||
$this->assertTrue($p->isUserAllowed(1, 2)); // Everybody should be allowed
|
||||
|
|
@ -32,8 +32,8 @@ class ProjectTest extends Base
|
|||
|
||||
public function testAllowUser()
|
||||
{
|
||||
$p = new Project($this->db, $this->event);
|
||||
$user = new User($this->db, $this->event);
|
||||
$p = new Project($this->registry);
|
||||
$user = new User($this->registry);
|
||||
$user->create(array('username' => 'unittest', 'password' => 'unittest'));
|
||||
|
||||
// We create a project
|
||||
|
|
@ -58,9 +58,9 @@ class ProjectTest extends Base
|
|||
|
||||
public function testRevokeUser()
|
||||
{
|
||||
$p = new Project($this->db, $this->event);
|
||||
$p = new Project($this->registry);
|
||||
|
||||
$user = new User($this->db, $this->event);
|
||||
$user = new User($this->registry);
|
||||
$user->create(array('username' => 'unittest', 'password' => 'unittest'));
|
||||
|
||||
// We create a project
|
||||
|
|
@ -113,9 +113,9 @@ class ProjectTest extends Base
|
|||
|
||||
public function testUsersList()
|
||||
{
|
||||
$p = new Project($this->db, $this->event);
|
||||
$p = new Project($this->registry);
|
||||
|
||||
$user = new User($this->db, $this->event);
|
||||
$user = new User($this->registry);
|
||||
$user->create(array('username' => 'unittest', 'password' => 'unittest'));
|
||||
|
||||
// We create project
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@ class TaskTest extends Base
|
|||
{
|
||||
public function testExport()
|
||||
{
|
||||
$t = new Task($this->db, $this->event);
|
||||
$p = new Project($this->db, $this->event);
|
||||
$c = new Category($this->db, $this->event);
|
||||
$t = new Task($this->registry);
|
||||
$p = new Project($this->registry);
|
||||
$c = new Category($this->registry);
|
||||
|
||||
$this->assertEquals(1, $p->create(array('name' => 'Export Project')));
|
||||
$this->assertNotFalse($c->create(array('name' => 'Category #1', 'project_id' => 1)));
|
||||
|
|
@ -45,8 +45,8 @@ class TaskTest extends Base
|
|||
|
||||
public function testFilter()
|
||||
{
|
||||
$t = new Task($this->db, $this->event);
|
||||
$p = new Project($this->db, $this->event);
|
||||
$t = new Task($this->registry);
|
||||
$p = new Project($this->registry);
|
||||
|
||||
$this->assertEquals(1, $p->create(array('name' => 'test1')));
|
||||
$this->assertEquals(1, $t->create(array('title' => 'test a', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1, 'description' => 'biloute')));
|
||||
|
|
@ -114,7 +114,7 @@ class TaskTest extends Base
|
|||
|
||||
public function testDateFormat()
|
||||
{
|
||||
$t = new Task($this->db, $this->event);
|
||||
$t = new Task($this->registry);
|
||||
|
||||
$this->assertEquals('2014-03-05', date('Y-m-d', $t->getValidDate('2014-03-05', 'Y-m-d')));
|
||||
$this->assertEquals('2014-03-05', date('Y-m-d', $t->getValidDate('2014_03_05', 'Y_m_d')));
|
||||
|
|
@ -133,8 +133,8 @@ class TaskTest extends Base
|
|||
|
||||
public function testDuplicateTask()
|
||||
{
|
||||
$t = new Task($this->db, $this->event);
|
||||
$p = new Project($this->db, $this->event);
|
||||
$t = new Task($this->registry);
|
||||
$p = new Project($this->registry);
|
||||
|
||||
// We create a task and a project
|
||||
$this->assertEquals(1, $p->create(array('name' => 'test1')));
|
||||
|
|
@ -146,7 +146,7 @@ class TaskTest extends Base
|
|||
|
||||
// We duplicate our task
|
||||
$this->assertEquals(2, $t->duplicate(1));
|
||||
$this->assertTrue($this->event->isEventTriggered(Task::EVENT_CREATE));
|
||||
$this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_CREATE));
|
||||
|
||||
// Check the values of the duplicated task
|
||||
$task = $t->getById(2);
|
||||
|
|
@ -160,8 +160,8 @@ class TaskTest extends Base
|
|||
|
||||
public function testDuplicateToAnotherProject()
|
||||
{
|
||||
$t = new Task($this->db, $this->event);
|
||||
$p = new Project($this->db, $this->event);
|
||||
$t = new Task($this->registry);
|
||||
$p = new Project($this->registry);
|
||||
|
||||
// We create 2 projects
|
||||
$this->assertEquals(1, $p->create(array('name' => 'test1')));
|
||||
|
|
@ -172,7 +172,7 @@ class TaskTest extends Base
|
|||
|
||||
// We duplicate our task to the 2nd project
|
||||
$this->assertEquals(2, $t->duplicateToAnotherProject(1, 2));
|
||||
$this->assertTrue($this->event->isEventTriggered(Task::EVENT_CREATE));
|
||||
$this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_CREATE));
|
||||
|
||||
// Check the values of the duplicated task
|
||||
$task = $t->getById(2);
|
||||
|
|
@ -185,39 +185,39 @@ class TaskTest extends Base
|
|||
|
||||
public function testEvents()
|
||||
{
|
||||
$t = new Task($this->db, $this->event);
|
||||
$p = new Project($this->db, $this->event);
|
||||
$t = new Task($this->registry);
|
||||
$p = new Project($this->registry);
|
||||
|
||||
// We create a project
|
||||
$this->assertEquals(1, $p->create(array('name' => 'test')));
|
||||
|
||||
// We create task
|
||||
$this->assertEquals(1, $t->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1)));
|
||||
$this->assertTrue($this->event->isEventTriggered(Task::EVENT_CREATE));
|
||||
$this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_CREATE));
|
||||
|
||||
// We update a task
|
||||
$this->assertTrue($t->update(array('title' => 'test2', 'id' => 1)));
|
||||
$this->assertTrue($this->event->isEventTriggered(Task::EVENT_UPDATE));
|
||||
$this->assertTrue($this->event->isEventTriggered(Task::EVENT_CREATE_UPDATE));
|
||||
$this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_UPDATE));
|
||||
$this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_CREATE_UPDATE));
|
||||
|
||||
// We close our task
|
||||
$this->assertTrue($t->close(1));
|
||||
$this->assertTrue($this->event->isEventTriggered(Task::EVENT_CLOSE));
|
||||
$this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_CLOSE));
|
||||
|
||||
// We open our task
|
||||
$this->assertTrue($t->open(1));
|
||||
$this->assertTrue($this->event->isEventTriggered(Task::EVENT_OPEN));
|
||||
$this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_OPEN));
|
||||
|
||||
// We change the column of our task
|
||||
$this->assertTrue($t->move(1, 2, 1));
|
||||
$this->assertTrue($this->event->isEventTriggered(Task::EVENT_MOVE_COLUMN));
|
||||
$this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_MOVE_COLUMN));
|
||||
|
||||
// We change the position of our task
|
||||
$this->assertTrue($t->move(1, 2, 2));
|
||||
$this->assertTrue($this->event->isEventTriggered(Task::EVENT_MOVE_POSITION));
|
||||
$this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_MOVE_POSITION));
|
||||
|
||||
// We change the column and the position of our task
|
||||
$this->assertTrue($t->move(1, 1, 3));
|
||||
$this->assertTrue($this->event->isEventTriggered(Task::EVENT_MOVE_COLUMN));
|
||||
$this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_MOVE_COLUMN));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -379,6 +379,12 @@ class Table
|
|||
$sql = sprintf('%s = ?', $this->db->escapeIdentifier($column));
|
||||
break;
|
||||
|
||||
case 'neq':
|
||||
case 'notequal':
|
||||
case 'notequals':
|
||||
$sql = sprintf('%s != ?', $this->db->escapeIdentifier($column));
|
||||
break;
|
||||
|
||||
case 'gt':
|
||||
case 'greaterthan':
|
||||
$sql = sprintf('%s > ?', $this->db->escapeIdentifier($column));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,80 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* General utility class in Swift Mailer, not to be instantiated.
|
||||
*
|
||||
*
|
||||
* @author Chris Corbyn
|
||||
*/
|
||||
abstract class Swift
|
||||
{
|
||||
public static $initialized = false;
|
||||
public static $inits = array();
|
||||
|
||||
/** Swift Mailer Version number generated during dist release process */
|
||||
const VERSION = '@SWIFT_VERSION_NUMBER@';
|
||||
|
||||
/**
|
||||
* Registers an initializer callable that will be called the first time
|
||||
* a SwiftMailer class is autoloaded.
|
||||
*
|
||||
* This enables you to tweak the default configuration in a lazy way.
|
||||
*
|
||||
* @param mixed $callable A valid PHP callable that will be called when autoloading the first Swift class
|
||||
*/
|
||||
public static function init($callable)
|
||||
{
|
||||
self::$inits[] = $callable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal autoloader for spl_autoload_register().
|
||||
*
|
||||
* @param string $class
|
||||
*/
|
||||
public static function autoload($class)
|
||||
{
|
||||
// Don't interfere with other autoloaders
|
||||
if (0 !== strpos($class, 'Swift_')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$path = dirname(__FILE__).'/'.str_replace('_', '/', $class).'.php';
|
||||
|
||||
if (!file_exists($path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
require $path;
|
||||
|
||||
if (self::$inits && !self::$initialized) {
|
||||
self::$initialized = true;
|
||||
foreach (self::$inits as $init) {
|
||||
call_user_func($init);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure autoloading using Swift Mailer.
|
||||
*
|
||||
* This is designed to play nicely with other autoloaders.
|
||||
*
|
||||
* @param mixed $callable A valid PHP callable that will be called when autoloading the first Swift class
|
||||
*/
|
||||
public static function registerAutoload($callable = null)
|
||||
{
|
||||
if (null !== $callable) {
|
||||
self::$inits[] = $callable;
|
||||
}
|
||||
spl_autoload_register(array('Swift', 'autoload'));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Attachment class for attaching files to a {@link Swift_Mime_Message}.
|
||||
*
|
||||
* @author Chris Corbyn
|
||||
*/
|
||||
class Swift_Attachment extends Swift_Mime_Attachment
|
||||
{
|
||||
/**
|
||||
* Create a new Attachment.
|
||||
*
|
||||
* Details may be optionally provided to the constructor.
|
||||
*
|
||||
* @param string|Swift_OutputByteStream $data
|
||||
* @param string $filename
|
||||
* @param string $contentType
|
||||
*/
|
||||
public function __construct($data = null, $filename = null, $contentType = null)
|
||||
{
|
||||
call_user_func_array(
|
||||
array($this, 'Swift_Mime_Attachment::__construct'),
|
||||
Swift_DependencyContainer::getInstance()
|
||||
->createDependenciesFor('mime.attachment')
|
||||
);
|
||||
|
||||
$this->setBody($data);
|
||||
$this->setFilename($filename);
|
||||
if ($contentType) {
|
||||
$this->setContentType($contentType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Attachment.
|
||||
*
|
||||
* @param string|Swift_OutputByteStream $data
|
||||
* @param string $filename
|
||||
* @param string $contentType
|
||||
*
|
||||
* @return Swift_Mime_Attachment
|
||||
*/
|
||||
public static function newInstance($data = null, $filename = null, $contentType = null)
|
||||
{
|
||||
return new self($data, $filename, $contentType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Attachment from a filesystem path.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $contentType optional
|
||||
*
|
||||
* @return Swift_Mime_Attachment
|
||||
*/
|
||||
public static function fromPath($path, $contentType = null)
|
||||
{
|
||||
return self::newInstance()->setFile(
|
||||
new Swift_ByteStream_FileByteStream($path),
|
||||
$contentType
|
||||
);
|
||||
}
|
||||
}
|
||||
179
vendor/swiftmailer/classes/Swift/ByteStream/AbstractFilterableInputStream.php
vendored
Normal file
179
vendor/swiftmailer/classes/Swift/ByteStream/AbstractFilterableInputStream.php
vendored
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provides the base functionality for an InputStream supporting filters.
|
||||
*
|
||||
* @author Chris Corbyn
|
||||
*/
|
||||
abstract class Swift_ByteStream_AbstractFilterableInputStream implements Swift_InputByteStream, Swift_Filterable
|
||||
{
|
||||
/**
|
||||
* Write sequence.
|
||||
*/
|
||||
protected $_sequence = 0;
|
||||
|
||||
/**
|
||||
* StreamFilters.
|
||||
*/
|
||||
private $_filters = array();
|
||||
|
||||
/**
|
||||
* A buffer for writing.
|
||||
*/
|
||||
private $_writeBuffer = '';
|
||||
|
||||
/**
|
||||
* Bound streams.
|
||||
*
|
||||
* @var Swift_InputByteStream[]
|
||||
*/
|
||||
private $_mirrors = array();
|
||||
|
||||
/**
|
||||
* Commit the given bytes to the storage medium immediately.
|
||||
*
|
||||
* @param string $bytes
|
||||
*/
|
||||
abstract protected function _commit($bytes);
|
||||
|
||||
/**
|
||||
* Flush any buffers/content with immediate effect.
|
||||
*/
|
||||
abstract protected function _flush();
|
||||
|
||||
/**
|
||||
* Add a StreamFilter to this InputByteStream.
|
||||
*
|
||||
* @param Swift_StreamFilter $filter
|
||||
* @param string $key
|
||||
*/
|
||||
public function addFilter(Swift_StreamFilter $filter, $key)
|
||||
{
|
||||
$this->_filters[$key] = $filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an already present StreamFilter based on its $key.
|
||||
*
|
||||
* @param string $key
|
||||
*/
|
||||
public function removeFilter($key)
|
||||
{
|
||||
unset($this->_filters[$key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes $bytes to the end of the stream.
|
||||
*
|
||||
* @param string $bytes
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @throws Swift_IoException
|
||||
*/
|
||||
public function write($bytes)
|
||||
{
|
||||
$this->_writeBuffer .= $bytes;
|
||||
foreach ($this->_filters as $filter) {
|
||||
if ($filter->shouldBuffer($this->_writeBuffer)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
$this->_doWrite($this->_writeBuffer);
|
||||
|
||||
return ++$this->_sequence;
|
||||
}
|
||||
|
||||
/**
|
||||
* For any bytes that are currently buffered inside the stream, force them
|
||||
* off the buffer.
|
||||
*
|
||||
* @throws Swift_IoException
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
$this->_doWrite($this->_writeBuffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach $is to this stream.
|
||||
*
|
||||
* The stream acts as an observer, receiving all data that is written.
|
||||
* All {@link write()} and {@link flushBuffers()} operations will be mirrored.
|
||||
*
|
||||
* @param Swift_InputByteStream $is
|
||||
*/
|
||||
public function bind(Swift_InputByteStream $is)
|
||||
{
|
||||
$this->_mirrors[] = $is;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an already bound stream.
|
||||
*
|
||||
* If $is is not bound, no errors will be raised.
|
||||
* If the stream currently has any buffered data it will be written to $is
|
||||
* before unbinding occurs.
|
||||
*
|
||||
* @param Swift_InputByteStream $is
|
||||
*/
|
||||
public function unbind(Swift_InputByteStream $is)
|
||||
{
|
||||
foreach ($this->_mirrors as $k => $stream) {
|
||||
if ($is === $stream) {
|
||||
if ($this->_writeBuffer !== '') {
|
||||
$stream->write($this->_writeBuffer);
|
||||
}
|
||||
unset($this->_mirrors[$k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush the contents of the stream (empty it) and set the internal pointer
|
||||
* to the beginning.
|
||||
*
|
||||
* @throws Swift_IoException
|
||||
*/
|
||||
public function flushBuffers()
|
||||
{
|
||||
if ($this->_writeBuffer !== '') {
|
||||
$this->_doWrite($this->_writeBuffer);
|
||||
}
|
||||
$this->_flush();
|
||||
|
||||
foreach ($this->_mirrors as $stream) {
|
||||
$stream->flushBuffers();
|
||||
}
|
||||
}
|
||||
|
||||
/** Run $bytes through all filters */
|
||||
private function _filter($bytes)
|
||||
{
|
||||
foreach ($this->_filters as $filter) {
|
||||
$bytes = $filter->filter($bytes);
|
||||
}
|
||||
|
||||
return $bytes;
|
||||
}
|
||||
|
||||
/** Just write the bytes to the stream */
|
||||
private function _doWrite($bytes)
|
||||
{
|
||||
$this->_commit($this->_filter($bytes));
|
||||
|
||||
foreach ($this->_mirrors as $stream) {
|
||||
$stream->write($bytes);
|
||||
}
|
||||
|
||||
$this->_writeBuffer = '';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,184 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Allows reading and writing of bytes to and from an array.
|
||||
*
|
||||
* @author Chris Corbyn
|
||||
*/
|
||||
class Swift_ByteStream_ArrayByteStream implements Swift_InputByteStream, Swift_OutputByteStream
|
||||
{
|
||||
/**
|
||||
* The internal stack of bytes.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
private $_array = array();
|
||||
|
||||
/**
|
||||
* The size of the stack
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $_arraySize = 0;
|
||||
|
||||
/**
|
||||
* The internal pointer offset.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $_offset = 0;
|
||||
|
||||
/**
|
||||
* Bound streams.
|
||||
*
|
||||
* @var Swift_InputByteStream[]
|
||||
*/
|
||||
private $_mirrors = array();
|
||||
|
||||
/**
|
||||
* Create a new ArrayByteStream.
|
||||
*
|
||||
* If $stack is given the stream will be populated with the bytes it contains.
|
||||
*
|
||||
* @param mixed $stack of bytes in string or array form, optional
|
||||
*/
|
||||
public function __construct($stack = null)
|
||||
{
|
||||
if (is_array($stack)) {
|
||||
$this->_array = $stack;
|
||||
$this->_arraySize = count($stack);
|
||||
} elseif (is_string($stack)) {
|
||||
$this->write($stack);
|
||||
} else {
|
||||
$this->_array = array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads $length bytes from the stream into a string and moves the pointer
|
||||
* through the stream by $length.
|
||||
*
|
||||
* If less bytes exist than are requested the
|
||||
* remaining bytes are given instead. If no bytes are remaining at all, boolean
|
||||
* false is returned.
|
||||
*
|
||||
* @param int $length
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function read($length)
|
||||
{
|
||||
if ($this->_offset == $this->_arraySize) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't use array slice
|
||||
$end = $length + $this->_offset;
|
||||
$end = $this->_arraySize<$end
|
||||
?$this->_arraySize
|
||||
:$end;
|
||||
$ret = '';
|
||||
for (; $this->_offset < $end; ++$this->_offset) {
|
||||
$ret .= $this->_array[$this->_offset];
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes $bytes to the end of the stream.
|
||||
*
|
||||
* @param string $bytes
|
||||
*/
|
||||
public function write($bytes)
|
||||
{
|
||||
$to_add = str_split($bytes);
|
||||
foreach ($to_add as $value) {
|
||||
$this->_array[] = $value;
|
||||
}
|
||||
$this->_arraySize = count($this->_array);
|
||||
|
||||
foreach ($this->_mirrors as $stream) {
|
||||
$stream->write($bytes);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Not used.
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach $is to this stream.
|
||||
*
|
||||
* The stream acts as an observer, receiving all data that is written.
|
||||
* All {@link write()} and {@link flushBuffers()} operations will be mirrored.
|
||||
*
|
||||
* @param Swift_InputByteStream $is
|
||||
*/
|
||||
public function bind(Swift_InputByteStream $is)
|
||||
{
|
||||
$this->_mirrors[] = $is;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an already bound stream.
|
||||
*
|
||||
* If $is is not bound, no errors will be raised.
|
||||
* If the stream currently has any buffered data it will be written to $is
|
||||
* before unbinding occurs.
|
||||
*
|
||||
* @param Swift_InputByteStream $is
|
||||
*/
|
||||
public function unbind(Swift_InputByteStream $is)
|
||||
{
|
||||
foreach ($this->_mirrors as $k => $stream) {
|
||||
if ($is === $stream) {
|
||||
unset($this->_mirrors[$k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the internal read pointer to $byteOffset in the stream.
|
||||
*
|
||||
* @param int $byteOffset
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function setReadPointer($byteOffset)
|
||||
{
|
||||
if ($byteOffset > $this->_arraySize) {
|
||||
$byteOffset = $this->_arraySize;
|
||||
} elseif ($byteOffset < 0) {
|
||||
$byteOffset = 0;
|
||||
}
|
||||
|
||||
$this->_offset = $byteOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush the contents of the stream (empty it) and set the internal pointer
|
||||
* to the beginning.
|
||||
*/
|
||||
public function flushBuffers()
|
||||
{
|
||||
$this->_offset = 0;
|
||||
$this->_array = array();
|
||||
$this->_arraySize = 0;
|
||||
|
||||
foreach ($this->_mirrors as $stream) {
|
||||
$stream->flushBuffers();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,229 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Allows reading and writing of bytes to and from a file.
|
||||
*
|
||||
* @author Chris Corbyn
|
||||
*/
|
||||
class Swift_ByteStream_FileByteStream extends Swift_ByteStream_AbstractFilterableInputStream implements Swift_FileStream
|
||||
{
|
||||
/** The internal pointer offset */
|
||||
private $_offset = 0;
|
||||
|
||||
/** The path to the file */
|
||||
private $_path;
|
||||
|
||||
/** The mode this file is opened in for writing */
|
||||
private $_mode;
|
||||
|
||||
/** A lazy-loaded resource handle for reading the file */
|
||||
private $_reader;
|
||||
|
||||
/** A lazy-loaded resource handle for writing the file */
|
||||
private $_writer;
|
||||
|
||||
/** If magic_quotes_runtime is on, this will be true */
|
||||
private $_quotes = false;
|
||||
|
||||
/** If stream is seekable true/false, or null if not known */
|
||||
private $_seekable = null;
|
||||
|
||||
/**
|
||||
* Create a new FileByteStream for $path.
|
||||
*
|
||||
* @param string $path
|
||||
* @param bool $writable if true
|
||||
*/
|
||||
public function __construct($path, $writable = false)
|
||||
{
|
||||
if (empty($path)) {
|
||||
throw new Swift_IoException('The path cannot be empty');
|
||||
}
|
||||
$this->_path = $path;
|
||||
$this->_mode = $writable ? 'w+b' : 'rb';
|
||||
|
||||
if (function_exists('get_magic_quotes_runtime') && @get_magic_quotes_runtime() == 1) {
|
||||
$this->_quotes = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the complete path to the file.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPath()
|
||||
{
|
||||
return $this->_path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads $length bytes from the stream into a string and moves the pointer
|
||||
* through the stream by $length.
|
||||
*
|
||||
* If less bytes exist than are requested the
|
||||
* remaining bytes are given instead. If no bytes are remaining at all, boolean
|
||||
* false is returned.
|
||||
*
|
||||
* @param int $length
|
||||
*
|
||||
* @return string|bool
|
||||
*
|
||||
* @throws Swift_IoException
|
||||
*/
|
||||
public function read($length)
|
||||
{
|
||||
$fp = $this->_getReadHandle();
|
||||
if (!feof($fp)) {
|
||||
if ($this->_quotes) {
|
||||
ini_set('magic_quotes_runtime', 0);
|
||||
}
|
||||
$bytes = fread($fp, $length);
|
||||
if ($this->_quotes) {
|
||||
ini_set('magic_quotes_runtime', 1);
|
||||
}
|
||||
$this->_offset = ftell($fp);
|
||||
|
||||
// If we read one byte after reaching the end of the file
|
||||
// feof() will return false and an empty string is returned
|
||||
if ($bytes === '' && feof($fp)) {
|
||||
$this->_resetReadHandle();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return $bytes;
|
||||
}
|
||||
|
||||
$this->_resetReadHandle();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the internal read pointer to $byteOffset in the stream.
|
||||
*
|
||||
* @param int $byteOffset
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function setReadPointer($byteOffset)
|
||||
{
|
||||
if (isset($this->_reader)) {
|
||||
$this->_seekReadStreamToPosition($byteOffset);
|
||||
}
|
||||
$this->_offset = $byteOffset;
|
||||
}
|
||||
|
||||
/** Just write the bytes to the file */
|
||||
protected function _commit($bytes)
|
||||
{
|
||||
fwrite($this->_getWriteHandle(), $bytes);
|
||||
$this->_resetReadHandle();
|
||||
}
|
||||
|
||||
/** Not used */
|
||||
protected function _flush()
|
||||
{
|
||||
}
|
||||
|
||||
/** Get the resource for reading */
|
||||
private function _getReadHandle()
|
||||
{
|
||||
if (!isset($this->_reader)) {
|
||||
if (!$this->_reader = fopen($this->_path, 'rb')) {
|
||||
throw new Swift_IoException(
|
||||
'Unable to open file for reading [' . $this->_path . ']'
|
||||
);
|
||||
}
|
||||
if ($this->_offset <> 0) {
|
||||
$this->_getReadStreamSeekableStatus();
|
||||
$this->_seekReadStreamToPosition($this->_offset);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->_reader;
|
||||
}
|
||||
|
||||
/** Get the resource for writing */
|
||||
private function _getWriteHandle()
|
||||
{
|
||||
if (!isset($this->_writer)) {
|
||||
if (!$this->_writer = fopen($this->_path, $this->_mode)) {
|
||||
throw new Swift_IoException(
|
||||
'Unable to open file for writing [' . $this->_path . ']'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->_writer;
|
||||
}
|
||||
|
||||
/** Force a reload of the resource for reading */
|
||||
private function _resetReadHandle()
|
||||
{
|
||||
if (isset($this->_reader)) {
|
||||
fclose($this->_reader);
|
||||
$this->_reader = null;
|
||||
}
|
||||
}
|
||||
|
||||
/** Check if ReadOnly Stream is seekable */
|
||||
private function _getReadStreamSeekableStatus()
|
||||
{
|
||||
$metas = stream_get_meta_data($this->_reader);
|
||||
$this->_seekable = $metas['seekable'];
|
||||
}
|
||||
|
||||
/** Streams in a readOnly stream ensuring copy if needed */
|
||||
private function _seekReadStreamToPosition($offset)
|
||||
{
|
||||
if ($this->_seekable===null) {
|
||||
$this->_getReadStreamSeekableStatus();
|
||||
}
|
||||
if ($this->_seekable === false) {
|
||||
$currentPos = ftell($this->_reader);
|
||||
if ($currentPos<$offset) {
|
||||
$toDiscard = $offset-$currentPos;
|
||||
fread($this->_reader, $toDiscard);
|
||||
|
||||
return;
|
||||
}
|
||||
$this->_copyReadStream();
|
||||
}
|
||||
fseek($this->_reader, $offset, SEEK_SET);
|
||||
}
|
||||
|
||||
/** Copy a readOnly Stream to ensure seekability */
|
||||
private function _copyReadStream()
|
||||
{
|
||||
if ($tmpFile = fopen('php://temp/maxmemory:4096', 'w+b')) {
|
||||
/* We have opened a php:// Stream Should work without problem */
|
||||
} elseif (function_exists('sys_get_temp_dir') && is_writable(sys_get_temp_dir()) && ($tmpFile = tmpfile())) {
|
||||
/* We have opened a tmpfile */
|
||||
} else {
|
||||
throw new Swift_IoException('Unable to copy the file to make it seekable, sys_temp_dir is not writable, php://memory not available');
|
||||
}
|
||||
$currentPos = ftell($this->_reader);
|
||||
fclose($this->_reader);
|
||||
$source = fopen($this->_path, 'rb');
|
||||
if (!$source) {
|
||||
throw new Swift_IoException('Unable to open file for copying [' . $this->_path . ']');
|
||||
}
|
||||
fseek($tmpFile, 0, SEEK_SET);
|
||||
while (!feof($source)) {
|
||||
fwrite($tmpFile, fread($source, 4096));
|
||||
}
|
||||
fseek($tmpFile, $currentPos, SEEK_SET);
|
||||
fclose($source);
|
||||
$this->_reader = $tmpFile;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @author Romain-Geissler
|
||||
*/
|
||||
class Swift_ByteStream_TemporaryFileByteStream extends Swift_ByteStream_FileByteStream
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$filePath = tempnam(sys_get_temp_dir(), 'FileByteStream');
|
||||
|
||||
if ($filePath === false) {
|
||||
throw new Swift_IoException('Failed to retrieve temporary file name.');
|
||||
}
|
||||
|
||||
parent::__construct($filePath, true);
|
||||
}
|
||||
|
||||
public function getContent()
|
||||
{
|
||||
if (($content = file_get_contents($this->getPath())) === false) {
|
||||
throw new Swift_IoException('Failed to get temporary file content.');
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
if (file_exists($this->getPath())) {
|
||||
@unlink($this->getPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Analyzes characters for a specific character set.
|
||||
*
|
||||
* @author Chris Corbyn
|
||||
* @author Xavier De Cock <xdecock@gmail.com>
|
||||
*/
|
||||
interface Swift_CharacterReader
|
||||
{
|
||||
const MAP_TYPE_INVALID = 0x01;
|
||||
const MAP_TYPE_FIXED_LEN = 0x02;
|
||||
const MAP_TYPE_POSITIONS = 0x03;
|
||||
|
||||
/**
|
||||
* Returns the complete character map
|
||||
*
|
||||
* @param string $string
|
||||
* @param int $startOffset
|
||||
* @param array $currentMap
|
||||
* @param mixed $ignoredChars
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars);
|
||||
|
||||
/**
|
||||
* Returns the mapType, see constants.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getMapType();
|
||||
|
||||
/**
|
||||
* Returns an integer which specifies how many more bytes to read.
|
||||
*
|
||||
* A positive integer indicates the number of more bytes to fetch before invoking
|
||||
* this method again.
|
||||
*
|
||||
* A value of zero means this is already a valid character.
|
||||
* A value of -1 means this cannot possibly be a valid character.
|
||||
*
|
||||
* @param integer[] $bytes
|
||||
* @param int $size
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function validateByteSequence($bytes, $size);
|
||||
|
||||
/**
|
||||
* Returns the number of bytes which should be read to start each character.
|
||||
*
|
||||
* For fixed width character sets this should be the number of octets-per-character.
|
||||
* For multibyte character sets this will probably be 1.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getInitialByteSize();
|
||||
}
|
||||
97
vendor/swiftmailer/classes/Swift/CharacterReader/GenericFixedWidthReader.php
vendored
Normal file
97
vendor/swiftmailer/classes/Swift/CharacterReader/GenericFixedWidthReader.php
vendored
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provides fixed-width byte sizes for reading fixed-width character sets.
|
||||
*
|
||||
* @author Chris Corbyn
|
||||
* @author Xavier De Cock <xdecock@gmail.com>
|
||||
*/
|
||||
class Swift_CharacterReader_GenericFixedWidthReader implements Swift_CharacterReader
|
||||
{
|
||||
/**
|
||||
* The number of bytes in a single character.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $_width;
|
||||
|
||||
/**
|
||||
* Creates a new GenericFixedWidthReader using $width bytes per character.
|
||||
*
|
||||
* @param int $width
|
||||
*/
|
||||
public function __construct($width)
|
||||
{
|
||||
$this->_width = $width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the complete character map.
|
||||
*
|
||||
* @param string $string
|
||||
* @param int $startOffset
|
||||
* @param array $currentMap
|
||||
* @param mixed $ignoredChars
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars)
|
||||
{
|
||||
$strlen = strlen($string);
|
||||
// % and / are CPU intensive, so, maybe find a better way
|
||||
$ignored = $strlen % $this->_width;
|
||||
$ignoredChars = substr($string, - $ignored);
|
||||
$currentMap = $this->_width;
|
||||
|
||||
return ($strlen - $ignored) / $this->_width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mapType.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getMapType()
|
||||
{
|
||||
return self::MAP_TYPE_FIXED_LEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an integer which specifies how many more bytes to read.
|
||||
*
|
||||
* A positive integer indicates the number of more bytes to fetch before invoking
|
||||
* this method again.
|
||||
*
|
||||
* A value of zero means this is already a valid character.
|
||||
* A value of -1 means this cannot possibly be a valid character.
|
||||
*
|
||||
* @param string $bytes
|
||||
* @param int $size
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function validateByteSequence($bytes, $size)
|
||||
{
|
||||
$needed = $this->_width - $size;
|
||||
|
||||
return ($needed > -1) ? $needed : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of bytes which should be read to start each character.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getInitialByteSize()
|
||||
{
|
||||
return $this->_width;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Analyzes US-ASCII characters.
|
||||
*
|
||||
* @author Chris Corbyn
|
||||
*/
|
||||
class Swift_CharacterReader_UsAsciiReader implements Swift_CharacterReader
|
||||
{
|
||||
/**
|
||||
* Returns the complete character map.
|
||||
*
|
||||
* @param string $string
|
||||
* @param int $startOffset
|
||||
* @param array $currentMap
|
||||
* @param string $ignoredChars
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars)
|
||||
{
|
||||
$strlen=strlen($string);
|
||||
$ignoredChars='';
|
||||
for ($i = 0; $i < $strlen; ++$i) {
|
||||
if ($string[$i]>"\x07F") { // Invalid char
|
||||
$currentMap[$i+$startOffset]=$string[$i];
|
||||
}
|
||||
}
|
||||
|
||||
return $strlen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns mapType
|
||||
*
|
||||
* @return int mapType
|
||||
*/
|
||||
public function getMapType()
|
||||
{
|
||||
return self::MAP_TYPE_INVALID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an integer which specifies how many more bytes to read.
|
||||
*
|
||||
* A positive integer indicates the number of more bytes to fetch before invoking
|
||||
* this method again.
|
||||
* A value of zero means this is already a valid character.
|
||||
* A value of -1 means this cannot possibly be a valid character.
|
||||
*
|
||||
* @param string $bytes
|
||||
* @param int $size
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function validateByteSequence($bytes, $size)
|
||||
{
|
||||
$byte = reset($bytes);
|
||||
if (1 == count($bytes) && $byte >= 0x00 && $byte <= 0x7F) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of bytes which should be read to start each character.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getInitialByteSize()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Analyzes UTF-8 characters.
|
||||
*
|
||||
* @author Chris Corbyn
|
||||
* @author Xavier De Cock <xdecock@gmail.com>
|
||||
*/
|
||||
class Swift_CharacterReader_Utf8Reader implements Swift_CharacterReader
|
||||
{
|
||||
/** Pre-computed for optimization */
|
||||
private static $length_map=array(
|
||||
// N=0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x0N
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x1N
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x2N
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x3N
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x4N
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x5N
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x6N
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x7N
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0x8N
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0x9N
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0xAN
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0xBN
|
||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 0xCN
|
||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 0xDN
|
||||
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 0xEN
|
||||
4,4,4,4,4,4,4,4,5,5,5,5,6,6,0,0 // 0xFN
|
||||
);
|
||||
|
||||
private static $s_length_map=array(
|
||||
"\x00"=>1, "\x01"=>1, "\x02"=>1, "\x03"=>1, "\x04"=>1, "\x05"=>1, "\x06"=>1, "\x07"=>1,
|
||||
"\x08"=>1, "\x09"=>1, "\x0a"=>1, "\x0b"=>1, "\x0c"=>1, "\x0d"=>1, "\x0e"=>1, "\x0f"=>1,
|
||||
"\x10"=>1, "\x11"=>1, "\x12"=>1, "\x13"=>1, "\x14"=>1, "\x15"=>1, "\x16"=>1, "\x17"=>1,
|
||||
"\x18"=>1, "\x19"=>1, "\x1a"=>1, "\x1b"=>1, "\x1c"=>1, "\x1d"=>1, "\x1e"=>1, "\x1f"=>1,
|
||||
"\x20"=>1, "\x21"=>1, "\x22"=>1, "\x23"=>1, "\x24"=>1, "\x25"=>1, "\x26"=>1, "\x27"=>1,
|
||||
"\x28"=>1, "\x29"=>1, "\x2a"=>1, "\x2b"=>1, "\x2c"=>1, "\x2d"=>1, "\x2e"=>1, "\x2f"=>1,
|
||||
"\x30"=>1, "\x31"=>1, "\x32"=>1, "\x33"=>1, "\x34"=>1, "\x35"=>1, "\x36"=>1, "\x37"=>1,
|
||||
"\x38"=>1, "\x39"=>1, "\x3a"=>1, "\x3b"=>1, "\x3c"=>1, "\x3d"=>1, "\x3e"=>1, "\x3f"=>1,
|
||||
"\x40"=>1, "\x41"=>1, "\x42"=>1, "\x43"=>1, "\x44"=>1, "\x45"=>1, "\x46"=>1, "\x47"=>1,
|
||||
"\x48"=>1, "\x49"=>1, "\x4a"=>1, "\x4b"=>1, "\x4c"=>1, "\x4d"=>1, "\x4e"=>1, "\x4f"=>1,
|
||||
"\x50"=>1, "\x51"=>1, "\x52"=>1, "\x53"=>1, "\x54"=>1, "\x55"=>1, "\x56"=>1, "\x57"=>1,
|
||||
"\x58"=>1, "\x59"=>1, "\x5a"=>1, "\x5b"=>1, "\x5c"=>1, "\x5d"=>1, "\x5e"=>1, "\x5f"=>1,
|
||||
"\x60"=>1, "\x61"=>1, "\x62"=>1, "\x63"=>1, "\x64"=>1, "\x65"=>1, "\x66"=>1, "\x67"=>1,
|
||||
"\x68"=>1, "\x69"=>1, "\x6a"=>1, "\x6b"=>1, "\x6c"=>1, "\x6d"=>1, "\x6e"=>1, "\x6f"=>1,
|
||||
"\x70"=>1, "\x71"=>1, "\x72"=>1, "\x73"=>1, "\x74"=>1, "\x75"=>1, "\x76"=>1, "\x77"=>1,
|
||||
"\x78"=>1, "\x79"=>1, "\x7a"=>1, "\x7b"=>1, "\x7c"=>1, "\x7d"=>1, "\x7e"=>1, "\x7f"=>1,
|
||||
"\x80"=>0, "\x81"=>0, "\x82"=>0, "\x83"=>0, "\x84"=>0, "\x85"=>0, "\x86"=>0, "\x87"=>0,
|
||||
"\x88"=>0, "\x89"=>0, "\x8a"=>0, "\x8b"=>0, "\x8c"=>0, "\x8d"=>0, "\x8e"=>0, "\x8f"=>0,
|
||||
"\x90"=>0, "\x91"=>0, "\x92"=>0, "\x93"=>0, "\x94"=>0, "\x95"=>0, "\x96"=>0, "\x97"=>0,
|
||||
"\x98"=>0, "\x99"=>0, "\x9a"=>0, "\x9b"=>0, "\x9c"=>0, "\x9d"=>0, "\x9e"=>0, "\x9f"=>0,
|
||||
"\xa0"=>0, "\xa1"=>0, "\xa2"=>0, "\xa3"=>0, "\xa4"=>0, "\xa5"=>0, "\xa6"=>0, "\xa7"=>0,
|
||||
"\xa8"=>0, "\xa9"=>0, "\xaa"=>0, "\xab"=>0, "\xac"=>0, "\xad"=>0, "\xae"=>0, "\xaf"=>0,
|
||||
"\xb0"=>0, "\xb1"=>0, "\xb2"=>0, "\xb3"=>0, "\xb4"=>0, "\xb5"=>0, "\xb6"=>0, "\xb7"=>0,
|
||||
"\xb8"=>0, "\xb9"=>0, "\xba"=>0, "\xbb"=>0, "\xbc"=>0, "\xbd"=>0, "\xbe"=>0, "\xbf"=>0,
|
||||
"\xc0"=>2, "\xc1"=>2, "\xc2"=>2, "\xc3"=>2, "\xc4"=>2, "\xc5"=>2, "\xc6"=>2, "\xc7"=>2,
|
||||
"\xc8"=>2, "\xc9"=>2, "\xca"=>2, "\xcb"=>2, "\xcc"=>2, "\xcd"=>2, "\xce"=>2, "\xcf"=>2,
|
||||
"\xd0"=>2, "\xd1"=>2, "\xd2"=>2, "\xd3"=>2, "\xd4"=>2, "\xd5"=>2, "\xd6"=>2, "\xd7"=>2,
|
||||
"\xd8"=>2, "\xd9"=>2, "\xda"=>2, "\xdb"=>2, "\xdc"=>2, "\xdd"=>2, "\xde"=>2, "\xdf"=>2,
|
||||
"\xe0"=>3, "\xe1"=>3, "\xe2"=>3, "\xe3"=>3, "\xe4"=>3, "\xe5"=>3, "\xe6"=>3, "\xe7"=>3,
|
||||
"\xe8"=>3, "\xe9"=>3, "\xea"=>3, "\xeb"=>3, "\xec"=>3, "\xed"=>3, "\xee"=>3, "\xef"=>3,
|
||||
"\xf0"=>4, "\xf1"=>4, "\xf2"=>4, "\xf3"=>4, "\xf4"=>4, "\xf5"=>4, "\xf6"=>4, "\xf7"=>4,
|
||||
"\xf8"=>5, "\xf9"=>5, "\xfa"=>5, "\xfb"=>5, "\xfc"=>6, "\xfd"=>6, "\xfe"=>0, "\xff"=>0,
|
||||
);
|
||||
|
||||
/**
|
||||
* Returns the complete character map.
|
||||
*
|
||||
* @param string $string
|
||||
* @param int $startOffset
|
||||
* @param array $currentMap
|
||||
* @param mixed $ignoredChars
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars)
|
||||
{
|
||||
if (!isset($currentMap['i']) || ! isset($currentMap['p'])) {
|
||||
$currentMap['p'] = $currentMap['i'] = array();
|
||||
}
|
||||
|
||||
$strlen=strlen($string);
|
||||
$charPos=count($currentMap['p']);
|
||||
$foundChars=0;
|
||||
$invalid=false;
|
||||
for ($i = 0; $i < $strlen; ++$i) {
|
||||
$char = $string[$i];
|
||||
$size = self::$s_length_map[$char];
|
||||
if ($size == 0) {
|
||||
/* char is invalid, we must wait for a resync */
|
||||
$invalid = true;
|
||||
continue;
|
||||
} else {
|
||||
if ($invalid == true) {
|
||||
/* We mark the chars as invalid and start a new char */
|
||||
$currentMap['p'][$charPos + $foundChars] = $startOffset + $i;
|
||||
$currentMap['i'][$charPos + $foundChars] = true;
|
||||
++$foundChars;
|
||||
$invalid = false;
|
||||
}
|
||||
if (($i + $size) > $strlen) {
|
||||
$ignoredChars = substr($string, $i);
|
||||
break;
|
||||
}
|
||||
for ($j = 1; $j < $size; ++$j) {
|
||||
$char = $string[$i + $j];
|
||||
if ($char > "\x7F" && $char < "\xC0") {
|
||||
// Valid - continue parsing
|
||||
} else {
|
||||
/* char is invalid, we must wait for a resync */
|
||||
$invalid = true;
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
/* Ok we got a complete char here */
|
||||
$currentMap['p'][$charPos + $foundChars] = $startOffset + $i + $size;
|
||||
$i += $j - 1;
|
||||
++$foundChars;
|
||||
}
|
||||
}
|
||||
|
||||
return $foundChars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns mapType.
|
||||
*
|
||||
* @return int mapType
|
||||
*/
|
||||
public function getMapType()
|
||||
{
|
||||
return self::MAP_TYPE_POSITIONS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an integer which specifies how many more bytes to read.
|
||||
*
|
||||
* A positive integer indicates the number of more bytes to fetch before invoking
|
||||
* this method again.
|
||||
* A value of zero means this is already a valid character.
|
||||
* A value of -1 means this cannot possibly be a valid character.
|
||||
*
|
||||
* @param string $bytes
|
||||
* @param int $size
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function validateByteSequence($bytes, $size)
|
||||
{
|
||||
if ($size<1) {
|
||||
return -1;
|
||||
}
|
||||
$needed = self::$length_map[$bytes[0]] - $size;
|
||||
|
||||
return ($needed > -1)
|
||||
? $needed
|
||||
: -1
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of bytes which should be read to start each character.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getInitialByteSize()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A factory for creating CharacterReaders.
|
||||
*
|
||||
* @author Chris Corbyn
|
||||
*/
|
||||
interface Swift_CharacterReaderFactory
|
||||
{
|
||||
/**
|
||||
* Returns a CharacterReader suitable for the charset applied.
|
||||
*
|
||||
* @param string $charset
|
||||
*
|
||||
* @return Swift_CharacterReader
|
||||
*/
|
||||
public function getReaderFor($charset);
|
||||
}
|
||||
124
vendor/swiftmailer/classes/Swift/CharacterReaderFactory/SimpleCharacterReaderFactory.php
vendored
Normal file
124
vendor/swiftmailer/classes/Swift/CharacterReaderFactory/SimpleCharacterReaderFactory.php
vendored
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Standard factory for creating CharacterReaders.
|
||||
*
|
||||
* @author Chris Corbyn
|
||||
*/
|
||||
class Swift_CharacterReaderFactory_SimpleCharacterReaderFactory implements Swift_CharacterReaderFactory
|
||||
{
|
||||
/**
|
||||
* A map of charset patterns to their implementation classes.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $_map = array();
|
||||
|
||||
/**
|
||||
* Factories which have already been loaded.
|
||||
*
|
||||
* @var Swift_CharacterReaderFactory[]
|
||||
*/
|
||||
private static $_loaded = array();
|
||||
|
||||
/**
|
||||
* Creates a new CharacterReaderFactory.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->init();
|
||||
}
|
||||
|
||||
public function __wakeup()
|
||||
{
|
||||
$this->init();
|
||||
}
|
||||
|
||||
public function init()
|
||||
{
|
||||
if (count(self::$_map) > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$prefix = 'Swift_CharacterReader_';
|
||||
|
||||
$singleByte = array(
|
||||
'class' => $prefix . 'GenericFixedWidthReader',
|
||||
'constructor' => array(1)
|
||||
);
|
||||
|
||||
$doubleByte = array(
|
||||
'class' => $prefix . 'GenericFixedWidthReader',
|
||||
'constructor' => array(2)
|
||||
);
|
||||
|
||||
$fourBytes = array(
|
||||
'class' => $prefix . 'GenericFixedWidthReader',
|
||||
'constructor' => array(4)
|
||||
);
|
||||
|
||||
// Utf-8
|
||||
self::$_map['utf-?8'] = array(
|
||||
'class' => $prefix . 'Utf8Reader',
|
||||
'constructor' => array()
|
||||
);
|
||||
|
||||
//7-8 bit charsets
|
||||
self::$_map['(us-)?ascii'] = $singleByte;
|
||||
self::$_map['(iso|iec)-?8859-?[0-9]+'] = $singleByte;
|
||||
self::$_map['windows-?125[0-9]'] = $singleByte;
|
||||
self::$_map['cp-?[0-9]+'] = $singleByte;
|
||||
self::$_map['ansi'] = $singleByte;
|
||||
self::$_map['macintosh'] = $singleByte;
|
||||
self::$_map['koi-?7'] = $singleByte;
|
||||
self::$_map['koi-?8-?.+'] = $singleByte;
|
||||
self::$_map['mik'] = $singleByte;
|
||||
self::$_map['(cork|t1)'] = $singleByte;
|
||||
self::$_map['v?iscii'] = $singleByte;
|
||||
|
||||
//16 bits
|
||||
self::$_map['(ucs-?2|utf-?16)'] = $doubleByte;
|
||||
|
||||
//32 bits
|
||||
self::$_map['(ucs-?4|utf-?32)'] = $fourBytes;
|
||||
|
||||
// Fallback
|
||||
self::$_map['.*'] = $singleByte;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a CharacterReader suitable for the charset applied.
|
||||
*
|
||||
* @param string $charset
|
||||
*
|
||||
* @return Swift_CharacterReader
|
||||
*/
|
||||
public function getReaderFor($charset)
|
||||
{
|
||||
$charset = trim(strtolower($charset));
|
||||
foreach (self::$_map as $pattern => $spec) {
|
||||
$re = '/^' . $pattern . '$/D';
|
||||
if (preg_match($re, $charset)) {
|
||||
if (!array_key_exists($pattern, self::$_loaded)) {
|
||||
$reflector = new ReflectionClass($spec['class']);
|
||||
if ($reflector->getConstructor()) {
|
||||
$reader = $reflector->newInstanceArgs($spec['constructor']);
|
||||
} else {
|
||||
$reader = $reflector->newInstance();
|
||||
}
|
||||
self::$_loaded[$pattern] = $reader;
|
||||
}
|
||||
|
||||
return self::$_loaded[$pattern];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* An abstract means of reading and writing data in terms of characters as opposed
|
||||
* to bytes.
|
||||
*
|
||||
* Classes implementing this interface may use a subsystem which requires less
|
||||
* memory than working with large strings of data.
|
||||
*
|
||||
* @author Chris Corbyn
|
||||
*/
|
||||
interface Swift_CharacterStream
|
||||
{
|
||||
/**
|
||||
* Set the character set used in this CharacterStream.
|
||||
*
|
||||
* @param string $charset
|
||||
*/
|
||||
public function setCharacterSet($charset);
|
||||
|
||||
/**
|
||||
* Set the CharacterReaderFactory for multi charset support.
|
||||
*
|
||||
* @param Swift_CharacterReaderFactory $factory
|
||||
*/
|
||||
public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory);
|
||||
|
||||
/**
|
||||
* Overwrite this character stream using the byte sequence in the byte stream.
|
||||
*
|
||||
* @param Swift_OutputByteStream $os output stream to read from
|
||||
*/
|
||||
public function importByteStream(Swift_OutputByteStream $os);
|
||||
|
||||
/**
|
||||
* Import a string a bytes into this CharacterStream, overwriting any existing
|
||||
* data in the stream.
|
||||
*
|
||||
* @param string $string
|
||||
*/
|
||||
public function importString($string);
|
||||
|
||||
/**
|
||||
* Read $length characters from the stream and move the internal pointer
|
||||
* $length further into the stream.
|
||||
*
|
||||
* @param int $length
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function read($length);
|
||||
|
||||
/**
|
||||
* Read $length characters from the stream and return a 1-dimensional array
|
||||
* containing there octet values.
|
||||
*
|
||||
* @param int $length
|
||||
*
|
||||
* @return int[]
|
||||
*/
|
||||
public function readBytes($length);
|
||||
|
||||
/**
|
||||
* Write $chars to the end of the stream.
|
||||
*
|
||||
* @param string $chars
|
||||
*/
|
||||
public function write($chars);
|
||||
|
||||
/**
|
||||
* Move the internal pointer to $charOffset in the stream.
|
||||
*
|
||||
* @param int $charOffset
|
||||
*/
|
||||
public function setPointer($charOffset);
|
||||
|
||||
/**
|
||||
* Empty the stream and reset the internal pointer.
|
||||
*/
|
||||
public function flushContents();
|
||||
}
|
||||
|
|
@ -0,0 +1,294 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A CharacterStream implementation which stores characters in an internal array.
|
||||
*
|
||||
* @author Chris Corbyn
|
||||
*/
|
||||
class Swift_CharacterStream_ArrayCharacterStream implements Swift_CharacterStream
|
||||
{
|
||||
/** A map of byte values and their respective characters */
|
||||
private static $_charMap;
|
||||
|
||||
/** A map of characters and their derivative byte values */
|
||||
private static $_byteMap;
|
||||
|
||||
/** The char reader (lazy-loaded) for the current charset */
|
||||
private $_charReader;
|
||||
|
||||
/** A factory for creating CharacterReader instances */
|
||||
private $_charReaderFactory;
|
||||
|
||||
/** The character set this stream is using */
|
||||
private $_charset;
|
||||
|
||||
/** Array of characters */
|
||||
private $_array = array();
|
||||
|
||||
/** Size of the array of character */
|
||||
private $_array_size = array();
|
||||
|
||||
/** The current character offset in the stream */
|
||||
private $_offset = 0;
|
||||
|
||||
/**
|
||||
* Create a new CharacterStream with the given $chars, if set.
|
||||
*
|
||||
* @param Swift_CharacterReaderFactory $factory for loading validators
|
||||
* @param string $charset used in the stream
|
||||
*/
|
||||
public function __construct(Swift_CharacterReaderFactory $factory, $charset)
|
||||
{
|
||||
self::_initializeMaps();
|
||||
$this->setCharacterReaderFactory($factory);
|
||||
$this->setCharacterSet($charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the character set used in this CharacterStream.
|
||||
*
|
||||
* @param string $charset
|
||||
*/
|
||||
public function setCharacterSet($charset)
|
||||
{
|
||||
$this->_charset = $charset;
|
||||
$this->_charReader = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the CharacterReaderFactory for multi charset support.
|
||||
*
|
||||
* @param Swift_CharacterReaderFactory $factory
|
||||
*/
|
||||
public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory)
|
||||
{
|
||||
$this->_charReaderFactory = $factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrite this character stream using the byte sequence in the byte stream.
|
||||
*
|
||||
* @param Swift_OutputByteStream $os output stream to read from
|
||||
*/
|
||||
public function importByteStream(Swift_OutputByteStream $os)
|
||||
{
|
||||
if (!isset($this->_charReader)) {
|
||||
$this->_charReader = $this->_charReaderFactory
|
||||
->getReaderFor($this->_charset);
|
||||
}
|
||||
|
||||
$startLength = $this->_charReader->getInitialByteSize();
|
||||
while (false !== $bytes = $os->read($startLength)) {
|
||||
$c = array();
|
||||
for ($i = 0, $len = strlen($bytes); $i < $len; ++$i) {
|
||||
$c[] = self::$_byteMap[$bytes[$i]];
|
||||
}
|
||||
$size = count($c);
|
||||
$need = $this->_charReader
|
||||
->validateByteSequence($c, $size);
|
||||
if ($need > 0 &&
|
||||
false !== $bytes = $os->read($need))
|
||||
{
|
||||
for ($i = 0, $len = strlen($bytes); $i < $len; ++$i) {
|
||||
$c[] = self::$_byteMap[$bytes[$i]];
|
||||
}
|
||||
}
|
||||
$this->_array[] = $c;
|
||||
++$this->_array_size;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Import a string a bytes into this CharacterStream, overwriting any existing
|
||||
* data in the stream.
|
||||
*
|
||||
* @param string $string
|
||||
*/
|
||||
public function importString($string)
|
||||
{
|
||||
$this->flushContents();
|
||||
$this->write($string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read $length characters from the stream and move the internal pointer
|
||||
* $length further into the stream.
|
||||
*
|
||||
* @param int $length
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function read($length)
|
||||
{
|
||||
if ($this->_offset == $this->_array_size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't use array slice
|
||||
$arrays = array();
|
||||
$end = $length + $this->_offset;
|
||||
for ($i = $this->_offset; $i < $end; ++$i) {
|
||||
if (!isset($this->_array[$i])) {
|
||||
break;
|
||||
}
|
||||
$arrays[] = $this->_array[$i];
|
||||
}
|
||||
$this->_offset += $i - $this->_offset; // Limit function calls
|
||||
$chars = false;
|
||||
foreach ($arrays as $array) {
|
||||
$chars .= implode('', array_map('chr', $array));
|
||||
}
|
||||
|
||||
return $chars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read $length characters from the stream and return a 1-dimensional array
|
||||
* containing there octet values.
|
||||
*
|
||||
* @param int $length
|
||||
*
|
||||
* @return integer[]
|
||||
*/
|
||||
public function readBytes($length)
|
||||
{
|
||||
if ($this->_offset == $this->_array_size) {
|
||||
return false;
|
||||
}
|
||||
$arrays = array();
|
||||
$end = $length + $this->_offset;
|
||||
for ($i = $this->_offset; $i < $end; ++$i) {
|
||||
if (!isset($this->_array[$i])) {
|
||||
break;
|
||||
}
|
||||
$arrays[] = $this->_array[$i];
|
||||
}
|
||||
$this->_offset += ($i - $this->_offset); // Limit function calls
|
||||
|
||||
return call_user_func_array('array_merge', $arrays);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write $chars to the end of the stream.
|
||||
*
|
||||
* @param string $chars
|
||||
*/
|
||||
public function write($chars)
|
||||
{
|
||||
if (!isset($this->_charReader)) {
|
||||
$this->_charReader = $this->_charReaderFactory->getReaderFor(
|
||||
$this->_charset);
|
||||
}
|
||||
|
||||
$startLength = $this->_charReader->getInitialByteSize();
|
||||
|
||||
$fp = fopen('php://memory', 'w+b');
|
||||
fwrite($fp, $chars);
|
||||
unset($chars);
|
||||
fseek($fp, 0, SEEK_SET);
|
||||
|
||||
$buffer = array(0);
|
||||
$buf_pos = 1;
|
||||
$buf_len = 1;
|
||||
$has_datas = true;
|
||||
do {
|
||||
$bytes = array();
|
||||
// Buffer Filing
|
||||
if ($buf_len - $buf_pos < $startLength) {
|
||||
$buf = array_splice($buffer, $buf_pos);
|
||||
$new = $this->_reloadBuffer($fp, 100);
|
||||
if ($new) {
|
||||
$buffer = array_merge($buf, $new);
|
||||
$buf_len = count($buffer);
|
||||
$buf_pos = 0;
|
||||
} else {
|
||||
$has_datas = false;
|
||||
}
|
||||
}
|
||||
if ($buf_len - $buf_pos > 0) {
|
||||
$size = 0;
|
||||
for ($i = 0; $i < $startLength && isset($buffer[$buf_pos]); ++$i) {
|
||||
++$size;
|
||||
$bytes[] = $buffer[$buf_pos++];
|
||||
}
|
||||
$need = $this->_charReader->validateByteSequence(
|
||||
$bytes, $size);
|
||||
if ($need > 0) {
|
||||
if ($buf_len - $buf_pos < $need) {
|
||||
$new = $this->_reloadBuffer($fp, $need);
|
||||
|
||||
if ($new) {
|
||||
$buffer = array_merge($buffer, $new);
|
||||
$buf_len = count($buffer);
|
||||
}
|
||||
}
|
||||
for ($i = 0; $i < $need && isset($buffer[$buf_pos]); ++$i) {
|
||||
$bytes[] = $buffer[$buf_pos++];
|
||||
}
|
||||
}
|
||||
$this->_array[] = $bytes;
|
||||
++$this->_array_size;
|
||||
}
|
||||
} while ($has_datas);
|
||||
|
||||
fclose($fp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the internal pointer to $charOffset in the stream.
|
||||
*
|
||||
* @param int $charOffset
|
||||
*/
|
||||
public function setPointer($charOffset)
|
||||
{
|
||||
if ($charOffset > $this->_array_size) {
|
||||
$charOffset = $this->_array_size;
|
||||
} elseif ($charOffset < 0) {
|
||||
$charOffset = 0;
|
||||
}
|
||||
$this->_offset = $charOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty the stream and reset the internal pointer.
|
||||
*/
|
||||
public function flushContents()
|
||||
{
|
||||
$this->_offset = 0;
|
||||
$this->_array = array();
|
||||
$this->_array_size = 0;
|
||||
}
|
||||
|
||||
private function _reloadBuffer($fp, $len)
|
||||
{
|
||||
if (!feof($fp) && ($bytes = fread($fp, $len)) !== false) {
|
||||
$buf = array();
|
||||
for ($i = 0, $len = strlen($bytes); $i < $len; ++$i) {
|
||||
$buf[] = self::$_byteMap[$bytes[$i]];
|
||||
}
|
||||
|
||||
return $buf;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static function _initializeMaps()
|
||||
{
|
||||
if (!isset(self::$_charMap)) {
|
||||
self::$_charMap = array();
|
||||
for ($byte = 0; $byte < 256; ++$byte) {
|
||||
self::$_charMap[$byte] = chr($byte);
|
||||
}
|
||||
self::$_byteMap = array_flip(self::$_charMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,275 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A CharacterStream implementation which stores characters in an internal array.
|
||||
*
|
||||
* @author Xavier De Cock <xdecock@gmail.com>
|
||||
*/
|
||||
|
||||
class Swift_CharacterStream_NgCharacterStream implements Swift_CharacterStream
|
||||
{
|
||||
/**
|
||||
* The char reader (lazy-loaded) for the current charset.
|
||||
*
|
||||
* @var Swift_CharacterReader
|
||||
*/
|
||||
private $_charReader;
|
||||
|
||||
/**
|
||||
* A factory for creating CharacterReader instances.
|
||||
*
|
||||
* @var Swift_CharacterReaderFactory
|
||||
*/
|
||||
private $_charReaderFactory;
|
||||
|
||||
/**
|
||||
* The character set this stream is using.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $_charset;
|
||||
|
||||
/**
|
||||
* The data's stored as-is.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $_datas = '';
|
||||
|
||||
/**
|
||||
* Number of bytes in the stream
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $_datasSize = 0;
|
||||
|
||||
/**
|
||||
* Map.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
private $_map;
|
||||
|
||||
/**
|
||||
* Map Type.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $_mapType = 0;
|
||||
|
||||
/**
|
||||
* Number of characters in the stream.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $_charCount = 0;
|
||||
|
||||
/**
|
||||
* Position in the stream.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $_currentPos = 0;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Swift_CharacterReaderFactory $factory
|
||||
* @param string $charset
|
||||
*/
|
||||
public function __construct(Swift_CharacterReaderFactory $factory, $charset)
|
||||
{
|
||||
$this->setCharacterReaderFactory($factory);
|
||||
$this->setCharacterSet($charset);
|
||||
}
|
||||
|
||||
/* -- Changing parameters of the stream -- */
|
||||
|
||||
/**
|
||||
* Set the character set used in this CharacterStream.
|
||||
*
|
||||
* @param string $charset
|
||||
*/
|
||||
public function setCharacterSet($charset)
|
||||
{
|
||||
$this->_charset = $charset;
|
||||
$this->_charReader = null;
|
||||
$this->_mapType = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the CharacterReaderFactory for multi charset support.
|
||||
*
|
||||
* @param Swift_CharacterReaderFactory $factory
|
||||
*/
|
||||
public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory)
|
||||
{
|
||||
$this->_charReaderFactory = $factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Swift_CharacterStream::flushContents()
|
||||
*/
|
||||
public function flushContents()
|
||||
{
|
||||
$this->_datas = null;
|
||||
$this->_map = null;
|
||||
$this->_charCount = 0;
|
||||
$this->_currentPos = 0;
|
||||
$this->_datasSize = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Swift_CharacterStream::importByteStream()
|
||||
*
|
||||
* @param Swift_OutputByteStream $os
|
||||
*/
|
||||
public function importByteStream(Swift_OutputByteStream $os)
|
||||
{
|
||||
$this->flushContents();
|
||||
$blocks=512;
|
||||
$os->setReadPointer(0);
|
||||
while(false!==($read = $os->read($blocks)))
|
||||
$this->write($read);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Swift_CharacterStream::importString()
|
||||
*
|
||||
* @param string $string
|
||||
*/
|
||||
public function importString($string)
|
||||
{
|
||||
$this->flushContents();
|
||||
$this->write($string);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Swift_CharacterStream::read()
|
||||
*
|
||||
* @param int $length
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function read($length)
|
||||
{
|
||||
if ($this->_currentPos>=$this->_charCount) {
|
||||
return false;
|
||||
}
|
||||
$ret=false;
|
||||
$length = ($this->_currentPos+$length > $this->_charCount)
|
||||
? $this->_charCount - $this->_currentPos
|
||||
: $length;
|
||||
switch ($this->_mapType) {
|
||||
case Swift_CharacterReader::MAP_TYPE_FIXED_LEN:
|
||||
$len = $length*$this->_map;
|
||||
$ret = substr($this->_datas,
|
||||
$this->_currentPos * $this->_map,
|
||||
$len);
|
||||
$this->_currentPos += $length;
|
||||
break;
|
||||
|
||||
case Swift_CharacterReader::MAP_TYPE_INVALID:
|
||||
$end = $this->_currentPos + $length;
|
||||
$end = $end > $this->_charCount
|
||||
?$this->_charCount
|
||||
:$end;
|
||||
$ret = '';
|
||||
for (; $this->_currentPos < $length; ++$this->_currentPos) {
|
||||
if (isset ($this->_map[$this->_currentPos])) {
|
||||
$ret .= '?';
|
||||
} else {
|
||||
$ret .= $this->_datas[$this->_currentPos];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Swift_CharacterReader::MAP_TYPE_POSITIONS:
|
||||
$end = $this->_currentPos + $length;
|
||||
$end = $end > $this->_charCount
|
||||
?$this->_charCount
|
||||
:$end;
|
||||
$ret = '';
|
||||
$start = 0;
|
||||
if ($this->_currentPos>0) {
|
||||
$start = $this->_map['p'][$this->_currentPos-1];
|
||||
}
|
||||
$to = $start;
|
||||
for (; $this->_currentPos < $end; ++$this->_currentPos) {
|
||||
if (isset($this->_map['i'][$this->_currentPos])) {
|
||||
$ret .= substr($this->_datas, $start, $to - $start).'?';
|
||||
$start = $this->_map['p'][$this->_currentPos];
|
||||
} else {
|
||||
$to = $this->_map['p'][$this->_currentPos];
|
||||
}
|
||||
}
|
||||
$ret .= substr($this->_datas, $start, $to - $start);
|
||||
break;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Swift_CharacterStream::readBytes()
|
||||
*
|
||||
* @param int $length
|
||||
*
|
||||
* @return integer[]
|
||||
*/
|
||||
public function readBytes($length)
|
||||
{
|
||||
$read=$this->read($length);
|
||||
if ($read!==false) {
|
||||
$ret = array_map('ord', str_split($read, 1));
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Swift_CharacterStream::setPointer()
|
||||
*
|
||||
* @param int $charOffset
|
||||
*/
|
||||
public function setPointer($charOffset)
|
||||
{
|
||||
if ($this->_charCount<$charOffset) {
|
||||
$charOffset=$this->_charCount;
|
||||
}
|
||||
$this->_currentPos = $charOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Swift_CharacterStream::write()
|
||||
*
|
||||
* @param string $chars
|
||||
*/
|
||||
public function write($chars)
|
||||
{
|
||||
if (!isset($this->_charReader)) {
|
||||
$this->_charReader = $this->_charReaderFactory->getReaderFor(
|
||||
$this->_charset);
|
||||
$this->_map = array();
|
||||
$this->_mapType = $this->_charReader->getMapType();
|
||||
}
|
||||
$ignored='';
|
||||
$this->_datas .= $chars;
|
||||
$this->_charCount += $this->_charReader->getCharPositions(substr($this->_datas, $this->_datasSize), $this->_datasSize, $this->_map, $ignored);
|
||||
if ($ignored!==false) {
|
||||
$this->_datasSize=strlen($this->_datas)-strlen($ignored);
|
||||
} else {
|
||||
$this->_datasSize=strlen($this->_datas);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2009 Fabien Potencier <fabien.potencier@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Base class for Spools (implements time and message limits).
|
||||
*
|
||||
* @author Fabien Potencier
|
||||
*/
|
||||
abstract class Swift_ConfigurableSpool implements Swift_Spool
|
||||
{
|
||||
/** The maximum number of messages to send per flush */
|
||||
private $_message_limit;
|
||||
|
||||
/** The time limit per flush */
|
||||
private $_time_limit;
|
||||
|
||||
/**
|
||||
* Sets the maximum number of messages to send per flush.
|
||||
*
|
||||
* @param int $limit
|
||||
*/
|
||||
public function setMessageLimit($limit)
|
||||
{
|
||||
$this->_message_limit = (int) $limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the maximum number of messages to send per flush.
|
||||
*
|
||||
* @return int The limit
|
||||
*/
|
||||
public function getMessageLimit()
|
||||
{
|
||||
return $this->_message_limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the time limit (in seconds) per flush.
|
||||
*
|
||||
* @param int $limit The limit
|
||||
*/
|
||||
public function setTimeLimit($limit)
|
||||
{
|
||||
$this->_time_limit = (int) $limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the time limit (in seconds) per flush.
|
||||
*
|
||||
* @return int The limit
|
||||
*/
|
||||
public function getTimeLimit()
|
||||
{
|
||||
return $this->_time_limit;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,370 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Dependency Injection container.
|
||||
*
|
||||
* @author Chris Corbyn
|
||||
*/
|
||||
class Swift_DependencyContainer
|
||||
{
|
||||
/** Constant for literal value types */
|
||||
const TYPE_VALUE = 0x0001;
|
||||
|
||||
/** Constant for new instance types */
|
||||
const TYPE_INSTANCE = 0x0010;
|
||||
|
||||
/** Constant for shared instance types */
|
||||
const TYPE_SHARED = 0x0100;
|
||||
|
||||
/** Constant for aliases */
|
||||
const TYPE_ALIAS = 0x1000;
|
||||
|
||||
/** Singleton instance */
|
||||
private static $_instance = null;
|
||||
|
||||
/** The data container */
|
||||
private $_store = array();
|
||||
|
||||
/** The current endpoint in the data container */
|
||||
private $_endPoint;
|
||||
|
||||
/**
|
||||
* Constructor should not be used.
|
||||
*
|
||||
* Use {@link getInstance()} instead.
|
||||
*/
|
||||
public function __construct() { }
|
||||
|
||||
/**
|
||||
* Returns a singleton of the DependencyContainer.
|
||||
*
|
||||
* @return Swift_DependencyContainer
|
||||
*/
|
||||
public static function getInstance()
|
||||
{
|
||||
if (!isset(self::$_instance)) {
|
||||
self::$_instance = new self();
|
||||
}
|
||||
|
||||
return self::$_instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* List the names of all items stored in the Container.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function listItems()
|
||||
{
|
||||
return array_keys($this->_store);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if an item is registered in this container with the given name.
|
||||
*
|
||||
* @see register()
|
||||
*
|
||||
* @param string $itemName
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function has($itemName)
|
||||
{
|
||||
return array_key_exists($itemName, $this->_store)
|
||||
&& isset($this->_store[$itemName]['lookupType']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup the item with the given $itemName.
|
||||
*
|
||||
* @see register()
|
||||
*
|
||||
* @param string $itemName
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws Swift_DependencyException If the dependency is not found
|
||||
*/
|
||||
public function lookup($itemName)
|
||||
{
|
||||
if (!$this->has($itemName)) {
|
||||
throw new Swift_DependencyException(
|
||||
'Cannot lookup dependency "' . $itemName . '" since it is not registered.'
|
||||
);
|
||||
}
|
||||
|
||||
switch ($this->_store[$itemName]['lookupType']) {
|
||||
case self::TYPE_ALIAS:
|
||||
return $this->_createAlias($itemName);
|
||||
case self::TYPE_VALUE:
|
||||
return $this->_getValue($itemName);
|
||||
case self::TYPE_INSTANCE:
|
||||
return $this->_createNewInstance($itemName);
|
||||
case self::TYPE_SHARED:
|
||||
return $this->_createSharedInstance($itemName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an array of arguments passed to the constructor of $itemName.
|
||||
*
|
||||
* @param string $itemName
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function createDependenciesFor($itemName)
|
||||
{
|
||||
$args = array();
|
||||
if (isset($this->_store[$itemName]['args'])) {
|
||||
$args = $this->_resolveArgs($this->_store[$itemName]['args']);
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new dependency with $itemName.
|
||||
*
|
||||
* This method returns the current DependencyContainer instance because it
|
||||
* requires the use of the fluid interface to set the specific details for the
|
||||
* dependency.
|
||||
* @see asNewInstanceOf(), asSharedInstanceOf(), asValue()
|
||||
*
|
||||
* @param string $itemName
|
||||
*
|
||||
* @return Swift_DependencyContainer
|
||||
*/
|
||||
public function register($itemName)
|
||||
{
|
||||
$this->_store[$itemName] = array();
|
||||
$this->_endPoint =& $this->_store[$itemName];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the previously registered item as a literal value.
|
||||
*
|
||||
* {@link register()} must be called before this will work.
|
||||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return Swift_DependencyContainer
|
||||
*/
|
||||
public function asValue($value)
|
||||
{
|
||||
$endPoint =& $this->_getEndPoint();
|
||||
$endPoint['lookupType'] = self::TYPE_VALUE;
|
||||
$endPoint['value'] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the previously registered item as an alias of another item.
|
||||
*
|
||||
* @param string $lookup
|
||||
*
|
||||
* @return Swift_DependencyContainer
|
||||
*/
|
||||
public function asAliasOf($lookup)
|
||||
{
|
||||
$endPoint =& $this->_getEndPoint();
|
||||
$endPoint['lookupType'] = self::TYPE_ALIAS;
|
||||
$endPoint['ref'] = $lookup;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the previously registered item as a new instance of $className.
|
||||
*
|
||||
* {@link register()} must be called before this will work.
|
||||
* Any arguments can be set with {@link withDependencies()},
|
||||
* {@link addConstructorValue()} or {@link addConstructorLookup()}.
|
||||
*
|
||||
* @see withDependencies(), addConstructorValue(), addConstructorLookup()
|
||||
*
|
||||
* @param string $className
|
||||
*
|
||||
* @return Swift_DependencyContainer
|
||||
*/
|
||||
public function asNewInstanceOf($className)
|
||||
{
|
||||
$endPoint =& $this->_getEndPoint();
|
||||
$endPoint['lookupType'] = self::TYPE_INSTANCE;
|
||||
$endPoint['className'] = $className;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the previously registered item as a shared instance of $className.
|
||||
*
|
||||
* {@link register()} must be called before this will work.
|
||||
*
|
||||
* @param string $className
|
||||
*
|
||||
* @return Swift_DependencyContainer
|
||||
*/
|
||||
public function asSharedInstanceOf($className)
|
||||
{
|
||||
$endPoint =& $this->_getEndPoint();
|
||||
$endPoint['lookupType'] = self::TYPE_SHARED;
|
||||
$endPoint['className'] = $className;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a list of injected dependencies for the previously registered item.
|
||||
*
|
||||
* This method takes an array of lookup names.
|
||||
*
|
||||
* @see addConstructorValue(), addConstructorLookup()
|
||||
*
|
||||
* @param array $lookups
|
||||
*
|
||||
* @return Swift_DependencyContainer
|
||||
*/
|
||||
public function withDependencies(array $lookups)
|
||||
{
|
||||
$endPoint =& $this->_getEndPoint();
|
||||
$endPoint['args'] = array();
|
||||
foreach ($lookups as $lookup) {
|
||||
$this->addConstructorLookup($lookup);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a literal (non looked up) value for the constructor of the
|
||||
* previously registered item.
|
||||
*
|
||||
* @see withDependencies(), addConstructorLookup()
|
||||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return Swift_DependencyContainer
|
||||
*/
|
||||
public function addConstructorValue($value)
|
||||
{
|
||||
$endPoint =& $this->_getEndPoint();
|
||||
if (!isset($endPoint['args'])) {
|
||||
$endPoint['args'] = array();
|
||||
}
|
||||
$endPoint['args'][] = array('type' => 'value', 'item' => $value);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a dependency lookup for the constructor of the previously
|
||||
* registered item.
|
||||
*
|
||||
* @see withDependencies(), addConstructorValue()
|
||||
*
|
||||
* @param string $lookup
|
||||
*
|
||||
* @return Swift_DependencyContainer
|
||||
*/
|
||||
public function addConstructorLookup($lookup)
|
||||
{
|
||||
$endPoint =& $this->_getEndPoint();
|
||||
if (!isset($this->_endPoint['args'])) {
|
||||
$endPoint['args'] = array();
|
||||
}
|
||||
$endPoint['args'][] = array('type' => 'lookup', 'item' => $lookup);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** Get the literal value with $itemName */
|
||||
private function _getValue($itemName)
|
||||
{
|
||||
return $this->_store[$itemName]['value'];
|
||||
}
|
||||
|
||||
/** Resolve an alias to another item */
|
||||
private function _createAlias($itemName)
|
||||
{
|
||||
return $this->lookup($this->_store[$itemName]['ref']);
|
||||
}
|
||||
|
||||
/** Create a fresh instance of $itemName */
|
||||
private function _createNewInstance($itemName)
|
||||
{
|
||||
$reflector = new ReflectionClass($this->_store[$itemName]['className']);
|
||||
if ($reflector->getConstructor()) {
|
||||
return $reflector->newInstanceArgs(
|
||||
$this->createDependenciesFor($itemName)
|
||||
);
|
||||
} else {
|
||||
return $reflector->newInstance();
|
||||
}
|
||||
}
|
||||
|
||||
/** Create and register a shared instance of $itemName */
|
||||
private function _createSharedInstance($itemName)
|
||||
{
|
||||
if (!isset($this->_store[$itemName]['instance'])) {
|
||||
$this->_store[$itemName]['instance'] = $this->_createNewInstance($itemName);
|
||||
}
|
||||
|
||||
return $this->_store[$itemName]['instance'];
|
||||
}
|
||||
|
||||
/** Get the current endpoint in the store */
|
||||
private function &_getEndPoint()
|
||||
{
|
||||
if (!isset($this->_endPoint)) {
|
||||
throw new BadMethodCallException(
|
||||
'Component must first be registered by calling register()'
|
||||
);
|
||||
}
|
||||
|
||||
return $this->_endPoint;
|
||||
}
|
||||
|
||||
/** Get an argument list with dependencies resolved */
|
||||
private function _resolveArgs(array $args)
|
||||
{
|
||||
$resolved = array();
|
||||
foreach ($args as $argDefinition) {
|
||||
switch ($argDefinition['type']) {
|
||||
case 'lookup':
|
||||
$resolved[] = $this->_lookupRecursive($argDefinition['item']);
|
||||
break;
|
||||
case 'value':
|
||||
$resolved[] = $argDefinition['item'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $resolved;
|
||||
}
|
||||
|
||||
/** Resolve a single dependency with an collections */
|
||||
private function _lookupRecursive($item)
|
||||
{
|
||||
if (is_array($item)) {
|
||||
$collection = array();
|
||||
foreach ($item as $k => $v) {
|
||||
$collection[$k] = $this->_lookupRecursive($v);
|
||||
}
|
||||
|
||||
return $collection;
|
||||
} else {
|
||||
return $this->lookup($item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* DependencyException gets thrown when a requested dependency is missing.
|
||||
*
|
||||
* @author Chris Corbyn
|
||||
*/
|
||||
class Swift_DependencyException extends Swift_SwiftException
|
||||
{
|
||||
/**
|
||||
* Create a new DependencyException with $message.
|
||||
*
|
||||
* @param string $message
|
||||
*/
|
||||
public function __construct($message)
|
||||
{
|
||||
parent::__construct($message);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* An embedded file, in a multipart message.
|
||||
*
|
||||
* @author Chris Corbyn
|
||||
*/
|
||||
class Swift_EmbeddedFile extends Swift_Mime_EmbeddedFile
|
||||
{
|
||||
/**
|
||||
* Create a new EmbeddedFile.
|
||||
*
|
||||
* Details may be optionally provided to the constructor.
|
||||
*
|
||||
* @param string|Swift_OutputByteStream $data
|
||||
* @param string $filename
|
||||
* @param string $contentType
|
||||
*/
|
||||
public function __construct($data = null, $filename = null, $contentType = null)
|
||||
{
|
||||
call_user_func_array(
|
||||
array($this, 'Swift_Mime_EmbeddedFile::__construct'),
|
||||
Swift_DependencyContainer::getInstance()
|
||||
->createDependenciesFor('mime.embeddedfile')
|
||||
);
|
||||
|
||||
$this->setBody($data);
|
||||
$this->setFilename($filename);
|
||||
if ($contentType) {
|
||||
$this->setContentType($contentType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new EmbeddedFile.
|
||||
*
|
||||
* @param string|Swift_OutputByteStream $data
|
||||
* @param string $filename
|
||||
* @param string $contentType
|
||||
*
|
||||
* @return Swift_Mime_EmbeddedFile
|
||||
*/
|
||||
public static function newInstance($data = null, $filename = null, $contentType = null)
|
||||
{
|
||||
return new self($data, $filename, $contentType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new EmbeddedFile from a filesystem path.
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @return Swift_Mime_EmbeddedFile
|
||||
*/
|
||||
public static function fromPath($path)
|
||||
{
|
||||
return self::newInstance()->setFile(
|
||||
new Swift_ByteStream_FileByteStream($path)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Interface for all Encoder schemes.
|
||||
* @author Chris Corbyn
|
||||
*/
|
||||
interface Swift_Encoder extends Swift_Mime_CharsetObserver
|
||||
{
|
||||
/**
|
||||
* Encode a given string to produce an encoded string.
|
||||
*
|
||||
* @param string $string
|
||||
* @param int $firstLineOffset if first line needs to be shorter
|
||||
* @param int $maxLineLength - 0 indicates the default length for this encoding
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0);
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Handles Base 64 Encoding in Swift Mailer.
|
||||
*
|
||||
* @author Chris Corbyn
|
||||
*/
|
||||
class Swift_Encoder_Base64Encoder implements Swift_Encoder
|
||||
{
|
||||
/**
|
||||
* Takes an unencoded string and produces a Base64 encoded string from it.
|
||||
*
|
||||
* Base64 encoded strings have a maximum line length of 76 characters.
|
||||
* If the first line needs to be shorter, indicate the difference with
|
||||
* $firstLineOffset.
|
||||
*
|
||||
* @param string $string to encode
|
||||
* @param int $firstLineOffset
|
||||
* @param int $maxLineLength optional, 0 indicates the default of 76 bytes
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0)
|
||||
{
|
||||
if (0 >= $maxLineLength || 76 < $maxLineLength) {
|
||||
$maxLineLength = 76;
|
||||
}
|
||||
|
||||
$encodedString = base64_encode($string);
|
||||
$firstLine = '';
|
||||
|
||||
if (0 != $firstLineOffset) {
|
||||
$firstLine = substr(
|
||||
$encodedString, 0, $maxLineLength - $firstLineOffset
|
||||
) . "\r\n";
|
||||
$encodedString = substr(
|
||||
$encodedString, $maxLineLength - $firstLineOffset
|
||||
);
|
||||
}
|
||||
|
||||
return $firstLine . trim(chunk_split($encodedString, $maxLineLength, "\r\n"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Does nothing.
|
||||
*/
|
||||
public function charsetChanged($charset)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,282 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Handles Quoted Printable (QP) Encoding in Swift Mailer.
|
||||
*
|
||||
* Possibly the most accurate RFC 2045 QP implementation found in PHP.
|
||||
*
|
||||
* @author Chris Corbyn
|
||||
*/
|
||||
class Swift_Encoder_QpEncoder implements Swift_Encoder
|
||||
{
|
||||
/**
|
||||
* The CharacterStream used for reading characters (as opposed to bytes).
|
||||
*
|
||||
* @var Swift_CharacterStream
|
||||
*/
|
||||
protected $_charStream;
|
||||
|
||||
/**
|
||||
* A filter used if input should be canonicalized.
|
||||
*
|
||||
* @var Swift_StreamFilter
|
||||
*/
|
||||
protected $_filter;
|
||||
|
||||
/**
|
||||
* Pre-computed QP for HUGE optimization.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected static $_qpMap = array(
|
||||
0 => '=00', 1 => '=01', 2 => '=02', 3 => '=03', 4 => '=04',
|
||||
5 => '=05', 6 => '=06', 7 => '=07', 8 => '=08', 9 => '=09',
|
||||
10 => '=0A', 11 => '=0B', 12 => '=0C', 13 => '=0D', 14 => '=0E',
|
||||
15 => '=0F', 16 => '=10', 17 => '=11', 18 => '=12', 19 => '=13',
|
||||
20 => '=14', 21 => '=15', 22 => '=16', 23 => '=17', 24 => '=18',
|
||||
25 => '=19', 26 => '=1A', 27 => '=1B', 28 => '=1C', 29 => '=1D',
|
||||
30 => '=1E', 31 => '=1F', 32 => '=20', 33 => '=21', 34 => '=22',
|
||||
35 => '=23', 36 => '=24', 37 => '=25', 38 => '=26', 39 => '=27',
|
||||
40 => '=28', 41 => '=29', 42 => '=2A', 43 => '=2B', 44 => '=2C',
|
||||
45 => '=2D', 46 => '=2E', 47 => '=2F', 48 => '=30', 49 => '=31',
|
||||
50 => '=32', 51 => '=33', 52 => '=34', 53 => '=35', 54 => '=36',
|
||||
55 => '=37', 56 => '=38', 57 => '=39', 58 => '=3A', 59 => '=3B',
|
||||
60 => '=3C', 61 => '=3D', 62 => '=3E', 63 => '=3F', 64 => '=40',
|
||||
65 => '=41', 66 => '=42', 67 => '=43', 68 => '=44', 69 => '=45',
|
||||
70 => '=46', 71 => '=47', 72 => '=48', 73 => '=49', 74 => '=4A',
|
||||
75 => '=4B', 76 => '=4C', 77 => '=4D', 78 => '=4E', 79 => '=4F',
|
||||
80 => '=50', 81 => '=51', 82 => '=52', 83 => '=53', 84 => '=54',
|
||||
85 => '=55', 86 => '=56', 87 => '=57', 88 => '=58', 89 => '=59',
|
||||
90 => '=5A', 91 => '=5B', 92 => '=5C', 93 => '=5D', 94 => '=5E',
|
||||
95 => '=5F', 96 => '=60', 97 => '=61', 98 => '=62', 99 => '=63',
|
||||
100 => '=64', 101 => '=65', 102 => '=66', 103 => '=67', 104 => '=68',
|
||||
105 => '=69', 106 => '=6A', 107 => '=6B', 108 => '=6C', 109 => '=6D',
|
||||
110 => '=6E', 111 => '=6F', 112 => '=70', 113 => '=71', 114 => '=72',
|
||||
115 => '=73', 116 => '=74', 117 => '=75', 118 => '=76', 119 => '=77',
|
||||
120 => '=78', 121 => '=79', 122 => '=7A', 123 => '=7B', 124 => '=7C',
|
||||
125 => '=7D', 126 => '=7E', 127 => '=7F', 128 => '=80', 129 => '=81',
|
||||
130 => '=82', 131 => '=83', 132 => '=84', 133 => '=85', 134 => '=86',
|
||||
135 => '=87', 136 => '=88', 137 => '=89', 138 => '=8A', 139 => '=8B',
|
||||
140 => '=8C', 141 => '=8D', 142 => '=8E', 143 => '=8F', 144 => '=90',
|
||||
145 => '=91', 146 => '=92', 147 => '=93', 148 => '=94', 149 => '=95',
|
||||
150 => '=96', 151 => '=97', 152 => '=98', 153 => '=99', 154 => '=9A',
|
||||
155 => '=9B', 156 => '=9C', 157 => '=9D', 158 => '=9E', 159 => '=9F',
|
||||
160 => '=A0', 161 => '=A1', 162 => '=A2', 163 => '=A3', 164 => '=A4',
|
||||
165 => '=A5', 166 => '=A6', 167 => '=A7', 168 => '=A8', 169 => '=A9',
|
||||
170 => '=AA', 171 => '=AB', 172 => '=AC', 173 => '=AD', 174 => '=AE',
|
||||
175 => '=AF', 176 => '=B0', 177 => '=B1', 178 => '=B2', 179 => '=B3',
|
||||
180 => '=B4', 181 => '=B5', 182 => '=B6', 183 => '=B7', 184 => '=B8',
|
||||
185 => '=B9', 186 => '=BA', 187 => '=BB', 188 => '=BC', 189 => '=BD',
|
||||
190 => '=BE', 191 => '=BF', 192 => '=C0', 193 => '=C1', 194 => '=C2',
|
||||
195 => '=C3', 196 => '=C4', 197 => '=C5', 198 => '=C6', 199 => '=C7',
|
||||
200 => '=C8', 201 => '=C9', 202 => '=CA', 203 => '=CB', 204 => '=CC',
|
||||
205 => '=CD', 206 => '=CE', 207 => '=CF', 208 => '=D0', 209 => '=D1',
|
||||
210 => '=D2', 211 => '=D3', 212 => '=D4', 213 => '=D5', 214 => '=D6',
|
||||
215 => '=D7', 216 => '=D8', 217 => '=D9', 218 => '=DA', 219 => '=DB',
|
||||
220 => '=DC', 221 => '=DD', 222 => '=DE', 223 => '=DF', 224 => '=E0',
|
||||
225 => '=E1', 226 => '=E2', 227 => '=E3', 228 => '=E4', 229 => '=E5',
|
||||
230 => '=E6', 231 => '=E7', 232 => '=E8', 233 => '=E9', 234 => '=EA',
|
||||
235 => '=EB', 236 => '=EC', 237 => '=ED', 238 => '=EE', 239 => '=EF',
|
||||
240 => '=F0', 241 => '=F1', 242 => '=F2', 243 => '=F3', 244 => '=F4',
|
||||
245 => '=F5', 246 => '=F6', 247 => '=F7', 248 => '=F8', 249 => '=F9',
|
||||
250 => '=FA', 251 => '=FB', 252 => '=FC', 253 => '=FD', 254 => '=FE',
|
||||
255 => '=FF'
|
||||
);
|
||||
|
||||
protected static $_safeMapShare = array();
|
||||
|
||||
/**
|
||||
* A map of non-encoded ascii characters.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $_safeMap = array();
|
||||
|
||||
/**
|
||||
* Creates a new QpEncoder for the given CharacterStream.
|
||||
*
|
||||
* @param Swift_CharacterStream $charStream to use for reading characters
|
||||
* @param Swift_StreamFilter $filter if input should be canonicalized
|
||||
*/
|
||||
public function __construct(Swift_CharacterStream $charStream, Swift_StreamFilter $filter = null)
|
||||
{
|
||||
$this->_charStream = $charStream;
|
||||
if (!isset(self::$_safeMapShare[$this->getSafeMapShareId()])) {
|
||||
$this->initSafeMap();
|
||||
self::$_safeMapShare[$this->getSafeMapShareId()] = $this->_safeMap;
|
||||
} else {
|
||||
$this->_safeMap = self::$_safeMapShare[$this->getSafeMapShareId()];
|
||||
}
|
||||
$this->_filter = $filter;
|
||||
}
|
||||
|
||||
public function __sleep()
|
||||
{
|
||||
return array('_charStream', '_filter');
|
||||
}
|
||||
|
||||
public function __wakeup()
|
||||
{
|
||||
if (!isset(self::$_safeMapShare[$this->getSafeMapShareId()])) {
|
||||
$this->initSafeMap();
|
||||
self::$_safeMapShare[$this->getSafeMapShareId()] = $this->_safeMap;
|
||||
} else {
|
||||
$this->_safeMap = self::$_safeMapShare[$this->getSafeMapShareId()];
|
||||
}
|
||||
}
|
||||
|
||||
protected function getSafeMapShareId()
|
||||
{
|
||||
return get_class($this);
|
||||
}
|
||||
|
||||
protected function initSafeMap()
|
||||
{
|
||||
foreach (array_merge(
|
||||
array(0x09, 0x20), range(0x21, 0x3C), range(0x3E, 0x7E)) as $byte)
|
||||
{
|
||||
$this->_safeMap[$byte] = chr($byte);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes an unencoded string and produces a QP encoded string from it.
|
||||
*
|
||||
* QP encoded strings have a maximum line length of 76 characters.
|
||||
* If the first line needs to be shorter, indicate the difference with
|
||||
* $firstLineOffset.
|
||||
*
|
||||
* @param string $string to encode
|
||||
* @param int $firstLineOffset, optional
|
||||
* @param int $maxLineLength, optional 0 indicates the default of 76 chars
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0)
|
||||
{
|
||||
if ($maxLineLength > 76 || $maxLineLength <= 0) {
|
||||
$maxLineLength = 76;
|
||||
}
|
||||
|
||||
$thisLineLength = $maxLineLength - $firstLineOffset;
|
||||
|
||||
$lines = array();
|
||||
$lNo = 0;
|
||||
$lines[$lNo] = '';
|
||||
$currentLine =& $lines[$lNo++];
|
||||
$size=$lineLen=0;
|
||||
|
||||
$this->_charStream->flushContents();
|
||||
$this->_charStream->importString($string);
|
||||
|
||||
// Fetching more than 4 chars at one is slower, as is fetching fewer bytes
|
||||
// Conveniently 4 chars is the UTF-8 safe number since UTF-8 has up to 6
|
||||
// bytes per char and (6 * 4 * 3 = 72 chars per line) * =NN is 3 bytes
|
||||
while (false !== $bytes = $this->_nextSequence()) {
|
||||
// If we're filtering the input
|
||||
if (isset($this->_filter)) {
|
||||
// If we can't filter because we need more bytes
|
||||
while ($this->_filter->shouldBuffer($bytes)) {
|
||||
// Then collect bytes into the buffer
|
||||
if (false === $moreBytes = $this->_nextSequence(1)) {
|
||||
break;
|
||||
}
|
||||
|
||||
foreach ($moreBytes as $b) {
|
||||
$bytes[] = $b;
|
||||
}
|
||||
}
|
||||
// And filter them
|
||||
$bytes = $this->_filter->filter($bytes);
|
||||
}
|
||||
|
||||
$enc = $this->_encodeByteSequence($bytes, $size);
|
||||
if ($currentLine && $lineLen+$size >= $thisLineLength) {
|
||||
$lines[$lNo] = '';
|
||||
$currentLine =& $lines[$lNo++];
|
||||
$thisLineLength = $maxLineLength;
|
||||
$lineLen=0;
|
||||
}
|
||||
$lineLen+=$size;
|
||||
$currentLine .= $enc;
|
||||
}
|
||||
|
||||
return $this->_standardize(implode("=\r\n", $lines));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the charset used.
|
||||
*
|
||||
* @param string $charset
|
||||
*/
|
||||
public function charsetChanged($charset)
|
||||
{
|
||||
$this->_charStream->setCharacterSet($charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode the given byte array into a verbatim QP form.
|
||||
*
|
||||
* @param integer[] $bytes
|
||||
* @param int $size
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function _encodeByteSequence(array $bytes, &$size)
|
||||
{
|
||||
$ret = '';
|
||||
$size=0;
|
||||
foreach ($bytes as $b) {
|
||||
if (isset($this->_safeMap[$b])) {
|
||||
$ret .= $this->_safeMap[$b];
|
||||
++$size;
|
||||
} else {
|
||||
$ret .= self::$_qpMap[$b];
|
||||
$size+=3;
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next sequence of bytes to read from the char stream.
|
||||
*
|
||||
* @param int $size number of bytes to read
|
||||
*
|
||||
* @return integer[]
|
||||
*/
|
||||
protected function _nextSequence($size = 4)
|
||||
{
|
||||
return $this->_charStream->readBytes($size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure CRLF is correct and HT/SPACE are in valid places.
|
||||
*
|
||||
* @param string $string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function _standardize($string)
|
||||
{
|
||||
$string = str_replace(array("\t=0D=0A", " =0D=0A", "=0D=0A"),
|
||||
array("=09\r\n", "=20\r\n", "\r\n"), $string
|
||||
);
|
||||
switch ($end = ord(substr($string, -1))) {
|
||||
case 0x09:
|
||||
case 0x20:
|
||||
$string = substr_replace($string, self::$_qpMap[$end], -1);
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Handles RFC 2231 specified Encoding in Swift Mailer.
|
||||
*
|
||||
* @author Chris Corbyn
|
||||
*/
|
||||
class Swift_Encoder_Rfc2231Encoder implements Swift_Encoder
|
||||
{
|
||||
/**
|
||||
* A character stream to use when reading a string as characters instead of bytes.
|
||||
*
|
||||
* @var Swift_CharacterStream
|
||||
*/
|
||||
private $_charStream;
|
||||
|
||||
/**
|
||||
* Creates a new Rfc2231Encoder using the given character stream instance.
|
||||
*
|
||||
* @param Swift_CharacterStream
|
||||
*/
|
||||
public function __construct(Swift_CharacterStream $charStream)
|
||||
{
|
||||
$this->_charStream = $charStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes an unencoded string and produces a string encoded according to
|
||||
* RFC 2231 from it.
|
||||
*
|
||||
* @param string $string
|
||||
* @param int $firstLineOffset
|
||||
* @param int $maxLineLength optional, 0 indicates the default of 75 bytes
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0)
|
||||
{
|
||||
$lines = array(); $lineCount = 0;
|
||||
$lines[] = '';
|
||||
$currentLine =& $lines[$lineCount++];
|
||||
|
||||
if (0 >= $maxLineLength) {
|
||||
$maxLineLength = 75;
|
||||
}
|
||||
|
||||
$this->_charStream->flushContents();
|
||||
$this->_charStream->importString($string);
|
||||
|
||||
$thisLineLength = $maxLineLength - $firstLineOffset;
|
||||
|
||||
while (false !== $char = $this->_charStream->read(4)) {
|
||||
$encodedChar = rawurlencode($char);
|
||||
if (0 != strlen($currentLine)
|
||||
&& strlen($currentLine . $encodedChar) > $thisLineLength)
|
||||
{
|
||||
$lines[] = '';
|
||||
$currentLine =& $lines[$lineCount++];
|
||||
$thisLineLength = $maxLineLength;
|
||||
}
|
||||
$currentLine .= $encodedChar;
|
||||
}
|
||||
|
||||
return implode("\r\n", $lines);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the charset used.
|
||||
*
|
||||
* @param string $charset
|
||||
*/
|
||||
public function charsetChanged($charset)
|
||||
{
|
||||
$this->_charStream->setCharacterSet($charset);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provides quick access to each encoding type.
|
||||
*
|
||||
* @author Chris Corbyn
|
||||
*/
|
||||
class Swift_Encoding
|
||||
{
|
||||
/**
|
||||
* Get the Encoder that provides 7-bit encoding.
|
||||
*
|
||||
* @return Swift_Mime_ContentEncoder
|
||||
*/
|
||||
public static function get7BitEncoding()
|
||||
{
|
||||
return self::_lookup('mime.7bitcontentencoder');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Encoder that provides 8-bit encoding.
|
||||
*
|
||||
* @return Swift_Mime_ContentEncoder
|
||||
*/
|
||||
public static function get8BitEncoding()
|
||||
{
|
||||
return self::_lookup('mime.8bitcontentencoder');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Encoder that provides Quoted-Printable (QP) encoding.
|
||||
*
|
||||
* @return Swift_Mime_ContentEncoder
|
||||
*/
|
||||
public static function getQpEncoding()
|
||||
{
|
||||
return self::_lookup('mime.qpcontentencoder');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Encoder that provides Base64 encoding.
|
||||
*
|
||||
* @return Swift_Mime_ContentEncoder
|
||||
*/
|
||||
public static function getBase64Encoding()
|
||||
{
|
||||
return self::_lookup('mime.base64contentencoder');
|
||||
}
|
||||
|
||||
// -- Private Static Methods
|
||||
|
||||
private static function _lookup($key)
|
||||
{
|
||||
return Swift_DependencyContainer::getInstance()->lookup($key);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Generated when a command is sent over an SMTP connection.
|
||||
*
|
||||
* @author Chris Corbyn
|
||||
*/
|
||||
class Swift_Events_CommandEvent extends Swift_Events_EventObject
|
||||
{
|
||||
/**
|
||||
* The command sent to the server.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $_command;
|
||||
|
||||
/**
|
||||
* An array of codes which a successful response will contain.
|
||||
*
|
||||
* @var integer[]
|
||||
*/
|
||||
private $_successCodes = array();
|
||||
|
||||
/**
|
||||
* Create a new CommandEvent for $source with $command.
|
||||
*
|
||||
* @param Swift_Transport $source
|
||||
* @param string $command
|
||||
* @param array $successCodes
|
||||
*/
|
||||
public function __construct(Swift_Transport $source, $command, $successCodes = array())
|
||||
{
|
||||
parent::__construct($source);
|
||||
$this->_command = $command;
|
||||
$this->_successCodes = $successCodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the command which was sent to the server.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCommand()
|
||||
{
|
||||
return $this->_command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the numeric response codes which indicate success for this command.
|
||||
*
|
||||
* @return integer[]
|
||||
*/
|
||||
public function getSuccessCodes()
|
||||
{
|
||||
return $this->_successCodes;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Listens for Transports to send commands to the server.
|
||||
*
|
||||
* @author Chris Corbyn
|
||||
*/
|
||||
interface Swift_Events_CommandListener extends Swift_Events_EventListener
|
||||
{
|
||||
/**
|
||||
* Invoked immediately following a command being sent.
|
||||
*
|
||||
* @param Swift_Events_CommandEvent $evt
|
||||
*/
|
||||
public function commandSent(Swift_Events_CommandEvent $evt);
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The minimum interface for an Event.
|
||||
*
|
||||
* @author Chris Corbyn
|
||||
*/
|
||||
interface Swift_Events_Event
|
||||
{
|
||||
/**
|
||||
* Get the source object of this event.
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function getSource();
|
||||
|
||||
/**
|
||||
* Prevent this Event from bubbling any further up the stack.
|
||||
*
|
||||
* @param bool $cancel, optional
|
||||
*/
|
||||
public function cancelBubble($cancel = true);
|
||||
|
||||
/**
|
||||
* Returns true if this Event will not bubble any further up the stack.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function bubbleCancelled();
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Interface for the EventDispatcher which handles the event dispatching layer.
|
||||
*
|
||||
* @author Chris Corbyn
|
||||
*/
|
||||
interface Swift_Events_EventDispatcher
|
||||
{
|
||||
/**
|
||||
* Create a new SendEvent for $source and $message.
|
||||
*
|
||||
* @param Swift_Transport $source
|
||||
* @param Swift_Mime_Message
|
||||
*
|
||||
* @return Swift_Events_SendEvent
|
||||
*/
|
||||
public function createSendEvent(Swift_Transport $source, Swift_Mime_Message $message);
|
||||
|
||||
/**
|
||||
* Create a new CommandEvent for $source and $command.
|
||||
*
|
||||
* @param Swift_Transport $source
|
||||
* @param string $command That will be executed
|
||||
* @param array $successCodes That are needed
|
||||
*
|
||||
* @return Swift_Events_CommandEvent
|
||||
*/
|
||||
public function createCommandEvent(Swift_Transport $source, $command, $successCodes = array());
|
||||
|
||||
/**
|
||||
* Create a new ResponseEvent for $source and $response.
|
||||
*
|
||||
* @param Swift_Transport $source
|
||||
* @param string $response
|
||||
* @param bool $valid If the response is valid
|
||||
*
|
||||
* @return Swift_Events_ResponseEvent
|
||||
*/
|
||||
public function createResponseEvent(Swift_Transport $source, $response, $valid);
|
||||
|
||||
/**
|
||||
* Create a new TransportChangeEvent for $source.
|
||||
*
|
||||
* @param Swift_Transport $source
|
||||
*
|
||||
* @return Swift_Events_TransportChangeEvent
|
||||
*/
|
||||
public function createTransportChangeEvent(Swift_Transport $source);
|
||||
|
||||
/**
|
||||
* Create a new TransportExceptionEvent for $source.
|
||||
*
|
||||
* @param Swift_Transport $source
|
||||
* @param Swift_TransportException $ex
|
||||
*
|
||||
* @return Swift_Events_TransportExceptionEvent
|
||||
*/
|
||||
public function createTransportExceptionEvent(Swift_Transport $source, Swift_TransportException $ex);
|
||||
|
||||
/**
|
||||
* Bind an event listener to this dispatcher.
|
||||
*
|
||||
* @param Swift_Events_EventListener $listener
|
||||
*/
|
||||
public function bindEventListener(Swift_Events_EventListener $listener);
|
||||
|
||||
/**
|
||||
* Dispatch the given Event to all suitable listeners.
|
||||
*
|
||||
* @param Swift_Events_EventObject $evt
|
||||
* @param string $target method
|
||||
*/
|
||||
public function dispatchEvent(Swift_Events_EventObject $evt, $target);
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* An identity interface which all EventListeners must extend.
|
||||
*
|
||||
* @author Chris Corbyn
|
||||
*/
|
||||
interface Swift_Events_EventListener
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A base Event which all Event classes inherit from.
|
||||
*
|
||||
* @author Chris Corbyn
|
||||
*/
|
||||
class Swift_Events_EventObject implements Swift_Events_Event
|
||||
{
|
||||
/** The source of this Event */
|
||||
private $_source;
|
||||
|
||||
/** The state of this Event (should it bubble up the stack?) */
|
||||
private $_bubbleCancelled = false;
|
||||
|
||||
/**
|
||||
* Create a new EventObject originating at $source.
|
||||
*
|
||||
* @param object $source
|
||||
*/
|
||||
public function __construct($source)
|
||||
{
|
||||
$this->_source = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the source object of this event.
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function getSource()
|
||||
{
|
||||
return $this->_source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent this Event from bubbling any further up the stack.
|
||||
*
|
||||
* @param bool $cancel, optional
|
||||
*/
|
||||
public function cancelBubble($cancel = true)
|
||||
{
|
||||
$this->_bubbleCancelled = $cancel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this Event will not bubble any further up the stack.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function bubbleCancelled()
|
||||
{
|
||||
return $this->_bubbleCancelled;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Generated when a response is received on a SMTP connection.
|
||||
*
|
||||
* @author Chris Corbyn
|
||||
*/
|
||||
class Swift_Events_ResponseEvent extends Swift_Events_EventObject
|
||||
{
|
||||
/**
|
||||
* The overall result.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $_valid;
|
||||
|
||||
/**
|
||||
* The response received from the server.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $_response;
|
||||
|
||||
/**
|
||||
* Create a new ResponseEvent for $source and $response.
|
||||
*
|
||||
* @param Swift_Transport $source
|
||||
* @param string $response
|
||||
* @param bool $valid
|
||||
*/
|
||||
public function __construct(Swift_Transport $source, $response, $valid = false)
|
||||
{
|
||||
parent::__construct($source);
|
||||
$this->_response = $response;
|
||||
$this->_valid = $valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the response which was received from the server.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getResponse()
|
||||
{
|
||||
return $this->_response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the success status of this Event.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isValid()
|
||||
{
|
||||
return $this->_valid;
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue