Compare commits
317 Commits
zentaopms_
...
zentaopms_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b7ba4d4a38 | ||
|
|
cf4e151f10 | ||
|
|
bfee27a912 | ||
|
|
b57e0ba64f | ||
|
|
17ac3a8996 | ||
|
|
dcb944f0ac | ||
|
|
9de63a3b15 | ||
|
|
9b339ac01f | ||
|
|
0b3ef6fba1 | ||
|
|
0e7c551027 | ||
|
|
7f2c61c891 | ||
|
|
7a0c793270 | ||
|
|
c6d21eec38 | ||
|
|
8c32fc916a | ||
|
|
e549511cbb | ||
|
|
b5a42dedda | ||
|
|
c374a6e482 | ||
|
|
e843e0004d | ||
|
|
d0a31b775e | ||
|
|
fa11f088a6 | ||
|
|
0bd5173f01 | ||
|
|
14f376e399 | ||
|
|
01fec363c4 | ||
|
|
9cfcab7dff | ||
|
|
96a8ff86f7 | ||
|
|
82a46bd196 | ||
|
|
ff43f65926 | ||
|
|
5dfd9e57e9 | ||
|
|
b5059fa0a5 | ||
|
|
81c7452008 | ||
|
|
f3bb4d7e3e | ||
|
|
b9b6821d36 | ||
|
|
d9ea62d417 | ||
|
|
d0030e82d3 | ||
|
|
8bbad78ec1 | ||
|
|
b2d49204b8 | ||
|
|
0f6e89bd70 | ||
|
|
516b1f0034 | ||
|
|
ae46e92be5 | ||
|
|
3d349b45d8 | ||
|
|
cc24cd982c | ||
|
|
9b050fea16 | ||
|
|
800a0efd9e | ||
|
|
70776effd6 | ||
|
|
0d7558d206 | ||
|
|
6c26ebb27f | ||
|
|
c604bf2ba2 | ||
|
|
5188f6aa0b | ||
|
|
4f4ddb3e5f | ||
|
|
0bebfe176a | ||
|
|
eb20cc4741 | ||
|
|
0190934f07 | ||
|
|
6b055c87fe | ||
|
|
bf33b5f108 | ||
|
|
ab8f86396f | ||
|
|
931a13641b | ||
|
|
80a3959415 | ||
|
|
4dcaa49d5b | ||
|
|
a3c5e42a7c | ||
|
|
eff03084c3 | ||
|
|
4763dc65f7 | ||
|
|
55c2f7e63a | ||
|
|
91194fcccc | ||
|
|
bbbd0891ff | ||
|
|
1a8a8a0be4 | ||
|
|
aea3e80a3f | ||
|
|
563541db13 | ||
|
|
2a748ac35f | ||
|
|
470eb3a281 | ||
|
|
2a8d4e92eb | ||
|
|
a4ca492969 | ||
|
|
7e626c0b6b | ||
|
|
cd760834af | ||
|
|
51b555c101 | ||
|
|
81c9b4d020 | ||
|
|
41df2d107b | ||
|
|
80957347ad | ||
|
|
ba4efcfa7f | ||
|
|
b0e0241676 | ||
|
|
7c349639df | ||
|
|
026dbe2f25 | ||
|
|
6f9b3d3e61 | ||
|
|
1e22ef4ea7 | ||
|
|
5f975e60ba | ||
|
|
4fc1f5286b | ||
|
|
142915aa30 | ||
|
|
c96be8964a | ||
|
|
2417ceeea2 | ||
|
|
019969ab90 | ||
|
|
7ba54fb85b | ||
|
|
0b99aaea7e | ||
|
|
b899f67e5c | ||
|
|
dffd808378 | ||
|
|
e617014b65 | ||
|
|
6d6d0a85dd | ||
|
|
c30be46e52 | ||
|
|
e996a9d4ed | ||
|
|
61fb9e38ba | ||
|
|
2e7698db31 | ||
|
|
4569039d98 | ||
|
|
7da16e22ca | ||
|
|
140a15b0be | ||
|
|
7a1eb61efd | ||
|
|
40a300031e | ||
|
|
12bdd87463 | ||
|
|
6f673a06ed | ||
|
|
80b9d18d73 | ||
|
|
81375e9147 | ||
|
|
a04db8bc49 | ||
|
|
4f7b7266f4 | ||
|
|
3525fe15bc | ||
|
|
152ad148e6 | ||
|
|
df85f2625e | ||
|
|
454d7d4942 | ||
|
|
26d831d0b6 | ||
|
|
8c05dd59f4 | ||
|
|
18f97e6478 | ||
|
|
d97d22c0db | ||
|
|
5722d28e77 | ||
|
|
fb65e3660b | ||
|
|
b3583677de | ||
|
|
8c911f45da | ||
|
|
dad0b0395d | ||
|
|
4017b1ae75 | ||
|
|
7603866e92 | ||
|
|
0d47f23a19 | ||
|
|
3e19bde847 | ||
|
|
f6186e949c | ||
|
|
f36272ed99 | ||
|
|
401e2c0ac1 | ||
|
|
9cc1a9e055 | ||
|
|
051e6530d8 | ||
|
|
833d40aba6 | ||
|
|
8bb0290077 | ||
|
|
51d75e71a2 | ||
|
|
0dafbb66dd | ||
|
|
f1454d2d99 | ||
|
|
f4980f8377 | ||
|
|
2fc659447f | ||
|
|
4f9fd70b9e | ||
|
|
59c99c29f3 | ||
|
|
d9e1606b2e | ||
|
|
bc18f5d692 | ||
|
|
a8089272bc | ||
|
|
59917d3a0a | ||
|
|
2dbfa69498 | ||
|
|
2f9ac5d436 | ||
|
|
46eeec68aa | ||
|
|
274639baa5 | ||
|
|
af9f3f8d37 | ||
|
|
09c8fa8aa8 | ||
|
|
20aa49dea9 | ||
|
|
abfb3f5fa5 | ||
|
|
a4fbf1ddef | ||
|
|
12ec619856 | ||
|
|
c7168f7db7 | ||
|
|
cb7663e691 | ||
|
|
c1a45df1cd | ||
|
|
ffd58aebb7 | ||
|
|
da0b5e611d | ||
|
|
e23311969d | ||
|
|
127d2e6a40 | ||
|
|
7f66f2018e | ||
|
|
8a604925ee | ||
|
|
288bfe5758 | ||
|
|
3abf28e9ed | ||
|
|
69f7a3341e | ||
|
|
7bb16d8f92 | ||
|
|
f3edc332fd | ||
|
|
b321098c26 | ||
|
|
8c3028d3c0 | ||
|
|
997f691665 | ||
|
|
8a5df03463 | ||
|
|
a261867468 | ||
|
|
b8474bddf5 | ||
|
|
7683db7228 | ||
|
|
0269715534 | ||
|
|
8499ea4819 | ||
|
|
8373cc09cf | ||
|
|
334a0b1009 | ||
|
|
ae4fd31b3d | ||
|
|
ea56bf4d25 | ||
|
|
98e7f59798 | ||
|
|
baa2b472c2 | ||
|
|
8c284f4459 | ||
|
|
2bde4bcba2 | ||
|
|
2f8121190d | ||
|
|
338cfa239b | ||
|
|
d06f0ecb5f | ||
|
|
80b50cb041 | ||
|
|
9141bb13d7 | ||
|
|
0f2f5eaf1a | ||
|
|
f3ab28ebdd | ||
|
|
173fa51902 | ||
|
|
e35b0f273e | ||
|
|
44d380dd34 | ||
|
|
4b76d36e9e | ||
|
|
1fce9b6d68 | ||
|
|
bbf3d672af | ||
|
|
d9ddbd0450 | ||
|
|
aa6f3bc46d | ||
|
|
33d94add3b | ||
|
|
46136fbf70 | ||
|
|
95de1da365 | ||
|
|
72c1f7dc8a | ||
|
|
9f99387a7e | ||
|
|
77b0403e53 | ||
|
|
19044c3115 | ||
|
|
a24f6cbeba | ||
|
|
8517690be4 | ||
|
|
ae81e0f85e | ||
|
|
83d41f0345 | ||
|
|
39928a235f | ||
|
|
454ed3acb2 | ||
|
|
ff800c6133 | ||
|
|
8230ffd6d0 | ||
|
|
ae9b46a05f | ||
|
|
d01b8eb8df | ||
|
|
8b1c8fb46f | ||
|
|
26e611bee5 | ||
|
|
46a7ceaad7 | ||
|
|
30b9c0d99b | ||
|
|
63b4164434 | ||
|
|
2f9807ab14 | ||
|
|
50b3d69bc9 | ||
|
|
fcc798f4d4 | ||
|
|
d324bb72e6 | ||
|
|
e8bb9aa1ee | ||
|
|
5266c8c064 | ||
|
|
86ee7a2055 | ||
|
|
ef9f7ca2fb | ||
|
|
1f9055b610 | ||
|
|
2b7df545f2 | ||
|
|
ba3ed90986 | ||
|
|
6acdab6742 | ||
|
|
a0d475720b | ||
|
|
052a1d7a7c | ||
|
|
a2e1a381e2 | ||
|
|
e3c51a6200 | ||
|
|
ce148bb582 | ||
|
|
dfa64599e2 | ||
|
|
ca7e1ab6f7 | ||
|
|
0f4856495a | ||
|
|
888c89fbe5 | ||
|
|
731bc2e5a8 | ||
|
|
fb2357ef32 | ||
|
|
82f04a6a22 | ||
|
|
4ebfcc3ac8 | ||
|
|
e45a196b7b | ||
|
|
957111c6f0 | ||
|
|
1e3c913063 | ||
|
|
b6e4fc2e41 | ||
|
|
b49fae3d74 | ||
|
|
7007f4b888 | ||
|
|
aab0b66e15 | ||
|
|
9c6d301c9c | ||
|
|
62c590a94b | ||
|
|
b5d020c652 | ||
|
|
72eca957bf | ||
|
|
92208eae36 | ||
|
|
b3f919b697 | ||
|
|
6ae74c1430 | ||
|
|
33dff40092 | ||
|
|
8fccef5df3 | ||
|
|
5933daa169 | ||
|
|
a2b2454760 | ||
|
|
b808b0c8c3 | ||
|
|
0160e99054 | ||
|
|
036cebc87e | ||
|
|
290d1a76bc | ||
|
|
61ecdb6000 | ||
|
|
5913f76f35 | ||
|
|
d04a6a0ba8 | ||
|
|
7acbf8c7bd | ||
|
|
9fe3b5ca05 | ||
|
|
119f3bfb20 | ||
|
|
998f465811 | ||
|
|
4bf02d062f | ||
|
|
62fc4ac385 | ||
|
|
f020e482c6 | ||
|
|
6d2f5f4c8e | ||
|
|
4040b541dd | ||
|
|
13c881ccda | ||
|
|
a9f3fe5270 | ||
|
|
02ce779b65 | ||
|
|
48ada5974b | ||
|
|
6670b94caf | ||
|
|
a94cd23f69 | ||
|
|
514376c307 | ||
|
|
aa8c0363f3 | ||
|
|
849ec91753 | ||
|
|
9012728c5a | ||
|
|
3c4c0e137e | ||
|
|
2aba28b253 | ||
|
|
715050df57 | ||
|
|
8ff1e21c95 | ||
|
|
a01925a0f2 | ||
|
|
6f67d9af0f | ||
|
|
c3a9804a56 | ||
|
|
5923c8e637 | ||
|
|
eebc5834ae | ||
|
|
75bd02ec48 | ||
|
|
103919866f | ||
|
|
57ef7bad74 | ||
|
|
3d46d2e1ed | ||
|
|
c657433fa2 | ||
|
|
7374c81949 | ||
|
|
d06306de00 | ||
|
|
ba0f4306c6 | ||
|
|
35cd899cd5 | ||
|
|
a05357d964 | ||
|
|
7955810546 | ||
|
|
6fe166a8f5 | ||
|
|
c1da3f39c2 | ||
|
|
e17126e526 | ||
|
|
7c5358ed0d | ||
|
|
7184cb3a90 |
6
Makefile
6
Makefile
@@ -38,9 +38,9 @@ pms:
|
||||
# notify.zip.
|
||||
mkdir zentaopms/www/data/notify/
|
||||
# change mode.
|
||||
chmod 777 -R zentaopms/tmp/
|
||||
chmod 777 -R zentaopms/www/data
|
||||
chmod 777 -R zentaopms/config
|
||||
chmod -R 777 zentaopms/tmp/
|
||||
chmod -R 777 zentaopms/www/data
|
||||
chmod -R 777 zentaopms/config
|
||||
chmod 777 zentaopms/module
|
||||
chmod 777 zentaopms/www
|
||||
chmod a+rx zentaopms/bin/*
|
||||
|
||||
@@ -6,19 +6,11 @@ error_reporting(E_ALL ^ E_NOTICE);
|
||||
$pmsRoot = dirname(dirname(dirname(__FILE__)));
|
||||
$myConfig = $pmsRoot . '/config/config.php';
|
||||
$zipClass = $pmsRoot . '/lib/pclzip/pclzip.class.php';
|
||||
$zdbClass = $pmsRoot . '/lib/zdb/zdb.class.php';
|
||||
|
||||
include $myConfig;
|
||||
include $zipClass;
|
||||
|
||||
/* Judge mysqldump cmd setted or not. */
|
||||
if(empty($config->mysqldump))
|
||||
{
|
||||
echo "Please set the mysqldump path in $myConfig:\n";
|
||||
echo "Just like: \n";
|
||||
echo '$config->mysqldump = \'/usr/bin/mysqldump\'; for linux' . "\n";
|
||||
echo '$config->mysqldump = \'D:\xampp\mysql\bin\mysqldump.exe\'; for windows' . "\n";
|
||||
exit;
|
||||
}
|
||||
include $zdbClass;
|
||||
|
||||
/* Init the backupRoot and dest directory. */
|
||||
$backupRoot = $pmsRoot . "/backup";
|
||||
@@ -29,12 +21,13 @@ if(!file_exists($destDir)) mkdir($destDir, 0777);
|
||||
|
||||
/* Backup database. */
|
||||
$dbRawFile = "db." . date('Ymd') . ".sql";
|
||||
$password = $config->db->password ? "-p{$config->db->password}" : ' ';
|
||||
$command = "\"{$config->mysqldump}\" -u{$config->db->user} $password -P {$config->db->port} {$config->db->name} > {$dbRawFile}";
|
||||
|
||||
$dsn = "mysql:host={$config->db->host}; port={$config->db->port}; dbname={$config->db->name}";
|
||||
$dbh = new PDO($dsn, $config->db->user, $config->db->password, array(PDO::ATTR_PERSISTENT => $config->db->persistant));
|
||||
$dbh->exec("SET NAMES {$config->db->encoding}");
|
||||
echo "Backuping database,";
|
||||
system($command, $return);
|
||||
if($return == 0)
|
||||
$zdb = new zdb();
|
||||
$return = $zdb->dump($dbRawFile);
|
||||
if($return->result)
|
||||
{
|
||||
$dbZipFile = $destDir . "/" . str_replace("sql", "zip", $dbRawFile);
|
||||
$archive = new pclzip($dbZipFile);
|
||||
|
||||
@@ -17,7 +17,7 @@ if(!function_exists('getWebRoot')){function getWebRoot(){}}
|
||||
|
||||
/* Basic settings. */
|
||||
$config = new config();
|
||||
$config->version = '7.4.beta'; // The version of zentaopms. Don't change it.
|
||||
$config->version = '8.1'; // The version of zentaopms. Don't change it.
|
||||
$config->charset = 'UTF-8'; // The charset of zentaopms.
|
||||
$config->cookieLife = time() + 2592000; // The cookie life time.
|
||||
$config->timezone = 'Asia/Shanghai'; // The time zone setting, for more see http://www.php.net/manual/en/timezones.php
|
||||
@@ -81,8 +81,11 @@ $config->file = new stdclass();
|
||||
$config->file->dangers = 'php,php3,php4,phtml,php5,jsp,py,rb,asp,asa,cer,cdx,aspl'; // Dangerous files.
|
||||
$config->file->maxSize = 1024 * 1024; // Max size.
|
||||
|
||||
/* IP white list settings.*/
|
||||
$config->ipWhiteList = '*';
|
||||
|
||||
/* View type settings. */
|
||||
$config->viewPrefix['mhtml'] = 'm.';
|
||||
$config->devicePrefix['mhtml'] = 'm.';
|
||||
|
||||
/* Master database settings. */
|
||||
$config->db = new stdclass();
|
||||
@@ -101,6 +104,14 @@ $config->slaveDB->encoding = 'UTF8';
|
||||
$config->slaveDB->strictMode = false;
|
||||
$config->slaveDB->checkCentOS= true;
|
||||
|
||||
/* Framework config. */
|
||||
$config->framework = new stdclass();
|
||||
$config->framework->jsWithPrefix = false;
|
||||
$config->framework->autoRepairTable = true;
|
||||
$config->framework->logDays = 14;
|
||||
$config->framework->purifier = true;
|
||||
$config->framework->autoLang = false;
|
||||
|
||||
/* Include the custom config file. */
|
||||
$configRoot = dirname(__FILE__) . DIRECTORY_SEPARATOR;
|
||||
$myConfig = $configRoot . 'my.php';
|
||||
|
||||
@@ -25,7 +25,7 @@ CREATE TABLE IF NOT EXISTS `zt_storystage` (
|
||||
`stage` varchar(50) NOT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
ALTER TABLE `zt_story` ADD INDEX `product` (`product`, `module`, `type`, `pri`), DROP INDEX `product`;
|
||||
ALTER TABLE `zt_story` ADD `plan` text COLLATE 'utf8_general_ci' NOT NULL AFTER `module`;
|
||||
ALTER TABLE `zt_story` CHANGE `plan` `plan` text COLLATE 'utf8_general_ci' NOT NULL AFTER `module`;
|
||||
UPDATE `zt_story` SET `plan`='' WHERE `plan`='0';
|
||||
|
||||
ALTER TABLE `zt_release` DROP INDEX `name`;
|
||||
|
||||
2
db/update7.4.beta.sql
Normal file
2
db/update7.4.beta.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE `zt_story` CHANGE `plan` `plan` text COLLATE 'utf8_general_ci' NOT NULL AFTER `module`;
|
||||
UPDATE `zt_story` SET `plan`='' WHERE `plan`='0';
|
||||
26
db/update8.0.1.sql
Normal file
26
db/update8.0.1.sql
Normal file
@@ -0,0 +1,26 @@
|
||||
ALTER TABLE `zt_action` ADD INDEX `action` (`objectID`, `product`, `project`, `action`, `date`);
|
||||
ALTER TABLE `zt_branch` ADD INDEX `product` (`product`);
|
||||
ALTER TABLE `zt_bug` ADD INDEX `bug` (`product`,`module`,`project`,`assignedTo`);
|
||||
ALTER TABLE `zt_build` ADD INDEX `build` (`product`, `project`);
|
||||
ALTER TABLE `zt_case` ADD INDEX `case` (`product`, `module`, `story`);
|
||||
ALTER TABLE `zt_cron` ADD INDEX `lastTime` (`lastTime`);
|
||||
ALTER TABLE `zt_dept` ADD INDEX `dept` (`parent`, `path`);
|
||||
ALTER TABLE `zt_doc` ADD INDEX `doc` (`product`, `project`);
|
||||
ALTER TABLE `zt_extension` ADD INDEX `extension` (`name`, `installedTime`), DROP INDEX `name`, DROP INDEX `addedTime`;
|
||||
ALTER TABLE `zt_file` ADD INDEX `file` (`objectType`, `objectID`), DROP INDEX `objectType`, DROP INDEX `objectID`;
|
||||
ALTER TABLE `zt_mailqueue` ADD INDEX `sendTime` (`sendTime`);
|
||||
ALTER TABLE `zt_module` ADD INDEX `module` (`root`, `type`, `path`), DROP INDEX `root`, DROP INDEX `type`;
|
||||
ALTER TABLE `zt_product` ADD INDEX `order` (`order`);
|
||||
ALTER TABLE `zt_productplan` ADD INDEX `plan` (`product`, `end`);
|
||||
ALTER TABLE `zt_project` ADD INDEX `project` (`parent`, `begin`, `end`, `status`, `order`), DROP INDEX `project`;
|
||||
ALTER TABLE `zt_release` ADD INDEX `build` (`build`);
|
||||
ALTER TABLE `zt_story` ADD INDEX `story` (`product`, `module`, `status`, `assignedTo`), DROP INDEX `status`, DROP INDEX `product`;
|
||||
ALTER TABLE `zt_storystage` ADD INDEX `story` (`story`);
|
||||
ALTER TABLE `zt_task` ADD INDEX `task` (`project`, `module`, `story`, `assignedTo`), DROP INDEX `project`, DROP INDEX `type`, DROP INDEX `status`;
|
||||
ALTER TABLE `zt_testresult` ADD INDEX `testresult` (`case`, `version`, `run`), DROP INDEX `run`, DROP INDEX `case`;
|
||||
ALTER TABLE `zt_testtask` ADD INDEX `build` (`build`);
|
||||
ALTER TABLE `zt_todo` ADD INDEX `todo` (`account`, `date`), DROP INDEX `user`;
|
||||
ALTER TABLE `zt_user` ADD INDEX `user` (`dept`, `email`, `commiter`), DROP INDEX `dept`;
|
||||
ALTER TABLE `zt_usercontact` ADD INDEX `account` (`account`);
|
||||
ALTER TABLE `zt_userquery` ADD INDEX `query` (`account`, `module`), DROP INDEX `account`, DROP INDEX `module`;
|
||||
ALTER TABLE `zt_testtask` ADD `mailto` varchar(255) COLLATE 'utf8_general_ci' NOT NULL DEFAULT '' AFTER `end`;
|
||||
110
db/zentao.sql
110
db/zentao.sql
@@ -11,7 +11,8 @@ CREATE TABLE IF NOT EXISTS `zt_action` (
|
||||
`comment` text NOT NULL,
|
||||
`extra` text NOT NULL,
|
||||
`read` enum('0','1') NOT NULL default '0',
|
||||
PRIMARY KEY (`id`)
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `action` (`objectID`,`product`,`project`,`action`,`date`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
-- DROP TABLE IF EXISTS `zt_branch`;
|
||||
@@ -20,7 +21,8 @@ CREATE TABLE IF NOT EXISTS `zt_branch` (
|
||||
`product` mediumint(8) unsigned NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`deleted` enum('0','1') NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `product` (`product`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_bug`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_bug` (
|
||||
@@ -69,7 +71,8 @@ CREATE TABLE IF NOT EXISTS `zt_bug` (
|
||||
`lastEditedBy` varchar(30) NOT NULL default '',
|
||||
`lastEditedDate` datetime NOT NULL,
|
||||
`deleted` enum('0','1') NOT NULL default '0',
|
||||
PRIMARY KEY (`id`)
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `bug` (`product`,`module`,`project`,`assignedTo`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_build`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_build` (
|
||||
@@ -86,7 +89,8 @@ CREATE TABLE IF NOT EXISTS `zt_build` (
|
||||
`builder` char(30) NOT NULL default '',
|
||||
`desc` text NOT NULL,
|
||||
`deleted` enum('0','1') NOT NULL default '0',
|
||||
PRIMARY KEY (`id`)
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `build` (`product`,`project`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_burn`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_burn` (
|
||||
@@ -130,7 +134,8 @@ CREATE TABLE IF NOT EXISTS `zt_case` (
|
||||
`lastRunner` varchar(30) NOT NULL,
|
||||
`lastRunDate` datetime NOT NULL,
|
||||
`lastRunResult` char(30) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `case` (`product`,`module`,`story`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_casestep`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_casestep` (
|
||||
@@ -182,7 +187,8 @@ CREATE TABLE IF NOT EXISTS `zt_cron` (
|
||||
`buildin` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`status` varchar(20) NOT NULL,
|
||||
`lastTime` datetime NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `lastTime` (`lastTime`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_lang`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_lang` (
|
||||
@@ -207,7 +213,8 @@ CREATE TABLE IF NOT EXISTS `zt_dept` (
|
||||
`position` char(30) NOT NULL default '',
|
||||
`function` char(255) NOT NULL default '',
|
||||
`manager` char(30) NOT NULL default '',
|
||||
PRIMARY KEY (`id`)
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `dept` (`parent`,`path`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_doc`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_doc` (
|
||||
@@ -228,7 +235,8 @@ CREATE TABLE IF NOT EXISTS `zt_doc` (
|
||||
`editedBy` varchar(30) NOT NULL,
|
||||
`editedDate` datetime NOT NULL,
|
||||
`deleted` enum('0','1') NOT NULL default '0',
|
||||
PRIMARY KEY (`id`)
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `doc` (`product`,`project`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_doclib`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_doclib` (
|
||||
@@ -272,8 +280,7 @@ CREATE TABLE IF NOT EXISTS `zt_extension` (
|
||||
`status` varchar(20) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `code` (`code`),
|
||||
KEY `name` (`name`),
|
||||
KEY `addedTime` (`installedTime`)
|
||||
KEY `extension` (`name`,`installedTime`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_file`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_file` (
|
||||
@@ -289,7 +296,8 @@ CREATE TABLE IF NOT EXISTS `zt_file` (
|
||||
`downloads` mediumint(8) unsigned NOT NULL default '0',
|
||||
`extra` varchar(255) NOT NULL,
|
||||
`deleted` enum('0','1') NOT NULL default '0',
|
||||
PRIMARY KEY (`id`)
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `file` (`objectType`,`objectID`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_group`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_group` (
|
||||
@@ -315,7 +323,8 @@ CREATE TABLE IF NOT EXISTS `zt_history` (
|
||||
`old` text NOT NULL,
|
||||
`new` text NOT NULL,
|
||||
`diff` mediumtext NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `action` (`action`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_mailqueue`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_mailqueue` (
|
||||
@@ -329,7 +338,8 @@ CREATE TABLE IF NOT EXISTS `zt_mailqueue` (
|
||||
`sendTime` datetime NOT NULL,
|
||||
`status` varchar(10) NOT NULL DEFAULT 'wait',
|
||||
`failReason` text NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `sendTime` (`sendTime`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_module`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_module` (
|
||||
@@ -343,7 +353,8 @@ CREATE TABLE IF NOT EXISTS `zt_module` (
|
||||
`order` smallint(5) unsigned NOT NULL default '0',
|
||||
`type` char(30) NOT NULL,
|
||||
`owner` varchar(30) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `module` (`root`,`type`,`path`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_product`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_product` (
|
||||
@@ -363,7 +374,8 @@ CREATE TABLE IF NOT EXISTS `zt_product` (
|
||||
`createdVersion` varchar(20) NOT NULL,
|
||||
`order` mediumint(8) unsigned NOT NULL,
|
||||
`deleted` enum('0','1') NOT NULL default '0',
|
||||
PRIMARY KEY (`id`)
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `order` (`order`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_productplan`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_productplan` (
|
||||
@@ -375,7 +387,8 @@ CREATE TABLE IF NOT EXISTS `zt_productplan` (
|
||||
`begin` date NOT NULL,
|
||||
`end` date NOT NULL,
|
||||
`deleted` enum('0','1') NOT NULL default '0',
|
||||
PRIMARY KEY (`id`)
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `plan` (`product`,`end`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_project`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_project` (
|
||||
@@ -410,7 +423,7 @@ CREATE TABLE IF NOT EXISTS `zt_project` (
|
||||
`order` mediumint(8) unsigned NOT NULL,
|
||||
`deleted` enum('0','1') NOT NULL default '0',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `project` (`type`,`parent`,`begin`,`end`,`status`,`statge`,`pri`)
|
||||
KEY `project` (`parent`,`begin`,`end`,`status`,`order`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_projectproduct`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_projectproduct` (
|
||||
@@ -441,7 +454,8 @@ CREATE TABLE IF NOT EXISTS `zt_release` (
|
||||
`desc` text NOT NULL,
|
||||
`status` varchar(20) NOT NULL default 'normal',
|
||||
`deleted` enum('0','1') NOT NULL default '0',
|
||||
PRIMARY KEY (`id`),
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `build` (`build`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_story`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_story` (
|
||||
@@ -478,8 +492,7 @@ CREATE TABLE IF NOT EXISTS `zt_story` (
|
||||
`version` smallint(6) NOT NULL default '1',
|
||||
`deleted` enum('0','1') NOT NULL default '0',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `product` (`product`,`module`,`type`,`pri`),
|
||||
KEY `status` (`status`)
|
||||
KEY `story` (`product`,`module`,`status`,`assignedTo`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_storyspec`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_storyspec` (
|
||||
@@ -494,7 +507,8 @@ CREATE TABLE IF NOT EXISTS `zt_storyspec` (
|
||||
CREATE TABLE IF NOT EXISTS `zt_storystage` (
|
||||
`story` mediumint(8) unsigned NOT NULL,
|
||||
`branch` mediumint(8) unsigned NOT NULL,
|
||||
`stage` varchar(50) NOT NULL
|
||||
`stage` varchar(50) NOT NULL,
|
||||
KEY `story` (`story`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_task`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_task` (
|
||||
@@ -530,8 +544,8 @@ CREATE TABLE IF NOT EXISTS `zt_task` (
|
||||
`lastEditedBy` varchar(30) NOT NULL,
|
||||
`lastEditedDate` datetime NOT NULL,
|
||||
`deleted` enum('0','1') NOT NULL default '0',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `type` (`type`)
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `task` (`project`,`module`,`story`,`assignedTo`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_taskestimate`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_taskestimate` (
|
||||
@@ -566,8 +580,7 @@ CREATE TABLE IF NOT EXISTS `zt_testresult` (
|
||||
`lastRunner` varchar(30) NOT NULL,
|
||||
`date` datetime NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `run` (`run`),
|
||||
KEY `case` (`case`,`version`)
|
||||
KEY `testresult` (`case`,`version`, `run`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_testrun`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_testrun` (
|
||||
@@ -594,11 +607,13 @@ CREATE TABLE IF NOT EXISTS `zt_testtask` (
|
||||
`pri` tinyint(3) unsigned NOT NULL default '0',
|
||||
`begin` date NOT NULL,
|
||||
`end` date NOT NULL,
|
||||
`mailto` varchar(255) NOT NULL default '',
|
||||
`desc` text NOT NULL,
|
||||
`report` text NOT NULL,
|
||||
`status` enum('blocked','doing','wait','done') NOT NULL DEFAULT 'wait',
|
||||
`deleted` enum('0','1') NOT NULL default '0',
|
||||
PRIMARY KEY (`id`)
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `build` (`build`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_todo`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_todo` (
|
||||
@@ -615,7 +630,7 @@ CREATE TABLE IF NOT EXISTS `zt_todo` (
|
||||
`status` enum('wait','doing','done') NOT NULL DEFAULT 'wait',
|
||||
`private` tinyint(1) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `user` (`account`)
|
||||
KEY `todo` (`account`,`date`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_user`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_user` (
|
||||
@@ -650,7 +665,7 @@ CREATE TABLE IF NOT EXISTS `zt_user` (
|
||||
`deleted` enum('0','1') NOT NULL default '0',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `account` (`account`),
|
||||
KEY `dept` (`dept`)
|
||||
KEY `user` (`dept`,`email`,`commiter`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_usercontact`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_usercontact` (
|
||||
@@ -658,7 +673,8 @@ CREATE TABLE IF NOT EXISTS `zt_usercontact` (
|
||||
`account` char(30) NOT NULL,
|
||||
`listName` varchar(60) NOT NULL,
|
||||
`userList` text NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `account` (`account`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_usergroup`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_usergroup` (
|
||||
@@ -675,8 +691,7 @@ CREATE TABLE IF NOT EXISTS `zt_userquery` (
|
||||
`form` text NOT NULL,
|
||||
`sql` text NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `account` (`account`),
|
||||
KEY `module` (`module`)
|
||||
KEY `query` (`account`, `module`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_usertpl`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_usertpl` (
|
||||
@@ -745,6 +760,8 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(1, 'bug', 'delete'),
|
||||
(1, 'bug', 'deleteTemplate'),
|
||||
(1, 'bug', 'edit'),
|
||||
(1, 'bug', 'linkBugs'),
|
||||
(1, 'bug', 'unlinkBug'),
|
||||
(1, 'bug', 'export'),
|
||||
(1, 'bug', 'index'),
|
||||
(1, 'bug', 'report'),
|
||||
@@ -947,6 +964,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(1, 'story', 'activate'),
|
||||
(1, 'story', 'batchAssignTo'),
|
||||
(1, 'story', 'batchChangePlan'),
|
||||
(1, 'story', 'batchChangeBranch'),
|
||||
(1, 'story', 'batchChangeStage'),
|
||||
(1, 'story', 'batchClose'),
|
||||
(1, 'story', 'batchCreate'),
|
||||
@@ -957,6 +975,8 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(1, 'story', 'create'),
|
||||
(1, 'story', 'delete'),
|
||||
(1, 'story', 'edit'),
|
||||
(1, 'story', 'linkStory'),
|
||||
(1, 'story', 'unlinkStory'),
|
||||
(1, 'story', 'export'),
|
||||
(1, 'story', 'report'),
|
||||
(1, 'story', 'review'),
|
||||
@@ -998,6 +1018,8 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(1, 'testcase', 'createBug'),
|
||||
(1, 'testcase', 'delete'),
|
||||
(1, 'testcase', 'edit'),
|
||||
(1, 'testcase', 'linkCases'),
|
||||
(1, 'testcase', 'unlinkCase'),
|
||||
(1, 'testcase', 'export'),
|
||||
(1, 'testcase', 'exportTemplet'),
|
||||
(1, 'testcase', 'groupCase'),
|
||||
@@ -1074,6 +1096,8 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(2, 'bug', 'create'),
|
||||
(2, 'bug', 'deleteTemplate'),
|
||||
(2, 'bug', 'edit'),
|
||||
(2, 'bug', 'linkBugs'),
|
||||
(2, 'bug', 'unlinkBug'),
|
||||
(2, 'bug', 'export'),
|
||||
(2, 'bug', 'index'),
|
||||
(2, 'bug', 'report'),
|
||||
@@ -1232,6 +1256,8 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(3, 'bug', 'create'),
|
||||
(3, 'bug', 'deleteTemplate'),
|
||||
(3, 'bug', 'edit'),
|
||||
(3, 'bug', 'linkBugs'),
|
||||
(3, 'bug', 'unlinkBug'),
|
||||
(3, 'bug', 'export'),
|
||||
(3, 'bug', 'index'),
|
||||
(3, 'bug', 'report'),
|
||||
@@ -1349,6 +1375,8 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(3, 'testcase', 'create'),
|
||||
(3, 'testcase', 'createBug'),
|
||||
(3, 'testcase', 'edit'),
|
||||
(3, 'testcase', 'linkCases'),
|
||||
(3, 'testcase', 'unlinkCase'),
|
||||
(3, 'testcase', 'export'),
|
||||
(3, 'testcase', 'exportTemplet'),
|
||||
(3, 'testcase', 'groupCase'),
|
||||
@@ -1416,6 +1444,8 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(4, 'bug', 'delete'),
|
||||
(4, 'bug', 'deleteTemplate'),
|
||||
(4, 'bug', 'edit'),
|
||||
(4, 'bug', 'linkBugs'),
|
||||
(4, 'bug', 'unlinkBug'),
|
||||
(4, 'bug', 'export'),
|
||||
(4, 'bug', 'index'),
|
||||
(4, 'bug', 'report'),
|
||||
@@ -1625,6 +1655,8 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(5, 'bug', 'create'),
|
||||
(5, 'bug', 'deleteTemplate'),
|
||||
(5, 'bug', 'edit'),
|
||||
(5, 'bug', 'linkBugs'),
|
||||
(5, 'bug', 'unlinkBug'),
|
||||
(5, 'bug', 'export'),
|
||||
(5, 'bug', 'index'),
|
||||
(5, 'bug', 'report'),
|
||||
@@ -1759,6 +1791,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(5, 'search', 'select'),
|
||||
(5, 'story', 'activate'),
|
||||
(5, 'story', 'batchChangePlan'),
|
||||
(5, 'story', 'batchChangeBranch'),
|
||||
(5, 'story', 'batchChangeStage'),
|
||||
(5, 'story', 'batchClose'),
|
||||
(5, 'story', 'batchCreate'),
|
||||
@@ -1769,6 +1802,8 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(5, 'story', 'create'),
|
||||
(5, 'story', 'delete'),
|
||||
(5, 'story', 'edit'),
|
||||
(5, 'story', 'linkStory'),
|
||||
(5, 'story', 'unlinkStory'),
|
||||
(5, 'story', 'export'),
|
||||
(5, 'story', 'report'),
|
||||
(5, 'story', 'review'),
|
||||
@@ -1849,6 +1884,8 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(6, 'bug', 'delete'),
|
||||
(6, 'bug', 'deleteTemplate'),
|
||||
(6, 'bug', 'edit'),
|
||||
(6, 'bug', 'linkBugs'),
|
||||
(6, 'bug', 'unlinkBug'),
|
||||
(6, 'bug', 'export'),
|
||||
(6, 'bug', 'index'),
|
||||
(6, 'bug', 'report'),
|
||||
@@ -2056,6 +2093,8 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(7, 'bug', 'delete'),
|
||||
(7, 'bug', 'deleteTemplate'),
|
||||
(7, 'bug', 'edit'),
|
||||
(7, 'bug', 'linkBugs'),
|
||||
(7, 'bug', 'unlinkBug'),
|
||||
(7, 'bug', 'export'),
|
||||
(7, 'bug', 'index'),
|
||||
(7, 'bug', 'report'),
|
||||
@@ -2174,6 +2213,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(7, 'story', 'activate'),
|
||||
(7, 'story', 'batchAssignTo'),
|
||||
(7, 'story', 'batchChangePlan'),
|
||||
(7, 'story', 'batchChangeBranch'),
|
||||
(7, 'story', 'batchChangeStage'),
|
||||
(7, 'story', 'batchClose'),
|
||||
(7, 'story', 'batchCreate'),
|
||||
@@ -2184,6 +2224,8 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(7, 'story', 'create'),
|
||||
(7, 'story', 'delete'),
|
||||
(7, 'story', 'edit'),
|
||||
(7, 'story', 'linkStory'),
|
||||
(7, 'story', 'unlinkStory'),
|
||||
(7, 'story', 'export'),
|
||||
(7, 'story', 'report'),
|
||||
(7, 'story', 'review'),
|
||||
@@ -2264,6 +2306,8 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(8, 'bug', 'delete'),
|
||||
(8, 'bug', 'deleteTemplate'),
|
||||
(8, 'bug', 'edit'),
|
||||
(8, 'bug', 'linkBugs'),
|
||||
(8, 'bug', 'unlinkBug'),
|
||||
(8, 'bug', 'export'),
|
||||
(8, 'bug', 'index'),
|
||||
(8, 'bug', 'report'),
|
||||
@@ -2392,6 +2436,8 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(8, 'testcase', 'createBug'),
|
||||
(8, 'testcase', 'delete'),
|
||||
(8, 'testcase', 'edit'),
|
||||
(8, 'testcase', 'linkCases'),
|
||||
(8, 'testcase', 'unlinkCase'),
|
||||
(8, 'testcase', 'export'),
|
||||
(8, 'testcase', 'exportTemplet'),
|
||||
(8, 'testcase', 'groupCase'),
|
||||
@@ -2601,6 +2647,8 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(10, 'bug', 'close'),
|
||||
(10, 'bug', 'create'),
|
||||
(10, 'bug', 'edit'),
|
||||
(10, 'bug', 'linkBugs'),
|
||||
(10, 'bug', 'unlinkBug'),
|
||||
(10, 'bug', 'index'),
|
||||
(10, 'bug', 'report'),
|
||||
(10, 'bug', 'view'),
|
||||
|
||||
131
doc/CHANGELOG
131
doc/CHANGELOG
@@ -1,3 +1,134 @@
|
||||
2016-03-15 8.1.stable
|
||||
完成的功能:
|
||||
1864 调整后台设置计划任务时星号和后面文字的间距
|
||||
1863 调整版本发布页面的样式
|
||||
1861 计划需求列表页面增加全屏按钮,点击,隐藏右侧的侧边栏。
|
||||
1860 计划关联需求页面增加创建需求的链接
|
||||
1859 研发阶段计算没有考虑任务的关闭原因。
|
||||
1857 升级到最新的ZUI版本
|
||||
1856 去掉模块的修正数据功能
|
||||
1855 恢复桌面提醒工具的下载功能
|
||||
1854 增加限制ip登录的配置项
|
||||
1852 ie8下面详情页面有js报错 kindeditor未定义。
|
||||
1851 计划列表页面把按照详情排序去掉。
|
||||
1850 同级下面不应该有重名的模块。
|
||||
1842 项目-任务 前面显示关联需求所在的平台信息
|
||||
1838 优化邮件内容的样式
|
||||
1837 调整日志的逻辑,只有打开debug的情况下面再记录
|
||||
1836 检查mysqldump的检查逻辑是否还需要
|
||||
1834 编辑任务更换项目的时候检查指派人是否在新的项目团队中
|
||||
1832 提交测试的时候,增加抄送功能
|
||||
1830 项目需求关联列表支持批量移除需求
|
||||
1824 优化历史记录中比对的展示
|
||||
1817 列表页面滚动的时候表头固定
|
||||
1816 优化列表页面的全选和批量操作按钮
|
||||
1815 优化需求,bug,任务,用例提交页面的样式
|
||||
1814 优化备注信息的样式
|
||||
1813 级别和优先级的图标更换。增强其区分度。
|
||||
1805 实现mysql表的检查修复功能
|
||||
1803 调整底部升级到专业版的小图标
|
||||
1800 优化数据库的SQL索引。
|
||||
1661 详情页面的上一个,下一个按钮提示用户快捷键
|
||||
1658 梳理需求,任务,bug,用例之间的相关关系
|
||||
1516 插件的license支持全局的
|
||||
1344 搜索表单的保存查询,删除查询改用ajax。
|
||||
1244 美化邮件提醒的模板
|
||||
1201 增加不兼容浏览器的列表
|
||||
1192 如果有gd库,自动进行压缩
|
||||
1174 将todo/view/footer.html.php移到todo/common.js
|
||||
1171 删除的用户名字上没有加横线
|
||||
1087 调整代码高亮的展示形式
|
||||
947 将pathFix变量改用DIRECTORY_SEPERATOR的缩写DS
|
||||
945 处理common和commonmodel的关系和逻辑
|
||||
722 清除没有使用的语言条目
|
||||
441 将统计报表程序移至model层
|
||||
439 重构各个模块的browse方法
|
||||
377 处理多人同时编辑某一条记录的问题
|
||||
295 权限分组的时候可以按照部门来选择用户
|
||||
180 合并我的地盘和用户组织视图中的代码
|
||||
|
||||
修复的Bug
|
||||
804 处理备份还原错误的问题
|
||||
803 http://ranzhi.5upm.com/story-view-2020.html 打开空白
|
||||
785 批量编辑任务工时消耗可以写 负数
|
||||
794 编辑需求任务bug的时候原有内容中的空格不要去掉
|
||||
787 每日提醒功能,只有测试任务时的邮件标题不全
|
||||
772 需求评审无乱指派给谁最后结果都是指派给创建人
|
||||
745 加强dao里面对sql的过滤
|
||||
750 用例执行页面界面显示不全
|
||||
790 需求导出csv里面包含html标签
|
||||
789 项目-版本 关联bug搜索 所属产品下拉表为空
|
||||
795 bug标题中如果英文双引号和英文逗号(或句号)连在一起,导出csv格式数据会出现截断
|
||||
801 用例批量执行如果步骤太多无法显示预期
|
||||
792 后台-回收站 找到删除的用户,点击用户名查看资料获取不到数据
|
||||
793 产品-需求-待关闭 然后点击需求列表中某个需求的名称页面空白
|
||||
796 项目关联所有平台提交bug时候选择某一平台无法列出该项目
|
||||
800 移动web版本登录禅道后点击返回pc 显示 “badRequest”
|
||||
788 计划任务0不能填写
|
||||
|
||||
2015-11-13 7.4.beta
|
||||
完成的功能:
|
||||
1770 用户属性中的“加入时间”改成“入职时间”
|
||||
1696 把数据库缺少字段时候的报错记录到 tmp/php日志中。
|
||||
1749 统计-组织-员工负责表增加实际可用工作日天数选项
|
||||
1519 调整批量添加用户页面部门下拉列宽
|
||||
1630 统计-产品页面当所有产品都没有计划的时候也列出所有产品的列表信息
|
||||
1631 项目-版本提交测试自动同步版本所属产品信息
|
||||
1636 创建版本如果项目没有关联产品,出现一个关联页面的链接提示
|
||||
1640 调整统计报表功能的界面
|
||||
1695 需求和bug的关闭原因如果是重复的话显示重复的链接
|
||||
1697 bug的自定义模板检查重复逻辑调整
|
||||
1699 调整安装页面的首页
|
||||
1700 详情页面处理连续英文字符的内容
|
||||
1701 优化浏览器贴图的逻辑
|
||||
1711 产品增加类型设置
|
||||
1712 完成产品多分支的数据库设计
|
||||
1713 实现产品多分支的管理功能
|
||||
1714 实现产品分支的切换
|
||||
1715 可以为分支维护独立的模块
|
||||
1716 添加需求的时候可以选择分支或者平台
|
||||
1717 添加计划的时候可以选择分支或者平台
|
||||
1718 添加项目的时候可以选择产品的平台或者分支
|
||||
1719 为项目关联需求的时候检索逻辑调整
|
||||
1720 调整需求的研发阶段的计算逻辑
|
||||
1721 调整需求详情页面的研发阶段的展示
|
||||
1722 调整需求的发布的计算逻辑和显示
|
||||
1723 调整需求的等待关闭的的判断逻辑
|
||||
1724 为发布增加分支的管理
|
||||
1725 为bug增加分支管理
|
||||
1726 为用例增加分支管理
|
||||
1727 为版本增加分支管理
|
||||
1750 新增需求的时候产品列表不显示已关闭产品
|
||||
1752 项目创建任务的时候如果只关联一个产品的话,模块列表把产品去掉
|
||||
1756 发布增加停止维护操作
|
||||
1757 优化创建bug时候的版本检索逻辑
|
||||
1758 优化编辑bug时候版本的检索逻辑
|
||||
1759 优化创建bug时候的指派人列表功能
|
||||
1761 项目导入任务的时候可以选择显示所有可以导入的任务
|
||||
1769 发布的遗留bug改为手工关联
|
||||
1771 然之集成的时候可以提示用户进行绑定
|
||||
1772 一键安装包对路径的格式进行判断。
|
||||
1773 调整需求的创建页面
|
||||
1774 调整bug的创建页面
|
||||
1776 发信页面的sendcloud按钮样式调整下。
|
||||
1778 批量添加bug的时候把和需求相关的类型隐藏掉
|
||||
1779 计划需求列表页面增加转移计划的功能
|
||||
1780 计划关联需求的搜索结果页面增加排序功能和title提示
|
||||
1781 需求批量修改计划的时候只列最近的若干个,其他的搜索
|
||||
1782 按照计划搜索的时候,计划的下拉菜单更改其宽度
|
||||
1784 计划的需求列表页面的删除图标改为移除图标
|
||||
|
||||
修复的BUG:
|
||||
748 后台->二次开发->编辑器->用户-> setMenu等 扩展 API 打不开
|
||||
749 如果用例比较多测试-版本下面用例列表显示时间会比较长
|
||||
751 搜索时表单展开时,导出下拉菜单弹出时被遮挡
|
||||
752 组织权限 产品视图出现2个同名权限
|
||||
753 组织-用户搜索没有隐藏现在不用的字段信息
|
||||
754 创建任务页面的抄送人员列表出现 closed
|
||||
756 后台-备份中设置只保留几天的备份功能只能删除过期的sql不能删除file文件
|
||||
757 发布检查是否重复的时候不要计算已经删除的发布
|
||||
758 邮件设置如果出错之后,button的状态没有解除
|
||||
|
||||
2015-09-18 7.3.stable
|
||||
完成的功能:
|
||||
1632 需求、任务、bug、用例、文档的搜索功能的下拉框增加关键字快捷搜索功能
|
||||
|
||||
@@ -1 +1 @@
|
||||
升级,请参考 http://www.zentao.net/article-view-78960.html
|
||||
升级,请参考 http://www.zentao.net/book/zentaopmshelp/41.html
|
||||
|
||||
830
framework/base/control.class.php
Normal file
830
framework/base/control.class.php
Normal file
@@ -0,0 +1,830 @@
|
||||
<?php
|
||||
/**
|
||||
* ZenTaoPHP的baseControl类。
|
||||
* The baseControl class file of ZenTaoPHP framework.
|
||||
*
|
||||
* The author disclaims copyright to this source code. In place of
|
||||
* a legal notice, here is a blessing:
|
||||
*
|
||||
* May you do good and not evil.
|
||||
* May you find forgiveness for yourself and forgive others.
|
||||
* May you share freely, never taking more than you give.
|
||||
*/
|
||||
|
||||
/**
|
||||
* baseControl基类.
|
||||
* The base class of control.
|
||||
*
|
||||
* @package framework
|
||||
*/
|
||||
class baseControl
|
||||
{
|
||||
/**
|
||||
* 全局对象 $app。
|
||||
* The global $app object.
|
||||
*
|
||||
* @var object
|
||||
* @access public
|
||||
*/
|
||||
public $app;
|
||||
|
||||
/**
|
||||
* 应用名称 $appName
|
||||
* The global $appName.
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
public $appName;
|
||||
|
||||
/**
|
||||
* 全局对象 $config。
|
||||
* The global $config object.
|
||||
*
|
||||
* @var object
|
||||
* @access public
|
||||
*/
|
||||
public $config;
|
||||
|
||||
/**
|
||||
* 全局对象 $lang。
|
||||
* The global $lang object.
|
||||
*
|
||||
* @var object
|
||||
* @access public
|
||||
*/
|
||||
public $lang;
|
||||
|
||||
/**
|
||||
* 全局对象 $dbh,数据库连接句柄。
|
||||
* The global $dbh object, the database connection handler.
|
||||
*
|
||||
* @var object
|
||||
* @access public
|
||||
*/
|
||||
public $dbh;
|
||||
|
||||
/**
|
||||
* $dao对象,实现sql的拼装和执行。
|
||||
* The $dao object, used to join sql and excute sql.
|
||||
*
|
||||
* @var object
|
||||
* @access public
|
||||
*/
|
||||
public $dao;
|
||||
|
||||
/**
|
||||
* $post对象,用户可以通过$this->post->key来引用$_POST变量。
|
||||
* The $post object, useer can access a post var by $this->post->key.
|
||||
*
|
||||
* @var ojbect
|
||||
* @access public
|
||||
*/
|
||||
public $post;
|
||||
|
||||
/**
|
||||
* $get对象,用户可以通过$this->get->key来引用$_GET变量。
|
||||
* The $get object, useer can access a get var by $this->get->key.
|
||||
*
|
||||
* @var ojbect
|
||||
* @access public
|
||||
*/
|
||||
public $get;
|
||||
|
||||
/**
|
||||
* $session对象,用户可以通过$this->session->key来引用$_SESSION变量。
|
||||
* The $session object, useer can access a session var by $this->session->key.
|
||||
*
|
||||
* @var ojbect
|
||||
* @access public
|
||||
*/
|
||||
public $session;
|
||||
|
||||
/**
|
||||
* $server对象,用户可以通过$this->server->key来引用$_SERVER变量。
|
||||
* The $server object, useer can access a server var by $this->server->key.
|
||||
*
|
||||
* @var ojbect
|
||||
* @access public
|
||||
*/
|
||||
public $server;
|
||||
|
||||
/**
|
||||
* $cookie对象,用户可以通过$this->cookie->key来引用$_COOKIE变量。
|
||||
* The $cookie object, useer can access a cookie var by $this->cookie->key.
|
||||
*
|
||||
* @var ojbect
|
||||
* @access public
|
||||
*/
|
||||
public $cookie;
|
||||
|
||||
/**
|
||||
* 当前模块的名称。
|
||||
* The name of current module.
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
public $moduleName;
|
||||
|
||||
/**
|
||||
* $view用于存放从control传到view视图的数据。
|
||||
* The vars assigned to the view page.
|
||||
*
|
||||
* @var object
|
||||
* @access public
|
||||
*/
|
||||
public $view;
|
||||
|
||||
/**
|
||||
* 视图的类型,比如html, json。
|
||||
* The type of the view, such html, json.
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
public $viewType;
|
||||
|
||||
/**
|
||||
* 输出到浏览器的内容。
|
||||
* The content to display.
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
public $output;
|
||||
|
||||
/**
|
||||
* 客户端设备。
|
||||
* The client device.
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
public $clientDevice;
|
||||
|
||||
/**
|
||||
* 不同设备下视图文件的前缀。
|
||||
* The prefix of view file for mobile or PC.
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
public $devicePrefix;
|
||||
|
||||
/**
|
||||
* 构造方法。
|
||||
*
|
||||
* 1. 将全局变量设为baseControl类的成员变量,方便baseControl的派生类调用;
|
||||
* 2. 设置当前模块,读取该模块的model类;
|
||||
* 3. 初始化$view视图类。
|
||||
*
|
||||
* The construct function.
|
||||
*
|
||||
* 1. global the global vars, refer them by the class member such as $this->app.
|
||||
* 2. set the pathes of current module, and load it's model class.
|
||||
* 3. auto assign the $lang and $config to the view.
|
||||
*
|
||||
* @param string $moduleName
|
||||
* @param string $methodName
|
||||
* @param string $appName
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($moduleName = '', $methodName = '', $appName = '')
|
||||
{
|
||||
/*
|
||||
* 将全局变量设为baseControl类的成员变量,方便baseControl的派生类调用。
|
||||
* Global the globals, and refer them as a class member.
|
||||
*/
|
||||
global $app, $config, $lang, $dbh, $common;
|
||||
$this->app = $app;
|
||||
$this->config = $config;
|
||||
$this->lang = $lang;
|
||||
$this->dbh = $dbh;
|
||||
$this->viewType = $this->app->getViewType();
|
||||
$this->appName = $appName ? $appName : $this->app->getAppName();
|
||||
|
||||
/**
|
||||
* 设置当前模块,读取该模块的model类。
|
||||
* Load the model file auto.
|
||||
*/
|
||||
$this->setModuleName($moduleName);
|
||||
$this->setMethodName($methodName);
|
||||
$this->loadModel($this->moduleName, $appName);
|
||||
|
||||
/**
|
||||
* 如果客户端是手机的话,视图文件增加m.前缀。
|
||||
* If the clent is mobile, add m. as prefix for view file.
|
||||
*/
|
||||
$this->setClientDevice();
|
||||
$this->setDevicePrefix();
|
||||
|
||||
/**
|
||||
* 初始化$view视图类。
|
||||
* Init the view vars.
|
||||
*/
|
||||
$this->view = new stdclass();
|
||||
$this->view->app = $app;
|
||||
$this->view->lang = $lang;
|
||||
$this->view->config = $config;
|
||||
$this->view->common = $common;
|
||||
$this->view->title = '';
|
||||
|
||||
/**
|
||||
* 设置超级变量,从$app引用过来。
|
||||
* Set super vars.
|
||||
*/
|
||||
$this->setSuperVars();
|
||||
}
|
||||
|
||||
//-------------------- Model相关方法(Model related methods) --------------------//
|
||||
|
||||
/*
|
||||
* 设置模块名。
|
||||
* Set the module name.
|
||||
*
|
||||
* @param string $moduleName 模块名,如果为空,则从$app中获取. The module name, if empty, get it from $app.
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setModuleName($moduleName = '')
|
||||
{
|
||||
$this->moduleName = $moduleName ? strtolower($moduleName) : $this->app->getModuleName();
|
||||
}
|
||||
|
||||
/**
|
||||
* set the method name.
|
||||
* 设置方法名。
|
||||
*
|
||||
* @param string $methodName 方法名,如果为空,则从$app中获取。The method name, if empty, get it from $app.
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setMethodName($methodName = '')
|
||||
{
|
||||
$this->methodName = $methodName ? strtolower($methodName) : $this->app->getMethodName();
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载指定模块的model文件。
|
||||
* Load the model file of one module.
|
||||
*
|
||||
* @param string $moduleName 模块名,如果为空,使用当前模块。The module name, if empty, use current module's name.
|
||||
* @param string $appName The app name, if empty, use current app's name.
|
||||
* @access public
|
||||
* @return object|bool 如果没有model文件,返回false,否则返回model对象。If no model file, return false, else return the model object.
|
||||
*/
|
||||
public function loadModel($moduleName = '', $appName = '')
|
||||
{
|
||||
if(empty($moduleName)) $moduleName = $this->moduleName;
|
||||
if(empty($appName)) $appName = $this->appName;
|
||||
$modelFile = helper::setModelFile($moduleName, $appName);
|
||||
|
||||
/**
|
||||
* 如果没有model文件,尝试加载config配置信息。
|
||||
* If no model file, try load config.
|
||||
*/
|
||||
if(!helper::import($modelFile))
|
||||
{
|
||||
$this->app->loadConfig($moduleName, $appName, false);
|
||||
$this->app->loadLang($moduleName, $appName);
|
||||
$this->dao = new dao();
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果没有扩展文件,model类名是$moduleName + 'model',如果有扩展,还需要增加ext前缀。
|
||||
* If no extension file, model class name is $moduleName + 'model', else with 'ext' as the prefix.
|
||||
*/
|
||||
$modelClass = class_exists('ext' . $appName . $moduleName. 'model') ? 'ext' . $appName . $moduleName . 'model' : $appName . $moduleName . 'model';
|
||||
if(!class_exists($modelClass))
|
||||
{
|
||||
$modelClass = class_exists('ext' . $moduleName. 'model') ? 'ext' . $moduleName . 'model' : $moduleName . 'model';
|
||||
if(!class_exists($modelClass)) $this->app->triggerError(" The model $modelClass not found", __FILE__, __LINE__, $exit = true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化model对象,在control对象中可以通过$this->$moduleName来引用。同时将dao对象赋为control对象的成员变量,方便引用。
|
||||
* Init the model object thus you can try $this->$moduleName to access it. Also assign the $dao object as a member of control object.
|
||||
*/
|
||||
$this->$moduleName = new $modelClass($appName);
|
||||
$this->dao = $this->$moduleName->dao;
|
||||
return $this->$moduleName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置超级全局变量,方便直接引用。
|
||||
* Set the super vars.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setSuperVars()
|
||||
{
|
||||
$this->post = $this->app->post;
|
||||
$this->get = $this->app->get;
|
||||
$this->server = $this->app->server;
|
||||
$this->session = $this->app->session;
|
||||
$this->cookie = $this->app->cookie;
|
||||
$this->global = $this->app->global;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置客户端的设备类型。
|
||||
* Set client device.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setClientDevice()
|
||||
{
|
||||
$this->clientDevice = $this->app->clientDevice;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果客户端是手机的话,视图文件增加m.前缀。
|
||||
* If the clent is mobile, add m. as prefix for view file.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setDevicePrefix()
|
||||
{
|
||||
$this->devicePrefix = zget($this->config->devicePrefix, $this->viewType, '');
|
||||
}
|
||||
|
||||
//-------------------- 视图相关方法(View related methods) --------------------//
|
||||
|
||||
/**
|
||||
* 设置视图文件:主视图文件,扩展视图文件, 站点扩展视图文件,以及钩子脚本。
|
||||
* Set view files: the main file, extension view file, site extension view file and hook files.
|
||||
*
|
||||
* @param string $moduleName module name
|
||||
* @param string $methodName method name
|
||||
* @access public
|
||||
* @return string the view file
|
||||
*/
|
||||
public function setViewFile($moduleName, $methodName)
|
||||
{
|
||||
$moduleName = strtolower(trim($moduleName));
|
||||
$methodName = strtolower(trim($methodName));
|
||||
|
||||
$modulePath = $this->app->getModulePath($this->appName, $moduleName);
|
||||
$viewExtPath = $this->app->getModuleExtPath($this->appName, $moduleName, 'view');
|
||||
$viewType = $this->viewType == 'mhtml' ? 'html' : $this->viewType;
|
||||
|
||||
$mainViewFile = $modulePath . 'view' . DS . $this->devicePrefix . $methodName . '.' . $viewType . '.php';
|
||||
$commonExtViewFile = $viewExtPath['common'] . $this->devicePrefix . $methodName . ".{$viewType}.php";
|
||||
$siteExtViewFile = empty($viewExtPath['site']) ? '' : $viewExtPath['site'] . $this->devicePrefix . $methodName . ".{$viewType}.php";
|
||||
|
||||
$viewFile = file_exists($commonExtViewFile) ? $commonExtViewFile : $mainViewFile;
|
||||
$viewFile = (!empty($siteExtViewFile) and file_exists($siteExtViewFile)) ? $siteExtViewFile : $viewFile;
|
||||
if(!is_file($viewFile)) $this->app->triggerError("the view file $viewFile not found", __FILE__, __LINE__, $exit = true);
|
||||
|
||||
$commonExtHookFiles = glob($viewExtPath['common'] . $this->devicePrefix . $methodName . ".*.{$viewType}.hook.php");
|
||||
$siteExtHookFiles = empty($viewExtPath['site']) ? '' : glob($viewExtPath['site'] . $this->devicePrefix . $methodName . ".*.{$viewType}.hook.php");
|
||||
$extHookFiles = array_merge((array) $commonExtHookFiles, (array) $siteExtHookFiles);
|
||||
|
||||
if(!empty($extHookFiles)) return array('viewFile' => $viewFile, 'hookFiles' => $extHookFiles);
|
||||
return $viewFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某一个视图文件的扩展。
|
||||
* Get the extension file of an view.
|
||||
*
|
||||
* @param string $viewFile
|
||||
* @access public
|
||||
* @return string|bool If extension view file exists, return the path. Else return fasle.
|
||||
*/
|
||||
public function getExtViewFile($viewFile)
|
||||
{
|
||||
/**
|
||||
* 首先找sitecode下的扩展文件,如果没有,再找ext下的扩展文件。
|
||||
* Find extViewFile in ext/_$siteCode/view first, then try ext/view/.
|
||||
*/
|
||||
if($this->config->site->code)
|
||||
{
|
||||
$extPath = dirname(dirname(realpath($viewFile))) . "/ext/_{$this->config->site->code}/view";
|
||||
$extViewFile = $extPath . basename($viewFile);
|
||||
|
||||
if(file_exists($extViewFile))
|
||||
{
|
||||
helper::cd($extPath);
|
||||
return $extViewFile;
|
||||
}
|
||||
}
|
||||
|
||||
$extPath = dirname(dirname(realpath($viewFile))) . '/ext/view/';
|
||||
$extViewFile = $extPath . basename($viewFile);
|
||||
if(file_exists($extViewFile))
|
||||
{
|
||||
helper::cd($extPath);
|
||||
return $extViewFile;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取适用于当前方法的css:该模块公用的css + 当前方法的css + 扩展的css。
|
||||
* Get css codes applied to current method: module common css + method css + extension css.
|
||||
*
|
||||
* @param string $moduleName
|
||||
* @param string $methodName
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function getCSS($moduleName, $methodName)
|
||||
{
|
||||
$moduleName = strtolower(trim($moduleName));
|
||||
$methodName = strtolower(trim($methodName));
|
||||
|
||||
$modulePath = $this->app->getModulePath($this->appName, $moduleName);
|
||||
$cssExtPath = $this->app->getModuleExtPath($this->appName, $moduleName, 'css') ;
|
||||
$cssMethodExt = $cssExtPath['common'] . $methodName . DS;
|
||||
$cssCommonExt = $cssExtPath['common'] . 'common' . DS;
|
||||
|
||||
$css = '';
|
||||
$mainCssFile = $modulePath . 'css' . DS . $this->devicePrefix . 'common.css';
|
||||
$methodCssFile = $modulePath . 'css' . DS . $this->devicePrefix . $methodName . '.css';
|
||||
if(file_exists($mainCssFile)) $css .= file_get_contents($mainCssFile);
|
||||
if(is_file($methodCssFile)) $css .= file_get_contents($methodCssFile);
|
||||
|
||||
$cssExtFiles = glob($cssCommonExt . $this->devicePrefix . '*.css');
|
||||
if(!empty($cssExtFiles) and is_array($cssExtFiles)) foreach($cssExtFiles as $cssFile) $css .= file_get_contents($cssFile);
|
||||
|
||||
$cssExtFiles = glob($cssMethodExt . $this->devicePrefix . '*.css');
|
||||
if(!empty($cssExtFiles) and is_array($cssExtFiles)) foreach($cssExtFiles as $cssFile) $css .= file_get_contents($cssFile);
|
||||
|
||||
if(!empty($cssExtPath['site']))
|
||||
{
|
||||
$cssMethodExt = $cssExtPath['site'] . $methodName . DS;
|
||||
$cssCommonExt = $cssExtPath['site'] . 'common' . DS;
|
||||
$cssExtFiles = glob($cssCommonExt . $this->devicePrefix . '*.css');
|
||||
if(!empty($cssExtFiles) and is_array($cssExtFiles)) foreach($cssExtFiles as $cssFile) $css .= file_get_contents($cssFile);
|
||||
|
||||
$cssExtFiles = glob($cssMethodExt . $this->devicePrefix . '*.css');
|
||||
if(!empty($cssExtFiles) and is_array($cssExtFiles)) foreach($cssExtFiles as $cssFile) $css .= file_get_contents($cssFile);
|
||||
}
|
||||
|
||||
return $css;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取适用于当前方法的js:该模块公用的js + 当前方法的js + 扩展的js。
|
||||
* Get js codes applied to current method: module common js + method js + extension js.
|
||||
*
|
||||
* @param string $moduleName
|
||||
* @param string $methodName
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function getJS($moduleName, $methodName)
|
||||
{
|
||||
$moduleName = strtolower(trim($moduleName));
|
||||
$methodName = strtolower(trim($methodName));
|
||||
|
||||
$modulePath = $this->app->getModulePath($this->appName, $moduleName);
|
||||
$jsExtPath = $this->app->getModuleExtPath($this->appName, $moduleName, 'js');
|
||||
$jsMethodExt = $jsExtPath['common'] . $methodName . DS;
|
||||
$jsCommonExt = $jsExtPath['common'] . 'common' . DS;
|
||||
|
||||
$js = '';
|
||||
$mainJsFile = $modulePath . 'js' . DS . $this->devicePrefix . 'common.js';
|
||||
$methodJsFile = $modulePath . 'js' . DS . $this->devicePrefix . $methodName . '.js';
|
||||
if(file_exists($mainJsFile)) $js .= file_get_contents($mainJsFile);
|
||||
if(is_file($methodJsFile)) $js .= file_get_contents($methodJsFile);
|
||||
|
||||
$jsExtFiles = glob($jsCommonExt . $this->devicePrefix . '*.js');
|
||||
if(!empty($jsExtFiles) and is_array($jsExtFiles)) foreach($jsExtFiles as $jsFile) $js .= file_get_contents($jsFile);
|
||||
|
||||
$jsExtFiles = glob($jsMethodExt . $this->devicePrefix . '*.js');
|
||||
if(!empty($jsExtFiles) and is_array($jsExtFiles)) foreach($jsExtFiles as $jsFile) $js .= file_get_contents($jsFile);
|
||||
|
||||
if(!empty($jsExtPath['site']))
|
||||
{
|
||||
$jsMethodExt = $jsExtPath['site'] . $methodName . DS;
|
||||
$jsCommonExt = $jsExtPath['site'] . 'common' . DS;
|
||||
|
||||
$jsExtFiles = glob($jsCommonExt . $this->devicePrefix . '*.js');
|
||||
if(!empty($jsExtFiles) and is_array($jsExtFiles)) foreach($jsExtFiles as $jsFile) $js .= file_get_contents($jsFile);
|
||||
|
||||
$jsExtFiles = glob($jsMethodExt . $this->devicePrefix . '*.js');
|
||||
if(!empty($jsExtFiles) and is_array($jsExtFiles)) foreach($jsExtFiles as $jsFile) $js .= file_get_contents($jsFile);
|
||||
}
|
||||
|
||||
return $js;
|
||||
}
|
||||
|
||||
/**
|
||||
* 向$view传递一个变量。
|
||||
* Assign one var to the view vars.
|
||||
*
|
||||
* @param string $name the name.
|
||||
* @param mixed $value the value.
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function assign($name, $value)
|
||||
{
|
||||
$this->view->$name = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空$output。
|
||||
* Clear the output.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$this->output = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染视图文件。
|
||||
* Parse view file.
|
||||
*
|
||||
* @param string $moduleName module name, if empty, use current module.
|
||||
* @param string $methodName method name, if empty, use current method.
|
||||
* @access public
|
||||
* @return string the parsed result.
|
||||
*/
|
||||
public function parse($moduleName = '', $methodName = '')
|
||||
{
|
||||
if(empty($moduleName)) $moduleName = $this->moduleName;
|
||||
if(empty($methodName)) $methodName = $this->methodName;
|
||||
|
||||
if($this->viewType == 'json') $this->parseJSON($moduleName, $methodName);
|
||||
if($this->viewType != 'json') $this->parseDefault($moduleName, $methodName);
|
||||
|
||||
return $this->output;
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染json格式。
|
||||
* Parse json format.
|
||||
*
|
||||
* @param string $moduleName module name
|
||||
* @param string $methodName method name
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function parseJSON($moduleName, $methodName)
|
||||
{
|
||||
unset($this->view->app);
|
||||
unset($this->view->config);
|
||||
unset($this->view->lang);
|
||||
unset($this->view->header);
|
||||
unset($this->view->position);
|
||||
unset($this->view->moduleTree);
|
||||
unset($this->view->common);
|
||||
unset($this->view->pager->app);
|
||||
unset($this->view->pager->lang);
|
||||
|
||||
$output['status'] = is_object($this->view) ? 'success' : 'fail';
|
||||
$output['data'] = json_encode($this->view);
|
||||
$output['md5'] = md5(json_encode($this->view));
|
||||
|
||||
$this->output = json_encode($output);
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* 默认渲染方法,适用于viewType = html的时候。
|
||||
* Default parse method when viewType != json, like html.
|
||||
*
|
||||
* @param string $moduleName module name
|
||||
* @param string $methodName method name
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function parseDefault($moduleName, $methodName)
|
||||
{
|
||||
/**
|
||||
* 设置视图文件。(PHP7有一个bug,不能直接$viewFile = $this->setViewFile())。
|
||||
* Set viewFile. (Can't assign $viewFile = $this->setViewFile() directly because one php7's bug.)
|
||||
*/
|
||||
$results = $this->setViewFile($moduleName, $methodName);
|
||||
$viewFile = $results;
|
||||
if(is_array($results)) extract($results);
|
||||
|
||||
/**
|
||||
* 获得当前页面的CSS和JS。
|
||||
* Get css and js codes for current method.
|
||||
*/
|
||||
$css = $this->getCSS($moduleName, $methodName);
|
||||
$js = $this->getJS($moduleName, $methodName);
|
||||
if($css) $this->view->pageCSS = $css;
|
||||
if($js) $this->view->pageJS = $js;
|
||||
|
||||
/**
|
||||
* 切换到视图文件所在的目录,以保证视图文件里面的include语句能够正常运行。
|
||||
* Change the dir to the view file to keep the relative pathes work.
|
||||
*/
|
||||
$currentPWD = getcwd();
|
||||
chdir(dirname($viewFile));
|
||||
|
||||
/**
|
||||
* 使用extract安定ob方法渲染$viewFile里面的代码。
|
||||
* Use extract and ob functions to eval the codes in $viewFile.
|
||||
*/
|
||||
extract((array)$this->view);
|
||||
ob_start();
|
||||
include $viewFile;
|
||||
if(isset($hookFiles)) foreach($hookFiles as $hookFile) if(file_exists($hookFile)) include $hookFile;
|
||||
$this->output .= ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
/**
|
||||
* 渲染完毕后,再切换回之前的路径。
|
||||
* At the end, chang the dir to the previous.
|
||||
*/
|
||||
chdir($currentPWD);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取一个方法的输出内容,这样我们可以在一个方法里获取其他模块方法的内容。
|
||||
* 如果模块名为空,则调用该模块、该方法;如果设置了模块名,调用指定模块指定方法。
|
||||
*
|
||||
* Get the output of one module's one method as a string, thus in one module's method, can fetch other module's content.
|
||||
* If the module name is empty, then use the current module and method. If set, use the user defined module and method.
|
||||
*
|
||||
* @param string $moduleName module name.
|
||||
* @param string $methodName method name.
|
||||
* @param array $params params.
|
||||
* @access public
|
||||
* @return string the parsed html.
|
||||
*/
|
||||
public function fetch($moduleName = '', $methodName = '', $params = array(), $appName = '')
|
||||
{
|
||||
if($moduleName == '') $moduleName = $this->moduleName;
|
||||
if($methodName == '') $methodName = $this->methodName;
|
||||
if($appName == '') $appName = $this->appName;
|
||||
if($moduleName == $this->moduleName and $methodName == $this->methodName)
|
||||
{
|
||||
$this->parse($moduleName, $methodName);
|
||||
return $this->output;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置引用的文件和路径。
|
||||
* Set the pathes and files to included.
|
||||
**/
|
||||
$modulePath = $this->app->getModulePath($appName, $moduleName);
|
||||
$moduleControlFile = $modulePath . 'control.php';
|
||||
$actionExtPath = $this->app->getModuleExtPath($appName, $moduleName, 'control');
|
||||
|
||||
$commonActionExtFile = $actionExtPath['common'] . strtolower($methodName) . '.php';
|
||||
$file2Included = file_exists($commonActionExtFile) ? $commonActionExtFile : $moduleControlFile;
|
||||
if(!empty($actionExtPath['site']))
|
||||
{
|
||||
$siteActionExtFile = $actionExtPath['site'] . strtolower($methodName) . '.php';
|
||||
$file2Included = file_exists($siteActionExtFile) ? $siteActionExtFile : $file2Included;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载控制器文件。
|
||||
* Load the control file.
|
||||
*/
|
||||
if(!is_file($file2Included)) $this->app->triggerError("The control file $file2Included not found", __FILE__, __LINE__, $exit = true);
|
||||
$currentPWD = getcwd();
|
||||
chdir(dirname($file2Included));
|
||||
if($moduleName != $this->moduleName) helper::import($file2Included);
|
||||
|
||||
/**
|
||||
* 设置调用的类名。
|
||||
* Set the name of the class to be called.
|
||||
*/
|
||||
$className = class_exists("my$moduleName") ? "my$moduleName" : $moduleName;
|
||||
if(!class_exists($className)) $this->app->triggerError(" The class $className not found", __FILE__, __LINE__, $exit = true);
|
||||
|
||||
/**
|
||||
* 解析参数,创建模块control对象。
|
||||
* Parse the params, create the $module control object.
|
||||
*/
|
||||
if(!is_array($params)) parse_str($params, $params);
|
||||
$module = new $className($moduleName, $methodName, $appName);
|
||||
|
||||
/**
|
||||
* 调用对应方法,使用ob方法获取输出内容。
|
||||
* Call the method and use ob function to get the output.
|
||||
*/
|
||||
ob_start();
|
||||
call_user_func_array(array($module, $methodName), $params);
|
||||
$output = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
/**
|
||||
* 返回内容。
|
||||
* Return the content.
|
||||
*/
|
||||
unset($module);
|
||||
chdir($currentPWD);
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* 向浏览器输出内容。
|
||||
* Print the content of the view.
|
||||
*
|
||||
* @param string $moduleName module name
|
||||
* @param string $methodName method name
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function display($moduleName = '', $methodName = '')
|
||||
{
|
||||
if(empty($this->output)) $this->parse($moduleName, $methodName);
|
||||
echo $this->output;
|
||||
}
|
||||
|
||||
/**
|
||||
* 直接输出data数据,通常用于ajax请求中。
|
||||
* Send data directly, for ajax requests.
|
||||
*
|
||||
* @param misc $data
|
||||
* @param string $type
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function send($data, $type = 'json')
|
||||
{
|
||||
if($type != 'json') die();
|
||||
|
||||
$data = (array) $data;
|
||||
if(helper::isAjaxRequest()) print(json_encode($data)) and die(helper::removeUTF8Bom(ob_get_clean()));
|
||||
|
||||
/**
|
||||
* 响应非ajax的请求。
|
||||
* Response request not ajax.
|
||||
*/
|
||||
if(isset($data['result']) and $data['result'] == 'success')
|
||||
{
|
||||
if(!empty($data['message'])) echo js::alert($data['message']);
|
||||
$locate = isset($data['locate']) ? $data['locate'] : (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '');
|
||||
if(!empty($locate)) die(js::locate($locate));
|
||||
die(isset($data['message']) ? $data['message'] : 'success');
|
||||
}
|
||||
|
||||
if(isset($data['result']) and $data['result'] == 'fail')
|
||||
{
|
||||
if(!empty($data['message']))
|
||||
{
|
||||
$message = json_decode(json_encode((array)$data['message']));
|
||||
foreach((array)$message as $item => $errors) $message->$item = implode(',', $errors);
|
||||
echo js::alert(strip_tags(implode(" ", (array) $message)));
|
||||
die(js::locate('back'));
|
||||
}
|
||||
die('fail');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个模块方法的链接。
|
||||
* Create a link to one method of one module.
|
||||
*
|
||||
* @param string $moduleName module name
|
||||
* @param string $methodName method name
|
||||
* @param string|array $vars the params passed, can be array(key=>value) or key1=value1&key2=value2
|
||||
* @param string $viewType the view type
|
||||
* @access public
|
||||
* @return string the link string.
|
||||
*/
|
||||
public function createLink($moduleName, $methodName = 'index', $vars = array(), $viewType = '', $onlybody = false)
|
||||
{
|
||||
if(empty($moduleName)) $moduleName = $this->moduleName;
|
||||
return helper::createLink($moduleName, $methodName, $vars, $viewType, $onlybody);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建当前模块的一个方法链接。
|
||||
* Create a link to the inner method of current module.
|
||||
*
|
||||
* @param string $methodName method name
|
||||
* @param string|array $vars the params passed, can be array(key=>value) or key1=value1&key2=value2
|
||||
* @param string $viewType the view type
|
||||
* @access public
|
||||
* @return string the link string.
|
||||
*/
|
||||
public function inlink($methodName = 'index', $vars = array(), $viewType = '', $onlybody = false)
|
||||
{
|
||||
return helper::createLink($this->moduleName, $methodName, $vars, $viewType, $onlybody);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重定向到另一个页面。
|
||||
* Location to another page.
|
||||
*
|
||||
* @param string $url the target url.
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function locate($url)
|
||||
{
|
||||
header("location: $url");
|
||||
exit;
|
||||
}
|
||||
}
|
||||
1260
framework/base/helper.class.php
Normal file
1260
framework/base/helper.class.php
Normal file
File diff suppressed because it is too large
Load Diff
290
framework/base/model.class.php
Normal file
290
framework/base/model.class.php
Normal file
@@ -0,0 +1,290 @@
|
||||
<?php
|
||||
/**
|
||||
* ZenTaoPHP的baseModel类。
|
||||
* The baseModel class file of ZenTaoPHP framework.
|
||||
*
|
||||
* The author disclaims copyright to this source code. In place of
|
||||
* a legal notice, here is a blessing:
|
||||
*
|
||||
* May you do good and not evil.
|
||||
* May you find forgiveness for yourself and forgive others.
|
||||
* May you share freely, never taking more than you give.
|
||||
*/
|
||||
|
||||
/**
|
||||
* baseModel基类。
|
||||
* The base class of model.
|
||||
*
|
||||
* @package framework
|
||||
*/
|
||||
class baseModel
|
||||
{
|
||||
/**
|
||||
* 全局对象$app。
|
||||
* The global $app object.
|
||||
*
|
||||
* @var object
|
||||
* @access public
|
||||
*/
|
||||
public $app;
|
||||
|
||||
/**
|
||||
* 应用名称$appName。
|
||||
* The global appName.
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
public $appName;
|
||||
|
||||
/**
|
||||
* 全局对象$config。
|
||||
* The global $config object.
|
||||
*
|
||||
* @var object
|
||||
* @access public
|
||||
*/
|
||||
public $config;
|
||||
|
||||
/**
|
||||
* 全局对象$lang。
|
||||
* The global $lang object.
|
||||
*
|
||||
* @var object
|
||||
* @access public
|
||||
*/
|
||||
public $lang;
|
||||
|
||||
/**
|
||||
* 全局对象$dbh,数据库连接句柄。
|
||||
* The global $dbh object, the database connection handler.
|
||||
*
|
||||
* @var object
|
||||
* @access public
|
||||
*/
|
||||
public $dbh;
|
||||
|
||||
/**
|
||||
* $dao对象,用于访问或者更新数据库。
|
||||
* The $dao object, used to access or update database.
|
||||
*
|
||||
* @var object
|
||||
* @access public
|
||||
*/
|
||||
public $dao;
|
||||
|
||||
/**
|
||||
* $post对象,用于访问$_POST变量。
|
||||
* The $post object, used to access the $_POST var.
|
||||
*
|
||||
* @var ojbect
|
||||
* @access public
|
||||
*/
|
||||
public $post;
|
||||
|
||||
/**
|
||||
* $get对象,用于访问$_GET变量。
|
||||
* The $get object, used to access the $_GET var.
|
||||
*
|
||||
* @var ojbect
|
||||
* @access public
|
||||
*/
|
||||
public $get;
|
||||
|
||||
/**
|
||||
* $session对象,用于访问$_SESSION变量。
|
||||
* The $session object, used to access the $_SESSION var.
|
||||
*
|
||||
* @var ojbect
|
||||
* @access public
|
||||
*/
|
||||
public $session;
|
||||
|
||||
/**
|
||||
* $server对象,用于访问$_SERVER变量。
|
||||
* The $server object, used to access the $_SERVER var.
|
||||
*
|
||||
* @var ojbect
|
||||
* @access public
|
||||
*/
|
||||
public $server;
|
||||
|
||||
/**
|
||||
* $cookie对象,用于访问$_COOKIE变量。
|
||||
* The $cookie object, used to access the $_COOKIE var.
|
||||
*
|
||||
* @var ojbect
|
||||
* @access public
|
||||
*/
|
||||
public $cookie;
|
||||
|
||||
/**
|
||||
* $global对象,用于访问$_GLOBAL变量。
|
||||
* The $global object, used to access the $_GLOBAL var.
|
||||
*
|
||||
* @var ojbect
|
||||
* @access public
|
||||
*/
|
||||
public $global;
|
||||
|
||||
/**
|
||||
* 构造方法。
|
||||
* 1. 将全局变量设为model类的成员变量,方便model的派生类调用;
|
||||
* 2. 设置$config, $lang, $dbh, $dao。
|
||||
*
|
||||
* The construct function.
|
||||
* 1. global the global vars, refer them by the class member such as $this->app.
|
||||
* 2. set the pathes, config, lang of current module
|
||||
*
|
||||
* @param string $appName
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($appName = '')
|
||||
{
|
||||
global $app, $config, $lang, $dbh;
|
||||
$this->app = $app;
|
||||
$this->config = $config;
|
||||
$this->lang = $lang;
|
||||
$this->dbh = $dbh;
|
||||
$this->appName = empty($appName) ? $this->app->getAppName() : $appName;
|
||||
|
||||
$moduleName = $this->getModuleName();
|
||||
$this->app->loadLang($moduleName, $this->appName);
|
||||
$this->app->loadConfig($moduleName, $this->appName, $exitIfNone = false);
|
||||
|
||||
$this->loadDAO();
|
||||
$this->setSuperVars();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取该model的模块名,而不是用户请求的模块名。
|
||||
*
|
||||
* 这个方法通过去掉该model类名的'ext'和'model'字符串,来获取当前模块名。
|
||||
* 不要使用$app->getModuleName(),因为其返回的是用户请求的模块名。
|
||||
* 另一个model可以通过loadModel()加载进来,与请求的模块名不一致。
|
||||
*
|
||||
* Get the module name of this model. Not the module user visiting.
|
||||
*
|
||||
* This method replace the 'ext' and 'model' string from the model class name, thus get the module name.
|
||||
* Not using $app->getModuleName() because it return the module user is visiting. But one module can be
|
||||
* loaded by loadModel() so we must get the module name of this model.
|
||||
*
|
||||
* @access public
|
||||
* @return string the module name.
|
||||
*/
|
||||
public function getModuleName()
|
||||
{
|
||||
$parentClass = get_parent_class($this);
|
||||
$selfClass = get_class($this);
|
||||
$className = $parentClass == 'model' ? $selfClass : $parentClass;
|
||||
if($className == 'extensionModel') return 'extension';
|
||||
return strtolower(str_ireplace(array('ext', 'Model'), '', $className));
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置全局超级变量。
|
||||
* Set the super vars.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setSuperVars()
|
||||
{
|
||||
$this->post = $this->app->post;
|
||||
$this->get = $this->app->get;
|
||||
$this->server = $this->app->server;
|
||||
$this->cookie = $this->app->cookie;
|
||||
$this->session = $this->app->session;
|
||||
$this->global = $this->app->global;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载一个模块的model。加载完成后,使用$this->$moduleName来访问这个model对象。
|
||||
* 比如:loadModel('user')引入user模块的model实例对象,可以通过$this->user来访问它。
|
||||
*
|
||||
* Load the model of one module. After loaded, can use $this->$moduleName to visit the model object.
|
||||
*
|
||||
* @param string $moduleName
|
||||
* @access public
|
||||
* @return object|bool the model object or false if model file not exists.
|
||||
*/
|
||||
public function loadModel($moduleName, $appName = '')
|
||||
{
|
||||
if(empty($moduleName)) return false;
|
||||
if(empty($appName)) $appName = $this->appName;
|
||||
$modelFile = helper::setModelFile($moduleName, $appName);
|
||||
|
||||
if(!helper::import($modelFile)) return false;
|
||||
$modelClass = class_exists('ext' . $appName . $moduleName. 'model') ? 'ext' . $appName . $moduleName . 'model' : $appName . $moduleName . 'model';
|
||||
if(!class_exists($modelClass))
|
||||
{
|
||||
$modelClass = class_exists('ext' . $moduleName. 'model') ? 'ext' . $moduleName . 'model' : $moduleName . 'model';
|
||||
if(!class_exists($modelClass)) $this->app->triggerError(" The model $modelClass not found", __FILE__, __LINE__, $exit = true);
|
||||
}
|
||||
|
||||
$this->$moduleName = new $modelClass($appName);
|
||||
return $this->$moduleName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载model的class扩展。
|
||||
* Load extension class of a model. Saved to $moduleName/ext/model/class/$extensionName.class.php.
|
||||
*
|
||||
* @param string $extensionName
|
||||
* @param string $moduleName
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function loadExtension($extensionName, $moduleName = '')
|
||||
{
|
||||
if(empty($extensionName)) return false;
|
||||
|
||||
/* Set extenson name and extension file. */
|
||||
$extensionName = strtolower($extensionName);
|
||||
$moduleName = $moduleName ? $moduleName : $this->getModuleName();
|
||||
$moduleExtPath = $this->app->getModuleExtPath($this->appName, $moduleName, 'model');
|
||||
if(!empty($moduleExtPath['site']))$extensionFile = $moduleExtPath['site'] . 'class/' . $extensionName . '.class.php';
|
||||
if(!isset($extensionFile) or !file_exists($extensionFile)) $extensionFile = $moduleExtPath['common'] . 'class/' . $extensionName . '.class.php';
|
||||
|
||||
/* Try to import parent model file auto and then import the extension file. */
|
||||
if(!class_exists($moduleName . 'Model')) helper::import($this->app->getModulePath($this->appName, $moduleName) . 'model.php');
|
||||
if(!helper::import($extensionFile)) return false;
|
||||
|
||||
/* Set the extension class name. */
|
||||
$extensionClass = $extensionName . ucfirst($moduleName);
|
||||
if(!class_exists($extensionClass)) return false;
|
||||
|
||||
/* Create an instance of the extension class and return it. */
|
||||
$extensionObject = new $extensionClass;
|
||||
$extensionClass = str_replace('Model', '', $extensionClass);
|
||||
$this->$extensionClass = $extensionObject;
|
||||
return $extensionObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载DAO。
|
||||
* Load DAO.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function loadDAO()
|
||||
{
|
||||
$this->dao = $this->app->loadClass('dao');
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除记录
|
||||
* Delete one record.
|
||||
*
|
||||
* @param string $table the table name
|
||||
* @param string $id the id value of the record to be deleted
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function delete($table, $id)
|
||||
{
|
||||
$this->dao->delete()->from($table)->where('id')->eq($id)->exec();
|
||||
}
|
||||
}
|
||||
2241
framework/base/router.class.php
Normal file
2241
framework/base/router.class.php
Normal file
File diff suppressed because it is too large
Load Diff
631
framework/control.class.php
Executable file → Normal file
631
framework/control.class.php
Executable file → Normal file
@@ -1,640 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* ZenTaoPHP的control类。
|
||||
* The control class file of ZenTaoPHP framework.
|
||||
*
|
||||
* The author disclaims copyright to this source code. In place of
|
||||
* a legal notice, here is a blessing:
|
||||
*
|
||||
*
|
||||
* May you do good and not evil.
|
||||
* May you find forgiveness for yourself and forgive others.
|
||||
* May you share freely, never taking more than you give.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The base class of control.
|
||||
*
|
||||
* control基类继承与baseControl,所有模块的control类都派生于它。
|
||||
* The base class of control extends baseControl.
|
||||
*
|
||||
* @package framework
|
||||
*/
|
||||
class control
|
||||
include dirname(__FILE__) . '/base/control.class.php';
|
||||
class control extends baseControl
|
||||
{
|
||||
/**
|
||||
* The global $app object.
|
||||
*
|
||||
* @var object
|
||||
* @access protected
|
||||
*/
|
||||
protected $app;
|
||||
|
||||
/**
|
||||
* The global $config object.
|
||||
*
|
||||
* @var object
|
||||
* @access protected
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* The global $lang object.
|
||||
*
|
||||
* @var object
|
||||
* @access protected
|
||||
*/
|
||||
protected $lang;
|
||||
|
||||
/**
|
||||
* The global $dbh object, the database connection handler.
|
||||
*
|
||||
* @var object
|
||||
* @access protected
|
||||
*/
|
||||
protected $dbh;
|
||||
|
||||
/**
|
||||
* The $dao object, used to access or update database.
|
||||
*
|
||||
* @var object
|
||||
* @access protected
|
||||
*/
|
||||
public $dao;
|
||||
|
||||
/**
|
||||
* The $post object, used to access the $_POST var.
|
||||
*
|
||||
* @var ojbect
|
||||
* @access public
|
||||
*/
|
||||
public $post;
|
||||
|
||||
/**
|
||||
* The $get object, used to access the $_GET var.
|
||||
*
|
||||
* @var ojbect
|
||||
* @access public
|
||||
*/
|
||||
public $get;
|
||||
|
||||
/**
|
||||
* The $session object, used to access the $_SESSION var.
|
||||
*
|
||||
* @var ojbect
|
||||
* @access public
|
||||
*/
|
||||
public $session;
|
||||
|
||||
/**
|
||||
* The $server object, used to access the $_SERVER var.
|
||||
*
|
||||
* @var ojbect
|
||||
* @access public
|
||||
*/
|
||||
public $server;
|
||||
|
||||
/**
|
||||
* The $cookie object, used to access the $_COOKIE var.
|
||||
*
|
||||
* @var ojbect
|
||||
* @access public
|
||||
*/
|
||||
public $cookie;
|
||||
|
||||
/**
|
||||
* The $global object, used to access the $_GLOBAL var.
|
||||
*
|
||||
* @var ojbect
|
||||
* @access public
|
||||
*/
|
||||
public $global;
|
||||
|
||||
/**
|
||||
* The name of current module.
|
||||
*
|
||||
* @var string
|
||||
* @access protected
|
||||
*/
|
||||
protected $moduleName;
|
||||
|
||||
/**
|
||||
* The vars assigned to the view page.
|
||||
*
|
||||
* @var object
|
||||
* @access public
|
||||
*/
|
||||
public $view;
|
||||
|
||||
/**
|
||||
* The type of the view, such html, json.
|
||||
*
|
||||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
private $viewType;
|
||||
|
||||
/**
|
||||
* The content to display.
|
||||
*
|
||||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
private $output;
|
||||
|
||||
/**
|
||||
* The directory seperator.
|
||||
*
|
||||
* @var string
|
||||
* @access protected
|
||||
*/
|
||||
protected $pathFix;
|
||||
|
||||
/**
|
||||
* The prefix of view file for mobile or PC.
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
public $viewPrefix;
|
||||
|
||||
/**
|
||||
* The construct function.
|
||||
*
|
||||
* 1. global the global vars, refer them by the class member such as $this->app.
|
||||
* 2. set the pathes of current module, and load it's mode class.
|
||||
* 3. auto assign the $lang and $config to the view.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($moduleName = '', $methodName = '')
|
||||
{
|
||||
/* Global the globals, and refer them to the class member. */
|
||||
global $app, $config, $lang, $dbh;
|
||||
$this->app = $app;
|
||||
$this->config = $config;
|
||||
$this->lang = $lang;
|
||||
$this->dbh = $dbh;
|
||||
$this->pathFix = $this->app->getPathFix();
|
||||
$this->viewType = $this->app->getViewType();
|
||||
|
||||
/* Load the model file auto. */
|
||||
$this->setModuleName($moduleName);
|
||||
$this->setMethodName($methodName);
|
||||
$this->loadModel();
|
||||
$this->setViewPrefix();
|
||||
|
||||
/* Init the view vars. */
|
||||
$this->view = new stdclass();
|
||||
$this->view->app = $app;
|
||||
$this->view->lang = $lang;
|
||||
$this->view->config = $config;
|
||||
$this->view->title = '';
|
||||
|
||||
/* Set super vars. */
|
||||
$this->setSuperVars();
|
||||
}
|
||||
|
||||
//-------------------- Model related methods --------------------//
|
||||
|
||||
/* Set the module name.
|
||||
*
|
||||
* @param string $moduleName The module name, if empty, get it from $app.
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
private function setModuleName($moduleName = '')
|
||||
{
|
||||
$this->moduleName = $moduleName ? strtolower($moduleName) : $this->app->getModuleName();
|
||||
}
|
||||
|
||||
/* Set the method name.
|
||||
*
|
||||
* @param string $methodName The method name, if empty, get it from $app.
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
private function setMethodName($methodName = '')
|
||||
{
|
||||
$this->methodName = $methodName ? strtolower($methodName) : $this->app->getMethodName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the model file of one module.
|
||||
*
|
||||
* @param string $methodName The method name, if empty, use current module's name.
|
||||
* @access public
|
||||
* @return object|bool If no model file, return false. Else return the model object.
|
||||
*/
|
||||
public function loadModel($moduleName = '')
|
||||
{
|
||||
if(empty($moduleName)) $moduleName = $this->moduleName;
|
||||
$modelFile = helper::setModelFile($moduleName);
|
||||
|
||||
/* If no model file, try load config. */
|
||||
if(!helper::import($modelFile))
|
||||
{
|
||||
$this->app->loadConfig($moduleName, false);
|
||||
$this->app->loadLang($moduleName);
|
||||
$this->dao = new dao();
|
||||
return false;
|
||||
}
|
||||
|
||||
$modelClass = class_exists('ext' . $moduleName. 'model') ? 'ext' . $moduleName . 'model' : $moduleName . 'model';
|
||||
if(!class_exists($modelClass)) $this->app->triggerError(" The model $modelClass not found", __FILE__, __LINE__, $exit = true);
|
||||
|
||||
$this->$moduleName = new $modelClass();
|
||||
$this->dao = $this->$moduleName->dao;
|
||||
return $this->$moduleName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the super vars.
|
||||
*
|
||||
* @access protected
|
||||
* @return void
|
||||
*/
|
||||
protected function setSuperVars()
|
||||
{
|
||||
$this->post = $this->app->post;
|
||||
$this->get = $this->app->get;
|
||||
$this->server = $this->app->server;
|
||||
$this->session = $this->app->session;
|
||||
$this->cookie = $this->app->cookie;
|
||||
$this->global = $this->app->global;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the prefix of view file for mobile or PC.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setViewPrefix()
|
||||
{
|
||||
$this->viewPrefix = '';
|
||||
if(isset($this->config->viewPrefix[$this->viewType])) $this->viewPrefix = $this->config->viewPrefix[$this->viewType];
|
||||
}
|
||||
|
||||
//-------------------- View related methods --------------------//
|
||||
|
||||
/**
|
||||
* Set the view file, thus can use fetch other module's page.
|
||||
*
|
||||
* @param string $moduleName module name
|
||||
* @param string $methodName method name
|
||||
* @access private
|
||||
* @return string the view file
|
||||
*/
|
||||
private function setViewFile($moduleName, $methodName)
|
||||
{
|
||||
$moduleName = strtolower(trim($moduleName));
|
||||
$methodName = strtolower(trim($methodName));
|
||||
|
||||
$modulePath = $this->app->getModulePath($moduleName);
|
||||
$viewExtPath = $this->app->getModuleExtPath($moduleName, 'view');
|
||||
|
||||
/* Set infix for view file in mobile or pc. */
|
||||
$viewType = $this->viewType;
|
||||
if(isset($this->config->viewPrefix[$this->viewType])) $viewType = 'html';
|
||||
|
||||
/* The main view file, extension view file and hook file. */
|
||||
$mainViewFile = $modulePath . 'view' . $this->pathFix . $this->viewPrefix . $methodName . '.' . $viewType . '.php';
|
||||
$extViewFile = $viewExtPath . $this->viewPrefix . $methodName . ".{$viewType}.php";
|
||||
$extHookFiles = glob($viewExtPath . $this->viewPrefix . $methodName . ".*.{$viewType}.hook.php");
|
||||
|
||||
$viewFile = file_exists($extViewFile) ? $extViewFile : $mainViewFile;
|
||||
if(!is_file($viewFile)) $this->app->triggerError("the view file $viewFile not found", __FILE__, __LINE__, $exit = true);
|
||||
if(!empty($extHookFiles)) return array('viewFile' => $viewFile, 'hookFiles' => $extHookFiles);
|
||||
return $viewFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the extension file of an view.
|
||||
*
|
||||
* @param string $viewFile
|
||||
* @access public
|
||||
* @return string|bool If extension view file exists, return the path. Else return fasle.
|
||||
*/
|
||||
public function getExtViewFile($viewFile)
|
||||
{
|
||||
$extPath = dirname(dirname(realpath($viewFile))) . '/ext/view/';
|
||||
$extViewFile = $extPath . basename($viewFile);
|
||||
if(file_exists($extViewFile))
|
||||
{
|
||||
helper::cd($extPath);
|
||||
return $extViewFile;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get css code for a method.
|
||||
*
|
||||
* @param string $moduleName
|
||||
* @param string $methodName
|
||||
* @access private
|
||||
* @return string
|
||||
*/
|
||||
private function getCSS($moduleName, $methodName)
|
||||
{
|
||||
$moduleName = strtolower(trim($moduleName));
|
||||
$methodName = strtolower(trim($methodName));
|
||||
$modulePath = $this->app->getModulePath($moduleName);
|
||||
$cssMethodExt = $this->app->getModuleExtPath($moduleName, 'css') . $methodName . $this->pathFix;
|
||||
$cssCommonExt = $this->app->getModuleExtPath($moduleName, 'css') . 'common' . $this->pathFix;
|
||||
|
||||
$css = '';
|
||||
$mainCssFile = $modulePath . 'css' . $this->pathFix . $this->viewPrefix . 'common.css';
|
||||
$methodCssFile = $modulePath . 'css' . $this->pathFix . $this->viewPrefix . $methodName . '.css';
|
||||
if(file_exists($mainCssFile)) $css .= file_get_contents($mainCssFile);
|
||||
if(is_file($methodCssFile)) $css .= file_get_contents($methodCssFile);
|
||||
|
||||
$cssExtFiles = glob($cssCommonExt . $this->viewPrefix . '*.css');
|
||||
if(is_array($cssExtFiles))
|
||||
{
|
||||
foreach($cssExtFiles as $cssFile)
|
||||
{
|
||||
$css .= file_get_contents($cssFile);
|
||||
}
|
||||
}
|
||||
|
||||
$cssExtFiles = glob($cssMethodExt . $this->viewPrefix . '*.css');
|
||||
if(is_array($cssExtFiles))
|
||||
{
|
||||
foreach($cssExtFiles as $cssFile)
|
||||
{
|
||||
$css .= file_get_contents($cssFile);
|
||||
}
|
||||
}
|
||||
return $css;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get js code for a method.
|
||||
*
|
||||
* @param string $moduleName
|
||||
* @param string $methodName
|
||||
* @access private
|
||||
* @return string
|
||||
*/
|
||||
private function getJS($moduleName, $methodName)
|
||||
{
|
||||
$moduleName = strtolower(trim($moduleName));
|
||||
$methodName = strtolower(trim($methodName));
|
||||
$modulePath = $this->app->getModulePath($moduleName);
|
||||
$jsMethodExt = $this->app->getModuleExtPath($moduleName, 'js') . $methodName . $this->pathFix;
|
||||
$jsCommonExt = $this->app->getModuleExtPath($moduleName, 'js') . 'common' . $this->pathFix;
|
||||
|
||||
$js = '';
|
||||
$mainJsFile = $modulePath . 'js' . $this->pathFix . $this->viewPrefix . 'common.js';
|
||||
$methodJsFile = $modulePath . 'js' . $this->pathFix . $this->viewPrefix . $methodName . '.js';
|
||||
if(file_exists($mainJsFile)) $js .= file_get_contents($mainJsFile);
|
||||
if(is_file($methodJsFile)) $js .= file_get_contents($methodJsFile);
|
||||
|
||||
$jsExtFiles = glob($jsCommonExt . $this->viewPrefix . '*.js');
|
||||
if(is_array($jsExtFiles))
|
||||
{
|
||||
foreach($jsExtFiles as $jsFile)
|
||||
{
|
||||
$js .= file_get_contents($jsFile);
|
||||
}
|
||||
}
|
||||
|
||||
$jsExtFiles = glob($jsMethodExt . $this->viewPrefix . '*.js');
|
||||
if(is_array($jsExtFiles))
|
||||
{
|
||||
foreach($jsExtFiles as $jsFile)
|
||||
{
|
||||
$js .= file_get_contents($jsFile);
|
||||
}
|
||||
}
|
||||
return $js;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign one var to the view vars.
|
||||
*
|
||||
* @param string $name the name.
|
||||
* @param mixed $value the value.
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function assign($name, $value)
|
||||
{
|
||||
$this->view->$name = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the output.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$this->output = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse view file.
|
||||
*
|
||||
* @param string $moduleName module name, if empty, use current module.
|
||||
* @param string $methodName method name, if empty, use current method.
|
||||
* @access public
|
||||
* @return string the parsed result.
|
||||
*/
|
||||
public function parse($moduleName = '', $methodName = '')
|
||||
{
|
||||
if(empty($moduleName)) $moduleName = $this->moduleName;
|
||||
if(empty($methodName)) $methodName = $this->methodName;
|
||||
|
||||
if($this->viewType == 'json')
|
||||
{
|
||||
$this->parseJSON($moduleName, $methodName);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->parseDefault($moduleName, $methodName);
|
||||
}
|
||||
return $this->output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse json format.
|
||||
*
|
||||
* @param string $moduleName module name
|
||||
* @param string $methodName method name
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
private function parseJSON($moduleName, $methodName)
|
||||
{
|
||||
unset($this->view->app);
|
||||
unset($this->view->config);
|
||||
unset($this->view->lang);
|
||||
unset($this->view->header);
|
||||
unset($this->view->position);
|
||||
unset($this->view->moduleTree);
|
||||
|
||||
$output['status'] = is_object($this->view) ? 'success' : 'fail';
|
||||
$output['data'] = json_encode($this->view);
|
||||
$output['md5'] = md5(json_encode($this->view));
|
||||
$this->output = json_encode($output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse default html format.
|
||||
*
|
||||
* @param string $moduleName module name
|
||||
* @param string $methodName method name
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
private function parseDefault($moduleName, $methodName)
|
||||
{
|
||||
/* Set the view file. */
|
||||
$viewFile = $this->setViewFile($moduleName, $methodName);
|
||||
if(is_array($viewFile)) extract($viewFile);
|
||||
|
||||
/* Get css and js. */
|
||||
$css = $this->getCSS($moduleName, $methodName);
|
||||
$js = $this->getJS($moduleName, $methodName);
|
||||
if($css) $this->view->pageCss = $css;
|
||||
if($js) $this->view->pageJS = $js;
|
||||
|
||||
/* Change the dir to the view file to keep the relative pathes work. */
|
||||
$currentPWD = getcwd();
|
||||
chdir(dirname($viewFile));
|
||||
|
||||
extract((array)$this->view);
|
||||
ob_start();
|
||||
include $viewFile;
|
||||
if(isset($hookFiles)) foreach($hookFiles as $hookFile) include $hookFile;
|
||||
$this->output .= ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
/* At the end, chang the dir to the previous. */
|
||||
chdir($currentPWD);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the output of one module's one method as a string, thus in one module's method, can fetch other module's content.
|
||||
*
|
||||
* If the module name is empty, then use the current module and method. If set, use the user defined module and method.
|
||||
*
|
||||
* @param string $moduleName module name.
|
||||
* @param string $methodName method name.
|
||||
* @param array $params params.
|
||||
* @access public
|
||||
* @return string the parsed html.
|
||||
*/
|
||||
public function fetch($moduleName = '', $methodName = '', $params = array())
|
||||
{
|
||||
if($moduleName == '') $moduleName = $this->moduleName;
|
||||
if($methodName == '') $methodName = $this->methodName;
|
||||
if($moduleName == $this->moduleName and $methodName == $this->methodName)
|
||||
{
|
||||
$this->parse($moduleName, $methodName);
|
||||
return $this->output;
|
||||
}
|
||||
|
||||
/* Set the pathes and files to included. */
|
||||
$modulePath = $this->app->getModulePath($moduleName);
|
||||
$moduleControlFile = $modulePath . 'control.php';
|
||||
$actionExtFile = $this->app->getModuleExtPath($moduleName, 'control') . strtolower($methodName) . '.php';
|
||||
$file2Included = file_exists($actionExtFile) ? $actionExtFile : $moduleControlFile;
|
||||
|
||||
/* Load the control file. */
|
||||
if(!is_file($file2Included)) $this->app->triggerError("The control file $file2Included not found", __FILE__, __LINE__, $exit = true);
|
||||
$currentPWD = getcwd();
|
||||
chdir(dirname($file2Included));
|
||||
if($moduleName != $this->moduleName) helper::import($file2Included);
|
||||
|
||||
/* Set the name of the class to be called. */
|
||||
$className = class_exists("my$moduleName") ? "my$moduleName" : $moduleName;
|
||||
if(!class_exists($className)) $this->app->triggerError(" The class $className not found", __FILE__, __LINE__, $exit = true);
|
||||
|
||||
/* Parse the params, create the $module control object. */
|
||||
if(!is_array($params)) parse_str($params, $params);
|
||||
$module = new $className($moduleName, $methodName);
|
||||
|
||||
/* Call the method and use ob function to get the output. */
|
||||
ob_start();
|
||||
call_user_func_array(array($module, $methodName), $params);
|
||||
$output = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
/* Return the content. */
|
||||
unset($module);
|
||||
chdir($currentPWD);
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the content of the view.
|
||||
*
|
||||
* @param string $moduleName module name
|
||||
* @param string $methodName method name
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function display($moduleName = '', $methodName = '')
|
||||
{
|
||||
if(empty($this->output)) $this->parse($moduleName, $methodName);
|
||||
echo $this->output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send data directly, for ajax requests.
|
||||
*
|
||||
* @param misc $data
|
||||
* @param string $type
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function send($data, $type = 'json')
|
||||
{
|
||||
if($type == 'json') echo json_encode($data);
|
||||
die(helper::removeUTF8Bom(ob_get_clean()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a link to one method of one module.
|
||||
*
|
||||
* @param string $moduleName module name
|
||||
* @param string $methodName method name
|
||||
* @param string|array $vars the params passed, can be array(key=>value) or key1=value1&key2=value2
|
||||
* @param string $viewType the view type
|
||||
* @access public
|
||||
* @return string the link string.
|
||||
*/
|
||||
public function createLink($moduleName, $methodName = 'index', $vars = array(), $viewType = '', $onlybody = false)
|
||||
{
|
||||
if(empty($moduleName)) $moduleName = $this->moduleName;
|
||||
return helper::createLink($moduleName, $methodName, $vars, $viewType, $onlybody);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a link to the inner method of current module.
|
||||
*
|
||||
* @param string $methodName method name
|
||||
* @param string|array $vars the params passed, can be array(key=>value) or key1=value1&key2=value2
|
||||
* @param string $viewType the view type
|
||||
* @access public
|
||||
* @return string the link string.
|
||||
*/
|
||||
public function inlink($methodName = 'index', $vars = array(), $viewType = '', $onlybody = false)
|
||||
{
|
||||
return helper::createLink($this->moduleName, $methodName, $vars, $viewType, $onlybody);
|
||||
}
|
||||
|
||||
/**
|
||||
* Location to another page.
|
||||
*
|
||||
* @param string $url the target url.
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function locate($url)
|
||||
{
|
||||
header("location: $url");
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,618 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* ZenTaoPHP的helper类。
|
||||
* The helper class file of ZenTaoPHP framework.
|
||||
*
|
||||
* The author disclaims copyright to this source code. In place of
|
||||
* The author disclaims copyright to this source code. In place of
|
||||
* a legal notice, here is a blessing:
|
||||
*
|
||||
*
|
||||
* May you do good and not evil.
|
||||
* May you find forgiveness for yourself and forgive others.
|
||||
* May you share freely, never taking more than you give.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 该类实现了一些常用的方法
|
||||
* The helper class, contains the tool functions.
|
||||
*
|
||||
* @package framework
|
||||
*/
|
||||
class helper
|
||||
include dirname(__FILE__) . '/base/helper.class.php';
|
||||
class helper extends baseHelper
|
||||
{
|
||||
/**
|
||||
* Set the member's value of one object.
|
||||
* <code>
|
||||
* <?php
|
||||
* $lang->db->user = 'wwccss';
|
||||
* helper::setMember('lang', 'db.user', 'chunsheng.wang');
|
||||
* ?>
|
||||
* </code>
|
||||
* @param string $objName the var name of the object.
|
||||
* @param string $key the key of the member, can be parent.child.
|
||||
* @param mixed $value the value to be set.
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
static public function setMember($objName, $key, $value)
|
||||
{
|
||||
global $$objName;
|
||||
if(!is_object($$objName) or empty($key)) return false;
|
||||
$key = str_replace('.', '->', $key);
|
||||
$value = serialize($value);
|
||||
$code = ("\$${objName}->{$key}=unserialize(<<<EOT\n$value\nEOT\n);");
|
||||
eval($code);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a link to a module's method.
|
||||
*
|
||||
* This method also mapped in control class to call conveniently.
|
||||
* <code>
|
||||
* <?php
|
||||
* helper::createLink('hello', 'index', 'var1=value1&var2=value2');
|
||||
* helper::createLink('hello', 'index', array('var1' => 'value1', 'var2' => 'value2');
|
||||
* ?>
|
||||
* </code>
|
||||
* @param string $moduleName module name
|
||||
* @param string $methodName method name
|
||||
* @param string|array $vars the params passed to the method, can be array('key' => 'value') or key1=value1&key2=value2) or key1=value1&key2=value2
|
||||
* @param string $viewType the view type
|
||||
* @param string $onlybody the view type
|
||||
* @static
|
||||
* @access public
|
||||
* @return string the link string.
|
||||
*/
|
||||
static public function createLink($moduleName, $methodName = 'index', $vars = '', $viewType = '', $onlybody = false)
|
||||
{
|
||||
global $app, $config;
|
||||
$link = $config->requestType == 'PATH_INFO' ? $config->webRoot : $_SERVER['PHP_SELF'];
|
||||
|
||||
/* Set the view type and vars. */
|
||||
if(empty($viewType)) $viewType = $app->getViewType();
|
||||
if(!is_array($vars)) parse_str($vars, $vars);
|
||||
|
||||
/* The PATH_INFO type. */
|
||||
if($config->requestType == 'PATH_INFO')
|
||||
{
|
||||
/* If the method equal the default method defined in the config file and the vars is empty, convert the link. */
|
||||
if($methodName == $config->default->method and empty($vars))
|
||||
{
|
||||
/* If the module also equal the default module, change index-index to index.html. */
|
||||
if($moduleName == $config->default->module)
|
||||
{
|
||||
$link .= 'index.' . $viewType;
|
||||
}
|
||||
else
|
||||
{
|
||||
$link .= $moduleName . '/';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$link .= "$moduleName{$config->requestFix}$methodName";
|
||||
if($config->pathType == 'full')
|
||||
{
|
||||
foreach($vars as $key => $value) $link .= "{$config->requestFix}$key{$config->requestFix}$value";
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach($vars as $value) $link .= "{$config->requestFix}$value";
|
||||
}
|
||||
$link .= '.' . $viewType;
|
||||
}
|
||||
}
|
||||
elseif($config->requestType == 'GET')
|
||||
{
|
||||
$link .= "?{$config->moduleVar}=$moduleName&{$config->methodVar}=$methodName";
|
||||
if($viewType != 'html') $link .= "&{$config->viewVar}=" . $viewType;
|
||||
foreach($vars as $key => $value) $link .= "&$key=$value";
|
||||
}
|
||||
|
||||
/* if page has onlybody param then add this param in all link. the param hide header and footer. */
|
||||
if($onlybody or isonlybody())
|
||||
{
|
||||
$onlybody = $config->requestType == 'PATH_INFO' ? "?onlybody=yes" : "&onlybody=yes";
|
||||
$link .= $onlybody;
|
||||
}
|
||||
return $link;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import a file instend of include or requie.
|
||||
*
|
||||
* @param string $file the file to be imported.
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
static public function import($file)
|
||||
{
|
||||
static $includedFiles = array();
|
||||
if(!isset($includedFiles[$file]))
|
||||
{
|
||||
$return = include $file;
|
||||
if(!$return) return false;
|
||||
$includedFiles[$file] = true;
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the model file of one module. If there's an extension file, merge it with the main model file.
|
||||
*
|
||||
* @param string $moduleName the module name
|
||||
* @static
|
||||
* @access public
|
||||
* @return string the model file
|
||||
*/
|
||||
static public function setModelFile($moduleName)
|
||||
{
|
||||
global $app;
|
||||
|
||||
/* Set the main model file and extension and hook pathes and files. */
|
||||
$mainModelFile = $app->getModulePath($moduleName) . 'model.php';
|
||||
$modelExtPath = $app->getModuleExtPath($moduleName, 'model');
|
||||
$modelHookPath = $modelExtPath . 'hook/';
|
||||
$extFiles = helper::ls($modelExtPath, '.php');
|
||||
$hookFiles = helper::ls($modelHookPath, '.php');
|
||||
|
||||
/* If no extension files and no hook files, return the main file directly. */
|
||||
if(empty($extFiles) and empty($hookFiles)) return $mainModelFile;
|
||||
|
||||
/* Else, judge whether needed update or not .*/
|
||||
$needUpdate = false;
|
||||
$mergedModelFile = $app->getTmpRoot() . 'model' . $app->getPathFix() . $moduleName . '.php';
|
||||
$lastTime = file_exists($mergedModelFile) ? filemtime($mergedModelFile) : 0;
|
||||
|
||||
while(!$needUpdate)
|
||||
{
|
||||
foreach($extFiles as $extFile) if(filemtime($extFile) > $lastTime) break 2;
|
||||
foreach($hookFiles as $hookFile) if(filemtime($hookFile) > $lastTime) break 2;
|
||||
|
||||
if(is_dir($modelExtPath ) and filemtime($modelExtPath) > $lastTime) break;
|
||||
if(is_dir($modelHookPath) and filemtime($modelHookPath) > $lastTime) break;
|
||||
|
||||
if(filemtime($mainModelFile) > $lastTime) break;
|
||||
|
||||
return $mergedModelFile;
|
||||
}
|
||||
|
||||
/* If loaded zend opcache module, turn off cache when create tmp model file to avoid the conflics. */
|
||||
if(extension_loaded('Zend OPcache')) ini_set('opcache.enable', 0);
|
||||
|
||||
/* Update the cache file. */
|
||||
$modelClass = $moduleName . 'Model';
|
||||
$extModelClass = 'ext' . $modelClass;
|
||||
$extTmpModelClass = 'tmpExt' . $modelClass;
|
||||
$modelLines = "<?php\n";
|
||||
$modelLines .= "helper::import('$mainModelFile');\n";
|
||||
$modelLines .= "class $extTmpModelClass extends $modelClass \n{\n";
|
||||
|
||||
/* Cycle all the extension files. */
|
||||
foreach($extFiles as $extFile)
|
||||
{
|
||||
$extLines = self::removeTagsOfPHP($extFile);
|
||||
$modelLines .= $extLines . "\n";
|
||||
}
|
||||
|
||||
/* Create the merged model file and import it. */
|
||||
$replaceMark = '//**//'; // This mark is for replacing code using.
|
||||
$modelLines .= "$replaceMark\n}";
|
||||
if(!@file_put_contents($mergedModelFile, $modelLines))
|
||||
{
|
||||
die("ERROR: $mergedModelFile not writable, please make sure the " . dirname($mergedModelFile) . ' directory exists and writable');
|
||||
}
|
||||
if(!class_exists($extTmpModelClass))include $mergedModelFile;
|
||||
|
||||
/* Get hook codes need to merge. */
|
||||
$hookCodes = array();
|
||||
foreach($hookFiles as $hookFile)
|
||||
{
|
||||
$fileName = baseName($hookFile);
|
||||
list($method) = explode('.', $fileName);
|
||||
$hookCodes[$method][] = self::removeTagsOfPHP($hookFile);
|
||||
}
|
||||
|
||||
/* Cycle the hook methods and merge hook codes. */
|
||||
$hookedMethods = array_keys($hookCodes);
|
||||
$mainModelCodes = file($mainModelFile);
|
||||
$mergedModelCodes = file($mergedModelFile);
|
||||
foreach($hookedMethods as $method)
|
||||
{
|
||||
/* Reflection the hooked method to get it's defined position. */
|
||||
$methodRelfection = new reflectionMethod($extTmpModelClass, $method);
|
||||
$definedFile = $methodRelfection->getFileName();
|
||||
$startLine = $methodRelfection->getStartLine() . ' ';
|
||||
$endLine = $methodRelfection->getEndLine() . ' ';
|
||||
|
||||
/* Merge hook codes. */
|
||||
$oldCodes = $definedFile == $mergedModelFile ? $mergedModelCodes : $mainModelCodes;
|
||||
$oldCodes = join("", array_slice($oldCodes, $startLine - 1, $endLine - $startLine + 1));
|
||||
$openBrace = strpos($oldCodes, '{');
|
||||
$newCodes = substr($oldCodes, 0, $openBrace + 1) . "\n" . join("\n", $hookCodes[$method]) . substr($oldCodes, $openBrace + 1);
|
||||
|
||||
/* Replace it. */
|
||||
if($definedFile == $mergedModelFile)
|
||||
{
|
||||
$modelLines = str_replace($oldCodes, $newCodes, $modelLines);
|
||||
}
|
||||
else
|
||||
{
|
||||
$modelLines = str_replace($replaceMark, $newCodes . "\n$replaceMark", $modelLines);
|
||||
}
|
||||
}
|
||||
|
||||
/* Save it. */
|
||||
$modelLines = str_replace($extTmpModelClass, $extModelClass, $modelLines);
|
||||
file_put_contents($mergedModelFile, $modelLines);
|
||||
|
||||
return $mergedModelFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove tags of PHP
|
||||
*
|
||||
* @param string $fileName
|
||||
* @static
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
static public function removeTagsOfPHP($fileName)
|
||||
{
|
||||
$code = trim(file_get_contents($fileName));
|
||||
if(strpos($code, '<?php') === 0) $code = ltrim($code, '<?php');
|
||||
if(strrpos($code, '?>') !== false) $code = rtrim($code, '?>');
|
||||
return trim($code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the in('a', 'b') string.
|
||||
*
|
||||
* @param string|array $ids the id lists, can be a array or a string with ids joined with comma.
|
||||
* @static
|
||||
* @access public
|
||||
* @return string the string like IN('a', 'b').
|
||||
*/
|
||||
static public function dbIN($ids)
|
||||
{
|
||||
if(is_array($ids)) return "IN ('" . join("','", $ids) . "')";
|
||||
return "IN ('" . str_replace(',', "','", str_replace(' ', '',$ids)) . "')";
|
||||
}
|
||||
|
||||
/**
|
||||
* Create safe base64 encoded string for the framework.
|
||||
*
|
||||
* @param string $string the string to encode.
|
||||
* @static
|
||||
* @access public
|
||||
* @return string encoded string.
|
||||
*/
|
||||
static public function safe64Encode($string)
|
||||
{
|
||||
return strtr(base64_encode($string), '/', '.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode the string encoded by safe64Encode.
|
||||
*
|
||||
* @param string $string the string to decode
|
||||
* @static
|
||||
* @access public
|
||||
* @return string decoded string.
|
||||
*/
|
||||
static public function safe64Decode($string)
|
||||
{
|
||||
return base64_decode(strtr($string, '.', '/'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Judge a string is utf-8 or not.
|
||||
*
|
||||
* @param string $string
|
||||
* @author hmdker@gmail.com
|
||||
* @see http://php.net/manual/en/function.mb-detect-encoding.php
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
static public function isUTF8($string)
|
||||
{
|
||||
$c = 0;
|
||||
$b = 0;
|
||||
$bits = 0;
|
||||
$len = strlen($string);
|
||||
for($i=0; $i<$len; $i++)
|
||||
{
|
||||
$c = ord($string[$i]);
|
||||
if($c > 128)
|
||||
{
|
||||
if(($c >= 254)) return false;
|
||||
elseif($c >= 252) $bits=6;
|
||||
elseif($c >= 248) $bits=5;
|
||||
elseif($c >= 240) $bits=4;
|
||||
elseif($c >= 224) $bits=3;
|
||||
elseif($c >= 192) $bits=2;
|
||||
else return false;
|
||||
if(($i+$bits) > $len) return false;
|
||||
while($bits > 1)
|
||||
{
|
||||
$i++;
|
||||
$b=ord($string[$i]);
|
||||
if($b < 128 || $b > 191) return false;
|
||||
$bits--;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the diff days of two date.
|
||||
*
|
||||
* @param date $date1 the first date.
|
||||
* @param date $date2 the sencode date.
|
||||
* @access public
|
||||
* @return int the diff of the two days.
|
||||
*/
|
||||
static public function diffDate($date1, $date2)
|
||||
{
|
||||
return round((strtotime($date1) - strtotime($date2)) / 86400, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get now time use the DT_DATETIME1 constant defined in the lang file.
|
||||
*
|
||||
* @access public
|
||||
* @return datetime now
|
||||
*/
|
||||
static public function now()
|
||||
{
|
||||
return date(DT_DATETIME1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get today according to the DT_DATE1 constant defined in the lang file.
|
||||
*
|
||||
* @access public
|
||||
* @return date today
|
||||
*/
|
||||
static public function today()
|
||||
{
|
||||
return date(DT_DATE1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Judge a date is zero or not.
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
static public function isZeroDate($date)
|
||||
{
|
||||
return substr($date, 0, 4) == '0000';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get files match the pattern under one directory.
|
||||
*
|
||||
* @access public
|
||||
* @return array the files match the pattern
|
||||
*/
|
||||
static public function ls($dir, $pattern = '')
|
||||
{
|
||||
$files = array();
|
||||
$dir = realpath($dir);
|
||||
if(is_dir($dir)) $files = glob($dir . DIRECTORY_SEPARATOR . '*' . $pattern);
|
||||
return empty($files) ? array() : $files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change directory.
|
||||
*
|
||||
* @param string $path
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
static function cd($path = '')
|
||||
{
|
||||
static $cwd = '';
|
||||
if($path)
|
||||
{
|
||||
$cwd = getcwd();
|
||||
chdir($path);
|
||||
}
|
||||
else
|
||||
{
|
||||
chdir($cwd);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove UTF8 Bom
|
||||
*
|
||||
* @param string $string
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public static function removeUTF8Bom($string)
|
||||
{
|
||||
if(substr($string, 0, 3) == pack('CCC', 239, 187, 191)) return substr($string, 3);
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check is ajax request.
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function isAjaxRequest()
|
||||
{
|
||||
return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
|
||||
}
|
||||
|
||||
/**
|
||||
* Set viewType.
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public static function setViewType()
|
||||
{
|
||||
global $config, $app;
|
||||
if($config->requestType == 'PATH_INFO')
|
||||
{
|
||||
$pathInfo = $app->getPathInfo('PATH_INFO');
|
||||
if(empty($pathInfo)) $pathInfo = $app->getPathInfo('ORIG_PATH_INFO');
|
||||
if(!empty($pathInfo))
|
||||
{
|
||||
$dotPos = strrpos($pathInfo, '.');
|
||||
if($dotPos)
|
||||
{
|
||||
$viewType = substr($pathInfo, $dotPos + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
$config->default->view = $config->default->view == 'mhtml' ? 'html' : $config->default->view;
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif($config->requestType == 'GET')
|
||||
{
|
||||
if(isset($_GET[$config->viewVar]))
|
||||
{
|
||||
$viewType = $_GET[$config->viewVar];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set default view when url has not module name. such as only domain. */
|
||||
$config->default->view = ($config->default->view == 'mhtml' and isset($_GET[$config->moduleVar])) ? 'html' : $config->default->view;
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($viewType) and strpos($config->views, ',' . $viewType . ',') === false) $viewType = $config->default->view;
|
||||
$app->viewType = isset($viewType) ? $viewType : $config->default->view;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The short alias of helper::createLink() method.
|
||||
*
|
||||
* @param string $methodName the method name
|
||||
* @param string|array $vars the params passed to the method, can be array('key' => 'value') or key1=value1&key2=value2)
|
||||
* @param string $viewType
|
||||
* @return string the link string.
|
||||
*/
|
||||
function inLink($methodName = 'index', $vars = '', $viewType = '')
|
||||
{
|
||||
global $app;
|
||||
return helper::createLink($app->getModuleName(), $methodName, $vars, $viewType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Static cycle a array
|
||||
*
|
||||
* @param array $items the array to be cycled.
|
||||
* @return mixed
|
||||
*/
|
||||
function cycle($items)
|
||||
{
|
||||
static $i = 0;
|
||||
if(!is_array($items)) $items = explode(',', $items);
|
||||
if(!isset($items[$i])) $i = 0;
|
||||
return $items[$i++];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current microtime.
|
||||
*
|
||||
* @access protected
|
||||
* @return float current time.
|
||||
*/
|
||||
function getTime()
|
||||
{
|
||||
list($usec, $sec) = explode(" ", microtime());
|
||||
return ((float)$usec + (float)$sec);
|
||||
}
|
||||
|
||||
/**
|
||||
* dump a var.
|
||||
*
|
||||
* @param mixed $var
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function a($var)
|
||||
{
|
||||
echo "<xmp class='a-left'>";
|
||||
print_r($var);
|
||||
echo "</xmp>";
|
||||
}
|
||||
|
||||
/**
|
||||
* When the $var has the $key, return it, esle result one default value.
|
||||
*
|
||||
* @param array|object $var
|
||||
* @param string|int $key
|
||||
* @param mixed $valueWhenNone value when the key not exits.
|
||||
* @param mixed $valueWhenExists value when the key exits.
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function zget($var, $key, $valueWhenNone = '', $valueWhenExists = '')
|
||||
{
|
||||
$var = (array)$var;
|
||||
if(isset($var[$key]))
|
||||
{
|
||||
if($valueWhenExists) return $valueWhenExists;
|
||||
return $var[$key];
|
||||
}
|
||||
return $valueWhenNone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Judge the server ip is local or not.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function isLocalIP()
|
||||
{
|
||||
$serverIP = $_SERVER['SERVER_ADDR'];
|
||||
if($serverIP == '127.0.0.1') return true;
|
||||
return !filter_var($serverIP, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get web root.
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
function getWebRoot()
|
||||
{
|
||||
$path = $_SERVER['SCRIPT_NAME'];
|
||||
if(PHP_SAPI == 'cli')
|
||||
{
|
||||
$url = parse_url($_SERVER['argv'][1]);
|
||||
$path = empty($url['path']) ? '/' : rtrim($url['path'], '/');
|
||||
$path = empty($path) ? '/' : preg_replace('/\/www$/', '/www/', $path);
|
||||
}
|
||||
|
||||
return substr($path, 0, (strrpos($path, '/') + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check exist onlybody param.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function isonlybody()
|
||||
{
|
||||
return (isset($_GET['onlybody']) and $_GET['onlybody'] == 'yes');
|
||||
}
|
||||
|
||||
223
framework/model.class.php
Executable file → Normal file
223
framework/model.class.php
Executable file → Normal file
@@ -1,5 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* ZenTaoPHP的model类。
|
||||
* The model class file of ZenTaoPHP framework.
|
||||
*
|
||||
* The author disclaims copyright to this source code. In place of
|
||||
@@ -11,226 +12,16 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* model基类。
|
||||
* The base class of model.
|
||||
*
|
||||
* @package framework
|
||||
*/
|
||||
class model
|
||||
include dirname(__FILE__) . '/base/model.class.php';
|
||||
class model extends baseModel
|
||||
{
|
||||
/**
|
||||
* The global $app object.
|
||||
*
|
||||
* @var object
|
||||
* @access protected
|
||||
*/
|
||||
protected $app;
|
||||
|
||||
/**
|
||||
* The global $config object.
|
||||
*
|
||||
* @var object
|
||||
* @access protected
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* The global $lang object.
|
||||
*
|
||||
* @var object
|
||||
* @access protected
|
||||
*/
|
||||
protected $lang;
|
||||
|
||||
/**
|
||||
* The global $dbh object, the database connection handler.
|
||||
*
|
||||
* @var object
|
||||
* @access protected
|
||||
*/
|
||||
protected $dbh;
|
||||
|
||||
/**
|
||||
* The $dao object, used to access or update database.
|
||||
*
|
||||
* @var object
|
||||
* @access protected
|
||||
*/
|
||||
public $dao;
|
||||
|
||||
/**
|
||||
* The $post object, used to access the $_POST var.
|
||||
*
|
||||
* @var ojbect
|
||||
* @access public
|
||||
*/
|
||||
public $post;
|
||||
|
||||
/**
|
||||
* The $get object, used to access the $_GET var.
|
||||
*
|
||||
* @var ojbect
|
||||
* @access public
|
||||
*/
|
||||
public $get;
|
||||
|
||||
/**
|
||||
* The $sesion object, used to access the $_SESSION var.
|
||||
*
|
||||
* @var ojbect
|
||||
* @access public
|
||||
*/
|
||||
public $session;
|
||||
|
||||
/**
|
||||
* The $server object, used to access the $_SERVER var.
|
||||
*
|
||||
* @var ojbect
|
||||
* @access public
|
||||
*/
|
||||
public $server;
|
||||
|
||||
/**
|
||||
* The $cookie object, used to access the $_COOKIE var.
|
||||
*
|
||||
* @var ojbect
|
||||
* @access public
|
||||
*/
|
||||
public $cookie;
|
||||
|
||||
/**
|
||||
* The $global object, used to access the $_GLOBAL var.
|
||||
*
|
||||
* @var ojbect
|
||||
* @access public
|
||||
*/
|
||||
public $global;
|
||||
|
||||
/**
|
||||
* The construct function.
|
||||
*
|
||||
* 1. global the global vars, refer them by the class member such as $this->app.
|
||||
* 2. set the pathes, config, lang of current module
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
global $app, $config, $lang, $dbh;
|
||||
$this->app = $app;
|
||||
$this->config = $config;
|
||||
$this->lang = $lang;
|
||||
$this->dbh = $dbh;
|
||||
|
||||
$moduleName = $this->getModuleName();
|
||||
$this->app->loadLang($moduleName, $exit = false);
|
||||
$this->app->loadConfig($moduleName, $exit = false);
|
||||
|
||||
$this->loadDAO();
|
||||
$this->setSuperVars();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the module name of this model. Not the module user visiting.
|
||||
*
|
||||
* This method replace the 'ext' and 'model' string from the model class name, thus get the module name.
|
||||
* Not useing $app->getModuleName() because it return the module user is visiting. But one module can be
|
||||
* loaded by loadModel() so we must get the module name of thie model.
|
||||
*
|
||||
* @access protected
|
||||
* @return string the module name.
|
||||
*/
|
||||
protected function getModuleName()
|
||||
{
|
||||
$parentClass = get_parent_class($this);
|
||||
$selfClass = get_class($this);
|
||||
$className = $parentClass == 'model' ? $selfClass : $parentClass;
|
||||
if($className == 'extensionModel') return 'extension';
|
||||
return strtolower(str_ireplace(array('ext', 'Model'), '', $className));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the super vars.
|
||||
*
|
||||
* @access protected
|
||||
* @return void
|
||||
*/
|
||||
protected function setSuperVars()
|
||||
{
|
||||
$this->post = $this->app->post;
|
||||
$this->get = $this->app->get;
|
||||
$this->server = $this->app->server;
|
||||
$this->cookie = $this->app->cookie;
|
||||
$this->session = $this->app->session;
|
||||
$this->global = $this->app->global;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the model of one module. After loaded, can use $this->modulename to visit the model object.
|
||||
*
|
||||
* @param string $moduleName
|
||||
* @access public
|
||||
* @return object|bool the model object or false if model file not exists.
|
||||
*/
|
||||
public function loadModel($moduleName)
|
||||
{
|
||||
if(empty($moduleName)) return false;
|
||||
$modelFile = helper::setModelFile($moduleName);
|
||||
|
||||
if(!helper::import($modelFile)) return false;
|
||||
$modelClass = class_exists('ext' . $moduleName. 'model') ? 'ext' . $moduleName . 'model' : $moduleName . 'model';
|
||||
if(!class_exists($modelClass)) $this->app->triggerError(" The model $modelClass not found", __FILE__, __LINE__, $exit = true);
|
||||
|
||||
$this->$moduleName = new $modelClass();
|
||||
return $this->$moduleName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load extension class of a model. Saved to $moduleName/ext/model/class/$extensionName.class.php.
|
||||
*
|
||||
* @param string $extensionName
|
||||
* @param string $moduleName
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function loadExtension($extensionName, $moduleName = '')
|
||||
{
|
||||
if(empty($extensionName)) return false;
|
||||
|
||||
/* Set extenson name and extension file. */
|
||||
$extensionName = strtolower($extensionName);
|
||||
$moduleName = $moduleName ? $moduleName : $this->getModuleName();
|
||||
$extensionFile = $this->app->getModuleExtPath($moduleName, 'model') . 'class/' . $extensionName . '.class.php';
|
||||
|
||||
/* Try to import parent model file auto and then import the extension file. */
|
||||
if(!class_exists($moduleName . 'Model')) helper::import($this->app->getModulePath($moduleName) . 'model.php');
|
||||
if(!helper::import($extensionFile)) return false;
|
||||
|
||||
/* Set the extension class name. */
|
||||
$extensionClass = $extensionName . ucfirst($moduleName);
|
||||
if(!class_exists($extensionClass)) return false;
|
||||
|
||||
/* Create an instance of the extension class and return it. */
|
||||
$extensionObject = new $extensionClass;
|
||||
$extensionClass = str_replace('Model', '', $extensionClass);
|
||||
$this->$extensionClass = $extensionObject;
|
||||
return $extensionObject;
|
||||
}
|
||||
|
||||
//-------------------- DAO related method s--------------------//
|
||||
|
||||
/**
|
||||
* Load DAO.
|
||||
*
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
private function loadDAO()
|
||||
{
|
||||
$this->dao = $this->app->loadClass('dao');
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除记录
|
||||
* Delete one record.
|
||||
*
|
||||
* @param string $table the table name
|
||||
@@ -241,7 +32,7 @@ class model
|
||||
public function delete($table, $id)
|
||||
{
|
||||
$this->dao->update($table)->set('deleted')->eq(1)->where('id')->eq($id)->exec();
|
||||
$object = str_replace($this->config->db->prefix, '', $table);
|
||||
$object = ltrim(strstr(trim($table, '`'), '_'), '_');
|
||||
$this->loadModel('action')->create($object, $id, 'deleted', '', $extra = ACTIONMODEL::CAN_UNDELETED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
2007
lib/base/dao/dao.class.php
Normal file
2007
lib/base/dao/dao.class.php
Normal file
File diff suppressed because it is too large
Load Diff
952
lib/base/filter/filter.class.php
Normal file
952
lib/base/filter/filter.class.php
Normal file
@@ -0,0 +1,952 @@
|
||||
<?php
|
||||
/**
|
||||
* ZenTaoPHP的验证和过滤类。
|
||||
* The validater and fixer class file of ZenTaoPHP framework.
|
||||
*
|
||||
* The author disclaims copyright to this source code. In place of
|
||||
* a legal notice, here is a blessing:
|
||||
*
|
||||
* May you do good and not evil.
|
||||
* May you find forgiveness for yourself and forgive others.
|
||||
* May you share freely, never taking more than you give.
|
||||
*/
|
||||
|
||||
/**
|
||||
* validater类,检查数据是否符合规则。
|
||||
* The validater class, checking data by rules.
|
||||
*
|
||||
* @package framework
|
||||
*/
|
||||
class baseValidater
|
||||
{
|
||||
/**
|
||||
* 最大参数个数。
|
||||
* The max count of args.
|
||||
*/
|
||||
const MAX_ARGS = 3;
|
||||
|
||||
/**
|
||||
* 是否是Bool类型。
|
||||
* Bool checking.
|
||||
*
|
||||
* @param bool $var
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkBool($var)
|
||||
{
|
||||
return filter_var($var, FILTER_VALIDATE_BOOLEAN);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是Int类型。
|
||||
* Int checking.
|
||||
*
|
||||
* @param int $var
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkInt($var)
|
||||
{
|
||||
$args = func_get_args();
|
||||
if($var != 0) $var = ltrim($var, 0); // 去掉变量左边的0,00不是Int类型
|
||||
// Remove the left 0, filter don't think 00 is an int.
|
||||
|
||||
/* 如果设置了最小的整数。 Min is setted. */
|
||||
if(isset($args[1]))
|
||||
{
|
||||
/* 如果最大的整数也设置了。 And Max is setted. */
|
||||
if(isset($args[2]))
|
||||
{
|
||||
$options = array('options' => array('min_range' => $args[1], 'max_range' => $args[2]));
|
||||
}
|
||||
else
|
||||
{
|
||||
$options = array('options' => array('min_range' => $args[1]));
|
||||
}
|
||||
|
||||
return filter_var($var, FILTER_VALIDATE_INT, $options);
|
||||
}
|
||||
else
|
||||
{
|
||||
return filter_var($var, FILTER_VALIDATE_INT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查不是Int类型。
|
||||
* Not int checking.
|
||||
*
|
||||
* @param int $var
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkNotInt($var)
|
||||
{
|
||||
return !self::checkInt($var);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查Float类型。
|
||||
* Float checking.
|
||||
*
|
||||
* @param float $var
|
||||
* @param string $decimal
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkFloat($var, $decimal = '.')
|
||||
{
|
||||
return filter_var($var, FILTER_VALIDATE_FLOAT, array('options' => array('decimal' => $decimal)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查Email。
|
||||
* Email checking.
|
||||
*
|
||||
* @param string $var
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkEmail($var)
|
||||
{
|
||||
return filter_var($var, FILTER_VALIDATE_EMAIL);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查电话或手机号码
|
||||
* Check phone number.
|
||||
*
|
||||
* @param string $var
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public static function checkPhone($var)
|
||||
{
|
||||
return (validater::checkTel($var) or validater::checkMobile($var));
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查电话号码
|
||||
* Check tel number.
|
||||
*
|
||||
* @param int $var
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public static function checkTel($var)
|
||||
{
|
||||
return preg_match("/^([0-9]{3,4}-)?[0-9]{7,8}$/", $var);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查手机号码
|
||||
* Check mobile number.
|
||||
*
|
||||
* @param string $var
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public static function checkMobile($var)
|
||||
{
|
||||
return preg_match("/^1[3-5,8]{1}[0-9]{9}$/", $var);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查网址。
|
||||
* 该规则不支持中文字符的网址。
|
||||
*
|
||||
* URL checking.
|
||||
* The check rule of filter don't support chinese.
|
||||
*
|
||||
* @param string $var
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkURL($var)
|
||||
{
|
||||
return filter_var($var, FILTER_VALIDATE_URL);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查域名,不支持中文。
|
||||
* Domain checking.
|
||||
*
|
||||
* The check rule of filter don't support chinese.
|
||||
*
|
||||
* @param string $var
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkDomain($var)
|
||||
{
|
||||
return preg_match('/^([a-z0-9-]+\.)+[a-z]{2,15}$/', $var);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查IP地址。
|
||||
* IP checking.
|
||||
*
|
||||
* @param ip $var
|
||||
* @param string $range all|public|static|private
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkIP($var, $range = 'all')
|
||||
{
|
||||
if($range == 'all') return filter_var($var, FILTER_VALIDATE_IP);
|
||||
if($range == 'public static') return filter_var($var, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE);
|
||||
if($range == 'private')
|
||||
{
|
||||
if($var == '127.0.0.1' or filter_var($var, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE) === false) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 日期检查。注意,2009-09-31是一个合法日期,系统会将它转换为2009-10-01。
|
||||
* Date checking. Note: 2009-09-31 will be an valid date, because strtotime auto fixed it to 10-01.
|
||||
*
|
||||
* @param date $date
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkDate($date)
|
||||
{
|
||||
if($date == '0000-00-00') return true;
|
||||
$stamp = strtotime($date);
|
||||
if(!is_numeric($stamp)) return false;
|
||||
return checkdate(date('m', $stamp), date('d', $stamp), date('Y', $stamp));
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查正则表达式。
|
||||
* REG checking.
|
||||
*
|
||||
* @param string $var
|
||||
* @param string $reg
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkREG($var, $reg)
|
||||
{
|
||||
return filter_var($var, FILTER_VALIDATE_REGEXP, array('options' => array('regexp' => $reg)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查长度。
|
||||
* Length checking.
|
||||
*
|
||||
* @param string $var
|
||||
* @param string $max
|
||||
* @param int $min
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkLength($var, $max, $min = 0)
|
||||
{
|
||||
$length = function_exists('mb_strlen') ? mb_strlen($var, 'utf-8') : strlen($var);
|
||||
return self::checkInt($length, $min, $max);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查不为空。
|
||||
* Not empty checking.
|
||||
*
|
||||
* @param mixed $var
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkNotEmpty($var)
|
||||
{
|
||||
return !empty($var);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查为空。
|
||||
* Empty checking.
|
||||
*
|
||||
* @param mixed $var
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkEmpty($var)
|
||||
{
|
||||
return empty($var);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查用户名。
|
||||
* Account checking.
|
||||
*
|
||||
* @param string $var
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkAccount($var)
|
||||
{
|
||||
global $config;
|
||||
$accountRule = empty($config->accountRule) ? '|^[a-zA-Z0-9_]{1}[a-zA-Z0-9_\.]{1,}[a-zA-Z0-9_]{1}$|' : $config->accountRule;
|
||||
return self::checkREG($var, $accountRule);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查Code。
|
||||
* Check code.
|
||||
*
|
||||
* @param string $var
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkCode($var)
|
||||
{
|
||||
return self::checkREG($var, '|^[A-Za-z0-9]+$|');
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查验证码。
|
||||
* Check captcha.
|
||||
*
|
||||
* @param mixed $var
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkCaptcha($var)
|
||||
{
|
||||
if(!isset($_SESSION['captcha'])) return false;
|
||||
return $var == $_SESSION['captcha'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否等于给定的值。
|
||||
* Must equal a value.
|
||||
*
|
||||
* @param mixed $var
|
||||
* @param mixed $value
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkEqual($var, $value)
|
||||
{
|
||||
return $var == $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查不等于给定的值
|
||||
* Must not equal a value.
|
||||
*
|
||||
* @param mixed $var
|
||||
* @param mixed $value
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkNotEqual($var, $value)
|
||||
{
|
||||
return $var != $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查大于给定的值。
|
||||
* Must greater than a value.
|
||||
*
|
||||
* @param mixed $var
|
||||
* @param mixed $value
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkGT($var, $value)
|
||||
{
|
||||
return $var > $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查小于给定的值
|
||||
* Must less than a value.
|
||||
*
|
||||
* @param mixed $var
|
||||
* @param mixed $value
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkLT($var, $value)
|
||||
{
|
||||
return $var < $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查大于等于给定的值
|
||||
* Must greater than a value or equal a value.
|
||||
*
|
||||
* @param mixed $var
|
||||
* @param mixed $value
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkGE($var, $value)
|
||||
{
|
||||
return $var >= $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查小于等于给定的值
|
||||
* Must less than a value or equal a value.
|
||||
*
|
||||
* @param mixed $var
|
||||
* @param mixed $value
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkLE($var, $value)
|
||||
{
|
||||
return $var <= $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否在给定的列表里面。
|
||||
* Must in value list.
|
||||
*
|
||||
* @param mixed $var
|
||||
* @param mixed $value
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkIn($var, $value)
|
||||
{
|
||||
if(!is_array($value)) $value = explode(',', $value);
|
||||
return in_array($var, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查文件名。
|
||||
* Check file name.
|
||||
*
|
||||
* @param string $var
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkFileName($var)
|
||||
{
|
||||
return !preg_match('/>+|:+|<+/', $var);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查敏感词。
|
||||
* Check sensitive words.
|
||||
*
|
||||
* @param object $vars
|
||||
* @param array $dicts
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public static function checkSensitive($vars, $dicts)
|
||||
{
|
||||
foreach($vars as $var)
|
||||
{
|
||||
if(!$var) continue;
|
||||
foreach($dicts as $dict)
|
||||
{
|
||||
if(strpos($var, $dict) === false) continue;
|
||||
if(strpos($var, $dict) !== false) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用一个方法进行检查。
|
||||
* Call a function to check it.
|
||||
*
|
||||
* @param mixed $var
|
||||
* @param string $func
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function call($var, $func)
|
||||
{
|
||||
return filter_var($var, FILTER_CALLBACK, array('options' => $func));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* fixer类,处理数据。
|
||||
* fixer class, to fix data types.
|
||||
*
|
||||
* @package framework
|
||||
*/
|
||||
class baseFixer
|
||||
{
|
||||
/**
|
||||
* 处理的数据。
|
||||
* The data to be fixed.
|
||||
*
|
||||
* @var ojbect
|
||||
* @access public
|
||||
*/
|
||||
public $data;
|
||||
|
||||
/**
|
||||
* 跳过处理的字段。
|
||||
* The fields to striped.
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
*/
|
||||
public $stripedFields = array();
|
||||
|
||||
/**
|
||||
* 构造方法,将超级全局变量转换为对象。
|
||||
* The construction function, according the scope, convert it to object.
|
||||
*
|
||||
* @param string $scope the scope of the var, should be post|get|server|session|cookie|env
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($scope)
|
||||
{
|
||||
switch($scope)
|
||||
{
|
||||
case 'post':
|
||||
$this->data = (object)$_POST;
|
||||
break;
|
||||
case 'server':
|
||||
$this->data = (object)$_SERVER;
|
||||
break;
|
||||
case 'get':
|
||||
$this->data = (object)$_GET;
|
||||
break;
|
||||
case 'session':
|
||||
$this->data = (object)$_SESSION;
|
||||
break;
|
||||
case 'cookie':
|
||||
$this->data = (object)$_COOKIE;
|
||||
break;
|
||||
case 'env':
|
||||
$this->data = (object)$_ENV;
|
||||
break;
|
||||
case 'file':
|
||||
$this->data = (object)$_FILES;
|
||||
break;
|
||||
|
||||
default:
|
||||
die('scope not supported, should be post|get|server|session|cookie|env');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 工厂方法。
|
||||
* The factory function.
|
||||
*
|
||||
* @param string $scope
|
||||
* @access public
|
||||
* @return object fixer object.
|
||||
*/
|
||||
public static function input($scope)
|
||||
{
|
||||
return new fixer($scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理Email。
|
||||
* Email fix.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @access public
|
||||
* @return object fixer object.
|
||||
*/
|
||||
public function cleanEmail($fieldName)
|
||||
{
|
||||
$fields = $this->processFields($fieldName);
|
||||
foreach($fields as $fieldName) $this->data->$fieldName = filter_var($this->data->$fieldName, FILTER_SANITIZE_EMAIL);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* url编码。
|
||||
* urlencode.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @access public
|
||||
* @return object fixer object.
|
||||
*/
|
||||
public function encodeURL($fieldName)
|
||||
{
|
||||
$fields = $this->processFields($fieldName);
|
||||
$args = func_get_args();
|
||||
foreach($fields as $fieldName)
|
||||
{
|
||||
$this->data->$fieldName = isset($args[1]) ? filter_var($this->data->$fieldName, FILTER_SANITIZE_ENCODED, $args[1]) : filter_var($this->data->$fieldName, FILTER_SANITIZE_ENCODED);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理网址。
|
||||
* Clean the url.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @access public
|
||||
* @return object fixer object.
|
||||
*/
|
||||
public function cleanURL($fieldName)
|
||||
{
|
||||
$fields = $this->processFields($fieldName);
|
||||
foreach($fields as $fieldName) $this->data->$fieldName = filter_var($this->data->$fieldName, FILTER_SANITIZE_URL);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理Float类型。
|
||||
* Float fixer.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @access public
|
||||
* @return object fixer object.
|
||||
*/
|
||||
public function cleanFloat($fieldName)
|
||||
{
|
||||
$fields = $this->processFields($fieldName);
|
||||
foreach($fields as $fieldName) $this->data->$fieldName = filter_var($this->data->$fieldName, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION|FILTER_FLAG_ALLOW_THOUSAND);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理Int类型。
|
||||
* Int fixer.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @access public
|
||||
* @return object fixer object.
|
||||
*/
|
||||
public function cleanINT($fieldName = '')
|
||||
{
|
||||
$fields = $this->processFields($fieldName);
|
||||
foreach($fields as $fieldName) $this->data->$fieldName = filter_var($this->data->$fieldName, FILTER_SANITIZE_NUMBER_INT);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串转换为可以在浏览器查看的编码。
|
||||
* Special chars.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @access public
|
||||
* @return object fixer object
|
||||
*/
|
||||
public function specialChars($fieldName)
|
||||
{
|
||||
$fields = $this->processFields($fieldName);
|
||||
foreach($fields as $fieldName)
|
||||
{
|
||||
if(empty($this->stripedFields) or !in_array($fieldName, $this->stripedFields)) $this->data->$fieldName = $this->specialArray($this->data->$fieldName);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Special array
|
||||
*
|
||||
* @param mix $data
|
||||
* @access public
|
||||
* @return mix
|
||||
*/
|
||||
public function specialArray($data)
|
||||
{
|
||||
if(!is_array($data)) return htmlspecialchars($data, ENT_QUOTES);
|
||||
|
||||
foreach($data as &$value) $value = $this->specialArray($value);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 忽略该标签。
|
||||
* Strip tags
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @param string $allowableTags
|
||||
* @access public
|
||||
* @return object fixer object
|
||||
*/
|
||||
public function stripTags($fieldName, $allowedTags = '')
|
||||
{
|
||||
global $app, $config;
|
||||
if(empty($allowedTags) and isset($config->allowedTags)) $allowedTags = $config->allowedTags;
|
||||
$usePurifier = isset($config->framework->purifier) ? $config->framework->purifier : false;
|
||||
if($usePurifier)
|
||||
{
|
||||
$app->loadClass('purifier', true);
|
||||
$purifierConfig = HTMLPurifier_Config::createDefault();
|
||||
$purifierConfig->set('Filter.YouTube', 1);
|
||||
|
||||
/* Disable caching. */
|
||||
$purifierConfig->set('Cache.DefinitionImpl', null);
|
||||
|
||||
$purifier = new HTMLPurifier($purifierConfig);
|
||||
$def = $purifierConfig->getHTMLDefinition(true);
|
||||
$def->addAttribute('a', 'target', 'Enum#_blank,_self,_target,_top');
|
||||
}
|
||||
|
||||
$fields = $this->processFields($fieldName);
|
||||
foreach($fields as $fieldName)
|
||||
{
|
||||
if(version_compare(phpversion(), '5.4', '<') and get_magic_quotes_gpc()) $this->data->$fieldName = stripslashes($this->data->$fieldName);
|
||||
|
||||
if(!in_array($fieldName, $this->stripedFields))
|
||||
{
|
||||
if(!defined('RUN_MODE') or RUN_MODE != 'admin')
|
||||
{
|
||||
/*
|
||||
* purifier会把 替换空格,kindeditor在会吧行首的空格去掉。
|
||||
* purifier will change to ' ', and edit it will no space in line head use kindeditor.
|
||||
**/
|
||||
if($usePurifier) $this->data->$fieldName = str_replace(' ', '&spnb;', $this->data->$fieldName);
|
||||
$this->data->$fieldName = $usePurifier ? $purifier->purify($this->data->$fieldName) : strip_tags($this->data->$fieldName, $allowedTags);
|
||||
if($usePurifier) $this->data->$fieldName = str_replace('&spnb;', ' ', $this->data->$fieldName);
|
||||
}
|
||||
}
|
||||
$this->stripedFields[] = $fieldName;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 忽略处理给定的字段。
|
||||
* Skip special chars check.
|
||||
*
|
||||
* @param string $filename
|
||||
* @access public
|
||||
* @return object fixer object
|
||||
*/
|
||||
public function skipSpecial($fieldName)
|
||||
{
|
||||
$fields = $this->processFields($fieldName);
|
||||
foreach($fields as $fieldName) $this->stripedFields[] = $fieldName;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 给字段添加引用,防止字符与关键字冲突。
|
||||
* Quote
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @access public
|
||||
* @return object fixer object
|
||||
*/
|
||||
public function quote($fieldName)
|
||||
{
|
||||
$fields = $this->processFields($fieldName);
|
||||
foreach($fields as $fieldName) $this->data->$fieldName = filter_var($this->data->$fieldName, FILTER_SANITIZE_MAGIC_QUOTES);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置字段的默认值。
|
||||
* Set default value of some fileds.
|
||||
*
|
||||
* @param string $fields
|
||||
* @param mixed $value
|
||||
* @access public
|
||||
* @return object fixer object
|
||||
*/
|
||||
public function setDefault($fields, $value)
|
||||
{
|
||||
$fields = strpos($fields, ',') ? explode(',', str_replace(' ', '', $fields)) : array($fields);
|
||||
foreach($fields as $fieldName)if(!isset($this->data->$fieldName) or empty($this->data->$fieldName)) $this->data->$fieldName = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果条件为真,则为字段赋值。
|
||||
* Set value of a filed on the condition is true.
|
||||
*
|
||||
* @param bool $condition
|
||||
* @param string $fieldName
|
||||
* @param string $value
|
||||
* @access public
|
||||
* @return object fixer object
|
||||
*/
|
||||
public function setIF($condition, $fieldName, $value)
|
||||
{
|
||||
if($condition) $this->data->$fieldName = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 强制给字段赋值。
|
||||
* Set the value of a filed in force.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @param mixed $value
|
||||
* @access public
|
||||
* @return object fixer object
|
||||
*/
|
||||
public function setForce($fieldName, $value)
|
||||
{
|
||||
$this->data->$fieldName = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除一个字段。
|
||||
* Remove a field.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @access public
|
||||
* @return object fixer object
|
||||
*/
|
||||
public function remove($fieldName)
|
||||
{
|
||||
$fields = $this->processFields($fieldName);
|
||||
foreach($fields as $fieldName) unset($this->data->$fieldName);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果条件为真,移除该字段。
|
||||
* Remove a filed on the condition is true.
|
||||
*
|
||||
* @param bool $condition
|
||||
* @param string $fields
|
||||
* @access public
|
||||
* @return object fixer object
|
||||
*/
|
||||
public function removeIF($condition, $fields)
|
||||
{
|
||||
$fields = $this->processFields($fields);
|
||||
if($condition) foreach($fields as $fieldName) unset($this->data->$fieldName);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 为数据添加新的项。
|
||||
* Add an item to the data.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @param mixed $value
|
||||
* @access public
|
||||
* @return object fixer object
|
||||
*/
|
||||
public function add($fieldName, $value)
|
||||
{
|
||||
$this->data->$fieldName = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果条件为真,则为数据添加新的项。
|
||||
* Add an item to the data on the condition if true.
|
||||
*
|
||||
* @param bool $condition
|
||||
* @param string $fieldName
|
||||
* @param mixed $value
|
||||
* @access public
|
||||
* @return object fixer object
|
||||
*/
|
||||
public function addIF($condition, $fieldName, $value)
|
||||
{
|
||||
if($condition) $this->data->$fieldName = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 为指定字段增加值。
|
||||
* Join the field.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @param string $value
|
||||
* @access public
|
||||
* @return object fixer object
|
||||
*/
|
||||
public function join($fieldName, $value)
|
||||
{
|
||||
if(!isset($this->data->$fieldName) or !is_array($this->data->$fieldName)) return $this;
|
||||
$this->data->$fieldName = join($value, $this->data->$fieldName);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用一个方法来处理数据。
|
||||
* Call a function to fix it.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @param string $func
|
||||
* @access public
|
||||
* @return object fixer object
|
||||
*/
|
||||
public function callFunc($fieldName, $func)
|
||||
{
|
||||
$fields = $this->processFields($fieldName);
|
||||
foreach($fields as $fieldName) $this->data->$fieldName = filter_var($this->data->$fieldName, FILTER_CALLBACK, array('options' => $func));
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理完成后返回数据。
|
||||
* Get the data after fixing.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function get($fields = '')
|
||||
{
|
||||
$fields = str_replace(' ', '', trim($fields));
|
||||
foreach($this->data as $field => $value) $this->specialChars($field);
|
||||
|
||||
if(empty($fields)) return $this->data;
|
||||
if(strpos($fields, ',') === false) return $this->data->$fields;
|
||||
|
||||
$fields = array_flip(explode(',', $fields));
|
||||
foreach($this->data as $field => $value)
|
||||
{
|
||||
if(!isset($fields[$field])) unset($this->data->$field);
|
||||
if(!in_array($field, $this->stripedFields)) $this->data->$field = $this->specialChars($this->data->field);
|
||||
}
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理字段,如果字段中含有',',拆分成数组。如果字段不在$data中,删除掉。
|
||||
* Process fields, if contains ',', split it to array. If not in $data, remove it.
|
||||
*
|
||||
* @param string $fields
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function processFields($fields)
|
||||
{
|
||||
$fields = strpos($fields, ',') ? explode(',', str_replace(' ', '', $fields)) : array($fields);
|
||||
foreach($fields as $key => $fieldName) if(!isset($this->data->$fieldName)) unset($fields[$key]);
|
||||
return $fields;
|
||||
}
|
||||
}
|
||||
1200
lib/base/front/front.class.php
Normal file
1200
lib/base/front/front.class.php
Normal file
File diff suppressed because it is too large
Load Diff
620
lib/base/pager/pager.class.php
Normal file
620
lib/base/pager/pager.class.php
Normal file
@@ -0,0 +1,620 @@
|
||||
<?php
|
||||
/**
|
||||
* ZenTaoPHP的分页类。
|
||||
* The pager class file of ZenTaoPHP framework.
|
||||
*
|
||||
* The author disclaims copyright to this source code. In place of
|
||||
* a legal notice, here is a blessing:
|
||||
*
|
||||
* May you do good and not evil.
|
||||
* May you find forgiveness for yourself and forgive others.
|
||||
* May you share freely, never taking more than you give.
|
||||
*/
|
||||
/**
|
||||
* pager类.
|
||||
* Pager class.
|
||||
*
|
||||
* @package framework
|
||||
*/
|
||||
class basePager
|
||||
{
|
||||
/**
|
||||
* 每页的默认显示记录数。
|
||||
* The default counts of per page.
|
||||
*
|
||||
* @public int
|
||||
*/
|
||||
const DEFAULT_REC_PER_PAGE = 20;
|
||||
|
||||
/**
|
||||
* 总个数。
|
||||
* The total counts.
|
||||
*
|
||||
* @var int
|
||||
* @access public
|
||||
*/
|
||||
public $recTotal;
|
||||
|
||||
/**
|
||||
* 每页的记录数。
|
||||
* Record count per page.
|
||||
*
|
||||
* @var int
|
||||
* @access public
|
||||
*/
|
||||
public $recPerPage;
|
||||
|
||||
/**
|
||||
* The cookie name of recPerPage.
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
public $pageCookie;
|
||||
|
||||
/**
|
||||
* 总页面数。
|
||||
* Page count.
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
public $pageTotal;
|
||||
|
||||
/**
|
||||
* 当前页码。
|
||||
* Current page id.
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
public $pageID;
|
||||
|
||||
/**
|
||||
* 全局变量$app。
|
||||
* The global $app.
|
||||
*
|
||||
* @var object
|
||||
* @access public
|
||||
*/
|
||||
public $app;
|
||||
|
||||
/**
|
||||
* 全局变量$lang。
|
||||
* The global $lang.
|
||||
*
|
||||
* @var object
|
||||
* @access public
|
||||
*/
|
||||
public $lang;
|
||||
|
||||
/**
|
||||
* 当前的模块名。
|
||||
* Current module name.
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
public $moduleName;
|
||||
|
||||
/**
|
||||
* 当前的方法名。
|
||||
* Current method.
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
public $methodName;
|
||||
|
||||
/**
|
||||
* 参数信息。
|
||||
* The params.
|
||||
*
|
||||
* @public array
|
||||
*/
|
||||
public $params;
|
||||
|
||||
/**
|
||||
* 构造方法。
|
||||
* The construct function.
|
||||
*
|
||||
* @param int $recTotal
|
||||
* @param int $recPerPage
|
||||
* @param int $pageID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($recTotal = 0, $recPerPage = 20, $pageID = 1)
|
||||
{
|
||||
$this->setApp();
|
||||
$this->setLang();
|
||||
$this->setModuleName();
|
||||
$this->setMethodName();
|
||||
|
||||
$this->setRecTotal($recTotal);
|
||||
$this->setRecPerPage($recPerPage);
|
||||
$this->setPageTotal();
|
||||
$this->setPageID($pageID);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造方法。
|
||||
* The factory function.
|
||||
*
|
||||
* @param int $recTotal
|
||||
* @param int $recPerPage
|
||||
* @param int $pageID
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public static function init($recTotal = 0, $recPerPage = 20, $pageID = 1)
|
||||
{
|
||||
return new pager($recTotal, $recPerPage, $pageID);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置总记录数。
|
||||
* Set the recTotal property.
|
||||
*
|
||||
* @param int $recTotal
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setRecTotal($recTotal = 0)
|
||||
{
|
||||
$this->recTotal = (int)$recTotal;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置每页记录数。
|
||||
* Set the recPerPage property.
|
||||
*
|
||||
* @param int $recPerPage
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setRecPerPage($recPerPage)
|
||||
{
|
||||
/* Set the cookie name. */
|
||||
$this->pageCookie = 'pager' . ucfirst($this->app->getModuleName()) . ucfirst($this->app->getMethodName());
|
||||
|
||||
if(isset($_COOKIE[$this->pageCookie])) $recPerPage = $_COOKIE[$this->pageCookie];
|
||||
$this->recPerPage = ($recPerPage > 0) ? $recPerPage : PAGER::DEFAULT_REC_PER_PAGE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置总页数。
|
||||
* Set the pageTotal property.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setPageTotal()
|
||||
{
|
||||
$this->pageTotal = ceil($this->recTotal / $this->recPerPage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置页码。
|
||||
* Set the page id.
|
||||
*
|
||||
* @param int $pageID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setPageID($pageID)
|
||||
{
|
||||
if($pageID > 0 and ($this->pageTotal == 0 or $pageID <= $this->pageTotal))
|
||||
{
|
||||
$this->pageID = $pageID;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->pageID = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置全局变量$app。
|
||||
* Set the $app property;
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setApp()
|
||||
{
|
||||
global $app;
|
||||
$this->app = $app;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置全局变量$lang。
|
||||
* Set the $lang property.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setLang()
|
||||
{
|
||||
global $lang;
|
||||
$this->lang = $lang;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置模块名。
|
||||
* Set the $moduleName property.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setModuleName()
|
||||
{
|
||||
$this->moduleName = $this->app->getModuleName();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置方法名。
|
||||
* Set the $methodName property.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setMethodName()
|
||||
{
|
||||
$this->methodName = $this->app->getMethodName();
|
||||
}
|
||||
|
||||
/**
|
||||
* 从请求网址中获取记录总数、每页记录数、页码。
|
||||
* Get recTotal, recPerpage, pageID from the request params, and add them to params.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setParams()
|
||||
{
|
||||
$this->params = $this->app->getParams();
|
||||
foreach($this->params as $key => $value)
|
||||
{
|
||||
if(strtolower($key) == 'rectotal') $this->params[$key] = $this->recTotal;
|
||||
if(strtolower($key) == 'recperpage') $this->params[$key] = $this->recPerPage;
|
||||
if(strtolower($key) == 'pageid') $this->params[$key] = $this->pageID;
|
||||
}
|
||||
|
||||
parse_str(strip_tags(urldecode($_SERVER['QUERY_STRING'])), $query);
|
||||
|
||||
unset($query['m']);
|
||||
unset($query['f']);
|
||||
unset($query['t']);
|
||||
|
||||
$this->params = array_merge($this->params, $query);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建limit语句。
|
||||
* Create the limit string.
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function limit()
|
||||
{
|
||||
$limit = '';
|
||||
if($this->pageTotal > 1) $limit = ' limit ' . ($this->pageID - 1) * $this->recPerPage . ", $this->recPerPage";
|
||||
return $limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* 向页面显示分页信息。
|
||||
* Print the pager's html.
|
||||
*
|
||||
* @param string $align
|
||||
* @param string $type
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function show($align = 'right', $type = 'full')
|
||||
{
|
||||
if($align === 'justify')
|
||||
{
|
||||
echo $this->getJustify($type);
|
||||
}
|
||||
else
|
||||
{
|
||||
echo $this->get($align, $type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取优化后的分页。
|
||||
* Get the justify pager html string
|
||||
*
|
||||
* @access public
|
||||
* @return [type] [description]
|
||||
*/
|
||||
public function getJustify()
|
||||
{
|
||||
if($this->recTotal <= 0) return '';
|
||||
|
||||
$this->setParams();
|
||||
$pager = '';
|
||||
|
||||
$pager .= "<li class='previous" . ($this->pageID == 1 ? ' disabled' : '') . "'>";
|
||||
$this->params['pageID'] = 1;
|
||||
$pager .= $this->createLink('« ' . $this->lang->pager->previousPage) . '</li>';
|
||||
|
||||
$pager .= "<li class='caption'>";
|
||||
$firstId = $this->recPerPage * ($this->pageID - 1) + 1;
|
||||
$pager .= sprintf($this->lang->pager->summery, $firstId, max(min($this->recPerPage * $this->pageID, $this->recTotal), $firstId), $this->recTotal);
|
||||
$pager .= '</li>';
|
||||
|
||||
$pager .= "<li class='next" . (($this->pageID == $this->pageTotal || $this->pageTotal <= 1) ? ' disabled' : '') . "'>";
|
||||
$this->params['pageID'] = min($this->pageTotal, $this->pageID + 1);
|
||||
$pager .= $this->createLink($this->lang->pager->nextPage . ' »') . '</li>';
|
||||
|
||||
return "<ul class='pager pager-justify'>{$pager}</ul>";
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置分页信息的样式。
|
||||
* Get the pager html string.
|
||||
*
|
||||
* @param string $align
|
||||
* @param string $type the pager type, full|short|shortest
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function get($align = 'right', $type = 'full')
|
||||
{
|
||||
/* 如果记录个数为0,返回没有记录。 */
|
||||
/* If the RecTotal is zero, return with no record. */
|
||||
if($this->recTotal == 0) return $type == 'mobile' ? '' : "<div style='float:$align; clear:none;' class='page'>{$this->lang->pager->noRecord}</div>";
|
||||
|
||||
/* Set the params. */
|
||||
$this->setParams();
|
||||
|
||||
/* 创建前一页和后一页链接。 */
|
||||
/* Create the prePage and nextpage, all types have them. */
|
||||
$pager = $this->createPrePage($type);
|
||||
$pager .= $this->createNextPage($type);
|
||||
|
||||
/* 简单和完全模式。 The short and full type. */
|
||||
if($type !== 'shortest' and $type !== 'mobile')
|
||||
{
|
||||
$pager = $this->createFirstPage() . $pager;
|
||||
$pager .= $this->createLastPage();
|
||||
}
|
||||
|
||||
if($type == 'mobile')
|
||||
{
|
||||
$position = $this->pageTotal == 1 ? '' : $this->pageID . '/' . $this->pageTotal;
|
||||
$pager = $pager . ' ' . $position;
|
||||
}
|
||||
else if($type != 'full')
|
||||
{
|
||||
$pager = $this->pageID . '/' . $this->pageTotal . ' ' . $pager;
|
||||
}
|
||||
|
||||
/* 只是完全模式。 Only the full type . */
|
||||
if($type == 'full')
|
||||
{
|
||||
$pager = $this->createDigest() . $pager;
|
||||
$pager .= $this->createGoTo();
|
||||
$pager .= $this->createRecPerPageJS();
|
||||
}
|
||||
|
||||
return "<div style='float:$align; clear:none;' class='pager form-inline'>$pager</div>";
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成分页摘要信息。
|
||||
* Create the digest code.
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function createDigest()
|
||||
{
|
||||
return sprintf($this->lang->pager->digest, $this->recTotal, $this->createRecPerPageList(), $this->pageID, $this->pageTotal);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建首页链接。
|
||||
* Create the first page.
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function createFirstPage()
|
||||
{
|
||||
if($this->pageID == 1) return $this->lang->pager->first . ' ';
|
||||
$this->params['pageID'] = 1;
|
||||
return $this->createLink($this->lang->pager->first);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建前一页链接。
|
||||
* Create the pre page html.
|
||||
*
|
||||
* @param string $type
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function createPrePage($type = 'full')
|
||||
{
|
||||
if($type == 'mobile')
|
||||
{
|
||||
if($this->pageID == 1) return '';
|
||||
$this->params['pageID'] = $this->pageID - 1;
|
||||
return $this->createLink($this->lang->pager->pre);
|
||||
}
|
||||
else
|
||||
{
|
||||
if($this->pageID == 1) return $this->lang->pager->pre . ' ';
|
||||
$this->params['pageID'] = $this->pageID - 1;
|
||||
return $this->createLink($this->lang->pager->pre);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建下一页链接。
|
||||
* Create the next page html.
|
||||
*
|
||||
* @param string $type
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function createNextPage($type = 'full')
|
||||
{
|
||||
if($type == 'mobile')
|
||||
{
|
||||
if($this->pageID == $this->pageTotal) return '';
|
||||
$this->params['pageID'] = $this->pageID + 1;
|
||||
return $this->createLink($this->lang->pager->next);
|
||||
}
|
||||
else
|
||||
{
|
||||
if($this->pageID == $this->pageTotal) return $this->lang->pager->next . ' ';
|
||||
$this->params['pageID'] = $this->pageID + 1;
|
||||
return $this->createLink($this->lang->pager->next);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建最后一页链接。
|
||||
* Create the last page
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function createLastPage()
|
||||
{
|
||||
if($this->pageID == $this->pageTotal) return $this->lang->pager->last . ' ';
|
||||
$this->params['pageID'] = $this->pageTotal;
|
||||
return $this->createLink($this->lang->pager->last);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建每页显示记录数的select标签。
|
||||
* Create the select object of record perpage.
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function createRecPerPageJS()
|
||||
{
|
||||
/*
|
||||
* 替换recTotal, recPerPage, pageID为特殊的字符串,然后用js代码替换掉。
|
||||
* Replace the recTotal, recPerPage, pageID to special string, and then replace them with values by JS.
|
||||
**/
|
||||
$params = $this->params;
|
||||
foreach($params as $key => $value)
|
||||
{
|
||||
if(strtolower($key) == 'rectotal') $params[$key] = '_recTotal_';
|
||||
if(strtolower($key) == 'recperpage') $params[$key] = '_recPerPage_';
|
||||
if(strtolower($key) == 'pageid') $params[$key] = '_pageID_';
|
||||
}
|
||||
$vars = '';
|
||||
foreach($params as $key => $value) $vars .= "$key=$value&";
|
||||
$vars = rtrim($vars, '&');
|
||||
|
||||
$js = <<<EOT
|
||||
<script language='Javascript'>
|
||||
vars = '$vars';
|
||||
pageCookie = '$this->pageCookie';
|
||||
function submitPage(mode, perPage)
|
||||
{
|
||||
pageTotal = parseInt(document.getElementById('_pageTotal').value);
|
||||
pageID = document.getElementById('_pageID').value;
|
||||
recPerPage = document.getElementById('_recPerPage').getAttribute('data-value');
|
||||
recTotal = document.getElementById('_recTotal').value;
|
||||
if(mode == 'changePageID')
|
||||
{
|
||||
if(pageID > pageTotal) pageID = pageTotal;
|
||||
if(pageID < 1) pageID = 1;
|
||||
}
|
||||
else if(mode == 'changeRecPerPage')
|
||||
{
|
||||
recPerPage = perPage;
|
||||
pageID = 1;
|
||||
}
|
||||
$.cookie(pageCookie, recPerPage, {expires:config.cookieLife, path:config.webRoot});
|
||||
|
||||
vars = vars.replace('_recTotal_', recTotal)
|
||||
vars = vars.replace('_recPerPage_', recPerPage)
|
||||
vars = vars.replace('_pageID_', pageID);
|
||||
location.href=createLink('$this->moduleName', '$this->methodName', vars);
|
||||
}
|
||||
</script>
|
||||
EOT;
|
||||
return $js;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成每页显示记录数的select列表。
|
||||
* Create the select list of RecPerPage.
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function createRecPerPageList()
|
||||
{
|
||||
for($i = 5; $i <= 50; $i += 5) $range[$i] = $i;
|
||||
$range[100] = 100;
|
||||
$range[200] = 200;
|
||||
$range[500] = 500;
|
||||
$range[1000] = 1000;
|
||||
$range[2000] = 2000;
|
||||
$html = "<div class='dropdown dropup'><a href='javascript:;' data-toggle='dropdown' id='_recPerPage' data-value='{$this->recPerPage}'>" . (sprintf($this->lang->pager->recPerPage, $this->recPerPage)) . "<span class='caret'></span></a><ul class='dropdown-menu'>";
|
||||
foreach ($range as $key => $value)
|
||||
{
|
||||
$html .= '<li' . ($this->recPerPage == $value ? " class='active'" : '') .'>' . "<a href='javascript:submitPage(\"changeRecPerPage\", $value)'>{$value}</a>" . '</li>';
|
||||
}
|
||||
$html .= '</ul></div>';
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成跳转到指定页码的部分。
|
||||
* Create the goto part html.
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function createGoTo()
|
||||
{
|
||||
$goToHtml = "<input type='hidden' id='_recTotal' value='$this->recTotal' />\n";
|
||||
$goToHtml .= "<input type='hidden' id='_pageTotal' value='$this->pageTotal' />\n";
|
||||
$goToHtml .= "<input type='text' id='_pageID' value='$this->pageID' style='text-align:center;width:30px;' class='form-control' /> \n";
|
||||
$goToHtml .= "<input type='button' id='goto' value='{$this->lang->pager->locate}' onclick='submitPage(\"changePageID\");' class='btn'/>";
|
||||
return $goToHtml;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建链接。
|
||||
* Create link.
|
||||
*
|
||||
* @param string $title
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function createLink($title)
|
||||
{
|
||||
global $config;
|
||||
if(helper::inSeoMode() && method_exists('uri', 'create' . $this->moduleName . $this->methodName))
|
||||
{
|
||||
$link = strip_tags(urldecode($_SERVER['REQUEST_URI']));
|
||||
|
||||
if($this->params['pageID'] == 1) return html::a(preg_replace('/\/p\d+\./', '.', $link), $title);
|
||||
|
||||
if(preg_match('/\/p\d+/', $link)) return html::a(preg_replace('/\/p\d+\./', '/p' . $this->params['pageID'] . '.', $link), $title);
|
||||
|
||||
if($config->requestType == 'PATH_INFO2') $link = str_replace('index.php/', 'index_php/', $link);
|
||||
$link = str_replace('.', "/p{$this->params['pageID']}.", $link);
|
||||
if($config->requestType == 'PATH_INFO2') $link = str_replace('index_php/', 'index.php/', $link);
|
||||
return html::a($link, $title);
|
||||
}
|
||||
return html::a(helper::createLink($this->moduleName, $this->methodName, $this->params), $title);
|
||||
}
|
||||
}
|
||||
1699
lib/dao/dao.class.php
Executable file → Normal file
1699
lib/dao/dao.class.php
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
740
lib/filter/filter.class.php
Executable file → Normal file
740
lib/filter/filter.class.php
Executable file → Normal file
@@ -1,755 +1,33 @@
|
||||
<?php
|
||||
/**
|
||||
* ZenTaoPHP的验证和过滤类。
|
||||
* The validater and fixer class file of ZenTaoPHP framework.
|
||||
*
|
||||
* The author disclaims copyright to this source code. In place of
|
||||
* a legal notice, here is a blessing:
|
||||
*
|
||||
*
|
||||
* May you do good and not evil.
|
||||
* May you find forgiveness for yourself and forgive others.
|
||||
* May you share freely, never taking more than you give.
|
||||
*/
|
||||
|
||||
helper::import(dirname(dirname(__FILE__)) . '/base/filter/filter.class.php');
|
||||
/**
|
||||
* The valida class, checking datas by rules.
|
||||
*
|
||||
* validater类,检查数据是否符合规则。
|
||||
* The validater class, checking data by rules.
|
||||
*
|
||||
* @package framework
|
||||
*/
|
||||
class validater
|
||||
class validater extends baseValidater
|
||||
{
|
||||
/**
|
||||
* The max count of args.
|
||||
*/
|
||||
const MAX_ARGS = 3;
|
||||
|
||||
/**
|
||||
* Bool checking.
|
||||
*
|
||||
* @param bool $var
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkBool($var)
|
||||
{
|
||||
return filter_var($var, FILTER_VALIDATE_BOOLEAN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Int checking.
|
||||
*
|
||||
* @param int $var
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkInt($var)
|
||||
{
|
||||
$args = func_get_args();
|
||||
if($var != 0) $var = ltrim($var, 0); // Remove the left 0, filter don't think 00 is an int.
|
||||
|
||||
/* Min is setted. */
|
||||
if(isset($args[1]))
|
||||
{
|
||||
/* And Max is setted. */
|
||||
if(isset($args[2]))
|
||||
{
|
||||
$options = array('options' => array('min_range' => $args[1], 'max_range' => $args[2]));
|
||||
}
|
||||
else
|
||||
{
|
||||
$options = array('options' => array('min_range' => $args[1]));
|
||||
}
|
||||
|
||||
return filter_var($var, FILTER_VALIDATE_INT, $options);
|
||||
}
|
||||
else
|
||||
{
|
||||
return filter_var($var, FILTER_VALIDATE_INT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Float checking.
|
||||
*
|
||||
* @param float $var
|
||||
* @param string $decimal
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkFloat($var, $decimal = '.')
|
||||
{
|
||||
return filter_var($var, FILTER_VALIDATE_FLOAT, array('options' => array('decimail' => $decimal)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Email checking.
|
||||
*
|
||||
* @param string $var
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkEmail($var)
|
||||
{
|
||||
return filter_var($var, FILTER_VALIDATE_EMAIL);
|
||||
}
|
||||
|
||||
/**
|
||||
* URL checking.
|
||||
*
|
||||
* The check rule of filter don't support chinese.
|
||||
*
|
||||
* @param string $var
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkURL($var)
|
||||
{
|
||||
return filter_var($var, FILTER_VALIDATE_URL);
|
||||
}
|
||||
|
||||
/**
|
||||
* IP checking.
|
||||
*
|
||||
* @param ip $var
|
||||
* @param string $range all|public|static|private
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkIP($var, $range = 'all')
|
||||
{
|
||||
if($range == 'all') return filter_var($var, FILTER_VALIDATE_IP);
|
||||
if($range == 'public static') return filter_var($var, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE);
|
||||
if($range == 'private')
|
||||
{
|
||||
if($var == '127.0.0.1' or filter_var($var, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE) === false) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Date checking. Note: 2009-09-31 will be an valid date, because strtotime auto fixed it to 10-01.
|
||||
*
|
||||
* @param date $date
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkDate($date)
|
||||
{
|
||||
if($date == '0000-00-00') return true;
|
||||
$stamp = strtotime($date);
|
||||
if(!is_numeric($stamp)) return false;
|
||||
return checkdate(date('m', $stamp), date('d', $stamp), date('Y', $stamp));
|
||||
}
|
||||
|
||||
/**
|
||||
* REG checking.
|
||||
*
|
||||
* @param string $var
|
||||
* @param string $reg
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkREG($var, $reg)
|
||||
{
|
||||
return filter_var($var, FILTER_VALIDATE_REGEXP, array('options' => array('regexp' => $reg)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Length checking.
|
||||
*
|
||||
* @param string $var
|
||||
* @param string $max
|
||||
* @param int $min
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkLength($var, $max, $min = 0)
|
||||
{
|
||||
$length = function_exists('mb_strlen') ? mb_strlen($var, 'utf-8') : strlen($var);
|
||||
return self::checkInt($length, $min, $max);
|
||||
}
|
||||
|
||||
/**
|
||||
* Not empty checking.
|
||||
*
|
||||
* @param mixed $var
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkNotEmpty($var)
|
||||
{
|
||||
return !empty($var);
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty checking.
|
||||
*
|
||||
* @param mixed $var
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkEmpty($var)
|
||||
{
|
||||
return empty($var);
|
||||
}
|
||||
|
||||
/**
|
||||
* Account checking.
|
||||
*
|
||||
* @param string $var
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkAccount($var)
|
||||
{
|
||||
global $config;
|
||||
$accountRule = empty($config->accountRule) ? '|^[a-zA-Z0-9_]{1}[a-zA-Z0-9_\.]{1,}[a-zA-Z0-9_]{1}$|' : $config->accountRule;
|
||||
return self::checkREG($var, $accountRule);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check captcha.
|
||||
*
|
||||
* @param mixed $var
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkCaptcha($var)
|
||||
{
|
||||
if(!isset($_SESSION['captcha'])) return false;
|
||||
return $var == $_SESSION['captcha'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Must equal a value.
|
||||
*
|
||||
* @param mixed $var
|
||||
* @param mixed $value
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkEqual($var, $value)
|
||||
{
|
||||
return $var == $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Must greater than a value.
|
||||
*
|
||||
* @param mixed $var
|
||||
* @param mixed $value
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkGT($var, $value)
|
||||
{
|
||||
return $var > $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Must less than a value.
|
||||
*
|
||||
* @param mixed $var
|
||||
* @param mixed $value
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkLT($var, $value)
|
||||
{
|
||||
return $var < $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Must greater than a value or equal a value.
|
||||
*
|
||||
* @param mixed $var
|
||||
* @param mixed $value
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkGE($var, $value)
|
||||
{
|
||||
return $var >= $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Must less than a value or equal a value.
|
||||
*
|
||||
* @param mixed $var
|
||||
* @param mixed $value
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkLE($var, $value)
|
||||
{
|
||||
return $var <= $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Must in value list.
|
||||
*
|
||||
* @param mixed $var
|
||||
* @param mixed $value
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkIn($var, $value)
|
||||
{
|
||||
if(!is_array($value)) $value = explode(',', $value);
|
||||
return in_array($var, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check file name.
|
||||
*
|
||||
* @param string $var
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkFileName($var)
|
||||
{
|
||||
return !preg_match('/>+|:+|<+/', $var);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call a function to check it.
|
||||
*
|
||||
* @param mixed $var
|
||||
* @param string $func
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function call($var, $func)
|
||||
{
|
||||
return filter_var($var, FILTER_CALLBACK, array('options' => $func));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* fixer类,处理数据。
|
||||
* fixer class, to fix data types.
|
||||
*
|
||||
* @package framework
|
||||
*/
|
||||
class fixer
|
||||
class fixer extends baseFixer
|
||||
{
|
||||
/**
|
||||
* The data to be fixed.
|
||||
*
|
||||
* @var ojbect
|
||||
* @access private
|
||||
*/
|
||||
private $data;
|
||||
|
||||
private $stripedFields = array();
|
||||
/**
|
||||
* The construction function, according the scope, convert it to object.
|
||||
*
|
||||
* @param string $scope the scope of the var, should be post|get|server|session|cookie|env
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
private function __construct($scope)
|
||||
{
|
||||
switch($scope)
|
||||
{
|
||||
case 'post':
|
||||
$this->data = (object)$_POST;
|
||||
break;
|
||||
case 'server':
|
||||
$this->data = (object)$_SERVER;
|
||||
break;
|
||||
case 'get':
|
||||
$this->data = (object)$_GET;
|
||||
break;
|
||||
case 'session':
|
||||
$this->data = (object)$_SESSION;
|
||||
break;
|
||||
case 'cookie':
|
||||
$this->data = (object)$_COOKIE;
|
||||
break;
|
||||
case 'env':
|
||||
$this->data = (object)$_ENV;
|
||||
break;
|
||||
case 'file':
|
||||
$this->data = (object)$_FILES;
|
||||
break;
|
||||
|
||||
default:
|
||||
die('scope not supported, should be post|get|server|session|cookie|env');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The factory function.
|
||||
*
|
||||
* @param string $scope
|
||||
* @access public
|
||||
* @return object fixer object.
|
||||
*/
|
||||
public static function input($scope)
|
||||
{
|
||||
return new fixer($scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* Email fix.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @access public
|
||||
* @return object fixer object.
|
||||
*/
|
||||
public function cleanEmail($fieldName)
|
||||
{
|
||||
$fields = $this->processFields($fieldName);
|
||||
foreach($fields as $fieldName) $this->data->$fieldName = filter_var($this->data->$fieldName, FILTER_SANITIZE_EMAIL);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* urlenocde.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @access public
|
||||
* @return object fixer object.
|
||||
*/
|
||||
public function encodeURL($fieldName)
|
||||
{
|
||||
$fields = $this->processFields($fieldName);
|
||||
$args = func_get_args();
|
||||
foreach($fields as $fieldName)
|
||||
{
|
||||
$this->data->$fieldName = isset($args[1]) ? filter_var($this->data->$fieldName, FILTER_SANITIZE_ENCODED, $args[1]) : filter_var($this->data->$fieldName, FILTER_SANITIZE_ENCODED);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean the url.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @access public
|
||||
* @return object fixer object.
|
||||
*/
|
||||
public function cleanURL($fieldName)
|
||||
{
|
||||
$fields = $this->processFields($fieldName);
|
||||
foreach($fields as $fieldName) $this->data->$fieldName = filter_var($this->data->$fieldName, FILTER_SANITIZE_URL);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Float fixer.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @access public
|
||||
* @return object fixer object.
|
||||
*/
|
||||
public function cleanFloat($fieldName)
|
||||
{
|
||||
$fields = $this->processFields($fieldName);
|
||||
foreach($fields as $fieldName) $this->data->$fieldName = filter_var($this->data->$fieldName, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION|FILTER_FLAG_ALLOW_THOUSAND);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Int fixer.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @access public
|
||||
* @return object fixer object.
|
||||
*/
|
||||
public function cleanINT($fieldName = '')
|
||||
{
|
||||
$fields = $this->processFields($fieldName);
|
||||
foreach($fields as $fieldName) $this->data->$fieldName = filter_var($this->data->$fieldName, FILTER_SANITIZE_NUMBER_INT);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Special chars
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @access public
|
||||
* @return object fixer object
|
||||
*/
|
||||
public function specialChars($fieldName)
|
||||
{
|
||||
$fields = $this->processFields($fieldName);
|
||||
foreach($fields as $fieldName)
|
||||
{
|
||||
if(empty($this->stripedFields) or !in_array($fieldName, $this->stripedFields)) $this->data->$fieldName = $this->specialArray($this->data->$fieldName);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Special array
|
||||
*
|
||||
* @param mix $data
|
||||
* @access public
|
||||
* @return mix
|
||||
*/
|
||||
public function specialArray($data)
|
||||
{
|
||||
if(!is_array($data)) return htmlspecialchars($data, ENT_QUOTES);
|
||||
|
||||
foreach($data as &$value) $value = $this->specialArray($value);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Strip tags
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @param string $allowedTags
|
||||
* @access public
|
||||
* @return object fixer object
|
||||
*/
|
||||
public function stripTags($fieldName, $allowedTags)
|
||||
{
|
||||
global $app;
|
||||
$app->loadClass('purifier', true);
|
||||
$config = HTMLPurifier_Config::createDefault();
|
||||
$config->set('Filter.YouTube', 1);
|
||||
|
||||
/* Disable caching. */
|
||||
$config->set('Cache.DefinitionImpl', null);
|
||||
|
||||
$purifier = new HTMLPurifier($config);
|
||||
$def = $config->getHTMLDefinition(true);
|
||||
$def->addAttribute('a', 'target', 'Enum#_blank,_self,_target,_top');
|
||||
|
||||
$fields = $this->processFields($fieldName);
|
||||
foreach($fields as $fieldName)
|
||||
{
|
||||
if(version_compare(phpversion(), '5.4', '<') and get_magic_quotes_gpc()) $this->data->$fieldName = stripslashes($this->data->$fieldName);
|
||||
|
||||
if(!in_array($fieldName, $this->stripedFields)) $this->data->$fieldName = $purifier->purify($this->data->$fieldName);
|
||||
$this->stripedFields[] = $fieldName;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip special chars.
|
||||
*
|
||||
* @param string $filename
|
||||
* @access public
|
||||
* @return object fixer object
|
||||
*/
|
||||
public function skipSpecial($fieldName)
|
||||
{
|
||||
$fields = $this->processFields($fieldName);
|
||||
foreach($fields as $fieldName) $this->stripedFields[] = $fieldName;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quote
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @access public
|
||||
* @return object fixer object
|
||||
*/
|
||||
public function quote($fieldName)
|
||||
{
|
||||
$fields = $this->processFields($fieldName);
|
||||
foreach($fields as $fieldName) $this->data->$fieldName = filter_var($this->data->$fieldName, FILTER_SANITIZE_MAGIC_QUOTES);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default value of some fileds.
|
||||
*
|
||||
* @param string $fields
|
||||
* @param mixed $value
|
||||
* @access public
|
||||
* @return object fixer object
|
||||
*/
|
||||
public function setDefault($fields, $value)
|
||||
{
|
||||
$fields = strpos($fields, ',') ? explode(',', str_replace(' ', '', $fields)) : array($fields);
|
||||
foreach($fields as $fieldName)if(!isset($this->data->$fieldName) or empty($this->data->$fieldName)) $this->data->$fieldName = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set value of a filed on the condition is true.
|
||||
*
|
||||
* @param bool $condition
|
||||
* @param string $fieldName
|
||||
* @param string $value
|
||||
* @access public
|
||||
* @return object fixer object
|
||||
*/
|
||||
public function setIF($condition, $fieldName, $value)
|
||||
{
|
||||
if($condition) $this->data->$fieldName = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of a filed in force.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @param mixed $value
|
||||
* @access public
|
||||
* @return object fixer object
|
||||
*/
|
||||
public function setForce($fieldName, $value)
|
||||
{
|
||||
$this->data->$fieldName = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a field.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @access public
|
||||
* @return object fixer object
|
||||
*/
|
||||
public function remove($fieldName)
|
||||
{
|
||||
$fields = $this->processFields($fieldName);
|
||||
foreach($fields as $fieldName) unset($this->data->$fieldName);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a filed on the condition is true.
|
||||
*
|
||||
* @param bool $condition
|
||||
* @param string $fields
|
||||
* @access public
|
||||
* @return object fixer object
|
||||
*/
|
||||
public function removeIF($condition, $fields)
|
||||
{
|
||||
$fields = $this->processFields($fields);
|
||||
if($condition) foreach($fields as $fieldName) unset($this->data->$fieldName);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an item to the data.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @param mixed $value
|
||||
* @access public
|
||||
* @return object fixer object
|
||||
*/
|
||||
public function add($fieldName, $value)
|
||||
{
|
||||
$this->data->$fieldName = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an item to the data on the condition if true.
|
||||
*
|
||||
* @param bool $condition
|
||||
* @param string $fieldName
|
||||
* @param mixed $value
|
||||
* @access public
|
||||
* @return object fixer object
|
||||
*/
|
||||
public function addIF($condition, $fieldName, $value)
|
||||
{
|
||||
if($condition) $this->data->$fieldName = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Join the field.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @param string $value
|
||||
* @access public
|
||||
* @return object fixer object
|
||||
*/
|
||||
public function join($fieldName, $value)
|
||||
{
|
||||
if(!isset($this->data->$fieldName) or !is_array($this->data->$fieldName)) return $this;
|
||||
$this->data->$fieldName = join($value, $this->data->$fieldName);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call a function to fix it.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @param string $func
|
||||
* @access public
|
||||
* @return object fixer object
|
||||
*/
|
||||
public function callFunc($fieldName, $func)
|
||||
{
|
||||
$fields = $this->processFields($fieldName);
|
||||
foreach($fields as $fieldName) $this->data->$fieldName = filter_var($this->data->$fieldName, FILTER_CALLBACK, array('options' => $func));
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data after fixing.
|
||||
*
|
||||
* If only one field, return it's value directly.
|
||||
* More fields, remove other fields not in the list and return $data.
|
||||
*
|
||||
* @param string $fields the fields list.
|
||||
* @access public
|
||||
* @return mix
|
||||
*/
|
||||
public function get($fields = '')
|
||||
{
|
||||
$fields = str_replace(' ', '', trim($fields));
|
||||
foreach($this->data as $field => $value) $this->specialChars($field);
|
||||
|
||||
if(empty($fields)) return $this->data;
|
||||
if(strpos($fields, ',') === false) return $this->data->$fields;
|
||||
|
||||
$fields = array_flip(explode(',', $fields));
|
||||
foreach($this->data as $field => $value)
|
||||
{
|
||||
if(!isset($fields[$field])) unset($this->data->$field);
|
||||
if(!in_array($field, $this->stripedFields)) $this->data->$field = $this->specialChars($this->data->field);
|
||||
}
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process fields, if contains ',', split it to array. If not in $data, remove it.
|
||||
*
|
||||
* @param string $fields
|
||||
* @access private
|
||||
* @return array
|
||||
*/
|
||||
private function processFields($fields)
|
||||
{
|
||||
$fields = strpos($fields, ',') ? explode(',', str_replace(' ', '', $fields)) : array($fields);
|
||||
foreach($fields as $key => $fieldName) if(!isset($this->data->$fieldName)) unset($fields[$key]);
|
||||
return $fields;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
492
lib/pager/pager.class.php
Executable file → Normal file
492
lib/pager/pager.class.php
Executable file → Normal file
@@ -1,5 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* ZenTaoPHP的分页类。
|
||||
* The pager class file of ZenTaoPHP framework.
|
||||
*
|
||||
* The author disclaims copyright to this source code. In place of
|
||||
@@ -9,497 +10,14 @@
|
||||
* May you find forgiveness for yourself and forgive others.
|
||||
* May you share freely, never taking more than you give.
|
||||
*/
|
||||
|
||||
helper::import(dirname(dirname(__FILE__)) . '/base/pager/pager.class.php');
|
||||
/**
|
||||
* pager类.
|
||||
* Pager class.
|
||||
*
|
||||
* @package framework
|
||||
*/
|
||||
class pager
|
||||
class pager extends basePager
|
||||
{
|
||||
/**
|
||||
* The default counts of per page.
|
||||
*
|
||||
* @public int
|
||||
*/
|
||||
const DEFAULT_REC_PRE_PAGE = 20;
|
||||
|
||||
/**
|
||||
* The total counts.
|
||||
*
|
||||
* @var int
|
||||
* @access public
|
||||
*/
|
||||
public $recTotal;
|
||||
|
||||
/**
|
||||
* Record count per page.
|
||||
*
|
||||
* @var int
|
||||
* @access public
|
||||
*/
|
||||
public $recPerPage;
|
||||
|
||||
/**
|
||||
* The cookie name of recPerPage.
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
public $pageCookie;
|
||||
|
||||
/**
|
||||
* Page count.
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
public $pageTotal;
|
||||
|
||||
/**
|
||||
* Current page id.
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
public $pageID;
|
||||
|
||||
/**
|
||||
* The global $app.
|
||||
*
|
||||
* @var object
|
||||
* @access private
|
||||
*/
|
||||
private $app;
|
||||
|
||||
/**
|
||||
* The global $lang.
|
||||
*
|
||||
* @var object
|
||||
* @access private
|
||||
*/
|
||||
private $lang;
|
||||
|
||||
/**
|
||||
* Current module name.
|
||||
*
|
||||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
private $moduleName;
|
||||
|
||||
/**
|
||||
* Current method.
|
||||
*
|
||||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
private $methodName;
|
||||
|
||||
/**
|
||||
* The params.
|
||||
*
|
||||
* @private array
|
||||
*/
|
||||
private $params;
|
||||
|
||||
/**
|
||||
* The construct function.
|
||||
*
|
||||
* @param int $recTotal
|
||||
* @param int $recPerPage
|
||||
* @param int $pageID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($recTotal = 0, $recPerPage = 20, $pageID = 1)
|
||||
{
|
||||
$this->setApp();
|
||||
$this->setLang();
|
||||
$this->setModuleName();
|
||||
$this->setMethodName();
|
||||
|
||||
$this->setRecTotal($recTotal);
|
||||
$this->setRecPerPage($recPerPage);
|
||||
$this->setPageTotal();
|
||||
$this->setPageID($pageID);
|
||||
}
|
||||
|
||||
/**
|
||||
* The factory function.
|
||||
*
|
||||
* @param int $recTotal
|
||||
* @param int $recPerPage
|
||||
* @param int $pageID
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public static function init($recTotal = 0, $recPerPage = 20, $pageID = 1)
|
||||
{
|
||||
return new pager($recTotal, $recPerPage, $pageID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the recTotal property.
|
||||
*
|
||||
* @param int $recTotal
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setRecTotal($recTotal = 0)
|
||||
{
|
||||
$this->recTotal = (int)$recTotal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the recTotal property.
|
||||
*
|
||||
* @param int $recPerPage
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setRecPerPage($recPerPage)
|
||||
{
|
||||
/* Set the cookie name. */
|
||||
$this->pageCookie = 'pager' . ucfirst($this->app->getModuleName()) . ucfirst($this->app->getMethodName());
|
||||
|
||||
if(isset($_COOKIE[$this->pageCookie])) $recPerPage = $_COOKIE[$this->pageCookie];
|
||||
$this->recPerPage = ($recPerPage > 0) ? $recPerPage : PAGER::DEFAULT_REC_PRE_PAGE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the pageTotal property.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setPageTotal()
|
||||
{
|
||||
$this->pageTotal = ceil($this->recTotal / $this->recPerPage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the page id.
|
||||
*
|
||||
* @param int $pageID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setPageID($pageID)
|
||||
{
|
||||
if($pageID > 0 and $pageID <= $this->pageTotal)
|
||||
{
|
||||
$this->pageID = $pageID;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->pageID = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the $app property;
|
||||
*
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
private function setApp()
|
||||
{
|
||||
global $app;
|
||||
$this->app = $app;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the $lang property.
|
||||
*
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
private function setLang()
|
||||
{
|
||||
global $lang;
|
||||
$this->lang = $lang;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the $moduleName property.
|
||||
*
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
private function setModuleName()
|
||||
{
|
||||
$this->moduleName = $this->app->getModuleName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the $methodName property.
|
||||
*
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
private function setMethodName()
|
||||
{
|
||||
$this->methodName = $this->app->getMethodName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get recTotal, recPerpage, pageID from the request params, and add them to params.
|
||||
*
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
private function setParams()
|
||||
{
|
||||
$this->params = $this->app->getParams();
|
||||
foreach($this->params as $key => $value)
|
||||
{
|
||||
if(strtolower($key) == 'rectotal') $this->params[$key] = $this->recTotal;
|
||||
if(strtolower($key) == 'recperpage') $this->params[$key] = $this->recPerPage;
|
||||
if(strtolower($key) == 'pageid') $this->params[$key] = $this->pageID;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the limit string.
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function limit()
|
||||
{
|
||||
$limit = '';
|
||||
if($this->pageTotal > 1) $limit = ' limit ' . ($this->pageID - 1) * $this->recPerPage . ", $this->recPerPage";
|
||||
return $limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the pager's html.
|
||||
*
|
||||
* @param string $align
|
||||
* @param string $type
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function show($align = 'right', $type = 'full')
|
||||
{
|
||||
echo $this->get($align, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the pager html string.
|
||||
*
|
||||
* @param string $align
|
||||
* @param string $type the pager type, full|short|shortest
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function get($align = 'right', $type = 'full')
|
||||
{
|
||||
/* If the RecTotal is zero, return with no record. */
|
||||
if($this->recTotal == 0) { return $type == 'mobile' ? '' : "<div style='float:$align; clear:none;' class='pager'>{$this->lang->pager->noRecord}</div>"; }
|
||||
|
||||
/* Set the params. */
|
||||
$this->setParams();
|
||||
|
||||
/* Create the prePage and nextpage, all types have them. */
|
||||
$pager = $this->createPrePage($type);
|
||||
$pager .= $this->createNextPage($type);
|
||||
|
||||
/* The short and full type. */
|
||||
if($type !== 'shortest' and $type !== 'mobile')
|
||||
{
|
||||
$pager = $this->createFirstPage() . $pager;
|
||||
$pager .= $this->createLastPage();
|
||||
}
|
||||
|
||||
if($type == 'mobile')
|
||||
{
|
||||
$position = $this->pageTotal == 1 ? '' : $this->pageID . '/' . $this->pageTotal;
|
||||
$pager = $pager . ' ' . $position;
|
||||
}
|
||||
else if($type != 'full')
|
||||
{
|
||||
$pager = $this->pageID . '/' . $this->pageTotal . ' ' . $pager;
|
||||
}
|
||||
|
||||
/* Only the full type . */
|
||||
if($type == 'full')
|
||||
{
|
||||
$pager = $this->createDigest() . $pager;
|
||||
$pager .= $this->createGoTo();
|
||||
$pager .= $this->createRecPerPageJS();
|
||||
}
|
||||
|
||||
return "<div style='float:$align; clear:none;' class='pager'>$pager</div>";
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the digest code.
|
||||
*
|
||||
* @access private
|
||||
* @return string
|
||||
*/
|
||||
private function createDigest()
|
||||
{
|
||||
return sprintf($this->lang->pager->digest, $this->recTotal, $this->createRecPerPageList(), $this->pageID, $this->pageTotal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the first page.
|
||||
*
|
||||
* @access private
|
||||
* @return string
|
||||
*/
|
||||
private function createFirstPage()
|
||||
{
|
||||
if($this->pageID == 1) return $this->lang->pager->first . ' ';
|
||||
$this->params['pageID'] = 1;
|
||||
return html::a(helper::createLink($this->moduleName, $this->methodName, $this->params), $this->lang->pager->first);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the pre page html.
|
||||
*
|
||||
* @access private
|
||||
* @return string
|
||||
*/
|
||||
private function createPrePage($type = 'full')
|
||||
{
|
||||
if($type == 'mobile')
|
||||
{
|
||||
if($this->pageID == 1) return '';
|
||||
$this->params['pageID'] = $this->pageID - 1;
|
||||
return html::a(helper::createLink($this->moduleName, $this->methodName, $this->params), $this->lang->pager->pre, '', 'data-role="button" data-icon="arrow-l" data-iconpos="left" data-inline="true"');
|
||||
}
|
||||
else
|
||||
{
|
||||
if($this->pageID == 1) return $this->lang->pager->pre . ' ';
|
||||
$this->params['pageID'] = $this->pageID - 1;
|
||||
return html::a(helper::createLink($this->moduleName, $this->methodName, $this->params), $this->lang->pager->pre);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the next page html.
|
||||
*
|
||||
* @access private
|
||||
* @return string
|
||||
*/
|
||||
private function createNextPage($type = 'full')
|
||||
{
|
||||
if($type == 'mobile')
|
||||
{
|
||||
if($this->pageID == $this->pageTotal) return '';
|
||||
$this->params['pageID'] = $this->pageID + 1;
|
||||
return html::a(helper::createLink($this->moduleName, $this->methodName, $this->params), $this->lang->pager->next, '', 'data-role="button" data-icon="arrow-r" data-iconpos="right" data-inline="true"');
|
||||
}
|
||||
else
|
||||
{
|
||||
if($this->pageID == $this->pageTotal) return $this->lang->pager->next . ' ';
|
||||
$this->params['pageID'] = $this->pageID + 1;
|
||||
return html::a(helper::createLink($this->moduleName, $this->methodName, $this->params), $this->lang->pager->next);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the last page
|
||||
*
|
||||
* @access private
|
||||
* @return string
|
||||
*/
|
||||
private function createLastPage()
|
||||
{
|
||||
if($this->pageID == $this->pageTotal) return $this->lang->pager->last . ' ';
|
||||
$this->params['pageID'] = $this->pageTotal;
|
||||
return html::a(helper::createLink($this->moduleName, $this->methodName, $this->params), $this->lang->pager->last);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the select object of record perpage.
|
||||
*
|
||||
* @access private
|
||||
* @return string
|
||||
*/
|
||||
private function createRecPerPageJS()
|
||||
{
|
||||
/* Replace the recTotal, recPerPage, pageID to special string, and then replace them with values by JS. */
|
||||
$params = $this->params;
|
||||
foreach($params as $key => $value)
|
||||
{
|
||||
if(strtolower($key) == 'rectotal') $params[$key] = '_recTotal_';
|
||||
if(strtolower($key) == 'recperpage') $params[$key] = '_recPerPage_';
|
||||
if(strtolower($key) == 'pageid') $params[$key] = '_pageID_';
|
||||
}
|
||||
$vars = '';
|
||||
foreach($params as $key => $value) $vars .= "$key=$value&";
|
||||
$vars = rtrim($vars, '&');
|
||||
|
||||
$js = <<<EOT
|
||||
<script>
|
||||
vars = '$vars';
|
||||
pageCookie = '$this->pageCookie';
|
||||
function submitPage(mode, perPage)
|
||||
{
|
||||
pageTotal = parseInt(document.getElementById('_pageTotal').value);
|
||||
pageID = document.getElementById('_pageID').value;
|
||||
recPerPage = document.getElementById('_recPerPage').getAttribute('data-value');
|
||||
recTotal = document.getElementById('_recTotal').value;
|
||||
if(mode == 'changePageID')
|
||||
{
|
||||
if(pageID > pageTotal) pageID = pageTotal;
|
||||
if(pageID < 1) pageID = 1;
|
||||
}
|
||||
else if(mode == 'changeRecPerPage')
|
||||
{
|
||||
recPerPage = perPage;
|
||||
pageID = 1;
|
||||
}
|
||||
$.cookie(pageCookie, recPerPage, {expires:config.cookieLife, path:config.webRoot});
|
||||
|
||||
vars = vars.replace('_recTotal_', recTotal)
|
||||
vars = vars.replace('_recPerPage_', recPerPage)
|
||||
vars = vars.replace('_pageID_', pageID);
|
||||
location.href=createLink('$this->moduleName', '$this->methodName', vars);
|
||||
}
|
||||
</script>
|
||||
EOT;
|
||||
return $js;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the select list of RecPerPage.
|
||||
*
|
||||
* @access private
|
||||
* @return string
|
||||
*/
|
||||
private function createRecPerPageList()
|
||||
{
|
||||
for($i = 5; $i <= 50; $i += 5) $range[$i] = $i;
|
||||
$range[100] = 100;
|
||||
$range[200] = 200;
|
||||
$range[500] = 500;
|
||||
$range[1000] = 1000;
|
||||
$html = "<div class='dropdown dropup'><a href='javascript:;' data-toggle='dropdown' id='_recPerPage' data-value='{$this->recPerPage}'>" . (sprintf($this->lang->pager->recPerPage, $this->recPerPage)) . "<span class='caret'></span></a><ul class='dropdown-menu'>";
|
||||
foreach ($range as $key => $value)
|
||||
{
|
||||
$html .= '<li' . ($this->recPerPage == $value ? " class='active'" : '') .'>' . "<a href='javascript:submitPage(\"changeRecPerPage\", $value)'>{$value}</a>" . '</li>';
|
||||
}
|
||||
$html .= '</ul></div>';
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the goto part html.
|
||||
*
|
||||
* @access private
|
||||
* @return string
|
||||
*/
|
||||
private function createGoTo()
|
||||
{
|
||||
$goToHtml = "<input type='hidden' id='_recTotal' value='$this->recTotal' />\n";
|
||||
$goToHtml .= "<input type='hidden' id='_pageTotal' value='$this->pageTotal' />\n";
|
||||
$goToHtml .= "<input type='text' id='_pageID' value='$this->pageID' style='text-align:center;width:30px;' class='form-control' /> \n";
|
||||
$goToHtml .= "<input type='button' id='goto' value='{$this->lang->pager->locate}' onclick='submitPage(\"changePageID\");' class='btn'/>";
|
||||
return $goToHtml;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ class zdb
|
||||
*/
|
||||
public function dump($fileName, $tables = array())
|
||||
{
|
||||
global $config;
|
||||
/* Init the return. */
|
||||
$return = new stdclass();
|
||||
$return->result = true;
|
||||
@@ -48,11 +49,12 @@ class zdb
|
||||
|
||||
/* Get all tables in database. */
|
||||
$allTables = array();
|
||||
$stmt = $this->dbh->query('show tables');
|
||||
while($table = $stmt->fetch(PDO::FETCH_ASSOC))
|
||||
$stmt = $this->dbh->query("show full tables");
|
||||
while($table = $stmt->fetch(PDO::FETCH_ASSOC))
|
||||
{
|
||||
$table = current($table);
|
||||
$allTables[$table] = $table;
|
||||
$tableName = $table["Tables_in_{$config->db->name}"];
|
||||
$tableType = strtolower($table['Table_type']);
|
||||
$allTables[$tableName] = $tableType == 'base table' ? 'table' : $tableType;
|
||||
}
|
||||
|
||||
/* Dump all tables when tables is empty. */
|
||||
@@ -75,15 +77,16 @@ class zdb
|
||||
/* Open this file. */
|
||||
$fp = fopen($fileName, 'w');
|
||||
fwrite($fp, "SET NAMES utf8;\n");
|
||||
foreach($tables as $table)
|
||||
foreach($tables as $table => $tableType)
|
||||
{
|
||||
/* Check table exists. */
|
||||
if(!isset($allTables[$table])) continue;
|
||||
|
||||
/* Create sql code. */
|
||||
$backupSql = "DROP TABLE IF EXISTS `$table`;\n";
|
||||
$backupSql .= $this->getSchemaSQL($table);
|
||||
$backupSql = "DROP " . strtoupper($tableType) . " IF EXISTS `$table`;\n";
|
||||
$backupSql .= $this->getSchemaSQL($table, $tableType);
|
||||
fwrite($fp, $backupSql);
|
||||
if($tableType != 'table') continue;
|
||||
|
||||
$rows = $this->dbh->query("select * from `$table`");
|
||||
while($row = $rows->fetch(PDO::FETCH_ASSOC))
|
||||
@@ -186,9 +189,10 @@ class zdb
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function getSchemaSQL($table)
|
||||
public function getSchemaSQL($table, $type = 'table')
|
||||
{
|
||||
$createSql = $this->dbh->query("show create table `$table`")->fetch(PDO::FETCH_ASSOC);
|
||||
return $createSql['Create Table'] . ";\n";
|
||||
$sql = "SHOW CREATE $type `$table`";
|
||||
$createSql = $this->dbh->query($sql)->fetch(PDO::FETCH_ASSOC);
|
||||
return $createSql['Create ' . ucfirst($type)] . ";\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ $lang->action->objectID = 'ID';
|
||||
$lang->action->objectName = 'Name';
|
||||
$lang->action->actor = 'Actor';
|
||||
$lang->action->action = 'Action';
|
||||
$lang->action->actionID = 'ActionID';
|
||||
$lang->action->date = 'Date';
|
||||
|
||||
$lang->action->trash = 'Trash';
|
||||
@@ -99,6 +98,10 @@ $lang->action->desc->diff1 = 'changed <strong><i>%s</i></strong>, old i
|
||||
$lang->action->desc->diff2 = 'changed <strong><i>%s</i></strong>, the diff is:' . "\n" . "<blockquote>%s</blockquote>" . "\n<div class='hidden'>%s</div>";
|
||||
$lang->action->desc->diff3 = "changed file's name %s to %s.";
|
||||
|
||||
/* The desc of actions for link and unlink related case. */
|
||||
$lang->action->desc->linkrelatedcase = '$date, linked related case <strong>$extra</strong> by <strong>$actor</strong>.' . "\n";
|
||||
$lang->action->desc->unlinkrelatedcase = '$date, unlinked related case <strong>$extra</strong> by <strong>$actor</strong>.' . "\n";
|
||||
|
||||
/* The action labels. */
|
||||
$lang->action->label = new stdclass();
|
||||
$lang->action->label->created = 'created';
|
||||
@@ -131,6 +134,14 @@ $lang->action->label->changestatus = 'change status';
|
||||
$lang->action->label->marked = 'edited';
|
||||
$lang->action->label->linked2project = "link to {$lang->projectCommon}";
|
||||
$lang->action->label->unlinkedfromproject = "unlik from {$lang->projectCommon}";
|
||||
$lang->action->label->linkrelatedbug = "linked related Bug";
|
||||
$lang->action->label->unlinkrelatedbug = "unlinked related Bug";
|
||||
$lang->action->label->linkrelatedcase = "linked related case";
|
||||
$lang->action->label->unlinkrelatedcase = "unlinked related case";
|
||||
$lang->action->label->linkrelatedstory = "linked related story";
|
||||
$lang->action->label->unlinkrelatedstory = "unlinked related story";
|
||||
$lang->action->label->subdividestory = "subdivided story";
|
||||
$lang->action->label->unlinkchildstory = "unlinked child story";
|
||||
$lang->action->label->started = 'started';
|
||||
$lang->action->label->restarted = 'continued';
|
||||
$lang->action->label->recordestimate = 'Hours';
|
||||
|
||||
@@ -17,7 +17,6 @@ $lang->action->objectID = '对象ID';
|
||||
$lang->action->objectName = '对象名称';
|
||||
$lang->action->actor = '操作者';
|
||||
$lang->action->action = '动作';
|
||||
$lang->action->actionID = '记录ID';
|
||||
$lang->action->date = '日期';
|
||||
|
||||
$lang->action->trash = '回收站';
|
||||
@@ -99,6 +98,10 @@ $lang->action->desc->diff1 = '修改了 <strong><i>%s</i></strong>,
|
||||
$lang->action->desc->diff2 = '修改了 <strong><i>%s</i></strong>,区别为:' . "\n" . "<blockquote>%s</blockquote>" . "\n<div class='hidden'>%s</div>";
|
||||
$lang->action->desc->diff3 = '将文件名 %s 改为 %s 。' . "\n";
|
||||
|
||||
/* 关联用例和移除用例时的历史操作记录。*/
|
||||
$lang->action->desc->linkrelatedcase = '$date, 由 <strong>$actor</strong> 关联相关用例 <strong>$extra</strong>。' . "\n";
|
||||
$lang->action->desc->unlinkrelatedcase = '$date, 由 <strong>$actor</strong> 移除相关用例 <strong>$extra</strong>。' . "\n";
|
||||
|
||||
/* 用来显示动态信息。*/
|
||||
$lang->action->label = new stdclass();
|
||||
$lang->action->label->created = '创建';
|
||||
@@ -131,6 +134,14 @@ $lang->action->label->changestatus = '修改状态';
|
||||
$lang->action->label->marked = '编辑了';
|
||||
$lang->action->label->linked2project = "关联{$lang->projectCommon}";
|
||||
$lang->action->label->unlinkedfromproject = "移除{$lang->projectCommon}";
|
||||
$lang->action->label->linkrelatedbug = "关联了相关Bug";
|
||||
$lang->action->label->unlinkrelatedbug = "移除了相关Bug";
|
||||
$lang->action->label->linkrelatedcase = "关联了相关用例";
|
||||
$lang->action->label->unlinkrelatedcase = "移除了相关用例";
|
||||
$lang->action->label->linkrelatedstory = "关联了相关需求";
|
||||
$lang->action->label->unlinkrelatedstory = "移除了相关需求";
|
||||
$lang->action->label->subdividestory = "细分了需求";
|
||||
$lang->action->label->unlinkchildstory = "移除了细分需求";
|
||||
$lang->action->label->started = '开始了';
|
||||
$lang->action->label->restarted = '继续了';
|
||||
$lang->action->label->recordestimate = '记录了工时';
|
||||
|
||||
@@ -17,7 +17,6 @@ $lang->action->objectID = '對象ID';
|
||||
$lang->action->objectName = '對象名稱';
|
||||
$lang->action->actor = '操作者';
|
||||
$lang->action->action = '動作';
|
||||
$lang->action->actionID = '記錄ID';
|
||||
$lang->action->date = '日期';
|
||||
|
||||
$lang->action->trash = '資源回收筒';
|
||||
@@ -99,6 +98,10 @@ $lang->action->desc->diff1 = '修改了 <strong><i>%s</i></strong>,
|
||||
$lang->action->desc->diff2 = '修改了 <strong><i>%s</i></strong>,區別為:' . "\n" . "<blockquote>%s</blockquote>" . "\n<div class='hidden'>%s</div>";
|
||||
$lang->action->desc->diff3 = '將檔案名 %s 改為 %s 。' . "\n";
|
||||
|
||||
/* 關聯用例和移除用例時的歷史操作記錄。*/
|
||||
$lang->action->desc->linkrelatedcase = '$date, 由 <strong>$actor</strong> 關聯相關用例 <strong>$extra</strong>。' . "\n";
|
||||
$lang->action->desc->unlinkrelatedcase = '$date, 由 <strong>$actor</strong> 移除相關用例 <strong>$extra</strong>。' . "\n";
|
||||
|
||||
/* 用來顯示動態信息。*/
|
||||
$lang->action->label = new stdclass();
|
||||
$lang->action->label->created = '創建';
|
||||
@@ -131,6 +134,14 @@ $lang->action->label->changestatus = '修改狀態';
|
||||
$lang->action->label->marked = '編輯了';
|
||||
$lang->action->label->linked2project = "關聯{$lang->projectCommon}";
|
||||
$lang->action->label->unlinkedfromproject = "移除{$lang->projectCommon}";
|
||||
$lang->action->label->linkrelatedbug = "關聯了相關Bug";
|
||||
$lang->action->label->unlinkrelatedbug = "移除了相關Bug";
|
||||
$lang->action->label->linkrelatedcase = "關聯了相關用例";
|
||||
$lang->action->label->unlinkrelatedcase = "移除了相關用例";
|
||||
$lang->action->label->linkrelatedstory = "關聯了相關需求";
|
||||
$lang->action->label->unlinkrelatedstory = "移除了相關需求";
|
||||
$lang->action->label->subdividestory = "細分了需求";
|
||||
$lang->action->label->unlinkchildstory = "移除了細分需求";
|
||||
$lang->action->label->started = '開始了';
|
||||
$lang->action->label->restarted = '繼續了';
|
||||
$lang->action->label->recordestimate = '記錄了工時';
|
||||
|
||||
@@ -241,8 +241,8 @@ class actionModel extends model
|
||||
}
|
||||
elseif($actionName == 'unlinkedfromproject')
|
||||
{
|
||||
$name = $this->dao->select('name')->from(TABLE_PRODUCT)->where('id')->eq($action->extra)->fetch('name');
|
||||
if($name) $action->extra = html::a(helper::createLink('product', 'browse', "productID=$action->extra"), "#$action->extra " . $name);
|
||||
$name = $this->dao->select('name')->from(TABLE_PROJECT)->where('id')->eq($action->extra)->fetch('name');
|
||||
if($name) $action->extra = html::a(helper::createLink('project', 'story', "projectID=$action->extra"), "#$action->extra " . $name);
|
||||
}
|
||||
elseif($actionName == 'unlinkedfromplan')
|
||||
{
|
||||
@@ -269,6 +269,21 @@ class actionModel extends model
|
||||
$name = $this->dao->select('name')->from(TABLE_TESTTASK)->where('id')->eq($action->objectID)->fetch('name');
|
||||
if($name) $action->extra = html::a(helper::createLink('testtask', 'view', "testtaskID=$action->objectID"), "#$action->objectID " . $name);
|
||||
}
|
||||
elseif(($actionName == 'closed' and $action->objectType == 'story') or ($actionName == 'resolved' and $action->objectType == 'bug'))
|
||||
{
|
||||
$action->appendLink = '';
|
||||
if(strpos($action->extra, ':')!== false)
|
||||
{
|
||||
list($extra, $id) = explode(':', $action->extra);
|
||||
$action->extra = $extra;
|
||||
if($id)
|
||||
{
|
||||
$table = $action->objectType == 'story' ? TABLE_STORY : TABLE_BUG;
|
||||
$name = $this->dao->select('title')->from($table)->where('id')->eq($id)->fetch('title');
|
||||
if($name) $action->appendLink = html::a(helper::createLink($action->objectType, 'view', "id=$id"), "#$id " . $name);
|
||||
}
|
||||
}
|
||||
}
|
||||
$action->history = isset($histories[$actionID]) ? $histories[$actionID] : array();
|
||||
$action->comment = $this->file->setImgSize($action->comment, $this->config->action->commonImgSize);
|
||||
$actions[$actionID] = $action;
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
<tr class='text-center'>
|
||||
<td><?php echo zget($lang->action->objectTypes, $action->objectType, '');?></td>
|
||||
<td><?php echo $action->objectID;?></td>
|
||||
<td class='text-left'><?php echo html::a($this->createLink($module, 'view', "id=$action->objectID"), $action->objectName);?></td>
|
||||
<td class='text-left'><?php echo html::a($this->createLink($module, 'view', $action->objectType == 'user' ? "account={$action->objectName}" : "id={$action->objectID}"), $action->objectName);?></td>
|
||||
<td><?php echo $users[$action->actor];?></td>
|
||||
<td><?php echo $action->date;?></td>
|
||||
<td>
|
||||
|
||||
@@ -18,7 +18,7 @@ class admin extends control
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$community = zget($this->config->global, 'community');
|
||||
$community = zget($this->config->global, 'community', '');
|
||||
if(!$community or $community == 'na')
|
||||
{
|
||||
$this->view->bind = false;
|
||||
@@ -116,10 +116,10 @@ class admin extends control
|
||||
*/
|
||||
public function checkDB()
|
||||
{
|
||||
$tables = $this->dbh->query('SHOW TABLES')->fetchAll();
|
||||
$tables = $this->dbh->query("show full tables where Table_Type != 'VIEW'")->fetchAll(PDO::FETCH_ASSOC);
|
||||
foreach($tables as $table)
|
||||
{
|
||||
$tableName = current((array)$table);
|
||||
$tableName = current($table);
|
||||
$result = $this->dbh->query("REPAIR TABLE $tableName")->fetch();
|
||||
echo "Repairing TABLE: " . $result->Table . "\t" . $result->Msg_type . ":" . $result->Msg_text . "\n";
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
.cards {margin: 5% auto;}
|
||||
.cards > .col-sm-6 {width: 25%; padding: 0 10px}
|
||||
.card {height: 250px; position: relative; padding-top: 50px; border-radius: 6px; margin: 0}
|
||||
.card {height: 250px; position: relative; padding-top: 50px; border-radius: 0; margin: 0}
|
||||
.card > .media {position: absolute; left: 0; top: 0; width: 100%; background: #f1f1f1; height:50px; bottom: 0; overflow: hidden; z-index: 90; transition: all 0.4s;}
|
||||
.card > .media > .icon {position: absolute; display: block; font-size: 56px; color: #ddd; z-index: 99; bottom: -10px; right: -6px; transition: all 0.4s;}
|
||||
.card > .media > h5 {position: absolute; display: block; color: #666; z-index: 100; font-size: 14px; left: 15px; top: 10px; transition: all 0.4s;}
|
||||
.card:hover > .media {background: #e5e5e5}
|
||||
.card:hover > .media {background: #F8FAFE}
|
||||
.card:hover > .media > .icon {color: #ccc}
|
||||
.card .card-content {padding: 20px}
|
||||
.card-content > ul {padding-left: 20px;}
|
||||
@@ -13,5 +13,6 @@
|
||||
.card a:hover {color: #000;}
|
||||
|
||||
#notice {margin: -20px -20px 0}
|
||||
#titlebar {margin-top: 0; border-top: 1px solid #e5e5e5}
|
||||
#titlebar {margin-top: -20px; border-top: none}
|
||||
#notice + #titlebar {margin-top: 0; border-top: 1px solid #e5e5e5}
|
||||
#proversion, #zentaotrain{color:#D2322D}
|
||||
|
||||
@@ -12,18 +12,11 @@
|
||||
$lang->admin->common = 'Admin';
|
||||
$lang->admin->index = 'Index';
|
||||
$lang->admin->checkDB = 'Repair data';
|
||||
$lang->admin->company = 'Company';
|
||||
$lang->admin->user = 'User';
|
||||
$lang->admin->group = 'Group';
|
||||
$lang->admin->sso = 'Integrate RanZhi';
|
||||
$lang->admin->safeIndex = 'Safe';
|
||||
$lang->admin->checkWeak = 'Check weak';
|
||||
$lang->admin->welcome = 'Welcome to ZenTaoPMS.';
|
||||
|
||||
$lang->admin->browseCompany = 'Browse Company';
|
||||
|
||||
$lang->admin->info = new stdclass();
|
||||
$lang->admin->info->caption = 'zentao information';
|
||||
$lang->admin->info->version = 'The current version of the system is %s,';
|
||||
$lang->admin->info->links = 'You can visit the following link:';
|
||||
$lang->admin->info->account = 'Your account in zentao community is %s. ';
|
||||
@@ -43,7 +36,6 @@ $lang->admin->register->success = "Register success";
|
||||
|
||||
$lang->admin->bind = new stdclass();
|
||||
$lang->admin->bind->caption = 'Bind with community account';
|
||||
$lang->admin->bind->action = 'bind';
|
||||
$lang->admin->bind->success = "Bind success";
|
||||
|
||||
$lang->admin->safe = new stdclass();
|
||||
|
||||
@@ -12,18 +12,11 @@
|
||||
$lang->admin->common = '后台管理';
|
||||
$lang->admin->index = '后台管理首页';
|
||||
$lang->admin->checkDB = '检查数据库';
|
||||
$lang->admin->company = '公司管理';
|
||||
$lang->admin->user = '用户管理';
|
||||
$lang->admin->group = '分组管理';
|
||||
$lang->admin->sso = '然之集成';
|
||||
$lang->admin->safeIndex = '安全';
|
||||
$lang->admin->checkWeak = '弱口令检查';
|
||||
$lang->admin->welcome = '欢迎使用禅道管理软件后台管理系统';
|
||||
|
||||
$lang->admin->browseCompany = '浏览公司';
|
||||
|
||||
$lang->admin->info = new stdclass();
|
||||
$lang->admin->info->caption = '禅道系统信息';
|
||||
$lang->admin->info->version = '当前系统的版本是%s,';
|
||||
$lang->admin->info->links = '您可以访问以下链接:';
|
||||
$lang->admin->info->account = "您的禅道社区账户为%s。";
|
||||
@@ -42,9 +35,8 @@ $lang->admin->register->bind = "如果您已经拥有社区账号,%s关
|
||||
$lang->admin->register->success = "登记账户成功";
|
||||
|
||||
$lang->admin->bind = new stdclass();
|
||||
$lang->admin->bind->caption = '关联社区账号';
|
||||
$lang->admin->bind->action = '关联';
|
||||
$lang->admin->bind->success = "关联账户成功";
|
||||
$lang->admin->bind->caption = '关联社区账号';
|
||||
$lang->admin->bind->success = "关联账户成功";
|
||||
|
||||
$lang->admin->safe = new stdclass();
|
||||
$lang->admin->safe->common = '安全';
|
||||
|
||||
@@ -12,18 +12,11 @@
|
||||
$lang->admin->common = '後台管理';
|
||||
$lang->admin->index = '後台管理首頁';
|
||||
$lang->admin->checkDB = '檢查資料庫';
|
||||
$lang->admin->company = '公司管理';
|
||||
$lang->admin->user = '用戶管理';
|
||||
$lang->admin->group = '分組管理';
|
||||
$lang->admin->sso = '然之整合';
|
||||
$lang->admin->safeIndex = '安全';
|
||||
$lang->admin->checkWeak = '弱口令檢查';
|
||||
$lang->admin->welcome = '歡迎使用禪道管理軟件後台管理系統';
|
||||
|
||||
$lang->admin->browseCompany = '瀏覽公司';
|
||||
|
||||
$lang->admin->info = new stdclass();
|
||||
$lang->admin->info->caption = '禪道系統信息';
|
||||
$lang->admin->info->version = '當前系統的版本是%s,';
|
||||
$lang->admin->info->links = '您可以訪問以下連結:';
|
||||
$lang->admin->info->account = "您的禪道社區賬戶為%s。";
|
||||
@@ -42,9 +35,8 @@ $lang->admin->register->bind = "如果您已經擁有社區賬號,%s關
|
||||
$lang->admin->register->success = "登記賬戶成功";
|
||||
|
||||
$lang->admin->bind = new stdclass();
|
||||
$lang->admin->bind->caption = '關聯社區賬號';
|
||||
$lang->admin->bind->action = '關聯';
|
||||
$lang->admin->bind->success = "關聯賬戶成功";
|
||||
$lang->admin->bind->caption = '關聯社區賬號';
|
||||
$lang->admin->bind->success = "關聯賬戶成功";
|
||||
|
||||
$lang->admin->safe = new stdclass();
|
||||
$lang->admin->safe->common = '安全';
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
<td><?php echo $user->mobile?></td>
|
||||
<td><?php echo $user->birthday?></td>
|
||||
<td><?php echo $lang->admin->safe->reasonList[$user->weakReason];?></td>
|
||||
<td><?php common::printIcon('user', 'edit', "userID=" . helper::safe64Encode($user->account), '', 'list');?></td>
|
||||
<td><?php common::printIcon('user', 'edit', "userID=$user->id", '', 'list');?></td>
|
||||
</tr>
|
||||
<?php endforeach;?>
|
||||
</tbody>
|
||||
|
||||
@@ -43,6 +43,6 @@
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
<div class='alert alert-info'><?php echo $lang->sso->help?></div>
|
||||
<div class='alert alert-info mg-0'><?php echo $lang->sso->help?></div>
|
||||
</div>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
|
||||
@@ -77,7 +77,7 @@ class backup extends control
|
||||
*/
|
||||
public function backup($reload = 'no')
|
||||
{
|
||||
set_time_limit(0);
|
||||
set_time_limit(7200);
|
||||
$fileName = date('YmdHis') . mt_rand(0, 9);
|
||||
$result = $this->backup->backSQL($this->backupPath . $fileName . '.sql.php');
|
||||
if(!$result->result)
|
||||
@@ -149,7 +149,7 @@ class backup extends control
|
||||
die(js::confirm($this->lang->backup->confirmRestore, inlink('restore', "fileName=$fileName&confirm=yes"), inlink('index'), 'self', 'parent'));
|
||||
}
|
||||
|
||||
set_time_limit(0);
|
||||
set_time_limit(7200);
|
||||
|
||||
/* Restore database. */
|
||||
$this->backup->removeFileHeader($this->backupPath . $fileName . '.sql.php');
|
||||
|
||||
@@ -8,7 +8,6 @@ $lang->backup->restore = 'Restore';
|
||||
$lang->backup->change = 'Change hold days';
|
||||
$lang->backup->changeAB = 'change';
|
||||
|
||||
$lang->backup->name = 'Name';
|
||||
$lang->backup->time = 'Time';
|
||||
$lang->backup->files = 'Files';
|
||||
$lang->backup->size = 'Size';
|
||||
|
||||
@@ -8,7 +8,6 @@ $lang->backup->restore = '还原';
|
||||
$lang->backup->change = '修改保留时间';
|
||||
$lang->backup->changeAB = '修改';
|
||||
|
||||
$lang->backup->name = '文件名称';
|
||||
$lang->backup->time = '备份时间';
|
||||
$lang->backup->files = '备份文件';
|
||||
$lang->backup->size = '大小';
|
||||
|
||||
@@ -8,7 +8,6 @@ $lang->backup->restore = '還原';
|
||||
$lang->backup->change = '修改保留時間';
|
||||
$lang->backup->changeAB = '修改';
|
||||
|
||||
$lang->backup->name = '檔案名稱';
|
||||
$lang->backup->time = '備份時間';
|
||||
$lang->backup->files = '備份檔案';
|
||||
$lang->backup->size = '大小';
|
||||
|
||||
@@ -55,9 +55,14 @@ class block extends control
|
||||
$params = json_decode(base64_decode($params));
|
||||
$sso = base64_decode($this->get->sso);
|
||||
|
||||
if(!isset($this->app->user)) $this->app->user = new stdclass();
|
||||
if(!isset($this->app->user->account) or $this->app->user->account != $params->account) $this->app->user->account = $params->account;
|
||||
$this->app->user = $this->dao->select('*')->from(TABLE_USER)->where('ranzhi')->eq($params->account)->fetch();
|
||||
if(empty($this->app->user))
|
||||
{
|
||||
$this->app->user = new stdclass();
|
||||
$this->app->user->account = 'guest';
|
||||
}
|
||||
|
||||
$this->viewType = (isset($params->viewType) and $params->viewType == 'json') ? 'json' : 'html';
|
||||
$this->params = $params;
|
||||
$this->view->sso = $sso;
|
||||
$this->view->sign = strpos($sso, '&') === false ? '?' : '&';
|
||||
@@ -65,6 +70,23 @@ class block extends control
|
||||
|
||||
$func = 'print' . ucfirst($code) . 'Block';
|
||||
$this->$func();
|
||||
|
||||
if($this->viewType == 'json')
|
||||
{
|
||||
unset($this->view->app);
|
||||
unset($this->view->config);
|
||||
unset($this->view->lang);
|
||||
unset($this->view->header);
|
||||
unset($this->view->position);
|
||||
unset($this->view->moduleTree);
|
||||
|
||||
$output['status'] = is_object($this->view) ? 'success' : 'fail';
|
||||
$output['data'] = json_encode($this->view);
|
||||
$output['md5'] = md5(json_encode($this->view));
|
||||
die(json_encode($output));
|
||||
}
|
||||
|
||||
$this->display();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,8 +98,8 @@ class block extends control
|
||||
*/
|
||||
public function printTodoBlock()
|
||||
{
|
||||
$this->view->todos = $this->loadModel('todo')->getList('all', $this->app->user->account, 'wait, doing', $this->params->num);
|
||||
$this->display();
|
||||
$this->view->todos = $this->loadModel('todo')->getList('all', $this->app->user->account, 'wait, doing', $this->viewType == 'json' ? 0 : $this->params->num);
|
||||
$this->view->listLink = $this->view->sso . $this->view->sign . 'referer=' . base64_encode($this->createLink('my', 'todo', "type=all"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,8 +110,8 @@ class block extends control
|
||||
*/
|
||||
public function printTaskBlock()
|
||||
{
|
||||
$this->view->tasks = $this->loadModel('task')->getUserTasks($this->app->user->account, $this->params->type, $this->params->num, null, $this->params->orderBy);
|
||||
$this->display();
|
||||
$this->view->tasks = $this->loadModel('task')->getUserTasks($this->app->user->account, $this->params->type, $this->viewType == 'json' ? 0 : $this->params->num, null, $this->params->orderBy);
|
||||
$this->view->listLink = $this->view->sso . $this->view->sign . 'referer=' . base64_encode($this->createLink('my', 'task', "type={$this->params->type}"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,9 +122,8 @@ class block extends control
|
||||
*/
|
||||
public function printBugBlock()
|
||||
{
|
||||
$this->view->bugs = $this->loadModel('bug')->getUserBugs($this->app->user->account, $this->params->type, $this->params->orderBy, $this->params->num);
|
||||
|
||||
$this->display();
|
||||
$this->view->bugs = $this->loadModel('bug')->getUserBugs($this->app->user->account, $this->params->type, $this->params->orderBy, $this->viewType == 'json' ? 0 : $this->params->num);
|
||||
$this->view->listLink = $this->view->sso . $this->view->sign . 'referer=' . base64_encode($this->createLink('my', 'bug', "type={$this->params->type}"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,17 +148,20 @@ class block extends control
|
||||
->andWhere('t3.status')->ne('done')
|
||||
->andWhere('t3.deleted')->eq(0)
|
||||
->andWhere('t2.deleted')->eq(0)
|
||||
->orderBy($this->params->orderBy)->limit($this->params->num)->fetchAll();
|
||||
->orderBy($this->params->orderBy)
|
||||
->beginIF($this->viewType != 'json')->limit($this->params->num)->fi()
|
||||
->fetchAll();
|
||||
}
|
||||
elseif($this->params->type == 'openedbyme')
|
||||
{
|
||||
$cases = $this->dao->findByOpenedBy($this->app->user->account)->from(TABLE_CASE)
|
||||
->andWhere('deleted')->eq(0)
|
||||
->orderBy($this->params->orderBy)->limit($this->params->num)->fetchAll();
|
||||
->orderBy($this->params->orderBy)
|
||||
->beginIF($this->viewType != 'json')->limit($this->params->num)->fi()
|
||||
->fetchAll();
|
||||
}
|
||||
$this->view->cases = $cases;
|
||||
|
||||
$this->display();
|
||||
$this->view->cases = $cases;
|
||||
$this->view->listLink = $this->view->sso . $this->view->sign . 'referer=' . base64_encode($this->createLink('my', 'testcase', "type={$this->params->type}"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,8 +174,8 @@ class block extends control
|
||||
{
|
||||
$this->app->loadClass('pager', $static = true);
|
||||
$pager = pager::init(0, $this->params->num, 1);
|
||||
$this->view->stories = $this->loadModel('story')->getUserStories($this->app->user->account, $this->params->type, $this->params->orderBy, $pager);
|
||||
$this->display();
|
||||
$this->view->stories = $this->loadModel('story')->getUserStories($this->app->user->account, $this->params->type, $this->params->orderBy, $this->viewType != 'json' ? $pager : '');
|
||||
$this->view->listLink = $this->view->sso . $this->view->sign . 'referer=' . base64_encode($this->createLink('my', 'story', "type={$this->params->type}"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -164,9 +188,8 @@ class block extends control
|
||||
{
|
||||
$this->app->loadClass('pager', $static = true);
|
||||
$pager = pager::init(0, $this->params->num, 1);
|
||||
$this->view->productStats = $this->loadModel('product')->getStats('code_asc', $pager);
|
||||
|
||||
$this->display();
|
||||
$this->view->productStats = $this->loadModel('product')->getStats('order_desc', $this->viewType != 'json' ? $pager : '');
|
||||
$this->view->listLink = $this->view->sso . $this->view->sign . 'referer=' . base64_encode($this->createLink('product', 'index', "locate=no&productID=" . current($this->view->productStats)->id));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -179,8 +202,7 @@ class block extends control
|
||||
{
|
||||
$this->app->loadClass('pager', $static = true);
|
||||
$pager = pager::init(0, $this->params->num, 1);
|
||||
$this->view->projectStats = $this->loadModel('project')->getProjectStats($status = 'undone', $productID = 0, $branch = 0, $itemCounts = 30, $orderBy = 'code', $pager);
|
||||
|
||||
$this->display();
|
||||
$this->view->projectStats = $this->loadModel('project')->getProjectStats($status = 'undone', $productID = 0, $branch = 0, $itemCounts = 30, $orderBy = 'order_desc', $this->viewType != 'json' ? $pager : '');
|
||||
$this->view->listLink = $this->view->sso . $this->view->sign . 'referer=' . base64_encode($this->createLink('my', 'project'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,8 +13,6 @@ $lang->block = new stdclass();
|
||||
$lang->block->num = 'Number';
|
||||
$lang->block->type = 'Type';
|
||||
$lang->block->orderBy = 'Order';
|
||||
$lang->block->status = 'Status';
|
||||
$lang->block->actions = 'Action';
|
||||
|
||||
$lang->block->availableBlocks = new stdclass();
|
||||
|
||||
|
||||
@@ -13,8 +13,6 @@ $lang->block = new stdclass();
|
||||
$lang->block->num = '数量';
|
||||
$lang->block->type = '类型';
|
||||
$lang->block->orderBy = '排序';
|
||||
$lang->block->status = '状态';
|
||||
$lang->block->actions = '操作';
|
||||
|
||||
$lang->block->availableBlocks = new stdclass();
|
||||
|
||||
|
||||
@@ -13,8 +13,6 @@ $lang->block = new stdclass();
|
||||
$lang->block->num = '數量';
|
||||
$lang->block->type = '類型';
|
||||
$lang->block->orderBy = '排序';
|
||||
$lang->block->status = '狀態';
|
||||
$lang->block->actions = '操作';
|
||||
|
||||
$lang->block->availableBlocks = new stdclass();
|
||||
|
||||
|
||||
@@ -29,4 +29,8 @@
|
||||
</tr>
|
||||
<?php endforeach;?>
|
||||
</table>
|
||||
<script>$('.block-bug').dataTable();</script>
|
||||
<p class='hide block-bug-link'><?php echo $listLink;?></p>
|
||||
<script>
|
||||
$('.block-bug').dataTable();
|
||||
$('.block-bug-link').closest('.panel').find('.panel-heading .more').attr('href', $('.block-bug-link').html());
|
||||
</script>
|
||||
|
||||
@@ -33,4 +33,8 @@
|
||||
</tr>
|
||||
<?php endforeach;?>
|
||||
</table>
|
||||
<script>$('.block-case').dataTable();</script>
|
||||
<p class='hide block-case-link'><?php echo $listLink;?></p>
|
||||
<script>
|
||||
$('.block-case').dataTable();
|
||||
$('.block-case-link').closest('.panel').find('.panel-heading .more').attr('href', $('.block-case-link').html());
|
||||
</script>
|
||||
|
||||
@@ -39,4 +39,8 @@
|
||||
<?php endforeach;?>
|
||||
</tbody>
|
||||
</table>
|
||||
<script>$('.block-product').dataTable();</script>
|
||||
<p class='hide block-product-link'><?php echo $listLink;?></p>
|
||||
<script>
|
||||
$('.block-product').dataTable();
|
||||
$('.block-product-link').closest('.panel').find('.panel-heading .more').attr('href', $('.block-product-link').html());
|
||||
</script>
|
||||
|
||||
@@ -38,4 +38,8 @@
|
||||
<?php endforeach;?>
|
||||
</tbody>
|
||||
</table>
|
||||
<script>$('.block-project').dataTable();</script>
|
||||
<p class='hide block-project-link'><?php echo $listLink;?></p>
|
||||
<script>
|
||||
$('.block-project').dataTable();
|
||||
$('.block-project-link').closest('.panel').find('.panel-heading .more').attr('href', $('.block-project-link').html());
|
||||
</script>
|
||||
|
||||
@@ -33,4 +33,8 @@
|
||||
</tr>
|
||||
<?php endforeach;?>
|
||||
</table>
|
||||
<script>$('.block-story').dataTable();</script>
|
||||
<p class='hide block-story-link'><?php echo $listLink;?></p>
|
||||
<script>
|
||||
$('.block-story').dataTable();
|
||||
$('.block-story-link').closest('.panel').find('.panel-heading .more').attr('href', $('.block-story-link').html());
|
||||
</script>
|
||||
|
||||
@@ -36,4 +36,8 @@ td.delayed{background: #e84e0f!important; color: white;}
|
||||
</tr>
|
||||
<?php endforeach;?>
|
||||
</table>
|
||||
<script>$('.block-task').dataTable();</script>
|
||||
<p class='hide block-task-link'><?php echo $listLink;?></p>
|
||||
<script>
|
||||
$('.block-task').dataTable();
|
||||
$('.block-task-link').closest('.panel').find('.panel-heading .more').attr('href', $('.block-task-link').html());
|
||||
</script>
|
||||
|
||||
@@ -31,4 +31,8 @@
|
||||
</tr>
|
||||
<?php endforeach;?>
|
||||
</table>
|
||||
<script>$('.block-todo').dataTable();</script>
|
||||
<p class='hide block-todo-link'><?php echo $listLink;?></p>
|
||||
<script>
|
||||
$('.block-todo').dataTable();
|
||||
$('.block-todo-link').closest('.panel').find('.panel-heading .more').attr('href', $('.block-todo-link').html());
|
||||
</script>
|
||||
|
||||
@@ -115,6 +115,6 @@ class branch extends control
|
||||
|
||||
$branches = $this->branch->getPairs($productID);
|
||||
if($oldBranch) $branches = array($oldBranch => $branches[$oldBranch]);
|
||||
die(html::select('branch', $branches, '', "class='form-control' onchange='loadBranch()'"));
|
||||
die(html::select('branch', $branches, '', "class='form-control' onchange='loadBranch(this)'"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,6 @@ $lang->branch->manage = 'Branch manage';
|
||||
$lang->branch->delete = 'Branch delete';
|
||||
|
||||
$lang->branch->manageTitle = '%s Manage';
|
||||
$lang->branch->all = 'All';
|
||||
$lang->branch->all = 'All ';
|
||||
|
||||
$lang->branch->confirmDelete = '%branch% deletion, will affect the %branch% of the demand, module, plan, release, Bug, testcase and so on, please consider carefully. Are you sure delete the %branch%?';
|
||||
|
||||
@@ -43,7 +43,7 @@ class branchModel extends model
|
||||
if(strpos($params, 'noempty') === false)
|
||||
{
|
||||
$product = $this->loadModel('product')->getById($productID);
|
||||
if($product->type == 'normal') return array();
|
||||
if(!$product or $product->type == 'normal') return array();
|
||||
|
||||
$branches = array('0' => $this->lang->branch->all . $this->lang->product->branchName[$product->type]) + $branches;
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@ class bug extends control
|
||||
* Browse bugs.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param string $branch
|
||||
* @param string $browseType
|
||||
* @param int $param
|
||||
* @param string $orderBy
|
||||
@@ -63,10 +64,10 @@ class bug extends control
|
||||
*/
|
||||
public function browse($productID = 0, $branch = '', $browseType = 'unclosed', $param = 0, $orderBy = '', $recTotal = 0, $recPerPage = 20, $pageID = 1)
|
||||
{
|
||||
/* Set browseType, productID, moduleID and queryID. */
|
||||
/* Set browseType, productID, moduleID, queryID and branch. */
|
||||
$browseType = strtolower($browseType);
|
||||
$productID = $this->product->saveState($productID, $this->products);
|
||||
if($branch === '') $branch = $this->session->branch;
|
||||
$branch = ($branch == '') ? $this->session->branch : $branch;
|
||||
$moduleID = ($browseType == 'bymodule') ? (int)$param : 0;
|
||||
$queryID = ($browseType == 'bysearch') ? (int)$param : 0;
|
||||
|
||||
@@ -86,98 +87,43 @@ class bug extends control
|
||||
if($this->app->getViewType() == 'mhtml') $recPerPage = 10;
|
||||
$pager = pager::init($recTotal, $recPerPage, $pageID);
|
||||
|
||||
$projects = $this->loadModel('project')->getPairs();
|
||||
$projects[0] = '';
|
||||
/* Get projects. */
|
||||
$projects = $this->loadModel('project')->getPairs('empty');
|
||||
|
||||
/* Get bugs. */
|
||||
$bugs = array();
|
||||
if($browseType == 'all') $bugs = $this->bug->getAllBugs($productID, $branch, $projects, $sort, $pager);
|
||||
elseif($browseType == "bymodule")
|
||||
{
|
||||
$childModuleIds = $this->tree->getAllChildId($moduleID);
|
||||
$bugs = $this->bug->getModuleBugs($productID, $branch, $childModuleIds, $projects, $sort, $pager);
|
||||
}
|
||||
elseif($browseType == 'assigntome') $bugs = $this->bug->getByAssigntome($productID, $branch, $projects, $sort, $pager);
|
||||
elseif($browseType == 'openedbyme') $bugs = $this->bug->getByOpenedbyme($productID, $branch, $projects, $sort, $pager);
|
||||
elseif($browseType == 'resolvedbyme') $bugs = $this->bug->getByResolvedbyme($productID, $branch, $projects, $sort, $pager);
|
||||
elseif($browseType == 'assigntonull') $bugs = $this->bug->getByAssigntonull($productID, $branch, $projects, $sort, $pager);
|
||||
elseif($browseType == 'unconfirmed') $bugs = $this->bug->getUnconfirmed($productID, $branch, $projects, $sort, $pager);
|
||||
elseif($browseType == 'unresolved') $bugs = $this->bug->getByStatus($productID, $branch, $projects, 'unresolved', $sort, $pager);
|
||||
elseif($browseType == 'unclosed') $bugs = $this->bug->getByStatus($productID, $branch, $projects, 'unclosed', $sort, $pager);
|
||||
elseif($browseType == 'toclosed') $bugs = $this->bug->getByStatus($productID, $branch, $projects, 'toclosed', $sort, $pager);
|
||||
elseif($browseType == 'longlifebugs') $bugs = $this->bug->getByLonglifebugs($productID, $branch, $projects, $sort, $pager);
|
||||
elseif($browseType == 'postponedbugs') $bugs = $this->bug->getByPostponedbugs($productID, $branch, $projects, $sort, $pager);
|
||||
elseif($browseType == 'needconfirm') $bugs = $this->bug->getByNeedconfirm($productID, $branch, $projects, $sort, $pager);
|
||||
elseif($browseType == 'bysearch') $bugs = $this->bug->getBySearch($productID, $queryID, $sort, $pager, $branch);
|
||||
$bugs = $this->bug->getBugs($productID, $projects, $branch, $browseType, $moduleID, $queryID, $sort, $pager);
|
||||
|
||||
/* Process the sql, get the conditon partion, save it to session. */
|
||||
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'bug', $browseType == 'needconfirm' ? false : true);
|
||||
|
||||
/* Process bug for check story changed. */
|
||||
$bugs = $this->loadModel('story')->checkNeedConfirm($bugs);
|
||||
|
||||
/* Build the search form. */
|
||||
$this->config->bug->search['actionURL'] = $this->createLink('bug', 'browse', "productID=$productID&branch=$branch&browseType=bySearch&queryID=myQueryID");
|
||||
$this->config->bug->search['queryID'] = $queryID;
|
||||
$this->config->bug->search['params']['product']['values'] = array($productID => $this->products[$productID], 'all' => $this->lang->bug->allProduct);
|
||||
$this->config->bug->search['params']['plan']['values'] = $this->loadModel('productplan')->getPairs($productID);
|
||||
$this->config->bug->search['params']['module']['values'] = $this->tree->getOptionMenu($productID, $viewType = 'bug', $startModuleID = 0);
|
||||
$this->config->bug->search['params']['project']['values'] = $this->product->getProjectPairs($productID);
|
||||
$this->config->bug->search['params']['openedBuild']['values'] = $this->loadModel('build')->getProductBuildPairs($productID, 0, $params = '');
|
||||
$this->config->bug->search['params']['resolvedBuild']['values'] = $this->config->bug->search['params']['openedBuild']['values'];
|
||||
if($this->session->currentProductType == 'normal')
|
||||
{
|
||||
unset($this->config->bug->search['fields']['branch']);
|
||||
unset($this->config->bug->search['params']['branch']);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->config->bug->search['fields']['branch'] = $this->lang->product->branch;
|
||||
$this->config->bug->search['params']['branch']['values'] = array('' => '') + $this->loadModel('branch')->getPairs($productID, 'noempty');
|
||||
}
|
||||
$this->loadModel('search')->setSearchParams($this->config->bug->search);
|
||||
|
||||
$users = $this->user->getPairs('noletter');
|
||||
$bugs = $this->loadModel('story')->checkNeedConfirm($bugs);
|
||||
|
||||
/* Process the openedBuild and resolvedBuild fields. */
|
||||
$productIdList = array();
|
||||
foreach($bugs as $bug) $productIdList[$bug->id] = $bug->product;
|
||||
$builds = $this->loadModel('build')->getProductBuildPairs(array_unique($productIdList), 0, $params = '');
|
||||
foreach($bugs as $key => $bug)
|
||||
{
|
||||
$openBuildIdList = explode(',', $bug->openedBuild);
|
||||
$openedBuild = '';
|
||||
foreach($openBuildIdList as $buildID)
|
||||
{
|
||||
$openedBuild .= isset($builds[$buildID]) ? $builds[$buildID] : $buildID;
|
||||
$openedBuild .= ',';
|
||||
}
|
||||
$bug->openedBuild = rtrim($openedBuild, ',');
|
||||
$bug->resolvedBuild = isset($builds[$bug->resolvedBuild]) ? $builds[$bug->resolvedBuild] : $bug->resolvedBuild;
|
||||
}
|
||||
$bugs = $this->bug->processBuildForBugs($bugs);
|
||||
|
||||
$memberPairs = $this->user->getPairs('noletter|nodeleted');
|
||||
|
||||
$title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->common;
|
||||
$position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]);
|
||||
$position[] = $this->lang->bug->common;
|
||||
/* Build the search form. */
|
||||
$actionURL = $this->createLink('bug', 'browse', "productID=$productID&branch=$branch&browseType=bySearch&queryID=myQueryID");
|
||||
$this->bug->buildSearchForm($productID, $this->products, $queryID, $actionURL);
|
||||
|
||||
$this->view->title = $title;
|
||||
$this->view->position = $position;
|
||||
$this->view->productID = $productID;
|
||||
$this->view->productName = $this->products[$productID];
|
||||
$this->view->builds = $this->loadModel('build')->getProductBuildPairs($productID);
|
||||
$this->view->moduleTree = $this->tree->getTreeMenu($productID, $viewType = 'bug', $startModuleID = 0, array('treeModel', 'createBugLink'), '', $branch);
|
||||
$this->view->browseType = $browseType;
|
||||
$this->view->bugs = $bugs;
|
||||
$this->view->users = $users;
|
||||
$this->view->pager = $pager;
|
||||
$this->view->param = $param;
|
||||
$this->view->orderBy = $orderBy;
|
||||
$this->view->moduleID = $moduleID;
|
||||
$this->view->memberPairs = $memberPairs;
|
||||
$this->view->branch = $branch;
|
||||
$this->view->branches = $this->loadModel('branch')->getPairs($productID);
|
||||
/* Set view. */
|
||||
$this->view->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->common;
|
||||
$this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]);
|
||||
$this->view->position[] = $this->lang->bug->common;
|
||||
$this->view->productID = $productID;
|
||||
$this->view->productName = $this->products[$productID];
|
||||
$this->view->builds = $this->loadModel('build')->getProductBuildPairs($productID);
|
||||
$this->view->moduleTree = $this->tree->getTreeMenu($productID, $viewType = 'bug', $startModuleID = 0, array('treeModel', 'createBugLink'), '', $branch);
|
||||
$this->view->browseType = $browseType;
|
||||
$this->view->bugs = $bugs;
|
||||
$this->view->users = $this->user->getPairs('noletter');
|
||||
$this->view->pager = $pager;
|
||||
$this->view->param = $param;
|
||||
$this->view->orderBy = $orderBy;
|
||||
$this->view->moduleID = $moduleID;
|
||||
$this->view->memberPairs = $this->user->getPairs('noletter|nodeleted');
|
||||
$this->view->branch = $branch;
|
||||
$this->view->branches = $this->loadModel('branch')->getPairs($productID);
|
||||
|
||||
$this->display();
|
||||
}
|
||||
@@ -351,7 +297,7 @@ class bug extends control
|
||||
$this->view->productName = $this->products[$productID];
|
||||
$this->view->moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'bug', $startModuleID = 0, $branch);
|
||||
$this->view->stories = $stories;
|
||||
$this->view->projects = $this->product->getProjectPairs($productID, $branch, $params = 'nodeleted');
|
||||
$this->view->projects = $this->product->getProjectPairs($productID, $branch ? "0,$branch" : 0, $params = 'nodeleted');
|
||||
$this->view->builds = $builds;
|
||||
$this->view->moduleID = $moduleID;
|
||||
$this->view->projectID = $projectID;
|
||||
@@ -416,19 +362,14 @@ class bug extends control
|
||||
|
||||
if($this->session->bugImagesFile)
|
||||
{
|
||||
$extractPath = $this->session->bugImagesFile;
|
||||
if(is_dir($extractPath))
|
||||
$files = $this->session->bugImagesFile;
|
||||
foreach($files as $fileName => $file)
|
||||
{
|
||||
$titles = array();
|
||||
$files = glob($extractPath . '/*');
|
||||
sort($files);
|
||||
foreach($files as $fileName)
|
||||
{
|
||||
$fileName = basename($fileName);
|
||||
$titles[$fileName] = preg_replace('/^\d+_/', '', pathinfo($fileName, PATHINFO_FILENAME));
|
||||
}
|
||||
$this->view->titles = $titles;
|
||||
$title = $file['title'];
|
||||
$titles[$title] = $fileName;
|
||||
}
|
||||
krsort($titles);
|
||||
$this->view->titles = $titles;
|
||||
}
|
||||
|
||||
$this->view->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->batchCreate;
|
||||
@@ -439,7 +380,7 @@ class bug extends control
|
||||
$this->view->stories = $stories;
|
||||
$this->view->builds = $builds;
|
||||
$this->view->users = $this->user->getPairs('nodeleted,devfirst');
|
||||
$this->view->projects = $this->product->getProjectPairs($productID, $branch, $params = 'nodeleted');
|
||||
$this->view->projects = $this->product->getProjectPairs($productID, $branch ? "0,$branch" : 0, $params = 'nodeleted');
|
||||
$this->view->projectID = $projectID;
|
||||
$this->view->moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'bug', $startModuleID = 0, $branch);
|
||||
$this->view->moduleID = $moduleID;
|
||||
@@ -585,7 +526,7 @@ class bug extends control
|
||||
$this->view->plans = $this->loadModel('productplan')->getPairs($productID, $bug->branch);
|
||||
$this->view->moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'bug', $startModuleID = 0, $bug->branch);
|
||||
$this->view->currentModuleID = $currentModuleID;
|
||||
$this->view->projects = $this->product->getProjectPairs($bug->product);
|
||||
$this->view->projects = $this->product->getProjectPairs($bug->product, $bug->branch ? "0,{$bug->branch}" : 0, 'nodeleted');
|
||||
$this->view->stories = $bug->project ? $this->story->getProjectStoryPairs($bug->project) : $this->story->getProductStoryPairs($bug->product, $bug->branch);
|
||||
$this->view->branches = $this->session->currentProductType == 'normal' ? array() : $this->loadModel('branch')->getPairs($bug->product);
|
||||
$this->view->tasks = $this->task->getProjectTaskPairs($bug->project);
|
||||
@@ -691,7 +632,7 @@ class bug extends control
|
||||
$bug = $this->bug->getById($bugID);
|
||||
|
||||
/* Set menu. */
|
||||
$this->bug->setMenu($this->products, $bug->product);
|
||||
$this->bug->setMenu($this->products, $bug->product, $bug->branch);
|
||||
|
||||
if(!empty($_POST))
|
||||
{
|
||||
@@ -764,7 +705,7 @@ class bug extends control
|
||||
|
||||
$bug = $this->bug->getById($bugID);
|
||||
$productID = $bug->product;
|
||||
$this->bug->setMenu($this->products, $productID);
|
||||
$this->bug->setMenu($this->products, $productID, $bug->branch);
|
||||
|
||||
$this->view->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->confirmBug;
|
||||
$this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]);
|
||||
@@ -811,7 +752,7 @@ class bug extends control
|
||||
$files = $this->loadModel('file')->saveUpload('bug', $bugID);
|
||||
|
||||
$fileAction = !empty($files) ? $this->lang->addFiles . join(',', $files) . "\n" : '';
|
||||
$actionID = $this->action->create('bug', $bugID, 'Resolved', $fileAction . $this->post->comment, $this->post->resolution);
|
||||
$actionID = $this->action->create('bug', $bugID, 'Resolved', $fileAction . $this->post->comment, $this->post->resolution . ($this->post->duplicateBug ? ':' . (int)$this->post->duplicateBug : ''));
|
||||
$this->sendmail($bugID, $actionID);
|
||||
|
||||
$bug = $this->bug->getById($bugID);
|
||||
@@ -832,7 +773,7 @@ class bug extends control
|
||||
$assignedTo = $bug->openedBy;
|
||||
if(!isset($users[$assignedTo])) $assignedTo = $this->bug->getModuleOwner($bug->module, $productID);
|
||||
|
||||
$this->bug->setMenu($this->products, $productID);
|
||||
$this->bug->setMenu($this->products, $productID, $bug->branch);
|
||||
|
||||
$this->view->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->resolve;
|
||||
$this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]);
|
||||
@@ -889,7 +830,7 @@ class bug extends control
|
||||
|
||||
$bug = $this->bug->getById($bugID);
|
||||
$productID = $bug->product;
|
||||
$this->bug->setMenu($this->products, $productID);
|
||||
$this->bug->setMenu($this->products, $productID, $bug->branch);
|
||||
|
||||
$this->view->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->activate;
|
||||
$this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]);
|
||||
@@ -924,7 +865,7 @@ class bug extends control
|
||||
|
||||
$bug = $this->bug->getById($bugID);
|
||||
$productID = $bug->product;
|
||||
$this->bug->setMenu($this->products, $productID);
|
||||
$this->bug->setMenu($this->products, $productID, $bug->branch);
|
||||
|
||||
$this->view->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->close;
|
||||
$this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]);
|
||||
@@ -936,6 +877,92 @@ class bug extends control
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Link related bugs.
|
||||
*
|
||||
* @param int $bugID
|
||||
* @param string $browseType
|
||||
* @param int $param
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function linkBugs($bugID, $browseType = '', $param = 0)
|
||||
{
|
||||
/* Link bugs. */
|
||||
if(!empty($_POST))
|
||||
{
|
||||
$this->bug->linkBugs($bugID);
|
||||
if(isonlybody()) die(js::closeModal('parent.parent', '', "function(){parent.parent.loadLinkBugs('$bugID')}"));
|
||||
die(js::locate($this->createLink('bug', 'edit', "bugID=$bugID"), 'parent'));
|
||||
}
|
||||
|
||||
/* Get bug and queryID. */
|
||||
$bug = $this->bug->getById($bugID);
|
||||
$queryID = ($browseType == 'bySearch') ? (int)$param : 0;
|
||||
|
||||
/* Set the menu. */
|
||||
$this->bug->setMenu($this->products, $bug->product, $bug->branch);
|
||||
|
||||
/* Build the search form. */
|
||||
$actionURL = $this->createLink('bug', 'linkBugs', "bugID=$bugID&browseType=bySearch&queryID=myQueryID", '', true);
|
||||
$this->bug->buildSearchForm($bug->product, $this->products, $queryID, $actionURL);
|
||||
|
||||
/* Get bugs to link. */
|
||||
$bugs2Link = $this->bug->getBugs2Link($bugID, $browseType, $queryID);
|
||||
|
||||
/* Assign. */
|
||||
$this->view->title = $this->lang->bug->linkBugs . "BUG #$bug->id $bug->title - " . $this->products[$bug->product];
|
||||
$this->view->position[] = html::a($this->createLink('product', 'view', "productID=$bug->product"), $this->products[$bug->product]);
|
||||
$this->view->position[] = html::a($this->createLink('bug', 'view', "bugID=$bugID"), $bug->title);
|
||||
$this->view->position[] = $this->lang->bug->linkBugs;
|
||||
$this->view->bug = $bug;
|
||||
$this->view->bugs2Link = $bugs2Link;
|
||||
$this->view->users = $this->loadModel('user')->getPairs('noletter');
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX: get linkBugs.
|
||||
*
|
||||
* @param int $bugID
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function ajaxGetLinkBugs($bugID)
|
||||
{
|
||||
/* Get linkbugs. */
|
||||
$bugs = $this->bug->getLinkBugs($bugID);
|
||||
|
||||
/* Build linkBug list.*/
|
||||
$output = '';
|
||||
foreach($bugs as $bugId => $bugTitle)
|
||||
{
|
||||
$output .= '<li>';
|
||||
$output .= html::a(inlink('view', "bugID=$bugId"), "#$bugId " . $bugTitle, '_blank');
|
||||
$output .= html::a("javascript:unlinkBug($bugID, $bugId)", '<i class="icon-remove"></i>', '', "title='{$this->lang->unlink}' style='float:right'");
|
||||
$output .= '</li>';
|
||||
}
|
||||
|
||||
die($output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlink related bug.
|
||||
*
|
||||
* @param int $bugID
|
||||
* @param int $bug2Unlink
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function unlinkBug($bugID, $bug2Unlink = 0)
|
||||
{
|
||||
/* Unlink related bug. */
|
||||
$this->bug->unlinkBug($bugID, $bug2Unlink);
|
||||
|
||||
die('success');
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch close bugs.
|
||||
*
|
||||
@@ -1182,7 +1209,8 @@ class bug extends control
|
||||
}
|
||||
|
||||
/* Get action info. */
|
||||
$action = $this->action->getById($actionID);
|
||||
$actions = $this->action->getList('bug', $bugID);
|
||||
$action = zget($actions, $actionID, null);
|
||||
$history = $this->action->getHistory($actionID);
|
||||
$action->history = isset($history[$actionID]) ? $history[$actionID] : array();
|
||||
if(strtolower($action->action) == 'opened') $action->comment = $bug->steps;
|
||||
|
||||
@@ -16,6 +16,17 @@
|
||||
|
||||
#module_chosen.chosen-container .chosen-drop {min-width: 400px; border-top: 1px solid #ddd!important}
|
||||
#openedBuild_chosen.chosen-container .chosen-drop {min-width: 450px; border-top: 1px solid #ddd!important}
|
||||
#module + .chosen-container-single .chosen-single,
|
||||
#task + .chosen-container-single .chosen-single,
|
||||
#openedBuild + .chosen-container-multi .chosen-choices {border-top-left-radius: 0; border-bottom-left-radius: 0;}
|
||||
#openedBuild + .chosen-container-multi .chosen-choices,
|
||||
#mailto + .chosen-container-multi .chosen-choices {border-top-right-radius: 0; border-bottom-right-radius: 0;}
|
||||
|
||||
.row .col-sm-8{width:75%;}
|
||||
.row .col-sm-4{padding-left:0px; width:25%;}
|
||||
.dropdown-pris > .btn {background-color: #fff; text-shadow: none}
|
||||
|
||||
/* Keep label has same width as relative task label*/
|
||||
#keywordsAddonLabel:before {content: '空'; color: transparent}
|
||||
|
||||
#contactListGroup .input-group-btn > .btn {margin-left: -1px!important;}
|
||||
|
||||
.minw-80px {min-width: 80px;}
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
.col-side .chosen-container {width: 218px!important}
|
||||
.col-side .chosen-container[id^="openedBuild"] {width: 172px!important}
|
||||
.col-side .chosen-container[id^="resolvedBuild"] {width: 172px!important}
|
||||
#linkBugBox > li {margin-left:-56px}
|
||||
|
||||
1
module/bug/css/linkbugs.css
Normal file
1
module/bug/css/linkbugs.css
Normal file
@@ -0,0 +1 @@
|
||||
#linkBugsForm {min-height: 300px}
|
||||
@@ -25,7 +25,7 @@ function loadProjectBuilds(productID, projectID, index)
|
||||
|
||||
$.get(link, function(builds)
|
||||
{
|
||||
var row = $('#buildBox' + index).parents('tbody').find('tr').size()
|
||||
var row = $('#buildBox' + index).closest('tbody').find('tr').size()
|
||||
do
|
||||
{
|
||||
var selected = $('#buildBox' + index).find('select').val();
|
||||
@@ -49,9 +49,9 @@ $(document).on('click', '.chosen-with-drop', function()
|
||||
var select = $(this).prev('select');
|
||||
if($(select).val() == 'ditto')
|
||||
{
|
||||
var index = $(select).parents('td').index();
|
||||
var row = $(select).parents('tr').index();
|
||||
var table = $(select).parents('tr').parent();
|
||||
var index = $(select).closest('td').index();
|
||||
var row = $(select).closest('tr').index();
|
||||
var table = $(select).closest('tr').parent();
|
||||
var value = '';
|
||||
for(i = row - 1; i >= 0; i--)
|
||||
{
|
||||
@@ -66,9 +66,9 @@ $(document).on('mousedown', 'select', function()
|
||||
{
|
||||
if($(this).val() == 'ditto')
|
||||
{
|
||||
var index = $(this).parents('td').index();
|
||||
var row = $(this).parents('tr').index();
|
||||
var table = $(this).parents('tr').parent();
|
||||
var index = $(this).closest('td').index();
|
||||
var row = $(this).closest('tr').index();
|
||||
var table = $(this).closest('tr').parent();
|
||||
var value = '';
|
||||
for(i = row - 1; i >= 0; i--)
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@ $(document).ready(function()
|
||||
}).on('keyup change paste', 'input', function()
|
||||
{
|
||||
var val = $(this).val().toLowerCase();
|
||||
var $options = $(this).parents('ul.dropdown-menu.with-search').find('.option');
|
||||
var $options = $(this).closest('ul.dropdown-menu.with-search').find('.option');
|
||||
if(val == '') return $options.removeClass('hide');
|
||||
$options.each(function()
|
||||
{
|
||||
@@ -19,4 +19,6 @@ $(document).ready(function()
|
||||
$option.toggleClass('hide', $option.text().toString().toLowerCase().indexOf(val) < 0 && $option.data('key').toString().toLowerCase().indexOf(val) < 0);
|
||||
});
|
||||
});
|
||||
setTimeout(function(){fixedTfootAction('#bugForm')}, 100);
|
||||
setTimeout(function(){fixedTheadOfList('#bugList')}, 100);
|
||||
});
|
||||
|
||||
@@ -426,15 +426,15 @@ function notice()
|
||||
}
|
||||
else
|
||||
{
|
||||
if($('#buildBox').parents('tr').find('td').size() > 1)
|
||||
if($('#buildBox').closest('tr').find('td').size() > 1)
|
||||
{
|
||||
$('#buildBox').parents('td').next().attr('id', 'buildBoxActions');
|
||||
$('#buildBox').parents('td').next().html(html);
|
||||
$('#buildBox').closest('td').next().attr('id', 'buildBoxActions');
|
||||
$('#buildBox').closest('td').next().html(html);
|
||||
}
|
||||
else
|
||||
{
|
||||
html = "<td id='buildBoxActions'>" + html + '</td>';
|
||||
$('#buildBox').parents('td').after(html);
|
||||
$('#buildBox').closest('td').after(html);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,47 +55,6 @@ function setAssignedTo(moduleID, productID)
|
||||
});
|
||||
}
|
||||
|
||||
$(function()
|
||||
{
|
||||
if($('#project').val()) loadProjectRelated($('#project').val());
|
||||
$('#saveTplBtn').on('click', function()
|
||||
{
|
||||
var content = $('#steps').val();
|
||||
bootbox.prompt(setTemplateTitle, function(r)
|
||||
{
|
||||
if(!r || !content) return;
|
||||
saveTemplateLink = createLink('bug', 'saveTemplate');
|
||||
$.post(saveTemplateLink, {title:r, content:content}, function(data)
|
||||
{
|
||||
$('#tplBox').html(data);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// /* Save template. */
|
||||
// KindEditor.plugin('savetemplate', function(K)
|
||||
// {
|
||||
// var self = this, name = 'savetemplate';
|
||||
// self.plugin.savetemplate =
|
||||
// {
|
||||
// click: function(id)
|
||||
// {
|
||||
// content = self.html();
|
||||
// bootbox.prompt(setTemplateTitle, function(r)
|
||||
// {
|
||||
// if(!r || !content) return;
|
||||
// saveTemplateLink = createLink('bug', 'saveTemplate');
|
||||
// $.post(saveTemplateLink, {title:r, content:content}, function(data)
|
||||
// {
|
||||
// $('#tplBox').html(data);
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
// };
|
||||
// self.clickToolbar(name, self.plugin.savetemplate.click);
|
||||
// });
|
||||
|
||||
/* Set template. */
|
||||
function setTemplate(templateID)
|
||||
{
|
||||
@@ -112,3 +71,31 @@ function deleteTemplate(templateID)
|
||||
hiddenwin.location.href = createLink('bug', 'deleteTemplate', 'templateID=' + templateID);
|
||||
$('#tplBox' + templateID).addClass('hidden');
|
||||
}
|
||||
|
||||
$(function()
|
||||
{
|
||||
if($('#project').val()) loadProjectRelated($('#project').val());
|
||||
$('#saveTplBtn').on('click', function()
|
||||
{
|
||||
var content = $('#steps').val();
|
||||
bootbox.prompt(setTemplateTitle, function(r)
|
||||
{
|
||||
if(!r || !content) return;
|
||||
saveTemplateLink = createLink('bug', 'saveTemplate');
|
||||
$.post(saveTemplateLink, {title:r, content:content}, function(data)
|
||||
{
|
||||
$('#tplBox').html(data);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$('[data-toggle=tooltip]').tooltip();
|
||||
|
||||
// ajust style for file box
|
||||
var ajustFilebox = function()
|
||||
{
|
||||
applyCssStyle('.fileBox > tbody > tr > td:first-child {transition: none; width: ' + ($('#contactListGroup').width() - 2) + 'px}', 'filebox')
|
||||
};
|
||||
ajustFilebox();
|
||||
$(window).resize(ajustFilebox);
|
||||
});
|
||||
|
||||
@@ -54,3 +54,33 @@ function loadModuleRelated()
|
||||
productID = $('#product').val();
|
||||
setStories(moduleID, productID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlink related bug.
|
||||
*
|
||||
* @param int $bugID
|
||||
* @param int $bug2Unlink
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function unlinkBug(bugID, bug2Unlink)
|
||||
{
|
||||
link = createLink('bug', 'unlinkBug', 'bugID=' + bugID + '&bug2Unlink=' + bug2Unlink);
|
||||
$.get(link, function(data)
|
||||
{
|
||||
if(data == 'success') $('#linkBugBox').load(createLink('bug', 'ajaxGetLinkBugs', 'bugID=' + bugID));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Load linkBugs.
|
||||
*
|
||||
* @param int $bugID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function loadLinkBugs(bugID)
|
||||
{
|
||||
bugLink = createLink('bug', 'ajaxGetLinkBugs', 'bugID=' + bugID);
|
||||
$('#linkBugBox').load(bugLink);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,6 @@ $(function()
|
||||
});
|
||||
};
|
||||
resizeChartTable();
|
||||
fixTableHead('.table-wrapper');
|
||||
fixedTableHead('.table-wrapper');
|
||||
$(window).resize(resizeChartTable);
|
||||
});
|
||||
|
||||
@@ -15,10 +15,8 @@ $lang->bug->id = 'ID';
|
||||
$lang->bug->product = $lang->productCommon;
|
||||
$lang->bug->productplan = 'Plan';
|
||||
$lang->bug->module = 'Module';
|
||||
$lang->bug->path = 'Path';
|
||||
$lang->bug->project = $lang->projectCommon;
|
||||
$lang->bug->story = 'Story';
|
||||
$lang->bug->storyVersion = 'Story Version';
|
||||
$lang->bug->task = 'Task';
|
||||
$lang->bug->title = 'Title';
|
||||
$lang->bug->severity = 'Severity';
|
||||
@@ -26,22 +24,16 @@ $lang->bug->severityAB = 'S';
|
||||
$lang->bug->pri = 'Priority';
|
||||
$lang->bug->type = 'Type';
|
||||
$lang->bug->os = 'OS';
|
||||
$lang->bug->plan = 'Plan';
|
||||
$lang->bug->hardware = 'Hardware';
|
||||
$lang->bug->browser = 'Browser';
|
||||
$lang->bug->machine = 'Machine';
|
||||
$lang->bug->found = 'How found';
|
||||
$lang->bug->steps = 'Steps';
|
||||
$lang->bug->status = 'Status';
|
||||
$lang->bug->statusAB = 'Status';
|
||||
$lang->bug->activatedCount = 'Activated count';
|
||||
$lang->bug->activatedCountAB = 'Activated count';
|
||||
$lang->bug->confirmed = 'Confirmed';
|
||||
$lang->bug->toTask = 'To task';
|
||||
$lang->bug->toStory = 'To story';
|
||||
$lang->bug->mailto = 'Mailto';
|
||||
$lang->bug->openedBy = 'Opened By';
|
||||
$lang->bug->openedByAB = 'Opened';
|
||||
$lang->bug->openedDate = 'Opened date';
|
||||
$lang->bug->openedDateAB = 'Date';
|
||||
$lang->bug->openedBuild = 'Opened Build';
|
||||
@@ -58,8 +50,9 @@ $lang->bug->closedBy = 'Closed By';
|
||||
$lang->bug->closedDate = 'Closed Date';
|
||||
$lang->bug->duplicateBug = 'Duplicate';
|
||||
$lang->bug->lastEditedBy = 'Last Edited By';
|
||||
$lang->bug->lastEditedDate = 'Last Edited Date';
|
||||
$lang->bug->linkBug = 'Related';
|
||||
$lang->bug->linkBugs = 'Link related bugs';
|
||||
$lang->bug->unlinkBug = 'Unlink related bug';
|
||||
$lang->bug->case = 'Case';
|
||||
$lang->bug->files = 'Files';
|
||||
$lang->bug->keywords = 'Keywords';
|
||||
@@ -91,15 +84,9 @@ $lang->bug->delete = 'Delete Bug';
|
||||
$lang->bug->deleted = 'Deleted';
|
||||
$lang->bug->saveTemplate = 'Save template';
|
||||
$lang->bug->deleteTemplate = 'Delete template';
|
||||
$lang->bug->customFields = 'Custom';
|
||||
$lang->bug->restoreDefault = 'Default';
|
||||
$lang->bug->ajaxGetUserBugs = 'API: My Bugs';
|
||||
$lang->bug->ajaxGetModuleOwner = 'API: Get module default owner';
|
||||
$lang->bug->confirmStoryChange = 'Confirm Story Change';
|
||||
|
||||
/* Browse tabs. */
|
||||
$lang->bug->selectProduct = "Select {$lang->productCommon}";
|
||||
$lang->bug->byModule = 'ByModule';
|
||||
$lang->bug->assignToMe = 'MyBugs';
|
||||
$lang->bug->openedByMe = 'MyOpen';
|
||||
$lang->bug->resolvedByMe = 'MyResolve';
|
||||
@@ -111,51 +98,30 @@ $lang->bug->unclosed = 'Unclosed';
|
||||
$lang->bug->longLifeBugs = 'Longlife';
|
||||
$lang->bug->postponedBugs = 'Postponed';
|
||||
$lang->bug->allBugs = 'Allbug';
|
||||
$lang->bug->moduleBugs = 'ByModule';
|
||||
$lang->bug->byQuery = 'Search';
|
||||
$lang->bug->needConfirm = 'StoryChanged';
|
||||
$lang->bug->allProduct = "All {$lang->productCommon}s";
|
||||
$lang->bug->ditto = 'Ditto';
|
||||
|
||||
/* Labels. */
|
||||
$lang->bug->lblProductAndModule = "{$lang->productCommon}&Module";
|
||||
$lang->bug->lblProjectAndTask = "{$lang->projectCommon}&Task";
|
||||
$lang->bug->lblStory = 'Story';
|
||||
$lang->bug->lblTypeAndSeverity = 'Type&Severity';
|
||||
$lang->bug->lblSystemBrowserAndHardware = 'OS&Browser';
|
||||
$lang->bug->lblAssignedTo = 'Assigned to';
|
||||
$lang->bug->lblMailto = 'Mailto';
|
||||
$lang->bug->lblLastEdited = 'Last edited';
|
||||
$lang->bug->lblResolved = 'Resolved';
|
||||
$lang->bug->lblAllFields = 'All Fields';
|
||||
$lang->bug->lblCustomFields = 'Custom Fields';
|
||||
$lang->bug->allUsers = 'All users';
|
||||
$lang->bug->allBuilds = 'All';
|
||||
|
||||
/* Legends. */
|
||||
$lang->bug->legendBasicInfo = 'Basic info';
|
||||
$lang->bug->legendMailto = 'Mailto';
|
||||
$lang->bug->legendAttatch = 'Files';
|
||||
$lang->bug->legendLinkBugs = 'Related bug';
|
||||
$lang->bug->legendPrjStoryTask = "{$lang->projectCommon}, story & task";
|
||||
$lang->bug->legendCases = 'Related case';
|
||||
$lang->bug->legendSteps = 'Steps';
|
||||
$lang->bug->legendAction = 'Action';
|
||||
$lang->bug->legendHistory = 'History';
|
||||
$lang->bug->legendComment = 'Comment';
|
||||
$lang->bug->legendLife = 'Lifetime';
|
||||
$lang->bug->legendMisc = 'Misc';
|
||||
|
||||
/* Action buttons. */
|
||||
$lang->bug->buttonConfirm = 'Confirm';
|
||||
$lang->bug->buttonCopy = 'Copy';
|
||||
$lang->bug->buttonAssign = 'Assgin';
|
||||
$lang->bug->buttonEdit = 'Edit';
|
||||
$lang->bug->buttonActivate = 'Activate';
|
||||
$lang->bug->buttonResolve = 'Resolve';
|
||||
$lang->bug->buttonClose = 'Close';
|
||||
$lang->bug->buttonToList = 'Back';
|
||||
$lang->bug->buttonCreateTestcase = 'Create Case';
|
||||
|
||||
/* Confirm messags. */
|
||||
$lang->bug->confirmChangeProduct = "Change {$lang->productCommon} will change {$lang->projectCommon}, task and story also, are you sure?";
|
||||
@@ -354,11 +320,13 @@ $lang->bug->report->bugHistories->graph->xAxisName = 'Histories';
|
||||
|
||||
/* 操作记录。*/
|
||||
$lang->bug->action = new stdclass();
|
||||
$lang->bug->action->resolved = array('main' => '$date, Resolved by <strong>$actor</strong>, resolution is <strong>$extra</strong>.', 'extra' => 'resolutionList');
|
||||
$lang->bug->action->resolved = array('main' => '$date, Resolved by <strong>$actor</strong>, resolution is <strong>$extra</strong> $appendLink.', 'extra' => 'resolutionList');
|
||||
$lang->bug->action->tostory = array('main' => '$date, To story by <strong>$actor</strong>, ID is <strong>$extra</strong>.');
|
||||
$lang->bug->action->totask = array('main' => '$date, To task by <strong>$actor</strong>, ID is <strong>$extra</strong>.');
|
||||
$lang->bug->action->linked2plan = array('main' => '$date, Link to plan by <strong>$actor</strong>,ID is <strong>$extra</strong>。');
|
||||
$lang->bug->action->unlinkedfromplan = array('main' => '$date, Unlink from plan <strong>$extra</strong> by <strong>$actor</strong>.');
|
||||
$lang->bug->action->linkrelatedbug = array('main' => '$date, link related bug <strong>$extra</strong> by <strong>$actor</strong>.');
|
||||
$lang->bug->action->unlinkrelatedbug = array('main' => '$date, unlink related bug <strong>$extra</strong> by <strong>$actor</strong>.');
|
||||
|
||||
$lang->bug->placeholder = new stdclass();
|
||||
$lang->bug->placeholder->chooseBuilds = 'Choose builds...';
|
||||
|
||||
@@ -15,10 +15,8 @@ $lang->bug->id = 'Bug编号';
|
||||
$lang->bug->product = '所属' . $lang->productCommon;
|
||||
$lang->bug->productplan = '所属计划';
|
||||
$lang->bug->module = '所属模块';
|
||||
$lang->bug->path = '模块路径';
|
||||
$lang->bug->project = '所属' . $lang->projectCommon;
|
||||
$lang->bug->story = '相关需求';
|
||||
$lang->bug->storyVersion = '需求版本';
|
||||
$lang->bug->task = '相关任务';
|
||||
$lang->bug->title = 'Bug标题';
|
||||
$lang->bug->severity = '严重程度';
|
||||
@@ -26,22 +24,16 @@ $lang->bug->severityAB = '级别';
|
||||
$lang->bug->pri = '优先级';
|
||||
$lang->bug->type = 'Bug类型';
|
||||
$lang->bug->os = '操作系统';
|
||||
$lang->bug->plan = '所属计划';
|
||||
$lang->bug->hardware = '硬件平台';
|
||||
$lang->bug->browser = '浏览器';
|
||||
$lang->bug->machine = '机器硬件';
|
||||
$lang->bug->found = '如何发现';
|
||||
$lang->bug->steps = '重现步骤';
|
||||
$lang->bug->status = 'Bug状态';
|
||||
$lang->bug->statusAB = '状态';
|
||||
$lang->bug->activatedCount = '激活次数';
|
||||
$lang->bug->activatedCountAB = '激活次数';
|
||||
$lang->bug->confirmed = '是否确认';
|
||||
$lang->bug->toTask = '转任务';
|
||||
$lang->bug->toStory = '转需求';
|
||||
$lang->bug->mailto = '抄送给';
|
||||
$lang->bug->openedBy = '由谁创建';
|
||||
$lang->bug->openedByAB = '创建';
|
||||
$lang->bug->openedDate = '创建日期';
|
||||
$lang->bug->openedDateAB = '创建日期';
|
||||
$lang->bug->openedBuild = '影响版本';
|
||||
@@ -58,8 +50,9 @@ $lang->bug->closedBy = '由谁关闭';
|
||||
$lang->bug->closedDate = '关闭日期';
|
||||
$lang->bug->duplicateBug = '重复ID';
|
||||
$lang->bug->lastEditedBy = '最后修改者';
|
||||
$lang->bug->lastEditedDate = '最后修改日期';
|
||||
$lang->bug->linkBug = '相关Bug';
|
||||
$lang->bug->linkBugs = '关联相关Bug';
|
||||
$lang->bug->unlinkBug = '移除相关Bug';
|
||||
$lang->bug->case = '相关用例';
|
||||
$lang->bug->files = '附件';
|
||||
$lang->bug->keywords = '关键词';
|
||||
@@ -91,15 +84,9 @@ $lang->bug->delete = '删除';
|
||||
$lang->bug->deleted = '已删除';
|
||||
$lang->bug->saveTemplate = '保存模板';
|
||||
$lang->bug->deleteTemplate = '删除模板';
|
||||
$lang->bug->customFields = '自定义字段';
|
||||
$lang->bug->restoreDefault = '恢复默认';
|
||||
$lang->bug->ajaxGetUserBugs = '接口:我的Bug';
|
||||
$lang->bug->ajaxGetModuleOwner = '接口:获得模块的默认指派人';
|
||||
$lang->bug->confirmStoryChange = '确认需求变动';
|
||||
|
||||
/* 查询条件列表。*/
|
||||
$lang->bug->selectProduct = '请选择' . $lang->productCommon;
|
||||
$lang->bug->byModule = '按模块';
|
||||
$lang->bug->assignToMe = '指派给我';
|
||||
$lang->bug->openedByMe = '由我创建';
|
||||
$lang->bug->resolvedByMe = '由我解决';
|
||||
@@ -111,51 +98,30 @@ $lang->bug->unclosed = '未关闭';
|
||||
$lang->bug->longLifeBugs = '久未处理';
|
||||
$lang->bug->postponedBugs = '被延期';
|
||||
$lang->bug->allBugs = '所有';
|
||||
$lang->bug->moduleBugs = '按模块';
|
||||
$lang->bug->byQuery = '搜索';
|
||||
$lang->bug->needConfirm = '需求变动';
|
||||
$lang->bug->allProduct = '所有' . $lang->productCommon;
|
||||
$lang->bug->ditto = '同上';
|
||||
|
||||
/* 页面标签。*/
|
||||
$lang->bug->lblProductAndModule = $lang->productCommon . '模块';
|
||||
$lang->bug->lblProjectAndTask = $lang->projectCommon . '任务';
|
||||
$lang->bug->lblStory = '相关需求';
|
||||
$lang->bug->lblTypeAndSeverity = '类型/严重程度';
|
||||
$lang->bug->lblSystemBrowserAndHardware = '系统/浏览器';
|
||||
$lang->bug->lblAssignedTo = '当前指派';
|
||||
$lang->bug->lblMailto = '抄送给';
|
||||
$lang->bug->lblLastEdited = '最后修改';
|
||||
$lang->bug->lblResolved = '由谁解决';
|
||||
$lang->bug->lblAllFields = '所有字段';
|
||||
$lang->bug->lblCustomFields = '自定义字段';
|
||||
$lang->bug->allUsers = '所有用户';
|
||||
$lang->bug->allBuilds = '所有';
|
||||
|
||||
/* legend列表。*/
|
||||
$lang->bug->legendBasicInfo = '基本信息';
|
||||
$lang->bug->legendMailto = '抄送给';
|
||||
$lang->bug->legendAttatch = '附件';
|
||||
$lang->bug->legendLinkBugs = '相关Bug';
|
||||
$lang->bug->legendPrjStoryTask = $lang->projectCommon . '/需求/任务';
|
||||
$lang->bug->legendCases = '相关用例';
|
||||
$lang->bug->legendSteps = '重现步骤';
|
||||
$lang->bug->legendAction = '操作';
|
||||
$lang->bug->legendHistory = '历史记录';
|
||||
$lang->bug->legendComment = '备注';
|
||||
$lang->bug->legendLife = 'BUG的一生';
|
||||
$lang->bug->legendMisc = '其他相关';
|
||||
|
||||
/* 功能按钮。*/
|
||||
$lang->bug->buttonConfirm = '确认';
|
||||
$lang->bug->buttonCopy = '复制';
|
||||
$lang->bug->buttonAssign = '指派';
|
||||
$lang->bug->buttonEdit = '编辑';
|
||||
$lang->bug->buttonActivate = '激活';
|
||||
$lang->bug->buttonResolve = '解决';
|
||||
$lang->bug->buttonClose = '关闭';
|
||||
$lang->bug->buttonToList = '返回';
|
||||
$lang->bug->buttonCreateTestcase = '转用例';
|
||||
|
||||
/* 交互提示。*/
|
||||
$lang->bug->confirmChangeProduct = "修改{$lang->productCommon}会导致相应的{$lang->projectCommon}、需求和任务发生变化,确定吗?";
|
||||
@@ -354,11 +320,13 @@ $lang->bug->report->bugHistories->graph->xAxisName = '处理步骤';
|
||||
|
||||
/* 操作记录。*/
|
||||
$lang->bug->action = new stdclass();
|
||||
$lang->bug->action->resolved = array('main' => '$date, 由 <strong>$actor</strong> 解决,方案为 <strong>$extra</strong>。', 'extra' => 'resolutionList');
|
||||
$lang->bug->action->resolved = array('main' => '$date, 由 <strong>$actor</strong> 解决,方案为 <strong>$extra</strong> $appendLink。', 'extra' => 'resolutionList');
|
||||
$lang->bug->action->tostory = array('main' => '$date, 由 <strong>$actor</strong> 转为<strong>需求</strong>,编号为 <strong>$extra</strong>。');
|
||||
$lang->bug->action->totask = array('main' => '$date, 由 <strong>$actor</strong> 导入为<strong>任务</strong>,编号为 <strong>$extra</strong>。');
|
||||
$lang->bug->action->linked2plan = array('main' => '$date, 由 <strong>$actor</strong> 关联到计划 <strong>$extra</strong>。');
|
||||
$lang->bug->action->unlinkedfromplan = array('main' => '$date, 由 <strong>$actor</strong> 从计划 <strong>$extra</strong> 移除。');
|
||||
$lang->bug->action->linkrelatedbug = array('main' => '$date, 由 <strong>$actor</strong> 关联相关Bug <strong>$extra</strong>。');
|
||||
$lang->bug->action->unlinkrelatedbug = array('main' => '$date, 由 <strong>$actor</strong> 移除相关Bug <strong>$extra</strong>。');
|
||||
|
||||
$lang->bug->placeholder = new stdclass();
|
||||
$lang->bug->placeholder->chooseBuilds = '选择相关版本...';
|
||||
|
||||
@@ -15,10 +15,8 @@ $lang->bug->id = 'Bug編號';
|
||||
$lang->bug->product = '所屬' . $lang->productCommon;
|
||||
$lang->bug->productplan = '所屬計劃';
|
||||
$lang->bug->module = '所屬模組';
|
||||
$lang->bug->path = '模組路徑';
|
||||
$lang->bug->project = '所屬' . $lang->projectCommon;
|
||||
$lang->bug->story = '相關需求';
|
||||
$lang->bug->storyVersion = '需求版本';
|
||||
$lang->bug->task = '相關任務';
|
||||
$lang->bug->title = 'Bug標題';
|
||||
$lang->bug->severity = '嚴重程度';
|
||||
@@ -26,22 +24,16 @@ $lang->bug->severityAB = '級別';
|
||||
$lang->bug->pri = '優先順序';
|
||||
$lang->bug->type = 'Bug類型';
|
||||
$lang->bug->os = '操作系統';
|
||||
$lang->bug->plan = '所屬計劃';
|
||||
$lang->bug->hardware = '硬件平台';
|
||||
$lang->bug->browser = '瀏覽器';
|
||||
$lang->bug->machine = '機器硬件';
|
||||
$lang->bug->found = '如何發現';
|
||||
$lang->bug->steps = '重現步驟';
|
||||
$lang->bug->status = 'Bug狀態';
|
||||
$lang->bug->statusAB = '狀態';
|
||||
$lang->bug->activatedCount = '激活次數';
|
||||
$lang->bug->activatedCountAB = '激活次數';
|
||||
$lang->bug->confirmed = '是否確認';
|
||||
$lang->bug->toTask = '轉任務';
|
||||
$lang->bug->toStory = '轉需求';
|
||||
$lang->bug->mailto = '抄送給';
|
||||
$lang->bug->openedBy = '由誰創建';
|
||||
$lang->bug->openedByAB = '創建';
|
||||
$lang->bug->openedDate = '創建日期';
|
||||
$lang->bug->openedDateAB = '創建日期';
|
||||
$lang->bug->openedBuild = '影響版本';
|
||||
@@ -58,8 +50,9 @@ $lang->bug->closedBy = '由誰關閉';
|
||||
$lang->bug->closedDate = '關閉日期';
|
||||
$lang->bug->duplicateBug = '重複ID';
|
||||
$lang->bug->lastEditedBy = '最後修改者';
|
||||
$lang->bug->lastEditedDate = '最後修改日期';
|
||||
$lang->bug->linkBug = '相關Bug';
|
||||
$lang->bug->linkBugs = '關聯相關Bug';
|
||||
$lang->bug->unlinkBug = '移除相關Bug';
|
||||
$lang->bug->case = '相關用例';
|
||||
$lang->bug->files = '附件';
|
||||
$lang->bug->keywords = '關鍵詞';
|
||||
@@ -91,15 +84,9 @@ $lang->bug->delete = '刪除';
|
||||
$lang->bug->deleted = '已刪除';
|
||||
$lang->bug->saveTemplate = '保存模板';
|
||||
$lang->bug->deleteTemplate = '刪除模板';
|
||||
$lang->bug->customFields = '自定義欄位';
|
||||
$lang->bug->restoreDefault = '恢復預設';
|
||||
$lang->bug->ajaxGetUserBugs = '介面:我的Bug';
|
||||
$lang->bug->ajaxGetModuleOwner = '介面:獲得模組的預設指派人';
|
||||
$lang->bug->confirmStoryChange = '確認需求變動';
|
||||
|
||||
/* 查詢條件列表。*/
|
||||
$lang->bug->selectProduct = '請選擇' . $lang->productCommon;
|
||||
$lang->bug->byModule = '按模組';
|
||||
$lang->bug->assignToMe = '指派給我';
|
||||
$lang->bug->openedByMe = '由我創建';
|
||||
$lang->bug->resolvedByMe = '由我解決';
|
||||
@@ -111,51 +98,30 @@ $lang->bug->unclosed = '未關閉';
|
||||
$lang->bug->longLifeBugs = '久未處理';
|
||||
$lang->bug->postponedBugs = '被延期';
|
||||
$lang->bug->allBugs = '所有';
|
||||
$lang->bug->moduleBugs = '按模組';
|
||||
$lang->bug->byQuery = '搜索';
|
||||
$lang->bug->needConfirm = '需求變動';
|
||||
$lang->bug->allProduct = '所有' . $lang->productCommon;
|
||||
$lang->bug->ditto = '同上';
|
||||
|
||||
/* 頁面標籤。*/
|
||||
$lang->bug->lblProductAndModule = $lang->productCommon . '模組';
|
||||
$lang->bug->lblProjectAndTask = $lang->projectCommon . '任務';
|
||||
$lang->bug->lblStory = '相關需求';
|
||||
$lang->bug->lblTypeAndSeverity = '類型/嚴重程度';
|
||||
$lang->bug->lblSystemBrowserAndHardware = '系統/瀏覽器';
|
||||
$lang->bug->lblAssignedTo = '當前指派';
|
||||
$lang->bug->lblMailto = '抄送給';
|
||||
$lang->bug->lblLastEdited = '最後修改';
|
||||
$lang->bug->lblResolved = '由誰解決';
|
||||
$lang->bug->lblAllFields = '所有欄位';
|
||||
$lang->bug->lblCustomFields = '自定義欄位';
|
||||
$lang->bug->allUsers = '所有用戶';
|
||||
$lang->bug->allBuilds = '所有';
|
||||
|
||||
/* legend列表。*/
|
||||
$lang->bug->legendBasicInfo = '基本信息';
|
||||
$lang->bug->legendMailto = '抄送給';
|
||||
$lang->bug->legendAttatch = '附件';
|
||||
$lang->bug->legendLinkBugs = '相關Bug';
|
||||
$lang->bug->legendPrjStoryTask = $lang->projectCommon . '/需求/任務';
|
||||
$lang->bug->legendCases = '相關用例';
|
||||
$lang->bug->legendSteps = '重現步驟';
|
||||
$lang->bug->legendAction = '操作';
|
||||
$lang->bug->legendHistory = '歷史記錄';
|
||||
$lang->bug->legendComment = '備註';
|
||||
$lang->bug->legendLife = 'BUG的一生';
|
||||
$lang->bug->legendMisc = '其他相關';
|
||||
|
||||
/* 功能按鈕。*/
|
||||
$lang->bug->buttonConfirm = '確認';
|
||||
$lang->bug->buttonCopy = '複製';
|
||||
$lang->bug->buttonAssign = '指派';
|
||||
$lang->bug->buttonEdit = '編輯';
|
||||
$lang->bug->buttonActivate = '激活';
|
||||
$lang->bug->buttonResolve = '解決';
|
||||
$lang->bug->buttonClose = '關閉';
|
||||
$lang->bug->buttonToList = '返回';
|
||||
$lang->bug->buttonCreateTestcase = '轉用例';
|
||||
|
||||
/* 交互提示。*/
|
||||
$lang->bug->confirmChangeProduct = "修改{$lang->productCommon}會導致相應的{$lang->projectCommon}、需求和任務發生變化,確定嗎?";
|
||||
@@ -354,11 +320,13 @@ $lang->bug->report->bugHistories->graph->xAxisName = '處理步驟';
|
||||
|
||||
/* 操作記錄。*/
|
||||
$lang->bug->action = new stdclass();
|
||||
$lang->bug->action->resolved = array('main' => '$date, 由 <strong>$actor</strong> 解決,方案為 <strong>$extra</strong>。', 'extra' => 'resolutionList');
|
||||
$lang->bug->action->resolved = array('main' => '$date, 由 <strong>$actor</strong> 解決,方案為 <strong>$extra</strong> $appendLink。', 'extra' => 'resolutionList');
|
||||
$lang->bug->action->tostory = array('main' => '$date, 由 <strong>$actor</strong> 轉為<strong>需求</strong>,編號為 <strong>$extra</strong>。');
|
||||
$lang->bug->action->totask = array('main' => '$date, 由 <strong>$actor</strong> 導入為<strong>任務</strong>,編號為 <strong>$extra</strong>。');
|
||||
$lang->bug->action->linked2plan = array('main' => '$date, 由 <strong>$actor</strong> 關聯到計劃 <strong>$extra</strong>。');
|
||||
$lang->bug->action->unlinkedfromplan = array('main' => '$date, 由 <strong>$actor</strong> 從計劃 <strong>$extra</strong> 移除。');
|
||||
$lang->bug->action->linkrelatedbug = array('main' => '$date, 由 <strong>$actor</strong> 關聯相關Bug <strong>$extra</strong>。');
|
||||
$lang->bug->action->unlinkrelatedbug = array('main' => '$date, 由 <strong>$actor</strong> 移除相關Bug <strong>$extra</strong>。');
|
||||
|
||||
$lang->bug->placeholder = new stdclass();
|
||||
$lang->bug->placeholder->chooseBuilds = '選擇相關版本...';
|
||||
|
||||
@@ -140,14 +140,11 @@ class bugModel extends model
|
||||
|
||||
if(!empty($data->uploadImage[$i]))
|
||||
{
|
||||
$fileName = htmlspecialchars_decode($data->uploadImage[$i]);
|
||||
$realPath = $this->session->bugImagesFile . $fileName;
|
||||
$fileName = $data->uploadImage[$i];
|
||||
$file = $this->session->bugImagesFile[$fileName];
|
||||
|
||||
$file = array();
|
||||
$file['extension'] = $this->file->getExtension($fileName);
|
||||
$file['pathname'] = $this->file->setPathName($i, $file['extension']);
|
||||
$file['title'] = str_replace(".{$file['extension']}", '', $fileName);
|
||||
$file['size'] = filesize($realPath);
|
||||
$realPath = $file['realpath'];
|
||||
unset($file['realpath']);
|
||||
if(rename($realPath, $this->file->savePath . $file['pathname']))
|
||||
{
|
||||
if(in_array($file['extension'], $this->config->file->imageExtensions))
|
||||
@@ -194,13 +191,52 @@ class bugModel extends model
|
||||
if(!empty($data->uploadImage) and $this->session->bugImagesFile)
|
||||
{
|
||||
$classFile = $this->app->loadClass('zfile');
|
||||
if(is_dir($this->session->bugImagesFile)) $classFile->removeDir($this->session->bugImagesFile);
|
||||
$file = current($_SESSION['bugImagesFile']);
|
||||
$realPath = dirname($file['realpath']);
|
||||
if(is_dir($realPath)) $classFile->removeDir($realPath);
|
||||
unset($_SESSION['bugImagesFile']);
|
||||
}
|
||||
|
||||
return $actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bugs.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param array $projects
|
||||
* @param int $branch
|
||||
* @param string $browseType
|
||||
* @param int $moduleID
|
||||
* @param int $queryID
|
||||
* @param string $sort
|
||||
* @param object $pager
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getBugs($productID, $projects, $branch, $browseType, $moduleID, $queryID, $sort, $pager)
|
||||
{
|
||||
/* Get bugs by browse type. */
|
||||
if($browseType == 'all') $bugs = $this->getAllBugs($productID, $branch, $projects, $sort, $pager);
|
||||
elseif($browseType == 'bymodule') $bugs = $this->getModuleBugs($productID, $branch, $this->loadModel('tree')->getAllChildId($moduleID), $projects, $sort, $pager);
|
||||
elseif($browseType == 'assigntome') $bugs = $this->getByAssigntome($productID, $branch, $projects, $sort, $pager);
|
||||
elseif($browseType == 'openedbyme') $bugs = $this->getByOpenedbyme($productID, $branch, $projects, $sort, $pager);
|
||||
elseif($browseType == 'resolvedbyme') $bugs = $this->getByResolvedbyme($productID, $branch, $projects, $sort, $pager);
|
||||
elseif($browseType == 'assigntonull') $bugs = $this->getByAssigntonull($productID, $branch, $projects, $sort, $pager);
|
||||
elseif($browseType == 'unconfirmed') $bugs = $this->getUnconfirmed($productID, $branch, $projects, $sort, $pager);
|
||||
elseif($browseType == 'unresolved') $bugs = $this->getByStatus($productID, $branch, $projects, 'unresolved', $sort, $pager);
|
||||
elseif($browseType == 'unclosed') $bugs = $this->getByStatus($productID, $branch, $projects, 'unclosed', $sort, $pager);
|
||||
elseif($browseType == 'toclosed') $bugs = $this->getByStatus($productID, $branch, $projects, 'toclosed', $sort, $pager);
|
||||
elseif($browseType == 'longlifebugs') $bugs = $this->getByLonglifebugs($productID, $branch, $projects, $sort, $pager);
|
||||
elseif($browseType == 'postponedbugs') $bugs = $this->getByPostponedbugs($productID, $branch, $projects, $sort, $pager);
|
||||
elseif($browseType == 'needconfirm') $bugs = $this->getByNeedconfirm($productID, $branch, $projects, $sort, $pager);
|
||||
elseif($browseType == 'bysearch') $bugs = $this->getBySearch($productID, $queryID, $sort, $pager, $branch);
|
||||
|
||||
if($bugs) return $bugs;
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bugs of a module.
|
||||
*
|
||||
@@ -394,6 +430,12 @@ class bugModel extends model
|
||||
public function update($bugID)
|
||||
{
|
||||
$oldBug = $this->getById($bugID);
|
||||
if($oldBug->lastEditedDate != $this->post->lastEditedDate)
|
||||
{
|
||||
dao::$errors[] = $this->lang->error->editedByOther;
|
||||
return false;
|
||||
}
|
||||
|
||||
$now = helper::now();
|
||||
$bug = fixer::input('post')
|
||||
->cleanInt('product,module,severity,project,story,task')
|
||||
@@ -751,6 +793,155 @@ class bugModel extends model
|
||||
$this->dao->update(TABLE_BUG)->data($bug)->autoCheck()->where('id')->eq((int)$bugID)->exec();
|
||||
}
|
||||
|
||||
/**
|
||||
* Link related bugs.
|
||||
*
|
||||
* @param int $bugID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function linkBugs($bugID)
|
||||
{
|
||||
if($this->post->bugs == false) return;
|
||||
|
||||
$bug = $this->getById($bugID);
|
||||
$bugs2Link = $this->post->bugs;
|
||||
|
||||
$bugs = implode(',', $bugs2Link) . ',' . trim($bug->linkBug, ',');
|
||||
$this->dao->update(TABLE_BUG)->set('linkBug')->eq(trim($bugs, ','))->where('id')->eq($bugID)->exec();
|
||||
if(dao::isError()) die(js::error(dao::getError()));
|
||||
$this->loadModel('action')->create('bug', $bugID, 'linkRelatedBug', '', implode(',', $bugs2Link));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bugs to link.
|
||||
*
|
||||
* @param int $bugID
|
||||
* @param string $browseType
|
||||
* @param int $queryID
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getBugs2Link($bugID, $browseType = 'bySearch', $queryID)
|
||||
{
|
||||
if($browseType == 'bySearch')
|
||||
{
|
||||
$bug = $this->getById($bugID);
|
||||
$bugs2Link = $this->getBySearch($bug->product, $queryID, 'id', null);
|
||||
foreach($bugs2Link as $key => $bug2Link)
|
||||
{
|
||||
if($bug2Link->id == $bugID) unset($bugs2Link[$key]);
|
||||
if(in_array($bug2Link->id, explode(',', $bug->linkBug))) unset($bugs2Link[$key]);
|
||||
}
|
||||
return $bugs2Link;
|
||||
}
|
||||
else
|
||||
{
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlink related bug.
|
||||
*
|
||||
* @param int $bugID
|
||||
* @param int $bug2Unlink
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function unlinkBug($bugID, $bug2Unlink = 0)
|
||||
{
|
||||
$bug = $this->getById($bugID);
|
||||
|
||||
$bugs = explode(',', trim($bug->linkBug, ','));
|
||||
foreach($bugs as $key => $bugId)
|
||||
{
|
||||
if($bugId == $bug2Unlink) unset($bugs[$key]);
|
||||
}
|
||||
$bugs = implode(',', $bugs);
|
||||
|
||||
$this->dao->update(TABLE_BUG)->set('linkBug')->eq($bugs)->where('id')->eq($bugID)->exec();
|
||||
if(dao::isError()) die(js::error(dao::getError()));
|
||||
$this->loadModel('action')->create('bug', $bugID, 'unlinkRelatedBug', '', $bug2Unlink);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get linkBugs.
|
||||
*
|
||||
* @param int $bugID
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getLinkBugs($bugID)
|
||||
{
|
||||
$bug = $this->getById($bugID);
|
||||
return $this->dao->select('id, title')->from(TABLE_BUG)->where('id')->in($bug->linkBug)->fetchPairs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build search form.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param array $products
|
||||
* @param int $queryID
|
||||
* @param string $actionURL
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function buildSearchForm($productID, $products, $queryID, $actionURL)
|
||||
{
|
||||
$this->config->bug->search['actionURL'] = $actionURL;
|
||||
$this->config->bug->search['queryID'] = $queryID;
|
||||
$this->config->bug->search['params']['product']['values'] = array($productID => $products[$productID], 'all' => $this->lang->bug->allProduct);
|
||||
$this->config->bug->search['params']['plan']['values'] = $this->loadModel('productplan')->getPairs($productID);
|
||||
$this->config->bug->search['params']['module']['values'] = $this->loadModel('tree')->getOptionMenu($productID, $viewType = 'bug', $startModuleID = 0);
|
||||
$this->config->bug->search['params']['project']['values'] = $this->product->getProjectPairs($productID);
|
||||
$this->config->bug->search['params']['openedBuild']['values'] = $this->loadModel('build')->getProductBuildPairs($productID, 0, $params = '');
|
||||
$this->config->bug->search['params']['resolvedBuild']['values'] = $this->config->bug->search['params']['openedBuild']['values'];
|
||||
if($this->session->currentProductType == 'normal')
|
||||
{
|
||||
unset($this->config->bug->search['fields']['branch']);
|
||||
unset($this->config->bug->search['params']['branch']);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->config->bug->search['fields']['branch'] = $this->lang->product->branch;
|
||||
$this->config->bug->search['params']['branch']['values'] = array('' => '') + $this->loadModel('branch')->getPairs($productID, 'noempty');
|
||||
}
|
||||
|
||||
$this->loadModel('search')->setSearchParams($this->config->bug->search);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the openedBuild and resolvedBuild fields for bugs.
|
||||
*
|
||||
* @param array $bugs
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function processBuildForBugs($bugs)
|
||||
{
|
||||
$productIdList = array();
|
||||
foreach($bugs as $bug) $productIdList[$bug->id] = $bug->product;
|
||||
$builds = $this->loadModel('build')->getProductBuildPairs(array_unique($productIdList), 0, $params = '');
|
||||
|
||||
/* Process the openedBuild and resolvedBuild fields. */
|
||||
foreach($bugs as $key => $bug)
|
||||
{
|
||||
$openBuildIdList = explode(',', $bug->openedBuild);
|
||||
$openedBuild = '';
|
||||
foreach($openBuildIdList as $buildID)
|
||||
{
|
||||
$openedBuild .= isset($builds[$buildID]) ? $builds[$buildID] : $buildID;
|
||||
$openedBuild .= ',';
|
||||
}
|
||||
$bug->openedBuild = rtrim($openedBuild, ',');
|
||||
$bug->resolvedBuild = isset($builds[$bug->resolvedBuild]) ? $builds[$bug->resolvedBuild] : $bug->resolvedBuild;
|
||||
}
|
||||
|
||||
return $bugs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract accounts from some bugs.
|
||||
*
|
||||
@@ -856,7 +1047,8 @@ class bugModel extends model
|
||||
{
|
||||
$bugs = $this->dao->select('*')->from(TABLE_BUG)
|
||||
->where('deleted')->eq(0)
|
||||
->andWhere("(project = '" . (int)$projectID . "' " . (empty($build) ? '' : "AND CONCAT(',', openedBuild, ',') like '%,$build,%'") . ")")
|
||||
->beginIF(empty($build))->andWhere('project')->eq($projectID)->fi()
|
||||
->beginIF($build)->andWhere("CONCAT(',', openedBuild, ',') like '%,$build,%'")->fi()
|
||||
->orderBy($orderBy)->page($pager)->fetchAll();
|
||||
|
||||
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'bug');
|
||||
@@ -1090,7 +1282,7 @@ class bugModel extends model
|
||||
{
|
||||
$datas = $this->dao->select('module as name, count(module) as value')->from(TABLE_BUG)->where($this->reportCondition())->groupBy('module')->orderBy('value DESC')->fetchAll('name');
|
||||
if(!$datas) return array();
|
||||
$modules = $this->dao->select('id, name')->from(TABLE_MODULE)->where('id')->in(array_keys($datas))->fetchPairs();
|
||||
$modules = $this->loadModel('tree')->getModulesName(array_keys($datas));
|
||||
foreach($datas as $moduleID => $data) $data->name = isset($modules[$moduleID]) ? $modules[$moduleID] : '/';
|
||||
return $datas;
|
||||
}
|
||||
@@ -1618,7 +1810,7 @@ class bugModel extends model
|
||||
$bugQuery = str_replace($allProduct, '1', $this->session->bugQuery);
|
||||
$bugQuery = $bugQuery . ' AND `product`' . helper::dbIN($products);
|
||||
}
|
||||
if($branch) $bugQuery .= "AND `branch` in('0','$branch')";
|
||||
if($branch) $bugQuery .= " AND `branch` in('0','$branch')";
|
||||
$bugs = $this->dao->select('*')->from(TABLE_BUG)->where($bugQuery)
|
||||
->andWhere('deleted')->eq(0)
|
||||
->orderBy($orderBy)->page($pager)->fetchAll();
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
<span class='prefix'><?php echo html::icon($lang->icons['bug']);?></span>
|
||||
<strong>
|
||||
<small class='text-muted'><?php echo html::icon($lang->icons['batchCreate']);?></small>
|
||||
<?php if($this->session->currentProductType !== 'normal') echo '<span class="label label-info">' . $branches[$branch] . '</span>';?>
|
||||
<?php echo $lang->bug->common . $lang->colon . $lang->bug->batchCreate;?>
|
||||
<?php if($this->session->currentProductType !== 'normal') echo '<span class="label label-info">' . $branches[$branch] . '</span>';?>
|
||||
</strong>
|
||||
<div class='actions'>
|
||||
<?php if(common::hasPriv('file', 'uploadImages')) echo html::a($this->createLink('file', 'uploadImages', 'module=bug¶ms=' . helper::safe64Encode("productID=$productID&projectID=$projectID&moduleID=$moduleID")), $lang->uploadImages, '', "data-toggle='modal' data-type='iframe' class='btn' data-width='600px'")?>
|
||||
@@ -57,7 +57,7 @@
|
||||
?>
|
||||
<?php $i = 0; ?>
|
||||
<?php if(!empty($titles)):?>
|
||||
<?php foreach($titles as $fileName => $bugTitle):?>
|
||||
<?php foreach($titles as $bugTitle => $fileName):?>
|
||||
<?php
|
||||
$moduleID = $i == 0 ? $moduleID : 'ditto';
|
||||
$projectID = $i == 0 ? $projectID : 'ditto';
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
?>
|
||||
<?php
|
||||
include '../../common/view/header.html.php';
|
||||
include '../../common/view/treeview.html.php';
|
||||
js::set('browseType', $browseType);
|
||||
js::set('moduleID', $moduleID);
|
||||
?>
|
||||
@@ -73,14 +72,13 @@ js::set('moduleID', $moduleID);
|
||||
<?php echo $moduleTree;?>
|
||||
<div class='text-right'>
|
||||
<?php common::printLink('tree', 'browse', "productID=$productID&view=bug", $lang->tree->manage);?>
|
||||
<?php common::printLink('tree', 'fix', "root=$productID&type=bug", $lang->tree->fix, 'hiddenwin');?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class='main'>
|
||||
<form method='post'>
|
||||
<form method='post' id='bugForm'>
|
||||
<table class='table table-condensed table-hover table-striped tablesorter table-fixed' id='bugList'>
|
||||
<?php $vars = "productID=$productID&branch=$branch&browseType=$browseType¶m=$param&orderBy=%s&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}"; ?>
|
||||
<thead>
|
||||
@@ -176,9 +174,7 @@ js::set('moduleID', $moduleID);
|
||||
<td colspan='<?php echo $columns;?>'>
|
||||
<?php if(!empty($bugs)):?>
|
||||
<div class='table-actions clearfix'>
|
||||
<div class='btn-group'>
|
||||
<?php echo html::selectButton();?>
|
||||
</div>
|
||||
<div class='btn-group dropup'>
|
||||
<?php
|
||||
$actionLink = $this->createLink('bug', 'batchEdit', "productID=$productID&branch=$branch");
|
||||
|
||||
@@ -63,7 +63,8 @@ js::set('refresh', $lang->refresh);
|
||||
<span class='input-group-addon'><?php echo $lang->bug->openedBuild?></span>
|
||||
<span id='buildBox'><?php echo html::select('openedBuild[]', $builds, $buildID, "size=4 multiple=multiple class='chosen form-control'");?></span>
|
||||
<span class='input-group-addon' id='buildBoxActions'></span>
|
||||
<span class='input-group-btn'><?php echo html::commonButton($lang->bug->allBuilds, "class='btn btn-default' onclick='loadAllBuilds()'")?></span>
|
||||
<span class='input-group-btn'><?php echo html::commonButton('<i class="icon icon-refresh"></i>', "class='btn btn-default' data-toggle='tooltip' onclick='loadAllBuilds()' title='{$lang->bug->allBuilds}'")?></span>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -72,7 +73,7 @@ js::set('refresh', $lang->refresh);
|
||||
<td>
|
||||
<div class='input-group'>
|
||||
<span id='assignedToBox'><?php echo html::select('assignedTo', $projectMembers, $assignedTo, "class='form-control chosen'");?></span>
|
||||
<span class='input-group-btn'><?php echo html::commonButton($lang->bug->allUsers, "class='btn btn-default' onclick='loadAllUsers()'");?></span>
|
||||
<span class='input-group-btn'><?php echo html::commonButton('<i class="icon icon-refresh"></i>', "class='btn btn-default' onclick='loadAllUsers()' data-toggle='tooltip' title='{$lang->bug->allUsers}'");?></span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -97,14 +98,36 @@ js::set('refresh', $lang->refresh);
|
||||
<tr>
|
||||
<th><?php echo $lang->bug->title;?></th>
|
||||
<td colspan='2'>
|
||||
<div class='row'>
|
||||
<div class='col-sm-8'><?php echo html::input('title', $bugTitle, "class='form-control'");?></div>
|
||||
<div class='col-sm-4'>
|
||||
<div class='row-table'>
|
||||
<div class='col-table w-p100'><?php echo html::input('title', $bugTitle, "class='form-control'");?></div>
|
||||
<div class='col-table'>
|
||||
<div class='input-group'>
|
||||
<span class='input-group-addon fix-border'><?php echo $lang->bug->severity?></span>
|
||||
<?php echo html::select('severity', $lang->bug->severityList, $severity, "class='form-control'");?>
|
||||
<span class='input-group-addon fix-border'><?php echo $lang->bug->pri?></span>
|
||||
<?php echo html::select('pri', $lang->bug->priList, $severity, "class='form-control'");?>
|
||||
<span class='input-group-addon fix-border br-0'><?php echo $lang->bug->severity;?></span>
|
||||
<?php $isAllNumberSeverity = is_numeric(join($lang->bug->severityList));?>
|
||||
<?php if(!$isAllNumberSeverity):?>
|
||||
<?php echo html::select('pri', (array)$lang->bug->severityList, $severity, "class='form-control minw-80px'");?>
|
||||
<?php else: ?>
|
||||
<div class='input-group-btn dropdown-pris' data-prefix='severity'>
|
||||
<button type='button' class='btn dropdown-toggle br-0' data-toggle='dropdown'>
|
||||
<span class='pri-text'></span> <span class='caret'></span>
|
||||
</button>
|
||||
<ul class='dropdown-menu pull-right'></ul>
|
||||
<?php echo html::select('severity', (array)$lang->bug->severityList, $severity, "class='hide'");?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<span class='input-group-addon fix-border br-0'><?php echo $lang->bug->pri;?></span>
|
||||
<?php $isAllNumberPri = is_numeric(join($lang->bug->priList));?>
|
||||
<?php if(!$isAllNumberPri):?>
|
||||
<?php echo html::select('pri', (array)$lang->bug->priList, '', "class='form-control minw-80px'");?>
|
||||
<?php else: ?>
|
||||
<div class='input-group-btn dropdown-pris'>
|
||||
<button type='button' class='btn dropdown-toggle br-0' data-toggle='dropdown'>
|
||||
<span class='pri-text'></span> <span class='caret'></span>
|
||||
</button>
|
||||
<ul class='dropdown-menu pull-right'></ul>
|
||||
<?php echo html::select('pri', $lang->bug->priList, '', "class='hide'");?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -142,17 +165,15 @@ js::set('refresh', $lang->refresh);
|
||||
<tr>
|
||||
<th><?php echo $lang->bug->lblMailto;?></th>
|
||||
<td>
|
||||
<div class='input-group'>
|
||||
<div class='input-group' id='contactListGroup'>
|
||||
<?php
|
||||
echo html::select('mailto[]', $users, str_replace(' ', '', $mailto), "class='form-control chosen' multiple");
|
||||
if($contactLists) echo html::select('', $contactLists, '', "class='form-control chosen' onchange=\"setMailto('mailto', this.value)\"");
|
||||
if($contactLists) echo html::select('', $contactLists, '', "class='form-control' style='min-width: 100px; margin-left: -1px' onchange=\"setMailto('mailto', this.value)\"");
|
||||
if(empty($contactLists))
|
||||
{
|
||||
echo '<span class="input-group-addon">';
|
||||
echo '<a href="' . $this->createLink('company', 'browse') . '" target="_blank">' . $lang->user->contacts->manage . '</a>';
|
||||
echo '</span>';
|
||||
echo '<span class="input-group-addon">';
|
||||
echo '<a href="###" onclick="ajaxGetContacts(this)">' . $lang->refresh . '</a>';
|
||||
echo '<span class="input-group-btn">';
|
||||
echo '<a href="' . $this->createLink('company', 'browse') . '" target="_blank" data-toggle="tooltip" class="btn" title="' . $lang->user->contacts->manage . '"><i class="icon icon-cog"></i></a>';
|
||||
echo '<a href="###" onclick="ajaxGetContacts(this)" data-toggle="tooltip" class="btn" title="' . $lang->refresh . '"><i class="icon icon-refresh"></i></a>';
|
||||
echo '</span>';
|
||||
}
|
||||
?>
|
||||
@@ -160,7 +181,7 @@ js::set('refresh', $lang->refresh);
|
||||
</td>
|
||||
<td>
|
||||
<div class='input-group'>
|
||||
<span class='input-group-addon'><?php echo $lang->bug->keywords;?></span>
|
||||
<span class='input-group-addon' id='keywordsAddonLabel'><?php echo $lang->bug->keywords;?></span>
|
||||
<?php echo html::input('keywords', $keywords, "class='form-control'");?>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
@@ -56,6 +56,7 @@ js::set('oldResolvedBuild' , $bug->resolvedBuild);
|
||||
</fieldset>
|
||||
<div class='actions'>
|
||||
<?php
|
||||
echo html::hidden('lastEditedDate', $bug->lastEditedDate);
|
||||
echo html::submitButton();
|
||||
$browseLink = $app->session->bugList != false ? $app->session->bugList : inlink('browse', "productID=$bug->product");
|
||||
echo html::linkButton($lang->goback, $browseLink);
|
||||
@@ -229,14 +230,32 @@ js::set('oldResolvedBuild' , $bug->resolvedBuild);
|
||||
<fieldset>
|
||||
<legend><?php echo $lang->bug->legendMisc;?></legend>
|
||||
<table class='table table-form'>
|
||||
<tr>
|
||||
<tr class='text-top'>
|
||||
<th class='w-80px'><?php echo $lang->bug->linkBug;?></th>
|
||||
<td><?php echo html::input('linkBug', $bug->linkBug, 'class="form-control"');?></td>
|
||||
<td>
|
||||
<?php echo html::a($this->createLink('bug', 'linkBugs', "bugID=$bug->id", '', true), $lang->bug->linkBugs, '', "data-toggle='modal' data-type='iframe' data-width='95%'");?>
|
||||
<ul class='list-unstyled' id='linkBugBox'>
|
||||
<?php
|
||||
if(isset($bug->linkBugTitles))
|
||||
{
|
||||
foreach($bug->linkBugTitles as $linkBugID => $linkBugTitle)
|
||||
{
|
||||
echo '<li>';
|
||||
echo html::a(inlink('view', "bugID=$linkBugID"), "#$linkBugID " . $linkBugTitle, '_blank');
|
||||
echo html::a("javascript:unlinkBug($bug->id, $linkBugID)", '<i class="icon-remove"></i>', '', "title='{$lang->unlink}' style='float:right'");
|
||||
echo '</li>';
|
||||
}
|
||||
}
|
||||
?>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<?php if($bug->case):?>
|
||||
<tr>
|
||||
<th><?php echo $lang->bug->case;?></th>
|
||||
<th><?php echo $lang->bug->fromCase;?></th>
|
||||
<td><?php echo html::input('case', $bug->case, 'class="form-control"');?></td>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
</table>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
75
module/bug/view/linkbugs.html.php
Normal file
75
module/bug/view/linkbugs.html.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
/**
|
||||
* The link bug view of bug 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 Fei Chen <chenfei@cnezsoft.com>
|
||||
* @package bug
|
||||
* @version $Id: linkbugs.html.php 4129 2016-03-08 09:00:12Z chenfei $
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<div class='container'>
|
||||
<div id='titlebar'>
|
||||
<div class='heading'>
|
||||
<span class='prefix'><?php echo html::icon($lang->icons['bug']);?> <strong><?php echo $bug->id;?></strong></span>
|
||||
<strong><?php echo html::a($this->createLink('bug', 'view', "bugID=$bug->id"), $bug->title, '_blank');?></strong>
|
||||
<small class='text-muted'> <?php echo $lang->bug->linkBugs;?> <?php echo html::icon($lang->icons['link']);?></small>
|
||||
</div>
|
||||
<div id='querybox' class='show'></div>
|
||||
</div>
|
||||
<form method='post' class='form-condensed' target='hiddenwin' id='linkBugsForm'>
|
||||
<table class='table table-condensed table-hover table-striped tablesorter' id='bugList'>
|
||||
<?php if($bugs2Link):?>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class='w-id'><?php echo $lang->idAB;?></th>
|
||||
<th class='w-pri'><?php echo $lang->priAB;?></th>
|
||||
<th><?php echo $lang->bug->product;?></th>
|
||||
<th><?php echo $lang->bug->title;?></th>
|
||||
<th><?php echo $lang->bug->statusAB;?></th>
|
||||
<th class='w-user'><?php echo $lang->openedByAB;?></th>
|
||||
<th class='w-user'><?php echo $lang->assignedToAB;?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php $bugCount = 0;?>
|
||||
<?php foreach($bugs2Link as $bug2Link):?>
|
||||
<?php $bugLink = $this->createLink('bug', 'view', "bugID=$bug2Link->id");?>
|
||||
<tr class='text-center'>
|
||||
<td class='text-left'>
|
||||
<input type='checkbox' name='bugs[]' value='<?php echo $bug2Link->id;?>'/>
|
||||
<?php echo html::a($bugLink, sprintf('%03d', $bug2Link->id));?>
|
||||
</td>
|
||||
<td><span class='<?php echo 'pri' . zget($lang->bug->priList, $bug2Link->pri, $bug2Link->pri)?>'><?php echo zget($lang->bug->priList, $bug2Link->pri, $bug2Link->pri);?></span></td>
|
||||
<td><?php echo html::a($this->createLink('product', 'browse', "productID=$bug2Link->product&branch=$bug2Link->branch"), $products[$bug2Link->product], '_blank');?></td>
|
||||
<td class='text-left nobr' title="<?php echo $bug2Link->title?>"><?php echo html::a($bugLink, $bug2Link->title);?></td>
|
||||
<td><?php echo $lang->bug->statusList[$bug->status];?></td>
|
||||
<td><?php echo $users[$bug2Link->openedBy];?></td>
|
||||
<td><?php echo $users[$bug2Link->assignedTo];?></td>
|
||||
</tr>
|
||||
<?php $bugCount ++;?>
|
||||
<?php endforeach;?>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan='7' class='text-left'>
|
||||
<div class='table-actions clearfix'>
|
||||
<?php if($bugCount) echo html::selectButton() . html::submitButton();?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='hidden'><?php echo html::input('bug', $bug->id);?></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
<?php endif;?>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
<script type='text/javascript'>
|
||||
$(function(){ajaxGetSearchForm();});
|
||||
</script>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
@@ -31,7 +31,7 @@
|
||||
<form method='post'>
|
||||
<?php echo html::checkBox('charts', $lang->bug->report->charts, $checkedCharts, '', 'block');?>
|
||||
<?php echo html::selectAll('', "button", false, 'btn-sm')?>
|
||||
<?php echo html::submitButton($lang->bug->report->create, '', "btn-primary btn-sm");?>
|
||||
<?php echo html::submitButton($lang->bug->report->create, '', "btn btn-primary btn-sm");?>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -10,26 +10,23 @@
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
?>
|
||||
<?php
|
||||
$onlybody = isonlybody() ? true : false;
|
||||
if($onlybody) $_GET['onlybody'] = 'no';
|
||||
?>
|
||||
<table width='98%' align='center'>
|
||||
<tr class='header'>
|
||||
<td>
|
||||
BUG #<?php echo $bug->id . "=>{$users[$bug->assignedTo]} " . html::a(common::getSysURL() . $this->createLink('bug', 'view', "bugID=$bug->id"), $bug->title);?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<fieldset>
|
||||
<legend><?php echo $lang->bug->legendSteps;?></legend>
|
||||
<div class='content'><?php echo $bug->steps;?></div>
|
||||
<?php $mailTitle = 'BUG #' . $bug->id . ' ' . $bug->title;?>
|
||||
<?php include '../../common/view/mail.header.html.php';?>
|
||||
<tr>
|
||||
<td>
|
||||
<table cellpadding='0' cellspacing='0' width='600' style='border: none; border-collapse: collapse;'>
|
||||
<tr>
|
||||
<td style='padding: 10px; background-color: #F8FAFE; border: none; font-size: 14px; font-weight: 500; border-bottom: 1px solid #e5e5e5;'><?php echo html::a(common::getSysURL() . $this->createLink('bug', 'view', "bugID=$bug->id"), $mailTitle, '', "style='color: #333'");?></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style='padding: 10px; border: none;'>
|
||||
<fieldset style='border: 1px solid #e5e5e5'>
|
||||
<legend style='color: #114f8e'><?php echo $lang->bug->legendSteps;?></legend>
|
||||
<div style='padding:5px;'><?php echo $bug->steps;?></div>
|
||||
</fieldset>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><?php include '../../common/view/mail.html.php';?></td>
|
||||
</tr>
|
||||
</table>
|
||||
<?php if($onlybody) $_GET['onlybody'] = 'yes';?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php include '../../common/view/mail.footer.html.php';?>
|
||||
|
||||
@@ -154,11 +154,11 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->bug->severity;?></th>
|
||||
<td><strong><?php echo zget($lang->bug->severityList, $bug->severity, $bug->severity);?></strong></td>
|
||||
<td><span class='<?php echo 'severity' . zget($lang->bug->severityList, $bug->severity);?>'><?php echo zget($lang->bug->severityList, $bug->severity)?></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->bug->pri;?></th>
|
||||
<td><strong><?php echo $lang->bug->priList[$bug->pri];?></strong></td>
|
||||
<td><span class='<?php echo 'pri' . zget($lang->bug->priList, $bug->pri);?>'><?php echo zget($lang->bug->priList, $bug->pri)?></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->bug->status;?></th>
|
||||
@@ -279,23 +279,8 @@
|
||||
</div>
|
||||
<div class='tab-pane' id='legendMisc'>
|
||||
<table class='table table-data table-condensed table-borderless table-fixed'>
|
||||
<tr>
|
||||
<th class='w-60px'><?php echo $lang->bug->fromCase;?></th>
|
||||
<td><?php if($bug->case) echo html::a($this->createLink('testcase', 'view', "caseID=$bug->case"), $bug->caseTitle);?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->bug->toCase;?></th>
|
||||
<td>
|
||||
<?php
|
||||
foreach($bug->toCases as $caseID => $case)
|
||||
{
|
||||
echo '<p style="margin-bottom:0;">' . html::a($this->createLink('testcase', 'view', "caseID=$caseID"), $case) . '</p>';
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->bug->linkBug;?></th>
|
||||
<tr class='text-top'>
|
||||
<th class='w-60px'><?php echo $lang->bug->linkBug;?></th>
|
||||
<td>
|
||||
<?php
|
||||
if(isset($bug->linkBugTitles))
|
||||
@@ -308,18 +293,37 @@
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php if($bug->case):?>
|
||||
<tr>
|
||||
<th><?php echo $lang->bug->case;?></th>
|
||||
<td><?php if(isset($bug->caseTitle)) echo html::a($this->createLink('testcase', 'view', "caseID=$bug->case"), "#$bug->case $bug->caseTitle", '_blank');?></td>
|
||||
<th class='w-60px'><?php echo $lang->bug->fromCase;?></th>
|
||||
<td><?php echo html::a($this->createLink('testcase', 'view', "caseID=$bug->case"), "#$bug->case $bug->caseTitle", '_blank');?></td>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
<?php if($bug->toCases):?>
|
||||
<tr>
|
||||
<th><?php echo $lang->bug->toCase;?></th>
|
||||
<td>
|
||||
<?php
|
||||
foreach($bug->toCases as $caseID => $case)
|
||||
{
|
||||
echo '<p style="margin-bottom:0;">' . html::a($this->createLink('testcase', 'view', "caseID=$caseID"), $case) . '</p>';
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
<?php if($bug->toStory != 0):?>
|
||||
<tr>
|
||||
<th><?php echo $lang->bug->toStory;?></th>
|
||||
<td><?php if($bug->toStory != 0) echo html::a($this->createLink('story', 'view', "storyID=$bug->toStory"), "#$bug->toStory $bug->toStoryTitle", '_blank');?></td>
|
||||
<td><?php echo html::a($this->createLink('story', 'view', "storyID=$bug->toStory"), "#$bug->toStory $bug->toStoryTitle", '_blank');?></td>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
<?php if($bug->toTask != 0):?>
|
||||
<tr>
|
||||
<th><?php echo $lang->bug->toTask;?></th>
|
||||
<td><?php if($bug->toTask != 0) echo html::a($this->createLink('task', 'view', "taskID=$bug->toTask"), "#$bug->toTask $bug->toTaskTitle", '_blank');?></td>
|
||||
<td><?php echo html::a($this->createLink('task', 'view', "taskID=$bug->toTask"), "#$bug->toTask $bug->toTaskTitle", '_blank');?></td>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -213,6 +213,7 @@ class build extends control
|
||||
*/
|
||||
public function ajaxGetProductBuilds($productID, $varName, $build = '', $branch = 0, $index = 0, $type = 'normal')
|
||||
{
|
||||
$branch = $branch ? "0,$branch" : $branch;
|
||||
if($varName == 'openedBuild' )
|
||||
{
|
||||
$params = ($type == 'all') ? 'noempty' : 'noempty, noterminate, nodone';
|
||||
@@ -241,7 +242,8 @@ class build extends control
|
||||
*/
|
||||
public function ajaxGetProjectBuilds($projectID, $productID, $varName, $build = '', $branch = 0, $index = 0, $needCreate = false, $type = 'normal')
|
||||
{
|
||||
if($varName == 'openedBuild')
|
||||
$branch = $branch ? "0,$branch" : $branch;
|
||||
if($varName == 'openedBuild')
|
||||
{
|
||||
$params = ($type == 'all') ? 'noempty' : 'noempty, noterminate, nodone';
|
||||
$builds = $this->build->getProjectBuildPairs($projectID, $productID, $branch, $params);
|
||||
@@ -273,7 +275,9 @@ class build extends control
|
||||
die(js::locate(inlink('view', "buildID=$buildID&type=story"), 'parent'));
|
||||
}
|
||||
|
||||
$build = $this->build->getById($buildID);
|
||||
$this->session->set('storyList', inlink('view', "buildID=$buildID&type=story&link=true¶m=" . helper::safe64Encode("&browseType=$browseType&queryID=$param")));
|
||||
$build = $this->build->getById($buildID);
|
||||
$product = $this->loadModel('product')->getById($build->product);
|
||||
$this->loadModel('project')->setMenu($this->project->getPairs(), $build->project);
|
||||
$this->loadModel('story');
|
||||
$this->loadModel('tree');
|
||||
@@ -289,8 +293,18 @@ class build extends control
|
||||
$this->config->product->search['params']['plan']['values'] = $this->loadModel('productplan')->getForProducts(array($build->product => $build->product));
|
||||
$this->config->product->search['params']['module']['values'] = $this->tree->getOptionMenu($build->product, $viewType = 'story', $startModuleID = 0);
|
||||
$this->config->product->search['params']['status'] = array('operator' => '=', 'control' => 'select', 'values' => $this->lang->story->statusList);
|
||||
unset($this->config->product->search['fields']['branch']);
|
||||
unset($this->config->product->search['params']['branch']);
|
||||
if($product->type == 'normal')
|
||||
{
|
||||
unset($this->config->product->search['fields']['branch']);
|
||||
unset($this->config->product->search['params']['branch']);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->config->product->search['fields']['branch'] = sprintf($this->lang->product->branch, $this->lang->product->branchName[$product->type]);
|
||||
$branches = array('' => '') + $this->loadModel('branch')->getPairs($build->product, 'noempty');
|
||||
if($build->branch) $branches = array('' => '', $build->branch => $branches[$build->branch]);
|
||||
$this->config->product->search['params']['branch']['values'] = $branches;
|
||||
}
|
||||
$this->loadModel('search')->setSearchParams($this->config->product->search);
|
||||
|
||||
if($browseType == 'bySearch')
|
||||
@@ -371,8 +385,10 @@ class build extends control
|
||||
die(js::locate(inlink('view', "buildID=$buildID&type=bug"), 'parent'));
|
||||
}
|
||||
|
||||
$this->session->set('bugList', inlink('view', "buildID=$buildID&type=bug&link=true¶m=" . helper::safe64Encode("&browseType=$browseType&queryID=$param")));
|
||||
/* Set menu. */
|
||||
$build = $this->build->getByID($buildID);
|
||||
$build = $this->build->getByID($buildID);
|
||||
$product = $this->loadModel('product')->getByID($build->product);
|
||||
$this->loadModel('project')->setMenu($this->project->getPairs(), $build->project);
|
||||
|
||||
$queryID = ($browseType == 'bysearch') ? (int)$param : 0;
|
||||
@@ -387,8 +403,21 @@ class build extends control
|
||||
$this->config->bug->search['params']['project']['values'] = $this->loadModel('product')->getProjectPairs($build->product);
|
||||
$this->config->bug->search['params']['openedBuild']['values'] = $this->build->getProductBuildPairs($build->product, $branch = 0, $params = '');
|
||||
$this->config->bug->search['params']['resolvedBuild']['values'] = $this->config->bug->search['params']['openedBuild']['values'];
|
||||
unset($this->config->bug->search['fields']['branch']);
|
||||
unset($this->config->bug->search['params']['branch']);
|
||||
|
||||
unset($this->config->bug->search['fields']['product']);
|
||||
unset($this->config->bug->search['params']['product']);
|
||||
if($product->type == 'normal')
|
||||
{
|
||||
unset($this->config->bug->search['fields']['branch']);
|
||||
unset($this->config->bug->search['params']['branch']);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->config->bug->search['fields']['branch'] = sprintf($this->lang->product->branch, $this->lang->product->branchName[$product->type]);
|
||||
$branches = array('' => '') + $this->loadModel('branch')->getPairs($build->product, 'noempty');
|
||||
if($build->branch) $branches = array('' => '', $build->branch => $branches[$build->branch]);
|
||||
$this->config->bug->search['params']['branch']['values'] = $branches;
|
||||
}
|
||||
$this->loadModel('search')->setSearchParams($this->config->bug->search);
|
||||
|
||||
if($browseType == 'bySearch')
|
||||
|
||||
@@ -3,3 +3,4 @@
|
||||
.red {color:red}
|
||||
.green {color:green}
|
||||
input[type=checkbox].ml-10px{margin-left:10px;}
|
||||
.pdl-8px{padding-left:8px;}
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
.tabs{position:relative;}
|
||||
.tabs .tab-content{padding:0px;border:0px;}
|
||||
.tabs .tab-content .tab-pane .action{position: absolute; right: 0px; top: 0px;}
|
||||
.tabs .tab-content .tab-pane #querybox{margin:0px; border-right:1px solid #ddd; border-left:1px solid #ddd;}
|
||||
.tabs .tab-content .tab-pane #querybox form{padding-left:0px;}
|
||||
.tabs {position:relative;}
|
||||
|
||||
.tabs .nav-tabs{border-bottom:none;}
|
||||
.tabs .nav-tabs>li{margin-bottom:0px;}
|
||||
|
||||
.tabs .tab-content {padding: 0; border: none;}
|
||||
.tabs .tab-content .tab-pane .action {position: absolute; right: 0; top: -1px;}
|
||||
.tabs .tab-content .tab-pane #querybox{margin:0px; border-left:1px solid #ddd; border-right:1px solid #ddd;}
|
||||
.tabs .tab-content .tab-pane #querybox form {padding-left:0px;}
|
||||
|
||||
.table-actions {padding-left: 8px;}
|
||||
|
||||
@@ -8,10 +8,21 @@ function showLink(buildID, type, param)
|
||||
$('#' + type + 'List').hide();
|
||||
|
||||
var formID = type == 'story' ? '#unlinkedStoriesForm' : '#unlinkedBugsForm';
|
||||
fixTfootAction(formID);
|
||||
setTimeout(function(){fixedTfootAction(formID)}, 100);
|
||||
autoCheck();
|
||||
});
|
||||
}
|
||||
$(function()
|
||||
{
|
||||
if(link == 'true') showLink(buildID, type, param);
|
||||
fixedTfootAction($('#' + type + 'List').closest('form'));
|
||||
$('.nav.nav-tabs a[data-toggle="tab"]').on('shown.zui.tab', function(e)
|
||||
{
|
||||
var href = $(e.target).attr('href');
|
||||
var tabPane = $(href + '.tab-pane');
|
||||
if(tabPane.size() == 0) return;
|
||||
var formID = tabPane.find('.linkBox').find('form:last');
|
||||
if(formID.size() == 0) formID = tabPane.find('form:last');
|
||||
setTimeout(function(){fixedTfootAction(formID)}, 100);
|
||||
});
|
||||
})
|
||||
|
||||
@@ -17,8 +17,6 @@ $lang->build->linkBug = "Link Bug";
|
||||
$lang->build->delete = "Delete";
|
||||
$lang->build->deleted = "Deleted";
|
||||
$lang->build->view = "Info";
|
||||
$lang->build->ajaxGetProductBuilds = "API:{$lang->productCommon} builds";
|
||||
$lang->build->ajaxGetProjectBuilds = "API:{$lang->projectCommon} builds";
|
||||
$lang->build->batchUnlink = 'Batch unlink';
|
||||
$lang->build->batchUnlinkStory = 'Batch unlink story';
|
||||
$lang->build->batchUnlinkBug = 'Batch unlink bug';
|
||||
@@ -31,7 +29,6 @@ $lang->build->basicInfo = 'Basic Info';
|
||||
|
||||
$lang->build->id = 'ID';
|
||||
$lang->build->product = $lang->productCommon;
|
||||
$lang->build->project = $lang->projectCommon;
|
||||
$lang->build->name = 'Name';
|
||||
$lang->build->date = 'Build date';
|
||||
$lang->build->builder = 'Builder';
|
||||
@@ -40,10 +37,7 @@ $lang->build->filePath = 'Package file path';
|
||||
$lang->build->desc = 'Desc';
|
||||
$lang->build->files = 'Upload package';
|
||||
$lang->build->last = 'Last build';
|
||||
$lang->build->linkStoriesAndBugs = 'stories and bugs';
|
||||
$lang->build->linkStories = 'Stories';
|
||||
$lang->build->unlinkStory = 'Remove story';
|
||||
$lang->build->linkBugs = 'Bugs';
|
||||
$lang->build->unlinkBug = 'Remove bug';
|
||||
$lang->build->stories = 'Finished stories';
|
||||
$lang->build->bugs = 'Resolved bugs';
|
||||
|
||||
@@ -17,8 +17,6 @@ $lang->build->linkBug = "关联Bug";
|
||||
$lang->build->delete = "删除版本";
|
||||
$lang->build->deleted = "已删除";
|
||||
$lang->build->view = "版本详情";
|
||||
$lang->build->ajaxGetProductBuilds = "接口:{$lang->productCommon}版本列表";
|
||||
$lang->build->ajaxGetProjectBuilds = "接口:{$lang->projectCommon}版本列表";
|
||||
$lang->build->batchUnlink = '批量移除';
|
||||
$lang->build->batchUnlinkStory = '批量移除需求';
|
||||
$lang->build->batchUnlinkBug = '批量移除Bug';
|
||||
@@ -31,7 +29,6 @@ $lang->build->basicInfo = '基本信息';
|
||||
|
||||
$lang->build->id = 'ID';
|
||||
$lang->build->product = $lang->productCommon;
|
||||
$lang->build->project = $lang->projectCommon;
|
||||
$lang->build->name = '名称编号';
|
||||
$lang->build->date = '打包日期';
|
||||
$lang->build->builder = '构建者';
|
||||
@@ -40,10 +37,7 @@ $lang->build->filePath = '下载地址';
|
||||
$lang->build->desc = '描述';
|
||||
$lang->build->files = '上传发行包';
|
||||
$lang->build->last = '上个版本';
|
||||
$lang->build->linkStoriesAndBugs = '关联需求和Bug';
|
||||
$lang->build->linkStories = '相关需求';
|
||||
$lang->build->unlinkStory = '移除需求';
|
||||
$lang->build->linkBugs = '相关Bug';
|
||||
$lang->build->unlinkBug = '移除Bug';
|
||||
$lang->build->stories = '完成的需求';
|
||||
$lang->build->bugs = '解决的Bug';
|
||||
|
||||
@@ -17,8 +17,6 @@ $lang->build->linkBug = "關聯Bug";
|
||||
$lang->build->delete = "刪除版本";
|
||||
$lang->build->deleted = "已刪除";
|
||||
$lang->build->view = "版本詳情";
|
||||
$lang->build->ajaxGetProductBuilds = "介面:{$lang->productCommon}版本列表";
|
||||
$lang->build->ajaxGetProjectBuilds = "介面:{$lang->projectCommon}版本列表";
|
||||
$lang->build->batchUnlink = '批量移除';
|
||||
$lang->build->batchUnlinkStory = '批量移除需求';
|
||||
$lang->build->batchUnlinkBug = '批量移除Bug';
|
||||
@@ -31,7 +29,6 @@ $lang->build->basicInfo = '基本信息';
|
||||
|
||||
$lang->build->id = 'ID';
|
||||
$lang->build->product = $lang->productCommon;
|
||||
$lang->build->project = $lang->projectCommon;
|
||||
$lang->build->name = '名稱編號';
|
||||
$lang->build->date = '打包日期';
|
||||
$lang->build->builder = '構建者';
|
||||
@@ -40,10 +37,7 @@ $lang->build->filePath = '下載地址';
|
||||
$lang->build->desc = '描述';
|
||||
$lang->build->files = '上傳發行包';
|
||||
$lang->build->last = '上個版本';
|
||||
$lang->build->linkStoriesAndBugs = '關聯需求和Bug';
|
||||
$lang->build->linkStories = '相關需求';
|
||||
$lang->build->unlinkStory = '移除需求';
|
||||
$lang->build->linkBugs = '相關Bug';
|
||||
$lang->build->unlinkBug = '移除Bug';
|
||||
$lang->build->stories = '完成的需求';
|
||||
$lang->build->bugs = '解決的Bug';
|
||||
|
||||
@@ -71,21 +71,24 @@ class buildModel extends model
|
||||
if(strpos($params, 'noempty') === false) $sysBuilds = array('' => '');
|
||||
if(strpos($params, 'notrunk') === false) $sysBuilds = $sysBuilds + array('trunk' => 'Trunk');
|
||||
|
||||
$projectBuilds = $this->dao->select('t1.id, t1.name, t4.name as branchName')->from(TABLE_BUILD)->alias('t1')
|
||||
$projectBuilds = $this->dao->select('t1.id, t1.name, t1.project, t2.status as projectStatus, t3.id as releaseID, t3.status as releaseStatus, t4.name as branchName')->from(TABLE_BUILD)->alias('t1')
|
||||
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id')
|
||||
->leftJoin(TABLE_RELEASE)->alias('t3')->on('t1.id = t3.build')
|
||||
->leftJoin(TABLE_BRANCH)->alias('t4')->on('t1.branch = t4.id')
|
||||
->where('t1.project')->eq((int)$projectID)
|
||||
->beginIF($productID)->andWhere('t1.product')->eq((int)$productID)->fi()
|
||||
->beginIF($branch)->andWhere('t1.branch')->eq($branch)->fi()
|
||||
->beginIF(strpos($params, 'nodone') !== false)->andWhere('t2.status')->ne('done')->fi()
|
||||
->beginIF(strpos($params, 'noterminate') !== false)->andWhere('t3.status')->ne('terminate')->fi()
|
||||
->beginIF($branch)->andWhere('t1.branch')->in($branch)->fi()
|
||||
->andWhere('t1.deleted')->eq(0)
|
||||
->orderBy('t1.date desc, t1.id desc')->fetchAll('id');
|
||||
|
||||
/* Set builds and filter terminate releases. */
|
||||
$builds = array();
|
||||
foreach($projectBuilds as $buildID => $build) $builds[$buildID] = $build->name;
|
||||
foreach($projectBuilds as $buildID => $build)
|
||||
{
|
||||
if(empty($build->releaseID) and (strpos($params, 'nodone') !== false) and ($build->projectStatus === 'done')) continue;
|
||||
if((strpos($params, 'noterminate') !== false) and ($build->releaseStatus === 'terminate')) continue;
|
||||
$builds[$buildID] = $build->name;
|
||||
}
|
||||
if(!$builds) return $sysBuilds;
|
||||
|
||||
/* if the build has been released, replace build name with release name. */
|
||||
@@ -113,20 +116,24 @@ class buildModel extends model
|
||||
if(strpos($params, 'noempty') === false) $sysBuilds = array('' => '');
|
||||
if(strpos($params, 'notrunk') === false) $sysBuilds = $sysBuilds + array('trunk' => 'Trunk');
|
||||
|
||||
$productBuilds = $this->dao->select('t1.id, t1.name, t1.project, t4.name as branchName')->from(TABLE_BUILD)->alias('t1')
|
||||
$productBuilds = $this->dao->select('t1.id, t1.name, t1.project, t2.status as projectStatus, t3.id as releaseID, t3.status as releaseStatus, t4.name as branchName')->from(TABLE_BUILD)->alias('t1')
|
||||
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id')
|
||||
->leftJoin(TABLE_RELEASE)->alias('t3')->on('t1.id = t3.build')
|
||||
->leftJoin(TABLE_BRANCH)->alias('t4')->on('t1.branch = t4.id')
|
||||
->where('t1.product')->in($products)
|
||||
->beginIF($branch)->andWhere('t1.branch')->eq($branch)->fi()
|
||||
->beginIF(strpos($params, 'nodone') !== false)->andWhere('t2.status')->ne('none')->fi()
|
||||
->beginIF(strpos($params, 'noterminate') !== false)->andWhere('t3.status')->ne('terminate')->fi()
|
||||
->beginIF($branch)->andWhere('t1.branch')->in($branch)->fi()
|
||||
->andWhere('t1.deleted')->eq(0)
|
||||
->orderBy('t1.date desc, t1.id desc')->fetchAll('id');
|
||||
|
||||
/* Set builds and filter done projects and terminate releases. */
|
||||
$builds = array();
|
||||
foreach($productBuilds as $key => $build) $builds[$key] = ((strpos($params, 'withbranch') !== false and $build->branchName) ? $build->branchName . '/' : '') . $build->name;
|
||||
foreach($productBuilds as $key => $build)
|
||||
{
|
||||
if(empty($build->releaseID) and (strpos($params, 'nodone') !== false) and ($build->projectStatus === 'done')) continue;
|
||||
if((strpos($params, 'noterminate') !== false) and ($build->releaseStatus === 'terminate')) continue;
|
||||
$builds[$key] = ((strpos($params, 'withbranch') !== false and $build->branchName) ? $build->branchName . '/' : '') . $build->name;
|
||||
}
|
||||
|
||||
if(!$builds) return $sysBuilds;
|
||||
|
||||
/* if the build has been released and replace is true, replace build name with release name. */
|
||||
@@ -174,13 +181,18 @@ class buildModel extends model
|
||||
|
||||
$build = fixer::input('post')
|
||||
->setDefault('product', 0)
|
||||
->setDefault('branch', 0)
|
||||
->add('project', (int)$projectID)
|
||||
->stripTags($this->config->build->editor->create['id'], $this->config->allowedTags)
|
||||
->remove('resolvedBy,allchecker,files,labels')
|
||||
->get();
|
||||
|
||||
$build = $this->loadModel('file')->processEditor($build, $this->config->build->editor->create['id']);
|
||||
$this->dao->insert(TABLE_BUILD)->data($build)->autoCheck()->batchCheck($this->config->build->create->requiredFields, 'notempty')->check('name', 'unique', "product = {$build->product} AND deleted = '0'")->exec();
|
||||
$this->dao->insert(TABLE_BUILD)->data($build)
|
||||
->autoCheck()
|
||||
->batchCheck($this->config->build->create->requiredFields, 'notempty')
|
||||
->check('name', 'unique', "product = {$build->product} AND branch = {$build->branch} AND deleted = '0'")
|
||||
->exec();
|
||||
if(!dao::isError())
|
||||
{
|
||||
$buildID = $this->dao->lastInsertID();
|
||||
@@ -199,7 +211,7 @@ class buildModel extends model
|
||||
public function update($buildID)
|
||||
{
|
||||
$oldBuild = $this->getByID($buildID);
|
||||
$build = fixer::input('post')->stripTags($this->config->build->editor->edit['id'], $this->config->allowedTags)
|
||||
$build = fixer::input('post')->setDefault('branch', $oldBuild->branch)->stripTags($this->config->build->editor->edit['id'], $this->config->allowedTags)
|
||||
->remove('allchecker,resolvedBy,files,labels')
|
||||
->get();
|
||||
|
||||
@@ -208,8 +220,9 @@ class buildModel extends model
|
||||
->autoCheck()
|
||||
->batchCheck($this->config->build->edit->requiredFields, 'notempty')
|
||||
->where('id')->eq((int)$buildID)
|
||||
->check('name', 'unique', "id != $buildID AND product = {$build->product} AND deleted = '0'")
|
||||
->check('name', 'unique', "id != $buildID AND product = {$build->product} AND branch = {$build->branch} AND deleted = '0'")
|
||||
->exec();
|
||||
if(isset($build->branch) and $oldBuild->branch != $build->branch) $this->dao->update(TABLE_RELEASE)->set('branch')->eq($build->branch)->where('build')->eq($buildID)->exec();
|
||||
if(!dao::isError()) return common::createChanges($oldBuild, $build);
|
||||
}
|
||||
|
||||
|
||||
@@ -47,8 +47,9 @@
|
||||
<?php if(count($allBugs))
|
||||
{
|
||||
echo "<div class='table-actions clearfix'>";
|
||||
echo "<div class='btn-group'>" . html::selectAll('unlinkedBugsForm') . html::selectReverse('unlinkedBugsForm') . '</div>';
|
||||
echo html::submitButton($lang->build->linkBug) . html::a(inlink('view', "buildID={$build->id}&type=bug"), $lang->goback, '', "class='btn'") . '</div>';
|
||||
echo html::selectButton() . html::submitButton($lang->build->linkBug);
|
||||
echo html::a(inlink('view', "buildID={$build->id}&type=bug"), $lang->goback, '', "class='btn'");
|
||||
echo '</div>';
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
|
||||
@@ -48,11 +48,13 @@
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan='8' class='text-left'>
|
||||
<?php if(count($allStories))
|
||||
<?php
|
||||
if(count($allStories))
|
||||
{
|
||||
echo "<div class='table-actions clearfix'>";
|
||||
echo "<div class='btn-group'>" . html::selectAll('unlinkedStoriesForm') . html::selectReverse('unlinkedStoriesForm') . '</div>';
|
||||
echo html::submitButton($lang->story->linkStory) . html::a(inlink('view', "buildID={$build->id}&type=story"), $lang->goback, '', "class='btn'") . '</div>';
|
||||
echo html::selectButton() . html::submitButton($lang->story->linkStory);
|
||||
echo html::a(inlink('view', "buildID={$build->id}&type=story"), $lang->goback, '', "class='btn'");
|
||||
echo '</div>';
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
<td class='text-left nobr'><?php echo html::a($storyLink,$story->title, '', "class='preview'");?></td>
|
||||
<td><?php echo $users[$story->openedBy];?></td>
|
||||
<td><?php echo $story->estimate;?></td>
|
||||
<td class='<?php echo $story->status;?>'><?php echo $lang->story->statusList[$story->status];?></td>
|
||||
<td class='story-<?php echo $story->status;?>'><?php echo $lang->story->statusList[$story->status];?></td>
|
||||
<td><?php echo $lang->story->stageList[$story->stage];?></td>
|
||||
<td>
|
||||
<?php
|
||||
@@ -100,7 +100,7 @@
|
||||
<tr>
|
||||
<td colspan='8'>
|
||||
<div class='table-actions clearfix'>
|
||||
<?php if($countStories and $canBatchUnlink) echo "<div class='table-actions clearfix'><div class='btn-group'>" . html::selectAll('linkedStoriesForm') . html::selectReverse('linkedStoriesForm') . '</div>' . html::submitButton($lang->build->batchUnlink) . '</div>';?>
|
||||
<?php if($countStories and $canBatchUnlink) echo html::selectButton() . html::submitButton($lang->build->batchUnlink);?>
|
||||
<div class='text'><?php echo sprintf($lang->build->finishStories, $countStories);?></div>
|
||||
</div>
|
||||
</td>
|
||||
@@ -158,7 +158,7 @@
|
||||
<tr>
|
||||
<td colspan='8'>
|
||||
<div class='table-actions clearfix'>
|
||||
<?php if($countBugs and $canBatchUnlink) echo "<div class='table-actions clearfix'><div class='btn-group'>" . html::selectAll('linkedBugsForm') . html::selectReverse('linkedBugsForm') . '</div>' . html::submitButton($lang->build->batchUnlink) . '</div>';?>
|
||||
<?php if($countBugs and $canBatchUnlink) echo html::selectButton() . html::submitButton($lang->build->batchUnlink);?>
|
||||
<div class='text'><?php echo sprintf($lang->build->resolvedBugs, $countBugs);?></div>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
@@ -1,462 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* The control file of common 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 common
|
||||
* @version $Id: control.php 5036 2013-07-06 05:26:44Z wyd621@gmail.com $
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class common extends control
|
||||
{
|
||||
/**
|
||||
* The construc method, to do some auto things.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->common->startSession();
|
||||
$this->common->sendHeader();
|
||||
$this->common->setCompany();
|
||||
$this->common->setUser();
|
||||
$this->common->loadConfigFromDB();
|
||||
if(isset($this->config->custom->productproject))
|
||||
{
|
||||
$productCommon = $projectCommon = 0;
|
||||
list($productCommon, $projectCommon) = explode('_', $this->config->custom->productproject);
|
||||
if($productCommon != 0 or $projectCommon != 0)
|
||||
{
|
||||
$this->lang->productCommon = $this->lang->productCommonList[$productCommon];
|
||||
$this->lang->projectCommon = $this->lang->projectCommonList[$projectCommon];
|
||||
$this->app->loadLang('common');
|
||||
}
|
||||
}
|
||||
|
||||
$this->common->loadCustomFromDB();
|
||||
if($this->app->getViewType() == 'mhtml') $this->common->setMobileMenu();
|
||||
$this->app->loadLang('company');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check upgrade's status file is ok or not.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function checkUpgradeStatus()
|
||||
{
|
||||
$statusFile = $this->loadModel('upgrade')->checkSafeFile();
|
||||
if($statusFile)
|
||||
{
|
||||
echo "<html><head><meta http-equiv='Content-Type' content='text/html; charset=utf-8' /></head><body>";
|
||||
echo "<table align='center' style='margin-top:100px; border:1px solid gray; font-size:14px;'><tr><td>";
|
||||
printf($this->lang->upgrade->setStatusFile, $statusFile, $statusFile, $statusFile);
|
||||
die('</td></tr></table></body></html>');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the user has permission to access this method, if not, locate to the login page or deny page.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function checkPriv()
|
||||
{
|
||||
$module = $this->app->getModuleName();
|
||||
$method = $this->app->getMethodName();
|
||||
if($this->common->isOpenMethod($module, $method)) return true;
|
||||
if(!$this->loadModel('user')->isLogon() and $this->server->php_auth_user) $this->user->identifyByPhpAuth();
|
||||
if(!$this->loadModel('user')->isLogon() and $this->cookie->za) $this->user->identifyByCookie();
|
||||
|
||||
if(isset($this->app->user))
|
||||
{
|
||||
if(!common::hasPriv($module, $method)) $this->common->deny($module, $method);
|
||||
}
|
||||
else
|
||||
{
|
||||
$referer = helper::safe64Encode($this->app->getURI(true));
|
||||
$this->locate($this->createLink('user', 'login', "referer=$referer"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the user has permisson of one method of one module.
|
||||
*
|
||||
* @param string $module
|
||||
* @param string $method
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function hasPriv($module, $method)
|
||||
{
|
||||
global $app, $lang;
|
||||
|
||||
/* Check is the super admin or not. */
|
||||
$account = ',' . $app->user->account . ',';
|
||||
if(strpos($app->company->admins, $account) !== false) return true;
|
||||
|
||||
/* If not super admin, check the rights. */
|
||||
$rights = $app->user->rights['rights'];
|
||||
$acls = $app->user->rights['acls'];
|
||||
$module = strtolower($module);
|
||||
$method = strtolower($method);
|
||||
if(isset($rights[$module][$method]))
|
||||
{
|
||||
if(empty($acls['views'])) return true;
|
||||
$menu = isset($lang->menugroup->$module) ? $lang->menugroup->$module : $module;
|
||||
$menu = strtolower($menu);
|
||||
if($menu != 'qa' and !isset($lang->$menu->menu)) return true;
|
||||
if($menu == 'my' or $menu == 'index' or $module == 'tree') return true;
|
||||
if($module == 'company' and $method == 'dynamic') return true;
|
||||
if($module == 'action' and $method == 'editcomment') return true;
|
||||
if(!isset($acls['views'][$menu])) return false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the %s of one key of a menu by $params.
|
||||
*
|
||||
* All the menus are defined in the common's language file. But there're many dynamic params, so in the defination,
|
||||
* we used %s as placeholder. These %s should be setted in one module.
|
||||
*
|
||||
* The items of one module's menu may be an string or array. For example, please see module/common/lang.
|
||||
*
|
||||
* @param string $object the menus of one module
|
||||
* @param string $key the menu item to be replaced
|
||||
* @param string $params the params passed to the menu item
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public static function setMenuVars($menu, $key, $params)
|
||||
{
|
||||
if(is_array($params))
|
||||
{
|
||||
if(is_array($menu->$key))
|
||||
{
|
||||
$menu->$key = (object)$menu->$key;
|
||||
$menu->$key->link = vsprintf($menu->$key->link, $params);
|
||||
$menu->$key = (array)$menu->$key;
|
||||
}
|
||||
else
|
||||
{
|
||||
$menu->$key = vsprintf($menu->$key, $params);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(is_array($menu->$key))
|
||||
{
|
||||
$menu->$key = (object)$menu->$key;
|
||||
$menu->$key->link = sprintf($menu->$key->link, $params);
|
||||
$menu->$key = (array)$menu->$key;
|
||||
}
|
||||
else
|
||||
{
|
||||
$menu->$key = sprintf($menu->$key, $params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the link contains orderBy field.
|
||||
*
|
||||
* This method will auto set the orderby param according the params. Fox example, if the order by is desc,
|
||||
* will be changed to asc.
|
||||
*
|
||||
* @param string $fieldName the field name to sort by
|
||||
* @param string $orderBy the order by string
|
||||
* @param string $vars the vars to be passed
|
||||
* @param string $label the label of the link
|
||||
* @param string $module the module name
|
||||
* @param string $method the method name
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public static function printOrderLink($fieldName, $orderBy, $vars, $label, $module = '', $method = '')
|
||||
{
|
||||
global $lang, $app;
|
||||
if(empty($module)) $module = $app->getModuleName();
|
||||
if(empty($method)) $method = $app->getMethodName();
|
||||
$className = 'header';
|
||||
|
||||
$order = explode('_', $orderBy);
|
||||
$order[0] = trim($order[0], '`');
|
||||
if($order[0] == $fieldName)
|
||||
{
|
||||
if(isset($order[1]) and $order[1] == 'asc')
|
||||
{
|
||||
$orderBy = "{$order[0]}_desc";
|
||||
$className = 'headerSortDown';
|
||||
}
|
||||
else
|
||||
{
|
||||
$orderBy = "{$order[0]}_asc";
|
||||
$className = 'headerSortUp';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
$orderBy = "" . trim($fieldName, '`') . "" . '_' . 'asc';
|
||||
$className = 'header';
|
||||
}
|
||||
$link = helper::createLink($module, $method, sprintf($vars, $orderBy));
|
||||
echo "<div class='$className'>" . html::a($link, $label) . '</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Print link to an modules' methd.
|
||||
*
|
||||
* Before printing, check the privilege first. If no privilege, return fasle. Else, print the link, return true.
|
||||
*
|
||||
* @param string $module the module name
|
||||
* @param string $method the method
|
||||
* @param string $vars vars to be passed
|
||||
* @param string $label the label of the link
|
||||
* @param string $target the target of the link
|
||||
* @param string $misc others
|
||||
* @param bool $newline
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function printLink($module, $method, $vars = '', $label, $target = '', $misc = '', $newline = true, $onlyBody = false)
|
||||
{
|
||||
if(!common::hasPriv($module, $method)) return false;
|
||||
echo html::a(helper::createLink($module, $method, $vars, '', $onlyBody), $label, $target, $misc, $newline);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print icon of split line.
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public static function printDivider()
|
||||
{
|
||||
echo " ";
|
||||
}
|
||||
|
||||
/**
|
||||
* Print icon of comment.
|
||||
*
|
||||
* @param string $module
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public static function printCommentIcon($module)
|
||||
{
|
||||
if(isonlybody()) return false;
|
||||
|
||||
global $lang;
|
||||
|
||||
if(!common::hasPriv($module, 'edit')) return false;
|
||||
echo html::a('#commentBox', '<i class="icon-comment-alt"></i>', '', "title='$lang->comment' onclick='setComment()' class='btn'");
|
||||
}
|
||||
|
||||
/**
|
||||
* Print link icon.
|
||||
*
|
||||
* @param string $module
|
||||
* @param string $method
|
||||
* @param string $vars
|
||||
* @param object $object
|
||||
* @param string $type button|list
|
||||
* @param string $icon
|
||||
* @param string $target
|
||||
* @param string $extraClass
|
||||
* @param bool $onlyBody
|
||||
* @param string $misc
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public static function printIcon($module, $method, $vars = '', $object = '', $type = 'button', $icon = '', $target = '', $extraClass = '', $onlyBody = false, $misc = '')
|
||||
{
|
||||
if(isonlybody() and strpos($extraClass, 'showinonlybody') === false) return false;
|
||||
|
||||
global $app, $lang;
|
||||
|
||||
/* Judge the $method of $module clickable or not, default is clickable. */
|
||||
$clickable = true;
|
||||
if(is_object($object))
|
||||
{
|
||||
if($app->getModuleName() != $module) $app->control->loadModel($module);
|
||||
$modelClass = class_exists("ext{$module}Model") ? "ext{$module}Model" : $module . "Model";
|
||||
if(class_exists($modelClass) and is_callable(array($modelClass, 'isClickable')))
|
||||
{
|
||||
$clickable = call_user_func_array(array($modelClass, 'isClickable'), array('object' => $object, 'method' => $method));
|
||||
}
|
||||
}
|
||||
|
||||
/* Set module and method, then create link to it. */
|
||||
if(strtolower($module) == 'story' and strtolower($method) == 'createcase') ($module = 'testcase') and ($method = 'create');
|
||||
if(strtolower($module) == 'bug' and strtolower($method) == 'tostory') ($module = 'story') and ($method = 'create');
|
||||
if(strtolower($module) == 'bug' and strtolower($method) == 'createcase') ($module = 'testcase') and ($method = 'create');
|
||||
if(!common::hasPriv($module, $method)) return false;
|
||||
$link = helper::createLink($module, $method, $vars, '', $onlyBody);
|
||||
|
||||
/* Set the icon title, try search the $method defination in $module's lang or $common's lang. */
|
||||
$title = $method;
|
||||
if($method == 'create' and $icon == 'copy') $method = 'copy';
|
||||
if(isset($lang->$method) and is_string($lang->$method)) $title = $lang->$method;
|
||||
if((isset($lang->$module->$method) or $app->loadLang($module)) and isset($lang->$module->$method))
|
||||
{
|
||||
$title = $method == 'report' ? $lang->$module->$method->common : $lang->$module->$method;
|
||||
}
|
||||
if($icon == 'toStory') $title = $lang->bug->toStory;
|
||||
if($icon == 'createBug') $title = $lang->testtask->createBug;
|
||||
|
||||
/* set the class. */
|
||||
if(!$icon)
|
||||
{
|
||||
$icon = $lang->icons[$method] ? $lang->icons[$method] : $method;
|
||||
}
|
||||
if(strpos(',edit,copy,report,export,delete,', ",$method,") !== false) $module = 'common';
|
||||
$class = "icon-$module-$method";
|
||||
if(!$clickable) $class .= ' disabled';
|
||||
if($icon) $class .= ' icon-' . $icon;
|
||||
|
||||
|
||||
/* Create the icon link. */
|
||||
if($clickable)
|
||||
{
|
||||
if($app->getViewType() == 'mhtml')
|
||||
{
|
||||
echo html::a($link, $title, $target, "class='$extraClass' data-role='button' data-mini='true' data-inline='true' data-theme='b'", true);
|
||||
return;
|
||||
}
|
||||
if($type == 'button')
|
||||
{
|
||||
if($method != 'edit' and $method != 'copy' and $method != 'delete')
|
||||
{
|
||||
echo html::a($link, "<i class='$class'></i> " . $title, $target, "class='btn $extraClass' $misc", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
echo html::a($link, "<i class='$class'></i>", $target, "class='btn $extraClass' title='$title' $misc", false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
echo html::a($link, "<i class='$class'></i>", $target, "class='btn-icon $extraClass' title='$title' $misc", false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if($type == 'list')
|
||||
{
|
||||
echo "<button type='button' class='disabled btn-icon $extraClass'><i class='$class' title='$title' $misc></i></button>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print backLink and preLink and nextLink.
|
||||
*
|
||||
* @param string $backLink
|
||||
* @param object $preAndNext
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
static public function printRPN($backLink, $preAndNext = '', $linkTemplate = '')
|
||||
{
|
||||
global $lang, $app;
|
||||
if(isonlybody()) return false;
|
||||
|
||||
echo html::a($backLink, '<i class="icon-goback icon-level-up icon-large icon-rotate-270"></i>', '', "class='btn' title={$lang->goback}");
|
||||
|
||||
if(isset($preAndNext->pre) and $preAndNext->pre)
|
||||
{
|
||||
$id = (isset($_SESSION['testcaseOnlyCondition']) and !$_SESSION['testcaseOnlyCondition'] and $app->getModuleName() == 'testcase' and isset($preAndNext->pre->case)) ? 'case' : 'id';
|
||||
$title = isset($preAndNext->pre->title) ? $preAndNext->pre->title : $preAndNext->pre->name;
|
||||
$title = '#' . $preAndNext->pre->$id . ' ' . $title;
|
||||
$link = $linkTemplate ? sprintf($linkTemplate, $preAndNext->pre->$id) : inLink('view', "ID={$preAndNext->pre->$id}");
|
||||
echo html::a($link, '<i class="icon-pre icon-chevron-left"></i>', '', "id='pre' class='btn' title='{$title}'");
|
||||
}
|
||||
if(isset($preAndNext->next) and $preAndNext->next)
|
||||
{
|
||||
$id = (isset($_SESSION['testcaseOnlyCondition']) and !$_SESSION['testcaseOnlyCondition'] and $app->getModuleName() == 'testcase' and isset($preAndNext->next->case)) ? 'case' : 'id';
|
||||
$title = isset($preAndNext->next->title) ? $preAndNext->next->title : $preAndNext->next->name;
|
||||
$title = '#' . $preAndNext->next->$id . ' ' . $title;
|
||||
$link = $linkTemplate ? sprintf($linkTemplate, $preAndNext->next->$id) : inLink('view', "ID={$preAndNext->next->$id}");
|
||||
echo html::a($link, '<i class="icon-pre icon-chevron-right"></i>', '', "id='next' class='btn' title='$title'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create changes of one object.
|
||||
*
|
||||
* @param mixed $old the old object
|
||||
* @param mixed $new the new object
|
||||
* @static
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public static function createChanges($old, $new)
|
||||
{
|
||||
global $config;
|
||||
$changes = array();
|
||||
$magicQuote = get_magic_quotes_gpc();
|
||||
foreach($new as $key => $value)
|
||||
{
|
||||
if(strtolower($key) == 'lastediteddate') continue;
|
||||
if(strtolower($key) == 'lasteditedby') continue;
|
||||
if(strtolower($key) == 'assigneddate') continue;
|
||||
if(strtolower($key) == 'editedby') continue;
|
||||
if(strtolower($key) == 'editeddate') continue;
|
||||
|
||||
if($magicQuote) $value = stripslashes($value);
|
||||
if($value != stripslashes($old->$key))
|
||||
{
|
||||
$diff = '';
|
||||
if(substr_count($value, "\n") > 1 or
|
||||
substr_count($old->$key, "\n") > 1 or
|
||||
strpos('name,title,desc,spec,steps,content,digest,verify,report', strtolower($key)) !== false)
|
||||
{
|
||||
$diff = commonModel::diff($old->$key, $value);
|
||||
}
|
||||
$changes[] = array('field' => $key, 'old' => $old->$key, 'new' => $value, 'diff' => $diff);
|
||||
}
|
||||
}
|
||||
return $changes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the full url of the system.
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public static function getSysURL()
|
||||
{
|
||||
$httpType = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == 'on') ? 'https' : 'http';
|
||||
$httpHost = $_SERVER['HTTP_HOST'];
|
||||
return "$httpType://$httpHost";
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the run info.
|
||||
*
|
||||
* @param mixed $startTime the start time.
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function printRunInfo($startTime)
|
||||
{
|
||||
vprintf($this->lang->runInfo, $this->common->getRunInfo($startTime));
|
||||
}
|
||||
}
|
||||
@@ -20,8 +20,6 @@ $lang->ellipsis = '...';
|
||||
|
||||
$lang->zentaoPMS = 'zentao';
|
||||
$lang->welcome = "%s PMS";
|
||||
$lang->myControl = "Dashboard";
|
||||
$lang->currentPos = 'Current';
|
||||
$lang->logout = 'Logout';
|
||||
$lang->login = 'Login';
|
||||
$lang->aboutZenTao = 'About';
|
||||
@@ -31,25 +29,20 @@ $lang->runInfo = "<div class='row'><div class='u-1 a-center' id='debugbar
|
||||
$lang->agreement = "I Agree to the <a href='http://zpl.pub/page/zplv12.html' target='_blank'>Z PUBLIC LICENSE 1.2</a>, <span class='text-danger'>and promise to keep the logo, link of ZenTao.</span>";
|
||||
|
||||
$lang->reset = 'Reset';
|
||||
$lang->cancel = 'Cancel';
|
||||
$lang->refresh = 'Refresh';
|
||||
$lang->edit = 'Edit';
|
||||
$lang->copy = 'Copy';
|
||||
$lang->delete = 'Delete';
|
||||
$lang->close = 'Close';
|
||||
$lang->link = 'Link';
|
||||
$lang->unlink = 'Unlink';
|
||||
$lang->import = 'Import';
|
||||
$lang->export = 'Export';
|
||||
$lang->setFileName = 'Filename:';
|
||||
$lang->activate = 'Activate';
|
||||
$lang->submitting = 'Saving...';
|
||||
$lang->save = 'Save';
|
||||
$lang->confirm = 'Confirm';
|
||||
$lang->preview = 'View';
|
||||
$lang->goback = 'Back';
|
||||
$lang->goPC = 'PC';
|
||||
$lang->go = 'GO';
|
||||
$lang->more = 'More';
|
||||
$lang->day = 'Day';
|
||||
|
||||
@@ -59,7 +52,6 @@ $lang->history = 'History';
|
||||
$lang->attatch = 'Attatch';
|
||||
$lang->reverse = 'Reverse';
|
||||
$lang->switchDisplay= 'Toggle Show';
|
||||
$lang->switchHelp = 'Toggle Help';
|
||||
$lang->addFiles = 'Add Files';
|
||||
$lang->files = 'Files ';
|
||||
$lang->pasteText = 'Paste text';
|
||||
@@ -67,14 +59,19 @@ $lang->uploadImages = 'Upload images ';
|
||||
$lang->timeout = 'Timed out, please check the network, or retry!';
|
||||
$lang->repairTable = 'The table may be damaged, please repair by phpmyadmin or myisamchk!';
|
||||
$lang->duplicate = '%s has the same title';
|
||||
$lang->ipLimited = "<html><head><meta http-equiv='Content-Type' content='text/html; charset=utf-8' /></head><body>Sorry, current IP is limited by Administrator. Please contact the Administrator to lift the restrictions.</body></html>";
|
||||
$lang->unfold = '+';
|
||||
$lang->fold = '-';
|
||||
|
||||
$lang->preShortcutKey = '[Shortcut key:←]';
|
||||
$lang->nextShortcutKey = '[Shortcut key:→]';
|
||||
|
||||
$lang->select = 'Select';
|
||||
$lang->selectAll = 'All';
|
||||
$lang->selectReverse = 'Inverse';
|
||||
$lang->loading = 'Wait...';
|
||||
$lang->notFound = 'Sorry, the object not found.';
|
||||
$lang->showAll = "[[Show all {$lang->projectCommon}s]]";
|
||||
$lang->hideClosed = "[[Show {$lang->projectCommon}s going]]";
|
||||
|
||||
$lang->future = 'Future';
|
||||
$lang->year = 'Year';
|
||||
@@ -364,6 +361,7 @@ $lang->error->passwordrule = "Password should more than six letters.";
|
||||
$lang->error->accessDenied = 'No purview';
|
||||
$lang->error->pasteImg = 'Your browser does not support the paste image!';
|
||||
$lang->error->noData = 'No data';
|
||||
$lang->error->editedByOther = 'The record may have been changed. Please refresh and re edit!';
|
||||
|
||||
/* Pager. */
|
||||
$lang->pager = new stdclass();
|
||||
@@ -376,11 +374,7 @@ $lang->pager->next = "<i class='icon-play' title='Next'></i>";
|
||||
$lang->pager->last = "<i class='icon-step-forward' title='Last'></i>";
|
||||
$lang->pager->locate = "GO!";
|
||||
|
||||
$lang->zentaoSite = "Official Site";
|
||||
$lang->chinaScrum = "<a href='http://api.zentao.net/goto.php?item=chinascrum' target='_blank'>Scrum community</a> ";
|
||||
$lang->agileTraining = "<a href='http://api.zentao.net/goto.php?item=agiletrain' target='_blank'>Training</a> ";
|
||||
$lang->donate = "<a href='http://api.zentao.net/goto.php?item=donate' target='_blank'>Donate</a> ";
|
||||
$lang->proVersion = "<a href='http://api.zentao.net/goto.php?item=proversion&from=footer' target='_blank' class='text-important'><i class='text-danger icon-reply icon-rotate-90'></i> PRO</a> ";
|
||||
$lang->proVersion = "<a href='http://api.zentao.net/goto.php?item=proversion&from=footer' target='_blank' class='text-important'>PRO <i class='text-danger icon-pro-version'></i></a> ";
|
||||
$lang->downNotify = "Down notify";
|
||||
|
||||
$lang->suhosinInfo = "Warming:data is too large! Please enlarge the setting of <font color=red>sohusin.post.max_vars</font> and <font color=red>sohusin.request.max_vars</font> in php.ini. Otherwise partial data can't be saved.";
|
||||
@@ -389,9 +383,8 @@ $lang->noticeImport = "<p style='font-size:14px'>Import data, containing the ex
|
||||
|
||||
$lang->noResultsMatch = "No results match";
|
||||
$lang->searchMore = "Search more results with the key:";
|
||||
$lang->selectAnOption = "Select an option";
|
||||
$lang->selectSomeOptions = "Select some options";
|
||||
$lang->chooseUsersToMail = "Choose users to mail...";
|
||||
$lang->browserNotice = 'Using the browser may not be able to get the best browsing effect, it is recommended to use chrome, Firefox, IE9 +, opera, Safari browser.';
|
||||
|
||||
/* Date times. */
|
||||
define('DT_DATETIME1', 'Y-m-d H:i:s');
|
||||
@@ -486,6 +479,7 @@ $lang->icons['close'] = 'off';
|
||||
$lang->icons['activate'] = 'off';
|
||||
$lang->icons['review'] = 'search';
|
||||
$lang->icons['confirm'] = 'search';
|
||||
$lang->icons['confirmBug'] = 'search';
|
||||
$lang->icons['putoff'] = 'calendar';
|
||||
$lang->icons['suspend'] = 'pause';
|
||||
$lang->icons['pause'] = 'pause';
|
||||
|
||||
@@ -20,8 +20,6 @@ $lang->ellipsis = '…';
|
||||
|
||||
$lang->zentaoPMS = '禅道';
|
||||
$lang->welcome = "%s项目管理系统";
|
||||
$lang->myControl = "我的地盘";
|
||||
$lang->currentPos = '当前位置:';
|
||||
$lang->logout = '退出';
|
||||
$lang->login = '登录';
|
||||
$lang->aboutZenTao = '关于';
|
||||
@@ -31,25 +29,20 @@ $lang->runInfo = "<div class='row'><div class='u-1 a-center' id='debugbar
|
||||
$lang->agreement = "已阅读并同意<a href='http://zpl.pub/page/zplv12.html' target='_blank'>《Z PUBLIC LICENSE授权协议1.2》</a>。<span class='text-danger'>未经许可,不得去除、隐藏或遮掩禅道软件的任何标志及链接。</span>";
|
||||
|
||||
$lang->reset = '重填';
|
||||
$lang->cancel = '取消';
|
||||
$lang->refresh = '刷新';
|
||||
$lang->edit = '编辑';
|
||||
$lang->copy = '复制';
|
||||
$lang->delete = '删除';
|
||||
$lang->close = '关闭';
|
||||
$lang->link = '关联';
|
||||
$lang->unlink = '移除';
|
||||
$lang->import = '导入';
|
||||
$lang->export = '导出';
|
||||
$lang->setFileName = '文件名:';
|
||||
$lang->activate = '激活';
|
||||
$lang->submitting = '稍候...';
|
||||
$lang->save = '保存';
|
||||
$lang->confirm = '确认';
|
||||
$lang->preview = '查看';
|
||||
$lang->goback = '返回';
|
||||
$lang->goPC = 'PC版';
|
||||
$lang->go = 'GO';
|
||||
$lang->more = '更多';
|
||||
$lang->day = '天';
|
||||
|
||||
@@ -59,7 +52,6 @@ $lang->history = '历史记录';
|
||||
$lang->attatch = '附件';
|
||||
$lang->reverse = '切换顺序';
|
||||
$lang->switchDisplay= '切换显示';
|
||||
$lang->switchHelp = '切换帮助';
|
||||
$lang->addFiles = '上传了附件 ';
|
||||
$lang->files = '附件 ';
|
||||
$lang->pasteText = '粘贴文本 ';
|
||||
@@ -67,14 +59,19 @@ $lang->uploadImages = '多图上传 ';
|
||||
$lang->timeout = '连接超时,请检查网络环境,或重试!';
|
||||
$lang->repairTable = '数据库表可能损坏,请用phpmyadmin或myisamchk检查修复。';
|
||||
$lang->duplicate = '已有相同标题的%s';
|
||||
$lang->ipLimited = "<html><head><meta http-equiv='Content-Type' content='text/html; charset=utf-8' /></head><body>抱歉,管理员限制当前IP登录,请联系管理员解除限制。</body></html>";
|
||||
$lang->unfold = '+';
|
||||
$lang->fold = '-';
|
||||
|
||||
$lang->preShortcutKey = '[快捷键:←]';
|
||||
$lang->nextShortcutKey = '[快捷键:→]';
|
||||
|
||||
$lang->select = '选择';
|
||||
$lang->selectAll = '全选';
|
||||
$lang->selectReverse = '反选';
|
||||
$lang->loading = '稍候...';
|
||||
$lang->notFound = '抱歉,您访问的对象并不存在!';
|
||||
$lang->showAll = '[[全部显示]]';
|
||||
$lang->hideClosed = '[[显示进行中]]';
|
||||
|
||||
$lang->future = '未来';
|
||||
$lang->year = '年';
|
||||
@@ -364,6 +361,7 @@ $lang->error->passwordrule = "密码应该符合规则,长度至少为六
|
||||
$lang->error->accessDenied = '您没有访问权限';
|
||||
$lang->error->pasteImg = '您的浏览器不支持粘贴图片!';
|
||||
$lang->error->noData = '没有数据';
|
||||
$lang->error->editedByOther = '该记录可能已经被改动。请刷新页面重新编辑!';
|
||||
|
||||
/* 分页信息。*/
|
||||
$lang->pager = new stdclass();
|
||||
@@ -376,11 +374,7 @@ $lang->pager->next = "<i class='icon-play' title='下一页'></i>";
|
||||
$lang->pager->last = "<i class='icon-step-forward' title='末页'></i>";
|
||||
$lang->pager->locate = "GO!";
|
||||
|
||||
$lang->zentaoSite = "官方网站";
|
||||
$lang->chinaScrum = "<a href='http://api.zentao.net/goto.php?item=chinascrum' target='_blank'>Scrum社区</a> ";
|
||||
$lang->agileTraining = "<a href='http://api.zentao.net/goto.php?item=agiletrain' target='_blank'>培训</a> ";
|
||||
$lang->donate = "<a href='http://api.zentao.net/goto.php?item=donate' target='_blank'>捐赠 </a>";
|
||||
$lang->proVersion = "<a href='http://api.zentao.net/goto.php?item=proversion&from=footer' target='_blank' id='proLink' class='text-important'><i class='text-danger icon-reply icon-rotate-90'></i> 专业版!</a> ";
|
||||
$lang->proVersion = "<a href='http://api.zentao.net/goto.php?item=proversion&from=footer' target='_blank' id='proLink' class='text-important'>专业版 <i class='text-danger icon-pro-version'></i></a> ";
|
||||
$lang->downNotify = "下载桌面提醒";
|
||||
|
||||
$lang->suhosinInfo = "警告:数据太多,请在php.ini中修改<font color=red>sohusin.post.max_vars</font>和<font color=red>sohusin.request.max_vars</font>(设置更大的数)。 保存并重新启动apache,否则会造成部分数据无法保存。";
|
||||
@@ -389,9 +383,8 @@ $lang->noticeImport = "<p style='font-size:14px'>导入数据中,含有已经
|
||||
|
||||
$lang->noResultsMatch = "没有匹配结果";
|
||||
$lang->searchMore = "搜索此关键字的更多结果:";
|
||||
$lang->selectAnOption = "选择一个选项";
|
||||
$lang->selectSomeOptions = "选择一些选项";
|
||||
$lang->chooseUsersToMail = "选择要发信通知的用户...";
|
||||
$lang->browserNotice = '你目前使用的浏览器可能无法得到最佳浏览效果,建议使用Chrome、火狐、IE9+、Opera、Safari浏览器。';
|
||||
|
||||
/* 时间格式设置。*/
|
||||
define('DT_DATETIME1', 'Y-m-d H:i:s');
|
||||
@@ -486,6 +479,7 @@ $lang->icons['close'] = 'off';
|
||||
$lang->icons['activate'] = 'off';
|
||||
$lang->icons['review'] = 'search';
|
||||
$lang->icons['confirm'] = 'search';
|
||||
$lang->icons['confirmBug'] = 'search';
|
||||
$lang->icons['putoff'] = 'calendar';
|
||||
$lang->icons['suspend'] = 'pause';
|
||||
$lang->icons['pause'] = 'pause';
|
||||
|
||||
@@ -20,8 +20,6 @@ $lang->ellipsis = '…';
|
||||
|
||||
$lang->zentaoPMS = '禪道';
|
||||
$lang->welcome = "%s項目管理系統";
|
||||
$lang->myControl = "我的地盤";
|
||||
$lang->currentPos = '當前位置:';
|
||||
$lang->logout = '退出';
|
||||
$lang->login = '登錄';
|
||||
$lang->aboutZenTao = '關於';
|
||||
@@ -31,25 +29,20 @@ $lang->runInfo = "<div class='row'><div class='u-1 a-center' id='debugbar
|
||||
$lang->agreement = "已閲讀並同意<a href='http://zpl.pub/page/zplv12.html' target='_blank'>《Z PUBLIC LICENSE授權協議1.2》</a>。<span class='text-danger'>未經許可,不得去除、隱藏或遮掩禪道軟件的任何標誌及連結。</span>";
|
||||
|
||||
$lang->reset = '重填';
|
||||
$lang->cancel = '取消';
|
||||
$lang->refresh = '刷新';
|
||||
$lang->edit = '編輯';
|
||||
$lang->copy = '複製';
|
||||
$lang->delete = '刪除';
|
||||
$lang->close = '關閉';
|
||||
$lang->link = '關聯';
|
||||
$lang->unlink = '移除';
|
||||
$lang->import = '導入';
|
||||
$lang->export = '導出';
|
||||
$lang->setFileName = '檔案名:';
|
||||
$lang->activate = '激活';
|
||||
$lang->submitting = '稍候...';
|
||||
$lang->save = '保存';
|
||||
$lang->confirm = '確認';
|
||||
$lang->preview = '查看';
|
||||
$lang->goback = '返回';
|
||||
$lang->goPC = 'PC版';
|
||||
$lang->go = 'GO';
|
||||
$lang->more = '更多';
|
||||
$lang->day = '天';
|
||||
|
||||
@@ -59,7 +52,6 @@ $lang->history = '歷史記錄';
|
||||
$lang->attatch = '附件';
|
||||
$lang->reverse = '切換順序';
|
||||
$lang->switchDisplay= '切換顯示';
|
||||
$lang->switchHelp = '切換幫助';
|
||||
$lang->addFiles = '上傳了附件 ';
|
||||
$lang->files = '附件 ';
|
||||
$lang->pasteText = '粘貼文本 ';
|
||||
@@ -67,14 +59,19 @@ $lang->uploadImages = '多圖上傳 ';
|
||||
$lang->timeout = '連接超時,請檢查網絡環境,或重試!';
|
||||
$lang->repairTable = '資料庫表可能損壞,請用phpmyadmin或myisamchk檢查修復。';
|
||||
$lang->duplicate = '已有相同標題的%s';
|
||||
$lang->ipLimited = "<html><head><meta http-equiv='Content-Type' content='text/html; charset=utf-8' /></head><body>抱歉,管理員限制當前IP登錄,請聯繫管理員解除限制。</body></html>";
|
||||
$lang->unfold = '+';
|
||||
$lang->fold = '-';
|
||||
|
||||
$lang->preShortcutKey = '[快捷鍵:←]';
|
||||
$lang->nextShortcutKey = '[快捷鍵:→]';
|
||||
|
||||
$lang->select = '選擇';
|
||||
$lang->selectAll = '全選';
|
||||
$lang->selectReverse = '反選';
|
||||
$lang->loading = '稍候...';
|
||||
$lang->notFound = '抱歉,您訪問的對象並不存在!';
|
||||
$lang->showAll = '[[全部顯示]]';
|
||||
$lang->hideClosed = '[[顯示進行中]]';
|
||||
|
||||
$lang->future = '未來';
|
||||
$lang->year = '年';
|
||||
@@ -364,6 +361,7 @@ $lang->error->passwordrule = "密碼應該符合規則,長度至少為六
|
||||
$lang->error->accessDenied = '您沒有訪問權限';
|
||||
$lang->error->pasteImg = '您的瀏覽器不支持粘貼圖片!';
|
||||
$lang->error->noData = '沒有數據';
|
||||
$lang->error->editedByOther = '該記錄可能已經被改動。請刷新頁面重新編輯!';
|
||||
|
||||
/* 分頁信息。*/
|
||||
$lang->pager = new stdclass();
|
||||
@@ -376,11 +374,7 @@ $lang->pager->next = "<i class='icon-play' title='下一頁'></i>";
|
||||
$lang->pager->last = "<i class='icon-step-forward' title='末頁'></i>";
|
||||
$lang->pager->locate = "GO!";
|
||||
|
||||
$lang->zentaoSite = "官方網站";
|
||||
$lang->chinaScrum = "<a href='http://api.zentao.net/goto.php?item=chinascrum' target='_blank'>Scrum社區</a> ";
|
||||
$lang->agileTraining = "<a href='http://api.zentao.net/goto.php?item=agiletrain' target='_blank'>培訓</a> ";
|
||||
$lang->donate = "<a href='http://api.zentao.net/goto.php?item=donate' target='_blank'>捐贈 </a>";
|
||||
$lang->proVersion = "<a href='http://api.zentao.net/goto.php?item=proversion&from=footer' target='_blank' id='proLink' class='text-important'><i class='text-danger icon-reply icon-rotate-90'></i> 專業版!</a> ";
|
||||
$lang->proVersion = "<a href='http://api.zentao.net/goto.php?item=proversion&from=footer' target='_blank' id='proLink' class='text-important'>專業版 <i class='text-danger icon-pro-version'></i></a> ";
|
||||
$lang->downNotify = "下載桌面提醒";
|
||||
|
||||
$lang->suhosinInfo = "警告:數據太多,請在php.ini中修改<font color=red>sohusin.post.max_vars</font>和<font color=red>sohusin.request.max_vars</font>(設置更大的數)。 保存並重新啟動apache,否則會造成部分數據無法保存。";
|
||||
@@ -389,9 +383,8 @@ $lang->noticeImport = "<p style='font-size:14px'>導入數據中,含有已經
|
||||
|
||||
$lang->noResultsMatch = "沒有匹配結果";
|
||||
$lang->searchMore = "搜索此關鍵字的更多結果:";
|
||||
$lang->selectAnOption = "選擇一個選項";
|
||||
$lang->selectSomeOptions = "選擇一些選項";
|
||||
$lang->chooseUsersToMail = "選擇要發信通知的用戶...";
|
||||
$lang->browserNotice = '你目前使用的瀏覽器可能無法得到最佳瀏覽效果,建議使用Chrome、火狐、IE9+、Opera、Safari瀏覽器。';
|
||||
|
||||
/* 時間格式設置。*/
|
||||
define('DT_DATETIME1', 'Y-m-d H:i:s');
|
||||
@@ -486,6 +479,7 @@ $lang->icons['close'] = 'off';
|
||||
$lang->icons['activate'] = 'off';
|
||||
$lang->icons['review'] = 'search';
|
||||
$lang->icons['confirm'] = 'search';
|
||||
$lang->icons['confirmBug'] = 'search';
|
||||
$lang->icons['putoff'] = 'calendar';
|
||||
$lang->icons['suspend'] = 'pause';
|
||||
$lang->icons['pause'] = 'pause';
|
||||
|
||||
@@ -11,6 +11,30 @@
|
||||
*/
|
||||
class commonModel extends model
|
||||
{
|
||||
/**
|
||||
* The construc method, to do some auto things.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
if(!defined('FIRST_RUN'))
|
||||
{
|
||||
$this->startSession();
|
||||
$this->sendHeader();
|
||||
$this->setCompany();
|
||||
$this->setUser();
|
||||
$this->loadConfigFromDB();
|
||||
$this->loadCustomFromDB();
|
||||
if(!$this->checkIP()) die($this->lang->ipLimited);
|
||||
if($this->app->getViewType() == 'mhtml') $this->setMobileMenu();
|
||||
$this->app->loadLang('company');
|
||||
define('FIRST_RUN', true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the session.
|
||||
*
|
||||
@@ -102,21 +126,8 @@ class commonModel extends model
|
||||
$this->config->personal = isset($config[$account]) ? $config[$account] : array();
|
||||
|
||||
/* Overide the items defined in config/config.php and config/my.php. */
|
||||
if(isset($this->config->system->common))
|
||||
{
|
||||
foreach($this->config->system->common as $record)
|
||||
{
|
||||
if($record->section)
|
||||
{
|
||||
if(!isset($this->config->{$record->section})) $this->config->{$record->section} = new stdclass();
|
||||
$this->config->{$record->section}->{$record->key} = $record->value;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!$record->section) $this->config->{$record->key} = $record->value;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(isset($this->config->system->common)) helper::mergeConfig($this->config->system->common, 'common');
|
||||
if(isset($this->config->personal->common)) helper::mergeConfig($this->config->personal->common, 'common');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -145,9 +156,10 @@ class commonModel extends model
|
||||
*/
|
||||
public function isOpenMethod($module, $method)
|
||||
{
|
||||
if($module == 'user' and strpos('login|logout|deny', $method) !== false) return true;
|
||||
if($module == 'user' and strpos('login|logout|deny|reset', $method) !== false) return true;
|
||||
if($module == 'api' and $method == 'getsessionid') return true;
|
||||
if($module == 'misc' and $method == 'ping') return true;
|
||||
if($module == 'misc' and $method == 'checktable') return true;
|
||||
if($module == 'block' and $method == 'main') return true;
|
||||
if($module == 'sso' and $method == 'login') return true;
|
||||
if($module == 'sso' and $method == 'logout') return true;
|
||||
@@ -161,7 +173,6 @@ class commonModel extends model
|
||||
|
||||
if(stripos($method, 'ajaxgetdropmenu') !== false) return true;
|
||||
if(stripos($method, 'ajaxgetmatcheditems') !== false) return true;
|
||||
if($method == 'ajaxgetdetail' and $this->app->viewType == 'mhtml') return true;
|
||||
if($module == 'misc' and $method == 'qrcode') return true;
|
||||
if($module == 'misc' and $method == 'about') return true;
|
||||
if($module == 'misc' and $method == 'checkupdate') return true;
|
||||
@@ -176,6 +187,14 @@ class commonModel extends model
|
||||
*/
|
||||
public function deny($module, $method)
|
||||
{
|
||||
/* Get authorize again. */
|
||||
$user = $this->app->user;
|
||||
$user->rights = $this->loadModel('user')->authorize($user->account);
|
||||
$user->groups = $this->user->getGroups($user->account);
|
||||
$this->session->set('user', $user);
|
||||
$this->app->user = $this->session->user;
|
||||
if(commonModel::hasPriv($module, $method)) return true;
|
||||
|
||||
$vars = "module=$module&method=$method";
|
||||
if(isset($this->server->http_referer))
|
||||
{
|
||||
@@ -198,17 +217,18 @@ class commonModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the run info.
|
||||
* Print the run info.
|
||||
*
|
||||
* @param mixed $startTime the start time of this execution
|
||||
* @param mixed $startTime the start time.
|
||||
* @access public
|
||||
* @return array the run info array.
|
||||
*/
|
||||
public function getRunInfo($startTime)
|
||||
public function printRunInfo($startTime)
|
||||
{
|
||||
$info['timeUsed'] = round(getTime() - $startTime, 4) * 1000;
|
||||
$info['memory'] = round(memory_get_peak_usage() / 1024, 1);
|
||||
$info['querys'] = count(dao::$querys);
|
||||
vprintf($this->lang->runInfo, $info);
|
||||
return $info;
|
||||
}
|
||||
|
||||
@@ -241,7 +261,7 @@ class commonModel extends model
|
||||
}
|
||||
|
||||
$isLeft = ($app->company->website and $app->company->backyard) ? '' : ' left';
|
||||
|
||||
|
||||
echo "<li class='dropdown-submenu{$isLeft}'>";
|
||||
echo "<a href='javascript:;'>" . $lang->theme . "</a><ul class='dropdown-menu'>";
|
||||
foreach ($app->lang->themes as $key => $value)
|
||||
@@ -285,7 +305,7 @@ class commonModel extends model
|
||||
public function setMobileMenu()
|
||||
{
|
||||
$menu = new stdclass();
|
||||
|
||||
|
||||
$role = isset($this->app->user->role) ? $this->app->user->role : '';
|
||||
|
||||
$this->config->locate = new stdclass();
|
||||
@@ -299,31 +319,19 @@ class commonModel extends model
|
||||
$bug = $this->lang->my->menu->bug['link'];
|
||||
$project = $this->lang->menu->project . '|locate=no&&status=isdoing';
|
||||
$product = $this->lang->menu->product . '|locate=no';
|
||||
$menu = array('todo' => $todo, 'task' => $task, 'bug' => $bug, 'project' => $project, 'product' => $product);
|
||||
|
||||
if($role == 'dev' or $role == 'td' or $role == 'pm')
|
||||
{
|
||||
$menu = array('todo' => $todo, 'task' => $task, 'bug' => $bug, 'product' => $product, 'project' => $project);
|
||||
}
|
||||
elseif($role == 'pd' or $role == 'po')
|
||||
{
|
||||
$menu = array('todo' => $todo, 'story' => $story, 'bug' => $bug, 'product' => $product, 'project' => $project);
|
||||
}
|
||||
elseif($role == 'qa' or $role == 'qd')
|
||||
{
|
||||
$menu = array('todo' => $todo, 'bug' => $bug, 'project' => $project, 'product' => $product);
|
||||
}
|
||||
elseif($role == 'top')
|
||||
{
|
||||
$menu = array('project' => $project, 'product' => $product, 'todo' => $todo);
|
||||
if($role and strpos('dev,td,pm', $role) !== false) $menu = array('todo' => $todo, 'task' => $task, 'bug' => $bug, 'product' => $product, 'project' => $project);
|
||||
if($role and strpos('pd,po', $role) !== false) $menu = array('todo' => $todo, 'story' => $story, 'bug' => $bug, 'product' => $product, 'project' => $project);
|
||||
if($role and strpos('qa,qd', $role) !== false) $menu = array('todo' => $todo, 'bug' => $bug, 'project' => $project, 'product' => $product);
|
||||
if($role and strpos('top', $role) !== false) $menu = array('project' => $project, 'product' => $product, 'todo' => $todo);
|
||||
|
||||
if($role == 'top')
|
||||
{
|
||||
$this->config->locate->module = 'project';
|
||||
$this->config->locate->method = 'index';
|
||||
$this->config->locate->params = 'locate=no&status=doing';
|
||||
}
|
||||
else
|
||||
{
|
||||
$menu = array('todo' => $todo, 'task' => $task, 'bug' => $bug, 'project' => $project, 'product' => $product);
|
||||
}
|
||||
|
||||
unset($this->lang->menuOrder);
|
||||
unset($this->lang->menugroup);
|
||||
@@ -343,7 +351,7 @@ class commonModel extends model
|
||||
{
|
||||
global $app, $lang;
|
||||
echo "<ul class='nav'>\n";
|
||||
|
||||
|
||||
/* Set the main main menu. */
|
||||
$mainMenu = $moduleName;
|
||||
if(isset($lang->menugroup->$moduleName)) $mainMenu = $lang->menugroup->$moduleName;
|
||||
@@ -384,7 +392,7 @@ class commonModel extends model
|
||||
list($menuLabel, $module, $method) = $link;
|
||||
$vars = isset($link[3]) ? $link[3] : '';
|
||||
|
||||
if(common::hasPriv($module, $method))
|
||||
if(commonModel::hasPriv($module, $method))
|
||||
{
|
||||
$link = helper::createLink($module, $method, $vars);
|
||||
echo "<li $active><a href='$link' $active id='menu$menuKey'>$menuLabel</a></li>\n";
|
||||
@@ -506,7 +514,7 @@ class commonModel extends model
|
||||
$link = explode('|', $link);
|
||||
list($label, $module, $method) = $link;
|
||||
$vars = isset($link[3]) ? $link[3] : '';
|
||||
if(common::hasPriv($module, $method))
|
||||
if(commonModel::hasPriv($module, $method))
|
||||
{
|
||||
/* Is the currentModule active? */
|
||||
$subModules = explode(',', $subModule);
|
||||
@@ -564,10 +572,7 @@ class commonModel extends model
|
||||
{
|
||||
if(strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'windows') !== false)
|
||||
{
|
||||
global $app, $lang;
|
||||
$notifyFile = $app->getBasePath() . 'www/data/notify/notify.zip';
|
||||
|
||||
if(!file_exists($notifyFile)) return false;
|
||||
global $lang;
|
||||
echo html::a(helper::createLink('misc', 'downNotify'), "<i class='icon-bell'></i>", '', "title='$lang->downNotify'") . ' ';
|
||||
}
|
||||
}
|
||||
@@ -588,6 +593,275 @@ class commonModel extends model
|
||||
echo '<script>$(function(){$("#qrcodeBtn").hover(function(){$(".popover-content img").attr("src", "' . helper::createLink('misc', 'qrCode') . '");});});</script>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the link contains orderBy field.
|
||||
*
|
||||
* This method will auto set the orderby param according the params. Fox example, if the order by is desc,
|
||||
* will be changed to asc.
|
||||
*
|
||||
* @param string $fieldName the field name to sort by
|
||||
* @param string $orderBy the order by string
|
||||
* @param string $vars the vars to be passed
|
||||
* @param string $label the label of the link
|
||||
* @param string $module the module name
|
||||
* @param string $method the method name
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public static function printOrderLink($fieldName, $orderBy, $vars, $label, $module = '', $method = '')
|
||||
{
|
||||
global $lang, $app;
|
||||
if(empty($module)) $module = $app->getModuleName();
|
||||
if(empty($method)) $method = $app->getMethodName();
|
||||
$className = 'header';
|
||||
|
||||
$order = explode('_', $orderBy);
|
||||
$order[0] = trim($order[0], '`');
|
||||
if($order[0] == $fieldName)
|
||||
{
|
||||
if(isset($order[1]) and $order[1] == 'asc')
|
||||
{
|
||||
$orderBy = "{$order[0]}_desc";
|
||||
$className = 'headerSortDown';
|
||||
}
|
||||
else
|
||||
{
|
||||
$orderBy = "{$order[0]}_asc";
|
||||
$className = 'headerSortUp';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
$orderBy = "" . trim($fieldName, '`') . "" . '_' . 'asc';
|
||||
$className = 'header';
|
||||
}
|
||||
$link = helper::createLink($module, $method, sprintf($vars, $orderBy));
|
||||
echo "<div class='$className'>" . html::a($link, $label) . '</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Print link to an modules' methd.
|
||||
*
|
||||
* Before printing, check the privilege first. If no privilege, return fasle. Else, print the link, return true.
|
||||
*
|
||||
* @param string $module the module name
|
||||
* @param string $method the method
|
||||
* @param string $vars vars to be passed
|
||||
* @param string $label the label of the link
|
||||
* @param string $target the target of the link
|
||||
* @param string $misc others
|
||||
* @param bool $newline
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function printLink($module, $method, $vars = '', $label, $target = '', $misc = '', $newline = true, $onlyBody = false)
|
||||
{
|
||||
if(!commonModel::hasPriv($module, $method)) return false;
|
||||
echo html::a(helper::createLink($module, $method, $vars, '', $onlyBody), $label, $target, $misc, $newline);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print icon of split line.
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public static function printDivider()
|
||||
{
|
||||
echo " ";
|
||||
}
|
||||
|
||||
/**
|
||||
* Print icon of comment.
|
||||
*
|
||||
* @param string $module
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public static function printCommentIcon($module)
|
||||
{
|
||||
if(isonlybody()) return false;
|
||||
|
||||
global $lang;
|
||||
|
||||
if(!commonModel::hasPriv($module, 'edit')) return false;
|
||||
echo html::a('#commentBox', '<i class="icon-comment-alt"></i>', '', "title='$lang->comment' onclick='setComment()' class='btn'");
|
||||
}
|
||||
|
||||
/**
|
||||
* Print link icon.
|
||||
*
|
||||
* @param string $module
|
||||
* @param string $method
|
||||
* @param string $vars
|
||||
* @param object $object
|
||||
* @param string $type button|list
|
||||
* @param string $icon
|
||||
* @param string $target
|
||||
* @param string $extraClass
|
||||
* @param bool $onlyBody
|
||||
* @param string $misc
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public static function printIcon($module, $method, $vars = '', $object = '', $type = 'button', $icon = '', $target = '', $extraClass = '', $onlyBody = false, $misc = '')
|
||||
{
|
||||
if(isonlybody() and strpos($extraClass, 'showinonlybody') === false) return false;
|
||||
|
||||
global $app, $lang;
|
||||
|
||||
/* Judge the $method of $module clickable or not, default is clickable. */
|
||||
$clickable = true;
|
||||
if(is_object($object))
|
||||
{
|
||||
if($app->getModuleName() != $module) $app->control->loadModel($module);
|
||||
$modelClass = class_exists("ext{$module}Model") ? "ext{$module}Model" : $module . "Model";
|
||||
if(class_exists($modelClass) and is_callable(array($modelClass, 'isClickable')))
|
||||
{
|
||||
$clickable = call_user_func_array(array($modelClass, 'isClickable'), array('object' => $object, 'method' => $method));
|
||||
}
|
||||
}
|
||||
|
||||
/* Set module and method, then create link to it. */
|
||||
if(strtolower($module) == 'story' and strtolower($method) == 'createcase') ($module = 'testcase') and ($method = 'create');
|
||||
if(strtolower($module) == 'bug' and strtolower($method) == 'tostory') ($module = 'story') and ($method = 'create');
|
||||
if(strtolower($module) == 'bug' and strtolower($method) == 'createcase') ($module = 'testcase') and ($method = 'create');
|
||||
if(!commonModel::hasPriv($module, $method)) return false;
|
||||
$link = helper::createLink($module, $method, $vars, '', $onlyBody);
|
||||
|
||||
/* Set the icon title, try search the $method defination in $module's lang or $common's lang. */
|
||||
$title = $method;
|
||||
if($method == 'create' and $icon == 'copy') $method = 'copy';
|
||||
if(isset($lang->$method) and is_string($lang->$method)) $title = $lang->$method;
|
||||
if((isset($lang->$module->$method) or $app->loadLang($module)) and isset($lang->$module->$method))
|
||||
{
|
||||
$title = $method == 'report' ? $lang->$module->$method->common : $lang->$module->$method;
|
||||
}
|
||||
if($icon == 'toStory') $title = $lang->bug->toStory;
|
||||
if($icon == 'createBug') $title = $lang->testtask->createBug;
|
||||
|
||||
/* set the class. */
|
||||
if(!$icon)
|
||||
{
|
||||
$icon = $lang->icons[$method] ? $lang->icons[$method] : $method;
|
||||
}
|
||||
if(strpos(',edit,copy,report,export,delete,', ",$method,") !== false) $module = 'common';
|
||||
$class = "icon-$module-$method";
|
||||
if(!$clickable) $class .= ' disabled';
|
||||
if($icon) $class .= ' icon-' . $icon;
|
||||
|
||||
|
||||
/* Create the icon link. */
|
||||
if($clickable)
|
||||
{
|
||||
if($app->getViewType() == 'mhtml')
|
||||
{
|
||||
echo html::a($link, $title, $target, "class='$extraClass' data-role='button' data-mini='true' data-inline='true' data-theme='b'", true);
|
||||
return;
|
||||
}
|
||||
if($type == 'button')
|
||||
{
|
||||
if($method != 'edit' and $method != 'copy' and $method != 'delete')
|
||||
{
|
||||
echo html::a($link, "<i class='$class'></i> " . $title, $target, "class='btn $extraClass' $misc", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
echo html::a($link, "<i class='$class'></i>", $target, "class='btn $extraClass' title='$title' $misc", false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
echo html::a($link, "<i class='$class'></i>", $target, "class='btn-icon $extraClass' title='$title' $misc", false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if($type == 'list')
|
||||
{
|
||||
echo "<button type='button' class='disabled btn-icon $extraClass'><i class='$class' title='$title' $misc></i></button>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print backLink and preLink and nextLink.
|
||||
*
|
||||
* @param string $backLink
|
||||
* @param object $preAndNext
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
static public function printRPN($backLink, $preAndNext = '', $linkTemplate = '')
|
||||
{
|
||||
global $lang, $app;
|
||||
if(isonlybody()) return false;
|
||||
|
||||
echo html::a($backLink, '<i class="icon-goback icon-level-up icon-large icon-rotate-270"></i>', '', "class='btn' title={$lang->goback}");
|
||||
|
||||
if(isset($preAndNext->pre) and $preAndNext->pre)
|
||||
{
|
||||
$id = (isset($_SESSION['testcaseOnlyCondition']) and !$_SESSION['testcaseOnlyCondition'] and $app->getModuleName() == 'testcase' and isset($preAndNext->pre->case)) ? 'case' : 'id';
|
||||
$title = isset($preAndNext->pre->title) ? $preAndNext->pre->title : $preAndNext->pre->name;
|
||||
$title = '#' . $preAndNext->pre->$id . ' ' . $title . ' ' . $lang->preShortcutKey;
|
||||
$link = $linkTemplate ? sprintf($linkTemplate, $preAndNext->pre->$id) : inLink('view', "ID={$preAndNext->pre->$id}");
|
||||
echo html::a($link, '<i class="icon-pre icon-chevron-left"></i>', '', "id='pre' class='btn' title='{$title}'");
|
||||
}
|
||||
if(isset($preAndNext->next) and $preAndNext->next)
|
||||
{
|
||||
$id = (isset($_SESSION['testcaseOnlyCondition']) and !$_SESSION['testcaseOnlyCondition'] and $app->getModuleName() == 'testcase' and isset($preAndNext->next->case)) ? 'case' : 'id';
|
||||
$title = isset($preAndNext->next->title) ? $preAndNext->next->title : $preAndNext->next->name;
|
||||
$title = '#' . $preAndNext->next->$id . ' ' . $title . ' ' . $lang->nextShortcutKey;
|
||||
$link = $linkTemplate ? sprintf($linkTemplate, $preAndNext->next->$id) : inLink('view', "ID={$preAndNext->next->$id}");
|
||||
echo html::a($link, '<i class="icon-pre icon-chevron-right"></i>', '', "id='next' class='btn' title='$title'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create changes of one object.
|
||||
*
|
||||
* @param mixed $old the old object
|
||||
* @param mixed $new the new object
|
||||
* @static
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public static function createChanges($old, $new)
|
||||
{
|
||||
global $config;
|
||||
$changes = array();
|
||||
$magicQuote = get_magic_quotes_gpc();
|
||||
foreach($new as $key => $value)
|
||||
{
|
||||
if(strtolower($key) == 'lastediteddate') continue;
|
||||
if(strtolower($key) == 'lasteditedby') continue;
|
||||
if(strtolower($key) == 'assigneddate') continue;
|
||||
if(strtolower($key) == 'editedby') continue;
|
||||
if(strtolower($key) == 'editeddate') continue;
|
||||
|
||||
if($magicQuote) $value = stripslashes($value);
|
||||
if($value != stripslashes($old->$key))
|
||||
{
|
||||
$diff = '';
|
||||
if(substr_count($value, "\n") > 1 or
|
||||
substr_count($old->$key, "\n") > 1 or
|
||||
strpos('name,title,desc,spec,steps,content,digest,verify,report', strtolower($key)) !== false)
|
||||
{
|
||||
$diff = commonModel::diff($old->$key, $value);
|
||||
}
|
||||
$changes[] = array('field' => $key, 'old' => $old->$key, 'new' => $value, 'diff' => $diff);
|
||||
}
|
||||
}
|
||||
return $changes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Diff two string. (see phpt)
|
||||
*
|
||||
@@ -819,4 +1093,186 @@ class commonModel extends model
|
||||
}
|
||||
return $hasField;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check upgrade's status file is ok or not.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function checkUpgradeStatus()
|
||||
{
|
||||
$statusFile = $this->loadModel('upgrade')->checkSafeFile();
|
||||
if($statusFile)
|
||||
{
|
||||
echo "<html><head><meta http-equiv='Content-Type' content='text/html; charset=utf-8' /></head><body>";
|
||||
echo "<table align='center' style='margin-top:100px; border:1px solid gray; font-size:14px;'><tr><td>";
|
||||
printf($this->lang->upgrade->setStatusFile, $statusFile, $statusFile, $statusFile);
|
||||
die('</td></tr></table></body></html>');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the user has permission to access this method, if not, locate to the login page or deny page.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function checkPriv()
|
||||
{
|
||||
$module = $this->app->getModuleName();
|
||||
$method = $this->app->getMethodName();
|
||||
if($this->isOpenMethod($module, $method)) return true;
|
||||
if(!$this->loadModel('user')->isLogon() and $this->server->php_auth_user) $this->user->identifyByPhpAuth();
|
||||
if(!$this->loadModel('user')->isLogon() and $this->cookie->za) $this->user->identifyByCookie();
|
||||
|
||||
if(isset($this->app->user))
|
||||
{
|
||||
if(!commonModel::hasPriv($module, $method)) $this->deny($module, $method);
|
||||
}
|
||||
else
|
||||
{
|
||||
$referer = helper::safe64Encode($this->app->getURI(true));
|
||||
die(js::locate(helper::createLink('user', 'login', "referer=$referer")));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the user has permisson of one method of one module.
|
||||
*
|
||||
* @param string $module
|
||||
* @param string $method
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public static function hasPriv($module, $method)
|
||||
{
|
||||
global $app, $lang;
|
||||
|
||||
/* Check is the super admin or not. */
|
||||
$account = ',' . $app->user->account . ',';
|
||||
if(strpos($app->company->admins, $account) !== false) return true;
|
||||
|
||||
/* If not super admin, check the rights. */
|
||||
$rights = $app->user->rights['rights'];
|
||||
$acls = $app->user->rights['acls'];
|
||||
$module = strtolower($module);
|
||||
$method = strtolower($method);
|
||||
if(isset($rights[$module][$method]))
|
||||
{
|
||||
if(empty($acls['views'])) return true;
|
||||
$menu = isset($lang->menugroup->$module) ? $lang->menugroup->$module : $module;
|
||||
$menu = strtolower($menu);
|
||||
if($menu != 'qa' and !isset($lang->$menu->menu)) return true;
|
||||
if($menu == 'my' or $menu == 'index' or $module == 'tree') return true;
|
||||
if($module == 'company' and $method == 'dynamic') return true;
|
||||
if($module == 'action' and $method == 'editcomment') return true;
|
||||
if(!isset($acls['views'][$menu])) return false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether IP in white list.
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function checkIP()
|
||||
{
|
||||
$ip = $this->server->remote_addr;
|
||||
|
||||
$ipWhiteList = $this->config->ipWhiteList;
|
||||
|
||||
/* If the ip white list is '*'. */
|
||||
if($ipWhiteList == '*') return true;
|
||||
|
||||
/* The ip is same as ip in white list. */
|
||||
if($ip == $ipWhiteList) return true;
|
||||
|
||||
/* If the ip in white list is like 192.168.1.1-192.168.1.10. */
|
||||
if(strpos($ipWhiteList, '-') !== false)
|
||||
{
|
||||
list($min, $max) = explode('-', $ipWhiteList);
|
||||
$min = ip2long(trim($min));
|
||||
$max = ip2long(trim($max));
|
||||
$ip = ip2long(trim($ip));
|
||||
|
||||
return $ip >= $min and $ip <= $max;
|
||||
}
|
||||
|
||||
/* If the ip in white list is in IP/CIDR format eg 127.0.0.1/24. Thanks to zcat. */
|
||||
if(strpos($ipWhiteList, '/') == false) $ipWhiteList .= '/32';
|
||||
list($ipWhiteList, $netmask) = explode('/', $ipWhiteList, 2);
|
||||
|
||||
$ip = ip2long($ip);
|
||||
$ipWhiteList = ip2long($ipWhiteList);
|
||||
$wildcard = pow(2, (32 - $netmask)) - 1;
|
||||
$netmask = ~ $wildcard;
|
||||
|
||||
return (($ip & $netmask) == ($ipWhiteList & $netmask));
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the %s of one key of a menu by $params.
|
||||
*
|
||||
* All the menus are defined in the common's language file. But there're many dynamic params, so in the defination,
|
||||
* we used %s as placeholder. These %s should be setted in one module.
|
||||
*
|
||||
* The items of one module's menu may be an string or array. For example, please see module/common/lang.
|
||||
*
|
||||
* @param string $object the menus of one module
|
||||
* @param string $key the menu item to be replaced
|
||||
* @param string $params the params passed to the menu item
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public static function setMenuVars($menu, $key, $params)
|
||||
{
|
||||
if(is_array($params))
|
||||
{
|
||||
if(is_array($menu->$key))
|
||||
{
|
||||
$menu->$key = (object)$menu->$key;
|
||||
$menu->$key->link = vsprintf($menu->$key->link, $params);
|
||||
$menu->$key = (array)$menu->$key;
|
||||
}
|
||||
else
|
||||
{
|
||||
$menu->$key = vsprintf($menu->$key, $params);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(is_array($menu->$key))
|
||||
{
|
||||
$menu->$key = (object)$menu->$key;
|
||||
$menu->$key->link = sprintf($menu->$key->link, $params);
|
||||
$menu->$key = (array)$menu->$key;
|
||||
}
|
||||
else
|
||||
{
|
||||
$menu->$key = sprintf($menu->$key, $params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the full url of the system.
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public static function getSysURL()
|
||||
{
|
||||
$httpType = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == 'on') ? 'https' : 'http';
|
||||
$httpHost = $_SERVER['HTTP_HOST'];
|
||||
return "$httpType://$httpHost";
|
||||
}
|
||||
}
|
||||
|
||||
class common extends commonModel
|
||||
{
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#actionbox a{font-weight:normal}
|
||||
.col-side fieldset#actionbox{padding-right:5px;}
|
||||
.col-side #actionbox #historyItem li span.item{white-space:nowrap}
|
||||
.changes blockquote{font-family: monospace, serif;}
|
||||
</style>
|
||||
<script language='Javascript'>
|
||||
var fold = '<?php echo $lang->fold;?>';
|
||||
@@ -29,15 +30,15 @@ function switchChange(historyID)
|
||||
function toggleStripTags(obj)
|
||||
{
|
||||
var btn = $(obj);
|
||||
var diffTag = btn.find('.diff-all');
|
||||
var diffTag = btn.find('.icon-file-code');
|
||||
if(diffTag.length)
|
||||
{
|
||||
diffTag.removeClass('diff-all').addClass('diff-short');
|
||||
diffTag.removeClass('icon-file-code').addClass('diff-short');
|
||||
btn.attr('title', '<?php echo $lang->action->textDiff?>');
|
||||
}
|
||||
else
|
||||
{
|
||||
btn.find('.diff-short').removeClass('diff-short').addClass('diff-all');
|
||||
btn.find('.diff-short').removeClass('diff-short').addClass('icon-file-code');
|
||||
btn.attr('title', '<?php echo $lang->action->original?>');
|
||||
}
|
||||
var boxObj = $(obj).next();
|
||||
@@ -89,7 +90,7 @@ function toggleComment(actionID)
|
||||
|
||||
$(function()
|
||||
{
|
||||
var diffButton = "<a href='javascript:;' onclick='toggleStripTags(this)' class='changeDiff btn-icon' style='display:none;' title='<?php echo $lang->action->original?>'><i class='icon- diff-all'></i></a>";
|
||||
var diffButton = "<a href='javascript:;' onclick='toggleStripTags(this)' class='changeDiff btn-icon' style='display:none;' title='<?php echo $lang->action->original?>'><i class='icon- icon-file-code'></i></a>";
|
||||
var newBoxID = ''
|
||||
var oldBoxID = ''
|
||||
$('blockquote').each(function()
|
||||
@@ -146,7 +147,7 @@ $(function()
|
||||
<?php echo $this->action->printChanges($action->objectType, $action->history);?>
|
||||
</div>
|
||||
<?php if($canEditComment):?>
|
||||
<span class='pull-right comment<?php echo $action->id;?>'><?php echo html::a('javascript:toggleComment(' . $action->id . ')', '<i class="icon-pencil"></i>', '', "class='btn btn-mini'")?></span>
|
||||
<span class='pull-right comment<?php echo $action->id;?>'><?php echo html::a('javascript:toggleComment(' . $action->id . ')', '<i class="icon-pencil"></i>', '', "class='btn btn-mini' style='border:none'")?></span>
|
||||
<?php endif;?>
|
||||
<?php
|
||||
if($action->comment)
|
||||
|
||||
@@ -19,6 +19,15 @@
|
||||
</div>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
|
||||
<?php if(!isset($config->global->browserNotice)):?>
|
||||
<script>
|
||||
browserNotice = '<?php echo $lang->browserNotice?>'
|
||||
function ajaxIgnoreBrowser(){$.get(createLink('misc', 'ajaxIgnoreBrowser'));}
|
||||
$(function(){showBrowserNotice()});
|
||||
</script>
|
||||
<?php endif;?>
|
||||
|
||||
<?php
|
||||
js::set('onlybody', $onlybody); // set the onlybody var.
|
||||
if($this->loadModel('cron')->runable()) js::execute('startCron()');
|
||||
|
||||
@@ -19,23 +19,23 @@ $clientTheme = $this->app->getClientTheme();
|
||||
js::exportConfigVars();
|
||||
if($config->debug)
|
||||
{
|
||||
js::import($jsRoot . 'jquery/lib.js', $config->version);
|
||||
js::import($jsRoot . 'zui/min.js', $config->version);
|
||||
js::import($jsRoot . 'my.min.js', $config->version);
|
||||
js::import($jsRoot . 'jquery/lib.js');
|
||||
js::import($jsRoot . 'zui/min.js');
|
||||
js::import($jsRoot . 'my.min.js');
|
||||
|
||||
css::import($themeRoot . 'zui/css/min.css', $config->version);
|
||||
css::import($defaultTheme . 'style.css', $config->version);
|
||||
css::import($themeRoot . 'zui/css/min.css');
|
||||
css::import($defaultTheme . 'style.css');
|
||||
|
||||
css::import($langTheme, $config->version);
|
||||
if(strpos($clientTheme, 'default') === false) css::import($clientTheme . 'style.css', $config->version);
|
||||
css::import($langTheme);
|
||||
if(strpos($clientTheme, 'default') === false) css::import($clientTheme . 'style.css');
|
||||
}
|
||||
else
|
||||
{
|
||||
js::import($jsRoot . 'all.js', $config->version);
|
||||
css::import($defaultTheme . $this->cookie->lang . '.' . $this->cookie->theme . '.css', $config->version);
|
||||
js::import($jsRoot . 'all.js');
|
||||
css::import($defaultTheme . $this->cookie->lang . '.' . $this->cookie->theme . '.css');
|
||||
}
|
||||
|
||||
if(isset($pageCss)) css::internal($pageCss);
|
||||
if(isset($pageCSS)) css::internal($pageCSS);
|
||||
|
||||
echo html::favicon($webRoot . 'favicon.ico');
|
||||
?>
|
||||
|
||||
@@ -19,22 +19,22 @@ $clientTheme = $this->app->getClientTheme();
|
||||
js::exportConfigVars();
|
||||
if($config->debug)
|
||||
{
|
||||
js::import($jsRoot . 'jquery/mobile/jquery-1.10.1.min.js', $config->version);
|
||||
js::import($jsRoot . 'm.my.full.js', $config->version);
|
||||
js::import($jsRoot . 'jquery/mobile/jquery.mobile.min.js', $config->version);
|
||||
js::import($jsRoot . 'jquery/jquery.pjax.js', $config->version);
|
||||
js::import($jsRoot . 'jquery/mobile/jquery-1.10.1.min.js');
|
||||
js::import($jsRoot . 'm.my.full.js');
|
||||
js::import($jsRoot . 'jquery/mobile/jquery.mobile.min.js');
|
||||
js::import($jsRoot . 'jquery/jquery.pjax.js');
|
||||
|
||||
css::import($defaultTheme . 'jquery.mobile.css', $config->version);
|
||||
css::import($defaultTheme . 'm.style.css', $config->version);
|
||||
css::import($langTheme, $config->version);
|
||||
css::import($defaultTheme . 'jquery.mobile.css');
|
||||
css::import($defaultTheme . 'm.style.css');
|
||||
css::import($langTheme);
|
||||
}
|
||||
else
|
||||
{
|
||||
js::import($jsRoot . 'm.all.js', $config->version);
|
||||
css::import($defaultTheme . 'm.' . $this->cookie->lang . '.default.css', $config->version);
|
||||
js::import($jsRoot . 'm.all.js');
|
||||
css::import($defaultTheme . 'm.' . $this->cookie->lang . '.default.css');
|
||||
}
|
||||
|
||||
if(isset($pageCss)) css::internal($pageCss);
|
||||
if(isset($pageCSS)) css::internal($pageCSS);
|
||||
|
||||
echo html::favicon($webRoot . 'favicon.ico');
|
||||
?>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user