From 9ba2bbdb9e4e3154324982ec83ec3866806c0581 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BB=94=E5=93=A5?= Date: Fri, 20 Oct 2017 14:12:39 +0800 Subject: [PATCH 1/8] add database change --- db/update9.5.1.sql | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/db/update9.5.1.sql b/db/update9.5.1.sql index 88c7cd1fdb..789f54ab2e 100644 --- a/db/update9.5.1.sql +++ b/db/update9.5.1.sql @@ -27,3 +27,15 @@ CREATE TABLE IF NOT EXISTS `zt_webhook` ( `editedDate` datetime NOT NULL, PRIMARY KEY `id` (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +ALTER TABLE `zt_task` ADD `parent` INT(11) NULL DEFAULT '0' AFTER `deleted`; +ALTER TABLE `zt_team` ADD `task` INT(11) NULL DEFAULT '0' AFTER `project`; +ALTER TABLE `zt_team` ADD `estimate` DECIMAL(12,2) UNSIGNED NOT NULL DEFAULT '0'; +ALTER TABLE `zt_team` ADD `consumed` DECIMAL(12,2) UNSIGNED NOT NULL DEFAULT '0' AFTER `estimate`; +ALTER TABLE `zt_team` ADD `left` DECIMAL(12,2) UNSIGNED NOT NULL DEFAULT '0' AFTER `consumed`; +ALTER TABLE `zt_team` ADD `order` TINYINT(3) NOT NULL DEFAULT '0' AFTER `left`; +ALTER TABLE `zt_team` CHANGE `days` `days` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0'; + + +ALTER TABLE `zt_team` DROP PRIMARY KEY; +ALTER TABLE `zt_team` ADD PRIMARY KEY (`project`, `task`, `account`); \ No newline at end of file From 2cf44d57e6354f0f32ce5ef97e75703d4ad2f9cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BB=94=E5=93=A5?= Date: Fri, 20 Oct 2017 14:18:41 +0800 Subject: [PATCH 2/8] (gitignore commit and remove .idea) --- .idea/vcs.xml | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 .idea/vcs.xml diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7f4c..0000000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file From 303ad1cb7da34d7c4d3615f804c7069177e95deb Mon Sep 17 00:00:00 2001 From: lvtao320 Date: Fri, 20 Oct 2017 14:26:43 +0800 Subject: [PATCH 3/8] Update helper.class.php --- framework/helper.class.php | 8 -------- 1 file changed, 8 deletions(-) diff --git a/framework/helper.class.php b/framework/helper.class.php index dc33d2ffa0..165ba1bab1 100644 --- a/framework/helper.class.php +++ b/framework/helper.class.php @@ -141,11 +141,3 @@ function formatTime($time, $format = '') if($format) return date($format, strtotime($time)); return trim($time); } - -function b($val) -{ - echo '
';
-    print_r($val);
-    echo '
'; - exit; -} \ No newline at end of file From 984f3940c9b8a966633351a9b7e491c46242a822 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BB=94=E5=93=A5?= Date: Fri, 20 Oct 2017 14:31:55 +0800 Subject: [PATCH 4/8] change .gitignore --- .gitignore | 19 - framework/base/control.class.php | 887 ------ framework/base/helper.class.php | 747 ----- framework/base/model.class.php | 302 -- framework/base/router.class.php | 2517 ----------------- framework/control.class.php | 23 - framework/helper.class.php | 143 - framework/model.class.php | 38 - framework/router.class.php | 159 -- .../tests/helper/.101.setmember.onelevel.et | 13 - .../tests/helper/.110.setmember.multilevel.et | 6 - .../tests/helper/.201.getwebroot.inbrowse.et | 2 - .../tests/helper/.202.getwebroot.inshell.et | 8 - .../tests/helper/101.setmember.onelevel.php | 27 - .../tests/helper/110.setmember.multilevel.php | 22 - .../tests/helper/201.getwebroot.inbrowse.php | 17 - .../tests/helper/202.getwebroot.inshell.php | 43 - module/action/ext/config/.gitkeep | 0 module/action/ext/control/.gitkeep | 0 module/action/ext/css/.gitkeep | 0 module/action/ext/js/.gitkeep | 0 module/action/ext/lang/en/.gitkeep | 0 module/action/ext/lang/zh-cn/.gitkeep | 0 module/action/ext/lang/zh-tw/.gitkeep | 0 module/action/ext/model/.gitkeep | 0 module/action/ext/view/.gitkeep | 0 module/admin/ext/config/.gitkeep | 0 module/admin/ext/control/.gitkeep | 0 module/admin/ext/css/.gitkeep | 0 module/admin/ext/js/.gitkeep | 0 module/admin/ext/lang/en/.gitkeep | 0 module/admin/ext/lang/zh-cn/.gitkeep | 0 module/admin/ext/lang/zh-tw/.gitkeep | 0 module/admin/ext/model/.gitkeep | 0 module/admin/ext/view/.gitkeep | 0 module/api/ext/config/.gitkeep | 0 module/api/ext/control/.gitkeep | 0 module/api/ext/css/.gitkeep | 0 module/api/ext/js/.gitkeep | 0 module/api/ext/lang/en/.gitkeep | 0 module/api/ext/lang/zh-cn/.gitkeep | 0 module/api/ext/lang/zh-tw/.gitkeep | 0 module/api/ext/model/.gitkeep | 0 module/api/ext/view/.gitkeep | 0 module/build/ext/config/.gitkeep | 0 module/build/ext/control/.gitkeep | 0 module/build/ext/css/.gitkeep | 0 module/build/ext/js/.gitkeep | 0 module/build/ext/lang/en/.gitkeep | 0 module/build/ext/lang/zh-cn/.gitkeep | 0 module/build/ext/lang/zh-tw/.gitkeep | 0 module/build/ext/model/.gitkeep | 0 module/build/ext/view/.gitkeep | 0 module/common/ext/config/.gitkeep | 0 module/common/ext/control/.gitkeep | 0 module/common/ext/css/.gitkeep | 0 module/common/ext/js/.gitkeep | 0 module/common/ext/lang/en/.gitkeep | 0 module/common/ext/lang/zh-cn/.gitkeep | 0 module/common/ext/lang/zh-tw/.gitkeep | 0 module/common/ext/model/.gitkeep | 0 module/common/ext/view/.gitkeep | 0 module/company/ext/config/.gitkeep | 0 module/company/ext/control/.gitkeep | 0 module/company/ext/css/.gitkeep | 0 module/company/ext/js/.gitkeep | 0 module/company/ext/lang/en/.gitkeep | 0 module/company/ext/lang/zh-cn/.gitkeep | 0 module/company/ext/lang/zh-tw/.gitkeep | 0 module/company/ext/model/.gitkeep | 0 module/company/ext/view/.gitkeep | 0 module/convert/ext/config/.gitkeep | 0 module/convert/ext/control/.gitkeep | 0 module/convert/ext/css/.gitkeep | 0 module/convert/ext/js/.gitkeep | 0 module/convert/ext/lang/en/.gitkeep | 0 module/convert/ext/lang/zh-cn/.gitkeep | 0 module/convert/ext/lang/zh-tw/.gitkeep | 0 module/convert/ext/model/.gitkeep | 0 module/convert/ext/view/.gitkeep | 0 module/dept/ext/config/.gitkeep | 0 module/dept/ext/control/.gitkeep | 0 module/dept/ext/css/.gitkeep | 0 module/dept/ext/js/.gitkeep | 0 module/dept/ext/lang/en/.gitkeep | 0 module/dept/ext/lang/zh-cn/.gitkeep | 0 module/dept/ext/lang/zh-tw/.gitkeep | 0 module/dept/ext/model/.gitkeep | 0 module/dept/ext/view/.gitkeep | 0 module/doc/ext/config/.gitkeep | 0 module/doc/ext/control/.gitkeep | 0 module/doc/ext/css/.gitkeep | 0 module/doc/ext/js/.gitkeep | 0 module/doc/ext/lang/en/.gitkeep | 0 module/doc/ext/lang/zh-cn/.gitkeep | 0 module/doc/ext/lang/zh-tw/.gitkeep | 0 module/doc/ext/model/.gitkeep | 0 module/doc/ext/view/.gitkeep | 0 module/editor/ext/config/.gitkeep | 0 module/editor/ext/control/.gitkeep | 0 module/editor/ext/css/.gitkeep | 0 module/editor/ext/js/.gitkeep | 0 module/editor/ext/lang/en/.gitkeep | 0 module/editor/ext/lang/zh-cn/.gitkeep | 0 module/editor/ext/lang/zh-tw/.gitkeep | 0 module/editor/ext/model/.gitkeep | 0 module/editor/ext/view/.gitkeep | 0 module/extension/ext/config/.gitkeep | 0 module/extension/ext/control/.gitkeep | 0 module/extension/ext/css/.gitkeep | 0 module/extension/ext/js/.gitkeep | 0 module/extension/ext/lang/en/.gitkeep | 0 module/extension/ext/lang/zh-cn/.gitkeep | 0 module/extension/ext/lang/zh-tw/.gitkeep | 0 module/extension/ext/model/.gitkeep | 0 module/extension/ext/view/.gitkeep | 0 module/file/ext/config/.gitkeep | 0 module/file/ext/control/.gitkeep | 0 module/file/ext/css/.gitkeep | 0 module/file/ext/js/.gitkeep | 0 module/file/ext/lang/en/.gitkeep | 0 module/file/ext/lang/zh-cn/.gitkeep | 0 module/file/ext/lang/zh-tw/.gitkeep | 0 module/file/ext/model/.gitkeep | 0 module/file/ext/view/.gitkeep | 0 module/git/ext/config/.gitkeep | 0 module/git/ext/control/.gitkeep | 0 module/git/ext/css/.gitkeep | 0 module/git/ext/js/.gitkeep | 0 module/git/ext/lang/.gitkeep | 0 module/git/ext/model/.gitkeep | 0 module/git/ext/view/.gitkeep | 0 module/group/ext/config/.gitkeep | 0 module/group/ext/control/.gitkeep | 0 module/group/ext/css/.gitkeep | 0 module/group/ext/js/.gitkeep | 0 module/group/ext/lang/en/.gitkeep | 0 module/group/ext/lang/zh-cn/.gitkeep | 0 module/group/ext/lang/zh-tw/.gitkeep | 0 module/group/ext/model/.gitkeep | 0 module/group/ext/view/.gitkeep | 0 module/index/ext/config/.gitkeep | 0 module/index/ext/control/.gitkeep | 0 module/index/ext/css/.gitkeep | 0 module/index/ext/js/.gitkeep | 0 module/index/ext/lang/en/.gitkeep | 0 module/index/ext/lang/zh-cn/.gitkeep | 0 module/index/ext/lang/zh-tw/.gitkeep | 0 module/index/ext/model/.gitkeep | 0 module/index/ext/view/.gitkeep | 0 module/install/ext/config/.gitkeep | 0 module/install/ext/control/.gitkeep | 0 module/install/ext/css/.gitkeep | 0 module/install/ext/js/.gitkeep | 0 module/install/ext/lang/en/.gitkeep | 0 module/install/ext/lang/zh-cn/.gitkeep | 0 module/install/ext/lang/zh-tw/.gitkeep | 0 module/install/ext/model/.gitkeep | 0 module/install/ext/view/.gitkeep | 0 module/mail/ext/config/.gitkeep | 0 module/mail/ext/control/.gitkeep | 0 module/mail/ext/css/.gitkeep | 0 module/mail/ext/js/.gitkeep | 0 module/mail/ext/lang/en/.gitkeep | 0 module/mail/ext/lang/zh-cn/.gitkeep | 0 module/mail/ext/lang/zh-tw/.gitkeep | 0 module/mail/ext/model/.gitkeep | 0 module/mail/ext/view/.gitkeep | 0 module/misc/ext/config/.gitkeep | 0 module/misc/ext/control/.gitkeep | 0 module/misc/ext/css/.gitkeep | 0 module/misc/ext/js/.gitkeep | 0 module/misc/ext/lang/en/.gitkeep | 0 module/misc/ext/lang/zh-cn/.gitkeep | 0 module/misc/ext/lang/zh-tw/.gitkeep | 0 module/misc/ext/model/.gitkeep | 0 module/misc/ext/view/.gitkeep | 0 module/my/ext/config/.gitkeep | 0 module/my/ext/control/.gitkeep | 0 module/my/ext/css/.gitkeep | 0 module/my/ext/js/.gitkeep | 0 module/my/ext/lang/en/.gitkeep | 0 module/my/ext/lang/zh-cn/.gitkeep | 0 module/my/ext/lang/zh-tw/.gitkeep | 0 module/my/ext/model/.gitkeep | 0 module/my/ext/view/.gitkeep | 0 module/product/ext/config/.gitkeep | 0 module/product/ext/control/.gitkeep | 0 module/product/ext/css/.gitkeep | 0 module/product/ext/js/.gitkeep | 0 module/product/ext/lang/en/.gitkeep | 0 module/product/ext/lang/zh-cn/.gitkeep | 0 module/product/ext/lang/zh-tw/.gitkeep | 0 module/product/ext/model/.gitkeep | 0 module/product/ext/view/.gitkeep | 0 module/productplan/ext/config/.gitkeep | 0 module/productplan/ext/control/.gitkeep | 0 module/productplan/ext/css/.gitkeep | 0 module/productplan/ext/js/.gitkeep | 0 module/productplan/ext/lang/en/.gitkeep | 0 module/productplan/ext/lang/zh-cn/.gitkeep | 0 module/productplan/ext/lang/zh-tw/.gitkeep | 0 module/productplan/ext/model/.gitkeep | 0 module/productplan/ext/view/.gitkeep | 0 module/project/ext/config/.gitkeep | 0 module/project/ext/control/.gitkeep | 0 module/project/ext/css/.gitkeep | 0 module/project/ext/js/.gitkeep | 0 module/project/ext/lang/en/.gitkeep | 0 module/project/ext/lang/zh-cn/.gitkeep | 0 module/project/ext/lang/zh-tw/.gitkeep | 0 module/project/ext/model/.gitkeep | 0 module/project/ext/view/.gitkeep | 0 module/qa/ext/config/.gitkeep | 0 module/qa/ext/control/.gitkeep | 0 module/qa/ext/css/.gitkeep | 0 module/qa/ext/js/.gitkeep | 0 module/qa/ext/lang/en/.gitkeep | 0 module/qa/ext/lang/zh-cn/.gitkeep | 0 module/qa/ext/lang/zh-tw/.gitkeep | 0 module/qa/ext/model/.gitkeep | 0 module/qa/ext/view/.gitkeep | 0 module/report/ext/config/.gitkeep | 0 module/report/ext/control/.gitkeep | 0 module/report/ext/css/.gitkeep | 0 module/report/ext/js/.gitkeep | 0 module/report/ext/lang/en/.gitkeep | 0 module/report/ext/lang/zh-cn/.gitkeep | 0 module/report/ext/lang/zh-tw/.gitkeep | 0 module/report/ext/model/.gitkeep | 0 module/report/ext/view/.gitkeep | 0 module/search/ext/config/.gitkeep | 0 module/search/ext/control/.gitkeep | 0 module/search/ext/css/.gitkeep | 0 module/search/ext/js/.gitkeep | 0 module/search/ext/lang/en/.gitkeep | 0 module/search/ext/lang/zh-cn/.gitkeep | 0 module/search/ext/lang/zh-tw/.gitkeep | 0 module/search/ext/model/.gitkeep | 0 module/search/ext/view/.gitkeep | 0 module/setting/ext/config/.gitkeep | 0 module/setting/ext/control/.gitkeep | 0 module/setting/ext/css/.gitkeep | 0 module/setting/ext/js/.gitkeep | 0 module/setting/ext/lang/en/.gitkeep | 0 module/setting/ext/lang/zh-cn/.gitkeep | 0 module/setting/ext/lang/zh-tw/.gitkeep | 0 module/setting/ext/model/.gitkeep | 0 module/setting/ext/view/.gitkeep | 0 module/story/ext/config/.gitkeep | 0 module/story/ext/control/.gitkeep | 0 module/story/ext/css/.gitkeep | 0 module/story/ext/js/.gitkeep | 0 module/story/ext/lang/en/.gitkeep | 0 module/story/ext/lang/zh-cn/.gitkeep | 0 module/story/ext/lang/zh-tw/.gitkeep | 0 module/story/ext/model/.gitkeep | 0 module/story/ext/view/.gitkeep | 0 module/svn/ext/config/.gitkeep | 0 module/svn/ext/control/.gitkeep | 0 module/svn/ext/css/.gitkeep | 0 module/svn/ext/js/.gitkeep | 0 module/svn/ext/lang/en/.gitkeep | 0 module/svn/ext/lang/zh-cn/.gitkeep | 0 module/svn/ext/lang/zh-tw/.gitkeep | 0 module/svn/ext/model/.gitkeep | 0 module/svn/ext/view/.gitkeep | 0 module/testcase/ext/config/.gitkeep | 0 module/testcase/ext/control/.gitkeep | 0 module/testcase/ext/css/.gitkeep | 0 module/testcase/ext/js/.gitkeep | 0 module/testcase/ext/lang/en/.gitkeep | 0 module/testcase/ext/lang/zh-cn/.gitkeep | 0 module/testcase/ext/lang/zh-tw/.gitkeep | 0 module/testcase/ext/model/.gitkeep | 0 module/testcase/ext/view/.gitkeep | 0 module/testtask/ext/config/.gitkeep | 0 module/testtask/ext/control/.gitkeep | 0 module/testtask/ext/css/.gitkeep | 0 module/testtask/ext/js/.gitkeep | 0 module/testtask/ext/lang/en/.gitkeep | 0 module/testtask/ext/lang/zh-cn/.gitkeep | 0 module/testtask/ext/lang/zh-tw/.gitkeep | 0 module/testtask/ext/model/.gitkeep | 0 module/testtask/ext/view/.gitkeep | 0 module/todo/ext/config/.gitkeep | 0 module/todo/ext/control/.gitkeep | 0 module/todo/ext/css/.gitkeep | 0 module/todo/ext/js/.gitkeep | 0 module/todo/ext/lang/en/.gitkeep | 0 module/todo/ext/lang/zh-cn/.gitkeep | 0 module/todo/ext/lang/zh-tw/.gitkeep | 0 module/todo/ext/model/.gitkeep | 0 module/todo/ext/view/.gitkeep | 0 module/tree/ext/config/.gitkeep | 0 module/tree/ext/control/.gitkeep | 0 module/tree/ext/css/.gitkeep | 0 module/tree/ext/js/.gitkeep | 0 module/tree/ext/lang/en/.gitkeep | 0 module/tree/ext/lang/zh-cn/.gitkeep | 0 module/tree/ext/lang/zh-tw/.gitkeep | 0 module/tree/ext/model/.gitkeep | 0 module/tree/ext/view/.gitkeep | 0 module/upgrade/ext/config/.gitkeep | 0 module/upgrade/ext/control/.gitkeep | 0 module/upgrade/ext/css/.gitkeep | 0 module/upgrade/ext/js/.gitkeep | 0 module/upgrade/ext/lang/en/.gitkeep | 0 module/upgrade/ext/lang/zh-cn/.gitkeep | 0 module/upgrade/ext/lang/zh-tw/.gitkeep | 0 module/upgrade/ext/model/.gitkeep | 0 module/upgrade/ext/view/.gitkeep | 0 module/user/ext/config/.gitkeep | 0 module/user/ext/control/.gitkeep | 0 module/user/ext/css/.gitkeep | 0 module/user/ext/js/.gitkeep | 0 module/user/ext/lang/en/.gitkeep | 0 module/user/ext/lang/zh-cn/.gitkeep | 0 module/user/ext/lang/zh-tw/.gitkeep | 0 module/user/ext/model/.gitkeep | 0 module/user/ext/view/.gitkeep | 0 tmp/cache/.gitkeep | 0 tmp/extension/.gitkeep | 0 tmp/log/.gitkeep | 0 tmp/model/.gitkeep | 0 tools/check.php | 259 -- tools/cn2tw.php | 18 - tools/copylang.php | 17 - tools/exportactions.php | 29 - tools/getallcommon.php | 28 - tools/initext.php | 73 - tools/minifyfront.php | 74 - tools/preparetest.php | 60 - tools/replace.sh | 17 - tools/syncext.php | 100 - tools/syncext.sh | 62 - tools/zdog.sh | 39 - 337 files changed, 5749 deletions(-) delete mode 100644 .gitignore delete mode 100644 framework/base/control.class.php delete mode 100644 framework/base/helper.class.php delete mode 100644 framework/base/model.class.php delete mode 100644 framework/base/router.class.php delete mode 100644 framework/control.class.php delete mode 100644 framework/helper.class.php delete mode 100644 framework/model.class.php delete mode 100755 framework/router.class.php delete mode 100644 framework/tests/helper/.101.setmember.onelevel.et delete mode 100644 framework/tests/helper/.110.setmember.multilevel.et delete mode 100644 framework/tests/helper/.201.getwebroot.inbrowse.et delete mode 100644 framework/tests/helper/.202.getwebroot.inshell.et delete mode 100755 framework/tests/helper/101.setmember.onelevel.php delete mode 100755 framework/tests/helper/110.setmember.multilevel.php delete mode 100755 framework/tests/helper/201.getwebroot.inbrowse.php delete mode 100755 framework/tests/helper/202.getwebroot.inshell.php delete mode 100755 module/action/ext/config/.gitkeep delete mode 100755 module/action/ext/control/.gitkeep delete mode 100755 module/action/ext/css/.gitkeep delete mode 100755 module/action/ext/js/.gitkeep delete mode 100755 module/action/ext/lang/en/.gitkeep delete mode 100755 module/action/ext/lang/zh-cn/.gitkeep delete mode 100755 module/action/ext/lang/zh-tw/.gitkeep delete mode 100755 module/action/ext/model/.gitkeep delete mode 100755 module/action/ext/view/.gitkeep delete mode 100644 module/admin/ext/config/.gitkeep delete mode 100644 module/admin/ext/control/.gitkeep delete mode 100644 module/admin/ext/css/.gitkeep delete mode 100644 module/admin/ext/js/.gitkeep delete mode 100644 module/admin/ext/lang/en/.gitkeep delete mode 100644 module/admin/ext/lang/zh-cn/.gitkeep delete mode 100644 module/admin/ext/lang/zh-tw/.gitkeep delete mode 100644 module/admin/ext/model/.gitkeep delete mode 100644 module/admin/ext/view/.gitkeep delete mode 100644 module/api/ext/config/.gitkeep delete mode 100644 module/api/ext/control/.gitkeep delete mode 100644 module/api/ext/css/.gitkeep delete mode 100644 module/api/ext/js/.gitkeep delete mode 100644 module/api/ext/lang/en/.gitkeep delete mode 100644 module/api/ext/lang/zh-cn/.gitkeep delete mode 100644 module/api/ext/lang/zh-tw/.gitkeep delete mode 100644 module/api/ext/model/.gitkeep delete mode 100644 module/api/ext/view/.gitkeep delete mode 100644 module/build/ext/config/.gitkeep delete mode 100755 module/build/ext/control/.gitkeep delete mode 100644 module/build/ext/css/.gitkeep delete mode 100644 module/build/ext/js/.gitkeep delete mode 100755 module/build/ext/lang/en/.gitkeep delete mode 100755 module/build/ext/lang/zh-cn/.gitkeep delete mode 100644 module/build/ext/lang/zh-tw/.gitkeep delete mode 100755 module/build/ext/model/.gitkeep delete mode 100755 module/build/ext/view/.gitkeep delete mode 100644 module/common/ext/config/.gitkeep delete mode 100644 module/common/ext/control/.gitkeep delete mode 100644 module/common/ext/css/.gitkeep delete mode 100644 module/common/ext/js/.gitkeep delete mode 100755 module/common/ext/lang/en/.gitkeep delete mode 100755 module/common/ext/lang/zh-cn/.gitkeep delete mode 100644 module/common/ext/lang/zh-tw/.gitkeep delete mode 100644 module/common/ext/model/.gitkeep delete mode 100644 module/common/ext/view/.gitkeep delete mode 100644 module/company/ext/config/.gitkeep delete mode 100644 module/company/ext/control/.gitkeep delete mode 100644 module/company/ext/css/.gitkeep delete mode 100644 module/company/ext/js/.gitkeep delete mode 100644 module/company/ext/lang/en/.gitkeep delete mode 100644 module/company/ext/lang/zh-cn/.gitkeep delete mode 100644 module/company/ext/lang/zh-tw/.gitkeep delete mode 100644 module/company/ext/model/.gitkeep delete mode 100644 module/company/ext/view/.gitkeep delete mode 100644 module/convert/ext/config/.gitkeep delete mode 100644 module/convert/ext/control/.gitkeep delete mode 100644 module/convert/ext/css/.gitkeep delete mode 100644 module/convert/ext/js/.gitkeep delete mode 100644 module/convert/ext/lang/en/.gitkeep delete mode 100644 module/convert/ext/lang/zh-cn/.gitkeep delete mode 100644 module/convert/ext/lang/zh-tw/.gitkeep delete mode 100644 module/convert/ext/model/.gitkeep delete mode 100644 module/convert/ext/view/.gitkeep delete mode 100644 module/dept/ext/config/.gitkeep delete mode 100644 module/dept/ext/control/.gitkeep delete mode 100644 module/dept/ext/css/.gitkeep delete mode 100644 module/dept/ext/js/.gitkeep delete mode 100644 module/dept/ext/lang/en/.gitkeep delete mode 100644 module/dept/ext/lang/zh-cn/.gitkeep delete mode 100644 module/dept/ext/lang/zh-tw/.gitkeep delete mode 100644 module/dept/ext/model/.gitkeep delete mode 100644 module/dept/ext/view/.gitkeep delete mode 100644 module/doc/ext/config/.gitkeep delete mode 100644 module/doc/ext/control/.gitkeep delete mode 100644 module/doc/ext/css/.gitkeep delete mode 100644 module/doc/ext/js/.gitkeep delete mode 100755 module/doc/ext/lang/en/.gitkeep delete mode 100755 module/doc/ext/lang/zh-cn/.gitkeep delete mode 100644 module/doc/ext/lang/zh-tw/.gitkeep delete mode 100644 module/doc/ext/model/.gitkeep delete mode 100644 module/doc/ext/view/.gitkeep delete mode 100644 module/editor/ext/config/.gitkeep delete mode 100644 module/editor/ext/control/.gitkeep delete mode 100644 module/editor/ext/css/.gitkeep delete mode 100644 module/editor/ext/js/.gitkeep delete mode 100644 module/editor/ext/lang/en/.gitkeep delete mode 100644 module/editor/ext/lang/zh-cn/.gitkeep delete mode 100644 module/editor/ext/lang/zh-tw/.gitkeep delete mode 100644 module/editor/ext/model/.gitkeep delete mode 100644 module/editor/ext/view/.gitkeep delete mode 100755 module/extension/ext/config/.gitkeep delete mode 100755 module/extension/ext/control/.gitkeep delete mode 100755 module/extension/ext/css/.gitkeep delete mode 100755 module/extension/ext/js/.gitkeep delete mode 100755 module/extension/ext/lang/en/.gitkeep delete mode 100755 module/extension/ext/lang/zh-cn/.gitkeep delete mode 100755 module/extension/ext/lang/zh-tw/.gitkeep delete mode 100755 module/extension/ext/model/.gitkeep delete mode 100755 module/extension/ext/view/.gitkeep delete mode 100644 module/file/ext/config/.gitkeep delete mode 100644 module/file/ext/control/.gitkeep delete mode 100644 module/file/ext/css/.gitkeep delete mode 100644 module/file/ext/js/.gitkeep delete mode 100644 module/file/ext/lang/en/.gitkeep delete mode 100644 module/file/ext/lang/zh-cn/.gitkeep delete mode 100644 module/file/ext/lang/zh-tw/.gitkeep delete mode 100644 module/file/ext/model/.gitkeep delete mode 100644 module/file/ext/view/.gitkeep delete mode 100644 module/git/ext/config/.gitkeep delete mode 100644 module/git/ext/control/.gitkeep delete mode 100644 module/git/ext/css/.gitkeep delete mode 100644 module/git/ext/js/.gitkeep delete mode 100644 module/git/ext/lang/.gitkeep delete mode 100644 module/git/ext/model/.gitkeep delete mode 100644 module/git/ext/view/.gitkeep delete mode 100644 module/group/ext/config/.gitkeep delete mode 100644 module/group/ext/control/.gitkeep delete mode 100644 module/group/ext/css/.gitkeep delete mode 100644 module/group/ext/js/.gitkeep delete mode 100755 module/group/ext/lang/en/.gitkeep delete mode 100755 module/group/ext/lang/zh-cn/.gitkeep delete mode 100644 module/group/ext/lang/zh-tw/.gitkeep delete mode 100644 module/group/ext/model/.gitkeep delete mode 100644 module/group/ext/view/.gitkeep delete mode 100644 module/index/ext/config/.gitkeep delete mode 100644 module/index/ext/control/.gitkeep delete mode 100644 module/index/ext/css/.gitkeep delete mode 100644 module/index/ext/js/.gitkeep delete mode 100644 module/index/ext/lang/en/.gitkeep delete mode 100644 module/index/ext/lang/zh-cn/.gitkeep delete mode 100644 module/index/ext/lang/zh-tw/.gitkeep delete mode 100644 module/index/ext/model/.gitkeep delete mode 100644 module/index/ext/view/.gitkeep delete mode 100644 module/install/ext/config/.gitkeep delete mode 100644 module/install/ext/control/.gitkeep delete mode 100644 module/install/ext/css/.gitkeep delete mode 100644 module/install/ext/js/.gitkeep delete mode 100644 module/install/ext/lang/en/.gitkeep delete mode 100644 module/install/ext/lang/zh-cn/.gitkeep delete mode 100644 module/install/ext/lang/zh-tw/.gitkeep delete mode 100644 module/install/ext/model/.gitkeep delete mode 100644 module/install/ext/view/.gitkeep delete mode 100644 module/mail/ext/config/.gitkeep delete mode 100644 module/mail/ext/control/.gitkeep delete mode 100644 module/mail/ext/css/.gitkeep delete mode 100644 module/mail/ext/js/.gitkeep delete mode 100644 module/mail/ext/lang/en/.gitkeep delete mode 100644 module/mail/ext/lang/zh-cn/.gitkeep delete mode 100644 module/mail/ext/lang/zh-tw/.gitkeep delete mode 100644 module/mail/ext/model/.gitkeep delete mode 100644 module/mail/ext/view/.gitkeep delete mode 100644 module/misc/ext/config/.gitkeep delete mode 100644 module/misc/ext/control/.gitkeep delete mode 100644 module/misc/ext/css/.gitkeep delete mode 100644 module/misc/ext/js/.gitkeep delete mode 100644 module/misc/ext/lang/en/.gitkeep delete mode 100644 module/misc/ext/lang/zh-cn/.gitkeep delete mode 100644 module/misc/ext/lang/zh-tw/.gitkeep delete mode 100644 module/misc/ext/model/.gitkeep delete mode 100644 module/misc/ext/view/.gitkeep delete mode 100755 module/my/ext/config/.gitkeep delete mode 100755 module/my/ext/control/.gitkeep delete mode 100644 module/my/ext/css/.gitkeep delete mode 100644 module/my/ext/js/.gitkeep delete mode 100755 module/my/ext/lang/en/.gitkeep delete mode 100755 module/my/ext/lang/zh-cn/.gitkeep delete mode 100644 module/my/ext/lang/zh-tw/.gitkeep delete mode 100644 module/my/ext/model/.gitkeep delete mode 100755 module/my/ext/view/.gitkeep delete mode 100644 module/product/ext/config/.gitkeep delete mode 100755 module/product/ext/control/.gitkeep delete mode 100644 module/product/ext/css/.gitkeep delete mode 100644 module/product/ext/js/.gitkeep delete mode 100755 module/product/ext/lang/en/.gitkeep delete mode 100755 module/product/ext/lang/zh-cn/.gitkeep delete mode 100644 module/product/ext/lang/zh-tw/.gitkeep delete mode 100755 module/product/ext/model/.gitkeep delete mode 100755 module/product/ext/view/.gitkeep delete mode 100644 module/productplan/ext/config/.gitkeep delete mode 100644 module/productplan/ext/control/.gitkeep delete mode 100644 module/productplan/ext/css/.gitkeep delete mode 100644 module/productplan/ext/js/.gitkeep delete mode 100644 module/productplan/ext/lang/en/.gitkeep delete mode 100644 module/productplan/ext/lang/zh-cn/.gitkeep delete mode 100644 module/productplan/ext/lang/zh-tw/.gitkeep delete mode 100644 module/productplan/ext/model/.gitkeep delete mode 100644 module/productplan/ext/view/.gitkeep delete mode 100644 module/project/ext/config/.gitkeep delete mode 100644 module/project/ext/control/.gitkeep delete mode 100644 module/project/ext/css/.gitkeep delete mode 100644 module/project/ext/js/.gitkeep delete mode 100644 module/project/ext/lang/en/.gitkeep delete mode 100644 module/project/ext/lang/zh-cn/.gitkeep delete mode 100644 module/project/ext/lang/zh-tw/.gitkeep delete mode 100644 module/project/ext/model/.gitkeep delete mode 100644 module/project/ext/view/.gitkeep delete mode 100644 module/qa/ext/config/.gitkeep delete mode 100644 module/qa/ext/control/.gitkeep delete mode 100644 module/qa/ext/css/.gitkeep delete mode 100644 module/qa/ext/js/.gitkeep delete mode 100644 module/qa/ext/lang/en/.gitkeep delete mode 100644 module/qa/ext/lang/zh-cn/.gitkeep delete mode 100644 module/qa/ext/lang/zh-tw/.gitkeep delete mode 100644 module/qa/ext/model/.gitkeep delete mode 100644 module/qa/ext/view/.gitkeep delete mode 100644 module/report/ext/config/.gitkeep delete mode 100755 module/report/ext/control/.gitkeep delete mode 100644 module/report/ext/css/.gitkeep delete mode 100644 module/report/ext/js/.gitkeep delete mode 100644 module/report/ext/lang/en/.gitkeep delete mode 100755 module/report/ext/lang/zh-cn/.gitkeep delete mode 100644 module/report/ext/lang/zh-tw/.gitkeep delete mode 100755 module/report/ext/model/.gitkeep delete mode 100755 module/report/ext/view/.gitkeep delete mode 100644 module/search/ext/config/.gitkeep delete mode 100644 module/search/ext/control/.gitkeep delete mode 100644 module/search/ext/css/.gitkeep delete mode 100644 module/search/ext/js/.gitkeep delete mode 100644 module/search/ext/lang/en/.gitkeep delete mode 100644 module/search/ext/lang/zh-cn/.gitkeep delete mode 100644 module/search/ext/lang/zh-tw/.gitkeep delete mode 100644 module/search/ext/model/.gitkeep delete mode 100644 module/search/ext/view/.gitkeep delete mode 100644 module/setting/ext/config/.gitkeep delete mode 100644 module/setting/ext/control/.gitkeep delete mode 100644 module/setting/ext/css/.gitkeep delete mode 100644 module/setting/ext/js/.gitkeep delete mode 100644 module/setting/ext/lang/en/.gitkeep delete mode 100644 module/setting/ext/lang/zh-cn/.gitkeep delete mode 100644 module/setting/ext/lang/zh-tw/.gitkeep delete mode 100644 module/setting/ext/model/.gitkeep delete mode 100644 module/setting/ext/view/.gitkeep delete mode 100644 module/story/ext/config/.gitkeep delete mode 100644 module/story/ext/control/.gitkeep delete mode 100644 module/story/ext/css/.gitkeep delete mode 100644 module/story/ext/js/.gitkeep delete mode 100644 module/story/ext/lang/en/.gitkeep delete mode 100644 module/story/ext/lang/zh-cn/.gitkeep delete mode 100644 module/story/ext/lang/zh-tw/.gitkeep delete mode 100644 module/story/ext/model/.gitkeep delete mode 100644 module/story/ext/view/.gitkeep delete mode 100644 module/svn/ext/config/.gitkeep delete mode 100644 module/svn/ext/control/.gitkeep delete mode 100644 module/svn/ext/css/.gitkeep delete mode 100644 module/svn/ext/js/.gitkeep delete mode 100644 module/svn/ext/lang/en/.gitkeep delete mode 100644 module/svn/ext/lang/zh-cn/.gitkeep delete mode 100644 module/svn/ext/lang/zh-tw/.gitkeep delete mode 100644 module/svn/ext/model/.gitkeep delete mode 100644 module/svn/ext/view/.gitkeep delete mode 100644 module/testcase/ext/config/.gitkeep delete mode 100644 module/testcase/ext/control/.gitkeep delete mode 100644 module/testcase/ext/css/.gitkeep delete mode 100644 module/testcase/ext/js/.gitkeep delete mode 100644 module/testcase/ext/lang/en/.gitkeep delete mode 100644 module/testcase/ext/lang/zh-cn/.gitkeep delete mode 100644 module/testcase/ext/lang/zh-tw/.gitkeep delete mode 100644 module/testcase/ext/model/.gitkeep delete mode 100755 module/testcase/ext/view/.gitkeep delete mode 100644 module/testtask/ext/config/.gitkeep delete mode 100644 module/testtask/ext/control/.gitkeep delete mode 100644 module/testtask/ext/css/.gitkeep delete mode 100644 module/testtask/ext/js/.gitkeep delete mode 100644 module/testtask/ext/lang/en/.gitkeep delete mode 100644 module/testtask/ext/lang/zh-cn/.gitkeep delete mode 100644 module/testtask/ext/lang/zh-tw/.gitkeep delete mode 100644 module/testtask/ext/model/.gitkeep delete mode 100755 module/testtask/ext/view/.gitkeep delete mode 100644 module/todo/ext/config/.gitkeep delete mode 100644 module/todo/ext/control/.gitkeep delete mode 100644 module/todo/ext/css/.gitkeep delete mode 100644 module/todo/ext/js/.gitkeep delete mode 100644 module/todo/ext/lang/en/.gitkeep delete mode 100644 module/todo/ext/lang/zh-cn/.gitkeep delete mode 100644 module/todo/ext/lang/zh-tw/.gitkeep delete mode 100644 module/todo/ext/model/.gitkeep delete mode 100644 module/todo/ext/view/.gitkeep delete mode 100644 module/tree/ext/config/.gitkeep delete mode 100644 module/tree/ext/control/.gitkeep delete mode 100644 module/tree/ext/css/.gitkeep delete mode 100644 module/tree/ext/js/.gitkeep delete mode 100644 module/tree/ext/lang/en/.gitkeep delete mode 100644 module/tree/ext/lang/zh-cn/.gitkeep delete mode 100644 module/tree/ext/lang/zh-tw/.gitkeep delete mode 100644 module/tree/ext/model/.gitkeep delete mode 100755 module/tree/ext/view/.gitkeep delete mode 100644 module/upgrade/ext/config/.gitkeep delete mode 100644 module/upgrade/ext/control/.gitkeep delete mode 100644 module/upgrade/ext/css/.gitkeep delete mode 100644 module/upgrade/ext/js/.gitkeep delete mode 100644 module/upgrade/ext/lang/en/.gitkeep delete mode 100644 module/upgrade/ext/lang/zh-cn/.gitkeep delete mode 100644 module/upgrade/ext/lang/zh-tw/.gitkeep delete mode 100644 module/upgrade/ext/model/.gitkeep delete mode 100644 module/upgrade/ext/view/.gitkeep delete mode 100644 module/user/ext/config/.gitkeep delete mode 100755 module/user/ext/control/.gitkeep delete mode 100644 module/user/ext/css/.gitkeep delete mode 100644 module/user/ext/js/.gitkeep delete mode 100644 module/user/ext/lang/en/.gitkeep delete mode 100644 module/user/ext/lang/zh-cn/.gitkeep delete mode 100644 module/user/ext/lang/zh-tw/.gitkeep delete mode 100644 module/user/ext/model/.gitkeep delete mode 100755 module/user/ext/view/.gitkeep delete mode 100755 tmp/cache/.gitkeep delete mode 100755 tmp/extension/.gitkeep delete mode 100755 tmp/log/.gitkeep delete mode 100755 tmp/model/.gitkeep delete mode 100755 tools/check.php delete mode 100755 tools/cn2tw.php delete mode 100755 tools/copylang.php delete mode 100755 tools/exportactions.php delete mode 100755 tools/getallcommon.php delete mode 100755 tools/initext.php delete mode 100755 tools/minifyfront.php delete mode 100755 tools/preparetest.php delete mode 100755 tools/replace.sh delete mode 100755 tools/syncext.php delete mode 100755 tools/syncext.sh delete mode 100755 tools/zdog.sh diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 1a682f8be0..0000000000 --- a/.gitignore +++ /dev/null @@ -1,19 +0,0 @@ -config/my.php -www/data/ -www/install.php -www/upgrade.php -www/ok.txt -tools/* -release/* -tmp/* -tmp/extensions/* -tmp/log/* -tmp/model/* -tmp/cache/* -tmp/extension/* -.gitkeep -.bak -.idea -.gitignore -_log -framework/ \ No newline at end of file diff --git a/framework/base/control.class.php b/framework/base/control.class.php deleted file mode 100644 index 23dde557c2..0000000000 --- a/framework/base/control.class.php +++ /dev/null @@ -1,887 +0,0 @@ -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; - - global $loadedModels; - if(isset($loadedModels[$appName][$moduleName])) - { - $this->$moduleName = $loadedModels[$appName][$moduleName]; - $this->dao = $this->$moduleName->dao; - return $this->$moduleName; - } - - $modelFile = $this->app->setModelFile($moduleName, $appName); - - /** - * 如果没有model文件,尝试加载config配置信息。 - * If no model file, try load config. - */ - if(!helper::import($modelFile)) - { - $this->app->loadModuleConfig($moduleName, $appName); - $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. - */ - $loadedModels[$appName][$moduleName] = new $modelClass($appName); - $this->$moduleName = $loadedModels[$appName][$moduleName]; - $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; - } - - /** - * 设置客户端的设备类型。 - * 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'; - $viewFile = $mainViewFile; - - if(!empty($viewExtPath)) - { - $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->app->siteCode) - { - $extPath = dirname(dirname(realpath($viewFile))) . "/ext/_{$this->app->siteCode}/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') ; - - $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); - - if(!empty($cssExtPath)) - { - $cssMethodExt = $cssExtPath['common'] . $methodName . DS; - $cssCommonExt = $cssExtPath['common'] . '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); - - 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'); - - $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); - - if(!empty($jsExtPath)) - { - $jsMethodExt = $jsExtPath['common'] . $methodName . DS; - $jsCommonExt = $jsExtPath['common'] . '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); - - 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 the module name is empty, then use the current module and method. - */ - 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; - } - - $currentModuleName = $this->moduleName; - $currentMethodName = $this->methodName; - $currentAppName = $this->appName; - $currentParams = $this->app->getParams(); - - /** - * 设置调用指定模块的指定方法。 - * chang the dir to the previous. - */ - $this->app->setModuleName($moduleName); - $this->app->setMethodName($methodName); - - if(!is_array($params)) parse_str($params, $params); - $this->app->params = $params; - - $currentPWD = getcwd(); - - /** - * 设置引用的文件和路径。 - * Set the pathes and files to included. - */ - $modulePath = $this->app->getModulePath($appName, $moduleName); - $moduleControlFile = $modulePath . 'control.php'; - $actionExtPath = $this->app->getModuleExtPath($appName, $moduleName, 'control'); - $file2Included = $moduleControlFile; - - if(!empty($actionExtPath)) - { - /** - * 设置公共扩展。 - * set common extension. - */ - $commonActionExtFile = $actionExtPath['common'] . strtolower($methodName) . '.php'; - $file2Included = file_exists($commonActionExtFile) ? $commonActionExtFile : $moduleControlFile; - - if(!empty($actionExtPath['site'])) - { - /** - * 设置站点扩展。 - * every site has it's extension. - */ - $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); - 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. - */ - $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(); - - unset($module); - - /** - * 切换回之前的模块和方法。 - * Chang the module、method to the previous. - */ - $this->app->setModuleName($currentModuleName); - $this->app->setMethodName($currentMethodName); - $this->app->params = $currentParams; - - chdir($currentPWD); - - /** - * 返回内容。 - * Return the content. - */ - 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() or $this->viewType == 'json') 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; - } -} diff --git a/framework/base/helper.class.php b/framework/base/helper.class.php deleted file mode 100644 index 9066ccc455..0000000000 --- a/framework/base/helper.class.php +++ /dev/null @@ -1,747 +0,0 @@ - - * db->user = 'wwccss'; - * helper::setMember('lang', 'db.user', 'chunsheng.wang'); - * ?> - * - * @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(<< - * 'value1', 'var2' => 'value2'); - * ?> - * - * @param string $moduleName module name, can pass appName like app.module. - * @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 bool $onlyBody pass onlyBody=yes to the link thus the app can control the header and footer hide or show.. - * @static - * @access public - * @return string the link string. - */ - static public function createLink($moduleName, $methodName = 'index', $vars = '', $viewType = '', $onlyBody = false) - { - /* 设置$appName和$moduleName。Set appName and moduleName. */ - global $app, $config; - if(strpos($moduleName, '.') !== false) - { - list($appName, $moduleName) = explode('.', $moduleName); - } - else - { - $appName = $app->getAppName(); - } - if(!empty($appName)) $appName .= '/'; - - /* 处理$viewType和$vars。Set $viewType and $vars. */ - if(empty($viewType)) $viewType = $app->getViewType(); - if(!is_array($vars)) parse_str($vars, $vars); - - /* 生成url链接的开始部分。Set the begin parts of the link. */ - if($config->requestType == 'PATH_INFO') $link = $config->webRoot . $appName; - if($config->requestType != 'PATH_INFO') $link = $config->webRoot . $appName . basename($_SERVER['SCRIPT_NAME']); - if($config->requestType == 'PATH_INFO2') $link .= '/'; - - /** - * #1: RequestType为GET。When the requestType is GET. - * Input: moduleName=article&methodName=index&var1=value1. Output: ?m=article&f=index&var1=value1. - * - */ - if($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"; - return self::processOnlyBodyParam($link, $onlyBody); - } - - /** - * #2: 方法名不是默认值或者是默认值,但有传参。MethodName equals the default method or vars not empty. - * Input: moduleName=article&methodName=view. Output: article-view.html - * Input: moduleName=article&methodName=view. Output: article-index-abc.html - * - */ - if($methodName != $config->default->method or !empty($vars)) - { - $link .= "$moduleName{$config->requestFix}$methodName"; - foreach($vars as $value) $link .= "{$config->requestFix}$value"; - $link .= '.' . $viewType; - - return self::processOnlyBodyParam($link, $onlyBody); - } - - /** - * #3: 方法名为默认值且没有传参且模块名为默认值。MethodName is the default and moduleName is default and vars empty. - * Input: moduleName=index&methodName=index. Output: index.html - * - */ - if($moduleName == $config->default->module) - { - $link .= $config->default->method . '.' . $viewType; - return self::processOnlyBodyParam($link, $onlyBody); - } - - /** - * #4: 方法名为默认值且没有传参且模块名不为默认值,viewType和app指定的相等。MethodName is default but moduleName not and viewType equal app's viewType.. - * Input: moduleName=article&methodName=index&viewType=html. Output: /article/ - * - */ - if($viewType == $app->getViewType()) - { - $link .= $moduleName . '/'; - return self::processOnlyBodyParam($link, $onlyBody); - } - - /** - * #5: 方法名为默认值且没有传参且模块名不为默认值,viewType有另外指定。MethodName is default but moduleName not and viewType no equls app's viewType. - * Input: moduleName=article&methodName=index&viewType=json. Output: /article.json - * - */ - $link .= $moduleName . '.' . $viewType; - return self::processOnlyBodyParam($link, $onlyBody); - } - - /** - * 处理onlyBody 参数。 - * Process the onlyBody param in url. - * - * 如果传参的时候设定了$onlyBody为真,或者当前页面请求中包含了onlybody=yes,在生成链接的时候继续追加。 - * If $onlyBody set to true or onlybody=yes in the url, append onlyBody param to the link. - * - * @param string $link - * @param bool $onlyBody - * @static - * @access public - * @return string - */ - public static function processOnlyBodyParam($link, $onlyBody = false) - { - global $config; - if(!$onlyBody and !self::inOnlyBodyMode()) return $link; - $onlybodyString = $config->requestType != 'GET' ? "?onlybody=yes" : "&onlybody=yes"; - return $link . $onlybodyString; - } - - /** - * 检查是否是onlybody模式。 - * Check in only body mode or not. - * - * @access public - * @return void - */ - public static function inOnlyBodyMode() - { - return (isset($_GET['onlybody']) and $_GET['onlybody'] == 'yes'); - } - - /** - * 使用helper::import()来引入文件,不要直接使用include或者require. - * Using helper::import() to import a file, instead of include or require. - * - * @param string $file the file to be imported. - * @static - * @access public - * @return bool - */ - static public function import($file) - { - if(!is_file($file)) return false; - - static $includedFiles = array(); - if(!isset($includedFiles[$file])) - { - include $file; - $includedFiles[$file] = true; - return true; - } - - return true; - } - - /** - * 将数组或者列表转化成 IN( 'a', 'b') 的形式。 - * Convert a list to IN('a', 'b') string. - * - * @param string|array $idList 列表,可以是数组或者用逗号隔开的列表。The id lists, can be a array or a string joined with comma. - * @static - * @access public - * @return string the string like IN('a', 'b'). - */ - static public function dbIN($idList) - { - if(is_array($idList)) - { - if(!function_exists('get_magic_quotes_gpc') or !get_magic_quotes_gpc()) - { - foreach ($idList as $key=>$value) $idList[$key] = addslashes($value); - } - return "IN ('" . join("','", $idList) . "')"; - } - - if(!function_exists('get_magic_quotes_gpc') or !get_magic_quotes_gpc()) $idList = addslashes($idList); - return "IN ('" . str_replace(',', "','", str_replace(' ', '', $idList)) . "')"; - } - - /** - * 安全的Base64编码,框架对'/'字符比较敏感,转换为'.'。 - * 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), '/', '.'); - } - - /** - * 解码base64,先将之前的'.' 转换回'/' - * 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, '.', '/')); - } - - /** - * JSON编码,自动处理转义的问题。 - * JSON encode, process the slashes. - * - * @param mixed $data the object to encode - * @static - * @access public - * @return string decoded string. - */ - static public function jsonEncode($data) - { - return (function_exists('get_magic_quotes_gpc') and get_magic_quotes_gpc()) ? addslashes(json_encode($data)) : json_encode($data); - } - - /** - * 判断是否是utf8编码 - * Judge a string is utf-8 or not. - * - * @author hmdker@gmail.com - * @param string $string - * @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; - } - - /** - * 去掉UTF-8 Bom头。 - * Remove UTF-8 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; - } - - /** - * 增强substr方法:支持多字节语言,比如中文。 - * Enhanced substr version: support multibyte languages like Chinese. - * - * @param string $string - * @param int $length - * @param string $append - * @return string - */ - public static function substr($string, $length, $append = '') - { - $rawString = $string; - - if(function_exists('mb_substr')) $string = mb_substr($string, 0, $length, 'utf-8'); - - preg_match_all("/./su", $string, $data); - $string = join("", array_slice($data[0], 0, $length)); - - return ($string != $rawString) ? $string . $append : $string; - } - - /** - * Get browser name and version. - * - * @access public - * @return array - */ - public static function getBrowser() - { - $browser = array('name'=>'unknown', 'version'=>'unknown'); - - if(empty($_SERVER['HTTP_USER_AGENT'])) return $browser; - - $agent = $_SERVER["HTTP_USER_AGENT"]; - - /* Chrome should checked before safari.*/ - if(strpos($agent, 'Firefox') !== false) $browser['name'] = "firefox"; - if(strpos($agent, 'Opera') !== false) $browser['name'] = 'opera'; - if(strpos($agent, 'Safari') !== false) $browser['name'] = 'safari'; - if(strpos($agent, 'Chrome') !== false) $browser['name'] = "chrome"; - - // Check the name of browser - if(strpos($agent, 'MSIE') !== false || strpos($agent, 'rv:11.0')) $browser['name'] = 'ie'; - if(strpos($agent, 'Edge') !== false) $browser['name'] = 'edge'; - - // Check the version of browser - if(preg_match('/MSIE\s(\d+)\..*/i', $agent, $regs)) $browser['version'] = $regs[1]; - if(preg_match('/FireFox\/(\d+)\..*/i', $agent, $regs)) $browser['version'] = $regs[1]; - if(preg_match('/Opera[\s|\/](\d+)\..*/i', $agent, $regs)) $browser['version'] = $regs[1]; - if(preg_match('/Chrome\/(\d+)\..*/i', $agent, $regs)) $browser['version'] = $regs[1]; - - if((strpos($agent, 'Chrome') == false) && preg_match('/Safari\/(\d+)\..*$/i', $agent, $regs)) $browser['version'] = $regs[1]; - if(preg_match('/rv:(\d+)\..*/i', $agent, $regs)) $browser['version'] = $regs[1]; - if(preg_match('/Edge\/(\d+)\..*/i', $agent, $regs)) $browser['version'] = $regs[1]; - - return $browser; - } - - /** - * Get client os from agent info. - * - * @static - * @access public - * @return string - */ - public static function getOS() - { - if(empty($_SERVER['HTTP_USER_AGENT'])) return 'unknow'; - - $osList = array(); - $osList['/windows nt 10/i'] = 'Windows 10'; - $osList['/windows nt 6.3/i'] = 'Windows 8.1'; - $osList['/windows nt 6.2/i'] = 'Windows 8'; - $osList['/windows nt 6.1/i'] = 'Windows 7'; - $osList['/windows nt 6.0/i'] = 'Windows Vista'; - $osList['/windows nt 5.2/i'] = 'Windows Server 2003/XP x64'; - $osList['/windows nt 5.1/i'] = 'Windows XP'; - $osList['/windows xp/i'] = 'Windows XP'; - $osList['/windows nt 5.0/i'] = 'Windows 2000'; - $osList['/windows me/i'] = 'Windows ME'; - $osList['/win98/i'] = 'Windows 98'; - $osList['/win95/i'] = 'Windows 95'; - $osList['/win16/i'] = 'Windows 3.11'; - $osList['/macintosh|mac os x/i'] = 'Mac OS X'; - $osList['/mac_powerpc/i'] = 'Mac OS 9'; - $osList['/linux/i'] = 'Linux'; - $osList['/ubuntu/i'] = 'Ubuntu'; - $osList['/iphone/i'] = 'iPhone'; - $osList['/ipod/i'] = 'iPod'; - $osList['/ipad/i'] = 'iPad'; - $osList['/android/i'] = 'Android'; - $osList['/blackberry/i'] = 'BlackBerry'; - $osList['/webos/i'] = 'Mobile'; - - foreach ($osList as $regex => $value) - { - if(preg_match($regex, $_SERVER['HTTP_USER_AGENT'])) return $value; - } - - return 'unknown'; - } - - /** - * 计算两个日期相差的天数,取整。 - * Compute the diff days of two date. - * - * @param string $date1 the first date. - * @param string $date2 the sencond 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); - } - - /** - * 获取当前时间,使用common语言文件定义的DT_DATETIME1常量。 - * 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); - } - - /** - * 获取当前日期,使用common语言文件定义的DT_DATE1常量。 - * 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); - } - - /** - * 获取当前日期,使用common语言文件定义的DT_TIME1常量。 - * Get now time use the DT_TIME1 constant defined in the lang file. - * - * @access public - * @return date today - */ - static public function time() - { - return date(DT_TIME1); - } - - /** - * 判断日期是不是零。 - * 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 a directory. - * - * @access public - * @return array the files match the pattern - */ - static public function ls($dir, $pattern = '') - { - if(empty($dir)) return array(); - - $files = array(); - $dir = realpath($dir); - if(is_dir($dir)) $files = glob($dir . DIRECTORY_SEPARATOR . '*' . $pattern); - return empty($files) ? array() : $files; - } - - /** - * 切换目录。第一次调用的时候记录当前的路径,再次调用的时候切换回之前的路径。 - * Change directory: first call, save the $cwd, secend call, change to $cwd. - * - * @param string $path - * @static - * @access public - * @return void - */ - static function cd($path = '') - { - static $cwd = ''; - if($path) $cwd = getcwd(); - !empty($path) ? chdir($path) : chdir($cwd); - } - - /** - * 通过域名获取站点代号。 - * Get siteCode for a domain. - * - * www.xirang.com => xirang - * xirang.com => xirang - * xirang.com.cn => xirang - * xirang.cn => xirang - * xirang => xirang - * - * @param string $domain - * @return string $siteCode - **/ - public static function parseSiteCode($domain) - { - global $config; - - /* 去除域名中的端口部分。Remove the port part of the domain. */ - if(strpos($domain, ':') !== false) $domain = substr($domain, 0, strpos($domain, ':')); - $domain = strtolower($domain); - - /* $config里面有定义或者是localhost,直接返回。 Return directly if defined in $config or is localhost. */ - if(isset($config->siteCodeList[$domain])) return $config->siteCodeList[$domain]; - if($domain == 'localhost') return $domain; - - /* 将域名中的-改为_。Replace '-' with '_' in the domain. */ - $domain = str_replace('-', '_', $domain); - $items = explode('.', $domain); - - /* 类似a.com的形式。 Domain like a.com. */ - $postfix = str_replace($items[0] . '.', '', $domain); - if(isset($config->domainPostfix) and strpos($config->domainPostfix, "|$postfix|") !== false) return $items[0]; - - /* 类似www.a.com的形式。 Domain like www.a.com. */ - $postfix = str_replace($items[0] . '.' . $items[1] . '.', '', $domain); - if(isset($config->domainPostfix) and strpos($config->domainPostfix, "|$postfix|") !== false) return $items[1]; - - /* 类似xxx.sub.a.com的形式。 Domain like xxx.sub.a.com. */ - $postfix = str_replace($items[0] . '.' . $items[1] . '.' . $items[2] . '.', '', $domain); - if(isset($config->domainPostfix) and strpos($config->domainPostfix, "|$postfix|") !== false) return $items[0]; - - return ''; - } - - /** - * 检查是否是AJAX请求。 - * Check is ajax request. - * - * @static - * @access public - * @return bool - */ - public static function isAjaxRequest() - { - if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') return true; - if(isset($_GET['HTTP_X_REQUESTED_WITH']) && $_GET['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') return true; - return false; - } - - /** - * 301跳转。 - * Header 301 Moved Permanently. - * - * @param string $locate - * @access public - * @return void - */ - public static function header301($locate) - { - header('HTTP/1.1 301 Moved Permanently'); - die(header('Location:' . $locate)); - } - - /** - * 获取远程IP。 - * Get remote ip. - * - * @access public - * @return string - */ - public static function getRemoteIp() - { - $ip = ''; - if(!empty($_SERVER["REMOTE_ADDR"])) $ip = $_SERVER["REMOTE_ADDR"]; - if(!empty($_SERVER["HTTP_X_FORWARDED_FOR"])) $ip = $_SERVER["HTTP_X_FORWARDED_FOR"]; - if(!empty($_SERVER['HTTP_CLIENT_IP'])) $ip = $_SERVER['HTTP_CLIENT_IP']; - - return $ip; - } -} - -//------------------------------- 常用函数。Some tool functions.-------------------------------// - -/** - * helper::createLink()的别名,方便创建本模块方法的链接。 - * The short alias of helper::createLink() method to create link to control method of current module. - * - * @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++]; -} - -/** - * 获取当前时间的Unix时间戳,精确到微妙。 - * Get current microtime. - * - * @access public - * @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 ""; - print_r($var); - echo ""; -} - -/** - * 判断是否内外IP。 - * Judge the server ip is local or not. - * - * @access public - * @return void - */ -function isLocalIP() -{ - global $config; - if(isset($config->islocalIP)) return $config->isLocalIP; - $serverIP = $_SERVER['SERVER_ADDR']; - if($serverIP == '127.0.0.1') return true; - if(strpos($serverIP, '10.70') !== false) return false; - return !filter_var($serverIP, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE); -} - -/** - * 获取webRoot。 - * Get web root. - * - * @access public - * @return string - */ -function getWebRoot($full = false) -{ - $path = $_SERVER['SCRIPT_NAME']; - - if(PHP_SAPI == 'cli') - { - if(isset($_SERVER['argv'][1])) - { - $url = parse_url($_SERVER['argv'][1]); - $path = empty($url['path']) ? '/' : rtrim($url['path'], '/'); - } - $path = empty($path) ? '/' : preg_replace('/\/www$/', '/www/', $path); - } - - if($full) - { - $http = (isset($_SERVER['HTTPS']) and strtolower($_SERVER['HTTPS']) != 'off') ? 'https://' : 'http://'; - return $http . $_SERVER['HTTP_HOST'] . substr($path, 0, (strrpos($path, '/') + 1)); - } - - $path = substr($path, 0, (strrpos($path, '/') + 1)); - $path = str_replace('\\', '/', $path); - return $path; -} - -/** - * 当数组/对象变量$var存在$key项时,返回存在的对应值或设定值,否则返回$key或不存在的设定值。 - * 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 string - */ -function zget($var, $key, $valueWhenNone = false, $valueWhenExists = false) -{ - if(!is_array($var) and !is_object($var)) return false; - - $type = is_array($var) ? 'array' : 'object'; - $checkExists = $type == 'array' ? isset($var[$key]) : isset($var->$key); - - if($checkExists) - { - if($valueWhenExists !== false) return $valueWhenExists; - return $type == 'array' ? $var[$key] : $var->$key; - } - - if($valueWhenNone !== false) return $valueWhenNone; - return $key; -} diff --git a/framework/base/model.class.php b/framework/base/model.class.php deleted file mode 100644 index 0b84a41ee2..0000000000 --- a/framework/base/model.class.php +++ /dev/null @@ -1,302 +0,0 @@ -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(); - if($this->config->framework->multiLanguage) $this->app->loadLang($moduleName, $this->appName); - if($moduleName != 'common') $this->app->loadModuleConfig($moduleName, $this->appName); - - $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; - } - - /** - * 加载一个模块的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; - - global $loadedModels; - if(isset($loadedModels[$appName][$moduleName])) - { - $this->$moduleName = $loadedModels[$appName][$moduleName]; - return $this->$moduleName; - } - - $modelFile = $this->app->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); - } - - $loadedModels[$appName][$moduleName] = new $modelClass($appName); - $this->$moduleName = $loadedModels[$appName][$moduleName]; - return $this->$moduleName; - } - - /** - * 加载model的class扩展,主要是为了开发加密代码使用。 - * 可以将主要的逻辑存放到$moduleName/ext/model/class/$extensionName.class.php中。 - * 然后在ext/model/$extension.php的扩展里面使用$this->loadExtension()来调用相应的方法。 - * ext/model/class/*.class.php代码可以加密。而ext/model/*.php可以不用加密。 - * 因为框架对model的扩展是采取合并文件的方式,ext/model/*.php文件不能加密。 - * - * Load extension class of a model thus user can encrypt the code. - * You can put the main extension logic codes in $moduleName/ext/model/class/$extensionName.class.php. - * And call them by the ext/model/$extension.php like this: $this->loadExtension('myextension')->method(). - * You can encrypt the code in ext/model/class/*.class.php. - * Because the framework will merge the extension files in ext/model/*.php to the module/model.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(); - } -} diff --git a/framework/base/router.class.php b/framework/base/router.class.php deleted file mode 100644 index d700da5fc4..0000000000 --- a/framework/base/router.class.php +++ /dev/null @@ -1,2517 +0,0 @@ -basePath/framework) - * - * @var string - * @access public - */ - public $frameRoot; - - /** - * 类库的根目录。{$this->basePath/lib} - * The root directory of the library($this->basePath/lib). - * - * @var string - * @access public - */ - public $coreLibRoot; - - /** - * 应用名称 - * The appName. - * - * @var string - * @access public - */ - public $appName = ''; - - /** - * 应用程序的根目录。 - * The root directory of the app. - * - * @var string - * @access public - */ - public $appRoot; - - /** - * 临时文件的根目录。 - * The root directory of temp. - * - * @var string - * @access public - */ - public $tmpRoot; - - /** - * 缓存的根目录。 - * The root directory of cache. - * - * @var string - * @access public - */ - public $cacheRoot; - - /** - * WWW目录。 - * The root directory of www. - * - * @var string - * @access public - */ - public $wwwRoot; - - /** - * 附件存放目录。 - * The root directory of data. - * - * @var string - * @access public - */ - public $dataRoot; - - /** - * 日志文件的根目录。 - * The root directory of log. - * - * @var string - * @access public - */ - public $logRoot; - - /** - * 配置文件的根目录。 - * The root directory of config. - * - * @var string - * @access public - */ - public $configRoot; - - /** - * 模块的根目录。 - * The root directory of module. - * - * @var string - * @access public - */ - public $moduleRoot; - - /** - * 主题的根目录。 - * The root directory of theme. - * - * @var string - * @access public - */ - public $themeRoot; - - /** - * 用户使用的语言。 - * The lang of the client user. - * - * @var string - * @access public - */ - public $clientLang; - - /** - * 用户使用的主题。 - * The theme of the client user. - * - * @var string - * @access public - */ - public $clientTheme; - - /** - * 客户端设备类型。 - * The device type of client. - * - * @var string - * @access public - */ - public $clientDevice; - - /** - * 当前模块的control对象。 - * The control object of current module. - * - * @var object - * @access public - */ - public $control; - - /** - * 模块名。 - * The module name - * - * @var string - * @access public - */ - public $moduleName; - - /** - * 当前访问模块的control文件。 - * The control file of the module current visiting. - * - * @var string - * @access public - */ - public $controlFile; - - /** - * 当前访问的方法名。 - * The name of the method current visiting. - * - * @var string - * @access public - */ - public $methodName; - - /** - * 当前方法的扩展文件。 - * The action extension file of current method. - * - * @var string - * @access public - */ - public $extActionFile; - - /** - * 访问的URI。 - * The URI. - * - * @var string - * @access public - */ - public $URI; - - /** - * url地址传递的参数。 - * The params passed in through url. - * - * @var array - * @access public - */ - public $params; - - /** - * 视图类型。 - * The view type. - * - * @var string - * @access public - */ - public $viewType; - - /** - * 全局$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; - - /** - * 从数据库的句柄。 - * The slave database handler. - * - * @var object - * @access public - */ - public $slaveDBH; - - /** - * $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; - - /** - * 网站代号。 - * The code of current site. - * - * @var string - * @access public - */ - public $siteCode; - - /** - * 构造方法, 设置路径,类,超级变量等。注意: - * 1.应该使用createApp()方法实例化router类; - * 2.如果$appRoot为空,框架会根据$appName计算应用路径。 - * - * The construct function. - * Prepare all the paths, classes, super objects and so on. - * Notice: - * 1. You should use the createApp() method to get an instance of the router. - * 2. If the $appRoot is empty, the framework will compute the appRoot according the $appName - * - * @param string $appName the name of the app - * @param string $appRoot the root path of the app - * @access public - * @return void - */ - public function __construct($appName = 'demo', $appRoot = '') - { - $this->setPathFix(); - $this->setBasePath(); - $this->setFrameRoot(); - $this->setCoreLibRoot(); - $this->setAppRoot($appName, $appRoot); - $this->setTmpRoot(); - $this->setCacheRoot(); - $this->setLogRoot(); - $this->setConfigRoot(); - $this->setModuleRoot(); - $this->setWwwRoot(); - $this->setThemeRoot(); - $this->setDataRoot(); - $this->loadMainConfig(); - - $this->loadClass('front', $static = true); - $this->loadClass('filter', $static = true); - $this->loadClass('dao', $static = true); - $this->loadClass('mobile', $static = true); - - $this->setSuperVars(); - $this->setDebug(); - $this->setErrorHandler(); - $this->setTimezone(); - $this->startSession(); - - if($this->config->framework->multiSite) $this->setSiteCode() && $this->loadExtraConfig(); - if($this->config->framework->autoConnectDB) $this->connectDB(); - if($this->config->framework->multiLanguage) $this->setClientLang(); - - $needDetectDevice = zget($this->config->framework->detectDevice, $this->clientLang, false); - $this->clientDevice = $needDetectDevice ? $this->setClientDevice() : 'desktop'; - - if($this->config->framework->multiLanguage) $this->loadLang('common'); - if($this->config->framework->multiTheme) $this->setClientTheme(); - } - - /** - * 创建一个应用。 - * Create an application. - * - * @param string $appName 应用名称。 The name of the app. - * @param string $appRoot 应用根路径。The root path of the app. - * @param string $className 应用类名,如果对router类做了扩展,需要指定类名。When extends router class, you should pass in the child router class name. - * @static - * @access public - * @return object the app object - */ - public static function createApp($appName = 'demo', $appRoot = '', $className = '') - { - if(empty($className)) $className = __CLASS__; - return new $className($appName, $appRoot); - } - - //-------------------- 路径相关方法(Path related methods)--------------------// - - /** - * 设置应用名称。 - * Set app name. - * - * @param string $appName - * @access public - * @return void - */ - public function setAppName($appName) - { - $this->appName = $appName; - } - - /** - * 设置目录分隔符。 - * Set the path directory separator. - * - * @access public - * @return void - */ - public function setPathFix() - { - define('DS', DIRECTORY_SEPARATOR); - } - - /** - * 设置基础目录。 - * Set the base path. - * - * @access public - * @return void - */ - public function setBasePath() - { - $this->basePath = realpath(dirname(dirname(dirname(__FILE__)))) . DS; - } - - /** - * 设置框架根目录。 - * Set the frame root. - * - * @access public - * @return void - */ - public function setFrameRoot() - { - $this->frameRoot = $this->basePath . 'framework' . DS; - } - - /** - * 设置类库的根目录。 - * Set the app lib root. - * - * @access public - * @return void - */ - public function setCoreLibRoot() - { - $this->coreLibRoot = $this->basePath . 'lib' . DS; - } - - /** - * 设置应用的根目录。 - * Set the app root. - * - * @param string $appName - * @param string $appRoot - * @access public - * @return void - */ - public function setAppRoot($appName = 'demo', $appRoot = '') - { - if(empty($appRoot)) $this->appRoot = $this->basePath . 'app' . DS . $appName . DS; - if(!empty($appRoot)) $this->appRoot = realpath($appRoot) . DS; - if(!is_dir($this->appRoot)) $this->triggerError("The app you call not found in {$this->appRoot}", __FILE__, __LINE__, $exit = true); - } - - /** - * 设置临时文件的根目录。 - * Set the tmp root. - * - * @access public - * @return void - */ - public function setTmpRoot() - { - $this->tmpRoot = $this->basePath . 'tmp' . DS; - } - - /** - * 设置缓存的根目录。 - * Set the cache root. - * - * @access public - * @return void - */ - public function setCacheRoot() - { - $this->cacheRoot = $this->tmpRoot . 'cache' . DS; - } - - /** - * 设置log的根目录。 - * Set the log root. - * - * @access public - * @return void - */ - public function setLogRoot() - { - $this->logRoot = $this->tmpRoot . 'log' . DS; - } - - /** - * 设置config配置文件的根目录。 - * Set the config root. - * - * @access public - * @return void - */ - public function setConfigRoot() - { - $this->configRoot = $this->basePath . 'config' . DS; - } - - /** - * 设置模块的根目录。 - * Set the module root. - * - * @access public - * @return void - */ - public function setModuleRoot() - { - $this->moduleRoot = $this->basePath . 'module' . DS; - } - - /** - * 设置www的根目录。 - * Set the www root. - * - * @access public - * @return void - */ - public function setWwwRoot() - { - $this->wwwRoot = rtrim(dirname($_SERVER['SCRIPT_FILENAME']), DS) . DS; - } - - /** - * 设置主题根目录。 - * Set the theme root. - * - * @access public - * @return void - */ - public function setThemeRoot() - { - $this->themeRoot = $this->wwwRoot . 'theme' . DS; - } - - /** - * 设置data根目录。 - * Set the data root. - * - * @access public - * @return void - */ - public function setDataRoot() - { - $this->dataRoot = $this->wwwRoot . 'data' . DS; - } - - /** - * 设置超级变量。 - * Set the super vars. - * - * @access public - * @return void - */ - public function setSuperVars() - { - $this->post = new super('post'); - $this->get = new super('get'); - $this->server = new super('server'); - $this->cookie = new super('cookie'); - $this->session = new super('session'); - - unset($GLOBALS); - unset($_REQUEST); - - $_FILES = validater::filterFiles(); - $_POST = validater::filterSuper($_POST); - $_GET = validater::filterSuper($_GET); - $_COOKIE = validater::filterSuper($_COOKIE); - } - - /** - * 设置Debug模式。 - * set Debug. - * - * @access public - * @return void - */ - public function setDebug() - { - if(!empty($this->config->debug)) error_reporting(E_ALL & ~ E_STRICT); - } - - /** - * 设置错误处理句柄。 - * Set the error handler. - * - * @access public - * @return void - */ - public function setErrorHandler() - { - set_error_handler(array($this, 'saveError')); - register_shutdown_function(array($this, 'shutdown')); - } - - /** - * 获取应用名称 - * Get app name - * - * @access public - * @return string - */ - public function getAppName() - { - return $this->appName; - } - - /** - * 获取$basePath,即基础路径。 - * Get the $basePath var. - * - * @access public - * @return string - */ - public function getBasePath() - { - return $this->basePath; - } - - /** - * 获取$frameRoot,即框架根目录。 - * Get the $frameRoot var. - * - * @access public - * @return string - */ - public function getFrameRoot() - { - return $this->frameRoot; - } - - /** - * 获取$appRoot变量,即应用的根目录。 - * Get the $appRoot var. - * - * @access public - * @return string - */ - public function getAppRoot() - { - return $this->appRoot; - } - - /** - * 获取$wwwRoot变量。 - * Get the $wwwRoot var - * - * @access public - * @return string - */ - public function getWwwRoot() - { - return $this->wwwRoot; - } - - /** - * 获取$coreLibRoot变量,即应用类库的根目录。 - * Get the $coreLibRoot var. - * - * @access public - * @return string - */ - public function getCoreLibRoot() - { - return $this->coreLibRoot; - } - - /** - * 获取$tmpRoot变量,即临时文件的根目录。 - * Get the $tmpRoot var. - * - * @access public - * @return string - */ - public function getTmpRoot() - { - return $this->tmpRoot; - } - - /** - * 获取$cacheRoot变量,即缓存文件的根目录。 - * Get the $cacheRoot var. - * - * @access public - * @return string - */ - public function getCacheRoot() - { - return $this->cacheRoot; - } - - /** - * 获取$logRoot变量,即日志文件的根目录。 - * Get the $logRoot var. - * - * @access public - * @return string - */ - public function getLogRoot() - { - return $this->logRoot; - } - - /** - * 获取$configRoot变量,即配置文件的根目录。 - * Get the $configRoot var. - * - * @access public - * @return string - */ - public function getConfigRoot() - { - return $this->configRoot; - } - - /** - * 获取$moduleRoot变量,即应用模块的根目录。 - * Get the $moduleRoot var. - * - * @param string $appName - * @access public - * @return string - */ - public function getModuleRoot($appName = '') - { - if($appName == '') return $this->moduleRoot; - return dirname($this->moduleRoot) . DS . $appName . DS; - } - - /** - * 获取$webRoot,即应用的路径。 - * Get the $webRoot var. - * - * @access public - * @return string - */ - public function getWebRoot() - { - return $this->config->webRoot; - } - - /** - * 获取$themeRoot变量,即主题的根目录。 - * Get the $themeRoot var. - * - * @access public - * @return string - */ - public function getThemeRoot() - { - return $this->themeRoot; - } - - /** - * 获取$dataRoot目录 - * Get the $dataRoot var - * - * @access public - * @return string - */ - public function getDataRoot() - { - return $this->dataRoot; - } - - //------ 客户端环境有关的函数(Client environment related functions) ------// - - /** - * 根据配置设置当前时区。 - * Set the time zone according to the config. - * - * @access public - * @return void - */ - public function setTimezone() - { - if(isset($this->config->timezone)) date_default_timezone_set($this->config->timezone); - } - - /** - * 开启 session - * Start the session. - * - * @access public - * @return void - */ - public function startSession() - { - if(!defined('SESSION_STARTED')) - { - $sessionName = $this->config->sessionVar; - session_name($sessionName); - if(isset($_GET[$this->config->sessionVar])) session_id($_GET[$this->config->sessionVar]); - session_start(); - define('SESSION_STARTED', true); - } - } - - /** - * 根据用户浏览器的语言设置和服务器配置,选择显示的语言。 - * 优先级:$lang参数 > session > cookie > 浏览器 > 配置文件。 - * - * Set the language. - * Using the order of method $lang param, session, cookie, browser and the default lang. - * - * @param string $lang zh-cn|zh-tw|zh-hk|en - * @access public - * @return void - */ - public function setClientLang($lang = '') - { - if(isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) $this->clientLang = $this->parseHttpAcceptLang(); - if(isset($_COOKIE['lang'])) $this->clientLang = $_COOKIE['lang']; - if(isset($_SESSION['lang'])) $this->clientLang = $_SESSION['lang']; - if(!empty($lang)) $this->clientLang = $lang; - - if(!empty($this->clientLang)) - { - $this->clientLang = strtolower($this->clientLang); - if(!isset($this->config->langs[$this->clientLang])) $this->clientLang = $this->config->default->lang; - } - else - { - $this->clientLang = $this->config->default->lang; - } - - setcookie('lang', $this->clientLang, $this->config->cookieLife, $this->config->webRoot); - if(!isset($_COOKIE['lang'])) $_COOKIE['lang'] = $this->clientLang; - - return true; - } - - /** - * 从HTTP_ACCEPT_LANGUAGE中提出去支持的语言。 - * Parse the lang str from HTTP_ACCEPT_LANGUAGE header. - * - * @access public - * @return string - */ - public function parseHttpAcceptLang() - { - if(empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) return ''; - - $raw = $_SERVER['HTTP_ACCEPT_LANGUAGE']; - $pos = strpos($raw, ','); - $lang = $pos === false ? $raw : substr($raw, 0, $pos); - - /* Fix clientLang for ie >= 10. https://www.drupal.org/node/365615. */ - if(stripos($lang, 'hans')) $lang = 'zh-cn'; - if(stripos($lang, 'hant')) $lang = 'zh-tw'; - return $lang; - } - - /** - * 设置客户端使用的主题,判断逻辑与客户端的语言相同。 - * 主题的css和图片文件应该存放在www/theme/$themeName路径。 - * - * Set the theme the client user using. The logic is same as the clientLang. - * The css and images files of an theme should saved at www/theme/$themeName - * - * @param string $theme - * @access public - * @return void - */ - public function setClientTheme($theme = '') - { - if(isset($this->config->client->theme)) $this->clientTheme = $this->config->client->theme; - if(isset($_COOKIE['theme'])) $this->clientTheme = $_COOKIE['theme']; - if(!empty($theme)) $this->clientTheme = $theme; - - if(!empty($this->clientTheme)) - { - $this->clientTheme = strtolower($this->clientTheme); - if(!isset($this->lang->themes[$this->clientTheme])) $this->clientTheme = $this->config->default->theme; - } - else - { - $this->clientTheme = $this->config->default->theme; - } - - setcookie('theme', $this->clientTheme, $this->config->cookieLife, $this->config->webRoot); - if(!isset($_COOKIE['theme'])) $_COOKIE['theme'] = $this->clientTheme; - - return true; - } - - /** - * 设置客户端的设备类型。 - * Set client device. - * - * @access public - * @return void - */ - public function setClientDevice() - { - $this->clientDevice = 'desktop'; - - if($this->cookie->device == 'mobile') $this->clientDevice = 'mobile'; - if($this->cookie->device == 'desktop') $this->clientDevice = 'desktop'; - - if(strpos('mobile,desktop', $this->cookie->device) === false) - { - $mobile = new mobile(); - $this->clientDevice = ($mobile->isMobile() and !$mobile->isTablet()) ? 'mobile' : 'desktop'; - } - - setcookie('device', $this->clientDevice, $this->config->cookieLife, $this->config->webRoot); - if(!isset($_COOKIE['device'])) $_COOKIE['device'] = $this->clientDevice; - - return $this->clientDevice; - } - - /** - * 设置站点代号,可以针对不同的站点来加载不同的扩展。 - * Set the code of current site, thus can load diffrent extension of diffrent site. - * - * @access public - * @return void - */ - public function setSiteCode() - { - return $this->siteCode = helper::parseSiteCode($this->server->http_host); - } - - /** - * 获取$clientLang变量,即客户端的语言。 - * Get the $clientLang var. - * - * @access public - * @return string - */ - public function getClientLang() - { - return $this->clientLang; - } - - /** - * 获取$clientTheme变量。 - * Get the $clientTheme var. - * - * @access public - * @return string - */ - public function getClientTheme() - { - return $this->config->webRoot . 'theme/' . $this->clientTheme . '/'; - } - - /** - * 获得客户端的终端设备。 - * Get the client device. - * - * @access public - * @return void - */ - public function getClientDevice() - { - return $this->clientDevice; - } - - //-------------------- 请求相关的方法(Request related methods) --------------------// - - /** - * 解析本次请求的入口方法,根据请求的类型(PATH_INFO GET),调用相应的方法。 - * The entrance of parseing request. According to the requestType, call related methods. - * - * @access public - * @return void - */ - public function parseRequest() - { - if($this->config->requestType == 'PATH_INFO' or $this->config->requestType == 'PATH_INFO2') - { - $this->parsePathInfo(); - $this->setRouteByPathInfo(); - } - elseif($this->config->requestType == 'GET') - { - $this->parseGET(); - $this->setRouteByGET(); - } - else - { - $this->triggerError("The request type {$this->config->requestType} not supported", __FILE__, __LINE__, $exit = true); - } - } - - /** - * PATH_INFO方式解析,获取$URI和$viewType。 - * Parse PATH_INFO, get the $URI and $viewType. - * - * @access public - * @return void - */ - public function parsePathInfo() - { - $pathInfo = $this->getPathInfo(); - if(!empty($pathInfo)) - { - $dotPos = strrpos($pathInfo, '.'); - if($dotPos) - { - $this->URI = substr($pathInfo, 0, $dotPos); - $this->viewType = substr($pathInfo, $dotPos + 1); - if(strpos($this->config->views, ',' . $this->viewType . ',') === false) - { - $this->viewType = $this->config->default->view; - } - } - else - { - $this->URI = $pathInfo; - $this->viewType = $this->config->default->view; - } - } - else - { - $this->viewType = $this->config->default->view; - } - } - - /** - * 从$_SERVER或者$_ENV全局变量根据pathinfo变量名获取$PATH_INFO值。 - * PATH_INFO的变量名几乎都是'PATH_INFO',但也有可能是ORIG_PATH_INFO。 - * - * Get $PATH_INFO from $_SERVER or $_ENV by the pathinfo var name. - * Mostly, the var name of PATH_INFO is PATH_INFO, but may be ORIG_PATH_INFO. - * - * @access public - * @return string the PATH_INFO - */ - public function getPathInfo() - { - if(isset($_SERVER['PATH_INFO'])) - { - $value = $_SERVER['PATH_INFO']; - } - elseif(isset($_SERVER['ORIG_PATH_INFO'])) - { - $value = $_SERVER['ORIG_PATH_INFO']; - } - elseif(isset($this->URI)) - { - $value = $this->URI; - $subpath = str_replace($_SERVER['DOCUMENT_ROOT'], '', dirname($_SERVER['SCRIPT_FILENAME'])); - if($subpath != '/') $subpath = '/' . $subpath; - if($subpath != '' and $subpath != '/' and strpos($value, $subpath) === 0) $value = substr($value, strlen($subpath)); - } - else - { - $value = @getenv('PATH_INFO'); - if(empty($value)) $value = @getenv('ORIG_PATH_INFO'); - } - - if(strpos($value, $_SERVER['SCRIPT_NAME']) !== false) $value = str_replace($_SERVER['SCRIPT_NAME'], '', $value); - if(strpos($value, '?') === false) return trim($value, '/'); - - $value = parse_url($value); - $pathInfo = trim(zget($value, 'path', ''), '/'); - if(trim($pathInfo, '/') == trim($this->config->webRoot, '/')) $pathInfo = ''; - - return $pathInfo; - } - - /** - * GET请求方式解析,获取$URI和$viewType。 - * Parse GET, get $URI and $viewType. - * - * @access public - * @return void - */ - public function parseGET() - { - if(isset($_GET[$this->config->viewVar])) - { - $this->viewType = $_GET[$this->config->viewVar]; - if(strpos($this->config->views, ',' . $this->viewType . ',') === false) $this->viewType = $this->config->default->view; - } - else - { - $this->viewType = $this->config->default->view; - } - $this->URI = $_SERVER['REQUEST_URI']; - } - - /** - * 获取$URL。 - * Get the $URL. - * - * @param bool $full true, the URI contains the webRoot, else only hte URI. - * @access public - * @return string - */ - public function getURI($full = false) - { - if($full and $this->config->requestType == 'PATH_INFO') - { - if($this->URI) return $this->config->webRoot . $this->URI . '.' . $this->viewType; - return $this->config->webRoot; - } - return $this->URI; - } - - /** - * 获取$vewType变量。 - * Get the $viewType var. - * - * @access public - * @return string - */ - public function getViewType() - { - return $this->viewType; - } - - //-------------------- 模块及扩展设置(Module and extension) --------------------// - - /** - * 加载common模块。 - * - * common模块比较特别,它会执行几乎每次请求都需要执行的操作,例如: - * 打开session,检查权限等等。 - * 加载完$lang, $config, $dbh后,需要在入口文件(www/index.php)中手动调用该方法。 - * - * Load the common module - * - * The common module is a special module, which can be used to do some common things. For examle: - * start session, check priviledge and so on. - * This method should called manually in the router file(www/index.php) after the $lang, $config, $dbh loaded. - * - * @access public - * @return object|bool the common model object or false if not exits. - */ - public function loadCommon() - { - $this->setModuleName('common'); - $commonModelFile = $this->setModelFile('common'); - if(!file_exists($commonModelFile)) return false; - - helper::import($commonModelFile); - - if($this->config->framework->extensionLevel == 0 and class_exists('commonModel')) return new commonModel(); - if($this->config->framework->extensionLevel > 0 and class_exists('extCommonModel')) return new extCommonModel(); - - if(class_exists('commonModel')) return new commonModel(); - return false; - } - - /** - * 设置要被调用的模块名。 - * Set the name of the module to be called. - * - * @param string $moduleName the module name - * @access public - * @return void - */ - public function setModuleName($moduleName = '') - { - if($this->checkModuleName($moduleName)) $this->moduleName = strtolower($moduleName); - } - - /** - * 设置要被调用的控制器文件。 - * Set the control file of the module to be called. - * - * @param bool $exitIfNone 没有找到该控制器文件的情况:如果该参数为true,则终止程序;如果为false,则打印错误日志 - * If control file not foundde, how to do. True, die the whole app. false, log error. - * @access public - * @return bool - */ - public function setControlFile($exitIfNone = true) - { - $this->controlFile = $this->moduleRoot . $this->moduleName . DS . 'control.php'; - if(file_exists($this->controlFile)) return true; - $this->triggerError("the control file $this->controlFile not found.", __FILE__, __LINE__, $exitIfNone); - } - - /** - * 设置要被调用的方法名。 - * Set the name of the method calling. - * - * @param string $methodName - * @access public - * @return void - */ - public function setMethodName($methodName = '') - { - if($this->checkMethodName($methodName)) $this->methodName = strtolower($methodName); - } - - /** - * 获取一个模块的路径。 - * Get the path of one module. - * - * @param string $appName the app name - * @param string $moduleName the module name - * @access public - * @return string the module path - */ - public function getModulePath($appName = '', $moduleName = '') - { - if($moduleName == '') $moduleName = $this->moduleName; - - if($this->checkModuleName($moduleName)) - { - $modulePath = $this->getModuleRoot($appName) . strtolower($moduleName) . DS; - return $modulePath; - } - } - - /** - * 获取一个模块的扩展路径。 Get extension path of one module. - * - * If the extensionLevel == 0, return empty array. - * If the extensionLevel == 1, return the common extension directory. - * If the extensionLevel == 2, return the common and site extension directories. - * - * @param string $appName the app name - * @param string $moduleName the module name - * @param string $ext the extension type, can be control|model|view|lang|config - * @access public - * @return string the extension path. - */ - public function getModuleExtPath($appName, $moduleName, $ext) - { - /* 检查失败或者extensionLevel为0,直接返回空。If check failed or extensionLevel == 0, return empty array. */ - if(!$this->checkModuleName($moduleName) or $this->config->framework->extensionLevel == 0) return array(); - - /* When extensionLevel == 1. */ - $modulePath = $this->getModulePath($appName, $moduleName); - $paths = array(); - $paths['common'] = $modulePath . 'ext' . DS . $ext . DS; - if($this->config->framework->extensionLevel == 1) return $paths; - - /* When extensionLevel == 2. */ - $paths['site'] = empty($this->siteCode) ? '' : $modulePath . 'ext' . DS . '_' . $this->siteCode . DS . $ext . DS; - return $paths; - } - - /** - * 检查模块中某一个变量必须为英文字母和数字组合。Check module a variable must be ascii. - * - * @param string $var - * @access public - * @return bool - */ - public function checkModuleName($var) - { - global $filter; - $rule = $filter->default->moduleName; - if(validater::checkByRule($var, $rule)) return true; - $this->triggerError("'$var' illegal. ", __FILE__, __LINE__, $exit = true); - } - - /** - * 检查方法中某一个变量必须为英文字母和数字组合。Check method a variable must be ascii. - * - * @param string $var - * @access public - * @return bool - */ - public function checkMethodName($var) - { - global $filter; - $rule = $filter->default->methodName; - if($this->config->framework->filterParam == 2 and isset($filter->{$this->moduleName}->methodName)) $rule = $filter->{$this->moduleName}->methodName; - - if(validater::checkByRule($var, $rule)) return true; - $this->triggerError("'$var' illegal. ", __FILE__, __LINE__, $exit = true); - } - - /** - * 设置Action的扩展文件。 Set the action extension file. - * - * @access public - * @return bool - */ - public function setActionExtFile() - { - $moduleExtPaths = $this->getModuleExtPath('', $this->moduleName, 'control'); - - /* 如果扩展目录为空,不包含任何扩展文件。If there's no ext pathes return false.*/ - if(empty($moduleExtPaths)) return false; - - /* 如果extensionLevel == 2,且扩展文件存在,返回该站点扩展文件。If extensionLevel == 2 and site extensionFile exists, return it. */ - if($this->config->framework->extensionLevel == 2 and !empty( $moduleExtPaths['site'])) - { - $this->extActionFile = $moduleExtPaths['site'] . $this->methodName . '.php'; - if(file_exists($this->extActionFile)) return true; - } - - /* 然后再尝试寻找公共扩展文件。Then try to find the common extension file. */ - $this->extActionFile = $moduleExtPaths['common'] . $this->methodName . '.php'; - return file_exists($this->extActionFile); - } - - /** - * 设置一个模块的model文件,如果存在model扩展,一起合并。 - * 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 - * @param string $appName the app name - * @static - * @access public - * @return string the model file - */ - public function setModelFile($moduleName, $appName = '') - { - if($appName == '') $appName = $this->getAppName(); - - /* 设置主model文件。 Set the main model file. */ - $mainModelFile = $this->getModulePath($appName, $moduleName) . 'model.php'; - if($this->config->framework->extensionLevel == 0) return $mainModelFile; - - /* 计算扩展的文件和hook文件。Compute the extension files and hook files. */ - $hookFiles = array(); - $extFiles = array(); - $siteExtended = false; - - $modelExtPaths = $this->getModuleExtPath($appName, $moduleName, 'model'); - foreach($modelExtPaths as $extType => $modelExtPath) - { - if(empty($modelExtPath)) continue; - - $tmpHookFiles = helper::ls($modelExtPath . 'hook/', '.php'); - $tmpExtFiles = helper::ls($modelExtPath, '.php'); - $hookFiles = array_merge($hookFiles, $tmpHookFiles); - $extFiles = array_merge($extFiles, $tmpExtFiles); - - if($extType == 'site' and (!empty($tmpHookFiles) or !empty($tmpExtFiles))) $siteExtended = true; - } - - /* 如果没有扩展文件,返回主文件。 If no extension or hook files, return the main file directly. */ - if(empty($extFiles) and empty($hookFiles)) return $mainModelFile; - - /* 计算合并之后的modelFile路径。Compute the merged model file path. */ - $extModelPrefix = ($siteExtended and !empty($this->siteCode)) ? $this->siteCode{0} . DS . $this->siteCode : ''; - $mergedModelDir = $this->getTmpRoot() . 'model' . DS . ($extModelPrefix ? $extModelPrefix . DS : ''); - $mergedModelFile = $mergedModelDir . $moduleName . '.php'; - if(!is_dir($mergedModelDir)) mkdir($mergedModelDir, 0755, true); - - /* 判断生成的缓存文件是否需要更新。 Judge whether the merged model file needed update or not. */ - if(!$this->needModelFileUpdate($mergedModelFile, $extFiles, $hookFiles, $modelExtPaths, $mainModelFile)) return $mergedModelFile; - - /* 合并扩展和hook文件。Merge the extension and hook files. */ - $modelLines = $this->mergeModelExtFiles($moduleName, $mainModelFile, $extFiles, $mergedModelDir); - $this->mergeModelHookFiles($moduleName, $mainModelFile, $modelLines, $hookFiles, $mergedModelDir, $mergedModelFile); - - return $mergedModelFile; - } - - /** - * 检查合并之后的model文件是否需要更新。Check whether the merged model file need update or not. - * - * @param string $mainModelFile - * @param string $mergedModelFile - * @param string $modelExtPaths - * @param array $extFiles - * @param array $hookFiles - * @access public - * @return bool - */ - public function needModelFileUpdate($mergedModelFile, $extFiles, $hookFiles, $modelExtPaths, $mainModelFile) - { - $lastTime = file_exists($mergedModelFile) ? filemtime($mergedModelFile) : 0; - - foreach($extFiles as $extFile) if(filemtime($extFile) > $lastTime) return true; - foreach($hookFiles as $hookFile) if(filemtime($hookFile) > $lastTime) return true; - - $modelExtPath = $modelExtPaths['common']; - $modelHookPath = $modelExtPaths['common'] . 'hook/'; - if(is_dir($modelExtPath ) and filemtime($modelExtPath) > $lastTime) return true; - if(is_dir($modelHookPath) and filemtime($modelHookPath) > $lastTime) return true; - - if(!empty($modelExtPaths['site'])) - { - $modelExtPath = $modelExtPaths['site']; - $modelHookPath = $modelExtPaths['site'] . 'hook/'; - if(is_dir($modelExtPath ) and filemtime($modelExtPath) > $lastTime) return true; - if(is_dir($modelHookPath) and filemtime($modelHookPath) > $lastTime) return true; - } - - if(filemtime($mainModelFile) > $lastTime) return true; - - return false; - } - - /** - * 将model的扩展文件合并在一起。Merge model ext files. - * - * @param string $moduleName - * @param string $mainModelFile - * @param array $extFiles - * @param string $mergedModelDir - * @access public - * @return void - */ - public function mergeModelExtFiles($moduleName, $mainModelFile, $extFiles, $mergedModelDir) - { - /* 设置类名。Set the class names. */ - $modelClass = "{$moduleName}Model"; - $tmpModelClass = "tmpExt$modelClass"; - - /* 开始拼装代码。Prepare the codes. */ - $modelLines = "getBasePath());\n"; - $modelLines .= "helper::import('" . str_replace($this->getBasePath(), '', $mainModelFile) . "');\n"; - $modelLines .= "helper::cd();\n"; - $modelLines .= "class $tmpModelClass extends $modelClass \n{\n"; - - /* 将扩展文件的代码合并到代码中。Cycle all the extension files and merge them into model lines. */ - foreach($extFiles as $extFile) $modelLines .= self::removePHPTAG($extFile); - - /* 做个标记,方便后面替换代码使用。Make a mark for replacing codes. */ - $replaceMark = '//**//'; - $modelLines .= "\n$replaceMark\n}"; - - /* 生成一个临时的model扩展文件,并加载,用于后续的hook文件加载使用。Create a tmp merged model file and import it for merge hook codes using. */ - $tmpModelFile = $mergedModelDir . "tmp$moduleName.php"; - if(@file_put_contents($tmpModelFile, $modelLines)) - { - if(!class_exists($tmpModelClass)) include $tmpModelFile; - return $modelLines; - } - - $this->triggerError("ERROR: $tmpModelFile not writable.", __FILE__, __LINE__, true); - } - - /** - * 合并model的hook脚本。Merge hook files for a model. - * - * @access public - * @return void - */ - public function mergeModelHookFiles($moduleName, $mainModelFile, $modelLines, $hookFiles, $mergedModelDir, $mergedModelFile) - { - /* 定义相关变量。Init vars. */ - $modelClass = $moduleName . 'Model'; - $extModelClass = 'ext' . $modelClass; - $tmpModelClass = 'tmpExt' . $modelClass; - $tmpModelFile = $mergedModelDir . "tmp$moduleName.php"; - $replaceMark = '//**//'; - - /* 读取hook文件。Get hook codes need to merge. */ - $hookCodes = array(); - foreach($hookFiles as $hookFile) - { - /* 通过文件名获得其对应的方法名。Get methods according it's filename. */ - $fileName = baseName($hookFile); - list($method) = explode('.', $fileName); - $hookCodes[$method][] = self::removePHPTAG($hookFile); - } - - /* 合并Hook文件。Cycle the hook methods and merge hook codes. */ - $hookedMethods = array_keys($hookCodes); - $mainModelCodes = file($mainModelFile); - $mergedModelCodes = file($tmpModelFile); - foreach($hookedMethods as $method) - { - /* 通过反射获得hook脚本对应的方法所在的文件和起止行数。Reflection the hooked method to get it's defined position. */ - if(!method_exists($tmpModelClass, $method)) continue; - $methodRelfection = new reflectionMethod($tmpModelClass, $method); - $definedFile = $methodRelfection->getFileName(); - $startLine = $methodRelfection->getStartLine() . ' '; - $endLine = $methodRelfection->getEndLine() . ' '; - - /* 将Hook脚本和老的代码合并在一起,并替换原来的定义。Merge hook codes with old codes and replace back. */ - $oldCodes = $definedFile == $tmpModelFile ? $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); - - if($definedFile == $tmpModelFile) $modelLines = str_replace($oldCodes, $newCodes, $modelLines); - if($definedFile != $tmpModelFile) $modelLines = str_replace($replaceMark, $newCodes . "\n$replaceMark", $modelLines); - } - - /* 保存最终的Model文件。Save the last merged model file. */ - $modelLines = str_replace($tmpModelClass, $extModelClass, $modelLines); - file_put_contents($mergedModelFile, $modelLines); - unlink($tmpModelFile); - } - - /** - * Remove tags of PHP - * - * @param string $fileName - * @static - * @access public - * @return string - */ - static public function removePHPTAG($fileName) - { - $code = trim(file_get_contents($fileName)); - if(strpos($code, '') !== false) $code = rtrim($code, '?>'); - return trim($code); - } - - //-------------------- 路由相关方法(Routing related methods) --------------------// - - /** - * 设置路由(PATH_INFO 方式): - * 1.设置模块名; - * 2.设置方法名; - * 3.设置控制器文件。 - * - * Set the route according to PATH_INFO. - * 1. set the module name. - * 2. set the method name. - * 3. set the control file. - * - * @access public - * @return void - */ - public function setRouteByPathInfo() - { - if(!empty($this->URI)) - { - /* - * 根据$requestFix分割符,分割网址。 - * There's the request seperator, split the URI by it. - **/ - if(strpos($this->URI, $this->config->requestFix) !== false) - { - $items = explode($this->config->requestFix, $this->URI); - $this->setModuleName($items[0]); - $this->setMethodName($items[1]); - } - /* - * 如果网址中没有分隔符,使用默认的方法。 - * No reqeust seperator, use the default method name. - **/ - else - { - $this->setModuleName($this->URI); - $this->setMethodName($this->config->default->method); - } - } - else - { - $this->setModuleName($this->config->default->module); // 使用默认模块 use the default module. - $this->setMethodName($this->config->default->method); // 使用默认方法 use the default method. - } - $this->setControlFile(); - } - - /** - * 设置路由(GET 方式): - * 1.设置模块名; - * 2.设置方法名; - * 3.设置控制器文件。 - * - * Set the route according to GET. - * 1. set the module name. - * 2. set the method name. - * 3. set the control file. - * - * @access public - * @return void - */ - public function setRouteByGET() - { - $moduleName = isset($_GET[$this->config->moduleVar]) ? strtolower($_GET[$this->config->moduleVar]) : $this->config->default->module; - $methodName = isset($_GET[$this->config->methodVar]) ? strtolower($_GET[$this->config->methodVar]) : $this->config->default->method; - $this->setModuleName($moduleName); - $this->setControlFile(); - $this->setMethodName($methodName); - } - - /** - * 加载一个模块: - * 1. 引入控制器文件或扩展的方法文件; - * 2. 创建control对象; - * 3. 解析url,得到请求的参数; - * 4. 使用call_user_function_array调用相应的方法。 - * - * Load a module. - * 1. include the control file or the extension action file. - * 2. create the control object. - * 3. set the params passed in through url. - * 4. call the method by call_user_function_array - * - * @access public - * @return bool|object if the module object of die. - */ - public function loadModule() - { - $appName = $this->appName; - $moduleName = $this->moduleName; - $methodName = $this->methodName; - - /* - * 引入该模块的control文件。 - * Include the control file of the module. - **/ - $file2Included = $this->setActionExtFile() ? $this->extActionFile : $this->controlFile; - chdir(dirname($file2Included)); - include $file2Included; - - /* - * 设置control的类名。 - * Set the class name of the control. - **/ - $className = class_exists("my$moduleName") ? "my$moduleName" : $moduleName; - if(!class_exists($className)) $this->triggerError("the control $className not found", __FILE__, __LINE__, $exit = true); - - /* - * 创建control类的实例。 - * Create a instance of the control. - **/ - $module = new $className(); - if(!method_exists($module, $methodName)) $this->triggerError("the module $moduleName has no $methodName method", __FILE__, __LINE__, $exit = true); - $this->control = $module; - - /* include default value for module*/ - $defaultValueFiles = glob($this->getTmpRoot() . "defaultvalue/*.php"); - if($defaultValueFiles) foreach($defaultValueFiles as $file) include $file; - - /* - * 使用反射机制获取函数参数的默认值。 - * Get the default settings of the method to be called using the reflecting. - * - * */ - $defaultParams = array(); - $methodReflect = new reflectionMethod($className, $methodName); - foreach($methodReflect->getParameters() as $param) - { - $name = $param->getName(); - - $default = '_NOT_SET'; - if(isset($paramDefaultValue[$appName][$className][$methodName][$name])) - { - $default = $paramDefaultValue[$appName][$className][$methodName][$name]; - } - elseif(isset($paramDefaultValue[$className][$methodName][$name])) - { - $default = $paramDefaultValue[$className][$methodName][$name]; - } - elseif($param->isDefaultValueAvailable()) - { - $default = $param->getDefaultValue(); - } - - $defaultParams[$name] = $default; - } - - /** - * 根据PATH_INFO或者GET方式设置请求的参数。 - * Set params according PATH_INFO or GET. - */ - if($this->config->requestType != 'GET') - { - $this->setParamsByPathInfo($defaultParams); - } - else - { - $this->setParamsByGET($defaultParams); - } - - if($this->config->framework->filterParam == 2) - { - $_GET = validater::filterParam($_GET, 'get'); - $_COOKIE = validater::filterParam($_COOKIE, 'cookie'); - } - - /* 调用该方法 Call the method. */ - call_user_func_array(array($module, $methodName), $this->params); - return $module; - } - - /** - * 设置请求的参数(PATH_INFO 方式)。 - * Set the params by PATH_INFO. - * - * @param array $defaultParams the default settings of the params. - * @param string $type - * @access public - * @return void - */ - public function setParamsByPathInfo($defaultParams = array(), $type = '') - { - $params = array(); - if($type != 'fetch') - { - /* 分割URI。 Spit the URI. */ - $items = explode($this->config->requestFix, $this->URI); - $itemCount = count($items); - - /** - * 前两项为模块名和方法名,参数从下标2开始。 - * The first two item is moduleName and methodName. So the params should begin at 2. - **/ - for($i = 2; $i < $itemCount; $i ++) - { - $key = key($defaultParams); // Get key from the $defaultParams. - if(empty($key)) continue; - - $params[$key] = $items[$i]; - next($defaultParams); - } - } - - $this->params = $this->mergeParams($defaultParams, $params); - } - - /** - * 设置请求的参数(GET 方式)。 - * Set the params by GET. - * - * @param array $defaultParams the default settings of the params. - * @param string $type - * @access public - * @return void - */ - public function setParamsByGET($defaultParams, $type = '') - { - $params = array(); - if($type != 'fetch') - { - /* Unset moduleVar, methodVar, viewVar and session 变量, 剩下的作为参数。 */ - /* Unset the moduleVar, methodVar, viewVar and session var, all the left are the params. */ - unset($_GET[$this->config->moduleVar]); - unset($_GET[$this->config->methodVar]); - unset($_GET[$this->config->viewVar]); - unset($_GET[$this->config->sessionVar]); - $params = $_GET; - } - - $this->params = $this->mergeParams($defaultParams, $params); - } - - /** - * 合并请求的参数和默认参数,这样就可以省略已经有默认值的参数了。 - * Merge the params passed in and the default params. Thus the params which have default values needn't pass value, just like a function. - * - * @param array $defaultParams the default params defined by the method. - * @param array $passedParams the params passed in through url. - * @access public - * @return array the merged params. - */ - public function mergeParams($defaultParams, $passedParams) - { - global $filter; - - /* Remove these two params. */ - unset($passedParams['onlybody']); - unset($passedParams['HTTP_X_REQUESTED_WITH']); - - /* Check params from URL. */ - $nameRule = isset($filter->{$this->moduleName}->{$this->methodName}->paramName) ? $filter->{$this->moduleName}->{$this->methodName}->paramName : $filter->default->paramName; - foreach($passedParams as $param => $value) - { - if(!validater::checkByRule($param, $nameRule)) die('Bad Request!'); - $valueRule = $filter->default->paramValue; - if(isset($filter->{$this->moduleName}->{$this->methodName}->paramValue[$param])) - { - $valueRule = $filter->{$this->moduleName}->{$this->methodName}->paramValue[$param]; - } - - if($value and !validater::checkByRule($value, $valueRule)) die('Bad Request!'); - } - - $passedParams = array_values($passedParams); - $i = 0; - foreach($defaultParams as $key => $defaultValue) - { - if(isset($passedParams[$i])) - { - $defaultParams[$key] = strip_tags($passedParams[$i]); - } - else - { - if($defaultValue === '_NOT_SET') $this->triggerError("The param '$key' should pass value. ", __FILE__, __LINE__, $exit = true); - } - $i ++; - } - - return $defaultParams; - } - - /** - * 获取$moduleName变量。 - * Get the $moduleName var. - * - * @access public - * @return string - */ - public function getModuleName() - { - return $this->moduleName; - } - - /** - * 获取$controlFile变量。 - * Get the $controlFile var. - * - * @access public - * @return string - */ - public function getControlFile() - { - return $this->controlFile; - } - - /** - * 获取$methodName变量。 - * Get the $methodName var. - * - * @access public - * @return string - */ - public function getMethodName() - { - return $this->methodName; - } - - /** - * 获取$param变量。 - * Get the $param var. - * - * @access public - * @return string - */ - public function getParams() - { - return $this->params; - } - - //-------------------- 常用的工具方法(Tool methods) ------------------// - - /** - * 从类库中加载一个类文件。 - * - * Load a class file. - * - * @param string $className the class name - * @param bool $static statis class or not - * @access public - * @return object|bool the instance of the class or just true. - */ - public function loadClass($className, $static = false) - { - $className = strtolower($className); - - /* 搜索$coreLibRoot(Search in $coreLibRoot) */ - $classFile = $this->coreLibRoot . $className; - if(is_dir($classFile)) $classFile .= DS . $className; - $classFile .= '.class.php'; - if(!helper::import($classFile)) $this->triggerError("class file $classFile not found", __FILE__, __LINE__, $exit = true); - - /* 如果是静态调用,则返回(If staitc, return) */ - if($static) return true; - - /* 实例化该类(Instance it) */ - global $$className; - if(!class_exists($className)) $this->triggerError("the class $className not found in $classFile", __FILE__, __LINE__, $exit = true); - if(!is_object($$className)) $$className = new $className(); - return $$className; - } - - /** - * 加载整个应用公共的配置文件。 - * Load the common config files for the app. - * - * @access public - * @return void - */ - public function loadMainConfig() - { - /* 初始化$config对象。Init the $config object. */ - global $config, $filter; - if(!is_object($config)) $config = new config(); - $this->config = $config; - - /* 加载主配置文件。 Load the main config file. */ - $mainConfigFile = $this->configRoot . 'config.php'; - if(!file_exists($mainConfigFile)) $this->triggerError("The main config file $mainConfigFile not found", __FILE__, __LINE__, $exit = true); - include $mainConfigFile; - } - - /** - * 当multiSite功能打开的时候,加载额外的配置文件。 - * When multiSite feature enabled, load extra config file. - * - * @access public - * @return void - */ - public function loadExtraConfig() - { - global $config; - $multiConfigFile = $this->configRoot . 'multi.php'; - if(file_exists($multiConfigFile)) include $multiConfigFile; - - $siteConfigFile = $this->configRoot . "sites/{$this->siteCode}.php"; - if(file_exists($siteConfigFile)) include $siteConfigFile; - } - - /** - * 加载模块的config文件,返回全局$config对象。 - * 如果该模块是common,加载$configRoot的配置文件,其他模块则加载其模块的配置文件。 - * - * Load config and return it as the global config object. - * If the module is common, search in $configRoot, else in $modulePath. - * - * @param string $moduleName module name - * @param string $appName app name - * @param bool $exitIfNone exit or not - * @access public - * @return object|bool the config object or false. - */ - public function loadModuleConfig($moduleName, $appName = '') - { - global $config; - - if($config and (!isset($config->$moduleName) or !is_object($config->$moduleName))) $config->$moduleName = new stdclass(); - - /* 初始化数组。Init the variables. */ - $extConfigFiles = array(); - $commonExtConfigFiles = array(); - $siteExtConfigFiles = array(); - - /* 先获得模块的主配置文件。Get the main config file for current module first. */ - $mainConfigFile = $this->getModulePath($appName, $moduleName) . 'config.php'; - - /* 查找扩展配置文件。Get extension config files. */ - if($config->framework->extensionLevel > 0) $extConfigPath = $this->getModuleExtPath($appName, $moduleName, 'config'); - if($config->framework->extensionLevel >= 1 and !empty($extConfigPath['common'])) $commonExtConfigFiles = helper::ls($extConfigPath['common'], '.php'); - if($config->framework->extensionLevel == 2 and !empty($extConfigPath['site'])) $siteExtConfigFiles = helper::ls($extConfigPath['site'], '.php'); - $extConfigFiles = array_merge($commonExtConfigFiles, $siteExtConfigFiles); - - /* 将主配置文件和扩展配置文件合并在一起。Put the main config file and extension config files together. */ - $configFiles = array_merge(array($mainConfigFile), $extConfigFiles); - - /* 加载每一个配置文件。Load every config file. */ - static $loadedConfigs = array(); - foreach($configFiles as $configFile) - { - if(in_array($configFile, $loadedConfigs)) continue; - if(file_exists($configFile)) include $configFile; - $loadedConfigs[] = $configFile; - } - - /* 加载数据库中与本模块相关的配置项。Merge from the db configs. */ - if($moduleName != 'common') - { - if(isset($config->system->$moduleName)) $this->mergeConfig($config->system->$moduleName, $moduleName); - if(isset($config->personal->$moduleName)) $this->mergeConfig($config->personal->$moduleName, $moduleName); - } - } - - /** - * Merge db config. - * - * @param array $dbConfig - * @param string $moduleName - * @access public - * @return void - */ - public function mergeConfig($dbConfig, $moduleName = 'common') - { - global $config; - - /* 如果没有设置本模块配置,则首先进行初始化。Init the $config->$moduleName if not set.*/ - if($moduleName != 'common' and !isset($config->$moduleName)) $config->$moduleName = new stdclass(); - - $config2Merge = $config; - if($moduleName != 'common') $config2Merge = $config->$moduleName; - - foreach($dbConfig as $item) - { - if($item->section) - { - if(!isset($config2Merge->{$item->section})) $config2Merge->{$item->section} = new stdclass(); - if(is_object($config2Merge->{$item->section})) - { - $config2Merge->{$item->section}->{$item->key} = $item->value; - } - } - else - { - $config2Merge->{$item->key} = $item->value; - } - } - } - - /** - * 向客户端输出配置参数,客户端可以根据这些参数实现和调整请求的逻辑。 - * Export the config params to the client, thus the client can adjust it's logic according the config. - * - * @access public - * @return void - */ - public function exportConfig() - { - $view = new stdclass(); - $view->version = $this->config->version; - $view->requestType = $this->config->requestType; - $view->requestFix = $this->config->requestFix; - $view->moduleVar = $this->config->moduleVar; - $view->methodVar = $this->config->methodVar; - $view->viewVar = $this->config->viewVar; - $view->sessionVar = $this->config->sessionVar; - - $this->session->set('random', mt_rand(0, 10000)); - $view->sessionName = session_name(); - $view->sessionID = session_id(); - $view->random = $this->session->random; - $view->expiredTime = ini_get('session.gc_maxlifetime'); - $view->serverTime = time(); - - echo json_encode($view); - } - - /** - * 加载语言文件,返回全局$lang对象。 - * Load lang and return it as the global lang object. - * - * @param string $moduleName the module name - * @param string $appName the app name - * @access public - * @return bool|ojbect the lang object or false. - */ - public function loadLang($moduleName, $appName = '') - { - /* 初始化变量。Init vars. */ - $modulePath = $this->getModulePath($appName, $moduleName); - $extLangFiles = array(); - $langFilesToLoad = array(); - - /* 判断主语言文件是否存在。Whether the main lang file exists or not. */ - $mainLangFile = $modulePath . 'lang' . DS . $this->clientLang . '.php'; - if(file_exists($mainLangFile)) $langFilesToLoad[] = $mainLangFile; - - /* 获取扩展语言文件。If extensionLevel > 0, get extension lang files. */ - if($this->config->framework->extensionLevel > 0) - { - $commonExtLangFiles = array(); - $siteExtLangFiles = array(); - - $extLangPath = $this->getModuleExtPath($appName, $moduleName, 'lang'); - if($this->config->framework->extensionLevel >= 1 and !empty($extLangPath['common'])) $commonExtLangFiles = helper::ls($extLangPath['common'] . $this->clientLang, '.php'); - if($this->config->framework->extensionLevel == 2 and !empty($extLangPath['site'])) $siteExtLangFiles = helper::ls($extLangPath['site'] . $this->clientLang, '.php'); - $extLangFiles = array_merge($commonExtLangFiles, $siteExtLangFiles); - } - - /* 计算最终要加载的语言文件。 Get the lang files to be loaded. */ - $langFilesToLoad = array_merge($langFilesToLoad, $extLangFiles); - if(empty($langFilesToLoad)) return false; - - /* 加载语言文件。Load lang files. */ - global $lang; - if(!is_object($lang)) $lang = new language(); - if(!isset($lang->$moduleName)) $lang->$moduleName = new stdclass(); - - static $loadedLangs = array(); - foreach($langFilesToLoad as $langFile) - { - if(in_array($langFile, $loadedLangs)) continue; - include $langFile; - $loadedLangs[] = $langFile; - } - - $this->lang = $lang; - return $lang; - } - - /** - * 连接数据库。 - * Connect to database. - * - * @access public - * @return void - */ - public function connectDB() - { - global $config, $dbh, $slaveDBH; - if(!isset($config->installed) or !$config->installed) return; - - if(isset($config->db->host)) $this->dbh = $dbh = $this->connectByPDO($config->db); - if(isset($config->slaveDB->host)) $this->slaveDBH = $slaveDBH = $this->connectByPDO($config->slaveDB); - } - - /** - * 使用PDO连接数据库。 - * Connect database by PDO. - * - * @param object $params the database params. - * @access public - * @return object|bool - */ - public function connectByPDO($params) - { - if(!isset($params->driver)) self::triggerError('no pdo driver defined, it should be mysql or sqlite', __FILE__, __LINE__, $exit = true); - if(!isset($params->user)) return false; - if($params->driver == 'mysql') - { - $dsn = "mysql:host={$params->host}; port={$params->port}; dbname={$params->name}"; - } - try - { - $dbh = new PDO($dsn, $params->user, $params->password, array(PDO::ATTR_PERSISTENT => $params->persistant)); - $dbh->exec("SET NAMES {$params->encoding}"); - - /* - * 如果系统是Linux,开启仿真预处理和缓冲查询。 - * If run on linux, set emulatePrepare and bufferQuery to true. - **/ - if(!isset($params->emulatePrepare) and PHP_OS == 'Linux') $params->emulatePrepare = true; - if(!isset($params->bufferQuery) and PHP_OS == 'Linux') $params->bufferQuery = true; - - $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ); - $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - if(isset($params->strictMode) and $params->strictMode == false) $dbh->exec("SET @@sql_mode= ''"); - if(isset($params->emulatePrepare)) $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, $params->emulatePrepare); - if(isset($params->bufferQuery)) $dbh->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, $params->bufferQuery); - - return $dbh; - } - catch (PDOException $exception) - { - self::triggerError($exception->getMessage(), __FILE__, __LINE__, $exit = true); - } - } - - //-------------------- 错误处理方法(Error methods) ------------------// - - /** - * 程序停止时执行的函数。 - * The shutdown handler. - * - * @access public - * @return void - */ - public function shutdown() - { - /* 如果debug模式开启,保存sql语句(If debug on, save sql queries) */ - if(!empty($this->config->debug)) $this->saveSQL(); - - /* - * 发现错误,保存到日志中。 - * If any error occers, save it. - * */ - if(!function_exists('error_get_last')) return; - $error = error_get_last(); - if($error) $this->saveError($error['type'], $error['message'], $error['file'], $error['line']); - } - - /** - * 触发一个错误。 - * Trigger an error. - * - * @param string $message 错误信息 error message - * @param string $file 所在文件 the file error occers - * @param int $line 错误行 the line error occers - * @param bool $exit 是否停止程序 exit the program or not - * @access public - * @return void - */ - public function triggerError($message, $file, $line, $exit = false) - { - /* 设置错误信息(Set the error info) */ - $message = htmlspecialchars($message); - $log = "ERROR: $message in $file on line $line"; - if(isset($_SERVER['SCRIPT_URI'])) $log .= ", request: $_SERVER[SCRIPT_URI]";; - $trace = debug_backtrace(); - extract($trace[0]); - extract($trace[1]); - $log .= ", last called by $file on line $line through function $function.\n"; - - /* 触发错误(Trigger the error) */ - trigger_error($log, $exit ? E_USER_ERROR : E_USER_WARNING); - } - - /** - * 保存错误信息。 - * Save error info. - * - * @param int $level - * @param string $message - * @param string $file - * @param int $line - * @access public - * @return void - */ - public function saveError($level, $message, $file, $line) - { - if(empty($this->config->debug)) return true; - if(!is_dir($this->logRoot)) return true; - if(!is_writable($this->logRoot)) return true; - - /* - * 删除设定时间之前的日志。 - * Delete the log before the set time. - **/ - if(mt_rand(0, 10) == 1) - { - $logDays = isset($this->config->framework->logDays) ? $this->config->framework->logDays : 14; - $dayTime = time() - $logDays * 24 * 3600; - foreach(glob($this->getLogRoot() . '*') as $logFile) - { - if(filemtime($logFile) <= $dayTime) unlink($logFile); - } - } - - /* - * 忽略该错误:Redefining already defined constructor。 - * Skip the error: Redefining already defined constructor. - **/ - if(strpos($message, 'Redefining') !== false) return true; - - /* - * 设置错误信息。 - * Set the error info. - **/ - $errorLog = "\n" . date('H:i:s') . " $message in $file on line $line "; - $errorLog .= "when visiting " . htmlspecialchars($this->getURI()) . "\n"; - - /* - * 为了安全起见,对公网环境隐藏脚本路径。 - * If the ip is pulic, hidden the full path of scripts. - */ - if(!defined('IN_SHELL') and !($this->server->remote_addr == '127.0.0.1' or filter_var($this->server->remote_addr, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE) === false)) - { - $errorLog = str_replace($this->getBasePath(), '', $errorLog); - } - - /* 保存到日志文件(Save to log file) */ - $errorFile = $this->logRoot . 'php.' . date('Ymd') . '.log.php'; - if(!is_file($errorFile)) file_put_contents($errorFile, "\n"); - - $fh = fopen($errorFile, 'a'); - if($fh) fwrite($fh, strip_tags($errorLog)) and fclose($fh); - - /* - * 如果debug > 1,显示warning, notice级别的错误。 - * If the debug > 1, show warning, notice error. - **/ - if($level == E_NOTICE or $level == E_WARNING or $level == E_STRICT or $level == 8192) // 8192: E_DEPRECATED - { - if(!empty($this->config->debug) and $this->config->debug > 1) - { - $cmd = "vim +$line $file"; - $size = strlen($cmd); - echo "
$message: ";
-                echo "
"; - } - } - - /* - * 如果是严重错误,停止程序。 - * If error level is serious, die. - * */ - if($level == E_ERROR or $level == E_PARSE or $level == E_CORE_ERROR or $level == E_COMPILE_ERROR or $level == E_USER_ERROR) - { - if(empty($this->config->debug)) die(); - if(PHP_SAPI == 'cli') die($errorLog); - - $htmlError = ""; - $htmlError .= "" . nl2br($errorLog) . ""; - die($htmlError); - } - } - - /** - * 保存sql语句。 - * Save the sql. - * - * @access public - * @return void - */ - public function saveSQL() - { - if(!$this->config->debug) return true; - if(!class_exists('dao')) return; - - $sqlLog = $this->getLogRoot() . 'sql.' . date('Ymd') . '.log.php'; - if(!is_file($sqlLog)) file_put_contents($sqlLog, "\n"); - - $fh = @fopen($sqlLog, 'a'); - if(!$fh) return false; - fwrite($fh, date('Ymd H:i:s') . ": " . $this->getURI() . "\n"); - foreach(dao::$querys as $query) fwrite($fh, " $query\n"); - fwrite($fh, "\n"); - fclose($fh); - } -} - -/** - * config类。 - * The config class. - * - * @package framework - */ -class config -{ - /** - * 设置成员变量,成员可以是'db.user'类似的格式。 - * Set the value of a member. the member can be the format like db.user. - * - * - * set('db.user', 'wwccss'); - * ?> - * - * @param string $key the key of the member - * @param mixed $value the value - * @access public - * @return void - */ - public function set($key, $value) - { - helper::setMember('config', $key, $value); - } -} - -/** - * lang类。 - * The lang class. - * - * @package framework - */ -class language -{ - /** - * 设置成员变量,成员可以是'db.user'类似的格式。 - * Set the value of a member. the member can be the foramt like db.user. - * - * - * set('version', '1.0); - * ?> - * - * @param string $key 成员的键名,可以是father.child的形式。 - * the key of the member, can be father.child - * @param mixed $value the value - * @access public - * @return void - */ - public function set($key, $value) - { - helper::setMember('lang', $key, $value); - } - - /** - * 显示一个成员的值。 - * Show a member. - * - * @param object $obj the object - * @param string $key the key - * @access public - * @return void - */ - public function show($obj, $key) - { - $obj = (array)$obj; - echo isset($obj[$key]) ? $obj[$key] : ''; - } -} - -/** - * 超级对象类,转化超级全局变量。 - * The super object class. - * - * @package framework - */ -class super -{ - /** - * 构造函数,设置超级变量名。 - * Construct, set the var scope. - * - * @param string $scope the scope, can be server, post, get, cookie, session, global - * @access public - * @return void - */ - public function __construct($scope) - { - $this->scope = $scope; - } - - /** - * 设置超级变量的成员值。 - * Set one member value. - * - * @param string the key - * @param mixed $value the value - * @access public - * @return void - */ - public function set($key, $value) - { - if($this->scope == 'post') - { - $_POST[$key] = $value; - } - elseif($this->scope == 'get') - { - $_GET[$key] = $value; - } - elseif($this->scope == 'server') - { - $_SERVER[$key] = $value; - } - elseif($this->scope == 'cookie') - { - $_COOKIE[$key] = $value; - } - elseif($this->scope == 'session') - { - $_SESSION[$key] = $value; - } - elseif($this->scope == 'env') - { - $_ENV[$key] = $value; - } - elseif($this->scope == 'global') - { - $GLOBALS[$key] = $value; - } - } - - /** - * 超级变量的魔术方法,比如用$post->key访问$_POST['key']。 - * The magic get method. - * - * @param string $key the key - * @access public - * @return mixed|bool return the value of the key or false. - */ - public function __get($key) - { - if($this->scope == 'post') - { - if(isset($_POST[$key])) return $_POST[$key]; - return false; - } - elseif($this->scope == 'get') - { - if(isset($_GET[$key])) return $_GET[$key]; - return false; - } - elseif($this->scope == 'server') - { - if($key == 'ajax') return isset($_SERVER['HTTP_X_REQUESTED_WITH']) ? true : false; - if(isset($_SERVER[$key])) return $_SERVER[$key]; - $key = strtoupper($key); - if(isset($_SERVER[$key])) return $_SERVER[$key]; - return false; - } - elseif($this->scope == 'cookie') - { - if(isset($_COOKIE[$key])) return $_COOKIE[$key]; - return false; - } - elseif($this->scope == 'session') - { - if(isset($_SESSION[$key])) return $_SESSION[$key]; - return false; - } - elseif($this->scope == 'env') - { - if(isset($_ENV[$key])) return $_ENV[$key]; - return false; - } - elseif($this->scope == 'global') - { - if(isset($GLOBALS[$key])) return $GLOBALS[$key]; - return false; - } - else - { - return false; - } - } - - /** - * 打印变量的详细结构。 - * Print the structure. - * - * @access public - * @return void - */ - public function a() - { - if($this->scope == 'post') a($_POST); - if($this->scope == 'get') a($_GET); - if($this->scope == 'server') a($_SERVER); - if($this->scope == 'cookie') a($_COOKIE); - if($this->scope == 'session') a($_SESSION); - if($this->scope == 'env') a($_ENV); - if($this->scope == 'global') a($GLOBALS); - } -} diff --git a/framework/control.class.php b/framework/control.class.php deleted file mode 100644 index 848194f79b..0000000000 --- a/framework/control.class.php +++ /dev/null @@ -1,23 +0,0 @@ -requestType != 'GET') - { - $pathInfo = $app->getPathInfo(); - 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($source and isset($viewType)) return $viewType; - - if(isset($viewType) and strpos($config->views, ',' . $viewType . ',') === false) $viewType = $config->default->view; - return isset($viewType) ? $viewType : $config->default->view; - } - - /** - * Encode json for $.parseJSON - * - * @param array $data - * @param int $options - * @static - * @access public - * @return string - */ - static public function jsonEncode4Parse($data, $options = 0) - { - $json = json_encode($data); - if($options) $json = str_replace(array("'", '"'), array('\u0027', '\u0022'), $json); - - $escapers = array("\\", "/", "\"", "'", "\n", "\r", "\t", "\x08", "\x0c", "\\\\u"); - $replacements = array("\\\\", "\\/", "\\\"", "\'", "\\n", "\\r", "\\t", "\\f", "\\b", "\\u"); - return str_replace($escapers, $replacements, $json); - } - - /** - * Convert encoding. - * - * @param string $string - * @param string $fromEncoding - * @param string $toEncoding - * @static - * @access public - * @return string - */ - static public function convertEncoding($string, $fromEncoding, $toEncoding = 'utf-8') - { - $toEncoding = str_replace('utf8', 'utf-8', $toEncoding); - if(function_exists('mb_convert_encoding')) - { - /* Remove like utf-8//TRANSLIT. */ - $position = strpos($toEncoding, '//'); - if($position !== false) $toEncoding = substr($toEncoding, 0, $position); - - /* Check string encoding. */ - $encoding = strtolower(mb_detect_encoding($string, array('ASCII','UTF-8','GB2312','GBK','BIG5'))); - if($encoding == $toEncoding) return $string; - return mb_convert_encoding($string, $toEncoding, $encoding); - } - elseif(function_exists('iconv')) - { - if($fromEncoding == $toEncoding) return $string; - $convertString = @iconv($fromEncoding, $toEncoding, $string); - /* iconv error then return original. */ - if(!$convertString) return $string; - return $convertString; - } - - return $string; - } -} - -/** - * 检查是否是onlybody模式。 - * Check exist onlybody param. - * - * @access public - * @return void - */ -function isonlybody() -{ - return helper::inOnlyBodyMode(); -} - -/** - * Format time. - * - * @param int $time - * @param string $format - * @access public - * @return void - */ -function formatTime($time, $format = '') -{ - $time = str_replace('0000-00-00', '', $time); - $time = str_replace('00:00:00', '', $time); - if(trim($time) == '') return ; - if($format) return date($format, strtotime($time)); - return trim($time); -} diff --git a/framework/model.class.php b/framework/model.class.php deleted file mode 100644 index 2335d5dd18..0000000000 --- a/framework/model.class.php +++ /dev/null @@ -1,38 +0,0 @@ -dao->update($table)->set('deleted')->eq(1)->where('id')->eq($id)->exec(); - $object = preg_replace('/^' . preg_quote($this->config->db->prefix) . '/', '', trim($table, '`')); - $this->loadModel('action')->create($object, $id, 'deleted', '', $extra = ACTIONMODEL::CAN_UNDELETED); - } -} diff --git a/framework/router.class.php b/framework/router.class.php deleted file mode 100755 index 536dddf8dd..0000000000 --- a/framework/router.class.php +++ /dev/null @@ -1,159 +0,0 @@ -dbh and !empty($this->config->db->name)) - { - global $config; - if(!isset($config->global)) $config->global = new stdclass(); - $flow = $this->dbh->query('SELECT value FROM' . TABLE_CONFIG . "WHERE `owner`='system' AND `module`='common' AND `key`='flow'")->fetch(); - $config->global->flow = $flow ? $flow->value : 'full'; - - try - { - $productProject = $this->dbh->query('SELECT value FROM' . TABLE_CONFIG . "WHERE `owner`='system' AND `module`='custom' AND `key`='productProject'")->fetch(); - } - catch (PDOException $exception) - { - $repairCode = '|1034|1035|1194|1195|1459|'; - $errorInfo = $exception->errorInfo; - $errorCode = $errorInfo[1]; - $errorMsg = $errorInfo[2]; - $message = $exception->getMessage(); - if(strpos($repairCode, "|$errorCode|") !== false or ($errorCode == '1016' and strpos($errorMsg, 'errno: 145') !== false) or strpos($message, 'repair') !== false) - { - if(isset($config->framework->autoRepairTable) and $config->framework->autoRepairTable) - { - header("location: " . $config->webRoot . 'checktable.php'); - exit; - } - } - } - } - - $productCommon = $projectCommon = 0; - if($productProject) - { - $productProject = $productProject->value; - list($productCommon, $projectCommon) = explode('_', $productProject); - } - $lang->productCommon = isset($this->config->productCommonList[$this->clientLang][(int)$productCommon]) ? $this->config->productCommonList[$this->clientLang][(int)$productCommon] : $this->config->productCommonList['zh-cn'][0]; - $lang->projectCommon = isset($this->config->projectCommonList[$this->clientLang][(int)$projectCommon]) ? $this->config->projectCommonList[$this->clientLang][(int)$projectCommon] : $this->config->projectCommonList['zh-cn'][0]; - } - - parent::loadLang($moduleName, $appName); - - /* Merge from the db lang. */ - if($moduleName != 'common' and isset($lang->db->custom[$moduleName])) - { - foreach($lang->db->custom[$moduleName] as $section => $fields) - { - if(isset($lang->{$moduleName}->{$section}[''])) - { - $nullKey = ''; - $nullValue = $lang->{$moduleName}->{$section}[$nullKey]; - } - elseif(isset($lang->{$moduleName}->{$section}[0])) - { - $nullKey = 0; - $nullValue = $lang->{$moduleName}->{$section}[0]; - } - unset($lang->{$moduleName}->{$section}); - - if(isset($nullKey))$lang->{$moduleName}->{$section}[$nullKey] = $nullValue; - foreach($fields as $key => $value) $lang->{$moduleName}->{$section}[$key] = $value; - unset($nullKey); - unset($nullValue); - } - } - return $lang; - } - - /** - * Save error info. - * - * @param int $level - * @param string $message - * @param string $file - * @param int $line - * @access public - * @return void - */ - public function saveError($level, $message, $file, $line) - { - $fatalLevel[E_ERROR] = E_ERROR; - $fatalLevel[E_PARSE] = E_PARSE; - $fatalLevel[E_CORE_ERROR] = E_CORE_ERROR; - $fatalLevel[E_USER_ERROR] = E_USER_ERROR; - if(isset($fatalLevel[$level])) $this->config->debug = true; - parent::saveError($level, $message, $file, $line); - } - - /** - * Alias load module config. - * - * @param string $moduleName - * @param string $appName - * @access public - * @return void - */ - public function loadConfig($moduleName, $appName = '') - { - return parent::loadModuleConfig($moduleName, $appName); - } - - /** - * Export config. - * - * @access public - * @return void - */ - public function exportConfig() - { - ob_start(); - parent::exportConfig(); - $view = ob_get_contents(); - ob_end_clean(); - - $view = json_decode($view); - $view->rand = $this->session->random; - $this->session->set('rand', $this->session->random); - echo json_encode($view); - } -} diff --git a/framework/tests/helper/.101.setmember.onelevel.et b/framework/tests/helper/.101.setmember.onelevel.et deleted file mode 100644 index 5b184f35fa..0000000000 --- a/framework/tests/helper/.101.setmember.onelevel.et +++ /dev/null @@ -1,13 +0,0 @@ -value1.1 -value2 -3 -Array -( - [0] => 1 - [1] => 2 - [2] => 3 -) -stdClass Object -( - [key1] => value2.1 -) diff --git a/framework/tests/helper/.110.setmember.multilevel.et b/framework/tests/helper/.110.setmember.multilevel.et deleted file mode 100644 index ee73e72ede..0000000000 --- a/framework/tests/helper/.110.setmember.multilevel.et +++ /dev/null @@ -1,6 +0,0 @@ -Mary -20 -stdClass Object -( - [postcode] => 10000 -) diff --git a/framework/tests/helper/.201.getwebroot.inbrowse.et b/framework/tests/helper/.201.getwebroot.inbrowse.et deleted file mode 100644 index 618380792d..0000000000 --- a/framework/tests/helper/.201.getwebroot.inbrowse.et +++ /dev/null @@ -1,2 +0,0 @@ -/ -/zentao/ diff --git a/framework/tests/helper/.202.getwebroot.inshell.et b/framework/tests/helper/.202.getwebroot.inshell.et deleted file mode 100644 index 3de39a7763..0000000000 --- a/framework/tests/helper/.202.getwebroot.inshell.et +++ /dev/null @@ -1,8 +0,0 @@ -http://localhost webRoot is / -http://localhost/ webRoot is / -http://localhost/my/ webRoot is / -http://localhost/my-todo.html webRoot is / -http://localhost/index.php?m=my&f=index webRoot is / -http://localhost/zentao/my/ webRoot is /zentao/ -http://localhost/zentao/my-todo.html webRoot is /zentao/ -http://localhost/zentao/index.php?m=my&f=index webRoot is /zentao/ diff --git a/framework/tests/helper/101.setmember.onelevel.php b/framework/tests/helper/101.setmember.onelevel.php deleted file mode 100755 index cb7a794639..0000000000 --- a/framework/tests/helper/101.setmember.onelevel.php +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env php -key1 = 'value1'; - -$obj2 = new stdclass(); -$obj2->key1 = 'value2.1'; - -helper::setMember('obj', 'key1', 'value1.1'); // overide the exists key. -helper::setMember('obj', 'key2', 'value2'); // add a new key. -helper::setMember('obj', 'key3', 3); // set an int value. -helper::setMember('obj', 'key4', array(1, 2, 3)); // set an array value. -helper::setMember('obj', 'key5', $obj2); // set an object value. - -echo $obj->key1 . "\n"; -echo $obj->key2 . "\n"; -echo $obj->key3 . "\n"; -print_r($obj->key4); -print_r($obj->key5); diff --git a/framework/tests/helper/110.setmember.multilevel.php b/framework/tests/helper/110.setmember.multilevel.php deleted file mode 100755 index 14d3baf0cd..0000000000 --- a/framework/tests/helper/110.setmember.multilevel.php +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env php -user = new stdclass(); -$obj->user->name = 'Tom'; - -helper::setMember('obj', 'user.name', 'Mary'); // overide the exists key. -helper::setMember('obj', 'user.age', 20); // add a child key to an existing key. -helper::setMember('obj', 'home.address', new stdclass()); // add a child key even the parent doesn't exist. -helper::setMember('obj', 'home.address.postcode', '10000'); // three level. - -echo $obj->user->name . "\n"; -echo $obj->user->age . "\n"; -print_r($obj->home->address); diff --git a/framework/tests/helper/201.getwebroot.inbrowse.php b/framework/tests/helper/201.getwebroot.inbrowse.php deleted file mode 100755 index a630da9b4d..0000000000 --- a/framework/tests/helper/201.getwebroot.inbrowse.php +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env php -global = new stdclass(); -$config->global->flow = 'full'; - -/* set module root path and included the resource of group module. */ -$moduleRoot = '../module/'; -include $moduleRoot . '/group/lang/resource.php'; -foreach(glob($moduleRoot . '/group/ext/lang/zh-cn/*.php') as $resourceFile) -{ - include $resourceFile; -} - -$lang->productCommon = ''; -$lang->projectCommon = ''; - -$whiteList[] = 'api-getsessionid'; -$whiteList[] = 'admin-setflow'; -$whiteList[] = 'bug-buildtemplates'; -$whiteList[] = 'bug-sendmail'; -$whiteList[] = 'board-managechild'; -$whiteList[] = 'custom-menu'; -$whiteList[] = 'company-create'; -$whiteList[] = 'company-delete'; -$whiteList[] = 'file-buildexporttpl'; -$whiteList[] = 'file-buildform'; -$whiteList[] = 'file-printfiles'; -$whiteList[] = 'file-export2csv'; -$whiteList[] = 'file-export2xml'; -$whiteList[] = 'file-export2html'; -$whiteList[] = 'file-export2excel'; -$whiteList[] = 'file-export2word'; -$whiteList[] = 'file-senddownheader'; -$whiteList[] = 'file-read'; -$whiteList[] = 'help-field'; -$whiteList[] = 'index-testext'; -$whiteList[] = 'productplan-commonaction'; -$whiteList[] = 'project-managechilds'; -$whiteList[] = 'project-tips'; -$whiteList[] = 'project-commonaction'; -$whiteList[] = 'project-sendmail'; -$whiteList[] = 'release-commonaction'; -$whiteList[] = 'task-commonaction'; -$whiteList[] = 'task-sendmail'; -$whiteList[] = 'testtask-sendmail'; -$whiteList[] = 'user-login'; -$whiteList[] = 'user-deny'; -$whiteList[] = 'user-logout'; -$whiteList[] = 'user-setreferer'; -$whiteList[] = 'svn-run'; -$whiteList[] = 'git-run'; -$whiteList[] = 'admin-ignore'; -$whiteList[] = 'admin-register'; -$whiteList[] = 'admin-win2unix'; -$whiteList[] = 'admin-bind'; -$whiteList[] = 'admin-certifyztemail'; -$whiteList[] = 'admin-certifyztmobile'; -$whiteList[] = 'admin-ztcompany'; -$whiteList[] = 'story-commonaction'; -$whiteList[] = 'story-sendmail'; -$whiteList[] = 'webapp-ajaxaddview'; -$whiteList[] = 'report-remind'; -$whiteList[] = 'sso-auth'; -$whiteList[] = 'sso-depts'; -$whiteList[] = 'sso-users'; -$whiteList[] = 'sso-login'; -$whiteList[] = 'sso-logout'; -$whiteList[] = 'sso-bind'; -$whiteList[] = 'sso-getuserpairs'; -$whiteList[] = 'sso-getbindusers'; -$whiteList[] = 'sso-binduser'; -$whiteList[] = 'sso-createuser'; -$whiteList[] = 'sso-gettodolist'; -$whiteList[] = 'mail-asyncsend'; -$whiteList[] = 'user-reset'; -$whiteList[] = 'product-showerrornone'; -$whiteList[] = 'tutorial-start'; -$whiteList[] = 'tutorial-index'; -$whiteList[] = 'tutorial-quit'; -$whiteList[] = 'tutorial-wizard'; -$whiteList[] = 'my-buildcontactlists'; -$whiteList[] = 'mail-ztcloud'; -$whiteList[] = 'doc-diff'; -$whiteList[] = 'testreport-commonaction'; -$whiteList[] = 'testsuite-library'; -$whiteList[] = 'testsuite-createlib'; -$whiteList[] = 'testsuite-createcase'; -$whiteList[] = 'testsuite-libview'; - - -/* checking actions of every module. */ -echo '-------------action checking-----------------' . "\n"; -foreach(glob($moduleRoot . '*') as $modulePath) -{ - $moduleName = basename($modulePath); - if(strpos('install|upgrade|convert|common|misc|editor', $moduleName) !== false) continue; - $controlFile = $modulePath . '/control.php'; - if(file_exists($controlFile)) - { - include $controlFile; - if(class_exists($moduleName)) - { - if($moduleName == 'block') continue; - $class = new ReflectionClass($moduleName); - $methods = $class->getMethods(); - foreach($methods as $method) - { - $methodRef = new ReflectionMethod($method->class, $method->name); - if($methodRef->isPublic() and strpos($method->name, '__') === false) - { - $methodName = $method->name; - if(in_array($moduleName . '-' . strtolower($method->name), $whiteList)) continue; - if(strpos($methodName, 'ajax') !== false) continue; - - $exits = false; - if(isset($lang->resource->$moduleName)) - { - foreach($lang->resource->$moduleName as $key => $label) - { - if(strtolower($methodName) == strtolower($key)) $exits = true; - } - } - if(!$exits) echo $moduleName . "\t" . $methodName . " not in the list. \n"; - } - } - } - } - - /* Checking extension files. */ - $extControlFiles = glob($modulePath . '/ext/control/*.php'); - if($extControlFiles) - { - foreach($extControlFiles as $extControlFile) - { - $methodFile = substr($extControlFile, strrpos($extControlFile, '/') + 1); - $methodName = substr($methodFile, 0, strpos($methodFile, '.')); - if(in_array($moduleName . '-' . strtolower($methodName), $whiteList)) continue; - if(strpos($methodName, 'ajax') !== false) continue; - - $exits = false; - foreach($lang->resource->$moduleName as $key => $label) - { - if(strtolower($methodName) == strtolower($key)) $exits = true; - } - if(!$exits) echo $moduleName . "\t" . $methodName . " not in the list. \n"; - } - } -} - -/* checking actions of every module. */ -echo '-------------lang checking-----------------' . "\n"; -include '../module/common/lang/zh-cn.php'; -include '../config/config.php'; -foreach(glob($moduleRoot . '*') as $modulePath) -{ - unset($lang); - $moduleName = basename($modulePath); - $mainLangFile = $modulePath . '/lang/zh-cn.php'; - if(!file_exists($mainLangFile)) continue; - $mainLines = file($mainLangFile); - - foreach($config->langs as $langKey => $langName) - { - if($langKey == 'zh-cn' or $langKey == 'zh-tw') continue; - $langFile = $modulePath . '/lang/' . $langKey . '.php'; - if(!file_exists($langFile)) continue; - $lines = file($langFile); - foreach($mainLines as $lineNO => $line) - { - if(strpos($line, '$lang') === false) - { - //if($line != $lines[$lineNO]) echo $moduleName . ' ' . $langKey . ' ' . $lineNO . "\n"; - } - else - { - if(strpos($line, '=') !== false) - { - list($mainKey, $mainValue) = explode('=', $line); - list($key, $value) = explode('=', $lines[$lineNO]); - } - if((strpos($line, '=') === false and $line != $lines[$lineNO]) or trim($mainKey) != trim($key)) - { - $key = trim($key); - $lineNO = $lineNO + 1; - echo "module $moduleName need checking, command is:"; - echo " vim -O +$lineNO ../module/$moduleName/lang/zh-cn.php +$lineNO ../module/$moduleName/lang/en.php \n"; - break; - } - } - } - } - - foreach(glob($modulePath . '/ext/lang/zh-cn/*.php') as $extMainLangFile) - { - $extMainLines = file($extMainLangFile); - $extLangFile = basename($extMainLangFile); - $extEnFile = $modulePath . '/ext/lang/en/' . $extLangFile; - $extLines = file($extEnFile); - foreach($extMainLines as $lineNO => $line) - { - if(strpos($line, '$lang') === false) - { - //if($line != $lines[$lineNO]) echo $moduleName . ' ' . $langKey . ' ' . $lineNO . "\n"; - } - else - { - list($mainKey, $mainValue) = explode('=', $line); - list($key, $value) = explode('=', $extLines[$lineNO]); - if(trim($mainKey) != trim($key)) - { - $key = trim($key); - $lineNO = $lineNO + 1; - echo "module $moduleName need checking, command is:"; - echo " vim -O +$lineNO ../../module/$moduleName/ext/lang/zh-cn/$extLangFile +$lineNO ../../module/$moduleName/ext/lang/en/$extLangFile \n"; - break; - } - } - } - } -} - -echo '-------------php5.4 synatax checking-----------------' . "\n"; -class app {function loadLang() {}} -$app = new app; -$lang = new stdclass(); - -error_reporting(E_WARNING | E_STRICT ); -foreach(glob($moduleRoot . '*') as $modulePath) -{ - $moduleName = basename($modulePath); - $cnLangFile = $modulePath . '/lang/zh-cn.php'; - $enLangFile = $modulePath . '/lang/en.php'; - $configFile = $modulePath . '/config.php'; - - if(!isset($lang->$moduleName)) $lang->$moduleName = new stdclass(); - if(!isset($config->$moduleName)) $config->$moduleName = new stdclass(); - if(file_exists($cnLangFile)) include $cnLangFile; - if(file_exists($enLangFile)) include $enLangFile; - if(file_exists($configFile)) include $configFile; -} - -echo '-------------demo data checking. -----------------' . "\n"; -$demoSQL = file("../db/demo.sql"); -foreach($demoSQL as $line => $sql) -{ - if(strpos($sql, 'INSERT') === false) continue; - - if(strpos($sql, $config->db->prefix . 'config') !== false or - strpos($sql, $config->db->prefix . 'company') !== false or - strpos($sql, $config->db->prefix . 'group') !== false) - { - die('line ' . ($line + 1) . " has error\n"); - } -} diff --git a/tools/cn2tw.php b/tools/cn2tw.php deleted file mode 100755 index 8af43a45b4..0000000000 --- a/tools/cn2tw.php +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env php - $targetLangFile"); - $defaultLang = file_get_contents($targetLangFile); - $targetLang = str_replace('zh-cn', $langDesc, $defaultLang); - file_put_contents($targetLangFile, $targetLang); -} -?> diff --git a/tools/copylang.php b/tools/copylang.php deleted file mode 100755 index 8f7d1a34ce..0000000000 --- a/tools/copylang.php +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env php - diff --git a/tools/exportactions.php b/tools/exportactions.php deleted file mode 100755 index 3bf58bdd0b..0000000000 --- a/tools/exportactions.php +++ /dev/null @@ -1,29 +0,0 @@ -getMethods(); - foreach($methods as $method) - { - $methodRef = new ReflectionMethod($method->class, $method->name); - if($methodRef->isPublic() and strpos($method->name, '__') === false) - { - echo "\$lang['action']['$moduleName']['$method->name'] = '$method->name';\n"; - } - } - echo "\n"; - } - } -} -?> diff --git a/tools/getallcommon.php b/tools/getallcommon.php deleted file mode 100755 index 6bea6b1765..0000000000 --- a/tools/getallcommon.php +++ /dev/null @@ -1,28 +0,0 @@ - $maxLength) $maxLength = strlen($moduleName); -} - -foreach($modules as $modulePath) -{ - $moduleName = basename($modulePath); - if($moduleName == 'help' or $moduleName == 'editor') continue; - $langFile = $modulePath . "/lang/$langType.php"; - if(!file_exists($langFile)) continue; - include $langFile; - - $moduleTitle = ''; - if(isset($lang->$moduleName->common)) - { - $moduleTitle = $lang->$moduleName->common; - } - - echo "\$lang->editor->modules['$moduleName'] " . str_pad('', $maxLength - strlen($moduleName)) . "= '$moduleTitle';\n"; - -} diff --git a/tools/initext.php b/tools/initext.php deleted file mode 100755 index be9f06a725..0000000000 --- a/tools/initext.php +++ /dev/null @@ -1,73 +0,0 @@ - - * @package common - * @version $Id$ - * @link http://www.zentao.net - */ -include '../config/config.php'; - -$modules = array(); -$moduleRoot = realpath('../module/') . '/'; - -if(is_dir($moduleRoot)) -{ - if($dh = opendir($moduleRoot)) - { - while($module = readdir($dh)) - { - if(strpos(basename($module), '.') === false) $modules[] = $module; - } - closedir($dh); - } -} -else -{ - die("The module you input does not exist. \n"); -} - -foreach($modules as $module) -{ - /* 设定各个目录。*/ - $extRoot = $moduleRoot . DIRECTORY_SEPARATOR. $module . DIRECTORY_SEPARATOR . 'ext'; - $extControl = $extRoot . DIRECTORY_SEPARATOR . 'control'; - $extModel = $extRoot . DIRECTORY_SEPARATOR . 'model'; - $extView = $extRoot . DIRECTORY_SEPARATOR . 'view'; - $extCSS = $extRoot . DIRECTORY_SEPARATOR . 'css'; - $extJS = $extRoot . DIRECTORY_SEPARATOR . 'js'; - $extConfig = $extRoot . DIRECTORY_SEPARATOR . 'config'; - $extLang = $extRoot . DIRECTORY_SEPARATOR . 'lang' . DIRECTORY_SEPARATOR; - - /* 建立各个扩展目录 */ - if(!file_exists($extRoot)) mkdir($extRoot, 0777); - if(!file_exists($extControl)) mkdir($extControl, 0777); - if(!file_exists($extModel)) mkdir($extModel, 0777); - if(!file_exists($extView)) mkdir($extView, 0777); - if(!file_exists($extCSS)) mkdir($extCSS, 0777); - if(!file_exists($extJS)) mkdir($extJS, 0777); - if(!file_exists($extConfig)) mkdir($extConfig, 0777); - if(!file_exists($extLang)) mkdir($extLang, 0777); - - /* Touch .gitkeep file. */ - touch($extControl . '/.gitkeep'); - touch($extModel . '/.gitkeep'); - touch($extView . '/.gitkeep'); - touch($extCSS . '/.gitkeep'); - touch($extJS . '/.gitkeep'); - touch($extConfig . '/.gitkeep'); - - /* 创建语言目录。*/ - $langs = array_keys($config->langs); - foreach($langs as $lang) - { - $langPath = $extLang . $lang; - if(!file_exists($langPath)) mkdir($langPath, 0777); - touch($langPath . '/.gitkeep'); - } - - echo "init $module ... \n"; -} diff --git a/tools/minifyfront.php b/tools/minifyfront.php deleted file mode 100755 index d8eaa75ead..0000000000 --- a/tools/minifyfront.php +++ /dev/null @@ -1,74 +0,0 @@ -productCommon = ''; -$lang->projectCommon = ''; -include $baseDir . '/module/common/lang/zh-cn.php'; -$langs = array_keys($config->langs); -$themes = array_keys($lang->themes); - -/* Create css files for every them and every lang. */ -$zuiCode = str_replace('../fonts', '../zui/fonts', file_get_contents($themeRoot . 'zui/css/min.css')); -foreach($langs as $lang) -{ - foreach($themes as $theme) - { - /* Common css files. */ - $cssCode = $zuiCode; - $cssCode .= file_get_contents($themeRoot . 'default/style.css'); - $cssCode .= file_get_contents($jqueryRoot . 'chosen/min.css'); - $cssCode .= file_get_contents($themeRoot . 'default/treeview.css'); - $cssCode .= file_get_contents($jqueryRoot . 'datetimepicker/min.css'); - - /* Css file for current lang and current them. */ - $cssCode .= file_get_contents($themeRoot . "lang/$lang.css"); - if($theme != 'default') - { - $themCode = file_get_contents($themeRoot . $theme . '/style.css'); - $cssCode .= str_replace('./images', "../$theme/images", $themCode); - } - - /* Combine them. */ - $cssFile = $themeRoot . "default/$lang.$theme.css"; - file_put_contents($cssFile, $cssCode); - - /* Compress it. */ - `java -jar ~/bin/yuicompressor/build/yuicompressor.jar --type css $cssFile -o $cssFile`; - } -} diff --git a/tools/preparetest.php b/tools/preparetest.php deleted file mode 100755 index bce62e92d7..0000000000 --- a/tools/preparetest.php +++ /dev/null @@ -1,60 +0,0 @@ - $database.sql;\n"; - $cmd .= "mysql -uroot $backupDatabase < $database.sql;\n"; - $cmd .= "rm -fr $database.sql"; - system($cmd); - } -} - -/* Restore stored backup databases. */ -function restore() -{ - global $databases; - foreach($databases as $database) - { - $backupDatabase = "back_$database"; - mysql_query("DROP DATABASE $database"); - mysql_query("CREATE DATABASE $database"); - $cmd = "mysqldump -u root $backupDatabase > $database.sql;\n"; - $cmd .= "mysql -uroot $database < $database.sql;\n"; - $cmd .= "rm -fr $database.sql"; - system($cmd); - } -} - -/* Connect to database. */ -function connectDB() -{ - global $config; - mysql_connect($config->db->host, $config->db->user, $config->db->password); -} diff --git a/tools/replace.sh b/tools/replace.sh deleted file mode 100755 index 8536f5eb8b..0000000000 --- a/tools/replace.sh +++ /dev/null @@ -1,17 +0,0 @@ -#replace title -foreachd(){ - for file in `ls $1` - do - if [ -d $1/$file ] - then - echo "into dir $1/$file" - foreachd $1/$file - elif [ -f $1/$file ] - then -# sed -i '1,11s/\@license.*$/\@license ZPL \(http:\/\/zpl\.pub\/page\/zplv11\.html\)/g' $1/$file - sed -i '1,11s/\@copyright.*$/\@copyright Copyright 2009-2015 青岛易软天创网络科技有限公司\(QingDao Nature Easy Soft Network Technology Co,LTD, www\.cnezsoft\.com\)/g' $1/$file - fi - done -} - -foreachd $1 diff --git a/tools/syncext.php b/tools/syncext.php deleted file mode 100755 index cad41b07ce..0000000000 --- a/tools/syncext.php +++ /dev/null @@ -1,100 +0,0 @@ -#!/usr/bin/env php - -# @author yidong wang -# - -# Judge the params, must give $src and $dest. -if [ $# -lt 2 ]; then - echo './syncext.sh src dest' - exit 1 -fi - -# Judge inotifywait tool exists or not. -which inotifywait > /dev/null -if [ $? -ne 0 ]; then - echo 'No inotifywait. Please install inotify-tools, for debian or ubuntun run apt-get install inotify-tools.'; - exit 1 -fi - -# Get $src and $dest. -src=$1/ -dest=$2/ - -# Rsync when the shell load first. -rsync -aqP --exclude="db/" $src $dest -echo `date "+%H:%M:%S"` sync $src to $dest succssfully. - -# Watch the $src directory, and sync files to destination. -inotifywait -mrq --event create,modify,delete,move --format '%w %e %f' $src |\ -while read watcher event file ; do - - # compute the $path2process. - path2process=$watcher$file - path2process=${path2process/$src/$dest} - - # Delete a file or a directory. - if [ "$event" == "DELETE" -o "$event" == "DELETE,ISDIR" ]; then - - # If delete a file, use rm -fr, directory, use rmdir for security. - if [ "$event" == "DELETE" ]; then - rm -fr $path2process - else - rmdir $path2process - fi - - echo `date "+%H:%M:%S"` $path2process deleted.; - - # If event is ngnored, continue. - elif [ "$event" == "IGNORED" ]; then - - continue - - # Sync files. - else - - echo `date "+%H:%M:%S"` $path2process copied. - rsync -aqP --exclude='db/' $src/ $dest - fi - -done diff --git a/tools/zdog.sh b/tools/zdog.sh deleted file mode 100755 index e0e6354df7..0000000000 --- a/tools/zdog.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash -# -# Watch a upload directory and remove dangder files. -# -# @author chunsheng wang - -# Judge the params, must give $dir -if [ $# -lt 1 ]; then - echo './zdog.sh directory' - exit 1 -fi - -# Judge inotifywait tool exists or not. -which inotifywait > /dev/null -if [ $? -ne 0 ]; then - echo 'No inotifywait. Please install inotify-tools, for debian or ubuntun run apt-get install inotify-tools.'; - exit 1 -fi - -# Get the directory to watch. -dir=$@ - -# Watch the $dir directory -if [ ! -d "/tmp/zdog" ]; then - mkdir -v /tmp/zdog; -fi -echo `date "+%H:%M:%S"` begin watching $dir > /tmp/zdog/zdog.log -inotifywait -mrq --event create,modify --format '%w %e %f' $dir |\ -while read watcher event file ; do - - # compute the $path2process. - path2process=$watcher$file - targetfile=/tmp/zdog/$file; - echo $path2process | grep -q '.php'; - if [ $? -eq 0 ] && [ -s $path2process ]; then - sudo mv -f $path2process $targetfile; - echo `date "+%H:%M:%S"` $path2process moved to $targetfile >> /tmp/zdog/zdog.log 2>&1; - fi -done From 1f102d851de8264d3e4a05d44c06faf3d78c21ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BB=94=E5=93=A5?= Date: Fri, 20 Oct 2017 15:11:27 +0800 Subject: [PATCH 5/8] "Task list add btn" --- module/project/js/common.js | 17 ++++++++++++++ module/task/js/common.js | 2 +- module/task/model.php | 1 + module/task/view/view.html.php | 42 ++++++++++++++++++++++++++++++++-- 4 files changed, 59 insertions(+), 3 deletions(-) diff --git a/module/project/js/common.js b/module/project/js/common.js index dc3a24d66a..5f3298ac06 100644 --- a/module/project/js/common.js +++ b/module/project/js/common.js @@ -174,3 +174,20 @@ $(function() computeWorkDays(this.id); }) }); + +$('.task-toggle').click(function() +{ + var obj = $(this).find('i'); + var id = $(this).data('id'); + if(obj.hasClass('icon-plus')) + { + $('tr.parent-'+id).show(); + obj.removeClass('icon-plus').addClass('icon-minus'); + } + else if(obj.hasClass('icon-minus')) + { + $('tr.parent-'+id).hide(); + obj.removeClass('icon-minus').addClass('icon-plus'); + } + return false; +}); \ No newline at end of file diff --git a/module/task/js/common.js b/module/task/js/common.js index 140db4051e..9363ddb004 100644 --- a/module/task/js/common.js +++ b/module/task/js/common.js @@ -56,4 +56,4 @@ $('#modalTeam .btn').click(function() $('#teamMember').val(team); $('#estimate').val(time); }) -}) +}) \ No newline at end of file diff --git a/module/task/model.php b/module/task/model.php index b7643dc362..1dc1000479 100644 --- a/module/task/model.php +++ b/module/task/model.php @@ -1836,6 +1836,7 @@ class taskModel extends model if($modulePairs and $task->module) echo "" . $modulePairs[$task->module] . ' '; echo html::a($taskLink, $task->name, null, "style='color: $task->color'"); if($task->fromBug) echo html::a(helper::createLink('bug', 'view', "id=$task->fromBug"), "[BUG#$task->fromBug]", '_blank', "class='bug'"); + if($task->children) echo '    '; break; case 'type': echo $this->lang->task->typeList[$task->type]; diff --git a/module/task/view/view.html.php b/module/task/view/view.html.php index 3decac4ae3..58ab441e40 100644 --- a/module/task/view/view.html.php +++ b/module/task/view/view.html.php @@ -87,7 +87,6 @@
storyVerify;?>
- cases) and $task->cases):?>
task->case;?> @@ -98,7 +97,46 @@
- + children)):?> +
+ lang->task->children;?> + + + + + + + + + + + + + children as $child):?> + + + + + + + + + + + + +
task->id;?> task->lblPri;?> task->name;?>task->deadline;?> task->assignedTo;?> task->status;?> task->consumedAB . $lang->task->lblHour;?>task->leftAB . $lang->task->lblHour;?>actions;?>
id;?>task->priList[$child->pri];?>id"); ?>">name;?>deadline;?>assignedTo])) echo $users[$child->assignedTo];?>task->statusList, $child->status);?>consumed;?>left;?> + project&taskID=$child->id", $child, 'list', '', '', 'iframe', true); + common::printIcon('task', 'start', "taskID=$child->id", $child, 'list', '', '', 'iframe', true); + common::printIcon('task', 'recordEstimate', "taskID=$child->id", $child, 'list', 'time', '', 'iframe', true); + common::printIcon('task', 'finish', "taskID=$child->id", $child, 'list', '', '', 'iframe', true); + common::printIcon('task', 'close', "taskID=$child->id", $child, 'list', '', '', 'iframe', true); + common::printIcon('task', 'edit',"taskID=$child->id", $child, 'list'); + ?> +
+
+ fetch('file', 'printFiles', array('files' => $task->files, 'fieldset' => 'true'));?>
deleted) echo $actionLinks;?>
From 421e046c930cb8b41990af585da9994d2759c50b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BB=94=E5=93=A5?= Date: Fri, 20 Oct 2017 15:17:24 +0800 Subject: [PATCH 6/8] "style change" --- module/task/view/view.html.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/module/task/view/view.html.php b/module/task/view/view.html.php index 58ab441e40..418625d699 100644 --- a/module/task/view/view.html.php +++ b/module/task/view/view.html.php @@ -115,7 +115,13 @@ children as $child):?> id;?> - task->priList[$child->pri];?> + + lang->task->priList, $child->pri, $child->pri) . "'>"; + echo $child->pri == '0' ? '' : zget($this->lang->task->priList, $child->pri, $child->pri); + echo ""; + ?> + id"); ?>">name;?> deadline;?> assignedTo])) echo $users[$child->assignedTo];?> From 371b945d32baadd23a1d46844e1b6cd942d6336a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BB=94=E5=93=A5?= Date: Fri, 20 Oct 2017 15:49:07 +0800 Subject: [PATCH 7/8] framework --- framework/base/control.class.php | 887 ++++++ framework/base/helper.class.php | 747 +++++ framework/base/model.class.php | 302 ++ framework/base/router.class.php | 2517 +++++++++++++++++ framework/control.class.php | 23 + framework/helper.class.php | 143 + framework/model.class.php | 38 + framework/router.class.php | 159 ++ .../tests/helper/.101.setmember.onelevel.et | 13 + .../tests/helper/.110.setmember.multilevel.et | 6 + .../tests/helper/.201.getwebroot.inbrowse.et | 2 + .../tests/helper/.202.getwebroot.inshell.et | 8 + .../tests/helper/101.setmember.onelevel.php | 27 + .../tests/helper/110.setmember.multilevel.php | 22 + .../tests/helper/201.getwebroot.inbrowse.php | 17 + .../tests/helper/202.getwebroot.inshell.php | 43 + 16 files changed, 4954 insertions(+) create mode 100644 framework/base/control.class.php create mode 100644 framework/base/helper.class.php create mode 100644 framework/base/model.class.php create mode 100644 framework/base/router.class.php create mode 100644 framework/control.class.php create mode 100644 framework/helper.class.php create mode 100644 framework/model.class.php create mode 100755 framework/router.class.php create mode 100644 framework/tests/helper/.101.setmember.onelevel.et create mode 100644 framework/tests/helper/.110.setmember.multilevel.et create mode 100644 framework/tests/helper/.201.getwebroot.inbrowse.et create mode 100644 framework/tests/helper/.202.getwebroot.inshell.et create mode 100755 framework/tests/helper/101.setmember.onelevel.php create mode 100755 framework/tests/helper/110.setmember.multilevel.php create mode 100755 framework/tests/helper/201.getwebroot.inbrowse.php create mode 100755 framework/tests/helper/202.getwebroot.inshell.php diff --git a/framework/base/control.class.php b/framework/base/control.class.php new file mode 100644 index 0000000000..23dde557c2 --- /dev/null +++ b/framework/base/control.class.php @@ -0,0 +1,887 @@ +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; + + global $loadedModels; + if(isset($loadedModels[$appName][$moduleName])) + { + $this->$moduleName = $loadedModels[$appName][$moduleName]; + $this->dao = $this->$moduleName->dao; + return $this->$moduleName; + } + + $modelFile = $this->app->setModelFile($moduleName, $appName); + + /** + * 如果没有model文件,尝试加载config配置信息。 + * If no model file, try load config. + */ + if(!helper::import($modelFile)) + { + $this->app->loadModuleConfig($moduleName, $appName); + $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. + */ + $loadedModels[$appName][$moduleName] = new $modelClass($appName); + $this->$moduleName = $loadedModels[$appName][$moduleName]; + $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; + } + + /** + * 设置客户端的设备类型。 + * 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'; + $viewFile = $mainViewFile; + + if(!empty($viewExtPath)) + { + $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->app->siteCode) + { + $extPath = dirname(dirname(realpath($viewFile))) . "/ext/_{$this->app->siteCode}/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') ; + + $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); + + if(!empty($cssExtPath)) + { + $cssMethodExt = $cssExtPath['common'] . $methodName . DS; + $cssCommonExt = $cssExtPath['common'] . '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); + + 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'); + + $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); + + if(!empty($jsExtPath)) + { + $jsMethodExt = $jsExtPath['common'] . $methodName . DS; + $jsCommonExt = $jsExtPath['common'] . '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); + + 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 the module name is empty, then use the current module and method. + */ + 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; + } + + $currentModuleName = $this->moduleName; + $currentMethodName = $this->methodName; + $currentAppName = $this->appName; + $currentParams = $this->app->getParams(); + + /** + * 设置调用指定模块的指定方法。 + * chang the dir to the previous. + */ + $this->app->setModuleName($moduleName); + $this->app->setMethodName($methodName); + + if(!is_array($params)) parse_str($params, $params); + $this->app->params = $params; + + $currentPWD = getcwd(); + + /** + * 设置引用的文件和路径。 + * Set the pathes and files to included. + */ + $modulePath = $this->app->getModulePath($appName, $moduleName); + $moduleControlFile = $modulePath . 'control.php'; + $actionExtPath = $this->app->getModuleExtPath($appName, $moduleName, 'control'); + $file2Included = $moduleControlFile; + + if(!empty($actionExtPath)) + { + /** + * 设置公共扩展。 + * set common extension. + */ + $commonActionExtFile = $actionExtPath['common'] . strtolower($methodName) . '.php'; + $file2Included = file_exists($commonActionExtFile) ? $commonActionExtFile : $moduleControlFile; + + if(!empty($actionExtPath['site'])) + { + /** + * 设置站点扩展。 + * every site has it's extension. + */ + $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); + 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. + */ + $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(); + + unset($module); + + /** + * 切换回之前的模块和方法。 + * Chang the module、method to the previous. + */ + $this->app->setModuleName($currentModuleName); + $this->app->setMethodName($currentMethodName); + $this->app->params = $currentParams; + + chdir($currentPWD); + + /** + * 返回内容。 + * Return the content. + */ + 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() or $this->viewType == 'json') 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; + } +} diff --git a/framework/base/helper.class.php b/framework/base/helper.class.php new file mode 100644 index 0000000000..9066ccc455 --- /dev/null +++ b/framework/base/helper.class.php @@ -0,0 +1,747 @@ + + * db->user = 'wwccss'; + * helper::setMember('lang', 'db.user', 'chunsheng.wang'); + * ?> + * + * @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(<< + * 'value1', 'var2' => 'value2'); + * ?> + * + * @param string $moduleName module name, can pass appName like app.module. + * @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 bool $onlyBody pass onlyBody=yes to the link thus the app can control the header and footer hide or show.. + * @static + * @access public + * @return string the link string. + */ + static public function createLink($moduleName, $methodName = 'index', $vars = '', $viewType = '', $onlyBody = false) + { + /* 设置$appName和$moduleName。Set appName and moduleName. */ + global $app, $config; + if(strpos($moduleName, '.') !== false) + { + list($appName, $moduleName) = explode('.', $moduleName); + } + else + { + $appName = $app->getAppName(); + } + if(!empty($appName)) $appName .= '/'; + + /* 处理$viewType和$vars。Set $viewType and $vars. */ + if(empty($viewType)) $viewType = $app->getViewType(); + if(!is_array($vars)) parse_str($vars, $vars); + + /* 生成url链接的开始部分。Set the begin parts of the link. */ + if($config->requestType == 'PATH_INFO') $link = $config->webRoot . $appName; + if($config->requestType != 'PATH_INFO') $link = $config->webRoot . $appName . basename($_SERVER['SCRIPT_NAME']); + if($config->requestType == 'PATH_INFO2') $link .= '/'; + + /** + * #1: RequestType为GET。When the requestType is GET. + * Input: moduleName=article&methodName=index&var1=value1. Output: ?m=article&f=index&var1=value1. + * + */ + if($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"; + return self::processOnlyBodyParam($link, $onlyBody); + } + + /** + * #2: 方法名不是默认值或者是默认值,但有传参。MethodName equals the default method or vars not empty. + * Input: moduleName=article&methodName=view. Output: article-view.html + * Input: moduleName=article&methodName=view. Output: article-index-abc.html + * + */ + if($methodName != $config->default->method or !empty($vars)) + { + $link .= "$moduleName{$config->requestFix}$methodName"; + foreach($vars as $value) $link .= "{$config->requestFix}$value"; + $link .= '.' . $viewType; + + return self::processOnlyBodyParam($link, $onlyBody); + } + + /** + * #3: 方法名为默认值且没有传参且模块名为默认值。MethodName is the default and moduleName is default and vars empty. + * Input: moduleName=index&methodName=index. Output: index.html + * + */ + if($moduleName == $config->default->module) + { + $link .= $config->default->method . '.' . $viewType; + return self::processOnlyBodyParam($link, $onlyBody); + } + + /** + * #4: 方法名为默认值且没有传参且模块名不为默认值,viewType和app指定的相等。MethodName is default but moduleName not and viewType equal app's viewType.. + * Input: moduleName=article&methodName=index&viewType=html. Output: /article/ + * + */ + if($viewType == $app->getViewType()) + { + $link .= $moduleName . '/'; + return self::processOnlyBodyParam($link, $onlyBody); + } + + /** + * #5: 方法名为默认值且没有传参且模块名不为默认值,viewType有另外指定。MethodName is default but moduleName not and viewType no equls app's viewType. + * Input: moduleName=article&methodName=index&viewType=json. Output: /article.json + * + */ + $link .= $moduleName . '.' . $viewType; + return self::processOnlyBodyParam($link, $onlyBody); + } + + /** + * 处理onlyBody 参数。 + * Process the onlyBody param in url. + * + * 如果传参的时候设定了$onlyBody为真,或者当前页面请求中包含了onlybody=yes,在生成链接的时候继续追加。 + * If $onlyBody set to true or onlybody=yes in the url, append onlyBody param to the link. + * + * @param string $link + * @param bool $onlyBody + * @static + * @access public + * @return string + */ + public static function processOnlyBodyParam($link, $onlyBody = false) + { + global $config; + if(!$onlyBody and !self::inOnlyBodyMode()) return $link; + $onlybodyString = $config->requestType != 'GET' ? "?onlybody=yes" : "&onlybody=yes"; + return $link . $onlybodyString; + } + + /** + * 检查是否是onlybody模式。 + * Check in only body mode or not. + * + * @access public + * @return void + */ + public static function inOnlyBodyMode() + { + return (isset($_GET['onlybody']) and $_GET['onlybody'] == 'yes'); + } + + /** + * 使用helper::import()来引入文件,不要直接使用include或者require. + * Using helper::import() to import a file, instead of include or require. + * + * @param string $file the file to be imported. + * @static + * @access public + * @return bool + */ + static public function import($file) + { + if(!is_file($file)) return false; + + static $includedFiles = array(); + if(!isset($includedFiles[$file])) + { + include $file; + $includedFiles[$file] = true; + return true; + } + + return true; + } + + /** + * 将数组或者列表转化成 IN( 'a', 'b') 的形式。 + * Convert a list to IN('a', 'b') string. + * + * @param string|array $idList 列表,可以是数组或者用逗号隔开的列表。The id lists, can be a array or a string joined with comma. + * @static + * @access public + * @return string the string like IN('a', 'b'). + */ + static public function dbIN($idList) + { + if(is_array($idList)) + { + if(!function_exists('get_magic_quotes_gpc') or !get_magic_quotes_gpc()) + { + foreach ($idList as $key=>$value) $idList[$key] = addslashes($value); + } + return "IN ('" . join("','", $idList) . "')"; + } + + if(!function_exists('get_magic_quotes_gpc') or !get_magic_quotes_gpc()) $idList = addslashes($idList); + return "IN ('" . str_replace(',', "','", str_replace(' ', '', $idList)) . "')"; + } + + /** + * 安全的Base64编码,框架对'/'字符比较敏感,转换为'.'。 + * 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), '/', '.'); + } + + /** + * 解码base64,先将之前的'.' 转换回'/' + * 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, '.', '/')); + } + + /** + * JSON编码,自动处理转义的问题。 + * JSON encode, process the slashes. + * + * @param mixed $data the object to encode + * @static + * @access public + * @return string decoded string. + */ + static public function jsonEncode($data) + { + return (function_exists('get_magic_quotes_gpc') and get_magic_quotes_gpc()) ? addslashes(json_encode($data)) : json_encode($data); + } + + /** + * 判断是否是utf8编码 + * Judge a string is utf-8 or not. + * + * @author hmdker@gmail.com + * @param string $string + * @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; + } + + /** + * 去掉UTF-8 Bom头。 + * Remove UTF-8 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; + } + + /** + * 增强substr方法:支持多字节语言,比如中文。 + * Enhanced substr version: support multibyte languages like Chinese. + * + * @param string $string + * @param int $length + * @param string $append + * @return string + */ + public static function substr($string, $length, $append = '') + { + $rawString = $string; + + if(function_exists('mb_substr')) $string = mb_substr($string, 0, $length, 'utf-8'); + + preg_match_all("/./su", $string, $data); + $string = join("", array_slice($data[0], 0, $length)); + + return ($string != $rawString) ? $string . $append : $string; + } + + /** + * Get browser name and version. + * + * @access public + * @return array + */ + public static function getBrowser() + { + $browser = array('name'=>'unknown', 'version'=>'unknown'); + + if(empty($_SERVER['HTTP_USER_AGENT'])) return $browser; + + $agent = $_SERVER["HTTP_USER_AGENT"]; + + /* Chrome should checked before safari.*/ + if(strpos($agent, 'Firefox') !== false) $browser['name'] = "firefox"; + if(strpos($agent, 'Opera') !== false) $browser['name'] = 'opera'; + if(strpos($agent, 'Safari') !== false) $browser['name'] = 'safari'; + if(strpos($agent, 'Chrome') !== false) $browser['name'] = "chrome"; + + // Check the name of browser + if(strpos($agent, 'MSIE') !== false || strpos($agent, 'rv:11.0')) $browser['name'] = 'ie'; + if(strpos($agent, 'Edge') !== false) $browser['name'] = 'edge'; + + // Check the version of browser + if(preg_match('/MSIE\s(\d+)\..*/i', $agent, $regs)) $browser['version'] = $regs[1]; + if(preg_match('/FireFox\/(\d+)\..*/i', $agent, $regs)) $browser['version'] = $regs[1]; + if(preg_match('/Opera[\s|\/](\d+)\..*/i', $agent, $regs)) $browser['version'] = $regs[1]; + if(preg_match('/Chrome\/(\d+)\..*/i', $agent, $regs)) $browser['version'] = $regs[1]; + + if((strpos($agent, 'Chrome') == false) && preg_match('/Safari\/(\d+)\..*$/i', $agent, $regs)) $browser['version'] = $regs[1]; + if(preg_match('/rv:(\d+)\..*/i', $agent, $regs)) $browser['version'] = $regs[1]; + if(preg_match('/Edge\/(\d+)\..*/i', $agent, $regs)) $browser['version'] = $regs[1]; + + return $browser; + } + + /** + * Get client os from agent info. + * + * @static + * @access public + * @return string + */ + public static function getOS() + { + if(empty($_SERVER['HTTP_USER_AGENT'])) return 'unknow'; + + $osList = array(); + $osList['/windows nt 10/i'] = 'Windows 10'; + $osList['/windows nt 6.3/i'] = 'Windows 8.1'; + $osList['/windows nt 6.2/i'] = 'Windows 8'; + $osList['/windows nt 6.1/i'] = 'Windows 7'; + $osList['/windows nt 6.0/i'] = 'Windows Vista'; + $osList['/windows nt 5.2/i'] = 'Windows Server 2003/XP x64'; + $osList['/windows nt 5.1/i'] = 'Windows XP'; + $osList['/windows xp/i'] = 'Windows XP'; + $osList['/windows nt 5.0/i'] = 'Windows 2000'; + $osList['/windows me/i'] = 'Windows ME'; + $osList['/win98/i'] = 'Windows 98'; + $osList['/win95/i'] = 'Windows 95'; + $osList['/win16/i'] = 'Windows 3.11'; + $osList['/macintosh|mac os x/i'] = 'Mac OS X'; + $osList['/mac_powerpc/i'] = 'Mac OS 9'; + $osList['/linux/i'] = 'Linux'; + $osList['/ubuntu/i'] = 'Ubuntu'; + $osList['/iphone/i'] = 'iPhone'; + $osList['/ipod/i'] = 'iPod'; + $osList['/ipad/i'] = 'iPad'; + $osList['/android/i'] = 'Android'; + $osList['/blackberry/i'] = 'BlackBerry'; + $osList['/webos/i'] = 'Mobile'; + + foreach ($osList as $regex => $value) + { + if(preg_match($regex, $_SERVER['HTTP_USER_AGENT'])) return $value; + } + + return 'unknown'; + } + + /** + * 计算两个日期相差的天数,取整。 + * Compute the diff days of two date. + * + * @param string $date1 the first date. + * @param string $date2 the sencond 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); + } + + /** + * 获取当前时间,使用common语言文件定义的DT_DATETIME1常量。 + * 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); + } + + /** + * 获取当前日期,使用common语言文件定义的DT_DATE1常量。 + * 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); + } + + /** + * 获取当前日期,使用common语言文件定义的DT_TIME1常量。 + * Get now time use the DT_TIME1 constant defined in the lang file. + * + * @access public + * @return date today + */ + static public function time() + { + return date(DT_TIME1); + } + + /** + * 判断日期是不是零。 + * 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 a directory. + * + * @access public + * @return array the files match the pattern + */ + static public function ls($dir, $pattern = '') + { + if(empty($dir)) return array(); + + $files = array(); + $dir = realpath($dir); + if(is_dir($dir)) $files = glob($dir . DIRECTORY_SEPARATOR . '*' . $pattern); + return empty($files) ? array() : $files; + } + + /** + * 切换目录。第一次调用的时候记录当前的路径,再次调用的时候切换回之前的路径。 + * Change directory: first call, save the $cwd, secend call, change to $cwd. + * + * @param string $path + * @static + * @access public + * @return void + */ + static function cd($path = '') + { + static $cwd = ''; + if($path) $cwd = getcwd(); + !empty($path) ? chdir($path) : chdir($cwd); + } + + /** + * 通过域名获取站点代号。 + * Get siteCode for a domain. + * + * www.xirang.com => xirang + * xirang.com => xirang + * xirang.com.cn => xirang + * xirang.cn => xirang + * xirang => xirang + * + * @param string $domain + * @return string $siteCode + **/ + public static function parseSiteCode($domain) + { + global $config; + + /* 去除域名中的端口部分。Remove the port part of the domain. */ + if(strpos($domain, ':') !== false) $domain = substr($domain, 0, strpos($domain, ':')); + $domain = strtolower($domain); + + /* $config里面有定义或者是localhost,直接返回。 Return directly if defined in $config or is localhost. */ + if(isset($config->siteCodeList[$domain])) return $config->siteCodeList[$domain]; + if($domain == 'localhost') return $domain; + + /* 将域名中的-改为_。Replace '-' with '_' in the domain. */ + $domain = str_replace('-', '_', $domain); + $items = explode('.', $domain); + + /* 类似a.com的形式。 Domain like a.com. */ + $postfix = str_replace($items[0] . '.', '', $domain); + if(isset($config->domainPostfix) and strpos($config->domainPostfix, "|$postfix|") !== false) return $items[0]; + + /* 类似www.a.com的形式。 Domain like www.a.com. */ + $postfix = str_replace($items[0] . '.' . $items[1] . '.', '', $domain); + if(isset($config->domainPostfix) and strpos($config->domainPostfix, "|$postfix|") !== false) return $items[1]; + + /* 类似xxx.sub.a.com的形式。 Domain like xxx.sub.a.com. */ + $postfix = str_replace($items[0] . '.' . $items[1] . '.' . $items[2] . '.', '', $domain); + if(isset($config->domainPostfix) and strpos($config->domainPostfix, "|$postfix|") !== false) return $items[0]; + + return ''; + } + + /** + * 检查是否是AJAX请求。 + * Check is ajax request. + * + * @static + * @access public + * @return bool + */ + public static function isAjaxRequest() + { + if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') return true; + if(isset($_GET['HTTP_X_REQUESTED_WITH']) && $_GET['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') return true; + return false; + } + + /** + * 301跳转。 + * Header 301 Moved Permanently. + * + * @param string $locate + * @access public + * @return void + */ + public static function header301($locate) + { + header('HTTP/1.1 301 Moved Permanently'); + die(header('Location:' . $locate)); + } + + /** + * 获取远程IP。 + * Get remote ip. + * + * @access public + * @return string + */ + public static function getRemoteIp() + { + $ip = ''; + if(!empty($_SERVER["REMOTE_ADDR"])) $ip = $_SERVER["REMOTE_ADDR"]; + if(!empty($_SERVER["HTTP_X_FORWARDED_FOR"])) $ip = $_SERVER["HTTP_X_FORWARDED_FOR"]; + if(!empty($_SERVER['HTTP_CLIENT_IP'])) $ip = $_SERVER['HTTP_CLIENT_IP']; + + return $ip; + } +} + +//------------------------------- 常用函数。Some tool functions.-------------------------------// + +/** + * helper::createLink()的别名,方便创建本模块方法的链接。 + * The short alias of helper::createLink() method to create link to control method of current module. + * + * @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++]; +} + +/** + * 获取当前时间的Unix时间戳,精确到微妙。 + * Get current microtime. + * + * @access public + * @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 ""; + print_r($var); + echo ""; +} + +/** + * 判断是否内外IP。 + * Judge the server ip is local or not. + * + * @access public + * @return void + */ +function isLocalIP() +{ + global $config; + if(isset($config->islocalIP)) return $config->isLocalIP; + $serverIP = $_SERVER['SERVER_ADDR']; + if($serverIP == '127.0.0.1') return true; + if(strpos($serverIP, '10.70') !== false) return false; + return !filter_var($serverIP, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE); +} + +/** + * 获取webRoot。 + * Get web root. + * + * @access public + * @return string + */ +function getWebRoot($full = false) +{ + $path = $_SERVER['SCRIPT_NAME']; + + if(PHP_SAPI == 'cli') + { + if(isset($_SERVER['argv'][1])) + { + $url = parse_url($_SERVER['argv'][1]); + $path = empty($url['path']) ? '/' : rtrim($url['path'], '/'); + } + $path = empty($path) ? '/' : preg_replace('/\/www$/', '/www/', $path); + } + + if($full) + { + $http = (isset($_SERVER['HTTPS']) and strtolower($_SERVER['HTTPS']) != 'off') ? 'https://' : 'http://'; + return $http . $_SERVER['HTTP_HOST'] . substr($path, 0, (strrpos($path, '/') + 1)); + } + + $path = substr($path, 0, (strrpos($path, '/') + 1)); + $path = str_replace('\\', '/', $path); + return $path; +} + +/** + * 当数组/对象变量$var存在$key项时,返回存在的对应值或设定值,否则返回$key或不存在的设定值。 + * 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 string + */ +function zget($var, $key, $valueWhenNone = false, $valueWhenExists = false) +{ + if(!is_array($var) and !is_object($var)) return false; + + $type = is_array($var) ? 'array' : 'object'; + $checkExists = $type == 'array' ? isset($var[$key]) : isset($var->$key); + + if($checkExists) + { + if($valueWhenExists !== false) return $valueWhenExists; + return $type == 'array' ? $var[$key] : $var->$key; + } + + if($valueWhenNone !== false) return $valueWhenNone; + return $key; +} diff --git a/framework/base/model.class.php b/framework/base/model.class.php new file mode 100644 index 0000000000..0b84a41ee2 --- /dev/null +++ b/framework/base/model.class.php @@ -0,0 +1,302 @@ +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(); + if($this->config->framework->multiLanguage) $this->app->loadLang($moduleName, $this->appName); + if($moduleName != 'common') $this->app->loadModuleConfig($moduleName, $this->appName); + + $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; + } + + /** + * 加载一个模块的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; + + global $loadedModels; + if(isset($loadedModels[$appName][$moduleName])) + { + $this->$moduleName = $loadedModels[$appName][$moduleName]; + return $this->$moduleName; + } + + $modelFile = $this->app->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); + } + + $loadedModels[$appName][$moduleName] = new $modelClass($appName); + $this->$moduleName = $loadedModels[$appName][$moduleName]; + return $this->$moduleName; + } + + /** + * 加载model的class扩展,主要是为了开发加密代码使用。 + * 可以将主要的逻辑存放到$moduleName/ext/model/class/$extensionName.class.php中。 + * 然后在ext/model/$extension.php的扩展里面使用$this->loadExtension()来调用相应的方法。 + * ext/model/class/*.class.php代码可以加密。而ext/model/*.php可以不用加密。 + * 因为框架对model的扩展是采取合并文件的方式,ext/model/*.php文件不能加密。 + * + * Load extension class of a model thus user can encrypt the code. + * You can put the main extension logic codes in $moduleName/ext/model/class/$extensionName.class.php. + * And call them by the ext/model/$extension.php like this: $this->loadExtension('myextension')->method(). + * You can encrypt the code in ext/model/class/*.class.php. + * Because the framework will merge the extension files in ext/model/*.php to the module/model.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(); + } +} diff --git a/framework/base/router.class.php b/framework/base/router.class.php new file mode 100644 index 0000000000..d700da5fc4 --- /dev/null +++ b/framework/base/router.class.php @@ -0,0 +1,2517 @@ +basePath/framework) + * + * @var string + * @access public + */ + public $frameRoot; + + /** + * 类库的根目录。{$this->basePath/lib} + * The root directory of the library($this->basePath/lib). + * + * @var string + * @access public + */ + public $coreLibRoot; + + /** + * 应用名称 + * The appName. + * + * @var string + * @access public + */ + public $appName = ''; + + /** + * 应用程序的根目录。 + * The root directory of the app. + * + * @var string + * @access public + */ + public $appRoot; + + /** + * 临时文件的根目录。 + * The root directory of temp. + * + * @var string + * @access public + */ + public $tmpRoot; + + /** + * 缓存的根目录。 + * The root directory of cache. + * + * @var string + * @access public + */ + public $cacheRoot; + + /** + * WWW目录。 + * The root directory of www. + * + * @var string + * @access public + */ + public $wwwRoot; + + /** + * 附件存放目录。 + * The root directory of data. + * + * @var string + * @access public + */ + public $dataRoot; + + /** + * 日志文件的根目录。 + * The root directory of log. + * + * @var string + * @access public + */ + public $logRoot; + + /** + * 配置文件的根目录。 + * The root directory of config. + * + * @var string + * @access public + */ + public $configRoot; + + /** + * 模块的根目录。 + * The root directory of module. + * + * @var string + * @access public + */ + public $moduleRoot; + + /** + * 主题的根目录。 + * The root directory of theme. + * + * @var string + * @access public + */ + public $themeRoot; + + /** + * 用户使用的语言。 + * The lang of the client user. + * + * @var string + * @access public + */ + public $clientLang; + + /** + * 用户使用的主题。 + * The theme of the client user. + * + * @var string + * @access public + */ + public $clientTheme; + + /** + * 客户端设备类型。 + * The device type of client. + * + * @var string + * @access public + */ + public $clientDevice; + + /** + * 当前模块的control对象。 + * The control object of current module. + * + * @var object + * @access public + */ + public $control; + + /** + * 模块名。 + * The module name + * + * @var string + * @access public + */ + public $moduleName; + + /** + * 当前访问模块的control文件。 + * The control file of the module current visiting. + * + * @var string + * @access public + */ + public $controlFile; + + /** + * 当前访问的方法名。 + * The name of the method current visiting. + * + * @var string + * @access public + */ + public $methodName; + + /** + * 当前方法的扩展文件。 + * The action extension file of current method. + * + * @var string + * @access public + */ + public $extActionFile; + + /** + * 访问的URI。 + * The URI. + * + * @var string + * @access public + */ + public $URI; + + /** + * url地址传递的参数。 + * The params passed in through url. + * + * @var array + * @access public + */ + public $params; + + /** + * 视图类型。 + * The view type. + * + * @var string + * @access public + */ + public $viewType; + + /** + * 全局$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; + + /** + * 从数据库的句柄。 + * The slave database handler. + * + * @var object + * @access public + */ + public $slaveDBH; + + /** + * $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; + + /** + * 网站代号。 + * The code of current site. + * + * @var string + * @access public + */ + public $siteCode; + + /** + * 构造方法, 设置路径,类,超级变量等。注意: + * 1.应该使用createApp()方法实例化router类; + * 2.如果$appRoot为空,框架会根据$appName计算应用路径。 + * + * The construct function. + * Prepare all the paths, classes, super objects and so on. + * Notice: + * 1. You should use the createApp() method to get an instance of the router. + * 2. If the $appRoot is empty, the framework will compute the appRoot according the $appName + * + * @param string $appName the name of the app + * @param string $appRoot the root path of the app + * @access public + * @return void + */ + public function __construct($appName = 'demo', $appRoot = '') + { + $this->setPathFix(); + $this->setBasePath(); + $this->setFrameRoot(); + $this->setCoreLibRoot(); + $this->setAppRoot($appName, $appRoot); + $this->setTmpRoot(); + $this->setCacheRoot(); + $this->setLogRoot(); + $this->setConfigRoot(); + $this->setModuleRoot(); + $this->setWwwRoot(); + $this->setThemeRoot(); + $this->setDataRoot(); + $this->loadMainConfig(); + + $this->loadClass('front', $static = true); + $this->loadClass('filter', $static = true); + $this->loadClass('dao', $static = true); + $this->loadClass('mobile', $static = true); + + $this->setSuperVars(); + $this->setDebug(); + $this->setErrorHandler(); + $this->setTimezone(); + $this->startSession(); + + if($this->config->framework->multiSite) $this->setSiteCode() && $this->loadExtraConfig(); + if($this->config->framework->autoConnectDB) $this->connectDB(); + if($this->config->framework->multiLanguage) $this->setClientLang(); + + $needDetectDevice = zget($this->config->framework->detectDevice, $this->clientLang, false); + $this->clientDevice = $needDetectDevice ? $this->setClientDevice() : 'desktop'; + + if($this->config->framework->multiLanguage) $this->loadLang('common'); + if($this->config->framework->multiTheme) $this->setClientTheme(); + } + + /** + * 创建一个应用。 + * Create an application. + * + * @param string $appName 应用名称。 The name of the app. + * @param string $appRoot 应用根路径。The root path of the app. + * @param string $className 应用类名,如果对router类做了扩展,需要指定类名。When extends router class, you should pass in the child router class name. + * @static + * @access public + * @return object the app object + */ + public static function createApp($appName = 'demo', $appRoot = '', $className = '') + { + if(empty($className)) $className = __CLASS__; + return new $className($appName, $appRoot); + } + + //-------------------- 路径相关方法(Path related methods)--------------------// + + /** + * 设置应用名称。 + * Set app name. + * + * @param string $appName + * @access public + * @return void + */ + public function setAppName($appName) + { + $this->appName = $appName; + } + + /** + * 设置目录分隔符。 + * Set the path directory separator. + * + * @access public + * @return void + */ + public function setPathFix() + { + define('DS', DIRECTORY_SEPARATOR); + } + + /** + * 设置基础目录。 + * Set the base path. + * + * @access public + * @return void + */ + public function setBasePath() + { + $this->basePath = realpath(dirname(dirname(dirname(__FILE__)))) . DS; + } + + /** + * 设置框架根目录。 + * Set the frame root. + * + * @access public + * @return void + */ + public function setFrameRoot() + { + $this->frameRoot = $this->basePath . 'framework' . DS; + } + + /** + * 设置类库的根目录。 + * Set the app lib root. + * + * @access public + * @return void + */ + public function setCoreLibRoot() + { + $this->coreLibRoot = $this->basePath . 'lib' . DS; + } + + /** + * 设置应用的根目录。 + * Set the app root. + * + * @param string $appName + * @param string $appRoot + * @access public + * @return void + */ + public function setAppRoot($appName = 'demo', $appRoot = '') + { + if(empty($appRoot)) $this->appRoot = $this->basePath . 'app' . DS . $appName . DS; + if(!empty($appRoot)) $this->appRoot = realpath($appRoot) . DS; + if(!is_dir($this->appRoot)) $this->triggerError("The app you call not found in {$this->appRoot}", __FILE__, __LINE__, $exit = true); + } + + /** + * 设置临时文件的根目录。 + * Set the tmp root. + * + * @access public + * @return void + */ + public function setTmpRoot() + { + $this->tmpRoot = $this->basePath . 'tmp' . DS; + } + + /** + * 设置缓存的根目录。 + * Set the cache root. + * + * @access public + * @return void + */ + public function setCacheRoot() + { + $this->cacheRoot = $this->tmpRoot . 'cache' . DS; + } + + /** + * 设置log的根目录。 + * Set the log root. + * + * @access public + * @return void + */ + public function setLogRoot() + { + $this->logRoot = $this->tmpRoot . 'log' . DS; + } + + /** + * 设置config配置文件的根目录。 + * Set the config root. + * + * @access public + * @return void + */ + public function setConfigRoot() + { + $this->configRoot = $this->basePath . 'config' . DS; + } + + /** + * 设置模块的根目录。 + * Set the module root. + * + * @access public + * @return void + */ + public function setModuleRoot() + { + $this->moduleRoot = $this->basePath . 'module' . DS; + } + + /** + * 设置www的根目录。 + * Set the www root. + * + * @access public + * @return void + */ + public function setWwwRoot() + { + $this->wwwRoot = rtrim(dirname($_SERVER['SCRIPT_FILENAME']), DS) . DS; + } + + /** + * 设置主题根目录。 + * Set the theme root. + * + * @access public + * @return void + */ + public function setThemeRoot() + { + $this->themeRoot = $this->wwwRoot . 'theme' . DS; + } + + /** + * 设置data根目录。 + * Set the data root. + * + * @access public + * @return void + */ + public function setDataRoot() + { + $this->dataRoot = $this->wwwRoot . 'data' . DS; + } + + /** + * 设置超级变量。 + * Set the super vars. + * + * @access public + * @return void + */ + public function setSuperVars() + { + $this->post = new super('post'); + $this->get = new super('get'); + $this->server = new super('server'); + $this->cookie = new super('cookie'); + $this->session = new super('session'); + + unset($GLOBALS); + unset($_REQUEST); + + $_FILES = validater::filterFiles(); + $_POST = validater::filterSuper($_POST); + $_GET = validater::filterSuper($_GET); + $_COOKIE = validater::filterSuper($_COOKIE); + } + + /** + * 设置Debug模式。 + * set Debug. + * + * @access public + * @return void + */ + public function setDebug() + { + if(!empty($this->config->debug)) error_reporting(E_ALL & ~ E_STRICT); + } + + /** + * 设置错误处理句柄。 + * Set the error handler. + * + * @access public + * @return void + */ + public function setErrorHandler() + { + set_error_handler(array($this, 'saveError')); + register_shutdown_function(array($this, 'shutdown')); + } + + /** + * 获取应用名称 + * Get app name + * + * @access public + * @return string + */ + public function getAppName() + { + return $this->appName; + } + + /** + * 获取$basePath,即基础路径。 + * Get the $basePath var. + * + * @access public + * @return string + */ + public function getBasePath() + { + return $this->basePath; + } + + /** + * 获取$frameRoot,即框架根目录。 + * Get the $frameRoot var. + * + * @access public + * @return string + */ + public function getFrameRoot() + { + return $this->frameRoot; + } + + /** + * 获取$appRoot变量,即应用的根目录。 + * Get the $appRoot var. + * + * @access public + * @return string + */ + public function getAppRoot() + { + return $this->appRoot; + } + + /** + * 获取$wwwRoot变量。 + * Get the $wwwRoot var + * + * @access public + * @return string + */ + public function getWwwRoot() + { + return $this->wwwRoot; + } + + /** + * 获取$coreLibRoot变量,即应用类库的根目录。 + * Get the $coreLibRoot var. + * + * @access public + * @return string + */ + public function getCoreLibRoot() + { + return $this->coreLibRoot; + } + + /** + * 获取$tmpRoot变量,即临时文件的根目录。 + * Get the $tmpRoot var. + * + * @access public + * @return string + */ + public function getTmpRoot() + { + return $this->tmpRoot; + } + + /** + * 获取$cacheRoot变量,即缓存文件的根目录。 + * Get the $cacheRoot var. + * + * @access public + * @return string + */ + public function getCacheRoot() + { + return $this->cacheRoot; + } + + /** + * 获取$logRoot变量,即日志文件的根目录。 + * Get the $logRoot var. + * + * @access public + * @return string + */ + public function getLogRoot() + { + return $this->logRoot; + } + + /** + * 获取$configRoot变量,即配置文件的根目录。 + * Get the $configRoot var. + * + * @access public + * @return string + */ + public function getConfigRoot() + { + return $this->configRoot; + } + + /** + * 获取$moduleRoot变量,即应用模块的根目录。 + * Get the $moduleRoot var. + * + * @param string $appName + * @access public + * @return string + */ + public function getModuleRoot($appName = '') + { + if($appName == '') return $this->moduleRoot; + return dirname($this->moduleRoot) . DS . $appName . DS; + } + + /** + * 获取$webRoot,即应用的路径。 + * Get the $webRoot var. + * + * @access public + * @return string + */ + public function getWebRoot() + { + return $this->config->webRoot; + } + + /** + * 获取$themeRoot变量,即主题的根目录。 + * Get the $themeRoot var. + * + * @access public + * @return string + */ + public function getThemeRoot() + { + return $this->themeRoot; + } + + /** + * 获取$dataRoot目录 + * Get the $dataRoot var + * + * @access public + * @return string + */ + public function getDataRoot() + { + return $this->dataRoot; + } + + //------ 客户端环境有关的函数(Client environment related functions) ------// + + /** + * 根据配置设置当前时区。 + * Set the time zone according to the config. + * + * @access public + * @return void + */ + public function setTimezone() + { + if(isset($this->config->timezone)) date_default_timezone_set($this->config->timezone); + } + + /** + * 开启 session + * Start the session. + * + * @access public + * @return void + */ + public function startSession() + { + if(!defined('SESSION_STARTED')) + { + $sessionName = $this->config->sessionVar; + session_name($sessionName); + if(isset($_GET[$this->config->sessionVar])) session_id($_GET[$this->config->sessionVar]); + session_start(); + define('SESSION_STARTED', true); + } + } + + /** + * 根据用户浏览器的语言设置和服务器配置,选择显示的语言。 + * 优先级:$lang参数 > session > cookie > 浏览器 > 配置文件。 + * + * Set the language. + * Using the order of method $lang param, session, cookie, browser and the default lang. + * + * @param string $lang zh-cn|zh-tw|zh-hk|en + * @access public + * @return void + */ + public function setClientLang($lang = '') + { + if(isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) $this->clientLang = $this->parseHttpAcceptLang(); + if(isset($_COOKIE['lang'])) $this->clientLang = $_COOKIE['lang']; + if(isset($_SESSION['lang'])) $this->clientLang = $_SESSION['lang']; + if(!empty($lang)) $this->clientLang = $lang; + + if(!empty($this->clientLang)) + { + $this->clientLang = strtolower($this->clientLang); + if(!isset($this->config->langs[$this->clientLang])) $this->clientLang = $this->config->default->lang; + } + else + { + $this->clientLang = $this->config->default->lang; + } + + setcookie('lang', $this->clientLang, $this->config->cookieLife, $this->config->webRoot); + if(!isset($_COOKIE['lang'])) $_COOKIE['lang'] = $this->clientLang; + + return true; + } + + /** + * 从HTTP_ACCEPT_LANGUAGE中提出去支持的语言。 + * Parse the lang str from HTTP_ACCEPT_LANGUAGE header. + * + * @access public + * @return string + */ + public function parseHttpAcceptLang() + { + if(empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) return ''; + + $raw = $_SERVER['HTTP_ACCEPT_LANGUAGE']; + $pos = strpos($raw, ','); + $lang = $pos === false ? $raw : substr($raw, 0, $pos); + + /* Fix clientLang for ie >= 10. https://www.drupal.org/node/365615. */ + if(stripos($lang, 'hans')) $lang = 'zh-cn'; + if(stripos($lang, 'hant')) $lang = 'zh-tw'; + return $lang; + } + + /** + * 设置客户端使用的主题,判断逻辑与客户端的语言相同。 + * 主题的css和图片文件应该存放在www/theme/$themeName路径。 + * + * Set the theme the client user using. The logic is same as the clientLang. + * The css and images files of an theme should saved at www/theme/$themeName + * + * @param string $theme + * @access public + * @return void + */ + public function setClientTheme($theme = '') + { + if(isset($this->config->client->theme)) $this->clientTheme = $this->config->client->theme; + if(isset($_COOKIE['theme'])) $this->clientTheme = $_COOKIE['theme']; + if(!empty($theme)) $this->clientTheme = $theme; + + if(!empty($this->clientTheme)) + { + $this->clientTheme = strtolower($this->clientTheme); + if(!isset($this->lang->themes[$this->clientTheme])) $this->clientTheme = $this->config->default->theme; + } + else + { + $this->clientTheme = $this->config->default->theme; + } + + setcookie('theme', $this->clientTheme, $this->config->cookieLife, $this->config->webRoot); + if(!isset($_COOKIE['theme'])) $_COOKIE['theme'] = $this->clientTheme; + + return true; + } + + /** + * 设置客户端的设备类型。 + * Set client device. + * + * @access public + * @return void + */ + public function setClientDevice() + { + $this->clientDevice = 'desktop'; + + if($this->cookie->device == 'mobile') $this->clientDevice = 'mobile'; + if($this->cookie->device == 'desktop') $this->clientDevice = 'desktop'; + + if(strpos('mobile,desktop', $this->cookie->device) === false) + { + $mobile = new mobile(); + $this->clientDevice = ($mobile->isMobile() and !$mobile->isTablet()) ? 'mobile' : 'desktop'; + } + + setcookie('device', $this->clientDevice, $this->config->cookieLife, $this->config->webRoot); + if(!isset($_COOKIE['device'])) $_COOKIE['device'] = $this->clientDevice; + + return $this->clientDevice; + } + + /** + * 设置站点代号,可以针对不同的站点来加载不同的扩展。 + * Set the code of current site, thus can load diffrent extension of diffrent site. + * + * @access public + * @return void + */ + public function setSiteCode() + { + return $this->siteCode = helper::parseSiteCode($this->server->http_host); + } + + /** + * 获取$clientLang变量,即客户端的语言。 + * Get the $clientLang var. + * + * @access public + * @return string + */ + public function getClientLang() + { + return $this->clientLang; + } + + /** + * 获取$clientTheme变量。 + * Get the $clientTheme var. + * + * @access public + * @return string + */ + public function getClientTheme() + { + return $this->config->webRoot . 'theme/' . $this->clientTheme . '/'; + } + + /** + * 获得客户端的终端设备。 + * Get the client device. + * + * @access public + * @return void + */ + public function getClientDevice() + { + return $this->clientDevice; + } + + //-------------------- 请求相关的方法(Request related methods) --------------------// + + /** + * 解析本次请求的入口方法,根据请求的类型(PATH_INFO GET),调用相应的方法。 + * The entrance of parseing request. According to the requestType, call related methods. + * + * @access public + * @return void + */ + public function parseRequest() + { + if($this->config->requestType == 'PATH_INFO' or $this->config->requestType == 'PATH_INFO2') + { + $this->parsePathInfo(); + $this->setRouteByPathInfo(); + } + elseif($this->config->requestType == 'GET') + { + $this->parseGET(); + $this->setRouteByGET(); + } + else + { + $this->triggerError("The request type {$this->config->requestType} not supported", __FILE__, __LINE__, $exit = true); + } + } + + /** + * PATH_INFO方式解析,获取$URI和$viewType。 + * Parse PATH_INFO, get the $URI and $viewType. + * + * @access public + * @return void + */ + public function parsePathInfo() + { + $pathInfo = $this->getPathInfo(); + if(!empty($pathInfo)) + { + $dotPos = strrpos($pathInfo, '.'); + if($dotPos) + { + $this->URI = substr($pathInfo, 0, $dotPos); + $this->viewType = substr($pathInfo, $dotPos + 1); + if(strpos($this->config->views, ',' . $this->viewType . ',') === false) + { + $this->viewType = $this->config->default->view; + } + } + else + { + $this->URI = $pathInfo; + $this->viewType = $this->config->default->view; + } + } + else + { + $this->viewType = $this->config->default->view; + } + } + + /** + * 从$_SERVER或者$_ENV全局变量根据pathinfo变量名获取$PATH_INFO值。 + * PATH_INFO的变量名几乎都是'PATH_INFO',但也有可能是ORIG_PATH_INFO。 + * + * Get $PATH_INFO from $_SERVER or $_ENV by the pathinfo var name. + * Mostly, the var name of PATH_INFO is PATH_INFO, but may be ORIG_PATH_INFO. + * + * @access public + * @return string the PATH_INFO + */ + public function getPathInfo() + { + if(isset($_SERVER['PATH_INFO'])) + { + $value = $_SERVER['PATH_INFO']; + } + elseif(isset($_SERVER['ORIG_PATH_INFO'])) + { + $value = $_SERVER['ORIG_PATH_INFO']; + } + elseif(isset($this->URI)) + { + $value = $this->URI; + $subpath = str_replace($_SERVER['DOCUMENT_ROOT'], '', dirname($_SERVER['SCRIPT_FILENAME'])); + if($subpath != '/') $subpath = '/' . $subpath; + if($subpath != '' and $subpath != '/' and strpos($value, $subpath) === 0) $value = substr($value, strlen($subpath)); + } + else + { + $value = @getenv('PATH_INFO'); + if(empty($value)) $value = @getenv('ORIG_PATH_INFO'); + } + + if(strpos($value, $_SERVER['SCRIPT_NAME']) !== false) $value = str_replace($_SERVER['SCRIPT_NAME'], '', $value); + if(strpos($value, '?') === false) return trim($value, '/'); + + $value = parse_url($value); + $pathInfo = trim(zget($value, 'path', ''), '/'); + if(trim($pathInfo, '/') == trim($this->config->webRoot, '/')) $pathInfo = ''; + + return $pathInfo; + } + + /** + * GET请求方式解析,获取$URI和$viewType。 + * Parse GET, get $URI and $viewType. + * + * @access public + * @return void + */ + public function parseGET() + { + if(isset($_GET[$this->config->viewVar])) + { + $this->viewType = $_GET[$this->config->viewVar]; + if(strpos($this->config->views, ',' . $this->viewType . ',') === false) $this->viewType = $this->config->default->view; + } + else + { + $this->viewType = $this->config->default->view; + } + $this->URI = $_SERVER['REQUEST_URI']; + } + + /** + * 获取$URL。 + * Get the $URL. + * + * @param bool $full true, the URI contains the webRoot, else only hte URI. + * @access public + * @return string + */ + public function getURI($full = false) + { + if($full and $this->config->requestType == 'PATH_INFO') + { + if($this->URI) return $this->config->webRoot . $this->URI . '.' . $this->viewType; + return $this->config->webRoot; + } + return $this->URI; + } + + /** + * 获取$vewType变量。 + * Get the $viewType var. + * + * @access public + * @return string + */ + public function getViewType() + { + return $this->viewType; + } + + //-------------------- 模块及扩展设置(Module and extension) --------------------// + + /** + * 加载common模块。 + * + * common模块比较特别,它会执行几乎每次请求都需要执行的操作,例如: + * 打开session,检查权限等等。 + * 加载完$lang, $config, $dbh后,需要在入口文件(www/index.php)中手动调用该方法。 + * + * Load the common module + * + * The common module is a special module, which can be used to do some common things. For examle: + * start session, check priviledge and so on. + * This method should called manually in the router file(www/index.php) after the $lang, $config, $dbh loaded. + * + * @access public + * @return object|bool the common model object or false if not exits. + */ + public function loadCommon() + { + $this->setModuleName('common'); + $commonModelFile = $this->setModelFile('common'); + if(!file_exists($commonModelFile)) return false; + + helper::import($commonModelFile); + + if($this->config->framework->extensionLevel == 0 and class_exists('commonModel')) return new commonModel(); + if($this->config->framework->extensionLevel > 0 and class_exists('extCommonModel')) return new extCommonModel(); + + if(class_exists('commonModel')) return new commonModel(); + return false; + } + + /** + * 设置要被调用的模块名。 + * Set the name of the module to be called. + * + * @param string $moduleName the module name + * @access public + * @return void + */ + public function setModuleName($moduleName = '') + { + if($this->checkModuleName($moduleName)) $this->moduleName = strtolower($moduleName); + } + + /** + * 设置要被调用的控制器文件。 + * Set the control file of the module to be called. + * + * @param bool $exitIfNone 没有找到该控制器文件的情况:如果该参数为true,则终止程序;如果为false,则打印错误日志 + * If control file not foundde, how to do. True, die the whole app. false, log error. + * @access public + * @return bool + */ + public function setControlFile($exitIfNone = true) + { + $this->controlFile = $this->moduleRoot . $this->moduleName . DS . 'control.php'; + if(file_exists($this->controlFile)) return true; + $this->triggerError("the control file $this->controlFile not found.", __FILE__, __LINE__, $exitIfNone); + } + + /** + * 设置要被调用的方法名。 + * Set the name of the method calling. + * + * @param string $methodName + * @access public + * @return void + */ + public function setMethodName($methodName = '') + { + if($this->checkMethodName($methodName)) $this->methodName = strtolower($methodName); + } + + /** + * 获取一个模块的路径。 + * Get the path of one module. + * + * @param string $appName the app name + * @param string $moduleName the module name + * @access public + * @return string the module path + */ + public function getModulePath($appName = '', $moduleName = '') + { + if($moduleName == '') $moduleName = $this->moduleName; + + if($this->checkModuleName($moduleName)) + { + $modulePath = $this->getModuleRoot($appName) . strtolower($moduleName) . DS; + return $modulePath; + } + } + + /** + * 获取一个模块的扩展路径。 Get extension path of one module. + * + * If the extensionLevel == 0, return empty array. + * If the extensionLevel == 1, return the common extension directory. + * If the extensionLevel == 2, return the common and site extension directories. + * + * @param string $appName the app name + * @param string $moduleName the module name + * @param string $ext the extension type, can be control|model|view|lang|config + * @access public + * @return string the extension path. + */ + public function getModuleExtPath($appName, $moduleName, $ext) + { + /* 检查失败或者extensionLevel为0,直接返回空。If check failed or extensionLevel == 0, return empty array. */ + if(!$this->checkModuleName($moduleName) or $this->config->framework->extensionLevel == 0) return array(); + + /* When extensionLevel == 1. */ + $modulePath = $this->getModulePath($appName, $moduleName); + $paths = array(); + $paths['common'] = $modulePath . 'ext' . DS . $ext . DS; + if($this->config->framework->extensionLevel == 1) return $paths; + + /* When extensionLevel == 2. */ + $paths['site'] = empty($this->siteCode) ? '' : $modulePath . 'ext' . DS . '_' . $this->siteCode . DS . $ext . DS; + return $paths; + } + + /** + * 检查模块中某一个变量必须为英文字母和数字组合。Check module a variable must be ascii. + * + * @param string $var + * @access public + * @return bool + */ + public function checkModuleName($var) + { + global $filter; + $rule = $filter->default->moduleName; + if(validater::checkByRule($var, $rule)) return true; + $this->triggerError("'$var' illegal. ", __FILE__, __LINE__, $exit = true); + } + + /** + * 检查方法中某一个变量必须为英文字母和数字组合。Check method a variable must be ascii. + * + * @param string $var + * @access public + * @return bool + */ + public function checkMethodName($var) + { + global $filter; + $rule = $filter->default->methodName; + if($this->config->framework->filterParam == 2 and isset($filter->{$this->moduleName}->methodName)) $rule = $filter->{$this->moduleName}->methodName; + + if(validater::checkByRule($var, $rule)) return true; + $this->triggerError("'$var' illegal. ", __FILE__, __LINE__, $exit = true); + } + + /** + * 设置Action的扩展文件。 Set the action extension file. + * + * @access public + * @return bool + */ + public function setActionExtFile() + { + $moduleExtPaths = $this->getModuleExtPath('', $this->moduleName, 'control'); + + /* 如果扩展目录为空,不包含任何扩展文件。If there's no ext pathes return false.*/ + if(empty($moduleExtPaths)) return false; + + /* 如果extensionLevel == 2,且扩展文件存在,返回该站点扩展文件。If extensionLevel == 2 and site extensionFile exists, return it. */ + if($this->config->framework->extensionLevel == 2 and !empty( $moduleExtPaths['site'])) + { + $this->extActionFile = $moduleExtPaths['site'] . $this->methodName . '.php'; + if(file_exists($this->extActionFile)) return true; + } + + /* 然后再尝试寻找公共扩展文件。Then try to find the common extension file. */ + $this->extActionFile = $moduleExtPaths['common'] . $this->methodName . '.php'; + return file_exists($this->extActionFile); + } + + /** + * 设置一个模块的model文件,如果存在model扩展,一起合并。 + * 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 + * @param string $appName the app name + * @static + * @access public + * @return string the model file + */ + public function setModelFile($moduleName, $appName = '') + { + if($appName == '') $appName = $this->getAppName(); + + /* 设置主model文件。 Set the main model file. */ + $mainModelFile = $this->getModulePath($appName, $moduleName) . 'model.php'; + if($this->config->framework->extensionLevel == 0) return $mainModelFile; + + /* 计算扩展的文件和hook文件。Compute the extension files and hook files. */ + $hookFiles = array(); + $extFiles = array(); + $siteExtended = false; + + $modelExtPaths = $this->getModuleExtPath($appName, $moduleName, 'model'); + foreach($modelExtPaths as $extType => $modelExtPath) + { + if(empty($modelExtPath)) continue; + + $tmpHookFiles = helper::ls($modelExtPath . 'hook/', '.php'); + $tmpExtFiles = helper::ls($modelExtPath, '.php'); + $hookFiles = array_merge($hookFiles, $tmpHookFiles); + $extFiles = array_merge($extFiles, $tmpExtFiles); + + if($extType == 'site' and (!empty($tmpHookFiles) or !empty($tmpExtFiles))) $siteExtended = true; + } + + /* 如果没有扩展文件,返回主文件。 If no extension or hook files, return the main file directly. */ + if(empty($extFiles) and empty($hookFiles)) return $mainModelFile; + + /* 计算合并之后的modelFile路径。Compute the merged model file path. */ + $extModelPrefix = ($siteExtended and !empty($this->siteCode)) ? $this->siteCode{0} . DS . $this->siteCode : ''; + $mergedModelDir = $this->getTmpRoot() . 'model' . DS . ($extModelPrefix ? $extModelPrefix . DS : ''); + $mergedModelFile = $mergedModelDir . $moduleName . '.php'; + if(!is_dir($mergedModelDir)) mkdir($mergedModelDir, 0755, true); + + /* 判断生成的缓存文件是否需要更新。 Judge whether the merged model file needed update or not. */ + if(!$this->needModelFileUpdate($mergedModelFile, $extFiles, $hookFiles, $modelExtPaths, $mainModelFile)) return $mergedModelFile; + + /* 合并扩展和hook文件。Merge the extension and hook files. */ + $modelLines = $this->mergeModelExtFiles($moduleName, $mainModelFile, $extFiles, $mergedModelDir); + $this->mergeModelHookFiles($moduleName, $mainModelFile, $modelLines, $hookFiles, $mergedModelDir, $mergedModelFile); + + return $mergedModelFile; + } + + /** + * 检查合并之后的model文件是否需要更新。Check whether the merged model file need update or not. + * + * @param string $mainModelFile + * @param string $mergedModelFile + * @param string $modelExtPaths + * @param array $extFiles + * @param array $hookFiles + * @access public + * @return bool + */ + public function needModelFileUpdate($mergedModelFile, $extFiles, $hookFiles, $modelExtPaths, $mainModelFile) + { + $lastTime = file_exists($mergedModelFile) ? filemtime($mergedModelFile) : 0; + + foreach($extFiles as $extFile) if(filemtime($extFile) > $lastTime) return true; + foreach($hookFiles as $hookFile) if(filemtime($hookFile) > $lastTime) return true; + + $modelExtPath = $modelExtPaths['common']; + $modelHookPath = $modelExtPaths['common'] . 'hook/'; + if(is_dir($modelExtPath ) and filemtime($modelExtPath) > $lastTime) return true; + if(is_dir($modelHookPath) and filemtime($modelHookPath) > $lastTime) return true; + + if(!empty($modelExtPaths['site'])) + { + $modelExtPath = $modelExtPaths['site']; + $modelHookPath = $modelExtPaths['site'] . 'hook/'; + if(is_dir($modelExtPath ) and filemtime($modelExtPath) > $lastTime) return true; + if(is_dir($modelHookPath) and filemtime($modelHookPath) > $lastTime) return true; + } + + if(filemtime($mainModelFile) > $lastTime) return true; + + return false; + } + + /** + * 将model的扩展文件合并在一起。Merge model ext files. + * + * @param string $moduleName + * @param string $mainModelFile + * @param array $extFiles + * @param string $mergedModelDir + * @access public + * @return void + */ + public function mergeModelExtFiles($moduleName, $mainModelFile, $extFiles, $mergedModelDir) + { + /* 设置类名。Set the class names. */ + $modelClass = "{$moduleName}Model"; + $tmpModelClass = "tmpExt$modelClass"; + + /* 开始拼装代码。Prepare the codes. */ + $modelLines = "getBasePath());\n"; + $modelLines .= "helper::import('" . str_replace($this->getBasePath(), '', $mainModelFile) . "');\n"; + $modelLines .= "helper::cd();\n"; + $modelLines .= "class $tmpModelClass extends $modelClass \n{\n"; + + /* 将扩展文件的代码合并到代码中。Cycle all the extension files and merge them into model lines. */ + foreach($extFiles as $extFile) $modelLines .= self::removePHPTAG($extFile); + + /* 做个标记,方便后面替换代码使用。Make a mark for replacing codes. */ + $replaceMark = '//**//'; + $modelLines .= "\n$replaceMark\n}"; + + /* 生成一个临时的model扩展文件,并加载,用于后续的hook文件加载使用。Create a tmp merged model file and import it for merge hook codes using. */ + $tmpModelFile = $mergedModelDir . "tmp$moduleName.php"; + if(@file_put_contents($tmpModelFile, $modelLines)) + { + if(!class_exists($tmpModelClass)) include $tmpModelFile; + return $modelLines; + } + + $this->triggerError("ERROR: $tmpModelFile not writable.", __FILE__, __LINE__, true); + } + + /** + * 合并model的hook脚本。Merge hook files for a model. + * + * @access public + * @return void + */ + public function mergeModelHookFiles($moduleName, $mainModelFile, $modelLines, $hookFiles, $mergedModelDir, $mergedModelFile) + { + /* 定义相关变量。Init vars. */ + $modelClass = $moduleName . 'Model'; + $extModelClass = 'ext' . $modelClass; + $tmpModelClass = 'tmpExt' . $modelClass; + $tmpModelFile = $mergedModelDir . "tmp$moduleName.php"; + $replaceMark = '//**//'; + + /* 读取hook文件。Get hook codes need to merge. */ + $hookCodes = array(); + foreach($hookFiles as $hookFile) + { + /* 通过文件名获得其对应的方法名。Get methods according it's filename. */ + $fileName = baseName($hookFile); + list($method) = explode('.', $fileName); + $hookCodes[$method][] = self::removePHPTAG($hookFile); + } + + /* 合并Hook文件。Cycle the hook methods and merge hook codes. */ + $hookedMethods = array_keys($hookCodes); + $mainModelCodes = file($mainModelFile); + $mergedModelCodes = file($tmpModelFile); + foreach($hookedMethods as $method) + { + /* 通过反射获得hook脚本对应的方法所在的文件和起止行数。Reflection the hooked method to get it's defined position. */ + if(!method_exists($tmpModelClass, $method)) continue; + $methodRelfection = new reflectionMethod($tmpModelClass, $method); + $definedFile = $methodRelfection->getFileName(); + $startLine = $methodRelfection->getStartLine() . ' '; + $endLine = $methodRelfection->getEndLine() . ' '; + + /* 将Hook脚本和老的代码合并在一起,并替换原来的定义。Merge hook codes with old codes and replace back. */ + $oldCodes = $definedFile == $tmpModelFile ? $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); + + if($definedFile == $tmpModelFile) $modelLines = str_replace($oldCodes, $newCodes, $modelLines); + if($definedFile != $tmpModelFile) $modelLines = str_replace($replaceMark, $newCodes . "\n$replaceMark", $modelLines); + } + + /* 保存最终的Model文件。Save the last merged model file. */ + $modelLines = str_replace($tmpModelClass, $extModelClass, $modelLines); + file_put_contents($mergedModelFile, $modelLines); + unlink($tmpModelFile); + } + + /** + * Remove tags of PHP + * + * @param string $fileName + * @static + * @access public + * @return string + */ + static public function removePHPTAG($fileName) + { + $code = trim(file_get_contents($fileName)); + if(strpos($code, '') !== false) $code = rtrim($code, '?>'); + return trim($code); + } + + //-------------------- 路由相关方法(Routing related methods) --------------------// + + /** + * 设置路由(PATH_INFO 方式): + * 1.设置模块名; + * 2.设置方法名; + * 3.设置控制器文件。 + * + * Set the route according to PATH_INFO. + * 1. set the module name. + * 2. set the method name. + * 3. set the control file. + * + * @access public + * @return void + */ + public function setRouteByPathInfo() + { + if(!empty($this->URI)) + { + /* + * 根据$requestFix分割符,分割网址。 + * There's the request seperator, split the URI by it. + **/ + if(strpos($this->URI, $this->config->requestFix) !== false) + { + $items = explode($this->config->requestFix, $this->URI); + $this->setModuleName($items[0]); + $this->setMethodName($items[1]); + } + /* + * 如果网址中没有分隔符,使用默认的方法。 + * No reqeust seperator, use the default method name. + **/ + else + { + $this->setModuleName($this->URI); + $this->setMethodName($this->config->default->method); + } + } + else + { + $this->setModuleName($this->config->default->module); // 使用默认模块 use the default module. + $this->setMethodName($this->config->default->method); // 使用默认方法 use the default method. + } + $this->setControlFile(); + } + + /** + * 设置路由(GET 方式): + * 1.设置模块名; + * 2.设置方法名; + * 3.设置控制器文件。 + * + * Set the route according to GET. + * 1. set the module name. + * 2. set the method name. + * 3. set the control file. + * + * @access public + * @return void + */ + public function setRouteByGET() + { + $moduleName = isset($_GET[$this->config->moduleVar]) ? strtolower($_GET[$this->config->moduleVar]) : $this->config->default->module; + $methodName = isset($_GET[$this->config->methodVar]) ? strtolower($_GET[$this->config->methodVar]) : $this->config->default->method; + $this->setModuleName($moduleName); + $this->setControlFile(); + $this->setMethodName($methodName); + } + + /** + * 加载一个模块: + * 1. 引入控制器文件或扩展的方法文件; + * 2. 创建control对象; + * 3. 解析url,得到请求的参数; + * 4. 使用call_user_function_array调用相应的方法。 + * + * Load a module. + * 1. include the control file or the extension action file. + * 2. create the control object. + * 3. set the params passed in through url. + * 4. call the method by call_user_function_array + * + * @access public + * @return bool|object if the module object of die. + */ + public function loadModule() + { + $appName = $this->appName; + $moduleName = $this->moduleName; + $methodName = $this->methodName; + + /* + * 引入该模块的control文件。 + * Include the control file of the module. + **/ + $file2Included = $this->setActionExtFile() ? $this->extActionFile : $this->controlFile; + chdir(dirname($file2Included)); + include $file2Included; + + /* + * 设置control的类名。 + * Set the class name of the control. + **/ + $className = class_exists("my$moduleName") ? "my$moduleName" : $moduleName; + if(!class_exists($className)) $this->triggerError("the control $className not found", __FILE__, __LINE__, $exit = true); + + /* + * 创建control类的实例。 + * Create a instance of the control. + **/ + $module = new $className(); + if(!method_exists($module, $methodName)) $this->triggerError("the module $moduleName has no $methodName method", __FILE__, __LINE__, $exit = true); + $this->control = $module; + + /* include default value for module*/ + $defaultValueFiles = glob($this->getTmpRoot() . "defaultvalue/*.php"); + if($defaultValueFiles) foreach($defaultValueFiles as $file) include $file; + + /* + * 使用反射机制获取函数参数的默认值。 + * Get the default settings of the method to be called using the reflecting. + * + * */ + $defaultParams = array(); + $methodReflect = new reflectionMethod($className, $methodName); + foreach($methodReflect->getParameters() as $param) + { + $name = $param->getName(); + + $default = '_NOT_SET'; + if(isset($paramDefaultValue[$appName][$className][$methodName][$name])) + { + $default = $paramDefaultValue[$appName][$className][$methodName][$name]; + } + elseif(isset($paramDefaultValue[$className][$methodName][$name])) + { + $default = $paramDefaultValue[$className][$methodName][$name]; + } + elseif($param->isDefaultValueAvailable()) + { + $default = $param->getDefaultValue(); + } + + $defaultParams[$name] = $default; + } + + /** + * 根据PATH_INFO或者GET方式设置请求的参数。 + * Set params according PATH_INFO or GET. + */ + if($this->config->requestType != 'GET') + { + $this->setParamsByPathInfo($defaultParams); + } + else + { + $this->setParamsByGET($defaultParams); + } + + if($this->config->framework->filterParam == 2) + { + $_GET = validater::filterParam($_GET, 'get'); + $_COOKIE = validater::filterParam($_COOKIE, 'cookie'); + } + + /* 调用该方法 Call the method. */ + call_user_func_array(array($module, $methodName), $this->params); + return $module; + } + + /** + * 设置请求的参数(PATH_INFO 方式)。 + * Set the params by PATH_INFO. + * + * @param array $defaultParams the default settings of the params. + * @param string $type + * @access public + * @return void + */ + public function setParamsByPathInfo($defaultParams = array(), $type = '') + { + $params = array(); + if($type != 'fetch') + { + /* 分割URI。 Spit the URI. */ + $items = explode($this->config->requestFix, $this->URI); + $itemCount = count($items); + + /** + * 前两项为模块名和方法名,参数从下标2开始。 + * The first two item is moduleName and methodName. So the params should begin at 2. + **/ + for($i = 2; $i < $itemCount; $i ++) + { + $key = key($defaultParams); // Get key from the $defaultParams. + if(empty($key)) continue; + + $params[$key] = $items[$i]; + next($defaultParams); + } + } + + $this->params = $this->mergeParams($defaultParams, $params); + } + + /** + * 设置请求的参数(GET 方式)。 + * Set the params by GET. + * + * @param array $defaultParams the default settings of the params. + * @param string $type + * @access public + * @return void + */ + public function setParamsByGET($defaultParams, $type = '') + { + $params = array(); + if($type != 'fetch') + { + /* Unset moduleVar, methodVar, viewVar and session 变量, 剩下的作为参数。 */ + /* Unset the moduleVar, methodVar, viewVar and session var, all the left are the params. */ + unset($_GET[$this->config->moduleVar]); + unset($_GET[$this->config->methodVar]); + unset($_GET[$this->config->viewVar]); + unset($_GET[$this->config->sessionVar]); + $params = $_GET; + } + + $this->params = $this->mergeParams($defaultParams, $params); + } + + /** + * 合并请求的参数和默认参数,这样就可以省略已经有默认值的参数了。 + * Merge the params passed in and the default params. Thus the params which have default values needn't pass value, just like a function. + * + * @param array $defaultParams the default params defined by the method. + * @param array $passedParams the params passed in through url. + * @access public + * @return array the merged params. + */ + public function mergeParams($defaultParams, $passedParams) + { + global $filter; + + /* Remove these two params. */ + unset($passedParams['onlybody']); + unset($passedParams['HTTP_X_REQUESTED_WITH']); + + /* Check params from URL. */ + $nameRule = isset($filter->{$this->moduleName}->{$this->methodName}->paramName) ? $filter->{$this->moduleName}->{$this->methodName}->paramName : $filter->default->paramName; + foreach($passedParams as $param => $value) + { + if(!validater::checkByRule($param, $nameRule)) die('Bad Request!'); + $valueRule = $filter->default->paramValue; + if(isset($filter->{$this->moduleName}->{$this->methodName}->paramValue[$param])) + { + $valueRule = $filter->{$this->moduleName}->{$this->methodName}->paramValue[$param]; + } + + if($value and !validater::checkByRule($value, $valueRule)) die('Bad Request!'); + } + + $passedParams = array_values($passedParams); + $i = 0; + foreach($defaultParams as $key => $defaultValue) + { + if(isset($passedParams[$i])) + { + $defaultParams[$key] = strip_tags($passedParams[$i]); + } + else + { + if($defaultValue === '_NOT_SET') $this->triggerError("The param '$key' should pass value. ", __FILE__, __LINE__, $exit = true); + } + $i ++; + } + + return $defaultParams; + } + + /** + * 获取$moduleName变量。 + * Get the $moduleName var. + * + * @access public + * @return string + */ + public function getModuleName() + { + return $this->moduleName; + } + + /** + * 获取$controlFile变量。 + * Get the $controlFile var. + * + * @access public + * @return string + */ + public function getControlFile() + { + return $this->controlFile; + } + + /** + * 获取$methodName变量。 + * Get the $methodName var. + * + * @access public + * @return string + */ + public function getMethodName() + { + return $this->methodName; + } + + /** + * 获取$param变量。 + * Get the $param var. + * + * @access public + * @return string + */ + public function getParams() + { + return $this->params; + } + + //-------------------- 常用的工具方法(Tool methods) ------------------// + + /** + * 从类库中加载一个类文件。 + * + * Load a class file. + * + * @param string $className the class name + * @param bool $static statis class or not + * @access public + * @return object|bool the instance of the class or just true. + */ + public function loadClass($className, $static = false) + { + $className = strtolower($className); + + /* 搜索$coreLibRoot(Search in $coreLibRoot) */ + $classFile = $this->coreLibRoot . $className; + if(is_dir($classFile)) $classFile .= DS . $className; + $classFile .= '.class.php'; + if(!helper::import($classFile)) $this->triggerError("class file $classFile not found", __FILE__, __LINE__, $exit = true); + + /* 如果是静态调用,则返回(If staitc, return) */ + if($static) return true; + + /* 实例化该类(Instance it) */ + global $$className; + if(!class_exists($className)) $this->triggerError("the class $className not found in $classFile", __FILE__, __LINE__, $exit = true); + if(!is_object($$className)) $$className = new $className(); + return $$className; + } + + /** + * 加载整个应用公共的配置文件。 + * Load the common config files for the app. + * + * @access public + * @return void + */ + public function loadMainConfig() + { + /* 初始化$config对象。Init the $config object. */ + global $config, $filter; + if(!is_object($config)) $config = new config(); + $this->config = $config; + + /* 加载主配置文件。 Load the main config file. */ + $mainConfigFile = $this->configRoot . 'config.php'; + if(!file_exists($mainConfigFile)) $this->triggerError("The main config file $mainConfigFile not found", __FILE__, __LINE__, $exit = true); + include $mainConfigFile; + } + + /** + * 当multiSite功能打开的时候,加载额外的配置文件。 + * When multiSite feature enabled, load extra config file. + * + * @access public + * @return void + */ + public function loadExtraConfig() + { + global $config; + $multiConfigFile = $this->configRoot . 'multi.php'; + if(file_exists($multiConfigFile)) include $multiConfigFile; + + $siteConfigFile = $this->configRoot . "sites/{$this->siteCode}.php"; + if(file_exists($siteConfigFile)) include $siteConfigFile; + } + + /** + * 加载模块的config文件,返回全局$config对象。 + * 如果该模块是common,加载$configRoot的配置文件,其他模块则加载其模块的配置文件。 + * + * Load config and return it as the global config object. + * If the module is common, search in $configRoot, else in $modulePath. + * + * @param string $moduleName module name + * @param string $appName app name + * @param bool $exitIfNone exit or not + * @access public + * @return object|bool the config object or false. + */ + public function loadModuleConfig($moduleName, $appName = '') + { + global $config; + + if($config and (!isset($config->$moduleName) or !is_object($config->$moduleName))) $config->$moduleName = new stdclass(); + + /* 初始化数组。Init the variables. */ + $extConfigFiles = array(); + $commonExtConfigFiles = array(); + $siteExtConfigFiles = array(); + + /* 先获得模块的主配置文件。Get the main config file for current module first. */ + $mainConfigFile = $this->getModulePath($appName, $moduleName) . 'config.php'; + + /* 查找扩展配置文件。Get extension config files. */ + if($config->framework->extensionLevel > 0) $extConfigPath = $this->getModuleExtPath($appName, $moduleName, 'config'); + if($config->framework->extensionLevel >= 1 and !empty($extConfigPath['common'])) $commonExtConfigFiles = helper::ls($extConfigPath['common'], '.php'); + if($config->framework->extensionLevel == 2 and !empty($extConfigPath['site'])) $siteExtConfigFiles = helper::ls($extConfigPath['site'], '.php'); + $extConfigFiles = array_merge($commonExtConfigFiles, $siteExtConfigFiles); + + /* 将主配置文件和扩展配置文件合并在一起。Put the main config file and extension config files together. */ + $configFiles = array_merge(array($mainConfigFile), $extConfigFiles); + + /* 加载每一个配置文件。Load every config file. */ + static $loadedConfigs = array(); + foreach($configFiles as $configFile) + { + if(in_array($configFile, $loadedConfigs)) continue; + if(file_exists($configFile)) include $configFile; + $loadedConfigs[] = $configFile; + } + + /* 加载数据库中与本模块相关的配置项。Merge from the db configs. */ + if($moduleName != 'common') + { + if(isset($config->system->$moduleName)) $this->mergeConfig($config->system->$moduleName, $moduleName); + if(isset($config->personal->$moduleName)) $this->mergeConfig($config->personal->$moduleName, $moduleName); + } + } + + /** + * Merge db config. + * + * @param array $dbConfig + * @param string $moduleName + * @access public + * @return void + */ + public function mergeConfig($dbConfig, $moduleName = 'common') + { + global $config; + + /* 如果没有设置本模块配置,则首先进行初始化。Init the $config->$moduleName if not set.*/ + if($moduleName != 'common' and !isset($config->$moduleName)) $config->$moduleName = new stdclass(); + + $config2Merge = $config; + if($moduleName != 'common') $config2Merge = $config->$moduleName; + + foreach($dbConfig as $item) + { + if($item->section) + { + if(!isset($config2Merge->{$item->section})) $config2Merge->{$item->section} = new stdclass(); + if(is_object($config2Merge->{$item->section})) + { + $config2Merge->{$item->section}->{$item->key} = $item->value; + } + } + else + { + $config2Merge->{$item->key} = $item->value; + } + } + } + + /** + * 向客户端输出配置参数,客户端可以根据这些参数实现和调整请求的逻辑。 + * Export the config params to the client, thus the client can adjust it's logic according the config. + * + * @access public + * @return void + */ + public function exportConfig() + { + $view = new stdclass(); + $view->version = $this->config->version; + $view->requestType = $this->config->requestType; + $view->requestFix = $this->config->requestFix; + $view->moduleVar = $this->config->moduleVar; + $view->methodVar = $this->config->methodVar; + $view->viewVar = $this->config->viewVar; + $view->sessionVar = $this->config->sessionVar; + + $this->session->set('random', mt_rand(0, 10000)); + $view->sessionName = session_name(); + $view->sessionID = session_id(); + $view->random = $this->session->random; + $view->expiredTime = ini_get('session.gc_maxlifetime'); + $view->serverTime = time(); + + echo json_encode($view); + } + + /** + * 加载语言文件,返回全局$lang对象。 + * Load lang and return it as the global lang object. + * + * @param string $moduleName the module name + * @param string $appName the app name + * @access public + * @return bool|ojbect the lang object or false. + */ + public function loadLang($moduleName, $appName = '') + { + /* 初始化变量。Init vars. */ + $modulePath = $this->getModulePath($appName, $moduleName); + $extLangFiles = array(); + $langFilesToLoad = array(); + + /* 判断主语言文件是否存在。Whether the main lang file exists or not. */ + $mainLangFile = $modulePath . 'lang' . DS . $this->clientLang . '.php'; + if(file_exists($mainLangFile)) $langFilesToLoad[] = $mainLangFile; + + /* 获取扩展语言文件。If extensionLevel > 0, get extension lang files. */ + if($this->config->framework->extensionLevel > 0) + { + $commonExtLangFiles = array(); + $siteExtLangFiles = array(); + + $extLangPath = $this->getModuleExtPath($appName, $moduleName, 'lang'); + if($this->config->framework->extensionLevel >= 1 and !empty($extLangPath['common'])) $commonExtLangFiles = helper::ls($extLangPath['common'] . $this->clientLang, '.php'); + if($this->config->framework->extensionLevel == 2 and !empty($extLangPath['site'])) $siteExtLangFiles = helper::ls($extLangPath['site'] . $this->clientLang, '.php'); + $extLangFiles = array_merge($commonExtLangFiles, $siteExtLangFiles); + } + + /* 计算最终要加载的语言文件。 Get the lang files to be loaded. */ + $langFilesToLoad = array_merge($langFilesToLoad, $extLangFiles); + if(empty($langFilesToLoad)) return false; + + /* 加载语言文件。Load lang files. */ + global $lang; + if(!is_object($lang)) $lang = new language(); + if(!isset($lang->$moduleName)) $lang->$moduleName = new stdclass(); + + static $loadedLangs = array(); + foreach($langFilesToLoad as $langFile) + { + if(in_array($langFile, $loadedLangs)) continue; + include $langFile; + $loadedLangs[] = $langFile; + } + + $this->lang = $lang; + return $lang; + } + + /** + * 连接数据库。 + * Connect to database. + * + * @access public + * @return void + */ + public function connectDB() + { + global $config, $dbh, $slaveDBH; + if(!isset($config->installed) or !$config->installed) return; + + if(isset($config->db->host)) $this->dbh = $dbh = $this->connectByPDO($config->db); + if(isset($config->slaveDB->host)) $this->slaveDBH = $slaveDBH = $this->connectByPDO($config->slaveDB); + } + + /** + * 使用PDO连接数据库。 + * Connect database by PDO. + * + * @param object $params the database params. + * @access public + * @return object|bool + */ + public function connectByPDO($params) + { + if(!isset($params->driver)) self::triggerError('no pdo driver defined, it should be mysql or sqlite', __FILE__, __LINE__, $exit = true); + if(!isset($params->user)) return false; + if($params->driver == 'mysql') + { + $dsn = "mysql:host={$params->host}; port={$params->port}; dbname={$params->name}"; + } + try + { + $dbh = new PDO($dsn, $params->user, $params->password, array(PDO::ATTR_PERSISTENT => $params->persistant)); + $dbh->exec("SET NAMES {$params->encoding}"); + + /* + * 如果系统是Linux,开启仿真预处理和缓冲查询。 + * If run on linux, set emulatePrepare and bufferQuery to true. + **/ + if(!isset($params->emulatePrepare) and PHP_OS == 'Linux') $params->emulatePrepare = true; + if(!isset($params->bufferQuery) and PHP_OS == 'Linux') $params->bufferQuery = true; + + $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ); + $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + if(isset($params->strictMode) and $params->strictMode == false) $dbh->exec("SET @@sql_mode= ''"); + if(isset($params->emulatePrepare)) $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, $params->emulatePrepare); + if(isset($params->bufferQuery)) $dbh->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, $params->bufferQuery); + + return $dbh; + } + catch (PDOException $exception) + { + self::triggerError($exception->getMessage(), __FILE__, __LINE__, $exit = true); + } + } + + //-------------------- 错误处理方法(Error methods) ------------------// + + /** + * 程序停止时执行的函数。 + * The shutdown handler. + * + * @access public + * @return void + */ + public function shutdown() + { + /* 如果debug模式开启,保存sql语句(If debug on, save sql queries) */ + if(!empty($this->config->debug)) $this->saveSQL(); + + /* + * 发现错误,保存到日志中。 + * If any error occers, save it. + * */ + if(!function_exists('error_get_last')) return; + $error = error_get_last(); + if($error) $this->saveError($error['type'], $error['message'], $error['file'], $error['line']); + } + + /** + * 触发一个错误。 + * Trigger an error. + * + * @param string $message 错误信息 error message + * @param string $file 所在文件 the file error occers + * @param int $line 错误行 the line error occers + * @param bool $exit 是否停止程序 exit the program or not + * @access public + * @return void + */ + public function triggerError($message, $file, $line, $exit = false) + { + /* 设置错误信息(Set the error info) */ + $message = htmlspecialchars($message); + $log = "ERROR: $message in $file on line $line"; + if(isset($_SERVER['SCRIPT_URI'])) $log .= ", request: $_SERVER[SCRIPT_URI]";; + $trace = debug_backtrace(); + extract($trace[0]); + extract($trace[1]); + $log .= ", last called by $file on line $line through function $function.\n"; + + /* 触发错误(Trigger the error) */ + trigger_error($log, $exit ? E_USER_ERROR : E_USER_WARNING); + } + + /** + * 保存错误信息。 + * Save error info. + * + * @param int $level + * @param string $message + * @param string $file + * @param int $line + * @access public + * @return void + */ + public function saveError($level, $message, $file, $line) + { + if(empty($this->config->debug)) return true; + if(!is_dir($this->logRoot)) return true; + if(!is_writable($this->logRoot)) return true; + + /* + * 删除设定时间之前的日志。 + * Delete the log before the set time. + **/ + if(mt_rand(0, 10) == 1) + { + $logDays = isset($this->config->framework->logDays) ? $this->config->framework->logDays : 14; + $dayTime = time() - $logDays * 24 * 3600; + foreach(glob($this->getLogRoot() . '*') as $logFile) + { + if(filemtime($logFile) <= $dayTime) unlink($logFile); + } + } + + /* + * 忽略该错误:Redefining already defined constructor。 + * Skip the error: Redefining already defined constructor. + **/ + if(strpos($message, 'Redefining') !== false) return true; + + /* + * 设置错误信息。 + * Set the error info. + **/ + $errorLog = "\n" . date('H:i:s') . " $message in $file on line $line "; + $errorLog .= "when visiting " . htmlspecialchars($this->getURI()) . "\n"; + + /* + * 为了安全起见,对公网环境隐藏脚本路径。 + * If the ip is pulic, hidden the full path of scripts. + */ + if(!defined('IN_SHELL') and !($this->server->remote_addr == '127.0.0.1' or filter_var($this->server->remote_addr, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE) === false)) + { + $errorLog = str_replace($this->getBasePath(), '', $errorLog); + } + + /* 保存到日志文件(Save to log file) */ + $errorFile = $this->logRoot . 'php.' . date('Ymd') . '.log.php'; + if(!is_file($errorFile)) file_put_contents($errorFile, "\n"); + + $fh = fopen($errorFile, 'a'); + if($fh) fwrite($fh, strip_tags($errorLog)) and fclose($fh); + + /* + * 如果debug > 1,显示warning, notice级别的错误。 + * If the debug > 1, show warning, notice error. + **/ + if($level == E_NOTICE or $level == E_WARNING or $level == E_STRICT or $level == 8192) // 8192: E_DEPRECATED + { + if(!empty($this->config->debug) and $this->config->debug > 1) + { + $cmd = "vim +$line $file"; + $size = strlen($cmd); + echo "
$message: ";
+                echo "
"; + } + } + + /* + * 如果是严重错误,停止程序。 + * If error level is serious, die. + * */ + if($level == E_ERROR or $level == E_PARSE or $level == E_CORE_ERROR or $level == E_COMPILE_ERROR or $level == E_USER_ERROR) + { + if(empty($this->config->debug)) die(); + if(PHP_SAPI == 'cli') die($errorLog); + + $htmlError = ""; + $htmlError .= "" . nl2br($errorLog) . ""; + die($htmlError); + } + } + + /** + * 保存sql语句。 + * Save the sql. + * + * @access public + * @return void + */ + public function saveSQL() + { + if(!$this->config->debug) return true; + if(!class_exists('dao')) return; + + $sqlLog = $this->getLogRoot() . 'sql.' . date('Ymd') . '.log.php'; + if(!is_file($sqlLog)) file_put_contents($sqlLog, "\n"); + + $fh = @fopen($sqlLog, 'a'); + if(!$fh) return false; + fwrite($fh, date('Ymd H:i:s') . ": " . $this->getURI() . "\n"); + foreach(dao::$querys as $query) fwrite($fh, " $query\n"); + fwrite($fh, "\n"); + fclose($fh); + } +} + +/** + * config类。 + * The config class. + * + * @package framework + */ +class config +{ + /** + * 设置成员变量,成员可以是'db.user'类似的格式。 + * Set the value of a member. the member can be the format like db.user. + * + * + * set('db.user', 'wwccss'); + * ?> + * + * @param string $key the key of the member + * @param mixed $value the value + * @access public + * @return void + */ + public function set($key, $value) + { + helper::setMember('config', $key, $value); + } +} + +/** + * lang类。 + * The lang class. + * + * @package framework + */ +class language +{ + /** + * 设置成员变量,成员可以是'db.user'类似的格式。 + * Set the value of a member. the member can be the foramt like db.user. + * + * + * set('version', '1.0); + * ?> + * + * @param string $key 成员的键名,可以是father.child的形式。 + * the key of the member, can be father.child + * @param mixed $value the value + * @access public + * @return void + */ + public function set($key, $value) + { + helper::setMember('lang', $key, $value); + } + + /** + * 显示一个成员的值。 + * Show a member. + * + * @param object $obj the object + * @param string $key the key + * @access public + * @return void + */ + public function show($obj, $key) + { + $obj = (array)$obj; + echo isset($obj[$key]) ? $obj[$key] : ''; + } +} + +/** + * 超级对象类,转化超级全局变量。 + * The super object class. + * + * @package framework + */ +class super +{ + /** + * 构造函数,设置超级变量名。 + * Construct, set the var scope. + * + * @param string $scope the scope, can be server, post, get, cookie, session, global + * @access public + * @return void + */ + public function __construct($scope) + { + $this->scope = $scope; + } + + /** + * 设置超级变量的成员值。 + * Set one member value. + * + * @param string the key + * @param mixed $value the value + * @access public + * @return void + */ + public function set($key, $value) + { + if($this->scope == 'post') + { + $_POST[$key] = $value; + } + elseif($this->scope == 'get') + { + $_GET[$key] = $value; + } + elseif($this->scope == 'server') + { + $_SERVER[$key] = $value; + } + elseif($this->scope == 'cookie') + { + $_COOKIE[$key] = $value; + } + elseif($this->scope == 'session') + { + $_SESSION[$key] = $value; + } + elseif($this->scope == 'env') + { + $_ENV[$key] = $value; + } + elseif($this->scope == 'global') + { + $GLOBALS[$key] = $value; + } + } + + /** + * 超级变量的魔术方法,比如用$post->key访问$_POST['key']。 + * The magic get method. + * + * @param string $key the key + * @access public + * @return mixed|bool return the value of the key or false. + */ + public function __get($key) + { + if($this->scope == 'post') + { + if(isset($_POST[$key])) return $_POST[$key]; + return false; + } + elseif($this->scope == 'get') + { + if(isset($_GET[$key])) return $_GET[$key]; + return false; + } + elseif($this->scope == 'server') + { + if($key == 'ajax') return isset($_SERVER['HTTP_X_REQUESTED_WITH']) ? true : false; + if(isset($_SERVER[$key])) return $_SERVER[$key]; + $key = strtoupper($key); + if(isset($_SERVER[$key])) return $_SERVER[$key]; + return false; + } + elseif($this->scope == 'cookie') + { + if(isset($_COOKIE[$key])) return $_COOKIE[$key]; + return false; + } + elseif($this->scope == 'session') + { + if(isset($_SESSION[$key])) return $_SESSION[$key]; + return false; + } + elseif($this->scope == 'env') + { + if(isset($_ENV[$key])) return $_ENV[$key]; + return false; + } + elseif($this->scope == 'global') + { + if(isset($GLOBALS[$key])) return $GLOBALS[$key]; + return false; + } + else + { + return false; + } + } + + /** + * 打印变量的详细结构。 + * Print the structure. + * + * @access public + * @return void + */ + public function a() + { + if($this->scope == 'post') a($_POST); + if($this->scope == 'get') a($_GET); + if($this->scope == 'server') a($_SERVER); + if($this->scope == 'cookie') a($_COOKIE); + if($this->scope == 'session') a($_SESSION); + if($this->scope == 'env') a($_ENV); + if($this->scope == 'global') a($GLOBALS); + } +} diff --git a/framework/control.class.php b/framework/control.class.php new file mode 100644 index 0000000000..848194f79b --- /dev/null +++ b/framework/control.class.php @@ -0,0 +1,23 @@ +requestType != 'GET') + { + $pathInfo = $app->getPathInfo(); + 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($source and isset($viewType)) return $viewType; + + if(isset($viewType) and strpos($config->views, ',' . $viewType . ',') === false) $viewType = $config->default->view; + return isset($viewType) ? $viewType : $config->default->view; + } + + /** + * Encode json for $.parseJSON + * + * @param array $data + * @param int $options + * @static + * @access public + * @return string + */ + static public function jsonEncode4Parse($data, $options = 0) + { + $json = json_encode($data); + if($options) $json = str_replace(array("'", '"'), array('\u0027', '\u0022'), $json); + + $escapers = array("\\", "/", "\"", "'", "\n", "\r", "\t", "\x08", "\x0c", "\\\\u"); + $replacements = array("\\\\", "\\/", "\\\"", "\'", "\\n", "\\r", "\\t", "\\f", "\\b", "\\u"); + return str_replace($escapers, $replacements, $json); + } + + /** + * Convert encoding. + * + * @param string $string + * @param string $fromEncoding + * @param string $toEncoding + * @static + * @access public + * @return string + */ + static public function convertEncoding($string, $fromEncoding, $toEncoding = 'utf-8') + { + $toEncoding = str_replace('utf8', 'utf-8', $toEncoding); + if(function_exists('mb_convert_encoding')) + { + /* Remove like utf-8//TRANSLIT. */ + $position = strpos($toEncoding, '//'); + if($position !== false) $toEncoding = substr($toEncoding, 0, $position); + + /* Check string encoding. */ + $encoding = strtolower(mb_detect_encoding($string, array('ASCII','UTF-8','GB2312','GBK','BIG5'))); + if($encoding == $toEncoding) return $string; + return mb_convert_encoding($string, $toEncoding, $encoding); + } + elseif(function_exists('iconv')) + { + if($fromEncoding == $toEncoding) return $string; + $convertString = @iconv($fromEncoding, $toEncoding, $string); + /* iconv error then return original. */ + if(!$convertString) return $string; + return $convertString; + } + + return $string; + } +} + +/** + * 检查是否是onlybody模式。 + * Check exist onlybody param. + * + * @access public + * @return void + */ +function isonlybody() +{ + return helper::inOnlyBodyMode(); +} + +/** + * Format time. + * + * @param int $time + * @param string $format + * @access public + * @return void + */ +function formatTime($time, $format = '') +{ + $time = str_replace('0000-00-00', '', $time); + $time = str_replace('00:00:00', '', $time); + if(trim($time) == '') return ; + if($format) return date($format, strtotime($time)); + return trim($time); +} \ No newline at end of file diff --git a/framework/model.class.php b/framework/model.class.php new file mode 100644 index 0000000000..2335d5dd18 --- /dev/null +++ b/framework/model.class.php @@ -0,0 +1,38 @@ +dao->update($table)->set('deleted')->eq(1)->where('id')->eq($id)->exec(); + $object = preg_replace('/^' . preg_quote($this->config->db->prefix) . '/', '', trim($table, '`')); + $this->loadModel('action')->create($object, $id, 'deleted', '', $extra = ACTIONMODEL::CAN_UNDELETED); + } +} diff --git a/framework/router.class.php b/framework/router.class.php new file mode 100755 index 0000000000..536dddf8dd --- /dev/null +++ b/framework/router.class.php @@ -0,0 +1,159 @@ +dbh and !empty($this->config->db->name)) + { + global $config; + if(!isset($config->global)) $config->global = new stdclass(); + $flow = $this->dbh->query('SELECT value FROM' . TABLE_CONFIG . "WHERE `owner`='system' AND `module`='common' AND `key`='flow'")->fetch(); + $config->global->flow = $flow ? $flow->value : 'full'; + + try + { + $productProject = $this->dbh->query('SELECT value FROM' . TABLE_CONFIG . "WHERE `owner`='system' AND `module`='custom' AND `key`='productProject'")->fetch(); + } + catch (PDOException $exception) + { + $repairCode = '|1034|1035|1194|1195|1459|'; + $errorInfo = $exception->errorInfo; + $errorCode = $errorInfo[1]; + $errorMsg = $errorInfo[2]; + $message = $exception->getMessage(); + if(strpos($repairCode, "|$errorCode|") !== false or ($errorCode == '1016' and strpos($errorMsg, 'errno: 145') !== false) or strpos($message, 'repair') !== false) + { + if(isset($config->framework->autoRepairTable) and $config->framework->autoRepairTable) + { + header("location: " . $config->webRoot . 'checktable.php'); + exit; + } + } + } + } + + $productCommon = $projectCommon = 0; + if($productProject) + { + $productProject = $productProject->value; + list($productCommon, $projectCommon) = explode('_', $productProject); + } + $lang->productCommon = isset($this->config->productCommonList[$this->clientLang][(int)$productCommon]) ? $this->config->productCommonList[$this->clientLang][(int)$productCommon] : $this->config->productCommonList['zh-cn'][0]; + $lang->projectCommon = isset($this->config->projectCommonList[$this->clientLang][(int)$projectCommon]) ? $this->config->projectCommonList[$this->clientLang][(int)$projectCommon] : $this->config->projectCommonList['zh-cn'][0]; + } + + parent::loadLang($moduleName, $appName); + + /* Merge from the db lang. */ + if($moduleName != 'common' and isset($lang->db->custom[$moduleName])) + { + foreach($lang->db->custom[$moduleName] as $section => $fields) + { + if(isset($lang->{$moduleName}->{$section}[''])) + { + $nullKey = ''; + $nullValue = $lang->{$moduleName}->{$section}[$nullKey]; + } + elseif(isset($lang->{$moduleName}->{$section}[0])) + { + $nullKey = 0; + $nullValue = $lang->{$moduleName}->{$section}[0]; + } + unset($lang->{$moduleName}->{$section}); + + if(isset($nullKey))$lang->{$moduleName}->{$section}[$nullKey] = $nullValue; + foreach($fields as $key => $value) $lang->{$moduleName}->{$section}[$key] = $value; + unset($nullKey); + unset($nullValue); + } + } + return $lang; + } + + /** + * Save error info. + * + * @param int $level + * @param string $message + * @param string $file + * @param int $line + * @access public + * @return void + */ + public function saveError($level, $message, $file, $line) + { + $fatalLevel[E_ERROR] = E_ERROR; + $fatalLevel[E_PARSE] = E_PARSE; + $fatalLevel[E_CORE_ERROR] = E_CORE_ERROR; + $fatalLevel[E_USER_ERROR] = E_USER_ERROR; + if(isset($fatalLevel[$level])) $this->config->debug = true; + parent::saveError($level, $message, $file, $line); + } + + /** + * Alias load module config. + * + * @param string $moduleName + * @param string $appName + * @access public + * @return void + */ + public function loadConfig($moduleName, $appName = '') + { + return parent::loadModuleConfig($moduleName, $appName); + } + + /** + * Export config. + * + * @access public + * @return void + */ + public function exportConfig() + { + ob_start(); + parent::exportConfig(); + $view = ob_get_contents(); + ob_end_clean(); + + $view = json_decode($view); + $view->rand = $this->session->random; + $this->session->set('rand', $this->session->random); + echo json_encode($view); + } +} diff --git a/framework/tests/helper/.101.setmember.onelevel.et b/framework/tests/helper/.101.setmember.onelevel.et new file mode 100644 index 0000000000..5b184f35fa --- /dev/null +++ b/framework/tests/helper/.101.setmember.onelevel.et @@ -0,0 +1,13 @@ +value1.1 +value2 +3 +Array +( + [0] => 1 + [1] => 2 + [2] => 3 +) +stdClass Object +( + [key1] => value2.1 +) diff --git a/framework/tests/helper/.110.setmember.multilevel.et b/framework/tests/helper/.110.setmember.multilevel.et new file mode 100644 index 0000000000..ee73e72ede --- /dev/null +++ b/framework/tests/helper/.110.setmember.multilevel.et @@ -0,0 +1,6 @@ +Mary +20 +stdClass Object +( + [postcode] => 10000 +) diff --git a/framework/tests/helper/.201.getwebroot.inbrowse.et b/framework/tests/helper/.201.getwebroot.inbrowse.et new file mode 100644 index 0000000000..618380792d --- /dev/null +++ b/framework/tests/helper/.201.getwebroot.inbrowse.et @@ -0,0 +1,2 @@ +/ +/zentao/ diff --git a/framework/tests/helper/.202.getwebroot.inshell.et b/framework/tests/helper/.202.getwebroot.inshell.et new file mode 100644 index 0000000000..3de39a7763 --- /dev/null +++ b/framework/tests/helper/.202.getwebroot.inshell.et @@ -0,0 +1,8 @@ +http://localhost webRoot is / +http://localhost/ webRoot is / +http://localhost/my/ webRoot is / +http://localhost/my-todo.html webRoot is / +http://localhost/index.php?m=my&f=index webRoot is / +http://localhost/zentao/my/ webRoot is /zentao/ +http://localhost/zentao/my-todo.html webRoot is /zentao/ +http://localhost/zentao/index.php?m=my&f=index webRoot is /zentao/ diff --git a/framework/tests/helper/101.setmember.onelevel.php b/framework/tests/helper/101.setmember.onelevel.php new file mode 100755 index 0000000000..cb7a794639 --- /dev/null +++ b/framework/tests/helper/101.setmember.onelevel.php @@ -0,0 +1,27 @@ +#!/usr/bin/env php +key1 = 'value1'; + +$obj2 = new stdclass(); +$obj2->key1 = 'value2.1'; + +helper::setMember('obj', 'key1', 'value1.1'); // overide the exists key. +helper::setMember('obj', 'key2', 'value2'); // add a new key. +helper::setMember('obj', 'key3', 3); // set an int value. +helper::setMember('obj', 'key4', array(1, 2, 3)); // set an array value. +helper::setMember('obj', 'key5', $obj2); // set an object value. + +echo $obj->key1 . "\n"; +echo $obj->key2 . "\n"; +echo $obj->key3 . "\n"; +print_r($obj->key4); +print_r($obj->key5); diff --git a/framework/tests/helper/110.setmember.multilevel.php b/framework/tests/helper/110.setmember.multilevel.php new file mode 100755 index 0000000000..14d3baf0cd --- /dev/null +++ b/framework/tests/helper/110.setmember.multilevel.php @@ -0,0 +1,22 @@ +#!/usr/bin/env php +user = new stdclass(); +$obj->user->name = 'Tom'; + +helper::setMember('obj', 'user.name', 'Mary'); // overide the exists key. +helper::setMember('obj', 'user.age', 20); // add a child key to an existing key. +helper::setMember('obj', 'home.address', new stdclass()); // add a child key even the parent doesn't exist. +helper::setMember('obj', 'home.address.postcode', '10000'); // three level. + +echo $obj->user->name . "\n"; +echo $obj->user->age . "\n"; +print_r($obj->home->address); diff --git a/framework/tests/helper/201.getwebroot.inbrowse.php b/framework/tests/helper/201.getwebroot.inbrowse.php new file mode 100755 index 0000000000..a630da9b4d --- /dev/null +++ b/framework/tests/helper/201.getwebroot.inbrowse.php @@ -0,0 +1,17 @@ +#!/usr/bin/env php + Date: Fri, 20 Oct 2017 16:24:50 +0800 Subject: [PATCH 8/8] "fix debug level 2" --- module/project/js/common.js | 2 +- module/project/view/task.html.php | 2 +- module/task/js/common.js | 2 +- module/task/js/create.js | 2 +- module/task/js/edit.js | 2 +- module/task/model.php | 16 ++++++++-------- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/module/project/js/common.js b/module/project/js/common.js index 5f3298ac06..24c3c6b85f 100644 --- a/module/project/js/common.js +++ b/module/project/js/common.js @@ -190,4 +190,4 @@ $('.task-toggle').click(function() obj.removeClass('icon-minus').addClass('icon-plus'); } return false; -}); \ No newline at end of file +}); diff --git a/module/project/view/task.html.php b/module/project/view/task.html.php index f9ce51581f..2f2022c87c 100644 --- a/module/project/view/task.html.php +++ b/module/project/view/task.html.php @@ -70,7 +70,7 @@ js::set('browseType', $browseType); $value) $this->task->printCell($value, $task, $users, $browseType, $branchGroups, $modulePairs);?> - children):?> + children)):?> children as $child):?> $value) $this->task->printCell($value, $child, $users, $browseType, $branchGroups, $modulePairs);?> diff --git a/module/task/js/common.js b/module/task/js/common.js index 9363ddb004..140db4051e 100644 --- a/module/task/js/common.js +++ b/module/task/js/common.js @@ -56,4 +56,4 @@ $('#modalTeam .btn').click(function() $('#teamMember').val(team); $('#estimate').val(time); }) -}) \ No newline at end of file +}) diff --git a/module/task/js/create.js b/module/task/js/create.js index bdb27f8b2f..b9b90827af 100644 --- a/module/task/js/create.js +++ b/module/task/js/create.js @@ -224,4 +224,4 @@ $(".btn[data-toggle='modalTeam']").click(function() { $('#modalTeam').modal('show'); adjustSortBtn(); -}); \ No newline at end of file +}); diff --git a/module/task/js/edit.js b/module/task/js/edit.js index 401c03d80e..72e23de445 100644 --- a/module/task/js/edit.js +++ b/module/task/js/edit.js @@ -88,4 +88,4 @@ $(document).ready(function() $('#teamTr').addClass('hidden'); } }); -}); \ No newline at end of file +}); diff --git a/module/task/model.php b/module/task/model.php index 1dc1000479..e33cbc5b2b 100644 --- a/module/task/model.php +++ b/module/task/model.php @@ -1082,7 +1082,7 @@ class taskModel extends model $taskList = array_keys($tasks); $children = $this->dao->select('*')->from(TABLE_TASK)->where('parent')->in($taskList)->orderBy('id_desc')->fetchGroup('parent'); - if($children) foreach($children as $key => $child) $tasks[$key]->children = $child; + if(!empty($children)) foreach($children as $key => $child) $tasks[$key]->children = $child; $teams = $this->dao->select('*')->from(TABLE_TEAM)->where('task')->in($taskList)->fetchGroup('task'); if($teams) foreach($teams as $key => $team) if(!empty($team)) $tasks[$key]->team = $team; @@ -1362,7 +1362,7 @@ class taskModel extends model foreach($tasks as $task) { $task = $this->processTask($task); - if($task->children) foreach($task->children as $child) + if(!empty($task->children)) foreach($task->children as $child) { $task = $this->processTask($child); } @@ -1393,7 +1393,7 @@ class taskModel extends model /* Story changed or not. */ $task->needConfirm = false; - if($task->storyStatus == 'active' and $task->latestStoryVersion > $task->storyVersion) $task->needConfirm = true; + if(!empty($task->storyStatus) and $task->storyStatus == 'active' and $task->latestStoryVersion > $task->storyVersion) $task->needConfirm = true; /* Set product type for task. */ if(isset($task->product)) @@ -1832,17 +1832,17 @@ class taskModel extends model echo ""; break; case 'name': - if(isset($branchGroups[$task->product][$task->branch])) echo "" . $branchGroups[$task->product][$task->branch] . ' '; + if(!empty($task->product) && isset($branchGroups[$task->product][$task->branch])) echo "" . $branchGroups[$task->product][$task->branch] . ' '; if($modulePairs and $task->module) echo "" . $modulePairs[$task->module] . ' '; echo html::a($taskLink, $task->name, null, "style='color: $task->color'"); if($task->fromBug) echo html::a(helper::createLink('bug', 'view', "id=$task->fromBug"), "[BUG#$task->fromBug]", '_blank', "class='bug'"); - if($task->children) echo '    '; + if(!empty($task->children)) echo '    '; break; case 'type': echo $this->lang->task->typeList[$task->type]; break; case 'status': - $storyChanged = ($task->storyStatus == 'active' and $task->latestStoryVersion > $task->storyVersion); + $storyChanged = (!empty($task->storyStatus) and $task->storyStatus == 'active' and $task->latestStoryVersion > $task->storyVersion); $storyChanged ? print("{$this->lang->story->changed} ") : print($this->lang->task->statusList[$task->status]); break; case 'estimate': @@ -1900,7 +1900,7 @@ class taskModel extends model echo $this->lang->task->reasonList[$task->closedReason]; break; case 'story': - if($task->storyID) + if(!empty($task->storyID)) { if(!common::printLink('story', 'view', "storyid=$task->storyID", $task->storyTitle)) print $task->storyTitle; } @@ -1933,7 +1933,7 @@ class taskModel extends model common::printIcon('task', 'finish', "taskID=$task->id", $task, 'list', '', '', 'iframe', true); common::printIcon('task', 'close', "taskID=$task->id", $task, 'list', '', '', 'iframe', true); common::printIcon('task', 'edit',"taskID=$task->id", $task, 'list'); - if(!$task->team or !$task->children) common::printIcon('task', 'batchCreate', "project=$task->project&storyID=$task->story&moduleID=$task->module&taskID=$task->id", $task, 'list','plus','','','','',$this->lang->task->children); + if(empty($task->team) or empty($task->children)) common::printIcon('task', 'batchCreate', "project=$task->project&storyID=$task->story&moduleID=$task->module&taskID=$task->id", $task, 'list','plus','','','','',$this->lang->task->children); break; } echo '';