]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - include/generic/SugarWidgets/SugarWidgetFielddatetime.php
Release 6.5.16
[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-2013 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         $date = $timedate->fromString($begin);
79
80         if (!$hasTime) {
81             return $this->queryDay(
82                 $layout_def,
83                 $date
84             );
85         }
86
87         return $this->queryDateOp(
88             $this->_get_column_select($layout_def),
89             $date,
90             '=',
91             "datetime"
92         );
93         }
94
95     /**
96      * expandDate
97      *
98      * This function helps to convert a date only value to have a time value as well.  It first checks
99      * to see if a time value exists.  If a time value exists, the function just returns the date value
100      * passed in.  If the date value is the 'Today' macro then some special processing occurs as well.
101      * Finally the time portion is applied depending on whether or not this date should be for the end
102      * in which case the 23:59:59 time value is applied otherwise 00:00:00 is used.
103      *
104      * @param $date String value of the date value to expand
105      * @param bool $end Boolean value indicating whether or not this is for an end time period or not
106      * @return $date TimeDate object with time value applied
107      */
108         protected function expandDate($date, $end = false)
109         {
110             global $timedate;
111             if($this->hasTime($date)) {
112                 return $date;
113             }
114
115         //C.L. Bug 48616 - If the $date is set to the Today macro, then adjust accordingly
116         if(strtolower($date) == 'today')
117         {
118            $startEnd = $timedate->getDayStartEndGMT($timedate->getNow(true));
119            return $end ? $startEnd['end'] : $startEnd['start'];
120         }
121
122         $parsed = $timedate->fromDbDate($date);
123         $date = $timedate->tzUser(new SugarDateTime());
124         $date->setDate($parsed->year, $parsed->month, $parsed->day);
125
126             if($end) {
127                 return $date->setTime(23, 59, 59);
128             } else {
129                 return $date->setTime(0, 0, 0);
130             }
131         }
132
133         function queryFilterBefore($layout_def)
134         {
135         $begin = $this->expandDate($layout_def['input_name0']);
136         return $this->queryDateOp($this->_get_column_select($layout_def), $begin, '<', "datetime");
137         }
138
139         function queryFilterAfter($layout_def)
140         {
141         $begin = $this->expandDate($layout_def['input_name0'], true);
142         return $this->queryDateOp($this->_get_column_select($layout_def), $begin, '>', "datetime");
143         }
144
145         function queryFilterBetween_Dates($layout_def)
146         {
147         $begin = $this->expandDate($layout_def['input_name0']);
148         $end = $this->expandDate($layout_def['input_name1'], true);
149         $column = $this->_get_column_select($layout_def);
150             return "(".$this->queryDateOp($column, $begin, ">=", "datetime")." AND ".
151             $this->queryDateOp($column, $end, "<=", "datetime").")\n";
152         }
153
154         function queryFilterNot_Equals_str($layout_def)
155         {
156                 global $timedate;
157
158         $column = $this->_get_column_select($layout_def);
159         $begin = $layout_def['input_name0'];
160         $hasTime = $this->hasTime($begin);
161         if(!$hasTime){
162             $end = $this->expandDate($begin, true);
163             $begin = $this->expandDate($begin);
164             $cond = $this->queryDateOp($column, $begin, "<", "datetime")." OR ".
165                 $this->queryDateOp($column, $end, ">", "datetime");
166         } else {
167             $cond =  $this->queryDateOp($column, $begin, "!=", "datetime");
168         }
169         return "($column IS NULL OR $cond)";
170         }
171
172     /**
173      * Get assigned or logged in user's current date and time value.
174      * @param boolean $timestamp Format of return value, if set to true, return unix like timestamp , else a formatted date.
175      */
176         function get_users_current_date_time($timestamp=false)
177         {
178                 global $current_user;
179         global $timedate;
180
181         $begin = TimeDate::getInstance()->nowDb();
182         //kbrill bug #13884
183         //$begin = $timedate->to_display_date_time($begin,true,true,$this->assigned_user);
184                 $begin = $timedate->handle_offset($begin, $timedate->get_db_date_time_format(), false, $this->assigned_user);
185
186         if (!$timestamp) {
187                 return $begin;
188         } else {
189                 $begin_parts = explode(' ', $begin);
190                 $date_parts=explode('-', $begin_parts[0]);
191                 $time_parts=explode(':', $begin_parts[1]);
192                 $curr_timestamp=mktime($time_parts[0],$time_parts[1],0,$date_parts[1], $date_parts[2],$date_parts[0]);
193                 return $curr_timestamp;
194         }
195
196         }
197         /**
198          * Get specified date and time for a particalur day, in current user's timezone.
199          * @param int $days Adjust date by this number of days, negative values are valid.
200          * @param time string falg for desired time value, start: minimum time, end: maximum time, default: current time
201          */
202         function get_db_date($days,$time) {
203         global $timedate;
204
205         $begin = date($GLOBALS['timedate']->get_db_date_time_format(), time()+(86400 * $days));  //gmt date with day adjustment applied.
206         //kbrill bug #13884
207         //$begin = $timedate->to_display_date_time($begin,true,true,$this->assigned_user);
208                 $begin = $timedate->handle_offset($begin, $timedate->get_db_date_time_format(), false, $this->assigned_user);
209
210         if ($time=='start') {
211             $begin_parts = explode(' ', $begin);
212             $be = $begin_parts[0] . ' 00:00:00';
213         }
214         else if ($time=='end') {
215             $begin_parts = explode(' ', $begin);
216             $be = $begin_parts[0] . ' 23:59:59';
217         } else {
218             $be=$begin;
219         }
220
221         //convert date to db format without converting to GMT.
222         $begin = $timedate->handle_offset($be, $timedate->get_db_date_time_format(), false, $this->assigned_user);
223
224         return $begin;
225         }
226
227         /**
228          * Get filter string for a date field.
229          * @param array layout_def field def for field being filtered
230          * @param string $begin start date value (in DB format)
231          * @param string $end End date value (in DB format)
232          */
233         function get_start_end_date_filter(& $layout_def, $begin,$end)
234         {
235             if (isset ($layout_def['rel_field'])) {
236                 $field_name = $this->reporter->db->convert(
237                     $this->reporter->db->convert($this->_get_column_select($layout_def), 'date_format', '%Y-%m-%d'),
238                     "CONCAT",
239                     array("' '", $this->reporter->db->convert($layout_def['rel_field'], 'time_format'))
240                 );
241             } else {
242                $field_name = $this->_get_column_select($layout_def);
243             }
244             return $field_name.">=".$this->reporter->db->quoted($begin)." AND ".$field_name."<=".$this->reporter->db->quoted($end)."\n";
245         }
246
247         /**
248          * Create query for binary operation of field of certain type
249          * Produces query like:
250          * arg1 op to_date(arg2), e.g.:
251          *              date_closed < '2009-12-01'
252          * @param string $arg1 1st arg - column name
253          * @param string|DateTime $arg2 2nd arg - value to be converted
254          * @param string $op
255          * @param string $type
256          */
257     protected function queryDateOp($arg1, $arg2, $op, $type)
258     {
259         global $timedate;
260         if($arg2 instanceof DateTime) {
261             $arg2 = $timedate->asDbType($arg2, $type);
262         }
263         return "$arg1 $op ".$this->reporter->db->convert($this->reporter->db->quoted($arg2), $type)."\n";
264     }
265
266     /**
267      * Return current date in required user's TZ
268      * @return SugarDateTime
269      */
270     protected function now()
271     {
272         global $timedate;
273         return $timedate->tzUser($timedate->getNow(), $this->getAssignedUser());
274     }
275
276         /**
277      * Create query from the beginning to the end of certain day
278      * @param array $layout_def
279      * @param SugarDateTime $day
280      */
281     protected function queryDay($layout_def, SugarDateTime $day)
282     {
283         $begin = $day->get_day_begin();
284         $end = $day->get_day_end();
285         return $this->get_start_end_date_filter($layout_def,$begin->asDb(),$end->asDb());
286     }
287
288         function queryFilterTP_yesterday($layout_def)
289         {
290                 global $timedate;
291                 return $this->queryDay($layout_def, $this->now()->get("-1 day"));
292         }
293
294         function queryFilterTP_today($layout_def)
295         {
296                 global $timedate;
297                 return $this->queryDay($layout_def, $this->now());
298         }
299
300         function queryFilterTP_tomorrow(& $layout_def)
301         {
302                 global $timedate;
303                 return $this->queryDay($layout_def, $this->now()->get("+1 day"));
304         }
305
306         function queryFilterTP_last_7_days($layout_def)
307         {
308                 global $timedate;
309
310                 $begin = $this->now()->get("-6 days")->get_day_begin();
311                 $end = $this->now()->get_day_end();
312
313                 return $this->get_start_end_date_filter($layout_def,$begin->asDb(),$end->asDb());
314         }
315
316         function queryFilterTP_next_7_days($layout_def)
317         {
318                 global $timedate;
319
320                 $begin = $this->now()->get_day_begin();
321                 $end = $this->now()->get("+6 days")->get_day_end();
322
323                 return $this->get_start_end_date_filter($layout_def,$begin->asDb(),$end->asDb());
324         }
325
326     /**
327      * Create query from the beginning to the end of certain month
328      * @param array $layout_def
329      * @param SugarDateTime $month
330      */
331     protected function queryMonth($layout_def, $month)
332     {
333         $begin = $month->setTime(0, 0, 0);
334         $end = clone($begin);
335                 $end->setDate($begin->year, $begin->month, $begin->days_in_month)->setTime(23, 59, 59);
336         return $this->get_start_end_date_filter($layout_def,$begin->asDb(),$end->asDb());
337     }
338
339     function queryFilterTP_last_month($layout_def)
340         {
341                 global $timedate;
342                 $month = $this->now();
343                 return $this->queryMonth($layout_def, $month->setDate($month->year, $month->month-1, 1));
344         }
345
346         function queryFilterTP_this_month($layout_def)
347         {
348                 global $timedate;
349
350         //Bug 62414 - take timezone into account when determining current month
351         $now = $this->now();
352         $timezoneOffset = $timedate->getUserUTCOffset();
353         $timezoneOffset = "$timezoneOffset minutes";
354         $now->modify($timezoneOffset);
355
356         return $this->queryMonth($layout_def, $now->get_day_by_index_this_month(0));
357         }
358
359         function queryFilterTP_next_month($layout_def)
360         {
361                 global $timedate;
362                 $month = $this->now();
363                 return $this->queryMonth($layout_def, $month->setDate($month->year, $month->month+1, 1));
364         }
365
366         function queryFilterTP_last_30_days($layout_def)
367         {
368                 global $timedate;
369                 $begin = $this->now()->get("-29 days")->get_day_begin();
370                 $end = $this->now()->get_day_end();
371                 return $this->get_start_end_date_filter($layout_def,$begin->asDb(),$end->asDb());
372         }
373
374         function queryFilterTP_next_30_days($layout_def)
375         {
376                 global $timedate;
377                 $begin = $this->now()->get_day_begin();
378                 $end = $this->now()->get("+29 days")->get_day_end();
379                 return $this->get_start_end_date_filter($layout_def,$begin->asDb(),$end->asDb());
380         }
381
382     /**
383      * Return the between WHERE query for Quarter filter
384      *
385      * Find quarter for given date, modify the start/end with $modifyFilter parameter
386      *
387      * @param $layout_def - Filter layout_def
388      * @param string $modifyFilter - Modification to start/end date, used to select previous/next quarter
389      * @param string $date - Date for which to find the quarter filter, if not set uses current date
390      * @return string - BETWEEN WHERE query for quarter filter
391      */
392     protected function getQuarterFilter($layout_def, $modifyFilter, $date = '')
393     {
394         $timedate = TimeDate::getInstance();
395
396         // See if date is set, if not, use current date
397         if (empty($date)) {
398             $begin = $timedate->getNow(true);
399         } else {
400             $begin = $timedate->fromString($date);
401         }
402
403         $begin->setDate(
404             $begin->year,
405             floor(($begin->month - 1) / 3) * 3 + 1, // Find starting month of quarter
406             1
407         )->setTime(0, 0);
408
409         $end = $begin->get("+3 month")->setTime(23, 59, 59)->get("-1 day");
410
411         // Modify begin/end if filter is set
412         if (!empty($modifyFilter)) {
413             $begin->modify($modifyFilter);
414             $end->modify($modifyFilter);
415         }
416
417         return $this->get_start_end_date_filter($layout_def, $begin->asDb(), $end->asDb());
418     }
419
420     /**
421      * Returns part of query for select
422      *
423      * @param array $layout_def for field
424      * @return string part of select query with last quarter only
425      */
426     public function queryFilterTP_last_quarter($layout_def)
427     {
428         return $this->getQuarterFilter($layout_def, '-3 month');
429     }
430
431     /**
432      * Returns part of query for select
433      *
434      * @param array $layout_def for field
435      * @return string part of select query with this quarter only
436      */
437     public function queryFilterTP_this_quarter($layout_def)
438     {
439         return $this->getQuarterFilter($layout_def, '');
440     }
441
442     /**
443      * Returns part of query for select
444      *
445      * @param array $layout_def for field
446      * @return string part of select query with next quarter only
447      */
448     public function queryFilterTP_next_quarter($layout_def)
449     {
450         return $this->getQuarterFilter($layout_def, '+3 month');
451     }
452
453         function queryFilterTP_last_year($layout_def)
454         {
455                 global $timedate;
456                 $begin = $this->now();
457                 $begin->setDate($begin->year-1, 1, 1)->setTime(0, 0);
458                 $end = clone $begin;
459                 $end->setDate($end->year, 12, 31)->setTime(23, 59, 59);
460                 return $this->get_start_end_date_filter($layout_def,$begin->asDb(),$end->asDb());
461         }
462
463         function queryFilterTP_this_year($layout_def)
464         {
465                 global $timedate;
466                 $begin = $this->now();
467                 $begin->setDate($begin->year, 1, 1)->setTime(0, 0);
468                 $end = clone $begin;
469                 $end->setDate($end->year, 12, 31)->setTime(23, 59, 59);
470                 return $this->get_start_end_date_filter($layout_def,$begin->asDb(),$end->asDb());
471         }
472
473         function queryFilterTP_next_year(& $layout_def)
474         {
475                 global $timedate;
476                 $begin = $this->now();
477                 $begin->setDate($begin->year+1, 1, 1)->setTime(0, 0);
478                 $end = clone $begin;
479                 $end->setDate($end->year, 12, 31)->setTime(23, 59, 59);
480                 return $this->get_start_end_date_filter($layout_def,$begin->asDb(),$end->asDb());
481         }
482
483         function queryGroupBy($layout_def)
484         {
485                 // i guess qualifier and column_function are the same..
486                 if (!empty ($layout_def['qualifier'])) {
487                         $func_name = 'queryGroupBy'.$layout_def['qualifier'];
488                         if (method_exists($this, $func_name)) {
489                                 return $this-> $func_name ($layout_def)." \n";
490                         }
491                 }
492                 return parent :: queryGroupBy($layout_def)." \n";
493         }
494
495         function queryOrderBy($layout_def)
496         {
497         if (!empty ($layout_def['qualifier'])) {
498                         $func_name ='queryOrderBy'.$layout_def['qualifier'];
499                         if (method_exists($this, $func_name)) {
500                                 return $this-> $func_name ($layout_def)."\n";
501                         }
502                 }
503                 $order_by = parent :: queryOrderBy($layout_def)."\n";
504                 return $order_by;
505         }
506
507     function displayListPlain($layout_def) {
508         global $timedate;
509         $content = parent:: displayListPlain($layout_def);
510         // awu: this if condition happens only in Reports where group by month comes back as YYYY-mm format
511         if (count(explode('-',$content)) == 2){
512             return $content;
513         // if date field
514         }elseif(substr_count($layout_def['type'], 'date') > 0){
515             // if date time field
516             if(substr_count($layout_def['type'], 'time') > 0 && $this->get_time_part($content)!= false){
517                 $td = $timedate->to_display_date_time($content);
518                 return $td;
519             }else{// if date only field
520                 $td = $timedate->to_display_date($content, false); // Avoid PHP notice of returning by reference.
521                 return $td;
522             }
523         }
524     }
525
526     function get_time_part($date_time_value)
527     {
528         global $timedate;
529
530         $date_parts=$timedate->split_date_time($date_time_value);
531         if (count($date_parts) > 1) {
532             return $date_parts[1];
533         } else {
534             return false;
535         }
536     }
537
538     function displayList($layout_def) {
539         global $timedate;
540         // i guess qualifier and column_function are the same..
541         if (!empty ($layout_def['column_function'])) {
542             $func_name = 'displayList'.$layout_def['column_function'];
543             if (method_exists($this, $func_name)) {
544                 return $this-> $func_name ($layout_def);
545             }
546         }
547         $content = parent :: displayListPlain($layout_def);
548         return $timedate->to_display_date_time($content);
549     }
550
551         function querySelect(& $layout_def) {
552                 // i guess qualifier and column_function are the same..
553                 if (!empty ($layout_def['column_function'])) {
554                         $func_name = 'querySelect'.$layout_def['column_function'];
555                         if (method_exists($this, $func_name)) {
556                                 return $this-> $func_name ($layout_def)." \n";
557                         }
558                 }
559                 return parent :: querySelect($layout_def)." \n";
560         }
561         function & displayListday(& $layout_def) {
562         $value = parent:: displayListPlain($layout_def);
563         return $value;
564         }
565
566         function & displayListyear(& $layout_def) {
567                 global $app_list_strings;
568         $value = parent:: displayListPlain($layout_def);
569         return $value;
570         }
571
572         function displayListmonth($layout_def)
573         {
574                 global $app_list_strings;
575                 $display = '';
576                 $match = array();
577         if (preg_match('/(\d{4})-(\d\d)/', $this->displayListPlain($layout_def), $match)) {
578                         $match[2] = preg_replace('/^0/', '', $match[2]);
579                         $display = $app_list_strings['dom_cal_month_long'][$match[2]]." {$match[1]}";
580                 }
581                 return $display;
582
583         }
584
585     /**
586      * Returns part of query for select
587      *
588      * @param array $layout_def for field
589      * @return string part of select query with year & month only
590      */
591     function querySelectmonth($layout_def)
592     {
593         $return = $this->_get_column_select($layout_def);
594         if ($layout_def['type'] == 'datetime')
595         {
596             $return = $this->reporter->db->convert($return, 'add_tz_offset');
597         }
598         return $this->reporter->db->convert($return, "date_format", array('%Y-%m')) . ' ' . $this->_get_column_alias($layout_def) . "\n";
599     }
600
601     /**
602      * Returns part of query for group by
603      *
604      * @param array $layout_def for field
605      * @return string part of group by query with year & month only
606      */
607     function queryGroupByMonth($layout_def)
608     {
609         $return = $this->_get_column_select($layout_def);
610         if ($layout_def['type'] == 'datetime')
611         {
612             $return = $this->reporter->db->convert($return, 'add_tz_offset');
613         }
614         return $this->reporter->db->convert($return, "date_format", array('%Y-%m')) . "\n";
615     }
616
617     /**
618      * For oracle we have to return order by string like group by string instead of return field alias
619      *
620      * @param array $layout_def definition of field
621      * @return string order by string for field
622      */
623     function queryOrderByMonth($layout_def)
624     {
625         $return = $this->_get_column_select($layout_def);
626         if ($layout_def['type'] == 'datetime')
627         {
628             $return = $this->reporter->db->convert($return, 'add_tz_offset');
629         }
630         $orderBy = $this->reporter->db->convert($return, "date_format", array('%Y-%m'));
631
632         if (empty($layout_def['sort_dir']) || $layout_def['sort_dir'] == 'a')
633         {
634             return $orderBy . " ASC\n";
635         }
636         else
637         {
638             return $orderBy . " DESC\n";
639         }
640     }
641
642     /**
643      * Returns part of query for select
644      *
645      * @param array $layout_def for field
646      * @return string part of select query with year & month & day
647      */
648     function querySelectday($layout_def)
649     {
650         $return = $this->_get_column_select($layout_def);
651         if ($layout_def['type'] == 'datetime')
652         {
653             $return = $this->reporter->db->convert($return, 'add_tz_offset');
654         }
655         return $this->reporter->db->convert($return, "date_format", array('%Y-%m-%d')) . ' ' . $this->_get_column_alias($layout_def) . "\n";
656     }
657
658     /**
659      * Returns part of query for group by
660      *
661      * @param array $layout_def for field
662      * @return string part of group by query with year & month & day
663      */
664     function queryGroupByDay($layout_def)
665     {
666         $return = $this->_get_column_select($layout_def);
667         if ($layout_def['type'] == 'datetime')
668         {
669             $return = $this->reporter->db->convert($return, 'add_tz_offset');
670         }
671         return $this->reporter->db->convert($return, "date_format", array('%Y-%m-%d')) . "\n";
672     }
673
674     /**
675      * Returns part of query for select
676      *
677      * @param array $layout_def for field
678      * @return string part of select query with year only
679      */
680     function querySelectyear($layout_def)
681     {
682         $return = $this->_get_column_select($layout_def);
683         if ($layout_def['type'] == 'datetime')
684         {
685             $return = $this->reporter->db->convert($return, 'add_tz_offset');
686         }
687         return $this->reporter->db->convert($return, "date_format", array('%Y')) . ' ' . $this->_get_column_alias($layout_def) . "\n";
688     }
689
690     /**
691      * Returns part of query for group by
692      *
693      * @param array $layout_def for field
694      * @return string part of group by query with year only
695      */
696     function queryGroupByYear($layout_def)
697     {
698         $return = $this->_get_column_select($layout_def);
699         if ($layout_def['type'] == 'datetime')
700         {
701             $return = $this->reporter->db->convert($return, 'add_tz_offset');
702         }
703         return $this->reporter->db->convert($return, "date_format", array('%Y')) . "\n";
704     }
705
706         function querySelectquarter($layout_def)
707         {
708             $column = $this->_get_column_select($layout_def);
709             return $this->reporter->db->convert($this->reporter->db->convert($column, "date_format", array('%Y')),
710                         'CONCAT',
711                     array("'-'", $this->reporter->db->convert($column, "quarter")))
712                 ." ".$this->_get_column_alias($layout_def)."\n";
713         }
714
715         function displayListquarter(& $layout_def) {
716                 $match = array();
717         if (preg_match('/(\d{4})-(\d)/', $this->displayListPlain($layout_def), $match)) {
718                         return "Q".$match[2]." ".$match[1];
719                 }
720                 return '';
721
722         }
723
724         function queryGroupByQuarter($layout_def)
725         {
726                 $this->getReporter();
727         $column = $this->_get_column_select($layout_def);
728             return $this->reporter->db->convert($this->reporter->db->convert($column, "date_format", array('%Y')),
729                         'CONCAT',
730                     array("'-'", $this->reporter->db->convert($column, "quarter")));
731         }
732
733     /**
734      * For oracle we have to return order by string like group by string instead of return field alias
735      *
736      * @param array $layout_def definition of field
737      * @return string order by string for field
738      */
739     public function queryOrderByQuarter($layout_def)
740     {
741         $column = $this->_get_column_select($layout_def);
742         $orderBy = $this->reporter->db->convert(
743             $this->reporter->db->convert($column, "date_format", array('%Y')),
744             'CONCAT',
745             array("'-'", $this->reporter->db->convert($column, "quarter"))
746         );
747
748
749         if (empty($layout_def['sort_dir']) || $layout_def['sort_dir'] == 'a')
750         {
751             return $orderBy . " ASC\n";
752         }
753         else
754         {
755             return $orderBy . " DESC\n";
756         }
757     }
758
759     function displayInput(&$layout_def) {
760         global $timedate, $current_language, $app_strings;
761         $home_mod_strings = return_module_language($current_language, 'Home');
762         $filterTypes = array(' '                 => $app_strings['LBL_NONE'],
763                              'TP_today'         => $home_mod_strings['LBL_TODAY'],
764                              'TP_yesterday'     => $home_mod_strings['LBL_YESTERDAY'],
765                              'TP_tomorrow'      => $home_mod_strings['LBL_TOMORROW'],
766                              'TP_this_month'    => $home_mod_strings['LBL_THIS_MONTH'],
767                              'TP_this_year'     => $home_mod_strings['LBL_THIS_YEAR'],
768                              'TP_last_30_days'  => $home_mod_strings['LBL_LAST_30_DAYS'],
769                              'TP_last_7_days'   => $home_mod_strings['LBL_LAST_7_DAYS'],
770                              'TP_last_month'    => $home_mod_strings['LBL_LAST_MONTH'],
771                              'TP_last_year'     => $home_mod_strings['LBL_LAST_YEAR'],
772                              'TP_next_30_days'  => $home_mod_strings['LBL_NEXT_30_DAYS'],
773                              'TP_next_7_days'   => $home_mod_strings['LBL_NEXT_7_DAYS'],
774                              'TP_next_month'    => $home_mod_strings['LBL_NEXT_MONTH'],
775                              'TP_next_year'     => $home_mod_strings['LBL_NEXT_YEAR'],
776                              );
777
778         $cal_dateformat = $timedate->get_cal_date_format();
779         $str = "<select name='type_{$layout_def['name']}'>";
780         $str .= get_select_options_with_id($filterTypes, (empty($layout_def['input_name0']) ? '' : $layout_def['input_name0']));
781 //        foreach($filterTypes as $value => $label) {
782 //            $str .= '<option value="' . $value . '">' . $label. '</option>';
783 //        }
784         $str .= "</select>";
785
786
787         return $str;
788     }
789
790     /**
791      * @param  $date
792      * @return bool false if the date is a only a date, true if the date includes time.
793      */
794     protected function hasTime($date)
795     {
796         return strlen(trim($date)) < 11 ? false : true;
797     }
798
799 }