Пример #1
0
function add_related($arr)
{
    global $log, $col, $db;
    static $imported = array();
    $task = $arr[1] . $arr[2];
    list($prefix, $task) = explode(strpos($task, '#') !== false ? '#' : ' ', $task);
    $task = Flyspray::GetTaskDetails($task, true, $prefix);
    if (!$task['task_id'] || isset($imported[$task['task_id'] . '-' . $log['version-name']])) {
        return;
    }
    echo sprintf('<p>&nbsp;&nbsp;&nbsp;Adding task %d for revision %d</p>', $task['task_id'], $log['version-name']);
    flush();
    $imported[$task['task_id'] . '-' . $log['version-name']] = true;
    $db->x->execParam("INSERT INTO {related} (this_task, related_task, {$col}) VALUES (?,?,?)", array($task['task_id'], $log['version-name'], RELATED_SVN));
}
Пример #2
0
 function imageAttachment($matches)
 {
     global $db, $baseurl, $user;
     // we'll not blindly make images out of all attachments
     $ext = substr($matches[1], -3);
     if (!in_array($ext, array('png', 'jpg', 'gif'))) {
         return $matches[0];
     }
     $att = $db->x->getRow('SELECT * FROM {attachments} WHERE orig_name = ?', null, $matches[1]);
     $task = Flyspray::GetTaskDetails($att['task_id']);
     if ($att && $user->can_view_task($task)) {
         return sprintf('<img src="%s" alt="%s" />', Filters::noXSS($baseurl . '?getfile=' . $att['attachment_id']), Filters::noXSS($att['orig_name']));
     } else {
         return $matches[0];
     }
 }
Пример #3
0
 function action_edit()
 {
     foreach (Get::val('ids') as $task_id) {
         // Edit or close? If we have a resolution_reason, then close! otherwise, edit.
         if (Post::val('resolution_reason')) {
             Backend::close_task($task_id, Post::val('resolution_reason'), Post::val('closure_comment'), Post::val('mark100'));
         } elseif (count(Post::val('changes'))) {
             $task = Flyspray::GetTaskDetails($task_id);
             $args = $task;
             // import previous values
             foreach (Post::val('changes') as $change) {
                 $args[$change] = Post::val($change);
             }
             if (is_array($args['assigned_to'])) {
                 $args['assigned_to'] = implode(';', $task['assigned_to_uname']);
             }
             Backend::edit_task($task, $args);
         }
     }
     return array(SUBMIT_OK, L('masseditsuccessful'));
 }
