php warnings
[Pman.MTrack] / DataObjects / Mtrack_report.php
1 <?php
2 /**
3  * Table Definition for mtrack_report
4  */
5 class_exists('DB_DataObject') ? '' : require_once 'DB/DataObject.php';
6
7 class Pman_MTrack_DataObjects_Mtrack_report extends DB_DataObject 
8 {
9     ###START_AUTOCODE
10     /* the code below is auto generated do not remove the above tag */
11
12     public $__table = 'mtrack_report';                   // table name
13     public $id;                              // int(11)  not_null primary_key auto_increment
14     public $summary;                         // string(128)  not_null
15     public $description;                     // blob(65535)  not_null blob
16     public $query;                           // blob(65535)  blob
17     public $changed;                         // int(11)  not_null
18
19     
20     /* the code above is auto generated do not remove the tag below */
21     ###END_AUTOCODE
22     
23   
24
25     function save($CS) // changes dataobject..
26     {
27         $old = false;
28         if ($this->rid) {
29             $old = DB_DAtaObject::factory('mtrack_report');
30             $old->get($this->rid);
31             $this->update($old);
32         } else {
33             $this->insert();
34         }
35         $CS->add("report:" . $this->rid , $old, $new);
36        
37     }
38     
39     function get($id) {
40         //DB_DataObject::debugLevel(1);
41         $id = (int) $id;
42         $cfg = array(
43             1 => (object)array(
44                 'title' => "Active tickets",
45                 'selectAdd' => array(
46                     '__color__' => 'join_severity_id_id.seqid' ,
47                     'act_now' => 'mtrack_ticket.act_now',
48                     'ticket' => 'mtrack_ticket.id',
49                     
50                     //'component' => 'join_component_id_id.name', << we need to have a 'main component'
51                     'summary' => array("'['",  'join_status_id.name' , "'] '", "summary"), // fixme..
52
53                     'assigned_to' => 'join_owner_id_id.name',
54                     'estimated' =>  'mtrack_ticket.estimated',
55
56                     'milestone' => 'join_milestone_id_id.name',
57                     '_milestone_id' => 'join_milestone_id_id.id',
58                     
59                     'severity' => 'join_severity_id_id.name',
60                     'priority' => 'join_priority_id_id.name',
61                     'classification' => 'join_classification_id_id.name',
62                     'updated' => 'join_updated_id.changedate',
63                 ),
64                 'whereAdd' => "join_status_id.name IN ('new', 'assigned', 'reopened', 'open')
65                         AND
66                         mtrack_ticket.project_id = [PROJECTID] ",
67                 'orderBy' => "
68                             mtrack_ticket.act_now DESC,
69                             (case when join_milestone_id_id.duedate is null then 1 else 0 end),
70                             join_milestone_id_id.duedate ASC ,
71                             join_severity_id_id.seqid ASC,
72                             join_priority_id_id.seqid ASC,
73                             join_classification_id_id.seqid ASC,
74                             join_updated_id.changedate  DESC"
75                 
76                 
77             ),
78             2 => (object)array(
79                 'title' => "Closed tickets",
80                 'selectAdd' => array(
81                     '__color__' => 'join_severity_id_id.seqid' ,
82                     'ticket' => 'mtrack_ticket.id',
83                     //'component' => 'join_component_id_id.name', << we need to have a 'main component'
84                     'summary' => array("'['",  'join_status_id.name' , "'] '", "summary"), // fixme..
85                     'assigned_to' => 'join_owner_id_id.name',
86                     
87                     'milestone' => 'join_milestone_id_id.name',
88                     '_milestone_id' => 'join_milestone_id_id.id',
89                     
90                     'severity' => 'join_severity_id_id.name',
91                     'priority' => 'join_priority_id_id.name',
92                     'classification' => 'join_classification_id_id.name',
93                     'updated' => 'join_updated_id.changedate',
94                     
95                 ),
96                 'whereAdd' => "join_status_id.name IN ('closed')
97                         AND
98                         mtrack_ticket.project_id = [PROJECTID] ",
99                 'orderBy' => "
100                     join_severity_id_id.seqid ASC,
101                     join_priority_id_id.seqid ASC,
102                     join_classification_id_id.seqid ASC,
103                     join_updated_id.changedate  DESC"
104                  
105             ),
106             3 => (object)array(
107                 'title' => "Pending Review",
108                 'selectAdd' => array(
109                     '__color__' => 'join_severity_id_id.seqid' ,
110                     'ticket' => 'mtrack_ticket.id',
111                     //'component' => 'join_component_id_id.name', << we need to have a 'main component'
112                     'summary' => array("'['",  'join_status_id.name' , "'] '", "summary"), // fixme..
113                     'assigned_to' => 'join_owner_id_id.name',
114                     'milestone' => 'join_milestone_id_id.name',
115                     '_milestone_id' => 'join_milestone_id_id.id',
116                     
117                     'severity' => 'join_severity_id_id.name',
118                     'priority' => 'join_priority_id_id.name',
119                     'classification' => 'join_classification_id_id.name',
120                     'updated' => 'join_updated_id.changedate',
121                     
122                 ),
123                 'whereAdd' => "join_status_id.name IN ('completed')
124                         AND
125                         mtrack_ticket.project_id = [PROJECTID] ",
126                 'orderBy' => "
127                     join_severity_id_id.seqid ASC,
128                     join_priority_id_id.seqid ASC,
129                     join_classification_id_id.seqid ASC,
130                     join_updated_id.changedate DESC "
131                 
132                 
133             ),
134              
135             4 => (object) array(
136                 'title' => "Assigned to me",
137                 'selectAdd' => array(
138                     '__color__' => 'join_severity_id_id.seqid' ,
139                     'ticket' => 'mtrack_ticket.id',
140                     //'component' => 'join_component_id_id.name', << we need to have a 'main component'
141                      'milestone' => 'join_milestone_id_id.name',
142                     '_milestone_id' => 'join_milestone_id_id.id',
143                     'estimated' =>  'mtrack_ticket.estimated',
144
145                     'summary' => array("'['",  'join_status_id.name' , "'] '", "summary"), // fixme..
146                     'milestone' => 'join_milestone_id_id.name',
147                     '_milestone_id' => 'join_milestone_id_id.id',
148                     
149                     'severity' => 'join_severity_id_id.name',
150                     'priority' => 'join_priority_id_id.name',
151                     'classification' => 'join_classification_id_id.name',
152                     'updated' => 'join_updated_id.changedate',
153                     
154                 ),
155                 'whereAdd' => "
156                     join_status_id.name IN ('new', 'assigned', 'reopened', 'open')
157                     AND
158                     (mtrack_ticket.owner_id = [UID] OR mtrack_ticket.developer_id = [UID] )
159                         AND
160                         mtrack_ticket.project_id = [PROJECTID] ",
161                 'orderBy' => "
162                         join_severity_id_id.seqid ASC,
163                         join_priority_id_id.seqid ASC,
164                         join_classification_id_id.seqid ASC,
165                         join_updated_id.changedate"
166                 
167                 
168             ),
169             5 => (object)array(
170                 'title' => "All Active tickets",
171                 'selectAdd' => array(
172                     '__group__' => 'join_project_id_id.name' ,
173                     // '_project_id' => 'mtrack_ticket.project_id' ,
174                     '__color__' => 'join_severity_id_id.seqid' ,
175                     'ticket' => 'mtrack_ticket.id',
176                     'milestone' => 'join_milestone_id_id.name',
177                     '_milestone_id' => 'join_milestone_id_id.id',
178                     'estimated' =>  'mtrack_ticket.estimated',
179
180                     //'component' => 'join_component_id_id.name', << we need to have a 'main component'
181                     'summary' => array("'['",  'join_status_id.name' , "'] '", "summary"), // fixme..
182                     'assigned_to' => 'join_owner_id_id.name',
183                     'classification' => 'join_classification_id_id.name',
184                     'priority' => 'join_priority_id_id.name',
185                     'severity' => 'join_severity_id_id.name',
186                     'updated' => 'join_updated_id.changedate',
187                 ),
188                 'whereAdd' => "
189                     join_status_id.name IN ('new', 'assigned', 'reopened', 'open')
190                 ",
191                 'orderBy' => "
192                     join_project_id_id.name ASC,
193                     (case when join_milestone_id_id.duedate is null then 1 else 0 end),
194                     join_milestone_id_id.duedate ASC ,
195                     join_severity_id_id.seqid ASC,
196                     join_priority_id_id.seqid ASC,
197                     join_classification_id_id.seqid ASC,
198                     join_updated_id.changedate DESC
199                 ",
200                                 
201                 
202             ),
203             6 => (object)array(
204                 'title' => "Work Schedule",
205                 'selectAdd' => array(
206                     '__color__' => 'join_severity_id_id.seqid' ,
207                     'ticket' => 'mtrack_ticket.id',
208                     'project' => 'join_project_id_id.name', 
209                     //'component' => 'join_component_id_id.name', << we need to have a 'main component'
210                      'due' => 'join_milestone_id_id.duedate',
211                     '_milestone_id' => 'join_milestone_id_id.id',
212  
213                     'summary' => array("'['",  'join_status_id.name' , "'] '", "summary"), // fixme..
214                     'assigned_to' => 'join_owner_id_id.name',
215                     'classification' => 'join_classification_id_id.name',
216                     'priority' => 'join_priority_id_id.name',
217                     'severity' => 'join_severity_id_id.name',
218              ),
219                 'whereAdd' => "
220                     join_status_id.name IN ('new', 'assigned', 'reopened', 'open')
221                     AND
222                     (mtrack_ticket.owner_id = [UID]   )
223                           ",
224                 'orderBy' => "
225                     (case when join_milestone_id_id.duedate is null then 1 else 0 end),
226                     join_milestone_id_id.duedate ASC ,
227                     join_severity_id_id.seqid ASC,
228                     join_updated_id.changedate
229                 "
230                 
231                                 
232                 
233             ),
234             
235             
236         );
237         if (!isset($cfg[$id])) {
238             die("invalid report id");
239         }
240         $this->cfg = $cfg[$id];
241         $this->id = $id;
242         $this->title = $this->cfg->title;
243
244     }
245     
246     // move back to controller...
247   
248     function render($params = array(), $format = 'html')
249     {
250         
251         $link = HTML_FlexyFramework::get()->page->link;
252         
253         
254         /* process the report string; any $PARAM in there is recognized
255          * as a parameter and the query munged accordingly to pass in the data */
256     
257         
258         $au = HTML_Flexyframework::get()->page->authUser;
259      
260         //DB_DataObject::DebugLevel(1);
261         
262         
263          
264         $this->title = $this->cfg->title;
265         
266          
267         $x = DB_DataObject::factory('mtrack_ticket'); 
268         $x->autoJoin();
269         
270         $x->selectAdd();
271         foreach($this->cfg->selectAdd  as $k=>$v) {
272             if (is_array($v)) {
273                 //foreach($v as $k) {   -- quote..
274                 //   $ar[] = $l[0] == "'" ? $k : 
275                 //}
276                 $v = 'CONCAT(' . implode(', ', $v) . ')';
277             } else {
278                 $v = '`' . str_replace('.', '`.`', $v ) . '`';
279             }
280             
281             $x->selectAdd("$v as $k"); 
282         }
283         // always..
284          //DB_DataObject::DebugLevel(1);
285         $pg = HTML_Flexyframework::get()->page;
286         //$x->project_id = HTML_Flexyframework::get()->page->currentProject();
287         
288         $uid = empty($au) ? -1 : $au->id;
289         
290         
291         $whereAdd =  str_replace('[UID]', $uid,  $this->cfg->whereAdd );
292         $whereAdd =  str_replace('[PROJECTID]',  $pg->currentProject(),  $whereAdd );
293         
294         $x->whereAdd( $whereAdd );
295         
296         // access to valid projects only.
297         
298         if ($au && $au->company()->comptype !='OWNER') {
299             $pd = DB_DataObject::factory('ProjectDirectory');
300             $pd->whereAdd("role != ''");
301             $pd->person_id = $au->id;
302             // what does featch all return if nothing there?
303             $x->whereAddIn('mtrack_ticket.project_id', $pd->fetchAll('project_id'), 'int');
304         }
305         // no authenticated user - > only current project
306         if (!$au) {
307             $x->project_id = $pg->currentProject();
308         }
309         
310         
311         $x->orderBy( $this->cfg->orderBy);
312                     
313         $x->find() ;
314         
315         $results = array();
316         while ($x->fetch()) {
317             //echo '<PRE>';print_r($x);exit;
318             $results[] =  $x->toArray('%s',0);
319         }
320             //echo '<PRE>'; print_r($results);
321     
322         $out = '';
323     
324         if (count($results) == 0) {
325             return "No records matched";
326         }
327     
328         /* figure out the table headings */
329         $captions = array();
330         $span = array();
331         $rules = array();
332         foreach ($results[0] as $name => $value) {
333           if (preg_match("/^__.*__$/", $name)) {
334             if ($format == 'html') {
335               /* special meaning, not a column */
336               continue;
337             }
338           }
339           $captions[$name] = preg_replace("/^_(.*)_$/", "\\1", $name);
340           // temporary.. names for columsn.
341          
342           
343           
344         }
345         /* for spanning purposes, calculate the longest row */
346         // no idea what this is supposed to do...
347         // colspans???
348         $max_width = 0;
349         $width = 0;
350         foreach ($captions as $name => $caption) {
351             if ($name[0] == '_' && substr($name, -1) == '_') {
352               $width = 1;
353             } else {
354               $width++;
355             }
356             if ($width > $max_width) {
357               $max_width = $width;
358             }
359             if (substr($name, -1) == '_') {
360               $width = 1;
361             }
362         }
363         
364         
365         $group = null;
366         foreach ($results as $nrow => $row) {
367             
368             $starting_new_group = false;
369             
370             if ($nrow == 0) {
371               $starting_new_group = true;
372               
373             } else if ($format == 'html' &&
374                 (isset($row['__group__']) && $group !== $row['__group__'])) {
375                  $starting_new_group = true;
376             }
377             
378             if ($starting_new_group) {
379               /* starting a new group */
380                 if ($nrow) {
381                   /* close the old one */
382                     if ($format == 'html') {
383                          $out .= "</tbody></table>\n";
384                     }
385                 }
386                 if ($format == 'html' && isset($row['__group__'])) {
387                     
388                     $out .= "<h2 class='reportgroup'>" .
389                         
390                         htmlentities($row['__group__'], ENT_COMPAT, 'utf-8') .
391                         "</h2>\n";
392                     $group = $row['__group__'];
393                 }
394             
395                 if ($format == 'html') {
396                     $out .= "<table class='report'><thead><tr>";
397                     
398                 }
399             
400                 foreach ($captions as $name => $caption) {
401             
402                     /* figure out sort info for javascript bits */
403                     $sort = null;
404                     switch (strtolower($caption)) {
405                         case 'priority':
406                         case 'ticket':
407                         case 'severity':
408                             $sort = strtolower($caption);
409                             break;
410                         
411                         case 'created':
412                         case 'modified':
413                         case 'date':
414                         case 'due':
415                             $sort = 'mtrackdate';
416                             break;
417                         
418                         case 'remaining':
419                             $sort = 'digit';
420                             break;
421                         
422                         case 'updated':
423                         case 'time':
424                         case 'content':
425                         case 'summary':
426                         default:
427                             break;
428                     }
429                      switch ($caption) {
430                         case 'ticket' : $caption = "Edit #"; break;
431                         case 'summary' : $caption = "Summary (View/Comment)"; break;
432                     }
433             
434                     $caption =  str_replace('_', ' ',ucfirst($caption));
435                     
436                     
437                     if ($name[0] == '_' && substr($name,-1) == '_') {
438                         if ($format == 'html') {
439                             $out .= "</tr><tr><th colspan='$max_width'>$caption</th></tr><tr>";
440                         } else if ($format == 'tab') {
441                           $out .= "$caption\t";
442                         }
443                     } elseif ($name[0] == '_') {
444                         continue;
445                     } else {
446                         if ($format == 'html') {
447                             $out .= "<th";
448                             if ($sort !== null) {
449                                 $out .= " class=\"{sorter: '$sort'}\"";
450                             }
451                             $out .= ">$caption</th>";
452                             if (substr($name, -1) == '_') {
453                                 $out .= "</tr><tr>";
454                             }
455                         } else if ($format == 'tab') {
456                             $out .= "$caption\t";
457                         }
458                     }
459                 }
460                 if ($format == 'html') {
461                     $out .= "</tr></thead><tbody>\n";
462                 } else if ($format == 'tab') {
463                     $out .= "\n";
464                 }
465             }
466
467             // and now the column data itself 
468             if (isset($row['__style__'])) {
469               $style = " style=\"$row[__style__]\"";
470             } else {
471               $style = "";
472             }
473             $class = $nrow % 2 ? "even" : "odd";
474             if (isset($row['__color__'])) {
475               $class .= " color". strtolower($row['__color__']);
476             }
477             if (isset($row['__status__'])) {
478               $class .= " status$row[__status__]";
479             }
480       
481             if ($format == 'html') {
482                  $begin_row = "<tr class=\"$class\"$style>";
483                 
484                  $out .= $begin_row;
485             }
486           //$href = null;
487     
488           /* determine if we should link to something for this row */
489           
490           //if (isset($row['ticket'])) {
491               
492             //    $href = $ABSWEB . "/Ticket.php/$row[ticket]";
493           //}
494         
495     
496           foreach ($captions as $name => $caption) {
497             $v = $row[$name];
498             //var_dump($v);
499             
500             /* apply special formatting rules */
501             if ($format == 'html') {
502               switch (strtolower($caption)) {
503                 case 'created':
504                 case 'modified':
505                 case 'date':
506                 case 'due':
507                 case 'updated':
508                 case 'time':
509                   if ($v !== null) {
510                     $v = $link->date($v);
511                   }
512                   break;
513                 
514                 case 'act_now' :
515                     $val = $v;
516                      $v = '<div class="x-grid-cell-text"
517                         unselectable="on"><img
518                             class="x-grid-check-icon' . ($val  ? '-checked' : '' ) . '"
519                         src="/roojs1/images/gray/s.gif"></div>';
520                     break;
521                 
522                 case 'priority':
523                 case 'classification':
524                 case 'severity':
525                     $v = '<div class="ticket-enum ticket-enum-' . strtolower($caption).'">' .
526                         htmlspecialchars($v) . '</div>';
527                     break;
528                     
529                 case 'content':
530                   $v = htmlspecialchars($v); //MTrack_Wiki::format_to_html($v);
531                   break;
532                 case 'owner':
533                   $v = $link->username($v, array('no_image' => true));
534                   break;
535                 case 'docid':
536                 case 'ticket':
537                // print_r($row);
538                   $v = $link->ticket($row['ticket']); // what about doc id?
539                   break;
540                 case 'summary':
541                 
542                   $v = isset($row['ticket']) ?
543                     $link->ticket($row['ticket'], array('display' => $v)) : 
544                     $v=  htmlspecialchars($v);
545                   break;
546                 case 'milestone':
547                     // actually we only have one milestone at present..
548                    // print_r($row);
549                     $v = $link->milestone($row['_milestone_id'], $v);
550                     //var_dump($v);
551                    
552                   break;
553                 case 'keyword':
554                   $oldv = $v;
555                   $v = '';
556                   foreach (preg_split("/\s*,\s*/", $oldv) as $m) {
557                     if (!strlen($m)) continue;
558                     $v .= $link->keyword($m) . ' ';
559                   }
560                   break;
561                 default:
562                   $v = htmlentities($v, ENT_QUOTES, 'utf-8');
563               }
564             } else if ($format == 'tab') {
565               $v = trim(preg_replace("/[\t\n\r]+/sm", " ", $v));
566             }
567     
568             if ($name[0] == '_' && substr($name, -1) == '_') {
569               if ($format == 'html') {
570                 $out .= "</tr>$begin_row<td class='$caption' colspan='$max_width'>$v</td></tr>$begin_row";
571               } else if ($format == 'tab') {
572                 $out .= "$v\t";
573               }
574             } elseif ($name[0] == '_') {
575               if ($format == 'tab') {
576                 $out .= "$v\t";
577               } else {
578                 continue;
579               }
580             } else {
581               if ($format == 'html') {
582                 $out .= "<td class='$caption'>$v</td>";
583                 if (substr($name, -1) == '_') {
584                   $out .= "</tr>$begin_row";
585                 }
586               } else if ($format == 'tab') {
587                 $out .= "$v\t";
588               }
589             }
590           }
591           if ($format == 'html') {
592             $out .= "</tr>\n";
593           } else if ($format == 'tab') {
594             $out .= "\n";
595           }
596         }
597         if ($format == 'html') {
598           $out .= "</tbody></table>";
599         } else if ($format == 'tab') {
600           $out = str_replace("\t\n", "\n", $out);
601         }
602         
603         return $out;
604     }
605     
606     
607     
608     function fetchResults()
609     {
610           $au = HTML_Flexyframework::get()->page->authUser;
611
612         $x = DB_DataObject::factory('mtrack_ticket'); 
613         $x->autoJoin();
614         
615         $x->selectAdd();
616         foreach($this->cfg->selectAdd  as $k=>$v) {
617             if (is_array($v)) {
618                 //foreach($v as $k) {   -- quote..
619                 //   $ar[] = $l[0] == "'" ? $k : 
620                 //}
621                 $v = 'CONCAT(' . implode(', ', $v) . ')';
622             } else {
623                 $v = '`' . str_replace('.', '`.`', $v ) . '`';
624             }
625             
626             $x->selectAdd("$v as $k"); 
627         }
628         // always..
629          //DB_DataObject::DebugLevel(1);
630         $pg = HTML_Flexyframework::get()->page;
631         //$x->project_id = HTML_Flexyframework::get()->page->currentProject();
632          $uid = empty($au) ? -1 : $au->id;
633         
634         
635         $whereAdd =  str_replace('[UID]', $uid,  $this->cfg->whereAdd );
636         $whereAdd =  str_replace('[PROJECTID]',  $pg->currentProject(),  $whereAdd );
637         
638         $x->whereAdd( $whereAdd );
639         
640         // access to valid projects only.
641         
642         if ($au && $au->company()->comptype !='OWNER') {
643             $pd = DB_DataObject::factory('ProjectDirectory');
644             $pd->whereAdd("role != ''");
645             $pd->person_id = $au->id;
646             // what does featch all return if nothing there?
647             $x->whereAddIn('mtrack_ticket.project_id', $pd->fetchAll('project_id'), 'int');
648         }
649         // no authenticated user - > only current project
650         if (!$au) {
651             $x->project_id = $pg->currentProject();
652         }
653         
654         
655         $x->orderBy( $this->cfg->orderBy);
656                     
657         $x->find() ;
658         
659         $results = array();
660         while ($x->fetch()) {
661             //echo '<PRE>';print_r($x);exit;
662             $results[] =  $x->toArray('%s',0);
663         }
664             //echo '<PRE>'; print_r($results);
665     
666         return $results;
667         
668         
669         
670     }
671     /**
672      *
673      * JSON version of report.
674      *
675      * should return
676      *
677      * array(
678      * 
679           'title'= >
680           'headers=> array(
681                    a,b,c,d,
682                 )
683           'groups' =>  array(   // GROUP
684                 'title' =>
685                 
686                 'data' => array(
687                     array(
688                         a =>
689                         b =>
690                         c=>
691                     )
692                         
693                         
694                     )
695                 )
696             )
697      )
698      *
699      */
700   
701     function renderToJSON()
702     {
703         
704         $link = HTML_FlexyFramework::get()->page->link;
705         
706         
707         /* process the report string; any $PARAM in there is recognized
708          * as a parameter and the query munged accordingly to pass in the data */
709     
710         
711         $au = HTML_Flexyframework::get()->page->authUser;
712      
713         //DB_DataObject::DebugLevel(1);
714         
715         
716          
717         $this->title = $this->cfg->title;
718          
719         $results = $this->fetchResults();
720          
721             //echo '<PRE>'; print_r($results);
722     
723         $ret = array();
724     
725         if (count($results) == 0) {
726             return $ret;
727         }
728         
729         
730         
731         
732         
733          
734         
735     
736         /* figure out the table headings */
737         $captions = array();
738         $span = array();
739         $rules = array();
740         foreach ($results[0] as $name => $value) {
741           if (preg_match("/^__.*__$/", $name)) {
742           
743               /* special meaning, not a column */
744               continue;
745            
746           }
747           
748           $captions[$name] = preg_replace("/^_(.*)_$/", "\\1", $name);
749           // temporary.. names for columsn.
750           
751         }
752         
753         $ret['headers'] = $captions;
754         
755         
756         /*
757          munge the header capiton names...
758             
759                 foreach ($captions as $name => $caption) {
760             
761         
762                   $sort = null;
763                   switch (strtolower($caption)) {
764                       case 'priority':
765                       case 'ticket':
766                       case 'severity':
767                           $sort = strtolower($caption);
768                           break;
769                       
770                       case 'created':
771                       case 'modified':
772                       case 'date':
773                       case 'due':
774                           $sort = 'mtrackdate';
775                           break;
776                       
777                       case 'remaining':
778                           $sort = 'digit';
779                           break;
780                       
781                       case 'updated':
782                       case 'time':
783                       case 'content':
784                       case 'summary':
785                       default:
786                           break;
787                   }
788                   
789                   switch ($caption) {
790                       case 'ticket' : $caption = "Edit #"; break;
791                       case 'summary' : $caption = "Summary (View/Comment)"; break;
792                   }
793           
794                   $caption =  str_replace('_', ' ',ucfirst($caption));
795                   
796                   
797                   if ($name[0] == '_' && substr($name,-1) == '_') {
798                       if ($format == 'html') {
799                           
800                           $out .= "</tr><tr><th colspan='$max_width'>$caption</th></tr><tr>";
801                       } else if ($format == 'tab') {
802                         $out .= "$caption\t";
803                       }
804                   } elseif ($name[0] == '_') {
805                       continue;
806                   } else {
807                       if ($format == 'html') {
808                           $out .= "<th";
809                           if ($sort !== null) {
810                               $out .= " class=\"{sorter: '$sort'}\"";
811                           }
812                           $out .= ">$caption</th>";
813                           if (substr($name, -1) == '_') {
814                               $out .= "</tr><tr>";
815                           }
816                       } else if ($format == 'tab') {
817                           $out .= "$caption\t";
818                       }
819                   }
820               }
821               if ($format == 'html') {
822                   $out .= "</tr></thead><tbody>\n";
823               } else if ($format == 'tab') {
824                   $out .= "\n";
825                 }
826                 
827         }
828         */
829         $curgroup = array(
830             'title' => 'Results'
831         );
832  
833         
834         $group = null;
835         foreach ($results as $nrow => $row) {
836             
837             $starting_new_group = false;
838             
839             if ($nrow == 0) {
840               $starting_new_group = true;
841               
842             } else if ( 
843                 (isset($row['__group__']) && $group !== $row['__group__'])) {
844                  $starting_new_group = true;
845             }
846             
847             if ($starting_new_group) {
848               /* starting a new group */
849                 if ($nrow) {
850                   /* close the old one */
851                     $ret['groups'][] = $curgroup;
852                     $curgroup = array();
853                 }
854                 if (isset($row['__group__'])) {
855                     $curgroup['title'] = $row['__group__'];
856                     $group = $row['__group__'];
857                 }
858             
859             
860             }
861             $style  = '';
862             // and now the column data itself 
863             if (isset($row['__style__'])) {
864                 
865                 $style = $row[__style__];
866             } else {
867                 $style = "";
868             }
869             $class = $nrow % 2 ? "even" : "odd";
870             if (isset($row['__color__'])) {
871                  $class .= " color". strtolower($row['__color__']);
872             }
873             if (isset($row['__status__'])) {
874                  $class .= " status$row[__status__]";
875             }
876       
877              
878             $crow = array(
879                 'class' => $class,
880                 'style' => $style 
881             );
882               
883            
884     
885           foreach ($captions as $name => $caption) {
886             $v = $row[$name];
887             //var_dump($v);
888             
889             /* apply special formatting rules */
890             
891             switch (strtolower($caption)) {
892                 case 'created':
893                 case 'modified':
894                 case 'date':
895                 case 'due':
896                 case 'updated':
897                 case 'time':
898                   //if ($v !== null) {
899                   //      $v = $link->date($v);
900                   //}
901                   break;
902                 
903                 case 'act_now' :
904                 case 'priority':
905                 case 'classification':
906                 case 'severity':
907                 case 'content':
908                     
909                   break;
910                 
911                 
912                 case 'owner':
913                   //  $v = $link->username($v, array('no_image' => true));
914                     
915                   break;
916                 case 'docid':
917                 case 'ticket':
918                // print_r($row);
919                   //$v = $link->ticket($row['ticket']); // what about doc id?
920                   break;
921                 
922                 case 'summary':
923                 
924                     //$v = isset($row['ticket']) ? $link->ticket($row['ticket'], array('display' => $v)) :  $v;
925                     break;
926                 
927                 
928                 
929                 case 'milestone':
930                     // actually we only have one milestone at present..
931                    // print_r($row);
932                     //$v = $link->milestone($row['_milestone_id'], $v);
933                     //var_dump($v);
934                    
935                   break;
936                 
937                 
938                 case 'keyword':
939                     $oldv = $v;
940                     $v = '';
941                     foreach (preg_split("/\s*,\s*/", $oldv) as $m) {
942                           if (!strlen($m)) continue;
943                           $v .= $link->keyword($m) . ' ';
944                     }
945                   break;
946                 
947                 
948                 default:
949                    break;
950              }
951             
952     
953             if ($name[0] == '_' && substr($name, -1) == '_') {
954                 // its' a caption row... ???
955                // $out .= "</tr>$begin_row<td class='$caption' colspan='$max_width'>$v</td></tr>$begin_row";
956               
957             }  else {
958                 $crow[$name] = $v;
959             
960             }
961           }
962           $curgroup['rows'][] = $crow;
963           
964         }
965         
966         $ret['groups'][] = $curgroup;
967         echo '<PRE>' . htmlspecialchars( print_R($ret,true));exit;
968         return $ret;
969     }
970
971 }