diff --git a/db/update17.6.sql b/db/update17.6.sql index 9d9d37cf92..68e4b95191 100644 --- a/db/update17.6.sql +++ b/db/update17.6.sql @@ -13,4 +13,5 @@ CREATE TABLE `zt_taskteam` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8; ALTER TABLE `zt_taskestimate` ADD `order` tinyint unsigned NULL DEFAULT '0'; ALTER TABLE `zt_effort` ADD `order` tinyint unsigned NOT NULL DEFAULT '0' AFTER `end`; -ALTER TABLE `zt_block` CHANGE `block` `block` varchar(30) COLLATE 'utf8_general_ci' NOT NULL AFTER `source`; +ALTER TABLE `zt_storyspec` ADD `files` text NOT NULL AFTER `verify`; +ALTER TABLE `zt_block` CHANGE `block` `block` varchar(30) COLLATE 'utf8_general_ci' NOT NULL AFTER `source`; \ No newline at end of file diff --git a/db/zentao.sql b/db/zentao.sql index 9cc580a01d..d5266fc5e3 100755 --- a/db/zentao.sql +++ b/db/zentao.sql @@ -1504,6 +1504,7 @@ CREATE TABLE IF NOT EXISTS `zt_storyspec` ( `title` varchar(255) NOT NULL, `spec` mediumtext NOT NULL, `verify` mediumtext NOT NULL, + `files` text NOT NULL, UNIQUE KEY `story` (`story`,`version`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- DROP TABLE IF EXISTS `zt_storystage`; diff --git a/module/bug/control.php b/module/bug/control.php index 2ed87d9010..66a0585929 100755 --- a/module/bug/control.php +++ b/module/bug/control.php @@ -969,17 +969,15 @@ class bug extends control return print(js::error(dao::getError())); } } - $files = $this->loadModel('file')->saveUpload('bug', $bugID); - if(empty($files) and $this->post->uid != '' and isset($_SESSION['album']['used'][$this->post->uid])) $files = $this->file->getPairs($_SESSION['album']['used'][$this->post->uid]); } - if($this->post->comment != '' or !empty($changes) or !empty($files)) + + if($this->post->comment != '' or !empty($changes)) { - $action = (!empty($changes) or !empty($files)) ? 'Edited' : 'Commented'; - $fileAction = ''; - if(!empty($files)) $fileAction = $this->lang->addFiles . join(',', $files) . "\n" ; - $actionID = $this->action->create('bug', $bugID, $action, $fileAction . $this->post->comment); + $action = !empty($changes) ? 'Edited' : 'Commented'; + $actionID = $this->action->create('bug', $bugID, $action, $this->post->comment); $this->action->logHistory($actionID, $changes); } + if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'success', 'data' => $bugID)); $bug = $this->bug->getById($bugID); diff --git a/module/bug/model.php b/module/bug/model.php index 276cffcb02..b7f1c4718a 100644 --- a/module/bug/model.php +++ b/module/bug/model.php @@ -687,7 +687,7 @@ class bugModel extends model */ public function update($bugID) { - $oldBug = $this->dao->select('*')->from(TABLE_BUG)->where('id')->eq((int)$bugID)->fetch(); + $oldBug = $this->getById($bugID); if(!empty($_POST['lastEditedDate']) and $oldBug->lastEditedDate != $this->post->lastEditedDate) { dao::$errors[] = $this->lang->error->editedByOther; @@ -707,6 +707,7 @@ class bugModel extends model ->setDefault('resolvedDate', '0000-00-00 00:00:00') ->setDefault('lastEditedBy', $this->app->user->account) ->setDefault('mailto', '') + ->setDefault('deleteFiles', array()) ->add('lastEditedDate', $now) ->setIF(strpos($this->config->bug->edit->requiredFields, 'deadline') !== false, 'deadline', $this->post->deadline) ->join('openedBuild', ',') @@ -736,7 +737,7 @@ class bugModel extends model ->get(); $bug = $this->loadModel('file')->processImgURL($bug, $this->config->bug->editor->edit['id'], $this->post->uid); - $this->dao->update(TABLE_BUG)->data($bug) + $this->dao->update(TABLE_BUG)->data($bug, 'deleteFiles') ->autoCheck() ->batchCheck($this->config->bug->edit->requiredFields, 'notempty') ->checkIF($bug->resolvedBy, 'resolution', 'notempty') @@ -783,7 +784,23 @@ class bugModel extends model } if(!empty($bug->resolvedBy)) $this->loadModel('score')->create('bug', 'resolve', $bugID); + + $oldBugFiles = empty($oldBug->files) ? '' : join(',', array_keys($oldBug->files)); + if(!empty($bug->deleteFiles)) + { + $this->dao->delete()->from(TABLE_FILE)->where('id')->in($bug->deleteFiles)->exec(); + foreach($bug->deleteFiles as $fileID) + { + @unlink($oldBug->files[$fileID]->realPath); + $oldBugFiles = empty($oldBugFiles) ? '' : str_replace(",$fileID,", ',', ",$oldBugFiles,"); + } + } + $this->file->updateObjectID($this->post->uid, $bugID, 'bug'); + $addedFiles = $this->loadModel('file')->saveUpload('bug', $bugID); + $addedFiles = empty($addedFiles) ? '' : ',' . join(',', array_keys($addedFiles)); + $bug->files = trim($oldBugFiles . $addedFiles, ','); + $oldBug->files = join(',', array_keys($oldBug->files)); if($bug->execution and $bug->status != $oldBug->status) $this->loadModel('kanban')->updateLane($bug->execution, 'bug'); diff --git a/module/bug/view/edit.html.php b/module/bug/view/edit.html.php index d2462c3443..1b662bb77e 100644 --- a/module/bug/view/edit.html.php +++ b/module/bug/view/edit.html.php @@ -72,7 +72,10 @@ if($this->app->tab == 'project') js::set('objectID', $bug->project); printExtendFields($bug, 'div', 'position=left');?>
files;?>
-
fetch('file', 'buildform');?>
+
+ fetch('file', 'printFiles', array('files' => $bug->files, 'fieldset' => 'false', 'object' => $bug, 'method' => 'edit'));?> + fetch('file', 'buildform');?> +
diff --git a/module/bug/view/view.html.php b/module/bug/view/view.html.php index 9be88c271a..d0a7ad32fd 100644 --- a/module/bug/view/view.html.php +++ b/module/bug/view/view.html.php @@ -73,7 +73,7 @@ ?>
- fetch('file', 'printFiles', array('files' => $bug->files, 'fieldset' => 'true', 'object' => $bug));?> + fetch('file', 'printFiles', array('files' => $bug->files, 'fieldset' => 'true', 'object' => $bug, 'method' => 'view', 'showDelete' => false));?> createLink('action', 'comment', "objectType=bug&objectID=$bug->id"); diff --git a/module/common/lang/de.php b/module/common/lang/de.php index 3de060ef37..91ed8d50d1 100644 --- a/module/common/lang/de.php +++ b/module/common/lang/de.php @@ -100,7 +100,6 @@ $lang->saveSuccess = 'Gespeichert'; $lang->importSuccess = 'Gespeichert'; $lang->fail = 'Fehlgeschlagen'; $lang->addFiles = 'Hinzufügen '; -$lang->deleteFiles = 'Anhang gelöscht '; $lang->files = 'Datei '; $lang->pasteText = 'Einfügen'; $lang->uploadImages = 'Hochladen'; diff --git a/module/common/lang/en.php b/module/common/lang/en.php index c4bba1c349..4dac83fa31 100644 --- a/module/common/lang/en.php +++ b/module/common/lang/en.php @@ -100,7 +100,6 @@ $lang->saveSuccess = 'Saved'; $lang->importSuccess = 'Saved'; $lang->fail = 'Fail'; $lang->addFiles = 'Added Files '; -$lang->deleteFiles = 'Deleted Files '; $lang->files = 'Files '; $lang->pasteText = 'Multi-line Paste'; $lang->uploadImages = 'Multi-image Upload'; diff --git a/module/common/lang/fr.php b/module/common/lang/fr.php index aec37d0a92..67caf6b5fd 100644 --- a/module/common/lang/fr.php +++ b/module/common/lang/fr.php @@ -100,7 +100,6 @@ $lang->saveSuccess = 'Sauvegardé'; $lang->importSuccess = 'Sauvé'; $lang->fail = 'Echec'; $lang->addFiles = 'Fichiers ajoutés '; -$lang->deleteFiles = 'Pièce jointe supprimée '; $lang->files = 'Fichiers '; $lang->pasteText = 'Collage Multi-lignes'; $lang->uploadImages = 'Upload Multi-images'; diff --git a/module/common/lang/vi.php b/module/common/lang/vi.php index 0113ca2d00..dd4c0ef845 100644 --- a/module/common/lang/vi.php +++ b/module/common/lang/vi.php @@ -79,7 +79,6 @@ $lang->saveSuccess = 'Đã lưu'; $lang->importSuccess = 'Đã lưu'; $lang->fail = 'Thất bại'; $lang->addFiles = 'Tập tin đã thêm '; -$lang->deleteFiles = 'Tháo ảnh '; $lang->files = 'Files '; $lang->pasteText = 'Dán nhiều dòng'; $lang->uploadImages = 'Tải lên nhiều ảnh'; diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php index 8080576b61..a27488d59e 100644 --- a/module/common/lang/zh-cn.php +++ b/module/common/lang/zh-cn.php @@ -100,7 +100,6 @@ $lang->saveSuccess = '保存成功'; $lang->importSuccess = '导入成功'; $lang->fail = '失败'; $lang->addFiles = '上传了附件 '; -$lang->deleteFiles = '删除了附件 '; $lang->files = '附件 '; $lang->pasteText = '多项录入'; $lang->uploadImages = '多图上传 '; diff --git a/module/file/model.php b/module/file/model.php index d664584737..1d61646733 100755 --- a/module/file/model.php +++ b/module/file/model.php @@ -46,25 +46,23 @@ class fileModel extends model ->where('objectType')->eq($objectType) ->andWhere('objectID')->eq((int)$objectID) ->andWhere('extra')->ne('editor') - ->beginIF(strpos('story,requirement', $objectType) !== false and $extra)->andWhere('extra')->like("%,$extra,%")->fi() - ->beginIF(strpos('story,requirement', $objectType) === false and $extra)->andWhere('extra')->eq($extra)->fi() + ->beginIF($extra)->andWhere('extra')->eq($extra) ->andWhere('deleted')->eq('0') ->orderBy('id') ->fetchAll('id'); foreach($files as $file) { - if($objectType != 'traincourse' and $objectType != 'traincontents') - { - $realPathName = $this->getRealPathName($file->pathname); - $file->realPath = $this->savePath . $realPathName; - $file->webPath = $this->webPath . $realPathName; - } - else + if($objectType == 'traincourse' or $objectType == 'traincontents') { $file->realPath = $this->app->getWwwRoot() . 'data/course/' . $file->pathname; $file->webPath = 'data/course/' . $file->pathname; + continue; } + + $realPathName = $this->getRealPathName($file->pathname); + $file->realPath = $this->savePath . $realPathName; + $file->webPath = $this->webPath . $realPathName; } return $files; @@ -81,33 +79,52 @@ class fileModel extends model { $file = $this->dao->findById($fileID)->from(TABLE_FILE)->fetch(); if(empty($file)) return false; - if($file->objectType != 'traincourse' and $file->objectType != 'traincontents') - { - $realPathName = $this->getRealPathName($file->pathname); - $file->realPath = $this->savePath . $realPathName; - $file->webPath = $this->webPath . $realPathName; - } - else - { - $file->realPath = $this->app->getWwwRoot() . 'data/course/' . $file->pathname; - $file->webPath = $this->app->getWebRoot() . 'data/course/' . $file->pathname; - } - if($file->objectType != 'traincourse' and $file->objectType != 'traincontents') - { - $realPathName = $this->getRealPathName($file->pathname); - $file->realPath = $this->savePath . $realPathName; - $file->webPath = $this->webPath . $realPathName; - } - else + if($file->objectType == 'traincourse' or $file->objectType == 'traincontents') { $file->realPath = $this->app->getWwwRoot() . 'data/course/' . $file->pathname; $file->webPath = 'data/course/' . $file->pathname; + + return $file; } + $realPathName = $this->getRealPathName($file->pathname); + $file->realPath = $this->savePath . $realPathName; + $file->webPath = $this->webPath . $realPathName; + return $file; } + /** + * Get files by ID list. + * + * @param int $fileIdList + * @access public + * @return array + */ + public function getByIdList($fileIdList) + { + if(empty($fileIdList)) return array(); + + $files = $this->dao->select('*')->from(TABLE_FILE)->where('id')->in($fileIdList)->orderBy('id')->fetchAll('id'); + + foreach($files as $file) + { + if($file->objectType == 'traincourse' or $file->objectType == 'traincontents') + { + $file->realPath = $this->app->getWwwRoot() . 'data/course/' . $file->pathname; + $file->webPath = 'data/course/' . $file->pathname; + continue; + } + + $realPathName = $this->getRealPathName($file->pathname); + $file->realPath = $this->savePath . $realPathName; + $file->webPath = $this->webPath . $realPathName; + } + + return $files; + } + /** * Save upload. * @@ -1119,62 +1136,4 @@ class fileModel extends model $this->dao->update(TABLE_CASE)->set('`fromCaseVersion`')->eq($fromcaseVersion)->where('`fromCaseID`')->eq($file->objectID)->exec(); } } - - /** - * Update version of story files. - * - * @param int $storyID - * @param int $storyVersion - * @param array $deleteFiles - * @access public - * @return void - */ - public function updateStoryFileVersion($storyID, $storyVersion, $deleteFiles = array()) - { - $oldStoryVersion = $storyVersion - 1; - $this->dao->update(TABLE_FILE)->set("extra = CONCAT(extra, '$storyVersion,')") - ->where('objectType')->in('story,requirement') - ->andWhere('objectID')->eq($storyID) - ->andWhere('extra')->like("%,$oldStoryVersion,%") - ->beginIF(!empty($deleteFiles))->andWhere('id')->notin($deleteFiles)->fi() - ->exec(); - } - - /** - * Delete story file. - * - * @param int $storyID - * @param int $storyVersion - * @param array $deleteFiles - * @access public - * @return void - */ - public function deleteStoryFile($storyID, $storyVersion, $deleteFiles = array()) - { - $deleteFileList = $this->dao->select('*')->from(TABLE_FILE) - ->where('objectType')->in('story,requirement') - ->andWhere('objectID')->eq($storyID) - ->andWhere('extra')->eq(",$storyVersion,") - ->beginIF(!empty($deleteFiles))->andWhere('id')->in($deleteFiles)->fi() - ->fetchAll('id'); - - if(!empty($deleteFileList)) - { - $this->dao->delete()->from(TABLE_FILE)->where('id')->in(array_keys($deleteFileList))->exec(); - - foreach($deleteFileList as $file) - { - $realPathName = $this->getRealPathName($file->pathname); - @unlink($realPathName); - } - } - - /* When the file is in multiple story versions, 'extra' need delete the version to be deleted. */ - $this->dao->update(TABLE_FILE)->set("extra = REPLACE(extra, '$storyVersion,', '')") - ->where('objectType')->in('story,requirement') - ->andWhere('objectID')->eq($storyID) - ->andWhere('extra')->like("%,$storyVersion,%") - ->beginIF(!empty($deleteFiles))->andWhere('id')->in($deleteFiles)->fi() - ->exec(); - } } diff --git a/module/story/control.php b/module/story/control.php index 9153b27453..b29572e3e1 100644 --- a/module/story/control.php +++ b/module/story/control.php @@ -863,7 +863,6 @@ class story extends control $this->view->reviewers = array_keys($reviewerList); $this->view->reviewedReviewer = $reviewedReviewer; $this->view->productReviewers = $this->user->getPairs('noclosed|nodeleted', array_keys($reviewerList), 0, $productReviewers); - $this->view->files = $this->file->getByObject($story->type, $storyID, $story->version); $this->display(); } @@ -1080,25 +1079,17 @@ class story extends control $this->loadModel('file'); if(!empty($_POST)) { - $deleteFiles = isset($_POST['deleteFiles']) ? $this->file->getPairs($_POST['deleteFiles'], 'title') : array(); - $changes = $this->story->change($storyID); + $changes = $this->story->change($storyID); if(dao::isError()) { if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'fail', 'message' => dao::getError())); return print(js::error(dao::getError())); } - $story = $this->story->getByID($storyID); - $version = $this->dao->findById($storyID)->from(TABLE_STORY)->fetch('version'); - $files = $this->file->saveUpload($story->type, $storyID, ",$version,"); - if(empty($files) and $this->post->uid != '' and isset($_SESSION['album']['used'][$this->post->uid])) $files = $this->file->getPairs($_SESSION['album']['used'][$this->post->uid]); - - if($this->post->comment != '' or !empty($changes) or !empty($files) or !empty($deleteFiles)) + if($this->post->comment != '' or !empty($changes)) { - $action = (!empty($changes) or !empty($files)) ? 'Changed' : 'Commented'; - $fileAction = empty($files) ? '' : $this->lang->addFiles . join(',', $files) . "\n" ; - $fileAction .= empty($deleteFiles) ? '' : $this->lang->deleteFiles . join(',', $deleteFiles) . "\n"; - $actionID = $this->action->create('story', $storyID, $action, $fileAction . $this->post->comment); + $action = !empty($changes) ? 'Changed' : 'Commented'; + $actionID = $this->action->create('story', $storyID, $action, $this->post->comment); $this->action->logHistory($actionID, $changes); } @@ -1148,7 +1139,7 @@ class story extends control $this->app->loadLang('testcase'); $this->app->loadLang('execution'); - $story = $this->story->getById($storyID); + $story = $this->view->story; $reviewer = $this->story->getReviewerPairs($storyID, $story->version); $product = $this->loadModel('product')->getByID($story->product); @@ -1163,7 +1154,6 @@ class story extends control $this->view->needReview = (($this->app->user->account == $this->view->product->PO or $this->config->story->needReview == 0) and empty($reviewer)) ? "checked='checked'" : ""; $this->view->reviewer = implode(',', array_keys($reviewer)); $this->view->productReviewers = $this->user->getPairs('noclosed|nodeleted', $reviewer, 0, $productReviewers); - $this->view->files = $this->file->getByObject($story->type, $storyID, $story->version); $this->display(); } @@ -1250,7 +1240,6 @@ class story extends control $this->story->replaceURLang($story->type); - $story->files = $this->loadModel('file')->getByObject($story->type, $storyID, $version); $product = $this->dao->findById($story->product)->from(TABLE_PRODUCT)->fields('name, id, type, status')->fetch(); $plan = $this->dao->findById($story->plan)->from(TABLE_PRODUCTPLAN)->fetch('title'); $bugs = $this->dao->select('id,title,status,pri,severity')->from(TABLE_BUG)->where('story')->eq($storyID)->andWhere('deleted')->eq(0)->fetchAll(); diff --git a/module/story/model.php b/module/story/model.php index 93040402d1..115e81a7e9 100644 --- a/module/story/model.php +++ b/module/story/model.php @@ -30,18 +30,20 @@ class storyModel extends model ->fetch(); if(!$story) return false; + $this->loadModel('file'); if(helper::isZeroDate($story->closedDate)) $story->closedDate = ''; if($version == 0) $version = $story->version; - $spec = $this->dao->select('title,spec,verify')->from(TABLE_STORYSPEC)->where('story')->eq($storyID)->andWhere('version')->eq($version)->fetch(); + $spec = $this->dao->select('title,spec,verify,files')->from(TABLE_STORYSPEC)->where('story')->eq($storyID)->andWhere('version')->eq($version)->fetch(); $story->title = isset($spec->title) ? $spec->title : ''; $story->spec = isset($spec->spec) ? $spec->spec : ''; $story->verify = isset($spec->verify) ? $spec->verify : ''; + $story->files = isset($spec->files) ? $this->file->getByIdList($spec->files) : ''; if(!empty($story->fromStory)) $story->sourceName = $this->dao->select('title')->from(TABLE_STORY)->where('id')->eq($story->fromStory)->fetch('title'); /* Check parent story. */ if($story->parent > 0) $story->parentName = $this->dao->findById($story->parent)->from(TABLE_STORY)->fetch('title'); - $story = $this->loadModel('file')->replaceImgURL($story, 'spec,verify'); + $story = $this->file->replaceImgURL($story, 'spec,verify'); if($setImgSize) $story->spec = $this->file->setImgSize($story->spec); if($setImgSize) $story->verify = $this->file->setImgSize($story->verify); @@ -264,21 +266,22 @@ class storyModel extends model $this->subdivide($story->parent, $stories); } - $this->file->updateObjectID($this->post->uid, $storyID, $story->type); - $this->file->saveUpload($story->type, $storyID, ',1,'); - if(!empty($story->plan)) { $this->updateStoryOrderOfPlan($storyID, $story->plan); // Set story order in this plan. $this->loadModel('action')->create('productplan', $story->plan, 'linkstory', '', $storyID); } + $this->file->updateObjectID($this->post->uid, $storyID, $story->type); + $files = $this->file->saveUpload($story->type, $storyID, 1); + $data = new stdclass(); $data->story = $storyID; $data->version = 1; $data->title = $story->title; $data->spec = $story->spec; $data->verify = $story->verify; + $data->files = join(',', array_keys($files)); $this->dao->insert(TABLE_STORYSPEC)->data($data)->exec(); /* Save the story reviewer to storyreview table. */ @@ -658,11 +661,7 @@ class storyModel extends model public function change($storyID) { $specChanged = false; - $oldStory = $this->dao->findById((int)$storyID)->from(TABLE_STORY)->fetch(); - $oldSpec = $this->dao->select('title,spec,verify')->from(TABLE_STORYSPEC)->where('story')->eq((int)$storyID)->andWhere('version')->eq($oldStory->version)->fetch(); - $oldStory->title = isset($oldSpec->title) ? $oldSpec->title : ''; - $oldStory->spec = isset($oldSpec->spec) ? $oldSpec->spec : ''; - $oldStory->verify = isset($oldSpec->verify) ? $oldSpec->verify : ''; + $oldStory = $this->getById($storyID); if(!empty($_POST['lastEditedDate']) and $oldStory->lastEditedDate != $this->post->lastEditedDate) { @@ -688,12 +687,13 @@ class storyModel extends model $oldStoryReviewers = $this->getReviewerPairs($storyID, $oldStory->version); $_POST['reviewer'] = isset($_POST['reviewer']) ? $_POST['reviewer'] : array(); $reviewerHasChanged = (array_diff(array_keys($oldStoryReviewers), $_POST['reviewer']) or array_diff($_POST['reviewer'], array_keys($oldStoryReviewers))); - if($story->spec != $oldStory->spec or $story->verify != $oldStory->verify or $story->title != $oldStory->title or $this->loadModel('file')->getCount() or $reviewerHasChanged or isset($_POST['deleteFiles'])) $specChanged = true; + if($story->spec != $oldStory->spec or $story->verify != $oldStory->verify or $story->title != $oldStory->title or $this->loadModel('file')->getCount() or $reviewerHasChanged or isset($story->deleteFiles)) $specChanged = true; $now = helper::now(); $story = fixer::input('post') ->callFunc('title', 'trim') ->setDefault('lastEditedBy', $this->app->user->account) + ->setDefault('deleteFiles', array()) ->add('id', $storyID) ->add('lastEditedDate', $now) ->setIF($specChanged, 'version', $oldStory->version + 1) @@ -706,11 +706,11 @@ class storyModel extends model ->setIF($specChanged and $oldStory->closedBy, 'closedDate', '0000-00-00') ->setIF(!$specChanged, 'status', $oldStory->status) ->stripTags($this->config->story->editor->change['id'], $this->config->allowedTags) - ->remove('files,labels,reviewer,comment,needNotReview,uid,deleteFiles') + ->remove('files,labels,reviewer,comment,needNotReview,uid') ->get(); $story = $this->loadModel('file')->processImgURL($story, $this->config->story->editor->change['id'], $this->post->uid); - $this->dao->update(TABLE_STORY)->data($story, 'spec,verify') + $this->dao->update(TABLE_STORY)->data($story, 'spec,verify,deleteFiles') ->autoCheck() ->batchCheck($this->config->story->change->requiredFields, 'notempty') ->checkFlow() @@ -720,20 +720,27 @@ class storyModel extends model { if($specChanged) { + $this->file->updateObjectID($this->post->uid, $storyID, 'story'); + $addedFiles = $this->file->saveUpload($oldStory->type, $storyID, $story->version); + $addedFiles = empty($addedFiles) ? '' : join(',', array_keys($addedFiles)) . ','; + $storyFiles = $oldStory->files = join(',', array_keys($oldStory->files)); + foreach($story->deleteFiles as $fileID) $storyFiles = str_replace(",$fileID,", ',', ",$storyFiles,"); + $data = new stdclass(); $data->story = $storyID; - $data->version = $oldStory->version + 1; + $data->version = $story->version; $data->title = $story->title; $data->spec = $story->spec; $data->verify = $story->verify; + $data->files = $story->files = $addedFiles . trim($storyFiles, ','); $this->dao->insert(TABLE_STORYSPEC)->data($data)->exec(); - $story = $this->getById($storyID); /* IF is story and has changed, update its relation version to new. */ if($oldStory->type == 'story') { + $newStory = $this->getById($storyID); $this->dao->update(TABLE_STORY)->set('URChanged')->eq(0)->where('id')->eq($oldStory->id)->exec(); - $this->updateStoryVersion($story); + $this->updateStoryVersion($newStory); } else { @@ -742,7 +749,7 @@ class storyModel extends model ->where('AType')->eq('requirement') ->andWhere('BType')->eq('story') ->andWhere('relation')->eq('subdivideinto') - ->andWhere('AID')->eq($story->id) + ->andWhere('AID')->eq($storyID) ->fetchPairs(); foreach($relations as $relationID) $this->dao->update(TABLE_STORY)->set('URChanged')->eq(1)->where('id')->eq($relationID)->exec(); @@ -763,13 +770,8 @@ class storyModel extends model $oldStory->reviewers = implode(',', array_keys($oldStoryReviewers)); $story->reviewers = implode(',', $_POST['reviewer']); } - - $deleteFiles = isset($_POST['deleteFiles']) ? $_POST['deleteFiles'] : array(); - if(!empty($deleteFiles)) $this->file->deleteStoryFile($story->id, $story->version, $deleteFiles); - $this->file->updateStoryFileVersion($story->id, $story->version, $deleteFiles); } - $this->file->updateObjectID($this->post->uid, $storyID, 'story'); return common::createChanges($oldStory, $story); } } @@ -784,7 +786,7 @@ class storyModel extends model public function update($storyID) { $now = helper::now(); - $oldStory = $this->dao->select('*')->from(TABLE_STORY)->where('id')->eq($storyID)->fetch(); + $oldStory = $this->getById($storyID); if(!empty($_POST['lastEditedDate']) and $oldStory->lastEditedDate != $this->post->lastEditedDate) { dao::$errors[] = $this->lang->error->editedByOther; @@ -797,11 +799,6 @@ class storyModel extends model return false; } - $oldSpec = $this->dao->select('title,spec,verify')->from(TABLE_STORYSPEC)->where('story')->eq((int)$storyID)->andWhere('version')->eq($oldStory->version)->fetch(); - $oldStory->title = isset($oldSpec->title) ? $oldSpec->title : ''; - $oldStory->spec = isset($oldSpec->spec) ? $oldSpec->spec : ''; - $oldStory->verify = isset($oldSpec->verify) ? $oldSpec->verify : ''; - $story = fixer::input('post') ->cleanInt('product,module,pri,duplicateStory') ->cleanFloat('estimate') @@ -812,6 +809,7 @@ class storyModel extends model ->setDefault('spec', $oldStory->spec) ->setDefault('verify', $oldStory->verify) ->setDefault('mailto', '') + ->setDefault('deleteFiles', array()) ->add('id', $storyID) ->add('lastEditedDate', $now) ->setDefault('plan,notifyEmail', '') @@ -831,7 +829,7 @@ class storyModel extends model ->join('linkStories', ',') ->join('linkRequirements', ',') ->join('childStories', ',') - ->remove('files,labels,comment,contactListMenu,stages,reviewer,needNotReview,deleteFiles') + ->remove('files,labels,comment,contactListMenu,stages,reviewer,needNotReview') ->get(); if($oldStory->type == 'story' and !isset($story->linkStories)) $story->linkStories = ''; @@ -904,7 +902,7 @@ class storyModel extends model } $this->dao->update(TABLE_STORY) - ->data($story, 'reviewers,spec,verify,finalResult') + ->data($story, 'reviewers,spec,verify,finalResult,deleteFiles') ->autoCheck() ->checkIF(isset($story->closedBy), 'closedReason', 'notempty') ->checkIF(isset($story->closedReason) and $story->closedReason == 'done', 'stage', 'notempty') @@ -916,12 +914,20 @@ class storyModel extends model if(!dao::isError()) { - if($story->spec != $oldStory->spec or $story->verify != $oldStory->verify or $story->title != $oldStory->title) + $this->file->updateObjectID($this->post->uid, $storyID, 'story'); + $addedFiles = $this->file->saveUpload($oldStory->type, $storyID, $oldStory->version); + + if($story->spec != $oldStory->spec or $story->verify != $oldStory->verify or $story->title != $oldStory->title or !empty($story->deleteFiles) or !empty($addedFiles)) { + $addedFiles = empty($addedFiles) ? '' : join(',', array_keys($addedFiles)) . ','; + $storyFiles = $oldStory->files = join(',', array_keys($oldStory->files)); + foreach($story->deleteFiles as $fileID) $storyFiles = str_replace(",$fileID,", ',', ",$storyFiles,"); + $data = new stdclass(); $data->title = $story->title; $data->spec = $story->spec; $data->verify = $story->verify; + $data->files = $story->files = $addedFiles . trim($storyFiles, ','); $this->dao->update(TABLE_STORYSPEC)->data($data)->where('story')->eq((int)$storyID)->andWhere('version')->eq($oldStory->version)->exec(); } @@ -1040,21 +1046,13 @@ class storyModel extends model } } - $changes = common::createChanges($oldStory, $story); - $deleteFiles = isset($_POST['deleteFiles']) ? $this->file->getPairs($_POST['deleteFiles'], 'title') : array(); - - if(isset($_POST['deleteFiles'])) $this->file->deleteStoryFile($storyID, $oldStory->version, $_POST['deleteFiles']); - $this->file->updateObjectID($this->post->uid, $storyID, 'story'); - - $files = $this->file->saveUpload($oldStory->type, $storyID, ",$oldStory->version,"); + $changes = common::createChanges($oldStory, $story); if(empty($files) and $this->post->uid != '' and isset($_SESSION['album']['used'][$this->post->uid])) $files = $this->file->getPairs($_SESSION['album']['used'][$this->post->uid]); - if($this->post->comment != '' or !empty($changes) or !empty($files) or !empty($deleteFiles)) + if($this->post->comment != '' or !empty($changes)) { - $action = (!empty($changes) or !empty($files)) ? 'Edited' : 'Commented'; - $fileAction = empty($files) ? '' : $this->lang->addFiles . join(',', $files) . "\n" ; - $fileAction .= empty($deleteFiles) ? '' : $this->lang->deleteFiles . join(',', $deleteFiles) . "\n"; - $actionID = $this->action->create('story', $storyID, $action, $fileAction . $this->post->comment); + $action = !empty($changes) ? 'Edited' : 'Commented'; + $actionID = $this->action->create('story', $storyID, $action, $this->post->comment); $this->action->logHistory($actionID, $changes); if(isset($story->finalResult)) $this->recordReviewAction($story); @@ -1609,8 +1607,6 @@ class storyModel extends model /* Delete versions that is after this version. */ $this->dao->delete()->from(TABLE_STORYSPEC)->where('story')->eq($storyID)->andWHere('version')->eq($story->version)->exec(); $this->dao->delete()->from(TABLE_STORYREVIEW)->where('story')->eq($storyID)->andWhere('version')->eq($story->version)->exec(); - - $this->loadModel('file')->deleteStoryFile($storyID, $story->version); } /** @@ -5620,8 +5616,6 @@ class storyModel extends model /* Delete versions that is after this version. */ $this->dao->delete()->from(TABLE_STORYSPEC)->where('story')->eq($story->id)->andWHere('version')->in($oldStory->version)->exec(); $this->dao->delete()->from(TABLE_STORYREVIEW)->where('story')->eq($story->id)->andWhere('version')->in($oldStory->version)->exec(); - - $this->file->deleteStoryFile($story->id, $oldStory->version); } if($result == 'reject') diff --git a/module/story/view/change.html.php b/module/story/view/change.html.php index 157e16aed3..af6fcf4670 100644 --- a/module/story/view/change.html.php +++ b/module/story/view/change.html.php @@ -68,7 +68,7 @@ attatch;?> - fetch('file', 'printFiles', array('files' => $files, 'fieldset' => 'false', 'object' => $story, 'method' => 'edit'));?> + fetch('file', 'printFiles', array('files' => $story->files, 'fieldset' => 'false', 'object' => $story, 'method' => 'edit'));?> fetch('file', 'buildform');?> diff --git a/module/story/view/edit.html.php b/module/story/view/edit.html.php index 62528e92cd..9ee361c6cb 100644 --- a/module/story/view/edit.html.php +++ b/module/story/view/edit.html.php @@ -85,13 +85,13 @@ status) !== false ? html::textarea('verify', htmlSpecialString($story->verify), "rows='5' class='form-control'") : $story->verify;?> - status) === false and empty($files)) ? false : true;?> + status) === false and empty($story->files)) ? false : true;?>
attatch;?>
status) !== false ? true : false;?> - fetch('file', 'printFiles', array('files' => $files, 'fieldset' => 'false', 'object' => $story, 'method' => 'edit', 'showDelete' => $canChangeFile));?> + fetch('file', 'printFiles', array('files' => $story->files, 'fieldset' => 'false', 'object' => $story, 'method' => 'edit', 'showDelete' => $canChangeFile));?> fetch('file', 'buildform') : '';?>
diff --git a/module/task/control.php b/module/task/control.php index 6349caefa5..c847bc4a05 100755 --- a/module/task/control.php +++ b/module/task/control.php @@ -537,20 +537,16 @@ class task extends control { $this->loadModel('action'); $changes = array(); - $files = array(); if($comment == false) { $changes = $this->task->update($taskID); if(dao::isError()) return print(js::error(dao::getError())); - $files = $this->loadModel('file')->saveUpload('task', $taskID); - if(empty($files) and $this->post->uid != '' and isset($_SESSION['album']['used'][$this->post->uid])) $files = $this->file->getPairs($_SESSION['album']['used'][$this->post->uid]); } - if($this->post->comment != '' or !empty($changes) or !empty($files)) + if($this->post->comment != '' or !empty($changes)) { - $action = (!empty($changes) or !empty($files)) ? 'Edited' : 'Commented'; - $fileAction = !empty($files) ? $this->lang->addFiles . join(',', $files) . "\n" : ''; - $actionID = $this->action->create('task', $taskID, $action, $fileAction . $this->post->comment); + $action = !empty($changes) ? 'Edited' : 'Commented'; + $actionID = $this->action->create('task', $taskID, $action, $this->post->comment); if(!empty($changes)) $this->action->logHistory($actionID, $changes); } diff --git a/module/task/model.php b/module/task/model.php index b5628c937c..ee67294584 100755 --- a/module/task/model.php +++ b/module/task/model.php @@ -1075,6 +1075,7 @@ class taskModel extends model ->setDefault('story, estimate, left, consumed', 0) ->setDefault('realStarted', '0000-00-00 00:00:00') ->setDefault('mailto', '') + ->setDefault('deleteFiles', array()) ->setIF(is_numeric($this->post->estimate), 'estimate', (float)$this->post->estimate) ->setIF(is_numeric($this->post->consumed), 'consumed', (float)$this->post->consumed) ->setIF(is_numeric($this->post->left), 'left', (float)$this->post->left) @@ -1158,7 +1159,7 @@ class taskModel extends model $requiredFields = trim($requiredFields, ','); - $this->dao->update(TABLE_TASK)->data($task) + $this->dao->update(TABLE_TASK)->data($task, 'deleteFiles') ->autoCheck() ->batchCheckIF($task->status != 'cancel', $requiredFields, 'notempty') ->checkIF(!helper::isZeroDate($task->deadline), 'deadline', 'ge', $task->estStarted) @@ -1247,12 +1248,10 @@ class taskModel extends model if(!empty($changes)) $this->action->logHistory($actionID, $changes); } } - $this->file->updateObjectID($this->post->uid, $taskID, 'task'); unset($oldTask->parent); unset($task->parent); - if(($this->config->edition == 'biz' || $this->config->edition == 'max') && $oldTask->feedback) $this->loadModel('feedback')->updateStatus('task', $oldTask->feedback, $task->status, $oldTask->status); if(isset($oldTask->team)) @@ -1269,6 +1268,23 @@ class taskModel extends model } } + $oldTaskFiles = empty($oldTask->files) ? '' : join(',', array_keys($oldTask->files)); + if(!empty($task->deleteFiles)) + { + $this->dao->delete()->from(TABLE_FILE)->where('id')->in($task->deleteFiles)->exec(); + foreach($task->deleteFiles as $fileID) + { + @unlink($oldTask->files[$fileID]->realPath); + $oldTaskFiles = empty($oldTaskFiles) ? '' : str_replace(",$fileID,", ',', ",$oldTaskFiles,"); + } + } + + $this->file->updateObjectID($this->post->uid, $taskID, 'task'); + $addedFiles = $this->loadModel('file')->saveUpload('task', $taskID); + $addedFiles = empty($addedFiles) ? '' : ',' . join(',', array_keys($addedFiles)); + $task->files = trim($oldTaskFiles . $addedFiles, ','); + $oldTask->files = join(',', array_keys($oldTask->files)); + return common::createChanges($oldTask, $task); } } diff --git a/module/task/view/edit.html.php b/module/task/view/edit.html.php index fb56d27a51..bbbc880e28 100644 --- a/module/task/view/edit.html.php +++ b/module/task/view/edit.html.php @@ -88,7 +88,10 @@ foreach(explode(',', $config->task->edit->requiredFields) as $field) printExtendFields($task, 'div', 'position=left');?>
files;?>
-
fetch('file', 'buildform');?>
+
+ fetch('file', 'printFiles', array('files' => $task->files, 'fieldset' => 'false', 'object' => $task, 'method' => 'edit'));?> + fetch('file', 'buildform');?> +
lastEditedDate);?> diff --git a/module/task/view/view.html.php b/module/task/view/view.html.php index a6e677e952..5caec05056 100644 --- a/module/task/view/view.html.php +++ b/module/task/view/view.html.php @@ -147,7 +147,7 @@
fetch('file', 'printFiles', array('files' => $task->files, 'fieldset' => 'true', 'object' => $task)); + echo $this->fetch('file', 'printFiles', array('files' => $task->files, 'fieldset' => 'true', 'object' => $task, 'method' => 'view', 'showDelete' => false)); $canBeChanged = common::canBeChanged('task', $task); if($canBeChanged) $actionFormLink = $this->createLink('action', 'comment', "objectType=task&objectID=$task->id"); diff --git a/module/upgrade/model.php b/module/upgrade/model.php index cea27ce07e..246e45a258 100644 --- a/module/upgrade/model.php +++ b/module/upgrade/model.php @@ -7220,27 +7220,18 @@ class upgradeModel extends model { $storyFileList = $this->dao->select('*')->from(TABLE_FILE)->where('objectType')->in('story,requirement')->andWhere('extra')->ne('editor')->fetchAll('id'); - /* Get story version. */ - $storyIDList = array(); - foreach($storyFileList as $file) $storyIDList[$file->objectID] = $file->objectID; - $storyVersionList = $this->dao->select('id,version')->from(TABLE_STORY)->where('id')->in($storyIDList)->fetchPairs(); - + $storyFiles = array(); foreach($storyFileList as $file) { if(!is_numeric($file->extra)) continue; - $fileExtra = ''; - $storyVersion = $storyVersionList[$file->objectID]; - if($file->extra != $storyVersion) - { - for($i = $file->extra; $i <= $storyVersion; $i ++) $fileExtra .= ",$i"; - $fileExtra .= ','; - } - if(empty($fileExtra)) $fileExtra = ",$file->extra,"; + if(!isset($storyFiles[$file->objectID])) $storyFiles[$file->objectID] = ''; - $this->dao->update(TABLE_FILE)->set('extra')->eq($fileExtra)->where('id')->eq($file->id)->exec(); + $storyFiles[$file->objectID] .= "$file->id,"; } + foreach($storyFiles as $storyID => $files) $this->dao->update(TABLE_STORYSPEC)->set('files')->eq($files)->where('story')->eq($storyID)->exec(); + return true; } @@ -7252,7 +7243,6 @@ class upgradeModel extends model */ public function processFeedbackModule() { - $products = $this->dao->select('id, name')->from(TABLE_PRODUCT)->fetchAll(); $modules = $this->dao->select('*')->from(TABLE_MODULE)->where('type')->eq('feedback')->andWhere('root')->eq(0)->fetchAll('id'); $feedbacks = $this->dao->select('*')->from(TABLE_FEEDBACK)->fetchAll();