0byt3m1n1
Path:
/
data
/
applications
/
aps.bak
/
phprojekt
/
6.0.6-0
/
standard
/
htdocs
/
library
/
Phprojekt
/
[
Home
]
File: Notification.php
<?php /** * Notification class. * * This software is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 3 as published by the Free Software Foundation * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * @category PHProjekt * @package Phprojekt * @subpackage Notification * @copyright Copyright (c) 2010 Mayflower GmbH (http://www.mayflower.de) * @license LGPL v3 (See LICENSE file) * @link http://www.phprojekt.com * @since File available since Release 6.0 * @version Release: 6.0.6 * @author Mariano La Penna <mariano.lapenna@mayflower.de> */ /** * Notification class. * * @category PHProjekt * @package Phprojekt * @subpackage Notification * @copyright Copyright (c) 2010 Mayflower GmbH (http://www.mayflower.de) * @license LGPL v3 (See LICENSE file) * @link http://www.phprojekt.com * @since File available since Release 6.0 * @version Release: 6.0.6 * @author Mariano La Penna <mariano.lapenna@mayflower.de> */ class Phprojekt_Notification { /** * Actions. */ const LAST_ACTION_ADD = 'add'; const LAST_ACTION_EDIT = 'edit'; const LAST_ACTION_DELETE = 'delete'; const LAST_ACTION_LOGOUT = 'logout'; const LAST_ACTION_LOGIN = 'login'; const LAST_ACTION_REMIND = 'remind'; /** * Transports. */ const TRANSPORT_MAIL_TEXT = 0; const TRANSPORT_MAIL_HTML = 1; /** * Last history data for one item. * * @var array */ protected $_lastHistory; /** * FrontendMessage class. * * @var Phprojekt_Notification_FrontendMessage */ protected $_frontendMessage; /** * Process 'add', 'delete' or 'update'. * * @var string */ protected $_controllProcess = null; /** * Model to use. * * @var Phprojekt_Model_Interface */ protected $_model = null; /** * Datetime until a frontend message is valid. * * @var integer */ protected $_validUntil = null; /** * Datetime from a frontend message is valid. * * @var integer */ protected $_validFrom = null; /** * List of recipients. * * @var array */ protected $_recipients = null; /** * Initialize new object. * * @return void */ public function __construct() { $this->_frontendMessage = new Phprojekt_Notification_FrontendMessage(); } /** * Stores in the private variable $_model the received model. * * @param Phprojekt_Model_Interface $model Model to use. * * @return void */ public function setModel(Phprojekt_Model_Interface $model) { $this->_model = $model; } /** * Sends an notification through the indicated transport, * the contents are made according to a specific module and a specific event. * * Previous to this function it has to be called setModel * so that the internal variable _model has the model where to obtain the data from. * * Depending on the indicated transport the notification will be sent currently via text or html email. * * @param integer $transport Type of transport to use. * * @return void */ public function send($transport) { // Sometimes, the user may try to modify an existing item and presses Save without having modified even one // field. In that case, no mail should be sent. $history = Phprojekt_Loader::getLibraryClass('Phprojekt_History'); $this->_lastHistory = $history->getLastHistoryData($this->_model); if (empty($this->_lastHistory)) { return; } $params = array(); switch ($transport) { case self::TRANSPORT_MAIL_TEXT: case self::TRANSPORT_MAIL_HTML: default: $adapterName = "Phprojekt_Notification_Mail"; $showSubject = true; $params[Phprojekt_Notification_Mail::PARAMS_CHARSET] = "UTF-8"; if ($transport == self::TRANSPORT_MAIL_TEXT) { $params[Phprojekt_Notification_Mail::PARAMS_BODYMODE] = Phprojekt_Notification_Mail::MODE_TEXT; } else { $params[Phprojekt_Notification_Mail::PARAMS_BODYMODE] = Phprojekt_Notification_Mail::MODE_HTML; } break; } $from = $this->getFrom(); $recipients = $this->getTo(); $subject = $this->getSubject(); $bodyParams = $this->getBodyParams(); if (!empty($recipients)) { $recipientsPerLang = array(); $setting = Phprojekt_Loader::getLibraryClass('Phprojekt_Setting'); foreach ($recipients as $recipient) { $lang = $setting->getSetting('language', (int) $recipient); if (null === $lang) { $lang = Phprojekt::getInstance()->getConfig()->language; } $recipientsPerLang[$lang][] = $recipient; } // Send one mail per language foreach ($recipientsPerLang as $lang => $recipients) { $bodyFields = $this->getBodyFields($lang); if ($this->_lastHistory[0]['action'] == self::LAST_ACTION_EDIT) { $changes = $this->getBodyChanges($lang); } else { $changes = null; } $adapter = new $adapterName($params); $adapter->setCustomFrom($from); $adapter->setTo($recipients); if (count($adapter->getRecipients()) > 0) { if ($showSubject) { $adapter->setCustomSubject($subject); } $adapter->setCustomBody($bodyParams, $bodyFields, $changes, $lang); $adapter->sendNotification(); } } } } /** * Return the id of the sender, that's the logged user. * * @return integer Current user id. */ public function getFrom() { return Phprojekt_Auth::getUserId(); } /** * Gets only the recipients with at least a 'read' right. * * If no recipient is given, returns an empty array. * Exclude the current user. * * @return array Array with user IDs. */ public function getTo() { $userIds = $this->_model->getUsersRights(); $recipients = array(); if (is_array($userIds) && !empty($userIds)) { foreach ($userIds as $right) { if (($right['userId'] == Phprojekt_Auth::getUserId()) || $right['none']) { continue; } $recipients[] = $right['userId']; } } return $recipients; } /** * Returns the subject of the notification * according to the current module, stored in $this->_model. * * @return string Subject. */ public function getSubject() { $mailTitle = ""; if (isset($this->_model->searchFirstDisplayField)) { $mailTitle = $this->_model->{$this->_model->searchFirstDisplayField}; } $subject = trim('[' . $this->_model->getModelName() . ' #' . $this->_model->id . '] ' . $mailTitle); return $subject; } /** * Returns some params for the body of the notification * according to the current module and the event we are informing to the users. * * @return array Array with options. */ public function getBodyParams() { $bodyParams = array(); // Action switch ($this->_lastHistory[0]['action']) { case self::LAST_ACTION_ADD: $bodyParams['actionLabel'] = "created"; break; case self::LAST_ACTION_EDIT: default: $bodyParams['actionLabel'] = "modified"; break; } // Module $bodyParams['moduleTable'] = $this->_model->getModelName(); // Url $url = Phprojekt::getInstance()->getConfig()->webpath . "index.php#" . $this->_model->getModelName(); if (Phprojekt_Module::saveTypeIsNormal(Phprojekt_Module::getId($this->_model->getModelName()))) { $url .= "," . $this->_model->projectId; } $url .= ",id," . $this->_model->id; $bodyParams['url'] = $url; return $bodyParams; } /** * Returns the fields part of the Notification body. * * @param Zend_Locale $lang Locale for use in translations. * * @return array Array with 'field', 'label' and 'value'. */ public function getBodyFields($lang) { $order = Phprojekt_ModelInformation_Default::ORDERING_FORM; $fieldDefinition = $this->_model->getInformation()->getFieldDefinition($order); $bodyFields = array(); foreach ($fieldDefinition as $key => $field) { switch ($field['type']) { case 'selectbox': case 'multipleselectbox': // Search the value foreach ($field['range'] as $range) { if ($range['id'] == $this->_model->$field['key']) { $value = isset($range['originalName']) ? Phprojekt::getInstance()->translate($range['originalName'], $lang) : $range['name']; break; } } break; case 'display': // Search if there is an Id value that should be translated into a descriptive String $value = null; foreach ($field['range'] as $range) { if (is_array($range)) { if ($range['id'] == $this->_model->$field['key']) { $value = isset($range['originalName']) ? Phprojekt::getInstance()->translate($range['originalName'], $lang) : $range['name']; break 2; } } } if (null === $value) { $value = $this->_model->$field['key']; } break; default: $value = Phprojekt_Converter_Text::convert($this->_model, $field); break; } $bodyFields[] = array('field' => $field['key'], 'label' => Phprojekt::getInstance()->translate($field['originalLabel'], $lang), 'value' => $value); } return $bodyFields; } /** * Goes into the contents of the 'changes' part of the Notification body * (from internal variable _lastHistory) and checks for contents that have to be translated * if the $translate option is true, then returns the final array. * * @param Zend_Locale $lang Locale for use in translations. * @param boolean $translate Translate the fields or not. * * @return array Array with changes. */ public function getBodyChanges($lang = null, $translate = true) { // The following algorithm loops inside $this->_lastHistory and prepares $bodyChanges while: // * Searches Integer values that should be converted into Strings and converts them $order = Phprojekt_ModelInformation_Default::ORDERING_FORM; $fieldDefinition = $this->_model->getInformation()->getFieldDefinition($order); $bodyChanges = $this->_lastHistory; // Iterate in every change done for ($i = 0; $i < count($bodyChanges); $i++) { foreach ($fieldDefinition as $field) { // Find the field definition for the field that has been modified if ($field['key'] == $bodyChanges[$i]['field']) { $bodyChanges[$i]['field'] = $field['key']; $bodyChanges[$i]['label'] = Phprojekt::getInstance()->translate($field['originalLabel'], $lang); $bodyChanges[$i]['type'] = $field['type']; if ($translate && in_array($field['type'], array('selectbox', 'display', 'multipleselectbox'))) { // Is the field of a type that should be translated from an Id into a descriptive String? $convertToString = true; if ($field['type'] == 'display') { if (!is_array($field['range'])) { $convertToString = false; } else { foreach ($field['range'] as $range) { if (!is_array($range)) { $convertToString = false; break; } } } } if ($convertToString) { // Yes, so translate it into the appropriate meaning foreach ($field['range'] as $range) { // Try to replace oldValue Integer with the String if ($range['id'] == $bodyChanges[$i]['oldValue']) { $bodyChanges[$i]['oldValue'] = isset($range['originalName']) ? Phprojekt::getInstance()->translate($range['originalName'], $lang) : $range['name']; } // Try to replace oldValue Integer with the String if ($range['id'] == $bodyChanges[$i]['newValue']) { $bodyChanges[$i]['newValue'] = isset($range['originalName']) ? Phprojekt::getInstance()->translate($range['originalName'], $lang) : $range['name']; } } } } } } } return $bodyChanges; } /** * Calls the saveFrontendMessage of the FrontendMessage class * to save a message to the corresponding table. * * @return boolean True for a sucessful save. */ public function saveFrontendMessage() { $bodyChanges = array(); $recipients = $this->getRecipients(); if (null !== $this->_model) { // This is only possible if $this->model is not null $history = Phprojekt_Loader::getLibraryClass('Phprojekt_History'); $this->_lastHistory = $history->getLastHistoryData($this->_model); $bodyChanges = (false === empty($this->_controllProcess)) ? array() : $this->getBodyChanges(null, false); // If no recipients were added, return immediately // allthough a check in FrontendMessage saveFrontendMessage is performed too, // but this is earlier and avoids all the set. if (true === empty($recipients)) { return; } } $process = $this->getProcess(); $description = $this->getDescription(); $this->_frontendMessage->setCustomModuleId($this->getModuleId()); $this->_frontendMessage->setCustomProjectId($this->getProjectId()); $this->_frontendMessage->setCustomItemId($this->getItemId()); $this->_frontendMessage->setCustomValidUntil($this->getValidUntil()); $this->_frontendMessage->setCustomValidFrom($this->getValidFrom()); $this->_frontendMessage->setCustomRecipients($recipients); $this->_frontendMessage->setCustomProcess($process); $this->_frontendMessage->setCustomDescription($description); $this->_frontendMessage->setCustomDetails($bodyChanges); $this->_frontendMessage->setCustomItemName($this->getItemName()); $return = $this->_frontendMessage->saveFrontendMessage(); return $return; } /** * Delivers the description to a message. * * @return string Description string. */ public function getDescription() { // Map process $process = $this->getProcess(); switch ($process) { case (self::LAST_ACTION_ADD): $description = 'has created the new entry'; break; case (self::LAST_ACTION_DELETE): $description = 'has deleted the entry'; break; case (self::LAST_ACTION_EDIT): $description = 'has edit the existing entry'; break; case (self::LAST_ACTION_LOGIN): $description = 'has logged in'; break; case (self::LAST_ACTION_LOGOUT): $description = 'has logged out'; break; case (self::LAST_ACTION_REMIND): $description = 'Your event starts at'; break; default: $description = 'has executed a not defined process'; break; } return $description; } /** * Setter for the controll process. * * @param string $customProcess Process ('add', 'delete' or 'update'). * * @return void */ public function setControllProcess($customProcess) { $this->_controllProcess = $customProcess; } /** * Getting the standard process like 'add', 'delete' or 'update'. * * @return string Process. */ public function getProcess() { if (false === empty($this->_controllProcess)) { return $this->_controllProcess; } if (isset($this->_lastHistory[0]) && $this->_lastHistory[0]['action'] === self::LAST_ACTION_ADD) { return self::LAST_ACTION_ADD; } else { return self::LAST_ACTION_EDIT; } } /** * Gets the project ID. * * Returns the default value for the root project if no model was instanciated. * * @return integer The project ID. */ public function getProjectId() { $projectId = IndexController::INVISIBLE_ROOT; if ($this->_model instanceof Phprojekt_Tree_Node_Database) { $projectId = $this->_model->id; } elseif ($this->_model instanceof Phprojekt_Model_Interface) { $projectId = $this->_model->projectId; } return $projectId; } /** * Gets the module ID. * * @return integer The module ID. */ public function getModuleId() { $moduleId = 0; if (($this->_model instanceof Phprojekt_Tree_Node_Database) || ($this->_model instanceof Phprojekt_Model_Interface)) { $moduleName = $this->_model->getModelName(); $moduleId = Phprojekt_Module::getId($moduleName); } return $moduleId; } /** * Gets the item name. * * @return string Item display. */ public function getItemName() { $itemName = "-"; if (false === empty($this->_model)) { if (isset($this->_model->{$this->_model->searchFirstDisplayField})) { $itemName = $this->_model->{$this->_model->searchFirstDisplayField}; } else { $itemName = "ID: " . $this->_model->id; } } return $itemName; } /** * Gets the item ID. * * @return integer The item ID. */ public function getItemId() { $itemId = 0; if (($this->_model instanceof Phprojekt_Tree_Node_Database) || ($this->_model instanceof Phprojekt_Model_Interface)) { $itemId = $this->_model->id; } return $itemId; } /** * Gets the datetime from which the frontend message is valid, * typically the moment where the message will be created. * * @return string Datetime format. */ public function getValidFrom() { if (false === empty($this->_validFrom)) { return $this->_validFrom; } return gmdate("Y-m-d H:i:s"); } /** * Gets the datetime until a frontend message is valid. * * This is from special interest in the calendar module, * where the user can add meetings and other time relevant events. * * This time is needed to calculate the 'alarm' before an event starts. * * @return string Datetime format. */ public function getValidUntil() { if (false === empty($this->_validUntil)) { return $this->_validUntil; } $validPeriod = Phprojekt::getInstance()->getConfig()->validPeriod; $validUntil = time() + (60 * $validPeriod); return gmdate("Y-m-d H:i:s", $validUntil); } /** * Gets only the recipients with at least a 'read' right * and checks if the user has disabled/enabled the settings for saving the messages. * * If no recipient is given, returns an empty array. * * @return array Array with user IDs. */ public function getRecipients() { if (false === empty($this->_recipients)) { return $this->_recipients; } $recipients = array(); if (($this->_model instanceof Phprojekt_Tree_Node_Database) || ($this->_model instanceof Phprojekt_Model_Interface)) { $userIds = $this->_model->getUsersRights(); if (is_array($userIds) && !empty($userIds)) { foreach ($userIds as $right) { if (($right['userId'] == Phprojekt_Auth::getUserId()) || true === $right['none']) { continue; } $recipients[] = $right['userId']; } } } else { $user = Phprojekt_Loader::getLibraryClass('Phprojekt_User_User'); $userIds = $user->fetchAll(); foreach ($userIds as $user) { if ($user->id == Phprojekt_Auth::getUserId()) { continue; } $recipients[] = $user->id; } } return $this->filterRecipientsToSettings($recipients); } /** * Returns the key from the settings regarding to the given process. * * @return string Setting name. */ public function mapProcessToSettings() { $settingKey = ''; $process = $this->getProcess(); switch ($process) { case (self::LAST_ACTION_ADD): case (self::LAST_ACTION_DELETE): case (self::LAST_ACTION_EDIT): $settingKey = 'datarecords'; break; case (self::LAST_ACTION_LOGIN): case (self::LAST_ACTION_LOGOUT): $settingKey = 'loginlogout'; break; case (self::LAST_ACTION_REMIND): $settingKey = 'alerts'; break; default: $settingKey = ''; break; } return $settingKey; } /** * Returns the setting value from the notification tab. * * @param string $settingName Setting name to get. * @param integer $userId User ID for get the setting. * * @return mixed Returns the setting value as integer or null if setting is not saved to the database yet. */ public function getSetting($settingName, $userId) { $setting = Phprojekt_Loader::getLibraryClass('Phprojekt_Setting'); $setting->setModule('Notification'); $value = $setting->getSetting($settingName, $userId); $value = (true === is_null($value)) ? $value : (int) $value; return $value; } /** * Disables all types of frontend messages. * * @return void */ public function disableFrontendMessages() { $defaultSettings = array(Core_Models_Notification_Setting::FIELD_LOGIN_LOGOUT => 0, Core_Models_Notification_Setting::FIELD_DATARECORDS => 0, Core_Models_Notification_Setting::FIELD_USERGENERATED => 0, Core_Models_Notification_Setting::FIELD_ALERTS => 0); $setting = Phprojekt_Loader::getLibraryClass('Phprojekt_Setting'); $setting->setModule('Notification'); $setting->setSettings($defaultSettings); } /** * Filters the users from the recipients list without the settings * for receiving one of the frontend messages. * * @param array $recipients Array with user IDs. * * @return array Filter array. */ public function filterRecipientsToSettings(array $recipients) { $users = $recipients; // get the setting to the process. $settingKey = $this->mapProcessToSettings(); foreach ($users as $user) { $setting = $this->getSetting($settingKey, $user); // Since the checkboxes doesn�t have a propper default value, // only users who realy have disabled the setting will be removed from the recipients array. // Users with no saved setting will be stay on the recipients list too, // because a user has to uncheck the setting to disable the frontend message. if ($setting === 0) { if (false !== ($key = array_search($user,$users))){ unset($users[$key]); } } } return $users; } }