* @package projectmanager * @copyright (c) 2005 by Ralf Becker * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License * @version $Id: class.ganttchart.inc.php 24310 2007-07-16 10:08:15Z ralfbecker $ */ include_once(PHPGW_INCLUDE_ROOT.'/projectmanager/inc/class.boprojectelements.inc.php'); // JPGraph does not work, if that got somehow set, so unset it if (isset($GLOBALS['php_errormsg'])) { unset ($GLOBALS['php_errormsg']); } // check if the admin installed a recent JPGraph parallel to eGroupWare if(file_exists(PHPGW_SERVER_ROOT . '/../jpgraph/src/jpgraph.php')) { if (!isset($GLOBALS['phpgw_info']['apps']['projectmanager']['config'])) { // read the pm ganttchart configuration and set some default if there's none require_once(PHPGW_API_INC.'/class.config.inc.php'); $pm_config = new config('projectmanager'); $GLOBALS['phpgw_info']['apps']['projectmanager']['config'] = $pm_config->read_repository(); //_debug_array($GLOBALS['phpgw_info']['apps']['projectmanager']['config']); unset($pm_config); foreach(array( 'TTF_DIR' => '', 'LANGUAGE_CHARSET' => 'iso-8859-1', 'GANTT_FONT' => 15, //FF_ARIAL 'GANTT_FONT_FILE' => 'arial.ttf', 'GANTT_STYLE' => 9002, //FS_BOLD, 'GANTT_CHAR_ENCODE'=> false, ) as $name => $default) { if (isset($GLOBALS['phpgw_info']['apps']['projectmanager']['config'][$name])) { define($name,$GLOBALS['phpgw_info']['apps']['projectmanager']['config'][$name]); } elseif($default) { define($name,$default); } } } if (!defined('TTF_DIR')) { // using the OS font dir if we can find it, otherwise fall back to our bundled Vera font foreach(array( '/usr/X11R6/lib/X11/fonts/truetype/', // linux / *nix default '/usr/share/fonts/ja/TrueType/', // japanese fonts '/usr/share/fonts/msttcorefonts/', // manual for install this fonts search at http://www.aditus.nu/jpgraph/jpdownload.php 'C:/windows/fonts/', // windows default // add your location here ... PHPGW_SERVER_ROOT.'/projectmanager/inc/ttf-bitstream-vera-1.10/', // our bundled Vera font ) as $dir) { if (@is_dir($dir) && (is_readable($dir.GANTT_FONT_FILE) || is_readable($dir.'Vera.ttf'))) { define('TTF_DIR',$dir); unset($dir); break; } } } if (!defined('MBTTF_DIR')) define('MBTTF_DIR',TTF_DIR); include(PHPGW_SERVER_ROOT . '/../jpgraph/src/jpgraph.php'); include(PHPGW_SERVER_ROOT . '/../jpgraph/src/jpgraph_gantt.php'); } else { include(PHPGW_SERVER_ROOT . '/projectmanager/inc/jpgraph-1.5.2/src/jpgraph.php'); include(PHPGW_SERVER_ROOT . '/projectmanager/inc/jpgraph-1.5.2/src/jpgraph_gantt.php'); define('TTF_DIR',PHPGW_SERVER_ROOT.'/projectmanager/inc/ttf-bitstream-vera-1.10/'); define('GANTT_FONT',FF_VERA); define('GANTT_STYLE',FS_BOLD); define('LANGUAGE_CHARSET','iso-8859-1'); define('GANTT_CHAR_ENCODE',true); } // some constanst for pre php4.3 if (!defined('PHP_SHLIB_SUFFIX')) { define('PHP_SHLIB_SUFFIX',strtoupper(substr(PHP_OS, 0,3)) == 'WIN' ? 'dll' : 'so'); } if (!defined('PHP_SHLIB_PREFIX')) { define('PHP_SHLIB_PREFIX',PHP_SHLIB_SUFFIX == 'dll' ? 'php_' : ''); } /** * ProjectManager: Ganttchart creation * * @package projectmanager * @author RalfBecker-AT-outdoor-training.de * @copyright (c) 2005 by RalfBecker-AT-outdoor-training.de * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License */ class ganttchart extends boprojectelements { /** * @var array $public_functions Functions to call via menuaction */ var $public_functions = array( 'create' => true, 'show' => true, ); /** * true if JPGraph version > 1.13 * * @var boolean */ var $modernJPGraph; /** * Charset used internaly by eGW, $GLOBALS['phpgw']->translation->charset() * * @var string */ var $charset; /** * Font used for the Gantt Chart, in the form used by JPGraphs SetFont method * * @var string */ var $gantt_font = GANTT_FONT; /** * Charset used by the above font * * @var string */ var $gantt_charset = LANGUAGE_CHARSET; /** * Should non-ascii chars be encoded * * @var boolean */ var $gantt_char_encode = GANTT_CHAR_ENCODE; var $debug; var $scale_start,$scale_end; var $tmpl; var $prefs; /** * Constructor, calls the constructor of the extended class */ function ganttchart() { $this->tmpl =& CreateObject('etemplate.etemplate'); $php_extension = 'gd'; if (!extension_loaded($php_extension) && (!function_exists('dl') || !dl(PHP_SHLIB_PREFIX.$php_extension.'.'.PHP_SHLIB_SUFFIX)) || !function_exists('imagecopyresampled')) { $this->tmpl->Location(array( 'menuaction' => 'projectmanager.uiprojectmanager.index', 'msg' => lang("Necessary PHP extentions %1 not loaded and can't be loaded !!!",$php_extension.' ('.PHP_SHLIB_PREFIX.$php_extension.'.'.PHP_SHLIB_SUFFIX.')'), )); } $this->modernJPGraph = version_compare('1.13',JPG_VERSION) < 0; //echo "version=".JPG_VERSION.", modernJPGraph=".(int)$this->modernJPGraph; exit; error_log("JPG_VERSION=".JPG_VERSION.", modernJPGraph=".(int)$this->modernJPGraph); if (isset($_REQUEST['pm_id'])) { $pm_id = (int) $_REQUEST['pm_id']; $GLOBALS['phpgw']->session->appsession('pm_id','projectmanager',$pm_id); } else { $pm_id = $GLOBALS['phpgw']->session->appsession('pm_id','projectmanager'); } if (!$pm_id) { $this->tmpl->Location(array( 'menuaction' => 'projectmanager.uiprojectmanager.index', 'msg' => lang('You need to select a project first'), )); } $this->boprojectelements($pm_id); // check if we have at least read-access to this project if (!$this->project->check_acl(PHPGW_ACL_READ)) { $GLOBALS['phpgw']->redirect_link('/index.php',array( 'menuaction' => 'projectmanager.uiprojectmanager.index', 'msg' => lang('Permission denied !!!'), )); } $this->charset = $GLOBALS['phpgw']->translation->charset(); $this->prefs =& $GLOBALS['phpgw_info']['user']['preferences']; // check if a arial font is availible and set FF_VERA (or bundled font) if not if (!is_readable((FF_MINCHO <= GANTT_FONT && GANTT_FONT <= FF_PGOTHI ? MBTTF_DIR : TTF_DIR).GANTT_FONT_FILE)) { $this->gantt_font = FF_VERA; } } /** * Converts text from eGW's internal encoding to something understood by JPGraph / GD * * The only working thing I found so far is numeric html-entities from iso-8859-1. * If you found other encoding do work, please let mit know: RalfBecker-AT-outdoor-training.de * It would be nice if we could use the full utf-8 charset, if supported by the used font. * * @param string $text * @return string */ function text_encode($text) { // convert to the charset used for the gantchart $text = $GLOBALS['phpgw']->translation->convert($text,$this->charset,$this->gantt_charset); // convert everything above ascii to nummeric html entities // not sure if this is necessary for non iso-8859-1 charsets, try to comment it out if you have problems if ($this->gantt_char_encode) $text = preg_replace('/[^\x00-\x7F]/e', '"&#".ord("$0").";"',$text); return $text; } /** * Try to guess a locale supported by the server, with fallback to 'en_EN' and 'C' * * @return string */ function guess_locale() { $lang = $this->prefs['common']['lang']; $country = $this->prefs['common']['country']; if (strlen($lang) == 2) { $country_from_lang = strtoupper($lang); } else { list($lang,$country_from_lang) = explode('-',$lang); $country_from_lang = strtoupper($country_from_lang); } if (setlocale(LC_ALL,$locale=$lang.'_'.$country)) return $locale; if (setlocale(LC_ALL,$locale=$lang.'_'.$country_from_lang)) return $locale; if (setlocale(LC_ALL,$locale=$lang)) return $locale; if (setlocale(LC_ALL,$locale='en_EN')) return $locale; return 'C'; } /** * create a new JPGraph Ganttchart object and setup a fitting scale * * @param string $title * @param string $subtile * @param int $start startdate of the ganttchart * @param int $end enddate of the ganttchart * @return object GantGraph */ function &new_gantt($title,$subtitle,$start,$end,$width=940) { // create new graph object $graph =& new GanttGraph($width,-1,'auto'); $graph->SetShadow(); $graph->SetBox(); // set the start and end date $graph->SetDateRange(date('Y-m-d',$start), date('Y-m-d',$end)); // some localizations if ($this->modernJPGraph) { $graph->scale->SetDateLocale($this->guess_locale()); } elseif ($this->prefs['common']['lang'] == 'de') { $graph->scale->SetDateLocale(LOCALE_DE); // others use english } // set start-day of the week from the cal-pref weekdaystarts $weekdaystarts2day = array( 'Sunday' => 0, 'Monday' => 1, 'Saturday' => 6, ); $weekdaystarts = $this->prefs['calendar']['weekdaystarts']; if ($this->modernJPGraph && isset($weekdaystarts2day[$weekdaystarts])) { $graph->scale->SetWeekStart($weekdaystarts2day[$weekdaystarts]); } // get and remember the real start- & enddates, to clip the bar for old JPGraph versions $this->scale_start = $graph->scale->iStartDate; $this->scale_end = $graph->scale->iEndDate; $days = round(($this->scale_end - $this->scale_start) / 86400); $month = $days / 31; //echo date('Y-m-d',$this->scale_start).' - '.date('Y-m-d',$this->scale_end).' '.$month; // 2 weeks and less: day (weekday date) and hour headers, only possible with modern JPGraph if($this->modernJPGraph && $days <= 14) { $graph->ShowHeaders(GANTT_HDAY | GANTT_HHOUR); $graph->scale->day->SetStyle($days < 7 ? DAYSTYLE_LONGDAYDATE1 : DAYSTYLE_SHORTDATE3); $graph->scale->hour->SetStyle($this->prefs['common']['timeformat'] == 12 ? HOURSTYLE_HAMPM : HOURSTYLE_H24); foreach(array(8=>6,5=>4,3=>2,2=>1) as $max => $int) { if ($days >= $max) break; } //echo "days=$days => $int ($max)"; $graph->scale->hour->SetIntervall($int); } // 1.5 month and less: month (with year), week and day (date) headers elseif($month <= 1.5) { $graph->ShowHeaders(GANTT_HMONTH | GANTT_HWEEK | GANTT_HDAY); $graph->scale->month->SetStyle(MONTHSTYLE_LONGNAMEYEAR4); if ($this->modernJPGraph) $graph->scale->day->SetStyle(DAYSTYLE_SHORTDATE4); } // 2.5 month and less: month (with year), week (week and startday) and day headers elseif($month <= 2.5) { $graph->ShowHeaders(GANTT_HMONTH | GANTT_HWEEK | GANTT_HDAY); if ($this->modernJPGraph) $graph->scale->week->SetStyle(WEEKSTYLE_FIRSTDAYWNBR); $graph->scale->month->SetStyle(MONTHSTYLE_LONGNAMEYEAR4); } // 6 month and less: year, month and week (with weeknumber) headers elseif($month <= 6) // half year { $graph->ShowHeaders(GANTT_HYEAR | GANTT_HMONTH | GANTT_HWEEK); $graph->scale->month->SetStyle(MONTHSTYLE_LONGNAME); } // more then 6 month: only year and month headers else { $graph->ShowHeaders(GANTT_HYEAR | GANTT_HMONTH); } // Change the font scale $graph->scale->week->SetFont($this->gantt_font,FS_NORMAL,8); $graph->scale->year->SetFont($this->gantt_font,GANTT_STYLE,10); // Title & subtitle $graph->title->Set($this->text_encode($title)); $graph->title->SetFont($this->gantt_font,GANTT_STYLE,12); $graph->subtitle->Set($this->text_encode($subtitle)); $graph->subtitle->SetFont($this->gantt_font,FS_NORMAL,10); return $graph; } /** * Ganttbar for a project * * @param array $pm project or project-element data array * @param int $level hierarchy level, 0=main project * @param int $line line-number of the gantchart, starting with 0 * @param boolean $planned_times=false show planned or real start- and end-dates * @return object GanttBar */ function &project2bar($pm,$level,$line,$planned_times=false) { if ($pm['pe_id']) { $pe =& $pm; } else { $pe = array( 'pm_id' => $pm['pm_id'], 'pe_id' => 0, ); foreach($pm as $key => $val) { if ($key != 'pm_id') $pe[str_replace('pm_','pe_',$key)] =& $pm[$key]; } } $bar =& $this->element2bar($pe,$level,$line,$planned_times); // set project-specific attributes: bold, solid bar, ... $bar->title->SetFont($this->gantt_font,GANTT_STYLE,!$level ? 9 : 8); $bar->SetPattern(BAND_SOLID,"#9999FF"); if ($this->modernJPGraph && !$pe['pe_id']) // main-project { $link = $GLOBALS['phpgw']->link('/index.php',array( 'menuaction' => 'projectmanager.uiprojectmanager.view', 'pm_id' => $pe['pm_id'], )); $title = lang('View this project'); $bar->SetCSIMTarget($link,$title); $bar->title->SetCSIMTarget($link,$title); } return $bar; } /** * Ganttbar for a project-element * * @param array $pe projectelement-data array * @param int $level hierarchy level, 0=main project * @param int $line line-number of the gantchart, starting with 0 * @param boolean $planned_times=false show planned or real start- and end-dates * @return object GanttBar */ function &element2bar($pe,$level,$line,$planned_times=false) { // create a shorter title (removes dates from calendar-titles and project-numbers from sub-projects if ($pe['pe_app'] == 'calendar' || $pe['pe_app'] == 'projectmanager') { list(,$title) = explode(': ',$pe['pe_title'],2); } if (!$title) $title = $pe['pe_title']; if ((int) $this->debug >= 1) { echo "

