2e97a72c8e102467ca3b6a3823870045f17ab114
[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      * if foreign Id fields should be resolved on search and get from json
34      * should have this format: 
35      *     array('Calendar_Model_Contact' => 'contact_id', ...)
36      * or for more fields:
37      *     array('Calendar_Model_Contact' => array('contact_id', 'customer_id), ...)
38      * (e.g. resolves contact_id with the corresponding Model)
39      * 
40      * @var array
41      */
42     protected static $_resolveForeignIdFields = array(
43         'Tinebase_Model_User'     => array('created_by', 'last_modified_by', 'organizer'),
44         'recursive'               => array('attachments' => 'Tinebase_Model_Tree_Node'),
45     );
46     
47     /**
48      * application the record belongs to
49      *
50      * @var string
51      */
52     protected $_application = 'Tasks';
53     
54     /**
55      * validators
56      *
57      * @var array
58      */
59     protected $_validators = array(
60         // tine record fields
61         'container_id'         => array(Zend_Filter_Input::ALLOW_EMPTY => true,  'Int' ),
62         'created_by'           => array(Zend_Filter_Input::ALLOW_EMPTY => true,        ),
63         'creation_time'        => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
64         'last_modified_by'     => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
65         'last_modified_time'   => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
66         'is_deleted'           => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
67         'deleted_time'         => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
68         'deleted_by'           => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
69         'seq'                  => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
70         // task only fields
71         'id'                   => array(Zend_Filter_Input::ALLOW_EMPTY => true, 'Alnum'),
72         'percent'              => array(Zend_Filter_Input::ALLOW_EMPTY => true, 'default' => 0),
73         'completed'            => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
74         'due'                  => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
75         // ical common fields
76         'class'                => array(
77             Zend_Filter_Input::ALLOW_EMPTY => true,
78             array('InArray', array(self::CLASS_PUBLIC, self::CLASS_PRIVATE, /*self::CLASS_CONFIDENTIAL*/)),
79         ),
80         'description'          => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
81         'geo'                  => array(Zend_Filter_Input::ALLOW_EMPTY => true, Zend_Filter_Input::DEFAULT_VALUE => NULL),
82         'location'             => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
83         'organizer'            => array(Zend_Filter_Input::ALLOW_EMPTY => true,        ),
84         'originator_tz'        => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
85         'priority'             => array(Zend_Filter_Input::ALLOW_EMPTY => true, 'default' => 1),
86         'status'               => array(Zend_Filter_Input::ALLOW_EMPTY => false        ),
87         'summary'              => array('presence' => 'required'     ),
88         'url'                  => array(Zend_Filter_Input::ALLOW_EMPTY => true         ),
89         // ical common fields with multiple appearance
90         'attach'               => array(Zend_Filter_Input::ALLOW_EMPTY => true        ),
91         'attendee'             => array(Zend_Filter_Input::ALLOW_EMPTY => true        ),
92         'tags'                 => array(Zend_Filter_Input::ALLOW_EMPTY => true        ), //originally categories
93         'comment'              => array(Zend_Filter_Input::ALLOW_EMPTY => true        ),
94         'contact'              => array(Zend_Filter_Input::ALLOW_EMPTY => true        ),
95         'related'              => array(Zend_Filter_Input::ALLOW_EMPTY => true        ),
96         'resources'            => array(Zend_Filter_Input::ALLOW_EMPTY => true        ),
97         'rstatus'              => array(Zend_Filter_Input::ALLOW_EMPTY => true        ),
98         // scheduleable interface fields
99         'dtstart'              => array(Zend_Filter_Input::ALLOW_EMPTY => true        ),
100         'duration'             => array(Zend_Filter_Input::ALLOW_EMPTY => true        ),
101         'recurid'              => array(Zend_Filter_Input::ALLOW_EMPTY => true        ),
102         // scheduleable interface fields with multiple appearance
103         'exdate'               => array(Zend_Filter_Input::ALLOW_EMPTY => true        ),
104         'exrule'               => array(Zend_Filter_Input::ALLOW_EMPTY => true        ),
105         'rdate'                => array(Zend_Filter_Input::ALLOW_EMPTY => true        ),
106         'rrule'                => array(Zend_Filter_Input::ALLOW_EMPTY => true        ),
107         // tine 2.0 notes, alarms and relations
108         'notes'                => array(Zend_Filter_Input::ALLOW_EMPTY => true        ),
109         'alarms'               => array(Zend_Filter_Input::ALLOW_EMPTY => true        ), // RecordSet of Tinebase_Model_Alarm
110         'relations'            => array(Zend_Filter_Input::ALLOW_EMPTY => true        ),
111         'attachments'          => array(Zend_Filter_Input::ALLOW_EMPTY => true),
112     );
113     
114     /**
115      * datetime fields
116      *
117      * @var array
118      */
119     protected $_datetimeFields = array(
120         'creation_time', 
121         'last_modified_time', 
122         'deleted_time', 
123         'completed', 
124         'dtstart', 
125         'due', 
126         'exdate', 
127         'rdate'
128     );
129     
130     /**
131      * the constructor
132      * it is needed because we have more validation fields in Tasks
133      * 
134      * @param mixed $_data
135      * @param bool $bypassFilters sets {@see this->bypassFilters}
136      * @param bool $convertDates sets {@see $this->convertDates}
137      */
138     public function __construct($_data = NULL, $_bypassFilters = false, $_convertDates = true)
139     {
140         $this->_filters['organizer'] = new Zend_Filter_Empty(NULL);
141         
142         parent::__construct($_data, $_bypassFilters, $_convertDates);
143     }
144     
145     /**
146      * sets the record related properties from user generated input.
147      *
148      * @param   array $_data
149      * @return void
150      */
151     public function setFromArray(array $_data)
152     {
153         //if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' ' . print_r($_data, true));
154         
155         if (empty($_data['geo'])) {
156             $_data['geo'] = NULL;
157         }
158         
159         if (empty($_data['class'])) {
160             $_data['class'] = self::CLASS_PUBLIC;
161         }
162         
163         if (isset($_data['organizer']) && is_array($_data['organizer'])) {
164             $_data['organizer'] = $_data['organizer']['accountId'];
165         }
166         
167         if (isset($_data['alarms']) && is_array($_data['alarms'])) {
168             $_data['alarms'] = new Tinebase_Record_RecordSet('Tinebase_Model_Alarm', $_data['alarms'], TRUE);
169         }
170         
171         //if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' ' . print_r($_data, true));
172         parent::setFromArray($_data);
173     }
174     
175     /**
176      * create notification message for task alarm
177      *
178      * @return string
179      * 
180      * @todo should we get the locale pref for each single user here instead of the default?
181      * @todo move lead stuff to Crm(_Model_Lead)?
182      * @todo add getSummary to Addressbook_Model_Contact for linked contacts?
183      */
184     public function getNotificationMessage()
185     {
186         // get locale from prefs
187         $localePref = Tinebase_Core::getPreference()->getValue(Tinebase_Preference::LOCALE);
188         $locale = Tinebase_Translation::getLocale($localePref);
189         
190         $translate = Tinebase_Translation::getTranslation($this->_application, $locale);
191         
192         // get date strings
193         $timezone = ($this->originator_tz) ? $this->originator_tz : Tinebase_Core::get(Tinebase_Core::USERTIMEZONE);
194         $dueDateString = Tinebase_Translation::dateToStringInTzAndLocaleFormat($this->due, $timezone, $locale);
195         
196         // resolve values
197         Tinebase_User::getInstance()->resolveUsers($this, 'organizer', true);
198         $status = Tasks_Config::getInstance()->get(Tasks_Config::TASK_STATUS)->records->getById($this->status);
199         $organizerName = ($this->organizer) ? $this->organizer->accountDisplayName : '';
200         
201         //if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' ' . print_r($this->toArray(), TRUE));
202         
203         $text = $this->summary . "\n\n" 
204             . $translate->_('Due')          . ': ' . $dueDateString                  . "\n" 
205             . $translate->_('Organizer')    . ': ' . $organizerName                  . "\n" 
206             . $translate->_('Description')  . ': ' . $this->description              . "\n"
207             . $translate->_('Priority')     . ': ' . $this->priority                 . "\n"
208             . $translate->_('Status')       . ': ' . $translate->_($status['value']) . "\n"
209             . $translate->_('Percent')      . ': ' . $this->percent                  . "%\n\n";
210             
211         // add relations (get with ignore acl)
212         $relations = Tinebase_Relations::getInstance()->getRelations(get_class($this), 'Sql', $this->getId(), NULL, array('TASK'), TRUE);
213         foreach ($relations as $relation) {
214             if ($relation->related_model == 'Crm_Model_Lead') {
215                 $lead = $relation->related_record;
216                 $text .= $translate->_('Lead') . ': ' . $lead->lead_name . "\n";
217                 $leadRelations = Tinebase_Relations::getInstance()->getRelations(get_class($lead), 'Sql', $lead->getId());
218                 foreach ($leadRelations as $leadRelation) {
219                     if ($leadRelation->related_model == 'Addressbook_Model_Contact') {
220                         $contact = $leadRelation->related_record;
221                         $text .= $leadRelation->type . ': ' . $contact->n_fn . ' (' . $contact->org_name . ')' . "\n"
222                             . ((! empty($contact->tel_work)) ?  "\t" . $translate->_('Telephone')   . ': ' . $contact->tel_work   . "\n" : '')
223                             . ((! empty($contact->email)) ?     "\t" . $translate->_('Email')       . ': ' . $contact->email      . "\n" : '');
224                     }
225                 }
226             }
227         }
228         
229         //if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' ' . $text);
230             
231         return $text;
232     }
233 }