/** * @param \Base $f3 */ public function config($f3) { $status = new \Model\Issue\Status(); $f3->set("issue_statuses", $status->find()); $f3->set("title", $f3->get("dict.configuration")); $this->_render("admin/config.html"); }
/** * Convert a status ID to a name * @param int $id * @return string */ public function convertStatus($id) { if (isset($this->cache['status.' . $id])) { $status = $this->cache['status.' . $id]; } else { $status = new \Model\Issue\Status(); $status->load($id); $this->cache['status.' . $id] = $status; } return $status->name; }
/** * Update an existing task */ public function edit($f3, $params) { $post = $f3->get("POST"); $issue = new \Model\Issue(); $issue->load($post["taskId"]); if (!empty($post["receiver"])) { if ($post["receiver"]["story"]) { $issue->parent_id = $post["receiver"]["story"]; } $issue->status = $post["receiver"]["status"]; $status = new \Model\Issue\Status(); $status->load($issue->status); if ($status->closed) { if (!$issue->closed_date) { $issue->closed_date = $this->now(); } } else { $issue->closed_date = null; } } else { $issue->name = $post["title"]; $issue->description = $post["description"]; $issue->owner_id = $post["assigned"]; $issue->hours_remaining = $post["hours"]; $issue->hours_spent += $post["hours_spent"]; if (!empty($post["hours_spent"]) && !empty($post["burndown"])) { $issue->hours_remaining -= $post["hours_spent"]; } if ($issue->hours_remaining < 0) { $issue->hours_remaining = 0; } if (!empty($post["dueDate"])) { $issue->due_date = date("Y-m-d", strtotime($post["dueDate"])); } else { $issue->due_date = null; } if (!empty($post["repeat_cycle"])) { $issue->repeat_cycle = $post["repeat_cycle"]; } $issue->priority = $post["priority"]; if (!empty($post["storyId"])) { $issue->parent_id = $post["storyId"]; } $issue->title = $post["title"]; } if (!empty($post["comment"])) { $comment = new \Model\Issue\Comment(); $comment->user_id = $this->_userId; $comment->issue_id = $issue->id; if (!empty($post["hours_spent"])) { $comment->text = trim($post["comment"]) . sprintf(" (%s %s spent)", $post["hours_spent"], $post["hours_spent"] == 1 ? "hour" : "hours"); } else { $comment->text = $post["comment"]; } $comment->created_date = $this->now(); $comment->save(); $issue->update_comment = $comment->id; } $issue->save(); $this->_printJson($issue->cast() + array("taskId" => $issue->id)); }
/** * GET /issues/@id * View an issue * * @param \Base $f3 * @param array $params * @throws \Exception */ public function single($f3, $params) { $issue = new \Model\Issue\Detail(); $issue->load(array("id=?", $params["id"])); $user = $f3->get("user_obj"); if (!$issue->id || $issue->deleted_date && !($user->role == 'admin' || $user->rank >= \Model\User::RANK_MANAGER || $issue->author_id == $user->id)) { $f3->error(404); return; } $type = new \Model\Issue\Type(); $type->load($issue->type_id); $f3->set("title", $type->name . " #" . $issue->id . ": " . $issue->name); $f3->set("menuitem", "browse"); $author = new \Model\User(); $author->load($issue->author_id); $owner = new \Model\User(); if ($issue->owner_id) { $owner->load($issue->owner_id); } $files = new \Model\Issue\File\Detail(); $f3->set("files", $files->find(array("issue_id = ? AND deleted_date IS NULL", $issue->id))); if ($issue->sprint_id) { $sprint = new \Model\Sprint(); $sprint->load($issue->sprint_id); $f3->set("sprint", $sprint); } $watching = new \Model\Issue\Watcher(); $watching->load(array("issue_id = ? AND user_id = ?", $issue->id, $this->_userId)); $f3->set("watching", !!$watching->id); $f3->set("issue", $issue); $f3->set("ancestors", $issue->getAncestors()); $f3->set("type", $type); $f3->set("author", $author); $f3->set("owner", $owner); $comments = new \Model\Issue\Comment\Detail(); $f3->set("comments", $comments->find(array("issue_id = ?", $issue->id), array("order" => "created_date DESC"))); // Extra data needed for inline edit form $status = new \Model\Issue\Status(); $f3->set("statuses", $status->find(null, null, $f3->get("cache_expire.db"))); $priority = new \Model\Issue\Priority(); $f3->set("priorities", $priority->find(null, array("order" => "value DESC"), $f3->get("cache_expire.db"))); $sprint = new \Model\Sprint(); $f3->set("sprints", $sprint->find(array("end_date >= ? OR id = ?", $this->now(false), $issue->sprint_id), array("order" => "start_date ASC"))); $users = new \Model\User(); $f3->set("users", $users->find("deleted_date IS NULL AND role != 'group'", array("order" => "name ASC"))); $f3->set("groups", $users->find("deleted_date IS NULL AND role = 'group'", array("order" => "name ASC"))); $this->_render("issues/single.html"); }
public function single($f3, $params) { $this->_requireLogin(); $user = new \Model\User(); $user->load(array("username = ? AND deleted_date IS NULL", $params["username"])); if ($user->id) { $f3->set("title", $user->name); $f3->set("this_user", $user); // Extra arrays required for bulk update $status = new \Model\Issue\Status(); $f3->set("statuses", $status->find(null, null, $f3->get("cache_expire.db"))); $f3->set("users", $user->getAll()); $f3->set("groups", $user->getAllGroups()); $priority = new \Model\Issue\Priority(); $f3->set("priorities", $priority->find(null, array("order" => "value DESC"), $f3->get("cache_expire.db"))); $type = new \Model\Issue\Type(); $f3->set("types", $type->find(null, null, $f3->get("cache_expire.db"))); $issue = new \Model\Issue\Detail(); $f3->set("created_issues", $issue->paginate(0, 200, array("status_closed = '0' AND deleted_date IS NULL AND author_id = ?", $user->id), array("order" => "priority DESC, due_date DESC"))); $f3->set("assigned_issues", $issue->paginate(0, 200, array("status_closed = '0' AND deleted_date IS NULL AND owner_id = ?", $user->id), array("order" => "priority DESC, due_date DESC"))); $f3->set("overdue_issues", $issue->paginate(0, 200, array("status_closed = '0' AND deleted_date IS NULL AND owner_id = ? AND due_date IS NOT NULL AND due_date < ?", $user->id, date("Y-m-d", \Helper\View::instance()->utc2local())), array("order" => "due_date ASC"))); $this->_render("user/single.html"); } else { $f3->error(404); } }
public function post($f3) { if ($_REQUEST) { // By default, use standard HTTP POST fields $post = $_REQUEST; } else { // For Redmine compatibility, also accept a JSON object try { $post = json_decode(file_get_contents('php://input'), true); } catch (Exception $e) { throw new Exception("Unable to parse input"); } if (!empty($post["issue"])) { $post = $post["issue"]; } // Convert Redmine names to Phproject names if (!empty($post["subject"])) { $post["name"] = $post["subject"]; } if (!empty($post["parent_issue_id"])) { $post["parent_id"] = $post["parent_issue_id"]; } if (!empty($post["tracker_id"])) { $post["type_id"] = $post["tracker_id"]; } if (!empty($post["assigned_to_id"])) { $post["owner_id"] = $post["assigned_to_id"]; } if (!empty($post["fixed_version_id"])) { $post["sprint_id"] = $post["fixed_version_id"]; } } // Ensure a status ID is added if (!empty($post["status_id"])) { $post["status"] = $post["status_id"]; } if (empty($post["status"])) { $post["status"] = 1; } // Verify the required "name" field is passed if (empty($post["name"])) { $f3->error("The 'name' value is required."); return; } // Verify given values are valid (types, statueses, priorities) if (!empty($post["type_id"])) { $type = new \Model\Issue\Type(); $type->load($post["type_id"]); if (!$type->id) { $f3->error("The 'type_id' field is not valid."); return; } } if (!empty($post["parent_id"])) { $parent = new \Model\Issue(); $parent->load($post["parent_id"]); if (!$parent->id) { $f3->error("The 'type_id' field is not valid."); return; } } if (!empty($post["status"])) { $status = new \Model\Issue\Status(); $status->load($post["status"]); if (!$status->id) { $f3->error("The 'status' field is not valid."); return; } } if (!empty($post["priority_id"])) { $priority = new \Model\Issue\Priority(); $priority->load(array("value" => $post["priority_id"])); if (!$priority->id) { $f3->error("The 'priority_id' field is not valid."); return; } } // Create a new issue based on the data $issue = new \Model\Issue(); $issue->author_id = !empty($post["author_id"]) ? $post["author_id"] : $this->_userId; $issue->name = trim($post["name"]); $issue->type_id = empty($post["type_id"]) ? 1 : $post["type_id"]; $issue->priority_id = empty($post["priority_id"]) ? $f3->get("issue_priority.default") : $post["priority_id"]; // Set due date if valid if (!empty($post["due_date"]) && preg_match("/^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}( [0-9:]{8})?\$/", $post["due_date"])) { $issue->due_date = $post["due_date"]; } elseif (!empty($post["due_date"]) && ($due_date = strtotime($post["due_date"]))) { $issue->due_date = date("Y-m-d", $due_date); } if (!empty($post["description"])) { $issue->description = $post["description"]; } if (!empty($post["parent_id"])) { $issue->parent_id = $post["parent_id"]; } if (!empty($post["owner_id"])) { $issue->owner_id = $post["owner_id"]; } $issue->save(); $this->_printJson(array("issue" => $issue->cast())); }
/** * @param \Base $f3 * @param array $params * @throws \Exception */ public function single($f3, $params) { $issue = new \Model\Issue\Detail(); $issue->load(array("id=?", $f3->get("PARAMS.id"))); $user = $f3->get("user_obj"); if (!$issue->id || $issue->deleted_date && !($user->role == 'admin' || $user->rank >= \Model\User::RANK_MANAGER || $issue->author_id == $user->id)) { $f3->error(404); return; } $type = new \Model\Issue\Type(); $type->load($issue->type_id); // Run actions if passed $post = $f3->get("POST"); if (!empty($post)) { switch ($post["action"]) { case "add_watcher": $watching = new \Model\Issue\Watcher(); // Loads just in case the user is already a watcher $watching->load(array("issue_id = ? AND user_id = ?", $issue->id, $post["user_id"])); if (!$watching->id) { $watching->issue_id = $issue->id; $watching->user_id = $post["user_id"]; $watching->save(); } if ($f3->get("AJAX")) { return; } break; case "remove_watcher": $watching = new \Model\Issue\Watcher(); $watching->load(array("issue_id = ? AND user_id = ?", $issue->id, $post["user_id"])); $watching->delete(); if ($f3->get("AJAX")) { return; } break; case "add_dependency": $dependencies = new \Model\Issue\Dependency(); // Loads just in case the task is already a dependency $dependencies->load(array("issue_id = ? AND dependency_id = ?", $issue->id, $post["id"])); $dependencies->issue_id = $issue->id; $dependencies->dependency_id = $post["id"]; $dependencies->dependency_type = $post["type_id"]; $dependencies->save(); if ($f3->get("AJAX")) { return; } break; case "add_dependent": $dependencies = new \Model\Issue\Dependency(); // Loads just in case the task is already a dependency $dependencies->load(array("issue_id = ? AND dependency_id = ?", $post["id"], $issue->id)); $dependencies->dependency_id = $issue->id; $dependencies->issue_id = $post["id"]; $dependencies->dependency_type = $post["type_id"]; $dependencies->save(); if ($f3->get("AJAX")) { return; } break; case "remove_dependency": $dependencies = new \Model\Issue\Dependency(); $dependencies->load($post["id"]); $dependencies->delete(); if ($f3->get("AJAX")) { return; } break; } } $f3->set("title", $type->name . " #" . $issue->id . ": " . $issue->name); $f3->set("menuitem", "browse"); $author = new \Model\User(); $author->load($issue->author_id); $owner = new \Model\User(); if ($issue->owner_id) { $owner->load($issue->owner_id); } $files = new \Model\Issue\File\Detail(); $f3->set("files", $files->find(array("issue_id = ? AND deleted_date IS NULL", $issue->id))); if ($issue->sprint_id) { $sprint = new \Model\Sprint(); $sprint->load($issue->sprint_id); $f3->set("sprint", $sprint); } $watching = new \Model\Issue\Watcher(); $watching->load(array("issue_id = ? AND user_id = ?", $issue->id, $this->_userId)); $f3->set("watching", !!$watching->id); $f3->set("issue", $issue); $f3->set("ancestors", $issue->getAncestors()); $f3->set("type", $type); $f3->set("author", $author); $f3->set("owner", $owner); $comments = new \Model\Issue\Comment\Detail(); $f3->set("comments", $comments->find(array("issue_id = ?", $issue->id), array("order" => "created_date DESC"))); // Extra data needed for inline edit form $status = new \Model\Issue\Status(); $f3->set("statuses", $status->find(null, null, $f3->get("cache_expire.db"))); $priority = new \Model\Issue\Priority(); $f3->set("priorities", $priority->find(null, array("order" => "value DESC"), $f3->get("cache_expire.db"))); $sprint = new \Model\Sprint(); $f3->set("sprints", $sprint->find(array("end_date >= ? OR id = ?", $this->now(false), $issue->sprint_id), array("order" => "start_date ASC"))); $users = new \Model\User(); $f3->set("users", $users->find("deleted_date IS NULL AND role != 'group'", array("order" => "name ASC"))); $f3->set("groups", $users->find("deleted_date IS NULL AND role = 'group'", array("order" => "name ASC"))); $this->_render("issues/single.html"); }
/** * Close the issue * @return Issue $this */ public function close() { if ($this->id && !$this->closed_date) { $status = new \Model\Issue\Status(); $status->load(array("closed = ?", 1)); $this->status = $status->id; $this->closed_date = date("Y-m-d H:i:s"); $this->save(); } return $this; }