Anonymous Login
2019-04-18 13:31 PDT

View Issue Details Jump to Notes ]
IDProjectCategoryView StatusLast Update
0001024v3.0 Release[All Projects] Generalpublic2013-08-28 11:22
Reporterproject_manager 
Assigned Tocaseydk 
PrioritynormalSeveritycrashReproducibilityalways
StatusclosedResolutionfixed 
Product Version 
Target VersionFixed in Version3.0.0 
Summary0001024: bug description & suggested solution
Descriptionhttp://forums.web2project.net/viewtopic.php?p=13827#13827

@pedroa:
@opto:

Thanks opto, I installed XAMPP for Win on my VISTA-PC and started to debug the php-code with Netbeans & Xdebug. Very nice & so simpel. I would recommend for anyone to do it. If I can do (no clue about servers, php and so on) probably anybody can do it too....

As I already evaluated in the posts before the error is caused by a really stupid syntax bug!

Enclosed I put also the "gantt_pdf.php" where I marked and commented the problem & solution.

The slicing works for the tasks (25x) but I kept the time-x-axis constant, so I dont know this is the expected behaviour. Otherwise the date-range on each slice has to be handled.

I would suggest that the developers take this as a suggestion, reviewing it and rework it where necessary and put it to SVN.

@pedroa:
Could you please additionally post the bug that the time-range can not be adjusted by the start/end-Tabs in the top of the view? It would be nice to adjust the time scale as already for the gantt-view possible! Thanks.

---------------------------------------------------------------------------
Change the following in gantt_pdf.php:

// set here any date span you want: bug work around!
$start_date = '2012-03-01 00:00:00' ;
$end_date = '2012-05-01 00:00:00' ;

/* --------------------------------------------------------- */
// initial store String variables $start_date & $end_date !!!
/* --------------------------------------------------------- */
$start_date2 = $start_date;
$end_date2 = $end_date;