GanttBar($line,'".($level ? str_repeat(' ',$level) : ''). $this->text_encode($title).' '."','". date('Y-m-d H:i',$pe['pe_start'])."','".date('Y-m-d H:i',$pe['pe_end'])."','". round($pe['pe_completion']).'%'."',0.5)

\n"; } if (!$this->modernJPGraph) // for an old JPGraph we have to clip the bar ourself { if ($pe['pe_start'] < $this->scale_start) $pe['pe_start'] = $this->scale_start; if ($pe['pe_end'] > $this->scale_end) $pe['pe_end'] = $this->scale_end-1; } $bar =& new GanttBar($line,($level ? str_repeat(' ',$level) : ''). $this->text_encode($title). ($level ? ' ' : ''), // fix for wrong length calculation in JPGraph date('Y-m-d'.($this->modernJPGraph ? ' H:i' : ''),$pe['pe_start']), date('Y-m-d'.($this->modernJPGraph ? ' H:i' : ''),$pe['pe_end']), round($pe['pe_completion']).'%',0.5); $bar->progress->Set($pe['pe_completion']/100); $bar->progress->SetHeight(0.5); if ($this->modernJPGraph && $pe['pe_id']) { $bar->SetCSIMTarget('@600x450'.$GLOBALS['phpgw']->link('/index.php',array( // @ = popup 'menuaction' => 'projectmanager.uiprojectelements.view', 'pm_id' => $pe['pm_id'], 'pe_id' => $pe['pe_id'], )),$pe['pe_remark'] ? $pe['pe_remark'] : lang('View this project-element')); if (($popup = $GLOBALS['phpgw']->link->is_popup($pe['pe_app']))) $popup = '@'.$popup; $bar->title->SetCSIMTarget($popup.$GLOBALS['phpgw']->link('/index.php',$this->link->view($pe['pe_app'],$pe['pe_app_id'])), lang('View this element in %1',lang($pe['pe_app']))); } $bar->title->SetFont($this->gantt_font,FS_NORMAL,!$level ? 9 : 8); return $bar; } /** * Milestone * * @param array $milestone data-array * @param int $level hierarchy level, 0=main project * @param int $line line-number of the gantchart, starting with 0 * @return object MileStone */ function &milestone2bar($milestone,$level,$line) { if ((int) $this->debug >= 1) { echo "

