function show() { global $page, $db, $user, $fs, $proj; $page->setTitle($fs->prefs['page_title'] . L('reports')); $events = array(1 => L('taskopened'), 13 => L('taskreopened'), 2 => L('taskclosed'), 3 => L('taskedited'), 14 => L('assignmentchanged'), 29 => L('events.useraddedtoassignees'), 4 => L('commentadded'), 5 => L('commentedited'), 6 => L('commentdeleted'), 7 => L('attachmentadded'), 8 => L('attachmentdeleted'), 11 => L('relatedadded'), 12 => L('relateddeleted'), 9 => L('notificationadded'), 10 => L('notificationdeleted'), 17 => L('reminderadded'), 18 => L('reminderdeleted')); $user_events = array(30 => L('created'), 31 => L('deleted')); $page->assign('events', $events); $page->assign('user_events', $user_events); $sort = strtoupper(Get::enum('sort', array('desc', 'asc'))); $where = array(); $params = array(); $orderby = ''; switch (Get::val('order')) { case 'type': $orderby = "h.event_type {$sort}, h.event_date {$sort}"; break; case 'user': $orderby = "user_id {$sort}, h.event_date {$sort}"; break; case 'date': default: $orderby = "h.event_date {$sort}, h.event_type {$sort}"; } foreach (Get::val('events', array()) as $eventtype) { $where[] = 'h.event_type = ?'; $params[] = $eventtype; } $where = '(' . implode(' OR ', $where) . ')'; if ($proj->id) { $where = $where . 'AND (t.project_id = ? OR h.event_type > 29) '; $params[] = $proj->id; } if (($fromdate = Req::val('fromdate')) || Req::val('todate')) { $where .= ' AND '; $todate = Req::val('todate'); if ($fromdate) { $where .= ' h.event_date > ?'; $params[] = Flyspray::strtotime($fromdate) + 0; } if ($todate && $fromdate) { $where .= ' AND h.event_date < ?'; $params[] = Flyspray::strtotime($todate) + 86400; } else { if ($todate) { $where .= ' h.event_date < ?'; $params[] = Flyspray::strtotime($todate) + 86400; } } } $histories = array(); if (count(Get::val('events'))) { if (Get::num('event_number') > 0) { $db->setLimit(Get::num('event_number')); } $histories = $db->x->getAll("SELECT h.*, t.*, p.project_prefix\n FROM {history} h\n LEFT JOIN {tasks} t ON h.task_id = t.task_id\n LEFT JOIN {projects} p ON t.project_id = p.project_id\n WHERE {$where}\n ORDER BY {$orderby}", null, $params); } $page->assign('histories', $histories); $page->assign('sort', $sort); $page->pushTpl('reports.tpl'); }
function is_accessible() { global $db, $page, $user; $this->comment = $db->x->getRow('SELECT c.*, u.real_name FROM {comments} c INNER JOIN {users} u ON c.user_id = u.user_id WHERE comment_id = ? AND task_id = ?', null, array(Get::num('id', 0), Get::num('task_id', 0))); return $user->can_edit_comment($this->comment); }
function show($area = null) { global $page, $fs, $db, $proj, $user, $conf; $perpage = '20'; if (isset($user->infos['tasks_perpage'])) { $perpage = $user->infos['tasks_perpage']; } $pagenum = max(1, Get::num('pagenum', 1)); $offset = $perpage * ($pagenum - 1); // Get the visibility state of all columns $visible = explode(' ', trim($proj->id ? $proj->prefs['visible_columns'] : $fs->prefs['visible_columns'])); if (!is_array($visible) || !count($visible) || !$visible[0]) { $visible = array('id'); } list($tasks, $id_list) = Backend::get_task_list($_GET, $visible, $offset, $perpage); $page->assign('tasks', $tasks); $page->assign('offset', $offset); $page->assign('perpage', $perpage); $page->assign('pagenum', $pagenum); $page->assign('visible', $visible); // List of task IDs for next/previous links $_SESSION['tasklist'] = $id_list; $page->assign('total', count($id_list)); // Javascript replacement if (Get::val('toggleadvanced')) { $advanced_search = intval(!Req::val('advancedsearch')); Flyspray::setCookie('advancedsearch', $advanced_search, time() + 60 * 60 * 24 * 30); $_COOKIE['advancedsearch'] = $advanced_search; } // Update check {{{ if (Get::has('hideupdatemsg')) { unset($_SESSION['latest_version']); } else { if ($conf['general']['update_check'] && $user->perms('is_admin') && $fs->prefs['last_update_check'] < time() - 60 * 60 * 24 * 3) { if (!isset($_SESSION['latest_version'])) { $latest = Flyspray::remote_request('http://flyspray.org/version.txt', GET_CONTENTS); //if for some silly reason we get and empty response, we use the actual version $_SESSION['latest_version'] = empty($latest) ? $fs->version : $latest; $db->x->execParam('UPDATE {prefs} SET pref_value = ? WHERE pref_name = ?', array(time(), 'last_update_check')); } } } if (isset($_SESSION['latest_version']) && version_compare($fs->version, $_SESSION['latest_version'], '<')) { $page->assign('updatemsg', true); } // }}} $page->setTitle($fs->prefs['page_title'] . $proj->prefs['project_title'] . ': ' . L('tasklist')); $page->pushTpl('index.tpl'); }
<?php /* This script updates a user's timezone if necessary */ define('IN_FS', true); require_once '../../header.php'; if (!$user->isAnon()) { $db->x->execParam('UPDATE {users} SET time_zone = ? WHERE user_id = ?', array(Get::num('timezone'), $user->id)); }
<?php /* This script is the AJAX callback that deletes a user's saved search */ define('IN_FS', true); require_once '../../header.php'; $baseurl = dirname(dirname($baseurl)) . '/'; if (Cookie::has('flyspray_userid') && Cookie::has('flyspray_passhash')) { $user = new User(Cookie::val('flyspray_userid')); $user->check_account_ok(); $db->Query('DELETE FROM {searches} WHERE id = ? AND user_id = ?', array(Get::num('id'), $user->id)); }
//look 30 + days and if found scale $projectCheck = Project::getActivityProjectCount($sixtyone_days, $thirtyone_days, Get::num('project_id')); if ($projectCheck > 0) { $data = Project::getDayActivityByProject($sixtyone_days, date('U', strtotime(date('Y-m-d'))), Get::num('project_id')); } else { $data = Project::getDayActivityByProject($thirtyone_days, date('U', strtotime(date('Y-m-d'))), Get::num('project_id')); } $data = implode(',', $data); //User Graph } else { if (Get::has('user_id') && Get::has('project_id') && Get::val('graph') == 'user') { $today = date('Y-m-d'); $thirtyone_days = date('U', strtotime("-31 day", strtotime($today))); $sixtyone_days = date('U', strtotime("-61 day", strtotime($today))); //look 30 + days and if found scale $projectCheck = Project::getActivityProjectCount($sixtyone_days, $thirtyone_days, Get::num('project_id')); if ($projectCheck > 0) { $data = User::getDayActivityByUser($sixtyone_days, date('U', strtotime(date('Y-m-d'))), Get::num('project_id'), Get::num('user_id')); } else { $data = User::getDayActivityByUser($thirtyone_days, date('U', strtotime(date('Y-m-d'))), Get::num('project_id'), Get::num('user_id')); } $data = implode(',', $data); } else { $data = ''; } } // Not pretty but gets the job done. $_SERVER['QUERY_STRING'] = 'size=160x25&data=' . $data; $_GET['size'] = '160x25'; $_GET['data'] = $data; require dirname(__DIR__) . '/vendor/jamiebicknell/Sparkline/sparkline.php';
// We can't include this script as part of index.php?do= etc, // as that would introduce html code into it. HTML != Valid XML // So, include the headerfile to set up database access etc define('IN_FS', true); require dirname(__FILE__) . '/header.php'; if (!$user->id && Get::val('user_id') && Get::val('auth')) { $user = new User(Get::val('user_id')); if (Get::val('auth') != md5($user->infos['user_pass'] . $user->infos['register_date'])) { $user = new User(); } } $page = new FSTpl(); // Set up the basic XML head header('Content-type: text/html; charset=utf-8'); $max_items = Get::num('num', 10) == 10 ? 10 : 20; $sql_project = ' 1=1 '; if ($proj->id) { $sql_project = sprintf(' t.project_id = %d', $proj->id); } $feed_type = Get::enum('feed_type', array('rss1', 'rss2', 'atom'), 'rss2'); switch (Get::val('topic')) { case 'clo': $orderby = 'date_closed'; $closed = 't.is_closed = 1'; $topic = 1; $title = 'Recently closed tasks'; break; case 'edit': $orderby = 'last_edited_time'; $closed = '1=1';
/* This script sets up and shows the front page with the list of all available tasks that the user is allowed to view. */ if (!defined('IN_FS')) { die('Do not access this file directly.'); } if (!$user->can_view_project($proj->id)) { $proj = new Project(0); } $perpage = '250'; if (isset($user->infos['tasks_perpage']) && $user->infos['tasks_perpage'] > 0) { $perpage = $user->infos['tasks_perpage']; } $pagenum = Get::num('pagenum', 1); if ($pagenum < 1) { $pagenum = 1; } $offset = $perpage * ($pagenum - 1); // Get the visibility state of all columns $visible = explode(' ', trim($proj->id ? $proj->prefs['visible_columns'] : $fs->prefs['visible_columns'])); if (!is_array($visible) || !count($visible) || !$visible[0]) { $visible = array('id'); } list($tasks, $id_list) = Backend::get_task_list($_GET, $visible, $offset, $perpage); //-- Added 2/1/2014 LAE. See if user wants to export the task list if (Get::has('export_list')) { export_task_list(); } $page->uses('tasks', 'offset', 'perpage', 'pagenum', 'visible');
$sparkline->SetData($i, $val[0]); } } } elseif (Get::has('user_id') && Get::has('project_id') && Get::val('graph') == 'user') { $thirtyDays = array(); $today = date('m/j/Y'); $daythirtyone = ''; for ($i = 1; $i < 31; $i++) { $newday = date('m/j/Y', strtotime("-{$i} day", strtotime($today))); $val = User::getDayActivityByUser($newday, Get::num('project_id'), Get::num('user_id')); $sparkline->SetData($i, $val[0]); $daythirtyone = $newday; } $daythirtyone = date('m/j/Y', strtotime("-2 day", strtotime($daythirtyone))); $daysixtyone = date('m/j/Y', strtotime("-32 day", strtotime($daythirtyone))); //look 30 days more and if found scale $check = Project::getActivityProjectCount($daysixtyone, $daythirtyone, Get::num('project_id')); if ($check[0] > 0) { for ($i = 30; $i < 61; $i++) { $newday = date('m/j/Y', strtotime("-{$i} day", strtotime($daythirtyone))); $val = User::getDayActivityByUser($newday, Get::num('project_id'), Get::num('user_id')); $sparkline->SetBarWidth(2); $sparkline->SetBarSpacing(0.5); $sparkline->SetData($i, $val[0]); } } } else { $sparkline->SetData(0, 0); } $sparkline->Render(20); $activity = $sparkline->Output();
$baseurl = dirname(dirname($baseurl)) . '/'; // Initialise user if (Cookie::has('flyspray_userid') && Cookie::has('flyspray_passhash')) { $user = new User(Cookie::val('flyspray_userid')); $user->check_account_ok(); } else { $user = new User(0, $proj); } // Check permissions if (!$user->perms('view_history')) { die; } // Load translations load_translations(); if ($details = Get::num('details')) { $details = " AND h.history_id = {$details}"; } else { $details = null; } $sql = get_events(Get::num('task_id'), $details); $histories = $db->fetchAllArray($sql); $page = new FSTpl(); $page->setTheme($proj->prefs['theme_style']); $page->uses('histories', 'details'); if ($details) { event_description($histories[0]); // modifies global variables $page->assign('details_previous', $GLOBALS['details_previous']); $page->assign('details_new', $GLOBALS['details_new']); } $page->display('details.tabs.history.callback.tpl');
/** * area_users * * @access public * @return void */ function area_users() { global $fs, $db, $proj, $user, $page; // Prepare the sorting $order_keys = array('username' => 'user_name', 'realname' => 'real_name', 'email' => 'email_address', 'jabber' => 'jabber_id', 'regdate' => 'register_date', 'status' => 'account_enabled'); $order_column[0] = $order_keys[Filters::enum(Get::val('order', 'username'), array_keys($order_keys))]; $order_column[1] = $order_keys[Filters::enum(Get::val('order2', 'username'), array_keys($order_keys))]; $sortorder = sprintf('%s %s, %s %s, u.user_id ASC', $order_column[0], Filters::enum(Get::val('sort', 'desc'), array('asc', 'desc')), $order_column[1], Filters::enum(Get::val('sort2', 'desc'), array('asc', 'desc'))); // Search options $search_keys = array('user_name', 'real_name', 'email_address', 'jabber_id'); $where = 'WHERE 1=1 '; $args = array(); foreach ($search_keys as $key) { if (Get::val($key) != '') { $where .= sprintf(' AND %s LIKE ? ', $key); $args[] = '%' . Get::val($key) . '%'; } } // Search for users in a specific group $groups = Get::val('group_id'); if (is_array($groups) && count($groups) && !in_array(0, $groups)) { $where = ' LEFT JOIN {users_in_groups} uig ON u.user_id = uig.user_id ' . $where; $where .= ' AND (' . substr(str_repeat(' uig.group_id = ? OR ', count($groups)), 0, -3) . ' ) '; $args = array_merge($args, $groups); } $sql = $db->x->getAll('SELECT u.user_id, u.user_name, u.real_name, u.register_date, u.jabber_id, u.email_address, u.account_enabled FROM {users} u ' . $where . 'ORDER BY ' . $sortorder, null, $args); $users = GroupBy($sql, 'user_id'); $page->assign('user_count', count($users)); // Offset and limit $user_list = array(); $offset = max(Get::num('pagenum') - 1, 0) * 50; for ($i = $offset; $i < $offset + 50 && $i < count($users); $i++) { $user_list[] = $users[$i]; } // Get the user groups in a separate query because groups may be hidden // because of search options which are disregarded here if (count($user_list)) { $in = implode(',', array_map(create_function('$x', 'return reset($x);'), $user_list)); $sql = $db->x->getAll('SELECT user_id, g.group_id, g.group_name, g.project_id FROM {groups} g LEFT JOIN {users_in_groups} uig ON uig.group_id = g.group_id WHERE user_id IN (' . $in . ')'); $user_groups = GroupBy($sql, 'user_id', array('group_id', 'group_name', 'project_id'), !REINDEX); $page->assign('user_groups', $user_groups); } $page->assign('all_groups', Flyspray::listallGroups()); $page->assign('user_list', $user_list); }
<?php /* This script is the AJAX callback that deletes a user's saved search */ define('IN_FS', true); require_once '../../header.php'; $baseurl = dirname(dirname($baseurl)) . '/'; $db->x->execParam('DELETE FROM {searches} WHERE id = ? AND user_id = ?', array(Get::num('id'), $user->id));
function show() { global $db, $page, $fs, $proj, $do; $page = new FSTpl(); $page->setTheme($proj->prefs['theme_style']); $page->assign('do', $do); $page->pushTpl('baseheader.tpl'); $assignees = ''; if (Get::val('onlyassignees')) { $assignees = 'AND (g.show_as_assignees = 1 OR g.is_admin = 1)'; } $query = 'SELECT g.group_id, g.group_name, g.group_desc, g.group_open, count(u.user_id) AS num_users FROM {groups} g LEFT JOIN {users_in_groups} uig ON uig.group_id = g.group_id LEFT JOIN {users} u ON (uig.user_id = u.user_id ' . $assignees . ') WHERE g.project_id = ? GROUP BY g.group_id'; $page->assign('groups', $db->x->getAll($query, null, $proj->id)); $page->assign('globalgroups', $db->x->getAll($query, null, 0)); // Search conditions $where = array(); $params = array(); foreach (array('user_name', 'real_name') as $key) { if (Post::val($key)) { $where[] = ' ' . $key . ' LIKE ? '; $params[] = '%' . Post::val($key) . '%'; } } $where = count($where) ? implode(' OR ', $where) : '1=1'; // fill the table with users if (Get::val('group_id', -1) > 0) { $order_keys = array('username' => 'user_name', 'realname' => 'real_name'); $order_column = $order_keys[Filters::enum(Get::val('order', 'username'), array_keys($order_keys))]; $sortorder = sprintf('ORDER BY %s %s, u.user_id ASC', $order_column, Filters::enum(Get::val('sort', 'desc'), array('asc', 'desc'))); $users = $db->x->getAll('SELECT u.user_id, user_name, real_name, email_address FROM {users} u LEFT JOIN {users_in_groups} uig ON uig.user_id = u.user_id LEFT JOIN {groups} g ON uig.group_id = g.group_id WHERE uig.group_id = ? ' . $assignees . ' AND ( ' . $where . ' )' . $sortorder, null, array_merge(array(Get::val('group_id')), $params)); // Offset and limit $user_list = array(); $offset = max(Get::num('pagenum') - 1, 0) * 20; for ($i = $offset; $i < $offset + 20 && $i < count($users); $i++) { $user_list[] = $users[$i]; } $page->assign('users', $user_list); } else { // be tricky ^^: show most assigned users $db->setLimit(20); $users = $db->x->getAll('SELECT a.user_id, u.user_name, u.real_name, email_address, count(a.user_id) AS a_count, CASE WHEN t.project_id = ? THEN 1 ELSE 0 END AS my_project FROM {assigned} a LEFT JOIN {users} u ON a.user_id = u.user_id LEFT JOIN {tasks} t ON a.task_id = t.task_id WHERE ( ' . $where . ' )' . ' AND u.account_enabled = 1 GROUP BY a.user_id ORDER BY my_project DESC, a_count DESC', null, array_merge(array($proj->id), $params)); $page->assign('users', $users); } $page->assign('usercount', count($users)); $page->setTitle($fs->prefs['page_title'] . L('userselect')); $page->pushTpl('userselect.tpl'); $page->finish(); }
<?php /************************************\ | Edit comment | | ~~~~~~~~~~~~ | | This script allows users | | to edit comments attached to tasks | \************************************/ if (!defined('IN_FS')) { die('Do not access this file directly.'); } $sql = $db->Query("SELECT c.*, u.real_name\n FROM {comments} c\n INNER JOIN {users} u ON c.user_id = u.user_id\n WHERE comment_id = ? AND task_id = ?", array(Get::num('id', 0), Get::num('task_id', 0))); $page->assign('comment', $comment = $db->FetchRow($sql)); if (!$user->can_edit_comment($comment)) { Flyspray::show_error(11); } $page->pushTpl('editcomment.tpl');
/** * show * * @access public * @return void */ function show() { global $user, $page, $fs, $conf, $db, $proj, $baseurl; $path_to_dot = array_get($conf['general'], 'dot_path', ''); //php 4 on windows does not have is_executable.. $func = function_exists('is_executable') ? 'is_executable' : 'is_file'; $path_to_dot = $func($path_to_dot) ? $path_to_dot : ''; $useLocal = !Flyspray::function_disabled('shell_exec') && $path_to_dot; $fmt = Filters::enum(array_get($conf['general'], 'dot_format', 'png'), array('png', 'svg')); $id = $this->task['task_id']; $page->assign('task_id', $id); $prunemode = Get::num('prune', 0); $selfurl = CreateURL(array('depends', 'task' . $id)); $pmodes = array(L('none'), L('pruneclosedlinks'), L('pruneclosedtasks')); foreach ($pmodes as $mode => $desc) { if ($mode == $prunemode) { $strlist[] = $desc; } else { $strlist[] = "<a href='" . Filters::noXSS($selfurl) . ($mode != 0 ? "&prune={$mode}" : "") . "'>{$desc}</a>\n"; } } $page->assign('strlist', $strlist); $starttime = microtime(); $sql = 'SELECT t1.task_id AS id1, t1.prefix_id AS pxid1, p1.project_prefix AS ppx1, t1.item_summary AS sum1, t1.percent_complete AS pct1, t1.is_closed AS clsd1, t1.closure_comment AS com1, u1c.real_name AS clsdby1, r1.item_name as res1, t2.task_id AS id2, t2.prefix_id AS pxid2, p2.project_prefix AS ppx2, t2.item_summary AS sum2, t2.percent_complete AS pct2, t2.is_closed AS clsd2, t2.closure_comment AS com2, u2c.real_name AS clsdby2, r2.item_name as res2 FROM {dependencies} AS d JOIN {tasks} AS t1 ON d.task_id=t1.task_id LEFT JOIN {users} AS u1c ON t1.closed_by=u1c.user_id LEFT JOIN {projects} AS p1 ON t1.project_id = p1.project_id LEFT JOIN {list_items} AS r1 ON t1.resolution_reason=r1.list_item_id JOIN {tasks} AS t2 ON d.dep_task_id=t2.task_id LEFT JOIN {users} AS u2c ON t2.closed_by=u2c.user_id LEFT JOIN {projects} AS p2 ON t2.project_id = p2.project_id LEFT JOIN {list_items} AS r2 ON t2.resolution_reason=r2.list_item_id WHERE t1.project_id= ? ORDER BY d.task_id, d.dep_task_id'; $edges = $db->x->getAll($sql, null, $proj->id); $edge_list = array(); $rvrs_list = array(); $node_list = array(); foreach ($edges as $row) { extract($row, EXTR_REFS); $edge_list[$id1][] = $id2; $rvrs_list[$id2][] = $id1; if (!isset($node_list[$id1])) { $node_list[$id1] = array('id' => $id1, 'sum' => $sum1, 'pct' => $pct1, 'clsd' => $clsd1, 'ppx' => $ppx1, 'pxid' => $pxid1, 'com' => $com1, 'clsdby' => $clsdby1, 'res' => $res1); } if (!isset($node_list[$id2])) { $node_list[$id2] = array('id' => $id2, 'sum' => $sum2, 'pct' => $pct2, 'clsd' => $clsd2, 'ppx' => $ppx2, 'pxid' => $pxid2, 'com' => $com2, 'clsdby' => $clsdby2, 'res' => $res2); } } // Now we have our lists of nodes and edges, along with a helper // list of reverse edges. Time to do the graph coloring, so we know // which ones are in our particular connected graph. We'll set up a // list and fill it up as we visit nodes that are connected to our // main task. $connected = array(); $levelsdown = 0; $levelsup = 0; function ConnectsTo($id, $down, $up, &$connected, &$edge_list, &$rvrs_list, &$levelsdown, &$levelsup, &$prunemode, &$node_list) { if (!isset($connected[$id])) { $connected[$id] = 1; } if ($down > $levelsdown) { $levelsdown = $down; } if ($up > $levelsup) { $levelsup = $up; } $selfclosed = $node_list[$id]['clsd']; if (isset($edge_list[$id])) { foreach ($edge_list[$id] as $neighbor) { $neighborclosed = $node_list[$neighbor]['clsd']; if (!isset($connected[$neighbor]) && !($prunemode == 1 && $selfclosed && $neighborclosed) && !($prunemode == 2 && $neighborclosed)) { ConnectsTo($neighbor, $down, $up + 1, $connected, $edge_list, $rvrs_list, $levelsdown, $levelsup, $prunemode, $node_list); } } } if (isset($rvrs_list[$id])) { foreach ($rvrs_list[$id] as $neighbor) { $neighborclosed = $node_list[$neighbor]['clsd']; if (!isset($connected[$neighbor]) && !($prunemode == 1 && $selfclosed && $neighborclosed) && !($prunemode == 2 && $neighborclosed)) { ConnectsTo($neighbor, $down + 1, $up, $connected, $edge_list, $rvrs_list, $levelsdown, $levelsup, $prunemode, $node_list); } } } } ConnectsTo($id, 0, 0, $connected, $edge_list, $rvrs_list, $levelsdown, $levelsup, $prunemode, $node_list); $connected_nodes = array_keys($connected); sort($connected_nodes); // Now lets get rid of the extra junk in our arrays. // In prunemode 0, we know we're only going to have to get rid of // whole lists, and not elements in the lists, because if they were // in the list, they'd be connected, so we wouldn't be removing them. // In prunemode 1 or 2, we may have to remove stuff from the list, because // you can have an edge to a node that didn't end up connected. foreach (array("edge_list", "rvrs_list", "node_list") as $l) { foreach (${$l} as $n => $list) { if (!isset($connected[$n])) { unset(${$l}[$n]); } if ($prunemode != 0 && $l != "node_list" && isset(${$l}[$n])) { // Only keep entries that appear in the $connected_nodes list ${$l}[$n] = array_intersect(${$l}[$n], $connected_nodes); } } } // Now we've got everything we need... let's draw the pretty pictures //Open the graph, and print global options $lj = 'n'; // label justification - l, r, or n (for center) $graphname = "task_{$id}_dependencies"; $dotgraph = "digraph {$graphname} {\n" . "node [width=1.1, shape=ellipse, border=10, color=\"#00E11E\", style=\"filled\", " . "fontsize=10.0, pencolor=black, margin=\"0.1, 0.0\"];\n"; // define the nodes foreach ($node_list as $n => $r) { $col = ""; if ($r['clsd'] && $n != $id) { $r['pct'] = 120; } // color code: shades of gray for % done $x = dechex(255 - ($r['pct'] + 10)); $col = "#{$x}{$x}{$x}"; // Make sure label terminates in \n! $label = $r['ppx'] . '#' . $r['pxid'] . " \n" . ($useLocal ? addslashes(utf8_substr($r['sum'], 0, 15)) . "\n" : '') . ($r['clsd'] ? L('closed') : "{$r['pct']}% " . L('complete')); $tooltip = $r['clsd'] ? L('closed') . ": {$r['res']}" . (!empty($r['clsdby']) ? " ({$r['clsdby']})" : '') . ($r['com'] != '' ? ' - ' . str_replace(array("\r", "\n"), '', $r['com']) : '') : $r['pct']; $dotgraph .= "FS{$n} [label=\"" . str_replace("\n", "\\{$lj}", $label) . "\", " . ($r['clsd'] ? 'color=black,' : '') . ($r['clsd'] ? 'fillcolor=white,' : "fillcolor=\"{$col}\",") . ($n == $id ? 'shape=box,' : '') . "href=\"javascript:top.window.location.href='" . CreateURL(array("details", 'task' . $n)) . "'\", target=\"_top\" " . "tooltip=\"{$tooltip}\"];\n"; } // Add edges foreach ($edge_list as $src => $dstlist) { foreach ($dstlist as $dst) { $dotgraph .= "FS{$src} -> FS{$dst};\n"; } } // all done $dotgraph .= "}\n"; // All done with the graph. Save it to a temp file (new name if the data has changed) $dotfilename = sprintf('cache/fs_depends_dot_%d_%s.dot', $id, md5($dotgraph)); $imgfilename = sprintf('%s/%s.%s', BASEDIR, $dotfilename, $fmt); $mapfilename = sprintf('%s/%s.%s', BASEDIR, $dotfilename, 'map'); //cannot use tempnam( ) as file has to end with $ftm extension if (!$useLocal) { //cannot use tempnam() as file has to end with $ftm extension $tname = $dotfilename; } else { // we are operating on the command line, avoid races. $tname = tempnam(Flyspray::get_tmp_dir(), md5(uniqid(mt_rand(), true))); } //get our dot done.. file_put_contents($tname, $dotgraph, LOCK_EX); // Now run dot on it, if target file does not already exist if (!is_file($imgfilename)) { if (!$useLocal) { require_once 'Zend/Rest/Client.php'; $client = new Zend_Rest_Client('http://webdot.flyspray.org/'); $data = base64_decode($client->getGraph(base64_encode($dotgraph), $fmt)->post()); file_put_contents($imgfilename, $data, LOCK_EX); $data = base64_decode($client->getGraph(base64_encode($dotgraph), 'cmapx')->post()); file_put_contents($mapfilename, $data, LOCK_EX); } else { $tfn = escapeshellarg($tname); shell_exec(sprintf('%s -T %s -o %s %s', $path_to_dot, escapeshellarg($fmt), escapeshellarg($imgfilename), $tfn)); $data['map'] = shell_exec(sprintf('%s -T cmapx %s', $path_to_dot, $tfn)); file_put_contents($mapfilename, $data['map'], LOCK_EX); // Remove files so that they are not exposed to the public unlink($tname); } } $page->assign('map', file_get_contents($mapfilename)); $page->assign('image', sprintf('%s%s.%s', $baseurl, $dotfilename, $fmt)); // we have to find out the image size if it is SVG if ($fmt == 'svg') { if (!$remote) { $data = file_get_contents(BASEDIR . '/' . $file_name . '.' . $fmt); } preg_match('/<svg width="([0-9.]+)([a-zA-Z]+)" height="([0-9.]+)([a-zA-Z]+)"/', $data, $matches); $page->assign('width', round($matches[1] * ($matches[2] == 'pt' ? 1.4 : ($matches[2] == 'in' ? 1.33 * 72.27 : 1)), 0)); $page->assign('height', round($matches[3] * ($matches[4] == 'pt' ? 1.4 : ($matches[4] == 'in' ? 1.35 * 72.27 : 1)), 0)); } /* [TC] We cannot have this stuff outputting here, so I put it in a quick template */ $page->assign('taskid', $id); $page->assign('fmt', $fmt); $page->assign('graphname', $graphname); $endtime = microtime(); list($startusec, $startsec) = explode(' ', $starttime); list($endusec, $endsec) = explode(' ', $endtime); $diff = $endsec - $startsec + ($endusec - $startusec); $page->assign('time', round($diff, 2)); $page->setTitle($this->task['project_prefix'] . '#' . $this->task['prefix_id'] . ': ' . L('dependencygraph')); $page->pushTpl('depends.tpl'); }
<?php /* This script gets the history of a task and returns it for HTML display in a page. */ define('IN_FS', true); header('Content-type: text/html; charset=utf-8'); require_once '../../header.php'; require_once '../../includes/events.inc.php'; $baseurl = dirname(dirname($baseurl)) . '/'; // Check permissions if (!$user->perms('view_history')) { die; } if ($details = Get::num('details')) { $details = " AND h.history_id = {$details}"; } else { $details = null; } $histories = get_events(Get::num('task_id'), $details); $page = new FSTpl(); $page->uses('histories', 'details'); if ($details) { event_description($histories[0]); // modifies global variables $page->assign('details_previous', $GLOBALS['details_previous']); $page->assign('details_new', $GLOBALS['details_new']); } $page->display('details.tabs.history.callback.tpl');