* @version $Id$
* @access public
* @license http://opensource.org/licenses/gpl-3.0.html
*/
$noplugin = true; // flag for ../config/define.php file
include_once('../config/define.php');
include_once('../languages/' . U_L . '/lang_project.' . CHARSET . '.php');
include_once('../languages/' . U_L . '/lang_common.' . CHARSET . '.php');
include_once("../level/".SQL.".inc.php");
include_once("../project/".SQL.".inc.php");
include_once("../admin/".SQL.".inc.php");
include_once(override('../project/display.php'));
securityCheck();
isset($_REQUEST['id']) ? $id = $_REQUEST['id'] : die("no way");
////////// Check Droits utilisateur ////////////
if (!$l21auth->isAuthenticated() || (!$l21auth->hasRight('project') && ! $l21auth->isSuperAdmin())) ReloadIndex('admin');
//////////
/////////////////////////////////////
function get_gantt_item_properties($startDate, $endDate, $config) {
$properties = [];
if(date_compare($endDate, $config['year-end'].'-12-31', '>')) $endDate = $config['year-end'].'-12-31'; // if endDate is out of bound, we take $config['year-end'] as reference
if(date_compare($startDate, $config['year-start'].'-01-01', '<')) $startDate = $config['year-start'].'-01-01';// if startDate is out of bound, we take $config['year-start'] as reference
// we calculate numbers of days between start and end dates
$datediff = strtotime($endDate) - strtotime($startDate);
$properties['numberOfDays'] = round($datediff / (60 * 60 * 24));
// we also calculate numbers of days between start date and $config['year-start'].'-01-01' to define the offset
$dateOffset = strtotime($startDate) - strtotime($config['year-start'].'-01-01');
$dateOffsetDays = round($dateOffset / (60 * 60 * 24));
$properties['numberOfDays'] = round($datediff / (60 * 60 * 24));
$properties['width'] = round(($config['year-width'] * $config['yearsNumber']) * $properties['numberOfDays'] / (365 * $config['yearsNumber']));
$properties['offset'] = round($dateOffsetDays * ($config['year-width'] * $config['yearsNumber']) / (365 * $config['yearsNumber']) );
return $properties;
}
function get_subdivisions($width, $nb) {
$s = '';
for($i = 0; $i < $nb; $i++) {
// we substract $nb to width beacase of border width
$s .= '
';
}
return $s;
}
function generate_recursive_content($data, $statut, $config, $output) {
// loop through all items in this level
foreach ($data as $key => &$item) {
// echo "$key
";
// where only interested in numeric items
// as those are the actual children
if (! is_numeric($key)) {
// otherwise continue
continue;
}
// 'level_parent' attribute is not set when there is no children level
if (isset($item['level_parent'])) {
if(!empty($item['level_code'])) $display = $item['level_code'];
else $display = cutText($item['level_name'], 40);
$output['labels'] .= '
';
$flag = false;
}
// we add css style to show that action is longer than current calendar
if(date_compare($endDate, $config['year-end'].'-12-31', '>')) $class .= ' ends-after';
if(date_compare($startDate, $config['year-start'].'-01-01', '<')) $class .= ' starts-before';
if ($projects[$i]['project_parent_id'] != 0) $class .= ' sub-project';
if($flag) {
// first we set labels
$output['labels'] .= '
'.PHP_EOL;
}
} // boucle projet
} // test si projet
// call this funcion recursively
// with the next level ($item)
// it will figure out again whether that level has numeric children as well
// returns a new complete set, if applicable, otherwise an empty string
if (isset($item['children'])) $output = generate_recursive_content($item['children'], $statut, $config, $output);
}
// return strings into array
return $output;
}
/////////////////////////////////////
// we prepare environnement
/////////////////////////////////////
// default values
$config = [];
$config['year-width'] = 365;
$config['year-start'] = '';
$config['year-end'] = '';
$config['subdivision'] = 12;
$config['dates-always-visible'] = 0;
$config['show-no-dates'] = 1;
// we get timeline information given in PROJECT_TIMELINE constant
$timeline = get_timeline_info();
// we override default values
if(isset($timeline['year-width'])) $config['year-width'] = $timeline['year-width'];
if(isset($timeline['subdivision'])) $config['subdivision'] = $timeline['subdivision'];
if(isset($timeline['dates-always-visible'])) $config['dates-always-visible'] = $timeline['dates-always-visible'];
if(isset($timeline['show-no-dates'])) $config['show-no-dates'] = $timeline['show-no-dates'];
// years is mandatory !!!
list($config['year-start'], $config['year-end']) = explode('-', $timeline['years']);
// if order is not correct, we invert dates
if($config['year-start'] > $config['year-end']) {
$tmp = $config['year-end'];
$config['year-end'] = $config['year-start'];
$config['year-start'] = $tmp;
}
$config['yearsNumber'] = ($config['year-end'] - $config['year-start']) + 1;
/////////////////////////////////////
// environnement is set and now available through 'config' array
// we start to create content
/////////////////////////////////////
$current = $GLOBALS['sql_object']->DBSelect(SQL_getoneLevel($id));
$data = getLevelChildren($GLOBALS['sql_object']->DBSelect(SQL_getLevelsList()), $id);
$sublevels = array_extract($data, 'level_id', true, 'children');
// if there is no sub-menu, we are working on last levels
// we emulate a level by passing choosen level but 'level_parent' is not set
if (count($sublevels) == 0) {
$sublevels = array($id);
$data = $current;
}
$output = [];
$output['labels'] = '';
$output['rows'] = '';
$output['legend'] = '';
$output['nocal'] = '';
$gantt = generate_recursive_content($data, 'all', $config, $output);
// A - we generate html code for Years and sub-divisions
$years = '';
$cnt = 0;
for($i = $config['year-start']; $i <= $config['year-end']; $i++) {
$subs = get_subdivisions($config['year-width'], $config['subdivision']);
$years .= '
' . $i . '
'.$subs.'
' . PHP_EOL;
$cnt++;
}
// B - we generate labels and gantt row based on fetched actions
// model adapted from : https://codepen.io/carlo-peluso/pen/XWWJwYE
$content = '