| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618 |
- <?php
- /**
- * The control file of todo module of ZenTaoPMS.
- *
- * @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net)
- * @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
- * @author Lanzongjun <lanzongjun@easycorp.ltd>
- * @package todo
- * @link https://www.zentao.net
- */
- class todo extends control
- {
- /**
- * 构造函数,日期的加载类,配置语言项。
- * Construct function, load class of date, lang of my.
- *
- * @access public
- * @return void
- */
- public function __construct()
- {
- parent::__construct();
- $this->app->loadClass('date');
- $this->app->loadLang('my');
- }
- /**
- * 创建待办。
- * Create a todo.
- *
- * @param string $date
- * @param string $from todo|feedback|block
- * @access public
- * @return void
- */
- public function create($date = 'today', $from = 'todo')
- {
- $this->app->loadClass('date');
- if($date == 'today') $date = date::today();
- if(!empty($_POST))
- {
- if($this->post->type != 'custom')
- {
- $this->config->todo->create->requiredFields = '';
- $this->config->todo->create->form['name']['required'] = false;
- }
- $form = form::data($this->config->todo->create->form);
- $form = $this->todoZen->addCycleYearConfig($form);
- $todoData = $this->todoZen->beforeCreate($form);
- $todo = $this->todoZen->prepareCreateData($todoData);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- $todoID = $this->todo->create($todo);
- if($todoID === false) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- $todo->id = $todoID;
- $this->todoZen->afterCreate($todo, $form);
- if(!empty($todoData->objectID)) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'load' => true));
- if($from == 'block')
- {
- $todo = $this->todo->getByID($todoID);
- $todo->begin = date::formatTime($todo->begin);
- return $this->send(array('result' => 'success', 'id' => $todoID, 'name' => $todo->name, 'pri' => $todo->pri, 'priName' => $this->lang->todo->priList[$todo->pri], 'time' => date(DT_DATE4, strtotime($todo->date)) . ' ' . $todo->begin));
- }
- if(isInModal() || isonlybody()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'load' => true));
- if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $todoID));
- if($this->viewType == 'xhtml') return print(js::locate($this->createLink('todo', 'view', "todoID=$todoID", 'html'), 'parent'));
- return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'load' => $this->createLink('my', 'todo', 'type=all&userID=&status=all&orderBy=id_desc')));
- }
- unset($this->lang->todo->typeList['cycle']);
- $this->todoZen->buildCreateView($date);
- }
- /**
- * 批量创建待办。
- * Batch create todo.
- *
- * @param string $date
- * @access public
- * @return void
- */
- public function batchCreate($date = 'today')
- {
- if($date == 'today') $date = helper::today();
- if(!empty($_POST))
- {
- $form = form::batchData($this->config->todo->batchCreate->form);
- $todosData = $this->todoZen->beforeBatchCreate($form);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- $todoIdList = $this->todo->batchCreate($todosData);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- /* Locate the browser. */
- $date = str_replace('-', '', $this->post->date);
- if($this->post->futureDate) $date = 'future';
- if($date == date('Ymd')) $date = 'today';
- if(isInModal() || isonlybody()) return $this->send(array('result' => 'success', 'load' => true, 'closeModal' => true));
- if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'idList' => $todoIdList));
- return $this->sendSuccess(array('closeModal' => true, 'load' => $this->createLink('my', 'todo', "type={$date}")));
- }
- unset($this->lang->todo->typeList['cycle']);
- $this->todoZen->buildBatchCreateView($date);
- }
- /**
- * 编辑待办数据。
- * Edit a todo.
- *
- * @param int $todoID
- * @access public
- * @return void
- */
- public function edit($todoID)
- {
- if(!empty($_POST))
- {
- if($this->post->type != 'custom')
- {
- if($this->post->type && in_array($this->post->type, $this->config->todo->moduleList)) $this->config->todo->edit->requiredFields = str_replace(',name,', ',', ",{$this->config->todo->edit->requiredFields},");
- $this->config->todo->edit->form['name']['required'] = false;
- }
- $form = form::data($this->config->todo->edit->form)->setIF($this->post->private == 'on', 'private', '1');
- $form = $this->todoZen->addCycleYearConfig($form);
- /* Processing edit request data. */
- $todo = $this->todoZen->beforeEdit($todoID, $form);
- if(dao::isError()) return $this->send(array('status' => 'fail', 'message' => dao::getError()));
- /* update a todo. */
- $changes = $this->todo->update($todoID, $todo);
- if(dao::isError()) return $this->send(array('status' => 'fail', 'message' => dao::getError()));
- /* Handle data after edit todo. */
- $this->todoZen->afterEdit($todoID, $changes);
- if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'success'));
- return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'load' => $this->session->todoList ? $this->session->todoList : $this->createLink('my', 'todo')));
- }
- /* Judge a private todo or not, If private, die. */
- $todo = $this->todo->getByID($todoID);
- if($todo->private and $this->app->user->account != $todo->account) return print('private');
- unset($this->lang->todo->typeList['cycle']);
- /* Build create form data. */
- $this->todoZen->buildEditView($todo);
- }
- /**
- * 批量编辑待办。
- * Batch edit todo.
- *
- * @param string $from example:myTodo, todoBatchEdit.
- * @param string $type
- * @param int $userID
- * @param string $status
- * @access public
- * @return void
- */
- public function batchEdit($from = '', $type = 'today', $userID = 0, $status = 'all')
- {
- /* Get form data for my-todo. */
- if($from == 'myTodo')
- {
- if(!$this->post->todoIdList) return $this->locate($this->session->todoList ? $this->session->todoList : createLink('my', 'todo'));
- $this->todoZen->batchEditFromMyTodo($this->post->todoIdList, $type, $userID, $status);
- }
- /* Save the todo data for batch edit. */
- if($from == 'todoBatchEdit')
- {
- $this->config->todo->edit->requiredFields = str_replace(',name,', ',', ",{$this->config->todo->edit->requiredFields},");
- $formData = form::batchData($this->config->todo->batchEdit->form)->get();
- $todos = $this->todoZen->beforeBatchEdit($formData);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- $allChanges = $this->todo->batchUpdate($todos, array_keys($formData));
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- $this->todoZen->afterBatchEdit($allChanges);
- return $this->sendSuccess(array('locate' => $this->session->todoList));
- }
- }
- /**
- * 开始一个待办事项。
- * Start a todo.
- *
- * @param int $todoID
- * @access public
- * @return void
- */
- public function start($todoID)
- {
- $todo = $this->todo->getByID($todoID);
- if($todo->status == 'wait')
- {
- $this->todo->start($todoID);
- if(dao::isError()) return print(js::error(dao::getError()));
- }
- if(in_array($todo->type, array('bug', 'task', 'story'))) return $this->todoZen->printStartConfirm($todo);
- if(isInModal()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true));
- return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'load' => $this->session->todoList ? $this->session->todoList : $this->createLink('my', 'todo')));
- }
- /**
- * 激活待办事项。
- * Activate a todo.
- *
- * @param int $todoID
- * @access public
- * @return void
- */
- public function activate($todoID)
- {
- $todo = $this->todo->getByID($todoID);
- if($todo->status == 'done' || $todo->status == 'closed')
- {
- $this->todo->activate($todoID);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- }
- if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'success'));
- if(isInModal()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true));
- return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'load' => $this->session->todoList ? $this->session->todoList : $this->createLink('my', 'todo')));
- }
- /**
- * 关闭待办。
- * Close one todo.
- *
- * @param int $todoID
- * @access public
- * @return void
- */
- public function close($todoID)
- {
- /* Close the todo with status done. */
- $todo = $this->todo->getByID($todoID);
- if($todo->status == 'done')
- {
- $isClosed = $this->todo->close($todoID);
- if(!$isClosed) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- }
- /* Return json if run mode is API. */
- if(defined('RUN_MODE') && RUN_MODE == 'api')
- {
- $this->send(array('status' => 'success'));
- }
- if(isInModal()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true));
- return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'load' => $this->session->todoList ? $this->session->todoList : $this->createLink('my', 'todo')));
- }
- /**
- * 指派待办。
- * Assign todo.
- *
- * @param int $todoID
- * @access public
- * @return void
- */
- public function assignTo($todoID)
- {
- if(!empty($_POST))
- {
- $formData = form::data($this->config->todo->assignTo->form);
- $todo = $this->todoZen->beforeAssignTo($formData);
- $todo->id = $todoID;
- $isAssigned = $this->todoZen->doAssignTo($todo);
- if(!$isAssigned) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- if(isInModal()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'load' => true));
- return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'load' => $this->session->todoList ? $this->session->todoList : $this->createLink('my', 'todo')));
- }
- $this->todoZen->buildAssignToView($todoID);
- }
- /**
- * 获取待办的信息。
- * Get info of todo.
- *
- * @param int $todoID
- * @param string $from my|company
- * @access public
- * @return void
- */
- public function view($todoID, $from = 'company')
- {
- $todo = $this->todo->getByID($todoID, true);
- if(!$todo)
- {
- if((defined('RUN_MODE') && RUN_MODE == 'api') or $this->app->viewType == 'json') return $this->send(array('status' => 'fail', 'message' => '404 Not found'));
- if(isInModal()) return print(js::start() . "zui.Modal.hide($(document).find('.modal'));zui.Modal.alert('{$this->lang->notFound}');" . js::end());
- return $this->send(array('result' => 'fail', 'load' => array('alert' => $this->lang->notFound)));
- }
- $account = $this->app->user->account;
- if($todo->private && $todo->account != $account)
- {
- if(isInModal()) return print(js::start() . "zui.Modal.hide($(document).find('.modal'));zui.Modal.alert('{$this->lang->todo->thisIsPrivate}');" . js::end());
- return $this->send(array('result' => 'fail', 'load' => array('alert' => $this->lang->todo->thisIsPrivate)));
- }
- if(!isInModal()) $this->todoZen->setSessionUri($this->app->getURI(true));
- /* Fix bug #936. */
- if($account != $todo->account && $account != $todo->assignedTo and !common::hasPriv('my', 'team'))
- {
- $this->locate($this->createLink('user', 'deny', "module=my&method=team"));
- }
- $projects = $this->todoZen->getProjectPairsByModel((string)$todo->type);
- if(!isset($this->session->project)) $this->session->set('project', (int)key($projects));
- $this->todoZen->buildAssignToTodoView((object)$todo, (int)$this->session->project, (array)$projects, (string)$account, $from);
- }
- /**
- * 删除待办。
- * Delete a todo.
- *
- * @param int $todoID
- * @param string $confirm yes|no
- * @access public
- * @return void
- */
- public function delete($todoID, $confirm = 'no')
- {
- if($confirm == 'no') return $this->send(array('result' => 'success', 'load' => array('confirm' => $this->lang->todo->confirmDelete, 'confirmed' => $this->createLink('todo', 'delete', "todoID={$todoID}&confirm=yes"), 'canceled' => $this->session->todoList ? $this->session->todoList : $this->createLink('my', 'todo'))));
- $todo = $this->todo->getByID($todoID);
- $allowDelete = true;
- if(!$this->app->user->admin && $todo && $todo->account != $this->app->user->account && $todo->assignedTo != $this->app->user->account) $allowDelete = false;
- if(!$allowDelete)
- {
- if(isonlybody()) return print(js::alert($this->lang->error->accessDenied));
- if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'fail', 'message' => $this->lang->error->accessDenied));
- if(helper::isAjaxRequest()) return $this->send(array('result' => 'fail', 'message' => $this->lang->error->accessDenied));
- }
- $this->todo->delete(TABLE_TODO, $todoID);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'success'));
- return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'load' => $this->session->todoList ? $this->session->todoList : $this->createLink('my', 'todo')));
- }
- /**
- * 完成待办。
- * Finish a todo.
- *
- * @param int $todoID
- * @access public
- * @return void
- */
- public function finish($todoID)
- {
- $todo = $this->todo->getByID($todoID);
- if($todo->status != 'done' && $todo->status != 'closed')
- {
- $result = $this->todo->finish($todoID);
- if(!$result) return false;
- }
- $types = $this->config->todo->moduleList;
- array_pop($types);
- if(in_array($todo->type, $types))
- {
- $confirmNote = 'confirm' . ucfirst($todo->type);
- if($this->config->vision == 'or' && $todo->type == 'task') $todo->type = 'researchtask';
- $confirmURL = $this->createLink($todo->type, 'view', "id=$todo->objectID");
- $message = sprintf($this->lang->todo->{$confirmNote}, $todo->objectID);
- $tab = $this->app->tab;
- if($todo->type == 'bug') $tab = 'qa';
- if($todo->type == 'task') $tab = 'execution';
- if($todo->type == 'researchtask') $tab = 'market';
- if($todo->type == 'story') $tab = 'product';
- if($todo->type == 'epic') $tab = 'product';
- if($todo->type == 'requirement') $tab = 'product';
- if($todo->type == 'feedback') $tab = 'feedback';
- if(in_array($todo->type, array('issue', 'risk'))) $tab = 'project';
- return $this->send(array('result' => 'success', 'callback' => "zui.Modal.confirm({message: '{$message}', icon: 'icon-exclamation-sign', iconClass: 'warning-pale rounded-full icon-2x'}).then((res) => {if(res) openPage('{$confirmURL}', '{$tab}'); else reloadPage();});"));
- }
- if(defined('RUN_MODE') && RUN_MODE == 'api')
- {
- return $this->send(array('status' => 'success'));
- }
- if(isInModal()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true));
- return $this->sendSuccess(array('load' => $this->session->todoList ? $this->session->todoList : $this->createLink('my', 'todo'), 'closeModal' => true));
- }
- /**
- * 批量完成待办。
- * Batch finish todos.
- *
- * @access public
- * @return void
- */
- public function batchFinish()
- {
- $todoIdList = form::data($this->config->todo->batchFinish->form)->get('todoIdList');
- $todoList = $this->todo->getByList($todoIdList);
- foreach($todoList as $todoID => $todo)
- {
- if($todo->status == 'done' || $todo->status == 'closed') unset($todoList[$todoID]);
- }
- $isBatchFinished = $this->todo->batchFinish(array_keys($todoList));
- if(!$isBatchFinished) return false;
- return $this->send(array('result' => 'success', 'load' => true));
- }
- /**
- * 批量关闭待办。只有完成的待办才能关闭。
- * Batch close todos. The status of todo which need to close should be done.
- *
- * @access public
- * @return void
- */
- public function batchClose()
- {
- $waitIdList = array();
- $todoIdList = form::data($this->config->todo->batchClose->form)->get('todoIdList');
- foreach($todoIdList as $todoID)
- {
- $todoID = (int)$todoID;
- $todo = $this->todo->getByID($todoID);
- if($todo->status == 'done') $this->todo->close($todoID);
- if($todo->status != 'done' and $todo->status != 'closed') $waitIdList[] = $todoID;
- }
- if(!empty($waitIdList)) return $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->todo->unfinishedTodo, implode(',', $waitIdList))));
- return $this->send(array('result' => 'success', 'load' => true));
- }
- /**
- * 修改选中待办的日期。
- * Import selected todos to today.
- *
- * @param string $todoID
- * @access public
- * @return void
- */
- public function import2Today($todoID = '')
- {
- if(!$_POST) $this->locate($this->createLink('my', 'todo'));
- $formData = form::data($this->config->todo->editDate->form);
- $todoIdList = !empty($formData->data->todoIdList) ? $formData->data->todoIdList : array($todoID);
- $date = !empty($formData->data->date) ? $formData->data->date : date::today();
- if(!$todoIdList) $this->locate((string)$this->session->todoList);
- $this->todo->editDate((array)$todoIdList, (string)$date);
- return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => true));
- }
- /**
- * 获取导出待办数据。
- * Get data to export.
- *
- * @param int $userID
- * @param string $orderBy
- * @access public
- * @return void
- */
- public function export($userID, $orderBy)
- {
- if($_POST)
- {
- $user = $this->todoZen->getUserById($userID);
- $todoLang = (object)$this->lang->todo;
- $configTime = $this->config->todo->times;
- $formData = form::data($this->config->todo->export->form);
- $checkedItem = $formData->data->exportType == 'selected' ? $this->cookie->checkedItem : '';
- $todos = $this->todo->getByExportList($orderBy, (string) $this->session->todoReportCondition, (string)$checkedItem);
- list($todos, $fields) = $this->todoZen->exportTodoInfo((array)$todos, (string)$this->config->todo->list->exportFields, $todoLang);
- list($users, $bugs, $stories, $epics, $requirements, $tasks, $testTasks) = $this->todoZen->exportAssociated('default', (string)$user->account);
- $times = date::buildTimeList((int)$configTime->begin, (int)$configTime->end, (int)$configTime->delta);
- $assemble = new stdclass();
- $assemble->users = $users;
- $assemble->bugs = $bugs;
- $assemble->stories = $stories;
- $assemble->epics = $epics;
- $assemble->requirements = $requirements;
- $assemble->tasks = $tasks;
- $assemble->testTasks = $testTasks;
- if(in_array($this->config->edition, array('max', 'ipd')))
- {
- $iroData = $this->todoZen->exportAssociated((string)$this->config->edition, (string)$user->account);
- $assemble->issues = $iroData[0];
- $assemble->risks = $iroData[1];
- $assemble->opportunities = $iroData[2];
- }
- $todos = $this->todoZen->assembleExportData((array)$todos, $assemble, $todoLang, (array)$times);
- $this->post->set('fields', $fields);
- $this->post->set('rows', $todos);
- $this->post->set('kind', 'todo');
- $this->fetch('file', 'export2' . $this->post->fileType, $_POST);
- }
- $this->view->fileName = $this->app->user->account . '-' . $this->lang->todo->common;
- $this->display();
- }
- /**
- * ajax请求:获得 todo 的动作。 用于 web 应用程序。
- * AJAX: get actions of a todo. for web app.
- *
- * @param int $todoID
- * @access public
- * @return void
- */
- public function ajaxGetDetail($todoID)
- {
- $this->view->actions = $this->loadModel('action')->getList('todo', $todoID);
- $this->display();
- }
- /**
- * ajax请求:获取程序id。
- * AJAX: get program id.
- *
- * @param int $objectID
- * @param string $objectType
- * @access public
- * @return void
- */
- public function ajaxGetProgramID($objectID, $objectType)
- {
- $table = $objectType == 'project' ? TABLE_PROJECT : TABLE_PRODUCT;
- $field = $objectType == 'project' ? 'parent' : 'program';
- echo $this->dao->select($field)->from($table)->where('id')->eq($objectID)->fetch($field);
- }
- /**
- * ajax请求:获取执行对。
- * AJAX: get execution pairs.
- *
- * @param int $projectID
- * @access public
- * @return void
- */
- public function ajaxGetExecutionPairs($projectID)
- {
- $this->session->set('project', $projectID);
- $project = $this->loadModel('project')->getByID($projectID);
- $executions = $this->loadModel('execution')->getByProject($projectID, 'undone');
- $items = array();
- foreach($executions as $id => $execution) $items[] = array('value' => $id, 'text' => $execution->name, 'keys' => $execution->name);
- return print(json_encode($items));
- }
- /**
- * ajax请求:获取产品对。
- * AJAX: get product pairs.
- *
- * @param int $projectID
- * @access public
- * @return void
- */
- public function ajaxGetProductPairs($projectID)
- {
- $this->session->set('project', $projectID);
- $products = $this->loadModel('product')->getProductPairsByProject($projectID);
- $items = array();
- foreach($products as $id => $name) $items[] = array('value' => $id, 'text' => $name, 'keys' => $name);
- return print(json_encode($items));
- }
- /**
- * 创建周期待办。
- * Create cycle.
- *
- * @access public
- * @return void
- */
- public function createCycle()
- {
- $todoList = $this->todo->getValidCycleList();
- $this->todo->createByCycle($todoList);
- }
- }
|