[ Index ]

Source Code Reference for V1.00

title

Body

[close]

/modules/projectdesigner/ -> gantt.php (source)

   1  <?php /* $Id: gantt.php 169 2008-05-21 00:51:56Z pedroix $ $URL: https://web2project.svn.sourceforge.net/svnroot/web2project/trunk/modules/projectdesigner/gantt.php $ */
   2  
   3  /*
   4  * Gantt.php - by J. Christopher Pereira
   5  * PROJECTDESIGNER $Id: gantt.php 169 2008-05-21 00:51:56Z pedroix $
   6  */
   7  
   8  ini_set('memory_limit', $w2Pconfig['reset_memory_limit']);
   9  
  10  include ($AppUI->getLibraryClass('jpgraph/src/jpgraph'));
  11  include ($AppUI->getLibraryClass('jpgraph/src/jpgraph_gantt'));
  12  
  13  global $caller, $locale_char_set, $showLabels, $showWork, $showLabels, $showPinned, $showArcProjs, $showHoldProjs, $showDynTasks, $showLowTasks, $user_id;
  14  
  15  $project_id = defVal($_REQUEST['project_id'], 0);
  16  $f = defVal($_REQUEST['f'], 0);
  17  
  18  // get the prefered date format
  19  $df = $AppUI->getPref('SHDATEFORMAT');
  20  
  21  require_once $AppUI->getModuleClass('projects');
  22  $project = &new CProject;
  23  $criticalTasks = ($project_id > 0) ? $project->getCriticalTasks($project_id) : null;
  24  $criticalTasksInverted = ($project_id > 0) ? getCriticalTasksInverted($project_id) : null;
  25  
  26  // pull valid projects and their percent complete information
  27  
  28  $q = new DBQuery;
  29  $q->addTable('projects', 'pr');
  30  $q->addQuery('pr.project_id, project_color_identifier, project_name, project_start_date, project_end_date');
  31  $q->addJoin('tasks', 't1', 'pr.project_id = t1.task_project');
  32  if ($project_id) {
  33      $q->addWhere('pr.project_id = ' . (int)$project_id);
  34  }
  35  $q->addGroup('pr.project_id');
  36  $q->addOrder('project_name');
  37  $project->setAllowedSQL($AppUI->user_id, $q, null, 'pr');
  38  $projects = $q->loadHashList('project_id');
  39  $q->clear();
  40  
  41  // pull tasks
  42  $q = new DBQuery;
  43  $q->addTable('tasks', 't');
  44  $q->addQuery('t.task_id, task_parent, task_name, task_start_date, task_end_date, task_duration, task_duration_type, task_priority, task_percent_complete, task_order, task_project, task_milestone, project_name, task_dynamic');
  45  $q->addJoin('projects', 'p', 'project_id = t.task_project', 'inner');
  46  $q->addOrder('project_id, task_start_date');
  47  if ($project_id) {
  48      $q->addWhere('task_project = ' . (int)$project_id);
  49  }
  50  switch ($f) {
  51      case 'all':
  52          $q->addWhere('task_status > -1');
  53          break;
  54      case 'myproj':
  55          $q->addWhere('task_status > -1');
  56          $q->addWhere('project_owner = ' . (int)$AppUI->user_id);
  57          break;
  58      case 'mycomp':
  59          $q->addWhere('task_status > -1');
  60          $q->addWhere('project_company = ' . (int)$AppUI->user_company);
  61          break;
  62      case 'myinact':
  63          $q->addTable('user_tasks', 'ut');
  64          $q->addWhere('task_project = p.project_id');
  65          $q->addWhere('ut.user_id = ' . (int)$AppUI->user_id);
  66          $q->addWhere('ut.task_id = t.task_id');
  67          break;
  68      default:
  69          $q->addTable('user_tasks', 'ut');
  70          $q->addWhere('task_status > -1');
  71          $q->addWhere('task_project = p.project_id');
  72          $q->addWhere('ut.user_id = ' . (int)$AppUI->user_id);
  73          $q->addWhere('ut.task_id = t.task_id');
  74          break;
  75  }
  76  
  77  // get any specifically denied tasks
  78  $task = &new CTask;
  79  $task->setAllowedSQL($AppUI->user_id, $q);
  80  
  81  $proTasks = $q->loadHashList('task_id');
  82  $orrarr[] = array('task_id' => 0, 'order_up' => 0, 'order' => '');
  83  
  84  $end_max = '0000-00-00 00:00:00';
  85  $start_min = date('Y-m-d H:i:s');
  86  
  87  //pull the tasks into an array
  88  foreach ($proTasks as $row) {
  89  
  90      //Check if start date exists, if not try giving it the end date.
  91      //If the end date does not exist then set it for today.
  92      //This avoids jpgraphs internal errors that render the gantt completely useless
  93      if ($row['task_start_date'] == '0000-00-00 00:00:00') {
  94          if ($row['task_end_date'] == '0000-00-00 00:00:00') {
  95              $todaydate = new CDate();
  96              $row['task_start_date'] = $todaydate->format(FMT_TIMESTAMP_DATE);
  97          } else {
  98              $row['task_start_date'] = $row['task_end_date'];
  99          }
 100      }
 101  
 102      $tsd = new CDate($row['task_start_date']);
 103  
 104      if ($tsd->before(new CDate($start_min))) {
 105          $start_min = $row['task_start_date'];
 106      }
 107  
 108      //Check if end date exists, if not try giving it the start date.
 109      //If the start date does not exist then set it for today.
 110      //This avoids jpgraphs internal errors that render the gantt completely useless
 111      if ($row['task_end_date'] == '0000-00-00 00:00:00') {
 112          if ($row['task_duration']) {
 113              $row['task_end_date'] = db_unix2dateTime(db_dateTime2unix($row['task_start_date']) + SECONDS_PER_DAY * convert2days($row['task_duration'], $row['task_duration_type']));
 114          } else {
 115              $todaydate = new CDate();
 116              $row['task_end_date'] = $todaydate->format(FMT_TIMESTAMP_DATE);
 117          }
 118      }
 119  
 120      $ted = new CDate($row['task_end_date']);
 121  
 122      if ($ted->after(new CDate($end_max))) {
 123          $end_max = $row['task_end_date'];
 124      }
 125  
 126      $projects[$row['task_project']]['tasks'][] = $row;
 127  }
 128  $q->clear();
 129  $width = w2PgetParam($_GET, 'width', 600);
 130  //consider critical (concerning end date) tasks as well
 131  $start_min = substr($criticalTasksInverted[0]['task_start_date'], 0, 10);
 132  if ($start_min == '0000-00-00' || !$start_min) {
 133      $start_min = $projects[$project_id]['project_start_date'];
 134  }
 135  //    $end_max = ($projects[$project_id]['project_end_date'] > $criticalTasks[0]['task_end_date']) ? $projects[$project_id]['project_end_date'] : $criticalTasks[0]['task_end_date'];
 136  $end_max = substr($criticalTasks[0]['task_end_date'], 0, 10);
 137  if ($end_max == '0000-00-00' || !$end_max) {
 138      $end_max = $projects[$project_id]['project_end_date'];
 139  }
 140  $start_date = w2PgetParam($_GET, 'start_date', $start_min);
 141  $end_date = w2PgetParam($_GET, 'end_date', $end_max);
 142  
 143  $count = 0;
 144  
 145  $graph = new GanttGraph($width);
 146  $graph->ShowHeaders(GANTT_HYEAR | GANTT_HMONTH | GANTT_HDAY | GANTT_HWEEK);
 147  //$graph->ShowHeaders(GANTT_HYEAR | GANTT_HMONTH | GANTT_HDAY);
 148  
 149  $graph->SetFrame(false);
 150  $graph->SetBox(true, array(0, 0, 0), 2);
 151  $graph->scale->week->SetStyle(WEEKSTYLE_FIRSTDAY);
 152  //$graph->scale->day->SetStyle(DAYSTYLE_SHORTDATE2);
 153  
 154  $pLocale = setlocale(LC_TIME, 0); // get current locale for LC_TIME
 155  $res = setlocale(LC_TIME, $AppUI->user_lang[2]);
 156  if ($res) { // Setting locale doesn't fail
 157      $graph->scale->SetDateLocale($AppUI->user_lang[2]);
 158  }
 159  setlocale(LC_TIME, $pLocale);
 160  
 161  if ($start_date && $end_date) {
 162      $graph->SetDateRange($start_date, $end_date);
 163  }
 164  if (is_file(TTF_DIR . 'FreeSans.ttf')) {
 165      $graph->scale->actinfo->SetFont(FF_CUSTOM);
 166  }
 167  $graph->scale->actinfo->vgrid->SetColor('gray');
 168  $graph->scale->actinfo->SetColor('darkgray');
 169  
 170  if ($showWork == '1') {
 171      $graph->scale->actinfo->SetColTitles(array($AppUI->_('Task name', UI_OUTPUT_RAW), $AppUI->_('Work', UI_OUTPUT_RAW), $AppUI->_('Start', UI_OUTPUT_RAW), $AppUI->_('Finish', UI_OUTPUT_RAW)), array(230, 60, 60, 60));
 172  } else {
 173      $graph->scale->actinfo->SetColTitles(array($AppUI->_('Task name', UI_OUTPUT_RAW), $AppUI->_('Dur.', UI_OUTPUT_RAW), $AppUI->_('Start', UI_OUTPUT_RAW), $AppUI->_('Finish', UI_OUTPUT_RAW)), array(230, 60, 60, 60));
 174  }
 175  $graph->scale->tableTitle->Set($projects[$project_id]['project_name']);
 176  
 177  // Use TTF font if it exists
 178  // try commenting out the following two lines if gantt charts do not display
 179  if (is_file(TTF_DIR . 'FreeSans.ttf')) {
 180      $graph->scale->tableTitle->SetFont(FF_CUSTOM, FS_BOLD, 12);
 181  }
 182  $graph->scale->SetTableTitleBackground('#' . $projects[$project_id]['project_color_identifier']);
 183  $font_color = bestColor('#' . $projects[$project_id]['project_color_identifier']);
 184  $graph->scale->tableTitle->SetColor($font_color);
 185  $graph->scale->tableTitle->Show(true);
 186  
 187  //-----------------------------------------
 188  // nice Gantt image
 189  // if diff(end_date,start_date) > 90 days it shows only
 190  //week number
 191  // if diff(end_date,start_date) > 240 days it shows only
 192  //month number
 193  //-----------------------------------------
 194  if ($start_date && $end_date) {
 195      $min_d_start = new CDate($start_date);
 196      $max_d_end = new CDate($end_date);
 197  } else {
 198      // find out DateRange from gant_arr
 199      $min_d_start = new CDate();
 200      $max_d_end = new CDate();
 201      $d_start = new CDate();
 202      $d_end = new CDate();
 203      for ($i = 0, $i_cmp = count($gantt_arr); $i < $i_cmp; $i++) {
 204          $a = $gantt_arr[$i][0];
 205          $start = substr($a['task_start_date'], 0, 10);
 206          $end = substr($a['task_end_date'], 0, 10);
 207  
 208          $d_start->Date($start);
 209          $d_end->Date($end);
 210  
 211          if ($i == 0) {
 212              $min_d_start = $d_start->duplicate();
 213              $max_d_end = $d_end->duplicate();
 214          } else {
 215              if (Date::compare($min_d_start, $d_start) > 0) {
 216                  $min_d_start = $d_start->duplicate();
 217              }
 218              if (Date::compare($max_d_end, $d_end) < 0) {
 219                  $max_d_end = $d_end->duplicate();
 220              }
 221          }
 222      }
 223  }
 224  
 225  // check day_diff and modify Headers
 226  $day_diff = $min_d_start->dateDiff($max_d_end);
 227  
 228  if ($day_diff > 240) {
 229      //more than 240 days
 230      $graph->ShowHeaders(GANTT_HYEAR | GANTT_HMONTH);
 231  } elseif ($day_diff > 90) {
 232      //more than 90 days and less of 241
 233      $graph->ShowHeaders(GANTT_HYEAR | GANTT_HMONTH | GANTT_HWEEK);
 234      $graph->scale->week->SetStyle(WEEKSTYLE_WNBR);
 235  }
 236  
 237  //This kludgy function echos children tasks as threads
 238  
 239  function showgtask(&$a, $level = 0) {
 240      /* Add tasks to gantt chart */
 241  
 242      global $gantt_arr;
 243  
 244      $gantt_arr[] = array($a, $level);
 245  
 246  }
 247  
 248  function findgchild(&$tarr, $parent, $level = 0) {
 249      global $projects;
 250      $level = $level + 1;
 251      $n = count($tarr);
 252      for ($x = 0; $x < $n; $x++) {
 253          if ($tarr[$x]['task_parent'] == $parent && $tarr[$x]['task_parent'] != $tarr[$x]['task_id']) {
 254              showgtask($tarr[$x], $level);
 255              findgchild($tarr, $tarr[$x]['task_id'], $level);
 256          }
 257      }
 258  }
 259  
 260  reset($projects);
 261  //$p = &$projects[$project_id];
 262  foreach ($projects as $p) {
 263      $tnums = count($p['tasks']);
 264  
 265      for ($i = 0; $i < $tnums; $i++) {
 266          $t = $p['tasks'][$i];
 267          if ($t['task_parent'] == $t['task_id']) {
 268              showgtask($t);
 269              findgchild($p['tasks'], $t['task_id']);
 270          }
 271      }
 272  }
 273  
 274  $hide_task_groups = false;
 275  
 276  if ($hide_task_groups) {
 277      for ($i = 0, $i_cmp = count($gantt_arr); $i < $i_cmp; $i++) {
 278          // remove task groups
 279          if ($i != count($gantt_arr) - 1 && $gantt_arr[$i + 1][1] > $gantt_arr[$i][1]) {
 280              // it's not a leaf => remove
 281              array_splice($gantt_arr, $i, 1);
 282              continue;
 283          }
 284      }
 285  }
 286  
 287  $row = 0;
 288  for ($i = 0, $i_cmp = count($gantt_arr); $i < $i_cmp; $i++) {
 289  
 290      $a = $gantt_arr[$i][0];
 291      $level = $gantt_arr[$i][1];
 292  
 293      if ($hide_task_groups) {
 294          $level = 0;
 295      }
 296  
 297      $name = $a['task_name'];
 298      if ($locale_char_set == 'utf-8' && function_exists('utf8_decode')) {
 299          $name = utf8_decode($name);
 300      }
 301      $name = strlen($name) > 34 ? substr($name, 0, 33) . '.' : $name;
 302      $name = str_repeat(' ', $level) . $name;
 303  
 304      if ($caller == 'todo') {
 305          $pname = $a['project_name'];
 306          if ($locale_char_set == 'utf-8') {
 307              if (function_exists('mb_substr')) {
 308                  $pname = mb_strlen($pname) > 14 ? mb_substr($pname, 0, 5) . '...' . mb_substr($pname, -5, 5) : $pname;
 309              } elseif (function_exists('utf8_decode')) {
 310                  $pname = utf8_decode($pname);
 311              }
 312          } else {
 313              $pname = strlen($pname) > 14 ? substr($pname, 0, 5) . '...' . substr($pname, -5, 5) : $pname;
 314          }
 315      }
 316      //using new jpGraph determines using Date object instead of string
 317      $start = $a['task_start_date'];
 318      $end_date = $a['task_end_date'];
 319  
 320      $end_date = new CDate($end_date);
 321      //        $end->addDays(0);
 322      $end = $end_date->getDate();
 323  
 324      $start = new CDate($start);
 325      //        $start->addDays(0);
 326      $start = $start->getDate();
 327  
 328      $progress = $a['task_percent_complete'] + 0;
 329  
 330      if ($progress > 100) {
 331          $progress = 100;
 332      } elseif ($progress < 0) {
 333          $progress = 0;
 334      }
 335  
 336      $flags = ($a['task_milestone'] ? 'm' : '');
 337  
 338      $cap = '';
 339      if (!$start || $start == '0000-00-00') {
 340          $start = !$end ? date('Y-m-d') : $end;
 341          $cap .= '(no start date)';
 342      }
 343  
 344      if (!$end) {
 345          $end = $start;
 346          $cap .= ' (no end date)';
 347      } else {
 348          $cap = '';
 349      }
 350  
 351      $caption = '';
 352      if ($showLabels == '1') {
 353          $q = new DBQuery;
 354          $q->addTable('user_tasks', 'ut');
 355          $q->addTable('users', 'u');
 356          $q->addTable('contacts', 'c');
 357          $q->addQuery('ut.task_id, u.user_username, ut.perc_assignment');
 358          $q->addQuery('c.contact_first_name, c.contact_last_name');
 359          $q->addWhere('u.user_id = ut.user_id');
 360          $q->addWhere('u.user_contact = c.contact_id');
 361          $q->addWhere('ut.task_id = ' . (int)$a['task_id']);
 362          $res = $q->loadList();
 363          foreach ($res as $rw) {
 364              switch ($rw['perc_assignment']) {
 365                  case 100:
 366                      $caption = $caption . '' . $rw['contact_first_name'] . ' ' . $rw['contact_last_name'] . ';';
 367                      break;
 368                  default:
 369                      $caption = $caption . '' . $rw['contact_first_name'] . ' ' . $rw['contact_last_name'] . ' [' . $rw['perc_assignment'] . '%];';
 370                      break;
 371              }
 372          }
 373          $q->clear();
 374          $caption = substr($caption, 0, strlen($caption) - 1);
 375      }
 376  
 377      if ($flags == 'm') {
 378          $start = new CDate($start);
 379          $start->addDays(0);
 380          $s = $start->