MileStone($line,'$milestone[ms_title],". date('Y-m-d',$milestone['ms_date']).','. date($this->prefs['common']['dateformat'],$milestone['ms_date']).")

\n"; } $ms =& new MileStone($line,($level ? str_repeat(' ',$level) : ''). $this->text_encode($milestone['ms_title']), date('Y-m-d',$milestone['ms_date']), date($this->prefs['common']['dateformat'],$milestone['ms_date'])); $ms->title->SetFont($this->gantt_font,FS_ITALIC,8); $ms->title->SetColor('blue'); $ms->mark->SetColor('black'); $ms->mark->SetFillColor('blue'); if ($this->modernJPGraph) { $link = $GLOBALS['phpgw']->link('/index.php',array( 'menuaction' => 'projectmanager.uimilestones.view', 'pm_id' => $milestone['pm_id'], 'ms_id' => $milestone['ms_id'], )); $title = lang('View this milestone'); $ms->SetCSIMTarget('@600x450'.$link,$title); // @ = popup $ms->title->SetCSIMTarget('@600x450'.$link,$title); } return $ms; } /** * Adds all elements of project $pm_id to the ganttchart, calls itself recursive for subprojects * * @param int $pm_id project-id * @param array $params * @param int &$line line-number of the gantchart, starting with 0, gets incremented * @param array &$bars bars are added here, with their pe_id as key * @param int $level hierarchy level starting with 1, function stops if $level > $params['deepth'] */ function add_elements($pm_id,$params,&$line,&$bars,$level=1) { static $filter=false; static $extra_cols; if (!$filter) // we do this only once for all shown projects { // defining start- and end-times depending on $params['planned_times'] and the availible data foreach(array('start','end') as $var) { if ($params['planned_times']) { $$var = "CASE WHEN pe_planned_$var IS NULL THEN pe_real_$var ELSE pe_planned_$var END"; } else { $$var = "CASE WHEN pe_real_$var IS NULL THEN pe_planned_$var ELSE pe_real_$var END"; } } $filter = array( "pe_status != 'ignore'", "$start IS NOT NULL", "$end IS NOT NULL", "$start <= ".(int)$this->scale_end, // starts befor the end of our period AND "$end >= ".(int)$this->scale_start, // ends after the start of our period 'cumulate' => true, ); switch ($params['filter']) { case 'not': $filter['pe_completion'] = 0; break; case 'ongoing': $filter[] = 'pe_completion!=100'; break; case 'done': $filter['pe_completion'] = 100; break; } if ($params['pe_resources']) { $filter['pe_resources'] = $params['pe_resources']; } $extra_cols = array( $start.' AS pe_start', $end.' AS pe_end', ); } $filter['pm_id'] = $pm_id; // this is NOT static $pe_id2line = array(); foreach((array) $this->search(array(),false,'pe_start,pe_end',$extra_cols, '',false,'AND',false,$filter) as $pe) { //echo "$line: ".print_r($pe,true)."
\n"; if (!$pe) continue; $pe_id = $pe['pe_id']; $pe_id2line[$pe_id] = $line; // need to remember the line to draw the constraints $pes[$pe_id] = $pe; if ($pe['pe_app'] == 'projectmanager') { $bars[$pe_id] =& $this->project2bar($pe,$level,$line++,$params['planned_times']); } else { $bars[$pe_id] =& $this->element2bar($pe,$level,$line++,$params['planned_times']); } // if we should display further levels, we call ourself recursive if ($pe['pe_app'] == 'projectmanager' && $level < $params['depth']) { $this->add_elements($pe['pe_app_id'],$params,$line,$bars,$level+1); } } if ($params['constraints'] && $this->modernJPGraph) // the old jpgraph does not support constrains { // adding milestones foreach((array)$this->milestones->search(array(),'pm_id,ms_id,ms_title,ms_date','ms_date','','',false,'AND',false,array( 'pm_id' => $pm_id, (int)$this->scale_start.' <= ms_date', 'ms_date <= '.(int)$this->scale_end, )) as $milestone) { if (!$milestone || !($ms_id = $milestone['ms_id'])) continue; $ms_id2line[$ms_id] = $line; $milestones[$ms_id] = $milestone; $bars[-$ms_id] =& $this->milestone2bar($milestone,$level,$line++); } // adding the constraints to the bars foreach((array)$this->constraints->search(array('pm_id'=>$pm_id)) as $constraint) { $pe_id = $constraint['pe_id_end']; // start of the array at the end of this pe if (isset($bars[$pe_id])) { $bar =& $bars[$pe_id]; if ($constraint['pe_id_start'] && isset($pe_id2line[$constraint['pe_id_start']])) { // show violated constrains in red $color = $pes[$constraint['pe_id_start']]['pe_start'] >= $pes[$pe_id]['pe_end'] ? 'black' : 'red'; $bar->SetConstrain($pe_id2line[$constraint['pe_id_start']],CONSTRAIN_ENDSTART,$color); } if ($constraint['ms_id'] && isset($ms_id2line[$constraint['ms_id']])) { // show violated constrains in red $color = $milestones[$constraint['ms_id']]['ms_date'] >= $pes[$pe_id]['pe_end'] ? 'black' : 'red'; $bar->SetConstrain($ms_id2line[$constraint['ms_id']],CONSTRAIN_ENDSTART,$color); } } } } } /** * Create a ganttchart * * @param array $params=null params, if (default) null, use them from the URL * @param string $filename='' filename to store the chart or (default) empty to send it direct to the browser */ function create($params=null,$filename='',$imagemap='ganttchar') { if (!$params) $params = $this->url2params($params); $title = lang('project overview').': '.(is_numeric($params['pm_id']) ? $this->project->data['pm_title'] : ''); $subtitle = lang('from %1 to %2',date($this->prefs['common']['dateformat'],$params['start']),date($this->prefs['common']['dateformat'],$params['end'])); // create new graph-object and set scale_{start|end} $graph =& $this->new_gantt($title,$subtitle,$params['start'],$params['end'],$params['width']); if ($params['start'] < $this->now_su && $this->now_su < $params['end']) { // add a vertical line to mark today $graph->add(new GanttVLine($this->now_su-24*60*60, date($GLOBALS['phpgw_info']['user']['preferences']['common']['dateformat'],$this->now_su))); } $line = 0; $bars = array(); foreach(explode(',',$params['pm_id']) as $pm_id) { if ($pm_id != $this->project->data['pm_id']) { if (!$this->project->read($pm_id) || !$this->project->check_acl(PHPGW_ACL_READ)) { continue; } } $graph->Add($this->project2bar($this->project->data,0,$line++,$params['planned_times'])); if ($params['depth'] > 0) { $this->add_elements($this->project->data['pm_id'],$params,$line,$bars); } } foreach($bars as $pe_id => $bar) { $graph->Add($bar); } if (!$this->debug) $graph->Stroke($filename); if ($filename && $imagemap) return $graph->GetHTMLImageMap($imagemap); } /** * read the ganttchart params from the URL * * @param array $params already set parameters, default empty array * @return array with params */ function url2params($params = array()) { if ((int) $this->debug >= 1) echo "

ganttchart::url2params(".print_r($params,true).")

\n"; if (!count($params)) { if (!($params = $GLOBALS['phpgw']->session->appsession('ganttchart','projectmanager'))) { $params = array( // some defaults, if called the first time 'constraints' => true, ); } // check if project changed => not use start and end if ($params['pm_id'] != $this->project->data['pm_id']) { $params['pm_id'] = $this->project->data['pm_id']; unset($params['start']); unset($params['end']); } } $data =& $this->project->data; foreach(array('start','end') as $var) { // set used start- and end-times of the project if ($params['planned_times'] && $data['pe_planned_'.$var] || !$data['pe_real_'.$var]) { $data['pm_'.$var] = $data['pm_planned_'.$var]; } else { $data['pm_'.$var] = $data['pm_real_'.$var]; } // set start- and end-times of the ganttchart if (isset($_GET[$var])) { $params[$var] = $_GET[$var]; } elseif (isset($params[$var]) && $params[$var]) { // already set } elseif ($data['pm_id'] && $data['pm_'.$var]) { $params[$var] = $data['pm_'.$var]; } else { $params[$var] = $var == 'start' ? date('Y-m-1') : date('Y-m-1',time()+61*24*60*60); } $params[$var] = is_numeric($params[$var]) ? (int) $params[$var] : strtotime($params[$var]); if ((int) $this->debug >= 1) echo "

$var=".$params[$var].'='.date('Y-m-d',$params[$var])."

\n"; } if ((int) $_GET['width']) { $params['width'] = (int) $_GET['width']; } else { $params['width'] = $this->tmpl->innerWidth - ($this->prefs['common']['auto_hide_sidebox'] ? 60 : 245); } if (!isset($params['pm_id']) && $this->project->data['pm_id']) { $params['pm_id'] = $this->project->data['pm_id']; } if (!isset($params['depth'])) $params['depth'] = 1; if ($_GET['pm_id'] && !is_numeric($_GET['pm_id'])) { $params['pm_id'] = $_GET['pm_id']; } $GLOBALS['phpgw']->session->appsession('ganttchart','projectmanager',$params); if ((int) $this->debug >= 1) _debug_array($params); return $params; } /** * Return message to install a new jpgraph version * * @static * @return string/boolean message or false if a new version is installed */ function msg_install_new_jpgraph() { return version_compare('1.13',JPG_VERSION) < 0 ? false : lang('You are using the old version of JPGraph, bundled with eGroupWare. It has only limited functionality.'). "
\n".lang('Please download a recent version from %1 and install it in %2.', 'www.aditus.nu/jpgraph', realpath(PHPGW_SERVER_ROOT.'/..').SEP.'jpgraph'); } /** * Shows a ganttchart * * As ganttcharts contain an image-map and the image, we save the image as a temporary file. * This for performance reasons, it saves a second creation / script-run. * projectmanager/ganttchart.php reads and output the temporary file/image and unlinks it after. */ function show($content=array(),$msg='') { if ($content['sync_all'] && $this->project->check_acl(PHPGW_ACL_ADD)) { $msg = lang('%1 element(s) updated',$this->sync_all()); unset($content['sync_all']); } // run $_GET[msg] through htmlspecialchars, as we output it raw, to allow the link in the jpgraph message. if (!$msg) $msg = $this->tmpl->html->htmlspecialchars($_GET['msg']); if (!$GLOBALS['phpgw']->session->appsession('ganttchart','projectmanager') && !$this->modernJPGraph) { $msg .= $this->msg_install_new_jpgraph(); } unset($content['update']); $content = $this->url2params($content); $tmp = $GLOBALS['phpgw_info']['server']['temp_dir']; if (!is_dir($tmp) || !is_writable($tmp)) { $tmp = ''; } $img = tempnam($tmp,'ganttchart'); $img_name = basename($img); $map = $this->create($content,$img,'ganttchart'); // replace the regular links with popups $map = preg_replace('/href="@(\d+)x(\d+)([^"]+)"/i','href="#" onclick="phpgw_openWindowCentered2(\'\\3\',\'_blank\',\'dependent=yes,width=\\1,height=\\2,scrollbars=yes,status=yes\'); return false;"' ,$map); $content['ganttchart'] = $GLOBALS['phpgw']->link('/projectmanager/ganttchart.php',$content+array( 'img' => $img_name, )); $content['map'] = $map; $content['msg'] = $msg; $sel_options = array( 'depth' => array( 0 => '0: '.lang('Mainproject only'), 1 => '1: '.lang('Project-elements'), 2 => '2: '.lang('Elements of elements'), 3 => '3: '.lang('Elements of elements'), 99 => lang('Everything recursive'), ), 'filter' => array( '' => lang('All'), 'not' => lang('Not started (0%)'), 'ongoing' => lang('0ngoing (0 < % < 100)'), 'done' => lang('Done (100%)'), ), ); $GLOBALS['phpgw_info']['flags']['app_header'] = lang('projectmanager').' - '.lang('Ganttchart').': '.$this->project->data['pm_title'];; $this->tmpl->read('projectmanager.ganttchart'); return $this->tmpl->exec('projectmanager.ganttchart.show',$content,$sel_options,'',array('pm_id'=>$content['pm_id'])); } }