source: contrib/Timesheet/inc/class.botimesheetooo.inc.php @ 3526

Revision 3526, 23.3 KB checked in by afernandes, 13 years ago (diff)

Ticket #1416 - Disponibilizado modulos Timesheet e DMS para a comunidade.

  • Property svn:executable set to *
Line 
1<?php
2/**
3 * TimeSheet - business object
4 *
5 * @link http://www.egroupware.org
6 * @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
7 * @package timesheet
8 * @copyright (c) 2005/6 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
9 * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
10 * @version $Id: class.botimesheet.inc.php 24276 2007-07-10 07:35:18Z ralfbecker $
11 */
12
13require_once(PHPGW_INCLUDE_ROOT.'/etemplate/inc/class.so_sql.inc.php');
14
15if (!defined('TIMESHEET_APP'))
16{
17        define('TIMESHEET_APP','timesheet');
18}
19
20/**
21 * Business object of the TimeSheet
22 *
23 * Uses eTemplate's so_sql as storage object (Table: phpgw_timesheet).
24 */
25class botimesheet extends so_sql
26{
27        /**
28         * Timesheets config data
29         *
30         * @var array
31         */
32        var $config = array();
33
34
35        /**
36         * Timesheets config data
37         *
38         * @var array
39         */
40        var $config_data = array();
41        /**
42         * Should we show a quantity sum, makes only sense if we sum up identical units (can be used to sum up negative (over-)time)
43         *
44         * @var boolean
45         */
46        var $quantity_sum=false;
47        /**
48         * Timestaps that need to be adjusted to user-time on reading or saving
49         *
50         * @var array
51         */
52        var $timestamps = array(
53                'ts_start','ts_modified'
54        );
55        /**
56         * Offset in secconds between user and server-time,     it need to be add to a server-time to get the user-time
57         * or substracted from a user-time to get the server-time
58         *
59         * @var int
60         */
61        var $tz_offset_s;
62        /**
63         * Current time as timestamp in user-time
64         *
65         * @var int
66         */
67        var $now;
68        /**
69         * Start of today in user-time
70         *
71         * @var int
72         */
73        var $today;
74        /**
75         * Filter for search limiting the date-range
76         *
77         * @var array
78         */
79        var $date_filters = array(      // Start: year,month,day,week, End: year,month,day,week
80                'Today'       => array(0,0,0,0,  0,0,1,0),
81                'Yesterday'   => array(0,0,-1,0, 0,0,0,0),
82                'This week'   => array(0,0,0,0,  0,0,0,1),
83                'Last week'   => array(0,0,0,-1, 0,0,0,0),
84                'This month'  => array(0,0,0,0,  0,1,0,0),
85                'Last month'  => array(0,-1,0,0, 0,0,0,0),
86                '2 month ago' => array(0,-2,0,0, 0,-1,0,0),
87                'This year'   => array(0,0,0,0,  1,0,0,0),
88                'Last year'   => array(-1,0,0,0, 0,0,0,0),
89                '2 years ago' => array(-2,0,0,0, -1,0,0,0),
90                '3 years ago' => array(-3,0,0,0, -2,0,0,0),
91        );
92        /**
93         * Reference to the (bo)link class instanciated at $GLOBALS['phpgw']->link
94         *
95         * @var bolink
96         */
97        var $link;
98        /**
99         * Grants: $GLOBALS['phpgw']->acl->get_grants(TIMESHEET_APP);
100         *
101         * @var array
102         */     
103        var $grants;
104        /**
105         * Sums of the last search in keys duration and price
106         *
107         * @var array
108         */
109        var $summary;
110        /**
111         * Array with boolean values in keys 'day', 'week' or 'month', for the sums to return in the search
112         *
113         * @var array
114         */
115        var $show_sums;
116
117        var $customfields=array();
118       
119        function botimesheet()
120        {
121                $this->so_sql(TIMESHEET_APP,'phpgw_timesheet');
122
123                $this->config =& CreateObject('phpgwapi.config',TIMESHEET_APP);
124                $this->config->read_repository();
125                $this->config_data =& $this->config->config_data;
126                $this->quantity_sum = $this->config_data['quantity_sum'] == 'true';
127
128                if (isset($this->config_data['customfields']) && is_array($this->config_data['customfields']))
129                {
130                        $this->customfields = $this->config_data['customfields'];
131                }
132
133                if (!is_object($GLOBALS['phpgw']->datetime))
134                {
135                        $GLOBALS['phpgw']->datetime =& CreateObject('phpgwapi.datetime');
136                }
137                $this->tz_offset_s = $GLOBALS['phpgw']->datetime->tz_offset;
138                $this->now = time() + $this->tz_offset_s;       // time() is server-time and we need a user-time
139                $this->today = mktime(0,0,0,date('m',$this->now),date('d',$this->now),date('Y',$this->now));
140
141                // save us in $GLOBALS['botimesheet'] for ExecMethod used in hooks
142                if (!is_object($GLOBALS['botimesheet']))
143                {
144                        $GLOBALS['botimesheet'] =& $this;
145                }
146                // instanciation of link-class has to be after making us globaly availible, as it calls us to get the search_link
147                if (!is_object($GLOBALS['phpgw']->link))
148                {
149                        $GLOBALS['phpgw']->link =& CreateObject('phpgwapi.bolink');
150                }
151                $this->link =& $GLOBALS['phpgw']->link;
152               
153                $this->grants = $GLOBALS['phpgw']->acl->get_grants(TIMESHEET_APP);
154        }
155       
156        /**
157         * get list of specified grants as uid => Username pairs
158         *
159         * @param int $required=EGW_ACL_READ
160         * @return array with uid => Username pairs
161         */
162        function grant_list($required=EGW_ACL_READ)
163        {
164                $result = array();
165                foreach($this->grants as $uid => $grant)
166                {
167                        if ($grant & $required)
168                        {
169                                $result[$uid] = $GLOBALS['phpgw']->common->grab_owner_name($uid);
170                        }
171                }
172                natcasesort($result);
173
174                return $result;
175        }
176       
177        /**
178         * checks if the user has enough rights for a certain operation
179         *
180         * Rights are given via owner grants or role based acl
181         *
182         * @param int $required EGW_ACL_READ, EGW_ACL_WRITE, EGW_ACL_ADD, EGW_ACL_DELETE, EGW_ACL_BUDGET, EGW_ACL_EDIT_BUDGET
183         * @param array/int $data=null project or project-id to use, default the project in $this->data
184         * @return boolean true if the rights are ok, null if not found, false if no rights
185         */
186        function check_acl($required,$data=null)
187        {
188                if (!$data)
189                {
190                        $data =& $this->data;
191                }
192                if (!is_array($data))
193                {
194                        $save_data = $this->data;
195                        $data = $this->read($data,true);
196                        $this->data = $save_data;
197                       
198                        if (!$data) return null;        // entry not found
199                }
200                $rights = $this->grants[$data['ts_owner']];
201               
202                return $data && !!($rights & $required);
203        }
204       
205        function date_filter($name,&$start,&$end_param)
206        {
207                $end = $end_param;
208
209                if ($name == 'custom' && $start)
210                {
211                        if ($end)
212                        {
213                                $end += 24*60*60;
214                        }
215                        else
216                        {
217                                $end = $start + 8*24*60*60;
218                        }
219                }
220                else
221                {
222                        if (!isset($this->date_filters[$name]))
223                        {
224                                return '1=1';
225                        }
226                        $year  = (int) date('Y',$this->today);
227                        $month = (int) date('m',$this->today);
228                        $day   = (int) date('d',$this->today);
229       
230                        list($syear,$smonth,$sday,$sweek,$eyear,$emonth,$eday,$eweek) = $this->date_filters[$name];
231                       
232                        if ($syear || $eyear)
233                        {
234                                $start = mktime(0,0,0,1,1,$syear+$year);
235                                $end   = mktime(0,0,0,1,1,$eyear+$year);
236                        }
237                        elseif ($smonth || $emonth)
238                        {
239                                $start = mktime(0,0,0,$smonth+$month,1,$year);
240                                $end   = mktime(0,0,0,$emonth+$month,1,$year);
241                        }
242                        elseif ($sday || $eday)
243                        {
244                                $start = mktime(0,0,0,$month,$sday+$day,$year);
245                                $end   = mktime(0,0,0,$month,$eday+$day,$year);
246                        }
247                        elseif ($sweek || $eweek)
248                        {
249                                $wday = (int) date('w',$this->today); // 0=sun, ..., 6=sat
250                                switch($GLOBALS['phpgw_info']['user']['preferences']['calendar']['weekdaystarts'])
251                                {
252                                        case 'Sunday':
253                                                $weekstart = $this->today - $wday * 24*60*60;
254                                                break;
255                                        case 'Saturday':
256                                                $weekstart = $this->today - (6-$wday) * 24*60*60;
257                                                break;
258                                        case 'Moday':
259                                        default:
260                                                $weekstart = $this->today - ($wday ? $wday-1 : 6) * 24*60*60;
261                                                break;
262                                }
263                                $start = $weekstart + $sweek*7*24*60*60;
264                                $end   = $weekstart + $eweek*7*24*60*60;
265                        }
266                        $end_param = $end - 24*60*60;
267                }
268                //echo "<p align='right'>date_filter($name,$start,$end) today=".date('l, Y-m-d H:i',$this->today)." ==> ".date('l, Y-m-d H:i:s',$start)." <= date < ".date('l, Y-m-d H:i:s',$end)."</p>\n";
269                // convert start + end from user to servertime for the filter
270                return '('.($start-$this->tz_offset_s).' <= ts_start AND ts_start < '.($end-$this->tz_offset_s).')';
271        }
272
273        /**
274         * search the timesheet
275         *
276         * reimplemented to limit result to users we have grants from
277         *
278         * @param array/string $criteria array of key and data cols, OR a SQL query (content for WHERE), fully quoted (!)
279         * @param boolean/string $only_keys=true True returns only keys, False returns all cols. comma seperated list of keys to return
280         * @param string $order_by='' fieldnames + {ASC|DESC} separated by colons ',', can also contain a GROUP BY (if it contains ORDER BY)
281         * @param string/array $extra_cols='' string or array of strings to be added to the SELECT, eg. "count(*) as num"
282         * @param string $wildcard='' appended befor and after each criteria
283         * @param boolean $empty=false False=empty criteria are ignored in query, True=empty have to be empty in row
284         * @param string $op='AND' defaults to 'AND', can be set to 'OR' too, then criteria's are OR'ed together
285         * @param mixed $start=false if != false, return only maxmatch rows begining with start, or array($start,$num)
286         * @param array $filter=null if set (!=null) col-data pairs, to be and-ed (!) into the query without wildcards
287         * @param string $join='' sql to do a join, added as is after the table-name, eg. ", table2 WHERE x=y" or
288         *      "LEFT JOIN table2 ON (x=y)", Note: there's no quoting done on $join!
289         * @param boolean $need_full_no_count=false If true an unlimited query is run to determine the total number of rows, default false
290         * @param boolean $only_summary=false If true only return the sums as array with keys duration and price, default false
291         * @return array of matching rows (the row is an array of the cols) or False
292         */
293        function &search($criteria,$only_keys=True,$order_by='',$extra_cols='',$wildcard='',$empty=False,$op='AND',$start=false,$filter=null,$join='',$need_full_no_count=false,$only_summary=false)
294        {
295                // postgres can't round from double precission, only from numeric ;-)
296                $total_sql = $this->db->Type != 'pgsql' ? "round(ts_quantity*ts_unitprice,2)" : "round(cast(ts_quantity*ts_unitprice AS numeric),2)";
297
298                if (!is_array($extra_cols))
299                {
300                        $extra_cols = $extra_cols ? explode(',',$extra_cols) : array();
301                }
302                $extra_cols[] = $total_sql.' AS ts_total';
303
304                if (!isset($filter['ts_owner']) || !count($filter['ts_owner']))
305                {
306                        $filter['ts_owner'] = array_keys($this->grants);
307                }
308                else
309                {
310                        if (!is_array($filter['ts_owner'])) $filter['ts_owner'] = array($filter['ts_owner']);
311                       
312                        foreach($filter['ts_owner'] as $key => $owner)
313                        {
314                                if (!isset($this->grants[$owner]))
315                                {
316                                        unset($filter['ts_owner'][$key]);
317                                }
318                        }
319                }
320                if (!count($filter['ts_owner']))
321                {
322                        $this->total = 0;
323                        $this->summary = array();
324                        return array();
325                }
326                $this->summary = parent::search($criteria,"SUM(ts_duration) AS duration,SUM($total_sql) AS price".
327                        ($this->quantity_sum ? ",SUM(ts_quantity) AS quantity" : ''),
328                        '','',$wildcard,$empty,$op,false,$filter,$join);
329                $this->summary = $this->summary[0];
330               
331                if ($only_summary) return $this->summary;
332
333                if ($this->show_sums && strpos($order_by,'ts_start') !== false &&       // sums only make sense if ordered by ts_start
334                        $this->db->capabilities['union'] && ($from_unixtime_ts_start = $this->db->from_unixtime('ts_start')))
335                {
336                        $sum_sql = array(
337                                'year'  => $this->db->date_format($from_unixtime_ts_start,'%Y'),
338                                'month' => $this->db->date_format($from_unixtime_ts_start,'%Y%m'),
339                                'week'  => $this->db->date_format($from_unixtime_ts_start,$GLOBALS['phpgw_info']['user']['preferences']['calendar']['weekdaystarts'] == 'Sunday' ? '%X%V' : '%x%v'),
340                                'day'   => $this->db->date_format($from_unixtime_ts_start,'%Y-%m-%d'),
341                        );
342                        foreach($this->show_sums as $type)
343                        {
344                                $extra_cols[] = $sum_sql[$type].' AS ts_'.$type;
345                                $extra_cols[] = '0 AS is_sum_'.$type;
346                                $sum_extra_cols[] = str_replace('ts_start','MIN(ts_start)',$sum_sql[$type]);    // as we dont group by ts_start
347                                $sum_extra_cols[$type] = '0 AS is_sum_'.$type;
348                        }
349                        // regular entries
350                        parent::search($criteria,$only_keys,$order_by,$extra_cols,$wildcard,$empty,$op,'UNION',$filter,$join,$need_full_no_count);
351                       
352                        $sort = substr($order_by,8);
353                        $union_order = array();
354                        $sum_ts_id = array('year' => -3,'month' => -2,'week' => -1,'day' => 0);
355                        foreach($this->show_sums as $type)
356                        {
357                                $union_order[] = 'ts_'.$type . ' ' . $sort;
358                                $union_order[] = 'is_sum_'.$type;
359                                $sum_extra_cols[$type]{0} = '1';
360                                // the $type sum
361                                parent::search($criteria,$sum_ts_id[$type].",'','','',MIN(ts_start),SUM(ts_duration) AS ts_duration,".
362                                        ($this->quantity_sum ? "SUM(ts_quantity) AS ts_quantity" : '0').",0,NULL,0,0,0,0,SUM($total_sql) AS ts_total",
363                                        'GROUP BY '.$sum_sql[$type],$sum_extra_cols,$wildcard,$empty,$op,'UNION',$filter,$join,$need_full_no_count);
364                                $sum_extra_cols[$type]{0} = '0';
365                        }
366                        $union_order[] = 'ts_start '.$sort;
367                        return parent::search('','',implode(',',$union_order),'','',false,'',$start);
368                }
369                return parent::search($criteria,$only_keys,$order_by,$extra_cols,$wildcard,$empty,$op,$start,$filter,$join,$need_full_no_count);
370        }
371
372        /**
373         * read a timesheet entry
374         *
375         * @param int $ts_id
376         * @param boolean $ignore_acl=false should the acl be checked
377         * @return array/boolean array with timesheet entry, null if timesheet not found or false if no rights
378         */
379        function read($ts_id,$ignore_acl=false)
380        {
381                $ret = null;
382                if (!(int)$ts_id || !$ignore_acl && !($ret = $this->check_acl(EGW_ACL_READ,$ts_id)) ||
383                        $this->data['ts_id'] != (int)$ts_id && !parent::read((int)$ts_id))
384                {
385                        return $ret;    // no read rights, or entry not found
386                }
387
388                //assign custom fields
389                foreach($this->customfields as $name => $value) {
390                        $row = $this->read_extra($name);
391                        $this->data['#'.$name] = $row['ts_extra_value'];
392                }
393
394                return $this->data;
395        }
396
397        /**
398         * reads a timesheet extra entry of the current timesheet dataset
399         *
400         * @param int $name => name of the current timesheet extra entry
401         * @param int $value => value of the current timesheet extra entry
402         * @return array of resultset
403         */
404        function read_extra($name='',$value='')
405        {
406                strlen($value) > 0 ? $where = ' and ts_extra_value ='.$this->db->quote($value) : '';
407                strlen($name) > 0 ? $where .= ' and ts_extra_name ='.$this->db->quote($name) : '';
408
409                $this->db->select('phpgw_timesheet_extra', 'ts_extra_name, ts_extra_value',$query,__LINE__,__FILE__,False,'',False,0,'where ts_id='.$this->data['ts_id'].$where);
410                $row = $this->db->row(true);
411
412                return $row;
413        }
414       
415        /**
416         * saves a timesheet entry
417         *
418         * reimplemented to notify the link-class
419         *
420         * @param array $keys if given $keys are copied to data before saveing => allows a save as
421         * @param boolean $touch_modified=true should modification date+user be set, default yes
422         * @param boolean $ignore_acl=false should the acl be checked, returns true if no edit-rigts
423         * @return int 0 on success and errno != 0 else
424         */
425        function save($keys=null,$touch_modified=true,$ignore_acl=false)
426        {
427                if ($keys) $this->data_merge($keys);
428               
429                if (!$ignore_acl && $this->data['ts_id'] && !$this->check_acl(EGW_ACL_EDIT))
430                {
431                        return true;
432                }
433                if ($touch_modified)
434                {
435                        $this->data['ts_modifier'] = $GLOBALS['phpgw_info']['user']['account_id'];
436                        $this->data['ts_modified'] = $this->now;
437                }
438                if (!($err = parent::save()))
439                {
440                        //saves data of custom fields in timesheet_extra
441                        $this->save_extra();
442
443                        // notify the link-class about the update, as other apps may be subscribt to it
444                        $this->link->notify_update(TIMESHEET_APP,$this->data['ts_id'],$this->data);
445                }
446                return $err;
447        }
448
449        /**
450         * saves a timesheet extra entry based one the "custom fields" settings
451         *
452         * @param boolean  $updateNames => if true "change timesheet extra name", otherwise update existing datasets or insert new ones
453         * @param boolean  $oldname => original name of the timesheet extra entry
454         * @param boolean  $name => new name of the timesheet extra entry
455         * @return int true on success else false
456         */
457        function save_extra($updateNames=False,$oldname='',$name='')
458        {
459                if($updateNames) {
460                        $keys = array('ts_extra_name' => $oldname);
461                        $fieldAssign = array('ts_extra_name' => $name);
462                        $this->db->update('phpgw_timesheet_extra',$fieldAssign,$keys,__LINE__,__FILE__);
463                        return true;
464                }
465                else {
466                        foreach($this->customfields as $namecf => $valuecf) {
467                                //if entry not exist => insert
468                                if(!$this->read_extra($namecf)) {
469                                        $fieldAssign = array('ts_id' => $this->data['ts_id'],'ts_extra_name' => $namecf,'ts_extra_value' => $this->data['#'.$namecf]);
470                                        $this->db->insert('phpgw_timesheet_extra',$fieldAssign,false,__LINE__,__FILE__);
471                                }
472                                //otherwise update existing dataset
473                                else {
474                                        $keys = array('ts_extra_name' => $namecf, 'ts_id' => $this->data['ts_id']);
475                                        $fieldAssign = array('ts_extra_value' => $this->data['#'.$namecf]);
476                                        $this->db->update('phpgw_timesheet_extra',$fieldAssign,$keys,__LINE__,__FILE__);
477                                }
478                        }
479                        return true;
480                }
481
482                return false;
483        }
484       
485        /**
486         * deletes a timesheet entry identified by $keys or the loaded one, reimplemented to notify the link class (unlink)
487         *
488         * @param array $keys if given array with col => value pairs to characterise the rows to delete
489         * @param boolean $ignore_acl=false should the acl be checked, returns false if no delete-rigts
490         * @return int affected rows, should be 1 if ok, 0 if an error
491         */
492        function delete($keys=null,$ignore_acl=false)
493        {
494                if (!is_array($keys) && (int) $keys)
495                {
496                        $keys = array('ts_id' => (int) $keys);
497                }
498                $ts_id = is_null($keys) ? $this->data['ts_id'] : $keys['ts_id'];
499               
500                if (!$this->check_acl(EGW_ACL_DELETE,$ts_id))
501                {
502                        return false;
503                }
504                if (($ret = parent::delete($keys)) && $ts_id)
505                {
506                        //delete custom fields entries
507                        $this->delete_extra($ts_id);
508
509                        // delete all links to timesheet entry $ts_id
510                        $this->link->unlink(0,TIMESHEET_APP,$ts_id);
511                }
512                return $ret;
513        }
514
515
516        /**
517         * deletes a timesheet extra entry identified by $ts_id and/or $ts_exra_name
518         *
519         * @param int $ts_id => number of timesheet
520         * @param string ts_extra_name => certain custom field name
521         * @return int false if an error
522         */
523        function delete_extra($ts_id='',$ts_extra_name='')
524        {
525                strlen($ts_id) > 0 ? $where['ts_id'] = $ts_id : '';
526                strlen($ts_extra_name) > 0 ? $where['ts_extra_name'] = $ts_extra_name : '';
527
528                if(count($where) > 0) {
529                        return $this->db->delete('phpgw_timesheet_extra', $where,__LINE__,__FILE__);
530                }
531
532                return false;
533        }
534
535        /**
536         * changes the data from the db-format to your work-format
537         *
538         * reimplemented to adjust the timezone of the timestamps (adding $this->tz_offset_s to get user-time)
539         * Please note, we do NOT call the method of the parent so_sql !!!
540         *
541         * @param array $data if given works on that array and returns result, else works on internal data-array
542         * @return array with changed data
543         */
544        function db2data($data=null)
545        {
546                if (!is_array($data))
547                {
548                        $data = &$this->data;
549                }
550                foreach($this->timestamps as $name)
551                {
552                        if (isset($data[$name]) && $data[$name]) $data[$name] += $this->tz_offset_s;
553                }
554                return $data;
555        }
556
557        /**
558         * changes the data from your work-format to the db-format
559         *
560         * reimplemented to adjust the timezone of the timestamps (subtraction $this->tz_offset_s to get server-time)
561         * Please note, we do NOT call the method of the parent so_sql !!!
562         *
563         * @param array $data if given works on that array and returns result, else works on internal data-array
564         * @return array with changed data
565         */
566        function data2db($data=null)
567        {
568                if ($intern = !is_array($data))
569                {
570                        $data = &$this->data;
571                }
572                foreach($this->timestamps as $name)
573                {
574                        if (isset($data[$name]) && $data[$name]) $data[$name] -= $this->tz_offset_s;
575                }
576                return $data;
577        }
578       
579        /**
580         * Get the time- and pricesum for the given timesheet entries
581         *
582         * @param array $ids array of timesheet id's
583         * @return array with keys time and price
584         */
585        function sum($ids)
586        {
587                return $this->search(array('ts_id'=>$ids),true,'','','',false,'AND',false,null,'',false,true);
588        }
589       
590        /**
591         * get title for an timesheet entry identified by $entry
592         *
593         * Is called as hook to participate in the linking
594         *
595         * @param int/array $entry int ts_id or array with timesheet entry
596         * @return string/boolean string with title, null if timesheet not found, false if no perms to view it
597         */
598        function link_title( $entry )
599        {
600                if (!is_array($entry))
601                {
602                        $entry = $this->read( $entry );
603                }
604                if (!$entry)
605                {
606                        return $entry;
607                }
608                $format = $GLOBALS['phpgw_info']['user']['preferences']['common']['dateformat'];
609                if (date('H:i',$entry['ts_start']) != '00:00')  // dont show 00:00 time, as it means date only
610                {
611                        $format .= ' '.($GLOBALS['phpgw_info']['user']['preferences']['common']['timeformat'] == 12 ? 'h:i a' : 'H:i');
612                }
613                return date($format,$entry['ts_start']).': '.$entry['ts_title'];
614        }
615
616        /**
617         * query timesheet for entries matching $pattern
618         *
619         * Is called as hook to participate in the linking
620         *
621         * @param string $pattern pattern to search
622         * @return array with ts_id - title pairs of the matching entries
623         */
624        function link_query( $pattern )
625        {
626                $criteria = array();
627                foreach(array('ts_project','ts_title','ts_description') as $col)
628                {
629                        $criteria[$col] = $pattern;
630                }
631                $result = array();
632                foreach((array) $this->search($criteria,false,'','','%',false,'OR') as $ts )
633                {
634                        if ($ts) $result[$ts['ts_id']] = $this->link_title($ts);
635                }
636                return $result;
637        }
638
639        /**
640         * Hook called by link-class to include timesheet in the appregistry of the linkage
641         *
642         * @param array/string $location location and other parameters (not used)
643         * @return array with method-names
644         */
645        function search_link($location)
646        {
647                return array(
648                        'query' => TIMESHEET_APP.'.botimesheet.link_query',
649                        'title' => TIMESHEET_APP.'.botimesheet.link_title',
650                        'view'  => array(
651                                'menuaction' => TIMESHEET_APP.'.uitimesheet.view',
652                        ),
653                        'view_id' => 'ts_id',
654                        'view_popup'  => '600x400',                     
655                        'add' => array(
656                                'menuaction' => TIMESHEET_APP.'.uitimesheet.edit',
657                        ),
658                        'add_app'    => 'link_app',
659                        'add_id'     => 'link_id',             
660                        'add_popup'  => '600x400',                     
661                );
662        }
663       
664        /**
665         * Return the timesheets linked with given project(s) AND with entries of other apps, which are also linked to the same project
666         *
667         * Projectmanager will cumulate them in the other apps entries.
668         *
669         * @param array $param int/array $param['pm_id'] project-id(s)
670         * @return array with pm_id, pe_id, pe_app('timesheet'), pe_app_id(ts_id), other_id, other_app, other_app_id
671         */
672        function cumulate($param)
673        {
674                $links = $this->link->get_3links(TIMESHEET_APP,'projectmanager',$param['pm_id']);
675               
676                $rows = array();
677                foreach($links as $link)
678                {
679                        $rows[$link['id']] = array(
680                                'pm_id'       => $link['id2'],
681                                'pe_id'       => $link['id'],
682                                'pe_app'      => $link['app1'],
683                                'pe_app_id'   => $link['id1'],
684                                'other_id'    => $link['link3'],
685                                'other_app'   => $link['app3'],
686                                'other_app_id'=> $link['id3'],
687                        );
688                }
689                return $rows;
690        }
691
692        /**
693         * updates the project titles in the timesheet application (called whenever a project name is changed in the project manager)
694         *
695         * Todo: implement via notification
696         *
697         * @param string $oldtitle => the origin title of the project
698         * @param string $newtitle => the new title of the project
699         * @return boolean true for success, false for invalid parameters
700         */
701         function update_ts_project($oldtitle='', $newtitle='')
702         {
703                if(strlen($oldtitle) > 0 && strlen($newtitle) > 0) {
704                        $keys = array('ts_project' => $oldtitle);
705                        $fieldAssign = array('ts_project' => $newtitle,'ts_title' => $newtitle);
706                        $this->db->update('phpgw_timesheet',$fieldAssign,$keys,__LINE__,__FILE__);
707
708                        return true;
709                }
710
711                return false;
712         }
713
714        /**
715         * returns array with relation link_id and ts_id (necessary for project-selection)
716         *
717         * @param int $pm_id ID of selected project
718         * @return array containing link_id and ts_id
719         */     
720        function get_ts_links($pm_id=0) {
721                $tslist = array();             
722                if(strlen($pm_id) > 0) {
723                        if(isset($GLOBALS['phpgw_info']['user']['apps']['projectmanager'])) {   
724                                $bo_pm = CreateObject('projectmanager.boprojectmanager');
725                                $childs = $bo_pm->children($pm_id);
726                                $childs[] = $pm_id;
727                                $pmChilds = implode(",",$childs);
728                                $this->db->select(      'phpgw_links','link_id, link_id1',$query,
729                                                        __LINE__,__FILE__,False,
730                                                        '',False,0,
731                                                        'JOIN phpgw_pm_projects ON (pm_id = link_id2)
732                                                         WHERE
733                                                                link_app1 = \'timesheet\' AND
734                                                                link_app2 = \'projectmanager\' AND
735                                                                link_id2 IN ('.$pmChilds.')');
736                                       
737                                while($row = $this->db->row(true)) {
738                                        $tslist[$row['link_id']] = $row['link_id1'];
739                                }
740                                       
741                        }
742
743                }
744                return $tslist;
745        }
746}
Note: See TracBrowser for help on using the repository browser.