/* --------------------------------------------------------- */
// 1. loop handling the number of sliced sub-projects, each having 25/26 tasks
/* --------------------------------------------------------- */
foreach ($gtask_sliced as $gts) {

/* --------------------------------------------------------- */
// always restore String variables $start_date & $end_date !!!
/* --------------------------------------------------------- */
$start_date = $start_date2;
$end_date = $end_date2;
/* --------------------------------------------------------- */
//
// during slicing(), if more than 25 tasks !, the variables $start_date & $end_date are re-assigned to an object...
// and also re-used in an another context.
//
// ---> in 2. loop: for($i = 0; $i ... count($gts); $i ++) {...
// ---> re-assign & re-use:
//
// $start_date = new w2p_Utilities_Date($a['task_start_date']);
// $end_date = new w2p_Utilities_Date($a['task_end_date']);
//
// causing:
// "strpos() expects parameter 1 to be string, object given in /var/customers/.../web2project-3.0/lib/jpgraph/src/jpgraph_gantt.php on line 524"
/* --------------------------------------------------------- */
---------------------------------------------------------------------------


Please notice also the other bug-report/solution for:

"JpGraph Error General PHP error : Undefined variable: criticalTasks"

http://forums.web2project.net/viewtopic.php?p=13826#13826

roger & out.
Additional Informationprobably all versions, syntax/logic bug in "gantt_pdf.php".
should be reviewed by the developers to accept
TagsNo tags attached.
Attached Files
  • txt file icon gantt_pdf.php.txt (23,981 bytes) 1969-12-31 16:00 -
    <?php /* $Id$ $URL$ */
    if (!defined('W2P_BASE_DIR')) {
    	die('You should not access this file directly.');
    }
    
    global $gantt_arr, $w2Pconfig, $project_id, $gtask_sliced, $printpdfhr, $showNoMilestones;
    
    w2PsetExecutionConditions($w2Pconfig);
    
    $f = w2PgetParam($_REQUEST, 'f', 0);
    
    $showLabels = (int) w2PgetParam($_REQUEST, 'showLabels', 0);
    $showWork = (int) w2PgetParam($_REQUEST, 'showWork', 0);
    
    $showPinned = (int) w2PgetParam( $_REQUEST, 'showPinned', false );
    $showArcProjs = (int) w2PgetParam( $_REQUEST, 'showArcProjs', false );
    $showHoldProjs = (int) w2PgetParam( $_REQUEST, 'showHoldProjs', false );
    $showDynTasks = (int) w2PgetParam( $_REQUEST, 'showDynTasks', false );
    $showLowTasks = (int) w2PgetParam( $_REQUEST, 'showLowTasks', true);
    
    $project = new CProject();
    $criticalTasks = ($project_id > 0) ? $project->getCriticalTasks($project_id) : null;
    
    // pull valid projects and their percent complete information
    $projects = $project->getAllowedProjects($AppUI->user_id, false);
    
    ##############################################
    /* gantt is called now by the todo page, too.
    ** there is a different filter approach in todo
    ** so we have to tweak a little bit,
    ** also we do not have a special project available
    */
    $caller = w2PgetParam($_REQUEST, 'caller', null);
    
    if ($caller == 'todo') {
    	$user_id = w2PgetParam($_REQUEST, 'user_id', $AppUI->user_id);
    
    	$projects[$project_id]['project_name'] = $AppUI->_('Todo for') . ' ' . CContact::getContactByUserid($user_id);
    	$projects[$project_id]['project_color_identifier'] = 'ff6000';
    
    	$q = new w2p_Database_Query;
    	$q->addQuery('t.*');
    	$q->addQuery('project_name, project_id, project_color_identifier');
    	$q->addQuery('tp.task_pinned');
    	$q->addTable('tasks', 't');
        $q->innerJoin('projects', 'pr', 'pr.project_id = t.task_project');
     	$q->leftJoin('user_tasks', 'ut', 'ut.task_id = t.task_id AND ut.user_id = ' . (int) $user_id);
    	$q->leftJoin('user_task_pin', 'tp', 'tp.task_id = t.task_id and tp.user_id = ' . (int)$user_id);
    	$q->addWhere('(t.task_percent_complete < 100 OR t.task_percent_complete IS NULL)');
    	$q->addWhere('t.task_status = 0');
    	if (!$showArcProjs) {
    		$q->addWhere('pr.project_active = 1');
    		if (($template_status = w2PgetConfig('template_projects_status_id')) != '') {
    			$q->addWhere('pr.project_status <> ' . (int)$template_status);
    		}
    	}
    	if (!$showLowTasks) {
    		$q->addWhere('task_priority >= 0');
    	}
    	if (!$showHoldProjs) {
    		$q->addWhere('project_active = 1');
    	}
    	if (!$showDynTasks) {
    		$q->addWhere('task_dynamic <> 1');
    	}
    	if ($showPinned) {
    		$q->addWhere('task_pinned = 1');
    	}
    
        $q->addGroup('t.task_id');
        
        
     // $q->addOrder('t.task_end_date, t.task_priority DESC');
        $q->addOrder('task_parent, task_start_date');    
        
        
        
    } 
    
    else {
    	// pull tasks
    	$q = new w2p_Database_Query();
    	$q->addTable('tasks', 't');
    	$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, task_access, task_owner, '.
            ' project_name, project_color_identifier, task_dynamic');
    	$q->addJoin('projects', 'p', 'project_id = t.task_project', 'inner');
      
                          
     //   $q->addOrder('p.project_id, t.task_end_date');
          $q->addOrder('p.project_id, task_parent, task_start_date, t.task_id'); 
    
    
    
    
    
        
    	if ($project_id) {
    		$q->addWhere('task_project = ' . (int)$project_id);
    	}
    
    	switch ($f) {
    		case 'all':
    			$q->addWhere('task_status > -1');
    			break;
    		case 'myproj':
    			$q->addWhere('task_status > -1');
    			$q->addWhere('project_owner = ' . (int)$AppUI->user_id);
    			break;
    		case 'mycomp':
    			$q->addWhere('task_status > -1');
    			$q->addWhere('project_company = ' . (int)$AppUI->user_company);
    			break;
    		case 'myinact':
    			$q->innerJoin('user_tasks', 'ut', 'ut.task_id = t.task_id');
    			$q->addWhere('ut.user_id = '.$AppUI->user_id);
    			break;
    		default:
    			$q->innerJoin('user_tasks', 'ut', 'ut.task_id = t.task_id');
    			$q->addWhere('ut.user_id = '.$AppUI->user_id);
    			break;
    	}
    }
    
    
    
    // get any specifically denied tasks
    $task = new CTask();
    $task->setAllowedSQL($AppUI->user_id, $q);
    $proTasks = $q->loadHashList('task_id');
    $q->clear();
    
    $orrarr[] = array('task_id'=>0, 'order_up'=>0, 'order'=>'');
    $end_max = '0000-00-00 00:00:00';
    $start_min = date('Y-m-d H:i:s');
    
    //pull the tasks into an array
    if ($caller != 'todo') {
    	$criticalTasks = $project->getCriticalTasks($project_id);
    }
    
    foreach ($proTasks as $row) {
    	//Check if start date exists, if not try giving it the end date.
    	//If the end date does not exist then set it for today.
    	//This avoids jpgraphs internal errors that render the gantt completely useless
    	if ($row['task_start_date'] == '0000-00-00 00:00:00') {
    		if ($row['task_end_date'] == '0000-00-00 00:00:00') {
    			$todaydate = new w2p_Utilities_Date();
    			$row['task_start_date'] = $todaydate->format(FMT_TIMESTAMP_DATE);
    		} else {
    			$row['task_start_date'] = $row['task_end_date'];
    		}
    	}
    
    	$tsd = new w2p_Utilities_Date($row['task_start_date']);
    	if ($tsd->before(new w2p_Utilities_Date($start_min))) {
    		$start_min = $row['task_start_date'];
    	}
    
    	//Check if end date exists, if not try giving it the start date.
    	//If the start date does not exist then set it for today.
    	//This avoids jpgraphs internal errors that render the gantt completely useless
    	if ($row['task_end_date'] == '0000-00-00 00:00:00') {
    		if ($row['task_duration']) {
    			$row['task_end_date'] = db_unix2dateTime(db_dateTime2unix($row['task_start_date']) + SECONDS_PER_DAY * convert2days($row['task_duration'], $row['task_duration_type']));
    		} else {
    			$todaydate = new w2p_Utilities_Date();
    			$row['task_end_date'] = $todaydate->format(FMT_TIMESTAMP_DATE);
    		}
    	}
    
    	$ted = new w2p_Utilities_Date($row['task_end_date']);
    	if ($ted->after(new w2p_Utilities_Date($end_max))) {
    		$end_max = $row['task_end_date'];
    	}
    	if ($ted->after(new w2p_Utilities_Date($projects[$row['task_project']]['project_end_date']))
            || $projects[$row['task_project']]['project_end_date'] == '') {
    		$projects[$row['task_project']]['project_end_date'] = $row['task_end_date'];
    	}
    
    	$projects[$row['task_project']]['tasks'][] = $row;
    }
    
    unset($proTasks);
    foreach ($projects as $p) {
        global $parents, $task_id;
        $parents = array();
        $tnums = count($p['tasks']);
    
        for ($i=0; $i < $tnums; $i++) {
            $t = $p['tasks'][$i];
            if (!(isset($parents[$t['task_parent']]))) {
                $parents[$t['task_parent']] = false;
            }
            if ($t['task_parent'] == $t['task_id']) {
                showgtask($t);
                findchild_gantt($p['tasks'], $t['task_id']);
            }
        }
    }
    
    
    
    
    $width = 1600;
    $start_date = w2PgetParam($_GET, 'start_date', $start_min);
    $end_date = w2PgetParam($_GET, 'end_date', $end_max);
    $s1 = ($start_date) ? new w2p_Utilities_Date($start_date) : new w2p_Utilities_Date();
    $e1 = ($end_date) ? new w2p_Utilities_Date($end_date) : new w2p_Utilities_Date();
    
    
    //consider critical (concerning end date) tasks as well
    if ($caller != 'todo') {
    	$start_min = $projects[$project_id]['project_start_date'];
    	$end_max = (($projects[$project_id]['project_end_date'] > $criticalTasks[0]['task_end_date']) 
    				? $projects[$project_id]['project_end_date'] : $criticalTasks[0]['task_end_date']);
    } 
    
    
    
    
    
    $count = 0;
    
    /*
    * 	Prepare Gantt_chart loop
    */
    $gtask_sliced = array() ;
    $gtask_sliced = smart_slice( $gantt_arr, $showNoMilestones, $printpdfhr, $e1->dateDiff($s1) );
    $page = 0 ;					// Numbering of output files
    $outpfiles = array();		// array of output files to be returned to caller
    $taskcount = 0 ;
    // Create task_index array
    $ctflag = false ;
    if ( count( $gtask_sliced ) > 1 ) {
        for ( $i = 0; $i < count($gantt_arr); $i++ ) {
            $task_index[$gantt_arr[$i][0]['task_id']] = $i+1 ;
        }
        $ctflag = true;
    }
    
    //    set here any date span you want: bug work around!       
        $start_date = '2012-03-01 00:00:00' ;
          $end_date = '2012-05-01 00:00:00'  ;  
    
    /* --------------------------------------------------------- */
    // initial store String variables $start_date & $end_date !!!
    /* --------------------------------------------------------- */
        $start_date2 = $start_date;
          $end_date2 = $end_date;
          
    /* --------------------------------------------------------- */ 
    // 1. loop handling the number of sliced sub-projects, each having 25/26 tasks 
    /* --------------------------------------------------------- */       
    foreach ($gtask_sliced as $gts) {
        
    /* --------------------------------------------------------- */
    // always restore String variables $start_date & $end_date !!!
    /* --------------------------------------------------------- */
        $start_date = $start_date2;
          $end_date = $end_date2;   
    /* --------------------------------------------------------- */
    // 
    // during slicing(), if more than 25 tasks !, the variables $start_date & $end_date are re-assigned to an object...
    // and also re-used in an another context.
    // 
    // ---> in 2. loop:    for($i = 0; $i < count($gts); $i ++) {...
    // ---> re-assign & re-use:
    // 
    //        $start_date = new w2p_Utilities_Date($a['task_start_date']);
    //        $end_date = new w2p_Utilities_Date($a['task_end_date']);
    //        
    // causing:
    // "strpos() expects parameter 1 to be string, object given in /var/customers/.../web2project-3.0/lib/jpgraph/src/jpgraph_gantt.php on line 524"    
     /* --------------------------------------------------------- */    
            
          
            
    	$gantt = new w2p_Output_GanttRenderer($AppUI, $width);
    	$gantt->localize();
    
    	$field = ($showWork == '1') ? 'Work' : 'Dur';
    
    	if ($showTaskNameOnly == '1') {
    	    $columnNames = array('Task name');
    	    $columnSizes = array(600);
    	} else {
    		if ($caller == 'todo') {
    			$columnNames = array('Task name', 'Project name', $field, 'Start', 'Finish');
    			$columnSizes = array(180, 135, 40, 75, 75);
    		} else {
    			$columnNames = array('Task name', $field, 'Start', 'Finish');
    			$columnSizes = array(250, 60, 80, 80);
    		}
    	}
    	$gantt->setColumnHeaders($columnNames, $columnSizes);
    	$gantt->setProperties(array('showhgrid' => true));
    
            
     /* --------------------------------------------------------- */         
    // What is the deeper sense of that loop ????   
     /* --------------------------------------------------------- */         
        if (!$start_date || !$end_date) {
            // find out DateRange from gant_arr
            $d_start = new w2p_Utilities_Date();
            $d_end = new w2p_Utilities_Date();
            $taskArray = count($gantt_arr);
             for ($i = 0, $i_cmp = $taskArray; $i < $i_cmp; $i++) {
                $a = $gantt_arr[$i][0];
                $start = substr($a['task_start_date'], 0, 10);
                $end = substr($a['task_end_date'], 0, 10);
    
                $d_start->Date($start);
                $d_end->Date($end);
    
                if ($i == 0) {
                    $min_d_start = $d_start;
                    $max_d_end = $d_end;
                    $start_date = $start;
                    $end_date = $end;
                } else {
                    if (Date::compare($min_d_start, $d_start) > 0) {
                        $min_d_start = $d_start;
                        $start_date = $start;
                    }
                    if (Date::compare($max_d_end, $d_end) < 0) {
                        $max_d_end = $d_end;
                        $end_date = $end;
                    }
                }
            }
        }
                 
             
    //    set here any date span you want: bug work around!       
    //    $start_date = '2012-01-01 00:00:00' ;
    //      $end_date = '2014-01-01 00:00:00'  ;       
    //    always strins neeeded, not objects !
       $gantt->setDateRange($start_date, $end_date);
    
    
    
        reset($projects);
        foreach ($projects as $p) {
            $parents = array();
            $tnums = count($p['tasks']);
    
            for ($i = 0; $i < $tnums; $i++) {
                $t = $p['tasks'][$i];
                if (!isset($parents[$t['task_parent']])) {
                    $parents[$t['task_parent']] = false;
                }
                if ($t['task_parent'] == $t['task_id']) {
                    $parents[$t['task_parent']] = true;
                    showgtask($t);
                    findchild_gantt($p['tasks'], $t['task_id']);
                }
            }
        }
        
        $gantt->loadTaskArray($gantt_arr);
    
        $row = 0;
        
    /* --------------------------------------------------------- */    
    // 2. loop handling the subtasks (25) on each SLICE 
    /* --------------------------------------------------------- */     
        for($i = 0; $i < count($gts); $i ++) {
            $a = $gts[$i][0];
            $level = $gts[$i][1];
            $name = $a['task_name'];
            $name = ((mb_strlen($name) > 34) ? (mb_substr($name, 0, 30) . '...') : $name);
            $name = str_repeat('  ', $level) . $name;
    
            if ($caller == 'todo') {
                $pname = $a['project_name'];
                $pname = ((mb_strlen($pname) > 20) ? (mb_substr($pname, 0, 14) . '...' . mb_substr($pname, -5, 5)) : $pname);
            }
    
       
    
            //using new jpGraph determines using Date object instead of string
            
            
     /* --------------------------------------------------------- */ 
     //           Here is the problem!
     /* --------------------------------------------------------- */             
            $start_date = new w2p_Utilities_Date($a['task_start_date']);
            $end_date = new w2p_Utilities_Date($a['task_end_date']);
      /* --------------------------------------------------------- */        
            
            $start = $start_date->getDate();
    	  $end = $end_date->getDate();
    
     
            $progress = (int) $a['task_percent_complete'];
    
            if ($progress > 100) {
                $progress = 100;
            } elseif ($progress < 0) {
                $progress = 0;
            }
    
            $flags = ($a['task_milestone'] ? 'm' : '');
    
            $cap = '';
            if (!$start || $start == '0000-00-00') {
                $start = !$end ? date('Y-m-d') : $end;
                $cap .= '(no start date)';
            }
            if (!$end) {
                $end = $start;
                $cap .= ' (no end date)';
            } else {
                $cap = '';
            }
    
            if ($showLabels == '1') {
                $q = new w2p_Database_Query;
                $q->addTable('user_tasks', 'ut');
                $q->innerJoin('users', 'u', 'u.user_id = ut.user_id');
                $q->innerJoin('contacts', 'c', 'c.contact_id = u.user_contact');
                $q->addQuery('ut.task_id, u.user_username, ut.perc_assignment');
                $q->addQuery('c.contact_first_name, c.contact_last_name');
                $q->addWhere('ut.task_id = ' . (int)$a['task_id']);
                $res = $q->loadList();
                foreach ($res as $rw) {
                    switch ($rw['perc_assignment']) {
                        case 100:
                            $caption .= $rw['contact_first_name'] . ' ' . $rw['contact_last_name'] . ';';
                            break;
                        default:
                            $caption .= $rw['contact_first_name'] . ' ' . $rw['contact_last_name'] . ' [' . $rw['perc_assignment'] . '%];';
                            break;
                    }
                }
                $q->clear();
                $caption = mb_substr($caption, 0, mb_strlen($caption) - 1);
            }
    
            if ($flags == 'm') {
                // if hide milestones is ticked this bit is not processed//////////////////////////////////////////
                if ($showNoMilestones != '1') {
                    $start = new w2p_Utilities_Date($start_date);
                    $start->addDays(0);
                    $start_mile = $start->getDate();
                    $s = $start_date->format($df);
                    $today_date = date('m/d/Y');
                    $today_date_stamp = strtotime($today_date);
                    $mile_date = $start_date->format($df);
                    $mile_date_stamp = strtotime($mile_date);
                    // honour the choice to show task names only///////////////////////////////////////////////////
                    if ($showTaskNameOnly == '1') {
                        $fieldArray = array($name);
                    } else {
                        if ($caller == 'todo') {
                            $fieldArray = array($name, $pname, '', $s, $s);
                        } else {
                            $fieldArray = array($name, '', $s, $s);
                        }
                    }
                    ///////////////////////////////////////////////////////////////////////////////////////
                    //set color for milestone according to progress
                    //red for 'not started' #990000
                    //yellow for 'in progress' #FF9900
                    //green for 'achieved' #006600
                    // blue for 'planned' #0000FF
                    if ($a['task_percent_complete'] == 100)  {
                        $color = '#006600';
                    } else {
                        if (strtotime($mile_date) < strtotime($today_date)) {
                            $color = '#990000';
                        } else {
                            if ($a['task_percent_complete'] == 0)  {
                                $color = '#0000FF';
                            } else {
                                $color = '#FF9900';
                            }
                        }
                    }
                    $gantt->addMilestone($fieldArray, $a['task_start_date'], $color);
                } //this closes the code that is not processed if hide milestones is checked ///////////////
            } else {
                $type = $a['task_duration_type'];
                $dur = $a['task_duration'];
                if ($type == 24) {
                    $dur *= $w2Pconfig['daily_working_hours'];
                }
    
                if ($showWork == '1') {
                    $work_hours = 0;
                    $q = new w2p_Database_Query;
                    $q->addTable('tasks', 't');
                    $q->addJoin('user_tasks', 'u', 't.task_id = u.task_id');
                    $q->addQuery('ROUND(SUM(t.task_duration*u.perc_assignment/100),2) AS wh');
                    $q->addWhere('t.task_duration_type = 24');
                    $q->addWhere('t.task_id = ' . (int)$a['task_id']);
    
                    $wh = $q->loadResult();
                    $work_hours = $wh * $w2Pconfig['daily_working_hours'];
                    $q->clear();
    
                    $q->addTable('tasks', 't');
                    $q->addJoin('user_tasks', 'u', 't.task_id = u.task_id');
                    $q->addQuery('ROUND(SUM(t.task_duration*u.perc_assignment/100),2) AS wh');
                    $q->addWhere('t.task_duration_type = 1');
                    $q->addWhere('t.task_id = ' . (int)$a['task_id']);
    
                    $wh2 = $q->loadResult();
                    $work_hours += $wh2;
                    $q->clear();
                    //due to the round above, we don't want to print decimals unless they really exist
                    $dur = $work_hours;
                }
    
                $dur .= ' h';
                $enddate = new w2p_Utilities_Date($end);
                $startdate = new w2p_Utilities_Date($start);
                $height = ($a['task_dynamic'] == 1) ? 0.1 : 0.6;
                if ($showTaskNameOnly == '1') {
                    $columnValues = array('task_name' => $name);
                } else {
                    if ($caller == 'todo') {
                        $columnValues = array('task_name' => $name, 'project_name' => $pname,
    						'duration' => $dur, 'start_date' => $start, 'end_date' => $end,
    						'actual_end' => '');
                    } else {
                        $columnValues = array('task_name' => $name, 'duration' => $dur,
    						'start_date' => $start, 'end_date' => $end, 'actual_end' => '');
                    }
                }
                $gantt->addBar($columnValues, $caption, $height, '8F8FBD', true, $progress, $a['task_id']);
            }
            $q->clear();
        }
        unset($gts);
        
      
        $filename = W2P_BASE_DIR."/files/temp/GanttPDF".md5(time()).".png";
    
       
        
        // Prepare Gantt image and store in $filename
        $gantt->render(true, $filename);
        $outpfiles[] = $filename;
        $page++;
    }
    
    //Override of some variables, not very tidy but necessary when importing code from other sources...
    $skip_page = 0;
    $do_report = 1;
    $show_task = 1;
    $show_assignee = 1;
    $show_gantt = 1;
    $show_gantt_taskdetails = ($showTaskNameOnly == '1') ? 0 : 1;
    $ganttfile = $outpfiles;
    
    // Initialize PDF document 
    $font_dir = W2P_BASE_DIR . '/lib/ezpdf/fonts';
    
    
    
    
    $temp_dir = W2P_BASE_DIR . '/files/temp';
    
    
    
    
    $base_url = w2PgetConfig('base_url');
    require( $AppUI->getLibraryClass( 'ezpdf/class.ezpdf' ) );
    
    
    $pdf = new Cezpdf($paper='A4',$orientation='landscape');
    
    
    $pdf->ezSetCmMargins( 2, 1.5, 1.4, 1.4 ); //(top, bottom, left, right)
    /*
    * 		Define page header to be displayed on top of each page
    */
    $pdf->saveState();
    if ( $skip_page ) $pdf->ezNewPage();
    $skip_page++;
    $page_header = $pdf->openObject();
    $pdf->selectFont( "$font_dir/Helvetica-Bold.afm" );
    $ypos= $pdf->ez['pageHeight'] - ( 30 + $pdf->getFontHeight(12) );
    $doc_title = strEzPdf( $projects[$project_id]['project_name'], UI_OUTPUT_RAW);
    $pwidth=$pdf->ez['pageWidth'];
    $xpos= round( ($pwidth - $pdf->getTextWidth( 12, $doc_title ))/2, 2 );
    $pdf->addText( $xpos, $ypos, 12, $doc_title) ;
    $pdf->selectFont( "$font_dir/Helvetica.afm" );
    $date = new w2p_Utilities_Date();
    $xpos = round( $pwidth - $pdf->getTextWidth( 10, $date->format($df)) - $pdf->ez['rightMargin'] , 2);
    $doc_date = strEzPdf($date->format( $df ));
    $pdf->addText( $xpos, $ypos, 10, $doc_date );
    $pdf->closeObject($page_header);
    $pdf->addObject($page_header, 'all');
    $gpdfkey = W2P_BASE_DIR. '/modules/tasks/images/ganttpdf_key.png';
    $gpdfkeyNM = W2P_BASE_DIR. '/modules/tasks/images/ganttpdf_keyNM.png';
    
    $pdf->ezStartPageNumbers( 802 , 30 , 10 ,'left','Page {PAGENUM} of {TOTALPAGENUM}') ;
    for ($i=0; $i < count($ganttfile); $i++) {
        $gf = $ganttfile[$i];
        $pdf->ezColumnsStart(array('num' =>1, 'gap' =>0));
        $pdf->ezImage( $gf, 0, 765, 'width', 'left'); // No pad, width = 800px, resize = 'none' (will go to next page if image height > remaining page space)
        if ($showNoMilestones == '1') {
            $pdf->ezImage( $gpdfkeyNM, 0, 765, 'width', 'left');
        } else {
            $pdf->ezImage( $gpdfkey, 0, 765, 'width', 'left');
        }
        $pdf->ezColumnsStop();
    }
    // End of project display
    // Create document body and pdf temp file
    $pdf->stopObject($page_header);
    $gpdffile = $temp_dir . '/GanttChart_'.md5(time()).'.pdf';
    if ($fp = fopen($gpdffile, 'wb')) {
        fwrite($fp, $pdf->ezOutput());
        fclose($fp);
    } else {
        //TODO: create error handler for permission problems
        echo "Could not open file to save PDF.  ";
        if (!is_writable( $temp_dir ))
        echo "The files/temp directory is not writable.  Check your file system permissions.";
    }
    
    $_POST['printpdf'] = '0';
    $printpdf = '0';
    $_POST['printpdfhr']= 0;
    $printpdfhr = 0;
    
    // check that file exists and is readable
    if (file_exists($gpdffile) && is_readable($gpdffile)) {
        // get the file size and send the http headers
        header('Content-Description: File Transfer');
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename='.basename($gpdffile));
        header('Content-Transfer-Encoding: binary');
        header('Expires: 0');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Pragma: public');
        header('Content-Length: ' . filesize($gpdffile));
        header('Content-disposition: attachment; filename="GanttChart_'.$AppUI->user_id.$project_id.'.pdf"');
        flush();
        ob_end_clean();
        readfile($gpdffile);
        exit;
    }
    txt file icon gantt_pdf.php.txt (23,981 bytes) 1969-12-31 16:00 +

