예제 #1
0
 /**
  * Adds a new task
  * @param array $args array containing all task properties. unknown properties will be ignored
  * @access public
  * @return integer the task ID on success
  * @version 1.0
  * @notes $args is POST data, bad..bad user..
  */
 public static function create_task($args)
 {
     global $db, $user, $proj;
     if (!isset($args)) {
         return 0;
     }
     // these are the POST variables that the user MUST send, if one of
     // them is missing or if one of them is empty, then we have to abort
     $requiredPostArgs = array('item_summary', 'project_id');
     //modify: made description not required
     foreach ($requiredPostArgs as $required) {
         if (empty($args[$required])) {
             return 0;
         }
     }
     $notify = new Notifications();
     if ($proj->id != $args['project_id']) {
         $proj = new Project($args['project_id']);
     }
     if (!$user->can_open_task($proj)) {
         return 0;
     }
     // first populate map with default values
     $sql_args = array('project_id' => $proj->id, 'date_opened' => time(), 'last_edited_time' => time(), 'opened_by' => intval($user->id), 'percent_complete' => 0, 'mark_private' => 0, 'supertask_id' => 0, 'closedby_version' => 0, 'closure_comment' => '', 'task_priority' => 2, 'due_date' => 0, 'anon_email' => '', 'item_status' => STATUS_UNCONFIRMED);
     // POST variables the user is ALLOWED to provide
     $allowedPostArgs = array('task_type', 'product_category', 'product_version', 'operating_system', 'task_severity', 'estimated_effort', 'supertask_id', 'item_summary', 'detailed_desc');
     // these POST variables the user is only ALLOWED to provide if he got the permissions
     if ($user->perms('modify_all_tasks')) {
         $allowedPostArgs[] = 'closedby_version';
         $allowedPostArgs[] = 'task_priority';
         $allowedPostArgs[] = 'due_date';
         $allowedPostArgs[] = 'item_status';
     }
     if ($user->perms('manage_project')) {
         $allowedPostArgs[] = 'mark_private';
     }
     // now copy all over all POST variables the user is ALLOWED to provide
     // (but only if they are not empty)
     foreach ($allowedPostArgs as $allowed) {
         if (!empty($args[$allowed])) {
             $sql_args[$allowed] = $args[$allowed];
         }
     }
     // Process the due_date
     if (isset($args['due_date']) && ($due_date = $args['due_date']) || ($due_date = 0)) {
         $due_date = Flyspray::strtotime($due_date);
     }
     $sql_params[] = 'mark_private';
     $sql_values[] = intval($user->perms('manage_project') && isset($args['mark_private']) && $args['mark_private'] == '1');
     $sql_params[] = 'due_date';
     $sql_values[] = $due_date;
     $sql_params[] = 'closure_comment';
     $sql_values[] = '';
     // Process estimated effort
     $estimated_effort = 0;
     if ($proj->prefs['use_effort_tracking'] && isset($sql_args['estimated_effort'])) {
         if (($estimated_effort = effort::EditStringToSeconds($sql_args['estimated_effort'], $proj->prefs['hours_per_manday'], $proj->prefs['estimated_effort_format'])) === FALSE) {
             Flyspray::show_error(L('invalideffort'));
             $estimated_effort = 0;
         }
         $sql_args['estimated_effort'] = $estimated_effort;
     }
     // Token for anonymous users
     $token = '';
     if ($user->isAnon()) {
         if (empty($args['anon_email'])) {
             return 0;
         }
         $token = md5(function_exists('openssl_random_pseudo_bytes') ? openssl_random_pseudo_bytes(32) : uniqid(mt_rand(), true));
         $sql_args['task_token'] = $token;
         $sql_args['anon_email'] = $args['anon_email'];
     }
     // ensure all variables are in correct format
     if (!empty($sql_args['due_date'])) {
         $sql_args['due_date'] = Flyspray::strtotime($sql_args['due_date']);
     }
     if (isset($sql_args['mark_private'])) {
         $sql_args['mark_private'] = intval($sql_args['mark_private'] == '1');
     }
     // split keys and values into two separate arrays
     $sql_keys = array();
     $sql_values = array();
     foreach ($sql_args as $key => $value) {
         $sql_keys[] = $key;
         $sql_values[] = $value;
     }
     /*
              * TODO: At least with PostgreSQL, this has caused the sequence to be
              * out of sync with reality. Must be fixed in upgrade process. Check
              * what's the situation with MySQL. (It's fine, it updates the value even
              * if the column was manually adjusted. Remove this whole block later.)
             $result = $db->Query('SELECT  MAX(task_id)+1
                                     FROM  {tasks}');
             $task_id = $db->FetchOne($result);
             $task_id = $task_id ? $task_id : 1;
     */
     //now, $task_id is always the first element of $sql_values
     #array_unshift($sql_keys, 'task_id');
     #array_unshift($sql_values, $task_id);
     $sql_keys_string = join(', ', $sql_keys);
     $sql_placeholder = $db->fill_placeholders($sql_values);
     $result = $db->Query("INSERT INTO {tasks}\n                                ({$sql_keys_string})\n                         VALUES ({$sql_placeholder})", $sql_values);
     $task_id = $db->Insert_ID();
     Backend::upload_links($task_id);
     // create tags
     if (isset($args['tags'])) {
         $tagList = explode(';', $args['tags']);
         $tagList = array_map('strip_tags', $tagList);
         $tagList = array_map('trim', $tagList);
         $tagList = array_unique($tagList);
         # avoid duplicates for inputs like: "tag1;tag1" or "tag1; tag1<p></p>"
         foreach ($tagList as $tag) {
             if ($tag == '') {
                 continue;
             }
             # old tag feature
             #$result2 = $db->Query("INSERT INTO {tags} (task_id, tag) VALUES (?,?)",array($task_id,$tag));
             # new tag feature. let's do it in 2 steps, it is getting too complicated to make it cross database compatible, drawback is possible (rare) race condition (use transaction?)
             $res = $db->Query("SELECT tag_id FROM {list_tag} WHERE (project_id=0 OR project_id=?) AND tag_name LIKE ? ORDER BY project_id", array($proj->id, $tag));
             if ($t = $db->FetchRow($res)) {
                 $tag_id = $t['tag_id'];
             } else {
                 if ($proj->prefs['freetagging'] == 1) {
                     # add to taglist of the project
                     $db->Query("INSERT INTO {list_tag} (project_id,tag_name) VALUES (?,?)", array($proj->id, $tag));
                     $tag_id = $db->Insert_ID();
                 } else {
                     continue;
                 }
             }
             $db->Query("INSERT INTO {task_tag}(task_id,tag_id) VALUES(?,?)", array($task_id, $tag_id));
         }
     }
     // Log the assignments and send notifications to the assignees
     if (isset($args['rassigned_to']) && is_array($args['rassigned_to'])) {
         // Convert assigned_to and store them in the 'assigned' table
         foreach ($args['rassigned_to'] as $val) {
             $db->Replace('{assigned}', array('user_id' => $val, 'task_id' => $task_id), array('user_id', 'task_id'));
         }
         // Log to task history
         Flyspray::logEvent($task_id, 14, implode(' ', $args['rassigned_to']));
         // Notify the new assignees what happened.  This obviously won't happen if the task is now assigned to no-one.
         $notify->Create(NOTIFY_NEW_ASSIGNEE, $task_id, null, $notify->SpecificAddresses($args['rassigned_to']), NOTIFY_BOTH, $proj->prefs['lang_code']);
     }
     // Log that the task was opened
     Flyspray::logEvent($task_id, 1);
     $result = $db->Query('SELECT  *
                             FROM  {list_category}
                            WHERE  category_id = ?', array($args['product_category']));
     $cat_details = $db->FetchRow($result);
     // We need to figure out who is the category owner for this task
     if (!empty($cat_details['category_owner'])) {
         $owner = $cat_details['category_owner'];
     } else {
         // check parent categories
         $result = $db->Query('SELECT  *
                                 FROM  {list_category}
                                WHERE  lft < ? AND rgt > ? AND project_id  = ?
                             ORDER BY  lft DESC', array($cat_details['lft'], $cat_details['rgt'], $cat_details['project_id']));
         while ($row = $db->FetchRow($result)) {
             // If there's a parent category owner, send to them
             if (!empty($row['category_owner'])) {
                 $owner = $row['category_owner'];
                 break;
             }
         }
     }
     if (!isset($owner)) {
         $owner = $proj->prefs['default_cat_owner'];
     }
     if ($owner) {
         if ($proj->prefs['auto_assign'] && ($args['item_status'] == STATUS_UNCONFIRMED || $args['item_status'] == STATUS_NEW)) {
             Backend::add_to_assignees($owner, $task_id, true);
         }
         Backend::add_notification($owner, $task_id, true);
     }
     // Reminder for due_date field
     if (!empty($sql_args['due_date'])) {
         Backend::add_reminder($task_id, L('defaultreminder') . "\n\n" . CreateURL('details', $task_id), 2 * 24 * 60 * 60, time());
     }
     // Create the Notification
     if (Backend::upload_files($task_id)) {
         $notify->Create(NOTIFY_TASK_OPENED, $task_id, 'files', null, NOTIFY_BOTH, $proj->prefs['lang_code']);
     } else {
         $notify->Create(NOTIFY_TASK_OPENED, $task_id, null, null, NOTIFY_BOTH, $proj->prefs['lang_code']);
     }
     // If the reporter wanted to be added to the notification list
     if (isset($args['notifyme']) && $args['notifyme'] == '1' && $user->id != $owner) {
         Backend::add_notification($user->id, $task_id, true);
     }
     if ($user->isAnon()) {
         $anonuser = array();
         $anonuser[$email] = array('recipient' => $args['anon_email'], 'lang' => $fs->prefs['lang_code']);
         $recipients = array($anonuser);
         $notify->Create(NOTIFY_ANON_TASK, $task_id, $token, $recipients, NOTIFY_EMAIL, $proj->prefs['lang_code']);
     }
     return array($task_id, $token);
 }
예제 #2
0
 /**
  * Adds a new task
  * @param array $args array containing all task properties. unknown properties will be ignored
  * @access public
  * @return array(error type, msg, false) or array(task ID, token, true)
  * @version 1.0
  * @notes $args is POST data, bad..bad user..
  */
 function create_task($args)
 {
     global $db, $user, $proj, $fs;
     if ($proj->id != $args['project_id']) {
         $proj = new Project($args['project_id']);
     }
     if (!$user->can_open_task($proj) || count($args) < 3) {
         return array(ERROR_RECOVER, L('missingrequired'), false);
     }
     // check required fields
     if (!(($item_summary = $args['item_summary']) && ($detailed_desc = $args['detailed_desc']))) {
         return array(ERROR_RECOVER, L('summaryanddetails'), false);
     }
     foreach ($proj->fields as $field) {
         if ($field->prefs['value_required'] && !array_get($args, 'field' . $field->id) && !($field->prefs['force_default'] && !$user->perms('modify_all_tasks'))) {
             return array(ERROR_RECOVER, L('missingrequired') . ' (' . $field->prefs['field_name'] . ')', false);
         }
     }
     if ($user->isAnon() && $fs->prefs['use_recaptcha']) {
         include_once BASEDIR . '/includes/external/recaptchalib.php';
         $solution = new reCAPTCHA_Solution();
         $solution->privatekey = $fs->prefs['recaptcha_priv_key'];
         $solution->challenge = Post::val('recaptcha_challenge_field');
         $solution->response = Post::val('recaptcha_response_field');
         $solution->remoteip = $_SERVER['REMOTE_ADDR'];
         if (!$solution->isValid()) {
             return array(ERROR_RECOVER, $solution->error_code, false);
         }
     }
     $sql_values = array(time(), time(), $args['project_id'], $item_summary, $detailed_desc, intval($user->id), 0);
     $sql_params[] = 'mark_private';
     $sql_values[] = isset($args['mark_private']) && $args['mark_private'] == '1';
     $sql_params[] = 'closure_comment';
     $sql_values[] = '';
     $sql_params[] = 'syntax_plugins';
     $plugins = trim(implode(' ', array_get($args, 'detailed_desc_syntax_plugins', array())));
     if (!$plugins) {
         $plugins = $proj->prefs['syntax_plugins'];
     }
     $sql_values[] = $plugins;
     // Token for anonymous users
     $token = '';
     if ($user->isAnon()) {
         $token = md5(uniqid(mt_rand(), true));
         $sql_params[] = 'task_token';
         $sql_values[] = $token;
     }
     $sql_params[] = 'anon_email';
     $sql_values[] = array_get($args, 'anon_email', '');
     $sql_cols = array_merge(array('date_opened', 'last_edited_time', 'project_id', 'item_summary', 'detailed_desc', 'opened_by', 'percent_complete'), $sql_params);
     $db->x->autoExecute('{tasks}', array_combine($sql_cols, $sql_values));
     $task_id = $db->lastInsertID();
     // [RED] Add task to redundancy table (opened by, last_changed_time)
     $db->x->autoExecute('{redundant}', array('task_id' => $task_id, 'last_changed_time' => time(), 'opened_by_real_name' => $user->infos['real_name'], 'opened_by_user_name' => $user->infos['user_name'], 'last_changed_by_real_name' => $user->infos['real_name'], 'last_changed_by_user_name' => $user->infos['user_name']));
     // Per project task ID
     $prefix_id = $db->x->GetOne('SELECT MAX(prefix_id)+1 FROM {tasks} WHERE project_id = ?', null, $proj->id);
     $db->x->execParam('UPDATE {tasks} SET prefix_id = ? WHERE task_id = ?', array($prefix_id, $task_id));
     // Now the custom fields
     if (count($proj->fields)) {
         $stmt = $db->x->autoPrepare('{field_values}', array('task_id', 'field_id', 'field_value'));
         foreach ($proj->fields as $field) {
             $stmt->execute(array($task_id, $field->id, $field->read(array_get($args, 'field' . $field->id, 0))));
         }
         $stmt->free();
     }
     $assignees = array();
     if (isset($args['assigned_to'])) {
         // Prepare assignee list
         $assignees = explode(';', trim($args['assigned_to']));
         $assignees = array_map(array('Flyspray', 'UserNameToId'), $assignees);
         $assignees = array_filter($assignees, create_function('$x', 'return ($x > 0);'));
         // Log the assignments and send notifications to the assignees
         if (count($assignees)) {
             // Convert assigned_to and store them in the 'assigned' table
             foreach ($assignees as $val) {
                 $fields = array('user_id' => array('value' => $val, 'key' => true), 'task_id' => array('value' => $task_id, 'key' => true));
                 $db->Replace('{assigned}', $fields);
             }
             Flyspray::logEvent($task_id, 14, implode(' ', $assignees));
             // Notify the new assignees what happened.  This obviously won't happen if the task is now assigned to no-one.
             Notifications::send($assignees, ADDRESS_USER, NOTIFY_NEW_ASSIGNEE, array('task_id' => $task_id));
         }
     }
     // Log that the task was opened
     Flyspray::logEvent($task_id, 1);
     // find category owners
     $owners = array();
     foreach ($proj->fields as $field) {
         if ($field->prefs['list_type'] != LIST_CATEGORY) {
             continue;
         }
         $cat = $db->x->getRow('SELECT  *
                              FROM  {list_category}
                             WHERE  category_id = ?', null, array_get($args, 'field' . $field->id, 0));
         if ($cat['category_owner']) {
             $owners[] = $cat['category_owner'];
         } else {
             // check parent categories
             $sql = $db->x->getAll('SELECT  *
                                  FROM  {list_category}
                                 WHERE  lft < ? AND rgt > ? AND list_id  = ?
                              ORDER BY  lft DESC', null, array($cat['lft'], $cat['rgt'], $cat['list_id']));
             foreach ($sql as $row) {
                 // If there's a parent category owner, send to them
                 if ($row['category_owner']) {
                     $owners[] = $row['category_owner'];
                     break;
                 }
             }
         }
     }
     // last try...
     if (!count($owners) && $proj->prefs['default_cat_owner']) {
         $owners[] = $proj->prefs['default_cat_owner'];
     }
     if (count($owners)) {
         foreach ($owners as $owner) {
             if ($proj->prefs['auto_assign'] && !in_array($owner, $assignees)) {
                 Backend::add_to_assignees($owner, $task_id, true);
             }
             Backend::add_notification($owner, $task_id, true);
         }
     }
     // Create the Notification
     if (Backend::upload_files($task_id)) {
         Notifications::send($task_id, ADDRESS_TASK, NOTIFY_TASK_OPENED, array('files' => true));
     } else {
         Notifications::send($task_id, ADDRESS_TASK, NOTIFY_TASK_OPENED);
     }
     // If the reporter wanted to be added to the notification list
     if (isset($args['notifyme']) && $args['notifyme'] == '1' && !in_array($user->id, $owners)) {
         Backend::add_notification($user->id, $task_id, true);
     }
     // this is relaxed, if the anonymous email is not valid, just dont bother..
     if ($user->isAnon() && Flyspray::check_email($args['anon_email'])) {
         Notifications::send($args['anon_email'], ADDRESS_EMAIL, NOTIFY_ANON_TASK, array('task_id' => $task_id, 'token' => $token));
     }
     return array($task_id, $token, true);
 }
예제 #3
0
 /**
  * Adds a new task
  * @param array $args array containing all task properties. unknown properties will be ignored
  * @access public
  * @return integer the task ID on success
  * @version 1.0
  * @notes $args is POST data, bad..bad user..
  */
 public static function create_task($args)
 {
     global $db, $user, $proj;
     $notify = new Notifications();
     if ($proj->id != $args['project_id']) {
         $proj = new Project($args['project_id']);
     }
     if (!$user->can_open_task($proj) || count($args) < 3) {
         return 0;
     }
     if (!(($item_summary = $args['item_summary']) && ($detailed_desc = $args['detailed_desc']))) {
         return 0;
     }
     // Some fields can have default values set
     if (!$user->perms('modify_all_tasks')) {
         $args['closedby_version'] = 0;
         $args['task_priority'] = 2;
         $args['due_date'] = 0;
         $args['item_status'] = STATUS_UNCONFIRMED;
     }
     $param_names = array('task_type', 'item_status', 'product_category', 'product_version', 'closedby_version', 'operating_system', 'task_severity', 'task_priority');
     $sql_values = array(time(), time(), $args['project_id'], $item_summary, $detailed_desc, intval($user->id), 0);
     $sql_params = array();
     foreach ($param_names as $param_name) {
         if (isset($args[$param_name])) {
             $sql_params[] = $param_name;
             $sql_values[] = $args[$param_name];
         }
     }
     // Process the due_date
     if (isset($args['due_date']) && ($due_date = $args['due_date']) || ($due_date = 0)) {
         $due_date = Flyspray::strtotime($due_date);
     }
     $sql_params[] = 'mark_private';
     $sql_values[] = intval($user->perms('manage_project') && isset($args['mark_private']) && $args['mark_private'] == '1');
     $sql_params[] = 'due_date';
     $sql_values[] = $due_date;
     $sql_params[] = 'closure_comment';
     $sql_values[] = '';
     // Token for anonymous users
     $token = '';
     if ($user->isAnon()) {
         $token = md5(function_exists('openssl_random_pseudo_bytes') ? openssl_random_pseudo_bytes(32) : uniqid(mt_rand(), true));
         $sql_params[] = 'task_token';
         $sql_values[] = $token;
         $sql_params[] = 'anon_email';
         $sql_values[] = $args['anon_email'];
     } else {
         $sql_params[] = 'anon_email';
         $sql_values[] = '';
     }
     $sql_params = join(', ', $sql_params);
     // +1 for the task_id column;
     $sql_placeholder = $db->fill_placeholders($sql_values, 1);
     $result = $db->Query('SELECT  MAX(task_id)+1
                             FROM  {tasks}');
     $task_id = $db->FetchOne($result);
     $task_id = $task_id ? $task_id : 1;
     //now, $task_id is always the first element of $sql_values
     array_unshift($sql_values, $task_id);
     $result = $db->Query("INSERT INTO  {tasks}\n                                 ( task_id, date_opened, last_edited_time,\n                                   project_id, item_summary,\n                                   detailed_desc, opened_by,\n                                   percent_complete, {$sql_params} )\n                         VALUES  ({$sql_placeholder})", $sql_values);
     // Log the assignments and send notifications to the assignees
     if (isset($args['rassigned_to']) && is_array($args['rassigned_to'])) {
         // Convert assigned_to and store them in the 'assigned' table
         foreach ($args['rassigned_to'] as $val) {
             $db->Replace('{assigned}', array('user_id' => $val, 'task_id' => $task_id), array('user_id', 'task_id'));
         }
         // Log to task history
         Flyspray::logEvent($task_id, 14, implode(' ', $args['rassigned_to']));
         // Notify the new assignees what happened.  This obviously won't happen if the task is now assigned to no-one.
         $notify->Create(NOTIFY_NEW_ASSIGNEE, $task_id, null, $notify->SpecificAddresses($args['rassigned_to']));
     }
     // Log that the task was opened
     Flyspray::logEvent($task_id, 1);
     $result = $db->Query('SELECT  *
                             FROM  {list_category}
                            WHERE  category_id = ?', array($args['product_category']));
     $cat_details = $db->FetchRow($result);
     // We need to figure out who is the category owner for this task
     if (!empty($cat_details['category_owner'])) {
         $owner = $cat_details['category_owner'];
     } else {
         // check parent categories
         $result = $db->Query('SELECT  *
                                 FROM  {list_category}
                                WHERE  lft < ? AND rgt > ? AND project_id  = ?
                             ORDER BY  lft DESC', array($cat_details['lft'], $cat_details['rgt'], $cat_details['project_id']));
         while ($row = $db->FetchRow($result)) {
             // If there's a parent category owner, send to them
             if (!empty($row['category_owner'])) {
                 $owner = $row['category_owner'];
                 break;
             }
         }
     }
     if (!isset($owner)) {
         $owner = $proj->prefs['default_cat_owner'];
     }
     if ($owner) {
         if ($proj->prefs['auto_assign'] && ($args['item_status'] == STATUS_UNCONFIRMED || $args['item_status'] == STATUS_NEW)) {
             Backend::add_to_assignees($owner, $task_id, true);
         }
         Backend::add_notification($owner, $task_id, true);
     }
     // Reminder for due_date field
     if ($due_date) {
         Backend::add_reminder($task_id, L('defaultreminder') . "\n\n" . CreateURL('details', $task_id), 2 * 24 * 60 * 60, time());
     }
     // Create the Notification
     if (Backend::upload_files($task_id)) {
         $notify->Create(NOTIFY_TASK_OPENED, $task_id, 'files');
     } else {
         $notify->Create(NOTIFY_TASK_OPENED, $task_id);
     }
     // If the reporter wanted to be added to the notification list
     if (isset($args['notifyme']) && $args['notifyme'] == '1' && $user->id != $owner) {
         Backend::add_notification($user->id, $task_id, true);
     }
     if ($user->isAnon()) {
         $notify->Create(NOTIFY_ANON_TASK, $task_id, $token, $args['anon_email'], NOTIFY_EMAIL);
     }
     return array($task_id, $token);
 }
예제 #4
0
 // ##################
 // taking ownership
 // ##################
 case 'takeownership':
     Backend::assign_to_me($user->id, Req::val('ids'));
     // TODO: Log event in a later version.
     $_SESSION['SUCCESS'] = L('takenownershipmsg');
     break;
     // ##################
     // add to assignees list
     // ##################
 // ##################
 // add to assignees list
 // ##################
 case 'addtoassignees':
     Backend::add_to_assignees($user->id, Req::val('ids'));
     // TODO: Log event in a later version.
     $_SESSION['SUCCESS'] = L('addedtoassignees');
     break;
     // ##################
     // admin request
     // ##################
 // ##################
 // admin request
 // ##################
 case 'requestclose':
 case 'requestreopen':
     if ($action == 'requestclose') {
         Flyspray::AdminRequest(1, $proj->id, $task['task_id'], $user->id, Post::val('reason_given'));
         Flyspray::logEvent($task['task_id'], 20, Post::val('reason_given'));
     } elseif ($action == 'requestreopen') {
예제 #5
0
파일: details.php 프로젝트: negram/flyspray
 function action_addtoassignees()
 {
     global $user;
     Backend::add_to_assignees($user->id, Req::val('ids'));
     return array(SUBMIT_OK, L('addedtoassignees'));
 }