Merge branch '2013.03'
[tine20] / tine20 / Tasks / Model / Task.php
1 <?php
2 /**
3  * Tine 2.0
4  * 
5  * @package     Tasks
6  * @subpackage  Model
7  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
8  * @author      Cornelius Weiss <c.weiss@metaways.de>
9  * @copyright   Copyright (c) 2007-2012 Metaways Infosystems GmbH (http://www.metaways.de)
10  */
11
12 /**
13  * Task-Record Class
14  * 
15  * @package     Tasks
16  * @subpackage    Model
17  */
18 class Tasks_Model_Task extends Tinebase_Record_Abstract
19 {
20     const CLASS_PUBLIC         = 'PUBLIC';
21     const CLASS_PRIVATE        = 'PRIVATE';
22     //const CLASS_CONFIDENTIAL   = 'CONFIDENTIAL';
23     
24     /**
25      * key in $_validators/$_properties array for the filed which 
26      * represents the identifier
27      * 
28      * @var string
29      */
30     protected $_identifier = 'id';
31     
32     /**
33      * application the record belongs to
34      *
35      * @var string
36      */
37     protected $_application = 'Tasks';
38     
39     /**
40      * validators
41      *
42      * @var array
43      */
44     protected $_validators = array(
45         // tine record fields
46         'container_id'         => array('allowEmpty' => true,  'Int' ),
47         'created_by'           => array('allowEmpty' => true,        ),
48         'creation_time'        => array('allowEmpty' => true         ),
49         'last_modified_by'     => array('allowEmpty' => true         ),
50         'last_modified_time'   => array('allowEmpty' => true         ),
51         'is_deleted'           => array('allowEmpty' => true         ),
52         'deleted_time'         => array('allowEmpty' => true         ),
53         'deleted_by'           => array('allowEmpty' => true         ),
54         'seq'                  => array('allowEmpty' => true         ),
55         // task only fields
56         'id'                   => array('allowEmpty' => true, 'Alnum'),
57         'percent'              => array('allowEmpty' => true, 'default' => 0),
58         'completed'            => array('allowEmpty' => true         ),
59         'due'                  => array('allowEmpty' => true         ),
60         // ical common fields
61         'class'                => array(
62             'allowEmpty' => true,
63             array('InArray', array(self::CLASS_PUBLIC, self::CLASS_PRIVATE, /*self::CLASS_CONFIDENTIAL*/)),
64         ),
65         'description'          => array('allowEmpty' => true         ),
66         'geo'                  => array('allowEmpty' => true, Zend_Filter_Input::DEFAULT_VALUE => NULL),
67         'location'             => array('allowEmpty' => true         ),
68         'organizer'            => array('allowEmpty' => true,        ),
69         'originator_tz'        => array('allowEmpty' => true         ),
70         'priority'             => array('allowEmpty' => true, 'default' => 1),
71         'status'               => array('allowEmpty' => false        ),
72         'summary'              => array('presence' => 'required'     ),
73         'url'                  => array('allowEmpty' => true         ),
74         // ical common fields with multiple appearance
75         'attach'                => array('allowEmpty' => true        ),
76         'attendee'              => array('allowEmpty' => true        ),
77         'tags'                  => array('allowEmpty' => true        ), //originally categories
78         'comment'               => array('allowEmpty' => true        ),
79         'contact'               => array('allowEmpty' => true        ),
80         'related'               => array('allowEmpty' => true        ),
81         'resources'             => array('allowEmpty' => true        ),
82         'rstatus'               => array('allowEmpty' => true        ),
83         // scheduleable interface fields
84         'dtstart'               => array('allowEmpty' => true        ),
85         'duration'              => array('allowEmpty' => true        ),
86         'recurid'               => array('allowEmpty' => true        ),
87         // scheduleable interface fields with multiple appearance
88         'exdate'                => array('allowEmpty' => true        ),
89         'exrule'                => array('allowEmpty' => true        ),
90         'rdate'                 => array('allowEmpty' => true        ),
91         'rrule'                 => array('allowEmpty' => true        ),
92         // tine 2.0 notes, alarms and relations
93         'notes'                 => array('allowEmpty' => true        ),
94         'alarms'                => array('allowEmpty' => true        ), // RecordSet of Tinebase_Model_Alarm
95         'relations'             => array('allowEmpty' => true        ),
96     );
97     
98     /**
99      * datetime fields
100      *
101      * @var array
102      */
103     protected $_datetimeFields = array(
104         'creation_time', 
105         'last_modified_time', 
106         'deleted_time', 
107         'completed', 
108         'dtstart', 
109         'due', 
110         'exdate', 
111         'rdate'
112     );
113     
114     /**
115      * the constructor
116      * it is needed because we have more validation fields in Tasks
117      * 
118      * @param mixed $_data
119      * @param bool $bypassFilters sets {@see this->bypassFilters}
120      * @param bool $convertDates sets {@see $this->convertDates}
121      */
122     public function __construct($_data = NULL, $_bypassFilters = false, $_convertDates = true)
123     {
124         $this->_filters['organizer'] = new Zend_Filter_Empty(NULL);
125         
126         parent::__construct($_data, $_bypassFilters, $_convertDates);
127     }
128     
129     /**
130      * sets the record related properties from user generated input.
131      *
132      * @param   array $_data
133      * @return void
134      */
135     public function setFromArray(array $_data)
136     {
137         //if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' ' . print_r($_data, true));
138         
139         if (empty($_data['geo'])) {
140             $_data['geo'] = NULL;
141         }
142         
143         if (empty($_data['class'])) {
144             $_data['class'] = self::CLASS_PUBLIC;
145         }
146         
147         if (isset($_data['organizer']) && is_array($_data['organizer'])) {
148             $_data['organizer'] = $_data['organizer']['accountId'];
149         }
150         
151         if (isset($_data['alarms']) && is_array($_data['alarms'])) {
152             $_data['alarms'] = new Tinebase_Record_RecordSet('Tinebase_Model_Alarm', $_data['alarms'], TRUE);
153         }
154         
155         //if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' ' . print_r($_data, true));
156         parent::setFromArray($_data);
157     }
158     
159     /**
160      * create notification message for task alarm
161      *
162      * @return string
163      * 
164      * @todo should we get the locale pref for each single user here instead of the default?
165      * @todo move lead stuff to Crm(_Model_Lead)?
166      * @todo add getSummary to Addressbook_Model_Contact for linked contacts?
167      */
168     public function getNotificationMessage()
169     {
170         // get locale from prefs
171         $localePref = Tinebase_Core::getPreference()->getValue(Tinebase_Preference::LOCALE);
172         $locale = Tinebase_Translation::getLocale($localePref);
173         
174         $translate = Tinebase_Translation::getTranslation($this->_application, $locale);
175         
176         // get date strings
177         $timezone = ($this->originator_tz) ? $this->originator_tz : Tinebase_Core::get(Tinebase_Core::USERTIMEZONE);
178         $dueDateString = Tinebase_Translation::dateToStringInTzAndLocaleFormat($this->due, $timezone, $locale);
179         
180         // resolve values
181         Tinebase_User::getInstance()->resolveUsers($this, 'organizer', true);
182         $status = Tasks_Config::getInstance()->get(Tasks_Config::TASK_STATUS)->records->getById($this->status);
183         $organizerName = ($this->organizer) ? $this->organizer->accountDisplayName : '';
184         
185         //if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' ' . print_r($this->toArray(), TRUE));
186         
187         $text = $this->summary . "\n\n" 
188             . $translate->_('Due')          . ': ' . $dueDateString                  . "\n" 
189             . $translate->_('Organizer')    . ': ' . $organizerName                  . "\n" 
190             . $translate->_('Description')  . ': ' . $this->description              . "\n"
191             . $translate->_('Priority')     . ': ' . $this->priority                 . "\n"
192             . $translate->_('Status')       . ': ' . $translate->_($status['value']) . "\n"
193             . $translate->_('Percent')      . ': ' . $this->percent                  . "%\n\n";
194             
195         // add relations (get with ignore acl)
196         $relations = Tinebase_Relations::getInstance()->getRelations(get_class($this), 'Sql', $this->getId(), NULL, array('TASK'), TRUE);
197         foreach ($relations as $relation) {
198             if ($relation->related_model == 'Crm_Model_Lead') {
199                 $lead = $relation->related_record;
200                 $text .= $translate->_('Lead') . ': ' . $lead->lead_name . "\n";
201                 $leadRelations = Tinebase_Relations::getInstance()->getRelations(get_class($lead), 'Sql', $lead->getId());
202                 foreach ($leadRelations as $leadRelation) {
203                     if ($leadRelation->related_model == 'Addressbook_Model_Contact') {
204                         $contact = $leadRelation->related_record;
205                         $text .= $leadRelation->type . ': ' . $contact->n_fn . ' (' . $contact->org_name . ')' . "\n"
206                             . ((! empty($contact->tel_work)) ?  "\t" . $translate->_('Telephone')   . ': ' . $contact->tel_work   . "\n" : '')
207                             . ((! empty($contact->email)) ?     "\t" . $translate->_('Email')       . ': ' . $contact->email      . "\n" : '');
208                     }
209                 }
210             }
211         }
212         
213         //if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' ' . $text);
214             
215         return $text;
216     }
217 }