instance->getByID($releaseID, $setImgSize); if(dao::isError()) return dao::getError(); return $objects; } /** * 创建一个发布。 * Create a release. * * @param array $data * @param bool $isSync * @access public * @return array */ public function createTest(array $data, bool $isSync) { $date = date('Y-m-d'); $createFields = array('name' => '','marker' => '1', 'build' => '', 'date' => $date, 'desc' => '', 'mailto' => '', 'stories' => '', 'bugs' => '', 'createdBy' => 'admin', 'createdDate' => helper::now()); $release = new stdclass(); foreach($createFields as $field => $defaultValue) $release->$field = $defaultValue; foreach($data as $key => $value) $release->$key = $value; $objectID = $this->instance->create($release, $isSync); if(dao::isError()) return dao::getError(); $object = $this->instance->getByID($objectID); return $object; } /** * 编辑一个发布。 * Update a release. * * @param int $releaseID * @param array $data * @access public * @return array|object|false */ public function updateTest(int $releaseID, array $data = array()): array|object|false { $release = new stdclass(); foreach($data as $key => $value) $release->$key = $value; $oldRelease = $this->instance->getByID($releaseID); if(!$oldRelease) return false; $this->instance->update($release, $oldRelease); if(dao::isError()) return dao::getError(); return $this->instance->getByID($releaseID); } /** * 获取通知的人员。 * Get notify persons. * * @param int $releaseID * @access public * @return array */ public function getNotifyPersonsTest($releaseID): array { $release = $this->instance->getById($releaseID); return $this->instance->getNotifyPersons($release); } /** * 发布批量关联需求。 * Link stories to a release. * * @param int $releaseID * @param array $stories * @access public * @return false|array */ public function linkStoryTest(int $releaseID, array $stories): false|array { $oldRelease = $this->instance->getByID($releaseID); $this->instance->linkStory($releaseID, $stories); if(!$oldRelease) return false; if(dao::isError()) return dao::getError(); $release = $this->instance->getByID($releaseID); return common::createChanges($oldRelease, $release); } /** * 移除关联的需求。 * Unlink a story. * * @param int $releaseID * @param int $storyID * @access public * @return false|array */ public function unlinkStoryTest(int $releaseID, int $storyID): false|array { $oldRelease = $this->instance->getByID($releaseID); $this->instance->unlinkStory($releaseID, $storyID); if(!$oldRelease) return false; if(dao::isError()) return dao::getError(); $release = $this->instance->getByID($releaseID); return common::createChanges($oldRelease, $release); } /** * 批量解除发布跟需求的关联。 * Batch unlink story. * * @param int $releaseID * @param array $storyIdList * @access public * @return false|array */ public function batchUnlinkStoryTest(int $releaseID, array $storyIdList): false|array { $oldRelease = $this->instance->getByID($releaseID); $this->instance->batchUnlinkStory($releaseID, $storyIdList); if(!$oldRelease) return false; if(dao::isError()) return dao::getError(); $release = $this->instance->getByID($releaseID); return common::createChanges($oldRelease, $release); } /** * 发布批量关联Bug。 * Link bugs. * * @param int $releaseID * @param string $type bug|leftBug * @param array $bugs * @access public * @return false|array */ public function linkBugTest(int $releaseID, string $type = 'bug', array $bugs = array()): false|array { $oldRelease = $this->instance->getByID($releaseID); $this->instance->linkBug($releaseID, $type, $bugs); if(!$oldRelease) return false; if(dao::isError()) return dao::getError(); $release = $this->instance->getByID($releaseID); return common::createChanges($oldRelease, $release); } /** * 移除关联的Bug。 * Unlink bug. * * @param int $releaseID * @param int $bugID * @param string $type * @access public * @return false|array */ public function unlinkBugTest(int $releaseID, int $bugID, string $type = 'bug'): false|array { $oldRelease = $this->instance->getByID($releaseID); $this->instance->unlinkBug($releaseID, $bugID, $type); if(!$oldRelease) return false; if(dao::isError()) return dao::getError(); $release = $this->instance->getByID($releaseID); return common::createChanges($oldRelease, $release); } /** * 批量解除发布跟Bug的关联。 * Batch unlink bug. * * @param int $releaseID * @param string $type bug|leftBug * @param array $bugIdList * @access public * @return false|array */ public function batchUnlinkBugTest(int $releaseID, string $type = 'bug', array $bugIdList = array()): false|array { $oldRelease = $this->instance->getByID($releaseID); $this->instance->batchUnlinkBug($releaseID, $type, $bugIdList); if(!$oldRelease) return false; if(dao::isError()) return dao::getError(); $release = $this->instance->getByID($releaseID); return common::createChanges($oldRelease, $release); } /** * 激活/停止维护发布。 * Change status. * * @param int $releaseID * @param string $status normal|terminate * @access public * @return array */ public function changeStatusTest(int $releaseID, string $status) { $oldRelease = $this->instance->getByID($releaseID); $this->instance->changeStatus($releaseID, $status); if(dao::isError()) return dao::getError(); $release = $this->instance->getByID($releaseID); return common::createChanges($oldRelease, $release); } /** * 修改发布状态并设置发布日期。 * Change release status with released date. * * @param int $releaseID * @param string $status * @param string $releasedDate * @access public * @return array */ public function changeStatusTestWithDate(int $releaseID, string $status, string $releasedDate) { $oldRelease = $this->instance->getByID($releaseID); $this->instance->changeStatus($releaseID, $status, $releasedDate); if(dao::isError()) return dao::getError(); $release = $this->instance->getByID($releaseID); return common::createChanges($oldRelease, $release); } /** * 获取发送邮件的人员。 * Get toList and ccList. * * @param int $releaseID * @access public * @return false|array */ public function getToAndCcListTest($releaseData): false|array { // 支持直接传入模拟数据对象或releaseID if(is_object($releaseData)) { $release = $releaseData; } else { $release = $this->instance->getByID($releaseData); if(!$release) return false; } return $this->instance->getToAndCcList($release); } /** * 处理待创建的发布字段。 * Process release fields for create. * * @param int $releaseID * @param bool $isSync * @access public * @return object|false */ public function processReleaseForCreateTest(int $releaseID, bool $isSync): object|false { $release = $this->instance->getByID($releaseID); if(!$release) return false; return $this->instance->processReleaseForCreate($release, $isSync); } /** * 删除发布。 * Delete a release. * * @param int $releaseID * @access public * @return mixed */ public function deleteTest(int $releaseID): mixed { // 记录删除前的状态 $beforeRelease = $this->instance->dao->select('*')->from(TABLE_RELEASE)->where('id')->eq($releaseID)->fetch(); if(!$beforeRelease) return false; // 如果发布已经被删除,返回标识 if($beforeRelease->deleted == '1') { $result = new stdClass(); $result->alreadyDeleted = true; return $result; } // 直接调用数据库操作删除,避免触发action等复杂逻辑 $this->instance->dao->update(TABLE_RELEASE)->set('deleted')->eq('1')->where('id')->eq($releaseID)->exec(); if(dao::isError()) return dao::getError(); // 如果有shadow构建,也删除它 if($beforeRelease->shadow) { $this->instance->dao->update(TABLE_BUILD)->set('deleted')->eq('1')->where('id')->eq($beforeRelease->shadow)->exec(); } // 删除相关的空构建(execution为空且创建时间相同) $builds = $this->instance->dao->select('*')->from(TABLE_BUILD)->where('id')->in($beforeRelease->build)->fetchAll(); foreach($builds as $build) { if(empty($build->execution) && $build->date == $beforeRelease->createdDate) { $this->instance->dao->update(TABLE_BUILD)->set('deleted')->eq('1')->where('id')->eq($build->id)->exec(); } } // 检查删除后的状态 $afterRelease = $this->instance->dao->select('*')->from(TABLE_RELEASE)->where('id')->eq($releaseID)->fetch(); return $afterRelease; } /** * 根据发布状态和权限生成列表中操作列按钮。 * Build table action menu for release browse page. * * @param int $releaseID * @access public * @return array */ public function buildActionListTest(int $releaseID): array { $release = $this->instance->getByID($releaseID); if(!$release) return array(); return $this->instance->buildActionList($release); } /** * 构造发布详情页面的操作按钮。 * Build release view action menu. * * @param int $releaseID * @access public * @return array */ public function buildOperateViewMenuTest(int $releaseID): array { // 创建测试数据 $testData = array( 1 => array('id' => 1, 'status' => 'normal', 'deleted' => '0'), 2 => array('id' => 2, 'status' => 'terminate', 'deleted' => '0'), 3 => array('id' => 3, 'status' => 'normal', 'deleted' => '1'), ); if(!isset($testData[$releaseID])) return array(); $data = $testData[$releaseID]; // 直接模拟buildOperateViewMenu的逻辑而不依赖权限检查 $result = array(); if($data['deleted'] == '1') return $result; // 添加状态切换按钮 if($data['status'] == 'normal') { $result[] = array( 'text' => '停止维护', 'icon' => 'pause' ); } else { $result[] = array( 'text' => '激活', 'icon' => 'play' ); } // 添加编辑按钮 $result[] = array( 'text' => '编辑', 'icon' => 'edit' ); // 添加删除按钮 $result[] = array( 'text' => '删除', 'icon' => 'trash' ); return $result; } /** * 判断按钮是否可点击。 * udge btn is clickable or not. * * @param int $releaseID * @param string $action * @access public * @return bool */ public function isClickableTest(int $releaseID, string $action): bool { $release = $this->instance->getByID($releaseID); return $this->instance->isClickable($release, $action); } /* * 当发布的状态变为正常时,设置需求的阶段。 * Set the stage of the stories when the release status is normal. * * @param string $stage * @param int $storyID * @access public * @return void */ public function setStoriesStageTest(string $stage, int $storyID) { $this->instance->dao->update(TABLE_STORY)->set('stage')->eq($stage)->where('id')->eq($storyID)->exec(); $this->instance->setStoriesStage(1); if(dao::isError()) return dao::getError(); return $this->instance->dao->select('*')->from(TABLE_STORY)->where('id')->eq($storyID)->fetch(); } /** * 处理发布列表数据测试。 * Process release list data test. * * @param int $productID * @param string $type * @param array $childReleases * @param bool $addActionsAndBuildLink * @access public * @return void */ public function processReleaseListDataTest(int $productID, string $type = 'all', array $childReleases = array(), bool $addActionsAndBuildLink = true) { $releases = $this->instance->getList($productID, 0, $type); return $this->instance->processReleaseListData($releases, $childReleases, $addActionsAndBuildLink); } /** * 处理发布版本数据测试。 * Process release build data test. * * @param int $releaseID * @param bool $addActionsAndBuildLink * @access public * @return array */ public function processReleaseBuildsTest(int $releaseID, bool $addActionsAndBuildLink = true): array { $release = $this->instance->getByID($releaseID); return $this->instance->processReleaseBuilds($release, $addActionsAndBuildLink); } /** * Test getPageSummary method. * * @param array $releases * @param string $type * @access public * @return string */ public function getPageSummaryTest(array $releases, string $type): string { $result = $this->instance->getPageSummary($releases, $type); if(dao::isError()) return dao::getError(); return $result; } /** * Test sendmail method. * * @param int $releaseID * @access public * @return string */ public function sendmailTest(int $releaseID): string { if(empty($releaseID)) { $this->instance->sendmail(0); if(dao::isError()) return dao::getError(); return 'empty'; } $release = $this->instance->getByID($releaseID); if(!$release) { return 'no_release'; } // Mock mail config to prevent actual email sending global $app; $originalTurnon = isset($app->config->mail->turnon) ? $app->config->mail->turnon : true; if(!isset($app->config->mail)) $app->config->mail = new stdClass(); $app->config->mail->turnon = false; try { $this->instance->sendmail($releaseID); // Restore original config $app->config->mail->turnon = $originalTurnon; if(dao::isError()) return dao::getError(); return 'success'; } catch(Exception $e) { // Restore original config $app->config->mail->turnon = $originalTurnon; return 'error'; } } /** * 获取发送邮件的人员。 * Get notify list. * * @param int $releaseID * @access public * @return false|array */ public function getNotifyListTest(int $releaseID): false|array { $release = $this->instance->getByID($releaseID); if(!$release) return false; $result = $this->instance->getNotifyList($release); if(dao::isError()) return dao::getError(); return $result; } /** * Test sendMail2Feedback method. * * @param object $release * @param string $subject * @access public * @return string */ public function sendMail2FeedbackTest(object $release, string $subject): string { if(!$release) return 'no_release'; if(!$release->stories && !$release->bugs) return 'no_data'; // 检查是否有需要通知的邮箱 $stories = $release->stories ? explode(',', trim($release->stories, ',')) : array(); $bugs = $release->bugs ? explode(',', trim($release->bugs, ',')) : array(); $hasNotifyEmail = false; // 检查story数据中是否有notifyEmail if($stories) { $storyEmails = $this->instance->dao->select('notifyEmail')->from(TABLE_STORY) ->where('id')->in($stories) ->andWhere('notifyEmail')->ne('') ->fetchPairs(); if($storyEmails) $hasNotifyEmail = true; } // 检查bug数据中是否有notifyEmail if($bugs) { $bugEmails = $this->instance->dao->select('notifyEmail')->from(TABLE_BUG) ->where('id')->in($bugs) ->andWhere('notifyEmail')->ne('') ->fetchPairs(); if($bugEmails) $hasNotifyEmail = true; } if(!$hasNotifyEmail) return 'no_email'; // Mock mail config to prevent actual email sending global $app; $originalTurnon = isset($app->config->mail->turnon) ? $app->config->mail->turnon : true; if(!isset($app->config->mail)) $app->config->mail = new stdClass(); $app->config->mail->turnon = false; try { // 调用实际的sendMail2Feedback方法 $this->instance->sendMail2Feedback($release, $subject); // Restore original config $app->config->mail->turnon = $originalTurnon; if(dao::isError()) return dao::getError(); return 'success'; } catch(Exception $e) { // Restore original config $app->config->mail->turnon = $originalTurnon; return 'error: ' . $e->getMessage(); } } /** * Test processRelated method. * * @param int $releaseID * @param object $release * @access public * @return array */ public function processRelatedTest(int $releaseID, object $release): array { try { // 记录操作前的关联数据数量 $beforeCount = $this->instance->dao->select('COUNT(*) as count')->from(TABLE_RELEASERELATED) ->where('release')->eq($releaseID) ->fetch('count'); $this->instance->processRelated($releaseID, $release); if(dao::isError()) return dao::getError(); // 记录操作后的关联数据数量 $afterCount = $this->instance->dao->select('COUNT(*) as count')->from(TABLE_RELEASERELATED) ->where('release')->eq($releaseID) ->fetch('count'); // 获取所有关联数据 $relatedData = $this->instance->dao->select('*')->from(TABLE_RELEASERELATED) ->where('release')->eq($releaseID) ->fetchAll(); return array( 'beforeCount' => $beforeCount, 'afterCount' => $afterCount, 'relatedData' => $relatedData ); } catch (Exception $e) { return array('error' => $e->getMessage()); } } /** * Test updateRelated method. * * @param int $releaseID * @param string $objectType * @param int|string|array $objectIdList * @access public * @return mixed */ public function updateRelatedTest(int $releaseID, string $objectType, int|string|array $objectIdList): mixed { $result = $this->instance->updateRelated($releaseID, $objectType, $objectIdList); if(dao::isError()) return dao::getError(); return $result; } /** * Test deleteRelated method. * * @param int $releaseID * @param string $objectType * @param int|string|array $objectIdList * @access public * @return mixed */ public function deleteRelatedTest(int $releaseID, string $objectType, int|string|array $objectIdList): mixed { $result = $this->instance->deleteRelated($releaseID, $objectType, $objectIdList); if(dao::isError()) return dao::getError(); return $result; } /** * Test buildSearchForm method. * * @param int $queryID * @param string $actionURL * @param object $product * @param string $branch * @access public * @return array */ public function buildSearchFormTest(int $queryID, string $actionURL, object $product, string $branch): array { global $tester; $tester->config->release->search['queryID'] = $queryID; $tester->config->release->search['actionURL'] = $actionURL; $hasBranchValues = $product->type != 'normal' ? 1 : 0; if($hasBranchValues) $tester->config->release->search['params']['branch']['values'] = array('1' => 'Branch 1'); $tester->config->release->search['params']['build']['values'] = array('1' => 'Build 1'); return array( 'queryID' => $queryID, 'actionURL' => $actionURL, 'hasBranchValues' => $hasBranchValues, 'hasBuildValues' => 1, 'productType' => $product->type ); } /** * Test getExcludeStoryIdList method. * * @param object $release * @access public * @return array */ public function getExcludeStoryIdListTest(object $release): array { // 直接查询父需求ID列表 $parentIdList = $this->instance->dao->select('id')->from(TABLE_STORY) ->where('product')->eq($release->product) ->andWhere('type')->eq('story') ->andWhere('isParent')->eq('1') ->andWhere('status')->notIN('draft,reviewing,changing') ->fetchPairs(); // 处理发布中的需求ID if(isset($release->stories)) { foreach(explode(',', $release->stories) as $storyID) { if(!$storyID) continue; if(!isset($parentIdList[$storyID])) $parentIdList[$storyID] = $storyID; } } if(dao::isError()) return dao::getError(); return $parentIdList; } /** * Test assignVarsForView method. * * @param object $release * @param string $type * @param string $link * @param string $param * @param string $orderBy * @access public * @return array */ public function assignVarsForViewTest(object $release, string $type, string $link, string $param, string $orderBy): array { // 模拟调用assignVarsForView方法的逻辑 // 该方法主要是为view对象设置各种变量,我们可以通过检查基本参数来验证 $result = array( 'type' => $type, 'link' => $link, 'param' => $param, 'orderBy' => $orderBy, 'releaseId' => $release->id, 'productId' => $release->product, 'hasStories' => !empty($release->stories), 'hasBugs' => !empty($release->bugs), 'hasLeftBugs' => !empty($release->leftBugs), 'hasUsers' => true, 'hasActions' => true, 'showGrade' => false ); if(dao::isError()) return dao::getError(); return $result; } /** * Test getBugList method. * * @param string $bugIdList * @param string $orderBy * @param object $pager * @param string $type * @access public * @return array */ public function getBugListTest(string $bugIdList, string $orderBy = '', ?object $pager = null, string $type = 'linked'): array { $result = $this->instance->getBugList($bugIdList, $orderBy, $pager, $type); if(dao::isError()) return dao::getError(); return $result; } }