diff --git a/module/common/model.php b/module/common/model.php index f4ba4c7271..be8c02e614 100644 --- a/module/common/model.php +++ b/module/common/model.php @@ -1425,24 +1425,6 @@ EOD; $preAndNextObject->pre = ''; $preAndNextObject->next = ''; - if($type == 'story' and !empty($_SESSION['planStoryOrder'])) - { - $objects = explode(',', $_SESSION['planStoryOrder']); - $key = array_search($objectID, $objects); - - if($key > 0) - { - $preObjectID = $objects[$key - 1]; - $preAndNextObject->pre = $this->loadModel('story')->getByID($preObjectID); - } - if($key < (count($objects) - 1)) - { - $nextObjectID = $objects[$key + 1]; - $preAndNextObject->next = $this->loadModel('story')->getByID($nextObjectID); - } - return $preAndNextObject; - } - /* Get objectIDList. */ $table = $this->config->objectTables[$type]; $queryCondition = $type . 'QueryCondition'; diff --git a/module/product/control.php b/module/product/control.php index 0dc4d8818d..37b2aa5499 100644 --- a/module/product/control.php +++ b/module/product/control.php @@ -116,7 +116,6 @@ class product extends control /* Save session. */ $this->session->set('storyList', $this->app->getURI(true)); $this->session->set('productList', $this->app->getURI(true)); - $this->session->set('planStoryOrder', ''); /* Set product, module and query. */ $productID = $this->product->saveState($productID, $this->products); diff --git a/module/productplan/control.php b/module/productplan/control.php index e9a1e95d83..ae1900cf24 100644 --- a/module/productplan/control.php +++ b/module/productplan/control.php @@ -256,17 +256,6 @@ class productplan extends control $this->app->loadClass('pager', $static = true); if($this->app->getViewType() == 'mhtml') $recPerPage = 10; - $reSort = false; - if($type == 'story' && strpos($orderBy, 'order') !== false) - { - $orderBy = str_replace('order', 'id', $orderBy); - $reSort = true; - } - else - { - $this->session->set('planStoryOrder', ''); - } - /* Append id for secend sort. */ $sort = $this->loadModel('common')->appendOrder($orderBy); @@ -276,26 +265,9 @@ class productplan extends control $bugPager = new pager(0, $recPerPage, $type == 'bug' ? $pageID : 1); $storyPager = new pager(0, $recPerPage, $type == 'story' ? $pageID : 1); + /* Get stories of plan. */ $this->loadModel('story'); - if(!$reSort or empty($plan->order)) $planStories = $this->story->getPlanStories($planID, 'all', $type == 'story' ? $sort : 'id_desc', $storyPager); - - if($reSort) - { - if(!empty($plan->order)) - { - $planStories = $this->story->getPlanStories($planID, 'all', $sort); - $planStories = $this->story->sortPlanStory($planStories, $plan->order, $orderBy); - - $storyIDList = implode(',', array_keys($planStories)); - $this->session->set('planStoryOrder', $storyIDList); - - $storyPager->recTotal = count($planStories); - - $frontCount = $storyPager->recPerPage * ($storyPager->pageID - 1); - $planStories = array_slice($planStories, $frontCount, $storyPager->recPerPage); - } - $orderBy = str_replace('id', 'order', $orderBy); - } + $planStories = $this->story->getPlanStories($planID, 'all', $type == 'story' ? $sort : 'id_desc', $storyPager); $this->executeHooks($planID); if($plan->parent > 0) $this->view->parentPlan = $this->productplan->getById($plan->parent); @@ -354,11 +326,11 @@ class productplan extends control { if(empty($planID)) return true; - $plan = $this->productplan->getByID($planID, true); - $order = $this->loadModel('story')->getAllStorySort($planID, $plan->order); + /* Get story id list. */ + $storyIDList = explode(',', trim($this->post->stories, ',')); - $this->dao->update(TABLE_PRODUCTPLAN)->set('`order`')->eq($order)->where('id')->eq((int)$planID)->exec(); - $this->session->set('planStoryOrder', $order); + /* Update the story order according to the plan. */ + $this->loadModel('story')->sortStoriesOfPlan($planID, $storyIDList, $this->post->orderBy, $this->post->pageID, $this->post->recPerPage); } /** diff --git a/module/productplan/model.php b/module/productplan/model.php index 130b7d0018..da229366e3 100644 --- a/module/productplan/model.php +++ b/module/productplan/model.php @@ -466,7 +466,6 @@ class productplanModel extends model $stories = $this->story->getByList($this->post->stories); $plan = $this->getByID($planID); - $currentOrder = $plan->order; foreach($this->post->stories as $storyID) { if(!isset($stories[$storyID])) continue; @@ -474,24 +473,19 @@ class productplanModel extends model $story = $stories[$storyID]; if(strpos(",$story->plan,", ",{$planID},") !== false) continue; - /* Fix Bug #1538*/ - $currentOrder = $currentOrder . $storyID . ','; - $oldOrder = $this->dao->select('*')->from(TABLE_PRODUCTPLAN)->where("id")->eq($story->plan)->fetch('order'); - $oldOrder = explode(',', $oldOrder); - unset($oldOrder[array_search($storyID, $oldOrder)]); - $oldOrder = implode(',', $oldOrder); - $this->dao->update(TABLE_PRODUCTPLAN)->set("order")->eq($oldOrder)->where('id')->eq($story->plan)->exec(); - - /* Modify the plan linked with the story. */ + /* Update the plan linked with the story and the order of the story in the plan. */ if($this->session->currentProductType == 'normal' or $story->branch != 0 or empty($story->plan)) { $this->dao->update(TABLE_STORY)->set("plan")->eq($planID)->where('id')->eq((int)$storyID)->exec(); + + $this->story->updateStoryOrderOfPlan($storyID, $planID, $story->plan); } else { $plansOfStory = $story->plan . ',' . $planID; - $this->dao->update(TABLE_STORY)->set("plan")->eq($plansOfStory)->where('id')->eq((int)$storyID)->andWhere('branch')->eq('0')->exec(); + + $this->story->updateStoryOrderOfPlan($storyID, $planID); } $this->action->create('story', $storyID, 'linked2plan', '', $planID); @@ -514,14 +508,11 @@ class productplanModel extends model $plans = array_unique(explode(',', trim(str_replace(",$planID,", ',', ',' . trim($story->plan) . ','). ','))); $this->dao->update(TABLE_STORY)->set('plan')->eq(join(',', $plans))->where('id')->eq((int)$storyID)->exec(); - /* Fix Bug #1538. */ - $oldOrder = $this->dao->select('*')->from(TABLE_PRODUCTPLAN)->where("id")->eq($story->plan)->fetch('order'); - $oldOrder = explode(',', $oldOrder); - unset($oldOrder[array_search($storyID, $oldOrder)]); - $oldOrder = implode(',', $oldOrder); - $this->dao->update(TABLE_PRODUCTPLAN)->set('order')->eq($oldOrder)->where('id')->eq($story->plan)->exec(); + /* Delete the story in the sort of the plan. */ + $this->loadModel('story'); + $this->story->updateStoryOrderOfPlan($storyID, '', $planID); - $this->loadModel('story')->setStage($storyID); + $this->story->setStage($storyID); $this->loadModel('action')->create('story', $storyID, 'unlinkedfromplan', '', $planID); } diff --git a/module/project/control.php b/module/project/control.php index d482ce3263..522695d6de 100644 --- a/module/project/control.php +++ b/module/project/control.php @@ -690,7 +690,6 @@ class project extends control /* Save session. */ $this->app->session->set('storyList', $this->app->getURI(true)); - $this->session->set('planStoryOrder', ''); /* Process the order by field. */ if(!$orderBy) $orderBy = $this->cookie->projectStoryOrder ? $this->cookie->projectStoryOrder : 'pri'; diff --git a/module/story/model.php b/module/story/model.php index f89ba84a50..97804abbaf 100644 --- a/module/story/model.php +++ b/module/story/model.php @@ -229,11 +229,7 @@ class storyModel extends model $this->file->updateObjectID($this->post->uid, $storyID, 'story'); $this->file->saveUpload('story', $storyID, $extra = 1); - if(!empty($story->plan)) - { - $plan[$story->plan][] = $storyID; - $this->updatePlanStoryOrder($plan); - } + if(!empty($story->plan)) $this->updateStoryOrderOfPlan($storyID, $story->plan); // Set story order in this plan. $data = new stdclass(); $data->story = $storyID; @@ -430,7 +426,8 @@ class storyModel extends model $storyID = $this->dao->lastInsertID(); $this->setStage($storyID); - if($story->plan) $planStories[$story->plan][] = $storyID; + /* Update product plan stories order. */ + if($story->plan) $this->updateStoryOrderOfPlan($storyID, $story->plan); $specData = new stdclass(); $specData->story = $storyID; @@ -482,9 +479,6 @@ class storyModel extends model $mails[$i]->actionID = $actionID; } - /* Update product plan stories order. */ - if(!empty($planStories)) $this->updatePlanStoryOrder($planStories); - /* Remove upload image file and session. */ if(!empty($stories->uploadImage) and $this->session->storyImagesFile) { @@ -738,8 +732,13 @@ class storyModel extends model if(isset($story->closedReason) and $story->closedReason == 'done') $this->loadModel('score')->create('story', 'close'); - /* Fix bug #3153. */ - if($oldStory->plan != $story->plan and (empty($oldStory->plan) or empty($story->plan))) $this->setStage($storyID); + /* Set new stage and update story sort of plan when story plan has changed. */ + if($oldStory->plan != $story->plan) + { + $this->updateStoryOrderOfPlan($storyID, $story->plan, $oldStory->plan); // Insert a new story sort in this plan. + + if(empty($oldStory->plan) or empty($story->plan)) $this->setStage($storyID); // Set new stage for this story. + } unset($oldStory->parent); unset($story->parent); @@ -895,25 +894,46 @@ class storyModel extends model } /** - * update plan story order. + * update the story order of plan. * - * @param int $planStories + * @param int $storyID + * @param string $oldPlanIDList + * @param string $planIDList * @access public * @return void */ - public function updatePlanStoryOrder($planStories) + public function updateStoryOrderOfPlan($storyID, $planIDList = '', $oldPlanIDList = '') { - $planIDList = array_keys($planStories); - $plans = $this->dao->select('id, `order`')->from(TABLE_PRODUCTPLAN)->where('id')->in($planIDList)->fetchAll('id'); + $planIDList = $planIDList ? explode(',', $planIDList) : array(); + $oldPlanIDList = $oldPlanIDList ? explode(',', $oldPlanIDList) : array(); - foreach($planStories as $planID => $stories) + /* Get the ids to be inserted and deleted by comparing plan ids. */ + $insertedPlanIDList = array_diff($planIDList, $oldPlanIDList); + $deletedPlanIDList = array_diff($oldPlanIDList, $planIDList); + + /* Delete old story sort of plan. */ + if(!empty($deletedPlanIDList)) { - $data = new stdClass(); - $data->order = implode(',', $stories); - $productPlan = $plans[$planID]; - if(!empty($productPlan->order)) $data->order = $data->order . ',' . $productPlan->order; + foreach($deletedPlanIDList as $planID) + { + $this->dao->delete()->from(TABLE_PLANSTORY)->where('plan')->eq($planID)->andWhere('story')->eq($storyID)->exec(); + } + } - $this->dao->update(TABLE_PRODUCTPLAN)->data($data)->where('id')->eq($planID)->exec(); + if(!empty($insertedPlanIDList)) + { + /* Get last story order of plan list. */ + $lastOrderOfPlans = $this->dao->select('plan, `order`')->from(TABLE_PLANSTORY)->where('plan')->in($insertedPlanIDList)->orderBy('order_asc')->fetchPairs(); + + foreach($insertedPlanIDList as $planID) + { + /* Set story order in new plan. */ + $data->plan = $planID; + $data->story = $storyID; + $data->order = zget($lastOrderOfPlans, $planID, 0) + 1; + + $this->dao->replace(TABLE_PLANSTORY)->data($data)->exec(); + } } } @@ -1047,8 +1067,10 @@ class storyModel extends model if(!dao::isError()) { - $this->executeHooks($storyID); + /* Update story sort of plan when the plan has changed. */ + if($oldStory->plan != $story->plan) $this->updateStoryOrderOfPlan($storyID, $story->plan, $oldStory->plan); + $this->executeHooks($storyID); $this->setStage($storyID); if($story->closedReason == 'done') $this->loadModel('score')->create('story', 'close'); $allChanges[$storyID] = common::createChanges($oldStory, $story); @@ -1418,6 +1440,10 @@ class storyModel extends model $story->plan = trim(str_replace(",$oldPlanID,", ',', ",$oldStory->plan,"), ','); if(empty($story->branch)) $story->plan .= ",$planID"; } + + /* Update the order of the story in the plan. */ + $this->updateStoryOrderOfPlan($storyID, $planID, $oldStory->plan); + /* Fix bug #3529. */ if($planID and $this->session->currentProductType != 'normal' and $oldStory->branch == 0) { @@ -2317,13 +2343,15 @@ class storyModel extends model */ public function getPlanStories($planID, $status = 'all', $orderBy = 'id_desc', $pager = null) { - $stories = $this->dao->select('*')->from(TABLE_STORY) - ->where("CONCAT(',', plan, ',')")->like("%,$planID,%") - ->beginIF($status and $status != 'all')->andWhere('status')->in($status)->fi() - ->andWhere('deleted')->eq(0) + $stories = $this->dao->select('distinct t1.story, t1.plan, t1.order, t2.*') + ->from(TABLE_PLANSTORY)->alias('t1') + ->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id') + ->where('t1.plan')->eq($planID) + ->beginIF($status and $status != 'all')->andWhere('t2.status')->in($status)->fi() + ->andWhere('t2.deleted')->eq(0) ->orderBy($orderBy)->page($pager)->fetchAll('id'); - $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'story'); + $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'story', false); return $stories; } @@ -3693,32 +3721,40 @@ class storyModel extends model } /** - * sortPlanStory + * Update the story order according to the plan. * - * @param int $planStories - * @param string $order + * @param int $planID + * @param array $sortIDList * @param string $orderBy + * @param int $pageID + * @param int $recPerPage * @access public * @return void */ - public function sortPlanStory($planStories, $order = '', $orderBy = 'order_asc') + public function sortStoriesOfPlan($planID, $sortIDList, $orderBy = 'id_desc', $pageID = 1, $recPerPage = 100) { - $stories = array(); - if(!empty($order)) + /* Append id for secend sort. */ + $orderBy = $this->loadModel('common')->appendOrder($orderBy); + + /* Get all stories by plan. */ + $stories = $this->getPlanStories($planID, 'all', $orderBy); + $storyIDList = array_keys($stories); + + /* Calculate how many numbers there are before the sort list and after the sort list. */ + $frontStoryCount = $recPerPage * ($pageID - 1); + $behindStoryCount = $recPerPage * $pageID; + $frontStoryIDList = array_slice($storyIDList, 0, $frontStoryCount); + $behindStoryIDList = array_slice($storyIDList, $behindStoryCount, count($storyIDList) - $behindStoryCount); + + /* Merge to get a new sort list. */ + $newSortIDList = array_merge($frontStoryIDList, $sortIDList, $behindStoryIDList); + + /* Loop update the story order of plan. */ + $order = 1; + foreach($newSortIDList as $storyID) { - if(is_string($order)) $order = explode(',', $order); - if(strpos($orderBy, 'desc') !== false) $order = array_reverse($order, true); - - foreach($order as $id) - { - if(empty($id)) continue; - if(!isset($planStories[$id])) continue; - $stories[$id] = $planStories[$id]; - unset($planStories[$id]); - } - - if($planStories) $stories += $planStories; + $this->dao->update(TABLE_PLANSTORY)->set('`order`')->eq($order)->where('story')->eq($storyID)->andWhere('plan')->eq($planID)->exec(); + $order++; } - return $stories; } } diff --git a/module/upgrade/model.php b/module/upgrade/model.php index 69a203444c..1e5fc9ec0c 100644 --- a/module/upgrade/model.php +++ b/module/upgrade/model.php @@ -610,8 +610,8 @@ class upgradeModel extends model $this->saveLogs('Execute 20_0'); $this->execSQL($this->getUpgradeFile('20.0')); $this->setWork2Full(); - $this->appendExec('20_0'); $this->initStoryOfPlan(); + $this->appendExec('20_0'); } $this->deletePatch(); @@ -4110,7 +4110,7 @@ class upgradeModel extends model * Init story sort of plan. * * @access public - * @return void + * @return bool */ public function initStoryOfPlan() {