예제 #1
0
파일: reports.php 프로젝트: negram/flyspray
 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');
 }
예제 #2
0
 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);
 }
예제 #3
0
파일: index.php 프로젝트: negram/flyspray
 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');
 }
예제 #4
0
<?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));
}
예제 #5
0
<?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));
}
예제 #6
0
    //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';
예제 #7
0
파일: feed.php 프로젝트: negram/flyspray
// 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';
예제 #8
0
파일: index.php 프로젝트: xcdam/flyspray
/*
   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');
예제 #9
0
            $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();
예제 #10
0
$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');
예제 #11
0
파일: admin.php 프로젝트: negram/flyspray
 /**
  * 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);
 }
예제 #12
0
<?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));
예제 #13
0
 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();
 }
예제 #14
0
<?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');
예제 #15
0
파일: depends.php 프로젝트: negram/flyspray
 /**
  * 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 ? "&amp;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');
 }
예제 #16
0
<?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');