-Relationships
+Relationships

-Notes

~0002339

kareljj (reporter)

Hi, I tested the suggested workaround and it definitely, generates the pdf Gantt but not correctly as expected. In my case I have 32 tasks but only 20 are printed. They appear on the same page but with the legend between them.

~0002340

project_manager (reporter)

@kareljj,
this posted solution avoids the reported bug-error that appears only with more than 25 tasks and the sclicing() starts to work. The print out quality is still not satisfying as you described. Now the "project-cutting" is performed only on the y-axis (tasks) and the x-axis (time scale) is kept const yielding probably not in a optimal paper-sheet cut. As I dont know how it should work and have never seen a correct working version, it is hard to debug it further. The developer should decide, how the proper output should look like. Probably the x-axis has to be scaled as well.
With only 32tasks you can avoid the sclicing-loop by setting this:
// $length = ($showNoMilestones) ? 26 : 25;
$length = ($showNoMilestones) ? 1000 : 1000;
and all will be scaled to one sheet.

~0002341

project_manager (reporter)

I have seen an additional problem, as the depedency arrows (lines) are not plotted anymore on the 2. pdf-slice, only tasks become visible!

~0002366

caseydk (administrator)

Resolved in r2263 along with 0001023;
+Notes

-Issue History
Date Modified Username Field Change
2011-11-30 04:36 project_manager New Issue
2011-11-30 04:42 project_manager File Added: gantt_pdf.php.txt
2011-12-08 05:35 kareljj Note Added: 0002339
2011-12-08 06:40 project_manager Note Added: 0002340
2011-12-08 06:42 project_manager Note Added: 0002341
2011-12-27 22:10 caseydk Note Added: 0002366
2011-12-27 22:10 caseydk Status new => resolved
2011-12-27 22:10 caseydk Resolution open => fixed
2011-12-27 22:10 caseydk Assigned To => caseydk
2013-08-28 11:14 caseydk Fixed in Version => 3.0.0
2013-08-28 11:22 caseydk Status resolved => closed
+Issue History