3 * Table Definition for mtrack_report
5 class_exists('DB_DataObject') ? '' : require_once 'DB/DataObject.php';
7 class Pman_MTrack_DataObjects_Mtrack_report extends DB_DataObject
10 /* the code below is auto generated do not remove the above tag */
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
20 /* the code above is auto generated do not remove the tag below */
25 function save($CS) // changes dataobject..
29 $old = DB_DAtaObject::factory('mtrack_report');
30 $old->get($this->rid);
35 $CS->add("report:" . $this->rid , $old, $new);
40 //DB_DataObject::debugLevel(1);
44 'title' => "Active tickets",
46 '__color__' => 'join_severity_id_id.seqid' ,
47 'act_now' => 'mtrack_ticket.act_now',
48 'ticket' => 'mtrack_ticket.id',
50 //'component' => 'join_component_id_id.name', << we need to have a 'main component'
51 'summary' => array("'['", 'join_status_id.name' , "'] '", "summary"), // fixme..
53 'assigned_to' => 'join_owner_id_id.name',
54 'estimated' => 'mtrack_ticket.estimated',
56 'milestone' => 'join_milestone_id_id.name',
57 '_milestone_id' => 'join_milestone_id_id.id',
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',
64 'whereAdd' => "join_status_id.name IN ('new', 'assigned', 'reopened', 'open')
66 mtrack_ticket.project_id = [PROJECTID] ",
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"
79 'title' => "Closed tickets",
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',
87 'milestone' => 'join_milestone_id_id.name',
88 '_milestone_id' => 'join_milestone_id_id.id',
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',
96 'whereAdd' => "join_status_id.name IN ('closed')
98 mtrack_ticket.project_id = [PROJECTID] ",
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"
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',
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',
123 'whereAdd' => "join_status_id.name IN ('completed')
125 mtrack_ticket.project_id = [PROJECTID] ",
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 "
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',
145 'summary' => array("'['", 'join_status_id.name' , "'] '", "summary"), // fixme..
146 'milestone' => 'join_milestone_id_id.name',
147 '_milestone_id' => 'join_milestone_id_id.id',
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',
156 join_status_id.name IN ('new', 'assigned', 'reopened', 'open')
158 (mtrack_ticket.owner_id = [UID] OR mtrack_ticket.developer_id = [UID] )
160 mtrack_ticket.project_id = [PROJECTID] ",
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"
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',
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',
189 join_status_id.name IN ('new', 'assigned', 'reopened', 'open')
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
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',
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',
220 join_status_id.name IN ('new', 'assigned', 'reopened', 'open')
222 (mtrack_ticket.owner_id = [UID] )
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
237 if (!isset($cfg[$id])) {
238 die("invalid report id");
240 $this->cfg = $cfg[$id];
242 $this->title = $this->cfg->title;
246 // move back to controller...
248 function render($params = array(), $format = 'html')
251 $link = HTML_FlexyFramework::get()->page->link;
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 */
258 $au = HTML_Flexyframework::get()->page->authUser;
260 //DB_DataObject::DebugLevel(1);
264 $this->title = $this->cfg->title;
267 $x = DB_DataObject::factory('mtrack_ticket');
271 foreach($this->cfg->selectAdd as $k=>$v) {
273 //foreach($v as $k) { -- quote..
274 // $ar[] = $l[0] == "'" ? $k :
276 $v = 'CONCAT(' . implode(', ', $v) . ')';
278 $v = '`' . str_replace('.', '`.`', $v ) . '`';
281 $x->selectAdd("$v as $k");
284 //DB_DataObject::DebugLevel(1);
285 $pg = HTML_Flexyframework::get()->page;
286 //$x->project_id = HTML_Flexyframework::get()->page->currentProject();
288 $uid = empty($au) ? -1 : $au->id;
291 $whereAdd = str_replace('[UID]', $uid, $this->cfg->whereAdd );
292 $whereAdd = str_replace('[PROJECTID]', $pg->currentProject(), $whereAdd );
294 $x->whereAdd( $whereAdd );
296 // access to valid projects only.
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');
305 // no authenticated user - > only current project
307 $x->project_id = $pg->currentProject();
311 $x->orderBy( $this->cfg->orderBy);
316 while ($x->fetch()) {
317 //echo '<PRE>';print_r($x);exit;
318 $results[] = $x->toArray('%s',0);
320 //echo '<PRE>'; print_r($results);
324 if (count($results) == 0) {
325 return "No records matched";
328 /* figure out the table headings */
332 foreach ($results[0] as $name => $value) {
333 if (preg_match("/^__.*__$/", $name)) {
334 if ($format == 'html') {
335 /* special meaning, not a column */
339 $captions[$name] = preg_replace("/^_(.*)_$/", "\\1", $name);
340 // temporary.. names for columsn.
345 /* for spanning purposes, calculate the longest row */
346 // no idea what this is supposed to do...
350 foreach ($captions as $name => $caption) {
351 if ($name[0] == '_' && substr($name, -1) == '_') {
356 if ($width > $max_width) {
359 if (substr($name, -1) == '_') {
366 foreach ($results as $nrow => $row) {
368 $starting_new_group = false;
371 $starting_new_group = true;
373 } else if ($format == 'html' &&
374 (isset($row['__group__']) && $group !== $row['__group__'])) {
375 $starting_new_group = true;
378 if ($starting_new_group) {
379 /* starting a new group */
381 /* close the old one */
382 if ($format == 'html') {
383 $out .= "</tbody></table>\n";
386 if ($format == 'html' && isset($row['__group__'])) {
388 $out .= "<h2 class='reportgroup'>" .
390 htmlentities($row['__group__'], ENT_COMPAT, 'utf-8') .
392 $group = $row['__group__'];
395 if ($format == 'html') {
396 $out .= "<table class='report'><thead><tr>";
400 foreach ($captions as $name => $caption) {
402 /* figure out sort info for javascript bits */
404 switch (strtolower($caption)) {
408 $sort = strtolower($caption);
415 $sort = 'mtrackdate';
430 case 'ticket' : $caption = "Edit #"; break;
431 case 'summary' : $caption = "Summary (View/Comment)"; break;
434 $caption = str_replace('_', ' ',ucfirst($caption));
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";
443 } elseif ($name[0] == '_') {
446 if ($format == 'html') {
448 if ($sort !== null) {
449 $out .= " class=\"{sorter: '$sort'}\"";
451 $out .= ">$caption</th>";
452 if (substr($name, -1) == '_') {
455 } else if ($format == 'tab') {
456 $out .= "$caption\t";
460 if ($format == 'html') {
461 $out .= "</tr></thead><tbody>\n";
462 } else if ($format == 'tab') {
467 // and now the column data itself
468 if (isset($row['__style__'])) {
469 $style = " style=\"$row[__style__]\"";
473 $class = $nrow % 2 ? "even" : "odd";
474 if (isset($row['__color__'])) {
475 $class .= " color". strtolower($row['__color__']);
477 if (isset($row['__status__'])) {
478 $class .= " status$row[__status__]";
481 if ($format == 'html') {
482 $begin_row = "<tr class=\"$class\"$style>";
488 /* determine if we should link to something for this row */
490 //if (isset($row['ticket'])) {
492 // $href = $ABSWEB . "/Ticket.php/$row[ticket]";
496 foreach ($captions as $name => $caption) {
500 /* apply special formatting rules */
501 if ($format == 'html') {
502 switch (strtolower($caption)) {
510 $v = $link->date($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>';
523 case 'classification':
525 $v = '<div class="ticket-enum ticket-enum-' . strtolower($caption).'">' .
526 htmlspecialchars($v) . '</div>';
530 $v = htmlspecialchars($v); //MTrack_Wiki::format_to_html($v);
533 $v = $link->username($v, array('no_image' => true));
538 $v = $link->ticket($row['ticket']); // what about doc id?
542 $v = isset($row['ticket']) ?
543 $link->ticket($row['ticket'], array('display' => $v)) :
544 $v= htmlspecialchars($v);
547 // actually we only have one milestone at present..
549 $v = $link->milestone($row['_milestone_id'], $v);
556 foreach (preg_split("/\s*,\s*/", $oldv) as $m) {
557 if (!strlen($m)) continue;
558 $v .= $link->keyword($m) . ' ';
562 $v = htmlentities($v, ENT_QUOTES, 'utf-8');
564 } else if ($format == 'tab') {
565 $v = trim(preg_replace("/[\t\n\r]+/sm", " ", $v));
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') {
574 } elseif ($name[0] == '_') {
575 if ($format == 'tab') {
581 if ($format == 'html') {
582 $out .= "<td class='$caption'>$v</td>";
583 if (substr($name, -1) == '_') {
584 $out .= "</tr>$begin_row";
586 } else if ($format == 'tab') {
591 if ($format == 'html') {
593 } else if ($format == 'tab') {
597 if ($format == 'html') {
598 $out .= "</tbody></table>";
599 } else if ($format == 'tab') {
600 $out = str_replace("\t\n", "\n", $out);
608 function fetchResults()
610 $au = HTML_Flexyframework::get()->page->authUser;
612 $x = DB_DataObject::factory('mtrack_ticket');
616 foreach($this->cfg->selectAdd as $k=>$v) {
618 //foreach($v as $k) { -- quote..
619 // $ar[] = $l[0] == "'" ? $k :
621 $v = 'CONCAT(' . implode(', ', $v) . ')';
623 $v = '`' . str_replace('.', '`.`', $v ) . '`';
626 $x->selectAdd("$v as $k");
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;
635 $whereAdd = str_replace('[UID]', $uid, $this->cfg->whereAdd );
636 $whereAdd = str_replace('[PROJECTID]', $pg->currentProject(), $whereAdd );
638 $x->whereAdd( $whereAdd );
640 // access to valid projects only.
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');
649 // no authenticated user - > only current project
651 $x->project_id = $pg->currentProject();
655 $x->orderBy( $this->cfg->orderBy);
660 while ($x->fetch()) {
661 //echo '<PRE>';print_r($x);exit;
662 $results[] = $x->toArray('%s',0);
664 //echo '<PRE>'; print_r($results);
673 * JSON version of report.
683 'groups' => array( // GROUP
701 function renderToJSON()
704 $link = HTML_FlexyFramework::get()->page->link;
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 */
711 $au = HTML_Flexyframework::get()->page->authUser;
713 //DB_DataObject::DebugLevel(1);
717 $this->title = $this->cfg->title;
719 $results = $this->fetchResults();
721 //echo '<PRE>'; print_r($results);
725 if (count($results) == 0) {
736 /* figure out the table headings */
740 foreach ($results[0] as $name => $value) {
741 if (preg_match("/^__.*__$/", $name)) {
743 /* special meaning, not a column */
748 $captions[$name] = preg_replace("/^_(.*)_$/", "\\1", $name);
749 // temporary.. names for columsn.
753 $ret['headers'] = $captions;
757 munge the header capiton names...
759 foreach ($captions as $name => $caption) {
763 switch (strtolower($caption)) {
767 $sort = strtolower($caption);
774 $sort = 'mtrackdate';
790 case 'ticket' : $caption = "Edit #"; break;
791 case 'summary' : $caption = "Summary (View/Comment)"; break;
794 $caption = str_replace('_', ' ',ucfirst($caption));
797 if ($name[0] == '_' && substr($name,-1) == '_') {
798 if ($format == 'html') {
800 $out .= "</tr><tr><th colspan='$max_width'>$caption</th></tr><tr>";
801 } else if ($format == 'tab') {
802 $out .= "$caption\t";
804 } elseif ($name[0] == '_') {
807 if ($format == 'html') {
809 if ($sort !== null) {
810 $out .= " class=\"{sorter: '$sort'}\"";
812 $out .= ">$caption</th>";
813 if (substr($name, -1) == '_') {
816 } else if ($format == 'tab') {
817 $out .= "$caption\t";
821 if ($format == 'html') {
822 $out .= "</tr></thead><tbody>\n";
823 } else if ($format == 'tab') {
835 foreach ($results as $nrow => $row) {
837 $starting_new_group = false;
840 $starting_new_group = true;
843 (isset($row['__group__']) && $group !== $row['__group__'])) {
844 $starting_new_group = true;
847 if ($starting_new_group) {
848 /* starting a new group */
850 /* close the old one */
851 $ret['groups'][] = $curgroup;
854 if (isset($row['__group__'])) {
855 $curgroup['title'] = $row['__group__'];
856 $group = $row['__group__'];
862 // and now the column data itself
863 if (isset($row['__style__'])) {
865 $style = $row[__style__];
869 $class = $nrow % 2 ? "even" : "odd";
870 if (isset($row['__color__'])) {
871 $class .= " color". strtolower($row['__color__']);
873 if (isset($row['__status__'])) {
874 $class .= " status$row[__status__]";
885 foreach ($captions as $name => $caption) {
889 /* apply special formatting rules */
891 switch (strtolower($caption)) {
899 // $v = $link->date($v);
905 case 'classification':
913 // $v = $link->username($v, array('no_image' => true));
919 //$v = $link->ticket($row['ticket']); // what about doc id?
924 //$v = isset($row['ticket']) ? $link->ticket($row['ticket'], array('display' => $v)) : $v;
930 // actually we only have one milestone at present..
932 //$v = $link->milestone($row['_milestone_id'], $v);
941 foreach (preg_split("/\s*,\s*/", $oldv) as $m) {
942 if (!strlen($m)) continue;
943 $v .= $link->keyword($m) . ' ';
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";
962 $curgroup['rows'][] = $crow;
966 $ret['groups'][] = $curgroup;
967 echo '<PRE>' . htmlspecialchars( print_R($ret,true));exit;