Пример #4
0
function tpl_tasklink($task, $text = null, $strict = false, $attrs = array(), $title = array('status', 'summary', 'percent_complete'))
{
    global $user;
    $params = array();
    if (!is_array($task) || !isset($task['status_name'])) {
        $td_id = is_array($task) && isset($task['task_id']) ? $task['task_id'] : $task;
        $task = Flyspray::GetTaskDetails($td_id, true);
    }
    if ($strict === true && (!is_object($user) || !$user->can_view_task($task))) {
        return '';
    }
    if (is_object($user) && $user->can_view_task($task)) {
        $summary = utf8_substr($task['item_summary'], 0, 64);
    } else {
        $summary = L('taskmadeprivate');
    }
    if (is_null($text)) {
        $text = sprintf('FS#%d - %s', $task['task_id'], Filters::noXSS($summary));
    } elseif (is_string($text)) {
        $text = htmlspecialchars(utf8_substr($text, 0, 64), ENT_QUOTES, 'utf-8');
    } else {
        //we can't handle non-string stuff here.
        return '';
    }
    if (!$task['task_id']) {
        return $text;
    }
    $title_text = array();
    foreach ($title as $info) {
        switch ($info) {
            case 'status':
                if ($task['is_closed']) {
                    $title_text[] = $task['resolution_name'];
                    $attrs['class'] = 'closedtasklink';
                } else {
                    $title_text[] = $task['status_name'];
                }
                break;
            case 'summary':
                $title_text[] = $summary;
                break;
            case 'assignedto':
                if (isset($task['assigned_to_name'])) {
                    if (is_array($task['assigned_to_name'])) {
                        $title_text[] = implode(', ', $task['assigned_to_name']);
                    } else {
                        $title_text[] = $task['assigned_to_name'];
                    }
                }
                break;
            case 'percent_complete':
                $title_text[] = $task['percent_complete'] . '%';
                break;
            case 'category':
                if ($task['product_category']) {
                    if (!isset($task['category_name'])) {
                        $task = Flyspray::GetTaskDetails($task['task_id'], true);
                    }
                    $title_text[] = $task['category_name'];
                }
                break;
                // ... more options if necessary
        }
    }
    $title_text = implode(' | ', $title_text);
    // to store search options
    $params = $_GET;
    unset($params['do'], $params['action'], $params['task_id'], $params['switch']);
    if (isset($params['event_number'])) {
        # shorter links to tasks from report page
        unset($params['events'], $params['event_number'], $params['fromdate'], $params['todate'], $params['submit']);
    }
    # We can unset the project param for shorter urls because flyspray knows project_id from current task data.
    # Except we made a search from an 'all projects' view before, so the prev/next navigation on details page knows
    # if it must search only in the project of current task or all projects the user is allowed to see tasks.
    if (!isset($params['advancedsearch']) || isset($params['project']) && $params['project'] != 0) {
        unset($params['project']);
    }
    $url = htmlspecialchars(CreateURL('details', $task['task_id'], null, $params), ENT_QUOTES, 'utf-8');
    $title_text = htmlspecialchars($title_text, ENT_QUOTES, 'utf-8');
    $link = sprintf('<a href="%s" title="%s" %s>%s</a>', $url, $title_text, join_attrs($attrs), $text);
    if ($task['is_closed']) {
        $link = '<del>&#160;' . $link . '&#160;</del>';
    }
    return $link;
}
Пример #5
0
    $args['item_summary'] = "Task {$i} ({$subject})";
    // 'detailed_desc'
    // echo $args['item_summary'] . "\r\n";
    $ok = Backend::create_task($args);
    if ($ok === 0) {
        echo "Failed to create task.\r\n";
    } else {
        list($id, $token) = $ok;
        $db->Query('UPDATE {tasks} SET opened_by = ?, date_opened = ? WHERE task_id = ?', array($reporter, $opened, $id));
    }
}
// One task in ten of is unconfirmed, probably just bullshit, not assigned to anyone,
// and we add just a comment "Cannot reproduce".
for ($i = 1; $i <= $maxcomments; $i++) {
    $taskid = rand(2, $maxtasks + 1);
    $task = Flyspray::GetTaskDetails($taskid, true);
    $project = $task['project_id'];
    $added = time() - rand(1, 315360000);
    // Find someone who is allowed to add comment, do not use global groups
    $sqltext = "SELECT uig.user_id\n                         FROM {users_in_groups} uig\n                         JOIN {groups} g ON g.group_id = uig.group_id AND g.add_comments = 1\n                          AND (g.project_id = 0 OR g.project_id = ?)\n                        WHERE g.group_id NOT IN (1, 2, 7, 8, 9)\n                     ORDER BY {$RANDOP} ";
    $sql = $db->Query($sqltext, array($project));
    $row = $db->FetchRow($sql);
    $reporter = new User($row['user_id']);
    // User might still not be able to add a comment, if he can not see the task...
    // Just try again until a suitable one comes out from the query. It will finally.
    // Try to enhance the query also to return fewer unsuitable ones.
    while (!$reporter->can_view_task($task)) {
        $row = $db->FetchRow($sql);
        $reporter = new User($row['user_id']);
    }
    $comment = 'Comment.';
Пример #6
0
 /**
  * Processes single command and performs some backend action
  *
  * @param FlySprayCommand $cmd
  * @param Backend $backend
  * @return mixed
  */
 private function process_command(FlySprayCommand $cmd, Backend &$backend)
 {
     $not_cackend_commands = array('active_user', 'get_task_details');
     if (!in_array($cmd->action, $not_cackend_commands) && !method_exists($backend, $cmd->action)) {
         throw new Exception('Needed action is not performed in Backend', API_ECODE_BACKEND_NOT_PORFORM);
     }
     global $db;
     switch ($cmd->action) {
         case 'active_user':
             // CommandActiveUser
             global $user;
             if ($user->infos['user_name'] != $cmd->id) {
                 $user_id = $db->x->GetOne('SELECT user_id FROM {users} WHERE user_name = ?', null, $cmd->id);
                 if (intval($user_id) > 0) {
                     $user = new User($user_id);
                 } else {
                     throw new Exception('ActiveUser can not be set', API_ECODE_SET_ACTIVE_USER);
                 }
             }
             break;
         case 'add_comment':
             // CommandAddComment
             if (!($task = Flyspray::GetTaskDetails($cmd->id))) {
                 throw new Exception('Cannot select task', API_ECODE_SELECT_TASK);
             }
             if (!($cid = $backend->add_comment($task, $cmd->ids[0]))) {
                 throw new Exception('Failed adding comment', API_ECODE_ADD_COMMENT);
             }
             return $cid;
         case 'close_task':
             // CommandCloseTask
             try {
                 $list_item_id = $this->get_list_item_id('resolution', 'fixed');
             } catch (Exception $exc) {
                 throw new Exception($exc->getMessage(), API_ECODE_CLOSE_TASK);
             }
             if (!$backend->close_task($cmd->id, $list_item_id, $cmd->ids['comment'], $cmd->ids['mark100'])) {
                 throw new Exception('Cannot close task', API_ECODE_CLOSE_TASK);
             }
             break;
         case 'edit_task':
             // CommandEditTask
             // default task fields, another fields should be treated as custom fields
             $def_fields = array('item_summary', 'project_id', 'percent_complete', 'assignedto');
             if (!($task = Flyspray::GetTaskDetails($cmd->id))) {
                 throw new Exception('Cannot select task', API_ECODE_SELECT_TASK);
             }
             $args = $task;
             $this->normalize_task_to_args($args);
             foreach ($cmd->ids as $param_key => $param_value) {
                 if (in_array($param_key, $def_fields)) {
                     $args[$param_key] = $param_value;
                 } else {
                     if (!($field = $db->x->getRow('SELECT * FROM {fields} WHERE field_name = ?', null, $param_key))) {
                         throw new Exception('Cannot find custom field row for ' . $param_key, API_ECODE_FIELD_NOT_FOUND);
                     }
                     if (!($field_val = $db->x->getRow("SELECT * FROM {list_items} WHERE list_id = ? AND item_name LIKE '%{$param_value}%'", null, $field['list_id']))) {
                         throw new Exception(sprintf('Cannot find field item row for %s like %s', $param_key, $param_value), API_ECODE_FIELD_VALUE_NOT_FOUND);
                     }
                     $args['field' . $field['field_id']] = $field_val['list_item_id'];
                 }
             }
             list($status_code, $msg) = $backend->edit_task($task, $args);
             if ($status_code != SUBMIT_OK) {
                 throw new Exception(sprintf('Failed editing task, status code is "%d", message is "%s"', $status_code, strval($msg)), API_ECODE_EDIT_TASK);
             }
             break;
         case 'assign_to_me':
             // CommandAssignToMe
             $user_to_assign = $db->x->getRow('SELECT * FROM {users} WHERE user_name = ?', null, $cmd->id);
             if (!$user_to_assign) {
                 throw new Exception(sprintf('Username "%s" is not found', $cmd->id), API_ECODE_USERNAME_NOT_FOUND);
             }
             $backend->assign_to_me($user_to_assign['user_id'], $cmd->ids);
             break;
         case 'get_task_details':
             if (!($task = Flyspray::GetTaskDetails($cmd->id))) {
                 throw new Exception('Cannot select task', API_ECODE_SELECT_TASK);
             }
             return $task;
         default:
             throw new Exception('Unrecognized command ' . $cmd->action, API_ECODE_UNRECOGNIZED_COMMAND);
     }
 }
Пример #7
0
<?php

/********************************************************\
  | Task Dependancy Graph                                  |
  | ~~~~~~~~~~~~~~~~~~~~~                                  |
  \********************************************************/
/**
 * XXX: This stuff looks incredible ugly, rewrite me for 1.0
 */
if (!defined('IN_FS')) {
    die('Do not access this file directly.');
}
if (!($task_details = Flyspray::GetTaskDetails(Req::num('task_id'))) || !$user->can_view_task($task_details)) {
    Flyspray::show_error(9);
}
$id = Req::num('task_id');
$page->assign('task_id', $id);
$prunemode = Req::num('prune', 0);
$selfurl = CreateURL('depends', $id);
$pmodes = array(L('none'), L('pruneclosedlinks'), L('pruneclosedtasks'));
foreach ($pmodes as $mode => $desc) {
    if ($mode == $prunemode) {
        $strlist[] = $desc;
    } else {
        $strlist[] = "<a href='" . htmlspecialchars($selfurl, ENT_QUOTES, 'utf-8') . ($mode != 0 ? "&amp;prune={$mode}" : "") . "'>{$desc}</a>\n";
    }
}
$page->uses('strlist');
$starttime = microtime();
$sql = 'SELECT t1.task_id AS id1, t1.item_summary AS sum1,
             t1.percent_complete AS pct1, t1.is_closed AS clsd1,
Пример #8
0
 function _onsubmit()
 {
     $action = Req::val('action');
     list($type, $msg, $url) = $this->handle('action', $action, $this->task);
     if ($type != NO_SUBMIT) {
         $this->task = Flyspray::GetTaskDetails(Req::num('task_id'));
     }
     return array($type, $msg, $url);
 }
Пример #9
0
 /**
  * Closes a task
  * @param integer $task_id
  * @param integer $reason
  * @param string $comment
  * @param bool $mark100
  * @access public
  * @return bool
  * @version 1.0
  */
 function close_task($task_id, $reason, $comment, $mark100 = true)
 {
     global $db, $user, $fs;
     $task = Flyspray::GetTaskDetails($task_id);
     if (!$user->can_close_task($task)) {
         return false;
     }
     if ($task['is_closed']) {
         return false;
     }
     $db->x->autoExecute('{tasks}', array('date_closed' => time(), 'closed_by' => $user->id, 'closure_comment' => $comment, 'is_closed' => 1, 'resolution_reason' => $reason, 'last_edited_time' => time(), 'last_edited_by' => $user->id, 'percent_complete' => (bool) $mark100 * 100), MDB2_AUTOQUERY_UPDATE, sprintf('task_id = %d', $task_id));
     if ($mark100) {
         Flyspray::logEvent($task_id, 3, 100, $task['percent_complete'], 'percent_complete');
     }
     // [RED] Update last changed date
     $db->x->execParam('UPDATE {redundant} SET last_changed_time = ?,
                               last_changed_by_real_name = ?, last_changed_by_user_name = ?,
                               closed_by_real_name = ?, closed_by_user_name = ?
                         WHERE task_id = ?', array(time(), $user->infos['real_name'], $user->infos['user_name'], $user->infos['real_name'], $user->infos['user_name'], $task_id));
     Notifications::send($task_id, ADDRESS_TASK, NOTIFY_TASK_CLOSED);
     Flyspray::logEvent($task_id, 2, $reason, $comment);
     // If there's an admin request related to this, close it
     $db->x->autoExecute('{admin_requests}', array('resolved_by' => $user->id, 'time_resolved' => time()), MDB2_AUTOQUERY_UPDATE, sprintf('task_id = %d AND request_type = 1', $task_id));
     // duplicate
     if ($reason == $fs->prefs['resolution_dupe']) {
         $look = array('FS#', 'bug ');
         foreach ($fs->projects as $project) {
             $look[] = preg_quote($project['project_prefix'] . '#', '/');
         }
         preg_match("/\\b(" . implode('|', $look) . ")(\\d+)\\b/", $comment, $dupe_of);
         if (count($dupe_of) >= 2) {
             $existing = $db->x->getOne('SELECT count(*) FROM {related} WHERE this_task = ? AND related_task = ? AND related_type = 1', null, array($task_id, $dupe_of[1]));
             if (!$existing) {
                 $db->x->autoExecute('{related}', array('this_task' => $task_id, 'related_task' => $dupe_of[1], 'related_type' => 1));
             }
             Backend::add_vote($task['opened_by'], $dupe_of[1]);
         }
     }
     return true;
 }
Пример #10
0
function tpl_tasklink($task, $text = null, $strict = false, $attrs = array(), $title = array('status', 'summary', 'percent_complete'))
{
    global $user;
    $params = array();
    if (!is_array($task) || !isset($task['status_name'])) {
        $td_id = is_array($task) && isset($task['task_id']) ? $task['task_id'] : $task;
        $task = Flyspray::GetTaskDetails($td_id, true);
    }
    if ($strict === true && (!is_object($user) || !$user->can_view_task($task))) {
        return '';
    }
    if (is_object($user) && $user->can_view_task($task)) {
        $summary = utf8_substr($task['item_summary'], 0, 64);
    } else {
        $summary = L('taskmadeprivate');
    }
    if (is_null($text)) {
        $text = sprintf('FS#%d - %s', $task['task_id'], Filters::noXSS($summary));
    } elseif (is_string($text)) {
        $text = htmlspecialchars(utf8_substr($text, 0, 64), ENT_QUOTES, 'utf-8');
    } else {
        //we can't handle non-string stuff here.
        return '';
    }
    if (!$task['task_id']) {
        return $text;
    }
    $title_text = array();
    foreach ($title as $info) {
        switch ($info) {
            case 'status':
                if ($task['is_closed']) {
                    $title_text[] = $task['resolution_name'];
                    $attrs['class'] = 'closedtasklink';
                } else {
                    $title_text[] = $task['status_name'];
                }
                break;
            case 'summary':
                $title_text[] = $summary;
                break;
            case 'assignedto':
                if (isset($task['assigned_to_name'])) {
                    if (is_array($task['assigned_to_name'])) {
                        $title_text[] = implode(', ', $task['assigned_to_name']);
                    } else {
                        $title_text[] = $task['assigned_to_name'];
                    }
                }
                break;
            case 'percent_complete':
                $title_text[] = $task['percent_complete'] . '%';
                break;
            case 'category':
                if ($task['product_category']) {
                    if (!isset($task['category_name'])) {
                        $task = Flyspray::GetTaskDetails($task['task_id'], true);
                    }
                    $title_text[] = $task['category_name'];
                }
                break;
                // ... more options if necessary
        }
    }
    $title_text = implode(' | ', $title_text);
    // to store search options
    $params = $_GET;
    unset($params['do'], $params['action'], $params['task_id'], $params['switch']);
    $url = htmlspecialchars(CreateURL('details', $task['task_id'], null, $params), ENT_QUOTES, 'utf-8');
    $title_text = htmlspecialchars($title_text, ENT_QUOTES, 'utf-8');
    $link = sprintf('<a href="%s" title="%s" %s>%s</a>', $url, $title_text, join_attrs($attrs), $text);
    if ($task['is_closed']) {
        $link = '<del>&#160;' . $link . '&#160;</del>';
    }
    return $link;
}
Пример #11
0
function createTestData()
{
    # quick safety
    exit;
    if (PHP_SAPI !== 'cli') {
        die('Please call it only from commandline');
    }
    global $db, $fs, $proj, $user, $notify;
    // Use this only on a new test installation, code does not work on
    // an existing one, and never will.
    ### Simulation Settings ###
    # Set conservative data as default, setup bigger values for further performance tests.
    # maybe setting moved out of this function to make performance graphs with multiple runs..
    // Borg Inc. is a big multinational company delivering
    $maxproducts = 3;
    # =projects
    $maxversions = 3;
    // both to it's
    $maxcorporateusers = 5;
    // working in
    $maxcorporates = 3;
    // and
    $maxindividualusers = 5;
    // who are all happy to report to us about
    $maxtasks = 10;
    // There are many problems in our products. And then there are also
    $maxviewers = 10;
    // who just like to watch what's going on here at Borg Inc.
    // Our users are also keen to add attachments to their reports and comments, so there are
    $maxattachments = 5;
    // in our database;
    // Our users are also very active with commenting.
    $maxcomments = 20;
    // To handle all the resulting work, we need
    $maxadmins = 2;
    $maxmanagers = 2;
    $maxdevelopers = 3;
    // people working together all over the globe to care for their needs.
    ### End of Simulation Settings ###
    // We also have both a very innovative and standardized naming scheme for our products.
    // And we have also made one big invention offered only to our customers in the world:
    // Time travel! You can comment on tasks and other comments in them even before the task
    // is even opened or the original comment made.
    // Add more according to your taste...
    $subjects[] = "%s sucks!";
    $subjects[] = "%s is utterly crap!";
    $subjects[] = "Developers of %s should be hanged!";
    $subjects[] = "Developers of %s should be strangled!";
    $subjects[] = "Developers of %s should be eaten alive by zombies!";
    $subjects[] = "Developers of %s should be thrown in a pit of snakes!";
    $subjects[] = "Who is the idiot responsible for %s?";
    error_reporting(E_ALL);
    // die('Enable me by commenting this out by editing and read the contents first!'.basename(__FILE__).' at line '.__LINE__);
    define('IN_FS', 1);
    require_once dirname(__FILE__) . '/../includes/fix.inc.php';
    require_once dirname(__FILE__) . '/../includes/class.flyspray.php';
    require_once dirname(__FILE__) . '/../includes/constants.inc.php';
    require_once dirname(__FILE__) . '/../includes/i18n.inc.php';
    require_once dirname(__FILE__) . '/../includes/class.tpl.php';
    require_once dirname(__FILE__) . '/../vendor/autoload.php';
    $conf = parse_ini_file('../flyspray.conf.php', true) or die('Cannot open config file.');
    $db = new Database();
    $db->dbOpenFast($conf['database']);
    $RANDOP = 'RAND()';
    if ($db->dblink->dataProvider == 'postgres') {
        $RANDOP = 'RANDOM()';
    }
    #die();
    $fs = new Flyspray();
    $user = new User(1);
    $proj = new Project(1);
    $notify = new Notifications();
    load_translations();
    for ($i = 1; $i <= $maxadmins; $i++) {
        $user_name = "admin{$i}";
        $real_name = "Administrator {$i}";
        $password = $user_name;
        $time_zone = 0;
        // Assign different one!
        $email = null;
        // $user_name . '@example.com';
        Backend::create_user($user_name, $password, $real_name, '', $email, 0, $time_zone, 1, 1);
    }
    for ($i = 1; $i <= $maxmanagers; $i++) {
        $user_name = "pm{$i}";
        $real_name = "Project Manager {$i}";
        $password = $user_name;
        $time_zone = 0;
        // Assign different one!
        $email = null;
        // $user_name . '@example.com';
        Backend::create_user($user_name, $password, $real_name, '', $email, 0, $time_zone, 2, 1);
    }
    $db->Query('UPDATE {projects} SET project_is_active = 0 WHERE project_id = 1');
    // Show more columns by default, trying to make database or flyspray crash under stress.
    $db->Query("UPDATE {prefs} SET pref_value = 'id project category tasktype severity summary status openedby dateopened progress comments attachments votes' WHERE pref_name = 'visible_columns'");
    // Add 3 different Global developer groups with different
    // view rights first, then assign developers to them at random.
    // Borg Inc. has a strict hierarchy on who can see and do what.
    // Somewhat more relaxed with our own developers.
    $db->Query("INSERT INTO {groups} " . "(group_name,group_desc,project_id,group_open,view_comments,manage_project,view_tasks, view_groups_tasks, view_own_tasks,open_new_tasks,modify_own_tasks) " . "VALUES('Developer Group 1', 'Developer Group 1', 0, 1, 1, 0, 1, 1, 1, 1, 1)");
    $db->Query("INSERT INTO {groups} " . "(group_name,group_desc,project_id,group_open,view_comments,manage_project,view_tasks, view_groups_tasks, view_own_tasks,open_new_tasks,modify_own_tasks) " . "VALUES('Developer Group 2', 'Developer Group 2', 0, 1, 1, 0, 0, 1, 1, 1, 1)");
    $db->Query("INSERT INTO {groups} " . "(group_name,group_desc,project_id,group_open,view_comments,manage_project,view_tasks, view_groups_tasks, view_own_tasks,open_new_tasks,modify_own_tasks) " . "VALUES('Developer Group 3', 'Developer Group 3', 0, 1, 1, 0, 0, 0, 1, 1, 1)");
    // Add also general groups for corporate users, individual users and viewers.
    // Allow only login. Not so relaxed with them bastards.
    $db->Query("INSERT INTO {groups} " . "(group_name,group_desc,project_id,group_open) " . "VALUES('Corporate Users', 'Corporate Users', 0, 1)");
    $db->Query("INSERT INTO {groups} " . "(group_name,group_desc,project_id,group_open) " . "VALUES('Trusted Users', 'Trusted Users', 0, 1)");
    $db->Query("INSERT INTO {groups} " . "(group_name,group_desc,project_id,group_open) " . "VALUES('Non-trusted Users', 'Non-trusted Users', 0, 1)");
    for ($i = 1; $i <= $maxdevelopers; $i++) {
        $user_name = "dev{$i}";
        $real_name = "Developer {$i}";
        $password = $user_name;
        $time_zone = 0;
        // Assign different one!
        $email = null;
        // $user_name . '@example.com';
        $group = rand(7, 9);
        Backend::create_user($user_name, $password, $real_name, '', $email, 0, $time_zone, $group, 1);
    }
    // We have been really active in the past years, AND have a lot of projects.
    for ($i = 1; $i <= $maxproducts; $i++) {
        $projname = strtoupper(substr(md5(uniqid(mt_rand(), true)), 0, mt_rand(8, 12)));
        $projname = 'Borg Inc. Product ' . preg_replace('/^(.{3})(.+)$/', '$1-$2', $projname);
        $db->Query('INSERT INTO  {projects}
				( project_title, theme_style, intro_message,
				others_view, anon_open, project_is_active,
				visible_columns, visible_fields, lang_code,
				notify_email, notify_jabber, disp_intro)
			VALUES  (?, ?, ?, ?, ?, 1, ?, ?, ?, ?, ?, ?)', array($projname, 'CleanFS', "Welcome to {$projname}", 0, 0, 'id category tasktype severity summary status openedby dateopened progress comments attachments votes', 'supertask tasktype category severity priority status private assignedto reportedin dueversion duedate progress os votes', 'en', '', '', 1));
        add_project_data();
    }
    // Assign some of the poor developers to project manager or project developer groups
    // rights to some of the projects they must work on.
    for ($i = 1; $i <= $maxproducts; $i++) {
        $projid = $i + 1;
        $sql = $db->Query('SELECT group_id FROM {groups} WHERE project_id = ? AND manage_project = 1', array($projid));
        $pmgroup = $db->FetchOne($sql);
        $sql = $db->Query('SELECT group_id FROM {groups} WHERE project_id = ? AND manage_project = 0', array($projid));
        $pdgroup = $db->FetchOne($sql);
        $pmlimit = intval($maxdevelopers / 100) + rand(-2, 2);
        $pdlimit = intval($maxdevelopers / 20) + rand(-10, 10);
        $pmlimit = $pmlimit < 1 ? 1 : $pmlimit;
        $pdlimit = $pdlimit < 1 ? 1 : $pdlimit;
        $sql = $db->Query("SELECT user_id FROM {users_in_groups} WHERE group_id in (7, 8, 9) ORDER BY {$RANDOP} limit {$pmlimit}");
        $pms = $db->fetchCol($sql);
        $sql = $db->Query("SELECT user_id FROM {users_in_groups} WHERE group_id in (8, 9) ORDER BY {$RANDOP} limit {$pdlimit}");
        $pds = $db->fetchCol($sql);
        foreach ($pms as $pm) {
            $db->Query('INSERT INTO {users_in_groups} (user_id, group_id) values (?, ?)', array($pm, $pmgroup));
        }
        foreach ($pds as $pd) {
            $check = $db->Query('SELECT * FROM {users_in_groups} WHERE user_id = ? AND group_id = ?', array($pd, $pmgroup));
            if (!$db->CountRows($check)) {
                $db->Query('INSERT INTO {users_in_groups} (user_id, group_id) values (?, ?)', array($pd, $pdgroup));
            }
        }
    }
    // Create corporate users.
    for ($i = 1; $i <= $maxcorporateusers; $i++) {
        $user_name = "cu{$i}";
        $real_name = "Corporate user {$i}";
        $password = $user_name;
        $time_zone = 0;
        // Assign different ones!
        $email = null;
        // $user_name . '@example.com';
        $group = 10;
        Backend::create_user($user_name, $password, $real_name, '', $email, 0, $time_zone, $group, 1);
    }
    // Now, create corporate user groups for some of our projects.
    // Just %5 change of getting added.
    for ($i = 1; $i <= $maxcorporates; $i++) {
        for ($j = 1; $j <= $maxproducts; $j++) {
            if (rand(1, 20) == 1) {
                $projid = $j + 1;
                $db->Query("INSERT INTO {groups} " . "(group_name,group_desc,project_id,manage_project,view_tasks, view_groups_tasks, view_own_tasks,open_new_tasks,add_comments,create_attachments,group_open,view_comments) " . "VALUES('Corporate {$i}', 'Corporate {$i} Users', {$projid}, 0, 0, 1, 1, 1, 1, 1,1,1)");
                $sql = $db->Query('SELECT MAX(group_id) FROM {groups}');
                $group_id = $db->FetchOne($sql);
                // Then, add users
                for ($k = $i; $k <= $maxcorporateusers; $k += $maxcorporates) {
                    $username = "******";
                    $sql = $db->Query('SELECT user_id FROM {users} WHERE user_name = ?', array($username));
                    $user_id = $db->FetchOne($sql);
                    $db->Query('INSERT INTO {users_in_groups} (user_id, group_id) VALUES (?, ?)', array($user_id, $group_id));
                }
            }
        }
    }
    // And also those individual users...
    for ($i = 1; $i <= $maxindividualusers; $i++) {
        $user_name = "iu{$i}";
        $real_name = "Individual user {$i}";
        $password = $user_name;
        $time_zone = 0;
        // Assign different ones!
        $email = null;
        // $user_name . '@example.com';
        $group = rand(11, 12);
        Backend::create_user($user_name, $password, $real_name, '', $email, 0, $time_zone, $group, 1);
    }
    // That's why we need some more global groups with different viewing rights
    // And 100 users just viewing our progress
    for ($i = 1; $i <= $maxindividualusers; $i++) {
        $user_name = "basic{$i}";
        $real_name = "Basic {$i}";
        $password = $user_name;
        $time_zone = 0;
        // Assign different ones!
        $email = null;
        // $user_name . '@example.com';
        $group = 4;
        Backend::create_user($user_name, $password, $real_name, '', $email, 0, $time_zone, $group, 1);
    }
    // But that was not enough for all needed permission, so in practice, every
    // project also has between 1 AND 20 project groups.
    //
    // Must recreate, so rights for new projects get loaded. Otherwise,
    // even first user in database can't create tasks.
    $user = new User(1);
    // And that's why we've got $maxtasks opened within the last 10 years
    for ($i = 1; $i <= $maxtasks; $i++) {
        $project = rand(2, $maxproducts);
        // Find someone who is allowed to open a task, do not use global groups
        $sql = $db->Query("SELECT uig.user_id\n\t\t\tFROM {users_in_groups} uig\n\t\t\tJOIN {groups} g ON g.group_id = uig.group_id AND g.open_new_tasks = 1 AND (g.project_id = 0 OR g.project_id = ?)\n\t\t\tWHERE g.group_id NOT IN (1, 2, 7, 8, 9)\n\t\t\tORDER BY {$RANDOP} LIMIT 1", array($project));
        $reporter = $db->FetchOne($sql);
        $sql = $db->Query("SELECT category_id FROM {list_category}\n\t\t\tWHERE project_id = ?\n\t\t\tAND category_name <> 'root'\n\t\t\tORDER BY {$RANDOP} LIMIT 1", array($project));
        $category = $db->FetchOne($sql);
        $opened = time() - rand(1, 315360000);
        $args = array();
        $args['project_id'] = $project;
        $args['date_opened'] = time() - rand(1, 315360000);
        // 'last_edited_time' => time(),
        $args['opened_by'] = $reporter;
        $args['product_category'] = $category;
        $args['task_severity'] = 1;
        $args['task_priority'] = 1;
        // 'task_type', , 'product_version',
        // 'operating_system', , 'estimated_effort',
        // 'supertask_id',
        $sql = $db->Query("SELECT project_title FROM {projects} WHERE project_id = ?", array($project));
        $projectname = $db->FetchOne($sql);
        $subject = $subjects[rand(0, count($subjects) - 1)];
        $subject = sprintf($subject, $projectname);
        $args['item_summary'] = "Task {$i} ({$subject})";
        // 'detailed_desc'
        // echo $args['item_summary'] . "\r\n";
        $ok = Backend::create_task($args);
        if ($ok === 0) {
            echo "Failed to create task.\r\n";
        } else {
            list($id, $token) = $ok;
            $db->Query('UPDATE {tasks} SET opened_by = ?, date_opened = ? WHERE task_id = ?', array($reporter, $opened, $id));
        }
    }
    # end for maxtasks
    // One task in ten of is unconfirmed, probably just bullshit, not assigned to anyone,
    // and we add just a comment "Cannot reproduce".
    for ($i = 1; $i <= $maxcomments; $i++) {
        $taskid = rand(2, $maxtasks + 1);
        $task = Flyspray::GetTaskDetails($taskid, true);
        $project = $task['project_id'];
        $added = time() - rand(1, 315360000);
        // Find someone who is allowed to add comment, do not use global groups
        $sqltext = "SELECT uig.user_id\n\t\t\tFROM {users_in_groups} uig\n                         JOIN {groups} g ON g.group_id = uig.group_id AND g.add_comments = 1\n                          AND (g.project_id = 0 OR g.project_id = ?)\n                        WHERE g.group_id NOT IN (1, 2, 7, 8, 9)\n                     ORDER BY {$RANDOP} ";
        $sql = $db->Query($sqltext, array($project));
        $row = $db->FetchRow($sql);
        $reporter = new User($row['user_id']);
        // User might still not be able to add a comment, if he can not see the task...
        // Just try again until a suitable one comes out from the query. It will finally.
        // Try to enhance the query also to return fewer unsuitable ones.
        while (!$reporter->can_view_task($task)) {
            $row = $db->FetchRow($sql);
            $reporter = new User($row['user_id']);
        }
        $comment = 'Comment.';
        Backend::add_comment($task, $comment);
        $sql = $db->Query('SELECT MAX(comment_id) FROM {comments}');
        $comment_id = $db->FetchOne($sql);
        $db->Query('UPDATE {comments} SET user_id = ?, date_added = ? WHERE comment_id = ?', array($reporter->id, $added, $comment_id));
    }
    # end for maxcomments
    // And $maxattachments total, either to task or comment
    for ($i = 1; $i <= $maxattachments; $i++) {
        $sql = $db->Query("SELECT comment_id, task_id, user_id, date_added FROM {comments} ORDER BY {$RANDOP} LIMIT 1");
        list($comment_id, $task_id, $user_id, $date_added) = $db->FetchRow($sql);
        $fname = "Attachment {$i}";
        if (rand(1, 100) == 1) {
            $comment_id = 0;
        }
        $origname = getAttachmentDescription() . " {$i}";
        $db->Query("INSERT INTO  {attachments}\n                                     ( task_id, comment_id, file_name,\n                                       file_type, file_size, orig_name,\n                                       added_by, date_added)\n                             VALUES  (?, ?, ?, ?, ?, ?, ?, ?)", array($task_id, $comment_id, $fname, 'application/octet-stream', 1024, $origname, $user_id, $date_added));
    }
    // // But at least we have been able to solve approximately half of the tasks
    // Of course, many of the tasks are somehow related to each other, so add
    // parents, relationships, dependencies, duplicates etc. last.
    // Do this ones last, after creating all the other data.
    // Approximately 200 hundred of our projects are already closed or deleted.
    // Cannot be sure when using random...
    for ($i = 1; $i < 200; $i++) {
    }
    // Some of our developers AND project managers couldn't take all that AND have already left the premises
    // No wonder, because we've got those corporate AND individual users always complaining
    // AND whining, not to speak about our management.
    $db->dbClose();
}
Пример #12
0
require_once '../../scripts/index.php';
$baseurl = dirname(dirname($baseurl)) . '/';
// first, find out about the field we are going to edit
$classnames = explode(' ', Post::val('classname'));
$field = '';
foreach ($classnames as $name) {
    if (substr($name, 0, 5) == 'task_') {
        $field = Filters::noXSS(substr($name, 5));
    }
}
// spare unnecessary queries
if (!$field) {
    header('HTTP/1.1 400 Bad Request');
    exit;
}
$task = Flyspray::GetTaskDetails(Post::val('task_id'));
// we better not forget this one ;)
if (!$user->can_edit_task($task)) {
    header('HTTP/1.1 400 Bad Request');
    exit;
}
// pre build some HTML
$task['num_assigned'] = count($task['assigned_to']);
$task['assigned_to_name'] = reset($task['assigned_to_name']);
$prev = Filters::noXSS(str_replace("'", "\\'", tpl_draw_cell($task, $field, '<span class="%s %s">%s</span>')));
$id = sprintf('id="task%d_%s" name="task%d_%s"', $task['task_id'], $field, $task['task_id'], $field);
switch ($field) {
    case 'summary':
        echo '<input type="text" class="text" ' . $id . ' value="' . Filters::noXSS($task['item_summary']) . '" />';
        break;
    case 'project':
Пример #13
0
 /**
  * is_accessible 
  * 
  * @access public
  * @return bool
  */
 function is_accessible()
 {
     global $user;
     return ($this->task = Flyspray::GetTaskDetails(Get::num('task_id'))) && $user->can_view_task($this->task);
 }
Пример #14
0
function tpl_tasklink($task, $text = null, $strict = false, $attrs = array(), $title = array('state', 'summary', 'percent_complete'))
{
    global $user;
    $params = array();
    if (!is_array($task)) {
        $task = Flyspray::GetTaskDetails(Flyspray::GetTaskId($task), true);
    }
    if ($strict === true && (!is_object($user) || !$user->can_view_task($task))) {
        return '';
    }
    if (is_object($user) && $user->can_view_task($task)) {
        $summary = utf8_substr($task['item_summary'], 0, 64);
    } else {
        $summary = L('taskmadeprivate');
    }
    if (is_null($text)) {
        $text = sprintf('%s#%d - %s', $task['project_prefix'], $task['prefix_id'], Filters::noXSS($summary));
    } elseif (is_string($text)) {
        $text = Filters::noXSS(utf8_substr($text, 0, 64));
    } else {
        //we can't handle non-string stuff here.
        return '';
    }
    if (!$task['task_id']) {
        return $text;
    }
    $title_text = array();
    foreach ($title as $info) {
        switch ($info) {
            case 'state':
                if ($task['is_closed']) {
                    $title_text[] = L('closed');
                    $attrs['class'] = 'closedtasklink';
                } elseif ($task['closed_by']) {
                    $title_text[] = L('reopened');
                } else {
                    $title_text[] = L('open');
                }
                break;
            case 'summary':
                $title_text[] = $summary;
                break;
            case 'assignedto':
                if (isset($task['assigned_to_name'])) {
                    if (is_array($task['assigned_to_name'])) {
                        $title_text[] = implode(', ', $task['assigned_to_name']);
                    } else {
                        $title_text[] = $task['assigned_to_name'];
                    }
                }
                break;
            case 'percent_complete':
                $title_text[] = $task['percent_complete'] . '%';
                break;
            case 'age':
                $title_text[] = formatDate($task['date_opened']);
                break;
                // ... more options if necessary
        }
    }
    $title_text = implode(' | ', $title_text);
    $params = $_GET;
    unset($params['do'], $params['action'], $params['task_id'], $params['switch']);
    $url = Filters::noXSS(FSTpl::relativeUrl(CreateURL(array('details', 'task' . $task['task_id']), $params)));
    $title_text = Filters::noXSS($title_text);
    $link = sprintf('<a href="%s" title="%s" %s>%s</a>', $url, $title_text, join_attrs($attrs), $text);
    if ($task['is_closed']) {
        $link = '<del>&#160;' . $link . '&#160;</del>';
    }
    return $link;
}
Пример #15
0
 function Address($task_id, $type)
 {
     global $db, $fs, $proj, $user;
     $users = array();
     $jabber_users = array();
     $email_users = array();
     $task_details = Flyspray::GetTaskDetails($task_id);
     // Get list of users from the notification tab
     $get_users = $db->Query('SELECT *
                            FROM {notifications} n
                            LEFT JOIN {users} u ON n.user_id = u.user_id
                            WHERE n.task_id = ?', array($task_id));
     while ($row = $db->FetchRow($get_users)) {
         if ($row['user_id'] == $user->id && !$user->infos['notify_own']) {
             continue;
         }
         if ($fs->prefs['user_notify'] == '1' && ($row['notify_type'] == NOTIFY_EMAIL || $row['notify_type'] == NOTIFY_BOTH) || $fs->prefs['user_notify'] == '2') {
             array_push($email_users, $row['email_address']);
         }
         if ($fs->prefs['user_notify'] == '1' && ($row['notify_type'] == NOTIFY_JABBER || $row['notify_type'] == NOTIFY_BOTH) || $fs->prefs['user_notify'] == '3') {
             array_push($jabber_users, $row['jabber_id']);
         }
     }
     // Get list of assignees
     $get_users = $db->Query('SELECT *
                            FROM {assigned} a
                            LEFT JOIN {users} u ON a.user_id = u.user_id
                            WHERE a.task_id = ?', array($task_id));
     while ($row = $db->FetchRow($get_users)) {
         if ($row['user_id'] == $user->id && !$user->infos['notify_own']) {
             continue;
         }
         if ($fs->prefs['user_notify'] == '1' && ($row['notify_type'] == NOTIFY_EMAIL || $row['notify_type'] == NOTIFY_BOTH) || $fs->prefs['user_notify'] == '2') {
             array_push($email_users, $row['email_address']);
         }
         if ($fs->prefs['user_notify'] == '1' && ($row['notify_type'] == NOTIFY_JABBER || $row['notify_type'] == NOTIFY_BOTH) || $fs->prefs['user_notify'] == '3') {
             array_push($jabber_users, $row['jabber_id']);
         }
     }
     // Now, we add the project contact addresses...
     // ...but only if the task is public
     if ($task_details['mark_private'] != '1' && in_array($type, Flyspray::int_explode(' ', $proj->prefs['notify_types']))) {
         $proj_emails = preg_split('/[\\s,;]+/', $proj->prefs['notify_email'], -1, PREG_SPLIT_NO_EMPTY);
         $proj_jids = explode(',', $proj->prefs['notify_jabber']);
         foreach ($proj_emails as $key => $val) {
             if (!empty($val) && !in_array($val, $email_users)) {
                 array_push($email_users, $val);
             }
         }
         foreach ($proj_jids as $key => $val) {
             if (!empty($val) && !in_array($val, $jabber_users)) {
                 array_push($jabber_users, $val);
             }
         }
         // End of checking if a task is private
     }
     // Send back two arrays containing the notification addresses
     return array($email_users, array_unique($jabber_users));
 }
Пример #16
0
<?php

/*************************************************************\
  | Details a task (and edit it)                                |
  | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~                                |
  | This script displays task details when in view mode,        |
  | and allows the user to edit task details when in edit mode. |
  | It also shows comments, attachments, notifications etc.     |
  \*************************************************************/
if (!defined('IN_FS')) {
    die('Do not access this file directly.');
}
$task_id = Req::num('task_id');
if (!($task_details = Flyspray::GetTaskDetails($task_id))) {
    Flyspray::show_error(10);
}
if (!$user->can_view_task($task_details)) {
    Flyspray::show_error($user->isAnon() ? 102 : 101, false);
} else {
    require_once BASEDIR . '/includes/events.inc.php';
    if ($proj->prefs['use_effort_tracking']) {
        require_once BASEDIR . '/includes/class.effort.php';
        $effort = new effort($task_id, $user->id);
        $effort->populateDetails();
        $page->assign('effort', $effort);
    }
    $page->uses('task_details');
    // Send user variables to the template
    $page->assign('assigned_users', $task_details['assigned_to']);
    $page->assign('old_assigned', implode(' ', $task_details['assigned_to']));
    $page->assign('tags', $task_details['tags']);
Пример #17
0
    function Address($task_id, $type)
    {
        global $db, $fs, $proj, $user;
        $users = array();
        $emails = array();
        $jabbers = array();
        $onlines = array();
        $task_details = Flyspray::GetTaskDetails($task_id);
        // Get list of users from the notification tab
        // Decision: If a notification-user have the limited-flag set, only
        // task-relevant messages should be send to him
        if ($type > 4) {
            $limitedStr = " AND n.limited = 0";
        } else {
            $limitedStr = "";
        }
        $get_users = $db->Query('
			SELECT * FROM {notifications} n
			LEFT JOIN {users} u ON n.user_id = u.user_id
			WHERE n.task_id = ? ' . $limitedStr, array($task_id));
        self::AssignRecipients($db->FetchAllArray($get_users), $emails, $jabbers, $onlines);
        // Get list of assignees
        $get_users = $db->Query('
			SELECT * FROM {assigned} a
			LEFT JOIN {users} u ON a.user_id = u.user_id
			WHERE a.task_id = ?', array($task_id));
        self::AssignRecipients($db->FetchAllArray($get_users), $emails, $jabbers, $onlines);
        // Now, we add the project contact addresses...
        // ...but only if the task is public
        if ($task_details['mark_private'] != '1' && in_array($type, Flyspray::int_explode(' ', $proj->prefs['notify_types']))) {
            // FIXME! Have to find users preferred language here too,
            // must fetch from database. But the address could also be a mailing
            // list address and user not exist in database, use fs->prefs in that case,
            $proj_emails = preg_split('/[\\s,;]+/', $proj->prefs['notify_email'], -1, PREG_SPLIT_NO_EMPTY);
            $desired = implode("','", $proj_emails);
            if ($desired != '') {
                $get_users = $db->Query("\n\t\t\t\t\tSELECT DISTINCT u.user_id, u.email_address, u.jabber_id,\n\t\t\t\t\tu.notify_online, u.notify_type, u.notify_own, u.lang_code\n\t\t\t\t\tFROM {users} u\n\t\t\t\t\tWHERE u.email_address IN ('{$desired}')");
                self::AssignRecipients($db->FetchAllArray($get_users), $emails, $jabbers, $onlines);
            }
            $proj_jids = explode(',', $proj->prefs['notify_jabber']);
            $desired = implode("','", $proj_jids);
            if ($desired != '') {
                $get_users = $db->Query("\n\t\t\t\t\tSELECT DISTINCT u.user_id, u.email_address, u.jabber_id,\n\t\t\t\t\tu.notify_online, u.notify_type, u.notify_own, u.lang_code\n\t\t\t\t\tFROM {users} u\n\t\t\t\t\tWHERE u.jabber_id IN ('{$desired}')");
                self::AssignRecipients($db->FetchAllArray($get_users), $emails, $jabbers, $onlines);
            }
            // Now, handle notification addresses that are not assigned to any user...
            foreach ($proj_emails as $email) {
                if (!array_key_exists($email, $emails)) {
                    $emails[$email] = array('recipient' => $email, 'lang' => $fs->prefs['lang_code']);
                }
            }
            foreach ($proj_jids as $jabber) {
                if (!array_key_exists($jabber, $jabbers)) {
                    $jabbers[$jabber] = array('recipient' => $jabber, 'lang' => $fs->prefs['lang_code']);
                }
            }
            /*
            echo "<pre>";
            echo var_dump($proj_emails);
            echo var_dump($proj_jids);
            echo "</pre>";
            */
            // End of checking if a task is private
        }
        // Send back three arrays containing the notification addresses
        return array($emails, $jabbers, $onlines);
    }
Пример #18
0
                                     VALUES  (?, ?)', array($id, $assignee));
                            }
                        }
                    }
                }
                // set success message
                $_SESSION['SUCCESS'] = L('tasksupdated');
                break;
            } else {
                if (!Post::val('resolution_reason')) {
                    Flyspray::show_error(L('noclosereason'));
                    break;
                }
                $task_ids = Post::val('ids');
                foreach ($task_ids as $task_id) {
                    $task = Flyspray::GetTaskDetails($task_id);
                    if (!$user->can_close_task($task)) {
                        continue;
                    }
                    if ($task['is_closed']) {
                        continue;
                    }
                    Backend::close_task($task_id, Post::val('resolution_reason'), Post::val('closure_comment', ''), Post::val('mark100', false));
                }
                $_SESSION['SUCCESS'] = L('taskclosedmsg');
                break;
            }
        } else {
            Flyspray::show_error(L('massopsdisabled'));
        }
}
Пример #19
0
              WHERE  task_id = ?', array(Post::val('project_id'), Post::val('task_type'), Post::val('item_summary'), Post::val('detailed_desc'), Post::val('item_status'), intval($user->can_change_private($task) && Post::val('mark_private')), Post::val('product_category'), Post::val('closedby_version', 0), Post::val('operating_system'), Post::val('task_severity'), Post::val('task_priority'), intval($user->id), $time, intval($due_date), Post::val('percent_complete'), Post::val('reportedver'), $task['task_id']));
 // Update the list of users assigned this task
 $assignees = (array) Post::val('rassigned_to');
 $assignees_changed = count(array_diff($task['assigned_to'], $assignees)) + count(array_diff($assignees, $task['assigned_to']));
 if ($user->perms('edit_assignments') && $assignees_changed) {
     // Delete the current assignees for this task
     $db->Query('DELETE FROM {assigned}
                       WHERE task_id = ?', array($task['task_id']));
     // Convert assigned_to and store them in the 'assigned' table
     foreach ((array) Post::val('rassigned_to') as $key => $val) {
         $db->Replace('{assigned}', array('user_id' => $val, 'task_id' => $task['task_id']), array('user_id', 'task_id'));
     }
 }
 // Get the details of the task we just updated
 // To generate the changed-task message
 $new_details_full = Flyspray::GetTaskDetails($task['task_id']);
 // Not very nice...maybe combine compare_tasks() and logEvent() ?
 $result = $db->Query("SELECT * FROM {tasks} WHERE task_id = ?", array($task['task_id']));
 $new_details = $db->FetchRow($result);
 foreach ($new_details as $key => $val) {
     if (strstr($key, 'last_edited_') || $key == 'assigned_to' || is_numeric($key)) {
         continue;
     }
     if ($val != $task[$key]) {
         // Log the changed fields in the task history
         Flyspray::logEvent($task['task_id'], 3, $val, $task[$key], $key, $time);
     }
 }
 $changes = Flyspray::compare_tasks($task, $new_details_full);
 if (count($changes) > 0) {
     $notify->Create(NOTIFY_TASK_CHANGED, $task['task_id'], $changes);
Пример #20
0
 /**
  * Closes a task
  * @param integer $task_id
  * @param integer $reason
  * @param string $comment
  * @param bool $mark100
  * @access public
  * @return bool
  * @version 1.0
  */
 public static function close_task($task_id, $reason, $comment, $mark100 = true)
 {
     global $db, $notify, $user, $proj;
     $task = Flyspray::GetTaskDetails($task_id);
     if (!$user->can_close_task($task)) {
         return false;
     }
     if ($task['is_closed']) {
         return false;
     }
     $db->Query('UPDATE  {tasks}
                    SET  date_closed = ?, closed_by = ?, closure_comment = ?,
                         is_closed = 1, resolution_reason = ?, last_edited_time = ?,
                         last_edited_by = ?
                  WHERE  task_id = ?', array(time(), $user->id, $comment, $reason, time(), $user->id, $task_id));
     if ($mark100) {
         $db->Query('UPDATE {tasks} SET percent_complete = 100 WHERE task_id = ?', array($task_id));
         Flyspray::logEvent($task_id, 3, 100, $task['percent_complete'], 'percent_complete');
     }
     $notify->Create(NOTIFY_TASK_CLOSED, $task_id, null, null, NOTIFY_BOTH, $proj->prefs['lang_code']);
     Flyspray::logEvent($task_id, 2, $reason, $comment);
     // If there's an admin request related to this, close it
     $db->Query('UPDATE  {admin_requests}
                    SET  resolved_by = ?, time_resolved = ?
                  WHERE  task_id = ? AND request_type = ?', array($user->id, time(), $task_id, 1));
     // duplicate
     if ($reason == 6) {
         preg_match("/\\b(?:FS#|bug )(\\d+)\\b/", $comment, $dupe_of);
         if (count($dupe_of) >= 2) {
             $existing = $db->Query('SELECT * FROM {related} WHERE this_task = ? AND related_task = ? AND is_duplicate = 1', array($task_id, $dupe_of[1]));
             if ($existing && $db->CountRows($existing) == 0) {
                 $db->Query('INSERT INTO {related} (this_task, related_task, is_duplicate) VALUES(?, ?, 1)', array($task_id, $dupe_of[1]));
             }
             Backend::add_vote($task['opened_by'], $dupe_of[1]);
         }
     }
     return true;
 }
Пример #21
0
function createTestData()
{
    # quick safety
    exit;
    if (PHP_SAPI !== 'cli') {
        die('');
    }
    // Use this only on a new test installation, code does not work on
    // an existing one, and never will.
    // Borg Inc. is a big multinational company delivering
    $maxproducts = 50;
    // both to it's
    $maxcorporateusers = 450;
    // working in
    $maxcorporates = 50;
    // and
    $maxindividualusers = 10;
    // who are all happy to report to us about
    $maxtasks = 150;
    // the many problems in our products. And then there are also
    $maxviewers = 50;
    // who just like to watch what's going on here at Borg Inc.
    // Our users are also keen to add attachments to their reports and comments, so there are
    $maxattachments = 500;
    // in our database;
    // Our users are also very active with commenting.
    $maxcomments = 750;
    // To handle all the resulting work, we need
    $maxadmins = 3;
    $maxmanagers = 5;
    $maxdevelopers = 50;
    // people working together all over the globe to care for their needs.
    // We also have both a very innovative and standardized naming scheme for our products.
    // And we have also made one big invention offered only to our customers in the world:
    // Time travel! You can comment on tasks and other comments in them even before the task
    // is even opened or the original comment made.
    // Add more according to your taste...
    $subjects[] = "%s sucks!";
    $subjects[] = "%s is utterly crap!";
    $subjects[] = "Developers of %s should be hanged!";
    $subjects[] = "Developers of %s should be strangled!";
    $subjects[] = "Developers of %s should be eaten alive by zombies!";
    $subjects[] = "Developers of %s should be thrown in a pit of snakes!";
    $subjects[] = "Who is the idiot responsible for %s?";
    error_reporting(E_ALL);
    // die('Enable me by commenting this out by editing and read the contents first!'.basename(__FILE__).' at line '.__LINE__);
    define('IN_FS', 1);
    require_once dirname(__FILE__) . '/../includes/fix.inc.php';
    require_once dirname(__FILE__) . '/../includes/class.flyspray.php';
    require_once dirname(__FILE__) . '/../includes/constants.inc.php';
    require_once dirname(__FILE__) . '/../includes/i18n.inc.php';
    require_once dirname(__FILE__) . '/../includes/class.tpl.php';
    require_once dirname(__FILE__) . '/../vendor/autoload.php';
    $conf = @parse_ini_file('../flyspray.conf.php', true) or die('Cannot open config file.');
    $db = new Database();
    $db->dbOpenFast($conf['database']);
    $RANDOP = 'RAND()';
    if ($db->dblink->dataProvider == 'postgres') {
        $RANDOP = 'RANDOM()';
    }
    $fs = new Flyspray();
    $user = new User(1);
    $proj = new Project(1);
    $notify = new Notifications();
    load_translations();
    for ($i = 1; $i <= $maxadmins; $i++) {
        $user_name = "admin{$i}";
        $real_name = "Administrator {$i}";
        $password = $user_name;
        $time_zone = 0;
        // Assign different one!
        $email = null;
        // $user_name . '@foo.bar.baz.org';
        Backend::create_user($user_name, $password, $real_name, '', $email, 0, $time_zone, 1, 1);
    }
    for ($i = 1; $i <= $maxmanagers; $i++) {
        $user_name = "pm{$i}";
        $real_name = "Project Manager {$i}";
        $password = $user_name;
        $time_zone = 0;
        // Assign different one!
        $email = null;
        // $user_name . '@foo.bar.baz.org';
        Backend::create_user($user_name, $password, $real_name, '', $email, 0, $time_zone, 2, 1);
    }
    $db->Query('UPDATE {projects} SET project_is_active = 0 WHERE project_id = 1');
    // Show more columns by default, trying to make database or flyspray crash under stress.
    $db->Query("UPDATE {prefs} SET pref_value = 'id project category tasktype severity summary status openedby dateopened progress comments attachments votes' WHERE pref_name = 'visible_columns'");
    // Add 3 different Global developer groups with different
    // view rights first, then assign developers to them at random.
    // Borg Inc. has a strict hierarchy on who can see and do what.
    // Somewhat more relaxed with our own developers.
    $db->Query("INSERT INTO {groups} " . "(group_name,group_desc,project_id,group_open,view_comments,manage_project,view_tasks, view_groups_tasks, view_own_tasks,open_new_tasks,modify_own_tasks) " . "VALUES('Developer Group 1', 'Developer Group 1', 0, 1, 1, 0, 1, 1, 1, 1, 1)");
    $db->Query("INSERT INTO {groups} " . "(group_name,group_desc,project_id,group_open,view_comments,manage_project,view_tasks, view_groups_tasks, view_own_tasks,open_new_tasks,modify_own_tasks) " . "VALUES('Developer Group 2', 'Developer Group 2', 0, 1, 1, 0, 0, 1, 1, 1, 1)");
    $db->Query("INSERT INTO {groups} " . "(group_name,group_desc,project_id,group_open,view_comments,manage_project,view_tasks, view_groups_tasks, view_own_tasks,open_new_tasks,modify_own_tasks) " . "VALUES('Developer Group 3', 'Developer Group 3', 0, 1, 1, 0, 0, 0, 1, 1, 1)");
    // Add also general groups for corporate users, individual users and viewers.
    // Allow only login. Not so relaxed with them bastards.
    $db->Query("INSERT INTO {groups} " . "(group_name,group_desc,project_id,group_open) " . "VALUES('Corporate Users', 'Corporate Users', 0, 1)");
    $db->Query("INSERT INTO {groups} " . "(group_name,group_desc,project_id,group_open) " . "VALUES('Trusted Users', 'Trusted Users', 0, 1)");
    $db->Query("INSERT INTO {groups} " . "(group_name,group_desc,project_id,group_open) " . "VALUES('Non-trusted Users', 'Non-trusted Users', 0, 1)");
    for ($i = 1; $i <= $maxdevelopers; $i++) {
        $user_name = "dev{$i}";
        $real_name = "Developer {$i}";
        $password = $user_name;
        $time_zone = 0;
        // Assign different one!
        $email = $email = null;
        $user_name . '@foo.bar.baz.org';
        $group = rand(7, 9);
        Backend::create_user($user_name, $password, $real_name, '', $email, 0, $time_zone, $group, 1);
    }
    // We have been really active in the past years, AND have a lot of projects.
    for ($i = 1; $i <= $maxproducts; $i++) {
        $projname = strtoupper(substr(md5(uniqid(mt_rand(), true)), 0, mt_rand(8, 12)));
        $projname = 'Borg Inc. Product ' . preg_replace('/^(.{3})(.+)$/', '$1-$2', $projname);
        $db->Query('INSERT INTO  {projects}
      ( project_title, theme_style, intro_message,
      others_view, anon_open, project_is_active,
      visible_columns, visible_fields, lang_code,
      notify_email, notify_jabber, disp_intro)
      VALUES  (?, ?, ?, ?, ?, 1, ?, ?, ?, ?, ?, ?)', array($projname, 'CleanFS', "Welcome to {$projname}", 0, 0, 'id category tasktype severity summary status openedby dateopened progress comments attachments votes', 'supertask tasktype category severity priority status private assignedto reportedin dueversion duedate progress os votes', 'en', '', '', 1));
        add_project_data();
    }
    // Assign some of the poor developers project manager or project developer
    // rights to some of the projects they must work on.
    for ($i = 1; $i <= $maxproducts; $i++) {
        $projid = $i + 1;
        $sql = $db->Query('SELECT group_id FROM {groups} WHERE project_id = ? AND manage_project = 1', array($projid));
        $pmgroup = $db->FetchOne($sql);
        $sql = $db->Query('SELECT group_id FROM {groups} WHERE project_id = ? AND manage_project = 0', array($projid));
        $pdgroup = $db->FetchOne($sql);
        $pmlimit = intval($maxdevelopers / 100) + rand(-2, 2);
        $pdlimit = intval($maxdevelopers / 20) + rand(-10, 10);
        $pmlimit = $pmlimit < 1 ? 1 : $pmlimit;
        $pdlimit = $pdlimit < 1 ? 1 : $pdlimit;
        $sql = $db->Query("SELECT user_id FROM {users_in_groups} WHERE group_id in (7, 8, 9) ORDER BY {$RANDOP} limit {$pmlimit}");
        $pms = $db->fetchCol($sql);
        $sql = $db->Query("SELECT user_id FROM {users_in_groups} WHERE group_id in (8, 9) ORDER BY {$RANDOP} limit {$pdlimit}");
        $pds = $db->fetchCol($sql);
        foreach ($pms as $pm) {
            $db->Query('INSERT INTO {users_in_groups} (user_id, group_id) values (?, ?)', array($pm, $pmgroup));
        }
        foreach ($pds as $pd) {
            $check = $db->Query('SELECT * FROM {users_in_groups} WHERE user_id = ? AND group_id = ?', array($pd, $pmgroup));
            if (!$db->CountRows($check)) {
                $db->Query('INSERT INTO {users_in_groups} (user_id, group_id) values (?, ?)', array($pd, $pdgroup));
            }
        }
    }
    // Create corporate users.
    for ($i = 1; $i <= $maxcorporateusers; $i++) {
        $user_name = "cu{$i}";
        $real_name = "Corporate user {$i}";
        $password = $user_name;
        $time_zone = 0;
        // Assign different ones!
        $email = $email = null;
        $user_name . '@foo.bar.baz.org';
        $group = 10;
        Backend::create_user($user_name, $password, $real_name, '', $email, 0, $time_zone, $group, 1);
    }
    // Now, create corporate user groups for some of our projects.
    // Just %5 change of getting added.
    for ($i = 1; $i <= $maxcorporates; $i++) {
        for ($j = 1; $j <= $maxproducts; $j++) {
            if (rand(1, 20) == 1) {
                $projid = $j + 1;
                $db->Query("INSERT INTO {groups} " . "(group_name,group_desc,project_id,manage_project,view_tasks, view_groups_tasks, view_own_tasks,open_new_tasks,add_comments,create_attachments,group_open,view_comments) " . "VALUES('Corporate {$i}', 'Corporate {$i} Users', {$projid}, 0, 0, 1, 1, 1, 1, 1,1,1)");
                $sql = $db->Query('SELECT MAX(group_id) FROM {groups}');
                $group_id = $db->FetchOne($sql);
                // Then, add users
                for ($k = $i; $k <= $maxcorporateusers; $k += $maxcorporates) {
                    $username = "******";
                    $sql = $db->Query('SELECT user_id FROM {users} WHERE user_name = ?', array($username));
                    $user_id = $db->FetchOne($sql);
                    $db->Query('INSERT INTO {users_in_groups} (user_id, group_id) VALUES (?, ?)', array($user_id, $group_id));
                }
            }
        }
    }
    // And also those individual users...
    for ($i = 1; $i <= $maxindividualusers; $i++) {
        $user_name = "iu{$i}";
        $real_name = "Individual user {$i}";
        $password = $user_name;
        $time_zone = 0;
        // Assign different ones!
        $email = $email = null;
        $user_name . '@foo.bar.baz.org';
        $group = rand(11, 12);
        Backend::create_user($user_name, $password, $real_name, '', $email, 0, $time_zone, $group, 1);
    }
    // That's why we need some more global groups with different viewing rights
    // And 100000 users just viewing our progress
    for ($i = 1; $i <= $maxindividualusers; $i++) {
        $user_name = "basic{$i}";
        $real_name = "Basic {$i}";
        $password = $user_name;
        $time_zone = 0;
        // Assign different ones!
        $email = $email = null;
        $user_name . '@foo.bar.baz.org';
        $group = 4;
        Backend::create_user($user_name, $password, $real_name, '', $email, 0, $time_zone, $group, 1);
    }
    // But that was not enough for all needed permission, so in practice, every
    // project also has between 1 AND 20 project groups.
    //
    // Must recreate, so rights for new projects get loaded. Otherwise,
    // even first user in database can't create tasks.
    $user = new User(1);
    // And that's why we've got 1000000 tasks opened within the last 10 years
    for ($i = 1; $i <= $maxtasks; $i++) {
        $project = rand(2, $maxproducts);
        // Find someone who is allowed to open a task, do not use global groups
        $sql = $db->Query("SELECT uig.user_id\n                         FROM {users_in_groups} uig\n                         JOIN {groups} g ON g.group_id = uig.group_id AND g.open_new_tasks = 1\n                          AND (g.project_id = 0 OR g.project_id = ?)\n                        WHERE g.group_id NOT IN (1, 2, 7, 8, 9)\n                     ORDER BY {$RANDOP} LIMIT 1", array($project));
        $reporter = $db->FetchOne($sql);
        $sql = $db->Query("SELECT category_id FROM {list_category} WHERE project_id = ? AND category_name <> 'root' ORDER BY {$RANDOP} LIMIT 1", array($project));
        $category = $db->FetchOne($sql);
        $opened = time() - rand(1, 315360000);
        $args = array();
        $args['project_id'] = $project;
        $args['date_opened'] = time() - rand(1, 315360000);
        // 'last_edited_time' => time(),
        $args['opened_by'] = $reporter;
        $args['product_category'] = $category;
        $args['task_severity'] = 1;
        $args['task_priority'] = 1;
        // 'task_type', , 'product_version',
        // 'operating_system', , 'estimated_effort',
        // 'supertask_id',
        $sql = $db->Query("SELECT project_title FROM {projects} WHERE project_id = ?", array($project));
        $projectname = $db->FetchOne($sql);
        $subject = $subjects[rand(0, count($subjects) - 1)];
        $subject = sprintf($subject, $projectname);
        $args['item_summary'] = "Task {$i} ({$subject})";
        // 'detailed_desc'
        // echo $args['item_summary'] . "\r\n";
        $ok = Backend::create_task($args);
        if ($ok === 0) {
            echo "Failed to create task.\r\n";
        } else {
            list($id, $token) = $ok;
            $db->Query('UPDATE {tasks} SET opened_by = ?, date_opened = ? WHERE task_id = ?', array($reporter, $opened, $id));
        }
    }
    // One task in ten of is unconfirmed, probably just bullshit, not assigned to anyone,
    // and we add just a comment "Cannot reproduce".
    for ($i = 1; $i <= $maxcomments; $i++) {
        $taskid = rand(2, $maxtasks + 1);
        $task = Flyspray::GetTaskDetails($taskid, true);
        $project = $task['project_id'];
        $added = time() - rand(1, 315360000);
        // Find someone who is allowed to add comment, do not use global groups
        $sqltext = "SELECT uig.user_id\n                         FROM {users_in_groups} uig\n                         JOIN {groups} g ON g.group_id = uig.group_id AND g.add_comments = 1\n                          AND (g.project_id = 0 OR g.project_id = ?)\n                        WHERE g.group_id NOT IN (1, 2, 7, 8, 9)\n                     ORDER BY {$RANDOP} ";
        $sql = $db->Query($sqltext, array($project));
        $row = $db->FetchRow($sql);
        $reporter = new User($row['user_id']);
        // User might still not be able to add a comment, if he can not see the task...
        // Just try again until a suitable one comes out from the query. It will finally.
        // Try to enhance the query also to return fewer unsuitable ones.
        while (!$reporter->can_view_task($task)) {
            $row = $db->FetchRow($sql);
            $reporter = new User($row['user_id']);
        }
        $comment = 'Comment.';
        Backend::add_comment($task, $comment);
        $sql = $db->Query('SELECT MAX(comment_id) FROM {comments}');
        $comment_id = $db->FetchOne($sql);
        $db->Query('UPDATE {comments} SET user_id = ?, date_added = ? WHERE comment_id = ?', array($reporter->id, $added, $comment_id));
    }
    // And 5000000 attachments total, either to task or comment
    for ($i = 1; $i <= $maxattachments; $i++) {
        $sql = $db->Query("SELECT comment_id, task_id, user_id, date_added FROM {comments} ORDER BY {$RANDOP} LIMIT 1");
        list($comment_id, $task_id, $user_id, $date_added) = $db->FetchRow($sql);
        $fname = "Attachment {$i}";
        if (rand(1, 100) == 1) {
            $comment_id = 0;
        }
        $origname = GetAttachmentDescription() . " {$i}";
        $db->Query("INSERT INTO  {attachments}\n                                     ( task_id, comment_id, file_name,\n                                       file_type, file_size, orig_name,\n                                       added_by, date_added)\n                             VALUES  (?, ?, ?, ?, ?, ?, ?, ?)", array($task_id, $comment_id, $fname, 'application/octet-stream', 1024, $origname, $user_id, $date_added));
    }
    function GetAttachmentDescription()
    {
        $type = rand(1, 100);
        if ($type > 80 && $type <= 100) {
            return 'Information that might help solve the problem';
        } elseif ($type == 79) {
            return 'Pic of my pet alligator';
        } elseif ($type == 78) {
            return 'Pic of my pet rhinoceros';
        } elseif ($type == 77) {
            return 'Pic of my pet elephant';
        } elseif ($type == 76 || $type == 75) {
            return 'Pic of my pet monkey';
        } elseif ($type == 74 || $type == 73) {
            return 'Pic of my undulate';
        } elseif ($type == 72 || $type == 71) {
            return 'Pic of my goldfish';
        } elseif ($type == 70 || $type == 69) {
            return 'Pic of my pet pig';
        } elseif ($type == 68 || $type == 67) {
            return 'Pic of my pet snake';
        } elseif ($type == 66 || $type == 65) {
            return 'Pic of my pet rat';
        } elseif ($type == 64 || $type == 63) {
            return 'Pic of my pet goat';
        } elseif ($type == 62 || $type == 61) {
            return 'Pic of my pet rabbit';
        } elseif ($type == 60 || $type == 59) {
            return 'Pic of my pet gerbil';
        } elseif ($type == 58 || $type == 57) {
            return 'Pic of my pet hamster';
        } elseif ($type == 56 || $type == 55) {
            return 'Pic of my pet chinchilla';
        } elseif ($type == 54 || $type == 53) {
            return 'Pic of my pet guinea pig';
        } elseif ($type == 52 || $type == 51) {
            return 'Pic of my pet turtle';
        } elseif ($type == 50 || $type == 49) {
            return 'Pic of my pet lizard';
        } elseif ($type == 48 || $type == 47) {
            return 'Pic of my pet frog';
        } elseif ($type == 46 || $type == 45) {
            return 'Pic of my pet tarantula';
        } elseif ($type == 44 || $type == 43) {
            return 'Pic of my pet hermit crab';
        } elseif ($type == 42 || $type == 41) {
            return 'Pic of my pet parrot';
        } elseif ($type >= 40 && $type < 25) {
            return 'Pic of my dog';
        } else {
            return 'Pic of my cat';
        }
    }
    // // But at least we have been able to solve approximately half of the tasks
    // Of course, many of the tasks are somehow related to each other, so add
    // parents, relationships, dependencies, duplicates etc. last.
    // Do this ones last, after creating all the other data.
    // Approximately 200 hundred of our projects are already closed or deleted.
    // Cannot be sure when using random...
    for ($i = 1; $i < 200; $i++) {
    }
    // Some of our developers AND project managers couldn't take all that AND have already left the premises
    // No wonder, because we've got those corporate AND individual users always complaining
    // AND whining, not to speak about our management.
    $db->dbClose();
    function add_project_data()
    {
        global $db;
        $sql = $db->Query('SELECT project_id FROM {projects} ORDER BY project_id DESC', false, 1);
        $pid = $db->fetchOne($sql);
        $cols = array('manage_project', 'view_tasks', 'open_new_tasks', 'modify_own_tasks', 'modify_all_tasks', 'view_comments', 'add_comments', 'edit_comments', 'delete_comments', 'show_as_assignees', 'create_attachments', 'delete_attachments', 'view_history', 'add_votes', 'close_own_tasks', 'close_other_tasks', 'assign_to_self', 'edit_own_comments', 'assign_others_to_self', 'add_to_assignees', 'view_reports', 'group_open', 'view_estimated_effort', 'view_current_effort_done', 'track_effort', 'add_multiple_tasks', 'view_roadmap', 'view_own_tasks', 'view_groups_tasks', 'edit_assignments');
        $args = array_fill(0, count($cols), '1');
        array_unshift($args, 'Project Managers', 'Permission to do anything related to this project.', intval($pid));
        $db->Query("INSERT INTO  {groups}\n                                 ( group_name, group_desc, project_id,\n                                   " . join(',', $cols) . ")\n                         VALUES  ( " . $db->fill_placeholders($cols, 3) . ")", $args);
        // Add 1 project specific developer group too.
        $args = array_fill(1, count($cols) - 1, '1');
        array_unshift($args, 'Project Developers', 'Permission to do almost anything but not manage project.', intval($pid), 0);
        $db->Query("INSERT INTO  {groups}\n                                 ( group_name, group_desc, project_id,\n                                   " . join(',', $cols) . ")\n                         VALUES  ( " . $db->fill_placeholders($cols, 3) . ")", $args);
        $db->Query("INSERT INTO  {list_category}\n                                 ( project_id, category_name,\n                                   show_in_list, category_owner, lft, rgt)\n                         VALUES  ( ?, ?, 1, 0, 1, 4)", array($pid, 'root'));
        $db->Query("INSERT INTO  {list_category}\n                                 ( project_id, category_name,\n                                   show_in_list, category_owner, lft, rgt )\n                         VALUES  ( ?, ?, 1, 0, 2, 3)", array($pid, 'Backend / Core'));
        // We develop software for a lot of operating systems.
        // Add your favorite ones to the end so we get more data.
        $os = 1;
        $db->Query("INSERT INTO  {list_os}\n                                 ( project_id, os_name, list_position, show_in_list )\n                         VALUES  (?, ?, ?, 1)", array($pid, 'All', $os++));
        $db->Query("INSERT INTO  {list_os}\n                                 ( project_id, os_name, list_position, show_in_list )\n                         VALUES  (?, ?, ?, 1)", array($pid, 'Windows 3.0', $os++));
        $db->Query("INSERT INTO  {list_os}\n                                 ( project_id, os_name, list_position, show_in_list )\n                         VALUES  (?, ?, ?, 1)", array($pid, 'Windows 3.1', $os++));
        $db->Query("INSERT INTO  {list_os}\n                                 ( project_id, os_name, list_position, show_in_list )\n                         VALUES  (?, ?, ?, 1)", array($pid, 'Windows 3.11', $os++));
        $db->Query("INSERT INTO  {list_os}\n                                 ( project_id, os_name, list_position, show_in_list )\n                         VALUES  (?, ?, ?, 1)", array($pid, 'Windows 95', $os++));
        $db->Query("INSERT INTO  {list_os}\n                                 ( project_id, os_name, list_position, show_in_list )\n                         VALUES  (?, ?, ?, 1)", array($pid, 'Windows ME', $os++));
        $db->Query("INSERT INTO  {list_os}\n                                 ( project_id, os_name, list_position, show_in_list )\n                         VALUES  (?, ?, ?, 1)", array($pid, 'Windows 2000', $os++));
        $db->Query("INSERT INTO  {list_os}\n                                 ( project_id, os_name, list_position, show_in_list )\n                         VALUES  (?, ?, ?, 1)", array($pid, 'Windows XP', $os++));
        $db->Query("INSERT INTO  {list_os}\n                                 ( project_id, os_name, list_position, show_in_list )\n                         VALUES  (?, ?, ?, 1)", array($pid, 'Windows Vista', $os++));
        $db->Query("INSERT INTO  {list_os}\n                                 ( project_id, os_name, list_position, show_in_list )\n                         VALUES  (?, ?, ?, 1)", array($pid, 'Windows 7', $os++));
        $db->Query("INSERT INTO  {list_os}\n                                 ( project_id, os_name, list_position, show_in_list )\n                         VALUES  (?, ?, ?, 1)", array($pid, 'Windows 8', $os++));
        $db->Query("INSERT INTO  {list_os}\n                                 ( project_id, os_name, list_position, show_in_list )\n                         VALUES  (?, ?, ?, 1)", array($pid, 'Windows 8.1', $os++));
        $db->Query("INSERT INTO  {list_os}\n                                 ( project_id, os_name, list_position, show_in_list )\n                         VALUES  (?, ?, ?, 1)", array($pid, 'Windows 10', $os++));
        $db->Query("INSERT INTO  {list_os}\n                                 ( project_id, os_name, list_position, show_in_list )\n                         VALUES  (?, ?, ?, 1)", array($pid, 'OS X 10.0', $os++));
        $db->Query("INSERT INTO  {list_os}\n                                 ( project_id, os_name, list_position, show_in_list )\n                         VALUES  (?, ?, ?, 1)", array($pid, 'OS X 10.1', $os++));
        $db->Query("INSERT INTO  {list_os}\n                                 ( project_id, os_name, list_position, show_in_list )\n                         VALUES  (?, ?, ?, 1)", array($pid, 'OS X 10.2', $os++));
        $db->Query("INSERT INTO  {list_os}\n                                 ( project_id, os_name, list_position, show_in_list )\n                         VALUES  (?, ?, ?, 1)", array($pid, 'OS X 10.3', $os++));
        $db->Query("INSERT INTO  {list_os}\n                                 ( project_id, os_name, list_position, show_in_list )\n                         VALUES  (?, ?, ?, 1)", array($pid, 'OS X 10.4', $os++));
        $db->Query("INSERT INTO  {list_os}\n                                 ( project_id, os_name, list_position, show_in_list )\n                         VALUES  (?, ?, ?, 1)", array($pid, 'OS X 10.5', $os++));
        $db->Query("INSERT INTO  {list_os}\n                                 ( project_id, os_name, list_position, show_in_list )\n                         VALUES  (?, ?, ?, 1)", array($pid, 'OS X 10.6', $os++));
        $db->Query("INSERT INTO  {list_os}\n                                 ( project_id, os_name, list_position, show_in_list )\n                         VALUES  (?, ?, ?, 1)", array($pid, 'OS X 10.7', $os++));
        $db->Query("INSERT INTO  {list_os}\n                                 ( project_id, os_name, list_position, show_in_list )\n                         VALUES  (?, ?, ?, 1)", array($pid, 'Windows Server 2003', $os++));
        $db->Query("INSERT INTO  {list_os}\n                                 ( project_id, os_name, list_position, show_in_list )\n                         VALUES  (?, ?, ?, 1)", array($pid, 'Windows Server 2003 R2', $os++));
        $db->Query("INSERT INTO  {list_os}\n                                 ( project_id, os_name, list_position, show_in_list )\n                         VALUES  (?, ?, ?, 1)", array($pid, 'Windows Server 2008', $os++));
        $db->Query("INSERT INTO  {list_os}\n                                 ( project_id, os_name, list_position, show_in_list )\n                         VALUES  (?, ?, ?, 1)", array($pid, 'Windows Server 2008 R2', $os++));
        $db->Query("INSERT INTO  {list_os}\n                                 ( project_id, os_name, list_position, show_in_list )\n                         VALUES  (?, ?, ?, 1)", array($pid, 'Windows Server 2012', $os++));
        $db->Query("INSERT INTO  {list_os}\n                                 ( project_id, os_name, list_position, show_in_list )\n                         VALUES  (?, ?, ?, 1)", array($pid, 'Windows Server 2012 R2', $os++));
        // We've got also a lot of versions.
        // Never go over 42! It's the universal answer to everything. So in that version,
        // every possible bug is finally solved AND every feature request implemented.
        $totalversions = rand(3, 42);
        $present = rand(1, $totalversions);
        for ($i = 1; $i <= $totalversions; $i++) {
            $tense = $i == $present ? 2 : ($i < $present ? 1 : 3);
            $db->Query("INSERT INTO  {list_version}\n                                 ( project_id, version_name, list_position,\n                                   show_in_list, version_tense )\n                         VALUES  (?, ?, ?, 1, ?)", array($pid, sprintf('%d.0', $i), $i, $tense));
        }
    }
}