]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - include/generic/SugarWidgets/SugarWidgetFielddatetime.php
Release 6.4.0
[Github/sugarcrm.git] / include / generic / SugarWidgets / SugarWidgetFielddatetime.php
1 <?php
2 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3 /*********************************************************************************
4  * SugarCRM Community Edition is a customer relationship management program developed by
5  * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc.
6  * 
7  * This program is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU Affero General Public License version 3 as published by the
9  * Free Software Foundation with the addition of the following permission added
10  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
11  * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
12  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
13  * 
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
17  * details.
18  * 
19  * You should have received a copy of the GNU Affero General Public License along with
20  * this program; if not, see http://www.gnu.org/licenses or write to the Free
21  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22  * 02110-1301 USA.
23  * 
24  * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
25  * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
26  * 
27  * The interactive user interfaces in modified source and object code versions
28  * of this program must display Appropriate Legal Notices, as required under
29  * Section 5 of the GNU Affero General Public License version 3.
30  * 
31  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
32  * these Appropriate Legal Notices must retain the display of the "Powered by
33  * SugarCRM" logo. If the display of the logo is not reasonably feasible for
34  * technical reasons, the Appropriate Legal Notices must display the words
35  * "Powered by SugarCRM".
36  ********************************************************************************/
37
38
39
40
41 class SugarWidgetFieldDateTime extends SugarWidgetReportField
42 {
43         var $reporter;
44         var $assigned_user=null;
45
46     function SugarWidgetFieldDateTime($layout_manager)
47     {
48         parent::SugarWidgetReportField($layout_manager);
49     }
50
51         // get the reporter attribute
52     // deprecated, now called in the constructor
53     /**
54      * @deprecated
55      */
56         function getReporter() {
57         }
58
59         // get the assigned user of the report
60         function getAssignedUser()
61         {
62                 $json_obj = getJSONobj();
63
64                 $report_def_str = $json_obj->decode($this->reporter->report_def_str);
65
66                 if(empty($report_def_str['assigned_user_id'])) return null;
67
68                 $this->assigned_user = new User();
69                 $this->assigned_user->retrieve($report_def_str['assigned_user_id']);
70                 return $this->assigned_user;
71         }
72
73         function queryFilterOn($layout_def)
74         {
75                 global $timedate;
76         $begin = $layout_def['input_name0'];
77         $hasTime = $this->hasTime($begin);
78         if(!$hasTime)
79         {
80             return $this->queryDay($layout_def, $timedate->fromDbDate($begin));
81         }
82         return $this->queryDateOp($this->_get_column_select($layout_def), $begin, '=', "datetime");
83         }
84
85     /**
86      * expandDate
87      *
88      * This function helps to convert a date only value to have a time value as well.  It first checks
89      * to see if a time value exists.  If a time value exists, the function just returns the date value
90      * passed in.  If the date value is the 'Today' macro then some special processing occurs as well.
91      * Finally the time portion is applied depending on whether or not this date should be for the end
92      * in which case the 23:59:59 time value is applied otherwise 00:00:00 is used.
93      *
94      * @param $date String value of the date value to expand
95      * @param bool $end Boolean value indicating whether or not this is for an end time period or not
96      * @return $date TimeDate object with time value applied
97      */
98         protected function expandDate($date, $end = false)
99         {
100             global $timedate;
101             if($this->hasTime($date)) {
102                 return $date;
103             }
104
105         //C.L. Bug 48616 - If the $date is set to the Today macro, then adjust accordingly
106         if(strtolower($date) == 'today')
107         {
108            $startEnd = $timedate->getDayStartEndGMT($timedate->getNow(true));
109            return $end ? $startEnd['end'] : $startEnd['start'];
110         }
111
112         $parsed = $timedate->fromDbDate($date);
113         $date = $timedate->tzUser(new SugarDateTime());
114         $date->setDate($parsed->year, $parsed->month, $parsed->day);
115
116             if($end) {
117                 return $date->setTime(23, 59, 59);
118             } else {
119                 return $date->setTime(0, 0, 0);
120             }
121         }
122
123         function queryFilterBefore($layout_def)
124         {
125         $begin = $this->expandDate($layout_def['input_name0']);
126         return $this->queryDateOp($this->_get_column_select($layout_def), $begin, '<', "datetime");
127         }
128
129         function queryFilterAfter($layout_def)
130         {
131         $begin = $this->expandDate($layout_def['input_name0'], true);
132         return $this->queryDateOp($this->_get_column_select($layout_def), $begin, '>', "datetime");
133         }
134
135         function queryFilterBetween_Dates($layout_def)
136         {
137         $begin = $this->expandDate($layout_def['input_name0']);
138         $end = $this->expandDate($layout_def['input_name1'], true);
139         $column = $this->_get_column_select($layout_def);
140             return "(".$this->queryDateOp($column, $begin, ">=", "datetime")." AND ".
141             $this->queryDateOp($column, $end, "<=", "datetime").")\n";
142         }
143
144         function queryFilterNot_Equals_str($layout_def)
145         {
146                 global $timedate;
147
148         $column = $this->_get_column_select($layout_def);
149         $begin = $layout_def['input_name0'];
150         $hasTime = $this->hasTime($begin);
151         if(!$hasTime){
152             $end = $this->expandDate($begin, true);
153             $begin = $this->expandDate($begin);
154             $cond = $this->queryDateOp($column, $begin, "<", "datetime")." OR ".
155                 $this->queryDateOp($column, $end, ">", "datetime");
156         } else {
157             $cond =  $this->queryDateOp($column, $begin, "!=", "datetime");
158         }
159         return "($column IS NULL OR $cond)";
160         }
161
162     /**
163      * Get assigned or logged in user's current date and time value.
164      * @param boolean $timestamp Format of return value, if set to true, return unix like timestamp , else a formatted date.
165      */
166         function get_users_current_date_time($timestamp=false)
167         {
168                 global $current_user;
169         global $timedate;
170
171         $begin = TimeDate::getInstance()->nowDb();
172         //kbrill bug #13884
173         //$begin = $timedate->to_display_date_time($begin,true,true,$this->assigned_user);
174                 $begin = $timedate->handle_offset($begin, $timedate->get_db_date_time_format(), false, $this->assigned_user);
175
176         if (!$timestamp) {
177                 return $begin;
178         } else {
179                 $begin_parts = explode(' ', $begin);
180                 $date_parts=explode('-', $begin_parts[0]);
181                 $time_parts=explode(':', $begin_parts[1]);
182                 $curr_timestamp=mktime($time_parts[0],$time_parts[1],0,$date_parts[1], $date_parts[2],$date_parts[0]);
183                 return $curr_timestamp;
184         }
185
186         }
187         /**
188          * Get specified date and time for a particalur day, in current user's timezone.
189          * @param int $days Adjust date by this number of days, negative values are valid.
190          * @param time string falg for desired time value, start: minimum time, end: maximum time, default: current time
191          */
192         function get_db_date($days,$time) {
193         global $timedate;
194
195         $begin = date($GLOBALS['timedate']->get_db_date_time_format(), time()+(86400 * $days));  //gmt date with day adjustment applied.
196         //kbrill bug #13884
197         //$begin = $timedate->to_display_date_time($begin,true,true,$this->assigned_user);
198                 $begin = $timedate->handle_offset($begin, $timedate->get_db_date_time_format(), false, $this->assigned_user);
199
200         if ($time=='start') {
201             $begin_parts = explode(' ', $begin);
202             $be = $begin_parts[0] . ' 00:00:00';
203         }
204         else if ($time=='end') {
205             $begin_parts = explode(' ', $begin);
206             $be = $begin_parts[0] . ' 23:59:59';
207         } else {
208             $be=$begin;
209         }
210
211         //convert date to db format without converting to GMT.
212         $begin = $timedate->handle_offset($be, $timedate->get_db_date_time_format(), false, $this->assigned_user);
213
214         return $begin;
215         }
216
217         /**
218          * Get filter string for a date field.
219          * @param array layout_def field def for field being filtered
220          * @param string $begin start date value (in DB format)
221          * @param string $end End date value (in DB format)
222          */
223         function get_start_end_date_filter(& $layout_def, $begin,$end)
224         {
225             if (isset ($layout_def['rel_field'])) {
226                 $field_name = $this->reporter->db->convert(
227                     $this->reporter->db->convert($this->_get_column_select($layout_def), 'date_format', '%Y-%m-%d'),
228                     "CONCAT",
229                     array("' '", $this->reporter->db->convert($layout_def['rel_field'], 'time_format'))
230                 );
231             } else {
232                $field_name = $this->_get_column_select($layout_def);
233             }
234             return $field_name.">=".$this->reporter->db->quoted($begin)." AND ".$field_name."<=".$this->reporter->db->quoted($end)."\n";
235         }
236
237         /**
238          * Create query for binary operation of field of certain type
239          * Produces query like:
240          * arg1 op to_date(arg2), e.g.:
241          *              date_closed < '2009-12-01'
242          * @param string $arg1 1st arg - column name
243          * @param string|DateTime $arg2 2nd arg - value to be converted
244          * @param string $op
245          * @param string $type
246          */
247     protected function queryDateOp($arg1, $arg2, $op, $type)
248     {
249         global $timedate;
250         if($arg2 instanceof DateTime) {
251             $arg2 = $timedate->asDbType($arg2, $type);
252         }
253         return "$arg1 $op ".$this->reporter->db->convert($this->reporter->db->quoted($arg2), $type)."\n";
254     }
255
256     /**
257      * Return current date in required user's TZ
258      * @return SugarDateTime
259      */
260     protected function now()
261     {
262         global $timedate;
263         return $timedate->tzUser($timedate->getNow(), $this->getAssignedUser());
264     }
265
266         /**
267      * Create query from the beginning to the end of certain day
268      * @param array $layout_def
269      * @param SugarDateTime $day
270      */
271     protected function queryDay($layout_def, SugarDateTime $day)
272     {
273         $begin = $day->get_day_begin();
274         $end = $day->get_day_end();
275         return $this->get_start_end_date_filter($layout_def,$begin->asDb(),$end->asDb());
276     }
277
278         function queryFilterTP_yesterday($layout_def)
279         {
280                 global $timedate;
281                 return $this->queryDay($layout_def, $this->now()->get("-1 day"));
282         }
283
284         function queryFilterTP_today($layout_def)
285         {
286                 global $timedate;
287                 return $this->queryDay($layout_def, $this->now());
288         }
289
290         function queryFilterTP_tomorrow(& $layout_def)
291         {
292                 global $timedate;
293                 return $this->queryDay($layout_def, $this->now()->get("+1 day"));
294         }
295
296         function queryFilterTP_last_7_days($layout_def)
297         {
298                 global $timedate;
299
300                 $begin = $this->now()->get("-6 days")->get_day_begin();
301                 $end = $this->now()->get_day_end();
302
303                 return $this->get_start_end_date_filter($layout_def,$begin->asDb(),$end->asDb());
304         }
305
306         function queryFilterTP_next_7_days($layout_def)
307         {
308                 global $timedate;
309
310                 $begin = $this->now()->get_day_begin();
311                 $end = $this->now()->get("+6 days")->get_day_end();
312
313                 return $this->get_start_end_date_filter($layout_def,$begin->asDb(),$end->asDb());
314         }
315
316     /**
317      * Create query from the beginning to the end of certain month
318      * @param array $layout_def
319      * @param SugarDateTime $month
320      */
321     protected function queryMonth($layout_def, $month)
322     {
323         $begin = $month->setTime(0, 0, 0);
324         $end = clone($begin);
325                 $end->setDate($begin->year, $begin->month, $begin->days_in_month)->setTime(23, 59, 59);
326         return $this->get_start_end_date_filter($layout_def,$begin->asDb(),$end->asDb());
327     }
328
329     function queryFilterTP_last_month($layout_def)
330         {
331                 global $timedate;
332                 $month = $this->now();
333                 return $this->queryMonth($layout_def, $month->setDate($month->year, $month->month-1, 1));
334         }
335
336         function queryFilterTP_this_month($layout_def)
337         {
338                 global $timedate;
339                 return $this->queryMonth($layout_def, $this->now()->get_day_by_index_this_month(1));
340         }
341
342         function queryFilterTP_next_month($layout_def)
343         {
344                 global $timedate;
345                 $month = $this->now();
346                 return $this->queryMonth($layout_def, $month->setDate($month->year, $month->month+1, 1));
347         }
348
349         function queryFilterTP_last_30_days($layout_def)
350         {
351                 global $timedate;
352                 $begin = $this->now()->get("-29 days")->get_day_begin();
353                 $end = $this->now()->get_day_end();
354                 return $this->get_start_end_date_filter($layout_def,$begin->asDb(),$end->asDb());
355         }
356
357         function queryFilterTP_next_30_days($layout_def)
358         {
359                 global $timedate;
360                 $begin = $this->now()->get_day_begin();
361                 $end = $this->now()->get("+29 days")->get_day_end();
362                 return $this->get_start_end_date_filter($layout_def,$begin->asDb(),$end->asDb());
363         }
364
365
366         function queryFilterTP_this_quarter($layout_def)
367         {
368                 global $timedate;
369                 $begin = $this->now();
370                 $begin->setDate($begin->year, floor(($begin->month-1)/3)*3+1, 1)->setTime(0, 0);
371                 $end = $begin->get("+3 month")->setTime(23, 59, 59);
372                 return $this->get_start_end_date_filter($layout_def,$begin->asDb(),$end->asDb());
373         }
374
375         function queryFilterTP_last_year($layout_def)
376         {
377                 global $timedate;
378                 $begin = $this->now();
379                 $begin->setDate($begin->year-1, 1, 1)->setTime(0, 0);
380                 $end = clone $begin;
381                 $end->setDate($end->year, 12, 31)->setTime(23, 59, 59);
382                 return $this->get_start_end_date_filter($layout_def,$begin->asDb(),$end->asDb());
383         }
384
385         function queryFilterTP_this_year($layout_def)
386         {
387                 global $timedate;
388                 $begin = $this->now();
389                 $begin->setDate($begin->year, 1, 1)->setTime(0, 0);
390                 $end = clone $begin;
391                 $end->setDate($end->year, 12, 31)->setTime(23, 59, 59);
392                 return $this->get_start_end_date_filter($layout_def,$begin->asDb(),$end->asDb());
393         }
394
395         function queryFilterTP_next_year(& $layout_def)
396         {
397                 global $timedate;
398                 $begin = $this->now();
399                 $begin->setDate($begin->year+1, 1, 1)->setTime(0, 0);
400                 $end = clone $begin;
401                 $end->setDate($end->year, 12, 31)->setTime(23, 59, 59);
402                 return $this->get_start_end_date_filter($layout_def,$begin->asDb(),$end->asDb());
403         }
404
405         function queryGroupBy($layout_def)
406         {
407                 // i guess qualifier and column_function are the same..
408                 if (!empty ($layout_def['qualifier'])) {
409                         $func_name = 'queryGroupBy'.$layout_def['qualifier'];
410                         if (method_exists($this, $func_name)) {
411                                 return $this-> $func_name ($layout_def)." \n";
412                         }
413                 }
414                 return parent :: queryGroupBy($layout_def)." \n";
415         }
416
417         function queryOrderBy($layout_def)
418         {
419         if (!empty ($layout_def['qualifier'])) {
420                         $func_name ='queryOrderBy'.$layout_def['qualifier'];
421                         if (method_exists($this, $func_name)) {
422                                 return $this-> $func_name ($layout_def)."\n";
423                         }
424                 }
425                 $order_by = parent :: queryOrderBy($layout_def)."\n";
426                 return $order_by;
427         }
428
429     function displayListPlain($layout_def) {
430         global $timedate;
431         $content = parent:: displayListPlain($layout_def);
432         // awu: this if condition happens only in Reports where group by month comes back as YYYY-mm format
433         if (count(explode('-',$content)) == 2){
434             return $content;
435         // if date field
436         }elseif(substr_count($layout_def['type'], 'date') > 0){
437             // if date time field
438             if(substr_count($layout_def['type'], 'time') > 0 && $this->get_time_part($content)!= false){
439                 $td = $timedate->to_display_date_time($content);
440                 return $td;
441             }else{// if date only field
442                 $td = $timedate->to_display_date($content, false); // avoid php notice of returing by reference
443                 return $td;
444             }
445         }
446     }
447
448     function get_time_part($date_time_value)
449     {
450         global $timedate;
451
452         $date_parts=$timedate->split_date_time($date_time_value);
453         if (count($date_parts) > 1) {
454             return $date_parts[1];
455         } else {
456             return false;
457         }
458     }
459
460     function displayList($layout_def) {
461         global $timedate;
462         // i guess qualifier and column_function are the same..
463         if (!empty ($layout_def['column_function'])) {
464             $func_name = 'displayList'.$layout_def['column_function'];
465             if (method_exists($this, $func_name)) {
466                 return $this-> $func_name ($layout_def);
467             }
468         }
469         $content = parent :: displayListPlain($layout_def);
470         return $timedate->to_display_date_time($content);
471     }
472
473         function querySelect(& $layout_def) {
474                 // i guess qualifier and column_function are the same..
475                 if (!empty ($layout_def['column_function'])) {
476                         $func_name = 'querySelect'.$layout_def['column_function'];
477                         if (method_exists($this, $func_name)) {
478                                 return $this-> $func_name ($layout_def)." \n";
479                         }
480                 }
481                 return parent :: querySelect($layout_def)." \n";
482         }
483         function & displayListday(& $layout_def) {
484                 return parent:: displayListPlain($layout_def);
485         }
486
487         function & displayListyear(& $layout_def) {
488                 global $app_list_strings;
489         return parent:: displayListPlain($layout_def);
490         }
491
492         function displayListmonth($layout_def)
493         {
494                 global $app_list_strings;
495                 $display = '';
496                 $match = array();
497         if (preg_match('/(\d{4})-(\d\d)/', $this->displayListPlain($layout_def), $match)) {
498                         $match[2] = preg_replace('/^0/', '', $match[2]);
499                         $display = $app_list_strings['dom_cal_month_long'][$match[2]]." {$match[1]}";
500                 }
501                 return $display;
502
503         }
504
505         function querySelectmonth($layout_def)
506         {
507             return $this->reporter->db->convert($this->_get_column_select($layout_def), "date_format", array('%Y-%m'))." ".$this->_get_column_alias($layout_def)."\n";
508         }
509
510         function queryGroupByMonth($layout_def)
511         {
512         return $this->reporter->db->convert($this->_get_column_select($layout_def), "date_format", array('%Y-%m'))."\n";
513         }
514
515         function querySelectday($layout_def)
516         {
517             return $this->reporter->db->convert($this->_get_column_select($layout_def), "date_format", array('%Y-%m-%d'))." ".$this->_get_column_alias($layout_def)."\n";
518         }
519
520         function queryGroupByDay($layout_def)
521         {
522             return $this->reporter->db->convert($this->_get_column_select($layout_def), "date_format", array('%Y-%m-%d'))."\n";
523         }
524
525         function querySelectyear($layout_def)
526         {
527             return $this->reporter->db->convert($this->_get_column_select($layout_def), "date_format", array('%Y'))." ".$this->_get_column_alias($layout_def)."\n";
528         }
529
530         function queryGroupByYear($layout_def)
531         {
532             return $this->reporter->db->convert($this->_get_column_select($layout_def), "date_format", array('%Y'))."\n";
533         }
534
535         function querySelectquarter($layout_def)
536         {
537             $column = $this->_get_column_select($layout_def);
538             return $this->reporter->db->convert($this->reporter->db->convert($column, "date_format", array('%Y')),
539                         'CONCAT',
540                     array("'-'", $this->reporter->db->convert($column, "quarter")))
541                 ." ".$this->_get_column_alias($layout_def)."\n";
542         }
543
544         function displayListquarter(& $layout_def) {
545                 $match = array();
546         if (preg_match('/(\d{4})-(\d)/', $this->displayListPlain($layout_def), $match)) {
547                         return "Q".$match[2]." ".$match[1];
548                 }
549                 return '';
550
551         }
552
553         function queryGroupByQuarter($layout_def)
554         {
555                 $this->getReporter();
556         $column = $this->_get_column_select($layout_def);
557             return $this->reporter->db->convert($this->reporter->db->convert($column, "date_format", array('%Y')),
558                         'CONCAT',
559                     array("'-'", $this->reporter->db->convert($column, "quarter")));
560         }
561
562     function displayInput(&$layout_def) {
563         global $timedate, $current_language, $app_strings;
564         $home_mod_strings = return_module_language($current_language, 'Home');
565         $filterTypes = array(' '                 => $app_strings['LBL_NONE'],
566                              'TP_today'         => $home_mod_strings['LBL_TODAY'],
567                              'TP_yesterday'     => $home_mod_strings['LBL_YESTERDAY'],
568                              'TP_tomorrow'      => $home_mod_strings['LBL_TOMORROW'],
569                              'TP_this_month'    => $home_mod_strings['LBL_THIS_MONTH'],
570                              'TP_this_year'     => $home_mod_strings['LBL_THIS_YEAR'],
571                              'TP_last_30_days'  => $home_mod_strings['LBL_LAST_30_DAYS'],
572                              'TP_last_7_days'   => $home_mod_strings['LBL_LAST_7_DAYS'],
573                              'TP_last_month'    => $home_mod_strings['LBL_LAST_MONTH'],
574                              'TP_last_year'     => $home_mod_strings['LBL_LAST_YEAR'],
575                              'TP_next_30_days'  => $home_mod_strings['LBL_NEXT_30_DAYS'],
576                              'TP_next_7_days'   => $home_mod_strings['LBL_NEXT_7_DAYS'],
577                              'TP_next_month'    => $home_mod_strings['LBL_NEXT_MONTH'],
578                              'TP_next_year'     => $home_mod_strings['LBL_NEXT_YEAR'],
579                              );
580
581         $cal_dateformat = $timedate->get_cal_date_format();
582         $str = "<select name='type_{$layout_def['name']}'>";
583         $str .= get_select_options_with_id($filterTypes, (empty($layout_def['input_name0']) ? '' : $layout_def['input_name0']));
584 //        foreach($filterTypes as $value => $label) {
585 //            $str .= '<option value="' . $value . '">' . $label. '</option>';
586 //        }
587         $str .= "</select>";
588
589
590         return $str;
591     }
592
593     /**
594      * @param  $date
595      * @return bool false if the date is a only a date, true if the date includes time.
596      */
597     protected function hasTime($date)
598     {
599         return strlen(trim($date)) < 11 ? false : true;
600     }
601
602 }