This commit is contained in:
Catouse
2019-10-14 17:01:34 +08:00
104 changed files with 3066 additions and 1569 deletions
+1 -1
View File
@@ -1 +1 @@
11.6.2
11.6.3
+1 -1
View File
@@ -16,7 +16,7 @@ if(!class_exists('config')){class config{}}
if(!function_exists('getWebRoot')){function getWebRoot(){}}
/* 基本设置。Basic settings. */
$config->version = '11.6.2'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it.
$config->version = '11.6.3'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it.
$config->charset = 'UTF-8'; // ZenTaoPHP的编码。 The encoding of ZenTaoPHP.
$config->cookieLife = time() + 2592000; // Cookie的生存时间。The cookie life time.
$config->timezone = 'Asia/Shanghai'; // 时区设置。 The time zone setting, for more see http://www.php.net/manual/en/timezones.php.
+937
View File
@@ -0,0 +1,937 @@
CREATE TABLE `zt_action` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`objectType` varchar(30) NOT NULL DEFAULT '',
`objectID` mediumint(8) unsigned NOT NULL DEFAULT '0',
`product` varchar(255) NOT NULL,
`project` mediumint(9) NOT NULL,
`actor` varchar(30) NOT NULL DEFAULT '',
`action` varchar(30) NOT NULL DEFAULT '',
`date` datetime NOT NULL,
`comment` text NOT NULL,
`extra` text NOT NULL,
`read` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `date` (`date`),
KEY `actor` (`actor`),
KEY `project` (`project`),
KEY `objectID` (`objectID`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_block` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`account` char(30) NOT NULL,
`module` varchar(20) NOT NULL,
`title` varchar(100) NOT NULL,
`source` varchar(20) NOT NULL,
`block` varchar(20) NOT NULL,
`params` text NOT NULL,
`order` tinyint(3) unsigned NOT NULL DEFAULT '0',
`grid` tinyint(3) unsigned NOT NULL DEFAULT '0',
`height` smallint(5) unsigned NOT NULL DEFAULT '0',
`hidden` tinyint(1) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `accountModuleOrder` (`account`,`module`,`order`),
KEY `account` (`account`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_branch` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`product` mediumint(8) unsigned NOT NULL,
`name` varchar(255) NOT NULL,
`order` smallint(5) unsigned NOT NULL,
`deleted` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `product` (`product`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_bug` (
`id` mediumint(8) NOT NULL AUTO_INCREMENT,
`product` mediumint(8) unsigned NOT NULL DEFAULT '0',
`branch` mediumint(8) unsigned NOT NULL DEFAULT '0',
`module` mediumint(8) unsigned NOT NULL DEFAULT '0',
`project` mediumint(8) unsigned NOT NULL DEFAULT '0',
`plan` mediumint(8) unsigned NOT NULL DEFAULT '0',
`story` mediumint(8) unsigned NOT NULL DEFAULT '0',
`storyVersion` smallint(6) NOT NULL DEFAULT '1',
`task` mediumint(8) unsigned NOT NULL DEFAULT '0',
`toTask` mediumint(8) unsigned NOT NULL DEFAULT '0',
`toStory` mediumint(8) NOT NULL DEFAULT '0',
`title` varchar(255) NOT NULL,
`keywords` varchar(255) NOT NULL,
`severity` tinyint(4) NOT NULL DEFAULT '0',
`pri` tinyint(3) unsigned NOT NULL,
`type` varchar(30) NOT NULL DEFAULT '',
`os` varchar(30) NOT NULL DEFAULT '',
`browser` varchar(30) NOT NULL DEFAULT '',
`hardware` varchar(30) NOT NULL,
`found` varchar(30) NOT NULL DEFAULT '',
`steps` text NOT NULL,
`status` enum('active','resolved','closed') NOT NULL DEFAULT 'active',
`subStatus` varchar(30) NOT NULL DEFAULT '',
`color` char(7) NOT NULL,
`confirmed` tinyint(1) NOT NULL DEFAULT '0',
`activatedCount` smallint(6) NOT NULL,
`activatedDate` datetime NOT NULL,
`mailto` text,
`openedBy` varchar(30) NOT NULL DEFAULT '',
`openedDate` datetime NOT NULL,
`openedBuild` varchar(255) NOT NULL,
`assignedTo` varchar(30) NOT NULL DEFAULT '',
`assignedDate` datetime NOT NULL,
`deadline` date NOT NULL,
`resolvedBy` varchar(30) NOT NULL DEFAULT '',
`resolution` varchar(30) NOT NULL DEFAULT '',
`resolvedBuild` varchar(30) NOT NULL DEFAULT '',
`resolvedDate` datetime NOT NULL,
`closedBy` varchar(30) NOT NULL DEFAULT '',
`closedDate` datetime NOT NULL,
`duplicateBug` mediumint(8) unsigned NOT NULL,
`linkBug` varchar(255) NOT NULL,
`case` mediumint(8) unsigned NOT NULL,
`caseVersion` smallint(6) NOT NULL DEFAULT '1',
`result` mediumint(8) unsigned NOT NULL,
`testtask` mediumint(8) unsigned NOT NULL,
`lastEditedBy` varchar(30) NOT NULL DEFAULT '',
`lastEditedDate` datetime NOT NULL,
`deleted` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `product` (`product`),
KEY `project` (`project`),
KEY `status` (`status`),
KEY `plan` (`plan`),
KEY `story` (`story`),
KEY `case` (`case`),
KEY `assignedTo` (`assignedTo`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_build` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`product` mediumint(8) unsigned NOT NULL DEFAULT '0',
`branch` mediumint(8) unsigned NOT NULL DEFAULT '0',
`project` mediumint(8) unsigned NOT NULL DEFAULT '0',
`name` char(150) NOT NULL,
`scmPath` char(255) NOT NULL,
`filePath` char(255) NOT NULL,
`date` date NOT NULL,
`stories` text NOT NULL,
`bugs` text NOT NULL,
`builder` char(30) NOT NULL DEFAULT '',
`desc` text NOT NULL,
`deleted` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `product` (`product`),
KEY `project` (`project`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_burn` (
`project` mediumint(8) unsigned NOT NULL,
`task` mediumint(8) unsigned NOT NULL DEFAULT '0',
`date` date NOT NULL,
`estimate` float NOT NULL,
`left` float NOT NULL,
`consumed` float NOT NULL,
PRIMARY KEY (`project`,`date`,`task`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_case` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`product` mediumint(8) unsigned NOT NULL DEFAULT '0',
`branch` mediumint(8) unsigned NOT NULL DEFAULT '0',
`lib` mediumint(8) unsigned NOT NULL DEFAULT '0',
`module` mediumint(8) unsigned NOT NULL DEFAULT '0',
`path` mediumint(8) unsigned NOT NULL DEFAULT '0',
`story` mediumint(30) unsigned NOT NULL DEFAULT '0',
`storyVersion` smallint(6) NOT NULL DEFAULT '1',
`title` varchar(255) NOT NULL,
`precondition` text NOT NULL,
`keywords` varchar(255) NOT NULL,
`pri` tinyint(3) unsigned NOT NULL DEFAULT '3',
`type` char(30) NOT NULL DEFAULT '1',
`stage` varchar(255) NOT NULL,
`howRun` varchar(30) NOT NULL,
`scriptedBy` varchar(30) NOT NULL,
`scriptedDate` date NOT NULL,
`scriptStatus` varchar(30) NOT NULL,
`scriptLocation` varchar(255) NOT NULL,
`status` char(30) NOT NULL DEFAULT '1',
`subStatus` varchar(30) NOT NULL DEFAULT '',
`color` char(7) NOT NULL,
`frequency` enum('1','2','3') NOT NULL DEFAULT '1',
`order` tinyint(30) unsigned NOT NULL DEFAULT '0',
`openedBy` char(30) NOT NULL DEFAULT '',
`openedDate` datetime NOT NULL,
`reviewedBy` varchar(255) NOT NULL,
`reviewedDate` date NOT NULL,
`lastEditedBy` char(30) NOT NULL DEFAULT '',
`lastEditedDate` datetime NOT NULL,
`version` tinyint(3) unsigned NOT NULL DEFAULT '0',
`linkCase` varchar(255) NOT NULL,
`fromBug` mediumint(8) unsigned NOT NULL,
`fromCaseID` mediumint(8) unsigned NOT NULL,
`fromCaseVersion` mediumint(8) unsigned NOT NULL,
`deleted` enum('0','1') NOT NULL DEFAULT '0',
`lastRunner` varchar(30) NOT NULL,
`lastRunDate` datetime NOT NULL,
`lastRunResult` char(30) NOT NULL,
PRIMARY KEY (`id`),
KEY `product` (`product`),
KEY `story` (`story`),
KEY `module` (`module`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_casestep` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`parent` mediumint(8) unsigned NOT NULL DEFAULT '0',
`case` mediumint(8) unsigned NOT NULL DEFAULT '0',
`version` smallint(3) unsigned NOT NULL DEFAULT '0',
`type` varchar(10) NOT NULL DEFAULT 'step',
`desc` text NOT NULL,
`expect` text NOT NULL,
PRIMARY KEY (`id`),
KEY `case` (`case`),
KEY `version` (`version`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_company` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`name` char(120) DEFAULT NULL,
`phone` char(20) DEFAULT NULL,
`fax` char(20) DEFAULT NULL,
`address` char(120) DEFAULT NULL,
`zipcode` char(10) DEFAULT NULL,
`website` char(120) DEFAULT NULL,
`backyard` char(120) DEFAULT NULL,
`guest` enum('1','0') NOT NULL DEFAULT '0',
`admins` char(255) DEFAULT NULL,
`deleted` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_config` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`owner` char(30) NOT NULL DEFAULT '',
`module` varchar(30) NOT NULL,
`section` char(30) NOT NULL DEFAULT '',
`key` char(30) NOT NULL DEFAULT '',
`value` text NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `unique` (`owner`,`module`,`section`,`key`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_cron` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`m` varchar(20) NOT NULL,
`h` varchar(20) NOT NULL,
`dom` varchar(20) NOT NULL,
`mon` varchar(20) NOT NULL,
`dow` varchar(20) NOT NULL,
`command` text NOT NULL,
`remark` varchar(255) NOT NULL,
`type` varchar(20) NOT NULL,
`buildin` tinyint(1) NOT NULL DEFAULT '0',
`status` varchar(20) NOT NULL,
`lastTime` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `lastTime` (`lastTime`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_dept` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`name` char(60) NOT NULL,
`parent` mediumint(8) unsigned NOT NULL DEFAULT '0',
`path` char(255) NOT NULL DEFAULT '',
`grade` tinyint(3) unsigned NOT NULL DEFAULT '0',
`order` tinyint(3) unsigned NOT NULL DEFAULT '0',
`position` char(30) NOT NULL DEFAULT '',
`function` char(255) NOT NULL DEFAULT '',
`manager` char(30) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `parent` (`parent`),
KEY `path` (`path`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_doc` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`product` mediumint(8) unsigned NOT NULL,
`project` mediumint(8) unsigned NOT NULL,
`lib` varchar(30) NOT NULL,
`module` varchar(30) NOT NULL,
`title` varchar(255) NOT NULL,
`keywords` varchar(255) NOT NULL,
`type` varchar(30) NOT NULL,
`views` smallint(5) unsigned NOT NULL,
`collector` text NOT NULL,
`addedBy` varchar(30) NOT NULL,
`addedDate` datetime NOT NULL,
`editedBy` varchar(30) NOT NULL,
`editedDate` datetime NOT NULL,
`acl` varchar(10) NOT NULL DEFAULT 'open',
`groups` varchar(255) NOT NULL,
`users` text NOT NULL,
`version` smallint(5) unsigned NOT NULL DEFAULT '1',
`deleted` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `product` (`product`),
KEY `project` (`project`),
KEY `lib` (`lib`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_doccontent` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`doc` mediumint(8) unsigned NOT NULL,
`title` varchar(255) NOT NULL,
`digest` varchar(255) NOT NULL,
`content` text NOT NULL,
`files` text NOT NULL,
`type` varchar(10) NOT NULL,
`version` smallint(5) unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `doc_version` (`doc`,`version`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_doclib` (
`id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
`type` varchar(30) NOT NULL,
`product` mediumint(8) unsigned NOT NULL,
`project` mediumint(8) unsigned NOT NULL,
`name` varchar(60) NOT NULL,
`acl` varchar(10) NOT NULL DEFAULT 'open',
`groups` varchar(255) NOT NULL,
`users` text NOT NULL,
`main` enum('0','1') NOT NULL DEFAULT '0',
`collector` text NOT NULL,
`order` tinyint(5) unsigned NOT NULL,
`deleted` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `product` (`product`),
KEY `project` (`project`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_effort` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`user` char(30) NOT NULL DEFAULT '',
`todo` enum('1','0') NOT NULL DEFAULT '1',
`date` date NOT NULL,
`begin` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`end` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`type` enum('1','2','3') NOT NULL DEFAULT '1',
`idvalue` mediumint(8) unsigned NOT NULL DEFAULT '0',
`name` char(30) NOT NULL DEFAULT '',
`desc` char(255) NOT NULL DEFAULT '',
`status` enum('1','2','3') NOT NULL DEFAULT '1',
PRIMARY KEY (`id`),
KEY `user` (`user`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `zt_entry` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`account` varchar(30) NOT NULL DEFAULT '',
`code` varchar(20) NOT NULL,
`key` varchar(32) NOT NULL,
`freePasswd` enum('0','1') NOT NULL DEFAULT '0',
`ip` varchar(100) NOT NULL,
`desc` text NOT NULL,
`createdBy` varchar(30) NOT NULL,
`createdDate` datetime NOT NULL,
`calledTime` int(10) unsigned NOT NULL DEFAULT '0',
`editedBy` varchar(30) NOT NULL,
`editedDate` datetime NOT NULL,
`deleted` enum('0', '1') NOT NULL DEFAULT '0',
PRIMARY KEY `id` (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_extension` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(150) NOT NULL,
`code` varchar(30) NOT NULL,
`version` varchar(50) NOT NULL,
`author` varchar(100) NOT NULL,
`desc` text NOT NULL,
`license` text NOT NULL,
`type` varchar(20) NOT NULL DEFAULT 'extension',
`site` varchar(150) NOT NULL,
`zentaoCompatible` varchar(100) NOT NULL,
`installedTime` datetime NOT NULL,
`depends` varchar(100) NOT NULL,
`dirs` mediumtext NOT NULL,
`files` mediumtext NOT NULL,
`status` varchar(20) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `code` (`code`),
KEY `name` (`name`),
KEY `installedTime` (`installedTime`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_file` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`pathname` char(100) NOT NULL,
`title` char(255) NOT NULL,
`extension` char(30) NOT NULL,
`size` int(10) unsigned NOT NULL DEFAULT '0',
`objectType` char(30) NOT NULL,
`objectID` mediumint(9) NOT NULL,
`addedBy` char(30) NOT NULL DEFAULT '',
`addedDate` datetime NOT NULL,
`downloads` mediumint(8) unsigned NOT NULL DEFAULT '0',
`extra` varchar(255) NOT NULL,
`deleted` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `objectType` (`objectType`),
KEY `objectID` (`objectID`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_group` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`name` char(30) NOT NULL,
`role` char(30) NOT NULL DEFAULT '',
`desc` char(255) NOT NULL DEFAULT '',
`acl` text,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_grouppriv` (
`group` mediumint(8) unsigned NOT NULL DEFAULT '0',
`module` char(30) NOT NULL DEFAULT '',
`method` char(30) NOT NULL DEFAULT '',
UNIQUE KEY `group` (`group`,`module`,`method`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_history` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`action` mediumint(8) unsigned NOT NULL DEFAULT '0',
`field` varchar(30) NOT NULL DEFAULT '',
`old` text NOT NULL,
`new` text NOT NULL,
`diff` mediumtext NOT NULL,
PRIMARY KEY (`id`),
KEY `action` (`action`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_lang` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`lang` varchar(30) NOT NULL,
`module` varchar(30) NOT NULL,
`section` varchar(30) NOT NULL,
`key` varchar(60) NOT NULL,
`value` text NOT NULL,
`system` enum('0','1') NOT NULL DEFAULT '1',
PRIMARY KEY (`id`),
UNIQUE KEY `lang` (`lang`,`module`,`section`,`key`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_log` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`objectType` varchar(30) NOT NULL,
`objectID` mediumint(8) unsigned NOT NULL,
`action` mediumint(8) unsigned NOT NULL,
`date` datetime NOT NULL,
`url` varchar(255) NOT NULL,
`contentType` varchar(30) NOT NULL,
`data` text NOT NULL,
`result` text NOT NULL,
PRIMARY KEY (`id`),
KEY `objectType` (`objectType`),
KEY `obejctID` (`objectID`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_module` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`root` mediumint(8) unsigned NOT NULL DEFAULT '0',
`branch` mediumint(8) unsigned NOT NULL DEFAULT '0',
`name` char(60) NOT NULL DEFAULT '',
`parent` mediumint(8) unsigned NOT NULL DEFAULT '0',
`path` char(255) NOT NULL DEFAULT '',
`grade` tinyint(3) unsigned NOT NULL DEFAULT '0',
`order` smallint(5) unsigned NOT NULL DEFAULT '0',
`type` char(30) NOT NULL,
`owner` varchar(30) NOT NULL,
`collector` text NOT NULL,
`short` varchar(30) NOT NULL,
`deleted` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `root` (`root`),
KEY `type` (`type`),
KEY `path` (`path`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_notify` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`objectType` varchar(50) NOT NULL,
`objectID` mediumint(8) unsigned NOT NULL,
`action` mediumint(9) NOT NULL,
`toList` varchar(255) NOT NULL,
`ccList` text NOT NULL,
`subject` varchar(255) NOT NULL,
`data` text NOT NULL,
`createdBy` char(30) NOT NULL,
`createdDate` datetime NOT NULL,
`sendTime` datetime NOT NULL,
`status` varchar(10) NOT NULL DEFAULT 'wait',
`failReason` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_product` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(90) NOT NULL,
`code` varchar(45) NOT NULL,
`line` mediumint(8) NOT NULL,
`type` varchar(30) NOT NULL DEFAULT 'normal',
`status` varchar(30) NOT NULL DEFAULT '',
`subStatus` varchar(30) NOT NULL DEFAULT '',
`desc` text NOT NULL,
`PO` varchar(30) NOT NULL,
`QD` varchar(30) NOT NULL,
`RD` varchar(30) NOT NULL,
`acl` enum('open','private','custom') NOT NULL DEFAULT 'open',
`whitelist` text NOT NULL,
`createdBy` varchar(30) NOT NULL,
`createdDate` datetime NOT NULL,
`createdVersion` varchar(20) NOT NULL,
`order` mediumint(8) unsigned NOT NULL,
`deleted` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `order` (`order`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_productplan` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`product` mediumint(8) unsigned NOT NULL,
`branch` mediumint(8) unsigned NOT NULL,
`parent` mediumint(9) NOT NULL DEFAULT '0',
`title` varchar(90) NOT NULL,
`desc` text NOT NULL,
`begin` date NOT NULL,
`end` date NOT NULL,
`order` text NOT NULL,
`deleted` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `product` (`product`),
KEY `end` (`end`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_project` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`isCat` enum('1','0') NOT NULL DEFAULT '0',
`catID` mediumint(8) unsigned NOT NULL,
`type` varchar(20) NOT NULL DEFAULT 'sprint',
`parent` mediumint(8) unsigned NOT NULL DEFAULT '0',
`name` varchar(90) NOT NULL,
`code` varchar(45) NOT NULL,
`begin` date NOT NULL,
`end` date NOT NULL,
`days` smallint(5) unsigned NOT NULL,
`status` varchar(10) NOT NULL,
`subStatus` varchar(30) NOT NULL DEFAULT '',
`statge` enum('1','2','3','4','5') NOT NULL DEFAULT '1',
`pri` enum('1','2','3','4') NOT NULL DEFAULT '1',
`desc` text NOT NULL,
`openedBy` varchar(30) NOT NULL DEFAULT '',
`openedDate` datetime NOT NULL,
`openedVersion` varchar(20) NOT NULL,
`closedBy` varchar(30) NOT NULL DEFAULT '',
`closedDate` datetime NOT NULL,
`canceledBy` varchar(30) NOT NULL DEFAULT '',
`canceledDate` datetime NOT NULL,
`PO` varchar(30) NOT NULL DEFAULT '',
`PM` varchar(30) NOT NULL DEFAULT '',
`QD` varchar(30) NOT NULL DEFAULT '',
`RD` varchar(30) NOT NULL DEFAULT '',
`team` varchar(90) NOT NULL,
`acl` enum('open','private','custom') NOT NULL DEFAULT 'open',
`whitelist` text NOT NULL,
`order` mediumint(8) unsigned NOT NULL,
`deleted` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `parent` (`parent`),
KEY `begin` (`begin`),
KEY `end` (`end`),
KEY `status` (`status`),
KEY `order` (`order`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_projectproduct` (
`project` mediumint(8) unsigned NOT NULL,
`product` mediumint(8) unsigned NOT NULL,
`branch` mediumint(8) unsigned NOT NULL,
`plan` mediumint(8) unsigned NOT NULL,
PRIMARY KEY (`project`,`product`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_projectstory` (
`project` mediumint(8) unsigned NOT NULL DEFAULT '0',
`product` mediumint(8) unsigned NOT NULL,
`story` mediumint(8) unsigned NOT NULL DEFAULT '0',
`version` smallint(6) NOT NULL DEFAULT '1',
`order` smallint(6) unsigned NOT NULL,
UNIQUE KEY `project` (`project`,`story`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_release` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`product` mediumint(8) unsigned NOT NULL DEFAULT '0',
`branch` mediumint(8) unsigned NOT NULL DEFAULT '0',
`build` mediumint(8) unsigned NOT NULL,
`name` varchar(255) NOT NULL DEFAULT '',
`marker` enum('0','1') NOT NULL DEFAULT '0',
`date` date NOT NULL,
`stories` text NOT NULL,
`bugs` text NOT NULL,
`leftBugs` text NOT NULL,
`desc` text NOT NULL,
`status` varchar(20) NOT NULL DEFAULT 'normal',
`subStatus` varchar(30) NOT NULL DEFAULT '',
`deleted` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `product` (`product`),
KEY `build` (`build`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_score` (
`id` bigint(12) unsigned NOT NULL AUTO_INCREMENT,
`account` varchar(30) NOT NULL,
`module` varchar(30) NOT NULL DEFAULT '',
`method` varchar(30) NOT NULL,
`desc` varchar(250) NOT NULL DEFAULT '',
`before` int(11) NOT NULL DEFAULT '0',
`score` int(11) NOT NULL DEFAULT '0',
`after` int(11) NOT NULL DEFAULT '0',
`time` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `account` (`account`),
KEY `model` (`module`),
KEY `method` (`method`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `zt_story` (
`id` mediumint(8) unsigned NOT NULL auto_increment,
`product` mediumint(8) unsigned NOT NULL default '0',
`branch` mediumint(8) unsigned NOT NULL default '0',
`module` mediumint(8) unsigned NOT NULL default '0',
`plan` text,
`source` varchar(20) NOT NULL,
`sourceNote` varchar(255) NOT NULL,
`fromBug` mediumint(8) unsigned NOT NULL default '0',
`title` varchar(255) NOT NULL,
`keywords` varchar(255) NOT NULL,
`type` varchar(30) NOT NULL default '',
`pri` tinyint(3) unsigned NOT NULL default '3',
`estimate` float unsigned NOT NULL,
`status` enum('','changed','active','draft','closed') NOT NULL default '',
`subStatus` varchar(30) NOT NULL DEFAULT '',
`color` char(7) NOT NULL,
`stage` enum('','wait','planned','projected','developing','developed','testing','tested','verified','released', 'closed') NOT NULL DEFAULT 'wait',
`stagedBy` char(30) NOT NULL,
`mailto` text,
`openedBy` varchar(30) NOT NULL default '',
`openedDate` datetime NOT NULL,
`assignedTo` varchar(30) NOT NULL default '',
`assignedDate` datetime NOT NULL,
`lastEditedBy` varchar(30) NOT NULL default '',
`lastEditedDate` datetime NOT NULL,
`reviewedBy` varchar(255) NOT NULL,
`reviewedDate` date NOT NULL,
`closedBy` varchar(30) NOT NULL default '',
`closedDate` datetime NOT NULL,
`closedReason` varchar(30) NOT NULL,
`toBug` mediumint(8) unsigned NOT NULL,
`childStories` varchar(255) NOT NULL,
`linkStories` varchar(255) NOT NULL,
`duplicateStory` mediumint(8) unsigned NOT NULL,
`version` smallint(6) NOT NULL default '1',
`deleted` enum('0','1') NOT NULL default '0',
PRIMARY KEY (`id`),
KEY `product` (`product`),
KEY `status` (`status`),
KEY `assignedTo` (`assignedTo`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_storyspec` (
`story` mediumint(9) NOT NULL,
`version` smallint(6) NOT NULL,
`title` varchar(255) NOT NULL,
`spec` text NOT NULL,
`verify` text NOT NULL,
UNIQUE KEY `story` (`story`,`version`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `zt_storystage` (
`story` mediumint(8) unsigned NOT NULL,
`branch` mediumint(8) unsigned NOT NULL,
`stage` varchar(50) NOT NULL,
`stagedBy` char(30) NOT NULL,
UNIQUE KEY `story_branch` (`story`,`branch`),
KEY `story` (`story`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_suitecase` (
`suite` mediumint(8) unsigned NOT NULL,
`product` mediumint(8) unsigned NOT NULL,
`case` mediumint(8) unsigned NOT NULL,
`version` smallint(5) unsigned NOT NULL,
UNIQUE KEY `suitecase` (`suite`,`case`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_task` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`parent` mediumint(8) NOT NULL DEFAULT '0',
`project` mediumint(8) unsigned NOT NULL DEFAULT '0',
`module` mediumint(8) unsigned NOT NULL DEFAULT '0',
`story` mediumint(8) unsigned NOT NULL DEFAULT '0',
`storyVersion` smallint(6) NOT NULL DEFAULT '1',
`fromBug` mediumint(8) unsigned NOT NULL DEFAULT '0',
`name` varchar(255) NOT NULL,
`type` varchar(20) NOT NULL,
`pri` tinyint(3) unsigned NOT NULL DEFAULT '0',
`estimate` float unsigned NOT NULL,
`consumed` float unsigned NOT NULL,
`left` float unsigned NOT NULL,
`deadline` date NOT NULL,
`status` enum('wait','doing','done','pause','cancel','closed') NOT NULL DEFAULT 'wait',
`subStatus` varchar(30) NOT NULL DEFAULT '',
`color` char(7) NOT NULL,
`mailto` text,
`desc` text NOT NULL,
`openedBy` varchar(30) NOT NULL,
`openedDate` datetime NOT NULL,
`assignedTo` varchar(30) NOT NULL,
`assignedDate` datetime NOT NULL,
`estStarted` date NOT NULL,
`realStarted` date NOT NULL,
`finishedBy` varchar(30) NOT NULL,
`finishedDate` datetime NOT NULL,
`finishedList` text NOT NULL,
`canceledBy` varchar(30) NOT NULL,
`canceledDate` datetime NOT NULL,
`closedBy` varchar(30) NOT NULL,
`closedDate` datetime NOT NULL,
`closedReason` varchar(30) NOT NULL,
`lastEditedBy` varchar(30) NOT NULL,
`lastEditedDate` datetime NOT NULL,
`deleted` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `project` (`project`),
KEY `story` (`story`),
KEY `assignedTo` (`assignedTo`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_taskestimate` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`task` mediumint(8) unsigned NOT NULL DEFAULT '0',
`date` date NOT NULL,
`left` float unsigned NOT NULL DEFAULT '0',
`consumed` float unsigned NOT NULL,
`account` char(30) NOT NULL DEFAULT '',
`work` text,
PRIMARY KEY (`id`),
KEY `task` (`task`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_team` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`root` mediumint(8) unsigned NOT NULL DEFAULT '0',
`type` enum('project','task') NOT NULL DEFAULT 'project',
`account` char(30) NOT NULL DEFAULT '',
`role` char(30) NOT NULL DEFAULT '',
`limited` char(8) NOT NULL DEFAULT 'no',
`join` date NOT NULL DEFAULT '0000-00-00',
`days` smallint(5) unsigned NOT NULL,
`hours` float(2,1) unsigned NOT NULL DEFAULT '0.0',
`estimate` decimal(12,2) unsigned NOT NULL DEFAULT '0.00',
`consumed` decimal(12,2) unsigned NOT NULL DEFAULT '0.00',
`left` decimal(12,2) unsigned NOT NULL DEFAULT '0.00',
`order` tinyint(3) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `team` (`root`,`type`,`account`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_testreport` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`product` mediumint(8) unsigned NOT NULL,
`project` mediumint(8) unsigned NOT NULL,
`tasks` varchar(255) NOT NULL,
`builds` varchar(255) NOT NULL,
`title` varchar(255) NOT NULL,
`begin` date NOT NULL,
`end` date NOT NULL,
`owner` char(30) NOT NULL,
`members` text NOT NULL,
`stories` text NOT NULL,
`bugs` text NOT NULL,
`cases` text NOT NULL,
`report` text NOT NULL,
`objectType` varchar(20) NOT NULL,
`objectID` mediumint(8) unsigned NOT NULL,
`createdBy` char(30) NOT NULL,
`createdDate` datetime NOT NULL,
`deleted` enum('0','1') NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_testresult` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`run` mediumint(8) unsigned NOT NULL,
`case` mediumint(8) unsigned NOT NULL,
`version` smallint(5) unsigned NOT NULL,
`caseResult` char(30) NOT NULL,
`stepResults` text NOT NULL,
`lastRunner` varchar(30) NOT NULL,
`date` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `case` (`case`),
KEY `version` (`version`),
KEY `run` (`run`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_testrun` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`task` mediumint(8) unsigned NOT NULL DEFAULT '0',
`case` mediumint(8) unsigned NOT NULL DEFAULT '0',
`version` tinyint(3) unsigned NOT NULL DEFAULT '0',
`assignedTo` char(30) NOT NULL DEFAULT '',
`lastRunner` varchar(30) NOT NULL,
`lastRunDate` datetime NOT NULL,
`lastRunResult` char(30) NOT NULL,
`status` char(30) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `task` (`task`,`case`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_testsuite` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`product` mediumint(8) unsigned NOT NULL,
`name` varchar(255) NOT NULL,
`desc` text NOT NULL,
`type` varchar(20) NOT NULL,
`addedBy` char(30) NOT NULL,
`addedDate` datetime NOT NULL,
`lastEditedBy` char(30) NOT NULL,
`lastEditedDate` datetime NOT NULL,
`deleted` enum('0','1') NOT NULL,
PRIMARY KEY (`id`),
KEY `product` (`product`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_testtask` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`name` char(90) NOT NULL,
`product` mediumint(8) unsigned NOT NULL,
`project` mediumint(8) unsigned NOT NULL DEFAULT '0',
`build` char(30) NOT NULL,
`owner` varchar(30) NOT NULL,
`pri` tinyint(3) unsigned NOT NULL DEFAULT '0',
`begin` date NOT NULL,
`end` date NOT NULL,
`mailto` text,
`desc` text NOT NULL,
`report` text NOT NULL,
`status` enum('blocked','doing','wait','done') NOT NULL DEFAULT 'wait',
`subStatus` varchar(30) NOT NULL DEFAULT '',
`deleted` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `product` (`product`),
KEY `build` (`build`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_translation` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`lang` varchar(30) NOT NULL,
`module` varchar(30) NOT NULL,
`key` varchar(100) NOT NULL,
`value` text NOT NULL,
`referer` text NOT NULL,
`status` varchar(30) NOT NULL,
`translator` char(30) NOT NULL,
`translatedTime` datetime NOT NULL,
`reviewer` char(30) NOT NULL,
`reviewedTime` datetime NOT NULL,
`reason` text NOT NULL,
`version` varchar(20) NOT NULL,
`mode` varchar(20) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `lang_module_key_mode` (`lang`,`module`,`key`,`mode`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_todo` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`account` char(30) NOT NULL,
`date` date NOT NULL,
`begin` smallint(4) unsigned zerofill NOT NULL,
`end` smallint(4) unsigned zerofill NOT NULL,
`type` char(10) NOT NULL,
`cycle` tinyint(3) unsigned NOT NULL DEFAULT '0',
`idvalue` mediumint(8) unsigned NOT NULL DEFAULT '0',
`pri` tinyint(3) unsigned NOT NULL,
`name` char(150) NOT NULL,
`desc` text NOT NULL,
`status` enum('wait','doing','done','closed') NOT NULL DEFAULT 'wait',
`private` tinyint(1) NOT NULL,
`config` varchar(255) NOT NULL,
`assignedTo` varchar(30) NOT NULL DEFAULT '',
`assignedBy` varchar(30) NOT NULL DEFAULT '',
`assignedDate` datetime NOT NULL,
`finishedBy` varchar(30) NOT NULL DEFAULT '',
`finishedDate` datetime NOT NULL,
`closedBy` varchar(30) NOT NULL DEFAULT '',
`closedDate` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `account` (`account`),
KEY `assignedTo` (`assignedTo`),
KEY `finishedBy` (`finishedBy`),
KEY `date` (`date`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_user` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`dept` mediumint(8) unsigned NOT NULL DEFAULT '0',
`account` char(30) NOT NULL DEFAULT '',
`password` char(32) NOT NULL DEFAULT '',
`role` char(10) NOT NULL DEFAULT '',
`realname` varchar(100) NOT NULL DEFAULT '',
`nickname` char(60) NOT NULL DEFAULT '',
`commiter` varchar(100) NOT NULL,
`avatar` char(30) NOT NULL DEFAULT '',
`birthday` date NOT NULL DEFAULT '0000-00-00',
`gender` enum('f','m') NOT NULL DEFAULT 'f',
`email` char(90) NOT NULL DEFAULT '',
`skype` char(90) NOT NULL DEFAULT '',
`qq` char(20) NOT NULL DEFAULT '',
`mobile` char(11) NOT NULL DEFAULT '',
`phone` char(20) NOT NULL DEFAULT '',
`weixin` varchar(90) NOT NULL DEFAULT '',
`dingding` varchar(90) NOT NULL DEFAULT '',
`slack` varchar(90) NOT NULL DEFAULT '',
`whatsapp` varchar(90) NOT NULL DEFAULT '',
`address` char(120) NOT NULL DEFAULT '',
`zipcode` char(10) NOT NULL DEFAULT '',
`join` date NOT NULL DEFAULT '0000-00-00',
`visits` mediumint(8) unsigned NOT NULL DEFAULT '0',
`ip` char(15) NOT NULL DEFAULT '',
`last` int(10) unsigned NOT NULL DEFAULT '0',
`fails` tinyint(5) NOT NULL DEFAULT '0',
`locked` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`ranzhi` char(30) NOT NULL DEFAULT '',
`score` int(11) NOT NULL DEFAULT '0',
`scoreLevel` int(11) NOT NULL DEFAULT '0',
`deleted` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `account` (`account`),
KEY `dept` (`dept`),
KEY `email` (`email`),
KEY `commiter` (`commiter`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_usercontact` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`account` char(30) NOT NULL,
`listName` varchar(60) NOT NULL,
`userList` text NOT NULL,
PRIMARY KEY (`id`),
KEY `account` (`account`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_usergroup` (
`account` char(30) NOT NULL DEFAULT '',
`group` mediumint(8) unsigned NOT NULL DEFAULT '0',
UNIQUE KEY `account` (`account`,`group`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_userquery` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`account` char(30) NOT NULL,
`module` varchar(30) NOT NULL,
`title` varchar(90) NOT NULL,
`form` text NOT NULL,
`sql` text NOT NULL,
`shortcut` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `account` (`account`),
KEY `module` (`module`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_usertpl` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`account` char(30) NOT NULL,
`type` char(30) NOT NULL,
`title` varchar(150) NOT NULL,
`content` text NOT NULL,
`public` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `account` (`account`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_userview` (
`account` char(30) NOT NULL,
`products` mediumtext NOT NULL,
`projects` mediumtext NOT NULL,
UNIQUE KEY `account` (`account`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_webhook` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`type` varchar(10) NOT NULL DEFAULT 'default',
`name` varchar(50) NOT NULL,
`url` varchar(255) NOT NULL,
`domain` varchar(255) NOT NULL,
`contentType` varchar(30) NOT NULL DEFAULT 'application/json',
`sendType` enum('sync','async') NOT NULL DEFAULT 'sync',
`products` text NOT NULL,
`projects` text NOT NULL,
`params` varchar(100) NOT NULL,
`actions` text NOT NULL,
`desc` text NOT NULL,
`createdBy` varchar(30) NOT NULL,
`createdDate` datetime NOT NULL,
`editedBy` varchar(30) NOT NULL,
`editedDate` datetime NOT NULL,
`deleted` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-10
View File
@@ -1026,7 +1026,6 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
(1, 'admin', 'index'),
(1, 'admin', 'safe'),
(1, 'api', 'debug'),
(1, 'api', 'getModel'),
(1, 'api', 'sql'),
(1, 'backup', 'backup'),
(1, 'backup', 'change'),
@@ -1433,7 +1432,6 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
(1, 'user', 'view'),
(1, 'user', 'unbind'),
(2, 'action', 'editComment'),
(2, 'api', 'getModel'),
(2, 'bug', 'activate'),
(2, 'bug', 'assignTo'),
(2, 'bug', 'batchAssignTo'),
@@ -1620,7 +1618,6 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
(2, 'user', 'todo'),
(2, 'user', 'view'),
(3, 'action', 'editComment'),
(3, 'api', 'getModel'),
(3, 'bug', 'activate'),
(3, 'bug', 'assignTo'),
(3, 'bug', 'batchClose'),
@@ -1847,7 +1844,6 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
(4, 'action', 'trash'),
(4, 'action', 'undelete'),
(4, 'admin', 'index'),
(4, 'api', 'getModel'),
(4, 'bug', 'activate'),
(4, 'bug', 'assignTo'),
(4, 'bug', 'batchAssignTo'),
@@ -2086,7 +2082,6 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
(5, 'action', 'trash'),
(5, 'action', 'undelete'),
(5, 'admin', 'index'),
(5, 'api', 'getModel'),
(5, 'bug', 'activate'),
(5, 'bug', 'assignTo'),
(5, 'bug', 'batchAssignTo'),
@@ -2351,7 +2346,6 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
(6, 'action', 'trash'),
(6, 'action', 'undelete'),
(6, 'admin', 'index'),
(6, 'api', 'getModel'),
(6, 'bug', 'activate'),
(6, 'bug', 'assignTo'),
(6, 'bug', 'batchAssignTo'),
@@ -2588,7 +2582,6 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
(7, 'action', 'trash'),
(7, 'action', 'undelete'),
(7, 'admin', 'index'),
(7, 'api', 'getModel'),
(7, 'bug', 'activate'),
(7, 'bug', 'assignTo'),
(7, 'bug', 'batchClose'),
@@ -2838,7 +2831,6 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
(8, 'action', 'trash'),
(8, 'action', 'undelete'),
(8, 'admin', 'index'),
(8, 'api', 'getModel'),
(8, 'bug', 'activate'),
(8, 'bug', 'assignTo'),
(8, 'bug', 'batchAssignTo'),
@@ -3098,7 +3090,6 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
(9, 'action', 'trash'),
(9, 'action', 'undelete'),
(9, 'admin', 'index'),
(9, 'api', 'getModel'),
(9, 'bug', 'browse'),
(9, 'bug', 'export'),
(9, 'bug', 'index'),
@@ -3266,7 +3257,6 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
(9, 'user', 'view'),
(9, 'user', 'unbind'),
(10, 'action', 'editComment'),
(10, 'api', 'getModel'),
(10, 'bug', 'activate'),
(10, 'bug', 'browse'),
(10, 'bug', 'close'),
+6
View File
@@ -1,3 +1,9 @@
2019-09-24 11.6.3
修复的Bug:
2722 多人任务轮流完成之后状态异常
2755 项目下需求页面搜索异常
2766 导入用例时解析了js代码
2019-09-06 11.6.2
完成的需求:
4346 执行 init.sh生成的脚本和后台计划任务保持一致
+3 -2
View File
@@ -96,7 +96,8 @@ class helper extends baseHelper
if($position !== false) $toEncoding = substr($toEncoding, 0, $position);
/* Check string encoding. */
$encoding = strtolower(mb_detect_encoding($string, array('ASCII','UTF-8','GB2312','GBK','BIG5')));
$encodings = array_merge(array('GB2312','GBK','BIG5'), mb_list_encodings());
$encoding = strtolower(mb_detect_encoding($string, $encodings));
if($encoding == $toEncoding) return $string;
return mb_convert_encoding($string, $toEncoding, $encoding);
}
@@ -178,4 +179,4 @@ function autoloader($class)
}
}
spl_autoload_register('autoloader');
spl_autoload_register('autoloader');
+1 -1
View File
@@ -99,7 +99,7 @@ class ztclient
$controlAPI = $this->zentao->root . $module . $this->zentao->requestFix . $method . $this->zentao->requestFix;
if($vars)
{
$vars = parse_str($vars);
parse_str($vars, $vars);
foreach($vars as $var) $controlAPI .= $var . $this->zentao->requestFix;
}
$controlAPI = rtrim($controlAPI, $this->zentao->requestFix) . '.json';
+3
View File
@@ -137,6 +137,7 @@ $lang->action->desc->linkchildtask = '$date, <strong>$actor</strong> linked
$lang->action->desc->unlinkchildrentask = '$date, <strong>$actor</strong> unlinked a child task <strong>$extra</strong>。' . "\n";
$lang->action->desc->linkparenttask = '$date, <strong>$actor</strong> linked to a parent task <strong>$extra</strong>。' . "\n";
$lang->action->desc->unlinkparenttask = '$date, <strong>$actor</strong> unlinked a parent task <strong>$extra</strong>。' . "\n";
$lang->action->desc->deletechildrentask = '$date, <strong>$actor</strong> deleted a child task <strong>$extra</strong>。' . "\n";
/* Historical record of actions when associating and removing cases. */
$lang->action->desc->linkrelatedcase = '$date, <strong>$actor</strong> linked a case <strong>$extra</strong>.' . "\n";
@@ -209,6 +210,7 @@ $lang->action->label->unlinkparenttask = "unlink from parent task";
$lang->action->label->batchcreate = "batch created tasks";
$lang->action->label->createchildren = "create child tasks";
$lang->action->label->managed = "managed";
$lang->action->label->deletechildrentask = "delete children task";
/* Dynamic information is grouped by object. */
$lang->action->dynamicAction = new stdclass;
@@ -281,6 +283,7 @@ $lang->action->dynamicAction->task['canceled'] = 'Cancel Task';
$lang->action->dynamicAction->task['activated'] = 'Activate Task';
$lang->action->dynamicAction->task['createchildren'] = 'Create Child Task';
$lang->action->dynamicAction->task['unlinkparenttask'] = 'Unlink Parent Task';
$lang->action->dynamicAction->task['deletechildrentask'] = 'Delete children task';
$lang->action->dynamicAction->task['linkparenttask'] = 'Link Parent Task';
$lang->action->dynamicAction->task['linkchildtask'] = 'Link Child Task';
$lang->action->dynamicAction->task['undeleted'] = 'Restore Task';
+3
View File
@@ -137,6 +137,7 @@ $lang->action->desc->linkchildtask = '$date, 由 <strong>$actor</strong>
$lang->action->desc->unlinkchildrentask = '$date, 由 <strong>$actor</strong> 移除子任务 <strong>$extra</strong>。' . "\n";
$lang->action->desc->linkparenttask = '$date, 由 <strong>$actor</strong> 关联到父任务 <strong>$extra</strong>。' . "\n";
$lang->action->desc->unlinkparenttask = '$date, 由 <strong>$actor</strong> 从父任务<strong>$extra</strong>取消关联。' . "\n";
$lang->action->desc->deletechildrentask = '$date, 由 <strong>$actor</strong> 删除子任务<strong>$extra</strong>。' . "\n";
/* 关联用例和移除用例时的历史操作记录。*/
$lang->action->desc->linkrelatedcase = '$date, 由 <strong>$actor</strong> 关联相关用例 <strong>$extra</strong>。' . "\n";
@@ -209,6 +210,7 @@ $lang->action->label->unlinkparenttask = "从父任务取消关联";
$lang->action->label->batchcreate = "批量创建任务";
$lang->action->label->createchildren = "创建子任务";
$lang->action->label->managed = "维护";
$lang->action->label->deletechildrentask = "删除子任务";
/* 动态信息按照对象分组 */
$lang->action->dynamicAction = new stdclass();
@@ -281,6 +283,7 @@ $lang->action->dynamicAction->task['canceled'] = '取消任务';
$lang->action->dynamicAction->task['activated'] = '激活任务';
$lang->action->dynamicAction->task['createchildren'] = '创建子任务';
$lang->action->dynamicAction->task['unlinkparenttask'] = '从父任务取消关联';
$lang->action->dynamicAction->task['deletechildrentask'] = '删除子任务';
$lang->action->dynamicAction->task['linkparenttask'] = '关联到父任务';
$lang->action->dynamicAction->task['linkchildtask'] = '关联子任务';
$lang->action->dynamicAction->task['undeleted'] = '还原任务';
+2 -2
View File
@@ -303,7 +303,7 @@ class actionModel extends model
}
$action->extra = trim(trim($action->extra), ',');
}
elseif($actionName == 'totask' or $actionName == 'linkchildtask' or $actionName == 'unlinkchildrentask' or $actionName == 'linkparenttask' or $actionName == 'unlinkparenttask')
elseif($actionName == 'totask' or $actionName == 'linkchildtask' or $actionName == 'unlinkchildrentask' or $actionName == 'linkparenttask' or $actionName == 'unlinkparenttask' or $actionName == 'deletechildrentask')
{
$name = $this->dao->select('name')->from(TABLE_TASK)->where('id')->eq($action->extra)->fetch('name');
if($name) $action->extra = common::hasPriv('task', 'view') ? html::a(helper::createLink('task', 'view', "taskID=$action->extra"), "#$action->extra " . $name) : "#$action->extra " . $name;
@@ -838,7 +838,7 @@ class actionModel extends model
}
$action->objectLink = helper::createLink($moduleName, $methodName, sprintf($vars, $action->objectID));
if($action->objectType == 'user') $action->objectLink = helper::createLink($moduleName, $methodName, sprintf($vars, $action->actor));
if($action->objectType == 'user') $action->objectLink = helper::createLink($moduleName, $methodName, sprintf($vars, $action->objectName));
$action->objectLabel = $objectLabel;
}
else
+4 -3
View File
@@ -105,8 +105,9 @@ class api extends control
*/
public function sql($keyField = '')
{
$sql = isset($_POST['sql']) ? $this->post->sql : '';
$this->view->results = $this->api->sql($sql, $keyField);
die($this->display());
die();
//$sql = isset($_POST['sql']) ? $this->post->sql : '';
//$this->view->results = $this->api->sql($sql, $keyField);
//die($this->display());
}
}
+14 -2
View File
@@ -346,7 +346,7 @@ class block extends control
}
else
{
$html = "<div class='panel-body'><div class='article-content'>" . htmlspecialchars_decode($block->params->html) .'</div></div>';
$html = "<div class='panel-body'><div class='article-content'>" . $block->params->html . '</div></div>';
}
}
elseif($block->source != '')
@@ -713,8 +713,20 @@ class block extends control
$pager = pager::init(0, $num , 1);
$productStats = $this->loadModel('product')->getStats('order_desc', $this->viewType != 'json' ? $pager : '', $type);
$projects = $this->loadModel('project')->getPairs();
$productIdList = array();
foreach($productStats as $product) $productIdList[] = $product->id;
$this->loadModel('action');
foreach($productStats as $product)
{
$currentProjectID = $this->dao->select('objectID')->from(TABLE_ACTION)
->where('objectType')->eq('project')
->andWhere('action')->eq('managed')
->andWhere("CONCAT(extra, ',,')")->like("%$product->id,,")
->orderBy('id_desc')
->fetch('objectID');
$product->currentProject = zget($projects, $currentProjectID, '');
$productIdList[] = $product->id;
}
$this->view->projects = $this->dao->select('t1.product,t2.name')->from(TABLE_PROJECTPRODUCT)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project=t2.id')
+2 -2
View File
@@ -39,8 +39,8 @@
<tr class='text-center' data-url='<?php echo empty($sso) ? $viewLink : $sso . $sign . 'referer=' . base64_encode($viewLink); ?>' <?php echo $appid?>>
<td class='c-name text-left' title='<?php echo $product->name?>'><?php echo $product->name?></td>
<?php if($longBlock):?>
<?php $projectName = zget($projects, $product->id, '');?>
<td class='c-name c-project text-left' title='<?php echo $projectName;?>'><?php echo zget($projects, $product->id, '');?></td>
<?php $projectName = $product->currentProject ? $product->currentProject : zget($projects, $product->id, '');?>
<td class='c-name c-project text-left' title='<?php echo $projectName;?>'><?php echo $projectName;?></td>
<?php endif;?>
<td class="c-num"><?php echo $product->plans?></td>
<td class="c-num"><?php echo $product->releases?></td>
+2 -2
View File
@@ -258,7 +258,7 @@ class bug extends control
if(!empty($_POST))
{
$response['result'] = 'success';
$response['message'] = '';
$response['message'] = $this->lang->saveSuccess;
/* Set from param if there is a object to transfer bug. */
$bugResult = $this->bug->create($from = isset($fromObjectIDKey) ? $fromObjectIDKey : '');
@@ -408,7 +408,7 @@ class bug extends control
$this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]);
$this->view->position[] = $this->lang->bug->create;
$this->view->products = $products;
$this->view->products = $products;
$this->view->productID = $productID;
$this->view->productName = $this->products[$productID];
$this->view->moduleOptionMenu = $moduleOptionMenu;
+2
View File
@@ -41,4 +41,6 @@ html[lang='en'] #deadlineTd .input-group-addon{padding: 5px 18px}
#mainContent .center-block{padding-bottom:40px;}
#typeBox {width:180px;}
#typeBox .required:after {right: 1px;}
#osBox .required:after {right: 1px;}
#osBox {width:190px;}
+1
View File
@@ -632,6 +632,7 @@ class bugModel extends model
->setIF($this->post->resolution == '' and $this->post->resolvedDate =='', 'status', 'active')
->setIF($this->post->resolution != '', 'confirmed', 1)
->setIF($this->post->story != false and $this->post->story != $oldBug->story, 'storyVersion', $this->loadModel('story')->getVersion($this->post->story))
->setIF(!$this->post->linkBug, 'linkBug', '')
->remove('comment,files,labels,uid,contactListMenu')
->get();
+1 -1
View File
@@ -38,7 +38,7 @@ js::set('flow', $config->global->flow);
<td class='w-600px'>
<div class='input-group'>
<?php echo html::select('product', $products, $productID, "onchange='loadAll(this.value);' class='form-control chosen control-product'");?>
<?php if($this->session->currentProductType != 'normal'):?>
<?php if($this->session->currentProductType != 'normal' and isset($products[$productID])):?>
<?php echo html::select('branch', $branches, $branch, "onchange='loadBranch()' class='form-control chosen control-branch'");?>
<?php endif;?>
</div>
+16
View File
@@ -0,0 +1,16 @@
<?php
$config->caselib = new stdclass();
$config->caselib->create = new stdclass();
$config->caselib->createcase = new stdclass();
$config->caselib->create->requiredFields = 'name';
$config->caselib->createcase->requiredFields = 'title,type';
$config->caselib->editor = new stdclass();
$config->caselib->editor->create = array('id' => 'desc', 'tools' => 'simpleTools');
$config->caselib->datatable = new stdclass();
$config->caselib->datatable->defaultField = array('id', 'pri', 'title', 'type', 'assignedTo', 'lastRunner', 'lastRunDate', 'lastRunResult', 'status', 'bugs', 'results', 'actions');
$config->caselib->custom = new stdclass();
$config->caselib->custom->createFields = 'stage,pri,keywords';
$config->caselib->customCreateFields = 'stage,pri,keywords';
+737
View File
@@ -0,0 +1,737 @@
<?php
/**
* The control file of caselib module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package caselib
* @version $Id: control.php 5114 2013-07-12 06:02:59Z chencongzhi520@gmail.com $
* @link http://www.zentao.net
*/
class caselib extends control
{
public $products = array();
/**
* Index page, header to browse.
*
* @access public
* @return void
*/
public function index()
{
$this->locate($this->createLink('caselib', 'browse'));
}
/**
* Create lib
*
* @access public
* @return void
*/
public function create()
{
if(!empty($_POST))
{
$response['result'] = 'success';
$response['message'] = $this->lang->saveSuccess;
$libID = $this->caselib->create();
if(dao::isError())
{
$response['result'] = 'fail';
$response['message'] = dao::getError();
$this->send($response);
}
$this->loadModel('action')->create('caselib', $libID, 'opened');
$response['locate'] = $this->createLink('caselib', 'browse', "libID=$libID");
$this->send($response);
}
/* Set menu. */
$libraries = $this->caselib->getLibraries();
$libID = $this->caselib->saveLibState(0, $libraries);
$this->caselib->setLibMenu($libraries, $libID);
$this->view->title = $this->lang->caselib->common . $this->lang->colon . $this->lang->caselib->create;
$this->view->position[] = $this->lang->caselib->common;
$this->view->position[] = $this->lang->caselib->create;
$this->display();
}
/**
* Edit a case lib.
*
* @param int $lib
* @access public
* @return void
*/
public function edit($libID)
{
$lib = $this->caselib->getById($libID);
if(!empty($_POST))
{
$response['result'] = 'success';
$response['message'] = $this->lang->saveSuccess;
$changes = $this->caselib->update($libID);
if(dao::isError())
{
$response['result'] = 'fail';
$response['message'] = dao::getError();
$this->send($response);
}
if($changes)
{
$actionID = $this->loadModel('action')->create('caselib', $libID, 'edited');
$this->action->logHistory($actionID, $changes);
}
$this->executeHooks($libID);
$response['locate'] = inlink('view', "libID=$libID");
$this->send($response);
}
/* Set lib menu. */
$libraries = $this->caselib->getLibraries();
$libID = $this->caselib->saveLibState($libID, $libraries);
$this->caselib->setLibMenu($libraries, $libID);
$this->view->title = $libraries[$libID] . $this->lang->colon . $this->lang->caselib->edit;
$this->view->position[] = html::a($this->createLink('caselib', 'browse', "libID=$libID"), $libraries[$libID]);
$this->view->position[] = $this->lang->caselib->common;
$this->view->position[] = $this->lang->caselib->edit;
$this->view->lib = $lib;
$this->display();
}
/**
* Delete a case lib.
*
* @param int $libID
* @param string $confirm yes|no
* @access public
* @return void
*/
public function delete($libID, $confirm = 'no')
{
if($confirm == 'no')
{
die(js::confirm($this->lang->caselib->libraryDelete, inlink('delete', "libID=$libID&confirm=yes")));
}
else
{
$this->caselib->delete($libID);
$this->executeHooks($libID);
/* if ajax request, send result. */
if($this->server->ajax)
{
if(dao::isError())
{
$response['result'] = 'fail';
$response['message'] = dao::getError();
}
else
{
$response['result'] = 'success';
$response['message'] = '';
}
$this->send($response);
}
die(js::reload('parent'));
}
}
/**
* Show library case.
*
* @param int $libID
* @param string $browseType
* @param int $param
* @param string $orderBy
* @param int $recTotal
* @param int $recPerPage
* @param int $pageID
* @access public
* @return void
*/
public function browse($libID = 0, $browseType = 'all', $param = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
{
/* Set browse type. */
$browseType = strtolower($browseType);
$libraries = $this->caselib->getLibraries();
if(empty($libraries)) $this->locate(inlink('create'));
/* Save session. */
$this->session->set('caseList', $this->app->getURI(true));
/* Set menu. */
$libID = $this->caselib->saveLibState($libID, $libraries);
setcookie('preCaseLibID', $libID, $this->config->cookieLife, $this->config->webRoot);
if($this->cookie->preCaseLibID != $libID)
{
$_COOKIE['libCaseModule'] = 0;
setcookie('libCaseModule', 0, 0, $this->config->webRoot);
}
if($browseType == 'bymodule') setcookie('libCaseModule', (int)$param, 0, $this->config->webRoot);
if($browseType != 'bymodule') $this->session->set('libBrowseType', $browseType);
$moduleID = ($browseType == 'bymodule') ? (int)$param : ($browseType == 'bysearch' ? 0 : ($this->cookie->libCaseModule ? $this->cookie->libCaseModule : 0));
$queryID = ($browseType == 'bysearch') ? (int)$param : 0;
/* Set lib menu. */
$this->caselib->setLibMenu($libraries, $libID, $moduleID);
/* Load pager. */
$this->app->loadClass('pager', $static = true);
$pager = pager::init($recTotal, $recPerPage, $pageID);
/* Build the search form. */
$this->loadModel('testcase');
$actionURL = $this->createLink('caselib', 'browse', "libID=$libID&browseType=bySearch&queryID=myQueryID");
$this->caselib->buildSearchForm($libID, $libraries, $queryID, $actionURL);
/* Append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
/* save session .*/
$cases = $this->caselib->getLibCases($libID, $browseType, $queryID, $moduleID, $sort, $pager);
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'testcase', true);
$this->loadModel('datatable');
$this->loadModel('tree');
$showModule = !empty($this->config->datatable->caselibLibrary->showModule) ? $this->config->datatable->caselibLibrary->showModule : '';
$this->view->modulePairs = $showModule ? $this->tree->getModulePairs($libID, 'caselib', $showModule) : array();
$this->view->title = $this->lang->caselib->common . $this->lang->colon . $libraries[$libID];
$this->view->position[] = html::a($this->createLink('caselib', 'browse', "libID=$libID"), $libraries[$libID]);
$this->view->libID = $libID;
$this->view->libName = $libraries[$libID];
$this->view->cases = $cases;
$this->view->orderBy = $orderBy;
$this->view->users = $this->loadModel('user')->getPairs('noclosed|noletter');
$this->view->modules = $this->tree->getOptionMenu($libID, $viewType = 'caselib', $startModuleID = 0);
$this->view->moduleTree = $this->tree->getTreeMenu($libID, $viewType = 'caselib', $startModuleID = 0, array('treeModel', 'createCaseLibLink'));
$this->view->pager = $pager;
$this->view->browseType = $browseType;
$this->view->moduleID = $moduleID;
$this->view->moduleName = $moduleID ? $this->tree->getById($moduleID)->name : $this->lang->tree->all;
$this->view->param = $param;
$this->view->setShowModule = true;
$this->display();
}
/**
* Create case for library.
*
* @param int $libID
* @param int $moduleID
* @access public
* @return void
*/
public function createCase($libID, $moduleID = 0, $param = 0)
{
if(!empty($_POST))
{
$this->loadModel('testcase');
$this->config->testcase->create->requiredFields = $this->config->caselib->createcase->requiredFields;
$caseResult = $this->testcase->create($bugID = 0);
if(!$caseResult or dao::isError()) die(js::error(dao::getError()));
$caseID = $caseResult['id'];
if($caseResult['status'] == 'exists')
{
echo js::alert(sprintf($this->lang->duplicate, $this->lang->testcase->common));
die(js::locate($this->createLink('testcase', 'view', "caseID=$caseID"), 'parent'));
}
$this->loadModel('action')->create('case', $caseID, 'Opened');
/* If link from no head then reload. */
if(isonlybody()) die(js::reload('parent'));
die(js::locate($this->createLink('caselib', 'browse', "libID={$libID}&browseType=byModule&param={$_POST['module']}"), 'parent'));
}
/* Set lib menu. */
$libraries = $this->caselib->getLibraries();
$libID = $this->caselib->saveLibState($libID, $libraries);
$this->caselib->setLibMenu($libraries, $libID);
$type = 'feature';
$stage = '';
$pri = 3;
$caseTitle = '';
$precondition = '';
$keywords = '';
$steps = array();
$this->loadModel('testcase');
if($param)
{
$testcase = $this->testcase->getById((int)$param);
$type = $testcase->type ? $testcase->type : 'feature';
$stage = $testcase->stage;
$pri = $testcase->pri;
$storyID = $testcase->story;
$caseTitle = $testcase->title;
$precondition = $testcase->precondition;
$keywords = $testcase->keywords;
$steps = $testcase->steps;
}
if(count($steps) < $this->config->testcase->defaultSteps)
{
$paddingCount = $this->config->testcase->defaultSteps - count($steps);
$step = new stdclass();
$step->type = 'item';
$step->desc = '';
$step->expect = '';
for($i = 1; $i <= $paddingCount; $i ++) $steps[] = $step;
}
$this->view->title = $libraries[$libID] . $this->lang->colon . $this->lang->testcase->create;
$this->view->position[] = html::a($this->createLink('caselib', 'browse', "libID=$libID"), $libraries[$libID]);
$this->view->position[] = $this->lang->caselib->common;
$this->view->position[] = $this->lang->testcase->create;
foreach(explode(',', $this->config->caselib->customCreateFields) as $field) $customFields[$field] = $this->lang->testcase->$field;
$this->view->showFields = $this->config->caselib->custom->createFields;
$this->view->customFields = $customFields;
$this->view->libraries = $libraries;
$this->view->libID = $libID;
$this->view->currentModuleID = (int)$moduleID;
$this->view->caseTitle = $caseTitle;
$this->view->type = $type;
$this->view->stage = $stage;
$this->view->pri = $pri;
$this->view->precondition = $precondition;
$this->view->keywords = $keywords;
$this->view->steps = $steps;
$this->view->moduleOptionMenu = $this->loadModel('tree')->getOptionMenu($libID, $viewType = 'caselib', $startModuleID = 0);
$this->display();
}
/**
* Batch create case.
*
* @param int $libID
* @param int $moduleID
* @access public
* @return void
*/
public function batchCreateCase($libID, $moduleID = 0)
{
$this->loadModel('testcase');
if(!empty($_POST))
{
$caseID = $this->caselib->batchCreateCase($libID);
if(dao::isError()) die(js::error(dao::getError()));
if(isonlybody()) die(js::closeModal('parent.parent', 'this'));
die(js::locate($this->createLink('caselib', 'browse', "libID=$libID&browseType=byModule&param=$moduleID"), 'parent'));
}
$libraries = $this->caselib->getLibraries();
if(empty($libraries)) $this->locate(inlink('create'));
/* Set lib menu. */
$this->caselib->setLibMenu($libraries, $libID);
$currentModuleID = (int)$moduleID;
/* Set module option menu. */
$moduleOptionMenu = $this->loadModel('tree')->getOptionMenu($libID, $viewType = 'caselib', $startModuleID = 0);
$moduleOptionMenu['ditto'] = $this->lang->testcase->ditto;
$this->view->title = $libraries[$libID] . $this->lang->colon . $this->lang->testcase->batchCreate;
$this->view->position[] = html::a($this->createLink('caselib', 'browse', "libID=$libID"), $libraries[$libID]);
$this->view->position[] = $this->lang->testcase->batchCreate;
$this->view->libID = $libID;
$this->view->moduleOptionMenu = $moduleOptionMenu;
$this->view->currentModuleID = $currentModuleID;
$this->display();
}
/**
* View library
*
* @param int $libID
* @access public
* @return void
*/
public function view($libID)
{
$lib = $this->caselib->getById($libID, true);
/* Set lib menu. */
$libraries = $this->caselib->getLibraries();
$this->caselib->setLibMenu($libraries, $libID);
$this->loadModel('testcase');
$this->view->title = $lib->name . $this->lang->colon . $this->lang->caselib->view;
$this->view->position[] = html::a($this->createLink('caselib', 'browse', "libID=$libID"), $lib->name);
$this->view->position[] = $this->lang->caselib->common;
$this->view->position[] = $this->lang->caselib->view;
$this->view->lib = $lib;
$this->view->users = $this->loadModel('user')->getPairs('noclosed|noletter');
$this->view->actions = $this->loadModel('action')->getList('caselib', $libID);
$this->display();
}
/**
* Ajax get drop menu.
*
* @param int $libID
* @param string $module
* @param string $method
* @param string $extra
* @access public
* @return void
*/
public function ajaxGetDropMenu($libID, $module, $method, $extra = '')
{
$this->view->link = $this->caselib->getLibLink($module, $method, $extra);
$this->view->libID = $libID;
$this->view->module = $module;
$this->view->method = $method;
$this->view->extra = $extra;
$libraries = $this->caselib->getLibraries();
$this->view->libraries = $libraries;
$this->view->librariesPinyin = common::convert2Pinyin($libraries);
$this->display();
}
/**
* The results page of search.
*
* @param string $keywords
* @param string $module
* @param string $method
* @param mix $extra
* @access public
* @return void
*/
public function ajaxGetMatchedItems($keywords, $module, $method, $extra)
{
$libraries = $this->dao->select('*')->from(TABLE_TESTSUITE)->where('deleted')->eq(0)->andWhere('name')->like("%$keywords%")->andWhere('type')->eq('library')->orderBy('`id` desc')->fetchAll();
$this->view->link = $this->caselib->getLibLink($module, $method, $extra);
$this->view->libraries = $libraries;
$this->view->keywords = $keywords;
$this->display();
}
/**
* Export templet.
*
* @param int $libID
* @access public
* @return void
*/
public function exportTemplet($libID)
{
$this->loadModel('testcase');
if($_POST)
{
$fields['module'] = $this->lang->testcase->module;
$fields['title'] = $this->lang->testcase->title;
$fields['precondition'] = $this->lang->testcase->precondition;
$fields['stepDesc'] = $this->lang->testcase->stepDesc;
$fields['stepExpect'] = $this->lang->testcase->stepExpect;
$fields['keywords'] = $this->lang->testcase->keywords;
$fields['pri'] = $this->lang->testcase->pri;
$fields['type'] = $this->lang->testcase->type;
$fields['stage'] = $this->lang->testcase->stage;
$fields[''] = '';
$fields['typeValue'] = $this->lang->testcase->lblTypeValue;
$fields['stageValue'] = $this->lang->testcase->lblStageValue;
$modules = $this->loadModel('tree')->getOptionMenu($libID, $viewType = 'caselib', $startModuleID = 0);
$rows = array();
$num = (int)$this->post->num;
for($i = 0; $i < $num; $i++)
{
foreach($modules as $moduleID => $module)
{
$row = new stdclass();
$row->module = $module . "(#$moduleID)";
$row->stepDesc = "1. \n2. \n3.";
$row->stepExpect = "1. \n2. \n3.";
if(empty($rows))
{
$row->typeValue = join("\n", $this->lang->testcase->typeList);
$row->stageValue = join("\n", $this->lang->testcase->stageList);
}
$rows[] = $row;
}
}
$this->post->set('fields', $fields);
$this->post->set('kind', 'testcase');
$this->post->set('rows', $rows);
$this->post->set('extraNum', $num);
$this->post->set('fileName', 'templet');
$this->fetch('file', 'export2csv', $_POST);
}
$this->display();
}
/**
* Import case csv file.
*
* @param int $libID
* @access public
* @return void
*/
public function import($libID)
{
$this->loadModel('testcase');
if($_FILES)
{
$file = $this->loadModel('file')->getUpload('file');
$file = $file[0];
$fileName = $this->file->savePath . $this->file->getSaveName($file['pathname']);
move_uploaded_file($file['tmpname'], $fileName);
$rows = $this->file->parseCSV($fileName);
$fields = $this->testcase->getImportFields($productID);
$fields = array_flip($fields);
$header = array();
foreach($rows[0] as $i => $rowValue)
{
if(empty($rowValue)) break;
$header[$i] = $rowValue;
}
unset($rows[0]);
$columnKey = array();
foreach($header as $title)
{
if(!isset($fields[$title])) continue;
$columnKey[] = $fields[$title];
}
if(count($columnKey) != count($header) or $this->post->encode != 'utf-8')
{
$fc = file_get_contents($fileName);
$encode = $this->post->encode != "utf-8" ? $this->post->encode : 'gbk';
$fc = helper::convertEncoding($fc, $encode, 'utf-8');
file_put_contents($fileName, $fc);
$rows = $this->file->parseCSV($fileName);
$columnKey = array();
$header = array();
foreach($rows[0] as $i => $rowValue)
{
if(empty($rowValue)) break;
$header[$i] = $rowValue;
}
unset($rows[0]);
foreach($header as $title)
{
if(!isset($fields[$title])) continue;
$columnKey[] = $fields[$title];
}
if(count($columnKey) != count($header)) die(js::alert($this->lang->testcase->errorEncode));
}
$this->session->set('importFile', $fileName);
die(js::locate(inlink('showImport', "libID=$libID"), 'parent.parent'));
}
$this->display();
}
/**
* Show import case.
*
* @param int $libID
* @access public
* @return void
*/
public function showImport($libID)
{
$this->loadModel('testcase');
if($_POST)
{
$this->caselib->createFromImport($libID);
die(js::locate(inlink('browse', "libID=$libID"), 'parent'));
}
$libraries = $this->caselib->getLibraries();
if(empty($libraries)) $this->locate(inlink('create'));
$this->caselib->setLibMenu($libraries, $libID);
$file = $this->session->importFile;
$caseLang = $this->lang->testcase;
$caseConfig = $this->config->testcase;
$modules = $this->loadModel('tree')->getOptionMenu($libID, $viewType = 'caselib', $startModuleID = 0);
$fields = explode(',', $caseConfig->exportFields);
foreach($fields as $key => $fieldName)
{
$fieldName = trim($fieldName);
$fields[$fieldName] = isset($caseLang->$fieldName) ? $caseLang->$fieldName : $fieldName;
unset($fields[$key]);
}
$fields = array_flip($fields);
$rows = $this->loadModel('file')->parseCSV($file);
$header = array();
foreach($rows[0] as $i => $rowValue)
{
if(empty($rowValue)) break;
$header[$i] = $rowValue;
}
unset($rows[0]);
foreach($header as $title)
{
if(!isset($fields[$title])) continue;
$columnKey[] = $fields[$title];
}
$endField = end($fields);
$caseData = array();
$stepData = array();
$stepVars = 0;
foreach($rows as $row => $data)
{
$case = new stdclass();
foreach($columnKey as $key => $field)
{
if(!isset($data[$key])) continue;
$cellValue = $data[$key];
if($field == 'module')
{
$case->$field = 0;
if(strrpos($cellValue, '(#') !== false)
{
$id = trim(substr($cellValue, strrpos($cellValue,'(#') + 2), ')');
$case->$field = $id;
}
}
elseif(in_array($field, $caseConfig->export->listFields))
{
if($field == 'stage')
{
$stages = explode("\n", $cellValue);
foreach($stages as $stage) $case->stage[] = array_search($stage, $caseLang->{$field . 'List'});
$case->stage = join(',', $case->stage);
}
else
{
$case->$field = array_search($cellValue, $caseLang->{$field . 'List'});
}
}
elseif($field != 'stepDesc' and $field != 'stepExpect')
{
$case->$field = $cellValue;
}
else
{
$steps = (array)$cellValue;
if(strpos($cellValue, "\n"))
{
$steps = explode("\n", $cellValue);
}
elseif(strpos($cellValue, "\r"))
{
$steps = explode("\r", $cellValue);
}
$stepKey = str_replace('step', '', strtolower($field));
$caseStep = array();
foreach($steps as $step)
{
$step = trim($step);
if(empty($step)) continue;
if(preg_match('/^(([0-9]+)\.[0-9]+)([.、]{1})/U', $step, $out))
{
$num = $out[1];
$parent = $out[2];
$sign = $out[3];
$signbit = $sign == '.' ? 1 : 3;
$step = trim(substr($step, strlen($num) + $signbit));
if(!empty($step)) $caseStep[$num]['content'] = $step;
$caseStep[$num]['type'] = 'item';
$caseStep[$parent]['type'] = 'group';
}
elseif(preg_match('/^([0-9]+)([.、]{1})/U', $step, $out))
{
$num = $out[1];
$sign = $out[2];
$signbit = $sign == '.' ? 1 : 3;
$step = trim(substr($step, strlen($num) + $signbit));
if(!empty($step)) $caseStep[$num]['content'] = $step;
$caseStep[$num]['type'] = 'step';
}
elseif(isset($num))
{
if(!isset($caseStep[$num]['content'])) $caseStep[$num]['content'] = '';
$caseStep[$num]['content'] .= "\n" . $step;
}
else
{
if($field == 'stepDesc')
{
$num = 1;
$caseStep[$num]['content'] = $step;
$caseStep[$num]['type'] = 'step';
}
if($field == 'stepExpect' and isset($stepData[$row]['desc']))
{
end($stepData[$row]['desc']);
$num = key($stepData[$row]['desc']);
$caseStep[$num]['content'] = $step;
}
}
}
unset($num);
unset($sign);
$stepVars += count($caseStep, COUNT_RECURSIVE) - count($caseStep);
$stepData[$row][$stepKey] = $caseStep;
}
}
$caseData[$row] = $case;
unset($case);
}
if(empty($caseData))
{
unlink($this->session->importFile);
unset($_SESSION['importFile']);
echo js::alert($this->lang->error->noData);
die(js::locate($this->createLink('caselib', 'browse', "libID=$libID")));
}
/* Judge whether the editedTasks is too large and set session. */
$countInputVars = count($caseData) * 9 + $stepVars;
$showSuhosinInfo = common::judgeSuhosinSetting($countInputVars);
if($showSuhosinInfo) $this->view->suhosinInfo = extension_loaded('suhosin') ? sprintf($this->lang->suhosinInfo, $countInputVars) : sprintf($this->lang->maxVarsInfo, $countInputVars);
$this->view->title = $this->lang->caselib->common . $this->lang->colon . $this->lang->testcase->showImport;
$this->view->position[] = $this->lang->testcase->showImport;
$this->view->modules = $modules;
$this->view->cases = $this->dao->select('id,module,stage,status,pri,type')->from(TABLE_CASE)->where('lib')->eq($libID)->andWhere('deleted')->eq(0)->andWhere('product')->eq(0)->fetchAll('id');
$this->view->caseData = $caseData;
$this->view->stepData = $stepData;
$this->view->libID = $libID;
$this->display();
}
}
+37
View File
@@ -0,0 +1,37 @@
<?php
/**
* The caselib module en file of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Yidong Wang <yidong@cnezsoft.com>
* @package caselib
* @version $Id: zh-cn.php 4490 2013-02-27 03:27:05Z wyd621@gmail.com $
* @link http://www.zentao.net
*/
$lang->caselib->common = 'Case Library';
$lang->caselib->all = 'All Case Libraries';
$lang->caselib->index = "Library Home";
$lang->caselib->create = "Create Case Library";
$lang->caselib->edit = 'Edit Case Library';
$lang->caselib->browse = 'View Cases in Library';
$lang->caselib->view = 'Library Detail';
$lang->caselib->createCase = 'Create Case';
$lang->caselib->delete = "Delete Suite";
$lang->caselib->linkVersion = "Version";
$lang->caselib->deleted = 'Deleted';
$lang->caselib->exportTemplet = 'Export Template';
$lang->caselib->batchCreateCase = 'Batch Create';
$lang->caselib->import = 'Import';
$lang->caselib->importAction = 'Import Case';
$lang->caselib->showImport = 'Imported Data';
$lang->caselib->id = 'ID';
$lang->caselib->name = 'Name';
$lang->caselib->desc = 'Description';
$lang->caselib->legendDesc = 'Description';
$lang->caselib->libraryDelete = 'Do you want to delete this library?';
$lang->caselib->noModule = '<div>You have no modules.</div><div>Manage it now.</div>';
+37
View File
@@ -0,0 +1,37 @@
<?php
/**
* The caselib module zh-cn file of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Yidong Wang <yidong@cnezsoft.com>
* @package caselib
* @version $Id: zh-cn.php 4490 2013-02-27 03:27:05Z wyd621@gmail.com $
* @link http://www.zentao.net
*/
$lang->caselib->common = '用例库';
$lang->caselib->all = '所有用例库';
$lang->caselib->index = "用例库首页";
$lang->caselib->create = "创建用例库";
$lang->caselib->edit = '编辑用例库';
$lang->caselib->browse = '浏览库用例';
$lang->caselib->view = '查看库概况';
$lang->caselib->createCase = '创建用例';
$lang->caselib->delete = "删除";
$lang->caselib->linkVersion = "版本";
$lang->caselib->deleted = '已删除';
$lang->caselib->exportTemplet = '导出模板';
$lang->caselib->batchCreateCase = '批量创建用例';
$lang->caselib->import = '导入';
$lang->caselib->importAction = '导入用例';
$lang->caselib->showImport = '显示导入数据';
$lang->caselib->id = '编号';
$lang->caselib->name = '名称';
$lang->caselib->desc = '描述';
$lang->caselib->legendDesc = '描述';
$lang->caselib->libraryDelete = '您确认要删除该用例库吗?';
$lang->caselib->noModule = '<div>您现在还没有模块信息</div><div>请维护用例库模块</div>';
+640
View File
@@ -0,0 +1,640 @@
<?php
/**
* The model file of caselib module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package caselib
* @version $Id: model.php 5114 2013-07-12 06:02:59Z chencongzhi520@gmail.com $
* @link http://www.zentao.net
*/
?>
<?php
class caselibModel extends model
{
/**
* Set library menu.
*
* @param array $libraries
* @param int $libID
* @access public
* @return void
*/
public function setLibMenu($libraries, $libID, $moduleID = 0)
{
$currentLibName = zget($libraries, $libID, '');
$isMobile = $this->app->viewType == 'mhtml';
$selectHtml = '';
if(!empty($libraries))
{
if($isMobile)
{
$selectHtml = "<a id='currentItem' href=\"javascript:showSearchMenu('caselib', '$libID', 'caselib', 'browse', '')\">{$currentLibName} <span class='icon-caret-down'></span></a><div id='currentItemDropMenu' class='hidden affix enter-from-bottom layer'></div>";
}
else
{
$dropMenuLink = helper::createLink('caselib', 'ajaxGetDropMenu', "objectID=$libID&module=caselib&method=browse");
$selectHtml = "<div class='btn-group angle-btn'><div class='btn-group'><button data-toggle='dropdown' type='button' class='btn btn-limit' id='currentItem'>{$currentLibName} <span class='caret'></span></button><div id='dropMenu' class='dropdown-menu search-list' data-ride='searchList' data-url='$dropMenuLink'>";
$selectHtml .= '<div class="input-control search-box has-icon-left has-icon-right search-example"><input type="search" class="form-control search-input" /><label class="input-control-icon-left search-icon"><i class="icon icon-search"></i></label><a class="input-control-icon-right search-clear-btn"><i class="icon icon-close icon-sm"></i></a></div>';
$selectHtml .= "</div></div></div>";
}
}
if($this->config->global->flow == 'onlyTest')
{
$modules = $this->loadModel('tree')->getModulePairs($libID, 'caselib');
$moduleName = ($moduleID && isset($modules[$moduleID])) ? $modules[$moduleID] : $this->lang->tree->all;
if(!$isMobile)
{
$dropMenuLink = helper::createLink('tree', 'ajaxGetDropMenu', "objectID=$libID&module=caselib&method=browse");
$selectHtml .= "<div class='btn-group'><button id='currentModule' data-toggle='dropdown' type='button' class='btn btn-limit'>{$moduleName} <span class='caret'></span></button><div id='dropMenu' class='dropdown-menu search-list' data-ride='searchList' data-url='$dropMenuLink'>";
$selectHtml .= '<div class="input-control search-box has-icon-left has-icon-right search-example"><input type="search" class="form-control search-input" /><label class="input-control-icon-left search-icon"><i class="icon icon-search"></i></label><a class="input-control-icon-right search-clear-btn"><i class="icon icon-close icon-sm"></i></a></div>';
$selectHtml .= "</div></div>";
}
else
{
$selectHtml .= "<a id='currentModule' href=\"javascript:showSearchMenu('tree', '$libID', 'caselib', 'browse', '')\">{$moduleName} <span class='icon-caret-down'></span></a><div id='currentBranchDropMenu' class='hidden affix enter-from-bottom layer'></div>";
}
}
setCookie("lastCaseLib", $libID, $this->config->cookieLife, $this->config->webRoot);
$pageNav = '';
$pageActions = '';
$isMobile = $this->app->viewType == 'mhtml';
if($isMobile)
{
$this->app->loadLang('qa');
$pageNav = html::a(helper::createLink('qa', 'index'), $this->lang->qa->index) . $this->lang->colon;
}
else
{
if($this->config->global->flow == 'full')
{
$this->app->loadLang('qa');
$pageNav .= '<div class="btn-group angle-btn"><div class="btn-group"><button data-toggle="dropdown" type="button" class="btn">' . $this->lang->qa->index . ' <span class="caret"></span></button>';
$pageNav .= '<ul class="dropdown-menu">';
if(common::hasPriv('caselib', 'create')) $pageNav .= '<li>' . html::a(helper::createLink('caselib', 'create'), '<i class="icon icon-plus"></i> ' . $this->lang->caselib->create) . '</li>';
$pageNav .= '</ul></div></div>';
}
else
{
$this->app->loadLang('testcase');
$pageActions .= "<div class='btn-group'>";
if(common::hasPriv('caselib', 'exportTemplet'))
{
$link = helper::createLink('caselib', 'exportTemplet', "libID=$libID");
$pageActions .= html::a($link, "<i class='icon icon-export muted'> </i>" . $this->lang->caselib->exportTemplet, '', "class='btn btn-link export'");
}
if(common::hasPriv('caselib', 'import'))
{
$link = helper::createLink('caselib', 'import', "libID=$libID");
$pageActions .= html::a($link, "<i class='icon muted icon-import'> </i>" . $this->lang->testcase->importFile, '', "class='btn btn-link export'");
}
$pageActions .= '</div>';
$params = "libID=$libID&moduleID=" . (isset($moduleID) ? $moduleID : 0);
if(common::hasPriv('caselib', 'batchCreateCase'))
{
$link = helper::createLink('caselib', 'batchCreateCase', $params);
$pageActions .= html::a($link, "<i class='icon-plus'></i>" . $this->lang->testcase->batchCreate, '', "class='btn btn-secondary'");
}
if(common::hasPriv('caselib', 'createCase'))
{
$link = helper::createLink('caselib', 'createCase', $params);
$pageActions .= html::a($link, "<i class='icon-plus'></i>" . $this->lang->testcase->create, '', "class='btn btn-primary'");
}
if(common::hasPriv('caselib', 'create'))
{
$link = helper::createLink('caselib', 'create');
$pageActions .= html::a($link, "<i class='icon-plus'></i>" . $this->lang->caselib->create, '', "class='btn btn-primary'");
}
}
}
$pageNav .= $selectHtml;
$this->lang->modulePageNav = $pageNav;
$this->lang->modulePageActions = $pageActions;
foreach($this->lang->caselib->menu as $key => $value)
{
$replace = '';
if($this->config->global->flow == 'onlyTest') $replace = $libID;
common::setMenuVars($this->lang->caselib->menu, $key, $replace);
}
if($this->config->global->flow != 'full' && $this->app->getMethodName() != 'view') $this->lang->caselib->menu->bysearch = "<a class='querybox-toggle' id='bysearchTab'><i class='icon icon-search muted'> </i>{$this->lang->testcase->bySearch}</a>";
}
/**
* Save lib state.
*
* @param int $libID
* @param array $libraries
* @access public
* @return int
*/
public function saveLibState($libID = 0, $libraries = array())
{
if($libID > 0) $this->session->set('caseLib', (int)$libID);
if($libID == 0 and $this->cookie->lastCaseLib) $this->session->set('caseLib', $this->cookie->lastCaseLib);
if($libID == 0 and $this->session->caseLib == '') $this->session->set('caseLib', key($libraries));
if(!isset($libraries[$this->session->caseLib]))
{
$this->session->set('caseLib', key($libraries));
$libID = $this->session->caseLib;
}
return $this->session->caseLib;
}
/**
* Get caselib info by id.
*
* @param int $libID
* @param bool $setImgSize
* @access public
* @return object
*/
public function getById($libID, $setImgSize = false)
{
$lib = $this->dao->select('*')->from(TABLE_TESTSUITE)->where('id')->eq((int)$libID)->fetch();
$lib = $this->loadModel('file')->replaceImgURL($lib, 'desc');
if($setImgSize) $lib->desc = $this->file->setImgSize($lib->desc);
return $lib;
}
/**
* Update a caselib.
*
* @param int $libID
* @access public
* @return bool|array
*/
public function update($libID)
{
$oldLib = $this->dao->select("*")->from(TABLE_TESTSUITE)->where('id')->eq((int)$libID)->fetch();
$lib = fixer::input('post')
->stripTags($this->config->caselib->editor->edit['id'], $this->config->allowedTags)
->add('lastEditedBy', $this->app->user->account)
->add('lastEditedDate', helper::now())
->remove('uid')
->get();
$lib = $this->loadModel('file')->processImgURL($lib, $this->config->caselib->editor->edit['id'], $this->post->uid);
$this->dao->update(TABLE_TESTSUITE)->data($lib)
->autoCheck()
->batchcheck($this->config->caselib->edit->requiredFields, 'notempty')
->where('id')->eq($libID)
->exec();
if(!dao::isError())
{
$this->file->updateObjectID($this->post->uid, $libID, 'caselib');
return common::createChanges($oldLib, $lib);
}
return false;
}
/**
* Delete library.
*
* @param int $libID
* @param string $table
* @access public
* @return bool
*/
public function delete($libID, $table = '')
{
$this->dao->update(TABLE_TESTSUITE)->set('deleted')->eq(1)->where('id')->eq($libID)->exec();
$this->loadModel('action');
$this->action->create('caselib', $libID, 'deleted', '', ACTIONMODEL::CAN_UNDELETED);
}
/**
* Get libraries.
*
* @access public
* @return array
*/
public function getLibraries()
{
return $this->dao->select("id,name")->from(TABLE_TESTSUITE)
->where('product')->eq(0)
->andWhere('deleted')->eq(0)
->andWhere('type')->eq('library')
->orderBy('id_desc')
->fetchPairs('id', 'name');
}
/**
* Create lib.
*
* @access public
* @return int
*/
public function create()
{
$lib = fixer::input('post')
->stripTags($this->config->caselib->editor->create['id'], $this->config->allowedTags)
->setForce('type', 'library')
->add('addedBy', $this->app->user->account)
->add('addedDate', helper::now())
->remove('uid')
->get();
$lib = $this->loadModel('file')->processImgURL($lib, $this->config->caselib->editor->create['id'], $this->post->uid);
$this->dao->insert(TABLE_TESTSUITE)->data($lib)
->batchcheck($this->config->caselib->create->requiredFields, 'notempty')
->check('name', 'unique', "deleted = '0'")
->exec();
if(!dao::isError())
{
$libID = $this->dao->lastInsertID();
$this->file->updateObjectID($this->post->uid, $libID, 'caselib');
return $libID;
}
return false;
}
/**
* Get lib cases.
*
* @param int $libID
* @param string $browseType
* @param int $queryID
* @param int $moduleID
* @param string $sort
* @param object $pager
* @access public
* @return array
*/
public function getLibCases($libID, $browseType, $queryID = 0, $moduleID = 0, $sort = 'id_desc', $pager = null)
{
$moduleIdList = $moduleID ? $this->loadModel('tree')->getAllChildId($moduleID) : '0';
$browseType = ($browseType == 'bymodule' and $this->session->libBrowseType and $this->session->libBrowseType != 'bysearch') ? $this->session->libBrowseType : $browseType;
$cases = array();
if($browseType == 'bymodule' or $browseType == 'all' or $browseType == 'wait')
{
$cases = $this->dao->select('*')->from(TABLE_CASE)
->where('lib')->eq((int)$libID)
->andWhere('product')->eq(0)
->beginIF($moduleIdList)->andWhere('module')->in($moduleIdList)->fi()
->beginIF($browseType == 'wait')->andWhere('status')->eq($browseType)->fi()
->andWhere('deleted')->eq('0')
->orderBy($sort)->page($pager)->fetchAll('id');
}
/* By search. */
elseif($browseType == 'bysearch')
{
if($queryID)
{
$query = $this->loadModel('search')->getQuery($queryID);
$this->session->set('caselibQuery', ' 1 = 1');
if($query)
{
$this->session->set('caselibQuery', $query->sql);
$this->session->set('caselibForm', $query->form);
}
}
else
{
if($this->session->caselibQuery == false) $this->session->set('caselibQuery', ' 1 = 1');
}
$queryLibID = $libID;
$allLib = "`lib` = 'all'";
$caseQuery = '(' . $this->session->caselibQuery;
if(strpos($this->session->caselibQuery, $allLib) !== false)
{
$caseQuery = str_replace($allLib, '1', $caseQuery);
$queryLibID = 'all';
}
$caseQuery .= ')';
$cases = $this->dao->select('*')->from(TABLE_CASE)->where($caseQuery)
->beginIF($queryLibID != 'all')->andWhere('lib')->eq((int)$libID)->fi()
->andWhere('product')->eq(0)
->andWhere('deleted')->eq(0)
->orderBy($sort)->page($pager)->fetchAll();
}
return $cases;
}
/**
* Build search form.
*
* @param int $libID
* @param array $libraries
* @param int $queryID
* @param string $actionURL
* @access public
* @return void
*/
public function buildSearchForm($libID, $libraries, $queryID, $actionURL)
{
$this->config->testcase->search['fields']['lib'] = $this->lang->testcase->lib;
$this->config->testcase->search['params']['lib']['values'] = array('' => '', $libID => $libraries[$libID], 'all' => $this->lang->caselib->all);
$this->config->testcase->search['params']['lib']['operator'] = '=';
$this->config->testcase->search['params']['lib']['control'] = 'select';
$this->config->testcase->search['params']['module']['values'] = $this->loadModel('tree')->getOptionMenu($libID, $viewType = 'caselib');
if(!$this->config->testcase->needReview) unset($this->config->testcase->search['params']['status']['values']['wait']);
unset($this->config->testcase->search['fields']['product']);
unset($this->config->testcase->search['params']['product']);
unset($this->config->testcase->search['fields']['branch']);
unset($this->config->testcase->search['params']['branch']);
unset($this->config->testcase->search['fields']['lastRunner']);
unset($this->config->testcase->search['params']['lastRunner']);
unset($this->config->testcase->search['fields']['lastRunResult']);
unset($this->config->testcase->search['params']['lastRunResult']);
unset($this->config->testcase->search['fields']['lastRunDate']);
unset($this->config->testcase->search['params']['lastRunDate']);
$this->config->testcase->search['module'] = 'caselib';
$this->config->testcase->search['actionURL'] = $actionURL;
$this->config->testcase->search['queryID'] = $queryID;
$this->loadModel('search')->setSearchParams($this->config->testcase->search);
}
/**
* Get lib link.
*
* @param string $module
* @param string $method
* @param string $extra
* @access public
* @return string
*/
public function getLibLink($module, $method, $extra)
{
$link = '';
if($module == 'caselib')
{
if($module == 'caselib' && ($method == 'create'))
{
$link = helper::createLink($module, 'browse', "libID=%s");
}
else
{
$link = helper::createLink($module, $method, "libID=%s");
}
}
else if($module == 'tree')
{
$link = helper::createLink($module, $method, "libID=%s&type=caselib&currentModuleID=0");
}
else
{
$link = helper::createLink('caselib', 'browse', "libID=%s");
}
return $link;
}
/**
* Create from import.
*
* @param int $libID
* @access public
* @return void
*/
public function createFromImport($libID)
{
$this->loadModel('action');
$this->loadModel('testcase');
$this->loadModel('file');
$now = helper::now();
$data = fixer::input('post')->get();
if(!empty($_POST['id']))
{
$oldSteps = $this->dao->select('t2.*')->from(TABLE_CASE)->alias('t1')
->leftJoin(TABLE_CASESTEP)->alias('t2')->on('t1.id = t2.case')
->where('t1.id')->in(($_POST['id']))
->andWhere('t1.version=t2.version')
->orderBy('t2.id')
->fetchGroup('case');
$oldCases = $this->dao->select('*')->from(TABLE_CASE)->where('id')->in($_POST['id'])->fetchAll('id');
}
$cases = array();
foreach($data->lib as $key => $lib)
{
$caseData = new stdclass();
$caseData->lib = $lib;
$caseData->module = $data->module[$key];
$caseData->title = $data->title[$key];
$caseData->pri = (int)$data->pri[$key];
$caseData->type = $data->type[$key];
$caseData->status = $data->status[$key];
$caseData->stage = join(',', $data->stage[$key]);
$caseData->keywords = $data->keywords[$key];
$caseData->frequency = 1;
$caseData->precondition = $data->precondition[$key];
if(isset($this->config->testcase->create->requiredFields))
{
$requiredFields = explode(',', $this->config->testcase->create->requiredFields);
foreach($requiredFields as $requiredField)
{
$requiredField = trim($requiredField);
if(empty($caseData->$requiredField)) dao::$errors[] = sprintf($this->lang->testcase->noRequire, $key, $this->lang->testcase->$requiredField);
}
}
$cases[$key] = $caseData;
}
if(dao::isError()) die(js::error(dao::getError()));
$forceNotReview = $this->testcase->forceNotReview();
foreach($cases as $key => $caseData)
{
if(!empty($_POST['id'][$key]) and empty($_POST['insert']))
{
$caseID = $data->id[$key];
$stepChanged = false;
$steps = array();
$oldStep = isset($oldSteps[$caseID]) ? $oldSteps[$caseID] : array();
$oldCase = $oldCases[$caseID];
/* Remove the empty setps in post. */
$steps = array();
if(isset($_POST['desc'][$key]))
{
foreach($data->desc[$key] as $id => $desc)
{
$desc = trim($desc);
if(empty($desc)) continue;
$step = new stdclass();
$step->type = $data->stepType[$key][$id];
$step->desc = $desc;
$step->expect = trim($data->expect[$key][$id]);
$steps[] = $step;
}
}
/* If step count changed, case changed. */
if((!$oldStep != !$steps) or (count($oldStep) != count($steps)))
{
$stepChanged = true;
}
else
{
/* Compare every step. */
foreach($oldStep as $id => $oldStep)
{
if(trim($oldStep->desc) != trim($steps[$id]->desc) or trim($oldStep->expect) != $steps[$id]->expect)
{
$stepChanged = true;
break;
}
}
}
$version = $stepChanged ? $oldCase->version + 1 : $oldCase->version;
$caseData->version = $version;
$changes = common::createChanges($oldCase, $caseData);
if(!$changes and !$stepChanged) continue;
if($changes or $stepChanged)
{
$caseData->lastEditedBy = $this->app->user->account;
$caseData->lastEditedDate = $now;
if($stepChanged and !$forceNotReview) $caseData->status = 'wait';
$this->dao->update(TABLE_CASE)->data($caseData)->where('id')->eq($caseID)->autoCheck()->exec();
if($stepChanged)
{
$parentStepID = 0;
foreach($steps as $id => $step)
{
$step = (array)$step;
if(empty($step['desc'])) continue;
$stepData = new stdclass();
$stepData->type = ($step['type'] == 'item' and $parentStepID == 0) ? 'step' : $step['type'];
$stepData->parent = ($stepData->type == 'item') ? $parentStepID : 0;
$stepData->case = $caseID;
$stepData->version = $version;
$stepData->desc = $step['desc'];
$stepData->expect = $step['expect'];
$this->dao->insert(TABLE_CASESTEP)->data($stepData)->autoCheck()->exec();
if($stepData->type == 'group') $parentStepID = $this->dao->lastInsertID();
if($stepData->type == 'step') $parentStepID = 0;
}
}
$oldCase->steps = $this->testcase->joinStep($oldStep);
$caseData->steps = $this->testcase->joinStep($steps);
$changes = common::createChanges($oldCase, $caseData);
$actionID = $this->action->create('case', $caseID, 'Edited');
$this->action->logHistory($actionID, $changes);
}
}
else
{
$caseData->version = 1;
$caseData->openedBy = $this->app->user->account;
$caseData->openedDate = $now;
$caseData->status = $forceNotReview ? 'normal' : 'wait';
$this->dao->insert(TABLE_CASE)->data($caseData)->autoCheck()->exec();
if(!dao::isError())
{
$caseID = $this->dao->lastInsertID();
$parentStepID = 0;
foreach($data->desc[$key] as $id => $desc)
{
$desc = trim($desc);
if(empty($desc)) continue;
$stepData = new stdclass();
$stepData->type = ($data->stepType[$key][$id] == 'item' and $parentStepID == 0) ? 'step' : $data->stepType[$key][$id];
$stepData->parent = ($stepData->type == 'item') ? $parentStepID : 0;
$stepData->case = $caseID;
$stepData->version = 1;
$stepData->desc = $desc;
$stepData->expect = $data->expect[$key][$id];
$this->dao->insert(TABLE_CASESTEP)->data($stepData)->autoCheck()->exec();
if($stepData->type == 'group') $parentStepID = $this->dao->lastInsertID();
if($stepData->type == 'step') $parentStepID = 0;
}
$this->action->create('case', $caseID, 'Opened');
}
}
}
unlink($this->session->importFile);
unset($_SESSION['importFile']);
}
/**
* Batch create case for lib.
*
* @param int $libID
* @access public
* @return void
*/
public function batchCreateCase($libID)
{
$this->loadModel('testcase');
$this->loadModel('action');
$now = helper::now();
$cases = fixer::input('post')->get();
$batchNum = count(reset($cases));
$result = $this->loadModel('common')->removeDuplicate('case', $cases, "lib={$libID}");
$cases = $result['data'];
for($i = 0; $i < $batchNum; $i++)
{
if(!empty($cases->title[$i]) and empty($cases->type[$i])) die(js::alert(sprintf($this->lang->error->notempty, $this->lang->testcase->type)));
}
$module = 0;
$type = '';
$pri = 3;
for($i = 0; $i < $batchNum; $i++)
{
$module = $cases->module[$i] == 'ditto' ? $module : $cases->module[$i];
$type = $cases->type[$i] == 'ditto' ? $type : $cases->type[$i];
$pri = $cases->pri[$i] == 'ditto' ? $pri : $cases->pri[$i];
$cases->module[$i] = (int)$module;
$cases->type[$i] = $type;
$cases->pri[$i] = $pri;
}
$forceNotReview = $this->testcase->forceNotReview();
for($i = 0; $i < $batchNum; $i++)
{
if($cases->type[$i] != '' and $cases->title[$i] != '')
{
$data[$i] = new stdclass();
$data[$i]->lib = $libID;
$data[$i]->module = $cases->module[$i];
$data[$i]->type = $cases->type[$i];
$data[$i]->pri = $cases->pri[$i];
$data[$i]->stage = empty($cases->stage[$i]) ? '' : implode(',', $cases->stage[$i]);
$data[$i]->color = $cases->color[$i];
$data[$i]->title = $cases->title[$i];
$data[$i]->precondition = $cases->precondition[$i];
$data[$i]->keywords = $cases->keywords[$i];
$data[$i]->openedBy = $this->app->user->account;
$data[$i]->openedDate = $now;
$data[$i]->status = $forceNotReview ? 'normal' : 'wait';
$data[$i]->version = 1;
$this->dao->insert(TABLE_CASE)->data($data[$i])
->autoCheck()
->batchCheck($this->config->testcase->create->requiredFields, 'notempty')
->exec();
if(dao::isError())
{
echo js::error(dao::getError());
die(js::reload('parent'));
}
$caseID = $this->dao->lastInsertID();
$actionID = $this->action->create('case', $caseID, 'Opened');
}
}
}
}
@@ -1,11 +1,11 @@
<?php
/**
* The batch create case view of testsuite module of ZenTaoPMS.
* The batch create case view of caselib module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Yidong Wang <yidong@cnezsoft.com>
* @package testsuite
* @package caselib
* @version $Id$
* @link http://www.zentao.net
*/
@@ -1,11 +1,11 @@
<?php
/**
* The library view file of testsuite module of ZenTaoPMS.
* The library view file of caselib module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Yidong Wang <yidong@cnezsoft.com>
* @package testsuite
* @package caselib
* @version $Id: library.html.php 5108 2013-07-12 01:59:04Z chencongzhi520@gmail.com $
* @link http://www.zentao.net
*/
@@ -15,7 +15,7 @@ include '../../common/view/header.html.php';
include '../../common/view/datatable.fix.html.php';
js::set('browseType', $browseType);
js::set('moduleID', $moduleID);
js::set('confirmDelete', $lang->testsuite->confirmDelete);
js::set('confirmDelete', $lang->testcase->confirmDelete);
js::set('batchDelete', $lang->testcase->confirmBatchDelete);
js::set('flow', $config->global->flow);
?>
@@ -36,29 +36,29 @@ js::set('flow', $config->global->flow);
</div>
<div class='btn-toolbar pull-left'>
<?php
if(common::hasPriv('testsuite', 'library'))
if(common::hasPriv('caselib', 'browse'))
{
echo html::a($this->inlink('library', "libID=$libID&browseType=all"), "<span class='text'>{$lang->testcase->allCases}</span>", '', "id='allTab' class='btn btn-link'");
echo html::a($this->inlink('browse', "libID=$libID&browseType=all"), "<span class='text'>{$lang->testcase->allCases}</span>", '', "id='allTab' class='btn btn-link'");
if($config->testcase->needReview or !empty($config->testcase->forceReview)) echo html::a($this->inlink('library', "libID=$libID&browseType=wait"), "<span class='text'>" . $lang->testcase->statusList['wait'] . "</span>", '', "id='waitTab' class='btn btn-link'");
}
?>
<a class="btn btn-link querybox-toggle" id='bysearchTab'><i class="icon icon-search muted"></i> <?php echo $lang->testcase->bySearch;?></a>
<?php
if(common::hasPriv('testsuite', 'libView'))
if(common::hasPriv('caselib', 'view'))
{
$link = helper::createLink('testsuite', 'libView', "libID=$libID");
echo html::a($link, "<i class='icon icon-list-alt muted'> </i>" . $this->lang->testsuite->libView, '', "class='btn btn-link'");
$link = helper::createLink('caselib', 'view', "libID=$libID");
echo html::a($link, "<i class='icon icon-list-alt muted'> </i>" . $this->lang->caselib->view, '', "class='btn btn-link'");
}
?>
</div>
<div class='btn-toolbar pull-right'>
<div class='btn-group'>
<?php common::printLink('testsuite', 'exportTemplet', "libID=$libID", "<i class='icon icon-export muted'> </i>" . $lang->testsuite->exportTemplet, '', "class='btn btn-link export' data-width='35%'");?>
<?php common::printLink('testsuite', 'import', "libID=$libID", "<i class='icon muted icon-import'> </i>" . $lang->testcase->importFile, '', "class='btn btn-link export'");?>
<?php common::printLink('caselib', 'exportTemplet', "libID=$libID", "<i class='icon icon-export muted'> </i>" . $lang->caselib->exportTemplet, '', "class='btn btn-link export' data-width='35%'");?>
<?php common::printLink('caselib', 'import', "libID=$libID", "<i class='icon muted icon-import'> </i>" . $lang->testcase->importFile, '', "class='btn btn-link export'");?>
</div>
<?php $params = "libID=$libID&moduleID=" . (isset($moduleID) ? $moduleID : 0);?>
<?php common::printLink('testsuite', 'batchCreateCase', $params, "<i class='icon-plus'></i>" . $lang->testcase->batchCreate, '', "class='btn btn-secondary'");?>
<?php common::printLink('testsuite', 'createCase', $params, "<i class='icon-plus'></i>" . $lang->testcase->create, '', "class='btn btn-primary'");?>
<?php common::printLink('caselib', 'batchCreateCase', $params, "<i class='icon-plus'></i>" . $lang->testcase->batchCreate, '', "class='btn btn-secondary'");?>
<?php common::printLink('caselib', 'createCase', $params, "<i class='icon-plus'></i>" . $lang->testcase->create, '', "class='btn btn-primary'");?>
</div>
</div>
<?php endif;?>
@@ -69,7 +69,7 @@ js::set('flow', $config->global->flow);
<?php if(!$moduleTree):?>
<hr class="space">
<div class="text-center text-muted">
<?php echo $lang->testsuite->noModule;?>
<?php echo $lang->caselib->noModule;?>
</div>
<hr class="space">
<?php endif;?>
@@ -86,8 +86,8 @@ js::set('flow', $config->global->flow);
<div class="table-empty-tip">
<p>
<span class="text-muted"><?php echo $lang->testcase->noCase;?></span>
<?php if(common::hasPriv('testsuite', 'createCase')):?>
<?php echo html::a($this->createLink('testsuite', 'createCase', "libID=$libID&moduleID=" . (isset($moduleID) ? $moduleID : 0)), "<i class='icon icon-plus'></i> " . $lang->testcase->create, '', "class='btn btn-info'");?>
<?php if(common::hasPriv('caselib', 'createCase')):?>
<?php echo html::a($this->createLink('caselib', 'createCase', "libID=$libID&moduleID=" . (isset($moduleID) ? $moduleID : 0)), "<i class='icon icon-plus'></i> " . $lang->testcase->create, '', "class='btn btn-info'");?>
<?php endif;?>
</p>
</div>
@@ -1,11 +1,11 @@
<?php
/**
* The createlib view of testsuite module of ZenTaoPMS.
* The createlib view of caselib module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package testsuite
* @package caselib
* @version $Id: create.html.php 4728 2013-05-03 06:14:34Z chencongzhi520@gmail.com $
* @link http://www.zentao.net
*/
@@ -15,16 +15,16 @@
<div id="mainContent" class="main-content">
<div class="center-block">
<div class="main-header">
<h2><?php echo $lang->testsuite->createLib;?></h2>
<h2><?php echo $lang->caselib->create;?></h2>
</div>
<form class="load-indicator main-form form-ajax" id="createForm" method="post" target='hiddenwin'>
<table class="table table-form">
<tr>
<th><?php echo $lang->testsuite->name;?></th>
<th><?php echo $lang->caselib->name;?></th>
<td><?php echo html::input('name', '', "class='form-control'");?></td>
</tr>
<tr>
<th><?php echo $lang->testsuite->desc;?></th>
<th><?php echo $lang->caselib->desc;?></th>
<td><?php echo html::textarea('desc', '', "rows=10 class='form-control'");?></td>
</tr>
<tr>
@@ -1,11 +1,11 @@
<?php
/**
* The create case view of testsuite module of ZenTaoPMS.
* The create case view of caselib module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Yidong Wang <yidong@cnezsoft.com>
* @package testsuite
* @package caselib
* @version $Id: createcase.html.php 4904 2013-06-26 05:37:45Z wyd621@gmail.com $
* @link http://www.zentao.net
*/
@@ -19,7 +19,7 @@
<div class='main-header'>
<h2><?php echo $lang->testcase->create;?></h2>
<div class="pull-right btn-toolbar">
<?php $customLink = $this->createLink('custom', 'ajaxSaveCustomFields', 'module=testsuite&section=custom&key=createFields');?>
<?php $customLink = $this->createLink('custom', 'ajaxSaveCustomFields', 'module=caselib&section=custom&key=createFields');?>
<?php include '../../common/view/customfield.html.php';?>
</div>
</div>
+41
View File
@@ -0,0 +1,41 @@
<?php
/**
* The edit view of caselib module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package caselib
* @version $Id: edit.html.php 4728 2013-05-03 06:14:34Z chencongzhi520@gmail.com $
* @link http://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<?php include '../../common/view/kindeditor.html.php';?>
<div id='mainContent' class='main-content'>
<div class='center-block'>
<div class='main-header'>
<h2><?php echo $lang->caselib->edit;?></h2>
</div>
<form class='load-indicator main-form form-ajax' method='post' target='hiddenwin' id='dataform'>
<table class='table table-form'>
<tr>
<th><?php echo $lang->caselib->name;?></th>
<td><?php echo html::input('name', $lib->name, "class='form-control'");?></td>
</tr>
<tr>
<th><?php echo $lang->caselib->desc;?></th>
<td><?php echo html::textarea('desc', htmlspecialchars($lib->desc), "rows=10 class='form-control'");?></td>
</tr>
<?php $this->printExtendFields($lib, 'table');?>
<tr>
<td class='text-center form-actions' colspan='2'>
<?php echo html::submitButton();?>
<?php echo html::backButton();?>
</td>
</tr>
</table>
</form>
</div>
</div>
<?php include '../../common/view/footer.html.php';?>
@@ -7,7 +7,7 @@
<?php else:?>
<div id="mainContent" class="main-content">
<div class="main-header">
<h2><?php echo $lang->testsuite->import;?></h2>
<h2><?php echo $lang->caselib->import;?></h2>
</div>
<form target='hiddenwin' method='post'>
<table class='table active-disabled table-form table-striped'>
@@ -1,11 +1,11 @@
<?php
/**
* The view lib file of testsuite module of ZenTaoPMS.
* The view lib file of caselib module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package testsuite
* @package caselib
* @version $Id: view.html.php 4141 2013-01-18 06:15:13Z zhujinyonging@gmail.com $
* @link http://www.zentao.net
*/
@@ -13,14 +13,14 @@
<?php include '../../common/view/header.html.php';?>
<div id='mainMenu' class='clearfix'>
<div class='btn-toolbar pull-left'>
<?php $browseLink = $this->session->caseList ? $this->session->caseList : $this->createLink('testsuite', 'library', "libID=$lib->id");?>
<?php $browseLink = $this->session->caseList ? $this->session->caseList : $this->createLink('caselib', 'browse', "libID=$lib->id");?>
<?php common::printBack($browseLink, 'btn btn-secondary');?>
<div class='divider'></div>
<div class='page-title'>
<span class='label label-id'><?php echo $lib->id;?></span>
<span class='text' title='<?php echo $lib->name;?>'><?php echo $lib->name;?></span>
<?php if($lib->deleted):?>
<span class='label label-danger'><?php echo $lang->testsuite->deleted;?></span>
<span class='label label-danger'><?php echo $lang->caselib->deleted;?></span>
<?php endif; ?>
</div>
</div>
@@ -28,7 +28,7 @@
<div id='mainContent'>
<div class='cell'>
<div class='detail'>
<div class='detail-title'><?php echo $lang->testsuite->legendDesc;?></div>
<div class='detail-title'><?php echo $lang->caselib->legendDesc;?></div>
<div class='detail-content article-content'><?php echo $lib->desc;?></div>
</div>
<?php include '../../common/view/action.html.php';?>
@@ -42,8 +42,8 @@
if(!$lib->deleted)
{
echo "<div class='divider'></div>";
common::printIcon('testsuite', 'edit', "libID=$lib->id");
common::printIcon('testsuite', 'delete', "libID=$lib->id", '', 'button', 'trash', 'hiddenwin');
common::printIcon('caselib', 'edit', "libID=$lib->id");
common::printIcon('caselib', 'delete', "libID=$lib->id", '', 'button', 'trash', 'hiddenwin');
}
?>
</div>
+15 -12
View File
@@ -142,7 +142,7 @@ $lang->searchObjects['release'] = 'Release';
$lang->searchObjects['productplan'] = $lang->productCommon . 'Plan';
$lang->searchObjects['testtask'] = 'Request';
$lang->searchObjects['doc'] = 'Document';
$lang->searchObjects['testsuite'] = 'Case Library';
$lang->searchObjects['caselib'] = 'Case Library';
$lang->searchObjects['testreport'] = 'Test Report';
$lang->searchTips = 'ID (ctrl+g)';
@@ -273,7 +273,7 @@ $lang->qa->menu->testcase = array('link' => 'Case|testcase|browse|productID=%s'
$lang->qa->menu->testtask = array('link' => 'Request|testtask|browse|productID=%s');
$lang->qa->menu->testsuite = array('link' => 'Suite|testsuite|browse|productID=%s');
$lang->qa->menu->report = array('link' => 'Report|testreport|browse|productID=%s');
$lang->qa->menu->caselib = array('link' => 'Case Library|testsuite|library');
$lang->qa->menu->caselib = array('link' => 'Case Library|caselib|browse');
$lang->bug = new stdclass();
$lang->bug->menu = new stdclass();
@@ -283,7 +283,7 @@ $lang->bug->menu->testcase = array('link' => 'Case|testcase|browse|productID=%s
$lang->bug->menu->testtask = array('link' => 'Request|testtask|browse|productID=%s');
$lang->bug->menu->testsuite = array('link' => 'Suite|testsuite|browse|productID=%s');
$lang->bug->menu->report = array('link' => 'Report|testreport|browse|productID=%s');
$lang->bug->menu->caselib = array('link' => 'Case Library|testsuite|library');
$lang->bug->menu->caselib = array('link' => 'Case Library|caselib|browse');
$lang->testcase = new stdclass();
$lang->testcase->menu = new stdclass();
@@ -292,7 +292,7 @@ $lang->testcase->menu->testcase = array('link' => 'Case|testcase|browse|product
$lang->testcase->menu->testtask = array('link' => 'Request|testtask|browse|productID=%s');
$lang->testcase->menu->testsuite = array('link' => 'Suite|testsuite|browse|productID=%s');
$lang->testcase->menu->report = array('link' => 'Report|testreport|browse|productID=%s');
$lang->testcase->menu->caselib = array('link' => 'Case Library|testsuite|library');
$lang->testcase->menu->caselib = array('link' => 'Case Library|caselib|browse');
$lang->testtask = new stdclass();
$lang->testtask->menu = new stdclass();
@@ -301,7 +301,7 @@ $lang->testtask->menu->testcase = array('link' => 'Case|testcase|browse|product
$lang->testtask->menu->testtask = array('link' => 'Request|testtask|browse|productID=%s', 'alias' => 'view,create,edit,linkcase,cases,start,close,batchrun,groupcase,report');
$lang->testtask->menu->testsuite = array('link' => 'Suite|testsuite|browse|productID=%s');
$lang->testtask->menu->report = array('link' => 'Report|testreport|browse|productID=%s');
$lang->testtask->menu->caselib = array('link' => 'Case Library|testsuite|library');
$lang->testtask->menu->caselib = array('link' => 'Case Library|caselib|browse');
$lang->testsuite = new stdclass();
$lang->testsuite->menu = new stdclass();
@@ -310,7 +310,7 @@ $lang->testsuite->menu->testcase = array('link' => 'Case|testcase|browse|produc
$lang->testsuite->menu->testtask = array('link' => 'Request|testtask|browse|productID=%s');
$lang->testsuite->menu->testsuite = array('link' => 'Suite|testsuite|browse|productID=%s', 'alias' => 'view,create,edit,linkcase');
$lang->testsuite->menu->report = array('link' => 'Report|testreport|browse|productID=%s');
$lang->testsuite->menu->caselib = array('link' => 'Case Library|testsuite|library');
$lang->testsuite->menu->caselib = array('link' => 'Case Library|caselib|browse');
$lang->testreport = new stdclass();
$lang->testreport->menu = new stdclass();
@@ -319,7 +319,7 @@ $lang->testreport->menu->testcase = array('link' => 'Case|testcase|browse|produ
$lang->testreport->menu->testtask = array('link' => 'Request|testtask|browse|productID=%s');
$lang->testreport->menu->testsuite = array('link' => 'Suite|testsuite|browse|productID=%s');
$lang->testreport->menu->report = array('link' => 'Report|testreport|browse|productID=%s', 'alias' => 'view,create,edit');
$lang->testreport->menu->caselib = array('link' => 'Case Library|testsuite|library');
$lang->testreport->menu->caselib = array('link' => 'Case Library|caselib|browse');
$lang->caselib = new stdclass();
$lang->caselib->menu = new stdclass();
@@ -328,7 +328,7 @@ $lang->caselib->menu->testcase = array('link' => 'Case|testcase|browse|');
$lang->caselib->menu->testtask = array('link' => 'Request|testtask|browse|');
$lang->caselib->menu->testsuite = array('link' => 'Suite|testsuite|browse|');
$lang->caselib->menu->report = array('link' => 'Report|testreport|browse|');
$lang->caselib->menu->caselib = array('link' => 'Case Library|testsuite|library', 'alias' => 'createlib,createcase,libview,edit,batchcreatecase,showimport', 'subModule' => 'tree,testcase');
$lang->caselib->menu->caselib = array('link' => 'Case Library|caselib|browse', 'alias' => 'create,createcase,view,edit,batchcreatecase,showimport', 'subModule' => 'tree,testcase');
/* Doc menu settings. */
$lang->doc = new stdclass();
@@ -691,6 +691,7 @@ if(isset($config->global->flow) and $config->global->flow == 'onlyStory')
unset($lang->searchObjects['build']);
unset($lang->searchObjects['testtask']);
unset($lang->searchObjects['testsuite']);
unset($lang->searchObjects['caselib']);
unset($lang->searchObjects['testreport']);
}
@@ -727,6 +728,7 @@ if(isset($config->global->flow) and $config->global->flow == 'onlyTask')
unset($lang->searchObjects['release']);
unset($lang->searchObjects['productplan']);
unset($lang->searchObjects['testsuite']);
unset($lang->searchObjects['caselib']);
unset($lang->searchObjects['testreport']);
}
@@ -760,7 +762,7 @@ if(isset($config->global->flow) and $config->global->flow == 'onlyTest')
$lang->menu->testcase = 'Case|testcase|index';
$lang->menu->testsuite = 'Suite|testsuite|index';
$lang->menu->testtask = 'Request|testtask|index';
$lang->menu->caselib = 'Case Library|testsuite|library';
$lang->menu->caselib = 'Case Library|caselib|browse';
$lang->menuOrder[6] = 'bug';
$lang->menuOrder[7] = 'testcase';
@@ -847,9 +849,9 @@ if(isset($config->global->flow) and $config->global->flow == 'onlyTest')
/* Adjust sub menu of caselib module. */
$lang->caselib->menu = new stdclass();
$lang->caselib->menu->all = 'All|testsuite|library|libID=%s&browseType=all';
$lang->caselib->menu->wait = 'Waiting|testsuite|library|libID=%s&browseType=wait';
$lang->caselib->menu->view = 'View|testsuite|libview|libID=%s';
$lang->caselib->menu->all = 'All|caselib|browse|libID=%s&browseType=all';
$lang->caselib->menu->wait = 'Waiting|caselib|browse|libID=%s&browseType=wait';
$lang->caselib->menu->view = 'View|caselib|view|libID=%s';
$lang->caselib->menuOrder[5] = 'lib';
$lang->caselib->menuOrder[10] = 'all';
@@ -881,6 +883,7 @@ if(isset($config->global->flow) and $config->global->flow == 'onlyTest')
$lang->menugroup->testcase = 'testcase';
$lang->menugroup->testtask = 'testtask';
$lang->menugroup->testsuite = 'testsuite';
$lang->menugroup->caselib = 'caselib';
$lang->menugroup->testreport = 'testtask';
$lang->menugroup->build = 'product';
+1
View File
@@ -73,6 +73,7 @@ $lang->bug->menuOrder = $lang->qa->menuOrder;
$lang->testcase->menuOrder = $lang->bug->menuOrder;
$lang->testtask->menuOrder = $lang->testcase->menuOrder;
$lang->testsuite->menuOrder = $lang->testcase->menuOrder;
$lang->caselib->menuOrder = $lang->testcase->menuOrder;
$lang->testreport->menuOrder = $lang->testcase->menuOrder;
/* doc menu order. */
+15 -12
View File
@@ -142,7 +142,7 @@ $lang->searchObjects['release'] = '发布';
$lang->searchObjects['productplan'] = $lang->productCommon . '计划';
$lang->searchObjects['testtask'] = '测试单';
$lang->searchObjects['doc'] = '文档';
$lang->searchObjects['testsuite'] = '用例库';
$lang->searchObjects['caselib'] = '用例库';
$lang->searchObjects['testreport'] = '测试报告';
$lang->searchTips = '编号(ctrl+g)';
@@ -273,7 +273,7 @@ $lang->qa->menu->testcase = array('link' => '用例|testcase|browse|productID=%
$lang->qa->menu->testtask = array('link' => '测试单|testtask|browse|productID=%s');
$lang->qa->menu->testsuite = array('link' => '套件|testsuite|browse|productID=%s');
$lang->qa->menu->report = array('link' => '报告|testreport|browse|productID=%s');
$lang->qa->menu->caselib = array('link' => '用例库|testsuite|library');
$lang->qa->menu->caselib = array('link' => '用例库|caselib|browse');
$lang->bug = new stdclass();
$lang->bug->menu = new stdclass();
@@ -283,7 +283,7 @@ $lang->bug->menu->testcase = array('link' => '用例|testcase|browse|productID=
$lang->bug->menu->testtask = array('link' => '测试单|testtask|browse|productID=%s');
$lang->bug->menu->testsuite = array('link' => '套件|testsuite|browse|productID=%s');
$lang->bug->menu->report = array('link' => '报告|testreport|browse|productID=%s');
$lang->bug->menu->caselib = array('link' => '用例库|testsuite|library');
$lang->bug->menu->caselib = array('link' => '用例库|caselib|browse');
$lang->testcase = new stdclass();
$lang->testcase->menu = new stdclass();
@@ -292,7 +292,7 @@ $lang->testcase->menu->testcase = array('link' => '用例|testcase|browse|produ
$lang->testcase->menu->testtask = array('link' => '测试单|testtask|browse|productID=%s');
$lang->testcase->menu->testsuite = array('link' => '套件|testsuite|browse|productID=%s');
$lang->testcase->menu->report = array('link' => '报告|testreport|browse|productID=%s');
$lang->testcase->menu->caselib = array('link' => '用例库|testsuite|library');
$lang->testcase->menu->caselib = array('link' => '用例库|caselib|browse');
$lang->testtask = new stdclass();
$lang->testtask->menu = new stdclass();
@@ -301,7 +301,7 @@ $lang->testtask->menu->testcase = array('link' => '用例|testcase|browse|produ
$lang->testtask->menu->testtask = array('link' => '测试单|testtask|browse|productID=%s', 'alias' => 'view,create,edit,linkcase,cases,start,close,batchrun,groupcase,report');
$lang->testtask->menu->testsuite = array('link' => '套件|testsuite|browse|productID=%s');
$lang->testtask->menu->report = array('link' => '报告|testreport|browse|productID=%s');
$lang->testtask->menu->caselib = array('link' => '用例库|testsuite|library');
$lang->testtask->menu->caselib = array('link' => '用例库|caselib|browse');
$lang->testsuite = new stdclass();
$lang->testsuite->menu = new stdclass();
@@ -310,7 +310,7 @@ $lang->testsuite->menu->testcase = array('link' => '用例|testcase|browse|prod
$lang->testsuite->menu->testtask = array('link' => '测试单|testtask|browse|productID=%s');
$lang->testsuite->menu->testsuite = array('link' => '套件|testsuite|browse|productID=%s', 'alias' => 'view,create,edit,linkcase');
$lang->testsuite->menu->report = array('link' => '报告|testreport|browse|productID=%s');
$lang->testsuite->menu->caselib = array('link' => '用例库|testsuite|library');
$lang->testsuite->menu->caselib = array('link' => '用例库|caselib|browse');
$lang->testreport = new stdclass();
$lang->testreport->menu = new stdclass();
@@ -319,7 +319,7 @@ $lang->testreport->menu->testcase = array('link' => '用例|testcase|browse|pro
$lang->testreport->menu->testtask = array('link' => '测试单|testtask|browse|productID=%s');
$lang->testreport->menu->testsuite = array('link' => '套件|testsuite|browse|productID=%s');
$lang->testreport->menu->report = array('link' => '报告|testreport|browse|productID=%s', 'alias' => 'view,create,edit');
$lang->testreport->menu->caselib = array('link' => '用例库|testsuite|library');
$lang->testreport->menu->caselib = array('link' => '用例库|caselib|browse');
$lang->caselib = new stdclass();
$lang->caselib->menu = new stdclass();
@@ -328,7 +328,7 @@ $lang->caselib->menu->testcase = array('link' => '用例|testcase|browse|');
$lang->caselib->menu->testtask = array('link' => '测试单|testtask|browse|');
$lang->caselib->menu->testsuite = array('link' => '套件|testsuite|browse|');
$lang->caselib->menu->report = array('link' => '报告|testreport|browse|');
$lang->caselib->menu->caselib = array('link' => '用例库|testsuite|library', 'alias' => 'createlib,createcase,libview,edit,batchcreatecase,showimport', 'subModule' => 'tree,testcase');
$lang->caselib->menu->caselib = array('link' => '用例库|caselib|browse', 'alias' => 'create,createcase,view,edit,batchcreatecase,showimport', 'subModule' => 'tree,testcase');
/* 文档视图菜单设置。*/
$lang->doc = new stdclass();
@@ -691,6 +691,7 @@ if(isset($config->global->flow) and $config->global->flow == 'onlyStory')
unset($lang->searchObjects['build']);
unset($lang->searchObjects['testtask']);
unset($lang->searchObjects['testsuite']);
unset($lang->searchObjects['caselib']);
unset($lang->searchObjects['testreport']);
}
@@ -727,6 +728,7 @@ if(isset($config->global->flow) and $config->global->flow == 'onlyTask')
unset($lang->searchObjects['release']);
unset($lang->searchObjects['productplan']);
unset($lang->searchObjects['testsuite']);
unset($lang->searchObjects['caselib']);
unset($lang->searchObjects['testreport']);
}
@@ -760,7 +762,7 @@ if(isset($config->global->flow) and $config->global->flow == 'onlyTest')
$lang->menu->testcase = '用例|testcase|index';
$lang->menu->testsuite = '套件|testsuite|index';
$lang->menu->testtask = '测试单|testtask|index';
$lang->menu->caselib = '用例库|testsuite|library';
$lang->menu->caselib = '用例库|caselib|browse';
$lang->menuOrder[6] = 'bug';
$lang->menuOrder[7] = 'testcase';
@@ -847,9 +849,9 @@ if(isset($config->global->flow) and $config->global->flow == 'onlyTest')
/* Adjust sub menu of caselib module. */
$lang->caselib->menu = new stdclass();
$lang->caselib->menu->all = '所有|testsuite|library|libID=%s&browseType=all';
$lang->caselib->menu->wait = '待评审|testsuite|library|libID=%s&browseType=wait';
$lang->caselib->menu->view = '概况|testsuite|libview|libID=%s';
$lang->caselib->menu->all = '所有|caselib|browse|libID=%s&browseType=all';
$lang->caselib->menu->wait = '待评审|caselib|browse|libID=%s&browseType=wait';
$lang->caselib->menu->view = '概况|caselib|view|libID=%s';
$lang->caselib->menuOrder[5] = 'lib';
$lang->caselib->menuOrder[10] = 'all';
@@ -882,6 +884,7 @@ if(isset($config->global->flow) and $config->global->flow == 'onlyTest')
$lang->menugroup->case = 'testcase';
$lang->menugroup->testtask = 'testtask';
$lang->menugroup->testsuite = 'testsuite';
$lang->menugroup->caselib = 'caselib';
$lang->menugroup->testreport = 'testtask';
$lang->menugroup->build = 'product';
+12 -6
View File
@@ -596,10 +596,10 @@ class commonModel extends model
/* Avoid user thinking the page is shaking when the menu toggle class 'active' */
if($config->global->flow == 'onlyTest')
{
if($currentModule == 'bug' && $currentMethod == 'browse') $active = '';
if($currentModule == 'testcase' && $currentMethod == 'browse') $active = '';
if($currentModule == 'testtask' && $currentMethod == 'browse') $active = '';
if($currentModule == 'testsuite' && $currentMethod == 'library') $active = '';
if($currentModule == 'bug' && $currentMethod == 'browse') $active = '';
if($currentModule == 'testcase' && $currentMethod == 'browse') $active = '';
if($currentModule == 'testtask' && $currentMethod == 'browse') $active = '';
if($currentModule == 'caselib' && $currentMethod == 'browse') $active = '';
}
$label = $menuItem->text;
@@ -1716,6 +1716,8 @@ EOD;
$user->admin = strpos($this->app->company->admins, ",{$user->account},") !== false;
$this->session->set('user', $user);
$this->app->user = $user;
$this->loadModel('action')->create('user', $user->id, 'login');
$this->loadModel('score')->create('user', 'login');
if($isFreepasswd) die(js::locate($this->config->webRoot));
@@ -1750,11 +1752,15 @@ EOD;
/* Change for task #5384. */
if(isset($queryString['time']))
{
$timestamp = $queryString['time'];
if(strlen($timestamp) > 10) $timestamp = substr($timestamp, 0, 10);
if(strlen($timestamp) != 10 or $timestamp{0} >= '4') $this->response('ERROR_TIMESTAMP');
$result = $this->get->token == md5($entry->code . $entry->key . $queryString['time']);
if($result)
{
if($queryString['time'] <= $entry->calledTime) $this->response('CALLED_TIME');
$this->loadModel('entry')->updateTime($entry->code, $queryString['time']);
if($timestamp <= $entry->calledTime) $this->response('CALLED_TIME');
$this->loadModel('entry')->updateTime($entry->code, $timestamp);
unset($_GET['time']);
return $result;
}
+2 -1
View File
@@ -64,9 +64,10 @@
<?php if(!empty($action->comment)):?>
<?php if($canEditComment):?>
<?php echo html::commonButton('<i class="icon icon-pencil"></i>', "title='{$lang->action->editComment}'", 'btn btn-link btn-icon btn-sm btn-edit-comment');?>
<style>.comment .comment-content{width: 98%}</style>
<?php endif;?>
<div class='article-content comment'>
<?php echo strip_tags($action->comment) == $action->comment ? nl2br($action->comment) : $action->comment;?>
<div class='comment-content'><?php echo strip_tags($action->comment) == $action->comment ? nl2br($action->comment) : $action->comment;?></div>
</div>
<?php if($canEditComment):?>
<form method='post' class='comment-edit-form' action='<?php echo $this->createLink('action', 'editComment', "actionID=$action->id")?>'>
+3 -1
View File
@@ -22,7 +22,8 @@ $config->custom->requiredModules[50] = 'bug';
$config->custom->requiredModules[55] = 'testcase';
$config->custom->requiredModules[60] = 'testsuite';
$config->custom->requiredModules[65] = 'testreport';
$config->custom->requiredModules[70] = 'testtask';
$config->custom->requiredModules[70] = 'caselib';
$config->custom->requiredModules[75] = 'testtask';
$config->custom->requiredModules[75] = 'doc';
@@ -50,6 +51,7 @@ $config->custom->fieldList['bug']['resolve'] = 'resolvedBuild,resolvedDa
$config->custom->fieldList['testcase']['create'] = 'stage,story,pri,precondition,keywords';
$config->custom->fieldList['testcase']['edit'] = 'stage,story,pri,precondition,keywords,status';
$config->custom->fieldList['testsuite'] = 'desc';
$config->custom->fieldList['caselib'] = 'desc';
$config->custom->fieldList['testcase']['createcase'] = 'lib,stage,pri,precondition,keywords';
$config->custom->fieldList['testreport'] = 'begin,end,members,report';
$config->custom->fieldList['testtask'] = 'owner,pri,status,desc,comment';
+1 -2
View File
@@ -42,8 +42,7 @@
if($moduleName == 'doc' and $method == 'createlib') $method = 'createLib';
if($moduleName == 'doc' and $method == 'editlib') $method = 'editLib';
if($moduleName == 'testsuite' and $method == 'createlib') $method = 'createLib';
if($moduleName == 'testsuite' and $method == 'createcase')
if($moduleName == 'caselib' and $method == 'createcase')
{
$this->app->loadLang('testcase');
$fields = $this->custom->getFormFields('testcase', $method);
+1 -1
View File
@@ -41,7 +41,7 @@ class devModel extends model
{
if(isset($this->config->dev->tableMap[$module])) $aliasModule = $this->config->dev->tableMap[$module];
if(strpos($aliasModule, '-') !== false) list($aliasModule, $subLang) = explode('-', $aliasModule);
$this->app->loadLang($aliasModule ? $aliasModule : $module);
if(strpos($module, 'im_') === false) $this->app->loadLang($aliasModule ? $aliasModule : $module);
}
catch(PDOException $e)
{
+2 -3
View File
@@ -364,7 +364,7 @@ class docModel extends model
elseif($browseType == "bymodule")
{
$modules = 0;
if($moduleID) $modules = $this->loadModel('tree')->getAllChildId($moduleID);
if($moduleID) $modules = (strpos($this->config->doc->custom->showLibs, 'children') === false) ? array($moduleID => $moduleID) : $this->loadModel('tree')->getAllChildId($moduleID);
$docs = $this->getDocs($libID, $modules, $sort, $pager);
}
elseif($browseType == "bygrid")
@@ -508,7 +508,6 @@ class docModel extends model
->beginIF(!empty($module) or strpos($this->config->doc->custom->showLibs, 'children') === false)->andWhere('module')->in($module)->fi()
->query();
$docIdList = array();
while($doc = $stmt->fetch())
{
@@ -566,7 +565,7 @@ class docModel extends model
$doc->content = isset($docContent->content) ? $docContent->content : '';
$doc->contentType = isset($docContent->type) ? $docContent->type : '';
$doc = $this->loadModel('file')->replaceImgURL($doc, 'content');
if($doc->type != 'url') $doc = $this->loadModel('file')->replaceImgURL($doc, 'content');
if($setImgSize) $doc->content = $this->file->setImgSize($doc->content);
$doc->files = $docFiles;
+1
View File
@@ -16,3 +16,4 @@ $config->entry->errcode['ACCOUNT_UNBOUND'] = 403;
$config->entry->errcode['EMPTY_ENTRY'] = 404;
$config->entry->errcode['CALLED_TIME'] = 405;
$config->entry->errcode['INVALID_ACCOUNT'] = 406;
$config->entry->errcode['ERROR_TIMESTAMP'] = 407;
+2
View File
@@ -54,3 +54,5 @@ $lang->entry->errmsg['IP_DENIED'] = 'IP ist unzulässig.';
$lang->entry->errmsg['ACCOUNT_UNBOUND'] = 'Account is not bound.';
$lang->entry->errmsg['INVALID_ACCOUNT'] = 'Account is not exists';
$lang->entry->errmsg['EMPTY_ENTRY'] = 'Key des Eintrags fehlt.';
$lang->entry->errmsg['CALLED_TIME'] = 'Token has expired';
$lang->entry->errmsg['ERROR_TIMESTAMP'] = 'Timestamp Error';
+1
View File
@@ -55,3 +55,4 @@ $lang->entry->errmsg['ACCOUNT_UNBOUND'] = 'Account is not bound.';
$lang->entry->errmsg['INVALID_ACCOUNT'] = 'Invalid account.';
$lang->entry->errmsg['EMPTY_ENTRY'] = 'Application does not exist.';
$lang->entry->errmsg['CALLED_TIME'] = 'Token has expired';
$lang->entry->errmsg['ERROR_TIMESTAMP'] = 'Timestamp Error';
+1
View File
@@ -55,3 +55,4 @@ $lang->entry->errmsg['ACCOUNT_UNBOUND'] = '未绑定用户';
$lang->entry->errmsg['INVALID_ACCOUNT'] = '用户不存在';
$lang->entry->errmsg['EMPTY_ENTRY'] = '应用不存在';
$lang->entry->errmsg['CALLED_TIME'] = 'Token已失效';
$lang->entry->errmsg['ERROR_TIMESTAMP'] = '错误的时间戳。';
+1
View File
@@ -55,3 +55,4 @@ $lang->entry->errmsg['ACCOUNT_UNBOUND'] = '未綁定用戶';
$lang->entry->errmsg['INVALID_ACCOUNT'] = '用戶不存在';
$lang->entry->errmsg['EMPTY_ENTRY'] = '應用不存在';
$lang->entry->errmsg['CALLED_TIME'] = 'Token已失效';
$lang->entry->errmsg['ERROR_TIMESTAMP'] = '錯誤的時間戳。';
+3
View File
@@ -510,6 +510,9 @@ class fileModel extends model
*/
public function parseCSV($fileName)
{
/* Parse file only in zentao. */
if(strpos(realpath($fileName), $this->app->getBasePath()) !== 0) return array();
$content = file_get_contents($fileName);
/* Fix bug #890. */
$content = str_replace("\x82\x32", "\x10", $content);
-1
View File
@@ -213,7 +213,6 @@ class group extends control
foreach($this->lang->resource as $module => $moduleActions)
{
$modules[$module] = $this->lang->$module->common;
if($module == 'caselib') $module = 'testsuite';
foreach($moduleActions as $action)
{
$actions[$module][$action] = $this->lang->$module->$action;
+7 -7
View File
@@ -658,22 +658,22 @@ $lang->testsuite->methodOrder[35] = 'unlinkCase';
$lang->testsuite->methodOrder[40] = 'batchUnlinkCases';
$lang->resource->caselib = new stdclass();
$lang->resource->caselib->library = 'library';
$lang->resource->caselib->createLib = 'createLib';
$lang->resource->caselib->edit = 'editLib';
$lang->resource->caselib->browse = 'browse';
$lang->resource->caselib->create = 'create';
$lang->resource->caselib->edit = 'edit';
$lang->resource->caselib->createCase = 'createCase';
$lang->resource->caselib->libView = 'libView';
$lang->resource->caselib->view = 'view';
$lang->resource->caselib->batchCreateCase = 'batchCreateCase';
$lang->resource->caselib->exportTemplet = 'exportTemplet';
$lang->resource->caselib->import = 'importAction';
$lang->resource->caselib->showImport = 'showImport';
$lang->caselib->methodOrder[0] = 'library';
$lang->caselib->methodOrder[5] = 'createLib';
$lang->caselib->methodOrder[0] = 'browse';
$lang->caselib->methodOrder[5] = 'create';
$lang->caselib->methodOrder[10] = 'edit';
$lang->caselib->methodOrder[15] = 'createCase';
$lang->caselib->methodOrder[20] = 'batchCreateCase';
$lang->caselib->methodOrder[25] = 'libView';
$lang->caselib->methodOrder[25] = 'view';
$lang->caselib->methodOrder[30] = 'exportTemplet';
$lang->caselib->methodOrder[35] = 'import';
$lang->caselib->methodOrder[40] = 'showImport';
-1
View File
@@ -420,7 +420,6 @@ class groupModel extends model
public function checkMenuModule($menu, $moduleName)
{
if(empty($menu)) return true;
if($menu == 'caselib' and $moduleName == 'testsuite') return true;
if($menu == 'other' and (isset($this->lang->menugroup->$moduleName) or isset($this->lang->menu->$moduleName))) return false;
if($menu != 'other' and !($moduleName == $menu or (isset($this->lang->menugroup->$moduleName) and $this->lang->menugroup->$moduleName == $menu))) return false;
return true;
-1
View File
@@ -111,7 +111,6 @@
<?php endif;?>
<td id='<?php echo $moduleName;?>' class='pv-10px' colspan='<?php echo !empty($lang->$moduleName->menus) ? 1 : 2?>'>
<?php $i = 1;?>
<?php if($moduleName == 'caselib') $moduleName = 'testsuite';?>
<?php foreach($moduleActions as $action => $actionLabel):?>
<?php if(!empty($lang->$moduleName->menus) and $action == 'browse') continue;;?>
<?php if(!empty($version) and strpos($changelogs, ",$moduleName-$actionLabel,") === false) continue;?>
+7 -7
View File
@@ -46,7 +46,7 @@ $lang->misc->zentao->cowin['reportbug'] = "Bug melden ";
$lang->misc->zentao->cowin['feedback'] = "Feedback";
$lang->misc->zentao->cowin['recommend'] = "More";
$lang->misc->zentao->service['zentaotrain']= 'Zentao Train';
$lang->misc->zentao->service['zentaotrain']= 'Zentao Training';
$lang->misc->zentao->service['idc'] = 'Zentao Cloud';
$lang->misc->zentao->service['custom'] = 'Zentao Custom';
$lang->misc->zentao->service['servicemore']= 'Mehr';
@@ -82,6 +82,7 @@ $lang->misc->feature = new stdclass();
$lang->misc->feature->lastest = 'Letzte Version';
$lang->misc->feature->detailed = 'Details';
$lang->misc->releaseDate['11.6.3'] = '2019-09-24';
$lang->misc->releaseDate['11.6.2'] = '2019-09-06';
$lang->misc->releaseDate['11.6.1'] = '2019-08-23';
$lang->misc->releaseDate['11.6.stable'] = '2019-07-12';
@@ -114,16 +115,15 @@ $lang->misc->releaseDate['7.2.stable'] = '2015-05-22';
$lang->misc->releaseDate['7.1.stable'] = '2015-03-07';
$lang->misc->releaseDate['6.3.stable'] = '2014-11-07';
$lang->misc->feature->all['11.6.2'][] = array('title'=>'Optimize details and fix bug.', 'desc' => '');
$lang->misc->feature->all['11.6.1'][] = array('title'=>'Optimize details and fix bug.', 'desc' => '');
$lang->misc->feature->all['11.6.3'][] = array('title'=>'Fix bug.', 'desc' => '');
$lang->misc->feature->all['11.6.2'][] = array('title'=>'Optimize details and fix bug.', 'desc' => '');
$lang->misc->feature->all['11.6.1'][] = array('title'=>'Optimize details and fix bug.', 'desc' => '');
$lang->misc->feature->all['11.6.stable'][] = array('title'=>'Improving the International Edition Interface', 'desc' => '');
$lang->misc->feature->all['11.6.stable'][] = array('title'=>'Add translate function', 'desc' => '');
$lang->misc->feature->all['11.5.2'][] = array('title'=>'Increase the security of ZenTao and increase the login password for weak password check', 'desc' => '');
$lang->misc->feature->all['11.5.1'][] = array('title'=>'Add a third-party authentication and fix bugs.', 'desc' => '');
$lang->misc->feature->all['11.5.2'][] = array('title'=>'Increase the security of ZenTao and increase the login password for weak password check', 'desc' => '');
$lang->misc->feature->all['11.5.1'][] = array('title'=>'Add a third-party authentication and fix bugs.', 'desc' => '');
$lang->misc->feature->all['11.5.stable'][] = array('title'=>'Optimize details and fix bug.', 'desc' => '');
$lang->misc->feature->all['11.5.stable'][] = array('title'=>'Added filters to Dynamics', 'desc' => '');
+7 -7
View File
@@ -46,7 +46,7 @@ $lang->misc->zentao->cowin['reportbug'] = "Report Bug ";
$lang->misc->zentao->cowin['feedback'] = "Feedback";
$lang->misc->zentao->cowin['recommend'] = "More";
$lang->misc->zentao->service['zentaotrain']= 'Zentao Train';
$lang->misc->zentao->service['zentaotrain']= 'Zentao Training';
$lang->misc->zentao->service['idc'] = 'Zentao Cloud';
$lang->misc->zentao->service['custom'] = 'Zentao Custom';
$lang->misc->zentao->service['servicemore']= 'More';
@@ -82,6 +82,7 @@ $lang->misc->feature = new stdclass();
$lang->misc->feature->lastest = 'Latest Version';
$lang->misc->feature->detailed = 'Detail';
$lang->misc->releaseDate['11.6.3'] = '2019-09-24';
$lang->misc->releaseDate['11.6.2'] = '2019-09-06';
$lang->misc->releaseDate['11.6.1'] = '2019-08-23';
$lang->misc->releaseDate['11.6.stable'] = '2019-07-12';
@@ -114,16 +115,15 @@ $lang->misc->releaseDate['7.2.stable'] = '2015-05-22';
$lang->misc->releaseDate['7.1.stable'] = '2015-03-07';
$lang->misc->releaseDate['6.3.stable'] = '2014-11-07';
$lang->misc->feature->all['11.6.2'][] = array('title'=>'Optimize details and fix bug.', 'desc' => '');
$lang->misc->feature->all['11.6.1'][] = array('title'=>'Optimize details and fix bug.', 'desc' => '');
$lang->misc->feature->all['11.6.3'][] = array('title'=>'Fix bug.', 'desc' => '');
$lang->misc->feature->all['11.6.2'][] = array('title'=>'Optimize details and fix bug.', 'desc' => '');
$lang->misc->feature->all['11.6.1'][] = array('title'=>'Optimize details and fix bug.', 'desc' => '');
$lang->misc->feature->all['11.6.stable'][] = array('title'=>'Improving the International Edition Interface', 'desc' => '');
$lang->misc->feature->all['11.6.stable'][] = array('title'=>'Add translate function', 'desc' => '');
$lang->misc->feature->all['11.5.2'][] = array('title'=>'Increase the security of ZenTao and increase the login password for weak password check', 'desc' => '');
$lang->misc->feature->all['11.5.1'][] = array('title'=>'Add a third-party authentication and fix bugs.', 'desc' => '');
$lang->misc->feature->all['11.5.2'][] = array('title'=>'Increase the security of ZenTao and increase the login password for weak password check', 'desc' => '');
$lang->misc->feature->all['11.5.1'][] = array('title'=>'Add a third-party authentication and fix bugs.', 'desc' => '');
$lang->misc->feature->all['11.5.stable'][] = array('title'=>'Optimize details and fix bug.', 'desc' => '');
$lang->misc->feature->all['11.5.stable'][] = array('title'=>'Added filters to Dynamics', 'desc' => '');
+6 -6
View File
@@ -82,6 +82,7 @@ $lang->misc->feature = new stdclass();
$lang->misc->feature->lastest = '最新版本';
$lang->misc->feature->detailed = '详情';
$lang->misc->releaseDate['11.6.3'] = '2019-09-24';
$lang->misc->releaseDate['11.6.2'] = '2019-09-06';
$lang->misc->releaseDate['11.6.1'] = '2019-08-23';
$lang->misc->releaseDate['11.6.stable'] = '2019-07-12';
@@ -114,16 +115,15 @@ $lang->misc->releaseDate['7.2.stable'] = '2015-05-22';
$lang->misc->releaseDate['7.1.stable'] = '2015-03-07';
$lang->misc->releaseDate['6.3.stable'] = '2014-11-07';
$lang->misc->feature->all['11.6.2'][] = array('title'=>'完善细节,修复Bug', 'desc' => '');
$lang->misc->feature->all['11.6.1'][] = array('title'=>'完善细节,修复Bug', 'desc' => '');
$lang->misc->feature->all['11.6.3'][] = array('title'=>'修复Bug', 'desc' => '');
$lang->misc->feature->all['11.6.2'][] = array('title'=>'完善细节,修复Bug', 'desc' => '');
$lang->misc->feature->all['11.6.1'][] = array('title'=>'完善细节,修复Bug', 'desc' => '');
$lang->misc->feature->all['11.6.stable'][] = array('title'=>'改善国际版界面', 'desc' => '');
$lang->misc->feature->all['11.6.stable'][] = array('title'=>'添加翻译功能', 'desc' => '');
$lang->misc->feature->all['11.5.2'][] = array('title'=>'增加禅道安全性,增加登录禅道弱口令检查', 'desc' => '');
$lang->misc->feature->all['11.5.1'][] = array('title'=>'新增第三方应用免密登录禅道,修复Bug', 'desc' => '');
$lang->misc->feature->all['11.5.2'][] = array('title'=>'增加禅道安全性,增加登录禅道弱口令检查', 'desc' => '');
$lang->misc->feature->all['11.5.1'][] = array('title'=>'新增第三方应用免密登录禅道,修复Bug', 'desc' => '');
$lang->misc->feature->all['11.5.stable'][] = array('title'=>'完善细节,修复Bug', 'desc' => '');
$lang->misc->feature->all['11.5.stable'][] = array('title'=>'新增动态过滤机制', 'desc' => '');
+6 -6
View File
@@ -82,6 +82,7 @@ $lang->misc->feature = new stdclass();
$lang->misc->feature->lastest = '最新版本';
$lang->misc->feature->detailed = '詳情';
$lang->misc->releaseDate['11.6.3'] = '2019-09-24';
$lang->misc->releaseDate['11.6.2'] = '2019-09-06';
$lang->misc->releaseDate['11.6.1'] = '2019-08-23';
$lang->misc->releaseDate['11.6.stable'] = '2019-07-12';
@@ -114,16 +115,15 @@ $lang->misc->releaseDate['7.2.stable'] = '2015-05-22';
$lang->misc->releaseDate['7.1.stable'] = '2015-03-07';
$lang->misc->releaseDate['6.3.stable'] = '2014-11-07';
$lang->misc->feature->all['11.6.2'][] = array('title'=>'完善細節,修復Bug', 'desc' => '');
$lang->misc->feature->all['11.6.1'][] = array('title'=>'完善細節,修復Bug', 'desc' => '');
$lang->misc->feature->all['11.6.3'][] = array('title'=>'修復Bug', 'desc' => '');
$lang->misc->feature->all['11.6.2'][] = array('title'=>'完善細節,修復Bug', 'desc' => '');
$lang->misc->feature->all['11.6.1'][] = array('title'=>'完善細節,修復Bug', 'desc' => '');
$lang->misc->feature->all['11.6.stable'][] = array('title'=>'改善國際版界面', 'desc' => '');
$lang->misc->feature->all['11.6.stable'][] = array('title'=>'添加翻譯功能', 'desc' => '');
$lang->misc->feature->all['11.5.2'][] = array('title'=>'增加禪道安全性,增加登錄禪道弱口令檢查', 'desc' => '');
$lang->misc->feature->all['11.5.1'][] = array('title'=>'新增第三方應用免密登錄禪道,修復Bug', 'desc' => '');
$lang->misc->feature->all['11.5.2'][] = array('title'=>'增加禪道安全性,增加登錄禪道弱口令檢查', 'desc' => '');
$lang->misc->feature->all['11.5.1'][] = array('title'=>'新增第三方應用免密登錄禪道,修復Bug', 'desc' => '');
$lang->misc->feature->all['11.5.stable'][] = array('title'=>'完善細節,修復Bug', 'desc' => '');
$lang->misc->feature->all['11.5.stable'][] = array('title'=>'新增動態過濾機制', 'desc' => '');
+1
View File
@@ -7,3 +7,4 @@
.release-line > li > a:before {border-color: #00da88;}
.release-line > li:nth-child(even) > a {padding-bottom: 38px;}
.release-link-line {pointer-events: none; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA+YAAADiCAMAAAD0xy2eAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAABOUExURUdwTOXl5eXl5ebm5ufn5+rq6u7u7unp6eXl5f///+Xl5eXl5efn5+Xl5eXl5eXl5ebm5uXl5eXl5ebm5ubm5ubm5uXl5ebm5uXl5eXl5Uh6G7kAAAAZdFJOUwDuuVQtFQwg1gXH+Dpzoq1CmIV7aEuOX+MTWsN0AAAGrUlEQVQYGe3ACbaYOHRF0SuQkETfw5v/RPNdLpMZZKWez5buVQBcu8zmJACO1WOwcAqAZ7kx66MAeNa+ZncnAI51t1kvAK7F/hEAAAAAAACA/xP93gmAZ6tZOKsAODb2ZuUSAM/aYtZEAXCsTsFs7gTAse4eigD4lqMAAAAAAMD/D09/CYBrvVl/CYBjdXrN+lUAHOumYNavAuBYNwWzTQA866ZwCYBvnQAAAAD8V7RHEgDParHhzgLg2NqYDXMUAMfiPJg1qwA4lu/BbBMAz7rjvQTAtyoAAOBG1wmAb1O4swB4NptZcwmAY3EbzN4pCYBfaSpmwywAnl2NNQLgW44CAABuZAHwLQ1lSgLg2BjMhuUSAL9q25jZu2cB8CsfxcweAfBsnYcsAL51AgAAboxL2wmAZ5vZMF9VANxKZ29mYRsFwK98FDN7swA4Fvc3VAHwLQsAALgxlSMKgGeNmZU9CoBb9dqCmb33KABu1XV7zSwJgGfjPQsAALixHlEAXJvN3u3qBMCtdXvNbGjOLABuxaO3H1EAHEvPUgQAANwYlycLgGe7mZX76gTAq3wuwcyGZsoC4FUd997MLgHwLLVbJwB/j7UTANeyDf2+dgLgVuwHMxv6fa0C4FR37b39WATAse66+0kA/h45CYBvjZX5yQLg1xLsR1imsQqATzVOy2s/kgA4lp+tEYC/R9rOsRMAx1r7UebjygLgU57mMtgvswC4VeNzN++hT0oC4FDVZ7ehLPe55ioAPu3BfhseAXCqi+2xNa9d+rTnFTsB8KLqH7Xq09iPoTTzngXApXNrSrBfRn1i7ATAlS5e5570KWbD2y/b8XQC4NJSgv2W9RljrgLgR5fH9tznqk8ws1D6ZTs6AXCp6d/B/lH1Oc52jakKgBcpj+156FPtt1B6AXCp27elKcHMgj5d6Zdtn55rzALgRcpRn2x/vPrUMaYqAP9hVZ8a1/Y87rnpG32y/Qhv38y7ALiU+xIG+6Xok5r5Ps52jbkTABe6PF5Pq89ofxR9upg7AXAiXc+0b0tT3kaf0cyGtzTLdgqAS2N5B/tHo09ctn162jGmKgAedDmu7Xnp09ofjT5dTFUAnEjtedzz0pd30+cxs/D2zXy3AuBSW4L9tumzzvdxtmvMnQC40OXxes5Vn8n+2PTpkgC4EZ9p35amvMOuz2QWSr/M9zQKgEtTsH/t+qzH2a4xVQFwoaY4Xs+0r/rs9lsopwC4tO7b0pcwmJ367KVftn16rjEJgBddTvrM9sejT46pCoATKY7tedxz06/6zGYWSr9sexQAl+4S7LdLn3Z6rpirAHiR4tieR9ansX+E0o8C4NJzz015BzMb9bmX7TjbMXcC4EaXx06fYv8aogC4NLbnvi19CZb06Usz38dzjVkA/Kj6X8H+SPpUAfAjxfWZ9rnp36pPCKWZ7+m5ogC4VAf7o+rTCYAjKa7PdM9Nr0+1UJr5ntoxC4BLebB/BQFwKsX1me6lb/RJ89HGKgB+jfZLae5zFACX0nk3xX5pBMCvGttjnvRJWQB8myw0e5sFwK0p2C+h2aMAOJXbvQlm1gqAZ/k6sgD8PfpmXzsB8KuzX8rWZgFwKrV3P9iPIgB+1fFoQi8AziV9qgA4d4bljALg2GY/3vnJAuBVfubXfryrAPgVzyVYFgDfogD8Per8JAHwbDWzfh+rAHiVpmYws7CcWQC8qtddzOwWAM/yuawCAABu9HPbCYBj2cyG5swC4FacevtR9lEA3ErPEswWAfCsrncrAADgxraPAuBZN5i921oFwK31fs0szG0nAG7FvZhZLwCe5ak/BAAA3FizAPj2WjmyAPjVzcHMyhEFwK16zcHMyiQAftVrCzYLgGt1jQIAAG7MRxYAz7KZ9VMWALfqNQcz66ckAG7VdhnM7BYAx2q7DKcA+NZ1AgAAXtSyjQLg2WVm7x4FwK94v2ZWpiwAfo1bMLNJAByr1zyMAuBbJwAA4EYsUxYAzw4za55OANyq1zKYDctVBcCt7mnMLIwC4Fg+ytAJgG9ZAADAjWuPAuBaY9afSQD8GrdgNixXFQC3atuYWbirAPiVpmJFAHyLqwAAgBtjEgDX6jssVxUAv9IymIU7CoBfaSpm1p9JAPwat2A2C4BntW1WAQAAAPiPyGVKAuDZYTYslwD4VdvGzN49C4Bf6Shm1kQBcGydhyEJgGvdJQAA4EZOAuDbMiyrAHi2mNl7ZAHwKx2vmTVXFQC/1mUw6wXAszSVQwCcqwIAAG4cSQBcW4ckAK7lU/8D/a9fSZZlwxkAAAAASUVORK5CYII=); height: 196px; position: absolute; left: 10px; right: 100px; top: 97px; background-size: 100% 100%; background-repeat: no-repeat;}
.release-line li .title{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
+2 -1
View File
@@ -66,7 +66,8 @@
<i class="icon icon-flag text-primary"></i>
<?php endif;?>
<div class="block">
<span class="title"><?php echo isset($roadmap->build) ? $roadmap->name : $roadmap->title;?></span>
<?php $roadmapTitle = isset($roadmap->build) ? $roadmap->name : $roadmap->title;?>
<span class="title" title='<?php echo $roadmapTitle;?>'><?php echo $roadmapTitle;?></span>
<span class="date"><?php echo isset($roadmap->build) ? $roadmap->date : ($roadmap->end == '2030-01-01' ? $lang->productplan->future : $roadmap->begin . '~' . $roadmap->end);?></span>
</div>
</a>
+5 -1
View File
@@ -1101,7 +1101,11 @@ class project extends control
$this->executeHooks($projectID);
$planID = reset($_POST['plans']);
$planID = '';
foreach($_POST['plans'] as $planID)
{
if(!empty($planID)) break;
}
if(!empty($planID))
{
$this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('create', "projectID=$projectID&copyProjectID=&planID=$planID&confirm=no")));
+4
View File
@@ -1566,6 +1566,8 @@ class projectModel extends model
$lastOrder = reset($linkedStories);
foreach($stories as $key => $storyID)
{
$status = $this->dao->findById($storyID)->from(TABLE_STORY)->fetch('status');
if($status == 'draft') continue;
if(isset($linkedStories[$storyID])) continue;
$productID = (int)$products[$storyID];
@@ -1599,6 +1601,7 @@ class projectModel extends model
{
foreach($plans as $planID => $productID)
{
if(empty($planID)) continue;
$planStory = $this->loadModel('story')->getPlanStories($planID);
if(!empty($planStory))
{
@@ -1716,6 +1719,7 @@ class projectModel extends model
->where('t1.account')->eq($account)
->andWhere('t1.root')->ne($currentProject)
->andWhere('t1.type')->eq('project')
->andWhere('t2.deleted')->eq('0')
->groupBy('t1.root')
->orderBy('t1.root DESC')
->fetchPairs();
+1 -1
View File
@@ -90,7 +90,7 @@
</div>
</div>
<div class="main-col">
<div id='queryBox' class='cell <?php if($type =='bySearch') echo 'show';?>'></div>
<div id='queryBox' class='cell <?php if($type =='bysearch') echo 'show';?>'></div>
<?php if(empty($stories)):?>
<div class="table-empty-tip">
<p>
+24 -23
View File
@@ -339,31 +339,31 @@ $(function()
var setDateField = function(query, fieldNO)
{
var $period = $('#selectPeriod');
if(!$period.length)
{
$period = $("<ul id='selectPeriod' class='dropdown-menu'><li class='dropdown-header'><?php echo $lang->datepicker->dpText->TEXT_OR . ' ' . $lang->datepicker->dpText->TEXT_DATE;?></li><li><a href='#lastWeek'><?php echo $lang->datepicker->dpText->TEXT_PREV_WEEK;?></a></li><li><a href='#thisWeek'><?php echo $lang->datepicker->dpText->TEXT_THIS_WEEK;?></a></li><li><a href='#yesterday'><?php echo $lang->datepicker->dpText->TEXT_YESTERDAY;?></a></li><li><a href='#today'><?php echo $lang->datepicker->dpText->TEXT_TODAY;?></a></li><li><a href='#lastMonth'><?php echo $lang->datepicker->dpText->TEXT_PREV_MONTH;?></a></li><li><a href='#thisMonth'><?php echo $lang->datepicker->dpText->TEXT_THIS_MONTH;?></a></li></ul>").appendTo('body');
$period.find('li > a').click(function(event)
{
var target = $(query).closest('form').find('#' + $period.data('target'));
if(target.length)
{
if(target.next('input[type=hidden]').length)
{
target.next('input[type=hidden]').val($(this).attr('href').replace('#', '$'));
target.attr('placeholder', $(this).attr('href').replace('#', '$'));
}
else
{
target.val($(this).attr('href').replace('#', '$'));
}
if($period.length) $period.remove();
$(query).closest('form').find('#operator' + $period.data('fieldNO')).val('between');
$period.hide();
$period = $("<ul id='selectPeriod' class='dropdown-menu'><li class='dropdown-header'><?php echo $lang->datepicker->dpText->TEXT_OR . ' ' . $lang->datepicker->dpText->TEXT_DATE;?></li><li><a href='#lastWeek'><?php echo $lang->datepicker->dpText->TEXT_PREV_WEEK;?></a></li><li><a href='#thisWeek'><?php echo $lang->datepicker->dpText->TEXT_THIS_WEEK;?></a></li><li><a href='#yesterday'><?php echo $lang->datepicker->dpText->TEXT_YESTERDAY;?></a></li><li><a href='#today'><?php echo $lang->datepicker->dpText->TEXT_TODAY;?></a></li><li><a href='#lastMonth'><?php echo $lang->datepicker->dpText->TEXT_PREV_MONTH;?></a></li><li><a href='#thisMonth'><?php echo $lang->datepicker->dpText->TEXT_THIS_MONTH;?></a></li></ul>").appendTo('body');
$period.find('li > a').click(function(event)
{
var target = $(query).closest('form').find('#' + $period.data('target'));
if(target.length)
{
if(target.next('input[type=hidden]').length)
{
target.next('input[type=hidden]').val($(this).attr('href').replace('#', '$'));
target.attr('placeholder', $(this).attr('href').replace('#', '$'));
}
event.stopPropagation();
return false;
});
}
else
{
target.val($(this).attr('href').replace('#', '$'));
}
$(query).closest('form').find('#operator' + $period.data('fieldNO')).val('between');
$period.hide();
}
event.stopPropagation();
return false;
});
$(query).datetimepicker('remove').datepicker(dtOptions).on('show', function(e)
{
var $e = $(e.target);
@@ -412,6 +412,7 @@ $(function()
if(typeof(params[fieldName]['class']) != undefined && params[fieldName]['class'] == 'date')
{
console.log($searchForm.find("#value" + fieldNO));
setDateField($searchForm.find("#value" + fieldNO), fieldNO);
$searchForm.find("#value" + fieldNO).addClass('date'); // Shortcut the width of the datepicker to make sure align with others.
var maxNO = 2 * groupItems;
+2 -2
View File
@@ -869,7 +869,6 @@ class storyModel extends model
->setDefault('assignedDate', $now)
->removeIF($this->post->closedReason != 'duplicate', 'duplicateStory')
->removeIF($this->post->closedReason != 'subdivided', 'childStories')
->setIF($this->post->closedReason != 'done', 'plan', 0)
->remove('comment')
->get();
@@ -1709,7 +1708,8 @@ class storyModel extends model
{
if(defined('TUTORIAL')) return $this->loadModel('tutorial')->getProjectStories();
if($type == 'bySearch')
$type = strtolower($type);
if($type == 'bysearch')
{
$queryID = (int)$param;
$products = $this->loadModel('project')->getProducts($projectID);
+15 -4
View File
@@ -90,7 +90,7 @@ class task extends control
if(!empty($_POST))
{
$response['result'] = 'success';
$response['message'] = '';
$response['message'] = $this->lang->saveSuccess;
if($this->post->project) $projectID = $this->post->project;
$tasksID = $this->task->create($projectID);
@@ -173,11 +173,18 @@ class task extends control
}
$users = $this->loadModel('user')->getPairs('noclosed|nodeleted');
$moduleIdList = $this->tree->getAllChildID($moduleID);
$stories = $this->story->getProjectStoryPairs($projectID, 0, 0, $moduleIdList);
$members = $this->project->getTeamMemberPairs($projectID, 'nodeleted');
$moduleOptionMenu = $this->tree->getTaskOptionMenu($projectID);
/* Fix bug #2737. When moduleID is not story module. */
$moduleIdList = array();
if($moduleID)
{
$moduleID = $this->tree->getStoryModule($moduleID);
$moduleIdList = $this->tree->getAllChildID($moduleID);
}
$stories = $this->story->getProjectStoryPairs($projectID, 0, 0, $moduleIdList);
$title = $project->name . $this->lang->colon . $this->lang->task->create;
$position[] = html::a($taskLink, $project->name);
$position[] = $this->lang->task->common;
@@ -1168,7 +1175,11 @@ class task extends control
else
{
$this->task->delete(TABLE_TASK, $taskID);
if($task->parent > 0) $this->task->updateParentStatus($task->id);
if($task->parent > 0)
{
$this->task->updateParentStatus($task->id);
$this->loadModel('action')->create('task', $task->parent, 'deleteChildrenTask', '', $taskID);
}
if($task->fromBug != 0) $this->dao->update(TABLE_BUG)->set('toTask')->eq(0)->where('id')->eq($task->fromBug)->exec();
if($task->story) $this->loadModel('story')->setStage($task->story);
+2
View File
@@ -199,6 +199,7 @@ $lang->task->cannotDeleteParent = 'Cannot delete parent task';
$lang->task->error = new stdclass();
$lang->task->error->consumedNumber = '"Current Cost" must be numbers.';
$lang->task->error->estimateNumber = '"Estimates" must be numbers.';
$lang->task->error->recordMinus = 'Work hours should not be negative number.';
$lang->task->error->consumedSmall = '"Hours Cost" must be > the last number.';
$lang->task->error->consumedThisTime = 'Please enter "Hours Cost"';
$lang->task->error->left = 'Please enter "Hours Left"';
@@ -207,6 +208,7 @@ $lang->task->error->skipClose = 'Task: %s is not "Finished” or “Cance
$lang->task->error->consumed = 'Task: %s hour must be < 0. Ignore changes to this task.';
$lang->task->error->assignedTo = 'Multi-user task in the current status cannot be assigned to a member who is not in the task team.';
$lang->task->error->consumedEmpty = '"Current Cost" should not be empty.';
$lang->task->error->deadlineSmall = '"Deadline" must be greater than "StartDate".';
/* Report. */
$lang->task->report = new stdclass();
+2
View File
@@ -199,6 +199,7 @@ $lang->task->cannotDeleteParent = '不能删除父任务。';
$lang->task->error = new stdclass();
$lang->task->error->consumedNumber = '"本次消耗"必须为数字';
$lang->task->error->estimateNumber = '"预计剩余"必须为数字';
$lang->task->error->recordMinus = '工时不能为负数';
$lang->task->error->consumedSmall = '"已经消耗"必须大于之前消耗';
$lang->task->error->consumedThisTime = '请填写"工时"';
$lang->task->error->left = '请填写"剩余"';
@@ -207,6 +208,7 @@ $lang->task->error->skipClose = '任务:%s 不是“已完成”或“
$lang->task->error->consumed = '任务:%s工时不能小于0,忽略该任务工时的改动';
$lang->task->error->assignedTo = '当前状态的多人任务不能指派给任务团队外的成员。';
$lang->task->error->consumedEmpty = '"本次消耗"不能为空';
$lang->task->error->deadlineSmall = '"截止日期"必须大于"预计开始"';
/* Report. */
$lang->task->report = new stdclass();
+30 -7
View File
@@ -22,6 +22,11 @@ class taskModel extends model
*/
public function create($projectID)
{
if($this->post->estimate < 0)
{
dao::$errors[] = $this->lang->task->error->recordMinus;
return false;
}
$taskIdList = array();
$taskFiles = array();
$this->loadModel('file');
@@ -272,6 +277,12 @@ class taskModel extends model
/* check data. */
foreach($data as $i => $task)
{
if($task->deadline != '0000-00-00' and $task->deadline <= $task->estStarted)
{
dao::$errors['message'][] = $this->lang->task->error->deadlineSmall;
return false;
}
if($task->estimate and !preg_match("/^[0-9]+(.[0-9]{1,3})?$/", $task->estimate))
{
dao::$errors['message'][] = $this->lang->task->error->estimateNumber;
@@ -413,6 +424,7 @@ class taskModel extends model
if($parentID <= 0) return true;
$oldParentTask = $this->dao->select('*')->from(TABLE_TASK)->where('id')->eq($parentID)->fetch();
if($oldParentTask->parent != '-1') $this->dao->update(TABLE_TASK)->set('parent')->eq('-1')->where('id')->eq($parentID)->exec();
$this->computeWorkingHours($parentID);
$childrenStatus = $this->dao->select('id,status')->from(TABLE_TASK)->where('parent')->eq($parentID)->andWhere('deleted')->eq(0)->fetchPairs('status', 'status');
@@ -547,10 +559,11 @@ class taskModel extends model
*
* @param object $oldTask
* @param object $task
* @param bool $autoStatus
* @access public
* @return object|bool
*/
public function computeHours4Multiple($oldTask, $task = null, $team = array())
public function computeHours4Multiple($oldTask, $task = null, $team = array(), $autoStatus = true)
{
if(!$oldTask) return false;
@@ -603,7 +616,7 @@ class taskModel extends model
if(!empty($task))
{
if($this->post->status) return $currentTask;
if(!$autoStatus) return $currentTask;
if($currentTask->consumed == 0)
{
@@ -662,6 +675,11 @@ class taskModel extends model
public function update($taskID)
{
$oldTask = $this->dao->select('*')->from(TABLE_TASK)->where('id')->eq((int)$taskID)->fetch();
if($this->post->estimate < 0 or $this->post->left < 0 or $this->post->consumed < 0)
{
dao::$errors[] = $this->lang->task->error->recordMinus;
return false;
}
if(!empty($_POST['lastEditedDate']) and $oldTask->lastEditedDate != $this->post->lastEditedDate)
{
dao::$errors[] = $this->lang->error->editedByOther;
@@ -749,7 +767,7 @@ class taskModel extends model
if(!empty($teams))
{
foreach($teams as $member) $this->dao->insert(TABLE_TEAM)->data($member)->autoCheck()->exec();
$task = $this->computeHours4Multiple($oldTask, $task);
$task = $this->computeHours4Multiple($oldTask, $task, array(), $autoStatus = false);
if($task->status == 'wait')
{
reset($teams);
@@ -1472,6 +1490,7 @@ class taskModel extends model
$this->dao->update(TABLE_TASK)->data($task)->autoCheck()->where('id')->eq((int)$taskID)->exec();
if($oldTask->parent > 0) $this->updateParentStatus($taskID);
if($oldTask->parent == '-1') $this->dao->update(TABLE_TASK)->data($task)->autoCheck()->where('parent')->eq((int)$taskID)->exec();
if($oldTask->story) $this->loadModel('story')->setStage($oldTask->story);
if(!dao::isError()) return common::createChanges($oldTask, $task);
}
@@ -1493,6 +1512,7 @@ class taskModel extends model
}
$oldTask = $this->getById($taskID);
if($oldTask->parent == '-1') $this->config->task->activate->requiredFields = '';
$task = fixer::input('post')
->setIF(is_numeric($this->post->left), 'left', (float)$this->post->left)
->setDefault('left', 0)
@@ -1529,6 +1549,12 @@ class taskModel extends model
->exec();
if($oldTask->parent > 0) $this->updateParentStatus($taskID);
if($oldTask->parent == '-1')
{
unset($task->left);
$this->dao->update(TABLE_TASK)->data($task)->autoCheck()->where('parent')->eq((int)$taskID)->exec();
$this->computeWorkingHours($taskID);
}
if($oldTask->story) $this->loadModel('story')->setStage($oldTask->story);
if(!dao::isError()) return common::createChanges($oldTask, $task);
}
@@ -1647,7 +1673,6 @@ class taskModel extends model
->leftJoin(TABLE_TEAM)->alias('t4')->on('t4.root = t1.id')
->leftJoin(TABLE_MODULE)->alias('t5')->on('t1.module = t5.id')
->where('t1.project')->eq((int)$projectID)
->beginIF(($type == 'all' || is_array($type)) && $modules == 0)->andWhere('t1.parent')->lt(1)->fi()
->beginIF($type == 'myinvolved')
->andWhere("((t4.`account` = '{$this->app->user->account}' AND t4.`type` = 'task') OR t1.`assignedTo` = '{$this->app->user->account}' OR t1.`finishedby` = '{$this->app->user->account}')")
->fi()
@@ -2542,9 +2567,7 @@ class taskModel extends model
if($action == 'start' and !empty($task->children)) return false;
if($action == 'finish' and !empty($task->children)) return false;
if($action == 'cancel' and !empty($task->children)) return false;
if($action == 'pause' and !empty($task->children)) return false;
if($action == 'activate' and !empty($task->children)) return false;
if($action == 'assignto' and !empty($task->children)) return false;
if($action == 'close' and !empty($task->children)) return false;
if($action == 'batchcreate' and !empty($task->team)) return false;
@@ -2760,7 +2783,7 @@ class taskModel extends model
case 'actions':
if($storyChanged)
{
common::printIcon('task', 'confirmStoryChange', "taskid=$task->id", '', 'list', '', 'hiddenwin', 'btn-wide');
common::printIcon('task', 'confirmStoryChange', "taskid=$task->id", '', 'list', '', 'hiddenwin');
break;
}
+2
View File
@@ -31,6 +31,7 @@
<td class='w-p25-f'><?php echo html::select('assignedTo', $members, $task->finishedBy, "class='form-control chosen'");?></td>
<td></td>
</tr>
<?php if($task->parent != '-1'):?>
<tr>
<th><?php echo $lang->task->left;?></th>
<td>
@@ -40,6 +41,7 @@
</div>
</td>
</tr>
<?php endif;?>
<tr class='hide'>
<th><?php echo $lang->task->status;?></th>
<td><?php echo html::hidden('status', 'doing');?></td>
+17 -5
View File
@@ -217,7 +217,7 @@ class testcase extends control
if(!empty($_POST))
{
$response['result'] = 'success';
$response['message'] = '';
$response['message'] = $this->lang->saveSuccess;
$caseResult = $this->testcase->create($bugID);
if(!$caseResult or dao::isError())
@@ -320,6 +320,7 @@ class testcase extends control
/* Get the status of stories are not closed. */
$storyStatus = $this->lang->story->statusList;
unset($storyStatus['closed']);
$modules = array();
if($currentModuleID)
{
@@ -482,7 +483,15 @@ class testcase extends control
{
$case = $this->testcase->getById($caseID, $version);
if(!$case) die(js::error($this->lang->notFound) . js::locate('back'));
if($from == 'testtask') $run = $this->loadModel('testtask')->getRunByCase($taskID, $caseID);
if($from == 'testtask')
{
$run = $this->loadModel('testtask')->getRunByCase($taskID, $caseID);
$case->assignedTo = $run->assignedTo;
$case->lastRunner = $run->lastRunner;
$case->lastRunDate = $run->lastRunDate;
$case->lastRunResult = $run->lastRunResult;
$case->status = $run->status;
}
$branches = $this->session->currentProductType == 'normal' ? array() : $this->loadModel('branch')->getPairs($case->product);
$isLibCase = ($case->lib and empty($case->product));
@@ -1077,6 +1086,7 @@ class testcase extends control
if($product->type != 'normal') $this->lang->testcase->branch = $this->lang->product->branchName[$product->type];
if($_POST)
{
$this->app->loadLang('testtask');
$caseLang = $this->lang->testcase;
$caseConfig = $this->config->testcase;
@@ -1122,6 +1132,7 @@ class testcase extends control
$row->id = $caseID;
}
}
if($taskID) $caseLang->statusList = $this->lang->testtask->statusList;
$stmt = $this->dao->select('t1.*')->from(TABLE_TESTRESULT)->alias('t1')
->leftJoin(TABLE_TESTRUN)->alias('t2')->on('t1.run=t2.id')
@@ -1173,7 +1184,7 @@ class testcase extends control
$case->stepExpect = '';
$case->real = '';
$result = isset($results[$case->id]) ? $results[$case->id] : array();
$case->real = $result[0]['real'];
$case->real = empty($result) ? '' : $result[0]['real'];
if(isset($relatedSteps[$case->id]))
{
$i = $childId = 0;
@@ -1681,8 +1692,9 @@ class testcase extends control
*/
public function ajaxGetStatus($methodName, $caseID = 0)
{
$status = $this->testcase->getStatus($methodName, $caseID);
$case = $this->testcase->getByID($caseID);
$status = $this->testcase->getStatus($methodName, $case);
if($methodName == 'update') $status = zget($status, 1, '');
die($status);
}
}
+1 -1
View File
@@ -11,7 +11,7 @@ $(document).ready(function()
{
var index = id.substring(5);
var moduleID = $('#module' + index).val();
var branch = $('#branch' + index).val();
var branch = $('#branch' + index).length > 0 ? $('#branch' + index).val() : 0;
if(moduleID == 'ditto')
{
for(var i = index - 1; i >=0; i--)
+24 -23
View File
@@ -1,24 +1,25 @@
$(document).on('change', '.moduleChange', function()
$(document).on('mouseup', '[id^=story].chosen-with-drop', function()
{
var moduleID = $(this).val();
if(typeof(moduleID) == 'undefined') moduleID = 0;
var id = $(this).attr('id');
var index = id.substring(6);
link = createLink('story', 'ajaxGetProductStories', 'productID=' + productID + '&branch=' + branch + '&moduleID=' + moduleID + '&storyID='+ '' + '&onlyOption=true&status=noclosed');
$('#story' + index).load(link, function(){$(this).trigger("chosen:updated");});
})
$(document).on('change', '.storyChange', function()
{
var storyID = $(this).val();
if(typeof(storyID) == 'undefined') storyID = 0;
var link = createLink('testcase', 'ajaxGetStoryModule', 'storyID=' + storyID);
var id = $(this).attr('id');
var index = id.substring(5);
$.get(link, function(json)
{
var obj = JSON.parse(json);
$("#module" + index).val(obj.moduleID);
$('#module' + index).trigger("chosen:updated");
})
})
var select = $(this).prev('select');
var id = $(select).attr('id');
var index = id.substring(5);
var moduleID = $('#module' + index).val();
var branch = $('#branch' + index).length > 0 ? $('#branch' + index).val() : 0;
if(moduleID == 'ditto')
{
for(var i = index - 1; i >=0; i--)
{
if($('#module' + i).val() != 'ditto')
{
moduleID = $('#module' + i).val();
break;
}
}
}
var link = createLink('story', 'ajaxGetProductStories', 'productID=' + productID + '&branch=' + branch + '&moduleID=' + moduleID + '&storyID='+ ($(select).val() || '0') + '&onlyOption=true&status=noclosed&limit=0&type=null');
var $story = $('#story' + index);
if($story.data('loadLink') !== link)
{
$story.load(link, function(){$story.data('loadLink', link).trigger("chosen:updated");});
}
});
+5 -5
View File
@@ -1103,8 +1103,8 @@ class testcaseModel extends model
if(empty($desc)) continue;
$step = new stdclass();
$step->type = $data->stepType[$key][$id];
$step->desc = $desc;
$step->expect = trim($this->post->expect[$key][$id]);
$step->desc = htmlspecialchars($desc);
$step->expect = htmlspecialchars(trim($this->post->expect[$key][$id]));
$steps[] = $step;
}
@@ -1152,7 +1152,7 @@ class testcaseModel extends model
$stepData->parent = ($stepData->type == 'item') ? $parentStepID : 0;
$stepData->case = $caseID;
$stepData->version = $version;
$stepData->desc = $step['desc'];
$stepData->desc = htmlspecialchars($step['desc']);
$stepData->expect = htmlspecialchars($step['expect']);
$this->dao->insert(TABLE_CASESTEP)->data($stepData)->autoCheck()->exec();
if($stepData->type == 'group') $parentStepID = $this->dao->lastInsertID();
@@ -1189,7 +1189,7 @@ class testcaseModel extends model
$stepData->parent = ($stepData->type == 'item') ? $parentStepID : 0;
$stepData->case = $caseID;
$stepData->version = 1;
$stepData->desc = $desc;
$stepData->desc = htmlspecialchars($desc);
$stepData->expect = htmlspecialchars($this->post->expect[$key][$id]);
$this->dao->insert(TABLE_CASESTEP)->data($stepData)->autoCheck()->exec();
if($stepData->type == 'group') $parentStepID = $this->dao->lastInsertID();
@@ -1592,7 +1592,7 @@ class testcaseModel extends model
return false;
}
$status = $this->post->status;
$status = $this->post->status ? $this->post->status : $case->status;
$stepChanged = false;
$steps = array();
+1 -1
View File
@@ -132,7 +132,7 @@ js::set('suiteID', $suiteID);
$actionLink = $this->createLink('testcase', 'batchDelete', "productID=$productID");
$misc = common::hasPriv('testcase', 'batchDelete') ? "onclick=\"confirmBatchDelete('$actionLink')\"" : $class;
echo "<li>" . html::a('#', $lang->delete, '', $misc) . "</li>";
if(common::hasPriv('testcase', 'batchDelete')) echo "<li>" . html::a('#', $lang->delete, '', $misc) . "</li>";
if(common::hasPriv('testcase', 'batchCaseTypeChange'))
{
+2 -2
View File
@@ -66,7 +66,7 @@
<thead>
<tr>
<th class='w-50px'><?php echo $lang->testcase->stepID;?></th>
<th class='w-p70 text-left'><?php echo $lang->testcase->stepDesc;?></th>
<th class='w-p60 text-left'><?php echo $lang->testcase->stepDesc;?></th>
<th class='text-left'><?php echo $lang->testcase->stepExpect;?></th>
</tr>
</thead>
@@ -85,7 +85,7 @@
echo "<th class='step-id'>$stepId</th>";
echo "<td class='text-left'><div class='input-group'>";
if($step->type == 'item') echo "<span class='step-item-id'>{$stepId}.{$childId}</span>";
echo nl2br(str_replace(' ', '&nbsp;', htmlspecialchars($step->desc))) . "</td>";
echo nl2br(str_replace(' ', '&nbsp;', $step->desc)) . "</td>";
echo "<td class='text-left'>" . nl2br(str_replace(' ', '&nbsp;', $step->expect)) . "</div></td>";
echo "</tr>";
$childId ++;
+2 -7
View File
@@ -2,17 +2,12 @@
$config->testsuite = new stdclass();
$config->testsuite->create = new stdclass();
$config->testsuite->edit = new stdclass();
$config->testsuite->createlib = new stdclass();
$config->testsuite->createcase = new stdclass();
$config->testsuite->create->requiredFields = 'name';
$config->testsuite->edit->requiredFields = 'name';
$config->testsuite->createlib->requiredFields = 'name';
$config->testsuite->createcase->requiredFields = 'title,type';
$config->testsuite->create->requiredFields = 'name';
$config->testsuite->edit->requiredFields = 'name';
$config->testsuite->editor = new stdclass();
$config->testsuite->editor->create = array('id' => 'desc', 'tools' => 'simpleTools');
$config->testsuite->editor->edit = array('id' => 'desc', 'tools' => 'simpleTools');
$config->testsuite->editor->createlib = array('id' => 'desc', 'tools' => 'simpleTools');
$config->testsuite->datatable = new stdclass();
$config->testsuite->datatable->defaultField = array('id', 'pri', 'title', 'type', 'assignedTo', 'lastRunner', 'lastRunDate', 'lastRunResult', 'status', 'bugs', 'results', 'actions');
+14 -665
View File
@@ -79,7 +79,7 @@ class testsuite extends control
if(!empty($_POST))
{
$response['result'] = 'success';
$response['message'] = '';
$response['message'] = $this->lang->testsuite->successSaved;
$suiteID = $this->testsuite->create($productID);
if(dao::isError())
{
@@ -92,7 +92,6 @@ class testsuite extends control
$this->executeHooks($suiteID);
$response['locate'] = $this->createLink('testsuite', 'browse', "productID=$productID");
$response['message'] = $this->lang->testsuite->successSaved;
$this->send($response);
}
@@ -176,7 +175,7 @@ class testsuite extends control
if(!empty($_POST))
{
$response['result'] = 'success';
$response['message'] = '';
$response['message'] = $this->lang->testsuite->successSaved;
$changes = $this->testsuite->update($suiteID);
if(dao::isError())
{
@@ -186,47 +185,28 @@ class testsuite extends control
}
if($changes)
{
$objectType = $suite->type == 'library' ? 'caselib' : 'testsuite';
$actionID = $this->loadModel('action')->create($objectType, $suiteID, 'edited');
$actionID = $this->loadModel('action')->create('testsuite', $suiteID, 'edited');
$this->action->logHistory($actionID, $changes);
}
$this->executeHooks($suiteID);
$method = $suite->type == 'library' ? 'libView' : 'view';
$response['locate'] = inlink($method, "suiteID=$suiteID");
$response['message'] = $this->lang->testsuite->successSaved;
$response['locate'] = inlink('view', "suiteID=$suiteID");
$this->send($response);
}
if($suite->type == 'library')
{
/* Set lib menu. */
if($this->config->global->flow == 'onlyTest') $this->lang->menugroup->testsuite = 'caselib';
$libraries = $this->testsuite->getLibraries();
$suiteID = $this->testsuite->saveLibState($suiteID, $libraries);
$this->testsuite->setLibMenu($libraries, $suiteID);
if($suite->type == 'private' and $suite->addedBy != $this->app->user->account and !$this->app->user->admin) die(js::error($this->lang->error->accessDenied) . js::locate('back'));
$this->view->title = $libraries[$suiteID] . $this->lang->colon . $this->lang->testsuite->edit;
$this->view->position[] = html::a($this->createLink('testsuite', 'library', "libID=$suiteID"), $libraries[$suiteID]);
$this->view->position[] = $this->lang->caselib->common;
}
else
{
if($suite->type == 'private' and $suite->addedBy != $this->app->user->account and !$this->app->user->admin) die(js::error($this->lang->error->accessDenied) . js::locate('back'));
/* Get suite info. */
$this->view->products = $this->products = $this->loadModel('product')->getPairs('nocode');
$productID = $this->product->saveState($suite->product, $this->products);
/* Get suite info. */
$this->view->products = $this->products = $this->loadModel('product')->getPairs('nocode');
$productID = $this->product->saveState($suite->product, $this->products);
/* Set menu. */
$this->testsuite->setMenu($this->products, $productID);
$this->view->title = $this->products[$productID] . $this->lang->colon . $this->lang->testsuite->edit;
$this->view->position[] = html::a($this->createLink('testsuite', 'browse', "productID=$productID"), $this->products[$productID]);
$this->view->position[] = $this->lang->testsuite->common;
}
/* Set menu. */
$this->testsuite->setMenu($this->products, $productID);
$this->view->title = $this->products[$productID] . $this->lang->colon . $this->lang->testsuite->edit;
$this->view->position[] = html::a($this->createLink('testsuite', 'browse', "productID=$productID"), $this->products[$productID]);
$this->view->position[] = $this->lang->testsuite->common;
$this->view->position[] = $this->lang->testsuite->edit;
$this->view->suite = $suite;
@@ -245,7 +225,7 @@ class testsuite extends control
{
if($confirm == 'no')
{
die(js::confirm($this->lang->testsuite->libraryDelete, inlink('delete', "suiteID=$suiteID&confirm=yes")));
die(js::confirm($this->lang->testsuite->confirmDelete, inlink('delete', "suiteID=$suiteID&confirm=yes")));
}
else
{
@@ -384,635 +364,4 @@ class testsuite extends control
die(js::locate($this->createLink('testsuite', 'view', "suiteID=$suiteID")));
}
/**
* Show library case.
*
* @param int $libID
* @param string $browseType
* @param int $param
* @param string $orderBy
* @param int $recTotal
* @param int $recPerPage
* @param int $pageID
* @access public
* @return void
*/
public function library($libID = 0, $browseType = 'all', $param = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
{
/* Set browse type. */
$browseType = strtolower($browseType);
$libraries = $this->testsuite->getLibraries();
if(empty($libraries)) $this->locate(inlink('createLib'));
/* Save session. */
$this->session->set('caseList', $this->app->getURI(true));
/* Set menu. */
$libID = $this->testsuite->saveLibState($libID, $libraries);
setcookie('preCaseLibID', $libID, $this->config->cookieLife, $this->config->webRoot);
if($this->cookie->preCaseLibID != $libID)
{
$_COOKIE['libCaseModule'] = 0;
setcookie('libCaseModule', 0, 0, $this->config->webRoot);
}
if($browseType == 'bymodule') setcookie('libCaseModule', (int)$param, 0, $this->config->webRoot);
if($browseType != 'bymodule') $this->session->set('libBrowseType', $browseType);
$moduleID = ($browseType == 'bymodule') ? (int)$param : ($browseType == 'bysearch' ? 0 : ($this->cookie->libCaseModule ? $this->cookie->libCaseModule : 0));
$queryID = ($browseType == 'bysearch') ? (int)$param : 0;
/* Set lib menu. */
$this->testsuite->setLibMenu($libraries, $libID, $moduleID);
if($this->config->global->flow == 'onlyTest') $this->lang->menugroup->testsuite = 'caselib';
/* Load pager. */
$this->app->loadClass('pager', $static = true);
$pager = pager::init($recTotal, $recPerPage, $pageID);
/* Build the search form. */
$this->loadModel('testcase');
$actionURL = $this->createLink('testsuite', 'library', "libID=$libID&browseType=bySearch&queryID=myQueryID");
$this->testsuite->buildSearchForm($libID, $libraries, $queryID, $actionURL);
/* Append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
/* save session .*/
$cases = $this->testsuite->getLibCases($libID, $browseType, $queryID, $moduleID, $sort, $pager);
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'testcase', true);
$this->loadModel('datatable');
$this->loadModel('tree');
$showModule = !empty($this->config->datatable->testsuiteLibrary->showModule) ? $this->config->datatable->testsuiteLibrary->showModule : '';
$this->view->modulePairs = $showModule ? $this->tree->getModulePairs($libID, 'caselib', $showModule) : array();
$this->view->title = $this->lang->caselib->common . $this->lang->colon . $libraries[$libID];
$this->view->position[] = html::a($this->createLink('testsuite', 'library', "libID=$libID"), $libraries[$libID]);
$this->view->libID = $libID;
$this->view->libName = $libraries[$libID];
$this->view->cases = $cases;
$this->view->orderBy = $orderBy;
$this->view->users = $this->loadModel('user')->getPairs('noclosed|noletter');
$this->view->modules = $this->tree->getOptionMenu($libID, $viewType = 'caselib', $startModuleID = 0);
$this->view->moduleTree = $this->tree->getTreeMenu($libID, $viewType = 'caselib', $startModuleID = 0, array('treeModel', 'createCaseLibLink'));
$this->view->pager = $pager;
$this->view->browseType = $browseType;
$this->view->moduleID = $moduleID;
$this->view->moduleName = $moduleID ? $this->tree->getById($moduleID)->name : $this->lang->tree->all;
$this->view->param = $param;
$this->view->setShowModule = true;
$this->display();
}
/**
* Create lib
*
* @access public
* @return void
*/
public function createLib()
{
if(!empty($_POST))
{
$response['result'] = 'success';
$response['message'] = '';
$libID = $this->testsuite->createLib();
if(dao::isError())
{
$response['result'] = 'fail';
$response['message'] = dao::getError();
$this->send($response);
}
$this->loadModel('action')->create('caselib', $libID, 'opened');
$response['locate'] = $this->createLink('testsuite', 'library', "libID=$libID");
$response['message'] = $this->lang->testsuite->successSaved;
$this->send($response);
}
/* Set menu. */
$libraries = $this->testsuite->getLibraries();
$libID = $this->testsuite->saveLibState(0, $libraries);
$this->testsuite->setLibMenu($libraries, $libID);
if($this->config->global->flow == 'onlyTest') $this->lang->menugroup->testsuite = 'caselib';
$this->view->title = $this->lang->caselib->common . $this->lang->colon . $this->lang->testsuite->createLib;
$this->view->position[] = $this->lang->caselib->common;
$this->view->position[] = $this->lang->testsuite->createLib;
$this->display();
}
/**
* Create case for library.
*
* @param int $libID
* @param int $moduleID
* @access public
* @return void
*/
public function createCase($libID, $moduleID = 0, $param = 0)
{
if(!empty($_POST))
{
$this->loadModel('testcase');
$this->config->testcase->create->requiredFields = $this->config->testsuite->createcase->requiredFields;
$caseResult = $this->testcase->create($bugID = 0);
if(!$caseResult or dao::isError()) die(js::error(dao::getError()));
$caseID = $caseResult['id'];
if($caseResult['status'] == 'exists')
{
echo js::alert(sprintf($this->lang->duplicate, $this->lang->testcase->common));
die(js::locate($this->createLink('testcase', 'view', "caseID=$caseID"), 'parent'));
}
$this->loadModel('action')->create('case', $caseID, 'Opened');
/* If link from no head then reload. */
if(isonlybody()) die(js::reload('parent'));
die(js::locate($this->createLink('testsuite', 'library', "libID={$libID}&browseType=byModule&param={$_POST['module']}"), 'parent'));
}
/* Set lib menu. */
$libraries = $this->testsuite->getLibraries();
$libID = $this->testsuite->saveLibState($libID, $libraries);
$this->testsuite->setLibMenu($libraries, $libID);
if($this->config->global->flow == 'onlyTest') $this->lang->menugroup->testsuite = 'caselib';
$type = 'feature';
$stage = '';
$pri = 3;
$caseTitle = '';
$precondition = '';
$keywords = '';
$steps = array();
$this->loadModel('testcase');
if($param)
{
$testcase = $this->testcase->getById((int)$param);
$type = $testcase->type ? $testcase->type : 'feature';
$stage = $testcase->stage;
$pri = $testcase->pri;
$storyID = $testcase->story;
$caseTitle = $testcase->title;
$precondition = $testcase->precondition;
$keywords = $testcase->keywords;
$steps = $testcase->steps;
}
if(count($steps) < $this->config->testcase->defaultSteps)
{
$paddingCount = $this->config->testcase->defaultSteps - count($steps);
$step = new stdclass();
$step->type = 'item';
$step->desc = '';
$step->expect = '';
for($i = 1; $i <= $paddingCount; $i ++) $steps[] = $step;
}
$this->view->title = $libraries[$libID] . $this->lang->colon . $this->lang->testcase->create;
$this->view->position[] = html::a($this->createLink('testsuite', 'library', "libID=$libID"), $libraries[$libID]);
$this->view->position[] = $this->lang->testsuite->common;
$this->view->position[] = $this->lang->testcase->create;
foreach(explode(',', $this->config->testsuite->customCreateFields) as $field) $customFields[$field] = $this->lang->testcase->$field;
$this->view->showFields = $this->config->testsuite->custom->createFields;
$this->view->customFields = $customFields;
$this->view->libraries = $libraries;
$this->view->libID = $libID;
$this->view->currentModuleID = (int)$moduleID;
$this->view->caseTitle = $caseTitle;
$this->view->type = $type;
$this->view->stage = $stage;
$this->view->pri = $pri;
$this->view->precondition = $precondition;
$this->view->keywords = $keywords;
$this->view->steps = $steps;
$this->view->moduleOptionMenu = $this->loadModel('tree')->getOptionMenu($libID, $viewType = 'caselib', $startModuleID = 0);
$this->display();
}
/**
* Batch create case.
*
* @param int $libID
* @param int $moduleID
* @access public
* @return void
*/
public function batchCreateCase($libID, $moduleID = 0)
{
$this->loadModel('testcase');
if(!empty($_POST))
{
$caseID = $this->testsuite->batchCreateCase($libID);
if(dao::isError()) die(js::error(dao::getError()));
if(isonlybody()) die(js::closeModal('parent.parent', 'this'));
die(js::locate($this->createLink('testsuite', 'library', "libID=$libID&browseType=byModule&param=$moduleID"), 'parent'));
}
$libraries = $this->testsuite->getLibraries();
if(empty($libraries)) $this->locate(inlink('createLib'));
/* Set lib menu. */
$this->testsuite->setLibMenu($libraries, $libID);
if($this->config->global->flow == 'onlyTest') $this->lang->menugroup->testsuite = 'caselib';
$currentModuleID = (int)$moduleID;
/* Set module option menu. */
$moduleOptionMenu = $this->loadModel('tree')->getOptionMenu($libID, $viewType = 'caselib', $startModuleID = 0);
$moduleOptionMenu['ditto'] = $this->lang->testcase->ditto;
$this->view->title = $libraries[$libID] . $this->lang->colon . $this->lang->testcase->batchCreate;
$this->view->position[] = html::a($this->createLink('testsuite', 'library', "libID=$libID"), $libraries[$libID]);
$this->view->position[] = $this->lang->testcase->batchCreate;
$this->view->libID = $libID;
$this->view->moduleOptionMenu = $moduleOptionMenu;
$this->view->currentModuleID = $currentModuleID;
$this->display();
}
/**
* View library
*
* @param int $libID
* @access public
* @return void
*/
public function libView($libID)
{
$lib = $this->testsuite->getById($libID, true);
/* Set lib menu. */
$libraries = $this->testsuite->getLibraries();
$this->testsuite->setLibMenu($libraries, $libID);
if($this->config->global->flow == 'onlyTest') $this->lang->menugroup->testsuite = 'caselib';
$this->loadModel('testcase');
$this->view->title = $lib->name . $this->lang->colon . $this->lang->testsuite->view;
$this->view->position[] = html::a($this->createLink('testsuite', 'library', "libID=$libID"), $lib->name);
$this->view->position[] = $this->lang->testsuite->common;
$this->view->position[] = $this->lang->testsuite->view;
$this->view->lib = $lib;
$this->view->users = $this->loadModel('user')->getPairs('noclosed|noletter');
$this->view->actions = $this->loadModel('action')->getList('caselib', $libID);
$this->display();
}
/**
* Ajax get drop menu.
*
* @param int $libID
* @param string $module
* @param string $method
* @param string $extra
* @access public
* @return void
*/
public function ajaxGetDropMenu($libID, $module, $method, $extra = '')
{
$this->view->link = $this->testsuite->getLibLink($module, $method, $extra);
$this->view->libID = $libID;
$this->view->module = $module;
$this->view->method = $method;
$this->view->extra = $extra;
$libraries = $this->testsuite->getLibraries();
$this->view->libraries = $libraries;
$this->view->librariesPinyin = common::convert2Pinyin($libraries);
$this->display();
}
/**
* The results page of search.
*
* @param string $keywords
* @param string $module
* @param string $method
* @param mix $extra
* @access public
* @return void
*/
public function ajaxGetMatchedItems($keywords, $module, $method, $extra)
{
$libraries = $this->dao->select('*')->from(TABLE_TESTSUITE)->where('deleted')->eq(0)->andWhere('name')->like("%$keywords%")->andWhere('type')->eq('library')->orderBy('`id` desc')->fetchAll();
$this->view->link = $this->testsuite->getLibLink($module, $method, $extra);
$this->view->libraries = $libraries;
$this->view->keywords = $keywords;
$this->display();
}
/**
* Export templet.
*
* @param int $libID
* @access public
* @return void
*/
public function exportTemplet($libID)
{
$this->loadModel('testcase');
if($_POST)
{
$fields['module'] = $this->lang->testcase->module;
$fields['title'] = $this->lang->testcase->title;
$fields['precondition'] = $this->lang->testcase->precondition;
$fields['stepDesc'] = $this->lang->testcase->stepDesc;
$fields['stepExpect'] = $this->lang->testcase->stepExpect;
$fields['keywords'] = $this->lang->testcase->keywords;
$fields['pri'] = $this->lang->testcase->pri;
$fields['type'] = $this->lang->testcase->type;
$fields['stage'] = $this->lang->testcase->stage;
$fields[''] = '';
$fields['typeValue'] = $this->lang->testcase->lblTypeValue;
$fields['stageValue'] = $this->lang->testcase->lblStageValue;
$modules = $this->loadModel('tree')->getOptionMenu($libID, $viewType = 'caselib', $startModuleID = 0);
$rows = array();
$num = (int)$this->post->num;
for($i = 0; $i < $num; $i++)
{
foreach($modules as $moduleID => $module)
{
$row = new stdclass();
$row->module = $module . "(#$moduleID)";
$row->stepDesc = "1. \n2. \n3.";
$row->stepExpect = "1. \n2. \n3.";
if(empty($rows))
{
$row->typeValue = join("\n", $this->lang->testcase->typeList);
$row->stageValue = join("\n", $this->lang->testcase->stageList);
}
$rows[] = $row;
}
}
$this->post->set('fields', $fields);
$this->post->set('kind', 'testcase');
$this->post->set('rows', $rows);
$this->post->set('extraNum', $num);
$this->post->set('fileName', 'templet');
$this->fetch('file', 'export2csv', $_POST);
}
$this->display();
}
/**
* Import case csv file.
*
* @param int $libID
* @access public
* @return void
*/
public function import($libID)
{
$this->loadModel('testcase');
if($_FILES)
{
$file = $this->loadModel('file')->getUpload('file');
$file = $file[0];
$fileName = $this->file->savePath . $this->file->getSaveName($file['pathname']);
move_uploaded_file($file['tmpname'], $fileName);
$rows = $this->file->parseCSV($fileName);
$fields = $this->testcase->getImportFields($productID);
$fields = array_flip($fields);
$header = array();
foreach($rows[0] as $i => $rowValue)
{
if(empty($rowValue)) break;
$header[$i] = $rowValue;
}
unset($rows[0]);
$columnKey = array();
foreach($header as $title)
{
if(!isset($fields[$title])) continue;
$columnKey[] = $fields[$title];
}
if(count($columnKey) != count($header) or $this->post->encode != 'utf-8')
{
$fc = file_get_contents($fileName);
$encode = $this->post->encode != "utf-8" ? $this->post->encode : 'gbk';
$fc = helper::convertEncoding($fc, $encode, 'utf-8');
file_put_contents($fileName, $fc);
$rows = $this->file->parseCSV($fileName);
$columnKey = array();
$header = array();
foreach($rows[0] as $i => $rowValue)
{
if(empty($rowValue)) break;
$header[$i] = $rowValue;
}
unset($rows[0]);
foreach($header as $title)
{
if(!isset($fields[$title])) continue;
$columnKey[] = $fields[$title];
}
if(count($columnKey) != count($header)) die(js::alert($this->lang->testcase->errorEncode));
}
$this->session->set('importFile', $fileName);
die(js::locate(inlink('showImport', "libID=$libID"), 'parent.parent'));
}
$this->display();
}
/**
* Show import case.
*
* @param int $libID
* @access public
* @return void
*/
public function showImport($libID)
{
$this->loadModel('testcase');
if($_POST)
{
$this->testsuite->createFromImport($libID);
die(js::locate(inlink('library', "libID=$libID"), 'parent'));
}
$libraries = $this->testsuite->getLibraries();
if(empty($libraries)) $this->locate(inlink('createLib'));
$this->testsuite->setLibMenu($libraries, $libID);
$file = $this->session->importFile;
$caseLang = $this->lang->testcase;
$caseConfig = $this->config->testcase;
$modules = $this->loadModel('tree')->getOptionMenu($libID, $viewType = 'caselib', $startModuleID = 0);
$fields = explode(',', $caseConfig->exportFields);
foreach($fields as $key => $fieldName)
{
$fieldName = trim($fieldName);
$fields[$fieldName] = isset($caseLang->$fieldName) ? $caseLang->$fieldName : $fieldName;
unset($fields[$key]);
}
$fields = array_flip($fields);
$rows = $this->loadModel('file')->parseCSV($file);
$header = array();
foreach($rows[0] as $i => $rowValue)
{
if(empty($rowValue)) break;
$header[$i] = $rowValue;
}
unset($rows[0]);
foreach($header as $title)
{
if(!isset($fields[$title])) continue;
$columnKey[] = $fields[$title];
}
$endField = end($fields);
$caseData = array();
$stepData = array();
$stepVars = 0;
foreach($rows as $row => $data)
{
$case = new stdclass();
foreach($columnKey as $key => $field)
{
if(!isset($data[$key])) continue;
$cellValue = $data[$key];
if($field == 'module')
{
$case->$field = 0;
if(strrpos($cellValue, '(#') !== false)
{
$id = trim(substr($cellValue, strrpos($cellValue,'(#') + 2), ')');
$case->$field = $id;
}
}
elseif(in_array($field, $caseConfig->export->listFields))
{
if($field == 'stage')
{
$stages = explode("\n", $cellValue);
foreach($stages as $stage) $case->stage[] = array_search($stage, $caseLang->{$field . 'List'});
$case->stage = join(',', $case->stage);
}
else
{
$case->$field = array_search($cellValue, $caseLang->{$field . 'List'});
}
}
elseif($field != 'stepDesc' and $field != 'stepExpect')
{
$case->$field = $cellValue;
}
else
{
$steps = (array)$cellValue;
if(strpos($cellValue, "\n"))
{
$steps = explode("\n", $cellValue);
}
elseif(strpos($cellValue, "\r"))
{
$steps = explode("\r", $cellValue);
}
$stepKey = str_replace('step', '', strtolower($field));
$caseStep = array();
foreach($steps as $step)
{
$step = trim($step);
if(empty($step)) continue;
if(preg_match('/^(([0-9]+)\.[0-9]+)([.、]{1})/U', $step, $out))
{
$num = $out[1];
$parent = $out[2];
$sign = $out[3];
$signbit = $sign == '.' ? 1 : 3;
$step = trim(substr($step, strlen($num) + $signbit));
if(!empty($step)) $caseStep[$num]['content'] = $step;
$caseStep[$num]['type'] = 'item';
$caseStep[$parent]['type'] = 'group';
}
elseif(preg_match('/^([0-9]+)([.、]{1})/U', $step, $out))
{
$num = $out[1];
$sign = $out[2];
$signbit = $sign == '.' ? 1 : 3;
$step = trim(substr($step, strlen($num) + $signbit));
if(!empty($step)) $caseStep[$num]['content'] = $step;
$caseStep[$num]['type'] = 'step';
}
elseif(isset($num))
{
if(!isset($caseStep[$num]['content'])) $caseStep[$num]['content'] = '';
$caseStep[$num]['content'] .= "\n" . $step;
}
else
{
if($field == 'stepDesc')
{
$num = 1;
$caseStep[$num]['content'] = $step;
$caseStep[$num]['type'] = 'step';
}
if($field == 'stepExpect' and isset($stepData[$row]['desc']))
{
end($stepData[$row]['desc']);
$num = key($stepData[$row]['desc']);
$caseStep[$num]['content'] = $step;
}
}
}
unset($num);
unset($sign);
$stepVars += count($caseStep, COUNT_RECURSIVE) - count($caseStep);
$stepData[$row][$stepKey] = $caseStep;
}
}
$caseData[$row] = $case;
unset($case);
}
if(empty($caseData))
{
unlink($this->session->importFile);
unset($_SESSION['importFile']);
echo js::alert($this->lang->error->noData);
die(js::locate($this->createLink('testsuite', 'library', "libID=$libID")));
}
/* Judge whether the editedTasks is too large and set session. */
$countInputVars = count($caseData) * 9 + $stepVars;
$showSuhosinInfo = common::judgeSuhosinSetting($countInputVars);
if($showSuhosinInfo) $this->view->suhosinInfo = extension_loaded('suhosin') ? sprintf($this->lang->suhosinInfo, $countInputVars) : sprintf($this->lang->maxVarsInfo, $countInputVars);
$this->view->title = $this->lang->caselib->common . $this->lang->colon . $this->lang->testcase->showImport;
$this->view->position[] = $this->lang->testcase->showImport;
$this->view->modules = $modules;
$this->view->cases = $this->dao->select('id,module,stage,status,pri,type')->from(TABLE_CASE)->where('lib')->eq($libID)->andWhere('deleted')->eq(0)->andWhere('product')->eq(0)->fetchAll('id');
$this->view->caseData = $caseData;
$this->view->stepData = $stepData;
$this->view->libID = $libID;
$this->display();
}
}
-15
View File
@@ -21,11 +21,6 @@ $lang->testsuite->unlinkCase = "Unlink";
$lang->testsuite->unlinkCaseAction = "Unlink Case";
$lang->testsuite->batchUnlinkCases = "Batch Unlink Cases";
$lang->testsuite->deleted = 'Deleted';
$lang->testsuite->exportTemplet = 'Export Template';
$lang->testsuite->batchCreateCase = 'Batch Create';
$lang->testsuite->import = 'Import';
$lang->testsuite->importAction = 'Import Case';
$lang->testsuite->showImport = 'Imported Data';
$lang->testsuite->successSaved = 'Saved';
$lang->testsuite->id = 'ID';
@@ -46,7 +41,6 @@ $lang->testsuite->legendBasicInfo = 'Basic Info';
$lang->testsuite->unlinkedCases = 'Unlinked Cases';
$lang->testsuite->confirmDelete = 'Do you want to delete this test suite?';
$lang->testsuite->libraryDelete = 'Do you want to delete this library?';
$lang->testsuite->confirmUnlinkCase = 'Do you want to unlink this Case?';
$lang->testsuite->noticeNone = 'You have not created any suite yet.';
$lang->testsuite->noModule = '<div>You have no modules.</div><div>Manage it now.</div>';
@@ -57,12 +51,3 @@ $lang->testsuite->lblUnlinkCase = 'Unlink Case';
$lang->testsuite->authorList['private'] = 'Private';
$lang->testsuite->authorList['public'] = 'Public';
$lang->caselib->common = 'Case Library';
$lang->caselib->all = 'All Case Libraries';
$lang->testsuite->createLib = 'Create Case Library';
$lang->testsuite->editLib = 'Edit Case Library';
$lang->testsuite->library = 'View Cases in Library';
$lang->testsuite->createCase = 'Create Case';
$lang->testsuite->libView = 'Library Detail';
-15
View File
@@ -21,11 +21,6 @@ $lang->testsuite->unlinkCase = "移除";
$lang->testsuite->unlinkCaseAction = "移除用例";
$lang->testsuite->batchUnlinkCases = "批量移除用例";
$lang->testsuite->deleted = '已删除';
$lang->testsuite->exportTemplet = '导出模板';
$lang->testsuite->batchCreateCase = '批量创建用例';
$lang->testsuite->import = '导入';
$lang->testsuite->importAction = '导入用例';
$lang->testsuite->showImport = '显示导入数据';
$lang->testsuite->successSaved = '保存成功';
$lang->testsuite->id = '编号';
@@ -46,7 +41,6 @@ $lang->testsuite->legendBasicInfo = '基本信息';
$lang->testsuite->unlinkedCases = '未关联';
$lang->testsuite->confirmDelete = '您确认要删除该套件吗?';
$lang->testsuite->libraryDelete = '您确认要删除该用例库吗?';
$lang->testsuite->confirmUnlinkCase = '您确认要移除该用例吗?';
$lang->testsuite->noticeNone = '您还没有创建套件';
$lang->testsuite->noModule = '<div>您现在还没有模块信息</div><div>请维护用例库模块</div>';
@@ -57,12 +51,3 @@ $lang->testsuite->lblUnlinkCase = '移除用例';
$lang->testsuite->authorList['private'] = '私有';
$lang->testsuite->authorList['public'] = '公开';
$lang->caselib->common = '公共用例库';
$lang->caselib->all = '所有用例库';
$lang->testsuite->createLib = '创建用例库';
$lang->testsuite->editLib = '编辑用例库';
$lang->testsuite->library = '浏览库用例';
$lang->testsuite->createCase = '创建用例';
$lang->testsuite->libView = '查看库概况';
+1 -573
View File
@@ -99,140 +99,6 @@ class testsuiteModel extends model
return $output;
}
/**
* Set library menu.
*
* @param array $libraries
* @param int $libID
* @access public
* @return void
*/
public function setLibMenu($libraries, $libID, $moduleID = 0)
{
$currentLibName = zget($libraries, $libID, '');
$isMobile = $this->app->viewType == 'mhtml';
$selectHtml = '';
if(!empty($libraries))
{
if($isMobile)
{
$selectHtml = "<a id='currentItem' href=\"javascript:showSearchMenu('testsuite', '$libID', 'testsuite', 'library', '')\">{$currentLibName} <span class='icon-caret-down'></span></a><div id='currentItemDropMenu' class='hidden affix enter-from-bottom layer'></div>";
}
else
{
$dropMenuLink = helper::createLink('testsuite', 'ajaxGetDropMenu', "objectID=$libID&module=testsuite&method=library");
$selectHtml = "<div class='btn-group angle-btn'><div class='btn-group'><button data-toggle='dropdown' type='button' class='btn btn-limit' id='currentItem'>{$currentLibName} <span class='caret'></span></button><div id='dropMenu' class='dropdown-menu search-list' data-ride='searchList' data-url='$dropMenuLink'>";
$selectHtml .= '<div class="input-control search-box has-icon-left has-icon-right search-example"><input type="search" class="form-control search-input" /><label class="input-control-icon-left search-icon"><i class="icon icon-search"></i></label><a class="input-control-icon-right search-clear-btn"><i class="icon icon-close icon-sm"></i></a></div>';
$selectHtml .= "</div></div></div>";
}
}
if($this->config->global->flow == 'onlyTest')
{
$modules = $this->loadModel('tree')->getModulePairs($libID, 'caselib');
$moduleName = ($moduleID && isset($modules[$moduleID])) ? $modules[$moduleID] : $this->lang->tree->all;
if(!$isMobile)
{
$dropMenuLink = helper::createLink('tree', 'ajaxGetDropMenu', "objectID=$libID&module=testsuite&method=library");
$selectHtml .= "<div class='btn-group'><button id='currentModule' data-toggle='dropdown' type='button' class='btn btn-limit'>{$moduleName} <span class='caret'></span></button><div id='dropMenu' class='dropdown-menu search-list' data-ride='searchList' data-url='$dropMenuLink'>";
$selectHtml .= '<div class="input-control search-box has-icon-left has-icon-right search-example"><input type="search" class="form-control search-input" /><label class="input-control-icon-left search-icon"><i class="icon icon-search"></i></label><a class="input-control-icon-right search-clear-btn"><i class="icon icon-close icon-sm"></i></a></div>';
$selectHtml .= "</div></div>";
}
else
{
$selectHtml .= "<a id='currentModule' href=\"javascript:showSearchMenu('tree', '$libID', 'testsuite', 'library', '')\">{$moduleName} <span class='icon-caret-down'></span></a><div id='currentBranchDropMenu' class='hidden affix enter-from-bottom layer'></div>";
}
}
setCookie("lastCaseLib", $libID, $this->config->cookieLife, $this->config->webRoot);
$pageNav = '';
$pageActions = '';
$isMobile = $this->app->viewType == 'mhtml';
if($isMobile)
{
$this->app->loadLang('qa');
$pageNav = html::a(helper::createLink('qa', 'index'), $this->lang->qa->index) . $this->lang->colon;
}
else
{
if($this->config->global->flow == 'full')
{
$this->app->loadLang('qa');
$pageNav .= '<div class="btn-group angle-btn"><div class="btn-group"><button data-toggle="dropdown" type="button" class="btn">' . $this->lang->qa->index . ' <span class="caret"></span></button>';
$pageNav .= '<ul class="dropdown-menu">';
if(common::hasPriv('testsuite', 'createLib')) $pageNav .= '<li>' . html::a(helper::createLink('testsuite', 'createLib'), '<i class="icon icon-plus"></i> ' . $this->lang->testsuite->createLib) . '</li>';
$pageNav .= '</ul></div></div>';
}
else
{
$this->app->loadLang('testcase');
$pageActions .= "<div class='btn-group'>";
if(common::hasPriv('testsuite', 'exportTemplet'))
{
$link = helper::createLink('testsuite', 'exportTemplet', "libID=$libID");
$pageActions .= html::a($link, "<i class='icon icon-export muted'> </i>" . $this->lang->testsuite->exportTemplet, '', "class='btn btn-link export'");
}
if(common::hasPriv('testsuite', 'import'))
{
$link = helper::createLink('testsuite', 'import', "libID=$libID");
$pageActions .= html::a($link, "<i class='icon muted icon-import'> </i>" . $this->lang->testcase->importFile, '', "class='btn btn-link export'");
}
$pageActions .= '</div>';
$params = "libID=$libID&moduleID=" . (isset($moduleID) ? $moduleID : 0);
if(common::hasPriv('testsuite', 'batchCreateCase'))
{
$link = helper::createLink('testsuite', 'batchCreateCase', $params);
$pageActions .= html::a($link, "<i class='icon-plus'></i>" . $this->lang->testcase->batchCreate, '', "class='btn btn-secondary'");
}
if(common::hasPriv('testsuite', 'createCase'))
{
$link = helper::createLink('testsuite', 'createCase', $params);
$pageActions .= html::a($link, "<i class='icon-plus'></i>" . $this->lang->testcase->create, '', "class='btn btn-primary'");
}
if(common::hasPriv('testsuite', 'createLib'))
{
$link = helper::createLink('testsuite', 'createLib');
$pageActions .= html::a($link, "<i class='icon-plus'></i>" . $this->lang->testsuite->createLib, '', "class='btn btn-primary'");
}
}
}
$pageNav .= $selectHtml;
$this->lang->modulePageNav = $pageNav;
$this->lang->modulePageActions = $pageActions;
foreach($this->lang->caselib->menu as $key => $value)
{
$replace = '';
if($this->config->global->flow == 'onlyTest') $replace = $libID;
common::setMenuVars($this->lang->caselib->menu, $key, $replace);
}
$this->lang->testsuite->menu = $this->lang->caselib->menu;
if($this->config->global->flow != 'full' && $this->app->getMethodName() != 'libview') $this->lang->testsuite->menu->bysearch = "<a class='querybox-toggle' id='bysearchTab'><i class='icon icon-search muted'> </i>{$this->lang->testcase->bySearch}</a>";
}
/**
* Save lib state.
*
* @param int $libID
* @param array $libraries
* @access public
* @return int
*/
public function saveLibState($libID = 0, $libraries = array())
{
if($libID > 0) $this->session->set('caseLib', (int)$libID);
if($libID == 0 and $this->cookie->lastCaseLib) $this->session->set('caseLib', $this->cookie->lastCaseLib);
if($libID == 0 and $this->session->caseLib == '') $this->session->set('caseLib', key($libraries));
if(!isset($libraries[$this->session->caseLib]))
{
$this->session->set('caseLib', key($libraries));
$libID = $this->session->caseLib;
}
return $this->session->caseLib;
}
/**
* Create a test suite.
*
@@ -424,130 +290,11 @@ class testsuiteModel extends model
*/
public function delete($suiteID, $table = '')
{
$suite = $this->getById($suiteID);
parent::delete(TABLE_TESTSUITE, $suiteID);
if($suite->type == 'library')
{
$this->dao->update(TABLE_ACTION)->set('objectType')->eq('caselib')->where('objectID')->eq($suiteID)->andWhere('objectType')->eq('testsuite')->exec();
}
else
{
$this->dao->delete()->from(TABLE_SUITECASE)->where('suite')->eq($suiteID)->exec();
}
$this->dao->delete()->from(TABLE_SUITECASE)->where('suite')->eq($suiteID)->exec();
return !dao::isError();
}
/**
* Get libraries.
*
* @access public
* @return array
*/
public function getLibraries()
{
return $this->dao->select("id,name")->from(TABLE_TESTSUITE)
->where('product')->eq(0)
->andWhere('deleted')->eq(0)
->andWhere('type')->eq('library')
->orderBy('id_desc')
->fetchPairs('id', 'name');
}
/**
* Create lib.
*
* @access public
* @return int
*/
public function createLib()
{
$lib = fixer::input('post')
->stripTags($this->config->testsuite->editor->create['id'], $this->config->allowedTags)
->setForce('type', 'library')
->add('addedBy', $this->app->user->account)
->add('addedDate', helper::now())
->remove('uid')
->get();
$lib = $this->loadModel('file')->processImgURL($lib, $this->config->testsuite->editor->create['id'], $this->post->uid);
$this->dao->insert(TABLE_TESTSUITE)->data($lib)
->batchcheck($this->config->testsuite->createlib->requiredFields, 'notempty')
->check('name', 'unique', "deleted = '0'")
->exec();
if(!dao::isError())
{
$libID = $this->dao->lastInsertID();
$this->file->updateObjectID($this->post->uid, $libID, 'caselib');
return $libID;
}
return false;
}
/**
* Get lib cases.
*
* @param int $libID
* @param string $browseType
* @param int $queryID
* @param int $moduleID
* @param string $sort
* @param object $pager
* @access public
* @return array
*/
public function getLibCases($libID, $browseType, $queryID = 0, $moduleID = 0, $sort = 'id_desc', $pager = null)
{
$moduleIdList = $moduleID ? $this->loadModel('tree')->getAllChildId($moduleID) : '0';
$browseType = ($browseType == 'bymodule' and $this->session->libBrowseType and $this->session->libBrowseType != 'bysearch') ? $this->session->libBrowseType : $browseType;
$cases = array();
if($browseType == 'bymodule' or $browseType == 'all' or $browseType == 'wait')
{
$cases = $this->dao->select('*')->from(TABLE_CASE)
->where('lib')->eq((int)$libID)
->andWhere('product')->eq(0)
->beginIF($moduleIdList)->andWhere('module')->in($moduleIdList)->fi()
->beginIF($browseType == 'wait')->andWhere('status')->eq($browseType)->fi()
->andWhere('deleted')->eq('0')
->orderBy($sort)->page($pager)->fetchAll('id');
}
/* By search. */
elseif($browseType == 'bysearch')
{
if($queryID)
{
$query = $this->loadModel('search')->getQuery($queryID);
$this->session->set('caselibQuery', ' 1 = 1');
if($query)
{
$this->session->set('caselibQuery', $query->sql);
$this->session->set('caselibForm', $query->form);
}
}
else
{
if($this->session->caselibQuery == false) $this->session->set('caselibQuery', ' 1 = 1');
}
$queryLibID = $libID;
$allLib = "`lib` = 'all'";
$caseQuery = '(' . $this->session->caselibQuery;
if(strpos($this->session->caselibQuery, $allLib) !== false)
{
$caseQuery = str_replace($allLib, '1', $caseQuery);
$queryLibID = 'all';
}
$caseQuery .= ')';
$cases = $this->dao->select('*')->from(TABLE_CASE)->where($caseQuery)
->beginIF($queryLibID != 'all')->andWhere('lib')->eq((int)$libID)->fi()
->andWhere('product')->eq(0)
->andWhere('deleted')->eq(0)
->orderBy($sort)->page($pager)->fetchAll();
}
return $cases;
}
/**
* Get not imported cases.
*
@@ -601,323 +348,4 @@ class testsuiteModel extends model
->page($pager)
->fetchAll('id');
}
/**
* Build search form.
*
* @param int $libID
* @param array $libraries
* @param int $queryID
* @param string $actionURL
* @access public
* @return void
*/
public function buildSearchForm($libID, $libraries, $queryID, $actionURL)
{
$this->config->testcase->search['fields']['lib'] = $this->lang->testcase->lib;
$this->config->testcase->search['params']['lib']['values'] = array('' => '', $libID => $libraries[$libID], 'all' => $this->lang->caselib->all);
$this->config->testcase->search['params']['lib']['operator'] = '=';
$this->config->testcase->search['params']['lib']['control'] = 'select';
$this->config->testcase->search['params']['module']['values'] = $this->loadModel('tree')->getOptionMenu($libID, $viewType = 'caselib');
if(!$this->config->testcase->needReview) unset($this->config->testcase->search['params']['status']['values']['wait']);
unset($this->config->testcase->search['fields']['product']);
unset($this->config->testcase->search['params']['product']);
unset($this->config->testcase->search['fields']['branch']);
unset($this->config->testcase->search['params']['branch']);
unset($this->config->testcase->search['fields']['lastRunner']);
unset($this->config->testcase->search['params']['lastRunner']);
unset($this->config->testcase->search['fields']['lastRunResult']);
unset($this->config->testcase->search['params']['lastRunResult']);
unset($this->config->testcase->search['fields']['lastRunDate']);
unset($this->config->testcase->search['params']['lastRunDate']);
$this->config->testcase->search['module'] = 'caselib';
$this->config->testcase->search['actionURL'] = $actionURL;
$this->config->testcase->search['queryID'] = $queryID;
$this->loadModel('search')->setSearchParams($this->config->testcase->search);
}
/**
* Get lib link.
*
* @param string $module
* @param string $method
* @param string $extra
* @access public
* @return string
*/
public function getLibLink($module, $method, $extra)
{
$link = '';
if($module == 'testsuite')
{
if($module == 'testsuite' && ($method == 'createlib'))
{
$link = helper::createLink($module, 'library', "libID=%s");
}
else
{
$link = helper::createLink($module, $method, "libID=%s");
}
}
else if($module == 'tree')
{
$link = helper::createLink($module, $method, "libID=%s&type=caselib&currentModuleID=0");
}
else
{
$link = helper::createLink('testsuite', 'library', "libID=%s");
}
return $link;
}
/**
* Create from import.
*
* @param int $libID
* @access public
* @return void
*/
public function createFromImport($libID)
{
$this->loadModel('action');
$this->loadModel('testcase');
$this->loadModel('file');
$now = helper::now();
$data = fixer::input('post')->get();
if(!empty($_POST['id']))
{
$oldSteps = $this->dao->select('t2.*')->from(TABLE_CASE)->alias('t1')
->leftJoin(TABLE_CASESTEP)->alias('t2')->on('t1.id = t2.case')
->where('t1.id')->in(($_POST['id']))
->andWhere('t1.version=t2.version')
->orderBy('t2.id')
->fetchGroup('case');
$oldCases = $this->dao->select('*')->from(TABLE_CASE)->where('id')->in($_POST['id'])->fetchAll('id');
}
$cases = array();
foreach($data->lib as $key => $lib)
{
$caseData = new stdclass();
$caseData->lib = $lib;
$caseData->module = $data->module[$key];
$caseData->title = $data->title[$key];
$caseData->pri = (int)$data->pri[$key];
$caseData->type = $data->type[$key];
$caseData->status = $data->status[$key];
$caseData->stage = join(',', $data->stage[$key]);
$caseData->keywords = $data->keywords[$key];
$caseData->frequency = 1;
$caseData->precondition = $data->precondition[$key];
if(isset($this->config->testcase->create->requiredFields))
{
$requiredFields = explode(',', $this->config->testcase->create->requiredFields);
foreach($requiredFields as $requiredField)
{
$requiredField = trim($requiredField);
if(empty($caseData->$requiredField)) dao::$errors[] = sprintf($this->lang->testcase->noRequire, $key, $this->lang->testcase->$requiredField);
}
}
$cases[$key] = $caseData;
}
if(dao::isError()) die(js::error(dao::getError()));
$forceNotReview = $this->testcase->forceNotReview();
foreach($cases as $key => $caseData)
{
if(!empty($_POST['id'][$key]) and empty($_POST['insert']))
{
$caseID = $data->id[$key];
$stepChanged = false;
$steps = array();
$oldStep = isset($oldSteps[$caseID]) ? $oldSteps[$caseID] : array();
$oldCase = $oldCases[$caseID];
/* Remove the empty setps in post. */
$steps = array();
if(isset($_POST['desc'][$key]))
{
foreach($data->desc[$key] as $id => $desc)
{
$desc = trim($desc);
if(empty($desc)) continue;
$step = new stdclass();
$step->type = $data->stepType[$key][$id];
$step->desc = $desc;
$step->expect = trim($data->expect[$key][$id]);
$steps[] = $step;
}
}
/* If step count changed, case changed. */
if((!$oldStep != !$steps) or (count($oldStep) != count($steps)))
{
$stepChanged = true;
}
else
{
/* Compare every step. */
foreach($oldStep as $id => $oldStep)
{
if(trim($oldStep->desc) != trim($steps[$id]->desc) or trim($oldStep->expect) != $steps[$id]->expect)
{
$stepChanged = true;
break;
}
}
}
$version = $stepChanged ? $oldCase->version + 1 : $oldCase->version;
$caseData->version = $version;
$changes = common::createChanges($oldCase, $caseData);
if(!$changes and !$stepChanged) continue;
if($changes or $stepChanged)
{
$caseData->lastEditedBy = $this->app->user->account;
$caseData->lastEditedDate = $now;
if($stepChanged and !$forceNotReview) $caseData->status = 'wait';
$this->dao->update(TABLE_CASE)->data($caseData)->where('id')->eq($caseID)->autoCheck()->exec();
if($stepChanged)
{
$parentStepID = 0;
foreach($steps as $id => $step)
{
$step = (array)$step;
if(empty($step['desc'])) continue;
$stepData = new stdclass();
$stepData->type = ($step['type'] == 'item' and $parentStepID == 0) ? 'step' : $step['type'];
$stepData->parent = ($stepData->type == 'item') ? $parentStepID : 0;
$stepData->case = $caseID;
$stepData->version = $version;
$stepData->desc = $step['desc'];
$stepData->expect = $step['expect'];
$this->dao->insert(TABLE_CASESTEP)->data($stepData)->autoCheck()->exec();
if($stepData->type == 'group') $parentStepID = $this->dao->lastInsertID();
if($stepData->type == 'step') $parentStepID = 0;
}
}
$oldCase->steps = $this->testcase->joinStep($oldStep);
$caseData->steps = $this->testcase->joinStep($steps);
$changes = common::createChanges($oldCase, $caseData);
$actionID = $this->action->create('case', $caseID, 'Edited');
$this->action->logHistory($actionID, $changes);
}
}
else
{
$caseData->version = 1;
$caseData->openedBy = $this->app->user->account;
$caseData->openedDate = $now;
$caseData->status = $forceNotReview ? 'normal' : 'wait';
$this->dao->insert(TABLE_CASE)->data($caseData)->autoCheck()->exec();
if(!dao::isError())
{
$caseID = $this->dao->lastInsertID();
$parentStepID = 0;
foreach($data->desc[$key] as $id => $desc)
{
$desc = trim($desc);
if(empty($desc)) continue;
$stepData = new stdclass();
$stepData->type = ($data->stepType[$key][$id] == 'item' and $parentStepID == 0) ? 'step' : $data->stepType[$key][$id];
$stepData->parent = ($stepData->type == 'item') ? $parentStepID : 0;
$stepData->case = $caseID;
$stepData->version = 1;
$stepData->desc = $desc;
$stepData->expect = $data->expect[$key][$id];
$this->dao->insert(TABLE_CASESTEP)->data($stepData)->autoCheck()->exec();
if($stepData->type == 'group') $parentStepID = $this->dao->lastInsertID();
if($stepData->type == 'step') $parentStepID = 0;
}
$this->action->create('case', $caseID, 'Opened');
}
}
}
unlink($this->session->importFile);
unset($_SESSION['importFile']);
}
/**
* Batch create case for lib.
*
* @param int $libID
* @access public
* @return void
*/
public function batchCreateCase($libID)
{
$this->loadModel('testcase');
$this->loadModel('action');
$now = helper::now();
$cases = fixer::input('post')->get();
$batchNum = count(reset($cases));
$result = $this->loadModel('common')->removeDuplicate('case', $cases, "lib={$libID}");
$cases = $result['data'];
for($i = 0; $i < $batchNum; $i++)
{
if(!empty($cases->title[$i]) and empty($cases->type[$i])) die(js::alert(sprintf($this->lang->error->notempty, $this->lang->testcase->type)));
}
$module = 0;
$type = '';
$pri = 3;
for($i = 0; $i < $batchNum; $i++)
{
$module = $cases->module[$i] == 'ditto' ? $module : $cases->module[$i];
$type = $cases->type[$i] == 'ditto' ? $type : $cases->type[$i];
$pri = $cases->pri[$i] == 'ditto' ? $pri : $cases->pri[$i];
$cases->module[$i] = (int)$module;
$cases->type[$i] = $type;
$cases->pri[$i] = $pri;
}
$forceNotReview = $this->testcase->forceNotReview();
for($i = 0; $i < $batchNum; $i++)
{
if($cases->type[$i] != '' and $cases->title[$i] != '')
{
$data[$i] = new stdclass();
$data[$i]->lib = $libID;
$data[$i]->module = $cases->module[$i];
$data[$i]->type = $cases->type[$i];
$data[$i]->pri = $cases->pri[$i];
$data[$i]->stage = empty($cases->stage[$i]) ? '' : implode(',', $cases->stage[$i]);
$data[$i]->color = $cases->color[$i];
$data[$i]->title = $cases->title[$i];
$data[$i]->precondition = $cases->precondition[$i];
$data[$i]->keywords = $cases->keywords[$i];
$data[$i]->openedBy = $this->app->user->account;
$data[$i]->openedDate = $now;
$data[$i]->status = $forceNotReview ? 'normal' : 'wait';
$data[$i]->version = 1;
$this->dao->insert(TABLE_CASE)->data($data[$i])
->autoCheck()
->batchCheck($this->config->testcase->create->requiredFields, 'notempty')
->exec();
if(dao::isError())
{
echo js::error(dao::getError());
die(js::reload('parent'));
}
$caseID = $this->dao->lastInsertID();
$actionID = $this->action->create('case', $caseID, 'Opened');
}
}
}
}
+5 -4
View File
@@ -289,6 +289,7 @@ class testtask extends control
$this->config->testcase->search['module'] = 'testtask';
$this->config->testcase->search['params']['product']['values'] = array($productID => $this->products[$productID], 'all' => $this->lang->testcase->allProduct);
$this->config->testcase->search['params']['module']['values'] = $this->loadModel('tree')->getOptionMenu($productID, $viewType = 'case');
$this->config->testcase->search['params']['status']['values'] = array('' => '') + $this->lang->testtask->statusList;
$this->config->testcase->search['queryID'] = $queryID;
$this->config->testcase->search['fields']['assignedTo'] = $this->lang->testtask->assignedTo;
@@ -505,7 +506,7 @@ class testtask extends control
if($this->post->comment != '' or !empty($changes))
{
$actionID = $this->action->create('testtask', $taskID, 'Started', $this->post->comment);
$actionID = $this->loadModel('action')->create('testtask', $taskID, 'Started', $this->post->comment);
$this->action->logHistory($actionID, $changes);
}
@@ -547,7 +548,7 @@ class testtask extends control
if($this->post->comment != '' or !empty($changes))
{
$actionID = $this->action->create('testtask', $taskID, 'Activated', $this->post->comment);
$actionID = $this->loadModel('action')->create('testtask', $taskID, 'Activated', $this->post->comment);
$this->action->logHistory($actionID, $changes);
}
@@ -589,7 +590,7 @@ class testtask extends control
if($this->post->comment != '' or !empty($changes))
{
$actionID = $this->action->create('testtask', $taskID, 'Closed', $this->post->comment);
$actionID = $this->loadModel('action')->create('testtask', $taskID, 'Closed', $this->post->comment);
$this->action->logHistory($actionID, $changes);
}
@@ -632,7 +633,7 @@ class testtask extends control
if($this->post->comment != '' or !empty($changes))
{
$actionID = $this->action->create('testtask', $taskID, 'Blocked', $this->post->comment);
$actionID = $this->loadModel('action')->create('testtask', $taskID, 'Blocked', $this->post->comment);
$this->action->logHistory($actionID, $changes);
}
+8 -7
View File
@@ -574,8 +574,8 @@ class testtaskModel extends model
{
$datas = $this->dao->select('lastRunner AS name, COUNT(*) AS value')->from(TABLE_TESTRUN)->where('task')->eq($taskID)->groupBy('name')->orderBy('value DESC')->fetchAll('name');
if(!$datas) return array();
foreach($datas as $result => $data) $data->name = $result ? $result : $this->lang->testtask->unexecuted;
$users = $this->loadModel('user')->getPairs('noclosed|noletter');
foreach($datas as $result => $data) $data->name = $result ? zget($users, $result, $result) : $this->lang->testtask->unexecuted;
return $datas;
}
@@ -764,7 +764,7 @@ class testtaskModel extends model
{
$orderBy = (strpos($orderBy, 'assignedTo') !== false or strpos($orderBy, 'lastRunResult') !== false) ? ('t1.' . $orderBy) : ('t2.' . $orderBy);
return $this->dao->select('t2.*,t1.*,t2.version as caseVersion,t3.title as storyTitle')->from(TABLE_TESTRUN)->alias('t1')
return $this->dao->select('t2.*,t1.*,t2.version as caseVersion,t3.title as storyTitle,t2.status as caseStatus')->from(TABLE_TESTRUN)->alias('t1')
->leftJoin(TABLE_CASE)->alias('t2')->on('t1.case = t2.id')
->leftJoin(TABLE_STORY)->alias('t3')->on('t2.story = t3.id')
->where('t1.task')->eq((int)$taskID)
@@ -788,7 +788,7 @@ class testtaskModel extends model
{
$orderBy = strpos($orderBy, 'assignedTo') !== false ? ('t1.' . $orderBy) : ('t2.' . $orderBy);
return $this->dao->select('t2.*,t1.*,t2.version as caseVersion,t3.title as storyTitle')->from(TABLE_TESTRUN)->alias('t1')
return $this->dao->select('t2.*,t1.*,t2.version as caseVersion,t3.title as storyTitle,t2.status as caseStatus')->from(TABLE_TESTRUN)->alias('t1')
->leftJoin(TABLE_CASE)->alias('t2')->on('t1.case = t2.id')
->leftJoin(TABLE_STORY)->alias('t3')->on('t2.story = t3.id')
->where('t1.task')->eq((int)$taskID)
@@ -852,9 +852,10 @@ class testtaskModel extends model
}
$caseQuery = preg_replace('/`(\w+)`/', 't2.`$1`', $caseQuery);
$caseQuery = str_replace(array('t2.`assignedTo`', 't2.`lastRunner`', 't2.`lastRunDate`', 't2.`lastRunResult`'), array('t1.`assignedTo`', 't1.`lastRunner`', 't1.`lastRunDate`', 't1.`lastRunResult`'), $caseQuery);
$runs = $this->dao->select('t2.*,t1.*, t2.version as caseVersion')->from(TABLE_TESTRUN)->alias('t1')
$caseQuery = str_replace(array('t2.`assignedTo`', 't2.`lastRunner`', 't2.`lastRunDate`', 't2.`lastRunResult`', 't2.`status`'), array('t1.`assignedTo`', 't1.`lastRunner`', 't1.`lastRunDate`', 't1.`lastRunResult`', 't1.`status`'), $caseQuery);
$runs = $this->dao->select('t2.*,t1.*, t2.version as caseVersion,t3.title as storyTitle,t2.status as caseStatus')->from(TABLE_TESTRUN)->alias('t1')
->leftJoin(TABLE_CASE)->alias('t2')->on('t1.case = t2.id')
->leftJoin(TABLE_STORY)->alias('t3')->on('t2.story = t3.id')
->where($caseQuery)
->andWhere('t1.task')->eq($task->id)
->andWhere('t2.deleted')->eq(0)
@@ -1159,7 +1160,7 @@ class testtaskModel extends model
if($action == 'block') return ($testtask->status == 'doing' || $testtask->status == 'wait');
if($action == 'activate') return ($testtask->status == 'blocked' || $testtask->status == 'done');
if($action == 'close') return $testtask->status != 'done';
if($action == 'runcase') return $testtask->status != 'wait';
if($action == 'runcase') return isset($testtask->caseStatus) ? $testtask->caseStatus != 'wait' : $testtask->status != 'wait';
return true;
}
+1 -1
View File
@@ -142,7 +142,7 @@ class todo extends control
$actionID = $this->loadModel('action')->create('todo', $todoID, 'edited');
$this->action->logHistory($actionID, $changes);
}
die(js::locate(inlink('view', "todoID=$todoID"), 'parent'));
die(js::locate($this->session->todoList, 'parent'));
}
/* Judge a private todo or not, If private, die. */
+1 -1
View File
@@ -20,7 +20,7 @@
<div class="modal-header">
<h4 class='modal-title pull-left'><?php echo html::a($this->createLink('todo', 'view', 'todo=' . $todo->id), "TODO #{$todo->id} {$todo->name}");?></h4>
</div>
<form class='modal-body form-horizontal' method='post' target='hiddenwin' id='dataform'>
<form class='modal-body form-horizontal' method='post' id='dataform'>
<div class="row form-group">
<label class="col-sm-1"><?php echo $lang->todo->date;?></label>
<div class="col-sm-10">
+7 -7
View File
@@ -54,8 +54,8 @@ class tree extends control
}
elseif(strpos($viewType, 'caselib') !== false)
{
$this->loadModel('testsuite');
$lib = $this->testsuite->getById($rootID);
$this->loadModel('caselib');
$lib = $this->caselib->getById($rootID);
$this->view->root = $lib;
}
@@ -116,13 +116,13 @@ class tree extends control
}
elseif($viewType == 'caselib')
{
$this->testsuite->setLibMenu($this->testsuite->getLibraries(), $rootID);
$this->lang->tree->menu = $this->lang->testsuite->menu;
$this->lang->tree->menuOrder = $this->lang->testsuite->menuOrder;
$this->caselib->setLibMenu($this->caselib->getLibraries(), $rootID);
$this->lang->tree->menu = $this->lang->caselib->menu;
$this->lang->tree->menuOrder = $this->lang->caselib->menuOrder;
$this->lang->set('menugroup.tree', 'qa');
$title = $this->lang->tree->manageCaseLib;
$position[] = html::a($this->createLink('testsuite', 'library', "libID=$rootID"), $lib->name);
$position[] = html::a($this->createLink('caselib', 'browse', "libID=$rootID"), $lib->name);
$position[] = $this->lang->tree->manageCaseLib;
}
elseif(strpos($viewType, 'doc') !== false)
@@ -438,9 +438,9 @@ class tree extends control
$this->view->method = $method;
$this->view->extra = $extra;
$viewType = $module;
if($module == 'bug') $viewType = 'bug';
if($module == 'testcase') $viewType = 'case';
if($module == 'testsuite') $viewType = 'caselib';
$modules = $this->tree->getOptionMenu($rootID, $viewType);
$modulesPinyin = common::convert2Pinyin($modules);
-1
View File
@@ -1 +0,0 @@
body{background:white; overflow:none}
+1 -1
View File
@@ -1 +1 @@
.thWidth{width:80px !important;}
.thWidth{width:90px !important;}
+1 -1
View File
@@ -1 +1 @@
.thWidth{width:80px !important;}
.thWidth{width:90px !important;}
+1
View File
@@ -39,6 +39,7 @@ $lang->tree->addChild = "增加子模块";
$lang->tree->confirmDelete = '该模块及其子模块都会被删除,您确定删除吗?';
$lang->tree->confirmDeleteLine = "您确定删除该{$lang->productCommon}线吗?";
$lang->tree->confirmRoot = "模块的所属{$lang->productCommon}修改,会关联修改该模块下的需求、Bug、用例的所属{$lang->productCommon},以及{$lang->projectCommon}和{$lang->productCommon}的关联关系。该操作比较危险,请谨慎操作。是否确认修改?";
$lang->tree->confirmRoot4Doc = "模块的所属文档库修改,会关联修改该模块下的文档的关联关系。该操作比较危险,请谨慎操作。是否确认修改?";
$lang->tree->successSave = '成功保存';
$lang->tree->successFixed = '成功修正数据!';
$lang->tree->repeatName = '模块名“%s”已经存在!';
+2
View File
@@ -248,6 +248,8 @@ class treeModel extends model
{
$parentModules = explode(',', trim($module->path, ','));
if($type == 'product' and isset($noProductModules[$parentModules[0]])) continue;
/* Fix bug #2007. */
if($type == 'product' and $module->type == 'task' and !isset($modules[$parentModules[0]])) continue;
$rootName = ($productNum > 1 and $type == 'product') ? "/$rootModule/" : '/';
if($type == 'product' and $module->branch and isset($branchGroups[$id][$module->branch])) $rootName .= $branchGroups[$id][$module->branch] . '/';
$this->buildTreeArray($treeMenu, $modules, $module, $rootName);
-1
View File
@@ -14,7 +14,6 @@
<?php if($viewType != 'story'):?>
<style>
li.tree-item-story > .tree-actions .tree-action[data-type=sort]{display:none;}
li.tree-item-story > .tree-actions .tree-action[data-type=edit]{display:none;}
li.tree-item-story > .tree-actions .tree-action[data-type=delete]{display:none;}
</style>
<?php endif;?>
+18 -15
View File
@@ -34,7 +34,7 @@ if(isset($pageCSS)) css::internal($pageCSS);
<?php if($type == 'doc'):?>
<tr>
<th class='thWidth'><?php echo $lang->doc->lib;?></th>
<td><?php echo html::select('root', $libs, $module->root, "class='form-control chosen' onchange=loadDocModule(this.value)");?></td>
<td><?php echo html::select('root', $libs, $module->root, "class='form-control chosen'");?></td>
</tr>
<?php endif;?>
<?php if($module->type != 'line'):?>
@@ -81,20 +81,7 @@ function getProductModules(productID)
$('#parent').trigger('chosen:updated')
}, 'json');
}
$(function()
{
if(type == 'doc') return;
$('#root').change(function()
{
if($(this).val() == currentRoot) return true;
if(!confirm('<?php echo $lang->tree->confirmRoot?>'))
{
$('#root').val(currentRoot);
$('#root').trigger('chosen:updated');
}
getProductModules($(this).val());
})
})
function loadDocModule(libID)
{
var link = createLink('doc', 'ajaxGetChild', 'libID=' + libID + '&type=parent');
@@ -105,6 +92,22 @@ function loadDocModule(libID)
}
$(function()
{
$('#root').change(function()
{
if($(this).val() == currentRoot) return true;
var confirmRoot = <?php echo json_encode($type == 'doc' ? $lang->tree->confirmRoot4Doc : $lang->tree->confirmRoot);?>;
if(!confirm(confirmRoot))
{
$('#root').val(currentRoot);
$('#root').trigger('chosen:updated');
}
else
{
if(type != 'doc') getProductModules($(this).val());
if(type == 'doc') loadDocModule($(this).val());
}
})
$('#dataform .chosen').chosen();
// hide #parent chosen dropdown on root dropdown show
+1
View File
@@ -111,3 +111,4 @@ $lang->upgrade->fromVersions['11_5_1'] = '11.5.1';
$lang->upgrade->fromVersions['11_5_2'] = '11.5.2';
$lang->upgrade->fromVersions['11_6'] = '11.6';
$lang->upgrade->fromVersions['11_6_1'] = '11.6.1';
$lang->upgrade->fromVersions['11_6_2'] = '11.6.2';
+199 -27
View File
@@ -110,235 +110,338 @@ class upgradeModel extends model
case '3_1':
$this->saveLogs('Execute 3_1');
$this->execSQL($this->getUpgradeFile('3.1'));
$this->appendExec('3_1');
case '3_2':
$this->saveLogs('Execute 3_2');
$this->execSQL($this->getUpgradeFile('3.2'));
$this->appendExec('3_2');
case '3_2_1':
$this->saveLogs('Execute 3_2_1');
$this->execSQL($this->getUpgradeFile('3.2.1'));
$this->appendExec('3_2_1');
case '3_3':
$this->saveLogs('Execute 3_3');
$this->execSQL($this->getUpgradeFile('3.3'));
$this->updateTaskAssignedTo();
$this->appendExec('3_3');
case '4_0_beta1':
$this->saveLogs('Execute 4_0_beta1');
$this->execSQL($this->getUpgradeFile('4.0.beta1'));
$this->appendExec('4_0_beta1');
case '4_0_beta2':
$this->saveLogs('Execute 4_0_beta2');
$this->execSQL($this->getUpgradeFile('4.0.beta2'));
$this->updateProjectType();
$this->updateEstimatePriv();
$this->appendExec('4_0_beta2');
case '4_0':
$this->saveLogs('Execute 4_0');
$this->execSQL($this->getUpgradeFile('4.0'));
$this->appendExec('4_0');
case '4_0_1':
$this->saveLogs('Execute 4_0_1');
$this->execSQL($this->getUpgradeFile('4.0.1'));
$this->addPriv4_0_1();
$this->appendExec('4_0_1');
case '4_1':
$this->saveLogs('Execute 4_1');
$this->execSQL($this->getUpgradeFile('4.1'));
$this->addPriv4_1();
$this->processTaskFinish();
$this->deleteCompany();
$this->appendExec('4_1');
case '4_2_beta':
$this->saveLogs('Execute 4_2_beta');
$this->execSQL($this->getUpgradeFile('4.2'));
$this->appendExec('4_2_beta');
case '4_3_beta':
$this->saveLogs('Execute 4_3_beta');
$this->execSQL($this->getUpgradeFile('4.3'));
case '5_0_beta1': $this->saveLogs('Execute 5_0_beta1');
case '5_0_beta2': $this->saveLogs('Execute 5_0_beta2');
case '5_0': $this->saveLogs('Execute 5_0');
case '5_1': $this->saveLogs('Execute 5_1');
case '5_2': $this->saveLogs('Execute 5_2');
$this->appendExec('4_3_beta');
case '5_0_beta1':
$this->saveLogs('Execute 5_0_beta1');
$this->appendExec('5_0_beta1');
case '5_0_beta2':
$this->saveLogs('Execute 5_0_beta2');
$this->appendExec('5_0_beta2');
case '5_0':
$this->saveLogs('Execute 5_0');
$this->appendExec('5_0');
case '5_1':
$this->saveLogs('Execute 5_1');
$this->appendExec('5_1');
case '5_2':
$this->saveLogs('Execute 5_2');
$this->appendExec('5_2');
case '5_2_1':
$this->saveLogs('Execute 5_2_1');
$this->mergeProjectGoalAndDesc();
$this->execSQL($this->getUpgradeFile('5.2.1'));
case '5_3': $this->saveLogs('Execute 5_3');
$this->appendExec('5_2_1');
case '5_3':
$this->saveLogs('Execute 5_3');
$this->appendExec('5_3');
case '6_0_beta1':
$this->saveLogs('Execute 6_0_beta');
$this->execSQL($this->getUpgradeFile('6.0.beta1'));
$this->toLowerTable();
$this->fixBugOSInfo();
$this->fixTaskFinishedBy();
$this->appendExec('6_0_beta1');
case '6_0':
$this->saveLogs('Execute 6_0');
$this->execSQL($this->getUpgradeFile('6.0'));
$this->fixDataIndex();
$this->appendExec('6_0');
case '6_1':
$this->saveLogs('Execute 6_1');
$this->execSQL($this->getUpgradeFile('6.1'));
case '6_2': $this->saveLogs('Execute 6_2');
case '6_3': $this->saveLogs('Execute 6_3');
case '6_4': $this->saveLogs('Execute 6_4');
$this->appendExec('6_1');
case '6_2':
$this->saveLogs('Execute 6_2');
$this->appendExec('6_2');
case '6_3':
$this->saveLogs('Execute 6_3');
$this->appendExec('6_3');
case '6_4':
$this->saveLogs('Execute 6_4');
$this->appendExec('6_4');
case '7_0':
$this->saveLogs('Execute 7_0');
$this->execSQL($this->getUpgradeFile('7.0'));
$this->appendExec('7_0');
case '7_1':
$this->saveLogs('Execute 7_1');
$this->execSQL($this->getUpgradeFile('7.1'));
$this->initOrder();
case '7_2': $this->saveLogs('Execute 7_2');
$this->appendExec('7_1');
case '7_2':
$this->saveLogs('Execute 7_2');
$this->appendExec('7_2');
case '7_2_4':
$this->saveLogs('Execute 7_2_4');
$this->execSQL($this->getUpgradeFile('7.2.4'));
$this->appendExec('7_2_4');
case '7_2_5':
$this->saveLogs('Execute 7_2_5');
$this->adjustOrder7_3();
$this->appendExec('7_2_5');
case '7_3':
$this->saveLogs('Execute 7_3');
$this->execSQL($this->getUpgradeFile('7.3'));
$this->adjustPriv7_4_beta();
$this->appendExec('7_3');
case '7_4_beta':
$this->saveLogs('Execute 7_4_beta');
$this->execSQL($this->getUpgradeFile('7.4.beta'));
case '8_0': $this->saveLogs('Execute 8_0');
$this->appendExec('7_4_beta');
case '8_0':
$this->saveLogs('Execute 8_0');
$this->appendExec('8_0');
case '8_0_1':
$this->saveLogs('Execute 8_0_1');
$this->execSQL($this->getUpgradeFile('8.0.1'));
$this->addPriv8_1();
$this->appendExec('8_0_1');
case '8_1':
$this->saveLogs('Execute 8_1');
$this->execSQL($this->getUpgradeFile('8.1'));
$this->appendExec('8_1');
case '8_1_3':
$this->saveLogs('Execute 8_1_3');
$this->execSQL($this->getUpgradeFile('8.1.3'));
$this->addPriv8_2_beta();
$this->adjustConfigSectionAndKey();
case '8_2_beta': $this->saveLogs('Execute 8_2_beta');
case '8_2': $this->saveLogs('Execute 8_2');
$this->appendExec('8_1_3');
case '8_2_beta':
$this->saveLogs('Execute 8_2_beta');
$this->appendExec('8_2_beta');
case '8_2':
$this->saveLogs('Execute 8_2');
$this->appendExec('8_2');
case '8_2_1':
$this->saveLogs('Execute 8_2_1');
$this->execSQL($this->getUpgradeFile('8.2.1'));
case '8_2_2': $this->saveLogs('Execute 8_2_2');
case '8_2_3': $this->saveLogs('Execute 8_2_3');
case '8_2_4': $this->saveLogs('Execute 8_2_4');
case '8_2_5': $this->saveLogs('Execute 8_2_5');
$this->appendExec('8_2_1');
case '8_2_2':
$this->saveLogs('Execute 8_2_2');
$this->appendExec('8_2_2');
case '8_2_3':
$this->saveLogs('Execute 8_2_3');
$this->appendExec('8_2_3');
case '8_2_4':
$this->saveLogs('Execute 8_2_4');
$this->appendExec('8_2_4');
case '8_2_5':
$this->saveLogs('Execute 8_2_5');
$this->appendExec('8_2_5');
case '8_2_6':
$this->saveLogs('Execute 8_2_6');
$this->execSQL($this->getUpgradeFile('8.2.6'));
$this->adjustDocModule();
$this->moveDocContent();
$this->adjustPriv8_3();
case '8_3': $this->saveLogs('Execute 8_3');
$this->appendExec('8_2_6');
case '8_3':
$this->saveLogs('Execute 8_3');
$this->appendExec('8_3');
case '8_3_1':
$this->saveLogs('Execute 8_3_1');
$this->execSQL($this->getUpgradeFile('8.3.1'));
$this->renameMainLib();
$this->adjustPriv8_4();
case '8_4': $this->saveLogs('Execute 8_4');
$this->appendExec('8_3_1');
case '8_4':
$this->saveLogs('Execute 8_4');
$this->appendExec('8_4');
case '8_4_1':
$this->saveLogs('Execute 8_4_1');
$this->execSQL($this->getUpgradeFile('8.4.1'));
$this->appendExec('8_4_1');
case '9_0_beta':
$this->saveLogs('Execute 9_0_beta');
$this->execSQL($this->getUpgradeFile('9.0.beta'));
$this->adjustPriv9_0();
$this->appendExec('9_0_beta');
case '9_0':
$this->saveLogs('Execute 9_0');
$this->fixProjectProductData();
$this->appendExec('9_0');
case '9_0_1':
$this->saveLogs('Execute 9_0_1');
$this->execSQL($this->getUpgradeFile('9.0.1'));
$this->addBugDeadlineToCustomFields();
$this->adjustPriv9_0_1();
$this->appendExec('9_0_1');
case '9_1':
$this->saveLogs('Execute 9_1');
$this->execSQL($this->getUpgradeFile('9.1'));
$this->appendExec('9_1');
case '9_1_1':
$this->saveLogs('Execute 9_1_1');
$this->execSQL($this->getUpgradeFile('9.1.1'));
$this->appendExec('9_1_1');
case '9_1_2':
$this->saveLogs('Execute 9_1_2');
$this->execSQL($this->getUpgradeFile('9.1.2'));
$this->processCustomMenus();
$this->adjustPriv9_2();
case '9_2': $this->saveLogs('Execute 9_2');
case '9_2_1': $this->saveLogs('Execute 9_2_1');
$this->appendExec('9_1_2');
case '9_2':
$this->saveLogs('Execute 9_2');
$this->appendExec('9_2');
case '9_2_1':
$this->saveLogs('Execute 9_2_1');
$this->appendExec('9_2_1');
case '9_3_beta':
$this->saveLogs('Execute 9_3_beta');
$this->execSQL($this->getUpgradeFile('9.3.beta'));
$this->appendExec('9_3_beta');
case '9_4':
$this->saveLogs('Execute 9_4');
$this->execSQL($this->getUpgradeFile('9.4'));
$this->adjustPriv9_4();
$this->appendExec('9_4');
case '9_5':
$this->saveLogs('Execute 9_5');
$this->execSQL($this->getUpgradeFile('9.5'));
$this->appendExec('9_5');
case '9_5_1':
$this->saveLogs('Execute 9_5_1');
$this->execSQL($this->getUpgradeFile('9.5.1'));
$this->initProjectStoryOrder();
$this->appendExec('9_5_1');
case '9_6':
$this->saveLogs('Execute 9_6');
$this->execSQL($this->getUpgradeFile('9.6'));
$this->fixDatatableColsConfig();
$this->appendExec('9_6');
case '9_6_1':
$this->saveLogs('Execute 9_6_1');
$this->addLimitedGroup();
case '9_6_2': $this->saveLogs('Execute 9_6_2');
$this->appendExec('9_6_1');
case '9_6_2':
$this->saveLogs('Execute 9_6_2');
$this->appendExec('9_6_2');
case '9_6_3':
$this->saveLogs('Execute 9_6_3');
$this->execSQL($this->getUpgradeFile('9.6.3'));
$this->changeLimitedName();
$this->adjustPriv9_7();
$this->changeStoryWidth();
$this->appendExec('9_6_3');
case '9_7':
$this->saveLogs('Execute 9_7');
$this->execSQL($this->getUpgradeFile('9.7'));
$this->changeTeamFields();
$this->moveData2Notify();
$this->appendExec('9_7');
case '9_8':
$this->saveLogs('Execute 9_8');
$this->fixTaskFinishedInfo();
$this->appendExec('9_8');
case '9_8_1':
$this->saveLogs('Execute 9_8_1');
$this->execSQL($this->getUpgradeFile('9.8.1'));
$this->fixTaskAssignedTo();
$this->fixProjectClosedInfo();
$this->resetProductLine();
$this->appendExec('9_8_1');
case '9_8_2':
$this->saveLogs('Execute 9_8_2');
$this->execSQL($this->getUpgradeFile('9.8.2'));
$this->addUniqueKeyToTeam();
$this->appendExec('9_8_2');
case '9_8_3':
$this->saveLogs('Execute 9_8_3');
$this->execSQL($this->getUpgradeFile('9.8.3'));
$this->adjustPriv10_0_alpha();
$this->appendExec('9_8_3');
case '10_0_alpha':
$this->saveLogs('Execute 10_0_alpha');
$this->execSQL($this->getUpgradeFile('10.0.alpha'));
$this->fixProjectStatisticBlock();
$this->appendExec('10_0_alpha');
case '10_0_beta':
$this->saveLogs('Execute 10_0_beta');
$this->execSQL($this->getUpgradeFile('10.0.beta'));
$this->appendExec('10_0_beta');
case '10_0':
$this->saveLogs('Execute 10_0');
$this->execSQL($this->getUpgradeFile('10.0'));
$this->fixStorySpecTitle();
$this->removeUnlinkPriv();//Remove unlink privilege for story, bug and testcase module.
$this->appendExec('10_0');
case '10_1':
$this->saveLogs('Execute 10_1');
$xuanxuanSql = $this->app->getAppRoot() . 'db' . DS . 'xuanxuan.sql';
$this->execSQL($xuanxuanSql);
$executeXuanxuan = true;
case '10_2': $this->saveLogs('Execute 10_2');
case '10_3': $this->saveLogs('Execute 10_3');
$this->appendExec('10_1');
case '10_2':
$this->saveLogs('Execute 10_2');
$this->appendExec('10_2');
case '10_3':
$this->saveLogs('Execute 10_3');
$this->appendExec('10_3');
case '10_3_1':
$this->saveLogs('Execute 10_3_1');
$this->execSQL($this->getUpgradeFile('10.3.1'));
$this->removeCustomMenu();
$this->initUserView();
$this->appendExec('10_3_1');
case '10_4':
$this->saveLogs('Execute 10_4');
$this->execSQL($this->getUpgradeFile('10.4'));
$this->changeTaskParentValue();
case '10_5': $this->saveLogs('Execute 10_5');
$this->appendExec('10_4');
case '10_5':
$this->saveLogs('Execute 10_5');
$this->appendExec('10_5');
case '10_5_1':
$this->saveLogs('Execute 10_5_1');
$this->execSQL($this->getUpgradeFile('10.5.1'));
$this->appendExec('10_5_1');
case '10_6':
$this->saveLogs('Execute 10_6');
if(!$executeXuanxuan)
@@ -349,7 +452,10 @@ class upgradeModel extends model
$this->execSQL($xuanxuanSql);
}
$this->initXuanxuan();
case '11_0': $this->saveLogs('Execute 11_0');
$this->appendExec('10_6');
case '11_0':
$this->saveLogs('Execute 11_0');
$this->appendExec('11_0');
case '11_1':
$this->saveLogs('Execute 11_1');
$this->execSQL($this->getUpgradeFile('11.1'));
@@ -363,17 +469,21 @@ class upgradeModel extends model
$this->dao->update(TABLE_CONFIG)->set('value')->eq('off')->where('`key`')->eq('isHttps')->andWhere('`section`')->eq('xuanxuan')->andWhere('`value`')->eq('0')->exec();
$this->dao->update(TABLE_CONFIG)->set('value')->eq('on')->where('`key`')->eq('isHttps')->andWhere('`section`')->eq('xuanxuan')->andWhere('`value`')->eq('1')->exec();
}
$this->appendExec('11_1');
case '11_2':
$this->saveLogs('Execute 11_2');
$this->execSQL($this->getUpgradeFile('11.2'));
$this->processDocLibAcl();
$this->appendExec('11_2');
case '11_3':
$this->saveLogs('Execute 11_3');
$this->execSQL($this->getUpgradeFile('11.3'));
$this->addPriv11_4();
$this->appendExec('11_3');
case '11_4':
$this->saveLogs('Execute 11_4');
$this->execSQL($this->getUpgradeFile('11.4'));
$this->appendExec('11_4');
case '11_4_1':
$this->saveLogs('Execute 11_4_1');
$this->execSQL($this->getUpgradeFile('11.4.1'));
@@ -389,20 +499,30 @@ class upgradeModel extends model
}
$this->updateXX_11_5();
}
$this->appendExec('11_4_1');
case '11_5':
$this->saveLogs('Execute 11_5');
$this->execSQL($this->getUpgradeFile('11.5'));
$this->appendExec('11_5');
case '11_5_1':
$this->saveLogs('Execute 11_5_1');
$this->appendExec('11_5_1');
case '11_5_2':
$this->saveLogs('Execute 11_5_2');
$this->execSQL($this->getUpgradeFile('11.5.2'));
$this->appendExec('11_5_2');
case '11_6':
$this->saveLogs('Execute 11_6');
$this->execSQL($this->getUpgradeFile('11.6'));
$this->appendExec('11_6');
case '11_6_1':
$this->saveLogs('Execute 11_6_1');
$this->adjustWebhookType();
$this->adjustPriv11_6_2();
$this->appendExec('11_6_1');
case '11_6_2':
$this->saveLogs('Execute 11_6_2');
$this->appendExec('11_6_2');
}
$this->deletePatch();
@@ -547,7 +667,9 @@ class upgradeModel extends model
case '11_5' : $confirmContent .= file_get_contents($this->getUpgradeFile('11.5'));
case '11_5_1' :
case '11_5_2' : $confirmContent .= file_get_contents($this->getUpgradeFile('11.5.2'));
case '11_6' : $confirmContent .= file_get_contents($this->getUpgradeFile('11.6'));
case '11_6' : $confirmContent .= file_get_contents($this->getUpgradeFile('11.6'));
case '11_6_1' :
case '11_6_2' :
}
return str_replace('zt_', $this->config->db->prefix, $confirmContent);
}
@@ -3199,6 +3321,45 @@ class upgradeModel extends model
return true;
}
/**
* Adjust priv for 11.6.4.
*
* @access public
* @return void
*/
public function adjustPriv11_6_4()
{
$this->saveLogs('Run Method ' . __FUNCTION__);
$this->dao->update(TABLE_GROUPPRIV)->set('module')->eq('caselib')->set('method')->eq('browse')->where('module')->eq('testsuite')->andWhere('method')->eq('library')->exec();
$this->dao->update(TABLE_GROUPPRIV)->set('module')->eq('caselib')->set('method')->eq('create')->where('module')->eq('testsuite')->andWhere('method')->eq('createLib')->exec();
$this->dao->update(TABLE_GROUPPRIV)->set('module')->eq('caselib')->set('method')->eq('view')->where('module')->eq('testsuite')->andWhere('method')->eq('libView')->exec();
$this->dao->update(TABLE_GROUPPRIV)->set('module')->eq('caselib')->where('module')->eq('testsuite')->andWhere('method')->in('exportTemplet,import,showImport,batchCreateCase,createCase')->exec();
$groups = $this->dao->select('*')->from(TABLE_GROUPPRIV)->where('module')->eq('testsuite')->andWhere('method')->eq('edit')->fetchPairs('group', 'group');
foreach($groups as $groupID)
{
$groupPriv = new stdclass();
$groupPriv->group = $groupID;
$groupPriv->module = 'caselib';
$groupPriv->method = 'edit';
$this->dao->replace(TABLE_GROUPPRIV)->data($groupPriv)->exec();
$this->saveLogs($this->dao->get());
}
$groups = $this->dao->select('*')->from(TABLE_GROUPPRIV)->where('module')->eq('testsuite')->andWhere('method')->eq('delete')->fetchPairs('group', 'group');
foreach($groups as $groupID)
{
$groupPriv = new stdclass();
$groupPriv->group = $groupID;
$groupPriv->module = 'caselib';
$groupPriv->method = 'delete';
$this->dao->replace(TABLE_GROUPPRIV)->data($groupPriv)->exec();
$this->saveLogs($this->dao->get());
}
return true;
}
/**
* Save Logs.
*
@@ -3216,4 +3377,15 @@ class upgradeModel extends model
if(empty($fh)) $fh = fopen($logFile, 'a');
fwrite($fh, $log);
}
/**
* Append execute for pro and biz.
*
* @param string $fromVersion
* @access public
* @return void
*/
public function appendExec($zentaoVersion)
{
}
}
+22 -3
View File
@@ -846,8 +846,25 @@ class user extends control
$this->view->refererBeforeDeny = $refererBeforeDeny; // The referer of the denied page.
$this->app->loadLang($module);
$this->app->loadLang('my');
$this->display();
exit;
/* Check deny type. */
$rights = $this->app->user->rights['rights'];
$acls = $this->app->user->rights['acls'];
$module = strtolower($module);
$method = strtolower($method);
$denyType = 'nopriv';
if(isset($rights[$module][$method]))
{
$menu = isset($this->lang->menugroup->$module) ? $this->lang->menugroup->$module : $module;
$menu = strtolower($menu);
if(!isset($acls['views'][$menu])) $denyType = 'noview';
$this->view->menu = $menu;
}
$this->view->denyType = $denyType;
die($this->display());
}
/**
@@ -1052,7 +1069,9 @@ class user extends control
*/
public function ajaxDeleteTemplate($templateID)
{
$this->dao->delete()->from(TABLE_USERTPL)->where('id')->eq($templateID)->andWhere('account')->eq($this->app->user->account)->exec();
$this->dao->delete()->from(TABLE_USERTPL)->where('id')->eq($templateID)
->beginIF(!$this->app->user->admin)->andWhere('account')->eq($this->app->user->account)->fi()
->exec();
die();
}
}
+1
View File
@@ -109,6 +109,7 @@ $lang->user->case2Him = '给%s的用例';
$lang->user->caseByHim = '%s建的用例';
$lang->user->errorDeny = "抱歉,您无权访问『<b>%s</b>』模块的『<b>%s</b>』功能。请联系管理员获取权限。点击后退返回上页。";
$lang->user->errorView = "抱歉,您无权访问『<b>%s</b>』视图。请联系管理员获取权限。点击后退返回上页。";
$lang->user->loginFailed = "登录失败,请检查您的用户名或密码是否填写正确。";
$lang->user->lockWarning = "您还有%s次尝试机会。";
$lang->user->loginLocked = "密码尝试次数太多,请联系管理员解锁,或%s分钟后重试。";

Some files were not shown because too many files have changed in this diff Show More