diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..6e32ffe9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +vendor + +composer.lock diff --git a/.styleci.yml b/.styleci.yml new file mode 100644 index 00000000..362ac647 --- /dev/null +++ b/.styleci.yml @@ -0,0 +1,49 @@ +preset: psr2 +risky: false +finder: + exclude: + - "data" + - "storage" + - "vendor" + - ".git" + - ".svn" + name: + - "*.php" + path: + - "" +enabled: + - double_arrow_multiline_whitespaces + - duplicate_semicolon + - blankline_after_open_tag + - concat_without_spaces + - function_typehint_space + - list_commas + - multiline_array_trailing_comma + - namespace_no_leading_whitespace + - no_blank_lines_after_class_opening + - object_operator + - phpdoc_indent + - phpdoc_no_access + - phpdoc_no_empty_return + - phpdoc_params + - phpdoc_scalar + - phpdoc_to_comment + - remove_leading_slash_use + - remove_lines_between_uses + - return + - single_blank_line_before_namespace + - spaces_after_semicolon + - spaces_cast + - standardize_not_equal + - unneeded_control_parentheses + - unused_use + - whitespacy_lines + - single_quote + - include + - unalign_double_arrow + - unalign_equals + - ternary_spaces + - operators_spaces + - trim_array_spaces + - array_element_white_space_after_comma + - array_element_no_space_before_comma diff --git a/_compile/compile.php b/_compile/compile.php deleted file mode 100644 index c727e004..00000000 --- a/_compile/compile.php +++ /dev/null @@ -1,77 +0,0 @@ - $value) { - $_key = Wind::getRealPath($key); - if (key_exists($key, $packInfo)) { - $fileList[$_key] = array($key, $value); - } - $content[$value] = parseFilePath($key); -} -//$pack->setContentInjectionCallBack('addImports'); -$pack->packFromFileList($fileList, WIND_PATH . 'wind_basic.php', WindPack::STRIP_PHP, true); -$message[] = "COMPILE: pack core file successful~"; - -WindFile::write(_COMPILE_PATH . 'wind_imports.php', 'parse(_COMPILE_PATH . 'config/' . $file); - $file = preg_replace('/\.(\w)*$/i', '', $file); - //WindFile::write(_COMPILE_PATH . $file . '.php', '", $message); - -/*********************************************************************/ -/* 向wind包中注入imports文件目录信息 */ -function addImports() { - $_content = WindString::varToString($GLOBALS['imports']); - $_content = str_replace(array("\r\n", "\t", " "), '', $_content); - return 'Wind::setImports(' . $_content . ');'; -} - -/* 清理所有缓存 */ -function parseFilePath($filePath) { - list($namespace, $filePath) = explode(':', $filePath); - return str_replace('.', '/', $filePath); -} \ No newline at end of file diff --git a/_compile/config/components_config.xml b/_compile/config/components_config.xml deleted file mode 100644 index 7731caeb..00000000 --- a/_compile/config/components_config.xml +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template - htm - 1 - compile.template - tpl - - - true - - - - - - - - - - - - - - - - - - - - - - - - - - DATA:caches - php - 0 - - - - - - - - i18n - - - - - 86400 - - - diff --git a/_compile/lib/CompileCmdHelp.php b/_compile/lib/CompileCmdHelp.php deleted file mode 100644 index c1896c26..00000000 --- a/_compile/lib/CompileCmdHelp.php +++ /dev/null @@ -1,49 +0,0 @@ - - * @copyright ©2003-2103 phpwind.com - * @license http://www.phpwind.com/license.php - * @version $Id$ - * @package wind - */ -class CompileCmdHelp { - - /** - * 获取用户输入信息 - * - * @param string $message - * @return string - */ - static public function getInput($message) { - echo $message; - return str_replace(array("\r", "\n"), '', fgets(STDIN)); - } - - /** - * 显示提示信息 - * - * @param string $message - */ - static public function showMessge($message) { - if (is_array($message)) { - foreach ($message as $key => $value) { - echo "'" . $key . "' => '" . $value . "',\r\n"; - } - } else - echo $message; - } - - /** - * 显示系统错误信息 - * - * @param string $message - * @param string $cmd - */ - static public function showError($message, $cmd = 'pack') { - $_msg = "Error: " . $message . "\r\n"; - $_msg .= "Try: " . $cmd . " help for usage\r\n"; - exit($_msg); - } -} - -?> \ No newline at end of file diff --git a/_compile/lib/CompilePack.php b/_compile/lib/CompilePack.php deleted file mode 100644 index f6cca8d5..00000000 --- a/_compile/lib/CompilePack.php +++ /dev/null @@ -1,95 +0,0 @@ - - * @copyright ©2003-2103 phpwind.com - * @license http://www.phpwind.com/license.php - * @version $Id$ - * @package wind - */ -class CompilePack { - private $extensions = 'php'; - private $_r = false; - private $_p = false; - public $fileList = array(); - public $imports = array(); - public $classes = array(); - public $namespace = array(); - - /** - * 默认为 r,p 都为 true - * - * @param boolean $r 是否递归文件夹 - * @param boolean $p 是否生成打包 - */ - public function __construct($r = false, $p = false) { - $this->_r = $r; - $this->_p = $p; - } - - /** - * 将一组文件列表合并为一个文件列表 - * - * @param array $files 文件/文件夹列表 - * @param string $packPath 打包文件存放路径 - * @param $boolean - */ - public function pack($files, $packPath = '', $namespace = '') { - $namespace = explode(' ', $namespace); - $i = 0; - foreach ($files as $filePath) { - if (!$filePath = realpath($filePath)) continue; - $_dir = dirname($filePath); - $_n = isset($namespace[$i]) ? $namespace[$i] : basename($_dir); - $_n = array(strtoupper($_n), $_dir . '/'); - $this->_import($filePath, $_n); - $i++; - } - if ($this->_p && $this->fileList) { - Wind::import('WIND:utility.WindPack'); - $pack = new WindPack(); - $pack->setContentInjectionCallBack(array($this, 'injectionImports')); - if (!$pack->packFromFileList($this->fileList, $packPath, WindPack::STRIP_PHP, true)) throw new Exception( - 'failed to create pack file (' . $packPath . ')'); - } - } - - /** - * 向打包好的文件头部注入 import 信息 - */ - public function injectionImports() { - $_content = WindString::varToString($this->imports); - $_content = str_replace(array("\r\n", "\t", " "), '', $_content); - return 'Wind::$_imports += ' . $_content . ';'; - } - - /** - * @param string $filePath - * @throws Exception - */ - private function _import($filePath, $namespace) { - if (is_dir($filePath)) { - if (false === ($files = scandir($filePath, 0))) throw new Exception( - 'the file ' . $filePath . ' open failed!'); - foreach ($files as $file) { - if (!$file || $file[0] === '.') continue; - if (!$this->_r && is_dir($filePath . '/' . $file)) continue; - $this->_import($filePath . '/' . $file, $namespace); - } - } elseif (is_file($filePath)) { - $_info = pathinfo($filePath); - if ($_info['extension'] !== 'php') return; - $this->fileList[$_info['filename']] = $filePath; - $_file = $_info['dirname'] . '/' . $_info['filename']; - $_key = str_replace(array($namespace[1], '/'), array($namespace[0] . ':', '.'), $_file); - $this->imports[$_key] = $_info['filename']; - $this->classes[$_info['filename']] = str_replace($namespace[1], '', $_file); - $this->namespace[$namespace[0]] = $namespace[1]; - Wind::$_classes[$_info['filename']] = $_file; - } else - throw new Exception($filePath . ': No such file or directory'); - } -} - -?> \ No newline at end of file diff --git a/_compile/readme b/_compile/readme deleted file mode 100644 index 628cc6a4..00000000 --- a/_compile/readme +++ /dev/null @@ -1,2 +0,0 @@ -运行: -compile.php diff --git a/_compile/tools/pack.php b/_compile/tools/pack.php deleted file mode 100644 index faf1ce16..00000000 --- a/_compile/tools/pack.php +++ /dev/null @@ -1,95 +0,0 @@ - - * -r 是否递归的方式打包文件夹 - * -p 将所列文件夹打包,合并成一个文件(去除空格,注释等) - * example: - * pack -pci /var/www/wind/utility /var/www/wind/base - * 这个例子中包含两个文件夹utility、base(支持文件,文件夹;支持一个或者多个)。打包工具将这两个文件夹下面的文件打包到同一个文件下。 - * 并将 /var/www/wind/ 以WIND别名注册为系统目录别名 - * - * @author Qiong Wu 2010-11-2 - * @link http://www.phpwind.com - * @copyright Copyright © 2003-2010 phpwind.com - * @license http://www.phpwind.com/license.php - */ -include '../../wind/Wind.php'; -Wind::register(dirname(dirname(__FILE__)), '_COMPILE'); -Wind::import('_COMPILE:lib.*'); - -$args = isset($_SERVER['argv']) ? $_SERVER['argv'] : array(); -if (count($args) < 2) CompileCmdHelp::showError('Not enough arguments provided'); -unset($args[0]); -$files = array(); -$params = ''; -foreach ($args as $value) { - if (!$value) continue; - if ($value[0] === '-') - $params .= trim($value, '-'); - else - $files[] = $value; -} -empty($files) && CompileCmdHelp::showError('Not enough arguments provided'); - -$params = '-' . $params; -$_p = strpos($params, 'p'); -$_r = strpos($params, 'r'); - -$packFile = $namespace = ''; -if ($_p) { - $packFile = CompileCmdHelp::getInput("Enter folder in which to save the pack file (default: /home/you/):"); - if (!$packFile) { - $processUser = posix_getpwuid(posix_geteuid()); - $packFile = '/home/' . $processUser['name'] . '/wind_basic.php'; - } - $namespace = CompileCmdHelp::getInput("Enter namespace for folder (default: folder name):"); -} - -try { - $pack = new CompilePack($_r, $_p); - $pack->pack($files, $packFile, $namespace); -} catch (Exception $e) { - CompileCmdHelp::showError($e->getMessage()); -} - -CompileCmdHelp::showMessge("Operation was successful!\r\n"); -$_p && CompileCmdHelp::showMessge( - "Your pack file has been saved in: " . $packFile . " (" . filesize($packFile) . ")\r\n"); -if ($pack->namespace) { - CompileCmdHelp::showMessge( - "If use the parameters (i or c), You need the 'wind_basic.php' is loaded before the registration of the following information to the system.\r\n"); - CompileCmdHelp::showMessge($pack->namespace); -} - -do { - $_op = CompileCmdHelp::getInput("Show Details(i/c/p):"); - switch ($_op) { - case 'i': - CompileCmdHelp::showMessge("The imports list:\r\n"); - CompileCmdHelp::showMessge($pack->imports); - break; - case 'c': - CompileCmdHelp::showMessge("The classes list:\r\n"); - CompileCmdHelp::showMessge($pack->classes); - break; - case 'p': - CompileCmdHelp::showMessge("The pack file list:\r\n"); - CompileCmdHelp::showMessge($pack->fileList); - break; - default: - $_op = ''; - break; - } -} while ($_op); - -exit(); - - - - - - - - diff --git a/_compile/tools/readme b/_compile/tools/readme deleted file mode 100644 index 632562b8..00000000 --- a/_compile/tools/readme +++ /dev/null @@ -1,5 +0,0 @@ -Performance tools 性能优化工具 - -1. pack - 打包工具,用于将一组文件打包成一个文件,并去除注释和空格。 - 通过打包,可以有效的减少字节,减少文件加载数,以及文件名处理时间。 diff --git a/_tests/AllTest.php b/_tests/AllTest.php deleted file mode 100644 index af8b4f73..00000000 --- a/_tests/AllTest.php +++ /dev/null @@ -1,15 +0,0 @@ -addTest(AllBaseTest::suite()); - $suite->addTest(AllWebTest::suite()); - return $suite; - } -} \ No newline at end of file diff --git a/_tests/BaseTestCase.php b/_tests/BaseTestCase.php deleted file mode 100644 index aaf743c5..00000000 --- a/_tests/BaseTestCase.php +++ /dev/null @@ -1,34 +0,0 @@ -fail("Error type for arg1"); - $this->assertTrue(is_array($array2) && (count($array1) == count($array2))); - foreach ($array1 as $key => $value) { - $this->assertTrue(isset($array2[$key])); - if (is_array($value)) { - $this->assertArrayEquals($value, $array2[$key]); - } elseif (is_object($value)) { - $this->assertEquals(get_class($value), get_class($array2[$key])); - } else { - $this->assertEquals($value, $array2[$key]); - } - } - } -} \ No newline at end of file diff --git "a/_tests/about\345\221\275\344\273\244\350\241\214" "b/_tests/about\345\221\275\344\273\244\350\241\214" deleted file mode 100644 index 300986fe..00000000 --- "a/_tests/about\345\221\275\344\273\244\350\241\214" +++ /dev/null @@ -1,53 +0,0 @@ -命令行下运行: -windTest AllTest - - -命令行下运行需要安装phpunit,目前最新版本为3.5 -安装: -1:安装pear:(如果已经安装跳过) - 命令行下进入php目录执行:go-pear - 一路yes / y - -2: 升级pear:(phpunit需要pear的版本在1.8以上,如果已经最新,跳过) - pear upgrade pear - (查看pear的版本信息:pear version) - -3: 安装phpunit: - 3.1: 添加phpunit的频道并初始化: - pear channel-discover pear.phpunit.de - 3.2: 获得phpunit并安装: - 采用全安装模式: - pear install --alldeps phpunit/PHPUnit - - 3.3:安装成功:查看phpunit命令 - phpunit - -需要获得覆盖率需要安装xdebug插件. -www.xdebug.org下载最新xdebug,修改为php_xdebug(可选)放在PHP/ext下 -配置php.ini: - -;xdebug配置 -[Xdebug] -zend_extension_ts="C:/wamp/php/ext/php_xdebug.dll" -;开启自动跟踪 -xdebug.auto_trace = On -;开启异常跟踪 -xdebug.show_exception_trace = On -;开启远程调试自动启动 -xdebug.remote_autostart = On -;开启远程调试 -xdebug.remote_enable = On -;收集变量 -xdebug.collect_vars = On -;收集返回值 -xdebug.collect_return = On -;收集参数 -xdebug.collect_params = On -;设置输出路径 -xdebug.trace_output_dir="D:/PHPAPP/Xdebug" -xdebug.profiler_output_dir="D:/PHPAPP/Xdebug" - -注意:xdebug和zend optimization冲突 -所以如果安装了zend optimization需要将该选项去掉(或是加;注释) -xdebug的加载模式需要是zend_extension_ts或是zend_extension -目前5.2.X需要采用zend_extension_ts加载,后续版本(5.3)才用zend_extension \ No newline at end of file diff --git a/_tests/base/AllBaseTest.php b/_tests/base/AllBaseTest.php deleted file mode 100644 index e3a1688c..00000000 --- a/_tests/base/AllBaseTest.php +++ /dev/null @@ -1,38 +0,0 @@ - - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package base - */ -class AllBaseTest extends PHPUnit_Framework_TestSuite { - - public static function main() { - PHPUnit_TestUI_TestRunner::run(self::suite()); - } - - public static function suite() { - $suite = new PHPUnit_Framework_TestSuite('WindFramework AllBaseTest'); - $suite->addTestSuite('WindModuleTest'); - $suite->addTestSuite('WindActionExceptionTest'); - $suite->addTestSuite('WindErrorMessageTest'); - $suite->addTestSuite('WindForwardExceptionTest'); - $suite->addTestSuite('WindExceptionTest'); - $suite->addTestSuite('WindFactoryTest'); - $suite->addTestSuite('WindClassProxyTest'); - $suite->addTestSuite('WindHelperTest'); - $suite->addTestSuite('WindEnableValidateModuleTest'); - return $suite; - } -} - diff --git a/_tests/base/WindActionExceptionTest.php b/_tests/base/WindActionExceptionTest.php deleted file mode 100644 index 321e02f5..00000000 --- a/_tests/base/WindActionExceptionTest.php +++ /dev/null @@ -1,49 +0,0 @@ - - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package base - */ -class WindActionExceptionTest extends BaseTestCase { - - /** - * @var WindErrorMessage - */ - private $errorMessage; - - public function setUp(){ - parent::setUp(); - require_once 'base\WindActionException.php'; - require_once 'base\WindErrorMessage.php'; - $this->errorMessage = new WindErrorMessage("error","errorAction"); - } - - public function tearDown(){ - parent::tearDown(); - } - - /** - * Tests WindActionException->__construct() - */ - public function test__construct() { - try { - $this->errorMessage->sendError(); - }catch (WindActionException $e){ - $this->assertEquals($e->getError(),$this->errorMessage); - return; - } - try { - throw new WindActionException("error!"); - }catch (Exception $e){ - $this->assertEquals($e->getMessage(), "error!"); - return; - } - $this->fail("WindActionExceptionTest Error"); - } - -} - diff --git a/_tests/base/WindClassProxyTest.php b/_tests/base/WindClassProxyTest.php deleted file mode 100644 index b9df28b8..00000000 --- a/_tests/base/WindClassProxyTest.php +++ /dev/null @@ -1,72 +0,0 @@ - - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package base - */ -class WindClassProxyTest extends BaseTestCase { - - /** - * @var WindClassProxy - */ - private $WindClassProxy; - /** - * @var ForWindFactoryTest - */ - private $test; - /** - * Prepares the environment before running a test. - */ - protected function setUp() { - parent::setUp(); - require_once 'base\WindClassProxy.php'; - require_once 'data\ForWindFactoryTest.php'; - require_once 'data\ForWindClassProxyTest.php'; - $this->test = new ForWindFactoryTest(); - $this->WindClassProxy = new WindClassProxy($this->test); - } - - /** - * Cleans up the environment after running a test. - */ - protected function tearDown() { - $this->WindClassProxy = null; - parent::tearDown(); - } - - /** - * Tests WindClassProxy->__call() - */ - public function test__call() { - $listener1 = new listener1(); - $this->WindClassProxy->registerEventListener("init", $listener1, WindClassProxy::EVENT_TYPE_METHOD); - $this->WindClassProxy->init('aaa'); - $this->assertEquals("aaalistener1_preaaa_post", $listener1->a); - - $listener2 = new listener2(); - $this->WindClassProxy->registerEventListener("init", $listener2, WindClassProxy::EVENT_TYPE_METHOD); - $this->WindClassProxy->init('shi', 'long'); - $this->assertEquals('shilistener2_preshi_post', $listener2->a); - $this->assertEquals('longlistener2_prelong_post', $listener2->b); - - try { - $this->WindClassProxy->registerEventListener("init", $listener2, "init"); - } catch (WindException $e) { - return; - } - $this->fail("RegisterEventListenerTest Error!"); - } - - /** - * Tests WindClassProxy->_setClassPath() - */ - public function test_setClassPath() { - $this->WindClassProxy->_setClassPath("TEST:data.ForWindClassProxyTest"); - $this->assertEquals("TEST:data.ForWindClassProxyTest", $this->WindClassProxy->_getClassPath()); - $this->assertEquals("ForWindClassProxyTest", $this->WindClassProxy->_getClassName()); - } -} diff --git a/_tests/base/WindEnableValidateModuleTest.php b/_tests/base/WindEnableValidateModuleTest.php deleted file mode 100644 index 051f1fe7..00000000 --- a/_tests/base/WindEnableValidateModuleTest.php +++ /dev/null @@ -1,48 +0,0 @@ - - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package base - */ -class WindEnableValidateModuleTest extends BaseTestCase { - - /** - * Prepares the environment before running a test. - */ - protected function setUp() { - parent::setUp(); - require_once 'base\WindEnableValidateModule.php'; - } - - public function testFormFilter() { - $_SERVER['SCRIPT_FILENAME'] = "index.php"; - $_SERVER['SCRIPT_NAME'] = 'index.php'; - $_SERVER['HTTP_HOST'] = 'localhost'; - $_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_FILENAME'] . '?c=long&a=test'; - $_POST['shi'] = 'shi'; - $_POST['long'] = 'long'; - Wind::application('EnableValidata', $this->getConfigData())->run(); - $testForm = Wind::getApp()->getRequest()->getAttribute("testForm"); - $this->assertEquals("shi", $testForm->getShi()); - $this->assertEquals("long", $testForm->getLong()); - } - - private function getConfigData() { - return array( - "web-apps" => array( - "EnableValidata" => array( - 'filters' => array( - 'filter' => array( - 'class' => 'WIND:web.filter.WindFormFilter', - 'pattern' => 'default/long/test', - 'form' => 'TEST:data.TestForm')), - - 'modules' => array('default' => array('controller-path' => 'data'))))); - } - -} - diff --git a/_tests/base/WindErrorMessageTest.php b/_tests/base/WindErrorMessageTest.php deleted file mode 100644 index 1f916772..00000000 --- a/_tests/base/WindErrorMessageTest.php +++ /dev/null @@ -1,61 +0,0 @@ - - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package base - */ -class WindErrorMessageTest extends BaseTestCase { - - /** - * @var WindErrorMessage - */ - private $WindErrorMessage; - - /** - * Prepares the environment before running a test. - */ - protected function setUp() { - parent::setUp(); - require_once 'base\WindErrorMessage.php'; - $this->WindErrorMessage = new WindErrorMessage("error","errorAction"); - } - - /** - * Cleans up the environment after running a test. - */ - protected function tearDown() { - $this->WindErrorMessage = null; - parent::tearDown(); - } - - /** - * @dataProvider dataForClearError - */ - public function testClearError($data, $key = '') { - $this->WindErrorMessage->addError($data, $key); - $this->assertEquals($this->WindErrorMessage->getError("content"), "shilong"); - $this->WindErrorMessage->clearError(); - $this->assertEquals($this->WindErrorMessage->getError(), array()); - } - - public function dataForClearError(){ - $args = array(); - $object = new stdClass(); - $object->content = 'shilong'; - $args[] = array($object); - $args[] = array(array('content' => 'shilong'),''); - $args[] = array('shilong', 'content'); - return $args; - } - - /** - * Tests WindErrorMessage->getErrorAction() - */ - public function testGetErrorAction() { - $this->assertEquals($this->WindErrorMessage->getErrorAction(), "errorAction"); - } -} diff --git a/_tests/base/WindExceptionTest.php b/_tests/base/WindExceptionTest.php deleted file mode 100644 index 2496dfba..00000000 --- a/_tests/base/WindExceptionTest.php +++ /dev/null @@ -1,29 +0,0 @@ - - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package base - */ -class WindExceptionTest extends BaseTestCase { - - /** - * Tests WindException->__construct() - */ - public function test__construct() { - try { - throw new WindException('method1',WindException::ERROR_CLASS_METHOD_NOT_EXIST); - } catch (Exception $e) { - $this->assertEquals("WindException",get_class($e)); - $this->assertEquals( - "Unable to access the method 'method1' in current class , the method is not exist or is protected.", - $e->getMessage()); - } - } - -} - diff --git a/_tests/base/WindFactoryTest.php b/_tests/base/WindFactoryTest.php deleted file mode 100644 index 8b0198dc..00000000 --- a/_tests/base/WindFactoryTest.php +++ /dev/null @@ -1,153 +0,0 @@ - - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package base - */ -class WindFactoryTest extends BaseTestCase { - - protected $factory; - - /** - * Prepares the environment before running a test. - */ - protected function setUp() { - parent::setUp(); - require_once 'base\WindFactory.php'; - require_once 'data\ForWindFactoryTest.php'; - Wind::application()->createApplication(); - $this->factory || $this->factory = Wind::getApp()->getWindFactory(); - } - - /** - * Cleans up the environment after running a test. - */ - protected function tearDown() { - parent::tearDown(); - $this->factory = null; - } - - /** - * Tests WindFactory->__construct() - */ - public function test__construct() { - $windFactory = $this->factory; - $this->assertEquals("WindFactory", get_class($windFactory)); - } - - /** - * Tests WindFactory->getInstance() - */ - public function testGetInstance() { - $this->assertTrue(Wind::getApp()->getComponent("forward") instanceof WindForward); - try { - Wind::getApp()->getComponent("notExistCom"); - } catch (WindException $e) { - return; - } - $this->fail("GetInstance Test Error"); - } - - /** - * Tests WindFactory::createInstance() - */ - public function testCreateInstance() { - try { - $this->factory->createInstance("notExistCom"); - } catch (WindException $e) { - return; - } - $this->fail("CreateInstance Error"); - } - - /** - * Tests WindFactory->registInstance() - */ - public function testRegistInstance() { - $testObject = new ForWindFactoryTest(); - $this->assertFalse($this->factory->checkAlias("test")); - $this->factory->registInstance($testObject, "test", "singleton"); - $this->assertTrue($this->factory->getInstance("test") instanceof ForWindFactoryTest); - $this->assertTrue($this->factory->checkAlias("test")); - } - - /** - * Tests WindFactory->addClassDefinitions() - */ - public function testAddClassDefinitions() { - $this->factory->addClassDefinitions("aaa", $this->getTestData()); - $aaa = $this->factory->getInstance("aaa"); - $this->assertEquals("ForWindFactoryTest", get_class($aaa)); - try { - $this->factory->executeDestroyMethod(); - } catch (Exception $e) { - return; - } - $this->fail("ExecuteDestroyMethodTest Error!"); - } - - /** - * Tests WindFactory->loadClassDefinitions() - */ - public function testLoadClassDefinitions() { - $this->factory->loadClassDefinitions( - array("bbb" => $this->getTestData(), "windSession" => $this->getTestData())); - $this->assertEquals("ForWindFactoryTest", get_class($this->factory->getInstance("bbb"))); - $this->assertEquals("ForWindFactoryTest", - get_class($this->factory->getInstance("windSession"))); - } - - public function testSetProxyForClass() { - $this->assertTrue($this->factory->getInstance("forward") instanceof WindForward); - $this->factory->loadClassDefinitions( - array("forward" => array('path' => 'WIND:web.WindForward', 'proxy' => true)), false); - $this->assertTrue($this->factory->getInstance("forward") instanceof WindClassProxy); - } - - /** - * @dataProvider dataForBulidProperties - */ - public function testBuildProperties($config) { - $this->factory->addClassDefinitions("xxx", $config); - $object = $this->factory->getInstance("xxx"); - $this->assertEquals("WindConnection", get_class($object->param)); - $this->assertTrue("WindLogger" == get_class($object->session)); - } - - public function dataForBulidProperties() { - $args = array(); - $args[] = array( - array( - 'path' => 'TEST:data.ForWindFactoryTest', - 'properties' => array( - 'param' => array('path' => 'WIND:db.WindConnection'), - 'session' => array('ref' => 'windLogger'), - 'delay' => false))); - return $args; - } - - public function testResolveConfig() { - $this->factory->addClassDefinitions("shilong", - array( - 'config' => array('resource' => 'TEST:data.testComponentConfig.php'), - 'path' => 'WIND:log.WindLogger')); - $logger = $this->factory->getInstance("shilong"); - $this->assertEquals("logByShiLong", $logger->getConfig("logName")); - } - - private function getTestData() { - return array( - 'path' => 'TEST:data.ForWindFactoryTest', - 'destroy' => 'clear', - 'constructor-args' => array( - '0' => array('value' => 2), - '1' => array('path' => 'WIND:web.WindForward'), - '2' => array('ref' => 'errorMessage')), - 'initMethod' => 'init'); - } - -} \ No newline at end of file diff --git a/_tests/base/WindForwardExceptionTest.php b/_tests/base/WindForwardExceptionTest.php deleted file mode 100644 index 4aef17d4..00000000 --- a/_tests/base/WindForwardExceptionTest.php +++ /dev/null @@ -1,43 +0,0 @@ - - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package base - */ -class WindForwardExceptionTest extends BaseTestCase { - - /** - * Prepares the environment before running a test. - */ - protected function setUp() { - parent::setUp(); - require_once 'base\WindForwardException.php'; - require_once 'web\WindForward.php'; - } - - /** - * Tests WindForwardException->__construct() - */ - public function test__construct() { - $f1 = new WindForward(); - $f1->setIsReAction(true); - $f2 = new WindForward(); - $f2->setIsReAction(false); - try { - throw new WindForwardException($f1); - } catch (Exception $e) { - $this->assertEquals("WindForwardException", get_class($e)); - $this->assertEquals($f1, $e->getForward()); - $e->setForward($f2); - $this->assertEquals($f2, $e->getForward()); - $this->assertNotEquals($f1, $e->getForward()); - } - } - - -} - diff --git a/_tests/base/WindHelperTest.php b/_tests/base/WindHelperTest.php deleted file mode 100644 index 26e5e036..00000000 --- a/_tests/base/WindHelperTest.php +++ /dev/null @@ -1,62 +0,0 @@ - - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package base - */ -class WindHelperTest extends BaseTestCase { - - protected function setUp(){ - parent::setUp(); - require_once 'base\WindHelper.php'; - require_once 'base\WindException.php'; - } - - protected function tearDown(){ - parent::tearDown(); - } - - /** - * Tests WindHelper::errorHandle() - */ - public function testErrorHandle() { - //set_error_handler("WindHelper::errorHandle"); - //$str = '111'; - //$a = unserialize($str); - //Unable to test - } - - /** - * Tests WindHelper::exceptionHandle() - */ - public function testExceptionHandle() { - //Unable to Test - } - - /** - * @dataProvider dataForGetErrorName - */ - public function testGetErrorName($errorNumber, $expected){ - $this->assertEquals($expected, ForWindHelper::getErrorName($errorNumber)); - } - - public function dataForGetErrorName(){ - $args = array(); - $args[] = array(E_ALL, "E_ALL"); - $args[] = array(E_STRICT, "E_STRICT"); - $args[] = array(3, "E_UNKNOWN"); - return $args; - } - -} - -class ForWindHelper extends WindHelper{ - public static function getErrorName($errorNumber) { - return parent::getErrorName($errorNumber); - } -} - diff --git a/_tests/base/WindModuleTest.php b/_tests/base/WindModuleTest.php deleted file mode 100644 index 8ba8b8a0..00000000 --- a/_tests/base/WindModuleTest.php +++ /dev/null @@ -1,82 +0,0 @@ - - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package base - */ -class WindModuleTest extends BaseTestCase { - - /** - * @var WindModule - */ - private $WindModule; - /** - * Prepares the environment before running a test. - */ - protected function setUp() { - parent::setUp(); - require_once 'base\WindModule.php'; - require_once 'data\TestFrontController.php'; - require_once 'data\ForWindFactoryTest.php'; - require_once 'data\LongController.php'; - Wind::application()->createApplication(); - $this->WindModule = new LongController(); - } - - - /** - * Cleans up the environment after running a test. - */ - protected function tearDown() { - $this->WindModule = null; - parent::tearDown(); - } - - /** - * Tests WindModule->__set() - */ - public function test__set() { - $this->WindModule->config = array(1); - $this->assertArrayEquals(array(1), $this->WindModule->config); - } - - /** - * @param unknown_type $attributes - * @dataProvider dataFor__call - */ - public function test__call($attributes) { - $this->WindModule->setDelayAttributes($attributes); - $this->assertTrue($this->WindModule->_getShi() instanceof ForWindFactoryTest); - $this->WindModule->_setShi(new stdClass()); - //call_user_func_array(array($this->WindModule,"_setShi"), array(new stdClass())); - $this->assertTrue($this->WindModule->_getShi() instanceof stdClass); - } - - public function dataFor__call(){ - require_once 'data\ForWindFactoryTest.php'; - $args = array(); - $args[] = array(array('shi' => array('path' => 'TEST:data.ForWindFactoryTest'))); - $args[] = array(array('shi' => array('value' => new ForWindFactoryTest()))); - return $args; - } - - /** - * Tests WindModule->toArray() - */ - public function testToArray() { - $this->WindModule->setConfig(array('destroy' => 'commit')); - $this->WindModule->setConfig(array('aaa' => 'aaa')); - $arr = $this->WindModule->toArray(); - $this->assertEquals($arr['_config'], array( - 'destroy' => 'commit', - 'aaa' => 'aaa' - )); - } - - -} - diff --git a/_tests/bootstrap.php b/_tests/bootstrap.php deleted file mode 100644 index 58d9d5b4..00000000 --- a/_tests/bootstrap.php +++ /dev/null @@ -1,10 +0,0 @@ - \ No newline at end of file diff --git a/_tests/data/ErrorControllerTest.php b/_tests/data/ErrorControllerTest.php deleted file mode 100644 index 203ef436..00000000 --- a/_tests/data/ErrorControllerTest.php +++ /dev/null @@ -1,9 +0,0 @@ - \ No newline at end of file diff --git a/_tests/data/ForWindClassProxyTest.php b/_tests/data/ForWindClassProxyTest.php deleted file mode 100644 index f41dcdaf..00000000 --- a/_tests/data/ForWindClassProxyTest.php +++ /dev/null @@ -1,24 +0,0 @@ -a = $a . 'listener1_pre'; - } - public function postHandle($a = ''){ - $this->a .= $a . '_post'; - } -} - -class listener2 extends WindHandlerInterceptor{ - public $a; - public $b; - public function preHandle($a = '', $b = ''){ - $this->a = $a . 'listener2_pre'; - $this->b = $b . 'listener2_pre'; - } - public function postHandle($a = '',$b = ''){ - $this->a .= $a . '_post'; - $this->b .= $b . '_post'; - } -} \ No newline at end of file diff --git a/_tests/data/ForWindFactoryTest.php b/_tests/data/ForWindFactoryTest.php deleted file mode 100644 index 9ed86467..00000000 --- a/_tests/data/ForWindFactoryTest.php +++ /dev/null @@ -1,30 +0,0 @@ -param = 0; - throw new WindException("test"); - } - - public function ForWindFactoryTest($param = 1, $session = null, $forward = null){ - $this->param = $param; - $this->session = $session; - $this->forward = $forward; - } - - public function setParam($param){ - $this->param = $param; - } - - public function setSession($session){ - $this->session = $session; - } - - public function init($session = null, $forward = null){ - $this->session = $session; - $this->forward = $forward; - } -} \ No newline at end of file diff --git a/_tests/data/Listener.php b/_tests/data/Listener.php deleted file mode 100644 index 8c27bed2..00000000 --- a/_tests/data/Listener.php +++ /dev/null @@ -1,31 +0,0 @@ -forward->setAction('pre_' . $this->forward->getAction()); - $this->errorMessage->addError('pre_' . $this->errorMessage->getError(0), 0); - } - public function postHandle(){ - $this->forward->setAction('post_' . $this->forward->getAction()); - $this->errorMessage->addError('post_' . $this->errorMessage->getError(0), 0); - } - - public function __construct($forward, $errorMessage){ - $this->forward = $forward; - $this->errorMessage = $errorMessage; - } - -} - -?> \ No newline at end of file diff --git a/_tests/data/LongController.php b/_tests/data/LongController.php deleted file mode 100644 index f0661167..00000000 --- a/_tests/data/LongController.php +++ /dev/null @@ -1,91 +0,0 @@ -shi; - } - - /** - * @return field_type - */ - public function getLong() { - return $this->long; - } - - /** - * @param field_type $shi - */ - public function setShi($shi) { - $this->shi = $shi; - } - - /** - * @param field_type $long - */ - public function setLong($long) { - $this->long = $long; - } - - /* (non-PHPdoc) - * @see WindEnableValidateModule::validateRules() - */ - public function validateRules() { - return array( - WindUtility::buildValidateRule("shi", "isRequired"), - WindUtility::buildValidateRule("long", "isRequired")); - } - -} \ No newline at end of file diff --git a/_tests/data/TestFrontController.php b/_tests/data/TestFrontController.php deleted file mode 100644 index 260b5095..00000000 --- a/_tests/data/TestFrontController.php +++ /dev/null @@ -1,57 +0,0 @@ -getApp()->getResponse()->sendResponse(); - $this->getApp()->getWindFactory()->executeDestroyMethod(); - array_pop($this->_currentApp); - $this->_currentAppName = end($this->_currentApp); - } - - public function beforRun($appName) { - if (in_array($appName, $this->_currentApp)) { - throw new WindException('[wind.beforRun] Nested request', WindException::ERROR_SYSTEM_ERROR); - } - $appName && $this->_currentAppName = $appName; - array_push($this->_currentApp, $this->_currentAppName); - set_error_handler('WindHelper::errorHandle'); - set_exception_handler('WindHelper::exceptionHandle'); - } - - public function createApplication($appName) { - if (!isset($this->_app[$appName])) { - $config = $this->getAppConfig($appName); - if (!empty($config['components'])) { - unset($config['components']['router']); - $this->factory->loadClassDefinitions($config['components']); - } - $application = $this->factory->getInstance('windApplication', - array($this->request, $this->response, $this->factory)); - $application->setConfig($config); - $this->request = $this->response = $this->factory = null; - $this->_app[$appName] = $application; - } - return $this->_app[$appName]; - } - - public function initConfig($config, $factory) { - is_array($config) || $config = $factory->getInstance('configParser')->parse($config); - foreach ($config['web-apps'] as $key => $value) { - if (isset($this->_config['web-apps'][$key])) continue; - $rootPath = empty($value['root-path']) ? dirname($_SERVER['SCRIPT_FILENAME']) : Wind::getRealPath( - $value['root-path'], true); - Wind::register($rootPath, $key, true); - if ('default' !== $key && !empty($config['default'])) { - $value = WindUtility::mergeArray($config['default'], $value); - } - $this->setConfig($key, $value); - } - $this->_config['router'] = isset($config['router']) ? $config['router'] : array(); - } -} - -?> \ No newline at end of file diff --git a/_tests/data/components_config.php b/_tests/data/components_config.php deleted file mode 100644 index 3c676c92..00000000 --- a/_tests/data/components_config.php +++ /dev/null @@ -1,113 +0,0 @@ - array( - 'path' => 'WIND:web.WindWebApplication', - 'scope' => 'singleton', - 'properties' => array( - 'dispatcher' => array( - 'ref' => 'dispatcher', - ), - 'handlerAdapter' => array( - 'ref' => 'router', - ), - ), - ), - 'windLogger' => array( - 'path' => 'WIND:log.WindLogger', - 'scope' => 'singleton', - 'destroy' => 'flush', - 'constructor-args' => array( - '0' => array( - 'value' => 'DATA:log', - ), - '1' => array( - 'value' => '2', - ), - ), - ), - 'dispatcher' => array( - 'path' => 'WIND:web.WindDispatcher', - 'scope' => 'application', - ), - 'forward' => array( - 'path' => 'WIND:web.WindForward', - 'scope' => 'prototype', - 'properties' => array( - 'windView' => array( - 'ref' => 'windView', - ), - ), - ), - 'router' => array( - 'path' => 'WIND:router.WindRouter', - 'scope' => 'application', - ), - 'urlHelper' => array( - 'path' => 'WIND:web.WindUrlHelper', - 'scope' => 'application', - ), - 'windView' => array( - 'path' => 'WIND:viewer.WindView', - 'scope' => 'prototype', - 'config' => array( - 'template-dir' => 'template', - 'template-ext' => 'htm', - 'is-compile' => '1', - 'compile-dir' => 'compile.template', - 'compile-ext' => 'tpl', - 'layout' => '', - 'theme' => '', - 'htmlspecialchars' => true, - ), - 'properties' => array( - 'viewResolver' => array( - 'ref' => 'viewResolver', - ), - ), - ), - 'viewResolver' => array( - 'path' => 'WIND:viewer.WindViewerResolver', - 'scope' => 'prototype', - 'properties' => array( - 'windLayout' => array( - 'ref' => 'layout', - ), - ), - ), - 'layout' => array( - 'path' => 'WIND:viewer.WindLayout', - 'scope' => 'prototype', - ), - 'template' => array( - 'path' => 'WIND:viewer.compiler.WindViewTemplate', - 'scope' => 'prototype', - ), - 'db' => array( - 'path' => 'WIND:db.WindConnection', - 'scope' => 'singleton', - 'config' => array( - 'resource' => 'db_config.xml', - ), - ), - 'errorMessage' => array( - 'path' => 'WIND:core.web.WindErrorMessage', - 'scope' => 'prototype', - ), - 'configParser' => array( - 'path' => 'WIND:parser.WindConfigParser', - 'scope' => 'singleton', - ), - 'windCache' => array( - 'path' => 'WIND:cache.strategy.WindFileCache', - 'scope' => 'singleton', - 'config' => array( - 'dir' => 'DATA:caches', - 'suffix' => 'php', - 'expires' => '0', - ), - ), - 'windSession' => array( - 'path' => 'WIND:http.session.WindSession', - 'scope' => 'singleton', - 'destroy' => 'commit', - ), -); \ No newline at end of file diff --git a/_tests/data/config.php b/_tests/data/config.php deleted file mode 100644 index 5a581f8d..00000000 --- a/_tests/data/config.php +++ /dev/null @@ -1,47 +0,0 @@ - array( - 'test' => array( - 'modules' => array( - 'default' => array( - 'controller-path' => 'controller', - 'controller-suffix' => 'Controller', - ) - ), - 'components' => array( - 'db' => array( - 'config' => array( - 'resource' => 'data.db_config.php' - ), - ), - ), - ), - 'shilong' => array( - 'modules' => array( - 'shilong' => array( - 'controller-path' => 'controller', - 'controller-suffix' => 'Controller', - ) - ), - 'filters' => array( - 'filter' => array( - 'class' => 'TEST:data.ForWindClassProxyTest', - 'pattern' => 'default_Index_run', - ) - ), - 'components' => array( - 'windCache' => array( - 'path' => 'WIND:cache.strategy.WindFileCache', - 'scope' => 'singleton', - 'config' => array( - 'dir' => 'TEST:data.caches', - 'suffix' => 'php', - 'expires' => '0', - ), - ), - ), - 'iscache' => true, - ) - ), - 'router' => array('config' => array('resource' => 'data.route_config.php')), -); \ No newline at end of file diff --git a/_tests/data/db_config.php b/_tests/data/db_config.php deleted file mode 100644 index f792111d..00000000 --- a/_tests/data/db_config.php +++ /dev/null @@ -1,7 +0,0 @@ - 'mysql:host=localhost;dbname=p9', - 'user' => 'root', - 'pwd' => 'phpwind.net', - 'charset' => 'utf8' -); \ No newline at end of file diff --git a/_tests/data/route_config.php b/_tests/data/route_config.php deleted file mode 100644 index c6da54c5..00000000 --- a/_tests/data/route_config.php +++ /dev/null @@ -1,9 +0,0 @@ - array( - 'WindRoute' => array( - 'class' => 'WIND:router.route.WindRoute', - 'default' => true, - ), - ), -); \ No newline at end of file diff --git a/_tests/data/testComponentConfig.php b/_tests/data/testComponentConfig.php deleted file mode 100644 index 74170123..00000000 --- a/_tests/data/testComponentConfig.php +++ /dev/null @@ -1,4 +0,0 @@ - 'logByShiLong', -); \ No newline at end of file diff --git a/_tests/readme b/_tests/readme deleted file mode 100644 index ed21a05a..00000000 --- a/_tests/readme +++ /dev/null @@ -1,87 +0,0 @@ -****************************************************************** -说明如下: -****************************************************************** -要用phpunit进行单元测试,需要先在zend中设置你的工程使用的unit类库,方法如下: -1]、点击需要测试的工程,右键->properties: -2]、在该选项框的左边选中:php-Include-Path -3]、在右边的选项卡片中,选中:Libraries -如果里面已经含有phpunit类库则可以跳过下面的步骤: -4]、单击添加类库按钮:Add Library -5]、选中PHPUnit,一路Next,然后OK 即可 -如果zend studio中没有默认的PHPUnit类库,则需要自己去网上下载该包并引入。 - - -****************************************************************** -目录说明: -单元测试的目录结构和框架的目录结构采用相同的结构, -对应目录下的单元测试放在对应的测试目录中。 -每个目录下都需要建一个统一测试该目录下的所有测试类的测试类,名称以All+目录名+Test为类名及文件名 -并且该类继承BaseTestSuite类 - - -****************************************************************** -测试编写说明: -引入文件:BaseTestCase.php //该文件中声明了一个常量R_P, 指定到框架所在目录的 -同时申明了一个BaseTestCase 和BaseTestSuite类分别 -继承了PHPUnit_Framework_TestCase和PHPUnit_Framework_TestSuite ---------------------------------------------------------------------- -单元测试单个测试类编写: -1、以类文件名字前加Test为测试类的类名及文件名。 - 比如,我要测试WindMySqlBuilder这个类,则将名字取名为WindMySqlBuilderTest -2、这个测试类需要继承BaseTestCase这个基类, -3、测试类中根据测试的需要加载自己的类文件,比如加载WindMySqlBuilder,而其 - 所需的基础文件已经在BaseTestCase这个文件中加载,需要引入这个文件 -4、该测试类中如果有初始化的信息可以重写setup ,销毁调用tearDown -5、对于需要测试的函数,需要使用test+方法名,添加测试方法 -6、测试的执行:点击页面右键->run as -> PHPUnit - 或者使用快捷键:alt+shift+x U - - -注意:这里需要引入要测试的类 - ---------------------------------------------------------------------- -单元测试多个测试类同时测试编写---suite: -1、继承PHPUnit_Framework_TestSuite 的子类BaseTestSuite -2、重写静态方法suite,该方法在加载完需要测试的测试类后最终返回一个自身对象 -3、加载测试类:有两种方式: - 1): addTest();//这个需要加载的是PHPUnit_Framework_TestSuite的子类对象,所以如果要用该方法加载,需要用测试类创建该对象 - 比如: addTest(new PHPUnit_Framework_TestSuite('TestWSqlBuilder')); - 同时该方法也用于在该suite集中增加另外一个suite集,比如我实现了一个suite是AllCoreTest - 则: addTest(AllCoreTest::suite()); - 2): addTestSuite();//这个需要加载只要测试类的名字就可以,该方法会自动创建对象 - 比如: addTestSuite('TestWSqlBuilder'); - -4、执行该suite - 点击页面右键->run as -> PHPUnit - 或者使用快捷键:alt+shift+x U - -注意:这里需要引入要加载的测试类 - - -------------------------------------------------------------------- -全局测试类的入口: -该为了使用方便,该测试部署也提供了一个全局的测试类入口,用来测试所有测试类 -入口为止:测试根目录下的WindAllTests.php文件, 执行该文件,将会测试所有被加载的测试类 -该类也是一个suite,满足上面所有suite需要的要求,不同的是: -1、该类中suite方法中加载了所有对应子目录下的AllTests 类, 而无需加载每一个测试类。 -2、该类引入的文件也除基本测试配置文件(BaseTestSetting)之外只要引入对应的AllTests类文件即可 - - - - -****************************************************************** -断言方法:assert* -****************************************************************** -测试结果说明: -红色条:存在测试失败的方法 -绿色条:全部方法测试成功 - -方法前面的: -红色叉叉:测试失败的方法 -蓝色叉叉:含有测试失败的情况 -绿色勾勾:测试成功的方法 - - - - - diff --git a/_tests/web/AllWebTest.php b/_tests/web/AllWebTest.php deleted file mode 100644 index f24e320d..00000000 --- a/_tests/web/AllWebTest.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package web - */ -class AllWebTest extends PHPUnit_Framework_TestSuite { - - public static function main() { - PHPUnit_TestUI_TestRunner::run(self::suite()); - } - - public static function suite() { - $suite = new PHPUnit_Framework_TestSuite('WindFramework AllWebTest'); - $suite->addTestSuite("WindWebApplicationTest"); - $suite->addTestSuite("WindUrlHelperTest"); - $suite->addTestSuite("WindForwardTest"); - $suite->addTestSuite("WindErrorHandlerTest"); - $suite->addTestSuite("WindDispatcherTest"); - $suite->addTestSuite("WindControllerTest"); - $suite->addTestSuite("WindFrontControllerTest"); - return $suite; - } -} - diff --git a/_tests/web/WindControllerTest.php b/_tests/web/WindControllerTest.php deleted file mode 100644 index d8ec87e1..00000000 --- a/_tests/web/WindControllerTest.php +++ /dev/null @@ -1,222 +0,0 @@ - - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package web - */ -class WindControllerTest extends BaseTestCase { - - private $testController; - - protected function setUp() { - parent::setUp(); - require_once 'web\WindSimpleController.php'; - require_once 'viewer\WindView.php'; - require_once 'data\LongController.php'; - $this->testController = new LongController(); - } - - protected function tearDown() { - parent::tearDown(); - } - - /** - * Tests WindSimpleController->setForward() - */ - public function testSetForward() { - $forward = new WindForward(); - $this->testController->setForward($forward); - $this->assertEquals($forward, $this->testController->getForward()); - } - - /** - * Tests WindSimpleController->setErrorMessage() - */ - public function testSetErrorMessage() { - $this->testController->setErrorMessage("123"); - $this->assertEquals("123", $this->testController->getErrorMessage()); - } - - public function testGetRequest() { - Wind::application()->createApplication(); - $this->assertTrue($this->testController->getRequest() instanceof WindHttpRequest); - } - - public function testGetInput() { - $_GET['long'] = $_POST['xxx'] = $_COOKIE['wq'] = 1; - $data = array('long', 'xxx', 'wq'); - Wind::application()->createApplication(); - $this->assertEquals($this->testController->getInput('long', 'get'), 1); - $this->assertEquals($this->testController->getInput('xxx', 'post'), 1); - $this->assertEquals($this->testController->getInput('wq', 'cookie'), 1); - $this->assertArrayEquals($this->testController->getInput($data), array_fill(0, 3, 1)); - $this->assertArrayEquals($this->testController->getInput($data, '', array($this, 'fun')), array_fill(0, 3, array(1,'shilong1'))); - } - - - public function fun($value) { - return 'shilong' . $value; - } - - /** - * 在WindForward中已测试 - */ - public function testForwardAction() { - try { - $this->testController->setForward(new WindForward()); - $this->testController->forwardAction("\test", array(), true, true); - } catch (WindForwardException $e) { - $this->assertEquals("\test", $e->getForward()->getAction()); - return; - } - $this->fail("ForwardAction Test Error"); - } - - /** - * 在WindForward中已测试 - */ - public function testForwardRedirect() { - try { - $this->testController->setForward(new WindForward()); - $this->testController->forwardRedirect("index.php"); - } catch (WindForwardException $e) { - $this->assertEquals("index.php", $e->getForward()->getUrl()); - return; - } - $this->fail("ForwardRedirect Test Error"); - } - - /** - * 在WindForward中已测试 - * @dataProvider dataForSetOutput - */ - public function testSetOutput($data, $key = '') { - $forward = new WindForward(); - $this->testController->setForward($forward); - $this->testController->setOutput($data, $key); - $this->assertEquals("shilong", $forward->getVars("name")); - } - - public function dataForSetOutput() { - $args = array(); - $object = new stdClass(); - $object->name = 'shilong'; - $args[] = array($object); - $args[] = array(array('name' => 'shilong')); - $args[] = array('shilong', 'name'); - return $args; - } - - /** - * @dataProvider dataForSetGlobal - */ - public function testSetGlobal($data, $key ='') { - Wind::application()->createApplication(); - $this->testController->setGlobal($data, $key); - $this->assertEquals('shilong', Wind::getApp()->getResponse()->getData('G', 'G', 'name')); - } - - public function dataForSetGlobal() { - $args = array(); - $object = new stdClass(); - $object->name = 'shilong'; - $args[] = array($object); - $args[] = array(array('name' => 'shilong')); - return $args; - } - - public function testShowMessage() { - $errorMessage = new WindErrorMessage(); - $this->testController->setErrorMessage($errorMessage); - try { - $this->testController->showMessage("shilong", "name", "a"); - } catch (WindActionException $e) { - $this->assertEquals(array("shilong", "a"), - array($e->getError()->getError("name"), $e->getError()->getErrorAction())); - return; - } - $this->fail("ShowMessage Test Error"); - } - - public function testTemplate() { - $forward = new WindForward(); - $windView = new WindView(); - $forward->setWindView($windView); - $this->testController->setForward($forward); - - $this->testController->setTemplate("LongController"); - $this->testController->setTemplateExt("php"); - $this->testController->setTemplatePath("/data"); - $this->testController->setTheme("style"); - $this->testController->setThemePackage('package'); - $this->testController->setLayout("layout1"); - - $this->assertEquals(array("LongController", "php", "/data", "layout1"), - array( - $windView->templateName, - $windView->templateExt, - $windView->templateDir, - $windView->layout)); - - } - - public function testResolveActionFilter() { - require_once 'data/Listener.php'; - Wind::application()->createApplication(); - $errorMessage = new WindErrorMessage("shi"); - $this->testController->setErrorMessage($errorMessage); - $forward = new WindForward(); - $forward->setAction("long"); - $this->testController->setForward($forward); - - $_GET['name'] = 'shilong'; - $this->testController->setGlobal('shilong', 'name'); - $forward->setVars('name', 'xxxxx'); - $_GET['wuq'] = 'wuq'; - - $this->testController->resolveActionFilter($this->dataForResolveActionFilter()); - $this->assertEquals("post_post_post_pre_pre_pre_shi", $errorMessage->getError(0)); - $this->assertEquals("post_post_post_pre_pre_pre_long", $forward->getAction()); - } - - public function dataForResolveActionFilter() { - $_GET['name'] = 'shilong'; - - return array( - array('class' => 'TEST:data.Listener', 'expression' => 'input:name==shilong'), - array('class' => 'TEST:data.Listener', 'expression' => 'g:name==shilong'), - array('class' => 'TEST:data.Listener', 'expression' => 'forward:name==xxx'), - array('class' => 'TEST:data.Listener', 'expression' => 'request:wuq==wuq')); - } - - /** - * @dataProvider dataForResolvedActionMethod - */ - public function testResolvedActionMethod($action) { - $router = new WindRouter(); - $router->setAction($action); - try { - $this->testController->doAction($router); - } catch (WindException $e) { - $this->assertEquals(WindException::ERROR_CLASS_METHOD_NOT_EXIST, $e->getCode()); - return; - } - $this->fail("ResolvedActionMethod Test Error"); - } - - public function dataForResolvedActionMethod() { - $args = array(); - $args[] = array('do'); - $args[] = array('privateMethod'); - return $args; - } - - - -} - - diff --git a/_tests/web/WindDispatcherTest.php b/_tests/web/WindDispatcherTest.php deleted file mode 100644 index 6d8bd7d9..00000000 --- a/_tests/web/WindDispatcherTest.php +++ /dev/null @@ -1,48 +0,0 @@ - - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package web - */ -class WindDispatcherTest extends BaseTestCase { - - /** - * Prepares the environment before running a test. - */ - protected function setUp() { - parent::setUp(); - require_once 'web\WindForward.php'; - } - - /** - * Tests WindDispatcher->dispatch() - */ - public function testDispatch() { - $_SERVER['SCRIPT_FILENAME'] = "index.php"; - $_SERVER['SCRIPT_NAME'] = 'index.php'; - $_SERVER['HTTP_HOST'] = 'localhost'; - $_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_FILENAME'] . '?c=long&a=noPrint'; - $front = Wind::application('long', - array( - 'web-apps' => array( - 'long' => array( - 'modules' => array( - 'default' => array( - 'controller-path' => 'data', - 'controller-suffix' => 'Controller', - 'error-handler' => 'TEST:data.ErrorControllerTest'))))))->run(); - - $forward = new WindForward(); - $forward->setIsReAction(true); - $forward->setAction('/long/test'); - ob_start(); - Wind::getApp()->doDispatch($forward); - $this->assertEquals(ob_get_clean(), 'LongController-test'); - } - -} - diff --git a/_tests/web/WindErrorHandlerTest.php b/_tests/web/WindErrorHandlerTest.php deleted file mode 100644 index b25a5789..00000000 --- a/_tests/web/WindErrorHandlerTest.php +++ /dev/null @@ -1,41 +0,0 @@ - - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package web - */ -class WindErrorHandlerTest extends BaseTestCase { - - public function testErrorHandler() { - $front = Wind::application("WindError", - array( - 'web-apps' => array( - 'WindError' => array( - 'modules' => array( - 'default' => array( - 'controller-path' => 'data', - 'controller-suffix' => 'Controller', - 'error-handler' => 'TEST:data.ErrorControllerTest', - 'compile-dir' => 'data')))))); - $_SERVER['SCRIPT_FILENAME'] = "index.php"; - $_SERVER['SCRIPT_NAME'] = 'index.php'; - $_SERVER['HTTP_HOST'] = 'localhost'; - $_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_FILENAME'] . '?a=shi&c=long'; - try { - $front->run(); - } catch (Exception $e) { - $this->assertEquals("error handled", $e->getMessage()); - return; - } - $this->fail("Error Handler Test Error"); - } - - protected function tearDown() { - parent::tearDown(); - } -} - diff --git a/_tests/web/WindForwardTest.php b/_tests/web/WindForwardTest.php deleted file mode 100644 index 96bebaf7..00000000 --- a/_tests/web/WindForwardTest.php +++ /dev/null @@ -1,116 +0,0 @@ - - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package web - */ -class WindForwardTest extends BaseTestCase { - - /** - * @var WindForward - */ - private $WindForward; - - /** - * Prepares the environment before running a test. - */ - protected function setUp() { - parent::setUp(); - require_once 'web\WindForward.php'; - require_once 'viewer\WindView.php'; - $this->WindForward = new WindForward(); - } - - /** - * Cleans up the environment after running a test. - */ - protected function tearDown() { - $this->WindForward = null; - parent::tearDown(); - } - - /** - * Tests WindForward->forwardAction() - * @dataProvider dataForForwardAction - */ - public function testForwardAction($action, $args, $isRedirect, $immediately) { - if ($immediately) { - try { - $this->WindForward->forwardAction($action, $args, $isRedirect, $immediately); - } catch (WindForwardException $e) { - $this->assertEquals(array($action, $args, $isRedirect, true), - array( - $e->getForward()->getAction(), - $e->getForward()->getArgs(), - $e->getForward()->getIsRedirect(), - $e->getForward()->getIsReAction())); - return; - } - $this->fail("ForwardAction Test Error!"); - } else { - $this->WindForward->forwardAction($action, $args, $isRedirect, $immediately); - $this->assertEquals(array($action, $args, $isRedirect, true), - array( - $this->WindForward->getAction(), - $this->WindForward->getArgs(), - $this->WindForward->getIsRedirect(), - $this->WindForward->getIsReAction())); - } - } - - public function dataForForwardAction() { - $args = array(); - $args[] = array("/default/long/shi", array('shi' => 'long'), true, false); - $args[] = array("/hello/long/shi", array(), false, true); - $args[] = array("/hello/shi/long", array(), true, true); - return $args; - } - - /** - * Tests WindForward->forwardRedirect() - */ - public function testForwardRedirect() { - try { - $this->WindForward->forwardRedirect("index.php"); - } catch (WindForwardException $e) { - $this->assertEquals(array("index.php", true), - array($e->getForward()->getUrl(), $e->getForward()->getIsRedirect())); - return; - } - $this->fail("ForwardRedirect Test Error!"); - } - - /** - * Tests WindForward->setVars() - * @dataProvider dataForSetVars - */ - public function testSetVars($vars, $key = '') { - $this->WindForward->setVars($vars, $key); - $this->assertEquals("long", $this->WindForward->getVars("shi")); - } - - public function dataForSetVars() { - $args = array(); - $object = new stdClass(); - $object->shi = 'long'; - $args[] = array($object); - $args[] = array(array('shi' => 'long')); - $args[] = array('long', 'shi'); - return $args; - } - - /** - * Tests WindForward->setWindView() - */ - public function testSetWindView() { - $windView = new WindView(); - $windView->setConfig(array('template-dir' => 'template/long', 'compile-dir' => 'compile/data')); - $this->WindForward->setWindView($windView); - $this->assertEquals($this->WindForward->getWindView(), $windView); - } -} - diff --git a/_tests/web/WindFrontControllerTest.php b/_tests/web/WindFrontControllerTest.php deleted file mode 100644 index 883e34bf..00000000 --- a/_tests/web/WindFrontControllerTest.php +++ /dev/null @@ -1,79 +0,0 @@ -WindFrontController = Wind::application("long", - array('web-apps' => array('long' => $this->appConfigData()))); - - } - - /** - * Cleans up the environment after running a test. - */ - protected function tearDown() { - $this->WindFrontController = null; - parent::tearDown(); - } - - /** - * Tests WindFrontController->registeComponent() - * - */ - public function testRegisteComponent() { - $httprequest = new WindHttpRequest(); - $httprequest->setAttribute(123, 'long'); - $httpresponse = new WindHttpResponse(); - $httpresponse->setData(123, 'long'); - $aaa = new stdClass(); - $aaa->long = 123; - $this->WindFrontController->registeComponent($aaa, 'aaa'); - $this->WindFrontController->registeComponent($httpresponse, 'response'); - $this->WindFrontController->registeComponent($httprequest, 'request'); - $this->WindFrontController->createApplication(); - $this->assertEquals(123, Wind::getApp()->getRequest()->getAttribute('long')); - $this->assertEquals(123, Wind::getApp()->getResponse()->getData('long')); - $this->assertEquals(123, Wind::getApp()->getComponent('aaa')->long); - } - - public function testCreateApplication() { - $this->assertEquals($this->WindFrontController->createApplication(), Wind::getApp()); - } - - public function testGetAppConfig() { - $config = $this->WindFrontController->getAppConfig('long'); - $this->assertArrayEquals($config, $this->appConfigData()); - } - - public function testGetApp() { - $this->assertEquals($this->WindFrontController->createApplication(), $this->WindFrontController->getApp()); - } - - public function testGetAppName() { - $this->WindFrontController->createApplication(); - $this->assertEquals($this->WindFrontController->getAppName(), 'default'); - } - - private function appConfigData() { - return array( - 'modules' => array( - 'default' => array( - 'controller-path' => 'data', - 'controller-suffix' => 'Controller', - 'error-handler' => 'TEST:data.ErrorControllerTest'))); - } -} - diff --git a/_tests/web/WindUrlHelperTest.php b/_tests/web/WindUrlHelperTest.php deleted file mode 100644 index d57da24e..00000000 --- a/_tests/web/WindUrlHelperTest.php +++ /dev/null @@ -1,46 +0,0 @@ - - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package web - */ -class WindUrlHelperTest extends BaseTestCase { - - /** - * Tests WindUrlHelper::resolveAction() - */ - public function testResolveAction() { - $this->assertEquals(array('action','controller','module','app',array('c' => 'c', 'b' => 'b')), - WindUrlHelper::resolveAction("app/module/controller/action?b=b",array('c' => 'c'))); - } - - /** - * Tests WindUrlHelper::createUrl() - */ - public function testCreateUrl() { - $this->provideApp(); - $this->assertEquals("http://localhost/index.php?b=b&m=module&c=controller&a=action", - WindUrlHelper::createUrl("/module/controller/action",array('b' => 'b'))); - } - - private function provideApp(){ - $_SERVER['SCRIPT_FILENAME'] = "index.php"; - $_SERVER['SCRIPT_NAME'] = 'index.php'; - $_SERVER['HTTP_HOST'] = 'localhost'; - $_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_FILENAME'] . '?c=long&a=noPrint'; - Wind::application("long", - array( - 'web-apps' => array( - 'long' => array( - 'modules' => array( - 'default' => array( - 'controller-path' => 'data', - 'controller-suffix' => 'Controller', - 'error-handler' => 'TEST:data.ErrorControllerTest'))))))->run(); - - } -} - diff --git a/_tests/web/WindWebApplicationTest.php b/_tests/web/WindWebApplicationTest.php deleted file mode 100644 index 38fb43ab..00000000 --- a/_tests/web/WindWebApplicationTest.php +++ /dev/null @@ -1,139 +0,0 @@ - - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package web - */ -class WindWebApplicationTest extends BaseTestCase { - - private $front; - - /** - * Prepares the environment before running a test. - */ - protected function setUp() { - parent::setUp(); - require_once 'web\WindWebApplication.php'; - require_once 'web\WindForward.php'; - require_once 'base\WindFactory.php'; - require_once 'data\ForWindFactoryTest.php'; - $this->front = Wind::application("long", - array( - 'web-apps' => array( - 'long' => array( - 'modules' => array( - 'default' => array( - 'controller-path' => 'data', - 'controller-suffix' => 'Controller', - 'error-handler' => 'TEST:data.ErrorControllerTest')))))); - } - - /** - * Cleans up the environment after running a test. - */ - protected function tearDown() { - parent::tearDown(); - } - - /** - * Tests WindWebApplication->run() - */ - public function testRun() { - $_SERVER['SCRIPT_FILENAME'] = "index.php"; - $_SERVER['SCRIPT_NAME'] = 'index.php'; - $_SERVER['HTTP_HOST'] = 'localhost'; - $_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_FILENAME'] . '?c=long'; - ob_start(); - $this->front->run(); - $this->assertEquals(ob_get_clean(), 'LongController-run'); - } - - public function testDoDispatch() { - $forward = new WindForward(); - $forward->setIsReAction(true); - $forward->setAction('/long/test'); - ob_start(); - $this->front->createApplication()->doDispatch($forward); - $this->assertEquals(ob_get_clean(), 'LongController-test'); - } - - public function testSetConfig() { - $this->front->createApplication()->setConfig(array('components' => array( - 'long' => array('path' => 'TEST:data.ForWindFactoryTest')))); - $this->assertEquals('ForWindFactoryTest', get_class(Wind::getApp()->getComponent('long'))); - $this->assertEquals(Wind::getApp()->getResponse()->getCharset(), 'utf-8'); - } - - /** - * Tests WindWebApplication->getGlobal() - * @dataProvider dataForGetGlobal - */ - public function testGetGlobal($data, $key = '') { - $this->front->createApplication()->setGlobal($data, $key); - $this->assertEquals("shilong", Wind::getApp()->getGlobal("name")); - } - - public function dataForGetGlobal() { - $args = array(); - $args[] = array('shilong', 'name'); - $object = new stdClass(); - $object->name = 'shilong'; - $args[] = array($object); - $args[] = array(array('name' => 'shilong')); - return $args; - } - - /** - * Tests WindWebApplication->setModules() - * @dataProvider dataForSetModules - */ - public function testSetModules($name, $config, $replace = false) { - $this->assertNotEquals($this->front->createApplication()->getModules($name), $config); - Wind::getApp()->setModules($name, $config, $replace); - $this->assertEquals(Wind::getApp()->getModules($name), $config); - } - - public function dataForSetModules() { - $args = array(); - $config = $this->getTestConfig(); - $args[] = array("xxx", array('name' => 'xxx') + $config, true); - $args[] = array("shilong", array('name' => 'shilong') + $config, true); - $args[] = array("wuq", array('name' => 'wuq') + $config, true); - return $args; - } - - /** - * Tests WindWebApplication->getComponent() - * getInstance在WindFactory已测试 - */ - public function testGetComponent() { - $this->assertTrue($this->front->createApplication()->getComponent("forward") instanceof WindForward); - } - - /** - * Tests WindWebApplication->getRequest() - */ - public function testGetRequest() { - $this->assertTrue($this->front->createApplication()->getRequest() instanceof WindHttpRequest); - } - - /** - * Tests WindWebApplication->getResponse() - */ - public function testGetResponse() { - $this->assertTrue($this->front->createApplication()->getResponse() instanceof WindHttpResponse); - } - - private function getTestConfig() { - return array( - 'controller-path' => 'data', - 'controller-suffix' => 'Controller', - 'error-handler' => 'shilong'); - } - -} - diff --git a/_tests/windTest.bat b/_tests/windTest.bat deleted file mode 100644 index a6f90284..00000000 --- a/_tests/windTest.bat +++ /dev/null @@ -1,2 +0,0 @@ -set TEST_DIR=%cd% -phpunit --bootstrap "%TEST_DIR%/bootstrap.php" %* \ No newline at end of file diff --git a/_tests/windTest.sh b/_tests/windTest.sh deleted file mode 100644 index 5b0d55c0..00000000 --- a/_tests/windTest.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/php - - */ - -require dirname(__FILE__) . '/bootstrap.php'; - -require_once 'PHPUnit/Util/Filter.php'; - -PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'PHPUNIT'); - -require 'PHPUnit/TextUI/Command.php'; - -define('PHPUnit_MAIN_METHOD', 'PHPUnit_TextUI_Command::main'); - -PHPUnit_TextUI_Command::main(); \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 00000000..3f0528d0 --- /dev/null +++ b/composer.json @@ -0,0 +1,44 @@ +{ + "name": "medz/windframework", + "type": "library", + "description": "A lightweight PHP open source framework.", + "keywords": ["medz", "php", "wind", "windframework", "framework"], + "homepage": "http://www.phpwind.com", + "license": "MIT", + "authors": [ + { + "name": "Seven Du", + "email": "shiweidu@outlook.com", + "homepage": "http://medz.cn" + }, + { + + "name": "phpwind", + "homepage": "http://www.phpwind.net", + "role": "Development company" + } + ], + "require": { + "php": ">=5.3", + "ext-curl": "*", + "ext-gd": "*", + "ext-iconv": "*", + "ext-json": "*", + "ext-mcrypt": "*", + "ext-zlib": "*", + "ext-zip": "*" + }, + "config": { + "preferred-install": "dist" + }, + "autoload": { + "classmap": [ + "wind/" + ] + }, + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + } +} \ No newline at end of file diff --git a/demos/blog/.tpl b/demos/blog/.tpl deleted file mode 100644 index 59ff4d3c..00000000 --- a/demos/blog/.tpl +++ /dev/null @@ -1,72 +0,0 @@ - - - - -首页 - - - - -
- -
-
-
-
- -
Hi, getUsername());?> 欢迎您!
- - -
用户登录
-
-
-
姓名*
-
-
-
-
密码*
-
-
- - -
- -
-
-
-
- -
- - \ No newline at end of file diff --git a/demos/blog/conf/config.php b/demos/blog/conf/config.php deleted file mode 100644 index 848d10c9..00000000 --- a/demos/blog/conf/config.php +++ /dev/null @@ -1,41 +0,0 @@ - array( - 'db' => array( - 'config' => array( - 'resource' => 'conf.db_config.php', - ) - ) - ), - //应用配置,支持多个应用配置。一个应用支持多个modules(业务模块),每个modules都有一个别名用于访问。 - //当不输入任何modules时访问‘default’默认模块 - 'web-apps' => array( - 'blog' => array( - 'modules' => array( - 'default' => array( - //应用控制器访问路径定义,当前定义的路径是当前应用根目录下的‘controller/’ - 'controller-path' => 'controller', - //应用控制器后缀定义 - 'controller-suffix' => 'Controller', - //模板目录定义 - 'template-path' => 'template', - //编译文件目录定义 - 'compile-path' => 'data.compile', - //错误处理句柄定义 - 'error-handler' => 'controller.ErrorController', - ) - ), - //过滤器配置,在这里部署了一个form表单过滤器 - 'filters' => array( - 'user' => array( - 'class' => 'WIND:web.filter.WindFormFilter', - 'pattern' => 'default/Index/(login|dreg)', - 'form' => 'service.UserForm' - ) - ) - ) - ) -); diff --git a/demos/blog/conf/db_config.php b/demos/blog/conf/db_config.php deleted file mode 100644 index ce429f3c..00000000 --- a/demos/blog/conf/db_config.php +++ /dev/null @@ -1,7 +0,0 @@ - 'mysql:host=localhost;dbname=test', - 'user' => 'root', - 'pwd' => 'phpwind.net', - 'charset' => 'utf8'); \ No newline at end of file diff --git a/demos/blog/conf/user.sql b/demos/blog/conf/user.sql deleted file mode 100644 index 9f30120f..00000000 --- a/demos/blog/conf/user.sql +++ /dev/null @@ -1,13 +0,0 @@ ---Table name: user 用户表 ---Field: userid 用户id ---Field: username 用户名 ---Field: password 密码 ---Primary key userid - -DROP TABLE IF EXISTS `user`; -CREATE TABLE `user` ( - `userid` int(10) unsigned NOT NULL AUTO_INCREMENT, - `username` varchar(50) NOT NULL DEFAULT '', - `password` varchar(50) NOT NULL DEFAULT '', - PRIMARY KEY (`userid`) - ) ENGINE=MyISAM; \ No newline at end of file diff --git a/demos/blog/controller/ErrorController.php b/demos/blog/controller/ErrorController.php deleted file mode 100644 index 8a37de1a..00000000 --- a/demos/blog/controller/ErrorController.php +++ /dev/null @@ -1,27 +0,0 @@ - - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package wind - */ -class ErrorController extends WindErrorHandler { - - /** - * (non-PHPdoc) - * @see WindErrorHandler::run() - */ - public function run() { - $this->setLayout('layout'); - $this->setGlobal($this->getRequest()->getBaseUrl(true) . '/template/images', 'images'); - $this->setGlobal($this->getRequest()->getBaseUrl(true) . '/template/images', 'css'); - $topic = "Blog Error"; - $this->setOutput($topic, "errorHeader"); - $this->setOutput($this->urlReferer, "baseUrl"); - $this->setOutput($this->error, "errors"); - $this->setTemplate('error'); - } -} \ No newline at end of file diff --git a/demos/blog/controller/IndexController.php b/demos/blog/controller/IndexController.php deleted file mode 100644 index bb2b1185..00000000 --- a/demos/blog/controller/IndexController.php +++ /dev/null @@ -1,83 +0,0 @@ - - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package demos.blog.controller - */ -class IndexController extends WindController { - - /* (non-PHPdoc) - * @see WindSimpleController::beforeAction() - */ - public function beforeAction($handlerAdapter) { - parent::beforeAction($handlerAdapter); - $this->setLayout('layout'); - $this->setOutput('utf8', 'charset'); - $this->setGlobal($this->getRequest()->getBaseUrl(true) . '/template/images', 'images'); - $this->setGlobal($this->getRequest()->getBaseUrl(true) . '/template/images', 'css'); - } - - /* (non-PHPdoc) - * @see WindController::run() - */ - public function run() { - Wind::import('service.UserForm'); - $userService = $this->load(); - $userInfo = $userService->isLogin(); - $this->setOutput($userInfo, 'userInfo'); - $this->setTemplate('index'); - } - - /** - * 访问用户注册页面 - */ - public function regAction() { - $this->setTemplate('reg'); - } - - /** - * 用户登录 - */ - public function loginAction() { - $userService = $this->load(); - $userInfo = $userService->isLogin(); - if ($userInfo) $this->showMessage('已登录~'); - - /* @var $userForm UserForm */ - $userForm = $this->getInput("userForm"); - if (!$userForm) $this->showMessage('获取用户登录数据失败'); - - if (!$userService->login($userForm)) $this->showMessage('登录失败.'); - $this->forwardRedirect(WindUrlHelper::createUrl('run')); - } - - /** - * 处理用户注册表单 - */ - public function dregAction() { - $userService = $this->load(); - $userForm = $this->getInput("userForm"); - if (!$userService->register($userForm)) $this->showMessage('注册失败.'); - $this->setOutput($userForm, 'userInfo'); - $this->setTemplate('reg'); - } - - /** - * 用户退出 - */ - public function logoutAction() { - $this->load()->logout(); - $this->forwardRedirect(WindUrlHelper::createUrl('run')); - } - - /** - * @return UserService - */ - private function load() { - return Wind::getApp()->getWindFactory()->createInstance(Wind::import('service.UserService')); - } -} \ No newline at end of file diff --git a/demos/blog/index.php b/demos/blog/index.php deleted file mode 100644 index db46cc83..00000000 --- a/demos/blog/index.php +++ /dev/null @@ -1,6 +0,0 @@ -run(); - diff --git a/demos/blog/service/UserForm.php b/demos/blog/service/UserForm.php deleted file mode 100644 index 98f45f48..00000000 --- a/demos/blog/service/UserForm.php +++ /dev/null @@ -1,53 +0,0 @@ - - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package wind - */ -class UserForm extends WindEnableValidateModule { - - private $username; - private $password; - - /** - * @return string 返回用户名 - */ - public function getUsername() { - return $this->username; - } - - /** - * @return string 返回用户密码 - */ - public function getPassword() { - return $this->password; - } - - /** - * @param string $username - */ - public function setUsername($username) { - $this->username = $username; - } - - /** - * @param string $password - */ - public function setPassword($password) { - $this->password = $password ? md5($password) : $password; - } - - /* (non-PHPdoc) - * @see WindEnableValidateModule::validateRules() - */ - public function validateRules() { - return array( - WindUtility::buildValidateRule("username", "isRequired"), - WindUtility::buildValidateRule("password", "isRequired")); - } - -} \ No newline at end of file diff --git a/demos/blog/service/UserService.php b/demos/blog/service/UserService.php deleted file mode 100644 index cc8a3bc8..00000000 --- a/demos/blog/service/UserService.php +++ /dev/null @@ -1,77 +0,0 @@ - 2012-3-15 - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package demos - * @subpackage blog.service - */ -class UserService { - protected $cookieName = 'blogloginUser'; - - /** - * 判断用户是否登录 - * - * @return boolean|UserForm - */ - public function isLogin() { - /* @var $user UserForm */ - $user = WindCookie::get($this->cookieName); - if (!$user) return false; - $stmt = $this->_getConnecion()->createStatement('SELECT * FROM user WHERE username=:username'); - if (!$stmt->getValue(array('username' => $user->getUsername()))) return false; - - return $user; - } - - /** - * 用户退出 - * - * @return boolean - */ - public function logout() { - return WindCookie::set($this->cookieName, '', -1); - } - - /** - * 用户登录服务 - * - * @param UserForm $userInfo - * @return boolean - */ - public function login($userInfo) { - $db = $this->_getConnecion(); - $stmt = $db->createStatement('SELECT * FROM user WHERE username=:username AND password =:password'); - if (!$stmt->getValue(array('username' => $userInfo->getUsername(), 'password' => $userInfo->getPassword()))) { - return false; - } - return WindCookie::set($this->cookieName, $userInfo); - } - - /** - * 用户注册服务 - * - *@param UserForm $userInfo - *@return boolean - */ - public function register($userInfo) { - $db = $this->_getConnecion(); - $stmt = $db->createStatement('SELECT * FROM user WHERE username=:username'); - if ($stmt->getOne(array(':username' => $userInfo->getUsername()))) $this->showMessage('该用户已经注册.'); - return $db->execute( - "INSERT INTO user SET " . $db->sqlSingle( - array('username' => $userInfo->getUsername(), 'password' => $userInfo->getPassword()))); - } - - /** - * @return WindConnection - */ - private function _getConnecion() { - return Wind::getApp()->getWindFactory()->getInstance('db'); - } - -} - -?> \ No newline at end of file diff --git a/demos/blog/template/error.htm b/demos/blog/template/error.htm deleted file mode 100644 index 8abc46dc..00000000 --- a/demos/blog/template/error.htm +++ /dev/null @@ -1,21 +0,0 @@ -
-
-
-
    - -
  1. {$error}
  2. - -
-
- -

You Can Get Help In:

-

getConfig('siteInfo', '', "http://www.windframework.com/") . ")" ; ?>

- -
-
-
\ No newline at end of file diff --git a/demos/blog/template/images/bg.png b/demos/blog/template/images/bg.png deleted file mode 100755 index cfbab345..00000000 Binary files a/demos/blog/template/images/bg.png and /dev/null differ diff --git a/demos/blog/template/images/down.png b/demos/blog/template/images/down.png deleted file mode 100755 index 9b3aee5c..00000000 Binary files a/demos/blog/template/images/down.png and /dev/null differ diff --git a/demos/blog/template/images/head.png b/demos/blog/template/images/head.png deleted file mode 100755 index 1d89a729..00000000 Binary files a/demos/blog/template/images/head.png and /dev/null differ diff --git a/demos/blog/template/images/hr.png b/demos/blog/template/images/hr.png deleted file mode 100755 index fb200d3c..00000000 Binary files a/demos/blog/template/images/hr.png and /dev/null differ diff --git a/demos/blog/template/images/logo.png b/demos/blog/template/images/logo.png deleted file mode 100644 index 319865cf..00000000 Binary files a/demos/blog/template/images/logo.png and /dev/null differ diff --git a/demos/blog/template/images/num.png b/demos/blog/template/images/num.png deleted file mode 100755 index 82fa18b1..00000000 Binary files a/demos/blog/template/images/num.png and /dev/null differ diff --git a/demos/blog/template/images/style.css b/demos/blog/template/images/style.css deleted file mode 100755 index 7960f719..00000000 --- a/demos/blog/template/images/style.css +++ /dev/null @@ -1,447 +0,0 @@ -@charset "utf-8"; -/* -=================== -@copyright: Copyright 2012,phpwind.com -@author: yanchixia@aliyun-inc.com -=================== -*/ -/* -=================== -初始化【请勿修改】 -=================== -*/ -html,body, -div, dl, dt, dd, ul, p, th, td, -h1, h2, h3, h4, h5, h6, -pre, code, form, -fieldset, legend{ - margin: 0; - padding: 0; -} -cite, -em, -strong, -th { - font-style: normal; -} -td, -th, -div { - word-break:break-all; - word-wrap:break-word; -} -table { - border-collapse: collapse; - border-spacing:0; -} -th { - text-align: left; - font-weight:100; -} -ol li { - list-style: decimal outside; -} -ol{ - padding:0 0 0 18px; - margin:0; -} -li { - list-style:none; -} -img { - border: 0; -} -html { - -webkit-text-size-adjust:none; -} - -/* -=================== -清除浮动【请勿修改】 ->> cc 作用于父模型 ->> c 作用于浮动模型后,父模型区域里 -=================== -*/ -.cc{ - zoom:1; -} -.cc:after{ - content:'\20'; - display:block; - height:0; - clear:both; - visibility: hidden; -} - -/* -=================== -结构 -=================== -*/ -html{ - overflow-y:scroll; -} -body{ - background:url(bg.png); - font:14px/1.5 Arial "Microsoft Yahei"; -} -.head_wrap{ - background:url(head.png); - height:90px; -} -.main_wrap{ - border-top:1px solid #ffffff; - min-height:600px; -} -.head, -.main{ - width:800px; - margin:0 auto; -} -.main{ - padding:20px 0; -} -a{ - color:#3a7cbb; - text-decoration:none; -} -a:hover{ - text-decoration:underline; -} - -/* -=================== -logo -=================== -*/ -.logo{ - float:left; - margin:25px 0 0 0; -} - -/* -=================== -导航 -=================== -*/ -.nav{ - float:right; - padding-top:42px; -} -.nav li{ - float:left; - margin-left:30px; - padding:15px 0; - position:relative; -} -.nav li a{ - color:#fff; - font-size:14px; - font-weight:700; - text-decoration:none; -} -.nav li.current em{ - position:absolute; - width:0; - height:0; - padding:0; - bottom:0; - left:50%; - margin-left:-8px; - border-bottom:8px #fff solid; - border-top:8px transparent dashed; - border-right:8px transparent dashed; - border-left:8px transparent dashed; - overflow:hidden; -} - -/* -=================== -底部 -=================== -*/ -.footer_wrap{ - background:#000; - padding:5px; - color:#999; - text-align:center; - font-size:12px; -} - -/* -=================== -通用标题 -=================== -*/ -.h{ - font-size:16px; - font-weight:400; - padding:10px 0; - background:url(hr.png) 0 bottom repeat-x; -} - -/* -=================== -首页框架简介 -=================== -*/ -.home_info{ - padding:15px 0; - font-size:14px; - color:#666; - line-height:1.8; -} - -/* -=================== -下载 -=================== -*/ -.home_down{ - padding:15px 0; - color:#666; -} -.home_down .downlink{ - height:56px; - margin-bottom:15px; -} -.home_down .other{ - padding-bottom:10px; -} -.home_down .other a{ - margin-right:20px; -} - -/* -=================== -下载按钮 -=================== -*/ -.zip_down, -.tar_down{ - float:left; - height:56px; - width:211px; - overflow:hidden; - text-indent:-2000em; - background:url(down.png) no-repeat; - margin-right:20px; -} -.zip_down:hover{ - background-position:0 -56px; -} -.tar_down{ - background-position:0 -112px; -} -.tar_down:hover{ - background-position:0 -168px; -} - -/* -=================== -优点 -=================== -*/ -.home_actor{ - padding:15px 0; -} -.home_actor li{ - float:left; - width:49.8%; - height:120px; - padding:15px 0 0; - font-size:16px; - color:#666; -} -.home_actor li span{ - overflow:hidden; - float:left; - width:280px; -} -.home_actor li:hover span{ - color:#115cb7; -} -.home_actor li p{ - float:left; - width:300px; - font-size:12px; - color:#999; -} -.home_actor li:hover p{ - color:#333; -} -.home_actor li em{ - width:30px; - height:30px; - float:left; - margin-right:15px; - background:url(num.png) no-repeat; - text-indent:-2000em; - overflow:hidden; -} -.home_actor li em.num_1{ - background-position:0 0; -} -.home_actor li em.num_2{ - background-position:-30px 0; -} -.home_actor li em.num_3{ - background-position:-60px 0; -} -.home_actor li em.num_4{ - background-position:-90px 0; -} -.home_actor li em.num_5{ - background-position:-120px 0; -} -.home_actor li em.num_6{ - background-position:-150px 0; -} -.home_actor li em.num_7{ - background-position:-180px 0; -} -.home_actor li em.num_8{ - background-position:-210px 0; -} -.home_actor li em.num_9{ - background-position:-240px 0; -} -.home_actor li em.num_10{ - background-position:-270px 0; -} -.home_actor li em.num_11{ - background-position:-300px 0; -} -.home_actor li em.num_12{ - background-position:-330px 0; -} -.home_actor li em.num_13{ - background-position:-360px 0; -} -.home_actor li em.num_14{ - background-position:-390px 0; -} -.home_actor li em.num_15{ - background-position:-420px 0; -} -.home_actor li em.num_16{ - background-position:-450px 0; -} -.home_actor li em.num_17{ - background-position:-480px 0; -} -.home_actor li:hover{ - color:#333; -} - -/* -=================== -项目背景 -=================== -*/ -.project_bg{ - padding:20px 0; - color:#444; -} -.project_bg p{ - padding:0 0 20px; - line-height:1.8; - text-indent:2em; -} - -/* -=================== -框架介绍 -=================== -*/ -.framework_info{ - padding:0; - color:#444; -} -.framework_info h3{ - padding-top:20px; - font-size:16px; - margin-bottom:10px; - color:#074179; -} -.framework_info h4{ - font-size:14px; - margin-bottom:10px; - color:#5183b2; -} -.framework_info p{ - padding:0 0 20px; - line-height:1.8; - text-indent:2em; -} -.framework_info .thumb{ - padding:10px; - background:#fff; - border:1px solid #e4e4e4; - text-align:center; - margin-bottom:10px; - overflow:hidden; -} -.framework_info .thumb p{ - padding:10px 0 0; -} -.framework_info ol{ - margin-left:3em; - margin-bottom:20px; -} - -.code{ - border:1px solid #e4e4e4; - min-height:200px; - margin-bottom:20px; - background:#fff; -} - - - - - - - -.login{ - padding:50px 20px; -} -.login dd{ - padding:5px 0 20px; -} -.login .input{ - padding:4px 4px; - font-size:100%; - line-height:18px; - border:1px solid #ccc; - background-color:#fff; - box-shadow:2px 2px 2px #f0f0f0 inset; - vertical-align: middle; - margin: 0; - font-family: inherit; - color:#333; - width:200px; -} -.input:focus{ - outline:1px solid #99d8f5; - border-color:#99d8f5; -} -.login button{ - overflow:visible; - padding:0 0px; - cursor:pointer; - height:30px; - text-align:center; - width:80px; -} - - - - - - - - - - - diff --git a/demos/blog/template/index.htm b/demos/blog/template/index.htm deleted file mode 100644 index a006e1b4..00000000 --- a/demos/blog/template/index.htm +++ /dev/null @@ -1,23 +0,0 @@ - - -
Hi, {$userInfo->getUsername()} 欢迎您!
-
››退出
- -

用户登录

-
- -
- diff --git a/demos/blog/template/layout.htm b/demos/blog/template/layout.htm deleted file mode 100644 index 7c01dd66..00000000 --- a/demos/blog/template/layout.htm +++ /dev/null @@ -1,32 +0,0 @@ - - - - -首页 - - - -
-
- - -
-
-
-
- -
-
- - - \ No newline at end of file diff --git a/demos/blog/template/reg.htm b/demos/blog/template/reg.htm deleted file mode 100644 index b9f3059d..00000000 --- a/demos/blog/template/reg.htm +++ /dev/null @@ -1,23 +0,0 @@ - - -
恭喜您,注册成功!
-
››返回登录
- -

用户注册

-
- -
- diff --git a/demos/helloworld/controller/IndexController.php b/demos/helloworld/controller/IndexController.php deleted file mode 100644 index cb01bdc8..00000000 --- a/demos/helloworld/controller/IndexController.php +++ /dev/null @@ -1,15 +0,0 @@ - - * @author Qiong Wu - * @version $Id$ - * @package - */ -class IndexController extends WindController { - - public function run() { - echo 'hello world!'; - } - -} -?> \ No newline at end of file diff --git a/demos/helloworld/index.php b/demos/helloworld/index.php deleted file mode 100644 index 9fae882c..00000000 --- a/demos/helloworld/index.php +++ /dev/null @@ -1,6 +0,0 @@ -run(); - diff --git a/docs/config/cache_config.xml b/docs/config/cache_config.xml deleted file mode 100644 index 9a122031..00000000 --- a/docs/config/cache_config.xml +++ /dev/null @@ -1,149 +0,0 @@ - - - - - - 0 - - - - - - pw_cache - - key - - value - - expire - - - - - - - 0 - - - - - - - WIND:_compile - - php - - 0 - - - - - - - - 0 - - - - - - - 0 - - - - - 127.0.0.1 - - 11211 - - true - - 1 - - 1 - - 15 - - true - - - - - 127.0.0.1 - 11212 - - - - - - - - - - 0 - - - - - - - - - - - - 127.0.0.1 - - 11211 - - true - - 1 - - - - - 127.0.0.1 - 11212 - - - - - - - - - - - 0 - - - - - - - - - - \ No newline at end of file diff --git a/docs/config/components_config.xml b/docs/config/components_config.xml deleted file mode 100644 index f14df1b8..00000000 --- a/docs/config/components_config.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - DATA:caches - php - 0 - - - diff --git a/docs/config/db_config.xml b/docs/config/db_config.xml deleted file mode 100644 index 3cf76631..00000000 --- a/docs/config/db_config.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - mysql:host=localhost;dbname=test;port=3306 - - root - - root - - utf8 - - pw_ - - - - - - - - - - - - - mysql:host=localhost;dbname=test - root - root - utf8 - pw_ - - - mysql:host=192.168.1.12;dbname=test;port=3305 - test - test - utf8 - pw_ - - - diff --git a/docs/config/ini/cache_config.ini b/docs/config/ini/cache_config.ini deleted file mode 100644 index c0a4e352..00000000 --- a/docs/config/ini/cache_config.ini +++ /dev/null @@ -1,110 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;;;;;;db缓存配置格式:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;数据库缓存的配置信息 -;;缓存文件的过期时间 -expires=0 -;;缓存key的前缀 -key-prefix='' -;;缓存key安全盐码 -security-code='' -;;缓存的表名 -table-name=pw_cache -;;缓存的key字段名称 -field-key=key -;; 缓存的value字段名称 -field-value=value -;;缓存的过期时间字段名称 -field-expire=expire - - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;;;;;;File缓存配置格式:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;文件缓存配置 -;;缓存文件的过期时间 -expires=0 -;;缓存key的前缀 -key-prefix='' -;;缓存key安全盐码 -security-code='' - -;;缓存文件的保存路径(支持命名空间的方式配置该路径 -dir=WIND:_compile -;;缓存文件的后缀 -suffix=php -;;缓存的目录支持级别 -dir-level=0 - - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;;;;;Memcache缓存配置格式:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;memcache配置: -;;memcache的配置和memecached的配置格式一样,但是compress配置将不会对memcached起作用,同样的主机配置只有host,port和weight会被用到 -;;详细看各自的支持 - -;;缓存文件的过期时间 -expires=0 -;;缓存key的前缀 -key-prefix='' -;;缓存key安全盐码 -security-code='' - -;;压缩的级次 -compress=0 -;;memcache服务器相关配置 可以配置多个 -[servers] -;;例如配置test1和test2两台主机 -test1.host=127.0.0.1 ;memcache主机ip -test1.port=11211 ;memcache端口 -test1.weight=1 ;为此服务器创建的桶的数量,用来控制此服务器被选中的权重 -test1.pconn='true' ;是否使用长连 -test1.timeout=1 ;连接持续(超时)时间(单位秒) -test1.retry=15 ;服务器连接失败时重试的间隔时间 -test1.status='true' ;控制此服务器是否可以被标记为在线状态 -test1.fcallback='' ;允许用户指定一个运行时发生错误后的回调函数 -test2.host=127.0.0.1 ;memcache主机ip -test2.port=11212 ;memcache端口 -test2.weight=1 ;为此服务器创建的桶的数量,用来控制此服务器被选中的权重 - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;;;;;redis缓存配置格式:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;redis配置: - -;;缓存文件的过期时间 -expires=0 -;;缓存key的前缀 -key-prefix='' -;;缓存key安全盐码 -security-code='' - -;;验证信息 -auth='' -;;redis服务器相关配置 可以配置多个 -[servers] -;;例如配置test1和test2两台主机 -test1.host=127.0.0.1 ;memcache主机ip -test1.port=6379 ;memcache端口 -test1.pconn='true' ;是否使用长连 -test1.timeout=1 ;连接持续(超时)时间(单位秒) -persistent_id='' ;如果是长链接,则会存在一个长链接的ID号 -test2.host=127.0.0.1 ;redis主机ip -test2.port=11212 ;redis端口 -test2.weight=1 ;为此服务器创建的桶的数量,用来控制此服务器被选中的权重 - - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;;;;;;xcache缓存配置格式:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;文件缓存配置 -;;缓存文件的过期时间 -expires=0 -;;缓存key的前缀 -key-prefix='' -;;缓存key安全盐码 -security-code='' - -;;验证用户名 -user='' -;;验证用户密码 -pwd='' diff --git a/docs/config/ini/db_config.ini b/docs/config/ini/db_config.ini deleted file mode 100644 index 41fa1817..00000000 --- a/docs/config/ini/db_config.ini +++ /dev/null @@ -1,37 +0,0 @@ -;db的配置也支持两种格式 -;;一种是单链接,只能配置一个链接 -;;一种是有连接池能力的多链接配置,同时支持读写分离和主从配置的能力 - -;第一种:单链接模式 -;WIND:db.WindConnection 配置格式,适合单链接应用,同时不支持连接池 -;;链接的DSN,方式:类型:name=value; 链接类型mysql host为localhost,链接的数据库名字为test, 链接端口为3306 -dsn='mysql:host=localhost;dbname=test' -;;链接数据库的用户名 -user=root -;;链接数据库的密码 -pwd=root -;;存取数据库的链接字符集 -charset=utf8 -;;表前缀,需要“{}”符号,将表名进行标识,才能进行正确替换 -tablePrefix=pw_ - - - -;第二种:多链接支持 -;WIND:db.WindConnectionManager 配置格式 ,支持链接池,允许配置多个链接 -[connections] -;;except: 配置多链接的分配规则 -;;每组规则将会以;号分割,*为通配符,:号则表示规则中的表名和链接分割 -;;比如如下: 所有的表名都将走db1链接,user开头的表和tablename2表将会走主db1 从db2的策略 -except='*:(db1);user*,tablename2:(db1|db2);' -;;各个链接的配置,配置格式如单个链接的配置 -db1.dsn='mysql:host=localhost;dbname=test' -db1.user=root -db1.pwd=root -db1.charset=utf8 -db1.tablePrefix=pw_ -db2.dsn='mysql:host=192.168.1.12;dbname=test;port=3305' -db2.user=test -db2.pwd=test -db2.charset=utf8 -db2.tablePrefix=pw_ \ No newline at end of file diff --git a/docs/config/ini/router_config.ini b/docs/config/ini/router_config.ini deleted file mode 100644 index ecbba3f4..00000000 --- a/docs/config/ini/router_config.ini +++ /dev/null @@ -1,36 +0,0 @@ -;路由规则配置 -;MVC 配置,url-param:配置访问的别名,default-value:配置缺省值 -;当开启多应用时候,路由组件指向WindMultiAppRouter时候,可配置路径中app的规则 -[app] -url-param=p -default-value=default -[module] -url-param=m -default-value=default -[controller] -url-param=c -default-value=index -[action] -url-param=a -default-value=run - -;路由规则配置 -;用户可以轻易的实现自己的额route,继承AbstractWindRoute,同时配置到routes下即可,所有的route下的规则根据自己的实现进行更改调整config -[routes] -;每个路由有唯一的一个名字,以下是框架提供的一个路由的规则配置 -;;比例如 配置框架提供的路由规则 -;;路由的实现 -WindRoute.class=WIND:router.route.WindRewriteRoute -;;路由的正则匹配 -WindRoute.pattern=^http[s]?:\/\/[^\/]+(\/\w+)?(\/\w+)?(\/\w+)?.*$ -;;参数匹配设置,针对正则中的每个匹配项 -;;;参数的名字:a, map:匹配上述正则中的子匹配的位置, default:缺省的值 -;;参数匹配:针对MVC的参数名字,需要注意和MVC配置中的别名一一对应,否则不能正确进行路由 -WindRoute.params.a.map=3 -WindRoute.params.a.default=run -WindRoute.params.c.map=2 -WindRoute.params.m.map=1 -;;普通参数的链接分隔符,支持两个字符的配置,第一个字符为参数之间的配置,第二个字符为参数key-value之间的分隔符,默认为&= -WindRoute.separator='&=' -;;build的格式,将会依次根据params中配置的map的顺序依次替换%s占位符,普通变量将会跟在其之后 -WindRoute.reverse='/%s' \ No newline at end of file diff --git a/docs/config/ini/view_config.ini b/docs/config/ini/view_config.ini deleted file mode 100644 index 5fba5d04..00000000 --- a/docs/config/ini/view_config.ini +++ /dev/null @@ -1,34 +0,0 @@ -;试图组件的配置有两部分: -;;一部分是试图组件的基本配置,包括模板路径编译路径及编译控制等 -;;第二部分是模板编译标签的配置,用户可以配置自己定义的编译解析规则 - - -;第一部分:试图组件的配置 -;;模板目录 -template-dir=template -;;指定模板后缀 -template-ext=htm -;;模板编译文件存放路径 -compile-dir=data.template -;;是否编译:如果为0则不编译模板,直接读取已经编译好的模板编译文件,如果为1则编译模板 -is-compile=0 -;;编译模板的后缀配置 -compile-ext=tpl -;;布局文件配置 -layout='' -;;主题包位置 -theme-package='' -;;是否开启对输出模板变量进行过滤 -htmlspecialchars='true' - - - -;第二部分:模板自定义标签配置 -[support-tags] -;比如配置:标签tag1 -;;标签定义 -;tag1.tag='' -;;标签匹配表达式 -;tag1.pattern='' -;;标签的解析类文件 -;tag1.compiler='' \ No newline at end of file diff --git a/docs/config/ini/wind_config.ini b/docs/config/ini/wind_config.ini deleted file mode 100644 index ceaa4532..00000000 --- a/docs/config/ini/wind_config.ini +++ /dev/null @@ -1,74 +0,0 @@ -;站点是否关闭设置 -isclose=1 - -;站点关闭后转向的模板路径 -isclose-tpl=TEST:template.closed.htm - -;组件的配置 -;组件个性配置,一下的组件配置将会替换掉compontents_config下的对应的组件的配置,同时这里也可以增加自己的组件 -[components] -;;比如配置一个db组件 -;;db相关配置,如果设置了resource则系统会默认找到resource指向的文件作为db配置信息.DB的配置config内容参照DOCS下的db_config配置 -db.config.resource=db_config.php -;;比如配置一个router组件 -;当开启多应用时候,路由组件需指向WindMultiAppRouter -router.path=WIND:router.WindMultiAppRouter -;;router组件主要允许用户配置module/controller/action的访问别名及各自缺省值,同时允许设置urlWrite规则 -;当开启多应用时候,可配置路径中app的规则 -router.config.app.url-param=p -router.config.app.default-value=default -router.config.module.url-param=m -router.config.module.default-value=default -router.config.controller.url-param=c -router.config.controller.default-value=index -router.config.action.url-param=a -router.config.action.default-value=run -;;以下为url路由规则的配置 -router.config.routes.WindRoute.class=WIND:router.route.WindRewriteRoute -router.config.routes.WindRoute.pattern=^http[s]?:\/\/[^\/]+(\/\w+)?(\/\w+)?(\/\w+)?.*$ -router.config.routes.WindRoute.params.a.map=3 -router.config.routes.WindRoute.params.a.default=run -router.config.routes.WindRoute.params.c.map=2 -router.config.routes.WindRoute.params.m.map=1 - -;应用配置 -[web-apps] -;default应用的配置 -;应用的实现组件 -default.class=windWebApp - -;default应用的编码 -default.charset=utf-8 - - - -;iscache属性控制windCache组件是否可用,如果关闭则windCache组件将不可用,通过Wind::getApp()->getComponent('windCache'); -default.iscache=1 - -;过滤链配置,可以配置通用的,同时也可以配置Module级别的,controller级别的,action级别的; class: 配置过滤链的实现 -;过滤器配置 -;name: 过滤器的名字:唯一 -;class: 过滤器的实现: -;pattern:*:则所有的请求都将会应用该过滤器 -; module/*: 则所有module模块的请求都将会应用该过滤器 -; module/index/*: 则module模块下的indexController下的所有Action请求都将会应用该过滤器 -; module/index/add: 则module模块下的indexController下的addAction将会应用该过滤器 -;form: 使用框架提供的formFilter的时候配置给该filter指明需要使用的form -;其他配置项:将会传递给配置的filter相同配置项的属性 -default.filters.formfilter.class=WIND:web.filter.WindFormFilter -default.filters.formfilter.pattern=* -default.filters.formfilter.form=Myform - - -;模块配置: -;;如下配置一个名为default的模块: -;;controller-path: 模块的路径(采用命名空间的方式) -default.modules.default.controller-path=controller -;controller-suffix: 模块的controller后缀信息 -default.modules.default.controller-suffix=Controller -;error-handler: 模块的错误处理类 -default.modules.default.error-handler=WIND:web.WindErrorHandler -;template-dir: 模块的模板目录,支持命名空间的方式如DEFAULT:template -default.modules.default.template-dir=template -;compile-dir: 模块的模板编译文件保存的目录,支持命名空间的方式如DEFAULT:compile.template -default.modules.default.compile-dir=data.template \ No newline at end of file diff --git a/docs/config/php/cache_config.php b/docs/config/php/cache_config.php deleted file mode 100644 index 29878a99..00000000 --- a/docs/config/php/cache_config.php +++ /dev/null @@ -1,117 +0,0 @@ - 2010-11-2 - * @link http://www.phpwind.com - * @copyright Copyright © 2003-2010 phpwind.com - * @license - */ -################################################################### -#######db缓存配置格式:############################################ -return array( - //缓存的过期时间 - 'expires' => '0', - //缓存key的前缀 - 'key-prefix' => '', - //缓存key安全盐码 - 'security-code' => '', - //缓存的表名 - 'table-name' => 'pw_cache', - //缓存的key字段名称 - 'field-key' => 'key', - //缓存的value字段名称 - 'field-value' => 'value', - //缓存的过期时间字段名称 - 'field-expire' => 'expire', - ); - - - -################################################################### -#######File缓存配置格式:############################################ -return array( - //缓存的过期时间 - 'expires' => '0', - //缓存key的前缀 - 'key-prefix' => '', - //缓存key安全盐码 - 'security-code' => '', - //缓存文件的保存路径(支持命名空间的方式配置该路径) - 'dir' => 'WIND:_compile', - //缓存文件的后缀 - 'suffix' => 'php', - //缓存的目录支持级别 - 'dir-level' => '0', -); - - - -################################################################### -######Memcache缓存配置格式:############################################ -return array( - //缓存的过期时间 - 'expires' => '0', - //缓存key的前缀 - 'key-prefix' => '', - //缓存key安全盐码 - 'security-code' => '', - /*压缩的级次*/ - 'compress' => '0', - /*memcache服务器相关配置 可以配置多个*/ - 'servers' => array( - //例如配置test1和test2两台主机 - 'test1' => array( - 'host' => '127.0.0.1', #memcache主机ip - 'port' => '11211', #memcache端口 - 'weight' => 1, #为此服务器创建的桶的数量,用来控制此服务器被选中的权重 - 'pconn' => true, #是否使用长连 - 'timeout' => 1, #连接持续(超时)时间(单位秒) - 'retry' => 15, #服务器连接失败时重试的间隔时间 - 'status' => true, #控制此服务器是否可以被标记为在线状态 - 'fcallback' => '', #允许用户指定一个运行时发生错误后的回调函数 - ), - 'test2' => array('host' => '127.0.0.1', 'port' => '11212', 'weight' => 1) - ), -); - - - -################################################################### -######redis缓存配置格式:############################################ -return array( - //缓存的过期时间 - 'expires' => '0', - //缓存key的前缀 - 'key-prefix' => '', - //缓存key安全盐码 - 'security-code' => '', - /*验证信息*/ - 'auth' => '', - /*redis服务器相关配置 可以配置多个*/ - 'servers' => array( - //例如配置test1和test2两台主机 - 'test1' => array( - 'host' => '127.0.0.1', #redis主机ip - 'port' => '6379', #redis端口 - 'pconn' => true, #是否使用长链接 - 'timeout' => 1, #连接持续(超时)时间(单位秒) - 'persistent_id' => '', #如果是长链接,则会存在一个长链接的ID号 - ), - 'test2' => array('host' => '127.0.0.1', 'port' => '6380') - ), -); - - -################################################################### -######xcache缓存配置格式:############################################ -return array( - //缓存的过期时间 - 'expires' => '0', - //缓存key的前缀 - 'key-prefix' => '', - //缓存key安全盐码 - 'security-code' => '', - /*验证用户名*/ - 'user' => '', - /*验证用户密码*/ - 'pwd' => '' -); \ No newline at end of file diff --git a/docs/config/php/db_config.php b/docs/config/php/db_config.php deleted file mode 100644 index 60fb8376..00000000 --- a/docs/config/php/db_config.php +++ /dev/null @@ -1,52 +0,0 @@ - 2011-3-8 - * @link http://www.phpwind.com - * @copyright Copyright © 2003-2110 phpwind.com - * @license - */ -#db的配置也支持两种格式 -##一种是单链接,只能配置一个链接 -##一种是有连接池能力的多链接配置,同时支持读写分离和主从配置的能力 - - -/** 第一种:单链接模式 **/ -#WIND:db.WindConnection 配置格式,适合单链接应用,同时不支持连接池 -return array( - //链接的DSN,方式:类型:name=value; 链接类型mysql host为localhost,链接的数据库名字为test, 链接端口为3306 - 'dsn' => 'mysql:host=localhost;dbname=test', - //链接数据库的用户名 - 'user' => 'root', - //链接数据库的密码 - 'pwd' => 'root', - //存取数据库的链接字符集 - 'charset' => 'utf8', - //表前缀,需要“{}”符号,将表名进行标识,才能进行正确替换 - 'tablePrefix' => 'pw_' -); - -/** 第二种:多链接支持 **/ -#WIND:db.WindConnectionManager 配置格式 ,支持链接池,允许配置多个链接 -return array( - 'connections' => array( - //except: 配置多链接的分配规则 - ##每组规则将会以;号分割,*为通配符,:号则表示规则中的表名和链接分割 - ##比如如下: 所有的表名都将走db1链接,user开头的表和tablename2表将会走主db1 从db2的策略 - 'except' => '*:db1;user*,tablename2:db1|db2;', - //各个链接的配置,配置格式如单个链接的配置 - 'db1' => array( - 'dsn' => 'mysql:host=localhost;dbname=test', - 'user' => 'root', - 'pwd' => 'root', - 'charset' => 'utf8', - 'tablePrefix' => 'pw_' - ), - 'db2' => array( - 'dsn' => 'mysql:host=192.168.1.12;dbname=test;port=3305', - 'user' => 'test', - 'pwd' => 'test', - 'charset' => 'utf8', - 'tablePrefix' => 'pw_' - ), - ), -); \ No newline at end of file diff --git a/docs/config/php/router_config.php b/docs/config/php/router_config.php deleted file mode 100644 index 3c724df6..00000000 --- a/docs/config/php/router_config.php +++ /dev/null @@ -1,54 +0,0 @@ - 2010-11-2 - * @link http://www.phpwind.com - * @copyright Copyright © 2003-2010 phpwind.com - * @license - */ - -return array( - /*配置default应用的路由规则*/ - //MVC 配置,url-param:配置访问的别名,default-value:配置缺省值 - /*当开启多应用时候,路由组件指向WindMultiAppRouter时候,可配置路径中app的规则*/ - 'app' => array( - 'url-param' => 'p', - 'default-value' => 'default', - ), - /*配置路径中module的规则*/ - 'module' => array( - 'url-param' => 'm', - 'default-value' => 'default', - ), - /*配置路径中controller的规则*/ - 'controller' => array( - 'url-param' => 'c', - 'default-value' => 'index', - ), - /*配置路径中action的规则*/ - 'action' => array( - 'url-param' => 'a', - 'default-value' => 'run', - ), - //路由规则配置 - /*用户可以轻易的实现自己的route,继承AbstractWindRoute,同时配置到routes下即可,所有的route下的规则根据自己的实现进行更改调整config*/ - /*正则匹配*/ - 'routes' => array( - 'WindRoute' => array( - //路由的实现 - 'class' => 'WIND:router.route.WindRewriteRoute', - /*正则匹配规则*/ - 'pattern' => '^http[s]?:\/\/[^\/]+(\/\w+)?(\/\w+)?(\/\w+)?.*$', - //参数匹配设置,针对正则中的每个匹配项 - 'params' => array( - //参数的名字:a, map:匹配上述正则中的子匹配的位置, default:缺省的值 - 'a' => array('map' => 3, 'default' => 'run'), - 'c' => array('map' => 2), - 'm' => array('map' => 1), - ), - //普通参数的链接分隔符,支持两个字符的配置,第一个字符为参数之间的配置,第二个字符为参数key-value之间的分隔符,默认为&= - 'separator' => '&=', - //build的格式,将会依次根据params中配置的map的顺序依次替换%s占位符,普通变量将会跟在其之后 - 'reverse' => '/%s', - ), - ), -); \ No newline at end of file diff --git a/docs/config/php/view_config.php b/docs/config/php/view_config.php deleted file mode 100644 index 0b1311ba..00000000 --- a/docs/config/php/view_config.php +++ /dev/null @@ -1,42 +0,0 @@ - 'template', - //指定模板后缀 - 'template-ext' => 'htm', - //模板编译文件存放路径 - 'compile-dir' => 'data.template', - //是否编译:如果为0则不编译模板,直接读取已经编译好的模板编译文件,如果为1则编译模板 - 'is-compile' => '0', - //编译模板的后缀配置 - 'compile-ext' => 'tpl', - //布局文件配置 - 'layout' => '', - //主题包位置 - 'theme-package' => '', - //是否开启对输出模板变量进行过滤 - 'htmlspecialchars' => true, - -); - -//第二部分:模板自定义标签配置 -return array( - 'support-tags' => array( - /** 比如配置:标签tag1 **/ - 'tag1' => array( - //标签定义 - 'tag' => '', - //标签匹配表达式 - 'pattern' => '', - //标签的解析类文件 - 'compiler' => '', - ), - ), -); \ No newline at end of file diff --git a/docs/config/php/wind_config.php b/docs/config/php/wind_config.php deleted file mode 100644 index 0281796c..00000000 --- a/docs/config/php/wind_config.php +++ /dev/null @@ -1,114 +0,0 @@ - '1', - - /*站点关闭后转向的模板路径*/ - 'isclose-tpl' => 'TEST:template.closed.htm', - - /*组件配置: - * 组件的配置将会覆盖框架提供的组件的默认配置行为*/ - 'components' => array( - /*可以根据自己的需求重新配置组件的相关项*/ - /** 比如我配置db组件 **/ - /*db相关配置,如果设置了resource则系统会默认找到resource指向的文件作为db配置信息.DB的配置config内容参照DOCS下的db_config配置*/ - 'db' => array( - 'config' => array( - 'resource' => 'db_config.ini' - ), - ), - /** 比如路由的组件配置 **/ - /*配置default应用的路由规则*/ - 'router' => array( - /*当开启多应用时候,路由组件需指向WindMultiAppRouter*/ - 'path' => 'WIND:router.WindMultiAppRouter', - 'config' => array( - /*当开启多应用时候,可配置路径中app的规则*/ - 'app' => array( - 'url-param' => 'p', - 'default-value' => 'default', - ), - /*配置路径中module的规则*/ - 'module' => array( - 'url-param' => 'm', - 'default-value' => 'default', - ), - /*配置路径中controller的规则*/ - 'controller' => array( - 'url-param' => 'c', - 'default-value' => 'index', - ), - /*配置路径中action的规则*/ - 'action' => array( - 'url-param' => 'a', - 'default-value' => 'run', - ), - /*路由协议配置*/ - 'routes' => array( - 'WindRoute' => array( - 'class' => 'WIND:router.route.WindRewriteRoute', - /*正则匹配*/ - 'pattern' => '^http[s]?:\/\/[^\/]+(\/\w+)?(\/\w+)?(\/\w+)?.*$', - 'params' => array( - 'a' => array('map' => 3, 'default' => 'run'), - 'c' => array('map' => 2), - 'm' => array('map' => 1), - ), - ), - ), - ), - ), - ), - - /*应用配置*/ - 'web-apps' => array( - /*配置应用项名为default*/ - /*name为default的应用将会作为缺省的应用配置,其他应用的配置将会和default配置进行merge;*/ - 'default' => array( - 'class' => 'windApplication', - /*过滤链配置,可以配置通用的,同时也可以配置Module级别的,controller级别的,action级别的;*/ - 'filters' => array( - /*过滤器的配置*/ - 'formfilter' => array( - /*过滤器实现*/ - 'class' => 'WIND:web.filter.WindFormFilter', - /*过滤器适用的范围: - * *:则所有的请求都将会应用该过滤器 - * module/*: 则所有module模块的请求都将会应用该过滤器 - * module/index/*: 则module模块下的indexController下的所有Action请求都将会应用该过滤器 - * module/index/add: 则module模块下的indexController下的addAction将会应用该过滤器 - */ - 'pattern' => '*', - /*使用框架提供的formFilter的时候配置给该filter指明需要使用的form*/ - 'form' => 'MyForm', - /*其他配置项:将会传递给配置的filter相同配置项的属性*/ - ) - ), - - /*iscache属性控制windCache组件是否可用,如果关闭则windCache组件将不可用,通过Wind::getApp()->getComponent('windCache');*/ - 'iscache' => 1, - - /*输出编码设置*/ - 'charset' => 'utf-8', - - /*模块配置: 可以通过设定多个module来设置多组模块配置,每组模块以name来相互区分*/ - 'modules' => array( - /** 比如配置default模块 **/ - /*模块名称为default*/ - 'default' => array( - /*default模块的路径*/ - 'controller-path' => 'controller', - /*default模块的中controller的后缀*/ - 'controller-suffix' => 'Controller', - /*配置该模块的error处理的action controller类*/ - 'error-handler' => 'WIND:web.WindErrorHandler', - /*default模块的视图目录配置*/ - 'template-dir' => 'template', - /*default模块的编译目录配置*/ - 'compile-dir' => 'data.template', - ), - ), - ), - ), -); \ No newline at end of file diff --git a/docs/config/properties/cache_config.properties b/docs/config/properties/cache_config.properties deleted file mode 100644 index 99c76172..00000000 --- a/docs/config/properties/cache_config.properties +++ /dev/null @@ -1,110 +0,0 @@ -################################################################### -#######db缓存配置格式:############################################ -#数据库缓存的配置信息 -##缓存文件的过期时间 -expires=0 -##缓存key的前缀 -key-prefix='' -##缓存key安全盐码 -security-code='' -##缓存的表名 -table-name=pw_cache -##缓存的key字段名称 -field-key=key -## 缓存的value字段名称 -field-value=value -##缓存的过期时间字段名称 -field-expire=expire - - - -################################################################### -#######File缓存配置格式:############################################ -#文件缓存配置 -##缓存文件的过期时间 -expires=0 -##缓存key的前缀 -key-prefix='' -##缓存key安全盐码 -security-code='' - -##缓存文件的保存路径(支持命名空间的方式配置该路径 -dir=WIND:_compile -##缓存文件的后缀 -suffix=php -##缓存的目录支持级别 -dir-level=0 - - - -################################################################### -######Memcache缓存配置格式:############################################ -#memcache配置: -##memcache的配置和memecached的配置格式一样,但是compress配置将不会对memcached起作用,同样的主机配置只有host,port和weight会被用到 -##详细看各自的支持 - -##缓存文件的过期时间 -expires=0 -##缓存key的前缀 -key-prefix='' -##缓存key安全盐码 -security-code='' - -##压缩的级次 -compress=0 -##memcache服务器相关配置 可以配置多个 -[servers] -##例如配置test1和test2两台主机 -test1.host=127.0.0.1 #memcache主机ip -test1.port=11211 #memcache端口 -test1.weight=1 #为此服务器创建的桶的数量,用来控制此服务器被选中的权重 -test1.pconn=true #是否使用长连 -test1.timeout=1 #连接持续(超时)时间(单位秒) -test1.retry=15 #服务器连接失败时重试的间隔时间 -test1.status=true #控制此服务器是否可以被标记为在线状态 -test1.fcallback='' #允许用户指定一个运行时发生错误后的回调函数 -test2.host=127.0.0.1 #memcache主机ip -test2.port=11212 #memcache端口 -test2.weight=1 #为此服务器创建的桶的数量,用来控制此服务器被选中的权重 - -################################################################### -######redis缓存配置格式:############################################ -#redis配置: - -##缓存文件的过期时间 -expires=0 -##缓存key的前缀 -key-prefix='' -##缓存key安全盐码 -security-code='' - -##验证信息 -auth='' -##redis服务器相关配置 可以配置多个 -[servers] -##例如配置test1和test2两台主机 -test1.host=127.0.0.1 #memcache主机ip -test1.port=6379 #memcache端口 -test1.pconn='true' #是否使用长连 -test1.timeout=1 #连接持续(超时)时间(单位秒) -persistent_id='' #如果是长链接,则会存在一个长链接的ID号 -test2.host=127.0.0.1 #redis主机ip -test2.port=11212 #redis端口 -test2.weight=1 #为此服务器创建的桶的数量,用来控制此服务器被选中的权重 - - - -################################################################### -#######xcache缓存配置格式:############################################ -#文件缓存配置 -##缓存文件的过期时间 -expires=0 -##缓存key的前缀 -key-prefix='' -##缓存key安全盐码 -security-code='' - -##验证用户名 -user='' -##验证用户密码 -pwd='' diff --git a/docs/config/properties/db_config.properties b/docs/config/properties/db_config.properties deleted file mode 100644 index 5fdae3de..00000000 --- a/docs/config/properties/db_config.properties +++ /dev/null @@ -1,37 +0,0 @@ -#db的配置也支持两种格式 -##一种是单链接,只能配置一个链接 -##一种是有连接池能力的多链接配置,同时支持读写分离和主从配置的能力 - -#第一种:单链接模式 -#WIND:db.WindConnection 配置格式,适合单链接应用,同时不支持连接池 -##链接的DSN,方式:类型:name=value; 链接类型mysql host为localhost,链接的数据库名字为test, 链接端口为3306 -dsn='mysql:host=localhost;dbname=test' -##链接数据库的用户名 -user=root -##链接数据库的密码 -pwd=root -##存取数据库的链接字符集 -charset=utf8 -##表前缀,需要“{}”符号,将表名进行标识,才能进行正确替换 -tablePrefix=pw_ - - - -#第二种:多链接支持 -#WIND:db.WindConnectionManager 配置格式 ,支持链接池,允许配置多个链接 -[connections] -##except: 配置多链接的分配规则 -##每组规则将会以;号分割,*为通配符,:号则表示规则中的表名和链接分割 -##比如如下: 所有的表名都将走db1链接,user开头的表和tablename2表将会走主db1 从db2的策略 -except='*:(db1);user*,tablename2:(db1|db2);' -##各个链接的配置,配置格式如单个链接的配置 -db1.dsn=mysql:host=localhost;dbname=test -db1.user=root -db1.pwd=root -db1.charset=utf8 -db1.tablePrefix=pw_ -db1.dsn=mysql:host=192.168.1.12;dbname=test;port=3305 -db1.user=test -db1.pwd=test -db1.charset=utf8 -db1.tablePrefix=pw_ \ No newline at end of file diff --git a/docs/config/properties/router_config.properties b/docs/config/properties/router_config.properties deleted file mode 100644 index 4167eff7..00000000 --- a/docs/config/properties/router_config.properties +++ /dev/null @@ -1,36 +0,0 @@ -#路由规则配置 -#MVC 配置,url-param:配置访问的别名,default-value:配置缺省值 -#当开启多应用时候,路由组件指向WindMultiAppRouter时候,可配置路径中app的规则 -[app] -url-param=p -default-value=default -[module] -url-param=m -default-value=default -[controller] -url-param=c -default-value=index -[action] -url-param=a -default-value=run - -#路由规则配置 -#用户可以轻易的实现自己的额route,继承AbstractWindRoute,同时配置到routes下即可,所有的route下的规则根据自己的实现进行更改调整config -[routes] -#每个路由有唯一的一个名字,以下是框架提供的一个路由的规则配置 -##比例如 配置框架提供的路由规则 -##路由的实现 -WindRoute.class=WIND:router.route.WindRewriteRoute -##路由的正则匹配 -WindRoute.pattern=^http[s]?:\/\/[^\/]+(\/\w+)?(\/\w+)?(\/\w+)?.*$ -##参数匹配设置,针对正则中的每个匹配项 -###参数的名字:a, map:匹配上述正则中的子匹配的位置, default:缺省的值 -##参数匹配:针对MVC的参数名字,需要注意和MVC配置中的别名一一对应,否则不能正确进行路由 -WindRoute.params.a.map=3 -WindRoute.params.a.default=run -WindRoute.params.c.map=2 -WindRoute.params.m.map=1 -##普通参数的链接分隔符,支持两个字符的配置,第一个字符为参数之间的配置,第二个字符为参数key-value之间的分隔符,默认为&= -WindRoute.separator='&=' -##build的格式,将会依次根据params中配置的map的顺序依次替换%s占位符,普通变量将会跟在其之后 -WindRoute.reverse='/%s' \ No newline at end of file diff --git a/docs/config/properties/view_config.properties b/docs/config/properties/view_config.properties deleted file mode 100644 index 5dac01c6..00000000 --- a/docs/config/properties/view_config.properties +++ /dev/null @@ -1,34 +0,0 @@ -#试图组件的配置有两部分: -##一部分是试图组件的基本配置,包括模板路径编译路径及编译控制等 -##第二部分是模板编译标签的配置,用户可以配置自己定义的编译解析规则 - - -#第一部分:试图组件的配置 -##模板目录 -template-dir=template -##指定模板后缀 -template-ext=htm -##模板编译文件存放路径 -compile-dir=data.template -##是否编译:如果为0则不编译模板,直接读取已经编译好的模板编译文件,如果为1则编译模板 -is-compile=0 -##编译模板的后缀配置 -compile-ext=tpl -##布局文件配置 -layout='' -##主题包位置 -theme-package='' -##是否开启对输出模板变量进行过滤 -htmlspecialchars='true' - - - -#第二部分:模板自定义标签配置 -[support-tags] -#比如配置:标签tag1 -##标签定义 -#tag1.tag='' -##标签匹配表达式 -#tag1.pattern='' -##标签的解析类文件 -#tag1.compiler='' \ No newline at end of file diff --git a/docs/config/properties/wind_config.properties b/docs/config/properties/wind_config.properties deleted file mode 100644 index 9c3bca96..00000000 --- a/docs/config/properties/wind_config.properties +++ /dev/null @@ -1,74 +0,0 @@ -#站点是否关闭设置 -isclose=1 - -#站点关闭后转向的模板路径 -isclose-tpl=TEST:template.closed.htm - -#组件的配置 -#组件个性配置,一下的组件配置将会替换掉compontents_config下的对应的组件的配置,同时这里也可以增加自己的组件 -[components] -##比如配置一个db组件 -##db相关配置,如果设置了resource则系统会默认找到resource指向的文件作为db配置信息.DB的配置config内容参照DOCS下的db_config配置 -db.config.resource=db_config.php -##比如配置一个router组件 -#当开启多应用时候,路由组件需指向WindMultiAppRouter -router.path=WIND:router.WindMultiAppRouter -##router组件主要允许用户配置module/controller/action的访问别名及各自缺省值,同时允许设置urlWrite规则 -#当开启多应用时候,可配置路径中app的规则 -router.config.app.url-param=p -router.config.app.default-value=default -router.config.module.url-param=m -router.config.module.default-value=default -router.config.controller.url-param=c -router.config.controller.default-value=index -router.config.action.url-param=a -router.config.action.default-value=run -##以下为url路由规则的配置 -router.config.routes.WindRoute.class=WIND:router.route.WindRewriteRoute -router.config.routes.WindRoute.pattern=^http[s]?:\/\/[^\/]+(\/\w+)?(\/\w+)?(\/\w+)?.*$ -router.config.routes.WindRoute.params.a.map=3 -router.config.routes.WindRoute.params.a.default=run -router.config.routes.WindRoute.params.c.map=2 -router.config.routes.WindRoute.params.m.map=1 - -#应用配置 -[web-apps] -#default应用的配置 -#应用的实现组件 -default.class=windWebApp - -#default应用的编码 -default.charset=utf-8 - - - -#iscache属性控制windCache组件是否可用,如果关闭则windCache组件将不可用,通过Wind::getApp()->getComponent('windCache')# -default.iscache=1 - -#过滤链配置,可以配置通用的,同时也可以配置Module级别的,controller级别的,action级别的; class: 配置过滤链的实现 -#过滤器配置 -#name: 过滤器的名字:唯一 -#class: 过滤器的实现: -#pattern:*:则所有的请求都将会应用该过滤器 -# module/*: 则所有module模块的请求都将会应用该过滤器 -# module/index/*: 则module模块下的indexController下的所有Action请求都将会应用该过滤器 -# module/index/add: 则module模块下的indexController下的addAction将会应用该过滤器 -#form: 使用框架提供的formFilter的时候配置给该filter指明需要使用的form -#其他配置项:将会传递给配置的filter相同配置项的属性 -default.filters.formfilter.class=WIND:web.filter.WindFormFilter -default.filters.formfilter.pattern=* -default.filters.formfilter.form=Myform - - -#模块配置: -##如下配置一个名为default的模块: -##controller-path: 模块的路径(采用命名空间的方式) -default.modules.default.controller-path=controller -#controller-suffix: 模块的controller后缀信息 -default.modules.default.controller-suffix=Controller -#error-handler: 模块的错误处理类 -default.modules.default.error-handler=WIND:web.WindErrorHandler -#template-dir: 模块的模板目录,支持命名空间的方式如DEFAULT:template -default.modules.default.template-dir=template -#compile-dir: 模块的模板编译文件保存的目录,支持命名空间的方式如DEFAULT:compile.template -default.modules.default.compile-dir=data.template \ No newline at end of file diff --git a/docs/config/router_config.xml b/docs/config/router_config.xml deleted file mode 100644 index c1c0c747..00000000 --- a/docs/config/router_config.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - WIND:router.route.WindRewriteRoute - - ^http[s]?:\/\/[^\/]+(\/\w+)?(\/\w+)?(\/\w+)?.*$ - - - - - - 3 - run - - - 2 - index - - - 1 - default - - - - &= - - /%s - - - \ No newline at end of file diff --git a/docs/config/view_config.xml b/docs/config/view_config.xml deleted file mode 100644 index 3daf78a8..00000000 --- a/docs/config/view_config.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - template - - htm - - data.template - - 0 - - tpl - - - - - - true - - - - - - - - - - - \ No newline at end of file diff --git a/docs/config/wind_config.xml b/docs/config/wind_config.xml deleted file mode 100644 index 4cc27d9f..00000000 --- a/docs/config/wind_config.xml +++ /dev/null @@ -1,98 +0,0 @@ - - - - - 1 - - TEST:template.closed.htm - - - - - - - - - - - - - - - p - default - - - m - default - - - c - index - - - a - run - - - - WIND:router.route.WindRewriteRoute - ^http[s]?:\/\/[^\/]+(\/\w+)?(\/\w+)?(\/\w+)?.*$ - - - - - - - - - - - - - - - - - 1 - - - utf-8 - - - - - - - - - - - - controller - - Controller - - WIND:web.WindErrorHandler - - template - - data.template - - - - - - \ No newline at end of file diff --git a/tool/compiler/pack.php b/tool/compiler/pack.php deleted file mode 100644 index a2eec8ba..00000000 --- a/tool/compiler/pack.php +++ /dev/null @@ -1,112 +0,0 @@ -packFromFileList($fileList, _COMPILE_PATH . 'wind_basic.php', WindPack::STRIP_PHP, true); -$message = array(); -$message[] = "COMPILE: pack core file successful~"; - -/*装载imports和classes*/ -$data = ' $fileName); - $GLOBALS['classes'] += array($fileName => $dir . '/' . $fileName); - } else if (is_dir($dir . '/' . $file)) { - readRecur($dir . '/' . $file, $alias . '.' . $file); - } - } - return $fileList; -} - -/** - * 输出错误信息 - * - * @param string $message - */ -function e($message) { - exit($message); -} - -/** - * 交互信息 - * - * @param string $message - * @return string - */ -function getLine($message) { - echo $message; - return fgets(STDIN); -} - -/** - * 处理目录别名 - * - * @param string $alias - * @return Ambigous - */ -function getAlias($alias) { - return substr($alias, '-1') == ':' ? $alias : $alias . '.'; -} diff --git a/tool/generator/command b/tool/generator/command deleted file mode 100644 index 75b95375..00000000 --- a/tool/generator/command +++ /dev/null @@ -1,14 +0,0 @@ - 2010-11-2 - * @link http://www.phpwind.com - * @copyright Copyright © 2003-2010 phpwind.com - * @license - */ -error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING); -//为了兼容类似php generator/command 统一使用绝对路径 -require_once dirname(dirname(__DIR__)) . '/wind/Wind.php'; -Wind::register(dirname(dirname(__DIR__)), 'PROJ'); -Wind::application('command', __DIR__ . '/conf/config.php', 'Command')->run(); \ No newline at end of file diff --git a/tool/generator/conf/config.php b/tool/generator/conf/config.php deleted file mode 100644 index 8eb67ead..00000000 --- a/tool/generator/conf/config.php +++ /dev/null @@ -1,22 +0,0 @@ - array( - 'command' => array( - 'root-path' => dirname(__DIR__), - 'modules' => array( - 'default' => array( - 'controller-path' => 'COMMAND:src.controller', - 'controller-suffix' => 'Command' - ) - ), - ), - 'web' => array( - 'root-path' => dirname(__DIR__), - 'modules' => array( - 'default' => array( - 'controller-path' => 'WEB:src.controller', - ) - ), - ) - ) -); \ No newline at end of file diff --git a/tool/generator/conf/project.default b/tool/generator/conf/project.default deleted file mode 100644 index 96cc9355..00000000 --- a/tool/generator/conf/project.default +++ /dev/null @@ -1,8 +0,0 @@ - 'data', - 'templateDir' => 'template', - 'srcDir' => 'src/controller', - 'confDir' => 'conf', - 'wwwDir' => 'www' -); \ No newline at end of file diff --git a/tool/generator/install.php b/tool/generator/install.php deleted file mode 100644 index 07bbe78c..00000000 --- a/tool/generator/install.php +++ /dev/null @@ -1,11 +0,0 @@ - - * @link http://www.phpwind.com - * @copyright Copyright © 2003-2010 phpwind.com - * @license - */ -error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING); -require_once dirname(dirname(__DIR__)) . '/wind/Wind.php'; -Wind::register(dirname(dirname(__DIR__)), 'PROJ'); -Wind::application('web', __DIR__ . '/conf/config.php')->run(); \ No newline at end of file diff --git a/tool/generator/src/WindGenerateProject.php b/tool/generator/src/WindGenerateProject.php deleted file mode 100644 index c170a4aa..00000000 --- a/tool/generator/src/WindGenerateProject.php +++ /dev/null @@ -1,227 +0,0 @@ - - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package tool - * @subpackage generator - */ -class WindGenerateProject { - - /** - * 工程目录 - */ - public $dir; - /** - * 工程名称 - */ - public $name; - /** - * 工程缓存目录 - */ - public $dataDir; - /** - * 工程模板目录 - */ - public $templateDir; - /** - * 工程业务逻辑目录 - */ - public $srcDir; - /** - * 工程配置目录 - */ - public $confDir; - /** - * 工程可访问资源目录 - */ - public $wwwDir; - - private $confFile; - - /** - * 创建工程接口 - * - */ - public function generate() { - WindFolder::mkRecur($this->dir); - if (!is_writable($this->dir)) return false; - $result = $this->generateData() - && $this->generateTemplate() - && $this->generateSrc() - && $this->generateConf() - && $this->generateWww(); - return $result; - } - - /** - * 解析配置文件 - * - * @param string $config - */ - public function setConfig($config) { - if (is_string($config)) $config = @include Wind::getRealPath($config, true); - $this->dataDir = $config['dataDir']; - $this->templateDir = $config['templateDir']; - $this->srcDir = $config['srcDir']; - $this->confDir = $config['confDir']; - $this->wwwDir = $config['wwwDir']; - } - - /** - * 生成data目录 - * - */ - protected function generateData() { - WindFolder::mkRecur($this->dir . '/' . $this->dataDir); - $this->dataDir = $this->_resolveDirName($this->dataDir); - return true; - } - - /** - * 生成模板目录 - * - */ - protected function generateTemplate() { - WindFolder::mkRecur($this->dir . '/' . $this->templateDir); - $this->templateDir = $this->_resolveDirName($this->templateDir); - return true; - } - - /** - * 生成src目录及IndexController.php - * - */ - protected function generateSrc() { - $content = << -EOF; - $dir = $this->dir . '/' . $this->srcDir; - WindFolder::mkRecur($dir); - if (!WindFile::write($dir . '/IndexController.php', $content)) return false; - $this->srcDir = $this->_resolveDirName($this->srcDir); - return true; - } - - /** - * 生成conf目录及config.php - * - */ - protected function generateConf() { - $content = << array( - '%s' => array( - 'modules' => array( - 'default' => array( - 'controller-path' => '%s', - 'controller-suffix' => '%s', - 'template-dir' => '%s', - 'compile-dir' => '%s', - ) - ) - ) - ) -); -EOD; - $alias = strtoupper($this->name) . ':'; - $content = sprintf($content, - $this->name, - $alias . $this->srcDir, - 'Controller', - $alias . $this->templateDir, - $alias . $this->dataDir . '.compile' - ); - $dir = $this->dir . '/' . $this->confDir; - WindFolder::mkRecur($dir); - $this->confFile = $dir . '/config.php'; - if (!WindFile::write($this->confFile, $content)) return false; - return true; - } - - /** - * 生成www目录及index.php - * - */ - protected function generateWww() { - $content = <<run(); -EOS; - $dir = $this->dir . '/' . $this->wwwDir; - WindFolder::mkRecur($dir); - $content = sprintf($content, - $this->_resolveRelativePath($dir, Wind::getRealPath('WIND:Wind.php', true)) , - $this->_resolveRelativePath($dir, $this->dir), - strtoupper($this->name), - $this->name, - $this->_resolveRelativePath($dir, $this->confFile)); - if (!WindFile::write($dir . '/index.php', $content)) return false; - return true; - } - - /** - * 处理路径 - * - * @param string $dir - * @return string - */ - private function _resolveDirName($dir) { - return str_replace('/', '.', $dir); - } - - /** - * 计算路径1对于路径2的相对路径 - * - * @param string $sourcePath - * @param string $targetPath - * @return string - */ - private function _resolveRelativePath($sourcePath, $targetPath) { - list($sourcePath, $targetPath) = array(realpath($sourcePath), realpath($targetPath)); - $src_paths = explode('/', $sourcePath); - $tgt_paths = explode('/', $targetPath); - $src_count = count($src_paths); - $tgt_count = count($tgt_paths); - - $relative_path = ''; - //默认把不同点设在最后一个 - $break_point = $src_count; - $i = 0; - //计算两个路径不相同的点,然后开始往上数.. - for ($i = 0; $i < $src_count; $i++) { - if ($src_paths[$i] == $tgt_paths[$i]) continue; - $relative_path .= '../'; - $break_point == $src_count && $break_point = $i; - } - $relative_path || $relative_path = './'; - - //往上..后,继续算目标路径的接下来的path - for ($i = $break_point; $i < $tgt_count; $i++) { - $relative_path .= $tgt_paths[$i] . '/'; - } - return rtrim($relative_path, '/'); - } -} - -?> \ No newline at end of file diff --git a/tool/generator/src/controller/IndexCommand.php b/tool/generator/src/controller/IndexCommand.php deleted file mode 100644 index acd1337b..00000000 --- a/tool/generator/src/controller/IndexCommand.php +++ /dev/null @@ -1,99 +0,0 @@ - - * @copyright ©2003-2103 phpwind.com - * @license http://www.phpwind.com - * @version $Id$ - * @package tool - * @subpackage generator - */ -class IndexCommand extends WindCommandController { - /** - * @var WindGenerateProject - */ - private $project; - private $config = 'COMMAND:conf.project.default'; - /* - * 主流程 (non-PHPdoc) - * - * @see WindCommandController::run() - */ - public function run($projName = 'test') { - list($projName, $dir) = $this->_checkDir($projName); - $this->project = new WindGenerateProject(); - $this->chooseMode(); - $this->project->name = $projName; - $this->project->dir = $dir; - - $result = $this->project->generate(); - if ($result === false) { - $this->setOutput(<<setOutput(<<project->dir} -EOT - ); - } - } - - /** - * 选择标准或者自定义模式 - * - * @param WindGenerateProject $project - */ - protected function chooseMode() { - $r = $this->getLine(<<project->setConfig($this->config); - } else { - $this->project->dataDir = $this->getLine('请输入你想要指定的缓存目录,默认是待创建工程目录下的data目录[data]:'); - $this->project->templateDir = $this->getLine('请输入你想要指定的模板目录,默认是待创建工程目录下的template目录[template]:'); - $this->project->srcDir = $this->getLine( - '请输入你想要指定的业务逻辑处理目录,默认是待创建工程目录下的src/controller目录[src/controller]:'); - $this->project->confDir = $this->getLine('请输入你想要指定的配置目录,默认是待创建工程目录下的conf目录[conf]:'); - $this->project->wwwDir = $this->getLine('请输入你想要指定的web可访问资源目录,默认是待创建工程目录下的www目录[www]:'); - } - } - - - - /** - * 检测路径 - * - * @param string $projName - * @return string - */ - private function _checkDir($projName) { - static $dir = '', $name = ''; - $name = $projName; - $dir = Wind::getRealDir('PROJ:' . $name); - if (is_dir($dir)) { - $r = $this->getLine( - "The Project Folder [$dir] Already Exist, Are you sure to override it?(Yes|No)"); - if (strtolower($r[0]) != 'y') { - $name = $this->getLine('Please input the project name:'); - $this->_checkDir($name); - } - } - return array($name, $dir); - } - -} - -?> \ No newline at end of file diff --git a/tool/generator/src/controller/IndexController.php b/tool/generator/src/controller/IndexController.php deleted file mode 100644 index ed964f4f..00000000 --- a/tool/generator/src/controller/IndexController.php +++ /dev/null @@ -1,38 +0,0 @@ - - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package tool - * @subpackage generator - */ -class IndexController extends WindController { - /** - * @var WindGenerateProject - */ - private $project; - private $config = 'WEB:conf.project.default'; - - /* (non-PHPdoc) - * @see WindController::run() - */ - public function run() { - $this->project = new WindGenerateProject(); - $this->project->name = 'test'; - $this->project->dir = Wind::getRealDir('PROJ:' . $this->project->name); - $this->project->setConfig($this->config); - $r = $this->project->generate(); - if (!$r) echo 'generate fail'; - else echo 'generate success'; - } - - public function doRun() { - - } -} - -?> \ No newline at end of file diff --git a/tool/readme b/tool/readme deleted file mode 100644 index 8ae3db3d..00000000 --- a/tool/readme +++ /dev/null @@ -1,29 +0,0 @@ -Wind Tool: - -wind tool工具包,包含了一组工程工具。用于快速创建wind框架工程、自定义方式创建wind框架工程、效率优化等。 -支持命令行模式(cmd,sh),web可视化模式等。 - -快速工程创建: -install.php\sh -系统将会自动生成工程目录、启动脚本(index.php)、应用配置文件(config.php)、默认controller等,如下: -/wind ---框架目录 -/data ---缓存目录 -/template ---模板目录 -/src/controller ---业务逻辑处理 - IndexController.php -/conf ---配置目录 - config.php -/www ---web可访问资源目录 - index.php - -注: 默认情况下生成的配置文件为php格式 - -分为‘自定义’、‘标准’两种模式。 -自定义模式: -用户可以自定义: -1. 目录结构 -2. 目录名称 -... - -1. 快速创建wind工程,支持自定义工程目录结构 -2. 效率优化,支持'预加载处理'、'核心打包加载' diff --git a/wind/Wind.php b/wind/Wind.php index 1d29d5bb..9be24795 100644 --- a/wind/Wind.php +++ b/wind/Wind.php @@ -1,251 +1,365 @@ 2011-10-9 * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: Wind.php 3904 2013-01-08 07:01:26Z yishuo $ */ -class Wind { - public static $_imports = array(); - public static $_classes = array(); - private static $_extensions = 'php'; - private static $_isAutoLoad = true; - private static $_namespace = array(); - private static $_includePaths = array(); - private static $_frontController = null; - - /** - * @param IWindRequest $request - * @param IWindResponse $response - * @param WindFactory $factory - * @return WindFrontController - */ - public static function application($appName = '', $config = array(), $type = 'Web') { - if (self::$_frontController === null) { - $_className = 'Wind' . $type . 'FrontController'; - self::$_classes[$_className] = strtolower($type) . '/Wind' . $type . 'FrontController'; - self::$_frontController = new $_className($appName, $config); - } - return self::$_frontController; - } - - /** - * @see WindFrontController::getAppName() - * @return string - */ - public static function getAppName() { - if (self::$_frontController === null) return ''; - return self::$_frontController->getAppName(); - } - - /** - * 返回当前的app应用 - * - * @param string $appName - * @see WindFrontController::getApp() - * @return WindWebApplication - */ - public static function getApp() { - if (self::$_frontController === null) return null; - return self::$_frontController->getApp(); - } - - /** - * 加载一个类或者加载一个包 - * 如果加载的包中有子文件夹不进行循环加载 - * 参数格式说明:'WIND:base.WFrontController' - * WIND 注册的应用名称,应用名称与路径信息用‘:’号分隔 - * base.WFrontController 相对的路径信息 - * 如果不填写应用名称 ,例如‘base.WFrontController’,那么加载路径则相对于默认的应用路径 - * - * 加载一个类的参数方式:'WIND:base.WFrontController' - * 加载一个包的参数方式:'WIND:base.*' - * - * @param string $filePath | 文件路径信息 或者className - * @return string|null - */ - public static function import($filePath) { - if (!$filePath) return; - if (isset(self::$_imports[$filePath])) return self::$_imports[$filePath]; - if (($pos = strrpos($filePath, '.')) !== false) - $fileName = substr($filePath, $pos + 1); - elseif (($pos = strrpos($filePath, ':')) !== false) - $fileName = substr($filePath, $pos + 1); - else - $fileName = $filePath; - $isPackage = $fileName === '*'; - if ($isPackage) { - $filePath = substr($filePath, 0, $pos + 1); - $dirPath = self::getRealPath(trim($filePath, '.'), false); - self::register($dirPath, '', true); - } else - self::_setImport($fileName, $filePath); - return $fileName; - } - - /** - * 将路径信息注册到命名空间,该方法不会覆盖已经定义过的命名空间 - * @param string $path | 需要注册的路径 - * @param string $name | 路径别名 - * @param boolean $includePath | 是否同时定义includePath - * @param boolean $reset | 是否覆盖已经存在的定义,默认false - * @return void - * @throws Exception - */ - public static function register($path, $alias = '', $includePath = false, $reset = false) { - if (!$path) return; - if (!empty($alias)) { - $alias = strtolower($alias); - if (!isset(self::$_namespace[$alias]) || $reset) self::$_namespace[$alias] = rtrim($path, '/') . '/'; - } - if ($includePath) { - if (empty(self::$_includePaths)) { - self::$_includePaths = array_unique(explode(PATH_SEPARATOR, get_include_path())); - if (($pos = array_search('.', self::$_includePaths, true)) !== false) unset(self::$_includePaths[$pos]); - } - array_unshift(self::$_includePaths, $path); - if (set_include_path('.' . PATH_SEPARATOR . implode(PATH_SEPARATOR, self::$_includePaths)) === false) { - throw new Exception('[wind.register] set include path error.'); - } - } - } - - /** - * 返回命名空间的路径信息 - * @param string $namespace - * @return string|Ambigous - */ - public static function getRootPath($namespace) { - $namespace = strtolower($namespace); - return isset(self::$_namespace[$namespace]) ? self::$_namespace[$namespace] : ''; - } - - /** - * 类文件自动加载方法 callback - * @param string $className - * @param string $path - * @return null - */ - public static function autoLoad($className, $path = '') { - if ($path) - include $path . '.' . self::$_extensions; - elseif (isset(self::$_classes[$className])) { - include self::$_classes[$className] . '.' . self::$_extensions; - } else - include $className . '.' . self::$_extensions; - } - - /** - * 解析路径信息,并返回路径的详情 - * @param string $filePath 路径信息 - * @param boolean $suffix 是否存在文件后缀true,false,default - * @return string|array('isPackage','fileName','extension','realPath') - */ - public static function getRealPath($filePath, $suffix = '', $absolut = false) { - if (false !== strpos($filePath, DIRECTORY_SEPARATOR)) return realpath($filePath); - if (false !== ($pos = strpos($filePath, ':'))) { - $namespace = self::getRootPath(substr($filePath, 0, $pos)); - $filePath = substr($filePath, $pos + 1); - } else - $namespace = $absolut ? self::getRootPath(self::getAppName()) : ''; - - $filePath = str_replace('.', '/', $filePath); - $namespace && $filePath = $namespace . $filePath; - if ($suffix === '') return $filePath . '.' . self::$_extensions; - if ($suffix === true && false !== ($pos = strrpos($filePath, '/'))) { - $filePath[$pos] = '.'; - return $filePath; - } - return $suffix ? $filePath . '.' . $suffix : $filePath; - } - - /** - * 解析路径信息,并返回路径的详情 - * @param string $filePath 路径信息 - * @param boolean $absolut 是否返回绝对路径 - * @return string|array('isPackage','fileName','extension','realPath') - */ - public static function getRealDir($dirPath, $absolut = false) { - if (false !== ($pos = strpos($dirPath, ':'))) { - $namespace = self::getRootPath(substr($dirPath, 0, $pos)); - $dirPath = substr($dirPath, $pos + 1); - } else - $namespace = $absolut ? self::getRootPath(self::getAppName()) : ''; - $namespace && $dirPath = $namespace . str_replace('.', '/', $dirPath); - return $dirPath; - } - - /** - * 初始化框架 - */ - public static function init() { - function_exists('date_default_timezone_set') && date_default_timezone_set('Etc/GMT+0'); - self::register(WIND_PATH, 'WIND', true); - if (!self::$_isAutoLoad) return; - if (function_exists('spl_autoload_register')) - spl_autoload_register('Wind::autoLoad'); - else - self::$_isAutoLoad = false; - self::_loadBaseLib(); - } - - /** - * @param string $className - * @param string $classPath - * @return void - */ - private static function _setImport($className, $classPath) { - self::$_imports[$classPath] = $className; - if (!isset(self::$_classes[$className])) { - $_classPath = self::getRealPath($classPath, false); - self::$_classes[$className] = $_classPath; - } else - $_classPath = self::$_classes[$className]; - if (!self::$_isAutoLoad) self::autoLoad($className, $_classPath); - } - - /** - * 加载核心层库函数 - * - * @return void - */ - private static function _loadBaseLib() { - self::$_classes = array( - 'AbstractWindFrontController' => 'base/AbstractWindFrontController', - 'IWindApplication' => 'base/IWindApplication', - 'IWindFactory' => 'base/IWindFactory', - 'IWindRequest' => 'base/IWindRequest', - 'IWindResponse' => 'base/IWindResponse', - 'WindActionException' => 'base/WindActionException', - 'WindClassProxy' => 'base/WindClassProxy', - 'WindEnableValidateModule' => 'base/WindEnableValidateModule', - 'WindErrorMessage' => 'base/WindErrorMessage', - 'WindException' => 'base/WindException', - 'WindFactory' => 'base/WindFactory', - 'WindFinalException' => 'base/WindFinalException', - 'WindForwardException' => 'base/WindForwardException', - 'WindHelper' => 'base/WindHelper', - 'WindModule' => 'base/WindModule', - 'WindActionFilter' => 'filter/WindActionFilter', - 'WindHandlerInterceptor' => 'filter/WindHandlerInterceptor', - 'WindHandlerInterceptorChain' => 'filter/WindHandlerInterceptorChain', - 'WindUtility' => 'utility/WindUtility', - 'WindString' => 'utility/WindString', - 'WindFile' => 'utility/WindFile', - 'WindJson' => 'utility/WindJson', - 'WindSecurity' => 'utility/WindSecurity'); - } +class Wind +{ + public static $isDebug = 0; + public static $_imports = array(); + public static $_classes = array(); + private static $_extensions = 'php'; + private static $_isAutoLoad = true; + private static $_namespace = array(); + private static $_includePaths = array(); + + /** + * + * @var AbstractWindFrontController + */ + private static $_front = null; + + /** + * command line mode application 应用入口 + * + * @param string $appName + * @param string|array $config + * @return WindCommandFrontController + */ + public static function commandApplication($appName = '', $config = array()) + { + if (self::$_front === null) { + self::$_front = new WindCommandFrontController($appName, $config); + } + + return self::$_front; + } + + /** + * Web Application应用入口 + * + * @param string $appName + * @param string|array $config + * @return WindWebApplication + */ + public static function application($appName = '', $config = array()) + { + if (self::$_front === null) { + self::$_front = new WindWebFrontController($appName, $config); + } + + return self::$_front; + } + + /** + * 获取系统组建 + * + * @param string $alias + * @param array $args + * @return Ambigous + */ + public static function getComponent($alias, $args = array()) + { + return WindFactory::_getInstance()->getInstance($alias, $args); + } + + /** + * 注册系统组建 + * + * 对象方式注册: + * $converter = new WindGeneralConverter(); + * Wind::registeComponent($converter,'windConverter',singleton); + * 定义方式注册: + * Wind::registeComponent(array('path' => + * 'WIND:convert.WindGeneralConverter', 'scope' => 'singleton'), + * 'windConverter'); + * + * @param object|array $componentInstance + * @param string $componentName + * @param string $scope + * @return bool + */ + public static function registeComponent($componentInstance, $componentName, $scope = 'application') + { + if (is_array($componentInstance)) { + isset($componentInstance['scope']) || $componentInstance['scope'] = $scope; + WindFactory::_getInstance()->loadClassDefinitions( + array($componentName => $componentInstance)); + } elseif (is_object($componentInstance)) { + WindFactory::_getInstance()->registInstance($componentInstance, $componentName, $scope); + } else { + throw new WindException('[Wind.registeComponent] registe component fail, array or object is required', + WindException::ERROR_PARAMETER_TYPE_ERROR); + } + } + + /** + * + * @see WindFrontController::getAppName() + * @return string + */ + public static function getAppName() + { + return self::$_front->getAppName(); + } + + /** + * 返回当前的app应用 + * + * @param string $appName + * @see WindFrontController::getApp() + * @return WindWebApplication + */ + public static function getApp() + { + return self::$_front->getApp(); + } + + /** + * 加载一个类或者加载一个包 + * 如果加载的包中有子文件夹不进行循环加载 + * 参数格式说明:'WIND:base.WFrontController' + * WIND 注册的应用名称,应用名称与路径信息用‘:’号分隔 + * base.WFrontController 相对的路径信息 + * 如果不填写应用名称 ,例如‘base.WFrontController’,那么加载路径则相对于默认的应用路径 + * 加载一个类的参数方式:'WIND:base.WFrontController' + * 加载一个包的参数方式:'WIND:base.*' + * + * @param string $filePath + * | 文件路径信息 或者className + * @return string null + */ + public static function import($filePath) + { + if (!$filePath) { + return; + } + if (isset(self::$_imports[$filePath])) { + return self::$_imports[$filePath]; + } + if (($pos = strrpos($filePath, '.')) !== false) { + $fileName = substr($filePath, $pos + 1); + } elseif (($pos = strrpos($filePath, ':')) !== false) { + $fileName = substr($filePath, $pos + 1); + } else { + $fileName = $filePath; + } + $isPackage = $fileName === '*'; + if ($isPackage) { + $filePath = substr($filePath, 0, $pos + 1); + $dirPath = self::getRealPath(trim($filePath, '.'), false); + self::register($dirPath, '', true); + } else { + self::_setImport($fileName, $filePath); + } + + return $fileName; + } + + /** + * 将路径信息注册到命名空间,该方法不会覆盖已经定义过的命名空间 + * + * @param string $path + * 需要注册的路径 + * @param string $name + * 路径别名 + * @param bool $includePath + * | 是否同时定义includePath + * @param bool $reset + * | 是否覆盖已经存在的定义,默认false + * @throws Exception + */ + public static function register($path, $alias = '', $includePath = false, $reset = false) + { + if (!$path) { + return; + } + if (!empty($alias)) { + $alias = strtolower($alias); + if (!isset(self::$_namespace[$alias]) || $reset) { + self::$_namespace[$alias] = rtrim( + $path, '\\/').DIRECTORY_SEPARATOR; + } + } + if ($includePath) { + if (empty(self::$_includePaths)) { + self::$_includePaths = array_unique(explode(PATH_SEPARATOR, get_include_path())); + if (($pos = array_search('.', self::$_includePaths, true)) !== false) { + unset( + self::$_includePaths[$pos]); + } + } + array_unshift(self::$_includePaths, $path); + if (set_include_path( + '.'.PATH_SEPARATOR.implode(PATH_SEPARATOR, self::$_includePaths)) === false) { + throw new Exception('[Wind.register] set include path error.'); + } + } + } + + /** + * 返回命名空间的路径信息 + * + * @param string $namespace + * @return string Ambigous multitype:> + */ + public static function getRootPath($namespace) + { + $namespace = strtolower($namespace); + + return isset(self::$_namespace[$namespace]) ? self::$_namespace[$namespace] : ''; + } + + /** + * 类文件自动加载方法 callback + * + * @param string $className + * @param string $path + */ + public static function autoLoad($className, $path = '') + { + $filePath = $className.'.'.self::$_extensions; + + if ($path) { + $filePath = $path.'.'.self::$_extensions; + } elseif (isset(self::$_classes[$className])) { + $filePath = self::$_classes[$className].'.'.self::$_extensions; + } + + if (file_exists($filePath) && is_file($filePath)) { + include $filePath; + } + } + + /** + * 解析路径信息,并返回路径的详情 + * + * @param string $filePath + * 路径信息 + * @param bool $suffix + * 是否存在文件后缀true,false,default + * @return string array('isPackage','fileName','extension','realPath') + */ + public static function getRealPath($filePath, $suffix = '', $absolut = false) + { + if (false !== strpos($filePath, DIRECTORY_SEPARATOR)) { + return realpath($filePath); + } + if (false !== ($pos = strpos($filePath, ':'))) { + $namespace = self::getRootPath(substr($filePath, 0, $pos)); + $filePath = substr($filePath, $pos + 1); + } else { + $namespace = $absolut ? self::getRootPath(self::getAppName()) : ''; + } + + $filePath = str_replace('.', '/', $filePath); + $namespace && $filePath = $namespace.$filePath; + if ($suffix === '') { + return $filePath.'.'.self::$_extensions; + } + if ($suffix === true && false !== ($pos = strrpos($filePath, '/'))) { + $filePath[$pos] = '.'; + + return $filePath; + } + + return $suffix ? $filePath.'.'.$suffix : $filePath; + } + + /** + * 解析路径信息,并返回路径的详情 + * + * @param string $filePath + * 路径信息 + * @param bool $absolut + * 是否返回绝对路径 + * @return string array('isPackage','fileName','extension','realPath') + */ + public static function getRealDir($dirPath, $absolut = false) + { + if (false !== ($pos = strpos($dirPath, ':'))) { + $namespace = self::getRootPath(substr($dirPath, 0, $pos)); + $dirPath = substr($dirPath, $pos + 1); + } else { + $namespace = $absolut ? self::getRootPath(self::getAppName()) : ''; + } + + return ($namespace ? $namespace : '').str_replace('.', '/', $dirPath); + } + + /** + * 初始化框架 + */ + public static function init() + { + self::$isDebug = WIND_DEBUG; + function_exists('date_default_timezone_set') && date_default_timezone_set('Etc/GMT+0'); + self::register(WIND_PATH, 'WIND', true); + if (!self::$_isAutoLoad) { + return; + } + if (function_exists('spl_autoload_register')) { + spl_autoload_register('Wind::autoLoad', true, false); + } else { + self::$_isAutoLoad = false; + } + } + + /** + * 日志记录 + * + * 调用WindLogger组建进行日志记录 + * @param string $message + * @param string $logType + * @throws WindMailException + */ + public static function log($message, $logType = 'wind.core') + { + if (self::$isDebug) { + $traces = debug_backtrace(); + if (isset($traces[1])) { + $message = "\r\n".$traces[0]['file'].' ('.$traces[0]['line'].') ['. + $traces[1]['class'].'::'.$traces[1]['function']."]\r\n".$message; + } + Wind::getComponent('windLogger')->info($message, $logType); + } + } + + /** + * + * @param string $className + * @param string $classPath + */ + private static function _setImport($className, $classPath) + { + self::$_imports[$classPath] = $className; + if (!isset(self::$_classes[$className])) { + $_classPath = self::getRealPath($classPath, false); + self::$_classes[$className] = $_classPath; + } else { + $_classPath = self::$_classes[$className]; + } + if (!self::$_isAutoLoad) { + self::autoLoad($className, $_classPath); + } + } } -Wind::init(); \ No newline at end of file +Wind::init(); diff --git a/wind/base/AbstractWindApplication.php b/wind/base/AbstractWindApplication.php new file mode 100644 index 00000000..eea05dcc --- /dev/null +++ b/wind/base/AbstractWindApplication.php @@ -0,0 +1,292 @@ +run,getRequest,getResponse,getWindFactory,自定义应用类型需要实现该接口. + * 基础实现有WindWebApplication + * @author Qiong Wu + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id: AbstractWindApplication.php 3919 2013-01-25 03:09:56Z yishuo $ + * @package base + */ +abstract class AbstractWindApplication extends WindModule +{ + /** + * 请求对象 + * + * @var WindHttpRequest + */ + protected $request; + + /** + * 响应对象 + * + * @var WindHttpResponse + */ + protected $response; + + /** + * 组建工厂对象 + * + * @var WindFactory + */ + protected $factory = null; + + /** + * 路由对象 + * + * @var WindRouter + */ + protected $handlerAdapter = null; + + /** + * 应用初始化操作 + * + * @param WindHttpRequest $request + * @param WindHttpResponse $response + * @param WindFactory $factory + */ + public function __construct($request, $response, $factory) + { + $this->response = $response; + $this->request = $request; + $this->factory = $factory; + } + + /** + * 请求处理完毕后,进一步分发 + * + * @param WindForward $forward + * @param bool $display + */ + abstract public function doDispatch($forward); + + /** + * 处理错误请求 + * 根据错误请求的相关信息,将程序转向到错误处理句柄进行错误处理 + * + * @param WindErrorMessage $errorMessage + * @param int $errorcode + */ + abstract protected function sendErrorMessage($errorMessage, $errorcode); + + /* + * (non-PHPdoc) @see IWindApplication::run() + */ + public function run($handlerAdapter = null) + { + $handlerAdapter !== null && $this->handlerAdapter = $handlerAdapter; + $module = $this->getModules(); + $handlerPath = $module['controller-path'].'.'.ucfirst($this->handlerAdapter->getController()).$module['controller-suffix']; + $className = Wind::import($handlerPath); + if (!class_exists($className)) { + throw new WindException( + 'Your requested \''.$handlerPath.'\' was not found on this server.', 404); + } + $handler = new $className(); + $handler->setDelayAttributes( + array('errorMessage' => array('ref' => 'errorMessage'), 'forward' => array('ref' => 'forward'))); + + $handlerAdapter !== null && $this->resolveActionFilters($handler); + + try { + $forward = $handler->doAction($this->handlerAdapter); + $this->doDispatch($forward); + } catch (WindForwardException $e) { + $this->doDispatch($e->getForward()); + } catch (WindActionException $e) { + $this->sendErrorMessage(($e->getError() ? $e->getError() : $e->getMessage()), $e->getCode()); + } catch (WindException $e) { + $this->sendErrorMessage($e->getMessage(), $e->getCode()); + } + } + + /** + * 添加module配置 + * + * controller + * + * Controller + * + * WIND:web.WindErrorHandler + * + * + * + * template + * + * htm + * + * @param string $name + * module名称 + * @param array $config + * 配置数组 + * @param bool $replace + * 如果module已经存在是否覆盖他 默认值为false不进行覆盖 + * @return array + */ + public function setModules($name, $config, $replace = false) + { + if ($replace || !isset($this->_config['modules'][$name])) { + $this->_config['modules'][$name] = (array) $config; + } + + return $this->_config['modules'][$name]; + } + + /** + * 获得module配置,$name为空时返回当前module配置 + * + * @param string $name + * module名称 默认为空 + * @param bool $merge + * 合并默认值 + * @return array + * @throws WindActionException + * @throws WindException + */ + public function getModules($name = '') + { + if ($name === '') { + $name = $this->handlerAdapter->getModule(); + } + if ($name === 'pattern') { + $name = $this->handlerAdapter->getDefaultModule(); + } + $_module = $this->getConfig('modules', $name, array()); + if (!isset($_module['_verified']) || $_module['_verified'] !== true) { + if (empty($_module) && !empty($this->_config['modules']['pattern'])) { + $_module = $this->_config['modules']['pattern']; + } + $_flag = empty($_module); + $_module = WindUtility::mergeArray($this->_config['modules']['default'], $_module); + $_module_str = implode('#', $_module); + if (strpos($_module_str, '{') !== false) { + preg_match_all('/{(\w+)}/i', $_module_str, $matches); + if (!empty($matches[1])) { + $_replace = array(); + foreach ($matches[1] as $key => $value) { + if ($value === $this->handlerAdapter->getModuleKey()) { + $_replace['{'.$value.'}'] = $this->handlerAdapter->getModule(); + } elseif ($value === $this->handlerAdapter->getControllerKey()) { + $_replace['{'.$value.'}'] = $this->handlerAdapter->getController(); + } elseif ($value === $this->handlerAdapter->getActionKey()) { + $_replace['{'.$value.'}'] = $this->handlerAdapter->getAction(); + } else { + $_replace['{'.$value.'}'] = $this->request->getGet($value); + } + } + $_module_str = strtr($_module_str, $_replace); + $_module = array_combine(array_keys($_module), explode('#', $_module_str)); + } + } elseif ($_flag) { + throw new WindException('Your request was not found on this server.', 404); + } + + $_module['_verified'] = true; + $this->_config['modules'][$name] = $_module; + } + + return $_module; + } + + /** + * 手动注册actionFilter + * 参数为数组格式: + * + * @param array $filters + */ + public function registeActionFilter($filters) + { + if (!$filters) { + return; + } + if (empty($this->_config['filters'])) { + $this->_config['filters'] = $filters; + } else { + $this->_config['filters'] += $filters; + } + } + + /** + * 解析action过滤链的配置信息 + * + * @param WindSimpleController $handler + */ + protected function resolveActionFilters(&$handler) + { + if (!$filters = $this->getConfig('filters')) { + return; + } + /* @var $cache AbstractWindCache */ + $_filters = array(); + if ($cache = Wind::getComponent('windCache')) { + $_filters = $cache->get('filters'); + } + $_token = $this->handlerAdapter->getModule().'/'.$this->handlerAdapter->getController().'/'.$this->handlerAdapter->getAction(); + if (!isset($_filters[$_token])) { + foreach ($filters as $_filter) { + if (empty($_filter['class'])) { + continue; + } + $_pattern = empty($_filter['pattern']) ? '' : $_filter['pattern']; + unset($_filter['pattern']); + if ($_pattern) { + $_pattern = str_replace(array('*', '/'), array('\w*', '\/'), $_pattern); + if (in_array($_pattern[0], array('~', '!'))) { + $_pattern = substr($_pattern, 1); + if (preg_match('/^'.$_pattern.'$/i', $_token)) { + continue; + } + } else { + if (!preg_match('/^'.$_pattern.'$/i', $_token)) { + continue; + } + } + } + $_filters[$_token][] = $_filter; + } + $cache && $cache->set('filters', $_filters); + } + if (empty($_filters[$_token])) { + return; + } + /* @var $proxy WindClassProxy */ + $proxy = new WindClassProxy(); + $proxy->registerTargetObject($handler); + foreach ($_filters[$_token] as $value) { + $proxy->registerEventListener( + $this->factory->createInstance(Wind::import($value['class']), + array($handler->getForward(), $handler->getErrorMessage(), $this->handlerAdapter, $value)), + 'doAction'); + } + $handler = $proxy; + } + + /** + * + * @return WindHttpRequest + */ + public function getRequest() + { + return $this->request; + } + + /** + * + * @return WindHttpResponse + */ + public function getResponse() + { + return $this->response; + } + + /** + * + * @return WindFactory + */ + public function getFactory() + { + return $this->factory; + } +} diff --git a/wind/base/AbstractWindBootstrap.php b/wind/base/AbstractWindBootstrap.php new file mode 100644 index 00000000..13835d7a --- /dev/null +++ b/wind/base/AbstractWindBootstrap.php @@ -0,0 +1,43 @@ + + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id$ + * @package wind + */ +abstract class AbstractWindBootstrap extends WindSimpleHandlerInterceptor +{ + /** + * @var AbstractWindFrontController + */ + protected $front = null; + + /** + * @param AbstractWindFrontController $front + */ + public function __construct($front = null) + { + $this->front = $front; + } + + /** + * 该方法在 application 创建之前被调用 + */ + abstract public function onCreate(); + + /** + * 该方法在路由之后,应用启动之前被调用 + */ + abstract public function onStart(); + + /** + * 该方法在应用运行结束,视图输出之前被调用 + */ + abstract public function onResponse(); +} diff --git a/wind/base/AbstractWindFrontController.php b/wind/base/AbstractWindFrontController.php index b3af0ea7..7f251a29 100644 --- a/wind/base/AbstractWindFrontController.php +++ b/wind/base/AbstractWindFrontController.php @@ -1,401 +1,329 @@ 2011-12-27 * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com * @version $$Id$$ * @package base */ -abstract class AbstractWindFrontController { - /** - * request类型定义 - * - * @var string - */ - protected $_request = null; - /** - * 组件工程实例对象 - * - * @var WindFactory - */ - protected $_factory = null; - /** - * 应用配置 - * - * @var array - */ - protected $_config = array(); - /** - * 当前app名称 - * - * @var string - */ - protected $_appName; - /** - * 应用对象数组 - * - * @var WindWebApplication - */ - private $_app = null; - /** - * @var WindHandlerInterceptorChain - */ - private $_chain = null; - /** - * @var AbstractWindCache - */ - private $_cache = null; - private $_cached = false; - protected $_errPage = 'error'; +abstract class AbstractWindFrontController +{ + /** + * 响应对象 + * + * @var WindHttpResponse + */ + protected $_response = null; + /** + * 请求对象 + * + * @var WindHttpRequest + */ + protected $_request = null; + /** + * 组件工程实例对象 + * + * @var WindFactory + */ + protected $_factory = null; + /** + * 应用配置 + * + * @var array + */ + protected $_config = array( + 'isclosed' => false, + 'web-apps' => array( + 'default' => array( + 'error-dir' => 'WIND:web.view', + 'compress' => true, + 'root-path' => '', + 'charset' => 'utf-8', + 'modules' => array( + 'default' => array( + 'controller-path' => 'controller', + 'controller-suffix' => 'Controller', + 'error-handler' => 'WindErrorHandler', ), ), ), ), + 'components' => array(), ); + /** + * 当前app名称 + * + * @var string + */ + protected $_appName = 'default'; + /** + * 应用对象数组 + * + * @var WindWebApplication + */ + protected $_app = null; + /** + * + * @var WindHandlerInterceptorChain + */ + private $_chain = null; - /** - * @param string $appName 默认app名称 - * @param Array|string $config 应用配置信息,支持为空或多应用配置 - */ - public function __construct($appName, $config) { - set_error_handler(array($this, '_errorHandle'), error_reporting()); - set_exception_handler(array($this, '_exceptionHandle')); - $appName && $this->_appName = $appName; - $this->_config = $config; - } + /** + * + * @param string $appName + * 默认app名称 + * @param Array|string $config + * 应用配置信息,支持为空或多应用配置 + */ + public function __construct($appName, $config) + { + $appName && $this->_appName = $appName; + $this->init($config); + } - /** - * 创建并返回应用对象实例 - * - * @return WindWebApplication - */ - abstract protected function _createApplication(); + /** + * 预加载系统文件,返回预加载系统文件数据 + * 预加载系统文件格式如下,键值为类名=>值为类的includePath,可以是相对的(如果includePath中已经包含了该地址) + * 也可以是绝对地址,但不能是wind的命名空间形式的地址
+     * return array(
+     * 'WindController' => 'web/WindController',
+     * 'WindDispatcher' => 'web/WindDispatcher'
+     * 
+ * + * @return array + */ + abstract protected function _loadBaseLib(); - /** - * 预加载系统文件,返回预加载系统文件数据 - * - * 预加载系统文件格式如下,键值为类名=>值为类的includePath,可以是相对的(如果includePath中已经包含了该地址) - * 也可以是绝对地址,但不能是wind的命名空间形式的地址
-	 * return array(
-	 * 		'WindController' => 'web/WindController', 
-	 *		'WindDispatcher' => 'web/WindDispatcher'
-	 * 
- * @return void - * @return array - */ - abstract protected function _loadBaseLib(); + /** + * 返回组建定义信息 + * 组件的配置标签说明: + * name: 组件的名字,唯一用于在应用中获取对应组件的对象实例 + * path: 该组件的实现 + * scope: 组件对象的范围: {singleton: 单例; application: 整个应用; prototype: 当前使用} + * initMethod: 在应用对象生成时执行的方法 + * destroy: 在应用结束的时候执行的操作 + * proxy: 组件是否用代理的方式调用 + * constructor-args:构造方法的参数 + * constructor-arg: + * name:参数的位置,起始位置从0开始,第一个参数为0,第二个参数为1 + * 参数的值的表示方式有一下几种: + * ref: 该属性是一个对象,ref的值对应着组件的名字 + * value: 一个字串值 + * path: path指向的类的实例将会被创建传递给该属性 + * properties: 属性的配置,表现为组件中的类属性 + * property: + * name:属性名称 + * 属性值的表示方式有以下几种: + * ref: 该属性是一个对象,ref的值对应着组件的名字,表现为在组件中获取方式为“_get+属性名()”称来获取 + * value: 一个字串值 + * path: path指向的类的实例将会被创建传递给该属性 + * config: 组件的配置-该值对应的配置会通过setConfig接口传递给组件; + * resource: 指定一个外部地址,将会去包含该文件 + * + * @return array() + */ + abstract protected function _components(); - /** - * 返回组建定义信息 - * - * 组件的配置标签说明: - * name: 组件的名字,唯一用于在应用中获取对应组件的对象实例 - * path: 该组件的实现 - * scope: 组件对象的范围: {singleton: 单例; application: 整个应用; prototype: 当前使用} - * initMethod: 在应用对象生成时执行的方法 - * destroy: 在应用结束的时候执行的操作 - * proxy: 组件是否用代理的方式调用 - * - * constructor-args:构造方法的参数 - * constructor-arg: - * name:参数的位置,起始位置从0开始,第一个参数为0,第二个参数为1 - * 参数的值的表示方式有一下几种: - * ref: 该属性是一个对象,ref的值对应着组件的名字 - * value: 一个字串值 - * path: path指向的类的实例将会被创建传递给该属性 - * - * properties: 属性的配置,表现为组件中的类属性 - * property: - * name:属性名称 - * 属性值的表示方式有以下几种: - * ref: 该属性是一个对象,ref的值对应着组件的名字,表现为在组件中获取方式为“_get+属性名()”称来获取 - * value: 一个字串值 - * path: path指向的类的实例将会被创建传递给该属性 - * - * - * config: 组件的配置-该值对应的配置会通过setConfig接口传递给组件; - * resource: 指定一个外部地址,将会去包含该文件 - * - * @return array() - */ - abstract protected function _components(); + /** + * 创建并初始化应用配置 + * + * @param array $config + * 当前应用配置信息 + * @param WindFactory $factory + * @return WindWebApplication + */ + abstract protected function createApplication($config, $factory); - /** - * 创建并返回应用实例 - * - * @deprecated - * @return WindWebApplication - */ - public function createApplication() { - if ($this->_app === null) { - $application = $this->_createApplication(); - /* @var $application WindWebApplication */ - if (!empty($this->_config['web-apps'][$this->_appName])) { - if ($this->_appName !== 'default' && isset($this->_config['web-apps']['default']) && !isset( - $this->_config['web-apps'][$this->_appName]['_merged'])) { - $this->_config['web-apps'][$this->_appName] = WindUtility::mergeArray( - $this->_config['web-apps']['default'], $this->_config['web-apps'][$this->_appName]); - $this->_config['web-apps'][$this->_appName]['_merged'] = true; - } - $application->setConfig($this->_config['web-apps'][$this->_appName]); - } - $this->_app = $application; - } - return $this->_app; - } + /** + * 初始化前端控制器 + *
    + *
  • 初始化应用配置
  • + *
  • 加载类加载器,拥有系统初始化加速
  • + *
  • 初始化组建工厂,组建工厂的组建分为,系统配置和自定义配置
  • + *
  • 初始化应用根目录
  • + *
+ * + * @param array|string $config + * 应用配置 + */ + protected function init($config) + { + $factory = WindFactory::_getInstance(); + $factory->setClassDefinitions($this->_components()); + $this->_loadBaseLib(); + $this->_initConfig($config, $factory); + if (!empty($this->_config['components'])) { + if (!empty($this->_config['components']['resource'])) { + $this->_config['components'] += $factory->getInstance('configParser')->parse( + Wind::getRealPath($this->_config['components']['resource'], true, true)); + } + $factory->loadClassDefinitions($this->_config['components']); + } + $rootPath = empty($this->_config['web-apps'][$this->_appName]['root-path']) ? dirname( + $_SERVER['SCRIPT_FILENAME']) : Wind::getRealPath( + $this->_config['web-apps'][$this->_appName]['root-path'], false); + Wind::register($rootPath, $this->_appName, true); - /** - * 创建并执行当前应用,单应用访问入口 - */ - public function run() { - $this->initConfig(); - - $this->_appName || $this->_appName = 'default'; - /* @var $router WindRouter */ - $router = $this->getFactory()->getInstance('router'); - $router->route($this->getRequest()); - $this->_run(); - } + if ($this->_appName === 'default') { + } elseif (isset( + $this->_config['web-apps'][$this->_appName])) { + $this->_config['web-apps'][$this->_appName] = WindUtility::mergeArray( + $this->_config['web-apps']['default'], $this->_config['web-apps'][$this->_appName]); + } else { + throw new WindException( + 'Your requested application \''.$this->_appName.'\' was not found on this server, please check your application configuration.', + WindException::ERROR_SYSTEM_ERROR); + } + } - /** - * 注册过滤器,监听Application Run - * - * @param WindHandlerInterceptor $filter - */ - public function registeFilter($filter) { - if (!$filter instanceof WindHandlerInterceptor) return; - if ($this->_chain === null) { - Wind::import("WIND:filter.WindHandlerInterceptorChain"); - $this->_chain = new WindHandlerInterceptorChain(); - } - $this->_chain->addInterceptors($filter); - } + /** + * 初始化配置信息 + * + * @param array|string $config + * @param WindFactory $factory + */ + protected function _initConfig($config, $factory) + { + if (!$config) { + return; + } + if (is_string($config)) { + $config = $factory->getInstance('configParser')->parse($config); + } + $this->_config = WindUtility::mergeArray($this->_config, $config); + } - /** - * 注册组件对象 - * - * @param object $componentInstance - * @param string $componentName - * @param string $scope 默认值为 'application' - */ - public function registeComponent($componentInstance, $componentName, $scope = 'application') { - switch ($componentName) { - case 'windCache': - $this->_cache = $componentInstance; - $this->_cache->setKeyPrefix($this->_appName . '_system_'); - $this->getFactory()->registInstance($this->_cache, $componentName, 'application'); - break; - case 'request': - $this->_request = $componentInstance; - break; - default: - $this->getFactory()->registInstance($componentInstance, $componentName, $scope); - break; - } - } + /** + * 创建并执行当前应用,单应用访问入口 + */ + public function run() + { + $this->_app = $this->createApplication($this->_config['web-apps'][$this->_appName], + WindFactory::_getInstance()); - /** - * 返回当前app应用名称 - * - * @return string - */ - public function getAppName() { - return $this->_appName; - } + set_error_handler(array($this, '_errorHandle'), error_reporting()); + set_exception_handler(array($this, '_exceptionHandle')); + if ($this->_config['isclosed']) { + throw new Exception('Sorry, Site has been closed!'); + } + if ($this->_chain !== null) { + $this->_chain->getHandler()->handle('onCreate'); + } + /* @var $router WindRouter */ + $router = $this->_app->getFactory()->getInstance('router'); + $router->route($this->_app->getRequest()); - /** - * 返回当前的app应用 - * - * @param string $appName - * @return WindWebApplication - */ - public function getApp() { - return $this->_app; - } + if ($this->_chain !== null) { + $this->_chain->getHandler()->handle('onStart'); + } + $this->_app->run($router); - /** - * @return WindHttpRequest - */ - public function getRequest() { - if ($this->_request === null) { - $this->_request = WindFactory::createInstance('WindHttpRequest'); - } - return $this->_request; - } + if ($this->_chain !== null) { + $this->_chain->getHandler()->handle('onResponse'); + } + $this->_app->getResponse()->sendResponse(); + $this->_app->getFactory()->executeDestroyMethod(); + restore_error_handler(); + restore_exception_handler(); + } - /** - * @return WindFactory - */ - public function getFactory() { - if ($this->_factory === null) { - if ($this->_cache !== null && ($classes = $this->_cache->get('classes'))) { - $imports = $this->_cache->get('imports'); - $classes && Wind::$_classes += $classes; - $imports && Wind::$_imports += $imports; - $this->_factory = $this->_cache->get('factory'); - $this->_config = $this->_cache->get('config'); - $this->_cached = true; - } - if (!$this->_factory) { - $this->_loadBaseLib(); - $this->_factory = new WindFactory($this->_components()); - } - } - return $this->_factory; - } + /** + * 注册过滤器,监听Application Run + * + * @param WindHandlerInterceptor $filter + */ + public function registeFilter($filter) + { + if ($this->_chain === null) { + $this->_chain = new WindHandlerInterceptorChain(); + } + if ($filter instanceof AbstractWindBootstrap) { + $this->_chain->addInterceptors($filter); + } + } - /** - * 异常处理句柄 - * - * @param Exception $exception - */ - public function _exceptionHandle($exception) { - restore_error_handler(); - restore_exception_handler(); - $trace = $exception->getTrace(); - if (@$trace[0]['file'] == '') { - unset($trace[0]); - $trace = array_values($trace); - } - $file = @$trace[0]['file']; - $line = @$trace[0]['line']; - $this->showErrorMessage($exception->getMessage(), $file, $line, $trace, $exception->getCode()); - } + /** + * 错误处理句柄 + * + * @param int $errno + * @param string $errstr + * @param string $errfile + * @param int $errline + */ + public function _errorHandle($errno, $errstr, $errfile, $errline) + { + if (0 === error_reporting()) { + return; + } + restore_error_handler(); + /* @var $error WindError */ + $error = $this->_app->getFactory()->getInstance('error', + array( + $this->_config['web-apps'][$this->_appName]['error-dir'], + $this->_config['isclosed'], )); + $error->errorHandle($errno, $errstr, $errfile, $errline); + } - /** - * 错误处理句柄 - * - * @param int $errno - * @param string $errstr - * @param string $errfile - * @param int $errline - */ - public function _errorHandle($errno, $errstr, $errfile, $errline) { - restore_error_handler(); - restore_exception_handler(); - $trace = debug_backtrace(); - unset($trace[0]["function"], $trace[0]["args"]); - $this->showErrorMessage($this->_friendlyErrorType($errno) . ': ' . $errstr, $errfile, $errline, $trace, $errno); - } + /** + * Exception处理 + * + * @param Exception $exception + */ + public function _exceptionHandle($exception) + { + restore_exception_handler(); + /* @var $error WindError */ + $error = $this->_app->getFactory()->getInstance('error', + array( + $this->_config['web-apps'][$this->_appName]['error-dir'], + $this->_config['isclosed'], )); + $error->exceptionHandle($exception); + } - /** - * 错误处理 - * - * @param string $message - * @param string $file 异常文件 - * @param int $line 错误发生的行 - * @param array $trace - * @param int $errorcode 错误代码 - * @throws WindFinalException - */ - protected function showErrorMessage($message, $file, $line, $trace, $errorcode) { - if (WIND_DEBUG & 2) { - $log = $message . "\r\n" . $file . ":" . $line . "\r\n"; - list($fileLines, $trace) = WindUtility::crash($file, $line, $trace); - foreach ($trace as $key => $value) { - $log .= $value . "\r\n"; - } - Wind::getApp()->getComponent('windLogger')->error($log, 'error', true); - } - } + /** + * 根据配置名取得相应的配置 + * 当configName为空时则返回整个配置.当配置值不存在时返回默认值.默认值默认为空 + * + * @param string $configName 键名 + * @param string $subConfigName 二级键名 + * @param string $default 默认值 + * @param array $config 外部配置 + * @return mixed + */ + public function getConfig($configName = '', $subConfigName = '', $default = '') + { + if ($configName === '') { + return $this->_config; + } + if (!isset($this->_config[$configName])) { + return $default; + } + if ($subConfigName === '') { + return $this->_config[$configName]; + } + if (!isset($this->_config[$configName][$subConfigName])) { + return $default; + } - /** - * 创建并运行当前应用 - * - * 配合过滤链策略部署,可以通过{@see AbstractWindFrontController::registeFilter} - * 方法注册过滤器,当应用被执行时会判断当前时候有初始化过滤链对象,并选择是否是通过过滤链方式执行应用 - * @return void - */ - protected function _run() { - $application = $this->createApplication(); - if ($this->_chain !== null) { - $this->_chain->setCallBack(array($application, 'run'), array(true)); - $this->_chain->getHandler()->handle($this); - } else - $application->run($application->getConfig('filters')); - restore_error_handler(); - restore_exception_handler(); - $this->_app->getResponse()->sendResponse(); - $this->_app->getWindFactory()->executeDestroyMethod(); - if ($this->_cache !== null && $this->_cached === false) { - $this->_cache->set('factory', $this->_factory); - $this->_cache->set('classes', Wind::$_classes); - $this->_cache->set('imports', Wind::$_imports); - $this->_cache->set('config', $this->_config); - } - } + return $this->_config[$configName][$subConfigName]; + } - /** - * 初始化配置信息 - * - * @param array $config - */ - protected function initConfig() { - if (!$this->_config) return; - if (is_string($this->_config)) { - $this->_config = $this->getFactory()->getInstance('configParser')->parse($this->_config); - } - if (isset($this->_config['isclosed']) && $this->_config['isclosed']) { - if ($this->_config['isclosed-tpl']) - $this->_errPage = $this->_config['isclosed-tpl']; - else - $this->_errPage = 'close'; - throw new Exception('Sorry, Site has been closed!'); - } - if (!empty($this->_config['components'])) { - if (!empty($this->_config['components']['resource'])) { - $this->_config['components'] += $this->getFactory()->getInstance('configParser')->parse( - Wind::getRealPath($this->_config['components']['resource'], true, true)); - } - $this->getFactory()->loadClassDefinitions($this->_config['components']); - unset($this->_config['components']); - } - if (empty($this->_config['web-apps'])) return; - foreach ($this->_config['web-apps'] as $key => $value) { - $rootPath = empty($value['root-path']) ? dirname($_SERVER['SCRIPT_FILENAME']) : Wind::getRealPath( - $value['root-path'], false); - Wind::register($rootPath, $key, true); - } - } + /** + * 返回当前app应用名称 + * + * @return string + */ + public function getAppName() + { + return $this->_appName; + } - /** - * 返回友好的错误类型名 - * - * @param int $type - * @return string|unknown - */ - private function _friendlyErrorType($type) { - switch ($type) { - case E_ERROR: - return 'E_ERROR'; - case E_WARNING: - return 'E_WARNING'; - case E_PARSE: - return 'E_PARSE'; - case E_NOTICE: - return 'E_NOTICE'; - case E_CORE_ERROR: - return 'E_CORE_ERROR'; - case E_CORE_WARNING: - return 'E_CORE_WARNING'; - case E_CORE_ERROR: - return 'E_COMPILE_ERROR'; - case E_CORE_WARNING: - return 'E_COMPILE_WARNING'; - case E_USER_ERROR: - return 'E_USER_ERROR'; - case E_USER_WARNING: - return 'E_USER_WARNING'; - case E_USER_NOTICE: - return 'E_USER_NOTICE'; - case E_STRICT: - return 'E_STRICT'; - case E_RECOVERABLE_ERROR: - return 'E_RECOVERABLE_ERROR'; - case E_DEPRECATED: - return 'E_DEPRECATED'; - case E_USER_DEPRECATED: - return 'E_USER_DEPRECATED'; - } - return $type; - } + /** + * 返回当前的app应用 + * + * @param string $appName + * @return WindWebApplication + */ + public function getApp() + { + return $this->_app; + } } -?> \ No newline at end of file diff --git a/wind/base/IWindApplication.php b/wind/base/IWindApplication.php index c13874ae..7da9ccba 100644 --- a/wind/base/IWindApplication.php +++ b/wind/base/IWindApplication.php @@ -1,44 +1,42 @@ run,getRequest,getResponse,getWindFactory,自定义应用类型需要实现该接口. * 基础实现有WindWebApplication * @author Qiong Wu * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: IWindApplication.php 3829 2012-11-19 11:13:22Z yishuo $ * @package base */ -interface IWindApplication { +interface IWindApplication +{ + /** + * 调用该方法启动应用 + * + * @throws Exception + */ + public function run(); - /** - * 调用该方法启动应用 - * - * @return void - * @throws Exception - */ - public function run(); + /** + * 返回WindHttpRequest + * + * @return WindHttpRequest $request + */ + public function getRequest(); - /** - * 返回WindHttpRequest - * - * @return WindHttpRequest $request - */ - public function getRequest(); + /** + * 返回WindHttpResponse + * + * @return WindHttpResponse $response + */ + public function getResponse(); - /** - * 返回WindHttpResponse - * - * @return WindHttpResponse $response - */ - public function getResponse(); - - /** - * 返回WindFactory - * - * @return WindFactory $windFactory - */ - public function getWindFactory(); + /** + * 返回WindFactory + * + * @return WindFactory $windFactory + */ + public function getFactory(); } -?> \ No newline at end of file diff --git a/wind/base/IWindController.php b/wind/base/IWindController.php new file mode 100644 index 00000000..278fd18c --- /dev/null +++ b/wind/base/IWindController.php @@ -0,0 +1,18 @@ + + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id: codetemplates(windframework_docs_zend_8.0).xml 2781 2011-09-22 03:59:17Z yishuo $ + * @package wind + */ +interface IWindController +{ + /** + * @param AbstractWindRouter $handlerAdapter + * @return WindForward + */ + public function doAction($handlerAdapter); +} diff --git a/wind/base/IWindFactory.php b/wind/base/IWindFactory.php deleted file mode 100644 index f4b9b719..00000000 --- a/wind/base/IWindFactory.php +++ /dev/null @@ -1,35 +0,0 @@ -getInstance,createInstance. - * 'getInstance'创建并返回类的实例对象,'createInstance'静态方法,用于创建类对象. - * @author Qiong Wu - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package base - */ -interface IWindFactory { - - /** - * 创建并返回类的实例对象 - * - * 通过调用该方法,获取类的实例对象.当类的实例对象不存在时调用{@link createInstance}方法创建. - * 通过该方法创建类对象,需要确定该类的组件定义已经被加载.如果未被加载则返回一个null. - * @param string $classAlias 类别名 组件定义名称 必须填写 - * @param array $args 参数列表 - * @return instance 返回类实例对象 - */ - public function getInstance($classAlias, $args = array()); - - /** - * 创建并返回类对象 - * - * 返回一个类类型的实例对象,通过此方法创建类实例,并不能自动获取类路径信息 - * @param string $className 类名称 - * @param array $args 类参数信息 - * @return Object 返回类的实例对象 - */ - static public function createInstance($className, $args = array()); -} \ No newline at end of file diff --git a/wind/base/IWindRequest.php b/wind/base/IWindRequest.php index 3b5b4a7c..7b1cc6d6 100644 --- a/wind/base/IWindRequest.php +++ b/wind/base/IWindRequest.php @@ -5,86 +5,77 @@ * @author Qiong Wu * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: IWindRequest.php 3829 2012-11-19 11:13:22Z yishuo $ * @package http * @subpackage request */ -interface IWindRequest { - /** - * 返回包含由客户端提供的、跟在真实脚本名称之后并且在查询语句(query string)之前的路径信息 - * - * @return string - * @throws WindException - */ - public function getPathInfo(); +interface IWindRequest +{ + /** + * 返回包含由客户端提供的、跟在真实脚本名称之后并且在查询语句(query string)之前的路径信息 + * + * @return string + * @throws WindException + */ + public function getPathInfo(); - /** - * 获得请求类型 - * - * 如果是web请求将返回web - * @return string - */ - public function getRequestType(); + /** + * 获得请求类型 + * + * 如果是web请求将返回web + * @return string + */ + public function getRequestType(); - /** - * 获得主机信息,包含协议信息,主机名,访问端口信息 - * - * @return string - * @throws WindException 获取主机信息失败的时候抛出异常 - */ - public function getHostInfo(); + /** + * 获得主机信息,包含协议信息,主机名,访问端口信息 + * + * @return string + * @throws WindException 获取主机信息失败的时候抛出异常 + */ + public function getHostInfo(); - /** - * 返回当前运行脚本所在的服务器的主机名。 - * - * 如果脚本运行于虚拟主机中 - * 该名称是由那个虚拟主机所设置的值决定 - * @return string - */ - public function getServerName(); + /** + * 返回当前运行脚本所在的服务器的主机名。 + * + * 如果脚本运行于虚拟主机中 + * 该名称是由那个虚拟主机所设置的值决定 + * @return string + */ + public function getServerName(); - /** - * 返回服务端口号 - * - * https链接的默认端口号为443 - * http链接的默认端口号为80 - * @return int - */ - public function getServerPort(); + /** + * 返回服务端口号 + * + * https链接的默认端口号为443 + * http链接的默认端口号为80 + * @return int + */ + public function getServerPort(); - /** - * @return IWindResponse - */ - public function getResponse(); + /** + * 返回客户端程序期望服务器返回哪个国家的语言文档 + * + * Accept-Language: en-us,zh-cn + * @return string + */ + public function getAcceptLanguage(); - /** - * 返回客户端程序期望服务器返回哪个国家的语言文档 - * - * Accept-Language: en-us,zh-cn - * @return string - */ - public function getAcceptLanguage(); + /** + * 设置属性数据 + * + * @param string|array|object $data 需要设置的数据 + * @param string $key 设置的数据保存用的key,默认为空,当数组和object类型的时候将会执行array_merge操作 + */ + public function setAttribute($data, $key = ''); - /** - * 设置属性数据 - * - * @param string|array|object $data 需要设置的数据 - * @param string $key 设置的数据保存用的key,默认为空,当数组和object类型的时候将会执行array_merge操作 - * @return void - */ - public function setAttribute($data, $key = ''); - - /** - * 根据名称获得服务器和执行环境信息 - * - * 主要获取的依次顺序为:_attribute、$_GET、$_POST、$_COOKIE、$_REQUEST、$_ENV、$_SERVER - * @param string $name 获取数据的key值 - * @param string $defaultValue 设置缺省值,当获取值失败的时候返回缺省值,默认该值为空字串 - * @return string|object|array 返回获得值 - */ - public function getAttribute($key, $defaultValue = ''); -} - - - - + /** + * 根据名称获得服务器和执行环境信息 + * + * 主要获取的依次顺序为:_attribute、$_GET、$_POST、$_COOKIE、$_REQUEST、$_ENV、$_SERVER + * @param string $name 获取数据的key值 + * @param string $defaultValue 设置缺省值,当获取值失败的时候返回缺省值,默认该值为空字串 + * @return string|object|array 返回获得值 + */ + public function getAttribute($key, $defaultValue = ''); +} diff --git a/wind/base/IWindResponse.php b/wind/base/IWindResponse.php index c0f03eb4..d000ac95 100644 --- a/wind/base/IWindResponse.php +++ b/wind/base/IWindResponse.php @@ -5,81 +5,74 @@ * @author Qiong Wu 2010-11-7 * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: IWindResponse.php 3533 2012-05-08 08:24:20Z yishuo $ * @package http * @subpackage response */ -interface IWindResponse { +interface IWindResponse +{ + /** + * 获得保存输出数据 + * + * @param string $var + * @return mixed + */ + public function getData(); - /** - * 获得保存输出数据 - * - * @param string $var - * @return mixed - */ - public function getData(); + /** + * 设置保存输出数据 + * + * @param mixed $data 待保存的输出数据 + * @param string $key 输出数据的key名称,默认为空 + */ + public function setData($data, $key = ''); - /** - * 设置保存输出数据 - * - * @param mixed $data 待保存的输出数据 - * @param string $key 输出数据的key名称,默认为空 - */ - public function setData($data, $key = ''); + /** + * 获得输出的编码方式 + * + * @return string + */ + public function getCharset(); - /** - * 获得输出的编码方式 - * - * @return string - */ - public function getCharset(); + /** + * 设置输出的编码方式 + * + * @param string $_charset 编码方式 + */ + public function setCharset($_charset); - /** - * 设置输出的编码方式 - * - * @param string $_charset 编码方式 - * @return void - */ - public function setCharset($_charset); + /** + * 设置响应内容 + * + * @param string $content 响应内容信息 + * @param string $name 相应内容片段名字,默认为null + */ + public function setBody($content, $name = 'default'); - /** - * 设置响应内容 - * - * @param string $content 响应内容信息 - * @param string $name 相应内容片段名字,默认为null - * @return void - */ - public function setBody($content, $name = 'default'); + /** + * 发送一个错误的响应信息 + * + * @param int $status 错误码,默认为404 + * @param string $message 错误信息,默认为空 + */ + public function sendError($status = self::W_NOT_FOUND, $message = ''); - /** - * 发送一个错误的响应信息 - * - * @param int $status 错误码,默认为404 - * @param string $message 错误信息,默认为空 - * @return void - */ - public function sendError($status = self::W_NOT_FOUND, $message = ''); + /** + * 发送响应内容 + * + */ + public function sendBody(); - /** - * 发送响应内容 - * - * @return void - */ - public function sendBody(); + /** + * 发送响应头部信息 + * + */ + public function sendHeaders(); - /** - * 发送响应头部信息 - * - * @return void - */ - public function sendHeaders(); - - /** - * 发送响应信息 - * - * 依次发送响应头和响应内容 - * @return void - */ - public function sendResponse(); - -} \ No newline at end of file + /** + * 发送响应信息 + * + * 依次发送响应头和响应内容 + */ + public function sendResponse(); +} diff --git a/wind/base/WindActionException.php b/wind/base/WindActionException.php index 91e5c634..6aa53b4d 100644 --- a/wind/base/WindActionException.php +++ b/wind/base/WindActionException.php @@ -1,54 +1,60 @@ * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindActionException.php 2973 2011-10-15 19:22:48Z yishuo $ * @package base */ -class WindActionException extends WindException { - /** - * @var WindErrorMessage - */ - private $error = null; +class WindActionException extends WindException +{ + /** + * @var WindErrorMessage + */ + private $error = null; - /** - * @param WindErrorMessage|string $error 异常描述或者错误处理类 - * @param int $code 错误码 - */ - public function __construct($error, $code = 0) { - if ($error instanceof WindErrorMessage) { - $this->setError($error); - parent::__construct($error->getError(0), $code); - } else - parent::__construct($error, $code); - } + /** + * @param WindErrorMessage|string $error 异常描述或者错误处理类 + * @param int $code 错误码 + */ + public function __construct($error, $code = 0) + { + if ($error instanceof WindErrorMessage) { + $this->setError($error); + parent::__construct($error->getError(0), $code); + } else { + parent::__construct($error, $code); + } + } - /* (non-PHPdoc) - * @see WindException::messageMapper() - */ - protected function messageMapper($code) { - $messages = array(); - return isset($messages[$code]) ? $messages[$code] : '$message'; - } + /* (non-PHPdoc) + * @see WindException::messageMapper() + */ + protected function messageMapper($code) + { + $messages = array(); - /** - * @return WindErrorMessage - */ - public function getError() { - return $this->error; - } + return isset($messages[$code]) ? $messages[$code] : '$message'; + } - /** - * @param WindErrorMessage $error - */ - public function setError($error) { - $this->error = $error; - } + /** + * @return WindErrorMessage + */ + public function getError() + { + return $this->error; + } + + /** + * @param WindErrorMessage $error + */ + public function setError($error) + { + $this->error = $error; + } } -?> \ No newline at end of file diff --git a/wind/base/WindClassProxy.php b/wind/base/WindClassProxy.php deleted file mode 100644 index a4170113..00000000 --- a/wind/base/WindClassProxy.php +++ /dev/null @@ -1,239 +0,0 @@ - - * //相关组件配置,只需设置 proxy为true,就可以通过组件工厂创建一个具有代理功能的类实例对象. - * - * - * - * - * - * - * $object = Wind::getApp()->getFactory()->getInstance('windApplication'); - * $object->registerEventListener('runProcess', new Listener()); - * - * @author Qiong Wu - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package base - */ -class WindClassProxy { - const EVENT_TYPE_METHOD = 'method'; - const EVENT_TYPE_SETTER = 'setter'; - const EVENT_TYPE_GETTER = 'getter'; - - /** - * 默认过滤链类型定义 - * - * @var string - */ - private $_interceptorChain = 'WIND:filter.WindHandlerInterceptorChain'; - /** - * 过滤链对象 - * - * @var WindHandlerInterceptorChain - */ - private $_interceptorChainObj = null; - protected $_className = ''; - protected $_classPath = ''; - protected $_instance = null; - protected $_listener = array(); - - /** - * @param object $targetObj 需要被代理监听的类对象实例 默认为null - */ - public function __construct($targetObject = null) { - $this->registerTargetObject($targetObject); - } - - /** - * 注册事件以及事件监听类 - * - * 通过调用该方法,将事件以及对事件的监听方法注册进来,当事件方法被调用的时候监听的方法被触发.例: - * ... - * $object = Wind::getApp()->getFactory()->getInstance('windApplication'); - * $object->registerEventListener('runProcess', new Listener()); - * - * @param stinrg $event 被监听的事件 - * @param object $listener 事件监听器 - * @param string $type 事件监听类型 - * @return void - */ - public function registerEventListener($event, $listener, $type = self::EVENT_TYPE_METHOD) { - if (!in_array($type, array(self::EVENT_TYPE_METHOD, self::EVENT_TYPE_GETTER, self::EVENT_TYPE_SETTER))) { - throw new WindException('[base.WindClassProxy.registerEventListener] Unsupport event type:' . $type, WindException::ERROR_PARAMETER_TYPE_ERROR); - } - !isset($this->_listener[$type][$event]) && $this->_listener[$type][$event] = array(); - array_push($this->_listener[$type][$event], $listener); - } - - /** - * 注册目标对象,如果已经注册了不重复注册 - * - * WindFactory中创建类代理的一段例子: - * $instance = new Object(); - * $this->addClassDefinitions($alias, array('path' => $proxy, 'scope' => 'prototype')); - * $proxy = $this->getInstance($alias); - * $proxy->registerTargetObject($instance); - * $instance->_proxy = $proxy; - * 注意:$instance继承自WindModule - * @param object $targetObject - * @return WindClassProxy - */ - public function registerTargetObject($targetObject) { - if ($this->_instance !== null || !is_object($targetObject)) return; - $this->_setClassName(get_class($targetObject)); - $this->_instance = $targetObject; - $types = array(self::EVENT_TYPE_METHOD, self::EVENT_TYPE_GETTER, self::EVENT_TYPE_SETTER); - foreach ($types as $type) - $this->_listener[$type] = array(); - return $this; - } - - /** - * 该方法用于监听类属性 - * - * @param string $propertyName 属性名称 - * @param mixed $value 属性值 - * @deprecated - * @throws WindException - * @return mixed - */ - public function __set($propertyName, $value) { - $property = $this->_getReflection()->getProperty($propertyName); - if (!$property || !$property->isPublic()) { - throw new WindException('undefined property name. '); - } - $listeners = $this->_getListenerByType(self::EVENT_TYPE_SETTER, $propertyName); - if (empty($listeners)) return call_user_func_array(array($this, '_setProperty'), array($propertyName, $value)); - $interceptorChain = $this->_getInterceptorChain($propertyName); - $interceptorChain->addInterceptors($listeners); - $interceptorChain->setCallBack(array($this, '_setProperty'), array($propertyName, $value)); - return $interceptorChain->getHandler()->handle($value); - } - - /** - * 监听属性调用 - * - * @param string $propertyName 属性名 - * @deprecated - * @return mixed - */ - public function __get($propertyName) { - $property = $this->_getReflection()->getProperty($propertyName); - if (!$property || !$property->isPublic()) { - throw new WindException('undefined property name. '); - } - $listeners = $this->_getListenerByType(self::EVENT_TYPE_GETTER, $propertyName); - if (empty($listeners)) return call_user_func_array(array($this, '_getProperty'), array($propertyName)); - $interceptorChain = $this->_getInterceptorChain($propertyName); - $interceptorChain->addInterceptors($listeners); - $interceptorChain->setCallBack(array($this, '_getProperty'), array($propertyName)); - return $interceptorChain->getHandler()->handle($propertyName); - } - - /** - * 监听类方法 - * - * @param string $methodName 方法名 - * @param array $args 方法参数 - * @return mixed - * @throws WindException - */ - public function __call($methodName, $args) { - $listeners = $this->_getListenerByType(self::EVENT_TYPE_METHOD, $methodName); - if (empty($listeners)) return call_user_func_array(array($this->_getInstance(), $methodName), (array) $args); - $interceptorChain = $this->_getInterceptorChain($methodName); - $interceptorChain->addInterceptors($listeners); - $interceptorChain->setCallBack(array($this->_getInstance(), $methodName), $args); - return call_user_func_array(array($interceptorChain->getHandler(), 'handle'), (array) $args); - } - - /** - * 创建并返回过滤链,如果过滤链已经被创建不重复创建 - * - * @param string $event 事件名称 默认值为空 - * @return WindHandlerInterceptorChain - * @throws WindException - */ - private function _getInterceptorChain($event = '') { - if (null === $this->_interceptorChainObj) { - $chain = Wind::import($this->_interceptorChain); - $interceptorChain = WindFactory::createInstance($chain); - if ($interceptorChain && $interceptorChain instanceof WindHandlerInterceptorChain) { - $this->_interceptorChainObj = $interceptorChain; - } else - throw new WindException('[base.WindClassProxy._getInterceptorChain] Unable to create interceptorChain.'); - } - $this->_interceptorChainObj->reset(); - return $this->_interceptorChainObj; - } - - /** - * 获得事件的所有监听器 - * - * @param string $type 监听器类型 - * @param string $event 事件名称 - * @return array - */ - private function _getListenerByType($type, $event) { - $listener = array(); - if (isset($this->_listener[$type]) && isset($this->_listener[$type][$event])) { - $listener = $this->_listener[$type][$event]; - } - return $listener; - } - - /** - * 返回当前代理对象的真实类对象 - * - * @return object - */ - public function _getInstance() { - return $this->_instance; - } - - /** - * 返回当前代理对象的真实类名称 - * - * @return string - */ - public function _getClassName() { - return $this->_className; - } - - /** - * 返回当前代理对象的真实类的路径信息 - * - * @return string - */ - public function _getClassPath() { - return $this->_classPath; - } - - /** - * 设置类名称 - * - * @param string $className - * @return void - */ - public function _setClassName($className) { - $this->_className = $className; - } - - /** - * 设置类路径 - * - * @param string $classPath - * @return void - */ - public function _setClassPath($classPath) { - $this->_setClassName(Wind::import($classPath)); - $this->_classPath = $classPath; - } -} -?> \ No newline at end of file diff --git a/wind/base/WindEnableValidateModule.php b/wind/base/WindEnableValidateModule.php index bdd061bb..43007161 100644 --- a/wind/base/WindEnableValidateModule.php +++ b/wind/base/WindEnableValidateModule.php @@ -1,135 +1,150 @@ * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindEnableValidateModule.php 3904 2013-01-08 07:01:26Z yishuo $ * @package base */ -class WindEnableValidateModule { - /** - * 验证类 - * - * @var string - */ - protected $_validatorClass = 'WIND:utility.WindValidator'; - /** - * 错误处理action - * - * @var string - */ - protected $errorAction = ''; - /** - * 验证类实例 - * - * @var WindValidator - */ - private $_validator = null; - /** - * 验证中产生的错误信息 - * - * @var array - */ - protected $_errors = array(); - /** - * 验证中产生错误信息时使用的默认错误信息 - * - * @var string - */ - private $_defaultMessage = 'the field validate fail.'; +class WindEnableValidateModule +{ + /** + * 验证类 + * + * @var string + */ + protected $_validatorClass = 'WindValidator'; + /** + * 错误处理action + * + * @var string + */ + protected $errorAction = ''; + /** + * 验证类实例 + * + * @var WindValidator + */ + private $_validator = null; + /** + * 验证中产生的错误信息 + * + * @var array + */ + protected $_errors = array(); + /** + * 验证中产生错误信息时使用的默认错误信息 + * + * @var string + */ + private $_defaultMessage = 'the field validate fail.'; + + /** + * 返回验证中产生的错误信息 + * + * @return array $_errors + */ + public function getErrors() + { + return $this->_errors; + } + + /** + * 返回验证出错时使用的错误errorAction + * + * errorAction的格式可以用/分割m,c,a三个部分:完整的方式为m/c/a + * + * @return string + */ + public function getErrorAction() + { + return $this->errorAction; + } + + /** + * 返回验证规则组成的数组 + * + * 每一个验证规则都需要如下格式: + * + * array( + * 'field' => 'name', //验证的字段名 + * 'default' => 'test', //如果字段为空 + * 'args' => array('args1', 'args2'), //validator验证方法接受的其他参数(必须在被验证参数的后面) + * 'validator' => 'isEmpty', //执行的验证方法(该方法必须在$_validatorClass指向的验证类中存在并可公开访问,并且该方法返回boolean类型) + * 'message' => 'name is empty', //验证失败时返回的错误信息 + * ) + * + * 验证规则可以采用{@link WindUtility::buildValidateRule()}方法进行构造. + * + * @return array + */ + protected function validateRules() + { + return array(); + } + + /** + * 验证方法 + * + */ + public function validate() + { + $rules = $this->validateRules(); + $methods = get_class_methods($this); + foreach ((array) $rules as $rule) { + $getMethod = 'get'.ucfirst($rule['field']); + $_input = in_array($getMethod, $methods) ? call_user_func(array($this, $getMethod)) : ''; + if (true === $this->check($_input, $rule)) { + continue; + } + $setMethod = 'set'.ucfirst($rule['field']); + in_array($setMethod, $methods) && call_user_func_array(array($this, $setMethod), array($rule['default'])); + } + } + + /** + * 执行rule验证 + * + * @param string $input 待验证的数据 + * @param array $rule 数据验证的规则 + * @return bool 如果验证成功返回true,验证失败返回false + */ + private function check($input, $rule) + { + $arg = (array) $rule['args']; + array_unshift($arg, $input); + if (call_user_func_array(array($this->getValidator(), $rule['validator']), $arg) !== false) { + return true; + } + if ($rule['default'] === null) { + $this->_errors[$rule['field']] = $rule['message']; - /** - * 返回验证中产生的错误信息 - * - * @return array $_errors - */ - public function getErrors() { - return $this->_errors; - } + return true; + } - /** - * 返回验证出错时使用的错误errorAction - * - * errorAction的格式可以用/分割m,c,a三个部分:完整的方式为m/c/a - * - * @return string - */ - public function getErrorAction() { - return $this->errorAction; - } + return false; + } - /** - * 返回验证规则组成的数组 - * - * 每一个验证规则都需要如下格式: - * - * array( - * 'field' => 'name', //验证的字段名 - * 'default' => 'test', //如果字段为空 - * 'args' => array('args1', 'args2'), //validator验证方法接受的其他参数(必须在被验证参数的后面) - * 'validator' => 'isEmpty', //执行的验证方法(该方法必须在$_validatorClass指向的验证类中存在并可公开访问,并且该方法返回boolean类型) - * 'message' => 'name is empty', //验证失败时返回的错误信息 - * ) - * - * 验证规则可以采用{@link WindUtility::buildValidateRule()}方法进行构造. - * - * @return array - */ - protected function validateRules() { - return array(); - } - - /** - * 验证方法 - * - * @return void - */ - public function validate() { - $rules = $this->validateRules(); - $methods = get_class_methods($this); - foreach ((array) $rules as $rule) { - $getMethod = 'get' . ucfirst($rule['field']); - $_input = in_array($getMethod, $methods) ? call_user_func(array($this, $getMethod)) : ''; - if (true === $this->check($_input, $rule)) continue; - $setMethod = 'set' . ucfirst($rule['field']); - in_array($setMethod, $methods) && call_user_func_array(array($this, $setMethod), array($rule['default'])); - } - } - - /** - * 执行rule验证 - * - * @param string $input 待验证的数据 - * @param array $rule 数据验证的规则 - * @return boolean 如果验证成功返回true,验证失败返回false - */ - private function check($input, $rule) { - $arg = (array) $rule['args']; - array_unshift($arg, $input); - if (call_user_func_array(array($this->getValidator(), $rule['validator']), $arg) !== false) return true; - if ($rule['default'] === null) { - $this->_errors[$rule['field']] = $rule['message']; - return true; - } - return false; - } + /** + * 返回验证器 + * + * @return WindValidator + * @throws WindException 验证器创建失败抛出异常 + */ + protected function getValidator() + { + if ($this->_validator === null) { + $_className = Wind::import($this->_validatorClass); + $this->_validator = WindFactory::createInstance($_className); + if ($this->_validator === null) { + throw new WindException('[base.WindEnableValidateModule.getValidator] validator', WindException::ERROR_RETURN_TYPE_ERROR); + } + } - /** - * 返回验证器 - * - * @return WindValidator - * @throws WindException 验证器创建失败抛出异常 - */ - protected function getValidator() { - if ($this->_validator === null) { - $_className = Wind::import($this->_validatorClass); - $this->_validator = WindFactory::createInstance($_className); - if ($this->_validator === null) throw new WindException('validator', WindException::ERROR_RETURN_TYPE_ERROR); - } - return $this->_validator; - } -} \ No newline at end of file + return $this->_validator; + } +} diff --git a/wind/base/WindError.php b/wind/base/WindError.php new file mode 100644 index 00000000..4607953c --- /dev/null +++ b/wind/base/WindError.php @@ -0,0 +1,208 @@ + + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id$ + * @package wind.base + */ +abstract class WindError extends WindModule +{ + protected $errorDir; + protected $isClosed; + + /** + * 构造方法 + * + * @param string $errorDir 错误目录地址 + * @param bool $isClosed 站点是否关闭 + */ + public function __construct($errorDir, $isClosed) + { + $this->errorDir = $errorDir; + $this->isClosed = $isClosed; + } + + /** + * 异常处理句柄 + * + * @param Exception $exception + */ + public function exceptionHandle($exception) + { + $trace = array(); + $file = $line = ''; + if (Wind::$isDebug) { + $trace = $exception->getTrace(); + if (@$trace[0]['file'] == '') { + unset($trace[0]); + $trace = array_values($trace); + } + $file = @$trace[0]['file']; + $line = @$trace[0]['line']; + } + $this->showErrorMessage($exception->getMessage(), $file, $line, $trace, + $exception->getCode()); + } + + /** + * 错误处理句柄 + * + * @param int $errno + * @param string $errstr + * @param string $errfile + * @param int $errline + */ + public function errorHandle($errno, $errstr, $errfile, $errline) + { + $trace = array(); + if (Wind::$isDebug) { + $trace = debug_backtrace(); + unset($trace[0]['function'], $trace[0]['args']); + } + $this->showErrorMessage($this->_friendlyErrorType($errno).': '.$errstr, $errfile, + $errline, $trace, $errno); + } + + /** + * 错误处理 + * + * @param string $message + * @param string $file 异常文件 + * @param int $line 错误发生的行 + * @param array $trace + * @param int $errorcode 错误代码 + * @throws WindFinalException + */ + abstract protected function showErrorMessage($message, $file, $line, $trace, $errorcode); + + /** + * 错误信息处理方法 + * + * @param string $file + * @param string $line + * @param array $trace + */ + protected function crash($file, $line, $trace) + { + if ($trace) { + $msg = ''; + $count = count($trace); + $padLen = strlen($count); + foreach ($trace as $key => $call) { + if (!isset($call['file']) || $call['file'] == '') { + $call['file'] = '~Internal Location~'; + $call['line'] = 'N/A'; + } + $traceLine = '#'.str_pad(($count - $key), $padLen, '0', STR_PAD_LEFT).' '.$this->_getCallLine( + $call); + $trace[$key] = $traceLine; + } + } + $fileLines = array(); + if (is_file($file)) { + $currentLine = $line - 1; + $fileLines = explode("\n", file_get_contents($file, null, null, 0, 10000000)); + $topLine = $currentLine - 5; + $fileLines = array_slice($fileLines, $topLine > 0 ? $topLine : 0, 10, true); + if (($count = count($fileLines)) > 0) { + $padLen = strlen($count); + foreach ($fileLines as $line => &$fileLine) { + $fileLine = ' '.htmlspecialchars( + str_pad($line + 1, $padLen, '0', STR_PAD_LEFT).': '.str_replace("\t", + ' ', rtrim($fileLine)), null, 'UTF-8'); + } + } + } + + return array($fileLines, $trace); + } + + /** + * + * @param array $call + * @return string + */ + private function _getCallLine($call) + { + $call_signature = ''; + if (isset($call['file'])) { + $call_signature .= $call['file'].' '; + } + if (isset($call['line'])) { + $call_signature .= '('.$call['line'].') '; + } + if (isset($call['function'])) { + $call_signature .= $call['function'].'('; + if (isset($call['args'])) { + foreach ($call['args'] as $arg) { + if (is_string($arg)) { + $arg = '"'.(strlen($arg) <= 64 ? $arg : substr($arg, 0, 64).'…').'"'; + } elseif (is_object($arg)) { + $arg = ''.get_class($arg).''; + } elseif ($arg === true) { + $arg = 'true'; + } elseif ($arg === false) { + $arg = 'false'; + } elseif ($arg === null) { + $arg = 'null'; + } elseif (is_array($arg)) { + $arg = WindString::varToString($arg); + } else { + $arg = strval($arg); + } + $call_signature .= $arg.','; + } + } + $call_signature = trim($call_signature, ',').')'; + } + + return $call_signature; + } + + /** + * 返回友好的错误类型名 + * + * @param int $type + * @return string unknown + */ + private function _friendlyErrorType($type) + { + switch ($type) { + case E_ERROR: + return 'E_ERROR'; + case E_WARNING: + return 'E_WARNING'; + case E_PARSE: + return 'E_PARSE'; + case E_NOTICE: + return 'E_NOTICE'; + case E_CORE_ERROR: + return 'E_CORE_ERROR'; + case E_CORE_WARNING: + return 'E_CORE_WARNING'; + case E_CORE_ERROR: + return 'E_COMPILE_ERROR'; + case E_CORE_WARNING: + return 'E_COMPILE_WARNING'; + case E_USER_ERROR: + return 'E_USER_ERROR'; + case E_USER_WARNING: + return 'E_USER_WARNING'; + case E_USER_NOTICE: + return 'E_USER_NOTICE'; + case E_STRICT: + return 'E_STRICT'; + case E_RECOVERABLE_ERROR: + return 'E_RECOVERABLE_ERROR'; + case E_DEPRECATED: + return 'E_DEPRECATED'; + case E_USER_DEPRECATED: + return 'E_USER_DEPRECATED'; + } + + return $type; + } +} diff --git a/wind/base/WindErrorMessage.php b/wind/base/WindErrorMessage.php index bb7da027..1f66e0e6 100644 --- a/wind/base/WindErrorMessage.php +++ b/wind/base/WindErrorMessage.php @@ -1,136 +1,146 @@ * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindErrorMessage.php 3264 2011-12-20 09:01:40Z yishuo $ * @package base */ -class WindErrorMessage extends WindModule implements IWindErrorMessage { - /** - * 用于存储错误信息 - * - * @var array - */ - private $error = array(); - /** - * 用于处理当前错误的action操作 - * - * 用于处理当前错误的action操作,当该值为空时,系统自动调用默认错误处理类,可以通过配置改变默认的错误处理类 - * @var string - */ - private $errorAction; +class WindErrorMessage extends WindModule implements IWindErrorMessage +{ + /** + * 用于存储错误信息 + * + * @var array + */ + private $error = array(); + /** + * 用于处理当前错误的action操作 + * + * 用于处理当前错误的action操作,当该值为空时,系统自动调用默认错误处理类,可以通过配置改变默认的错误处理类 + * @var string + */ + private $errorAction; - /** - * @param string $message 错误消息 默认为空 - * @param string $errorAction 用于处理当前错误的Action操作 默认为空 - */ - public function __construct($message = '', $errorAction = '') { - $message !== '' && $this->addError($message); - $errorAction !== '' && $this->setErrorAction($errorAction); - } + /** + * @param string $message 错误消息 默认为空 + * @param string $errorAction 用于处理当前错误的Action操作 默认为空 + */ + public function __construct($message = '', $errorAction = '') + { + $message !== '' && $this->addError($message); + $errorAction !== '' && $this->setErrorAction($errorAction); + } - /* (non-PHPdoc) - * @see IWindErrorMessage::sendError() - */ - public function sendError($message = '') { - if ($message) - $this->addError($message); - elseif (empty($this->error)) - return; - throw new WindActionException($this); - } + /* (non-PHPdoc) + * @see IWindErrorMessage::sendError() + */ + public function sendError($message = '') + { + if ($message) { + $this->addError($message); + } elseif (empty($this->error)) { + return; + } + throw new WindActionException($this); + } - /* (non-PHPdoc) - * @see IWindErrorMessage::clearError() - */ - public function clearError() { - $this->error = array(); - } + /* (non-PHPdoc) + * @see IWindErrorMessage::clearError() + */ + public function clearError() + { + $this->error = array(); + } - /* (non-PHPdoc) - * @see IWindErrorMessage::getError() - */ - public function getError($key = '') { - if ($key === '') return $this->error; - return isset($this->error[$key]) ? $this->error[$key] : ''; - } + /* (non-PHPdoc) + * @see IWindErrorMessage::getError() + */ + public function getError($key = '') + { + if ($key === '') { + return $this->error; + } - /* (non-PHPdoc) - * @see IWindErrorMessage::addError() - */ - public function addError($error, $key = '') { - if ($key === '') - $this->error[] = $error; - else - $this->error[$key] = $error; - } + return isset($this->error[$key]) ? $this->error[$key] : ''; + } - /** - * 返回用于处理当前错误的action操作 - * - * @return string - */ - public function getErrorAction() { - return $this->errorAction; - } + /* (non-PHPdoc) + * @see IWindErrorMessage::addError() + */ + public function addError($error, $key = '') + { + if ($key === '') { + $this->error[] = $error; + } else { + $this->error[$key] = $error; + } + } - /** - * 设置用于处理当前错误的action操作 - * - * $errorAction支持的输入格式/module/controller/action/?args - * @param string $errorAction - * @return void - */ - public function setErrorAction($errorAction) { - $this->errorAction = $errorAction; - } + /** + * 返回用于处理当前错误的action操作 + * + * @return string + */ + public function getErrorAction() + { + return $this->errorAction; + } + + /** + * 设置用于处理当前错误的action操作 + * + * $errorAction支持的输入格式/module/controller/action/?args + * @param string $errorAction + */ + public function setErrorAction($errorAction) + { + $this->errorAction = $errorAction; + } } /** * 错误消息类接口定义 - * + * * the last known user to change this file in the repository <$LastChangedBy: yishuo $> * @author Qiong Wu - * @version $Id$ - * @package + * @version $Id: WindErrorMessage.php 3264 2011-12-20 09:01:40Z yishuo $ + * @package */ -interface IWindErrorMessage { - - /** - * 添加一条错误信息 - * - * 添加一条错误信息,可存储多条错误信息,以数组方式存储错误信息,当key值为空时,消息索引为自然索引 - * @param string $message 错误信息 - * @param string $key key值 默认为空 - */ - public function addError($message, $key = ''); +interface IWindErrorMessage +{ + /** + * 添加一条错误信息 + * + * 添加一条错误信息,可存储多条错误信息,以数组方式存储错误信息,当key值为空时,消息索引为自然索引 + * @param string $message 错误信息 + * @param string $key key值 默认为空 + */ + public function addError($message, $key = ''); - /** - * 返回错误信息 - * - * 返回错误信息,当key为空时,返回全部的错误信息 - * @param string $key - * @return string|array - */ - public function getError($key = ''); + /** + * 返回错误信息 + * + * 返回错误信息,当key为空时,返回全部的错误信息 + * @param string $key + * @return string|array + */ + public function getError($key = ''); - /** - * 清空当前错误对象中的全部错误信息 - * - * @return void - */ - public function clearError(); + /** + * 清空当前错误对象中的全部错误信息 + * + */ + public function clearError(); - /** - * 发送错误信息 - * - * @return void - * @throws WindActionException - */ - public function sendError(); -} \ No newline at end of file + /** + * 发送错误信息 + * + * @throws WindActionException + */ + public function sendError(); +} diff --git a/wind/base/WindException.php b/wind/base/WindException.php index c527c13a..5ad86e01 100644 --- a/wind/base/WindException.php +++ b/wind/base/WindException.php @@ -1,69 +1,75 @@ 2011-10-8 * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindException.php 3904 2013-01-08 07:01:26Z yishuo $ * @package base */ -class WindException extends Exception { - /* 系统错误 */ - const ERROR_SYSTEM_ERROR = '0'; - /* 类错误 */ - const ERROR_CLASS_NOT_EXIST = '100'; - const ERROR_CLASS_TYPE_ERROR = '101'; - const ERROR_CLASS_METHOD_NOT_EXIST = '102'; - const ERROR_OBJECT_NOT_EXIST = '103'; - /* 参数错误 */ - const ERROR_PARAMETER_TYPE_ERROR = '110'; - /* 配置错误 */ - const ERROR_CONFIG_ERROR = '120'; - /* 返回值类型错误 */ - const ERROR_RETURN_TYPE_ERROR = '130'; +class WindException extends Exception +{ + /* 系统错误 */ + const ERROR_SYSTEM_ERROR = '0'; + /* 类错误 */ + const ERROR_CLASS_NOT_EXIST = '1100'; + const ERROR_CLASS_TYPE_ERROR = '1101'; + const ERROR_CLASS_METHOD_NOT_EXIST = '1102'; + const ERROR_OBJECT_NOT_EXIST = '1103'; + /* 参数错误 */ + const ERROR_PARAMETER_TYPE_ERROR = '1110'; + /* 配置错误 */ + const ERROR_CONFIG_ERROR = '1120'; + /* 返回值类型错误 */ + const ERROR_RETURN_TYPE_ERROR = '1130'; - /** - * 异常构造函数 - * - * @param $message 异常信息 - * @param $code 异常代号 默认为0 - * @param $innerException 内部异常 默认为null - */ - public function __construct($message, $code = 0) { - $message = $this->buildMessage($message, $code); - parent::__construct($message, $code); - } + /** + * 异常构造函数 + * + * @param $message 异常信息 + * @param $code 异常代号 默认为0 + * @param $innerException 内部异常 默认为null + */ + public function __construct($message, $code = 0) + { + $message = $this->buildMessage($message, $code); + parent::__construct($message, $code); + } - /** - * 根据exception code返回构建的异常信息描述 - * - * @param string $message 用户自定义的信息 - * @param int $code 异常号 - * @return string 组装后的异常信息 - */ - public function buildMessage($message, $code) { - $message = str_replace(array("
", "
", "\r\n"), '', $message); - eval('$message="' . addcslashes($this->messageMapper($code), '"') . '";'); - return $message; - } + /** + * 根据exception code返回构建的异常信息描述 + * + * @param string $message 用户自定义的信息 + * @param int $code 异常号 + * @return string 组装后的异常信息 + */ + public function buildMessage($message, $code) + { + $message = str_replace(array('
', '
', "\r\n"), '', $message); + $_message = $this->messageMapper($code); - /** - * 自定义异常号的对应异常信息 - * - * @param int $code 异常号 - * @return string 返回异常号对应的异常组装信息原型 - */ - protected function messageMapper($code) { - $messages = array( - self::ERROR_SYSTEM_ERROR => 'System error \'$message\'.', - self::ERROR_CLASS_TYPE_ERROR => 'Incorrect class type \'$message\'.', - self::ERROR_CLASS_NOT_EXIST => 'Unable to create instance for \'$message\' , class is not exist.', - self::ERROR_CLASS_METHOD_NOT_EXIST => 'Unable to access the method \'$message\' in current class , the method is not exist or is protected.', - self::ERROR_OBJECT_NOT_EXIST => 'Unable to access the object in current class \'$message\' ', - self::ERROR_CONFIG_ERROR => 'Incorrect config. the config about \'$message\' error.', - self::ERROR_PARAMETER_TYPE_ERROR => 'Incorrect parameter type \'$message\'.', - self::ERROR_RETURN_TYPE_ERROR => 'Incorrect return type for \'$message\'.'); - return isset($messages[$code]) ? $messages[$code] : '$message'; - } -} \ No newline at end of file + return $_message ? str_replace('$message', $message, $_message) : $message; + } + + /** + * 自定义异常号的对应异常信息 + * + * @param int $code 异常号 + * @return string 返回异常号对应的异常组装信息原型 + */ + protected function messageMapper($code) + { + $messages = array( + self::ERROR_SYSTEM_ERROR => 'System error \'$message\'.', + self::ERROR_CLASS_TYPE_ERROR => 'Incorrect class type \'$message\'.', + self::ERROR_CLASS_NOT_EXIST => 'Unable to create instance for \'$message\' , class is not exist.', + self::ERROR_CLASS_METHOD_NOT_EXIST => 'Unable to access the method \'$message\' in current class , the method is not exist or is protected.', + self::ERROR_OBJECT_NOT_EXIST => 'Unable to access the object in current class \'$message\' ', + self::ERROR_CONFIG_ERROR => 'Incorrect config. the config about \'$message\' error.', + self::ERROR_PARAMETER_TYPE_ERROR => 'Incorrect parameter type \'$message\'.', + self::ERROR_RETURN_TYPE_ERROR => 'Incorrect return type for \'$message\'.', ); + + return isset($messages[$code]) ? $messages[$code] : ''; + } +} diff --git a/wind/base/WindFactory.php b/wind/base/WindFactory.php index 683e4a5d..49f6def7 100644 --- a/wind/base/WindFactory.php +++ b/wind/base/WindFactory.php @@ -1,306 +1,398 @@ - * * * * * 支持定义类对象的别名,路径,工厂方法,初始化方法,作用域,是否启动代理,析构方法,属性值,构造参数,以及配置解析等. + * * @author Qiong Wu * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindFactory.php 3914 2013-01-23 03:07:17Z yishuo $ * @package base */ -class WindFactory implements IWindFactory { - protected $proxyType = 'WIND:factory.WindClassProxy'; - protected $classDefinitions = array(); - protected $instances = array(); - protected $prototype = array(); - protected $destories = array(); - protected $singleton = array(); +class WindFactory +{ + protected $proxyType = 'WindClassProxy'; + protected $classDefinitions = array(); + protected $instances = array(); + protected $prototype = array(); + protected $destories = array(); + protected $singleton = array(); + private static $_instance = null; - /** - * 初始化工厂类 - * - * @param array $classDefinitions 组件定义 默认值为空数组 - */ - public function __construct($classDefinitions = array()) { - if (is_array($classDefinitions)) $this->classDefinitions = $classDefinitions; - } - - /* (non-PHPdoc) - * @see IWindFactory::getInstance() - */ - public function getInstance($alias, $args = array()) { - $instance = null; - $definition = isset($this->classDefinitions[$alias]) ? $this->classDefinitions[$alias] : array(); - if (isset($this->prototype[$alias])) { - $instance = clone $this->prototype[$alias]; - if (isset($definition['destroy'])) $this->destories[] = array($instance, $definition['destroy']); - } elseif (isset($this->instances[$alias])) { - $instance = $this->instances[$alias]; - } elseif (isset($this->singleton[$alias])) { - $instance = $this->singleton[$alias]; - } else { - if (!$definition) return null; - if (isset($definition['constructor-args']) && !$args) $this->buildArgs($definition['constructor-args'], - $args); - if (!isset($definition['className'])) $definition['className'] = Wind::import(@$definition['path']); - $instance = $this->createInstance($definition['className'], $args); - if (isset($definition['config'])) $this->resolveConfig($definition['config'], $alias, $instance); - if (isset($definition['properties'])) $this->buildProperties($definition['properties'], $instance); - if (isset($definition['initMethod'])) $this->executeInitMethod($definition['initMethod'], $instance); - !isset($definition['scope']) && $definition['scope'] = 'application'; - $this->setScope($alias, $definition['scope'], $instance); - if (isset($definition['destroy'])) $this->destories[$alias] = array($instance, $definition['destroy']); - } - if (isset($definition['proxy'])) $instance = $this->setProxyForClass($definition['proxy'], $instance); - return $instance; - } - - /* (non-PHPdoc) - * @see IWindFactory::createInstance() - */ - static public function createInstance($className, $args = array()) { - try { - if (empty($args)) { - return new $className(); - } else { - $reflection = new ReflectionClass($className); - return call_user_func_array(array($reflection, 'newInstance'), (array) $args); - } - } catch (Exception $e) { - throw new WindException('[base.WindFactory] create instance \'' . $className . '\' fail.' . $e->getMessage(), - WindException::ERROR_CLASS_NOT_EXIST); - } - } + /** + * 初始化工厂类 + * + * @param array $classDefinitions + * 组件定义 默认值为空数组 + */ + private function __construct() + { + } - /** - * 注册组件对象,如果已经存在则覆盖原有值 - * - * @param object $instance - * @param string $alias - * @param string $scope 对象作用域 默认为'singleton' - * @return boolean - */ - public function registInstance($instance, $alias, $scope = 'singleton') { - if (!is_object($instance) || !$alias) return false; - return $this->setScope($alias, $scope, $instance); - } + /* + * (non-PHPdoc) @see IWindFactory::getInstance() + */ + public function getInstance($alias, $args = array()) + { + $instance = null; + $definition = isset($this->classDefinitions[$alias]) ? $this->classDefinitions[$alias] : array(); + if (isset($this->prototype[$alias])) { + $instance = clone $this->prototype[$alias]; + if (isset($definition['destroy'])) { + $this->destories[] = array($instance, $definition['destroy']); + } + } elseif (isset($this->instances[$alias])) { + $instance = $this->instances[$alias]; + } elseif (isset($this->singleton[$alias])) { + $instance = $this->singleton[$alias]; + } else { + if (!$definition) { + return null; + } + $_unscope = empty($args); + if (isset($definition['constructor-args']) && $_unscope) { + $this->buildArgs($definition['constructor-args'], + $args); + } + if (!isset($definition['className'])) { + $definition['className'] = Wind::import(@$definition['path']); + } + $instance = $this->createInstance($definition['className'], $args); + if (isset($definition['config'])) { + $this->resolveConfig($definition['config'], $alias, $instance); + } + if (isset($definition['properties'])) { + $this->buildProperties($definition['properties'], $instance); + } + if (isset($definition['initMethod'])) { + $this->executeInitMethod($definition['initMethod'], $instance); + } + !isset($definition['scope']) && $definition['scope'] = 'application'; + $_unscope && $this->setScope($alias, $definition['scope'], $instance); + if (isset($definition['destroy'])) { + $this->destories[$alias] = array($instance, $definition['destroy']); + } + } + if (isset($definition['proxy'])) { + $listeners = isset($definition['listeners']) ? $definition['listeners'] : array(); + $instance = $this->setProxyForClass($definition['proxy'], $listeners, $instance); + } - /** - * 动态添加组件定义 - * - * @param string $alias - * @param array $classDefinition - * @return void - * @throws WindException - */ - public function addClassDefinitions($alias, $classDefinition) { - if (is_string($alias) && !empty($alias)) { - if (!isset($this->classDefinitions[$alias])) $this->classDefinitions[$alias] = $classDefinition; - } else - throw new WindException('[base.WindFactory.addClassDefinitions] class alias is empty.', - WindException::ERROR_PARAMETER_TYPE_ERROR); - } + return $instance; + } - /** - * 加载类定义 - * - * 调用该方法加载组件定义,如果merge为true,则覆盖原有配置信息. - * @param array $classDefinitions - * @param boolean $merge 是否进行merge操作,默认为true - * @return void - */ - public function loadClassDefinitions($classDefinitions, $merge = true) { - foreach ((array) $classDefinitions as $alias => $definition) { - if (!is_array($definition)) continue; - if (isset($this->instances[$alias]) || isset($this->prototype[$alias])) continue; - if (!isset($this->classDefinitions[$alias]) || $merge === false) - $this->classDefinitions[$alias] = $definition; - else - $this->classDefinitions[$alias] = WindUtility::mergeArray($this->classDefinitions[$alias], $definition); - } - } + /* + * (non-PHPdoc) @see IWindFactory::createInstance() + */ + public static function createInstance($className, $args = array()) + { + try { + if (empty($args)) { + return new $className(); + } else { + $reflection = new ReflectionClass($className); - /** - * 组件定义检查 - * - * 检查类定义是否已经存在,或者是否已经被创建.避免重复注册组件定义 - * @param string $alias - * @return boolean - */ - public function checkAlias($alias) { - if (isset($this->prototype[$alias])) - return true; - elseif (isset($this->instances[$alias])) - return true; - return false; - } + return call_user_func_array(array($reflection, 'newInstance'), (array) $args); + } + } catch (Exception $e) { + throw new WindException('[base.WindFactory] create instance \''.$className.'\' fail.'.$e->getMessage(), + WindException::ERROR_CLASS_NOT_EXIST); + } + } - /** - * 执行组件定义的注销方法 - * - * 调用全部组件的注销方法,按照组件的定义顺序依次调用,相关组件的定义方法... - * 该方法在应用结束时统一被调用. - * @return void - * @throws WindException - */ - public function executeDestroyMethod() { - try { - foreach ($this->destories as $call) - call_user_func_array($call, array()); - $this->instances = array(); - $this->destories = array(); - } catch (Exception $e) { - throw new WindException($e->getMessage()); - } - } + /** + * 注册组件对象,如果已经存在则覆盖原有值 + * + * @param object $instance + * @param string $alias + * @param string $scope + * 对象作用域 默认为'singleton' + * @return bool + */ + public function registInstance($instance, $alias, $scope = 'singleton') + { + return $this->setScope($alias, $scope, $instance); + } - /** - * 解析组件对象构造方法参数信息,并返回参数列表 - * - * 该方法解析组件对象构造方法的参数信息,相关的组件配置 - * - * - * 相关定义同properties相同.'name'为参数位置,生成的参数列表按照'name'一次排序. - * @param array $constructors - * @param array $args - * @return void - */ - protected function buildArgs($constructors, &$args) { - foreach ((array) $constructors as $key => $_var) { - $key = intval($key); - if (isset($_var['value'])) { - $args[$key] = $_var['value']; - } elseif (isset($_var['ref'])) - $args[$key] = $this->getInstance($_var['ref']); - elseif (isset($_var['path'])) { - $_className = Wind::import($_var['path']); - $args[$key] = $this->createInstance($_className); - } - } - ksort($args); - } + /** + * 动态添加组件定义 + * + * @param string $alias + * @param array $classDefinition + * @throws WindException + */ + public function addClassDefinitions($alias, $classDefinition) + { + if (is_string($alias) && !empty($alias)) { + if (!isset($this->classDefinitions[$alias])) { + $this->classDefinitions[$alias] = $classDefinition; + } + } else { + throw new WindException('[base.WindFactory.addClassDefinitions] class alias is empty.', + WindException::ERROR_PARAMETER_TYPE_ERROR); + } + } - /** - * 组件对象的作用域解析 - * - * 组件对象的作用域解析,目前支持的属性作用于为'prototype','application','singleton',默认为'application'. - * 相关组件定义方式... - * @param string $alias - * @param string $scope - * @param WindModule $instance - * @return boolean - */ - protected function setScope($alias, $scope, $instance) { - switch ($scope) { - case 'prototype': - $this->prototype[$alias] = clone $instance; - break; - case 'application': - $this->instances[$alias] = $instance; - break; - case 'singleton': - $this->singleton[$alias] = $instance; - break; - default: - break; - } - return true; - } + /** + * 加载类定义 + * 调用该方法加载组件定义,如果merge为true,则覆盖原有配置信息. + * + * @param array $classDefinitions + * @param bool $merge + * 是否进行merge操作,默认为true + */ + public function loadClassDefinitions($classDefinitions, $merge = true) + { + foreach ((array) $classDefinitions as $alias => $definition) { + if (!is_array($definition)) { + continue; + } + if (isset($this->instances[$alias]) || isset($this->prototype[$alias])) { + continue; + } + if (!isset($this->classDefinitions[$alias]) || $merge === false) { + $this->classDefinitions[$alias] = $definition; + } else { + $this->classDefinitions[$alias] = WindUtility::mergeArray($this->classDefinitions[$alias], $definition); + } + } + } - /** - * 解析组件配置 - * - * 解析组件配置并将配置信息设置进组件,默认调用windCache组件对进行配置缓存处理,可以通过配置'isCache'开启或关闭系统缓存. - * 组件配置定义..., - * 可以通过配置'resource'引入外部配置(支持命名空间方式定义路径地址),也可以直接将配置定义到config标签下. - * @param array|string $config - * @param string $alias - * @param WindModule $instance - * @return void - */ - protected function resolveConfig($config, $alias, $instance) { - if (!empty($config['resource'])) { - $_configPath = Wind::getRealPath($config['resource'], true, true); - $config = $this->getInstance('configParser')->parse($_configPath, $alias, 'components_config', - (!empty($this->instances['windCache']) ? $this->instances['windCache'] : null)); - } - if ($config && method_exists($instance, 'setConfig')) $instance->setConfig($config); - } + /** + * 设置类定义 + * 通过该方法设置会覆盖原有类定义,请注意该方法于{@see loadClassDefinitions}的区别 + * + * @param array $classDefinitions + */ + public function setClassDefinitions($classDefinitions) + { + $this->classDefinitions = $classDefinitions; + } - /** - * 执行类的初始化方法 - * - * 类的初始化方法的组件定义... - * @param string $initMethod - * @param object $instance - * @return mixed - * @throws WindException - */ - protected function executeInitMethod($initMethod, $instance) { - try { - return call_user_func_array(array($instance, $initMethod), array()); - } catch (Exception $e) { - throw new WindException( - '[base.WindFactory.executeInitMethod] (' . $initMethod . ', ' . $e->getMessage() . ')', - WindException::ERROR_CLASS_METHOD_NOT_EXIST); - } - } + /** + * 组件定义检查 + * 检查类定义是否已经存在,或者是否已经被创建.避免重复注册组件定义 + * + * @param string $alias + * @return bool + */ + public function checkAlias($alias) + { + if (isset($this->prototype[$alias])) { + return true; + } elseif (isset($this->instances[$alias])) { + return true; + } - /** - * 设置类代理对象,并返回代理类对象 - * - * 代理类同当前类拥有同样的职责和功能,可以通过访问代理类对象访问当前类. - * 类的代理信息对应的组件配置为...当'proxy'设置为false时返回该类的代理类型, - * 类默认的代理类型为WindClassProxy,不可以通过配置进行修改. - * @param string $proxy - * @param WindModule $instance - * @return WindClassProxy - */ - protected function setProxyForClass($proxy, $instance) { - if (!$proxy) return $instance; - if (true === $proxy) $proxy = $this->proxyType; - $proxy = self::createInstance(Wind::import($proxy)); - $proxy->registerTargetObject($instance); - $instance->_proxy = $proxy; - return $proxy; - } + return false; + } - /** - * 构建类的属性信息 - * - * 类的属性信息对应的组件配置为 - * 他支持的标签为'delay','property-name','ref','value','path'. - * 当'delay'设置为true时该属性延迟加载.'property-name'设置了属性名称.'ref','value','path'是定义属性值的三种方式,'ref'指向另外的组件定义名称, - * 'value'直接输入属性的值,'path'定义一个属性对象的路径,系统会自动创建该属性的对象. - * @param string $properties 属性定义 - * @param WindModule $instance 类对象 - * @return void - */ - protected function buildProperties($properties, $instance) { - isset($properties['delay']) || $properties['delay'] = true; - if ($properties['delay'] === 'false' || $properties['delay'] === false) { - foreach ($properties as $key => $subDefinition) { - $_value = ''; - if (isset($subDefinition['value'])) - $_value = $subDefinition['value']; - elseif (isset($subDefinition['ref'])) - $_value = $this->getInstance($subDefinition['ref']); - elseif (isset($subDefinition['path'])) { - $_className = Wind::import($subDefinition['path']); - $_value = $this->createInstance($_className); - } - $_setter = 'set' . ucfirst(trim($key, '_')); - if (method_exists($instance, $_setter)) call_user_func_array(array($instance, $_setter), array($_value)); - } - } else - $instance->setDelayAttributes($properties); - } -} \ No newline at end of file + /** + * 执行组件定义的注销方法 + * 调用全部组件的注销方法,按照组件的定义顺序依次调用,相关组件的定义方法... + * 该方法在应用结束时统一被调用. + * + * @throws WindException + */ + public function executeDestroyMethod() + { + try { + foreach ($this->destories as $call) { + call_user_func_array($call, array()); + } + $this->instances = array(); + $this->destories = array(); + } catch (Exception $e) { + throw new WindException($e->getMessage()); + } + } + + /** + * 解析组件对象构造方法参数信息,并返回参数列表 + * 该方法解析组件对象构造方法的参数信息,相关的组件配置 + * + * + * 相关定义同properties相同.'name'为参数位置,生成的参数列表按照'name'一次排序. + * + * @param array $constructors + * @param array $args + */ + protected function buildArgs($constructors, &$args) + { + foreach ((array) $constructors as $key => $_var) { + $key = intval($key); + if (isset($_var['value'])) { + $args[$key] = $_var['value']; + } elseif (isset($_var['ref'])) { + $args[$key] = $this->getInstance($_var['ref']); + } elseif (isset($_var['path'])) { + $_className = Wind::import($_var['path']); + $args[$key] = $this->createInstance($_className); + } + } + ksort($args); + } + + /** + * 组件对象的作用域解析 + * 组件对象的作用域解析,目前支持的属性作用于为'prototype','application','singleton',默认为'application'. + * 相关组件定义方式... + * + * @param string $alias + * @param string $scope + * @param WindModule $instance + * @return bool + */ + protected function setScope($alias, $scope, $instance) + { + switch ($scope) { + case 'prototype': + $this->prototype[$alias] = clone $instance; + break; + case 'application': + $this->instances[$alias] = $instance; + break; + case 'singleton': + $this->singleton[$alias] = $instance; + break; + default: + break; + } + + return true; + } + + /** + * 解析组件配置 + * 解析组件配置并将配置信息设置进组件,默认调用windCache组件对进行配置缓存处理,可以通过配置'isCache'开启或关闭系统缓存. + * 组件配置定义..., + * 可以通过配置'resource'引入外部配置(支持命名空间方式定义路径地址),也可以直接将配置定义到config标签下. + * + * @param array|string $config + * @param string $alias + * @param WindModule $instance + */ + protected function resolveConfig($config, $alias, $instance) + { + if (!empty($config['resource'])) { + $_configPath = Wind::getRealPath($config['resource'], true, true); + $config = $this->getInstance('configParser')->parse($_configPath, $alias, 'components_config', + (!empty($this->instances['windCache']) ? $this->instances['windCache'] : null)); + } + if ($config && method_exists($instance, 'setConfig')) { + $instance->setConfig($config); + } + } + + /** + * 执行类的初始化方法 + * 类的初始化方法的组件定义... + * + * @param string $initMethod + * @param object $instance + * @return mixed + * @throws WindException + */ + protected function executeInitMethod($initMethod, $instance) + { + try { + return $instance->$initMethod(); + // return call_user_func_array(array($instance, $initMethod), + // array()); + } catch (Exception $e) { + throw new WindException( + '[base.WindFactory.executeInitMethod] ('.$initMethod.', '.$e->getMessage().')', + WindException::ERROR_CLASS_METHOD_NOT_EXIST); + } + } + + /** + * 设置类代理对象,并返回代理类对象 + * 代理类同当前类拥有同样的职责和功能,可以通过访问代理类对象访问当前类. + * 类的代理信息对应的组件配置为...当'proxy'设置为false时返回该类的代理类型, + * 类默认的代理类型为WindClassProxy,不可以通过配置进行修改. + * + * @param string $proxy + * @param WindModule $instance + * @return WindClassProxy + */ + protected function setProxyForClass($proxy, $listeners, $instance) + { + if (!$proxy) { + return $instance; + } + if (true === $proxy) { + $proxy = $this->proxyType; + } + /* @var $proxy WindClassProxy */ + $proxy = self::createInstance(Wind::import($proxy)); + $proxy->registerTargetObject($instance); + foreach ($listeners as $key => $value) { + $listener = WindFactory::createInstance(Wind::import($value)); + $proxy->registerEventListener($listener, $key); + } + // $instance->_proxy = $proxy; + return $proxy; + } + + /** + * 构建类的属性信息 + * 类的属性信息对应的组件配置为 + * 他支持的标签为'delay','property-name','ref','value','path'. + * 当'delay'设置为true时该属性延迟加载.'property-name'设置了属性名称.'ref','value','path'是定义属性值的三种方式,'ref'指向另外的组件定义名称, + * 'value'直接输入属性的值,'path'定义一个属性对象的路径,系统会自动创建该属性的对象. + * + * @param string $properties + * 属性定义 + * @param WindModule $instance + * 类对象 + */ + protected function buildProperties($properties, $instance) + { + isset($properties['delay']) || $properties['delay'] = true; + if ($properties['delay'] === 'false' || $properties['delay'] === false) { + foreach ($properties as $key => $subDefinition) { + $_value = ''; + if (isset($subDefinition['value'])) { + $_value = $subDefinition['value']; + } elseif (isset($subDefinition['ref'])) { + $_value = $this->getInstance($subDefinition['ref']); + } elseif (isset($subDefinition['path'])) { + $_className = Wind::import($subDefinition['path']); + $_value = $this->createInstance($_className); + } + $_setter = 'set'.ucfirst(trim($key, '_')); + if (method_exists($instance, $_setter)) { + call_user_func_array(array($instance, $_setter), array($_value)); + } + } + } else { + $instance->setDelayAttributes($properties); + } + } + + /** + * 返回组建工厂单例对象 + * + * @return WindFactory + */ + public static function _getInstance() + { + if (!(self::$_instance instanceof self)) { + self::$_instance = new self(); + } + + return self::$_instance; + } +} diff --git a/wind/base/WindFinalException.php b/wind/base/WindFinalException.php index fc86a941..140867c6 100644 --- a/wind/base/WindFinalException.php +++ b/wind/base/WindFinalException.php @@ -1,23 +1,22 @@ * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindFinalException.php 2973 2011-10-15 19:22:48Z yishuo $ * @package base */ -class WindFinalException extends Exception { - - /** - * @param string $message 异常信息 - */ - public function __construct($message = '') { - $message || $message = 'system error~'; - parent::__construct($message, 500); - } +class WindFinalException extends Exception +{ + /** + * @param string $message 异常信息 + */ + public function __construct($message = '') + { + $message || $message = 'system error~'; + parent::__construct($message, 500); + } } - -?> \ No newline at end of file diff --git a/wind/base/WindForwardException.php b/wind/base/WindForwardException.php index 7601f299..b3689073 100644 --- a/wind/base/WindForwardException.php +++ b/wind/base/WindForwardException.php @@ -1,43 +1,44 @@ * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindForwardException.php 2973 2011-10-15 19:22:48Z yishuo $ * @package base */ -class WindForwardException extends WindException { - /** - * @var WindForward - */ - private $forward; - - /** - * @param WindForward $forward - */ - public function __construct($forward) { - $this->forward = $forward; - } +class WindForwardException extends WindException +{ + /** + * @var WindForward + */ + private $forward; - /** - * @return WindForward - */ - public function getForward() { - return $this->forward; - } + /** + * @param WindForward $forward + */ + public function __construct($forward) + { + $this->forward = $forward; + } - /** - * @param WindForward $forward - */ - public function setForward($forward) { - $this->forward = $forward; - } + /** + * @return WindForward + */ + public function getForward() + { + return $this->forward; + } + /** + * @param WindForward $forward + */ + public function setForward($forward) + { + $this->forward = $forward; + } } - -?> \ No newline at end of file diff --git a/wind/base/WindModule.php b/wind/base/WindModule.php index 5dcf4c07..3b02d927 100644 --- a/wind/base/WindModule.php +++ b/wind/base/WindModule.php @@ -1,182 +1,201 @@ * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindModule.php 3850 2012-12-04 07:30:02Z yishuo $ * @package base */ -class WindModule { - /** - * 代理类对象 - * - * @var WindClassProxy - */ - public $_proxy = null; - /** - * 配置数据 - * - * @var array - */ - protected $_config = array(); - /** - * 在延迟加载策略中使用,保存需要延迟加载的属性配置信息 - * - * @var array - */ - protected $_delayAttributes = array(); +class WindModule +{ + /** + * 代理类对象 + * + * @var WindClassProxy + */ + public $_proxy = null; + /** + * 配置数据 + * + * @var array + */ + protected $_config = array(); + /** + * 在延迟加载策略中使用,保存需要延迟加载的属性配置信息 + * + * @var array + */ + protected $_delayAttributes = array(); - /** - * 重载了魔术方法__set - * - * 当属性访问不到时该方法被调用,该方法会尝试去访问对应属性的setter设置器,如果不存在则什么也不做 - * @param string $propertyName - * @param mixed $value - * @return void - */ - public function __set($propertyName, $value) { - $_setter = 'set' . ucfirst($propertyName); - if (method_exists($this, $_setter)) $this->$_setter($value); - } + /** + * 重载了魔术方法__set + * 当属性访问不到时该方法被调用,该方法会尝试去访问对应属性的setter设置器,如果不存在则什么也不做 + * + * @param string $propertyName + * @param mixed $value + */ + public function __set($propertyName, $value) + { + $_setter = 'set'.ucfirst($propertyName); + if (method_exists($this, $_setter)) { + $this->$_setter($value); + } + } - /** - * 重载了魔术方法__get - * - * 当属性访问不到时该方法被调用,该方法会尝试去访问对应属性的getter并返回对应的值,如果不存在则什么也不做 - * @param string $propertyName - * @return mixed - */ - public function __get($propertyName) { - $_getter = 'get' . ucfirst($propertyName); - if (method_exists($this, $_getter)) return $this->$_getter(); - } + /** + * 重载了魔术方法__get + * 当属性访问不到时该方法被调用,该方法会尝试去访问对应属性的getter并返回对应的值,如果不存在则什么也不做 + * + * @param string $propertyName + * @return mixed + */ + public function __get($propertyName) + { + $_getter = 'get'.ucfirst($propertyName); + if (method_exists($this, $_getter)) { + return $this->$_getter(); + } + } - /** - * 重载了魔术方法__call - * - * 当类的方法访问不到时调用该方法,在这里的实现是配置类属性对象的延迟加载策略 - * - * //延迟访问某个属性,当使用这种方式调用时该方法被调用,并访问该类中的$_delayAttributes属性,并创建该属性对象并返回 - * $this->_getMethodName(); - * - * @param string $methodName - * @param array $args - * @return mixed - */ - public function __call($methodName, $args) { - $_prefix = substr($methodName, 0, 4); - $_propertyName = substr($methodName, 4); - $_propertyName = WindUtility::lcfirst($_propertyName); - if ($_prefix == '_get') { - if (!$this->$_propertyName && isset($this->_delayAttributes[$_propertyName])) { - $_property = $this->_delayAttributes[$_propertyName]; - $_value = null; - if (isset($_property['value'])) { - $_value = $_property['value']; - } elseif (isset($_property['ref'])) { - $_value = Wind::getApp()->getWindFactory()->getInstance($_property['ref'], - $args); - } elseif (isset($_property['path'])) { - $_className = Wind::import($_property['path']); - $_value = WindFactory::createInstance($_className, $args); - } - $this->$_propertyName = $_value; - - /*unset($this->delayAttributes[$_propertyName]);*/ - } - return $this->$_propertyName; - } elseif ($_prefix == '_set') { - $this->$_propertyName = $args[0]; - } - } + /** + * 重载了魔术方法__call + * 当类的方法访问不到时调用该方法,在这里的实现是配置类属性对象的延迟加载策略 + * + * //延迟访问某个属性,当使用这种方式调用时该方法被调用,并访问该类中的$_delayAttributes属性,并创建该属性对象并返回 + * $this->_getMethodName(); + * + * + * @param string $methodName + * @param array $args + * @return mixed + */ + public function __call($methodName, $args) + { + $_prefix = substr($methodName, 0, 4); + $_propertyName = substr($methodName, 4); + $_propertyName = WindUtility::lcfirst($_propertyName); + if ($_prefix == '_get') { + if (!$this->$_propertyName && isset($this->_delayAttributes[$_propertyName])) { + $_property = $this->_delayAttributes[$_propertyName]; + $_value = null; + if (isset($_property['value'])) { + $_value = $_property['value']; + } elseif (isset($_property['ref'])) { + $_value = Wind::getComponent($_property['ref'], $args); + } elseif (isset($_property['path'])) { + $_className = Wind::import($_property['path']); + $_value = WindFactory::createInstance($_className, $args); + } + $this->$_propertyName = $_value; + } - /** - * 返回该对象的数组类型 - * - * @return array - */ - public function toArray() { - $reflection = new ReflectionClass(get_class($this)); - $properties = $reflection->getProperties(); - $_result = array(); - foreach ($properties as $property) { - $_propertyName = $property->name; - $_result[$_propertyName] = $this->$_propertyName; - } - return $_result; - } + return $this->$_propertyName; + } elseif ($_prefix == '_set') { + $this->$_propertyName = $args[0]; + } + } - /** - * 根据配置名取得相应的配置 - * - * 当configName为空时则返回整个配置.当配置值不存在时返回默认值.默认值默认为空 - * @param string $configName 键名 - * @param string $subConfigName 二级键名 - * @param string $default 默认值 - * @param array $config 外部配置 - * @return mixed - */ - public function getConfig($configName = '', $subConfigName = '', $default = '', $config = array()) { - if (empty($config)) $config = $this->_config; - if ($configName === '') return $config; - if (!isset($config[$configName])) return $default; - if ($subConfigName === '') return $config[$configName]; - if (!isset($config[$configName][$subConfigName])) return $default; - return $config[$configName][$subConfigName]; - } + /** + * 返回该对象的数组类型 + * + * @return array + */ + public function toArray() + { + $reflection = new ReflectionClass(get_class($this)); + $properties = $reflection->getProperties(); + $_result = array(); + foreach ($properties as $property) { + $_propertyName = $property->name; + $_result[$_propertyName] = $this->$_propertyName; + } - /** - * 设置类配置 - * - * 设置类配置信息,如果配置已经存在,则将以存在配置和输入配置进行合并. 重复配置后者将覆盖前者. - * 支持配置路径解析,当输入值为配置路径时则会调用配置解析器进行解析并自动缓存当前配置值.(缓存是由wind_config中的isCache配置值决定是否开启) - * @param string|array $config - * @return void - */ - public function setConfig($config) { - if ($config) { - if (is_string($config)) { - $config = Wind::getApp()->getComponent('configParser')->parse($config, - get_class($this), false, Wind::getApp()->getComponent('windCache')); - } - if (!empty($this->_config)) { - $this->_config = array_merge($this->_config, (array) $config); - } else - $this->_config = $config; - } - } + return $_result; + } - /** - * 返回当前应用的WindHttpRequest对象 - * - * @return WindHttpRequest - */ - protected function getRequest() { - return Wind::getApp()->getRequest(); - } + /** + * 根据配置名取得相应的配置 + * 当configName为空时则返回整个配置.当配置值不存在时返回默认值.默认值默认为空 + * + * @param string $configName 键名 + * @param string $subConfigName 二级键名 + * @param string $default 默认值 + * @param array $config 外部配置 + * @return mixed + */ + public function getConfig($configName = '', $subConfigName = '', $default = '', $config = array()) + { + if ($configName === '') { + return $this->_config; + } + if (!isset($this->_config[$configName])) { + return $default; + } + if ($subConfigName === '') { + return $this->_config[$configName]; + } + if (!isset($this->_config[$configName][$subConfigName])) { + return $default; + } - /** - * 返回当前应用的WindHttpResponse对象 - * - * @return WindHttpResponse - */ - protected function getResponse() { - return Wind::getApp()->getResponse(); - } + return $this->_config[$configName][$subConfigName]; + } - /** - * 设置延迟加载类属性相关组件配置信息 - * - * @param array $delayAttributes - * @return void - */ - public function setDelayAttributes($delayAttributes) { - $this->_delayAttributes = array_merge($this->_delayAttributes, $delayAttributes); - } + /** + * 设置类配置 + * 设置类配置信息,如果配置已经存在,则将以存在配置和输入配置进行合并. + * 重复配置后者将覆盖前者. + * 支持配置路径解析,当输入值为配置路径时则会调用配置解析器进行解析并自动缓存当前配置值.(缓存是由wind_config中的isCache配置值决定是否开启) + * + * @param string|array $config + */ + public function setConfig($config) + { + if ($config) { + if (is_string($config)) { + $config = Wind::getComponent('configParser')->parse($config, get_class($this), false, + Wind::getComponent('windCache')); + } + if (!empty($this->_config)) { + $this->_config = array_merge($this->_config, (array) $config); + } else { + $this->_config = $config; + } + } + } -} \ No newline at end of file + /** + * 返回当前应用的WindHttpRequest对象 + * + * @return WindHttpRequest + */ + protected function getRequest() + { + return Wind::getComponent('request'); + } + + /** + * 返回当前应用的WindHttpResponse对象 + * + * @return WindHttpResponse + */ + protected function getResponse() + { + return Wind::getComponent('response'); + } + + /** + * 设置延迟加载类属性相关组件配置信息 + * + * @param array $delayAttributes + */ + public function setDelayAttributes($delayAttributes) + { + $this->_delayAttributes = array_merge($this->_delayAttributes, $delayAttributes); + } +} diff --git a/wind/cache/AbstractWindCache.php b/wind/cache/AbstractWindCache.php index 390cdc79..97b0ca8c 100644 --- a/wind/cache/AbstractWindCache.php +++ b/wind/cache/AbstractWindCache.php @@ -1,9 +1,10 @@ *
  • {@link set}: 保存缓存数据,需要子类实现{@link setValue()}方法实现对应具体的方法.
  • @@ -13,399 +14,446 @@ *
  • {@link batchDelete}: 批量删除缓存数据.
  • * * 该基类支持三个配置项{@link setConfig()},所有继承该类的子类都拥有对该三个配置项的配置。 - * - * the last known user to change this file in the repository <$LastChangedBy: yishuo $> - * @author Su Qian + * + * the last known user to change this file in the repository <$LastChangedBy: yishuo $> + * @author Su Qian * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ + * @license http://www.windframework.com + * @version $Id: AbstractWindCache.php 3904 2013-01-08 07:01:26Z yishuo $ * @package cache */ -abstract class AbstractWindCache extends WindModule { - /** - * key的安全码 - * - * @var string - */ - private $securityCode = ''; - /** - * 缓存前缀 - * - * @var sting - */ - private $keyPrefix = ''; - /** - * 缓存过期时间 - * - * @var int - */ - private $expire = 0; - /** - * 缓存依赖的类名称 - * - * @var string - */ - const DEPENDENCYCLASS = 'dependencyclass'; - /** - * 标志存储时间 - * - * @var string - */ - const STORETIME = 'store'; - /** - * 标志存储数据 - * - * @var string - */ - const DATA = 'data'; - /** - * 配置文件中标志缓存依赖名称的定义 - * - * @var string - */ - const DEPENDENCY = 'dependency'; - /** - * 配置文件中标志过期时间名称定义(也包含缓存元数据中过期时间的定义) - * - * @var string - */ - const EXPIRE = 'expires'; - - /** - * 执行设置操作 - * - * @param string $key 缓存数据的唯一key - * @param string $value 缓存数据值,该值是一个含有有效数据的序列化的字符串 - * @param int $expires 缓存数据保存的有效时间,单位为秒,默认时间为0即永不过期 - * @return boolean - * @throws WindException 缓存失败的时候抛出异常 - */ - protected abstract function setValue($key, $value, $expires = 0); - - /** - * 执行添加操作 - * - * 当数据key不存在的时候添加,如果key已经存在则添加失败 - * - * @param string $key 缓存数据的唯一key - * @param string $value 缓存数据值,该值是一个含有有效数据的序列化的字符串 - * @param int $expires 缓存数据保存的有效时间,单位为秒,默认时间为0即永不过期 - * @return boolean - * @throws WindException 缓存失败的时候抛出异常 - */ - protected abstract function addValue($key, $value, $expires = 0); - - /** - * 执行获取操作 - * - * @param string $key 缓存数据的唯一key - * @return string 缓存的数据 - * @throws WindException 缓存数据获取失败抛出异常 - */ - protected abstract function getValue($key); - - /** - * 需要实现的删除操作 - * - * @param string $key 需要删除的缓存数据的key - * @return boolean - */ - protected abstract function deleteValue($key); - - /** - * 清楚缓存,过期及所有缓存 - * - * @return boolean - */ - public abstract function clear(); - - /** - * 设置缓存 - * 如果key不存在,添加缓存;否则,将会替换已有key的缓存。 - * - * @param string $key 保存缓存数据的键。 - * @param string $value 保存缓存数据。 - * @param int $expires 缓存数据的过期时间,0表示永不过期 - * @param IWindCacheDependency $denpendency 缓存依赖 - * @return boolean - * @throws WindCacheException 缓存失败时抛出异常 - */ - public function set($key, $value, $expires = 0, IWindCacheDependency $dependency = null) { - try { - $data = $this->buildData($value, $expires, $dependency); - return $this->setValue($this->buildSecurityKey($key), serialize($data), $data[self::EXPIRE]); - } catch (Exception $e) { - throw new WindCacheException('[cache.AbstractWindCache.set]Setting cache failed.' . $e->getMessage()); - } - } - - /** - * 增加一个条目到缓存服务器 - * - * 方法在缓存服务器之前不存在key时, 以key作为key存储一个变量var到缓存服务器。 - * 注意:新的元素的值不会小于0。 并且在元素不存在时不能创建它 - * - * @param string $key 保存缓存数据的键。 - * @param string $value 保存缓存数据。 - * @param int $expires 缓存数据的过期时间,0表示永不过期 - * @param IWindCacheDependency $denpendency 缓存依赖 - * @return boolean 成功时返回 TRUE, 或者在失败时返回 FALSE. 如果这个key已经存在返回FALSE。 - */ - public function add($key, $value, $expires = 0, IWindCacheDependency $dependency = null) { - try { - $key = $this->buildSecurityKey($key); - $data = $this->getValue($key); - if ($data) return false; - $data = $this->buildData($value, $expires, $dependency); - return $this->addValue($key, serialize($data), $data[self::EXPIRE]); - } catch (Exception $e) { - throw new WindCacheException('[cache.AbstractWindCache.set]Setting cache failed.' . $e->getMessage()); - } - } - - /** - * 根据缓存key获取指定缓存 - * - * @param string $key 获取缓存数据的标识,即键 - * @return mixed 返回被缓存的数据 - * @throws WindCacheException 获取失败时抛出异常 - */ - public function get($key) { - try { - return $this->formatData($key, $this->getValue($this->buildSecurityKey($key))); - } catch (Exception $e) { - throw new WindCacheException('Getting cache data failed. (' . $e->getMessage() . ')'); - } - } - - /** - * 通过key批量获取缓存数据 - * - * @param array $keys 批量缓存的key集合 - * @return array 返回批量key对应的缓存数据组成的缓存数据数组 - */ - public function batchGet(array $keys) { - $data = array(); - foreach ($keys as $key) { - $data[$key] = $this->get($key); - } - return $data; - } - - /** - * 删除缓存数据 - * - * @param string $key 获取缓存数据的标识,即键 - * @return boolean - * @throws WindCacheException 删除失败时抛出异常 - */ - public function delete($key) { - try { - return $this->deleteValue($this->buildSecurityKey($key)); - } catch (Exception $e) { - throw new WindCacheException('Delete cache data failed. (' . $e->getMessage() . ')'); - } - } - - /** - * 通过key批量删除缓存数据 - * - * @param array $keys 需要批量删除的缓存key组成的组数 - * @return boolean - */ - public function batchDelete(array $keys) { - foreach ($keys as $key) - $this->delete($key); - return true; - } - - /** - * 将指定元素的值增加value - * - * 如果指定的key 对应的元素不是数值类型并且不能被转换为数值, 会将此值修改为value. - * 注意:不会在key对应元素不存在时创建元素。 - * - * @param string $key 将要增加值的元素的key。 - * @param int $step 参数value表明要将指定元素值增加多少。 - * @return int 成功时返回新的元素值失败时返回false。 - */ - public function increment($key, $step = 1) { - $data = $this->get($key); - if (!is_numeric($data)) return false; - $data += intval($step); - $this->set($key, $data); - return $data; - } - - /** - * 将元素的值减小value - * - * 如果指定的key 对应的元素不是数值类型并且不能被转换为数值, 会将此值修改为value. - * 注意:新的元素的值不会小于0。 并且在元素不存在时不能创建它 - * - * @param string $key 将要增加值的元素的key。 - * @param int $step value参数指要将指定元素的值减小多少。 - * @return int 成功的时候返回元素的新值,失败的时候返回false。 - */ - public function decrement($key, $step = 1) { - $data = $this->get($key); - if (!is_numeric($data)) return false; - $data -= intval($step); - $data < 0 && $data = 0; - $this->set($key, $data); - return $data; - } - - /** - * 构造保存的数据 - * - * @param string $value 保存缓存数据。 - * @param int $expires 缓存数据的过期时间,0表示永不过期 - * @param IWindCacheDependency $denpendency 缓存依赖 - * @return array - */ - protected function buildData($value, $expires = 0, IWindCacheDependency $dependency = null) { - $data = array( - self::DATA => $value, - self::EXPIRE => $expires ? $expires : $this->getExpire(), - self::STORETIME => time(), - self::DEPENDENCY => null, - self::DEPENDENCYCLASS => ''); - if (null !== $dependency) { - $dependency->injectDependent(self::EXPIRE); - $data[self::DEPENDENCY] = $dependency; - $data[self::DEPENDENCYCLASS] = get_class($dependency); - } - return $data; - } - - /** - * 格式化输出 - * - * 将从缓存对象中获得的缓存源数据进行格式化输出.该源数据是一个格式良好的数组的序列化字符串,需要反序列化获得源数组. - * 如果没有数据,则返回false - * 如果含有数据,则返回该数据 - * - * @param string $key 缓存的key值 - * @param string $value 缓存的数据的序列化值 - * @return mixed 返回保存的真实数据,如果没有数值则返回false - */ - protected function formatData($key, $value) { - if (!$value) return false; - $data = unserialize($value); - return $this->hasChanged($key, $data) ? false : $data[self::DATA]; - } - - /** - * 判断数据是否已经被更新 - * - * 如果缓存中有数据,则检查缓存依赖是否已经变更,如果变更则删除缓存,并且返回true. - * 如果没有更新则返回false. - * - * @param string $key 缓存的key - * @param array $data 缓存中的数据 - * @return boolean true表示缓存已变更,false表示缓存未变改 - */ - protected function hasChanged($key, array $data) { - if ($data[self::DEPENDENCY]) { - $dependency = $data[self::DEPENDENCY]; - if (!$dependency->hasChanged($this, $key, $data[self::EXPIRE])) return false; - } elseif ($data[self::EXPIRE]) { - $_overTime = $data[self::EXPIRE] + $data[self::STORETIME]; - if ($_overTime >= time()) return false; - } else - return false; - $this->delete($key); - return true; - } - - /** - * 将数据key计算生成安全的key - * - * @param string $key 真实的缓存key - * @return string 加入安全码计算之后返回的保存key - */ - protected function buildSecurityKey($key) { - $this->keyPrefix && $key = $this->keyPrefix . '_' . $key; - return $key . $this->getSecurityCode(); - } - - /** - * 返回缓存Key值前缀 - * - * 默认值为null无任何前缀添加 - * - * @return string $prefix 返回key前缀 - */ - protected function getKeyPrefix() { - return $this->keyPrefix; - } - - /** - * 设置key前缀 - * - * @param sting $keyPrefix key的前缀 - */ - public function setKeyPrefix($keyPrefix) { - $this->keyPrefix = $keyPrefix; - } - - /** - * 获得缓存key计算中加入的安全码 - * - * @return string $securityCode - */ - protected function getSecurityCode() { - return $this->securityCode; - } - - /** - * 设置缓存key计算中加入的安全码 - * - * @param string $securityCode 安全码 - */ - public function setSecurityCode($securityCode) { - $this->securityCode = $securityCode; - } - - /** - * 返回过期时间设置 - * - * 单位为秒,默认值为0永不过期 - * - * @return int $expire 缓存过期时间,默认为0永不过期,单位为秒 - */ - public function getExpire() { - return $this->expire; - } - - /** - * 设置缓存过期时间 - * - * 单位为秒,默认为0永不过期 - * - * @param int $expire 缓存过期时间,单位为秒,默认为0永不过期 - */ - public function setExpire($expire) { - $this->expire = intval($expire); - } - - /** - * 设置配置信息 - * - * 支持三个配置项: - *
      - *
    • security-code: 安全码配置
    • - *
    • key-prefix: key前缀设置
    • - *
    • expires: 缓存过期时间配置,单位为秒,默认为0
    • - *
    - * - * @param array $config 缓存配置信息 - */ - public function setConfig($config) { - parent::setConfig($config); - $this->setSecurityCode($this->getConfig('security-code', '', '')); - $this->setKeyPrefix($this->getConfig('key-prefix', '', '')); - $this->setExpire($this->getConfig('expires', '', 0)); - } -} \ No newline at end of file +abstract class AbstractWindCache extends WindModule +{ + /** + * key的安全码 + * + * @var string + */ + private $securityCode = ''; + /** + * 缓存前缀 + * + * @var sting + */ + private $keyPrefix = ''; + /** + * 缓存过期时间 + * + * @var int + */ + private $expire = 0; + /** + * 缓存依赖的类名称 + * + * @var string + */ + const DEPENDENCYCLASS = 'dependencyclass'; + /** + * 标志存储时间 + * + * @var string + */ + const STORETIME = 'store'; + /** + * 标志存储数据 + * + * @var string + */ + const DATA = 'data'; + /** + * 配置文件中标志缓存依赖名称的定义 + * + * @var string + */ + const DEPENDENCY = 'dependency'; + /** + * 配置文件中标志过期时间名称定义(也包含缓存元数据中过期时间的定义) + * + * @var string + */ + const EXPIRE = 'expires'; + + /** + * 执行设置操作 + * + * @param string $key 缓存数据的唯一key + * @param string $value 缓存数据值,该值是一个含有有效数据的序列化的字符串 + * @param int $expires 缓存数据保存的有效时间,单位为秒,默认时间为0即永不过期 + * @return bool + * @throws WindException 缓存失败的时候抛出异常 + */ + abstract protected function setValue($key, $value, $expires = 0); + + /** + * 执行添加操作 + * + * 当数据key不存在的时候添加,如果key已经存在则添加失败 + * + * @param string $key 缓存数据的唯一key + * @param string $value 缓存数据值,该值是一个含有有效数据的序列化的字符串 + * @param int $expires 缓存数据保存的有效时间,单位为秒,默认时间为0即永不过期 + * @return bool + * @throws WindException 缓存失败的时候抛出异常 + */ + abstract protected function addValue($key, $value, $expires = 0); + + /** + * 执行获取操作 + * + * @param string $key 缓存数据的唯一key + * @return string 缓存的数据 + * @throws WindException 缓存数据获取失败抛出异常 + */ + abstract protected function getValue($key); + + /** + * 需要实现的删除操作 + * + * @param string $key 需要删除的缓存数据的key + * @return bool + */ + abstract protected function deleteValue($key); + + /** + * 清楚缓存,过期及所有缓存 + * + * @return bool + */ + abstract public function clear(); + + /** + * 设置缓存 + * 如果key不存在,添加缓存;否则,将会替换已有key的缓存。 + * + * @param string $key 保存缓存数据的键。 + * @param string $value 保存缓存数据。 + * @param int $expires 缓存数据的过期时间,0表示永不过期 + * @param IWindCacheDependency $denpendency 缓存依赖 + * @return bool + * @throws WindCacheException 缓存失败时抛出异常 + */ + public function set($key, $value, $expires = 0, IWindCacheDependency $dependency = null) + { + try { + $expires = $expires ? $expires : $this->getExpire(); + $data = $this->buildData($value, $expires, $dependency); + + return $this->setValue($this->buildSecurityKey($key), $data, $expires); + } catch (Exception $e) { + throw new WindCacheException('[cache.AbstractWindCache.set] Setting cache failed.'.$e->getMessage()); + } + } + + /** + * 增加一个条目到缓存服务器 + * + * 方法在缓存服务器之前不存在key时, 以key作为key存储一个变量var到缓存服务器。 + * 注意:新的元素的值不会小于0。 并且在元素不存在时不能创建它 + * + * @param string $key 保存缓存数据的键。 + * @param string $value 保存缓存数据。 + * @param int $expires 缓存数据的过期时间,0表示永不过期 + * @param IWindCacheDependency $denpendency 缓存依赖 + * @return bool 成功时返回 TRUE, 或者在失败时返回 FALSE. 如果这个key已经存在返回FALSE。 + */ + public function add($key, $value, $expires = 0, IWindCacheDependency $dependency = null) + { + try { + $key = $this->buildSecurityKey($key); + $data = $this->getValue($key); + if ($data) { + return false; + } + $expires = $expires ? $expires : $this->getExpire(); + $data = $this->buildData($value, $expires, $dependency); + + return $this->addValue($key, $data, $expires); + } catch (Exception $e) { + throw new WindCacheException('[cache.AbstractWindCache.set] Setting cache failed.'.$e->getMessage()); + } + } + + /** + * 根据缓存key获取指定缓存 + * + * @param string $key 获取缓存数据的标识,即键 + * @return mixed 返回被缓存的数据 + * @throws WindCacheException 获取失败时抛出异常 + */ + public function get($key) + { + try { + return $this->formatData($key, $this->getValue($this->buildSecurityKey($key))); + } catch (Exception $e) { + throw new WindCacheException('[cache.AbstractWindCache.get] Getting cache data failed. ('.$e->getMessage().')'); + } + } + + /** + * 通过key批量获取缓存数据 + * + * @param array $keys 批量缓存的key集合 + * @return array 返回批量key对应的缓存数据组成的缓存数据数组 + */ + public function batchGet(array $keys) + { + $data = array(); + foreach ($keys as $key) { + $data[$key] = $this->get($key); + } + + return $data; + } + + /** + * 删除缓存数据 + * + * @param string $key 获取缓存数据的标识,即键 + * @return bool + * @throws WindCacheException 删除失败时抛出异常 + */ + public function delete($key) + { + try { + return $this->deleteValue($this->buildSecurityKey($key)); + } catch (Exception $e) { + throw new WindCacheException('[cache.AbstractWindCache.delete] Delete cache data failed. ('.$e->getMessage().')'); + } + } + + /** + * 通过key批量删除缓存数据 + * + * @param array $keys 需要批量删除的缓存key组成的组数 + * @return bool + */ + public function batchDelete(array $keys) + { + foreach ($keys as $key) { + $this->delete($key); + } + + return true; + } + + /** + * 将指定元素的值增加value + * + * 如果指定的key 对应的元素不是数值类型并且不能被转换为数值, 会将此值修改为value. + * 注意:不会在key对应元素不存在时创建元素。 + * + * @param string $key 将要增加值的元素的key。 + * @param int $step 参数value表明要将指定元素值增加多少。 + * @return int 成功时返回新的元素值失败时返回false。 + */ + public function increment($key, $step = 1) + { + $data = $this->get($key); + if (!is_numeric($data)) { + return false; + } + $data += intval($step); + $this->set($key, $data); + + return $data; + } + + /** + * 将元素的值减小value + * + * 如果指定的key 对应的元素不是数值类型并且不能被转换为数值, 会将此值修改为value. + * 注意:新的元素的值不会小于0。 并且在元素不存在时不能创建它 + * + * @param string $key 将要增加值的元素的key。 + * @param int $step value参数指要将指定元素的值减小多少。 + * @return int 成功的时候返回元素的新值,失败的时候返回false。 + */ + public function decrement($key, $step = 1) + { + $data = $this->get($key); + if (!is_numeric($data)) { + return false; + } + $data -= intval($step); + $data < 0 && $data = 0; + $this->set($key, $data); + + return $data; + } + + /** + * 构造保存的数据 + * + * @param string $value 保存缓存数据。 + * @param int $expires 缓存数据的过期时间,0表示永不过期 + * @param IWindCacheDependency $denpendency 缓存依赖 + * @return array + */ + protected function buildData($value, $expires = 0, IWindCacheDependency $dependency = null) + { + $data = array( + self::DATA => $value, + self::EXPIRE => $expires, + self::STORETIME => time(), + self::DEPENDENCY => null, + self::DEPENDENCYCLASS => '', ); + if (null !== $dependency) { + $dependency->injectDependent(self::EXPIRE); + $data[self::DEPENDENCY] = $dependency; + $data[self::DEPENDENCYCLASS] = get_class($dependency); + } + + return serialize($data); + } + + /** + * 格式化输出 + * + * 将从缓存对象中获得的缓存源数据进行格式化输出.该源数据是一个格式良好的数组的序列化字符串,需要反序列化获得源数组. + * 如果没有数据,则返回false + * 如果含有数据,则返回该数据 + * + * @param string $key 缓存的key值 + * @param string $value 缓存的数据的序列化值 + * @return mixed 返回保存的真实数据,如果没有数值则返回false + */ + protected function formatData($key, $value) + { + if (!$value) { + return false; + } + + $data = (array) unserialize($value); + + return $this->hasChanged($key, $data) ? false : $data[self::DATA]; + } + + /** + * 判断数据是否已经被更新 + * + * 如果缓存中有数据,则检查缓存依赖是否已经变更,如果变更则删除缓存,并且返回true. + * 如果没有更新则返回false. + * + * @param string $key 缓存的key + * @param array $data 缓存中的数据 + * @return bool true表示缓存已变更,false表示缓存未变改 + */ + protected function hasChanged($key, array $data) + { + if ($data[self::DEPENDENCY]) { + $dependency = $data[self::DEPENDENCY]; + if (!$dependency->hasChanged($this, $key, $data[self::EXPIRE])) { + return false; + } + } elseif ($data[self::EXPIRE]) { + $_overTime = $data[self::EXPIRE] + $data[self::STORETIME]; + if ($_overTime >= time()) { + return false; + } + } else { + return false; + } + $this->delete($key); + + return true; + } + + /** + * 将数据key计算生成安全的key + * + * @param string $key 真实的缓存key + * @return string 加入安全码计算之后返回的保存key + */ + protected function buildSecurityKey($key) + { + $this->keyPrefix && $key = $this->keyPrefix.'_'.$key; + + return $key.$this->getSecurityCode(); + } + + /** + * 返回缓存Key值前缀 + * + * 默认值为null无任何前缀添加 + * + * @return string $prefix 返回key前缀 + */ + protected function getKeyPrefix() + { + return $this->keyPrefix; + } + + /** + * 设置key前缀 + * + * @param sting $keyPrefix key的前缀 + */ + public function setKeyPrefix($keyPrefix) + { + $this->keyPrefix = $keyPrefix; + } + + /** + * 获得缓存key计算中加入的安全码 + * + * @return string $securityCode + */ + protected function getSecurityCode() + { + return $this->securityCode; + } + + /** + * 设置缓存key计算中加入的安全码 + * + * @param string $securityCode 安全码 + */ + public function setSecurityCode($securityCode) + { + $this->securityCode = $securityCode; + } + + /** + * 返回过期时间设置 + * + * 单位为秒,默认值为0永不过期 + * + * @return int $expire 缓存过期时间,默认为0永不过期,单位为秒 + */ + public function getExpire() + { + return $this->expire; + } + + /** + * 设置缓存过期时间 + * + * 单位为秒,默认为0永不过期 + * + * @param int $expire 缓存过期时间,单位为秒,默认为0永不过期 + */ + public function setExpire($expire) + { + $this->expire = intval($expire); + } + + /** + * 设置配置信息 + * + * 支持三个配置项: + *
      + *
    • security-code: 安全码配置
    • + *
    • key-prefix: key前缀设置
    • + *
    • expires: 缓存过期时间配置,单位为秒,默认为0
    • + *
    + * + * @param array $config 缓存配置信息 + */ + public function setConfig($config) + { + parent::setConfig($config); + $this->setSecurityCode($this->getConfig('security-code', '', '')); + $this->setKeyPrefix($this->getConfig('key-prefix', '', '')); + $this->setExpire($this->getConfig('expires', '', 0)); + } +} diff --git a/wind/cache/IWindCacheDependency.php b/wind/cache/IWindCacheDependency.php index a62e7162..be29e94e 100644 --- a/wind/cache/IWindCacheDependency.php +++ b/wind/cache/IWindCacheDependency.php @@ -5,26 +5,25 @@ * @author xiaoxia.xu * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: IWindCacheDependency.php 2973 2011-10-15 19:22:48Z yishuo $ * @package cache */ -interface IWindCacheDependency { +interface IWindCacheDependency +{ + /** + * 初始化依赖设置 + * + * @param int $expires 缓存的过期时间 + */ + public function injectDependent($expires); - /** - * 初始化依赖设置 - * - * @param int $expires 缓存的过期时间 - */ - public function injectDependent($expires); - - /** - * 检查是否有变更 - * - * @param AbstractWindCache $cache 缓存对象 - * @param string $key - * @param int $expires - * @return boolean 如果有变化则返回true,如果没有变化返回false - */ - public function hasChanged($cache, $key, $expires); - -} \ No newline at end of file + /** + * 检查是否有变更 + * + * @param AbstractWindCache $cache 缓存对象 + * @param string $key + * @param int $expires + * @return bool 如果有变化则返回true,如果没有变化返回false + */ + public function hasChanged($cache, $key, $expires); +} diff --git a/wind/cache/dependency/WindResolvedCrashDependency.php b/wind/cache/dependency/WindResolvedCrashDependency.php index e7c784b9..3dacf7bf 100644 --- a/wind/cache/dependency/WindResolvedCrashDependency.php +++ b/wind/cache/dependency/WindResolvedCrashDependency.php @@ -1,8 +1,9 @@ * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindResolvedCrashDependency.php 2973 2011-10-15 19:22:48Z yishuo $ * @package cache * @subpackage dependency */ -class WindResolvedCrashDependency implements IWindCacheDependency { - - private $timeOut = ''; - - private $callBack = array(); - - private $args = array(); - - /** - * @param array $callBack 回调方法,通过该方法返回当前数据 - * @param array $args 回调方法参数 - * @param int $timeOut 超时时间 - */ - public function __construct($callBack, $args = array(), $timeOut = 0) { - $this->timeOut = (int) $timeOut + time(); - $this->callBack = serialize($callBack); - $this->args = serialize($args); - } - - /* (non-PHPdoc) - * @see IWindCacheDependency::injectDependent() - */ - public function injectDependent($expires) { - if ($this->timeOut > 0) return; - $this->timeOut = $expires > 0 ? 0.8 * $expires + time() : 0; - } - - /* (non-PHPdoc) - * @see IWindCacheDependency::hasChanged() - */ - public function hasChanged($cache, $key, $expires) { - if (0 == $this->timeOut) return false; - if ($this->timeOut <= time()) { - $lock = $key . '_lock_'; - if ($cache->add($lock, 3 * 60 * 1000) == true) { - $callBack = unserialize($this->callBack); - $data = call_user_func_array($callBack, unserialize($this->args)); - $cache->set($key, $data, $expires, $this); - $cache->delete($lock); - } - } - return false; - } -} \ No newline at end of file +class WindResolvedCrashDependency implements IWindCacheDependency +{ + private $timeOut = ''; + + private $callBack = array(); + + private $args = array(); + + /** + * @param array $callBack 回调方法,通过该方法返回当前数据 + * @param array $args 回调方法参数 + * @param int $timeOut 超时时间 + */ + public function __construct($callBack, $args = array(), $timeOut = 0) + { + $this->timeOut = (int) $timeOut + time(); + $this->callBack = serialize($callBack); + $this->args = serialize($args); + } + + /* (non-PHPdoc) + * @see IWindCacheDependency::injectDependent() + */ + public function injectDependent($expires) + { + if ($this->timeOut > 0) { + return; + } + $this->timeOut = $expires > 0 ? 0.8 * $expires + time() : 0; + } + + /* (non-PHPdoc) + * @see IWindCacheDependency::hasChanged() + */ + public function hasChanged($cache, $key, $expires) + { + if (0 == $this->timeOut) { + return false; + } + if ($this->timeOut <= time()) { + $lock = $key.'_lock_'; + if ($cache->add($lock, 3 * 60 * 1000) == true) { + $callBack = unserialize($this->callBack); + $data = call_user_func_array($callBack, unserialize($this->args)); + $cache->set($key, $data, $expires, $this); + $cache->delete($lock); + } + } + + return false; + } +} diff --git a/wind/cache/exception/WindCacheException.php b/wind/cache/exception/WindCacheException.php index 56a3c0db..29dabee5 100644 --- a/wind/cache/exception/WindCacheException.php +++ b/wind/cache/exception/WindCacheException.php @@ -1,18 +1,15 @@ * @author Qiong Wu * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindCacheException.php 2973 2011-10-15 19:22:48Z yishuo $ * @package cache * @subpackage exception */ -class WindCacheException extends WindException { - - +class WindCacheException extends WindException +{ } - -?> \ No newline at end of file diff --git a/wind/cache/strategy/WindApcCache.php b/wind/cache/strategy/WindApcCache.php index ab4b1a42..e2d7f1b6 100644 --- a/wind/cache/strategy/WindApcCache.php +++ b/wind/cache/strategy/WindApcCache.php @@ -1,8 +1,9 @@ @@ -24,11 +25,11 @@ * 使用方式:
    * 1、您可以像使用普通的类一样使用该组件,如下: * - * Wind::import('WIND:cache.strategy.WindApcCache'); + * * $cache = new WindApcCache(); * $cache->set('name', 'windframework'); * - * + * * 2、同时作为组件,WindApcCache也允许用户通过组件配置得方式,通过框架的组件机制来获得该缓存对象进行操作. * 在应用配置中的组件配置块(components),配置使用该组件如下: * @@ -36,7 +37,7 @@ * 'path' => 'WIND:cache.strategy.WindApcCache', * 'scope' => 'singleton', * 'config' => array( - * 'security-code' => '', + * 'security-code' => '', * 'key-prefix' => '', * 'expires' => '0', * ), @@ -44,54 +45,59 @@ * * 在应用中通过如下方式使用: * - * $cache = Wind::getApp()->getComponent('apcCache'); //注意这里的apcCache组件名称和配置的组件名称需要对应 + * $cache = Wind::getComponent('apcCache'); //注意这里的apcCache组件名称和配置的组件名称需要对应 * $cache->set('name', 'wf'); * * 关于组件配置的相关说明请参考组件配置一章. - * + * * 注意: 要使用ApcCache组件,需要安装apc扩展支持. - * - * the last known user to change this file in the repository + * + * the last known user to change this file in the repository * @author xiaoxiao * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ + * @license http://www.windframework.com + * @version $Id: WindApcCache.php 3791 2012-10-30 04:01:29Z liusanbian $ * @package strategy */ -class WindApcCache extends AbstractWindCache { +class WindApcCache extends AbstractWindCache +{ + /* (non-PHPdoc) + * @see AbstractWindCache::setValue() + */ + protected function setValue($key, $value, $expires = 0) + { + return apc_store($key, $value, $expires); + } - /* (non-PHPdoc) - * @see AbstractWindCache::setValue() - */ - protected function setValue($key, $value, $expires = 0) { - return apc_store($key, $value, $expires); - } + /* (non-PHPdoc) + * @see AbstractWindCache::getValue() + */ + protected function getValue($key) + { + return apc_fetch($key); + } - /* (non-PHPdoc) - * @see AbstractWindCache::getValue() - */ - protected function getValue($key) { - return apc_fetch($key); - } + /* (non-PHPdoc) + * @see AbstractWindCache::deleteValue() + */ + protected function deleteValue($key) + { + return apc_delete($key); + } - /* (non-PHPdoc) - * @see AbstractWindCache::deleteValue() - */ - protected function deleteValue($key) { - return apc_delete($key); - } + /*(non-PHPdoc) + * @see AbstractWindCache::clear() + */ + public function clear() + { + return apc_clear_cache('user'); + } - /*(non-PHPdoc) - * @see AbstractWindCache::clear() - */ - public function clear() { - return apc_clear_cache('user'); - } - - /* (non-PHPdoc) - * @see AbstractWindCache::addValue() - */ - public function addValue($key, $value, $expires = 0) { - return apc_add($key, $value, $expires); - } -} \ No newline at end of file + /* (non-PHPdoc) + * @see AbstractWindCache::addValue() + */ + public function addValue($key, $value, $expires = 0) + { + return apc_add($key, $value, $expires); + } +} diff --git a/wind/cache/strategy/WindDbCache.php b/wind/cache/strategy/WindDbCache.php index 1109f98c..593dd6ff 100644 --- a/wind/cache/strategy/WindDbCache.php +++ b/wind/cache/strategy/WindDbCache.php @@ -1,8 +1,9 @@ @@ -13,11 +14,11 @@ *
  • batchDelete($keys): 继承自{@link AbstractWindCache::batchDelete()}.
  • *
  • {@link setConfig($config)}: 重写了父类的{@link AbstractWindCache::setConfig()}.
  • * - * + * * 它接收如下配置: * * array( - * 'table-name' => 'pw_cache', //缓存的表名 + * 'table-name' => 'cache', //缓存的表名 * 'field-key' => 'key', //缓存key的字段名,唯一键值 * 'field-value' => 'value', //缓存数据存储的字段名 * 'field-expire' => 'expire', //缓存数据的过期时间字段名,为int类型,默认为0 @@ -29,7 +30,7 @@ * Db缓存的使用:
    * 1、像使用普通类库一样使用该组件: * - * Wind::import('WIND:cache.strategy.WindDbCache'); + * * $cache = new WindDbCache($dbHandler, array('table-name' => 'pw_cache', 'field-key' => 'key', 'field-value' => 'value', 'field-expire' => '0')); * $cache->set('name', 'windDbTest'); * @@ -44,11 +45,11 @@ * 'connection' => array('ref' => 'db'); * ), * 'config' => array( - * 'table-name' => 'pw_cache', + * 'table-name' => 'cache', * 'field-key' => 'key', * 'field-value' => 'value', * 'field-expire' => 'expire', - * 'security-code' => '', + * 'security-code' => '', * 'key-prefix' => '', * 'expires' => '0', * ), @@ -56,204 +57,247 @@ * * 在应用中可以通过如下方式获得dbCache对象: * - * $cache = Wind::getApp()->getComponent('dbCache'); //dbCache的名字来自于组件配置中的名字 + * $cache = Wind::getComponent('dbCache'); //dbCache的名字来自于组件配置中的名字 * $cache->set('name', 'test'); * * 注意: 组件配置需要配置属性(preperties),connection其值为db组件的一个引用 - * + * * the last known user to change this file in the repository * @author xiaoxiao * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindDbCache.php 3791 2012-10-30 04:01:29Z liusanbian $ * @package strategy */ -class WindDbCache extends AbstractWindCache { - - /** - * 链接句柄 - * - * @var WindConnection - */ - protected $connection; - - /** - * 缓存表名 - * - * @var string - */ - private $table = 'pw_cache'; - - /** - * 缓存表的键字段 - * - * @var string - */ - private $keyField = 'key'; - - /** - * 缓存表的值字段 - * - * @var string - */ - private $valueField = 'value'; - - /** - * 缓存表过期时间字段 - * - * @var string - */ - private $expireField = 'expire'; +class WindDbCache extends AbstractWindCache +{ + /** + * 链接句柄 + * + * @var WindConnection + */ + protected $connection; + + /** + * 缓存表名 + * + * @var string + */ + private $table = 'cache'; + + /** + * 缓存表的键字段 + * + * @var string + */ + private $keyField = 'key'; + + /** + * 缓存表的值字段 + * + * @var string + */ + private $valueField = 'value'; + + /** + * 缓存表过期时间字段 + * + * @var string + */ + private $expireField = 'expire'; + + /** + * 构造函数 + * + * 初始化数据 + * + * @param WindConnection $connection 数据库链接对象,缺省值为null + * @param array $config 缓存的配置文件,缺省值为array() + */ + public function __construct(WindConnection $connection = null, $config = array()) + { + $connection && $this->setConnection($connection); + $config && $this->setConfig($config); + } + + /* (non-PHPdoc) + * @see AbstractWindCache::setValue() + */ + protected function setValue($key, $value, $expire = 0) + { + return $this->store($key, $value, $expire); + } + + /* (non-PHPdoc) + * @see AbstractWindCache::addValue() + */ + protected function addValue($key, $value, $expire = 0) + { + return $this->store($key, $value, $expire, 'add'); + } + + /* (non-PHPdoc) + * @see AbstractWindCache::getValue() + */ + protected function getValue($key) + { + $sql = 'SELECT * FROM '.$this->getTableName().' WHERE `'.$this->keyField.'` =? '; + $data = $this->getConnection()->createStatement($sql)->getOne(array($key)); + if (!$data) { + return false; + } + + return $this->_checkExpire($data[$this->expireField], time()) ? false : $data[$this->valueField]; + } + + /* (non-PHPdoc) + * @see AbstractWindCache::batchGet() + */ + public function batchGet(array $keys) + { + if (!$keys) { + return array(); + } + $_temp = $result = array(); + foreach ($keys as $value) { + $_temp[$value] = $this->buildSecurityKey($value); + } + $sql = 'SELECT * FROM '.$this->getTableName().' WHERE `'.$this->keyField.'` IN '.$this->getConnection()->quoteArray($_temp); + $data = $this->getConnection()->createStatement($sql)->queryAll(array(), $this->keyField); + $_now = time(); + foreach ($_temp as $key => $cacheKey) { + $result[$key] = false; + if (!isset($data[$cacheKey])) { + continue; + } + $tmp = $data[$cacheKey]; + $result[$key] = $this->_checkExpire($tmp[$this->expireField], $_now) ? false : $this->formatData($key, $tmp[$this->valueField]); + } + + return $result; + } + + /* (non-PHPdoc) + * @see AbstractWindCache::deleteValue() + */ + protected function deleteValue($key) + { + $sql = 'DELETE FROM '.$this->getTableName().' WHERE `'.$this->keyField.'` = ? '; + + return $this->getConnection()->createStatement($sql)->update(array($key)); + } - /** - * 构造函数 - * - * 初始化数据 - * - * @param WindConnection $connection 数据库链接对象,缺省值为null - * @param array $config 缓存的配置文件,缺省值为array() - */ - public function __construct(WindConnection $connection = null, $config = array()) { - $connection && $this->setConnection($connection); - $config && $this->setConfig($config); - } + /* (non-PHPdoc) + * @see AbstractWindCache::batchDelete() + */ + public function batchDelete(array $keys) + { + array_walk($keys, array($this, 'buildSecurityKey')); + $sql = 'DELETE FROM '.$this->getTableName().' WHERE `'.$this->keyField.'` IN '.$this->getConnection()->quoteArray($keys); - /* (non-PHPdoc) - * @see AbstractWindCache::setValue() - */ - protected function setValue($key, $value, $expire = 0) { - return $this->store($key, $value, $expire); - } - - /* (non-PHPdoc) - * @see AbstractWindCache::addValue() - */ - protected function addValue($key, $value, $expire = 0) { - return $this->store($key, $value, $expire, 'add'); - } + return $this->getConnection()->execute($sql); + } - /* (non-PHPdoc) - * @see AbstractWindCache::getValue() - */ - protected function getValue($key) { - $sql = 'SELECT * FROM ' . $this->getTableName() . ' WHERE `' . $this->keyField . '` =? AND (`' . $this->expireField . '`=0 OR `' . $this->expireField . '`>?)'; - $data = $this->getConnection()->createStatement($sql)->getOne(array($key, time())); - return $data[$this->valueField]; - } + /** + * 清除缓存数据 + *
      + *
    • 如果$expireOnly=true,则将只删除过期的数据。
    • + *
    • 如果$expireOnly=false,则将删除所有缓存数据。
    • + *
    + * + * @param bool $expireOnly 如果删除过期数据则设置为true,如果全部缓存都删除则为false,缺省值为true + * @return int + */ + public function clear($expireOnly = true) + { + $sql = sprintf('DELETE FROM `%s`', $this->getTableName()); + if ($expireOnly) { + $sql = sprintf('DELETE FROM `%s` WHERE `%s` < ', $this->getTableName(), $this->expireField).$this->getConnection()->quote(time()); + } - /* (non-PHPdoc) - * @see AbstractWindCache::batchGet() - */ - public function batchGet(array $keys) { - $_temp = array(); - foreach ($keys as $value) { - $_temp[$value] = $this->buildSecurityKey($value); - } - list($sql, $result) = array('', array()); - $sql = 'SELECT * FROM ' . $this->getTableName() . ' WHERE `' . $this->keyField . '` IN ' . $this->getConnection()->quoteArray( - $_temp) . ' AND (`' . $this->expireField . '`=0 OR `' . $this->expireField . '`>?)'; - $data = $this->getConnection()->createStatement($sql)->queryAll(array(time())); - $_keys = array_flip($_temp); - foreach ($data as $tmp) { - $result[$_keys[$tmp[$this->keyField]]] = $this->formatData($_keys[$tmp[$this->keyField]], $tmp[$this->valueField]); - } - return $result; - } + return $this->getConnection()->execute($sql); + } - /* (non-PHPdoc) - * @see AbstractWindCache::deleteValue() - */ - protected function deleteValue($key) { - $sql = 'DELETE FROM ' . $this->getTableName() . ' WHERE `' . $this->keyField . '` = ? '; - return $this->getConnection()->createStatement($sql)->update(array($key)); - } + /* (non-PHPdoc) + * @see AbstractWindCache::setConfig() + */ + public function setConfig($config) + { + parent::setConfig($config); + $this->table = $this->getConfig('table-name', '', 'cache', $config); + $this->keyField = $this->getConfig('field-key', '', 'key', $config); + $this->valueField = $this->getConfig('field-value', '', 'value', $config); + $this->expireField = $this->getConfig('field-expire', '', 'expire', $config); + } - /* (non-PHPdoc) - * @see AbstractWindCache::batchDelete() - */ - public function batchDelete(array $keys) { - foreach ($keys as $key => $value) { - $keys[$key] = $this->buildSecurityKey($value); - } - $sql = 'DELETE FROM ' . $this->getTableName() . ' WHERE `' . $this->keyField . '` IN ' . $this->getConnection()->quoteArray( - $keys); - return $this->getConnection()->execute($sql); - } + /** + * 设置链接对象 + * + * @param WindConnection $connection + */ + public function setConnection($connection) + { + if ($connection instanceof WindConnection) { + $this->connection = $connection; + } + } - /** - * 清除缓存数据 - *
      - *
    • 如果$expireOnly=true,则将只删除过期的数据。
    • - *
    • 如果$expireOnly=false,则将删除所有缓存数据。
    • - *
    - * - * @param boolean $expireOnly 如果删除过期数据则设置为true,如果全部缓存都删除则为false,缺省值为true - * @return int - */ - public function clear($expireOnly = true) { - $sql = sprintf('DELETE FROM `%s`', $this->getTableName()); - if ($expireOnly) { - $sql = sprintf('DELETE FROM `%s` WHERE `%s` < ', $this->getTableName(), $this->expireField) . $this->getConnection()->quote( - time()); - } - return $this->getConnection()->execute($sql); - } + /** + * 返回缓存表名 + * + * @return string + */ + private function getTableName() + { + return $this->getConnection()->getTablePrefix().$this->table; + } - /* (non-PHPdoc) - * @see AbstractWindCache::setConfig() - */ - public function setConfig($config) { - parent::setConfig($config); - $this->table = $this->getConfig('table-name', '', 'pw_cache', $config); - $this->keyField = $this->getConfig('field-key', '', 'key', $config); - $this->valueField = $this->getConfig('field-value', '', 'value', $config); - $this->expireField = $this->getConfig('field-expire', '', 'expire', $config); - } + /** + * 存储数据 + * + * @param string $key 保存的缓存key, + * @param string $value 保存的缓存数据 + * @param int $expires 缓存保存的时间,如果为0则永不过期,默认为0 + * @param string $type 缓存的保存方式,默认为set将使用replace方式保存 + * @return int + */ + private function store($key, $value, $expires = 0, $type = 'set') + { + ($expires > 0) ? $expires += time() : $expire = 0; + $db = array($this->keyField => $key, $this->valueField => $value, $this->expireField => $expires); + if ($type == 'add') { + $sql = 'INSERT INTO '.$this->getTableName().' SET '.$this->getConnection()->sqlSingle($db); + } else { + $sql = 'REPLACE INTO '.$this->getTableName().' SET '.$this->getConnection()->sqlSingle($db); + } - /** - * 设置链接对象 - * - * @param WindConnection $connection - */ - public function setConnection($connection) { - if ($connection instanceof WindConnection) $this->connection = $connection; - } + return $this->getConnection()->createStatement($sql)->update(); + } - /** - * 返回缓存表名 - * - * @return string - */ - private function getTableName() { - return $this->table; - } + /** + * 判断是否过期 + * 过期则返回true/否则返回false + * + * @param int $endTime + * @param int $nowTime + * @return bool + */ + private function _checkExpire($endTime, $nowTime) + { + if ($endTime == 0) { + return false; + } - /** - * 存储数据 - * - * @param string $key 保存的缓存key, - * @param string $value 保存的缓存数据 - * @param int $expires 缓存保存的时间,如果为0则永不过期,默认为0 - * @param string $type 缓存的保存方式,默认为set将使用replace方式保存 - * @return int - */ - private function store($key, $value, $expires = 0, $type="set") { - ($expires > 0) ? $expires += time() : $expire = 0; - $db = array($this->keyField => $key, $this->valueField => $value, $this->expireField => $expires); - if ($type == 'add') { - $sql = 'INSERT INTO ' . $this->getTableName() . ' SET ' . $this->getConnection()->sqlSingle($db); - } else { - $sql = 'REPLACE INTO ' . $this->getTableName() . ' SET ' . $this->getConnection()->sqlSingle($db); - } - return $this->getConnection()->createStatement($sql)->update(); - } + return $endTime <= $nowTime; + } - /** - * 获得链接对象 - * - * @return WindConnection - */ - private function getConnection() { - return $this->_getConnection(); - } -} \ No newline at end of file + /** + * 获得链接对象 + * + * @return WindConnection + */ + private function getConnection() + { + return $this->_getConnection(); + } +} diff --git a/wind/cache/strategy/WindEacceleratorCache.php b/wind/cache/strategy/WindEacceleratorCache.php index 1658998d..8c7f472d 100644 --- a/wind/cache/strategy/WindEacceleratorCache.php +++ b/wind/cache/strategy/WindEacceleratorCache.php @@ -1,108 +1,115 @@ - - *
  • set($key, $value, $expire): 继承自{@link AbstractWindCache::set()}.
  • - *
  • get($key): 继承自{@link AbstractWindCache::get()}.
  • - *
  • delete($key): 继承自{@link AbstractWindCache::delete()}.
  • - *
  • batchGet($keys): 继承自{@link AbstractWindCache::batchGet()}.
  • - *
  • batchDelete($keys): 继承自{@link AbstractWindCache::batchDelete()}.
  • - *
  • setConfig($config): 继承自{@link AbstractWindCache::setConfig()}.
  • - * - * 该缓存策略从AbstractWindCache类中继承三个配置项: - * - * array( - * 'security-code' => '', //继承自AbstractWindCache,安全码配置 - * 'key-prefix' => '', //继承自AbstractWindCache,缓存key前缀 - * 'expires' => '0', //继承自AbstractWindCache,缓存过期时间配置 - * ) - * - * 使用方式:
    - * 1、您可以像使用普通类库一样使用该组件: - * - * Wind::import('WIND:cache.strategy.WindEacceleratorCache'); - * $cache = new WindEacceleratorCache(); - * $cache->set('name', 'xxx'); - * - * 2、同时您也可以使用组件配置的方式实现调用,在应用配置中的组件配置块(components),配置该组件命名为eacceleratorCache如下: - * - * 'eacceleratorCache' => array( - * 'path' => 'WIND:cache.strategy.WindEacceleratorCache', - * 'scope' => 'singleton', - * 'config' => array( - * 'security-code' => '', - * 'key-prefix' => '', - * 'expires' => '0', - * ), - * ), - * - * 在应用中可以通过如下方式实现访问: - * - * $cache = Wind::getApp()->getComponent('eacceleratorCache'); - * $cache->set('name', 'cacheTest'); - * - * 关于组件配置的相关说明请参考组件配置一章. - * - * 注意:要使用EacceleratorCache组件,需要安装eaccelerator扩展支持。 - * - * the last known user to change this file in the repository - * @author xiaoxiao - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package strategy - */ -class WindEacceleratorCache extends AbstractWindCache { - - /** - * 构造函数 - * - * 判断是否有安装eaccelerator扩展,如果没有安装则会抛出WindCacheException异常 - * - * @throws WindCacheException - */ - public function __construct() { - if (!function_exists('eaccelerator_get')) { - throw new WindCacheException('The eaccelerator extension must be loaded !'); - } - } - - /* (non-PHPdoc) - * @see AbstractWindCache::setValue() - */ - protected function setValue($key, $value, $expire = 0) { - return eaccelerator_put($key, $value, $expire); - } - - /* (non-PHPdoc) - * @see AbstractWindCache::addValue() - */ - protected function addValue($key, $value, $expire = 0) { - return eaccelerator_put($key,$value,$expire); - } - - /* (non-PHPdoc) - * @see AbstractWindCache::get() - */ - protected function getValue($key) { - return eaccelerator_get($key); - } - - /* (non-PHPdoc) - * @see AbstractWindCache::deleteValue() - */ - protected function deleteValue($key) { - return eaccelerator_rm($key); - } - - /* (non-PHPdoc) - * @see AbstractWindCache::clear() - */ - public function clear() { - return eaccelerator_gc(); - } -} \ No newline at end of file + + *
  • set($key, $value, $expire): 继承自{@link AbstractWindCache::set()}.
  • + *
  • get($key): 继承自{@link AbstractWindCache::get()}.
  • + *
  • delete($key): 继承自{@link AbstractWindCache::delete()}.
  • + *
  • batchGet($keys): 继承自{@link AbstractWindCache::batchGet()}.
  • + *
  • batchDelete($keys): 继承自{@link AbstractWindCache::batchDelete()}.
  • + *
  • setConfig($config): 继承自{@link AbstractWindCache::setConfig()}.
  • + * + * 该缓存策略从AbstractWindCache类中继承三个配置项: + * + * array( + * 'security-code' => '', //继承自AbstractWindCache,安全码配置 + * 'key-prefix' => '', //继承自AbstractWindCache,缓存key前缀 + * 'expires' => '0', //继承自AbstractWindCache,缓存过期时间配置 + * ) + * + * 使用方式:
    + * 1、您可以像使用普通类库一样使用该组件: + * + * + * $cache = new WindEacceleratorCache(); + * $cache->set('name', 'xxx'); + * + * 2、同时您也可以使用组件配置的方式实现调用,在应用配置中的组件配置块(components),配置该组件命名为eacceleratorCache如下: + * + * 'eacceleratorCache' => array( + * 'path' => 'WIND:cache.strategy.WindEacceleratorCache', + * 'scope' => 'singleton', + * 'config' => array( + * 'security-code' => '', + * 'key-prefix' => '', + * 'expires' => '0', + * ), + * ), + * + * 在应用中可以通过如下方式实现访问: + * + * $cache = Wind::getComponent('eacceleratorCache'); + * $cache->set('name', 'cacheTest'); + * + * 关于组件配置的相关说明请参考组件配置一章. + * + * 注意:要使用EacceleratorCache组件,需要安装eaccelerator扩展支持。 + * + * the last known user to change this file in the repository + * @author xiaoxiao + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id: WindEacceleratorCache.php 3904 2013-01-08 07:01:26Z yishuo $ + * @package strategy + */ +class WindEacceleratorCache extends AbstractWindCache +{ + /** + * 构造函数 + * + * 判断是否有安装eaccelerator扩展,如果没有安装则会抛出WindCacheException异常 + * + * @throws WindCacheException + */ + public function __construct() + { + if (!function_exists('eaccelerator_get')) { + throw new WindCacheException('[cache.strategy.WindEacceleratorCache] The eaccelerator extension must be loaded !'); + } + } + + /* (non-PHPdoc) + * @see AbstractWindCache::setValue() + */ + protected function setValue($key, $value, $expire = 0) + { + return eaccelerator_put($key, $value, $expire); + } + + /* (non-PHPdoc) + * @see AbstractWindCache::addValue() + */ + protected function addValue($key, $value, $expire = 0) + { + return eaccelerator_put($key, $value, $expire); + } + + /* (non-PHPdoc) + * @see AbstractWindCache::get() + */ + protected function getValue($key) + { + return eaccelerator_get($key); + } + + /* (non-PHPdoc) + * @see AbstractWindCache::deleteValue() + */ + protected function deleteValue($key) + { + return eaccelerator_rm($key); + } + + /* (non-PHPdoc) + * @see AbstractWindCache::clear() + */ + public function clear() + { + return eaccelerator_gc(); + } +} diff --git a/wind/cache/strategy/WindFileCache.php b/wind/cache/strategy/WindFileCache.php index 36e08d1a..3d654419 100644 --- a/wind/cache/strategy/WindFileCache.php +++ b/wind/cache/strategy/WindFileCache.php @@ -1,9 +1,9 @@ *
  • set($key, $value, $expire): 继承自{@link AbstractWindCache::set()}.
  • @@ -11,7 +11,8 @@ *
  • delete($key): 继承自{@link AbstractWindCache::delete()}.
  • *
  • batchGet($keys): 继承自{@link AbstractWindCache::batchGet()}.
  • *
  • batchDelete($keys): 继承自{@link AbstractWindCache::batchDelete()}.
  • - *
  • {@link setConfig($config)}: 重写了父类的{@link AbstractWindCache::setConfig()}.
  • + *
  • {@link setConfig($config)}: 重写了父类的{@link + * AbstractWindCache::setConfig()}.
  • * * 它接收如下配置: * @@ -20,14 +21,14 @@ * 'suffix' => 'txt', //缓存文件的后缀,默认为txt后缀 * 'dir-level' => '0', //缓存文件存放目录的子目录长度,默认为0不分子目录 * 'security-code' => '', //继承自AbstractWindCache,安全码配置 - * 'key-prefix' => '', //继承自AbstractWindCache,缓存key前缀 + * 'key-prefix' => '', //继承自AbstractWindCache,缓存key前缀 * 'expires' => '0', //继承自AbstractWindCache,缓存过期时间配置 * ) * * 使用方法:
    * 1、您可以像使用普通类库一样使用该组件: * - * Wind::import('WIND:cache.strategy.WindFileCache'); + * * $cache = new WindFileCache(); * $cache->setConfig(array('dir' => 'data', 'suffix' => 'php')); * $cache->set('name', 'fileCacheTest'); @@ -42,7 +43,7 @@ * 'dir' => 'data', * 'suffix' => 'txt', * 'dir-level' => '0', - * 'security-code' => '', + * 'security-code' => '', * 'key-prefix' => '', * 'expires' => '0', * ), @@ -50,200 +51,218 @@ * * 在应用中可以通过如下方式获得dbCache对象: * - * $fileCache = Wind::getApp()->getComponent('fileCache'); //dbCache的名字来自于组件配置中的名字 + * $fileCache = Wind::getComponent('fileCache'); //dbCache的名字来自于组件配置中的名字 * - * - * the last known user to change this file in the repository + * the last known user to change this file in the repository + * * @author xiaoxiao * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindFileCache.php 3791 2012-10-30 04:01:29Z liusanbian $ * @package strategy */ -class WindFileCache extends AbstractWindCache { - - /** - * 缓存目录 - * - * @var string - */ - private $cacheDir; - - /** - * 缓存后缀 - * - * @var string - */ - private $cacheFileSuffix = 'txt'; - - /** - * 缓存子目录的长度 - * - * @var int - */ - private $cacheDirectoryLevel = 0; - - /** - * 保存缓存目录列表 - * - * 如果用户已经访问过统一个缓存,则会直接从该列表中获取该具体值而不重新计算。 - * - * @var array - */ - private $cacheFileList = array(); - - /* (non-PHPdoc) - * @see AbstractWindCache::setValue() - */ - protected function setValue($key, $value, $expire = 0) { - return WindFile::write($key, $value) == strlen($value); - } - - /* (non-PHPdoc) - * @see AbstractWindCache::addValue() - */ - protected function addValue($key, $value, $expire = 0) { - return WindFile::write($key, $value) == strlen($value); - } - - /* (non-PHPdoc) - * @see AbstractWindCache::get() - */ - protected function getValue($key) { - if (!is_file($key)) return null; - return WindFile::read($key); - } - - /* (non-PHPdoc) - * @see AbstractWindCache::deleteValue() - */ - protected function deleteValue($key) { - return WindFile::write($key, ''); - } - - /* (non-PHPdoc) - * @see AbstractWindCache::clear() - */ - public function clear() { - return WindFolder::clearRecur($this->getCacheDir()); - } - - /** - * 根据用户key计算获取真是缓存文件 - * - * 缓存key在安全处理之后,判断该key是否已经被访问过 - *
      - *
    • 如果被访问过,则直接返回该真实缓存文件
    • - *
    • 没有访问过,则将会进入计算流程. - *
        - *
      1. 如果用该组件配置了缓存子目录的长度n: - *
          - *
        • 获得缓存key的md5值的0~n的子字串作为子缓存目录;
        • - *
        • 将缓存文件存放在该缓存子目录下.同时将该缓存文件的新路径保存到已访问的缓存路径列表中,供下次直接调用.
        • - *
        - *
      2. - *
      3. 如果没有配置缓存子目录长度,则直接将该文件缓存在缓存根目录下,同时也将该缓存文件路径保存在已访问的缓存路径列表中.
      4. - *
      - *
    • - *
    - * - * @param string $key 用户的缓存文件key - * @return string 真实的缓存文件 - */ - protected function buildSecurityKey($key) { - $key = parent::buildSecurityKey($key); - if (false !== ($dir = $this->checkCacheDir($key))) return $dir; - $_dir = $this->getCacheDir(); - if (0 < ($level = $this->getCacheDirectoryLevel())) { - $_subdir = substr(md5($key), 0, $level); - $_dir .= '/' . $_subdir; - WindFolder::mk($_dir); - } - $filename = $key . '.' . $this->getCacheFileSuffix(); - $this->cacheFileList[$key] = ($_dir ? $_dir . '/' . $filename : $filename); - return $this->cacheFileList[$key]; - } - - /** - * 是否缓存key已经存在缓存访问列表中 - * - *
      - *
    • 如果缓存key已经在缓存访问列表中,则将会直接返回存在的值
    • - *
    • 如果不存在则返回false.
    • - *
    - * - * @param string $key 待检查的缓存key - * @return string|boolean 如果存在则返回被保存的值,如果不存在则返回false; - */ - private function checkCacheDir($key) { - return isset($this->cacheFileList[$key]) ? $this->cacheFileList[$key] : false; - } - - /** - * 设置缓存目录 - * - * @param string $dir 缓存目录,必须是可写可读权限 - */ - public function setCacheDir($dir) { - $_dir = Wind::getRealPath($dir, false, true); - WindFolder::mkRecur($_dir); - $this->cacheDir = realpath($_dir); - } - - /** - * 获得缓存目录 - * - * @return string $cacheDir 返回配置的缓存目录 - */ - private function getCacheDir() { - return $this->cacheDir; - } - - /** - * 设置缓存文件的后缀 - * - * @param string $cacheFileSuffix 缓存文件的后缀,默认为txt - */ - public function setCacheFileSuffix($cacheFileSuffix) { - $this->cacheFileSuffix = $cacheFileSuffix; - } - - /** - * 获得缓存文件的后缀 - * - * @return string $cacheFileSuffix 缓存文件的后缀 - */ - private function getCacheFileSuffix() { - return $this->cacheFileSuffix; - } - - /** - * 设置缓存存放的目录下子目录的长度 - * - * @param int $cacheDirectoryLevel 该值将会决定缓存目录下子缓存目录的长度,最小为0(不建子目录),最大为32(md5值最长32),缺省为0 - */ - public function setCacheDirectoryLevel($cacheDirectoryLevel) { - $this->cacheDirectoryLevel = $cacheDirectoryLevel; - } - - /** - * 返回缓存存放的目录下子目录的长度 - * - * 该值将会决定缓存目录下子缓存目录的长度,最小为0(不建子目录),最大为32(md5值最长32),缺省为0 - * - * @return int $cacheDirectoryLevel - */ - public function getCacheDirectoryLevel() { - return $this->cacheDirectoryLevel; - } - - /* (non-PHPdoc) - * @see AbstractWindCache::setConfig() - */ - public function setConfig($config) { - parent::setConfig($config); - $this->setCacheDir($this->getConfig('dir')); - $this->setCacheFileSuffix($this->getConfig('suffix', '', 'txt')); - $this->setCacheDirectoryLevel($this->getConfig('dir-level', '', 0)); - } -} \ No newline at end of file +class WindFileCache extends AbstractWindCache +{ + /** + * 缓存目录 + * + * @var string + */ + private $cacheDir; + + /** + * 缓存后缀 + * + * @var string + */ + private $cacheFileSuffix = 'txt'; + + /** + * 缓存子目录的长度 + * + * @var int + */ + private $cacheDirectoryLevel = 0; + + /** + * 保存缓存目录列表 + * 如果用户已经访问过统一个缓存,则会直接从该列表中获取该具体值而不重新计算。 + * + * @var array + */ + private $cacheFileList = array(); + + /* + * (non-PHPdoc) @see AbstractWindCache::setValue() + */ + protected function setValue($key, $value, $expire = 0) + { + return WindFile::write($key, $value) == strlen($value); + } + + /* + * (non-PHPdoc) @see AbstractWindCache::addValue() + */ + protected function addValue($key, $value, $expire = 0) + { + return WindFile::write($key, $value) == strlen($value); + } + + /* + * (non-PHPdoc) @see AbstractWindCache::get() + */ + protected function getValue($key) + { + if (!is_file($key)) { + return null; + } + + return WindFile::read($key); + } + + /* + * (non-PHPdoc) @see AbstractWindCache::deleteValue() + */ + protected function deleteValue($key) + { + return WindFile::write($key, ''); + } + + /* + * (non-PHPdoc) @see AbstractWindCache::clear() + */ + public function clear() + { + return WindFolder::clearRecur($this->getCacheDir()); + } + + /** + * 根据用户key计算获取真是缓存文件 + * 缓存key在安全处理之后,判断该key是否已经被访问过 + *
      + *
    • 如果被访问过,则直接返回该真实缓存文件
    • + *
    • 没有访问过,则将会进入计算流程. + *
        + *
      1. 如果用该组件配置了缓存子目录的长度n: + *
          + *
        • 获得缓存key的md5值的0~n的子字串作为子缓存目录;
        • + *
        • 将缓存文件存放在该缓存子目录下.同时将该缓存文件的新路径保存到已访问的缓存路径列表中,供下次直接调用.
        • + *
        + *
      2. + *
      3. 如果没有配置缓存子目录长度,则直接将该文件缓存在缓存根目录下,同时也将该缓存文件路径保存在已访问的缓存路径列表中.
      4. + *
      + *
    • + *
    + * + * @param string $key 用户的缓存文件key + * @return string 真实的缓存文件 + */ + protected function buildSecurityKey($key) + { + $key = parent::buildSecurityKey($key); + if (false !== ($dir = $this->checkCacheDir($key))) { + return $dir; + } + $_dir = $this->getCacheDir(); + if (0 < ($level = $this->getCacheDirectoryLevel())) { + $_subdir = substr(md5($key), 0, $level); + $_dir .= '/'.$_subdir; + WindFolder::isDir($_dir) || WindFolder::mk($_dir); + } + $filename = $key.'.'.$this->getCacheFileSuffix(); + $this->cacheFileList[$key] = ($_dir ? $_dir.'/'.$filename : $filename); + + return $this->cacheFileList[$key]; + } + + /** + * 是否缓存key已经存在缓存访问列表中 + *
      + *
    • 如果缓存key已经在缓存访问列表中,则将会直接返回存在的值
    • + *
    • 如果不存在则返回false.
    • + *
    + * + * @param string $key 待检查的缓存key + * @return string boolean + */ + private function checkCacheDir($key) + { + return isset($this->cacheFileList[$key]) ? $this->cacheFileList[$key] : false; + } + + /** + * 设置缓存目录 + * + * @param string $dir 缓存目录,必须是可写可读权限 + */ + public function setCacheDir($dir) + { + $_dir = Wind::getRealPath($dir, false, true); + WindFolder::mkRecur($_dir); + $this->cacheDir = realpath($_dir); + } + + /** + * 获得缓存目录 + * + * @return string $cacheDir 返回配置的缓存目录 + */ + private function getCacheDir() + { + return $this->cacheDir; + } + + /** + * 设置缓存文件的后缀 + * + * @param string $cacheFileSuffix 缓存文件的后缀,默认为txt + */ + public function setCacheFileSuffix($cacheFileSuffix) + { + $this->cacheFileSuffix = $cacheFileSuffix; + } + + /** + * 获得缓存文件的后缀 + * + * @return string $cacheFileSuffix 缓存文件的后缀 + */ + private function getCacheFileSuffix() + { + return $this->cacheFileSuffix; + } + + /** + * 设置缓存存放的目录下子目录的长度 + * + * @param int $cacheDirectoryLevel + * 该值将会决定缓存目录下子缓存目录的长度,最小为0(不建子目录),最大为32(md5值最长32),缺省为0 + */ + public function setCacheDirectoryLevel($cacheDirectoryLevel) + { + $this->cacheDirectoryLevel = $cacheDirectoryLevel; + } + + /** + * 返回缓存存放的目录下子目录的长度 + * 该值将会决定缓存目录下子缓存目录的长度,最小为0(不建子目录),最大为32(md5值最长32),缺省为0 + * + * @return int $cacheDirectoryLevel + */ + public function getCacheDirectoryLevel() + { + return $this->cacheDirectoryLevel; + } + + /* + * (non-PHPdoc) @see AbstractWindCache::setConfig() + */ + public function setConfig($config) + { + parent::setConfig($config); + $this->setCacheDir($this->getConfig('dir')); + $this->setCacheFileSuffix($this->getConfig('suffix', '', 'txt')); + $this->setCacheDirectoryLevel($this->getConfig('dir-level', '', 0)); + } +} diff --git a/wind/cache/strategy/WindMemCache.php b/wind/cache/strategy/WindMemCache.php index 963dba09..8bad1423 100644 --- a/wind/cache/strategy/WindMemCache.php +++ b/wind/cache/strategy/WindMemCache.php @@ -1,8 +1,9 @@ @@ -13,7 +14,7 @@ *
  • batchDelete($keys): 继承自{@link AbstractWindCache::batchDelete()}.
  • *
  • {@link setConfig($config)}: 重写了父类的{@link AbstractWindCache::setConfig()}.
  • * - * + * * 它接收如下配置: * * array( @@ -48,7 +49,7 @@ * * 'memCache' => array( * 'path' => 'WIND:cache.strategy.WindMemCache', - 'scope' => 'singleton', + 'scope' => 'singleton', * 'config' = array( * 'security-code' => '', * 'key-prefix' => '', @@ -70,104 +71,162 @@ * ), * * 如果含有多个memCache主机,可以设置多组host在config中,如host1,host2,其key值也可以自定义. - * + * * 注意:要使用该组件需要安装memcache扩展库. - * + * * the last known user to change this file in the repository * @author xiaoxiao * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindMemCache.php 3904 2013-01-08 07:01:26Z yishuo $ * @package strategy */ -class WindMemCache extends AbstractWindCache { - - /** - * memcache缓存操作句柄 - * - * @var WindMemcache - */ - protected $memcache = null; - /** - * 是否对缓存采取压缩存储 - * - * @var int - */ - protected $compress = 0; - - /** - * 构造函数 - * - * 判断是否有支持memCache,如果没有安装扩展库将会抛出异常,
    - * 首先尝试使用memcached扩展,如果然后尝试创建memcache - * - * @throws WindCacheException 如果没有安装memcache扩展则抛出异常 - */ - public function __construct() { - $this->memcache = new Memcached(); - } - - /* (non-PHPdoc) - * @see AbstractWindCache::setValue() - */ - protected function setValue($key, $value, $expire = 0) { - return $this->memcache->set($key, $value, (int) $expire); - } - - /* (non-PHPdoc) - * @see AbstractWindCache::addValue() - */ - protected function addValue($key, $value, $expires = 0) { - return $this->memcache->add($key, $value, (int) $expires); - } - - /* (non-PHPdoc) - * @see AbstractWindCache::getValue() - */ - protected function getValue($key) { - return $this->memcache->get($key); - } - - /* (non-PHPdoc) - * @see AbstractWindCache::deleteValue() - */ - protected function deleteValue($key) { - return $this->memcache->delete($key); - } - - /* (non-PHPdoc) - * @see AbstractWindCache::clear() - */ - public function clear() { - return $this->memcache->flush(); - } - - /* (non-PHPdoc) - * @see AbstractWindCache::increment() - */ - public function increment($key, $step = 1) { - return $this->memcache->increment($this->buildSecurityKey($key), $step); - } - - /* (non-PHPdoc) - * @see AbstractWindCache::decrement() - */ - public function decrement($key, $step = 1) { - return $this->memcache->decrement($this->buildSecurityKey($key), $step); - } - - /* (non-PHPdoc) - * @see AbstractWindCache::setConfig() - */ - public function setConfig($config) { - parent::setConfig($config); - $servers = $this->getConfig('servers', '', array()); - foreach ((array) $servers as $server) { - if (!is_array($server)) throw new WindException('The memcache config is incorrect'); - if (!isset($server['host'])) throw new WindException('The memcache server ip address is not exist'); - if (!isset($server['port'])) throw new WindException('The memcache server port is not exist'); - $this->memcache->addServer($server['host'], $server['port'], - isset($server['weight']) ? $server['weight'] : null); - } - } -} \ No newline at end of file +class WindMemCache extends AbstractWindCache +{ + /** + * memcache缓存操作句柄 + * + * @var WindMemcache + */ + protected $memcache = null; + + /** + * 是否对缓存采取压缩存储 + * + * @var int + */ + protected $compress = 0; + + /** + * 构造函数 + * + * 判断是否有支持memCache,如果没有安装扩展库将会抛出异常,
    + * 首先尝试使用memcached扩展,如果然后尝试创建memcache + * + * @throws WindCacheException 如果没有安装memcache扩展则抛出异常 + */ + public function __construct() + { + $this->memcache = new Memcache(); + } + + /* (non-PHPdoc) + * @see AbstractWindCache::setValue() + */ + protected function setValue($key, $value, $expire = 0) + { + return $this->memcache->set($key, $value, $this->compress, (int) $expire); + } + + /* (non-PHPdoc) + * @see AbstractWindCache::addValue() + */ + protected function addValue($key, $value, $expires = 0) + { + return $this->memcache->add($key, $value, $this->compress, (int) $expires); + } + + /* (non-PHPdoc) + * @see AbstractWindCache::getValue() + */ + protected function getValue($key) + { + return $this->memcache->get($key, $this->compress); + } + + /* (non-PHPdoc) + * @see AbstractWindCache::deleteValue() + */ + protected function deleteValue($key) + { + return $this->memcache->delete($key); + } + + /* (non-PHPdoc) + * @see AbstractWindCache::clear() + */ + public function clear() + { + return $this->memcache->flush(); + } + + /* (non-PHPdoc) + * @see AbstractWindCache::increment() + */ + public function increment($key, $step = 1) + { + return $this->memcache->increment($this->buildSecurityKey($key), $step); + } + + /* (non-PHPdoc) + * @see AbstractWindCache::decrement() + */ + public function decrement($key, $step = 1) + { + return $this->memcache->decrement($this->buildSecurityKey($key), $step); + } + + /* (non-PHPdoc) + * @see AbstractWindCache::batchGet() + */ + public function batchGet(array $keys) + { + $_keys = array_map(array($this, 'buildSecurityKey'), $keys); + $tags = array_fill(0, count($_keys), $this->compress); + $_datas = $this->memcache->get($_keys, $tags); + $_return = array(); + foreach ($keys as $_i => $key) { + $_return[$key] = isset($_datas[$_keys[$_i]]) ? $this->formatData($key, $_datas[$_keys[$_i]]) : false; + } + + return $_return; + } + + /* (non-PHPdoc) + * @see AbstractWindCache::buildData() + */ + protected function buildData($value, $expires = 0, IWindCacheDependency $dependency = null) + { + return $value; + } + + /* (non-PHPdoc) + * @see AbstractWindCache::formatData() + */ + protected function formatData($key, $value) + { + return $value; + } + + /* (non-PHPdoc) + * @see AbstractWindCache::setConfig() + */ + public function setConfig($config) + { + parent::setConfig($config); + $this->compress = $this->getConfig('compress', '', '0'); + $servers = $this->getConfig('servers', '', array()); + $defaultServer = array( + 'host' => '', + 'port' => '', + 'pconn' => true, + 'weight' => 1, + 'timeout' => 1, + 'retry' => 15, + 'status' => true, + 'fcallback' => null, ); + foreach ((array) $servers as $server) { + if (!is_array($server)) { + throw new WindCacheException('[cache.strategy.WindMemCache.setConfig] The memcache config is incorrect'); + } + $args = array_merge($defaultServer, $server); + if (empty($server['host'])) { + throw new WindCacheException('[cache.strategy.WindMemCache.setConfig] The memcache server ip address is not exist'); + } + if (empty($server['port'])) { + throw new WindCacheException('[cache.strategy.WindMemCache.setConfig] The memcache server port is not exist'); + } + $this->memcache->addServer($args['host'], $args['port'], $args['pconn'], $args['weight'], $args['timeout'], $args['retry'], $args['status'], $args['fcallback']); + } + } +} diff --git a/wind/cache/strategy/WindMemCached.php b/wind/cache/strategy/WindMemCached.php new file mode 100644 index 00000000..629ededa --- /dev/null +++ b/wind/cache/strategy/WindMemCached.php @@ -0,0 +1,204 @@ + + *
  • set($key, $value, $expire): 继承自{@link AbstractWindCache::set()}.
  • + *
  • get($key): 继承自{@link AbstractWindCache::get()}.
  • + *
  • delete($key): 继承自{@link AbstractWindCache::delete()}.
  • + *
  • batchGet($keys): 继承自{@link AbstractWindCache::batchGet()}.
  • + *
  • batchDelete($keys): 继承自{@link AbstractWindCache::batchDelete()}.
  • + *
  • {@link setConfig($config)}: 重写了父类的{@link AbstractWindCache::setConfig()}.
  • + * + * + * 它接收如下配置: + * + * array( + * 'security-code' => '', //继承自AbstractWindCache,安全码配置. + * 'key-prefix' => '', //继承自AbstractWindCache,缓存key前缀. + * 'expires' => '0', //继承自AbstractWindCache,缓存过期时间配置. + * 'compress' => '0', //压缩等级,默认为0 + * 'servers' => array( + * 'host' => array( + * 'host'=>'localhost', //要连接的memcached服务端监听的主机位置. + * 'port'=>11211, //要连接的memcached服务端监听的端口. + * 'weight' => 1, //为此服务器创建的桶的数量,用来控制此服务器被选中的权重,单个服务器被选中的概率是相对于所有服务器weight总和而言的. + * ), + * ), + * ) + * + * 使用方法:
    + * 1、按照普通的调用类库的方式去调用: + * + * Wind::import("WIND:cache.strategy.WindMemCached"); + * $cache = new WindMemCached(); + * $cache->setConfig(array('host' => 'localhost', 'port' => 11211)); + * $cache->set('name', 'test'); + * + * 2、采用组件配置的方式,通过组件机制调用 + * 在应用配置的components组件配置块中,配置memCache(该名字将决定调用的时候使用的组件名字): + * + * 'memCache' => array( + * 'path' => 'WIND:cache.strategy.WindMemCached', + 'scope' => 'singleton', + * 'config' = array( + * 'security-code' => '', + * 'key-prefix' => '', + * 'expires' => '0', + * 'compress' => '0', + * 'servers' => array( + * 'host1' => array( + * 'host'=>'localhost', + * 'port'=>11211, + * 'pconn'=>true, + * 'weight' => 1, + * ), + * ), + * ), + * ), + * + * 如果含有多个memCache主机,可以设置多组host在config中,如host1,host2,其key值也可以自定义. + * + * 注意:要使用该组件需要安装memcache扩展库. + * + * the last known user to change this file in the repository + * @author xiaoxiao + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id: WindMemCached.php 3891 2013-01-08 03:44:46Z xiaoxia.xuxx $ + * @package strategy + */ +class WindMemCached extends AbstractWindCache +{ + /** + * memcache缓存操作句柄 + * + * @var WindMemcache + */ + protected $memcache = null; + + /** + * 构造函数 + * + * 判断是否有支持memCache,如果没有安装扩展库将会抛出异常,
    + * 首先尝试使用memcached扩展,如果然后尝试创建memcache + * + * @throws WindCacheException 如果没有安装memcache扩展则抛出异常 + */ + public function __construct() + { + $this->memcache = new Memcached(); + } + + /* (non-PHPdoc) + * @see AbstractWindCache::setValue() + */ + protected function setValue($key, $value, $expire = 0) + { + return $this->memcache->set($key, $value, (int) $expire); + } + + /* (non-PHPdoc) + * @see AbstractWindCache::addValue() + */ + protected function addValue($key, $value, $expires = 0) + { + return $this->memcache->add($key, $value, (int) $expires); + } + + /* (non-PHPdoc) + * @see AbstractWindCache::getValue() + */ + protected function getValue($key) + { + return $this->memcache->get($key); + } + + /* (non-PHPdoc) + * @see AbstractWindCache::deleteValue() + */ + protected function deleteValue($key) + { + return $this->memcache->delete($key); + } + + /* (non-PHPdoc) + * @see AbstractWindCache::clear() + */ + public function clear() + { + return $this->memcache->flush(); + } + + /* (non-PHPdoc) + * @see AbstractWindCache::increment() + */ + public function increment($key, $step = 1) + { + return $this->memcache->increment($this->buildSecurityKey($key), $step); + } + + /* (non-PHPdoc) + * @see AbstractWindCache::decrement() + */ + public function decrement($key, $step = 1) + { + return $this->memcache->decrement($this->buildSecurityKey($key), $step); + } + + /* (non-PHPdoc) + * @see AbstractWindCache::batchGet() + */ + public function batchGet(array $keys) + { + $_keys = array_map(array($this, 'buildSecurityKey'), $keys); + $_datas = $this->memcache->getMulti($_keys); + $_return = array(); + foreach ($keys as $_i => $key) { + $_return[$key] = isset($_datas[$_keys[$_i]]) ? $this->formatData($key, $_datas[$_keys[$_i]]) : false; + } + + return $_return; + } + + /* (non-PHPdoc) + * @see AbstractWindCache::buildData() + */ + protected function buildData($value, $expires = 0, IWindCacheDependency $dependency = null) + { + return $value; + } + + /* (non-PHPdoc) + * @see AbstractWindCache::formatData() + */ + protected function formatData($key, $value) + { + return $value; + } + + /* (non-PHPdoc) + * @see AbstractWindCache::setConfig() + */ + public function setConfig($config) + { + parent::setConfig($config); + $servers = $this->getConfig('servers', '', array()); + foreach ((array) $servers as $server) { + if (!is_array($server)) { + throw new WindCacheException('[cache.strategy.WindMemCached.setConfig] The memcache config is incorrect'); + } + if (!isset($server['host'])) { + throw new WindCacheException('[cache.strategy.WindMemCached.setConfig] The memcache server ip address is not exist'); + } + if (!isset($server['port'])) { + throw new WindCacheException('[cache.strategy.WindMemCached.setConfig] The memcache server port is not exist'); + } + $this->memcache->addServer($server['host'], $server['port'], isset($server['weight']) ? $server['weight'] : null); + } + } +} diff --git a/wind/cache/strategy/WindRedisCache.php b/wind/cache/strategy/WindRedisCache.php index 42ff24d6..6543a351 100644 --- a/wind/cache/strategy/WindRedisCache.php +++ b/wind/cache/strategy/WindRedisCache.php @@ -1,27 +1,26 @@ 注意:使用该类型的缓存,需要安装phpredis扩展 - * * 配置文件格式: * * array( - * 'security-code' => '', //继承自AbstractWindCache,安全码配置. - * 'key-prefix' => '', //继承自AbstractWindCache,缓存key前缀. - * 'expires' => '0', //继承自AbstractWindCache,缓存过期时间配置. - * 'auth' => '', //链接认证密码,redis->auth - * 'servers' => array( - * array( - * 'host'=>'127.0.0.1', //要连接的redis服务端监听的主机位置. - * 'port'=>6379, //要连接的redis服务端监听的端口. - * 'timeout' => 0, //连接持续(超时)时间(单位秒),默认值0.不限制 - * 'pconn'=>true, //控制是否使用持久化连接,默认true. - * ), - * ), + * 'security-code' => '', //继承自AbstractWindCache,安全码配置. + * 'key-prefix' => '', //继承自AbstractWindCache,缓存key前缀. + * 'expires' => '0', //继承自AbstractWindCache,缓存过期时间配置. + * 'auth' => '', //链接认证密码,redis->auth + * 'servers' => array( + * array( + * 'host'=>'127.0.0.1', //要连接的redis服务端监听的主机位置. + * 'port'=>6379, //要连接的redis服务端监听的端口. + * 'timeout' => 0, //连接持续(超时)时间(单位秒),默认值0.不限制 + * 'pconn'=>true, //控制是否使用持久化连接,默认true. + * ), + * ), * ) * - * * 1、按照普通的调用类库的方式去调用: * * Wind::import("WIND:cache.strategy.WindRedisCache"); @@ -30,141 +29,153 @@ * $cache->set('name', 'test'); * echo $cache->get('name'); * - * * 2、采用组件配置的方式,通过组件机制调用 * 在应用配置的components组件配置块中,配置redisCache(该名字将决定调用的时候使用的组件名字): * * //配置组件 * 'redisCache' => array( - * 'path' => 'WIND:cache.strategy.WindRedisCache', - * 'scope' => 'singleton', - * 'config' = array( - * 'security-code' => '', - * 'key-prefix' => '', - * 'expires' => '0', - * 'auth' => '', - * 'servers' => array( - * 'host1' => array( - * 'host' => '127.0.0.1', - * 'port' => 6379, - * 'pconn' => true, - * 'timeout' => 0, - * ), - * ), - * ), + * 'path' => 'WIND:cache.strategy.WindRedisCache', + * 'scope' => 'singleton', + * 'config' = array( + * 'security-code' => '', + * 'key-prefix' => '', + * 'expires' => '0', + * 'auth' => '', + * 'servers' => array( + * 'host1' => array( + * 'host' => '127.0.0.1', + * 'port' => 6379, + * 'pconn' => true, + * 'timeout' => 0, + * ), + * ), + * ), * ), * //使用: - * $redis = Wind::getApp()->getComponent('redisCache'); + * $redis = Wind::getComponent('redisCache'); * $redis->set('name', 'windFramework'); * echo $redis->get('name'); * - * + * * @author xiaoxia.xu * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindRedisCache.php 3904 2013-01-08 07:01:26Z yishuo $ * @package wind.cache.strategy */ -class WindRedisCache extends AbstractWindCache { - /** - * redis缓存操作句柄 - * - * @var Redis - */ - protected $redis = null; - - /** - * redis链接使用的认证密码 - * - * @var string - */ - protected $auth = ''; +class WindRedisCache extends AbstractWindCache +{ + /** + * redis缓存操作句柄 + * + * @var Redis + */ + protected $redis = null; + + /** + * redis链接使用的认证密码 + * + * @var string + */ + protected $auth = ''; + + /** + * 构造函数 + * + * @throws WindCacheException + */ + public function __construct() + { + $this->redis = new Redis(); + } + + /* + * (non-PHPdoc) @see AbstractWindCache::setValue() + */ + protected function setValue($key, $value, $expires = 0) + { + $r = $this->redis->set($key, $value); + if ($r && $expires) { + $this->redis->setTimeout($key, $expires); + } + + return $r; + } - /** - * 构造函数 - * - * @throws WindCacheException - */ - public function __construct() { - $this->redis = new Redis(); - } + /* + * (non-PHPdoc) @see AbstractWindCache::addValue() + */ + protected function addValue($key, $value, $expires = 0) + { + $r = $this->redis->setnx($key, $value); + if ($r && $expires) { + $this->redis->setTimeout($key, $expires); + } - /* (non-PHPdoc) - * @see AbstractWindCache::setValue() - */ - protected function setValue($key, $value, $expires = 0) { - $r = $this->redis->set($key, $value); - if ($r && $expires) $this->redis->setTimeout($key, $expires); - return $r; - } + return $r; + } - /* (non-PHPdoc) - * @see AbstractWindCache::addValue() - */ - protected function addValue($key, $value, $expires = 0) { - $r = $this->redis->setnx($key, $value); - if ($r && $expires) { - $this->redis->setTimeout($key, $expires); - } - return $r; - } + /* + * (non-PHPdoc) @see AbstractWindCache::getValue() + */ + protected function getValue($key) + { + return $this->redis->get($key); + } - /* (non-PHPdoc) - * @see AbstractWindCache::getValue() - */ - protected function getValue($key) { - return $this->redis->get($key); - } + /* + * (non-PHPdoc) @see AbstractWindCache::deleteValue() + */ + protected function deleteValue($key) + { + return $this->redis->delete($key); + } - /* (non-PHPdoc) - * @see AbstractWindCache::deleteValue() - */ - protected function deleteValue($key) { - return $this->redis->delete($key); - } + /* + * (non-PHPdoc) @see AbstractWindCache::clear() + */ + public function clear() + { + $this->redis->flushAll(); + } - /* (non-PHPdoc) - * @see AbstractWindCache::clear() - */ - public function clear() { - $this->redis->flushAll(); - } + /* + * //TODO 调用其他方法开放调用,重构 @see WindModule::__call() + */ + public function __call($methodName, $args) + { + if (!method_exists($this->redis, $methodName)) { + throw new WindCacheException('[cache.strategy.WindRedisCache] The method "'.$methodName.'" is no in redis'); + } - /* //TODO 调用其他方法开放调用,重构 - * @see WindModule::__call() - */ - public function __call($methodName, $args) { - if (!method_exists($this->redis, $methodName)) throw new WindCacheException( - 'The method "' . $methodName . '" is no in redis'); - return call_user_func_array(array($this->redis, $methodName), $args); - } + return call_user_func_array(array($this->redis, $methodName), $args); + } - /* (non-PHPdoc) - * @see AbstractWindCache::setConfig() - */ - public function setConfig($config) { - parent::setConfig($config); - $auth = $this->getConfig('auth', '', ''); - if ($auth && (true !== $this->redis->auth($auth))) { - throw new WindCacheException('Authenticate the redis connection error'); - } - $servers = $this->getConfig('servers', '', array()); - $defaultServer = array( - 'host' => '', - 'port' => 6379, - 'timeout' => 0, - 'pconn' => false, - 'persistent_id' => ''); - foreach ((array) $servers as $server) { - if (!is_array($server)) throw new WindCacheException('The redis config is incorrect'); - $args = array_merge($defaultServer, $server); - if (!isset($server['host'])) throw new WindCacheException( - 'The redis server ip address is not exist'); - $method = $args['pconn'] === true ? 'pconnect' : 'connect'; - $m_args = array($args['host'], $args['port'], $args['timeout']); - //如果是长链接,则会存在一个长链接的ID号 - ($args['pconn'] === true && $args['persistent_id']) && $m_args[] = $args['persistent_id']; - call_user_func_array(array($this->redis, $method), $m_args); - } - } -} \ No newline at end of file + /* + * (non-PHPdoc) @see AbstractWindCache::setConfig() + */ + public function setConfig($config) + { + parent::setConfig($config); + $auth = $this->getConfig('auth', '', ''); + if ($auth && (true !== $this->redis->auth($auth))) { + throw new WindCacheException('[cache.strategy.WindRedisCache.setConfig] Authenticate the redis connection error'); + } + $servers = $this->getConfig('servers', '', array()); + $defaultServer = array('host' => '', 'port' => 6379, 'timeout' => 0, 'pconn' => false, 'persistent_id' => ''); + foreach ((array) $servers as $server) { + if (!is_array($server)) { + throw new WindCacheException('[cache.strategy.WindRedisCache.setConfig] The redis config is incorrect'); + } + $args = array_merge($defaultServer, $server); + if (!isset($server['host'])) { + throw new WindCacheException('[cache.strategy.WindRedisCache.setConfig] The redis server ip address is not exist'); + } + $method = $args['pconn'] === true ? 'pconnect' : 'connect'; + $m_args = array($args['host'], $args['port'], $args['timeout']); + // 如果是长链接,则会存在一个长链接的ID号 + ($args['pconn'] === true && $args['persistent_id']) && $m_args[] = $args['persistent_id']; + call_user_func_array(array($this->redis, $method), $m_args); + } + } +} diff --git a/wind/cache/strategy/WindWinCache.php b/wind/cache/strategy/WindWinCache.php index 6ecfd0fd..7b17922c 100644 --- a/wind/cache/strategy/WindWinCache.php +++ b/wind/cache/strategy/WindWinCache.php @@ -1,97 +1,101 @@ - *
  • set($key, $value, $expire): 继承自{@link AbstractWindCache::set()}.
  • - *
  • get($key): 继承自{@link AbstractWindCache::get()}.
  • - *
  • delete($key): 继承自{@link AbstractWindCache::delete()}.
  • - *
  • batchGet($keys): 继承自{@link AbstractWindCache::batchGet()}.
  • - *
  • batchDelete($keys): 继承自{@link AbstractWindCache::batchDelete()}.
  • - *
  • setConfig($config): 继承自{@link AbstractWindCache::setConfig()}.
  • + *
  • set($key, $value, $expire): 继承自{@link AbstractWindCache::set()}.
  • + *
  • get($key): 继承自{@link AbstractWindCache::get()}.
  • + *
  • delete($key): 继承自{@link AbstractWindCache::delete()}.
  • + *
  • batchGet($keys): 继承自{@link AbstractWindCache::batchGet()}.
  • + *
  • batchDelete($keys): 继承自{@link AbstractWindCache::batchDelete()}.
  • + *
  • setConfig($config): 继承自{@link AbstractWindCache::setConfig()}.
  • * * 该缓存策略从AbstractWindCache类中继承三个配置项: * - * array( - * 'security-code' => '', //继承自AbstractWindCache,安全码配置 - * 'key-prefix' => '', //继承自AbstractWindCache,缓存key前缀 - * 'expires' => '0', //继承自AbstractWindCache,缓存过期时间配置 - * ) + * array( + * 'security-code' => '', //继承自AbstractWindCache,安全码配置 + * 'key-prefix' => '', //继承自AbstractWindCache,缓存key前缀 + * 'expires' => '0', //继承自AbstractWindCache,缓存过期时间配置 + * ) * - * 使用方式:
    + * 使用方式:
    * 1、您可以像使用普通的类一样使用该组件,如下: * - * Wind::import('WIND:cache.strategy.WindWinCache'); + * * $cache = new WindWinCache(); * $cache->set('name', 'windframework'); * - * * 2、同时作为组件,WindWinCache也允许用户通过组件配置得方式,通过框架的组件机制来获得该缓存对象进行操作. * 在应用配置中的组件配置块(components),配置使用该组件为winCache如下: * - * 'winCache' => array( - * 'path' => 'WIND:cache.strategy.WindwinCache', - * 'scope' => 'singleton', - * 'config' => array( - * 'security-code' => '', - * 'key-prefix' => '', - * 'expires' => '0', - * ), - * ), + * 'winCache' => array( + * 'path' => 'WIND:cache.strategy.WindwinCache', + * 'scope' => 'singleton', + * 'config' => array( + * 'security-code' => '', + * 'key-prefix' => '', + * 'expires' => '0', + * ), + * ), * * 在应用中通过如下方式使用: * - * $cache = Wind::getApp()->getComponent('winCache'); //注意这里的winCache组件名称和配置的组件名称需要对应 + * $cache = Wind::getComponent('winCache'); //注意这里的winCache组件名称和配置的组件名称需要对应 * $cache->set('name', 'wf'); * * 关于组件配置的相关说明请参考组件配置一章. - * * 注意: 要使用WindWinCache组件,需要安装wincache扩展支持. - * - * the last known user to change this file in the repository + * the last known user to change this file in the repository + * * @author xiaoxiao * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindWinCache.php 3791 2012-10-30 04:01:29Z liusanbian $ * @package strategy */ -class WindWinCache extends AbstractWindCache { +class WindWinCache extends AbstractWindCache +{ + /* + * (non-PHPdoc) @see AbstractWindCache::setValue() + */ + protected function setValue($key, $value, $expire = 0) + { + return wincache_ucache_set($key, $value, $expire); + } - /* (non-PHPdoc) - * @see AbstractWindCache::setValue() - */ - protected function setValue($key, $value, $expire = 0) { - return wincache_ucache_set($key, $value, $expire); - } - - /* (non-PHPdoc) - * @see AbstractWindCache::addValue() - */ - protected function addValue($key, $value, $expire = 0) { - return wincache_ucache_add($key, $value, $expire); - } + /* + * (non-PHPdoc) @see AbstractWindCache::addValue() + */ + protected function addValue($key, $value, $expire = 0) + { + return wincache_ucache_add($key, $value, $expire); + } - /* (non-PHPdoc) - * @see AbstractWindCache::getValue() - */ - protected function getValue($key) { - return wincache_ucache_get($key); - } + /* + * (non-PHPdoc) @see AbstractWindCache::getValue() + */ + protected function getValue($key) + { + return wincache_ucache_get($key); + } - /* (non-PHPdoc) - * @see AbstractWindCache::deleteValue() - */ - protected function deleteValue($key) { - return wincache_ucache_delete($key); - } + /* + * (non-PHPdoc) @see AbstractWindCache::deleteValue() + */ + protected function deleteValue($key) + { + return wincache_ucache_delete($key); + } - /* (non-PHPdoc) - * @see AbstractWindCache::clear() - */ - public function clear() { - return wincache_ucache_clear(); - } -} \ No newline at end of file + /* + * (non-PHPdoc) @see AbstractWindCache::clear() + */ + public function clear() + { + return wincache_ucache_clear(); + } +} diff --git a/wind/cache/strategy/WindXCache.php b/wind/cache/strategy/WindXCache.php index a9b9921c..a32b0964 100644 --- a/wind/cache/strategy/WindXCache.php +++ b/wind/cache/strategy/WindXCache.php @@ -1,138 +1,146 @@ - *
  • set($key, $value, $expire): 继承自{@link AbstractWindCache::set()}.
  • - *
  • get($key): 继承自{@link AbstractWindCache::get()}.
  • - *
  • delete($key): 继承自{@link AbstractWindCache::delete()}.
  • - *
  • batchGet($keys): 继承自{@link AbstractWindCache::batchGet()}.
  • - *
  • batchDelete($keys): 继承自{@link AbstractWindCache::batchDelete()}.
  • - *
  • {@link setConfig($config)}: 重写了父类的{@link AbstractWindCache::setConfig()}.
  • + *
  • set($key, $value, $expire): 继承自{@link AbstractWindCache::set()}.
  • + *
  • get($key): 继承自{@link AbstractWindCache::get()}.
  • + *
  • delete($key): 继承自{@link AbstractWindCache::delete()}.
  • + *
  • batchGet($keys): 继承自{@link AbstractWindCache::batchGet()}.
  • + *
  • batchDelete($keys): 继承自{@link AbstractWindCache::batchDelete()}.
  • + *
  • {@link setConfig($config)}: 重写了父类的{@link + * AbstractWindCache::setConfig()}.
  • * - * * 它接收如下配置: * - * array( - * 'user' => '', //拥有清空xcache数据的权限用户 - * 'pwd' => '', //拥有清空xcache数据的权限用户的密码 - * 'security-code' => '', //继承自AbstractWindCache,安全码配置 - * 'key-prefix' => '', //继承自AbstractWindCache,缓存key前缀 - * 'expires' => '0', //继承自AbstractWindCache,缓存过期时间配置 - * ) + * array( + * 'user' => '', //拥有清空xcache数据的权限用户 + * 'pwd' => '', //拥有清空xcache数据的权限用户的密码 + * 'security-code' => '', //继承自AbstractWindCache,安全码配置 + * 'key-prefix' => '', //继承自AbstractWindCache,缓存key前缀 + * 'expires' => '0', //继承自AbstractWindCache,缓存过期时间配置 + * ) * * xcache缓存的使用:
    * 1、像使用普通类库一样使用该组件: * - * Wind::import('WIND:cache.strategy.WindXCache'); - * $cache = new WindxCache(); - * $cache->set('name', 'windDbTest'); + * + * $cache = new WindxCache(); + * $cache->set('name', 'windDbTest'); * * 2、采用组件配置的方式,通过组件机制调用 * 在应用配置的components组件配置块中,配置xCache(该名字将决定调用的时候使用的组件名字): * - * 'xCache' => array( - * 'path' => 'WIND:cache.strategy.WindXCache', - * 'scope' => 'singleton', - * 'config' => array( - * 'user' => '', - * 'pwd' => '', - * 'security-code' => '', - * 'key-prefix' => '', - * 'expires' => '0', - * ), - * ), + * 'xCache' => array( + * 'path' => 'WIND:cache.strategy.WindXCache', + * 'scope' => 'singleton', + * 'config' => array( + * 'user' => '', + * 'pwd' => '', + * 'security-code' => '', + * 'key-prefix' => '', + * 'expires' => '0', + * ), + * ), * * 在应用中可以通过如下方式获得xCache对象: * - * $cache = Wind::getApp()->getComponent('xCache'); //xCache的名字来自于组件配置中的名字 + * $cache = Wind::getComponent('xCache'); //xCache的名字来自于组件配置中的名字 * $cache->set('name', 'test'); * * 注意: 该组件需要安装扩展xcache. - * - * the last known user to change this file in the repository + * the last known user to change this file in the repository + * * @author xiaoxiao * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindXCache.php 3791 2012-10-30 04:01:29Z liusanbian $ * @package strategy */ -class WindXCache extends AbstractWindCache { - /** - * 拥有删除数据的权限用户 - * - * xcache清空缓存的时候需要获得有权限的用户 - * - * @var string - */ - private $authUser = ''; - /** - * 拥有删除数据的权限用户的密码 - * - * xcache清空缓存的时候需要获得有权限的用户 - * - * @var string - */ - private $authPwd = ''; +class WindXCache extends AbstractWindCache +{ + /** + * 拥有删除数据的权限用户 + * xcache清空缓存的时候需要获得有权限的用户 + * + * @var string + */ + private $authUser = ''; + /** + * 拥有删除数据的权限用户的密码 + * xcache清空缓存的时候需要获得有权限的用户 + * + * @var string + */ + private $authPwd = ''; + + /* + * (non-PHPdoc) @see AbstractWindCache::setValue() + */ + protected function setValue($key, $value, $expire = 0) + { + return xcache_set($key, $value, $expire); + } - /* (non-PHPdoc) - * @see AbstractWindCache::setValue() - */ - protected function setValue($key, $value, $expire = 0) { - return xcache_set($key, $value, $expire); - } - - /* (non-PHPdoc) - * @see AbstractWindCache::addValue() - */ - protected function addValue($key, $value, $expire = 0) { - return xcache_set($key, $value, $expire); - } + /* + * (non-PHPdoc) @see AbstractWindCache::addValue() + */ + protected function addValue($key, $value, $expire = 0) + { + return xcache_set($key, $value, $expire); + } - /* (non-PHPdoc) - * @see AbstractWindCache::getValue() - */ - protected function getValue($key) { - return xcache_get($key); - } + /* + * (non-PHPdoc) @see AbstractWindCache::getValue() + */ + protected function getValue($key) + { + return xcache_get($key); + } - /* (non-PHPdoc) - * @see AbstractWindCache::deleteValue() - */ - protected function deleteValue($key) { - return xcache_unset($key); - } + /* + * (non-PHPdoc) @see AbstractWindCache::deleteValue() + */ + protected function deleteValue($key) + { + return xcache_unset($key); + } - /* (non-PHPdoc) - * @see AbstractWindCache::clear() - */ - public function clear() { - //xcache_clear_cache需要验证权限 - $tmp['user'] = isset($_SERVER['PHP_AUTH_USER']) ? null : $_SERVER['PHP_AUTH_USER']; - $tmp['pwd'] = isset($_SERVER['PHP_AUTH_PW']) ? null : $_SERVER['PHP_AUTH_PW']; - $_SERVER['PHP_AUTH_USER'] = $this->authUser; - $_SERVER['PHP_AUTH_PW'] = $this->authPwd; - //如果配置中xcache.var_count > 0 则不能用xcache_clear_cache(XC_TYPE_VAR, 0)的方式删除 - $max = xcache_count(XC_TYPE_VAR); - for ($i = 0; $i < $max; $i++) { - xcache_clear_cache(XC_TYPE_VAR, $i); - } - //恢复之前的权限 - $_SERVER['PHP_AUTH_USER'] = $tmp['user']; - $_SERVER['PHP_AUTH_PW'] = $tmp['pwd']; - return true; - } + /* + * (non-PHPdoc) @see AbstractWindCache::clear() + */ + public function clear() + { + // xcache_clear_cache需要验证权限 + $tmp['user'] = isset($_SERVER['PHP_AUTH_USER']) ? null : $_SERVER['PHP_AUTH_USER']; + $tmp['pwd'] = isset($_SERVER['PHP_AUTH_PW']) ? null : $_SERVER['PHP_AUTH_PW']; + $_SERVER['PHP_AUTH_USER'] = $this->authUser; + $_SERVER['PHP_AUTH_PW'] = $this->authPwd; + // 如果配置中xcache.var_count > 0 则不能用xcache_clear_cache(XC_TYPE_VAR, 0)的方式删除 + $max = xcache_count(XC_TYPE_VAR); + for ($i = 0; $i < $max; $i++) { + xcache_clear_cache(XC_TYPE_VAR, $i); + } + // 恢复之前的权限 + $_SERVER['PHP_AUTH_USER'] = $tmp['user']; + $_SERVER['PHP_AUTH_PW'] = $tmp['pwd']; - /* (non-PHPdoc) - * @see AbstractWindCache::setConfig() - */ - public function setConfig($config = array()) { - if (!$config) return false; - parent::setConfig($config); - $this->authUser = $this->getConfig('user'); - $this->authPwd = $this->getConfig('pwd'); - } + return true; + } -} \ No newline at end of file + /* + * (non-PHPdoc) @see AbstractWindCache::setConfig() + */ + public function setConfig($config = array()) + { + if (!$config) { + return false; + } + parent::setConfig($config); + $this->authUser = $this->getConfig('user'); + $this->authPwd = $this->getConfig('pwd'); + } +} diff --git a/wind/cache/strategy/WindZendCache.php b/wind/cache/strategy/WindZendCache.php index dd6971cd..663ce9c2 100644 --- a/wind/cache/strategy/WindZendCache.php +++ b/wind/cache/strategy/WindZendCache.php @@ -1,97 +1,101 @@ - *
  • set($key, $value, $expire): 继承自{@link AbstractWindCache::set()}.
  • - *
  • get($key): 继承自{@link AbstractWindCache::get()}.
  • - *
  • delete($key): 继承自{@link AbstractWindCache::delete()}.
  • - *
  • batchGet($keys): 继承自{@link AbstractWindCache::batchGet()}.
  • - *
  • batchDelete($keys): 继承自{@link AbstractWindCache::batchDelete()}.
  • - *
  • setConfig($config): 继承自{@link AbstractWindCache::setConfig()}.
  • + *
  • set($key, $value, $expire): 继承自{@link AbstractWindCache::set()}.
  • + *
  • get($key): 继承自{@link AbstractWindCache::get()}.
  • + *
  • delete($key): 继承自{@link AbstractWindCache::delete()}.
  • + *
  • batchGet($keys): 继承自{@link AbstractWindCache::batchGet()}.
  • + *
  • batchDelete($keys): 继承自{@link AbstractWindCache::batchDelete()}.
  • + *
  • setConfig($config): 继承自{@link AbstractWindCache::setConfig()}.
  • * * 该缓存策略从AbstractWindCache类中继承三个配置项: * - * array( - * 'security-code' => '', //继承自AbstractWindCache,安全码配置 - * 'key-prefix' => '', //继承自AbstractWindCache,缓存key前缀 - * 'expires' => '0', //继承自AbstractWindCache,缓存过期时间配置 - * ) + * array( + * 'security-code' => '', //继承自AbstractWindCache,安全码配置 + * 'key-prefix' => '', //继承自AbstractWindCache,缓存key前缀 + * 'expires' => '0', //继承自AbstractWindCache,缓存过期时间配置 + * ) * * 使用方式:
    * 1、您可以像使用普通的类一样使用该组件,如下: * - * Wind::import('WIND:cache.strategy.WindZendCache'); + * * $cache = new WindZendCache(); * $cache->set('name', 'windframework'); * - * * 2、同时作为组件,WindZendCache也允许用户通过组件配置得方式,通过框架的组件机制来获得该缓存对象进行操作. * 在应用配置中的组件配置块(components),配置使用该组件如下: * - * 'zendCache' => array( - * 'path' => 'WIND:cache.strategy.WindZendCache', - * 'scope' => 'singleton', - * 'config' => array( - * 'security-code' => '', - * 'key-prefix' => '', - * 'expires' => '0', - * ), - * ), + * 'zendCache' => array( + * 'path' => 'WIND:cache.strategy.WindZendCache', + * 'scope' => 'singleton', + * 'config' => array( + * 'security-code' => '', + * 'key-prefix' => '', + * 'expires' => '0', + * ), + * ), * * 在应用中通过如下方式使用: * - * $cache = Wind::getApp()->getComponent('zendCache'); //注意这里的zendCache组件名称和配置的组件名称需要对应 + * $cache = Wind::getComponent('zendCache'); //注意这里的zendCache组件名称和配置的组件名称需要对应 * $cache->set('name', 'wf'); * * 关于组件配置的相关说明请参考组件配置一章. - * * 注意: 要使用WindZendCache组件,需要安装zend_cache扩展支持. - * - * the last known user to change this file in the repository + * the last known user to change this file in the repository + * * @author xiaoxiao * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindZendCache.php 3791 2012-10-30 04:01:29Z liusanbian $ * @package strategy */ -class WindZendCache extends AbstractWindCache { +class WindZendCache extends AbstractWindCache +{ + /* + * (non-PHPdoc) @see AbstractWindCache::setValue() + */ + protected function setValue($key, $value, $expire = 0) + { + return zend_shm_cache_store($key, $value, $expire); + } - /* (non-PHPdoc) - * @see AbstractWindCache::setValue() - */ - protected function setValue($key, $value, $expire = 0) { - return zend_shm_cache_store($key, $value, $expire); - } - - /* (non-PHPdoc) - * @see AbstractWindCache::addValue() - */ - protected function addValue($key, $value, $expire = 0) { - return zend_shm_cache_store($key, $value, $expire); - } + /* + * (non-PHPdoc) @see AbstractWindCache::addValue() + */ + protected function addValue($key, $value, $expire = 0) + { + return zend_shm_cache_store($key, $value, $expire); + } - /* (non-PHPdoc) - * @see AbstractWindCache::getValue() - */ - protected function getValue($key) { - return zend_shm_cache_fetch($key); - } + /* + * (non-PHPdoc) @see AbstractWindCache::getValue() + */ + protected function getValue($key) + { + return zend_shm_cache_fetch($key); + } - /* (non-PHPdoc) - * @see AbstractWindCache::deleteValue() - */ - protected function deleteValue($key) { - return zend_shm_cache_delete($key); - } + /* + * (non-PHPdoc) @see AbstractWindCache::deleteValue() + */ + protected function deleteValue($key) + { + return zend_shm_cache_delete($key); + } - /* (non-PHPdoc) - * @see AbstractWindCache::clear() - */ - public function clear() { - return zend_shm_cache_clear(); - } -} \ No newline at end of file + /* + * (non-PHPdoc) @see AbstractWindCache::clear() + */ + public function clear() + { + return zend_shm_cache_clear(); + } +} diff --git a/wind/command/WindCommandApplication.php b/wind/command/WindCommandApplication.php index 52e61c86..95126f18 100644 --- a/wind/command/WindCommandApplication.php +++ b/wind/command/WindCommandApplication.php @@ -5,222 +5,64 @@ * @author Shi Long * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindCommandApplication.php 3859 2012-12-18 09:25:51Z yishuo $ * @package command */ -class WindCommandApplication extends WindModule implements IWindApplication { - - /** - * @var WindCommandView - */ - protected $windView = null; - - /** - * @var WindCommandRouter - */ - protected $handlerAdapter = null; - /** - * @var WindCommandRequest - */ - protected $request; - /** - * @var WindCommandResponse - */ - protected $response; - /** - * @var WindFactory - */ - protected $windFactory = null; - protected $defaultModule = array( - 'controller-path' => 'controller', - 'controller-suffix' => 'Controller', - 'error-handler' => 'WIND:command.WindCommandErrorHandler'); +class WindCommandApplication extends AbstractWindApplication +{ + /** + * 显示帮助信息 + * + * @param string $className + * @param WindException $e + */ + protected function help($className, $e = null) + { + $helps = array(); + $helps[10] = 'usage: command [options] [args]'; + $helps[11] = 'Valid options:'; + $helps[12] = $this->handlerAdapter->getModuleKey().' routing information,the name of application module'; + $helps[13] = $this->handlerAdapter->getControllerKey().' routing information,the name of controller'; + $helps[14] = $this->handlerAdapter->getActionKey().' routing information,the name of action'; + $helps[15] = $this->handlerAdapter->getParamKey().' the parameters of the method [action]'; + if (class_exists($className)) { + /* @var $handler WindCommandController */ + $handler = new $className(); + $action = $this->handlerAdapter->getAction(); + if ($action !== 'run') { + $action = $handler->resolvedActionName( + $this->handlerAdapter->getAction()); + } + if (!method_exists($handler, $action)) { + return; + } + $method = new ReflectionMethod($handler, $action); + $helps[20] = "\r\nlist -p [paraments] of '$className::$action' \r\n"; + $method = $method->getParameters(); + $i = 21; + foreach ($method as $value) { + $helps[$i++] = $value; + } + } + if ($e !== null) { + $helps[0] = $e->getMessage()."\r\n"; + } + exit(implode("\r\n", $helps)); + } - /** - * 应用初始化操作 - * - * @param WindCommandRequest $request - * @param WindCommandResponse $response - * @param WindFactory $factory - */ - public function __construct($request, $factory) { - $this->request = $request; - $this->response = $request->getResponse(); - $this->windFactory = $factory; - } - - /* (non-PHPdoc) - * @see IWindApplication::run() - */ - public function run() { - $module = $this->getModules($this->_getHandlerAdapter()->getModule()); - $handlerPath = $module['controller-path'] . '.' . ucfirst($this->handlerAdapter->getController()) . $module['controller-suffix']; - $className = Wind::import($handlerPath); - if ($this->handlerAdapter->isHelp()) { - $this->help($className); - } - if (!class_exists($className)) throw new WindException( - "Your requested '$handlerPath' was not found on this server."); - - try { - $handler = new $className(); - $handler->setDelayAttributes( - array('errorMessage' => array('ref' => 'errorMessage'), 'forward' => array('ref' => 'forward'))); - $handler->doAction($this->handlerAdapter); - } catch (WindException $e) { - $this->help($className, $e); - } - } + /* (non-PHPdoc) + * @see AbstractWindApplication::doDispatch() + */ + public function doDispatch($forward) + { + // TODO Auto-generated method stub + } - /** - * 显示帮助信息 - * - * @param string $className - * @param WindException $e - */ - protected function help($className, $e = null) { - $helps = array(); - $helps[10] = 'usage: command [options] [args]'; - $helps[11] = 'Valid options:'; - $helps[12] = $this->handlerAdapter->getModuleKey() . ' routing information,the name of application module'; - $helps[13] = $this->handlerAdapter->getControllerKey() . ' routing information,the name of controller'; - $helps[14] = $this->handlerAdapter->getActionKey() . ' routing information,the name of action'; - $helps[15] = $this->handlerAdapter->getParamKey() . ' the parameters of the method [action]'; - if (class_exists($className)) { - /*@var $handler WindCommandController */ - $handler = new $className(); - $action = $this->handlerAdapter->getAction(); - if ($action !== 'run') $action = $handler->resolvedActionName($this->handlerAdapter->getAction()); - if (!method_exists($handler, $action)) return; - $method = new ReflectionMethod($handler, $action); - $helps[20] = "\r\nlist -p [paraments] of '$className::$action' \r\n"; - $method = $method->getParameters(); - $i = 21; - foreach ($method as $value) { - $helps[$i++] = $value; - } - } - if ($e !== null) $helps[0] = $e->getMessage() . "\r\n"; - exit(implode("\r\n", $helps)); - } - - /* (non-PHPdoc) - * @see WindModule::setConfig() - */ - public function setConfig($config) { - parent::setConfig($config); - if ($default = $this->getModules('default')) { - $this->defaultModule = WindUtility::mergeArray($this->defaultModule, $default); - } - } - - /** - * 添加module配置 - * - * controller - * - * Controller - * - * WIND:command.WindCommandErrorHandler - * - * - * @param string $name module名称 - * @param array $config 配置数组 - * @param boolean $replace 如果module已经存在是否覆盖他 默认值为false不进行覆盖 - * @return array - */ - public function setModules($name, $config, $replace = false) { - if ($replace || !isset($this->_config['modules'][$name])) { - $this->_config['modules'][$name] = WindUtility::mergeArray($this->defaultModule, (array) $config); - } - return $this->_config['modules'][$name]; - } - - /** - * 获得module配置,$name为空时返回当前module配置 - * - * @param string $name module名称 默认为空 - * @return array - * @throws WindActionException - * @throws WindException - */ - public function getModules($name = '') { - if ($name === '') $name = $this->handlerAdapter->getModule(); - $_module = $this->getConfig('modules', $name, array()); - if (!isset($_module['_verified'])) { - $_module = WindUtility::mergeArray($this->defaultModule, $_module); - $_module['_verified'] = true; - $this->_config['modules'][$name] = $_module; - } - return $_module; - } - - /** - * 获得组件对象 - * - * @param string $componentName 组件名称呢个 - * @return object - */ - public function getComponent($componentName, $args = array()) { - return $this->windFactory->getInstance($componentName, $args); - } - - /** - * 处理错误请求 - * - * 根据错误请求的相关信息,将程序转向到错误处理句柄进行错误处理 - * @param WindActionException actionException - * @return void - * @throws WindFinalException - */ - protected function sendErrorMessage($exception) { - $moduleName = $this->handlerAdapter->getModule(); - if ($moduleName === 'error') throw new WindFinalException($exception->getMessage()); - $errorMessage = null; - if ($exception instanceof WindActionException) $errorMessage = $exception->getError(); - if (!$errorMessage) { - $errorMessage = $this->getComponent('errorMessage'); - $errorMessage->addError($exception->getMessage()); - } - if (!$_errorAction = $errorMessage->getErrorAction()) { - $module = $this->getModules($moduleName); - if (empty($module)) $module = $this->getModules('default'); - preg_match("/([a-zA-Z]*)$/", @$module['error-handler'], $matchs); - $_errorHandler = trim(substr(@$module['error-handler'], 0, -(strlen(@$matchs[0]) + 1))); - $_errorAction = 'error/' . @$matchs[0] . '/run/'; - $this->setModules('error', - array('controller-path' => $_errorHandler, 'controller-suffix' => '', 'error-handler' => '')); - } - $this->handlerAdapter->setModule('error'); - $this->handlerAdapter->setController($matchs[0]); - Wind::getApp()->getRequest()->setAttribute(array($errorMessage->getError(), $exception->getCode()), 'argv'); - Wind::getApp()->run(); - } - - /** - * @return WindFactory - */ - public function getWindFactory() { - return $this->windFactory; - } - - /** - * 返回WindCommandRequest - * - * @return WindCommandRequest $request - */ - public function getRequest() { - return $this->request; - } - - /** - * 返回WindCommandResponse - * - * @return WindCommandResponse $response - */ - public function getResponse() { - return $this->response; - } + /* (non-PHPdoc) + * @see AbstractWindApplication::sendErrorMessage() + */ + protected function sendErrorMessage($errorMessage, $errorcode) + { + // TODO Auto-generated method stub + } } - -?> \ No newline at end of file diff --git a/wind/command/WindCommandController.php b/wind/command/WindCommandController.php index 8afb3199..fd45acca 100644 --- a/wind/command/WindCommandController.php +++ b/wind/command/WindCommandController.php @@ -5,98 +5,177 @@ * @author Shi Long * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindCommandController.php 3859 2012-12-18 09:25:51Z yishuo $ * @package command */ -abstract class WindCommandController extends WindModule { - - /** - * 默认的操作处理方法 - * - * @return void - */ - abstract public function run(); - - /** - * action操作开始前调用 - * - * @param AbstractWindRouter $handlerAdapter - */ - protected function beforeAction($handlerAdapter) {} - - /** - * action操作结束后调用 - * - * @param AbstractWindRouter $handlerAdapter - */ - protected function afterAction($handlerAdapter) {} - - /* (non-PHPdoc) - * @see IWindController::doAction() - */ - public function doAction($handlerAdapter) { - $this->beforeAction($handlerAdapter); - $action = $handlerAdapter->getAction(); - if ($action !== 'run') $action = $this->resolvedActionName($action); - if (in_array($action, array('doAction', 'beforeAction', 'afterAction', 'resolvedActionName')) || !method_exists( - $this, $action)) { - throw new WindException('[command.WindCommandController.doAction] ', - WindException::ERROR_CLASS_METHOD_NOT_EXIST); - } - $method = new ReflectionMethod($this, $action); - if ($method->isProtected()) throw new WindException('[command.WindCommandController.doAction] ', - WindException::ERROR_CLASS_METHOD_NOT_EXIST); - $args = $this->getRequest()->getRequest('argv'); - call_user_func_array(array($this, $action), $args); - $this->afterAction($handlerAdapter); - } - - /** - * 显示错误信息 - * - * @param string $error - */ - protected function showError($error) { - echo "Error: " . $error . "\r\n"; - echo "Try: command help -m someModule -c someController -a someAction"; - exit(); - } - - /** - * 显示信息 - * - * @param string $message 默认为空字符串 - * @return void - */ - protected function showMessage($message) { - if (is_array($message)) { - foreach ($message as $key => $value) - echo "'" . $key . "' => '" . $value . "',\r\n"; - } else - echo $message, "\r\n"; - } - - /** - * 解析action操作方法名称 - * - * 默认解析规则,在请求的action名称后加'Action'后缀 - * 请求的action为 'add',则对应的处理方法名为 'addAction',可以通过覆盖本方法,修改解析规则 - * @param string $action - * @return void - */ - public function resolvedActionName($action) { - return $action . 'Action'; - } - - /** - * 读取输入行 - * - * @return string - */ - protected function getLine($message) { - echo $message; - return trim(fgets(STDIN)); - } -} +abstract class WindCommandController extends WindModule implements IWindController +{ + /** + * 默认的操作处理方法 + * + */ + abstract public function run(); + + /** + * action操作开始前调用 + * + * @param AbstractWindRouter $handlerAdapter + */ + protected function beforeAction($handlerAdapter) + { + } + + /** + * action操作结束后调用 + * + * @param AbstractWindRouter $handlerAdapter + */ + protected function afterAction($handlerAdapter) + { + } + + /* (non-PHPdoc) + * @see IWindController::doAction() + */ + public function doAction($handlerAdapter) + { + $this->beforeAction($handlerAdapter); + $action = $handlerAdapter->getAction(); + if ($action !== 'run') { + $action = $this->resolvedActionName($action); + } + $args = $this->getRequest()->getRequest('argv'); + call_user_func_array(array($this, $action), $args); + print_r($args); + if ($this->errorMessage !== null) { + $this->getErrorMessage()->sendError(); + } + $this->afterAction($handlerAdapter); + + return $this->forward; + } + + /** + * 设置模板数据 + * + * @param string|array|object $data + * @param string $key + */ + protected function setOutput($data, $key = '') + { + $this->getForward()->setVars($data, $key); + } + + /* 错误处理 */ + /** + * 添加错误信息 + * + * @param string $message + * @param string $key 默认为空字符串 + */ + protected function addMessage($message, $key = '') + { + $this->getErrorMessage()->addError($message, $key); + } + + /** + * 发送一个错误请求 + * + * @param string $message 默认为空字符串 + * @param string $key 默认为空字符串 + * @param string $errorAction 默认为空字符串 + */ + protected function showMessage($message = '', $key = '', $errorAction = '') + { + $this->addMessage($message, $key); + $errorAction && $this->getErrorMessage()->setErrorAction($errorAction); + $this->getErrorMessage()->sendError(); + } + + // /** + // * 显示错误信息 + // * + // * @param string $error + // */ + // protected function showError($error) { + // echo "Error: " . $error . "\r\n"; + // echo "Try: command help -m someModule -c someController -a someAction"; + // exit(); + // } + -?> \ No newline at end of file + // /** + // * 显示信息 + // * + // * @param string $message 默认为空字符串 + // * @return void + // */ + // protected function showMessage($message) { + // if (is_array($message)) { + // foreach ($message as $key => $value) + // echo "'" . $key . "' => '" . $value . "',\r\n"; + // } else + // echo $message, "\r\n"; + // } + + + /** + * 解析action操作方法名称 + * + * 默认解析规则,在请求的action名称后加'Action'后缀 + * 请求的action为 'add',则对应的处理方法名为 'addAction',可以通过覆盖本方法,修改解析规则 + * @param string $action + */ + protected function resolvedActionName($action) + { + return $action.'Action'; + } + + /** + * 读取输入行 + * + * @return string + */ + protected function getLine($message) + { + echo $message; + + return trim(fgets(STDIN)); + } + + /** + * + * @return WindForward + */ + public function getForward() + { + return $this->_getForward(); + } + + /** + * + * @return WindErrorMessage + */ + public function getErrorMessage() + { + return $this->_getErrorMessage(); + } + + /** + * + * @param WindForward $forward + */ + public function setForward($forward) + { + $this->forward = $forward; + } + + /** + * + * @param WindErrorMessage $errorMessage + */ + public function setErrorMessage($errorMessage) + { + $this->errorMessage = $errorMessage; + } +} diff --git a/wind/command/WindCommandError.php b/wind/command/WindCommandError.php new file mode 100644 index 00000000..78e4f78e --- /dev/null +++ b/wind/command/WindCommandError.php @@ -0,0 +1,21 @@ + + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id: codetemplates(windframework_docs_zend_8.0).xml 2781 2011-09-22 + * 03:59:17Z yishuo $ + * @package wind + */ +class WindCommandError extends WindError +{ + /* + * (non-PHPdoc) @see WindError::showErrorMessage() + */ + protected function showErrorMessage($message, $file, $line, $trace, $errorcode) + { + // TODO + } +} diff --git a/wind/command/WindCommandFrontController.php b/wind/command/WindCommandFrontController.php index fc43e576..54c42464 100644 --- a/wind/command/WindCommandFrontController.php +++ b/wind/command/WindCommandFrontController.php @@ -1,110 +1,95 @@ * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindCommandFrontController.php 3859 2012-12-18 09:25:51Z yishuo $ * @package command */ -class WindCommandFrontController extends AbstractWindFrontController { - - /* (non-PHPdoc) - * @see AbstractWindFrontController::run() - */ - public function run() { - parent::run(); - exit("Completely Done~\r\n"); - } +class WindCommandFrontController extends AbstractWindFrontController +{ + /* + * (non-PHPdoc) @see AbstractWindFrontController::createApplication() + */ + public function createApplication($config, $factory) + { + $request = $factory->getInstance('request'); + $response = $factory->getInstance('response'); + $application = new WindCommandApplication($request, $response, $factory); + $application->setConfig($config); + + return $application; + } + + /* + * (non-PHPdoc) @see AbstractWindFrontController::_components() + */ + protected function _components() + { + return array( + 'request' => array( + 'path' => 'WindCommandRequest', + 'scope' => 'application', ), + 'response' => array( + 'path' => 'WindCommandResponse', + 'scope' => 'application', ), + 'router' => array('path' => 'WindCommandRouter', 'scope' => 'application'), + 'windView' => array('path' => 'WindCommandView', 'scope' => 'prototype'), + 'db' => array('path' => 'WindConnection', 'scope' => 'singleton'), + 'configParser' => array( + 'path' => 'WindConfigParser', + 'scope' => 'singleton', ), + 'error' => array('path' => 'WIND:command.WindCommandError', 'scope' => 'application'), + 'errorMessage' => array('path' => 'WindErrorMessage', 'scope' => 'prototype'), + 'windLogger' => array( + 'path' => 'WindLogger', + 'scope' => 'singleton', + 'destroy' => 'flush', + 'constructor-args' => array( + '0' => array('value' => 'DATA:log'), + '1' => array('value' => '2'), ), ), + 'i18n' => array( + 'path' => 'WindLangResource', + 'scope' => 'singleton', + 'config' => array('path' => 'i18n'), ), ); + } + + /* + * (non-PHPdoc) @see AbstractWindFrontController::_loadBaseLib() + */ + protected function _loadBaseLib() + { + Wind::$_imports += array( + 'WIND:i18n.WindLangResource' => 'WindLangResource', + 'WIND:log.WindLogger' => 'WindLogger', + 'WIND:base.WindErrorMessage' => 'WindErrorMessage', + 'WIND:parser.WindConfigParser' => 'WindConfigParser', + 'WIND:db.WindConnection' => 'WindConnection', + 'WIND:router.WindCommandRouter' => 'WindCommandRouter', + + 'WIND:command.WindCommandView' => 'WindCommandView', + 'WIND:command.WindCommandErrorHandler' => 'WindCommandErrorHandler', + 'WIND:command.WindCmmandRequest' => 'WindCommandRequest', + 'WIND:command.WindCommandResponse' => 'WindCommandResponse', + 'WIND:command.WindCommandController' => 'WindCommandController', + 'WIND:command.WindCommandApplication' => 'WindCommandApplication', ); - /** - * @return WindHttpRequest - */ - public function getRequest() { - if ($this->_request === null) { - $this->_request = WindFactory::createInstance('WindCommandRequest'); - } - return $this->_request; - } + Wind::$_classes += array( + 'WindLangResource' => 'i18n/WindLangResource', + 'WindLogger' => 'log/WindLogger', + 'WindErrorMessage' => 'base/WindErrorMessage', + 'WindConfigParser' => 'parser/WindConfigParser', + 'WindConnection' => 'db/WindConnection', + 'WindCommandRouter' => 'router/WindCommandRouter', - /** - * 创建并返回应用 - * - * @return WindCommandApplication - */ - protected function _createApplication() { - $application = new WindCommandApplication($this->getRequest(), $this->getFactory()); - $application->setDelayAttributes( - array('windView' => array('ref' => 'windView'), 'handlerAdapter' => array('ref' => 'router'))); - return $application; - } - - /* (non-PHPdoc) - * @see AbstractWindFrontController::showErrorMessage() - */ - protected function showErrorMessage($message, $file, $line, $trace, $errorcode) { - $log = $message . "\r\n" . $file . ":" . $line . "\r\n"; - list($fileLines, $trace) = WindUtility::crash($file, $line, $trace); - foreach ($trace as $key => $value) { - $log .= $value . "\r\n"; - } - if (WIND_DEBUG & 2) Wind::getApp()->getComponent('windLogger')->error($log, 'error', true); - exit($log); - } - - /* (non-PHPdoc) - * @see AbstractWindFrontController::_components() - */ - protected function _components() { - return array( - 'router' => array('path' => 'WIND:command.WindCommandRouter', 'scope' => 'application'), - 'windView' => array('path' => 'WIND:command.WindCommandView', 'scope' => 'prototype'), - 'db' => array('path' => 'WIND:db.WindConnection', 'scope' => 'singleton'), - 'configParser' => array('path' => 'WIND:parser.WindConfigParser', 'scope' => 'singleton'), - 'errorMessage' => array('path' => 'WIND:base.WindErrorMessage', 'scope' => 'prototype'), - 'windLogger' => array( - 'path' => 'WIND:log.WindLogger', - 'scope' => 'singleton', - 'destroy' => 'flush', - 'constructor-args' => array('0' => array('value' => 'DATA:log'), '1' => array('value' => '2'))), - 'i18n' => array( - 'path' => 'WIND:i18n.WindLangResource', - 'scope' => 'singleton', - 'config' => array('path' => 'i18n'))); - } - - /* (non-PHPdoc) - * @see AbstractWindFrontController::_loadBaseLib() - */ - protected function _loadBaseLib() { - Wind::$_imports += array( - 'WIND:i18n.WindLangResource' => 'WindLangResource', - 'WIND:log.WindLogger' => 'WindLogger', - 'WIND:base.WindErrorMessage' => 'WindErrorMessage', - 'WIND:parser.WindConfigParser' => 'WindConfigParser', - 'WIND:db.WindConnection' => 'WindConnection', - 'WIND:command.WindCommandView' => 'WindCommandView', - 'WIND:command.WindCommandRouter' => 'WindCommandRouter', - 'WIND:command.WindCommandErrorHandler' => 'WindCommandErrorHandler', - 'WIND:command.WindCmmandRequest' => 'WindCommandRequest', - 'WIND:command.WindCommandResponse' => 'WindCommandResponse', - 'WIND:command.WindCommandController' => 'WindCommandController', - 'WIND:command.WindCommandApplication' => 'WindCommandApplication'); - - Wind::$_classes += array( - 'WindLangResource' => 'i18n/WindLangResource', - 'WindLogger' => 'log/WindLogger', - 'WindErrorMessage' => 'base/WindErrorMessage', - 'WindConfigParser' => 'parser/WindConfigParser', - 'WindConnection' => 'db/WindConnection', - 'WindCommandView' => 'command/WindCommandView', - 'WindCommandRouter' => 'command/WindCommandRouter', - 'WindCommandApplication' => 'command/WindCommandApplication', - 'WindCommandController' => 'command/WindCommandController', - 'WindCommandErrorHandler' => 'command/WindCommandErrorHandler', - 'WindCommandRequest' => 'command/WindCommandRequest', - 'WindCommandResponse' => 'command/WindCommandResponse'); - } + 'WindCommandView' => 'command/WindCommandView', + 'WindCommandApplication' => 'command/WindCommandApplication', + 'WindCommandController' => 'command/WindCommandController', + 'WindCommandErrorHandler' => 'command/WindCommandErrorHandler', + 'WindCommandRequest' => 'command/WindCommandRequest', + 'WindCommandResponse' => 'command/WindCommandResponse', ); + } } -?> \ No newline at end of file diff --git a/wind/command/WindCommandRequest.php b/wind/command/WindCommandRequest.php index db90e53b..68646293 100644 --- a/wind/command/WindCommandRequest.php +++ b/wind/command/WindCommandRequest.php @@ -5,126 +5,146 @@ * @author Shi Long * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindCommandRequest.php 3668 2012-06-12 03:36:18Z yishuo $ * @package command */ -class WindCommandRequest implements IWindRequest { - /** - * 请求参数信息 - * - * @var array - */ - private $_attribute = array(); - - /** - * 应答对象 - * - * @var WindCommandResponse - */ - private $_response = null; +class WindCommandRequest implements IWindRequest +{ + /** + * 请求参数信息 + * + * @var array + */ + private $_attribute = array(); - /** - * 获得用户请求的数据 - * - * @param string $key 获取的参数name,默认为null将获得$_GET和$_POST两个数组的所有值 - * @param mixed $defaultValue 当获取值失败的时候返回缺省值,默认值为null - * @return mixed - */ - public function getRequest($key, $defaultValue = null) { - if (isset($_SERVER[$key])) return $_SERVER[$key]; - if (isset($_ENV[$key])) return $_ENV[$key]; - return $defaultValue; - } + /** + * 应答对象 + * + * @var WindCommandResponse + */ + private $_response = null; - /** - * 根据名称获得服务器和执行环境信息 - * - * 主要获取的依次顺序为:_attribute、$_SERVER、$_ENV - * - * @param string $name 获取数据的key值 - * @param string $defaultValue 设置缺省值,当获取值失败的时候返回缺省值,默认该值为空字串 - * @return string|object|array 返回获得值 - */ - public function getAttribute($key, $defaultValue = '') { - if (isset($this->_attribute[$key])) - return $this->_attribute[$key]; - else if (isset($_SERVER[$key])) - return $_SERVER[$key]; - else if (isset($_ENV[$key])) - return $_ENV[$key]; - else - return $defaultValue; - } + /** + * 获得用户请求的数据 + * + * @param string $key 获取的参数name,默认为null将获得$_GET和$_POST两个数组的所有值 + * @param mixed $defaultValue 当获取值失败的时候返回缺省值,默认值为null + * @return mixed + */ + public function getRequest($key, $defaultValue = null) + { + if (isset($_SERVER[$key])) { + return $_SERVER[$key]; + } + if (isset($_ENV[$key])) { + return $_ENV[$key]; + } - /** - * 设置属性数据 - * - * @param string|array|object $data 需要设置的数据 - * @param string $key 设置的数据保存用的key,默认为空,当数组和object类型的时候将会执行array_merge操作 - * @return void - */ - public function setAttribute($data, $key = '') { - if ($key) { - $this->_attribute[$key] = $data; - return; - } - if (is_object($data)) $data = get_object_vars($data); - if (is_array($data)) $this->_attribute = array_merge($this->_attribute, $data); - } + return $defaultValue; + } - /** - * 获得请求类型 - * - * @return string - */ - public function getRequestType() { - return 'command'; - } - - /* (non-PHPdoc) - * @see IWindRequest::getPathInfo() - */ - public function getPathInfo() { - return ''; - } - - /* (non-PHPdoc) - * @see IWindRequest::getHostInfo() - */ - public function getHostInfo() { - return ''; - } - - /* (non-PHPdoc) - * @see IWindRequest::getServerName() - */ - public function getServerName() { - return ''; - } - - /* (non-PHPdoc) - * @see IWindRequest::getServerPort() - */ - public function getServerPort() { - return ''; - } - - /* (non-PHPdoc) - * @see IWindRequest::getResponse() - */ - public function getResponse() { - if ($this->_response === null) { - $this->_response = new WindCommandResponse(); - } - return $this->_response; - } - - /* (non-PHPdoc) - * @see IWindRequest::getAcceptLanguage() - */ - public function getAcceptLanguage() { - return ''; - } -} + /** + * 根据名称获得服务器和执行环境信息 + * + * 主要获取的依次顺序为:_attribute、$_SERVER、$_ENV + * + * @param string $name 获取数据的key值 + * @param string $defaultValue 设置缺省值,当获取值失败的时候返回缺省值,默认该值为空字串 + * @return string|object|array 返回获得值 + */ + public function getAttribute($key, $defaultValue = '') + { + if (isset($this->_attribute[$key])) { + return $this->_attribute[$key]; + } elseif (isset($_SERVER[$key])) { + return $_SERVER[$key]; + } elseif (isset($_ENV[$key])) { + return $_ENV[$key]; + } else { + return $defaultValue; + } + } + + /** + * 设置属性数据 + * + * @param string|array|object $data 需要设置的数据 + * @param string $key 设置的数据保存用的key,默认为空,当数组和object类型的时候将会执行array_merge操作 + */ + public function setAttribute($data, $key = '') + { + if ($key) { + $this->_attribute[$key] = $data; + + return; + } + if (is_object($data)) { + $data = get_object_vars($data); + } + if (is_array($data)) { + $this->_attribute = array_merge($this->_attribute, $data); + } + } + + /** + * 获得请求类型 + * + * @return string + */ + public function getRequestType() + { + return 'command'; + } + + /* (non-PHPdoc) + * @see IWindRequest::getPathInfo() + */ + public function getPathInfo() + { + return ''; + } + + /* (non-PHPdoc) + * @see IWindRequest::getHostInfo() + */ + public function getHostInfo() + { + return ''; + } -?> \ No newline at end of file + /* (non-PHPdoc) + * @see IWindRequest::getServerName() + */ + public function getServerName() + { + return ''; + } + + /* (non-PHPdoc) + * @see IWindRequest::getServerPort() + */ + public function getServerPort() + { + return ''; + } + + /* (non-PHPdoc) + * @see IWindRequest::getResponse() + */ + public function getResponse() + { + if ($this->_response === null) { + $this->_response = new WindCommandResponse(); + } + + return $this->_response; + } + + /* (non-PHPdoc) + * @see IWindRequest::getAcceptLanguage() + */ + public function getAcceptLanguage() + { + return ''; + } +} diff --git a/wind/command/WindCommandResponse.php b/wind/command/WindCommandResponse.php index 44612cff..0ed45799 100644 --- a/wind/command/WindCommandResponse.php +++ b/wind/command/WindCommandResponse.php @@ -5,93 +5,102 @@ * @author Shi Long * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindCommandResponse.php 3668 2012-06-12 03:36:18Z yishuo $ * @package command */ -class WindCommandResponse implements IWindResponse { - private $_output = ''; - private $charset = 'utf-8'; +class WindCommandResponse implements IWindResponse +{ + private $_output = ''; + private $charset = 'utf-8'; - /** - * 发送响应信息 - * - * @return void - */ - public function sendResponse() { - echo $this->_output; - } + /** + * 发送响应信息 + * + */ + public function sendResponse() + { + echo $this->_output; + } - /** - * 设置输出信息 - * - * @param string $output - */ - public function setOutput($output) { - $this->_output = $output; - } + /** + * 设置输出信息 + * + * @param string $output + */ + public function setOutput($output) + { + $this->_output = $output; + } - /** - * @return array - */ - public function getHeaders() { - return array(); - } - - /* (non-PHPdoc) - * @see IWindResponse::getData() - */ - public function getData() { - return array(); - } - - /* (non-PHPdoc) - * @see IWindResponse::setData() - */ - public function setData($data, $key = '') { - return false; - } - - /* (non-PHPdoc) - * @see IWindResponse::getCharset() - */ - public function getCharset() { - return $this->charset; - } - - /* (non-PHPdoc) - * @see IWindResponse::setCharset() - */ - public function setCharset($_charset) { - return $this->charset = $_charset; - } - - /* (non-PHPdoc) - * @see IWindResponse::setBody() - */ - public function setBody($content, $name = 'default') { - return false; - } - - /* (non-PHPdoc) - * @see IWindResponse::sendError() - */ - public function sendError($status = self::W_NOT_FOUND, $message = '') { - return false; - } - - /* (non-PHPdoc) - * @see IWindResponse::sendBody() - */ - public function sendBody() { - return false; - } - - /* (non-PHPdoc) - * @see IWindResponse::sendHeaders() - */ - public function sendHeaders() { - return false; - } -} + /** + * @return array + */ + public function getHeaders() + { + return array(); + } + + /* (non-PHPdoc) + * @see IWindResponse::getData() + */ + public function getData() + { + return array(); + } + + /* (non-PHPdoc) + * @see IWindResponse::setData() + */ + public function setData($data, $key = '') + { + return false; + } + + /* (non-PHPdoc) + * @see IWindResponse::getCharset() + */ + public function getCharset() + { + return $this->charset; + } + + /* (non-PHPdoc) + * @see IWindResponse::setCharset() + */ + public function setCharset($_charset) + { + return $this->charset = $_charset; + } -?> \ No newline at end of file + /* (non-PHPdoc) + * @see IWindResponse::setBody() + */ + public function setBody($content, $name = 'default') + { + return false; + } + + /* (non-PHPdoc) + * @see IWindResponse::sendError() + */ + public function sendError($status = self::W_NOT_FOUND, $message = '') + { + return false; + } + + /* (non-PHPdoc) + * @see IWindResponse::sendBody() + */ + public function sendBody() + { + return false; + } + + /* (non-PHPdoc) + * @see IWindResponse::sendHeaders() + */ + public function sendHeaders() + { + return false; + } +} diff --git a/wind/command/WindCommandRouter.php b/wind/command/WindCommandRouter.php deleted file mode 100644 index 1bd6761f..00000000 --- a/wind/command/WindCommandRouter.php +++ /dev/null @@ -1,101 +0,0 @@ - - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package command - */ -class WindCommandRouter extends AbstractWindRouter { - protected $moduleKey = '-m,module,--module'; - protected $controllerKey = '-c,controller,--controller'; - protected $actionKey = '-a,action,--action'; - protected $helpKey = '-h,help,--help'; - protected $paramKey = '-p,param,--param'; - protected $help = false; - protected $cmd = ''; - /** - * @var WindCommandRequest - */ - private $request = null; - - /* (non-PHPdoc) - * @see AbstractWindRouter::route() - */ - public function route($request) { - $this->request = $request; - $this->_action = $this->action; - $this->_controller = $this->controller; - $this->_module = $this->module; - if (!empty($this->_config['routes'])) { - $params = $this->getHandler()->handle($request); - $this->setParams($params, $request); - } else { - $args = $request->getRequest('argv', array()); - $this->cmd = $args[0]; - $_count = count($args); - for ($i = 1; $i < $_count; $i++) { - if (in_array($args[$i], explode(',', $this->helpKey))) { - $this->help = true; - } elseif (in_array($args[$i], explode(',', $this->moduleKey))) { - $this->module = $args[++$i]; - } elseif (in_array($args[$i], explode(',', $this->controllerKey))) { - $this->controller = $args[++$i]; - } elseif (in_array($args[$i], explode(',', $this->actionKey))) { - $this->action = $args[++$i]; - } elseif (in_array($args[$i], explode(',', $this->paramKey))) { - $_SERVER['argv'] = array_slice($args, $i + 1); - break; - } - } - } - } - - /* (non-PHPdoc) - * @see AbstractWindRouter::assemble() - */ - public function assemble($action, $args = array(), $route = '') { - return ''; - } - - /* (non-PHPdoc) - * @see AbstractWindRouter::setParams() - */ - protected function setParams($params, $request) { - /* @var $request WindCommandRequest */ - $_SERVER['argv'] = isset($params[$this->paramKey]) ? $params[$this->paramKey] : array(); - isset($params[$this->moduleKey]) && $this->setModule($params[$this->moduleKey]); - isset($params[$this->controllerKey]) && $this->setController($params[$this->controllerKey]); - isset($params[$this->actionKey]) && $this->setAction($params[$this->actionKey]); - } - - /** - * 是否是请求帮助 - * - * @return boolean - */ - public function isHelp() { - return $this->help; - } - - /** - * 返回当前命令 - * - * @return string - */ - public function getCmd() { - return $this->cmd; - } - - /** - * @return string - */ - public function getParamKey() { - return $this->paramKey; - } -} - -?> \ No newline at end of file diff --git a/wind/convert/IWindConverter.php b/wind/convert/IWindConverter.php index 98411b0d..8d2060df 100644 --- a/wind/convert/IWindConverter.php +++ b/wind/convert/IWindConverter.php @@ -1,23 +1,21 @@ 2011-10-19 * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: IWindConverter.php 3016 2011-10-20 02:23:08Z yishuo $ * @package convert */ -interface IWindConverter { - - /** - * 编码转化 - * - * 对输入的字符串进行从原编码到目标编码的转化,请确定原编码与目标编码 - * @param string $srcText - * @return string 转化后的编码 - */ - public function convert($str); +interface IWindConverter +{ + /** + * 编码转化 + * + * 对输入的字符串进行从原编码到目标编码的转化,请确定原编码与目标编码 + * @param string $srcText + * @return string 转化后的编码 + */ + public function convert($str); } - -?> \ No newline at end of file diff --git a/wind/convert/WindGeneralConverter.php b/wind/convert/WindGeneralConverter.php index b0901e67..3547b230 100644 --- a/wind/convert/WindGeneralConverter.php +++ b/wind/convert/WindGeneralConverter.php @@ -1,330 +1,354 @@ 2011-10-19 * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindGeneralConverter.php 3016 2011-10-20 02:23:08Z yishuo $ * @package convert */ -class WindGeneralConverter extends WindModule implements IWindConverter { - protected $tableName = './encode/encode.table'; - protected $tableHandle = 0; - protected $encodeLang = ''; - protected $iconvEnabled = false; - protected $tableIndex = array(); - protected $tableEncode = array(); - - protected $IndexPoint = array( - 'GBKtoUTF8' => 0, - 'GBKtoUNICODE' => 0, - 'BIG5toUTF8' => 1024, - 'BIG5toUNICODE' => 1024, - 'UTF8toGBK' => 512, - 'UTF8toBIG5' => 1536); +class WindGeneralConverter extends WindModule implements IWindConverter +{ + protected $tableName = './encode/encode.table'; + protected $tableHandle = 0; + protected $encodeLang = ''; + protected $iconvEnabled = false; + protected $tableIndex = array(); + protected $tableEncode = array(); + + protected $IndexPoint = array( + 'GBKtoUTF8' => 0, + 'GBKtoUNICODE' => 0, + 'BIG5toUTF8' => 1024, + 'BIG5toUNICODE' => 1024, + 'UTF8toGBK' => 512, + 'UTF8toBIG5' => 1536, ); + + /** + * @param string $SourceLang + * @param string $TargetLang + * @param bool $ForceTable + */ + public function WindGeneralConverter($sourceLang = '', $targetLang = '', $forceTable = false) + { + if ($sourceLang && $targetLang) { + $this->initConvert($sourceLang, $targetLang, $forceTable); + } + } + + /** + * 编码转化 + * + * 对输入的字符串进行从原编码到目标编码的转化,请确定原编码与目标编码 + * @param string $srcText + * @param string $SourceLang + * @param string $TargetLang + * @param bool $ForceTable + * @return Ambigous |string|unknown + */ + public function convert($srcText, $sourceLang = '', $targetLang = '', $forceTable = false) + { + if ($sourceLang && $targetLang) { + $this->initConvert($sourceLang, $targetLang, $forceTable); + } + + if ($this->encodeLang) { + switch ($this->encodeLang) { + case 'GBKtoUTF8': + return $this->iconvEnabled ? iconv('GBK', 'UTF-8', $srcText) : $this->chstoUTF8($srcText); + break; + case 'BIG5toUTF8': + return $this->iconvEnabled ? iconv('BIG5', 'UTF-8', $srcText) : $this->chstoUTF8($srcText); + break; + case 'UTF8toGBK': + return $this->iconvEnabled ? iconv('UTF-8', 'GBK', $srcText) : $this->utf8toCHS($srcText); + break; + case 'UTF8toBIG5': + return $this->utf8toCHS($srcText); + break; + case 'GBKtoUNICODE': + return $this->chstoUNICODE($srcText, 'GBK'); + break; + case 'BIG5toUNICODE': + return $this->chstoUNICODE($srcText, 'BIG5'); + break; + case 'GBKtoBIG5': + case 'BIG5toGBK': + return $this->chsConvert($srcText, $this->encodeLang); + break; + } + } + + return $srcText; + } + + /** + * 初始化类 + * + * @param string $SourceLang + * @param string $TargetLang + * @param bool $ForceTable + */ + protected function initConvert($SourceLang, $targetLang, $forceTable) + { + if (($SourceLang = $this->_getCharset($SourceLang)) && ($targetLang = $this->_getCharset($targetLang)) && $SourceLang != $targetLang) { + $this->encodeLang = $SourceLang.'to'.$targetLang; + $this->iconvEnabled = (function_exists('iconv') && $targetLang != 'BIG5' && !$forceTable) ? true : false; + $this->iconvEnabled || is_resource($this->tableHandle) || $this->tableHandle = fopen($this->tableName, 'r'); + } + } + + /** + * unicode to utf8 + * + * @param string $c + * @return string + */ + protected function unicodeToUTF8($c) + { + if ($c < 0x80) { + $c = chr($c); + } elseif ($c < 0x800) { + $c = chr(0xC0 | $c >> 6).chr(0x80 | $c & 0x3F); + } elseif ($c < 0x10000) { + $c = chr(0xE0 | $c >> 12).chr(0x80 | $c >> 6 & 0x3F).chr(0x80 | $c & 0x3F); + } elseif ($c < 0x200000) { + $c = chr(0xF0 | $c >> 18).chr(0x80 | $c >> 12 & 0x3F).chr(0x80 | $c >> 6 & 0x3F).chr(0x80 | $c & 0x3F); + } elseif ($c < 0x4000000) { + $c = chr(0xF8 | $c >> 24).chr(0xF0 | $c >> 18).chr(0x80 | $c >> 12 & 0x3F).chr(0x80 | $c >> 6 & 0x3F).chr( + 0x80 | $c & 0x3F); + } else { + $c = chr(0xF8 | $c >> 30).chr(0xF8 | $c >> 24).chr(0xF0 | $c >> 18).chr(0x80 | $c >> 12 & 0x3F).chr( + 0x80 | $c >> 6 & 0x3F).chr(0x80 | $c & 0x3F); + } + + return $c; + } + + /** + * BIG5,GBK to Unicode + * + * @param string $c + * @return string + */ + protected function chsUTF8toU($c) + { + switch (strlen($c)) { + case 1: + return ord($c); + case 2: + return ((ord($c[0]) & 0x3F) << 6) + (ord($c[1]) & 0x3F); + case 3: + return ((ord($c[0]) & 0x1F) << 12) + ((ord($c[1]) & 0x3F) << 6) + (ord($c[2]) & 0x3F); + case 4: + return ((ord($c[0]) & 0x0F) << 18) + ((ord($c[1]) & 0x3F) << 12) + ((ord($c[2]) & 0x3F) << 6) + (ord( + $c[3]) & 0x3F); + } + } - /** - * @param string $SourceLang - * @param string $TargetLang - * @param boolean $ForceTable - */ - public function WindGeneralConverter($sourceLang = '', $targetLang = '', $forceTable = false) { - if ($sourceLang && $targetLang) $this->initConvert($sourceLang, $targetLang, $forceTable); - } + /** + * BIG5,GBK to UTF8 + * + * @param string $srcText + * @return Ambigous + */ + protected function chstoUTF8($srcText) + { + $this->_getTableIndex(); + $tarText = ''; + for ($i = 0; $i < strlen($srcText); $i += 2) { + $h = ord($srcText[$i]); + if ($h > 127 && isset($this->tableIndex[$this->encodeLang][$h])) { + $l = ord($srcText[$i + 1]); + if (!isset($this->tableEncode[$this->encodeLang][$h][$l])) { + fseek($this->tableHandle, $l * 2 + $this->tableIndex[$this->encodeLang][$h]); + $this->tableEncode[$this->encodeLang][$h][$l] = $this->unicodeToUTF8( + hexdec(bin2hex(fread($this->tableHandle, 2)))); + } + $tarText .= $this->tableEncode[$this->encodeLang][$h][$l]; + } elseif ($h < 128) { + $tarText .= $srcText[$i]; + $i--; + } + } - /** - * 编码转化 - * - * 对输入的字符串进行从原编码到目标编码的转化,请确定原编码与目标编码 - * @param string $srcText - * @param string $SourceLang - * @param string $TargetLang - * @param boolean $ForceTable - * @return Ambigous |string|unknown - */ - public function convert($srcText, $sourceLang = '', $targetLang = '', $forceTable = false) { - if ($sourceLang && $targetLang) $this->initConvert($sourceLang, $targetLang, $forceTable); - - if ($this->encodeLang) { - switch ($this->encodeLang) { - case 'GBKtoUTF8': - return $this->iconvEnabled ? iconv('GBK', 'UTF-8', $srcText) : $this->chstoUTF8($srcText); - break; - case 'BIG5toUTF8': - return $this->iconvEnabled ? iconv('BIG5', 'UTF-8', $srcText) : $this->chstoUTF8($srcText); - break; - case 'UTF8toGBK': - return $this->iconvEnabled ? iconv('UTF-8', 'GBK', $srcText) : $this->utf8toCHS($srcText); - break; - case 'UTF8toBIG5': - return $this->utf8toCHS($srcText); - break; - case 'GBKtoUNICODE': - return $this->chstoUNICODE($srcText, 'GBK'); - break; - case 'BIG5toUNICODE': - return $this->chstoUNICODE($srcText, 'BIG5'); - break; - case 'GBKtoBIG5': - case 'BIG5toGBK': - return $this->chsConvert($srcText, $this->encodeLang); - break; - } - } - return $srcText; - } + return $tarText; + } - /** - * 初始化类 - * - * @param string $SourceLang - * @param string $TargetLang - * @param boolean $ForceTable - */ - protected function initConvert($SourceLang, $targetLang, $forceTable) { - if (($SourceLang = $this->_getCharset($SourceLang)) && ($targetLang = $this->_getCharset($targetLang)) && $SourceLang != $targetLang) { - $this->encodeLang = $SourceLang . 'to' . $targetLang; - $this->iconvEnabled = (function_exists('iconv') && $targetLang != 'BIG5' && !$forceTable) ? true : false; - $this->iconvEnabled || is_resource($this->tableHandle) || $this->tableHandle = fopen($this->tableName, "r"); - } - } + /** + * UTF8 to GBK,BIG5 + * + * @param string $srcText + * @return string + */ + protected function utf8toCHS($srcText) + { + $this->_getTableIndex(); + $tarText = ''; + $i = 0; + while ($i < strlen($srcText)) { + $c = ord($srcText[$i++]); + switch ($c >> 4) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + $tarText .= chr($c); + break; + case 12: + case 13: + $c = (($c & 0x1F) << 6) | (ord($srcText[$i++]) & 0x3F); + $h = $c >> 8; + if (isset($this->tableIndex[$this->encodeLang][$h])) { + $l = $c & 0xFF; + if (!isset($this->tableEncode[$this->encodeLang][$h][$l])) { + fseek($this->tableHandle, $l * 2 + $this->tableIndex[$this->encodeLang][$h]); + $this->tableEncode[$this->encodeLang][$h][$l] = fread($this->tableHandle, 2); + } + $tarText .= $this->tableEncode[$this->encodeLang][$h][$l]; + } + break; + case 14: + $c = (($c & 0x0F) << 12) | ((ord($srcText[$i++]) & 0x3F) << 6) | ((ord($srcText[$i++]) & 0x3F)); + $h = $c >> 8; + if (isset($this->tableIndex[$this->encodeLang][$h])) { + $l = $c & 0xFF; + if (!isset($this->tableEncode[$h][$l])) { + fseek($this->tableHandle, $l * 2 + $this->tableIndex[$this->encodeLang][$h]); + $this->tableEncode[$h][$l] = fread($this->tableHandle, 2); + } + $tarText .= $this->tableEncode[$h][$l]; + } + break; + } + } - /** - * unicode to utf8 - * - * @param string $c - * @return string - */ - protected function unicodeToUTF8($c) { - if ($c < 0x80) { - $c = chr($c); - } elseif ($c < 0x800) { - $c = chr(0xC0 | $c >> 6) . chr(0x80 | $c & 0x3F); - } elseif ($c < 0x10000) { - $c = chr(0xE0 | $c >> 12) . chr(0x80 | $c >> 6 & 0x3F) . chr(0x80 | $c & 0x3F); - } elseif ($c < 0x200000) { - $c = chr(0xF0 | $c >> 18) . chr(0x80 | $c >> 12 & 0x3F) . chr(0x80 | $c >> 6 & 0x3F) . chr(0x80 | $c & 0x3F); - } elseif ($c < 0x4000000) { - $c = chr(0xF8 | $c >> 24) . chr(0xF0 | $c >> 18) . chr(0x80 | $c >> 12 & 0x3F) . chr(0x80 | $c >> 6 & 0x3F) . chr( - 0x80 | $c & 0x3F); - } else { - $c = chr(0xF8 | $c >> 30) . chr(0xF8 | $c >> 24) . chr(0xF0 | $c >> 18) . chr(0x80 | $c >> 12 & 0x3F) . chr( - 0x80 | $c >> 6 & 0x3F) . chr(0x80 | $c & 0x3F); - } - return $c; - } + return $tarText; + } - /** - * BIG5,GBK to Unicode - * - * @param string $c - * @return string - */ - protected function chsUTF8toU($c) { - switch (strlen($c)) { - case 1: - return ord($c); - case 2: - return ((ord($c[0]) & 0x3F) << 6) + (ord($c[1]) & 0x3F); - case 3: - return ((ord($c[0]) & 0x1F) << 12) + ((ord($c[1]) & 0x3F) << 6) + (ord($c[2]) & 0x3F); - case 4: - return ((ord($c[0]) & 0x0F) << 18) + ((ord($c[1]) & 0x3F) << 12) + ((ord($c[2]) & 0x3F) << 6) + (ord( - $c[3]) & 0x3F); - } - } + /** + * GBK,BIG5 to UNICODE + * + * @param string $srcText + * @param string $SourceLang + * @return Ambigous + */ + protected function chstoUNICODE($srcText, $SourceLang = '') + { + $tarText = ''; + if ($this->iconvEnabled && isset($SourceLang)) { + for ($i = 0; $i < strlen($srcText); $i += 2) { + if (ord($srcText[$i]) > 127) { + $tarText .= '&#x'.dechex( + $this->Utf8_Unicode(iconv($SourceLang, 'UTF-8', $srcText[$i].$srcText[$i + 1]))).';'; + } else { + $tarText .= $srcText[$i--]; + } + } + } else { + $this->_getTableIndex(); + for ($i = 0; $i < strlen($srcText); $i += 2) { + $h = ord($srcText[$i]); + if ($h > 127 && isset($this->tableIndex[$this->encodeLang][$h])) { + $l = ord($srcText[$i + 1]); + if (!isset($this->tableEncode[$this->encodeLang][$h][$l])) { + fseek($this->tableHandle, $l * 2 + $this->tableIndex[$this->encodeLang][$h]); + $this->tableEncode[$this->encodeLang][$h][$l] = '&#x'.bin2hex(fread($this->tableHandle, 2)).';'; + } + $tarText .= $this->tableEncode[$this->encodeLang][$h][$l]; + } elseif ($h < 128) { + $tarText .= $srcText[$i--]; + } + } + } - /** - * BIG5,GBK to UTF8 - * - * @param string $srcText - * @return Ambigous - */ - protected function chstoUTF8($srcText) { - $this->_getTableIndex(); - $tarText = ''; - for ($i = 0; $i < strlen($srcText); $i += 2) { - $h = ord($srcText[$i]); - if ($h > 127 && isset($this->tableIndex[$this->encodeLang][$h])) { - $l = ord($srcText[$i + 1]); - if (!isset($this->tableEncode[$this->encodeLang][$h][$l])) { - fseek($this->tableHandle, $l * 2 + $this->tableIndex[$this->encodeLang][$h]); - $this->tableEncode[$this->encodeLang][$h][$l] = $this->unicodeToUTF8( - hexdec(bin2hex(fread($this->tableHandle, 2)))); - } - $tarText .= $this->tableEncode[$this->encodeLang][$h][$l]; - } elseif ($h < 128) { - $tarText .= $srcText[$i]; - $i--; - } - } - return $tarText; - } + return $tarText; + } - /** - * UTF8 to GBK,BIG5 - * - * @param string $srcText - * @return string - */ - protected function utf8toCHS($srcText) { - $this->_getTableIndex(); - $tarText = ''; - $i = 0; - while ($i < strlen($srcText)) { - $c = ord($srcText[$i++]); - switch ($c >> 4) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - $tarText .= chr($c); - break; - case 12: - case 13: - $c = (($c & 0x1F) << 6) | (ord($srcText[$i++]) & 0x3F); - $h = $c >> 8; - if (isset($this->tableIndex[$this->encodeLang][$h])) { - $l = $c & 0xFF; - if (!isset($this->tableEncode[$this->encodeLang][$h][$l])) { - fseek($this->tableHandle, $l * 2 + $this->tableIndex[$this->encodeLang][$h]); - $this->tableEncode[$this->encodeLang][$h][$l] = fread($this->tableHandle, 2); - } - $tarText .= $this->tableEncode[$this->encodeLang][$h][$l]; - } - break; - case 14: - $c = (($c & 0x0F) << 12) | ((ord($srcText[$i++]) & 0x3F) << 6) | ((ord($srcText[$i++]) & 0x3F)); - $h = $c >> 8; - if (isset($this->tableIndex[$this->encodeLang][$h])) { - $l = $c & 0xFF; - if (!isset($this->tableEncode[$h][$l])) { - fseek($this->tableHandle, $l * 2 + $this->tableIndex[$this->encodeLang][$h]); - $this->tableEncode[$h][$l] = fread($this->tableHandle, 2); - } - $tarText .= $this->tableEncode[$h][$l]; - } - break; - } - } - return $tarText; - } + /** + * BIG5toGBK + * + * @param string $srcText + * @param string $SourceLang + * @return mixed + */ + protected function chsConvert($srcText, $SourceLang = 'GBK') + { + if (strtoupper(substr($SourceLang, 0, 3)) == 'GBK') { + $handle = fopen('./encode/gb-big5.table', 'r'); + } else { + $handle = fopen('./encode/big5-gb.table', 'r'); + } + $encode = array(); + for ($i = 0; $i < strlen($srcText) - 1; $i++) { + $h = ord($srcText[$i]); + if ($h >= 160) { + $l = ord($srcText[$i + 1]); + if (!isset($encode[$h][$l])) { + fseek($handle, ($h - 160) * 510 + ($l - 1) * 2); + $encode[$h][$l] = fread($handle, 2); + } + $srcText[$i++] = $encode[$h][$l][0]; + $srcText[$i] = $encode[$h][$l][1]; + } + } + fclose($handle); - /** - * GBK,BIG5 to UNICODE - * - * @param string $srcText - * @param string $SourceLang - * @return Ambigous - */ - protected function chstoUNICODE($srcText, $SourceLang = '') { - $tarText = ''; - if ($this->iconvEnabled && isset($SourceLang)) { - for ($i = 0; $i < strlen($srcText); $i += 2) { - if (ord($srcText[$i]) > 127) { - $tarText .= "&#x" . dechex( - $this->Utf8_Unicode(iconv($SourceLang, "UTF-8", $srcText[$i] . $srcText[$i + 1]))) . ";"; - } else { - $tarText .= $srcText[$i--]; - } - } - } else { - $this->_getTableIndex(); - for ($i = 0; $i < strlen($srcText); $i += 2) { - $h = ord($srcText[$i]); - if ($h > 127 && isset($this->tableIndex[$this->encodeLang][$h])) { - $l = ord($srcText[$i + 1]); - if (!isset($this->tableEncode[$this->encodeLang][$h][$l])) { - fseek($this->tableHandle, $l * 2 + $this->tableIndex[$this->encodeLang][$h]); - $this->tableEncode[$this->encodeLang][$h][$l] = '&#x' . bin2hex(fread($this->tableHandle, 2)) . ';'; - } - $tarText .= $this->tableEncode[$this->encodeLang][$h][$l]; - } elseif ($h < 128) { - $tarText .= $srcText[$i--]; - } - } - } - return $tarText; - } + return $srcText; + } - /** - * BIG5toGBK - * - * @param string $srcText - * @param string $SourceLang - * @return mixed - */ - protected function chsConvert($srcText, $SourceLang = 'GBK') { - if (strtoupper(substr($SourceLang, 0, 3)) == 'GBK') { - $handle = fopen('./encode/gb-big5.table', "r"); - } else { - $handle = fopen('./encode/big5-gb.table', "r"); - } - $encode = array(); - for ($i = 0; $i < strlen($srcText) - 1; $i++) { - $h = ord($srcText[$i]); - if ($h >= 160) { - $l = ord($srcText[$i + 1]); - if (!isset($encode[$h][$l])) { - fseek($handle, ($h - 160) * 510 + ($l - 1) * 2); - $encode[$h][$l] = fread($handle, 2); - } - $srcText[$i++] = $encode[$h][$l][0]; - $srcText[$i] = $encode[$h][$l][1]; - } - } - fclose($handle); - return $srcText; - } + /** + * 解析编码表 + * + */ + private function _getTableIndex() + { + if (!isset($this->tableIndex[$this->encodeLang])) { + fseek($this->tableHandle, $this->IndexPoint[$this->encodeLang]); + $tmpData = fread($this->tableHandle, 512); + $pFirstEncode = hexdec(bin2hex(substr($tmpData, 4, 4))); + for ($i = 8; $i < 512; $i += 4) { + $item = unpack('nkey/nvalue', substr($tmpData, $i, 4)); + if (isset($this->tableIndex[$this->encodeLang][$item['key']])) { + break; + } + $this->tableIndex[$this->encodeLang][$item['key']] = $pFirstEncode + $item['value']; + } + } + } - /** - * 解析编码表 - * - * @return void - */ - private function _getTableIndex() { - if (!isset($this->tableIndex[$this->encodeLang])) { - fseek($this->tableHandle, $this->IndexPoint[$this->encodeLang]); - $tmpData = fread($this->tableHandle, 512); - $pFirstEncode = hexdec(bin2hex(substr($tmpData, 4, 4))); - for ($i = 8; $i < 512; $i += 4) { - $item = unpack('nkey/nvalue', substr($tmpData, $i, 4)); - if (isset($this->tableIndex[$this->encodeLang][$item['key']])) break; - $this->tableIndex[$this->encodeLang][$item['key']] = $pFirstEncode + $item['value']; - } - } - } + /** + * 获得编码类型 + * + * @param string $lang + * @return string + */ + private function _getCharset($lang) + { + switch (strtoupper(substr($lang, 0, 2))) { + case 'GB': + $lang = 'GBK'; + break; + case 'UT': + $lang = 'UTF8'; + break; + case 'UN': + $lang = 'UNICODE'; + break; + case 'BI': + $lang = 'BIG5'; + break; + default: + $lang = ''; + } - /** - * 获得编码类型 - * - * @param string $lang - * @return string - */ - private function _getCharset($lang) { - switch (strtoupper(substr($lang, 0, 2))) { - case 'GB': - $lang = 'GBK'; - break; - case 'UT': - $lang = 'UTF8'; - break; - case 'UN': - $lang = 'UNICODE'; - break; - case 'BI': - $lang = 'BIG5'; - break; - default: - $lang = ''; - } - return $lang; - } + return $lang; + } } -?> \ No newline at end of file diff --git a/wind/dao/WindDao.php b/wind/dao/WindDao.php index 47beb2d8..4fc20b3f 100644 --- a/wind/dao/WindDao.php +++ b/wind/dao/WindDao.php @@ -1,39 +1,41 @@ * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindDao.php 2973 2011-10-15 19:22:48Z yishuo $ * @package dao */ -class WindDao extends WindModule { - /** - * 链接句柄 - * - * @var WindConnection - */ - protected $connection = null; +class WindDao extends WindModule +{ + /** + * 链接句柄 + * + * @var WindConnection + */ + protected $connection = null; - /** - * 获得链接对象 - * - * 根据用户配置决定配置是采用配置链接管理 - * - * @return WindConnection - */ - public function getConnection() { - return $this->_getConnection(); - } + /** + * 获得链接对象 + * + * 根据用户配置决定配置是采用配置链接管理 + * + * @return WindConnection + */ + public function getConnection() + { + return $this->_getConnection(); + } - /** - * 设置链接对象 - * - * @param WindConnection $connection 链接对象 - */ - public function setConnection($connection) { - $this->connection = $connection; - } + /** + * 设置链接对象 + * + * @param WindConnection $connection 链接对象 + */ + public function setConnection($connection) + { + $this->connection = $connection; + } } -?> \ No newline at end of file diff --git a/wind/dao/WindDaoFactory.php b/wind/dao/WindDaoFactory.php index 11a7553e..9227344b 100644 --- a/wind/dao/WindDaoFactory.php +++ b/wind/dao/WindDaoFactory.php @@ -1,8 +1,8 @@ *
  • 创建DAO实例
  • @@ -13,63 +13,66 @@ * @author Qiong Wu * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindDaoFactory.php 3904 2013-01-08 07:01:26Z yishuo $ * @package dao */ -class WindDaoFactory extends WindModule { - /** - * dao路径信息 - * - * @var string - */ - protected $daoResource = ''; +class WindDaoFactory extends WindModule +{ + /** + * dao路径信息 + * + * @var string + */ + protected $daoResource = ''; + + /** + * 返回Dao类实例 + * $className接受两种形式呃参数如下 + *
      + *
    • 'namespace:path'
    • + *
    • 'className'
    • + *
    + * + * @param string $className + * Dao名字 + * @return WindDao + * @throws WindDaoException 如果获取实例错误抛出异常 + */ + public function getDao($className) + { + try { + if (strpos($className, ':') === false) { + $className = $this->getDaoResource().'.'.$className; + } + Wind::registeComponent(array('path' => $className, 'scope' => 'application'), $className); + $daoInstance = Wind::getComponent($className); + $daoInstance->setDelayAttributes(array('connection' => array('ref' => 'db'))); - /** - * 返回Dao类实例 - * - * $className接受两种形式呃参数如下 - *
      - *
    • 'namespace:path'
    • - *
    • 'className'
    • - *
    - * - * @param string $className Dao名字 - * @return WindDao - * @throws WindDaoException 如果获取实例错误抛出异常 - */ - public function getDao($className) { - try { - if (strpos($className, ":") === false) - $className = $this->getDaoResource() . '.' . $className; - Wind::getApp()->getWindFactory()->addClassDefinitions($className, - array('path' => $className, 'scope' => 'application')); - $daoInstance = Wind::getApp()->getWindFactory()->getInstance($className); - $daoInstance->setDelayAttributes(array('connection' => array('ref' => 'db'))); - return $daoInstance; - } catch (Exception $exception) { - throw new WindDaoException( - '[dao.WindDaoFactory] create dao ' . $className . ' fail.' . $exception->getMessage()); - } - } + return $daoInstance; + } catch (Exception $exception) { + throw new WindDaoException('[dao.WindDaoFactory.getDao] create dao '.$className.' fail.'.$exception->getMessage()); + } + } - /** - * 获得dao存放的目录 - * - * @return string $daoResource Dao目录 - */ - public function getDaoResource() { - return $this->daoResource; - } + /** + * 获得dao存放的目录 + * + * @return string $daoResource Dao目录 + */ + public function getDaoResource() + { + return $this->daoResource; + } - /** - * 设置dao的获取目录 - * - * 以框架的命名空间方式设置比如:WIND:dao来设置路径信息,WIND的位置为注册过的命名空间名字. - * - * @param string $daoResource Dao目录 - */ - public function setDaoResource($daoResource) { - $this->daoResource = $daoResource; - } + /** + * 设置dao的获取目录 + * 以框架的命名空间方式设置比如:WIND:dao来设置路径信息,WIND的位置为注册过的命名空间名字. + * + * @param string $daoResource + * Dao目录 + */ + public function setDaoResource($daoResource) + { + $this->daoResource = $daoResource; + } } -?> \ No newline at end of file diff --git a/wind/dao/exception/WindDaoException.php b/wind/dao/exception/WindDaoException.php index 2c907da7..2c84d61a 100644 --- a/wind/dao/exception/WindDaoException.php +++ b/wind/dao/exception/WindDaoException.php @@ -1,25 +1,26 @@ * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindDaoException.php 2973 2011-10-15 19:22:48Z yishuo $ * @package dao * @subpackage exception */ -class WindDaoException extends WindException { +class WindDaoException extends WindException +{ + /* (non-PHPdoc) + * @see WindException::messageMapper() + */ + protected function messageMapper($code) + { + $messages = array(); - /* (non-PHPdoc) - * @see WindException::messageMapper() - */ - protected function messageMapper($code) { - $messages = array(); - return isset($messages[$code]) ? $messages[$code] : '$message'; - } + return isset($messages[$code]) ? $messages[$code] : '$message'; + } } - -?> \ No newline at end of file diff --git a/wind/dao/listener/WindDaoCacheListener.php b/wind/dao/listener/WindDaoCacheListener.php index 438ef26f..f96b6c6e 100644 --- a/wind/dao/listener/WindDaoCacheListener.php +++ b/wind/dao/listener/WindDaoCacheListener.php @@ -1,65 +1,69 @@ * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindDaoCacheListener.php 2973 2011-10-15 19:22:48Z yishuo $ * @package dao * @subpackage listener */ -class WindDaoCacheListener extends WindHandlerInterceptor { +class WindDaoCacheListener extends WindHandlerInterceptor +{ + /** + * dao实例对象 + * + * @var WindDao + */ + private $daoObject = null; - /** - * dao实例对象 - * - * @var WindDao - */ - private $daoObject = null; + /** + * 构造函数 + * + * 设置需要监听的dao实例对象 + * + * @param WindDao $instance + */ + public function __construct($instance) + { + $this->daoObject = $instance; + } - /** - * 构造函数 - * - * 设置需要监听的dao实例对象 - * - * @param WindDao $instance - */ - public function __construct($instance) { - $this->daoObject = $instance; - } + /* (non-PHPdoc) + * @see WindHandlerInterceptor::preHandle() + */ + public function preHandle() + { + /* @var $cacheHandler AbstractWindCache */ + $cacheHandler = $this->daoObject->getCacheHandler(); + $key = $this->generateKey(func_get_args()); + $result = $cacheHandler->get($key); - /* (non-PHPdoc) - * @see WindHandlerInterceptor::preHandle() - */ - public function preHandle() { - /* @var $cacheHandler AbstractWindCache */ - $cacheHandler = $this->daoObject->getCacheHandler(); - $key = $this->generateKey(func_get_args()); - $result = $cacheHandler->get($key); - return empty($result) ? null : $result; - } + return empty($result) ? null : $result; + } - /* (non-PHPdoc) - * @see WindHandlerInterceptor::postHandle() - */ - public function postHandle() { - /* @var $cacheHandler AbstractWindCache */ - $cacheHandler = $this->daoObject->getCacheHandler(); - $key = $this->generateKey(func_get_args()); - $cacheHandler->set($key, $this->result); - } + /* (non-PHPdoc) + * @see WindHandlerInterceptor::postHandle() + */ + public function postHandle() + { + /* @var $cacheHandler AbstractWindCache */ + $cacheHandler = $this->daoObject->getCacheHandler(); + $key = $this->generateKey(func_get_args()); + $cacheHandler->set($key, $this->result); + } - /** - * 返回缓存键值 - * - * @param array $args 被监听方法的传递参数 - * @return string 计算生成保存的缓存键值 - */ - private function generateKey($args) { - return $this->event[0] . '_' . $this->event[1] . '_' . (is_array($args[0]) ? $args[0][0] : $args[0]); - } + /** + * 返回缓存键值 + * + * @param array $args 被监听方法的传递参数 + * @return string 计算生成保存的缓存键值 + */ + private function generateKey($args) + { + return $this->event[0].'_'.$this->event[1].'_'.(is_array($args[0]) ? $args[0][0] : $args[0]); + } } - -?> \ No newline at end of file diff --git a/wind/db/AbstractWindPdoAdapter.php b/wind/db/AbstractWindPdoAdapter.php index e10b4da3..3a170a1d 100644 --- a/wind/db/AbstractWindPdoAdapter.php +++ b/wind/db/AbstractWindPdoAdapter.php @@ -1,89 +1,92 @@ 2011-9-22 * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: AbstractWindPdoAdapter.php 3113 2011-11-11 07:28:09Z yishuo $ * @package db */ -abstract class AbstractWindPdoAdapter extends PDO { - private $_typeMap = array( - 'boolean' => PDO::PARAM_BOOL, - 'integer' => PDO::PARAM_INT, - 'string' => PDO::PARAM_STR, - 'NULL' => PDO::PARAM_NULL); +abstract class AbstractWindPdoAdapter extends PDO +{ + private $_typeMap = array( + 'boolean' => PDO::PARAM_BOOL, + 'integer' => PDO::PARAM_INT, + 'string' => PDO::PARAM_STR, + 'NULL' => PDO::PARAM_NULL, ); - /** - * 获得绑定参数的类型 - * - * @param string $variable - * @return int - */ - protected function _getPdoDataType($variable) { - return isset($this->_typeMap[gettype($variable)]) ? $this->_typeMap[gettype($variable)] : PDO::PARAM_STR; - } + /** + * 获得绑定参数的类型 + * + * @param string $variable + * @return int + */ + protected function _getPdoDataType($variable) + { + return isset($this->_typeMap[gettype($variable)]) ? $this->_typeMap[gettype($variable)] : PDO::PARAM_STR; + } - /* (non-PHPdoc) - * @see PDO::quote() - */ - public function quote($value, $type = null) { - if (is_array($value) || is_object($value)) return "''"; - return parent::quote($value, $type ? $type : $this->_getPdoDataType(gettype($value))); - } + /* (non-PHPdoc) + * @see PDO::quote() + */ + public function quote($value, $type = null) + { + if (is_array($value) || is_object($value)) { + return "''"; + } - /** - * 过滤SQL元数据,数据库对象(如表名字,字段等) - * - * @param array $data - * @return string - */ - abstract public function fieldMeta($data); + return parent::quote($value, $type ? $type : $this->_getPdoDataType(gettype($value))); + } - /** - * 过滤数组并组装单条 key=value 形式的SQL查询语句值(insert/update) - * - * @param array $array - * @return string - */ - abstract public function sqlSingle($array); - - /** - * 过滤数组并将数组变量转换为sql字符串 - * - * @param array $variable 需要组装的数据 - * @return string - */ - abstract public function quoteArray($variable); - - /** - * 过滤二维数组将数组变量转换为多组的sql字符串 - * - * @param array $var - * @return string - */ - abstract public function quoteMultiArray($var); + /** + * 过滤SQL元数据,数据库对象(如表名字,字段等) + * + * @param array $data + * @return string + */ + abstract public function fieldMeta($data); - /** - * 添加数据表 - * - * 添加数据表注意:最后一个参数'$replace',有两个取值'true,false',当值为false时表示如果数据表存在不创建新表, - * 值为true时则删除已经存在的数据表并创建新表 - * @param string $tableName 数据表名称 - * @param string|array $values 数据表字段信息 - * @param boolean $replace 如果表已经存在是否覆盖,接收两个值true|false - * @return boolean - */ - abstract public function createTable($tableName, $values, $replace = false); + /** + * 过滤数组并组装单条 key=value 形式的SQL查询语句值(insert/update) + * + * @param array $array + * @return string + */ + abstract public function sqlSingle($array); - /** - * 设置连接数据库是所用的编码方式 - * - * @param string $charset 编码格式 - */ - abstract public function setCharset($charset); + /** + * 过滤数组并将数组变量转换为sql字符串 + * + * @param array $variable 需要组装的数据 + * @return string + */ + abstract public function quoteArray($variable); -} + /** + * 过滤二维数组将数组变量转换为多组的sql字符串 + * + * @param array $var + * @return string + */ + abstract public function quoteMultiArray($var); + + /** + * 添加数据表 + * + * 添加数据表注意:最后一个参数'$replace',有两个取值'true,false',当值为false时表示如果数据表存在不创建新表, + * 值为true时则删除已经存在的数据表并创建新表 + * @param string $tableName 数据表名称 + * @param string|array $values 数据表字段信息 + * @param bool $replace 如果表已经存在是否覆盖,接收两个值true|false + * @return bool + */ + abstract public function createTable($tableName, $values, $replace = false); -?> \ No newline at end of file + /** + * 设置连接数据库是所用的编码方式 + * + * @param string $charset 编码格式 + */ + abstract public function setCharset($charset); +} diff --git a/wind/db/WindConnection.php b/wind/db/WindConnection.php index 709fb71d..2d184b5f 100644 --- a/wind/db/WindConnection.php +++ b/wind/db/WindConnection.php @@ -1,10 +1,11 @@ * $connection = new WindConnection('mysql:host=localhost;dbname=test', 'root', 'root'); * $stm = $connection->createStatement('SELECT * FROM {members} WHERE uid<=:uid', true); @@ -25,337 +26,367 @@ *
    * * @author Qiong Wu 2011-9-23 - * @copyright ©2003-2103 phpwind.com + * @copyright (c)2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindConnection.php 3904 2013-01-08 07:01:26Z yishuo $ * @package db */ -class WindConnection extends WindModule { - /** - * 链接字符串,携带数据驱动类型,主机信息,库名等 - * - * mysql:host=localhost;dbname=test - * @var string - */ - protected $_dsn; - /** - * 驱动名 - * - * @var string - */ - protected $_driverName; - /** - * 用户名 - * - * @var string - */ - protected $_user; - /** - * 数据密码 - * - * @var string - */ - protected $_pwd; - /** - * 数据表前缀 - * - * @var string - */ - protected $_tablePrefix; - /** - * 数据连接编码方式 - * - * @var string - */ - protected $_charset; - /** - * 属性值 - * - * @var array - */ - protected $_attributes = array(); - /** - * 数据连接句柄 - * - * @var PDO - */ - protected $_dbHandle = null; - - /** - * @param string $dsn - * @param string $username - * @param string $password - */ - public function __construct($dsn = '', $username = '', $password = '') { - $this->_dsn = $dsn; - $this->_user = $username; - $this->_pwd = $password; - } - - /** - * 接受一条sql语句,并返回sqlStatement对象 - * - * @param string $sql sql语句 - * @return WindSqlStatement - */ - public function createStatement($sql = null) { - return new WindSqlStatement($this, $this->parseQueryString($sql)); - } - - /** - * 返回数据库链接对象 - * - * @return AbstractWindPdoAdapter - */ - public function getDbHandle() { - $this->init(); - return $this->_dbHandle; - } - - /** - * 获得链接相关属性设置 - * - * @param string $attribute - * @return string - * */ - public function getAttribute($attribute) { - if ($this->_dbHandle !== null) { - return $this->_dbHandle->getAttribute($attribute); - } else - return isset($this->_attributes[$attribute]) ? $this->_attributes[$attribute] : ''; - } - - /** - * 设置链接相关属性 - * - * @param string $attribute - * @param string $value 默认值为null - * @return void - */ - public function setAttribute($attribute, $value = null) { - if (!$attribute) return; - if ($this->_dbHandle !== null) { - $this->_dbHandle->setAttribute($attribute, $value); - } else - $this->_attributes[$attribute] = $value; - } - - /** - * 返回DB驱动类型 - * - * @return string - */ - public function getDriverName() { - if ($this->_driverName) return $this->_driverName; - if ($this->_dbHandle !== null) { - $this->_driverName = $this->_dbHandle->getAttribute(PDO::ATTR_DRIVER_NAME); - } elseif (($pos = strpos($this->_dsn, ':')) !== false) { - $this->_driverName = strtolower(substr($this->_dsn, 0, $pos)); - } - return $this->_driverName; - } - - /** - * 执行一条sql语句 同时返回影响行数 - * - * @param string $sql sql语句 - * @return int - */ - public function execute($sql) { - try { - $result = $this->getDbHandle()->exec($this->parseQueryString($sql)); - if (WIND_DEBUG & 2) { - Wind::getApp()->getComponent('windLogger')->info( - "[db.WindConnection.execute] \r\n\tSQL: " . $sql . " \r\n\tResult:" . WindString::varToString( - $result)); - } - return $result; - } catch (PDOException $e) { - $this->close(); - throw new WindDbException($e->getMessage()); - } - } - - /** - * 执行一条查询同时返回结果集 - * - * @param string $sql sql语句 - * @return WindResultSet - */ - public function query($sql) { - try { - $sql = $this->parseQueryString($sql); - return new WindResultSet($this->getDbHandle()->query($sql)); - } catch (PDOException $e) { - throw new WindDbException($e->getMessage(), WindDbException::DB_QUERY_ERROR); - } - } - - /** - * 过滤SQL元数据,数据库对象(如表名字,字段等) - * - * @param string $data - * @throws WindDbException - */ - public function sqlMetadata($data) { - return $this->getDbHandle()->fieldMeta($data); - } - - /** - * 过滤数组变量,将数组变量转换为字符串,并用逗号分隔每个数组元素支持多维数组 - * - * @param array $array - * @return string - */ - public function quoteArray($array) { - return $this->getDbHandle()->quoteArray($array); - } - - /** - * 过滤二维数组将数组变量转换为多组的sql字符串 - * - * @param array $array - * @return string - */ - public function quoteMultiArray($array) { - return $this->getDbHandle()->quoteMultiArray($array); - } - - /** - * sql元数据安全过滤,并返回过滤后值 - * - * @param string $string - * @return string - */ - public function quote($string) { - return $this->getDbHandle()->quote($string); - } - - /** - * 过滤数组值并返回(insert/update)sql语句形式 - * - * 该方法接收一个数组变量,进行安全过滤,并返回组装单条 key=value 形式的SQL查询语句值 (适用于insert/update value值组装). - * 该方法的具体实现根据数据库的链接类型不同有所不同. - * @param array $array - * @return string - * @see AbstractWindPdoAdapter::sqlSingle() - */ - public function sqlSingle($array) { - return $this->getDbHandle()->sqlSingle($array); - } - - /** - * 创建表,返回是否创建成功 - * - * 创建表并返回是否创建成功'$values'为字段信息.该方法的具体实现根据数据库的链接类型不同有所不同. - * @param string $tableName 表名称 - * @param array $values 字段值信息 - * @param boolean $replace 是否覆盖 - * @return boolean - * @see AbstractWindPdoAdapter::createTable() - */ - public function createTable($tableName, $values, $replace = false) { - return $this->getDbHandle()->createTable($tableName, $values, $replace); - } - - /** - * 返回最后一条插入的数据值,当传一个'name'给该方法,则返回'name'对应的列值 - * - * @param string $name 默认为空字符串 - * @return int - */ - public function lastInsertId($name = '') { - if ($name) - return $this->getDbHandle()->lastInsertId($name); - else - return $this->getDbHandle()->lastInsertId(); - } - - /** - * 关闭数据库连接 - * - * @return void - */ - public function close() { - $this->_dbHandle = null; - } - - /** - * 初始化DB句柄 - * - * @return void - * @throws WindDbException - */ - public function init() { - try { - if ($this->_dbHandle !== null) return; - $driverName = $this->getDriverName(); - $dbHandleClass = "WIND:db." . $driverName . ".Wind" . ucfirst($driverName) . "PdoAdapter"; - $dbHandleClass = Wind::import($dbHandleClass); - $this->_dbHandle = new $dbHandleClass($this->_dsn, $this->_user, $this->_pwd, (array) $this->_attributes); - $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - $this->_dbHandle->setCharset($this->_charset); - if (WIND_DEBUG & 2) Wind::getApp()->getComponent('windLogger')->info( - "[db.WindConnection.init] Initialize db connection success. \r\n\tDSN:" . $this->_dsn . "\r\n\tUser:" . $this->_user . "\r\n\tCharset:" . $this->_charset . "\r\n\tTablePrefix:" . $this->_tablePrefix . "\r\n\tDriverName:" . $this->_driverName, - 'db'); - } catch (PDOException $e) { - $this->close(); - throw new WindDbException($e->getMessage()); - } - } - - /** - * (non-PHPdoc) - * @see WindModule::setConfig() - */ - public function setConfig($config) { - parent::setConfig($config); - $this->_initConfig(); - $this->_attributes = array(); - } - - /** - * 根据配置信息,初始化当前连接对象 - * - * @param array $config 连接配置,默认为空数组 - */ - protected function _initConfig($config = array()) { - $this->_dsn = $this->getConfig('dsn', '', '', $config); - $this->_user = $this->getConfig('user', '', '', $config); - $this->_pwd = $this->getConfig('pwd', '', '', $config); - $this->_charset = $this->getConfig('charset', '', '', $config); - $this->_tablePrefix = $this->getConfig('tableprefix', '', '', $config); - } - - /** - * 解析当前查询语句,并返回解析后结果 - * - * @param string $sql - */ - protected function parseQueryString($sql) { - if ($_prefix = $this->getTablePrefix()) { - list($new, $old) = explode('|', $_prefix . '|'); - $sql = preg_replace('/{{(' . $old . ')?(.*?)}}/', $new . '\2', $sql); - } - return $sql; - } - - /** - * 获得表前缀 - * - * @return string $tablePrefix - */ - public function getTablePrefix() { - return $this->_tablePrefix; - } - - /** - * 设置表前缀 - * - * @param string $tablePrefix - */ - public function setTablePrefix($tablePrefix) { - $this->_tablePrefix = $tablePrefix; - } +class WindConnection extends WindModule +{ + /** + * 链接字符串,携带数据驱动类型,主机信息,库名等 + * + * mysql:host=localhost;dbname=test + * @var string + */ + protected $_dsn; + /** + * 驱动名 + * + * @var string + */ + protected $_driverName; + /** + * 用户名 + * + * @var string + */ + protected $_user; + /** + * 数据密码 + * + * @var string + */ + protected $_pwd; + /** + * 数据表前缀 + * + * @var string + */ + protected $_tablePrefix; + /** + * 数据连接编码方式 + * + * @var string + */ + protected $_charset; + /** + * 属性值 + * + * @var array + */ + protected $_attributes = array(); + /** + * 数据连接句柄 + * + * @var PDO + */ + protected $_dbHandle = null; + + /** + * @param string $dsn + * @param string $username + * @param string $password + */ + public function __construct($dsn = '', $username = '', $password = '') + { + $this->_dsn = $dsn; + $this->_user = $username; + $this->_pwd = $password; + } + + /** + * 接受一条sql语句,并返回sqlStatement对象 + * + * @param string $sql sql语句 + * @return WindSqlStatement + */ + public function createStatement($sql = null) + { + /* @var $statement WindSqlStatement */ + $statement = Wind::getComponent('sqlStatement'); + $statement->setConnection($this); + $statement->setQueryString($this->parseQueryString($sql)); + + return $statement; + } + + /** + * 返回数据库链接对象 + * + * @return AbstractWindPdoAdapter + */ + public function getDbHandle() + { + $this->init(); + + return $this->_dbHandle; + } + + /** + * 获得链接相关属性设置 + * + * @param string $attribute + * @return string + * */ + public function getAttribute($attribute) + { + if ($this->_dbHandle !== null) { + return $this->_dbHandle->getAttribute($attribute); + } else { + return isset($this->_attributes[$attribute]) ? $this->_attributes[$attribute] : ''; + } + } + + /** + * 设置链接相关属性 + * + * @param string $attribute + * @param string $value 默认值为null + */ + public function setAttribute($attribute, $value = null) + { + if (!$attribute) { + return; + } + if ($this->_dbHandle !== null) { + $this->_dbHandle->setAttribute($attribute, $value); + } else { + $this->_attributes[$attribute] = $value; + } + } + + /** + * 返回DB驱动类型 + * + * @return string + */ + public function getDriverName() + { + if ($this->_driverName) { + return $this->_driverName; + } + if ($this->_dbHandle !== null) { + $this->_driverName = $this->_dbHandle->getAttribute(PDO::ATTR_DRIVER_NAME); + } elseif (($pos = strpos($this->_dsn, ':')) !== false) { + $this->_driverName = strtolower(substr($this->_dsn, 0, $pos)); + } + + return $this->_driverName; + } + + /** + * 执行一条sql语句 同时返回影响行数 + * + * @param string $sql sql语句 + * @return int + */ + public function execute($sql) + { + try { + $statement = $this->createStatement($sql); + + return $statement->execute(); + } catch (PDOException $e) { + $this->close(); + throw new WindDbException('[db.WindConnection.execute] '.$e->getMessage()."\r\nSQL:$sql", WindDbException::DB_QUERY_ERROR); + } + } + + /** + * 执行一条查询同时返回结果集 + * @param string $sql sql语句 + * @return WindResultSet + */ + public function query($sql) + { + try { + $sql = $this->parseQueryString($sql); + + return new WindResultSet($this->getDbHandle()->query($sql)); + } catch (PDOException $e) { + throw new WindDbException('[db.WindConnection.query] '.$e->getMessage()."\r\nSQL:$sql", WindDbException::DB_QUERY_ERROR); + } + } + + /** + * 过滤SQL元数据,数据库对象(如表名字,字段等) + * + * @param string $data + * @throws WindDbException + */ + public function sqlMetadata($data) + { + return $this->getDbHandle()->fieldMeta($data); + } + + /** + * 过滤数组变量,将数组变量转换为字符串,并用逗号分隔每个数组元素支持多维数组 + * + * @param array $array + * @return string + */ + public function quoteArray($array) + { + return $this->getDbHandle()->quoteArray($array); + } + + /** + * 过滤二维数组将数组变量转换为多组的sql字符串 + * + * @param array $array + * @return string + */ + public function quoteMultiArray($array) + { + return $this->getDbHandle()->quoteMultiArray($array); + } + + /** + * sql元数据安全过滤,并返回过滤后值 + * + * @param string $string + * @return string + */ + public function quote($string) + { + return $this->getDbHandle()->quote($string); + } + + /** + * 过滤数组值并返回(insert/update)sql语句形式 + * + * 该方法接收一个数组变量,进行安全过滤,并返回组装单条 key=value 形式的SQL查询语句值 (适用于insert/update value值组装). + * 该方法的具体实现根据数据库的链接类型不同有所不同. + * @param array $array + * @return string + * @see AbstractWindPdoAdapter::sqlSingle() + */ + public function sqlSingle($array) + { + return $this->getDbHandle()->sqlSingle($array); + } + + /** + * 创建表,返回是否创建成功 + * + * 创建表并返回是否创建成功'$values'为字段信息.该方法的具体实现根据数据库的链接类型不同有所不同. + * @param string $tableName 表名称 + * @param array $values 字段值信息 + * @param bool $replace 是否覆盖 + * @return bool + * @see AbstractWindPdoAdapter::createTable() + */ + public function createTable($tableName, $values, $replace = false) + { + return $this->getDbHandle()->createTable($tableName, $values, $replace); + } + + /** + * 返回最后一条插入的数据值,当传一个'name'给该方法,则返回'name'对应的列值 + * + * @param string $name 默认为空字符串 + * @return int + */ + public function lastInsertId($name = '') + { + if ($name) { + return $this->getDbHandle()->lastInsertId($name); + } else { + return $this->getDbHandle()->lastInsertId(); + } + } + + /** + * 关闭数据库连接 + * + */ + public function close() + { + $this->_dbHandle = null; + } + + /** + * 初始化DB句柄 + * + * @throws WindDbException + */ + public function init() + { + try { + if ($this->_dbHandle !== null) { + return; + } + $driverName = $this->getDriverName(); + $dbHandleClass = 'WIND:db.'.$driverName.'.Wind'.ucfirst($driverName).'PdoAdapter'; + $dbHandleClass = Wind::import($dbHandleClass); + $this->_dbHandle = new $dbHandleClass($this->_dsn, $this->_user, $this->_pwd, (array) $this->_attributes); + $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + $this->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); + $this->_dbHandle->setCharset($this->_charset); + } catch (PDOException $e) { + $this->close(); + throw new WindDbException('[db.WindConnection.init] '.$e->getMessage()); + } + } + + /** + * (non-PHPdoc) + * @see WindModule::setConfig() + */ + public function setConfig($config) + { + parent::setConfig($config); + $this->_initConfig(); + $this->_attributes = array(); + } + + /** + * 根据配置信息,初始化当前连接对象 + * + * @param array $config 连接配置,默认为空数组 + */ + protected function _initConfig($config = array()) + { + $this->_dsn = $this->getConfig('dsn', '', '', $config); + $this->_user = $this->getConfig('user', '', '', $config); + $this->_pwd = $this->getConfig('pwd', '', '', $config); + $this->_charset = $this->getConfig('charset', '', '', $config); + $this->_tablePrefix = $this->getConfig('tableprefix', '', '', $config); + } + + /** + * 解析当前查询语句,并返回解析后结果 + * + * @param string $sql + */ + protected function parseQueryString($sql) + { + if ($_prefix = $this->getTablePrefix()) { + list($new, $old) = explode('|', $_prefix.'|'); + $sql = preg_replace('/{{('.$old.')?(.*?)}}/', $new.'\2', $sql); + } + + return $sql; + } + + /** + * 获得表前缀 + * + * @return string $tablePrefix + */ + public function getTablePrefix() + { + return $this->_tablePrefix; + } + + /** + * 设置表前缀 + * + * @param string $tablePrefix + */ + public function setTablePrefix($tablePrefix) + { + $this->_tablePrefix = $tablePrefix; + } } -?> \ No newline at end of file diff --git a/wind/db/WindConnectionManager.php b/wind/db/WindConnectionManager.php index 46344d2d..e952cd60 100644 --- a/wind/db/WindConnectionManager.php +++ b/wind/db/WindConnectionManager.php @@ -1,8 +1,8 @@ * 1. 当没有任何策略部署时 ,默认返回当前配置中的第一个链接句柄 * 2. 当没有任何策略部署时,如果在sql语句中有链接句柄指定时则返回指定的链接句柄 @@ -31,224 +31,239 @@ * @author Qiong Wu 2011-9-23 * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindConnectionManager.php 3904 2013-01-08 07:01:26Z yishuo $ * @package db */ -class WindConnectionManager extends WindConnection { - /** - * 通配符设置 - * - * @var string - */ - private $wildcard = '*'; - /** - * 数据链接池,临时保存当前所有数据库连接句柄 - * - * @var array - */ - private $pool = array(); - /** - * 当前数据表名称 - * - * @var string - */ - private $tableName; - /** - * 当前的sql语句查询类型 - * - * @var string - */ - private $sqlType; - /** - * 数据库连接池策略部署配置信息 - * - * @var array - */ - private $except = array('_current' => '', '_default' => array(), '_except' => array(), '_db' => array()); - - /** - * 是否强制主链接,默认为false - * - * @var boolean - */ - private $forceMaster = false; - - /* - * (non-PHPdoc) @see WindConnection::createStatement() - */ - public function createStatement($sql = null, $forceMaster = false) { - $this->forceMaster = $forceMaster; - return parent::createStatement($sql); - } - - /* - * (non-PHPdoc) @see WindConnection::getDbHandle() - */ - public function getDbHandle() { - $this->init(); - return $this->_dbHandle; - } - - /* - * (non-PHPdoc) @see WindConnection::init() - */ - public function init() { - try { - if (!isset($this->pool[$this->except['_current']])) { - $driverName = $this->getDriverName(); - $dbHandleClass = "WIND:db." . $driverName . ".Wind" . ucfirst($driverName) . "PdoAdapter"; - $dbHandleClass = Wind::import($dbHandleClass); - $_dbHandle = new $dbHandleClass($this->_dsn, $this->_user, $this->_pwd, - (array) $this->_attributes); - $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - $_dbHandle->setCharset($this->_charset); - $this->pool[$this->except['_current']] = $_dbHandle; - } - $this->_dbHandle = $this->pool[$this->except['_current']]; - if (WIND_DEBUG & 2) Wind::getApp()->getComponent('windLogger')->info( - "db.WindConnectionManager.init() Initialize db connection successful. use '" . $this->except['_current'] . "'", - 'db'); - } catch (PDOException $e) { - $this->close(); - throw new WindDbException($e->getMessage()); - } - } - - /* - * (non-PHPdoc) @see WindConnection::parseQueryString() - */ - protected function parseQueryString($sql) { - $sql = preg_replace_callback( - '/^([a-zA-Z]*)\s[\w\*\s]+(\{\{([\w]+\:)?([\w]+\.)?([\w]+)\}\})?[\w\s\<\=\:]*/i', - array($this, '_pregQueryString'), $sql); - if (!$this->except['_current']) { - if (!isset($this->except['_db'][$this->tableName])) { - foreach ((array) $this->except['_except'] as $value) { - preg_match('/' . str_replace($this->wildcard, '\w*', $value) . '/i', - $this->tableName, $matchs); - if (!empty($matchs)) { - $_c = $this->except['_db'][$value]; - break; - } - } - $_c || $_c = $this->except['_default']; - } else - $_c = $this->except['_db'][$this->tableName]; - $this->_resolveCurrentDb($_c); - } - if ($this->except['_current']) { - $_config = $this->getConfig($this->except['_current']); - if (!$_config) throw new WindDbException( - '[db.WindConnectionManager.parseQueryString] db connection ' . $this->except['_current'] . ' is not exist.'); - parent::_initConfig($_config); - } - return parent::parseQueryString($sql); - } - - /** - * 根据当前sql语句类型,从一条数据连接配置中解析出主从信息,并设置当前db链接名 - * - * @param array $_c - * @return void - */ - private function _resolveCurrentDb($_c) { - if (empty($_c) || empty($_c['_m'])) throw new WindDbException( - '[db.WindConnectionManager._resolveCurrentDb] db error.', - WindDbException::DB_BUILDER_NOT_EXIST); - - switch ($this->sqlType) { - case 'SELECT': - if (!$this->forceMaster && !empty($_c['_s'])) { - $_count = count($_c['_s']); - $_index = $_count > 1 ? mt_rand(0, $_count - 1) : 0; - $this->except['_current'] = $_c['_s'][$_index]; - break; - } - default: - $this->except['_current'] = $_c['_m']; - break; - } - } - - /** - * 解析sql语句 - * - * 解析sql语句,在sql语句中提取数据库连接信息,返回解析后的sql语句 - * Array( - * [0] => SELECT * FROM {db1:database.members} WHERE uid<=:uid | 匹配到的完整str - * [1] => SELECT | 当前的sql类型 - * [2] => {db1:database.members} | 当前table - * [3] => db1: | 当前table自定义链接 - * [4] => database. | 当前database - * [5] => members | 当前表名 - * ) - * - * @param array $matchs - * @return string - */ - private function _pregQueryString($matchs) { - $this->sqlType = $matchs[1]; - if (isset($matchs[2])) { - $this->tableName = $matchs[5]; - $this->except['_current'] = trim($matchs[3], ':'); - $matchs[0] = str_replace($matchs[3] . $matchs[4], '', $matchs[0]); - } else - $this->except['_current'] = $this->tableName = ''; - return $matchs[0]; - } - - /* - * (non-PHPdoc) @see WindConnection::_initConfig() - */ - protected function _initConfig() { - $_except = $this->getConfig('connections', 'except'); - unset($this->_config['connections']['except']); - $this->_config = $this->_config['connections']; - $_dbNames = array_keys($this->_config); - if (empty($_dbNames)) throw new WindDbException( - '[db.WindConnectionManager._initConfig] db config is required.'); - $this->_resetConnection($_dbNames[0]); - $this->except['_default']['_m'] = $_dbNames[0]; - if ($_except) preg_replace_callback('/([\w\*\,]+):([\w]+)\|*([\w\,]+)*/i', - array($this, '_pregExcept'), $_except); - } - - /** - * 重置链接信息 - * - * @param string $db - * @return void - */ - private function _resetConnection($db) { - $_config = $this->getConfig($db); - if (!$_config) throw new WindDbException( - '[db.WindConnectionManager._initConfig] db connection ' . $db . ' is not exist.'); - parent::_initConfig($_config); - } - - /** - * 解析链接管理链接策略 - * - * db链接管理配置信息如下:except='*:(db1);user*,tablename2:(db1|db2);' - * 一组'*:(db1);'代表一组数据配置,格式如:'tableName1,tableName2,tableName3:(db1|db2,db3,db4)'. - * 数据表名称与策略用':'隔开,':'前面表示一组数据表,可以是多个也可以是一个,多个表名用','隔开. - * ':'后面'()'中表示一组数据策略,例子中策略的意思是'db1'是主链接(master),'db2,db3,db4'为从属链接(slaves). - * 该方法解析这段数据库链接配置,并将解析结果存储到 'except' 属性中. - * - * @param array $matchs - * @return void - */ - private function _pregExcept($matchs) { - $_keys = explode(',', $matchs[1]); - foreach ($_keys as $_v) { - if ($_v === $this->wildcard) { - $this->except['_default']['_m'] = $matchs[2]; - $this->except['_default']['_s'] = isset($matchs[3]) ? explode(',', $matchs[3]) : array(); - break; - } - if (strpos($_v, $this->wildcard) !== false) $this->except['_except'][] = $_v; - $this->except['_db'][$_v]['_m'] = $matchs[2]; - $this->except['_db'][$_v]['_s'] = isset($matchs[3]) ? explode(',', $matchs[3]) : array(); - } - } -} \ No newline at end of file +class WindConnectionManager extends WindConnection +{ + /** + * 通配符设置 + * + * @var string + */ + private $wildcard = '*'; + /** + * 数据链接池,临时保存当前所有数据库连接句柄 + * + * @var array + */ + private $pool = array(); + /** + * 当前数据表名称 + * + * @var string + */ + private $tableName; + /** + * 当前的sql语句查询类型 + * + * @var string + */ + private $sqlType; + /** + * 数据库连接池策略部署配置信息 + * + * @var array + */ + private $except = array('_current' => '', '_default' => array(), '_except' => array(), '_db' => array()); + + /** + * 是否强制主链接,默认为false + * + * @var bool + */ + private $forceMaster = false; + + /* + * (non-PHPdoc) @see WindConnection::createStatement() + */ + public function createStatement($sql = null, $forceMaster = false) + { + $this->forceMaster = $forceMaster; + + return parent::createStatement($sql); + } + + /* + * (non-PHPdoc) @see WindConnection::getDbHandle() + */ + public function getDbHandle() + { + $this->init(); + + return $this->_dbHandle; + } + + /* + * (non-PHPdoc) @see WindConnection::init() + */ + public function init() + { + try { + if (!isset($this->pool[$this->except['_current']])) { + parent::init(); + $this->pool[$this->except['_current']] = $this->_dbHandle; + } else { + $this->_dbHandle = $this->pool[$this->except['_current']]; + } + } catch (PDOException $e) { + $this->close(); + throw new WindDbException('[db.WindConnectionManager.init] '.$e->getMessage()); + } + } + + /* + * (non-PHPdoc) @see WindConnection::parseQueryString() + */ + protected function parseQueryString($sql) + { + $sql = preg_replace_callback( + '/^([a-zA-Z]*)\s[\w\*\s]+(\{\{([\w]+\:)?([\w]+\.)?([\w]+)\}\})?[\w\s\<\=\:]*/i', + array($this, '_pregQueryString'), $sql); + if (!$this->except['_current']) { + if (!isset($this->except['_db'][$this->tableName])) { + foreach ((array) $this->except['_except'] as $value) { + preg_match('/'.str_replace($this->wildcard, '\w*', $value).'/i', + $this->tableName, $matchs); + if (!empty($matchs)) { + $_c = $this->except['_db'][$value]; + break; + } + } + $_c || $_c = $this->except['_default']; + } else { + $_c = $this->except['_db'][$this->tableName]; + } + $this->_resolveCurrentDb($_c); + } + if ($this->except['_current']) { + $_config = $this->getConfig($this->except['_current']); + if (!$_config) { + throw new WindDbException( + '[db.WindConnectionManager.parseQueryString] db connection '.$this->except['_current'].' is not exist.'); + } + parent::_initConfig($_config); + } + + return parent::parseQueryString($sql); + } + + /** + * 根据当前sql语句类型,从一条数据连接配置中解析出主从信息,并设置当前db链接名 + * + * @param array $_c + */ + private function _resolveCurrentDb($_c) + { + if (empty($_c) || empty($_c['_m'])) { + throw new WindDbException( + '[db.WindConnectionManager._resolveCurrentDb] db error.', + WindDbException::DB_BUILDER_NOT_EXIST); + } + + switch ($this->sqlType) { + case 'SELECT': + if (!$this->forceMaster && !empty($_c['_s'])) { + $_count = count($_c['_s']); + $_index = $_count > 1 ? mt_rand(0, $_count - 1) : 0; + $this->except['_current'] = $_c['_s'][$_index]; + break; + } + default: + $this->except['_current'] = $_c['_m']; + break; + } + } + + /** + * 解析sql语句 + * 解析sql语句,在sql语句中提取数据库连接信息,返回解析后的sql语句 + * Array( + * [0] => SELECT * FROM {db1:database.members} WHERE uid<=:uid | 匹配到的完整str + * [1] => SELECT | 当前的sql类型 + * [2] => {db1:database.members} | 当前table + * [3] => db1: | 当前table自定义链接 + * [4] => database. | 当前database + * [5] => members | 当前表名 + * ) + * + * @param array $matchs + * @return string + */ + private function _pregQueryString($matchs) + { + $this->sqlType = $matchs[1]; + if (isset($matchs[2])) { + $this->tableName = $matchs[5]; + $this->except['_current'] = trim($matchs[3], ':'); + $matchs[0] = str_replace($matchs[3].$matchs[4], '', $matchs[0]); + } else { + $this->except['_current'] = $this->tableName = ''; + } + + return $matchs[0]; + } + + /* + * (non-PHPdoc) @see WindConnection::_initConfig() + */ + protected function _initConfig() + { + $_except = $this->getConfig('connections', 'except'); + unset($this->_config['connections']['except']); + $this->_config = $this->_config['connections']; + $_dbNames = array_keys($this->_config); + if (empty($_dbNames)) { + throw new WindDbException( + '[db.WindConnectionManager._initConfig] db config is required.'); + } + $this->_resetConnection($_dbNames[0]); + $this->except['_default']['_m'] = $_dbNames[0]; + if ($_except) { + preg_replace_callback('/([\w\*\,]+):([\w]+)\|*([\w\,]+)*/i', + array($this, '_pregExcept'), $_except); + } + } + + /** + * 重置链接信息 + * + * @param string $db + */ + private function _resetConnection($db) + { + $_config = $this->getConfig($db); + if (!$_config) { + throw new WindDbException( + '[db.WindConnectionManager._initConfig] db connection '.$db.' is not exist.'); + } + parent::_initConfig($_config); + } + + /** + * 解析链接管理链接策略 + * db链接管理配置信息如下:except='*:(db1);user*,tablename2:(db1|db2);' + * 一组'*:(db1);'代表一组数据配置,格式如:'tableName1,tableName2,tableName3:(db1|db2,db3,db4)'. + * 数据表名称与策略用':'隔开,':'前面表示一组数据表,可以是多个也可以是一个,多个表名用','隔开. + * ':'后面'()'中表示一组数据策略,例子中策略的意思是'db1'是主链接(master),'db2,db3,db4'为从属链接(slaves). + * 该方法解析这段数据库链接配置,并将解析结果存储到 'except' 属性中. + * + * @param array $matchs + */ + private function _pregExcept($matchs) + { + $_keys = explode(',', $matchs[1]); + foreach ($_keys as $_v) { + if ($_v === $this->wildcard) { + $this->except['_default']['_m'] = $matchs[2]; + $this->except['_default']['_s'] = isset($matchs[3]) ? explode(',', $matchs[3]) : array(); + break; + } + if (strpos($_v, $this->wildcard) !== false) { + $this->except['_except'][] = $_v; + } + $this->except['_db'][$_v]['_m'] = $matchs[2]; + $this->except['_db'][$_v]['_s'] = isset($matchs[3]) ? explode(',', $matchs[3]) : array(); + } + } +} diff --git a/wind/db/WindResultSet.php b/wind/db/WindResultSet.php index c8b9507d..f63f109c 100644 --- a/wind/db/WindResultSet.php +++ b/wind/db/WindResultSet.php @@ -5,153 +5,194 @@ * @author Qiong Wu 2011-9-23 * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindResultSet.php 3829 2012-11-19 11:13:22Z yishuo $ * @package db */ -class WindResultSet { - /** - * @var PDOStatement - */ - private $_statement = null; - /** - * PDO fetchMode, default fetchMode PDO::FETCH_ASSOC - * - * @var number - */ - private $_fetchMode = PDO::FETCH_ASSOC; - /** - * PDO fetchType, default fetchType PDO::FETCH_ORI_FIRST - * - * @var number - */ - private $_fetchType = PDO::FETCH_ORI_FIRST; - private $_columns = array(); +class WindResultSet +{ + /** + * + * @var PDOStatement + */ + private $_statement = null; + /** + * PDO fetchMode, default fetchMode PDO::FETCH_ASSOC + * + * @var number + */ + private $_fetchMode = PDO::FETCH_ASSOC; + /** + * PDO fetchType, default fetchType PDO::FETCH_ORI_FIRST + * + * @var number + */ + private $_fetchType = PDO::FETCH_ORI_FIRST; + private $_columns = array(); - /** - * @param WindSqlStatement $sqlStatement 预处理对象 - * @param int $fetchMode 获得结果集的模式PDO::FETCH_BOTH/PDO::FETCH_ASSOC/PDO::FETCH_NUM - * @param int $fetchType 设置结果集的读取方式,PDO::FETCH_ORI_NEXT/PDO::FETCH_ORI_PRE,注意要使用该属性,必须通过setAttribute设置PDO::ATTR_CURSOR=PDO::CURSOR_SCROLL - */ - public function __construct($sqlStatement, $fetchMode = 0, $fetchType = 0) { - if ($sqlStatement instanceof WindSqlStatement) { - $this->_statement = $sqlStatement->getStatement(); - $this->_columns = $sqlStatement->getColumns(); - } else - $this->_statement = $sqlStatement; - if ($fetchMode != 0) $this->_fetchMode = $fetchMode; - if ($fetchType != 0) $this->_fetchType = $fetchType; - } + /** + * + * @param WindSqlStatement $sqlStatement + * 预处理对象 + * @param int $fetchMode + * 获得结果集的模式PDO::FETCH_BOTH/PDO::FETCH_ASSOC/PDO::FETCH_NUM + * @param int $fetchType + * 设置结果集的读取方式,PDO::FETCH_ORI_NEXT/PDO::FETCH_ORI_PRE,注意要使用该属性, + * 必须通过setAttribute设置PDO::ATTR_CURSOR=PDO::CURSOR_SCROLL + */ + public function __construct($sqlStatement, $fetchMode = 0, $fetchType = 0) + { + if ($sqlStatement instanceof WindSqlStatement) { + $this->_statement = $sqlStatement->getStatement(); + $this->_columns = $sqlStatement->getColumns(); + } else { + $this->_statement = $sqlStatement; + } + if ($fetchMode != 0) { + $this->_fetchMode = $fetchMode; + } + if ($fetchType != 0) { + $this->_fetchType = $fetchType; + } + } - /** - * 设置获取模式 - * - * @param int $fetchMode 设置获取的模式PDO::FETCH_BOTH/PDO::FETCH_ASSOC/PDO::FETCH_NUM... - * @param boolean $flush 是否统一设置所有PDOStatement中的获取方式 - */ - public function setFetchMode($fetchMode, $flush = false) { - $this->_fetchMode = $fetchMode; - if ($flush) { - $fetchMode = func_get_args(); - call_user_func_array(array($this->_statement, 'setFetchMode'), $fetchMode); - } - } + /** + * 设置获取模式 + * + * @param int $fetchMode + * 设置获取的模式PDO::FETCH_BOTH/PDO::FETCH_ASSOC/PDO::FETCH_NUM... + * @param bool $flush + * 是否统一设置所有PDOStatement中的获取方式 + */ + public function setFetchMode($fetchMode, $flush = false) + { + $this->_fetchMode = $fetchMode; + $flush && $this->_statement->setFetchMode($fetchMode); + } - /** - * 返回最后一条Sql语句的影响行数 - * - * @return int - */ - public function rowCount() { - return $this->_statement->rowCount(); - } + /** + * 返回最后一条Sql语句的影响行数 + * + * @return int + */ + public function rowCount() + { + return $this->_statement->rowCount(); + } - /** - * 返回结果集中的列数 - * - * @return number - */ - public function columnCount() { - return $this->_statement->columnCount(); - } + /** + * 返回结果集中的列数 + * + * @return number + */ + public function columnCount() + { + return $this->_statement->columnCount(); + } - /** - * 获得结果集的下一行 - * - * @param int $fetchMode 获得结果集的模式PDO::FETCH_BOTH/PDO::FETCH_ASSOC/PDO::FETCH_NUM - * @param int $fetchType 设置结果集的读取方式,PDO::FETCH_ORI_NEXT/PDO::FETCH_ORI_PRE,注意要使用该属性,设置Statement的属性设置PDO::ATTR_CURSOR=PDO::CURSOR_SCROLL - * @return array - */ - public function fetch($fetchMode = 0, $fetchType = 0) { - if ($fetchMode === 0) $fetchMode = $this->_fetchMode; - if ($fetchType === 0) $fetchType = $this->_fetchType; - return $this->_fetch($fetchMode, $fetchType); - } + /** + * 获得结果集的下一行 + * + * @param int $fetchMode + * 获得结果集的模式PDO::FETCH_BOTH/PDO::FETCH_ASSOC/PDO::FETCH_NUM + * @param int $fetchType + * 设置结果集的读取方式,PDO::FETCH_ORI_NEXT/PDO::FETCH_ORI_PRE,注意要使用该属性, + * 设置Statement的属性设置PDO::ATTR_CURSOR=PDO::CURSOR_SCROLL + * @return array + */ + public function fetch($fetchMode = 0, $fetchType = 0) + { + if ($fetchMode === 0) { + $fetchMode = $this->_fetchMode; + } + if ($fetchType === 0) { + $fetchType = $this->_fetchType; + } - /** - * @param string $fetchMode - * @param string $fetchType - */ - private function _fetch($fetchMode, $fetchType) { - if (!empty($this->_columns)) $fetchMode = PDO::FETCH_BOUND; - $result = array(); - if ($row = $this->_statement->fetch($fetchMode, $fetchType)) { - if (empty($this->_columns)) - $result = $row; - else - foreach ($this->_columns as $key => $value) { - $result[$key] = $value; - } - } - return $result; - } + return $this->_fetch($fetchMode, $fetchType); + } - /** - * 返回所有的查询结果 - * - * @param string $index 输出数组下标 - * @param int $fetchMode 获得结果集的模式PDO::FETCH_BOTH/PDO::FETCH_ASSOC/PDO::FETCH_NUM - * @return array - */ - public function fetchAll($index = '', $fetchMode = 0) { - if ($fetchMode === 0) $fetchMode = $this->_fetchMode; - $result = array(); - if (!$index) - while ($row = $this->fetch($fetchMode)) - $result[] = $row; - else - while ($row = $this->fetch($fetchMode)) { - if (!isset($row[$index])) continue; - $result[$row[$index]] = $row; - } - return $result; - } + /** + * + * @param string $fetchMode + * @param string $fetchType + */ + private function _fetch($fetchMode, $fetchType) + { + if (!empty($this->_columns)) { + $fetchMode = PDO::FETCH_BOUND; + } + $result = array(); + if ($row = $this->_statement->fetch($fetchMode, $fetchType)) { + if (empty($this->_columns)) { + $result = $row; + } else { + foreach ($this->_columns as $key => $value) { + $result[$key] = $value; + } + } + } - /** - * 从下一行记录中获得下标是$index的值,如果获取失败则返回false - * - * @param int $index 列下标 - * @return string|bool - */ - public function fetchColumn($index = 0) { - $result = $this->_statement->fetchColumn($index); - if (WIND_DEBUG & 2) Wind::getApp()->getComponent('windLogger')->info( - "[component.db.WindResultSet.fetchColumn] \r\n\tResult:" . WindString::varToString( - $result)); - return $result; - } + return $result; + } - /** - * 获得结果集中的下一行,同时根据设置的类返回如果没有设置则返回的使StdClass对象 - * - * @param string $className 使用的类 - * @param array $ctor_args 初始化参数 - * @return object - */ - public function fetchObject($className = '', $ctor_args = array()) { - if ($className === '') - return $this->_statement->fetchObject(); - else - return $this->_statement->fetchObject($className, $ctor_args); - } + /** + * 返回所有的查询结果 + * + * @param string $index + * 输出数组下标 + * @param int $fetchMode + * 获得结果集的模式PDO::FETCH_BOTH/PDO::FETCH_ASSOC/PDO::FETCH_NUM + * @return array + */ + public function fetchAll($index = '', $fetchMode = 0) + { + if ($fetchMode === 0) { + $fetchMode = $this->_fetchMode; + } + $result = array(); + if (!$index) { + while ($row = $this->fetch($fetchMode)) { + $result[] = $row; + } + } else { + while ($row = $this->fetch($fetchMode)) { + if (!isset($row[$index])) { + continue; + } + $result[$row[$index]] = $row; + } + } + + return $result; + } + + /** + * 从下一行记录中获得下标是$index的值,如果获取失败则返回false + * + * @param int $index + * 列下标 + * @return string bool + */ + public function fetchColumn($index = 0) + { + return $this->_statement->fetchColumn($index); + } + + /** + * 获得结果集中的下一行,同时根据设置的类返回如果没有设置则返回的使StdClass对象 + * + * @param string $className + * 使用的类 + * @param array $ctor_args + * 初始化参数 + * @return object + */ + public function fetchObject($className = '', $ctor_args = array()) + { + if ($className === '') { + return $this->_statement->fetchObject(); + } else { + return $this->_statement->fetchObject($className, $ctor_args); + } + } } -?> \ No newline at end of file diff --git a/wind/db/WindSqlStatement.php b/wind/db/WindSqlStatement.php index da5007f6..e2131922 100644 --- a/wind/db/WindSqlStatement.php +++ b/wind/db/WindSqlStatement.php @@ -1,363 +1,412 @@ 2011-9-23 * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindSqlStatement.php 3904 2013-01-08 07:01:26Z yishuo $ * @package db */ -class WindSqlStatement { - /** - * @var WindConnection - */ - private $_connection; - /** - * @var PDOStatement - */ - private $_statement = null; - /** - * @var string - */ - private $_queryString; - /** - * PDO类型映射 - * - * @var array - */ - private $_typeMap = array( - 'boolean' => PDO::PARAM_BOOL, - 'integer' => PDO::PARAM_INT, - 'string' => PDO::PARAM_STR, - 'NULL' => PDO::PARAM_NULL); - /** - * @var array - */ - private $_columns = array(); - - /** - * @param WindConnection $connection WindConnection对象 - * @param string $query 预定义语句 - */ - public function __construct($connection, $query) { - $this->_connection = $connection; - $this->_queryString = $query; - } - - /** - * 参数绑定 - * - * @param mixed $parameter 预定义语句的待绑定的位置 - * @param mixed &$variable 绑定的值 - * @param int $dataType 值的类型(PDO::PARAM_STR/PDO::PARAM_INT...) - * @param int $length 绑定值的长度 - * @param mixed $driverOptions - * @return WindSqlStatement - * @see PDOStatement::bindParam() - * @throws WindDbException - */ - public function bindParam($parameter, &$variable, $dataType = null, $length = null, $driverOptions = null) { - try { - $this->init(); - if ($dataType === null) { - $dataType = $this->_getPdoDataType($variable); - } - if ($length === null) - $this->getStatement()->bindParam($parameter, $variable, $dataType); - else - $this->getStatement()->bindParam($parameter, $variable, $dataType, $length, $driverOptions); - return $this; - } catch (PDOException $e) { - throw new WindDbException($e->getMessage()); - } - } - - /** - * 批量绑定变量 - * - * 如果是一维数组,则使用key=>value的形式,key代表变量位置,value代表替换的值,而替换值需要的类型则通过该值的类型来判断---不准确 - * 如果是一个二维数组,则允许,key=>array(0=>value, 1=>data_type, 2=>length, 3=>driver_options)的方式来传递变量。 - * - * @param array $parameters - * @return WindSqlStatement - * @see PDOStatement::bindParam() - * @throws WindDbException - */ - public function bindParams(&$parameters) { - if (!is_array($parameters)) throw new WindDbException( - '[component.db.WindSqlStatement.bindParams] Error unexpected paraments type ' . gettype($parameters)); - - $keied = (array_keys($parameters) !== range(0, sizeof($parameters) - 1)); - foreach ($parameters as $key => $value) { - $_key = $keied ? $key : $key + 1; - if (is_array($value)) { - $dataType = isset($value[1]) ? $value[1] : $this->_getPdoDataType($value[0]); - $length = isset($value[2]) ? $value[2] : null; - $driverOptions = isset($value[3]) ? $value[3] : null; - $this->bindParam($_key, $parameters[$key][0], $dataType, $length, $driverOptions); - } else - $this->bindParam($_key, $parameters[$key], $this->_getPdoDataType($value)); - } - return $this; - } - - /** - * 参数绑定 - * - * @param string $parameter 预定义语句的待绑定的位置 - * @param string $value 绑定的值 - * @param int $data_type 值的类型 - * @return WindSqlStatement - * @see PDOStatement::bindValue() - * @throws WindDbException - */ - public function bindValue($parameter, $value, $data_type = null) { - try { - $this->init(); - if ($data_type === null) $data_type = $this->_getPdoDataType($value); - $this->getStatement()->bindValue($parameter, $value, $data_type); - return $this; - } catch (PDOException $e) { - throw new WindDbException($e->getMessage()); - } - } - - /** - * 调用bindValue的批量绑定参数 - * - * @param array $values 待绑定的参数值 - * @return WindSqlStatement - * @see PDOStatement::bindValue() - * @throws WindDbException - */ - public function bindValues($values) { - if (!is_array($values)) throw new WindDbException( - '[component.db.WindSqlStatement.bindValues] Error unexpected paraments type \'' . gettype($values) . '\''); - - $keied = (array_keys($values) !== range(0, sizeof($values) - 1)); - foreach ($values as $key => $value) { - if (!$keied) $key = $key + 1; - $this->bindValue($key, $value, $this->_getPdoDataType($value)); - } - return $this; - } - - /** - * 绑定输出结果集的列到PHP变量 - * - * @param mixed $column 需要被绑定的字段列表,可以是字段名,也可以是字段的对应的下标 - * @param mixed &$param 需要被绑定的php变量 - * @param int $type 参数的数据类型 PDO::PARAM_* - * @param int $maxlen A hint for pre-allocation. - * @param mixed $driverdata Optional parameter(s) for the driver. - * @return WindSqlStatement - * @see PDOStatement::bindColumn() - * @throws WindDbException - */ - public function bindColumn($column, &$param = '', $type = null, $maxlen = null, $driverdata = null) { - try { - $this->init(); - if ($type == null) $type = $this->_getPdoDataType($param); - if ($type == null) - $this->getStatement()->bindColumn($column, $param); - elseif ($maxlen == null) - $this->getStatement()->bindColumn($column, $param, $type); - else - $this->getStatement()->bindColumn($column, $param, $type, $maxlen, $driverdata); - $this->_columns[$column] = & $param; - return $this; - } catch (PDOException $e) { - throw new WindDbException($e->getMessage()); - } - } - - /** - * 批量绑定输出结果集的列到PHP变量 - * - * @param array $columns 待绑定的列 - * @param array &$param 需要绑定的php变量 - * @see PDOStatement::bindColumn() - * @return WindSqlStatement - */ - public function bindColumns($columns, &$param = array()) { - $int = 0; - foreach ($columns as $value) { - $this->bindColumn($value, $param[$int++]); - } - return $this; - } - - /** - * 绑定参数,执行SQL语句,并返回更新影响行数 - * - * @param array $params 预定义语句中需要绑定的参数 - * @param boolean $rowCount 是否返回影响行数 - * @return int|boolean - * @throws WindDbException - */ - public function update($params = array(), $rowCount = false) { - return $this->execute($params, $rowCount); - } - - /** - * 绑定参数,执行SQL语句,并返回查询结果 - * - * @param array $params 预定义语句中需要绑定的参数 - * @param int $fetchMode 获得结果集的模式PDO::FETCH_BOTH/PDO::FETCH_ASSOC/PDO::FETCH_NUM - * @param int $fetchType 设置结果集的读取方式,PDO::FETCH_ORI_NEXT/PDO::FETCH_ORI_PRE,注意要使用该属性,必须通过setAttribute设置PDO::ATTR_CURSOR=PDO::CURSOR_SCROLL - * @return WindResultSet - */ - public function query($params = array(), $fetchMode = 0, $fetchType = 0) { - $this->execute($params, false); - return new WindResultSet($this, $fetchMode, $fetchType); - } - - /** - * 绑定参数,执行SQL语句,并返回查询结果 - * - * @param array $params 预定义语句中需要绑定的参数 - * @param string $index 返回的数组的下标对应的字段 - * @param int $fetchMode 获得结果集的模式PDO::FETCH_BOTH/PDO::FETCH_ASSOC/PDO::FETCH_NUM - * @param int $fetchType 设置结果集的读取方式,PDO::FETCH_ORI_NEXT/PDO::FETCH_ORI_PRE,注意要使用该属性,必须通过setAttribute设置PDO::ATTR_CURSOR=PDO::CURSOR_SCROLL - * @return array 返回处理后的结果 - */ - public function queryAll($params = array(), $index = '', $fetchMode = 0, $fetchType = 0) { - $this->execute($params, false); - $rs = new WindResultSet($this, $fetchMode, $fetchType); - return $rs->fetchAll($index); - } - - /** - * 绑定参数,执行SQL语句,并返回查询到的结果集中某一个列的值 - * - * @param array $params 预定义语句中需要绑定的参数 - * @param int $column 列的下标,默认为0即第一列 - * @return string - */ - public function getValue($params = array(), $column = 0) { - $this->execute($params, false); - $rs = new WindResultSet($this, PDO::FETCH_NUM, 0); - return $rs->fetchColumn($column); - } - - /** - * 绑定参数,执行SQL语句,并返回一行查询结果 - * - * @param array $params 预定义语句中需要绑定的参数 - * @param int $fetchMode 获得结果集的模式PDO::FETCH_BOTH/PDO::FETCH_ASSOC/PDO::FETCH_NUM - * @param int $fetchType 设置结果集的读取方式,PDO::FETCH_ORI_NEXT/PDO::FETCH_ORI_PRE,注意要使用该属性,必须通过setAttribute设置PDO::ATTR_CURSOR=PDO::CURSOR_SCROLL - * @return array - */ - public function getOne($params = array(), $fetchMode = 0, $fetchType = 0) { - $this->execute($params, false); - $rs = new WindResultSet($this, $fetchMode, $fetchType); - return $rs->fetch(); - } - - /* (non-PHPdoc) - * @see WindConnection::lastInsterId() - */ - public function lastInsertId($name = '') { - return $this->getConnection()->lastInsertId($name); - } - - /** - * 绑定参数,执行SQL语句,并返回影响行数 - * - * @param array $params -- 绑定的参数和bindValues的参数一样 - * @param boolean $rowCount 是否返回受印象行数 - * @return rowCount - */ - public function execute($params = array(), $rowCount = true) { - try { - if (WIND_DEBUG & 2) { - Wind::getApp()->getComponent('windLogger')->profileBegin('SQL:execute sql statement.', 'db'); - Wind::getApp()->getComponent('windLogger')->info( - "[component.db.WindSqlStatement.execute] \r\n\tSQL:" . $this->getQueryString(), 'db'); - } - $this->init(); - $this->bindValues($params); - $this->getStatement()->execute(); - $_result = $rowCount ? $this->getStatement()->rowCount() : true; - if (WIND_DEBUG & 2) { - Wind::getApp()->getComponent('windLogger')->profileEnd('SQL:execute sql statement.', 'db'); - Wind::getApp()->getComponent('windLogger')->info( - "[component.db.WindSqlStatement.execute] execute sql statement success.\r\n", 'db'); - } - return $_result; - } catch (PDOException $e) { - throw new WindDbException('[component.db.WindSqlStatement.execute]' . $e->getMessage()); - } - } - - /** - * 获得查询的预定义语句 - * - * @return string - */ - public function getQueryString() { - return $this->_queryString; - } - - /** - * 获得PDO链接对象 - * - * @return WindConnection - */ - public function getConnection() { - return $this->_connection; - } - - /** - * 获得PDOStatement对象 - * - * @return PDOStatement - */ - public function getStatement() { - return $this->_statement; - } - - /** - * 获得需要绑定的结果输出的列值 - * - * @return array - */ - public function getColumns() { - return $this->_columns; - } - - /** - * 初始化数据库链接信息 - * - * @return void - * @throws WindDbException - */ - public function init() { - if ($this->_statement === null) { - try { - $this->_statement = $this->getConnection()->getDbHandle()->prepare($this->getQueryString()); - if (WIND_DEBUG & 2) Wind::getApp()->getComponent('windLogger')->info( - "[component.db.WindSqlStatement.init] Initialize statement success.", 'db'); - } catch (PDOException $e) { - throw new WindDbException("Initialization WindSqlStatement failed." . $e->getMessage()); - } - } - } - - /** - * 获得绑定参数的类型 - * - * @param string $variable - * @return int - */ - private function _getPdoDataType($variable) { - return isset($this->_typeMap[gettype($variable)]) ? $this->_typeMap[gettype($variable)] : PDO::PARAM_STR; - } +class WindSqlStatement +{ + /** + * @var WindConnection + */ + private $_connection; + /** + * @var PDOStatement + */ + private $_statement = null; + /** + * @var string + */ + private $_queryString; + /** + * PDO类型映射 + * + * @var array + */ + private $_typeMap = array( + 'boolean' => PDO::PARAM_BOOL, + 'integer' => PDO::PARAM_INT, + 'string' => PDO::PARAM_STR, + 'NULL' => PDO::PARAM_NULL, ); + /** + * @var array + */ + private $_columns = array(); + /** + * @var array + */ + private $_param = array(); + + /** + * @param WindConnection $connection WindConnection对象 + * @param string $query 预定义语句 + */ + public function __construct($connection = null, $query = '') + { + $connection && $this->_connection = $connection; + $query && $this->setQueryString($query); + } + + /** + * 参数绑定 + * + * @param mixed $parameter 预定义语句的待绑定的位置 + * @param mixed &$variable 绑定的值 + * @param int $dataType 值的类型(PDO::PARAM_STR/PDO::PARAM_INT...) + * @param int $length 绑定值的长度 + * @param mixed $driverOptions + * @return WindSqlStatement + * @see PDOStatement::bindParam() + * @throws WindDbException + */ + public function bindParam($parameter, &$variable, $dataType = null, $length = null, $driverOptions = null) + { + try { + if ($dataType === null) { + $dataType = $this->_getPdoDataType($variable); + } + if ($length === null) { + $this->getStatement()->bindParam($parameter, $variable, $dataType); + } else { + $this->getStatement()->bindParam($parameter, $variable, $dataType, $length, $driverOptions); + } + $this->_param[$parameter] = $variable; + + return $this; + } catch (PDOException $e) { + throw new WindDbException('[db.WindSqlStatement.bindParam] '.$e->getMessage()); + } + } + + /** + * 批量绑定变量 + * + * 如果是一维数组,则使用key=>value的形式,key代表变量位置,value代表替换的值,而替换值需要的类型则通过该值的类型来判断---不准确 + * 如果是一个二维数组,则允许,key=>array(0=>value, 1=>data_type, 2=>length, 3=>driver_options)的方式来传递变量。 + * + * @param array $parameters + * @return WindSqlStatement + * @see PDOStatement::bindParam() + * @throws WindDbException + */ + public function bindParams(&$parameters) + { + if (!is_array($parameters)) { + throw new WindDbException( + '[db.WindSqlStatement.bindParams] Error unexpected paraments type '.gettype($parameters)); + } + + $keied = (array_keys($parameters) !== range(0, count($parameters) - 1)); + foreach ($parameters as $key => $value) { + $_key = $keied ? $key : $key + 1; + if (is_array($value)) { + $dataType = isset($value[1]) ? $value[1] : $this->_getPdoDataType($value[0]); + $length = isset($value[2]) ? $value[2] : null; + $driverOptions = isset($value[3]) ? $value[3] : null; + $this->bindParam($_key, $parameters[$key][0], $dataType, $length, $driverOptions); + } else { + $this->bindParam($_key, $parameters[$key], $this->_getPdoDataType($value)); + } + } + + return $this; + } + + /** + * 参数绑定 + * + * @param string $parameter 预定义语句的待绑定的位置 + * @param string $value 绑定的值 + * @param int $data_type 值的类型 + * @return WindSqlStatement + * @see PDOStatement::bindValue() + * @throws WindDbException + */ + public function bindValue($parameter, $value, $data_type = null) + { + try { + if ($data_type === null) { + $data_type = $this->_getPdoDataType($value); + } + $this->getStatement()->bindValue($parameter, $value, $data_type); + $this->_param[$parameter] = $value; + + return $this; + } catch (PDOException $e) { + throw new WindDbException('[db.WindSqlStatement.bindValue] '.$e->getMessage()); + } + } + + /** + * 调用bindValue的批量绑定参数 + * + * @param array $values 待绑定的参数值 + * @return WindSqlStatement + * @see PDOStatement::bindValue() + * @throws WindDbException + */ + public function bindValues($values) + { + if (!is_array($values)) { + throw new WindDbException( + '[db.WindSqlStatement.bindValues] Error unexpected paraments type \''.gettype($values).'\''); + } + + $keied = (array_keys($values) !== range(0, count($values) - 1)); + foreach ($values as $key => $value) { + if (!$keied) { + $key = $key + 1; + } + $this->bindValue($key, $value, $this->_getPdoDataType($value)); + } + + return $this; + } + + /** + * 绑定输出结果集的列到PHP变量 + * + * @param mixed $column 需要被绑定的字段列表,可以是字段名,也可以是字段的对应的下标 + * @param mixed &$param 需要被绑定的php变量 + * @param int $type 参数的数据类型 PDO::PARAM_* + * @param int $maxlen A hint for pre-allocation. + * @param mixed $driverdata Optional parameter(s) for the driver. + * @return WindSqlStatement + * @see PDOStatement::bindColumn() + * @throws WindDbException + */ + public function bindColumn($column, &$param = '', $type = null, $maxlen = null, $driverdata = null) + { + try { + if ($type == null) { + $type = $this->_getPdoDataType($param); + } + if ($type == null) { + $this->getStatement()->bindColumn($column, $param); + } elseif ($maxlen == null) { + $this->getStatement()->bindColumn($column, $param, $type); + } else { + $this->getStatement()->bindColumn($column, $param, $type, $maxlen, $driverdata); + } + $this->_columns[$column] = & $param; + + return $this; + } catch (PDOException $e) { + throw new WindDbException('[db.WindSqlStatement.bindColumn] '.$e->getMessage()); + } + } + + /** + * 批量绑定输出结果集的列到PHP变量 + * + * @param array $columns 待绑定的列 + * @param array &$param 需要绑定的php变量 + * @see PDOStatement::bindColumn() + * @return WindSqlStatement + */ + public function bindColumns($columns, &$param = array()) + { + $int = 0; + foreach ($columns as $value) { + $this->bindColumn($value, $param[$int++]); + } + + return $this; + } + + /** + * 绑定参数,执行SQL语句,并返回更新影响行数 + * + * @param array $params 预定义语句中需要绑定的参数 + * @param bool $rowCount 是否返回影响行数 + * @return int|bool + * @throws WindDbException + */ + public function update($params = array(), $rowCount = false) + { + return $this->execute($params, $rowCount); + } + + /** + * 绑定参数,执行SQL语句,并返回查询结果 + * + * @param array $params 预定义语句中需要绑定的参数 + * @param int $fetchMode 获得结果集的模式PDO::FETCH_BOTH/PDO::FETCH_ASSOC/PDO::FETCH_NUM + * @param int $fetchType 设置结果集的读取方式,PDO::FETCH_ORI_NEXT/PDO::FETCH_ORI_PRE,注意要使用该属性,必须通过setAttribute设置PDO::ATTR_CURSOR=PDO::CURSOR_SCROLL + * @return WindResultSet + */ + public function query($params = array(), $fetchMode = 0, $fetchType = 0) + { + $this->execute($params, false); + + return new WindResultSet($this, $fetchMode, $fetchType); + } + + /** + * 绑定参数,执行SQL语句,并返回查询结果 + * + * @param array $params 预定义语句中需要绑定的参数 + * @param string $index 返回的数组的下标对应的字段 + * @param int $fetchMode 获得结果集的模式PDO::FETCH_BOTH/PDO::FETCH_ASSOC/PDO::FETCH_NUM + * @param int $fetchType 设置结果集的读取方式,PDO::FETCH_ORI_NEXT/PDO::FETCH_ORI_PRE,注意要使用该属性,必须通过setAttribute设置PDO::ATTR_CURSOR=PDO::CURSOR_SCROLL + * @return array 返回处理后的结果 + */ + public function queryAll($params = array(), $index = '', $fetchMode = 0, $fetchType = 0) + { + $this->execute($params, false); + $rs = new WindResultSet($this, $fetchMode, $fetchType); + + return $rs->fetchAll($index); + } + + /** + * 绑定参数,执行SQL语句,并返回查询到的结果集中某一个列的值 + * + * @param array $params 预定义语句中需要绑定的参数 + * @param int $column 列的下标,默认为0即第一列 + * @return string + */ + public function getValue($params = array(), $column = 0) + { + $this->execute($params, false); + $rs = new WindResultSet($this, PDO::FETCH_NUM, 0); + + return $rs->fetchColumn($column); + } + + /** + * 绑定参数,执行SQL语句,并返回一行查询结果 + * + * @param array $params 预定义语句中需要绑定的参数 + * @param int $fetchMode 获得结果集的模式PDO::FETCH_BOTH/PDO::FETCH_ASSOC/PDO::FETCH_NUM + * @param int $fetchType 设置结果集的读取方式,PDO::FETCH_ORI_NEXT/PDO::FETCH_ORI_PRE,注意要使用该属性,必须通过setAttribute设置PDO::ATTR_CURSOR=PDO::CURSOR_SCROLL + * @return array + */ + public function getOne($params = array(), $fetchMode = 0, $fetchType = 0) + { + $this->execute($params, false); + $rs = new WindResultSet($this, $fetchMode, $fetchType); + + return $rs->fetch(); + } + + /* (non-PHPdoc) + * @see WindConnection::lastInsterId() + */ + public function lastInsertId($name = '') + { + return $this->getConnection()->lastInsertId($name); + } + + /** + * 绑定参数,执行SQL语句,并返回影响行数 + * + * @param array $params -- 绑定的参数和bindValues的参数一样 + * @param bool $rowCount 是否返回受印象行数 + * @return rowCount + */ + public function execute($params = array(), $rowCount = true) + { + try { + $this->bindValues($params); + $this->getStatement()->execute(); + $_result = $rowCount ? $this->getStatement()->rowCount() : true; + + return $_result; + } catch (PDOException $e) { + throw new WindDbException('[db.WindSqlStatement.execute] '.$e->getMessage()."\r\nSQL:".$this->getQueryString()); + } + } + + /** + * @param string $sql + */ + public function setQueryString($sql) + { + try { + $this->_queryString = $sql; + $this->_statement = $this->getConnection()->getDbHandle()->prepare($sql); + } catch (PDOException $e) { + throw new WindDbException('[db.WindSqlStatement.setQueryString] Initialization WindSqlStatement failed.'.$e->getMessage()); + } + } + + /** + * 获得查询的预定义语句 + * + * @return string + */ + public function getQueryString() + { + return $this->_queryString; + } + + /** + * @param WindConnection $connection + */ + public function setConnection($connection) + { + $this->_connection = $connection; + } + + /** + * 获得PDO链接对象 + * + * @return WindConnection + */ + public function getConnection() + { + return $this->_connection; + } + + /** + * 获得PDOStatement对象 + * + * @return PDOStatement + */ + public function getStatement() + { + return $this->_statement; + } + + /** + * 获取参数绑定列表 + * + * @return array + */ + public function getParams() + { + return $this->_param; + } + + /** + * 获得需要绑定的结果输出的列值 + * + * @return array + */ + public function getColumns() + { + return $this->_columns; + } + + /** + * 获得绑定参数的类型 + * + * @param string $variable + * @return int + */ + private function _getPdoDataType($variable) + { + return isset($this->_typeMap[gettype($variable)]) ? $this->_typeMap[gettype($variable)] : PDO::PARAM_STR; + } } -?> \ No newline at end of file diff --git a/wind/db/exception/WindDbException.php b/wind/db/exception/WindDbException.php index d3c0ae2e..1e493354 100644 --- a/wind/db/exception/WindDbException.php +++ b/wind/db/exception/WindDbException.php @@ -1,123 +1,125 @@ 2011-9-22 * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindDbException.php 3871 2012-12-25 07:14:59Z yishuo $ * @package db * @subpackage exception */ -class WindDbException extends WindException { - /** - * 连接相关的异常 - */ - const DB_CONN_EMPTY = 200; - - const DB_CONN_FORMAT = 201; - - const DB_CONN_NOT_EXIST = 202; - - const DB_CONN_EXIST = 203; - - const DB_CONNECT_NOT_EXIST = 204; - - /** - * 查讯 相关的异常 - */ - const DB_QUERY_EMPTY = 210; - - const DB_QUERY_LINK_EMPTY = 211; - - const DB_QUERY_FIELD_EMPTY = 212; - - const DB_QUERY_FIELD_EXIST = 213; - - const DB_QUERY_FIELD_FORMAT = 214; - - const DB_QUERY_INSERT_DATA = 215; - - const DB_QUERY_UPDATE_DATA = 216; - - const DB_QUERY_CONDTTION_FORMAT = 217; - - const DB_QUERY_GROUP_MATCH = 218; - - const DB_QUERY_LOGIC_MATCH = 219; - - const DB_QUERY_FETCH_ERROR = 220; - - const DB_QUERY_TRAN_BEGIN = 221; - - const DB_QUERY_COMPARESS_ERROR = 222; - - const DB_QUERY_COMPARESS_EXIST = 223; - - const DB_QUERY_WHERE_ERROR = 224; - - const DB_QUERY_JOIN_TYPE_ERROR = 225; - - const DB_QUERY_ERROR = 226; - - /** - * 字段异常 - */ - const DB_TABLE_EMPTY = 240; - - const DB_EMPTY = 241; - - const DB_DRIVER_NOT_EXIST = 242; - - const DB_DRIVER_EXIST = 243; - - const DB_BUILDER_NOT_EXIST = 250; - - const DB_BUILDER_EXIST = 251; - - const DB_DRIVER_BUILDER_NOT_MATCH = 252; - - const DB_ADAPTER_NOT_EXIST = 260; - - const DB_ADAPTER_EXIST = 261; - - /* (non-PHPdoc) - * @see WindException::messageMapper() - */ - protected function messageMapper($code) { - $messages = array( - self::DB_CONN_EMPTY => 'Database configuration is empty. \'$message\' ', - self::DB_CONN_FORMAT => 'Database configuration format is incorrect. \'$message\' ', - self::DB_CONN_NOT_EXIST => '\'$message\' The identify of the database connection does not exist. ', - self::DB_CONN_EXIST => '\'$message\' The identify of the database connection is aleady exist.', - self::DB_CONNECT_NOT_EXIST => '\'$message\' The database connection does not exist.', - self::DB_QUERY_EMPTY => 'Query is empty. \'$message\'', - self::DB_QUERY_LINK_EMPTY => '\'$message\' Query link is not a validate resource.', - self::DB_QUERY_FIELD_EMPTY => '\'$message\' Query field is empty.', - self::DB_QUERY_FIELD_EXIST => '\'$message\' Query field is not exist.', - self::DB_QUERY_FIELD_FORMAT => 'Inside the field in the query not formatted correctly. \'$message\'', - self::DB_QUERY_INSERT_DATA => 'The new data is empty. \'$message\'', - self::DB_QUERY_UPDATE_DATA => 'The Updated data is empty. \'$message\'', - self::DB_QUERY_CONDTTION_FORMAT => 'The conditions of query are not right. \'$message\'', - self::DB_QUERY_GROUP_MATCH => '\'$message\' Query group does not match.', - self::DB_QUERY_LOGIC_MATCH => '\'$message\' Query logic does not match.', - self::DB_QUERY_FETCH_ERROR => 'The wrong way to obtain the result set. \'$message\'', - self::DB_QUERY_TRAN_BEGIN => 'Transaction has not started. \'$message\'', - self::DB_QUERY_COMPARESS_ERROR => 'Query comparison is incorrect conversion or assembly. \'$message\'', - self::DB_QUERY_COMPARESS_EXIST => 'Comparison does not exist query. \'$message\'', - self::DB_QUERY_WHERE_ERROR => 'Query where is Error. \'$message\'', - self::DB_QUERY_JOIN_TYPE_ERROR => 'The database is wrong type of join query. \'$message\'', - self::DB_QUERY_ERROR => 'Query error. \'$message\'', - self::DB_TABLE_EMPTY => 'Table is empty. \'$message\'', - self::DB_EMPTY => 'Database is empty. \'$message\'', - self::DB_DRIVER_NOT_EXIST => 'The database driver does not exist. \'$message\'', - self::DB_DRIVER_EXIST => 'The database driver is aleady exist. \'$message\'', - self::DB_BUILDER_NOT_EXIST => 'The database builder does not exist. \'$message\'', - self::DB_BUILDER_EXIST => 'The database builder is aleady exist. \'$message\'', - self::DB_ADAPTER_NOT_EXIST => 'The database adapter does not exist. \'$message\'', - self::DB_ADAPTER_EXIST => 'The database adapter is aleady exist. \'$message\'', - self::DB_DRIVER_BUILDER_NOT_MATCH => '\'$message\' The database driver does not match with the builder. '); - return isset($messages[$code]) ? $messages[$code] : '$message'; - } +class WindDbException extends WindException +{ + /** + * 连接相关的异常 + */ + const DB_CONN_EMPTY = 1200; + + const DB_CONN_FORMAT = 1201; + + const DB_CONN_NOT_EXIST = 1202; + + const DB_CONN_EXIST = 1203; + + const DB_CONNECT_NOT_EXIST = 1204; + + /** + * 查讯 相关的异常 + */ + const DB_QUERY_EMPTY = 1210; + + const DB_QUERY_LINK_EMPTY = 1211; + + const DB_QUERY_FIELD_EMPTY = 1212; + + const DB_QUERY_FIELD_EXIST = 1213; + + const DB_QUERY_FIELD_FORMAT = 1214; + + const DB_QUERY_INSERT_DATA = 1215; + + const DB_QUERY_UPDATE_DATA = 1216; + + const DB_QUERY_CONDTTION_FORMAT = 1217; + + const DB_QUERY_GROUP_MATCH = 1218; + + const DB_QUERY_LOGIC_MATCH = 1219; + + const DB_QUERY_FETCH_ERROR = 1220; + + const DB_QUERY_TRAN_BEGIN = 1221; + + const DB_QUERY_COMPARESS_ERROR = 1222; + + const DB_QUERY_COMPARESS_EXIST = 1223; + + const DB_QUERY_WHERE_ERROR = 1224; + + const DB_QUERY_JOIN_TYPE_ERROR = 1225; + + const DB_QUERY_ERROR = 126; + + /** + * 字段异常 + */ + const DB_TABLE_EMPTY = 1240; + + const DB_EMPTY = 1241; + + const DB_DRIVER_NOT_EXIST = 1242; + + const DB_DRIVER_EXIST = 1243; + + const DB_BUILDER_NOT_EXIST = 1250; + + const DB_BUILDER_EXIST = 1251; + + const DB_DRIVER_BUILDER_NOT_MATCH = 1252; + + const DB_ADAPTER_NOT_EXIST = 1260; + + const DB_ADAPTER_EXIST = 1261; + + /* (non-PHPdoc) + * @see WindException::messageMapper() + */ + protected function messageMapper($code) + { + $messages = array( + self::DB_CONN_EMPTY => 'Database configuration is empty. \'$message\' ', + self::DB_CONN_FORMAT => 'Database configuration format is incorrect. \'$message\' ', + self::DB_CONN_NOT_EXIST => '\'$message\' The identify of the database connection does not exist. ', + self::DB_CONN_EXIST => '\'$message\' The identify of the database connection is aleady exist.', + self::DB_CONNECT_NOT_EXIST => '\'$message\' The database connection does not exist.', + self::DB_QUERY_EMPTY => 'Query is empty. \'$message\'', + self::DB_QUERY_LINK_EMPTY => '\'$message\' Query link is not a validate resource.', + self::DB_QUERY_FIELD_EMPTY => '\'$message\' Query field is empty.', + self::DB_QUERY_FIELD_EXIST => '\'$message\' Query field is not exist.', + self::DB_QUERY_FIELD_FORMAT => 'Inside the field in the query not formatted correctly. \'$message\'', + self::DB_QUERY_INSERT_DATA => 'The new data is empty. \'$message\'', + self::DB_QUERY_UPDATE_DATA => 'The Updated data is empty. \'$message\'', + self::DB_QUERY_CONDTTION_FORMAT => 'The conditions of query are not right. \'$message\'', + self::DB_QUERY_GROUP_MATCH => '\'$message\' Query group does not match.', + self::DB_QUERY_LOGIC_MATCH => '\'$message\' Query logic does not match.', + self::DB_QUERY_FETCH_ERROR => 'The wrong way to obtain the result set. \'$message\'', + self::DB_QUERY_TRAN_BEGIN => 'Transaction has not started. \'$message\'', + self::DB_QUERY_COMPARESS_ERROR => 'Query comparison is incorrect conversion or assembly. \'$message\'', + self::DB_QUERY_COMPARESS_EXIST => 'Comparison does not exist query. \'$message\'', + self::DB_QUERY_WHERE_ERROR => 'Query where is Error. \'$message\'', + self::DB_QUERY_JOIN_TYPE_ERROR => 'The database is wrong type of join query. \'$message\'', + self::DB_QUERY_ERROR => 'Query error. \'$message\'', + self::DB_TABLE_EMPTY => 'Table is empty. \'$message\'', + self::DB_EMPTY => 'Database is empty. \'$message\'', + self::DB_DRIVER_NOT_EXIST => 'The database driver does not exist. \'$message\'', + self::DB_DRIVER_EXIST => 'The database driver is aleady exist. \'$message\'', + self::DB_BUILDER_NOT_EXIST => 'The database builder does not exist. \'$message\'', + self::DB_BUILDER_EXIST => 'The database builder is aleady exist. \'$message\'', + self::DB_ADAPTER_NOT_EXIST => 'The database adapter does not exist. \'$message\'', + self::DB_ADAPTER_EXIST => 'The database adapter is aleady exist. \'$message\'', + self::DB_DRIVER_BUILDER_NOT_MATCH => '\'$message\' The database driver does not match with the builder. ', ); + + return isset($messages[$code]) ? $messages[$code] : '$message'; + } } -?> \ No newline at end of file diff --git a/wind/db/mysql/WindMysqlPdoAdapter.php b/wind/db/mysql/WindMysqlPdoAdapter.php index 7e054f4d..f4c1f15c 100644 --- a/wind/db/mysql/WindMysqlPdoAdapter.php +++ b/wind/db/mysql/WindMysqlPdoAdapter.php @@ -1,128 +1,153 @@ * mysql:host=localhost;dbname=test * //':'前面部分标明了链接类型为mysql. *
    * @author Qiong Wu 2011-9-22 - * @copyright ©2003-2103 phpwind.com + * @copyright (c)2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindMysqlPdoAdapter.php 3941 2013-05-31 05:41:07Z long.shi $ * @package db * @subpackage mysql */ -class WindMysqlPdoAdapter extends AbstractWindPdoAdapter { +class WindMysqlPdoAdapter extends AbstractWindPdoAdapter +{ + /* (non-PHPdoc) + * @see AbstractWindPdoAdapter::setCharset() + */ + public function setCharset($charset) + { + if ($charset) { + $charset = $this->quote($charset); + $this->query(sprintf("set character_set_connection= %s, character_set_results= %s, character_set_client=binary, sql_mode='';", $charset, $charset)); + $this->query("set names {$charset}"); + } + } + + /** + * 创建数据表 + * + * 添加数据表,支持三个参数'数据表明,字段定义,是否覆盖已存在表'.'$values'举例如下,当数据表名称未定义,或者当'fields'字段未定义,或者为空时抛出异常: + * + * $values = array( + * 'fields' => "`id` smallint(5) unsigned NOT NULL auto_increment, + * `name` varchar(30) NOT NULL default '',PRIMARY KEY (`id`)", + * 'charset' => "utf-8", + * 'autoIncrement' => 'id', + * 'engine' => 'InnerDB'); + * + * 注意:最后一个参数'$replace',有两个取值'true,false',当值为false时表示如果数据表存在不创建新表, + * 值为true时则删除已经存在的数据表并创建新表 + * + * @param string $tableName 数据表名称 + * @param string|array $values 数据表字段信息 + * @param bool $replace 如果表已经存在是否覆盖,接收两个值true|false + * @see AbstractWindPdoAdapter::createTable() + * @return bool + * @throws WindDbException + */ + public function createTable($tableName, $values, $replace = false) + { + if (empty($values['fields']) || !$tableName) { + throw new WindDbException( + '[db.mysql.WindMysqlPdoAdapter.createTable] create table file. '); + } + + if ($replace) { + $_sql = 'DROP TABLE IF EXISTS '.$tableName.';'; + } + $_sql .= 'CREATE TABLE IF NOT EXISTS '.$tableName; + $_sql .= '('.$values['fields'].')ENGINE='.(isset($values['engine']) ? $values['engine'] : 'MyISAM'); + $_sql .= isset($values['charset']) ? ' DEFAULT CHARSET='.$values['charset'] : ''; + $_sql .= isset($values['autoIncrement']) ? ' AUTO_INCREMENT='.$values['autoIncrement'] : ''; + + return $this->query($_sql); + } + + /** + * 过滤数组并将数组变量转换为sql字符串 + * + * 对数组中的值进行安全过滤,并转化为mysql支持的values的格式,如下例子: + * + * $variable = array('a','b','c'); + * quoteArray($variable); + * //return string: ('a','b','c') + * + * + * @see AbstractWindPdoAdapter::quoteArray() + */ + public function quoteArray($variable) + { + if (empty($variable) || !is_array($variable)) { + return ''; + } + $_returns = array(); + foreach ($variable as $value) { + $_returns[] = $this->quote($value); + } + + return '('.implode(', ', $_returns).')'; + } + + /** + * 过滤二维数组将数组变量转换为多组的sql字符串 + * + * + * $var = array(array('a1','b1','c1'),array('a2','b2','c2')); + * quoteMultiArrray($var); + * //return string: ('a1','b1','c1'),('a2','b2','c2') + * + * + * @see AbstractWindPdoAdapter::quoteMultiArray() + */ + public function quoteMultiArray($var) + { + if (empty($var) || !is_array($var)) { + return ''; + } + $_returns = array(); + foreach ($var as $val) { + if (!empty($val) && is_array($val)) { + $_returns[] = $this->quoteArray($val); + } + } - /* (non-PHPdoc) - * @see AbstractWindPdoAdapter::setCharset() - */ - public function setCharset($charset) { - $charset && $this->query("set names " . $this->quote($charset) . ";"); - } + return implode(', ', $_returns); + } - /** - * 创建数据表 - * - * 添加数据表,支持三个参数'数据表明,字段定义,是否覆盖已存在表'.'$values'举例如下,当数据表名称未定义,或者当'fields'字段未定义,或者为空时抛出异常: - * - * $values = array( - * 'fields' => "`id` smallint(5) unsigned NOT NULL auto_increment, - * `name` varchar(30) NOT NULL default '',PRIMARY KEY (`id`)", - * 'charset' => "utf-8", - * 'autoIncrement' => 'id', - * 'engine' => 'InnerDB'); - * - * 注意:最后一个参数'$replace',有两个取值'true,false',当值为false时表示如果数据表存在不创建新表, - * 值为true时则删除已经存在的数据表并创建新表 - * - * @param string $tableName 数据表名称 - * @param string|array $values 数据表字段信息 - * @param boolean $replace 如果表已经存在是否覆盖,接收两个值true|false - * @see AbstractWindPdoAdapter::createTable() - * @return boolean - * @throws WindDbException - */ - public function createTable($tableName, $values, $replace = false) { - if (empty($values['fields']) || !$tableName) throw new WindDbException( - '[db.mysql.WindMysqlPdoAdapter.createTable] create table file. '); - - if ($replace) $_sql = 'DROP TABLE IF EXISTS ' . $tableName . ';'; - $_sql .= 'CREATE TABLE IF NOT EXISTS ' . $tableName; - $_sql .= "(" . $values['fields'] . ")ENGINE=" . (isset($values['engine']) ? $values['engine'] : 'MyISAM'); - $_sql .= isset($values['charset']) ? " DEFAULT CHARSET=" . $values['charset'] : ''; - $_sql .= isset($values['autoIncrement']) ? " AUTO_INCREMENT=" . $values['autoIncrement'] : ''; - return $this->query($_sql); - } + /** + * 组装单条 key=value 形式的SQL查询语句值 insert/update + * + * @param array $array + * @return string + * @see AbstractWindPdoAdapter + */ + public function sqlSingle($array) + { + if (!is_array($array)) { + return ''; + } + $str = array(); + foreach ($array as $key => $val) { + $str[] = $this->fieldMeta($key).'='.$this->quote($val); + } - /** - * 过滤数组并将数组变量转换为sql字符串 - * - * 对数组中的值进行安全过滤,并转化为mysql支持的values的格式,如下例子: - * - * $variable = array('a','b','c'); - * quoteArray($variable); - * //return string: ('a','b','c') - * - * - * @see AbstractWindPdoAdapter::quoteArray() - */ - public function quoteArray($variable) { - if (empty($variable) || !is_array($variable)) return ''; - $_returns = array(); - foreach ($variable as $value) { - $_returns[] = $this->quote($value); - } - return '(' . implode(', ', $_returns) . ')'; - } - - /** - * 过滤二维数组将数组变量转换为多组的sql字符串 - * - * - * $var = array(array('a1','b1','c1'),array('a2','b2','c2')); - * quoteMultiArrray($var); - * //return string: ('a1','b1','c1'),('a2','b2','c2') - * - * - * @see AbstractWindPdoAdapter::quoteMultiArray() - */ - public function quoteMultiArray($var) { - if (empty($var) || !is_array($var)) return ''; - $_returns = array(); - foreach ($var as $val) { - if (!empty($val) && is_array($val)) { - $_returns[] = $this->quoteArray($val); - } - } - return implode(', ', $_returns); - } + return $str ? implode(',', $str) : ''; + } - /** - * 组装单条 key=value 形式的SQL查询语句值 insert/update - * - * @param array $array - * @return string - * @see AbstractWindPdoAdapter - */ - public function sqlSingle($array) { - if (!is_array($array)) return ''; - $str = array(); - foreach ($array as $key => $val) { - $str[] = $this->fieldMeta($key) . '=' . $this->quote($val); - } - return $str ? implode(',', $str) : ''; - } + /* (non-PHPdoc) + * @see AbstractWindPdoAdapter::fieldMeta() + */ + public function fieldMeta($data) + { + $data = str_replace(array('`', ' '), '', $data); - /* (non-PHPdoc) - * @see AbstractWindPdoAdapter::fieldMeta() - */ - public function fieldMeta($data) { - $data = str_replace(array('`', ' '), '', $data); - return ' `' . $data . '` '; - } + return ' `'.$data.'` '; + } } -?> \ No newline at end of file diff --git a/wind/filter/WindActionFilter.php b/wind/filter/WindActionFilter.php index 82526ec0..3a8a7323 100644 --- a/wind/filter/WindActionFilter.php +++ b/wind/filter/WindActionFilter.php @@ -1,15 +1,16 @@ * 'filters' => array( * 'class' => 'WIND:filter.WindFilterChain', //设置使用的拦截链实现 * 'filter1' => array( - * 'class' => 'MYAPP:filter.MyFilter', //设置设置实现的MyFilter类路径,MYAPP必须是一个有效的经过注册的命名空间 + * 'class' => + * 'MYAPP:filter.MyFilter', //设置设置实现的MyFilter类路径,MYAPP必须是一个有效的经过注册的命名空间 * 'pattern' => '*', //此处设置该拦截规则应用的范围,*意味着所有的action都将会应用该拦截规则 * ) * ) @@ -24,119 +25,117 @@ * 用户可以在filter中添加自己的特殊配置:比如: * * 'filters' => array( - * 'class' => 'WIND:filter.WindFilterChain', + * 'class' => 'WIND:filter.WindFilterChain', * 'filter1' => array( - * 'class' => 'MYAPP:filter.TestFilter', - * 'pattern' => '*', + * 'class' => 'MYAPP:filter.TestFilter', + * 'pattern' => '*', * 'isOpen' => '1', //添加的配置 * ) * ) * * 则在自己的TestFilter中设置一个属性名为isOpen同时设置该属性为protected权限,那么在使用的时候该配置的值将会赋值给该属性. - * + * * @author Qiong Wu * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindActionFilter.php 3829 2012-11-19 11:13:22Z yishuo $ * @package filter */ -abstract class WindActionFilter extends WindHandlerInterceptor { - /** - * action跳转类 - * - * @var WindForward - */ - protected $forward = null; - /** - * 错误处理类 - * - * @var WindErrorMessage - */ - protected $errorMessage = null; - /** - * 路由对象 - * - * @var AbstractWindRouter - */ - protected $router = null; +abstract class WindActionFilter extends WindHandlerInterceptor +{ + /** + * action跳转类 + * + * @var WindForward + */ + protected $forward = null; + /** + * 错误处理类 + * + * @var WindErrorMessage + */ + protected $errorMessage = null; + /** + * 路由对象 + * + * @var AbstractWindRouter + */ + protected $router = null; - /** - * 构造函数 - * - * 初始化类属性 - * - * @param WindForward $forward 设置当前的forward对象 - * @param WindErrorMessage $errorMessage 设置错误处理的errorMessage - * @param AbstractWindRouter $router 路由对象 - * @param array $args 接受数组传递,数组以关联数组的方式给出,如果存在属性和关联数组中的key相同则将该key对应值设置给该属性. - */ - public function __construct($forward, $errorMessage, $router, $args = array()) { - $this->forward = $forward; - $this->errorMessage = $errorMessage; - $this->router = $router; - foreach ($args as $key => $value) - property_exists($this, $key) && $this->$key = $value; - } + /** + * 构造函数 + * 初始化类属性 + * + * @param WindForward $forward + * 设置当前的forward对象 + * @param WindErrorMessage $errorMessage + * 设置错误处理的errorMessage + * @param AbstractWindRouter $router + * 路由对象 + * @param array $args + * 接受数组传递,数组以关联数组的方式给出,如果存在属性和关联数组中的key相同则将该key对应值设置给该属性. + */ + public function __construct($forward, $errorMessage, $router, $args = array()) + { + $this->forward = $forward; + $this->errorMessage = $errorMessage; + $this->router = $router; + foreach ($args as $key => $value) { + property_exists($this, $key) && $this->$key = $value; + } + } - /** - * 设置模板数据 - * - * 此方法设置的参数,作用域仅仅只是在当前模板中可用,调用的方法为{$varName} - * - * @param string|array|object $data 需要设置输出的参数 - * @param string $key 参数的名字,默认为空,如果key为空,并且$data是数组或是对象的时候,则$data中的元素将会作为单独的参数保存到输出数据中. - */ - protected function setOutput($data, $key = '') { - $this->forward->setVars($data, $key); - } + /** + * 设置模板数据 + * 此方法设置的参数,作用域仅仅只是在当前模板中可用,调用的方法为{$varName} + * + * @param string|array|object $data + * 需要设置输出的参数 + * @param string $key + * 参数的名字,默认为空,如果key为空,并且$data是数组或是对象的时候,则$data中的元素将会作为单独的参数保存到输出数据中. + */ + protected function setOutput($data, $key = '') + { + $this->forward->setVars($data, $key); + } - /** - * 设置全局模板数据 - * - * 设置为Global的参数数据,将可以在所有子模板中共用,在模板中的通过{@G:varName}的方式去获取变量 - * - * @param string|array|object $data 需要设置的数据 - * @param string $key 参数的名字,默认为空,如果key为空,并且$data是数组或是对象的时候,则$data中的元素将会作为单独的参数保存到Global数据中. - */ - protected function setGlobal($data, $key = '') { - Wind::getApp()->setGlobal($data, $key); - } + /** + * 从指定源中根据输入的参数名获得输入数据 + * + * @param string $name + * 需要获取的值的key + * @param string $type + * 获取数据源,可以是(GET POST COOKIE)中的一个,每种都将从各自的源中去获取对应的数值: + *
      + *
    • GET: 将从$_GET中去获取数据
    • + *
    • POST: 将从$_POST中去获取数据
    • + *
    • COOKIE: 将从$_COOKIE中去获取数据
    • + *
    • 其他值: + * 将依次从request对象的attribute,$_GET,$_POST,$_COOKIE,$_REQUEST,$_ENV,$_SERVER中去尝试获取该值.
    • + *
    + * 该参数默认为空 + * @return array string
      + *
    • 第一个元素: 获得的用户输入的值
    • + *
    • 第二个元素:执行$callback之后返回的值
    • + *
    + */ + protected function getInput($name, $type = '') + { + $value = ''; + switch (strtolower($type)) { + case 'get': + $value = $this->getRequest()->getGet($name); + break; + case 'post': + $value = $this->getRequest()->getPost($name); + break; + case 'cookie': + $value = $this->getRequest()->getCookie($name); + break; + default: + $value = $this->getRequest()->getRequest($name); + } - /** - * 从指定源中根据输入的参数名获得输入数据 - * - * @param string $name 需要获取的值的key - * @param string $type 获取数据源,可以是(GET POST COOKIE)中的一个,每种都将从各自的源中去获取对应的数值: - *
      - *
    • GET: 将从$_GET中去获取数据
    • - *
    • POST: 将从$_POST中去获取数据
    • - *
    • COOKIE: 将从$_COOKIE中去获取数据
    • - *
    • 其他值: 将依次从request对象的attribute,$_GET,$_POST,$_COOKIE,$_REQUEST,$_ENV,$_SERVER中去尝试获取该值.
    • - *
    - * 该参数默认为空 - * @param string $callback 回调函数,缺省值为空数组,该回调函数支持数组格式,即可以是调用类中的方法 - * @return array|string 当有$callback的时候返回一个数组,其有两个元素: - *
      - *
    • 第一个元素: 获得的用户输入的值
    • - *
    • 第二个元素:执行$callback之后返回的值
    • - *
    - */ - protected function getInput($name, $type = '', $callback = array()) { - $value = ''; - switch (strtolower($type)) { - case 'get': - $value = $this->getRequest()->getGet($name, null); - break; - case 'post': - $value = $this->getRequest()->getPost($name, null); - break; - case 'cookie': - $value = $this->getRequest()->getCookie($name, null); - break; - default: - $value = $this->getRequest()->getAttribute($name, null); - } - return $callback ? array($value, call_user_func_array($callback, array($value))) : $value; - } + return $value; + } } -?> \ No newline at end of file diff --git a/wind/filter/WindEnhancedListener.php b/wind/filter/WindEnhancedListener.php new file mode 100644 index 00000000..5be4070e --- /dev/null +++ b/wind/filter/WindEnhancedListener.php @@ -0,0 +1,76 @@ + + *
  • {@link preHandle()}: 抽象接口,前置操作,需要子类实现
  • + *
  • {@link postHandle()}: 抽象接口,后置操作,需要子类实现
  • + *
  • {@link handle()}: 入口接口,调用拦截器的实现.
  • + * + * 该拦截器需要配合拦截链WindHandlerInterceptorChain实现真正的拦截链. + * + * the last known user to change this file in the repository <$LastChangedBy: yishuo $> + * @author Qiong Wu + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id: WindHandlerInterceptor.php 3107 2011-11-11 03:40:09Z yishuo $ + * @package filter + */ +abstract class WindEnhancedListener extends WindModule +{ + protected $targetObject = null; + /** + * 保存执行的结果 + * + * @var mixed + */ + protected $result = null; + /** + * 保存拦截链 + * + * 用以传递控制到下一个拦截器 + * + * @var WindHandlerInterceptorChain + */ + protected $interceptorChain = null; + + /** + * 拦截器的执行入口 + * + * @param mixed $var=.. 该接口接受任意参数,并将依次传递给拦截器的前置和后置操作 + * @return mixed 返回拦截链执行的最终结果 + */ + public function handle($event, $targetObject = null) + { + $args = func_get_args(); + $_args = array_slice($args, 2); + $this->targetObject = $targetObject; + if (method_exists($this, 'pre'.$event)) { + $this->result = call_user_func_array(array($this, 'pre'.$event), $_args); + if (null !== $this->result) { + return $this->result; + } + } + if (null !== ($handler = $this->interceptorChain->getHandler())) { + $this->result = call_user_func_array(array($handler, 'handle'), $args); + } else { + $this->result = call_user_func_array(array($this->interceptorChain, 'handle'), $_args); + } + if (method_exists($this, 'post'.$event)) { + call_user_func_array(array($this, 'post'.$event), $_args); + } + + return $this->result; + } + + /** + * 设置拦截链对象 + * + * @param WindHandlerInterceptorChain $interceptorChain + */ + public function setHandlerInterceptorChain($interceptorChain) + { + $this->interceptorChain = $interceptorChain; + } +} diff --git a/wind/filter/WindHandlerInterceptor.php b/wind/filter/WindHandlerInterceptor.php index b287b658..503c03ee 100644 --- a/wind/filter/WindHandlerInterceptor.php +++ b/wind/filter/WindHandlerInterceptor.php @@ -1,7 +1,7 @@ *
  • {@link preHandle()}: 抽象接口,前置操作,需要子类实现
  • @@ -14,68 +14,71 @@ * @author Qiong Wu * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindHandlerInterceptor.php 3113 2011-11-11 07:28:09Z yishuo $ * @package filter */ -abstract class WindHandlerInterceptor extends WindModule { - /** - * 保存执行的结果 - * - * @var mixed - */ - protected $result = null; - /** - * 保存拦截链 - * - * 用以传递控制到下一个拦截器 - * - * @var WindHandlerInterceptorChain - */ - protected $interceptorChain = null; +abstract class WindHandlerInterceptor extends WindModule +{ + /** + * 保存执行的结果 + * + * @var mixed + */ + protected $result = null; + /** + * 保存拦截链 + * + * 用以传递控制到下一个拦截器 + * + * @var WindHandlerInterceptorChain + */ + protected $interceptorChain = null; + + /** + * 拦截器的前置操作 + * + * @param mixed $var=.. 参数列表将会从handle接口中传递继承 + * @return null|mixed 如果返回为null则将会继续执行下一个拦截器,如果返回不为null则会中断拦截链的执行 + */ + abstract public function preHandle(); - /** - * 拦截器的前置操作 - * - * @param mixed $var=.. 参数列表将会从handle接口中传递继承 - * @return null|mixed 如果返回为null则将会继续执行下一个拦截器,如果返回不为null则会中断拦截链的执行 - */ - abstract public function preHandle(); + /** + * 拦截器的后置操作 + * + * @param mixed $var=.. 参数列表将会从handle接口中传递继承 + */ + abstract public function postHandle(); - /** - * 拦截器的后置操作 - * - * @param mixed $var=.. 参数列表将会从handle接口中传递继承 - */ - abstract public function postHandle(); + /** + * 拦截器的执行入口 + * + * @param mixed $var=.. 该接口接受任意参数,并将依次传递给拦截器的前置和后置操作 + * @return mixed 返回拦截链执行的最终结果 + */ + public function handle() + { + $args = func_get_args(); + $this->result = call_user_func_array(array($this, 'preHandle'), $args); + if ($this->result !== null) { + return $this->result; + } + if (null !== ($handler = $this->interceptorChain->getHandler())) { + $this->result = call_user_func_array(array($handler, 'handle'), $args); + } else { + $this->result = call_user_func_array(array($this->interceptorChain, 'handle'), $args); + } + call_user_func_array(array($this, 'postHandle'), $args); - /** - * 拦截器的执行入口 - * - * @param mixed $var=.. 该接口接受任意参数,并将依次传递给拦截器的前置和后置操作 - * @return mixed 返回拦截链执行的最终结果 - */ - public function handle() { - $args = func_get_args(); - $this->result = call_user_func_array(array($this, 'preHandle'), $args); - if ($this->result !== null) { - return $this->result; - } - if (null !== ($handler = $this->interceptorChain->getHandler())) { - $this->result = call_user_func_array(array($handler, 'handle'), $args); - } else { - $this->result = call_user_func_array(array($this->interceptorChain, 'handle'), $args); - } - call_user_func_array(array($this, 'postHandle'), $args); - return $this->result; - } + return $this->result; + } - /** - * 设置拦截链对象 - * - * @param WindHandlerInterceptorChain $interceptorChain - */ - public function setHandlerInterceptorChain($interceptorChain) { - $this->interceptorChain = $interceptorChain; - } + /** + * 设置拦截链对象 + * + * @param WindHandlerInterceptorChain $interceptorChain + */ + public function setHandlerInterceptorChain($interceptorChain) + { + $this->interceptorChain = $interceptorChain; + } } -?> \ No newline at end of file diff --git a/wind/filter/WindHandlerInterceptorChain.php b/wind/filter/WindHandlerInterceptorChain.php index 71a042c5..faea8537 100644 --- a/wind/filter/WindHandlerInterceptorChain.php +++ b/wind/filter/WindHandlerInterceptorChain.php @@ -1,109 +1,125 @@ * - * the last known user to change this file in the repository <$LastChangedBy: yishuo $> * @author Qiong Wu * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindHandlerInterceptorChain.php 3776 2012-10-23 09:30:30Z + * yishuo $ * @package filter */ -class WindHandlerInterceptorChain extends WindModule { - /** - * 拦截器 - * - * @var array - */ - protected $_interceptors = array('_Na' => null); - /** - * 设置拦截链的回调函数 - * - * @var string|array - */ - protected $_callBack = null; - /** - * 拦截链回调函数的参数 - * - * @var array - */ - protected $_args = array(); +class WindHandlerInterceptorChain extends WindModule +{ + /** + * 拦截器 + * + * @var array + */ + protected $_interceptors = array('_Na' => null); + /** + * 设置拦截链的回调函数 + * + * @var string array + */ + protected $_callBack = null; + /** + * 拦截链回调函数的参数 + * + * @var array + */ + protected $_args = array(); - /** - * 设置回调方法 - * - * @param string|array $callBack 回调方法,可以是字符串: 函数;也可以是数组: 类中的方法 - * @param array $args 回调函数的参数列表 - */ - public function setCallBack($callBack, $args = array()) { - $this->_callBack = $callBack; - $this->_args = $args; - } + /** + * 设置回调方法 + * + * @param string|array $callBack + * 回调方法,可以是字符串: 函数;也可以是数组: 类中的方法 + * @param array $args + * 回调函数的参数列表 + */ + public function setCallBack($callBack, $args = array()) + { + $this->_callBack = $callBack; + $this->_args = $args; + } - /** - * 执行callback方法 - * - * @return mixed $var=.. 如果callBack没有被设置则返回null,否则返回回调函数的结果 - * @throws WindException 如果回调函数调用失败则抛出异常 - */ - public function handle() { - reset($this->_interceptors); - if ($this->_callBack === null) return null; - if (is_string($this->_callBack) && !function_exists($this->_callBack)) { - throw new WindException('[filter.WindHandlerInterceptorChain.execute]' . $this->_callBack, - WindException::ERROR_FUNCTION_NOT_EXIST); - } - $this->_args || $this->_args = func_get_args(); - return call_user_func_array($this->_callBack, (array) $this->_args); - } + /** + * 执行callback方法 + * + * @return mixed $var=.. 如果callBack没有被设置则返回null,否则返回回调函数的结果 + * @throws WindException 如果回调函数调用失败则抛出异常 + */ + public function handle() + { + reset($this->_interceptors); + if ($this->_callBack === null) { + return null; + } + if (is_string($this->_callBack) && !function_exists($this->_callBack)) { + throw new WindException('[filter.WindHandlerInterceptorChain.handle] '.$this->_callBack, + WindException::ERROR_FUNCTION_NOT_EXIST); + } + $this->_args || $this->_args = func_get_args(); - /** - * 返回拦截链中的下一个拦截器 - * - * @return WindHandlerInterceptor - */ - public function getHandler() { - if (count($this->_interceptors) <= 1) { - return $this; - } - $handler = next($this->_interceptors); - if ($handler === false) { - return null; - } - if (method_exists($handler, 'handle')) { - $handler->setHandlerInterceptorChain($this); - return $handler; - } - return $this->getHandler(); - } + return call_user_func_array($this->_callBack, (array) $this->_args); + } - /** - * 添加拦截连中的拦截器对象 - * - * 支持数组和对象两种类型,如果是数组则进行array_merge操作,如果不是数组则直接进行追加操作 - * - * @param array|WindHandlerInterceptor $interceptors 拦截器数组或是单个拦截器 - */ - public function addInterceptors($interceptors) { - if (is_array($interceptors)) - $this->_interceptors = array_merge($this->_interceptors, $interceptors); - else - $this->_interceptors[] = $interceptors; - } + /** + * 返回拦截链中的下一个拦截器 + * + * @return WindHandlerInterceptor + */ + public function getHandler() + { + if (count($this->_interceptors) <= 1) { + return $this; + } + $handler = next($this->_interceptors); + if ($handler === false) { + reset($this->_interceptors); - /** - * 重置拦截链初始化信息 - * - * @return boolean - */ - public function reset() { - $this->_interceptors = array('_Na' => null); - $this->_callBack = null; - $this->_args = array(); - return true; - } + return null; + } + if (method_exists($handler, 'handle')) { + $handler->setHandlerInterceptorChain($this); + + return $handler; + } + + return $this->getHandler(); + } + + /** + * 添加拦截连中的拦截器对象 + * 支持数组和对象两种类型,如果是数组则进行array_merge操作,如果不是数组则直接进行追加操作 + * + * @param array|WindHandlerInterceptor $interceptors + * 拦截器数组或是单个拦截器 + */ + public function addInterceptors($interceptors) + { + if (is_array($interceptors)) { + $this->_interceptors = array_merge($this->_interceptors, $interceptors); + } else { + $this->_interceptors[] = $interceptors; + } + } + + /** + * 重置拦截链初始化信息 + * + * @return bool + */ + public function reset() + { + $this->_interceptors = array('_Na' => null); + $this->_callBack = null; + $this->_args = array(); + + return true; + } } -?> \ No newline at end of file diff --git a/wind/filter/WindSimpleHandlerInterceptor.php b/wind/filter/WindSimpleHandlerInterceptor.php new file mode 100644 index 00000000..fb3de9ac --- /dev/null +++ b/wind/filter/WindSimpleHandlerInterceptor.php @@ -0,0 +1,51 @@ + + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id$ + * @package wind + */ +class WindSimpleHandlerInterceptor +{ + /** + * 保存拦截链 + * 用以传递控制到下一个拦截器 + * + * @var WindHandlerInterceptorChain + */ + protected $interceptorChain = null; + + /** + * 拦截器的执行入口 + * + * @param mixed $var=.. + * 该接口接受任意参数,并将依次传递给拦截器的前置和后置操作 + * @return mixed 返回拦截链执行的最终结果 + */ + public function handle($method) + { + if (method_exists($this, $method)) { + $this->$method(); + } + $handler = $this->interceptorChain->getHandler(); + if (null !== $handler) { + $handler->handle($method); + } + + return; + } + + /** + * 设置拦截链对象 + * + * @param WindHandlerInterceptorChain $interceptorChain + */ + public function setHandlerInterceptorChain($interceptorChain) + { + $this->interceptorChain = $interceptorChain; + } +} diff --git a/wind/filter/proxy/WindClassProxy.php b/wind/filter/proxy/WindClassProxy.php new file mode 100644 index 00000000..adc947b4 --- /dev/null +++ b/wind/filter/proxy/WindClassProxy.php @@ -0,0 +1,178 @@ + + * //相关组件配置,只需设置 proxy为true,就可以通过组件工厂创建一个具有代理功能的类实例对象. + * + * + * + * + * + * + * $object = Wind::getComponents('windApplication'); + * $object->registerEventListener('runProcess', new Listener()); + * + * @author Qiong Wu + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id: WindClassProxy.php 3681 2012-06-18 02:45:28Z yishuo $ + * @package base + */ +class WindClassProxy +{ + /** + * 默认过滤链类型定义 + * + * @var string + */ + protected $_class_interceptorChain = 'WIND:filter.WindHandlerInterceptorChain'; + + /** + * 过滤链对象 + * + * @var WindHandlerInterceptorChain + */ + private $_interceptorChain = null; + protected $_className = ''; + protected $_classPath = ''; + protected $_instance = null; + protected $_listener = array(); + + /** + * @param object $targetObj 需要被代理监听的类对象实例 默认为null + */ + public function __construct($targetObject = null) + { + $targetObject && $this->registerTargetObject($targetObject); + } + + /** + * 注册事件以及事件监听类 + * + * 通过调用该方法,将事件以及对事件的监听方法注册进来,当事件方法被调用的时候监听的方法被触发.例: + * ... + * $object = Wind::getComponents('windApplication'); + * $object->registerEventListener('runProcess', new Listener()); + * + * @param object $listener 事件监听器 + * @param stinrg $event 被监听的事件 + */ + public function registerEventListener($listener, $event) + { + $this->_listener[$event][] = $listener; + } + + /** + * 注册目标对象,如果已经注册了不重复注册 + * + * WindFactory中创建类代理的一段例子: + * $instance = new Object(); + * $this->addClassDefinitions($alias, array('path' => $proxy, 'scope' => 'prototype')); + * $proxy = $this->getInstance($alias); + * $proxy->registerTargetObject($instance); + * $instance->_proxy = $proxy; + * 注意:$instance继承自WindModule + * @param object $targetObject + * @return WindClassProxy + */ + public function registerTargetObject($targetObject) + { + $this->_className = get_class($targetObject); + $this->_instance = $targetObject; + + return $this; + } + + /** + * 监听类方法 + * + * @param string $methodName 方法名 + * @param array $args 方法参数 + * @return mixed + * @throws WindException + */ + public function __call($methodName, $args) + { + $listeners = isset($this->_listener[$methodName]) ? $this->_listener[$methodName] : array(); + if (empty($listeners)) { + return call_user_func_array(array($this->_instance, $methodName), $args); + } + $interceptorChain = $this->_getInterceptorChain($methodName); + $interceptorChain->addInterceptors($listeners); + $interceptorChain->setCallBack(array($this->_getInstance(), $methodName), $args); + + return call_user_func_array(array($interceptorChain->getHandler(), 'handle'), (array) $args); + } + + /** + * 创建并返回过滤链,如果过滤链已经被创建不重复创建 + * + * @param string $event 事件名称 默认值为空 + * @return WindHandlerInterceptorChain + * @throws WindException + */ + private function _getInterceptorChain($event = '') + { + if (null === $this->_interceptorChain) { + $chain = Wind::import($this->_class_interceptorChain); + $this->_interceptorChain = WindFactory::createInstance($chain); + } + $this->_interceptorChain->reset(); + + return $this->_interceptorChain; + } + + /** + * 返回当前代理对象的真实类对象 + * + * @return object + */ + public function _getInstance() + { + return $this->_instance; + } + + /** + * 返回当前代理对象的真实类名称 + * + * @return string + */ + public function _getClassName() + { + return $this->_className; + } + + /** + * 返回当前代理对象的真实类的路径信息 + * + * @return string + */ + public function _getClassPath() + { + return $this->_classPath; + } + + /** + * 设置类名称 + * + * @param string $className + */ + public function _setClassName($className) + { + $this->_className = $className; + } + + /** + * 设置类路径 + * + * @param string $classPath + */ + public function _setClassPath($classPath) + { + $this->_setClassName(Wind::import($classPath)); + $this->_classPath = $classPath; + } +} diff --git a/wind/filter/proxy/WindEnhancedClassProxy.php b/wind/filter/proxy/WindEnhancedClassProxy.php new file mode 100644 index 00000000..1590b58e --- /dev/null +++ b/wind/filter/proxy/WindEnhancedClassProxy.php @@ -0,0 +1,180 @@ + + * //相关组件配置,只需设置 proxy为true,就可以通过组件工厂创建一个具有代理功能的类实例对象. + * + * + * + * + * + * + * $object = Wind::getComponents('windApplication'); + * $object->registerEventListener('runProcess', new Listener()); + * + * @author Qiong Wu + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id: WindClassProxy.php 3681 2012-06-18 02:45:28Z yishuo $ + * @package base + */ +class WindEnhancedClassProxy +{ + /** + * 默认过滤链类型定义 + * + * @var string + */ + protected $_class_interceptorChain = 'WIND:filter.WindHandlerInterceptorChain'; + + /** + * 过滤链对象 + * + * @var WindHandlerInterceptorChain + */ + private $_interceptorChain = null; + protected $_className = ''; + protected $_classPath = ''; + protected $_instance = null; + protected $_listener = array(); + + /** + * @param object $targetObj 需要被代理监听的类对象实例 默认为null + */ + public function __construct($targetObject = null) + { + $targetObject && $this->registerTargetObject($targetObject); + } + + /** + * 注册事件以及事件监听类 + * + * 通过调用该方法,将事件以及对事件的监听方法注册进来,当事件方法被调用的时候监听的方法被触发.例: + * ... + * $object = Wind::getComponents('windApplication'); + * $object->registerEventListener('runProcess', new Listener()); + * + * @param stinrg $event 被监听的事件 + * @param object $listener 事件监听器 + */ + public function registerEventListener($listener) + { + $this->_listener[] = $listener; + } + + /** + * 注册目标对象,如果已经注册了不重复注册 + * + * WindFactory中创建类代理的一段例子: + * $instance = new Object(); + * $this->addClassDefinitions($alias, array('path' => $proxy, 'scope' => 'prototype')); + * $proxy = $this->getInstance($alias); + * $proxy->registerTargetObject($instance); + * $instance->_proxy = $proxy; + * 注意:$instance继承自WindModule + * @param object $targetObject + * @return WindClassProxy + */ + public function registerTargetObject($targetObject) + { + $this->_className = get_class($targetObject); + $this->_instance = $targetObject; + + return $this; + } + + /** + * 监听类方法 + * + * @param string $methodName 方法名 + * @param array $args 方法参数 + * @return mixed + * @throws WindException + */ + public function __call($methodName, $args) + { + if (empty($this->_listener)) { + return call_user_func_array(array($this->_instance, $methodName), $args); + } + $interceptorChain = $this->_getInterceptorChain(); + $interceptorChain->setCallBack(array($this->_getInstance(), $methodName), $args); + if (empty($args)) { + $args = array($methodName, $this->_instance); + } else { + array_unshift($args, $methodName, $this->_instance); + } + + return call_user_func_array(array($interceptorChain->getHandler(), 'handle'), (array) $args); + } + + /** + * 创建并返回过滤链,如果过滤链已经被创建不重复创建 + * + * @return WindHandlerInterceptorChain + * @throws WindException + */ + private function _getInterceptorChain() + { + if (null === $this->_interceptorChain) { + $chain = Wind::import($this->_class_interceptorChain); + $this->_interceptorChain = WindFactory::createInstance($chain); + $this->_interceptorChain->addInterceptors($this->_listener); + } + + return $this->_interceptorChain; + } + + /** + * 返回当前代理对象的真实类对象 + * + * @return object + */ + public function _getInstance() + { + return $this->_instance; + } + + /** + * 返回当前代理对象的真实类名称 + * + * @return string + */ + public function _getClassName() + { + return $this->_className; + } + + /** + * 返回当前代理对象的真实类的路径信息 + * + * @return string + */ + public function _getClassPath() + { + return $this->_classPath; + } + + /** + * 设置类名称 + * + * @param string $className + */ + public function _setClassName($className) + { + $this->_className = $className; + } + + /** + * 设置类路径 + * + * @param string $classPath + */ + public function _setClassPath($classPath) + { + $this->_setClassName(Wind::import($classPath)); + $this->_classPath = $classPath; + } +} diff --git a/wind/ftp/AbstractWindFtp.php b/wind/ftp/AbstractWindFtp.php index 5565a14d..ede212aa 100644 --- a/wind/ftp/AbstractWindFtp.php +++ b/wind/ftp/AbstractWindFtp.php @@ -1,266 +1,249 @@ * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: AbstractWindFtp.php 3930 2013-02-05 03:55:24Z yishuo $ * @package ftp */ -abstract class AbstractWindFtp { - - /** - * ftp主机地址 - * - * @var string - */ - protected $server = ''; - - /** - * ftp链接端口号 - * - * @var int - */ - protected $port = 21; - - /** - * ftp链接的用户名 - * - * @var string - */ - protected $user = ''; - - /** - * ftp链接的用户密码 - * - * @var string - */ - protected $pwd = ''; - - /** - * ftp链接之后使用的当前路径 - * - * @var string - */ - protected $dir = ''; - - /** - * ftp链接的过期时间单位秒 - * - * @var int - */ - protected $timeout = 10; - - /** - * 保存ftp的跟目录路径 - * - * @var string - */ - protected $rootPath = ''; - - /** - * ftp链接对象 - * - * @var resource - */ - protected $conn = null; - - /** - * 初始化配置信息 - * - * @param array $config ftp的配置信息: - *
      - *
    • server: ftp主机地址
    • - *
    • port: ftp链接端口号,默认为21
    • - *
    • user: ftp链接用户名
    • - *
    • pwd: ftp链接用户密码
    • - *
    • dir: ftp链接后切换的目录,默认为空
    • - *
    • timeout: ftp链接超时时间,默认为10秒
    • - *
    - * @return boolean 配置成功返回true,配置失败返回false - */ - public function initConfig($config) { - if (!$config || !is_array($config)) return false; - isset($config['server']) && $this->server = $config['server']; - isset($config['port']) && $this->port = $config['port']; - isset($config['user']) && $this->user = $config['user']; - isset($config['pwd']) && $this->pwd = $config['pwd']; - isset($config['dir']) && $this->dir = $config['dir']; - isset($config['timeout']) && $this->timeout = $config['timeout']; - return true; - } - - /** - * 重命名文件 - * - * @param string $oldName 现在的文件名 - * @param string $newName 新的文件名 - * @return boolean 重命名成功则返回true,失败则返回false - */ - abstract public function rename($oldName, $newName); - - /** - * 删除文件 - * - * @param string $filename 待删除的文件 - * @return boolean 删除成功返回true,删除失败返回false - */ - abstract public function delete($filename); - - /** - * 上传文件 - * - * @param string $sourceFile 待上传的文件 - * @param string $desFile 文件上传的存放位置 - * @param string $mode 上传模式二进制还是ASCII上传,I为二进制模式,A为ASCII模式,默认为A模式 - * @return int 返回上传文件的大小 - */ - abstract public function upload($sourceFile, $desFile, $mode = 'A'); - - /** - * 下载文件 - * - * @param string $localfile 下载文件存放位置 - * @param string $remotefile 待下载的文件 - * @param string $mode 下载的模式二进制还是ASCII上传,I为二进制模式,A为ASCII模式,默认为A模式 - * @return boolean 返回文件下载是否成功 - */ - abstract public function download($localfile, $remotefile = '', $mode = 'A'); - - /** - * 列出给定目录的文件列表 - * - * @param string $dir 目录,默认为空即为当前目录 - * @return array 返回该目录下的文件列表 - */ - abstract public function fileList($dir = ''); - - /** - * 关闭ftp链接 - * - * @return boolean 返回关闭链接是否成功 - */ - abstract public function close(); - - /** - * 创建文件夹 - * - * @param string $dir 待创建的文件夹 - * @return boolean 创建文件夹成功则返回true,失败则返回false - */ - abstract public function mkdir($dir); - - /** - * 更改当前目录到指定目录下 - * - * @param string $dir 需要设置为当前目录的目录 - * @return boolean 设置成功则返回true,失败则返回false - */ - abstract public function changeDir($dir); - - /** - * 获得文件大小 - * - * @param string $file 待获取的文件 - * @return int 获取成功返回文件大小 - */ - abstract public function size($file); - - /** - * 获得当前路径 - * - * @return string 返回当前路径 - */ - abstract protected function pwd(); - - /** - * 级联创建文件夹 - * - * @param string $dir 待创建文件夹路径 - * @param string $permissions 创建的文件夹的权限 - * @return boolean 创建成功返回true创建失败返回false - */ - public function mkdirs($dir, $permissions = 0777) { - $dir = explode('/', WindSecurity::escapePath($dir)); - $dirs = ''; - $result = false; - $count = count($dir); - for ($i = 0; $i < $count; $i++) { - if (strpos($dir[$i], '.') === 0) continue; - $result = $this->mkdir($dir[$i], $permissions); - $this->changeDir($this->rootPath . $dirs . $dir[$i]); - $dirs .= "$dir[$i]/"; - } - $this->changeDir($this->rootPath); - return $result; - } - - /** - * 检查文件是否存在 - * - * @param string $filename 待检查的文件 - * @return boolean 文件存在则返回true,失败则返回false - */ - public function file_exists($filename) { - $directory = substr($filename, 0, strrpos($filename, '/')); - $filename = str_replace("$directory/", '', $filename); - if ($directory) { - $directory = $this->rootPath . $directory . '/'; - } else { - $directory = $this->rootPath; - } - $this->changeDir($directory); - $list = $this->fileList(); - $this->changeDir($this->rootPath); - if (!empty($list) && in_array($filename, $list)) return true; - return false; - } - - /** - * 重设当前目录为初始化目录信息 - */ - protected function initRootPath() { - $this->rootPath = $this->pwd(); - if ($this->dir) { - $this->rootPath .= trim(str_replace('\\', '/', $this->dir), '/') . '/'; - } - $this->changeDir($this->rootPath); - } - - /** - * 检查文件类型 - * - * @param string $filename 待检查的文件 - * @return boolean 如果文件带有.php字串则返回false,否则返回true - * @TODO 文件内容的安全性检查 - */ - protected function checkFile($filename) { - return (str_replace(array('..', '.php.'), '', $filename) != $filename || preg_match('/\.php$/i', $filename)); - } - - /** - * 获得文件后缀 - * - * @param string $filename 文件 - * @return string 返回文件的后缀,如果传入的文件没有后缀将会返回txt - */ - protected function getExt($filename) { - if (false === strpos($filename, '.')) return 'txt'; - $x = explode('.', $filename); - return strtolower(end($x)); - } - - /** - * 显示错误信息 - * - * @param string $str 错误信息 - * @param boolean $close 是否关闭链接,默认为true需要关闭链接 - */ - protected function showError($str, $close = true) { - $close && $this->close(); - exit($str); - } -} \ No newline at end of file +abstract class AbstractWindFtp +{ + /** + * ftp主机地址 + * + * @var string + */ + protected $server = ''; + + /** + * ftp链接端口号 + * + * @var int + */ + protected $port = 21; + + /** + * ftp链接的用户名 + * + * @var string + */ + protected $user = ''; + + /** + * ftp链接的用户密码 + * + * @var string + */ + protected $pwd = ''; + + /** + * ftp链接之后使用的当前路径 + * + * @var string + */ + protected $dir = ''; + + /** + * ftp链接的过期时间单位秒 + * + * @var int + */ + protected $timeout = 10; + + /** + * 保存ftp的跟目录路径 + * + * @var string + */ + protected $rootPath = ''; + + /** + * ftp链接对象 + * + * @var resource + */ + protected $conn = null; + + /** + * 初始化配置信息 + * + * @param array $config ftp的配置信息: + *
      + *
    • server: ftp主机地址
    • + *
    • port: ftp链接端口号,默认为21
    • + *
    • user: ftp链接用户名
    • + *
    • pwd: ftp链接用户密码
    • + *
    • dir: ftp链接后切换的目录,默认为空
    • + *
    • timeout: ftp链接超时时间,默认为10秒
    • + *
    + * @return bool 配置成功返回true,配置失败返回false + */ + public function initConfig($config) + { + if (!$config || !is_array($config)) { + return false; + } + isset($config['server']) && $this->server = $config['server']; + isset($config['port']) && $this->port = $config['port']; + isset($config['user']) && $this->user = $config['user']; + isset($config['pwd']) && $this->pwd = $config['pwd']; + isset($config['dir']) && $this->dir = $config['dir']; + isset($config['timeout']) && $this->timeout = $config['timeout']; + + return true; + } + + /** + * 重命名文件 + * + * @param string $oldName 现在的文件名 + * @param string $newName 新的文件名 + * @return bool 重命名成功则返回true,失败则返回false + */ + abstract public function rename($oldName, $newName); + + /** + * 删除文件 + * + * @param string $filename 待删除的文件 + * @return bool 删除成功返回true,删除失败返回false + */ + abstract public function delete($filename); + + /** + * 上传文件 + * + * 'I' == BINARY mode + * 'A' == ASCII mode + * + * @param string $sourceFile 待上传的文件 + * @param string $desFile 文件上传的存放位置 + * @param string $mode 上传模式二进制还是ASCII上传,I为二进制模式,A为ASCII模式,默认为A模式 + * @return int 返回上传文件的大小 + */ + abstract public function upload($sourceFile, $desFile, $mode = 'I'); + + /** + * 下载文件 + * + * @param string $localfile 下载文件存放位置 + * @param string $remotefile 待下载的文件 + * @param string $mode 下载的模式二进制还是ASCII上传,I为二进制模式,A为ASCII模式,默认为A模式 + * @return bool 返回文件下载是否成功 + */ + abstract public function download($localfile, $remotefile = '', $mode = 'I'); + + /** + * 列出给定目录的文件列表 + * + * @param string $dir 目录,默认为空即为当前目录 + * @return array 返回该目录下的文件列表 + */ + abstract public function fileList($dir = ''); + + /** + * 关闭ftp链接 + * + * @return bool 返回关闭链接是否成功 + */ + abstract public function close(); + + /** + * 创建文件夹 + * + * @param string $dir 待创建的文件夹 + * @return bool 创建文件夹成功则返回true,失败则返回false + */ + abstract public function mkdir($dir); + + /** + * 更改当前目录到指定目录下 + * + * @param string $dir 需要设置为当前目录的目录 + * @return bool 设置成功则返回true,失败则返回false + */ + abstract public function changeDir($dir); + + /** + * 获得文件大小 + * + * @param string $file 待获取的文件 + * @return int 获取成功返回文件大小 + */ + abstract public function size($file); + + /** + * 获得当前路径 + * + * @return string 返回当前路径 + */ + abstract protected function pwd(); + + /** + * 级联创建文件夹 + * + * @param string $dir 待创建文件夹路径 + * @param string $permissions 创建的文件夹的权限 + * @return bool 创建成功返回true创建失败返回false + */ + public function mkdirs($dir, $permissions = 0777) + { + $dir = explode('/', WindSecurity::escapePath($dir)); + $dirs = ''; + $result = false; + $count = count($dir); + for ($i = 0; $i < $count; $i++) { + if ('.' !== $dir[$i] && '..' !== $dir[$i]) { + $result = $this->mkdir($dir[$i], $permissions); + $this->changeDir($this->rootPath.$dirs.$dir[$i]); + $dirs .= "$dir[$i]/"; + } + } + $this->changeDir($this->rootPath); + + return $result; + } + + /** + * 检查文件是否存在 + * + * @param string $filename 待检查的文件 + * @return bool 文件存在则返回true,失败则返回false + */ + public function file_exists($filename) + { + $directory = substr($filename, 0, strrpos($filename, '/')); + $filename = str_replace("$directory/", '', $filename); + if ($directory) { + $directory = $this->rootPath.$directory.'/'; + } else { + $directory = $this->rootPath; + } + $this->changeDir($directory); + $list = $this->fileList(); + $this->changeDir($this->rootPath); + if (!empty($list) && in_array($filename, $list)) { + return true; + } + + return false; + } + + /** + * 重设当前目录为初始化目录信息 + */ + protected function initRootPath() + { + $this->rootPath = $this->pwd(); + if ($this->dir) { + $this->rootPath .= trim(str_replace('\\', '/', $this->dir), '/').'/'; + } + $this->changeDir($this->rootPath); + } +} diff --git a/wind/ftp/WindFtp.php b/wind/ftp/WindFtp.php index afc4379b..3c668145 100644 --- a/wind/ftp/WindFtp.php +++ b/wind/ftp/WindFtp.php @@ -1,11 +1,12 @@ - * Wind::import('WIND:ftp.WindFtp'); + * * $ftp = new WindFtp(array('server' => '192.168.1.10', 'port' => '21', ‘user' => 'test', 'pwd' => '123456')); * print_r($ftp->fileList()); * @@ -13,199 +14,235 @@ * @author xiaoxia.xu * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindFtp.php 3904 2013-01-08 07:01:26Z yishuo $ * @package ftp */ -class WindFtp extends AbstractWindFtp { - - /** - * 被动模式是否开启默认为true开启 - * - * @var boolean - */ - private $isPasv = true; - - /** - * 构造函数 - * - * 通过传入config构造链接对象 - * - * @param array $config ftp配置文件 - */ - public function __construct($config = array()) { - $this->connection($config); - } - - /** - * 链接ftp - * - * @param array $config ftp的配置信息: - *
      - *
    • server: ftp主机地址
    • - *
    • port: ftp链接端口号,默认为21
    • - *
    • user: ftp链接用户名
    • - *
    • pwd: ftp链接用户密码
    • - *
    • dir: ftp链接后切换的目录,默认为空
    • - *
    • timeout: ftp链接超时时间,默认为10秒
    • - *
    • ispasv: ftp是否采用被动模式,默认为1,如果配置为0则表示不开启被动模式,其他值都将设置为开启被动模式
    • - *
    - * @return boolean - */ - private function connection($config = array()) { - $this->initConfig($config); - if (false === ($this->conn = ftp_connect($this->server, $this->port, $this->timeout))) { - $this->showError('The ftp ' . $this->server . ' cann\'t connection!'); - } - if (false == ftp_login($this->conn, $this->user, $this->pwd)) { - $this->showError('Login error: ' . $this->user); - } - if ($this->isPasv) { - ftp_pasv($this->conn, true); - } - $this->initRootPath(); - return true; - } - - /** - * 获得ftp链接 - * - * @return resource - */ - private function getFtp() { - if (is_resource($this->conn)) return $this->conn; - $this->connection(); - return $this->conn; - } - - /* (non-PHPdoc) - * @see AbstractWindFtp::rename() - */ - public function rename($oldName, $newName) { - return ftp_rename($this->getFtp(), $oldName, $newName); - } - - /* (non-PHPdoc) - * @see AbstractWindFtp::delete() - */ - public function delete($filename) { - return ftp_delete($this->getFtp(), $filename); - } - - /* (non-PHPdoc) - * @see AbstractWindFtp::upload() - */ - public function upload($sourceFile, $desFile, $mode = 'A') { - $mode = $this->getMode($sourceFile, $mode); - if (!in_array(($savedir = dirname($desFile)), array('.', '/'))) { - $this->mkdirs($savedir); - } - $desFile = $this->rootPath . WindSecurity::escapePath($desFile); - $result = ftp_put($this->getFtp(), $desFile, $sourceFile, $mode); - if (false === $result) return false; - $this->chmod($desFile, 0644); - return $this->size($desFile); - } - - /* (non-PHPdoc) - * @see AbstractWindFtp::download() - */ - public function download($filename, $localname = '', $mode = 'auto') { - $mode = $this->getMode($filename, $mode); - return ftp_get($this->getFtp(), $localname, $filename, $mode); - } - - /* (non-PHPdoc) - * @see AbstractWindFtp::fileList() - */ - public function fileList($dir = '') { - return ftp_nlist($this->getFtp(), $dir); - } - - /* (non-PHPdoc) - * @see AbstractWindFtp::close() - */ - public function close() { - is_resource($this->conn) && ftp_close($this->conn); - $this->conn = null; - return true; - } - - /* (non-PHPdoc) - * @see AbstractWindFtp::initConfig() - */ - public function initConfig($config) { - if (!$config || !is_array($config)) return false; - parent::initConfig($config); - $this->isPasv = (isset($config['ispasv']) && $config['ispasv'] == 0) ? false : true; - } - - /* (non-PHPdoc) - * @see AbstractWindFtp::mkdir() - */ - public function mkdir($dir, $permissions = 0777) { - $result = ftp_mkdir($this->getFtp(), $dir); - if (!$result) return false; - return $this->chmod($result, $permissions); - } - - /** - * 给文件赋指定权限 - * - * @param string $file 待处理的文件 - * @param int $permissions 文件的需要的权限 - * @return boolean 设置成功返回true,设置失败返回false - */ - private function chmod($file, $permissions = 0777) { - return ftp_chmod($this->getFtp(), $permissions, $file); - } - - /* (non-PHPdoc) - * @see AbstractWindFtp::pwd() - */ - protected function pwd() { - return ftp_pwd($this->getFtp()) . '/'; - } - - /* (non-PHPdoc) - * @see AbstractWindFtp::changeDir() - */ - public function changeDir($dir) { - return ftp_chdir($this->getFtp(), $dir); - } - - /* (non-PHPdoc) - * @see AbstractWindFtp::size() - */ - public function size($file) { - return ftp_size($this->getFtp(), $file); - } - - /** - * 根据文件获得文件访问的模式 - * - * @param string $filename 文件名 - * @param string $mode 模式,二进制还是ASCII上传,I为二进制模式,A为ASCII模式,默认为A模式,如果是auto将会根据文件后缀来设置模式 - * @return string 返回模式方式FTP_ASCII或是FTP_BINARY - */ - private function getMode($filename, $mode) { - $ext = $this->getExt($filename); - $mode = strtolower($mode); - if ($mode == 'auto') { - $ext = $this->getExt($filename); - $mode = $this->getModeMap($ext); - } - return (strtolower($mode) == 'A') ? FTP_ASCII : FTP_BINARY; - } - - /** - * 根据文件后缀获得该文件的访问模式 - * - * @param string 文件的后缀 - * @return string A(ASCII)或是I(BINARY)模式 - */ - private function getModeMap($ext){ - $exts = array('txt', 'text', 'php', 'phps', 'php4', 'js', 'css', - 'htm', 'html', 'phtml', 'shtml', 'log', 'xml'); - return (in_array($ext, $exts)) ? 'A' : 'I'; - } -} \ No newline at end of file +class WindFtp extends AbstractWindFtp +{ + /** + * 被动模式是否开启默认为true开启 + * + * @var bool + */ + private $isPasv = true; + + /** + * 构造函数 + * + * 通过传入config构造链接对象 + * + * @param array $config ftp配置文件 + */ + public function __construct($config = array()) + { + $this->connection($config); + } + + /** + * 链接ftp + * + * @param array $config ftp的配置信息: + *
      + *
    • server: ftp主机地址
    • + *
    • port: ftp链接端口号,默认为21
    • + *
    • user: ftp链接用户名
    • + *
    • pwd: ftp链接用户密码
    • + *
    • dir: ftp链接后切换的目录,默认为空
    • + *
    • timeout: ftp链接超时时间,默认为10秒
    • + *
    • ispasv: ftp是否采用被动模式,默认为1,如果配置为0则表示不开启被动模式,其他值都将设置为开启被动模式
    • + *
    + * @return bool + */ + private function connection($config = array()) + { + $this->initConfig($config); + if (false === ($this->conn = ftp_connect($this->server, $this->port, $this->timeout))) { + throw new WindFtpException("[ftp.WindFtp.connection] $this->server:$this->port", + WindFtpException::CONNECT_FAILED); + } + if (false == ftp_login($this->conn, $this->user, $this->pwd)) { + throw new WindFtpException('[ftp.WindFtp.connection] '.$this->user, WindFtpException::LOGIN_FAILED); + } + if ($this->isPasv) { + ftp_pasv($this->conn, true); + } + $this->initRootPath(); + + return true; + } + + /** + * 获得ftp链接 + * + * @return resource + */ + private function getFtp() + { + if (is_resource($this->conn)) { + return $this->conn; + } + $this->connection(); + + return $this->conn; + } + + /* (non-PHPdoc) + * @see AbstractWindFtp::rename() + */ + public function rename($oldName, $newName) + { + return ftp_rename($this->getFtp(), $oldName, $newName); + } + + /* (non-PHPdoc) + * @see AbstractWindFtp::delete() + */ + public function delete($filename) + { + return ftp_delete($this->getFtp(), $filename); + } + + /* (non-PHPdoc) + * @see AbstractWindFtp::upload() + */ + public function upload($sourceFile, $desFile, $mode = 'I') + { + $mode = $this->getMode($sourceFile, $mode); + if (!in_array(($savedir = dirname($desFile)), array('.', '/'))) { + $this->mkdirs($savedir); + } + $desFile = $this->rootPath.WindSecurity::escapePath($desFile); + $result = ftp_put($this->getFtp(), $desFile, $sourceFile, $mode); + if (false === $result) { + throw new WindFtpException('[ftp.WindFtp.upload] PUT', WindFtpException::COMMAND_FAILED); + } + $this->chmod($desFile, 0644); + + return $this->size($desFile); + } + + /* (non-PHPdoc) + * @see AbstractWindFtp::download() + */ + public function download($filename, $localname = '', $mode = 'I') + { + $mode = $this->getMode($filename, $mode); + + return ftp_get($this->getFtp(), $localname, $filename, $mode); + } + + /* (non-PHPdoc) + * @see AbstractWindFtp::fileList() + */ + public function fileList($dir = '') + { + return ftp_nlist($this->getFtp(), $dir); + } + + /* (non-PHPdoc) + * @see AbstractWindFtp::close() + */ + public function close() + { + is_resource($this->conn) && ftp_close($this->conn); + $this->conn = null; + + return true; + } + + /* (non-PHPdoc) + * @see AbstractWindFtp::initConfig() + */ + public function initConfig($config) + { + if (!$config || !is_array($config)) { + return false; + } + parent::initConfig($config); + $this->isPasv = (isset($config['ispasv']) && $config['ispasv'] == 0) ? false : true; + } + + /* (non-PHPdoc) + * @see AbstractWindFtp::mkdir() + */ + public function mkdir($dir, $permissions = 0777) + { + $result = ftp_mkdir($this->getFtp(), $dir); + if (!$result) { + return false; + } + + return $this->chmod($result, $permissions) === false ? false : true; + } + + /** + * 给文件赋指定权限 + * + * @param string $file 待处理的文件 + * @param int $permissions 文件的需要的权限 + * @return bool 设置成功返回true,设置失败返回false + */ + private function chmod($file, $permissions = 0777) + { + return ftp_chmod($this->getFtp(), $permissions, $file); + } + + /* (non-PHPdoc) + * @see AbstractWindFtp::pwd() + */ + protected function pwd() + { + return ftp_pwd($this->getFtp()).'/'; + } + + /* (non-PHPdoc) + * @see AbstractWindFtp::changeDir() + */ + public function changeDir($dir) + { + if (false === ftp_chdir($this->getFtp(), $dir)) { + throw new WindFtpException('[ftp.WindFtp.changeDir] '.$dir, WindFtpException::COMMAND_FAILED_CWD); + } + + return true; + } + + /* (non-PHPdoc) + * @see AbstractWindFtp::size() + */ + public function size($file) + { + return ftp_size($this->getFtp(), $file); + } + + /** + * 根据文件获得文件访问的模式 + * + * @param string $filename 文件名 + * @param string $mode 模式,二进制还是ASCII上传,I为二进制模式,A为ASCII模式,默认为A模式,如果是auto将会根据文件后缀来设置模式 + * @return string 返回模式方式FTP_ASCII或是FTP_BINARY + */ + private function getMode($filename, $mode) + { + if (strcasecmp($mode, 'auto') == 0) { + $ext = WindFile::getSuffix($filename); + $mode = (in_array(strtolower($ext), + array( + 'txt', + 'text', + 'php', + 'phps', + 'php4', + 'js', + 'css', + 'htm', + 'html', + 'phtml', + 'shtml', + 'log', + 'xml', ))) ? 'A' : 'I'; + } + + return ($mode == 'A') ? FTP_ASCII : FTP_BINARY; + } +} diff --git a/wind/ftp/WindSocketFtp.php b/wind/ftp/WindSocketFtp.php index e2d1f640..080b278b 100644 --- a/wind/ftp/WindSocketFtp.php +++ b/wind/ftp/WindSocketFtp.php @@ -1,12 +1,12 @@ - * Wind::import('WIND:ftp.WindSocketFtp'); + * * $ftp = new WindSocketFtp(array('server' => '192.168.1.10', 'port' => '21', ‘user' => 'test', 'pwd' => '123456')); * print_r($ftp->fileList()); * @@ -14,286 +14,314 @@ * @author xiaoxia.xu * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindSocketFtp.php 3904 2013-01-08 07:01:26Z yishuo $ * @package ftp */ -class WindSocketFtp extends AbstractWindFtp { - /** - * 临时链接对象保存 - * - * @var object - */ - private $tmpConnection; - - /** - * 构造函数 - * - * 通过传入config构造链接对象 - * - * @param array $config ftp配置文件 - */ - public function __construct($config = array()) { - $this->getConnection($config); - } - - /** - * 获得ftp链接 - * - * @param array $config ftp的配置信息: - *
      - *
    • server: ftp主机地址
    • - *
    • port: ftp链接端口号,默认为21
    • - *
    • user: ftp链接用户名
    • - *
    • pwd: ftp链接用户密码
    • - *
    • dir: ftp链接后切换的目录,默认为空
    • - *
    • timeout: ftp链接超时时间,默认为10秒
    • - *
    - * @return boolean - */ - private function getConnection($config) { - $this->initConfig($config); - $errno = 0; - $errstr = ''; - $this->conn = fsockopen($this->server, $this->port, $errno, $errstr, $this->timeout); - if (!$this->conn || !$this->checkcmd()) { - $this->showError('ftp_connect_failed'); - } - stream_set_timeout($this->conn, $this->timeout); - - if (!$this->sendcmd('USER', $this->user)) { - $this->showError('ftp_user_failed'); - } - if (!$this->sendcmd('PASS', $this->pwd)) { - $this->showError('ftp_pass_failed'); - } - - $this->initRootPath(); - return true; - } - - /* (non-PHPdoc) - * @see AbstractWindFtp::pwd() - */ - protected function pwd() { - $this->sendcmd('PWD', '', false); - if (!($path = $this->checkcmd(true)) || !preg_match("/^[0-9]{3} \"(.+?)\"/", $path, $matchs)) { - return '/'; - } - return $matchs[1] . ((substr($matchs[1], -1) == '/') ? '' : '/'); - } - - /* (non-PHPdoc) - * @see AbstractWindFtp::upload() - */ - public function upload($localfile, $remotefile, $mode = 'A') { - if ($this->checkFile($localfile)) { - $this->showError("Error:illegal file type!({$localfile})"); - } - if ($this->checkFile($remotefile)) { - $this->showError("Error:illegal file type!({$remotefile})"); - } - if (!in_array(($savedir = dirname($remotefile)), array('.', '/'))) { - $this->mkdirs($savedir); - } - $remotefile = $this->rootPath . WindSecurity::escapePath($remotefile); - if (!($fp = fopen($localfile, 'rb'))) { - $this->showError("Error:Cannot read file \"$localfile\""); - } - // 'I' == BINARY mode - // 'A' == ASCII mode - $mode != 'I' && $mode = 'A'; - $this->delete($remotefile); - if (!$this->sendcmd('TYPE', $mode)) { - $this->showError('Error:TYPE command failed'); - } - $this->openTmpConnection(); - $this->sendcmd('STOR', $remotefile); - while (!feof($fp)) { - fwrite($this->tmpConnection, fread($fp, 4096)); - } - fclose($fp); - $this->closeTmpConnection(); - - if (!$this->checkcmd()) { - $this->showError('Error:PUT command failed'); - } else { - $this->sendcmd('SITE CHMOD', base_convert(0644, 10, 8) . " $remotefile"); - } - return $this->size($remotefile); - } - - /* (non-PHPdoc) - * @see AbstractWindFtp::download() - */ - public function download($localfile, $remotefile = '', $mode = 'I') { - if ($this->checkFile($localfile)) { - $this->showError("Error:illegal file type!({$localfile})"); - } - if ($this->checkFile($remotefile)) { - $this->showError("Error:illegal file type!({$remotefile})"); - } - $mode != 'I' && $mode = 'A'; - if (!$this->sendcmd('TYPE', $mode)) { - $this->showError('Error:TYPE command failed'); - } - $this->openTmpConnection(); - if (!$this->sendcmd('RETR', $remotefile)) { - $this->closeTmpConnection(); - return false; - } - if (!($fp = fopen($localfile, 'wb'))) { - $this->showError("Error:Cannot read file \"$localfile\""); - } - while (!feof($this->tmpConnection)) { - fwrite($fp, fread($this->tmpConnection, 4096)); - } - fclose($fp); - $this->closeTmpConnection(); - - if (!$this->checkcmd()) $this->showError('Error:GET command failed'); - return true; - } - - /* (non-PHPdoc) - * @see AbstractWindFtp::size() - */ - public function size($file) { - $this->sendcmd('SIZE', $file, false); - if (!($size_port = $this->checkcmd(true))) { - $this->showError('Error:Check SIZE command failed'); - } - return preg_replace("/^[0-9]{3} ([0-9]+)\r\n/", "\\1", $size_port); - } - - /* (non-PHPdoc) - * @see AbstractWindFtp::delete() - */ - public function delete($file) { - return $this->sendcmd('DELE', $this->rootPath . WindSecurity::escapePath($file)); - } - - /* (non-PHPdoc) - * @see AbstractWindFtp::rename() - */ - public function rename($oldname, $newname) { - if (!in_array(($savedir = dirname($newname)), array('.', '/'))) { - $this->mkdirs($savedir); - } - $oldname = $this->rootPath . WindSecurity::escapeDir($oldname); - $this->sendcmd('RNFR', $oldname); - return $this->sendcmd('RNTO', $newname); - } - - /* (non-PHPdoc) - * @see AbstractWindFtp::mkdir() - */ - public function mkdir($dir) { - $base777 = base_convert(0777, 10, 8); - $result = $this->sendcmd('MKD', $dir); - return $this->sendcmd('SITE CHMOD', "$base777 $dir"); - } - - /* (non-PHPdoc) - * @see AbstractWindFtp::changeDir() - */ - public function changeDir($dir) { - $dir = (($dir[0] != '/') ? '/' : '') . $dir; - if ($dir !== '/' && substr($dir, -1) == '/') { - $dir = substr($dir, 0, -1); - } - if (!$this->sendcmd('CWD', $dir)) { - $this->showError('ftp_cwd_failed'); - } - return true; - } - - /* (non-PHPdoc) - * @see AbstractWindFtp::fileList() - */ - public function fileList($dir = '') { - $this->openTmpConnection(); - $this->sendcmd('NLST', $dir); - $list = array(); - while (!feof($this->tmpConnection)) { - $list[] = preg_replace('/[\r\n]/', '', fgets($this->tmpConnection, 512)); - } - $this->closeTmpConnection(); - if (!$this->checkcmd(true)) $this->showError('Error:LIST command failed'); - return $list; - } - - /* (non-PHPdoc) - * @see AbstractWindFtp::close() - */ - public function close() { - if (!$this->conn) return false; - if (!$this->sendcmd('QUIT') || !fclose($this->conn)) $this->showError('Error:QUIT command failed', false); - return true; - } - - /** - * 发送ftp处理命令 - * - * @param string $cmd 待发送的命令 - * @param string $args 命令参数 - * @param boolean $check 是否需要检查返回状态,默认为true需要检查 - * @return boolean 如果检查命令发送失败则返回false,否则返回true - */ - private function sendcmd($cmd, $args = '', $check = true) { - !empty($args) && $cmd .= " $args"; - fputs($this->conn, "$cmd\r\n"); - if ($check === true && !$this->checkcmd()) return false; - return true; - } - - /** - * 检查命令状态 - * - * @param boolean $return 是否需要返回命令状态信息,默认为false,不许要返回 - * @return boolean|string 检查命令已经发送成功,则返回true,失败则返回false,如果设置了参数$return=true并且命令状态正确的情况下将会返回状态信息 - */ - private function checkcmd($return = false) { - $resp = $rcmd = ''; - $i = 0; - do { - $rcmd = fgets($this->conn, 512); - $resp .= $rcmd; - } while (++$i < 20 && !preg_match('/^\d{3}\s/is', $rcmd)); - - if (!preg_match('/^[123]/', $rcmd)) return false; - return $return ? $resp : true; - } - - /** - * 打开临时链接句柄 - * - * @return boolean 如果打开成功返回true - */ - private function openTmpConnection() { - $this->sendcmd('PASV', '', false); - if (!($ip_port = $this->checkcmd(true))) { - $this->showError('Error:Check PASV command failed'); - } - if (!preg_match('/[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]+,[0-9]+/', $ip_port, $temp)) { - $this->showError("Error:Illegal ip-port format($ip_port)"); - } - $temp = explode(',', $temp[0]); - $server_ip = "$temp[0].$temp[1].$temp[2].$temp[3]"; - $server_port = $temp[4] * 256 + $temp[5]; - if (!$this->tmpConnection = fsockopen($server_ip, $server_port, $errno, $errstr, $this->timeout)) { - $this->showError("Error:Cannot open data connection to $server_ip:$server_port
    Error:$errstr ($errno)"); - } - stream_set_timeout($this->tmpConnection, $this->timeout); - return true; - } - - /** - * 关闭临时链接对象 - * - * @return boolean 关闭成功返回true,失败返回false - */ - private function closeTmpConnection() { - return fclose($this->tmpConnection); - } +class WindSocketFtp extends AbstractWindFtp +{ + /** + * 临时链接对象保存 + * + * @var object + */ + private $tmpConnection; + + /** + * 构造函数 + * + * 通过传入config构造链接对象 + * + * @param array $config ftp配置文件 + */ + public function __construct($config = array()) + { + $this->getConnection($config); + } + + /** + * 获得ftp链接 + * + * @param array $config ftp的配置信息: + *
      + *
    • server: ftp主机地址
    • + *
    • port: ftp链接端口号,默认为21
    • + *
    • user: ftp链接用户名
    • + *
    • pwd: ftp链接用户密码
    • + *
    • dir: ftp链接后切换的目录,默认为空
    • + *
    • timeout: ftp链接超时时间,默认为10秒
    • + *
    + * @return bool + */ + private function getConnection($config) + { + $this->initConfig($config); + $errno = 0; + $errstr = ''; + $this->conn = fsockopen($this->server, $this->port, $errno, $errstr, $this->timeout); + if (!$this->conn || !$this->checkcmd()) { + throw new WindFtpException("[ftp.WindSocketFtp.getConnection] $this->server:$this->port\r\nEroor:$errstr ($errno)!", WindFtpException::CONNECT_FAILED); + } + stream_set_timeout($this->conn, $this->timeout); + + if (!$this->sendcmd('USER', $this->user)) { + throw new WindFtpException('[ftp.WindSocketFtp.getConnection] '.$this->user, WindFtpException::LOGIN_FAILED); + } + if (!$this->sendcmd('PASS', $this->pwd)) { + throw new WindFtpException('[ftp.WindSocketFtp.getConnection] error password for '.$this->user, WindFtpException::LOGIN_FAILED); + } + + $this->initRootPath(); + + return true; + } + + /* (non-PHPdoc) + * @see AbstractWindFtp::pwd() + */ + protected function pwd() + { + $this->sendcmd('PWD', '', false); + if (!($path = $this->checkcmd(true)) || !preg_match('/^[0-9]{3} "(.+?)"/', $path, $matchs)) { + return '/'; + } + + return $matchs[1].((substr($matchs[1], -1) == '/') ? '' : '/'); + } + + /* (non-PHPdoc) + * @see AbstractWindFtp::upload() + */ + public function upload($localfile, $remotefile, $mode = 'I') + { + if (!in_array(($savedir = dirname($remotefile)), array('.', '/'))) { + $this->mkdirs($savedir); + } + $remotefile = $this->rootPath.WindSecurity::escapePath($remotefile); + if (!($fp = fopen($localfile, 'rb'))) { + throw new WindFtpException('[ftp.WindSocketFtp.upload] '.$localfile, WindFtpException::FILE_READ_FOBIDDEN); + } + $mode != 'I' && $mode = 'A'; + $this->delete($remotefile); + if (!$this->sendcmd('TYPE', $mode)) { + throw new WindFtpException('[ftp.WindSocketFtp.upload] '.$mode, WindFtpException::COMMUNICATE_TYPE_FAILED); + } + $this->openTmpConnection(); + $this->sendcmd('STOR', $remotefile); + while (!feof($fp)) { + fwrite($this->tmpConnection, fread($fp, 4096)); + } + fclose($fp); + $this->closeTmpConnection(); + + if (!$this->checkcmd()) { + throw new WindFtpException('[ftp.WindSocketFtp.upload] PUT', WindFtpException::COMMAND_FAILED); + } else { + $this->sendcmd('SITE CHMOD', base_convert(0644, 10, 8)." $remotefile"); + } + + return $this->size($remotefile); + } + + /* (non-PHPdoc) + * @see AbstractWindFtp::download() + */ + public function download($localfile, $remotefile = '', $mode = 'I') + { + $mode != 'I' && $mode = 'A'; + if (!$this->sendcmd('TYPE', $mode)) { + throw new WindFtpException('[ftp.WindSocketFtp.download] '.$mode, WindFtpException::COMMUNICATE_TYPE_FAILED); + } + $this->openTmpConnection(); + if (!$this->sendcmd('RETR', $remotefile)) { + $this->closeTmpConnection(); + + return false; + } + if (!($fp = fopen($localfile, 'wb'))) { + throw new WindFtpException('[ftp.WindSocketFtp.download] '.$localfile, WindFtpException::FILE_READ_FOBIDDEN); + } + while (!feof($this->tmpConnection)) { + fwrite($fp, fread($this->tmpConnection, 4096)); + } + fclose($fp); + $this->closeTmpConnection(); + + if (!$this->checkcmd()) { + throw new WindFtpException('[ftp.WindSocketFtp.download] GET', WindFtpException::COMMAND_FAILED); + } + + return true; + } + + /* (non-PHPdoc) + * @see AbstractWindFtp::size() + */ + public function size($file) + { + $this->sendcmd('SIZE', $file, false); + if (!($size_port = $this->checkcmd(true))) { + throw new WindFtpException('[ftp.WindSocketFtp.size] SIZE', WindFtpException::COMMAND_FAILED); + } + + return preg_replace("/^[0-9]{3} ([0-9]+)\r\n/", '\\1', $size_port); + } + + /* (non-PHPdoc) + * @see AbstractWindFtp::delete() + */ + public function delete($file) + { + return $this->sendcmd('DELE', $this->rootPath.WindSecurity::escapePath($file)); + } + + /* (non-PHPdoc) + * @see AbstractWindFtp::rename() + */ + public function rename($oldname, $newname) + { + if (!in_array(($savedir = dirname($newname)), array('.', '/'))) { + $this->mkdirs($savedir); + } + $oldname = $this->rootPath.WindSecurity::escapeDir($oldname); + $this->sendcmd('RNFR', $oldname); + + return $this->sendcmd('RNTO', $newname); + } + + /* (non-PHPdoc) + * @see AbstractWindFtp::mkdir() + */ + public function mkdir($dir) + { + $base777 = base_convert(0777, 10, 8); + $result = $this->sendcmd('MKD', $dir); + + return $this->sendcmd('SITE CHMOD', "$base777 $dir"); + } + + /* (non-PHPdoc) + * @see AbstractWindFtp::changeDir() + */ + public function changeDir($dir) + { + $dir = (($dir[0] != '/') ? '/' : '').$dir; + if ($dir !== '/' && substr($dir, -1) == '/') { + $dir = substr($dir, 0, -1); + } + if (!$this->sendcmd('CWD', $dir)) { + throw new WindFtpException('[ftp.WindSocketFtp.changeDir] '.$dir, WindFtpException::COMMAND_FAILED_CWD); + } + + return true; + } + + /* (non-PHPdoc) + * @see AbstractWindFtp::fileList() + */ + public function fileList($dir = '') + { + $this->openTmpConnection(); + $this->sendcmd('NLST', $dir); + $list = array(); + while (!feof($this->tmpConnection)) { + $list[] = preg_replace('/[\r\n]/', '', fgets($this->tmpConnection, 512)); + } + $this->closeTmpConnection(); + if (!$this->checkcmd(true)) { + throw new WindFtpException('[ftp.WindSocketFtp.fileList] LIST', WindFtpException::COMMAND_FAILED); + } + + return $list; + } + + /* (non-PHPdoc) + * @see AbstractWindFtp::close() + */ + public function close() + { + if (!$this->conn) { + return false; + } + if (!$this->sendcmd('QUIT') || !fclose($this->conn)) { + throw new WindFtpException('[ftp.WindSocketFtp.fileList] QUIT', WindFtpException::COMMAND_FAILED); + } + + return true; + } + + /** + * 发送ftp处理命令 + * + * @param string $cmd 待发送的命令 + * @param string $args 命令参数 + * @param bool $check 是否需要检查返回状态,默认为true需要检查 + * @return bool 如果检查命令发送失败则返回false,否则返回true + */ + private function sendcmd($cmd, $args = '', $check = true) + { + !empty($args) && $cmd .= " $args"; + fwrite($this->conn, "$cmd\r\n"); + if ($check === true && !$this->checkcmd()) { + return false; + } + + return true; + } + + /** + * 检查命令状态 + * + * @param bool $return 是否需要返回命令状态信息,默认为false,不许要返回 + * @return bool|string 检查命令已经发送成功,则返回true,失败则返回false,如果设置了参数$return=true并且命令状态正确的情况下将会返回状态信息 + */ + private function checkcmd($return = false) + { + $resp = $rcmd = ''; + $i = 0; + do { + $rcmd = fgets($this->conn, 512); + $resp .= $rcmd; + } while (++$i < 20 && !preg_match('/^\d{3}\s/is', $rcmd)); + + if (!preg_match('/^[123]/', $rcmd)) { + return false; + } + + return $return ? $resp : true; + } + + /** + * 打开临时链接句柄 + * + * @return bool 如果打开成功返回true + */ + private function openTmpConnection() + { + $this->sendcmd('PASV', '', false); + if (!($ip_port = $this->checkcmd(true))) { + throw new WindFtpException('[ftp.WindSocketFtp.openTmpConnection] PASV', WindFtpException::COMMAND_FAILED); + } + if (!preg_match('/[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]+,[0-9]+/', $ip_port, $temp)) { + throw new WindFtpException('[ftp.WindSocketFtp.openTmpConnection] '.$ip_port, WindFtpException::COMMAND_FAILED_PASS_PORT); + } + $temp = explode(',', $temp[0]); + $server_ip = "$temp[0].$temp[1].$temp[2].$temp[3]"; + $server_port = $temp[4] * 256 + $temp[5]; + if (!$this->tmpConnection = fsockopen($server_ip, $server_port, $errno, $errstr, $this->timeout)) { + throw new WindFtpException("[ftp.WindSocketFtp.openTmpConnection] {$server_ip}:{$server_port}\r\nError:{$errstr} ({$errno})", WindFtpException::OPEN_DATA_CONNECTION_FAILED); + } + stream_set_timeout($this->tmpConnection, $this->timeout); + + return true; + } + + /** + * 关闭临时链接对象 + * + * @return bool 关闭成功返回true,失败返回false + */ + private function closeTmpConnection() + { + return fclose($this->tmpConnection); + } } -?> \ No newline at end of file diff --git a/wind/ftp/exception/WindFtpException.php b/wind/ftp/exception/WindFtpException.php new file mode 100644 index 00000000..d301eb3c --- /dev/null +++ b/wind/ftp/exception/WindFtpException.php @@ -0,0 +1,47 @@ + + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id: WindFtpEcxeption.php 1532 2011-9-20下午02:16:54 xiaoxiao $ + * @package ftp + */ +class WindFtpException extends WindException +{ + const CONNECT_FAILED = 1100; + const LOGIN_FAILED = 1101; + const LOGIN_FAILED_PASS_ERROR = 1102; + + const FILE_FOBIDDEN = 1110; + const FILE_READ_FOBIDDEN = 1115; + const COMMAND_FAILED = 1120; + const COMMAND_FAILED_COMMUNICATE_TYPE = 1121; + const COMMAND_FAILED_CWD = 1122; + const COMMAND_FAILED_PASS_PORT = 1123; + + const OPEN_DATA_CONNECTION_FAILED = 1130; + + + /* (non-PHPdoc) + * @see WindException::messageMapper() + */ + protected function messageMapper($code) + { + $messages = array( + self::CONNECT_FAILED => 'Cannot connect to $message', + self::LOGIN_FAILED => 'User error! \'$message\' login error!', + self::LOGIN_FAILED_PASS_ERROR => 'Password error! \'$message\'', + self::FILE_FOBIDDEN => 'File error! The type of \'$message\' is fobidden!', + self::FILE_READ_FOBIDDEN => 'File read error! Please check the right of the \'$message\'', + self::COMMAND_FAILED => 'Command \'$message\' failed! Please check command!', + self::COMMAND_FAILED_COMMUNICATE_TYPE => 'Command TYPE failed! Can not set the mode \'$message\'. Please check it!', + self::COMMAND_FAILED_CWD => 'Command CWD failed! Cannot changes the current directory to \'$message\'!', + self::COMMAND_FAILED_PASS_PORT => 'Command PASS Failed! Illegal ip-port format \'$message\'!', + self::OPEN_DATA_CONNECTION_FAILED => 'Cannot open data connection to $message', + ); + + return isset($messages[$code]) ? $messages[$code] : '$message'; + } +} diff --git a/wind/http/IWindHttpContainer.php b/wind/http/IWindHttpContainer.php index cf4ee72a..5e25497b 100644 --- a/wind/http/IWindHttpContainer.php +++ b/wind/http/IWindHttpContainer.php @@ -1,7 +1,7 @@ * 1. set 向容器中设置值 * 2. get 获取内容值 @@ -11,42 +11,39 @@ * @author Qiong Wu 2011-10-19 * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: IWindHttpContainer.php 3113 2011-11-11 07:28:09Z yishuo $ * @package http */ -interface IWindHttpContainer { - - /** - * 向容器中设置值 - * - * @param string $key - * @param mixed $value - * @return boolean - */ - public function set($key, $value); +interface IWindHttpContainer +{ + /** + * 向容器中设置值 + * + * @param string $key + * @param mixed $value + * @return bool + */ + public function set($key, $value); - /** - * 获取容器中的内容值 - * - * @param string $key - */ - public function get($key); + /** + * 获取容器中的内容值 + * + * @param string $key + */ + public function get($key); - /** - * 删除容器中的值 - * - * @param string $key - */ - public function delete($key); - - /** - * 检测变量是否已经被注册 - * - * @param string $key 需要进行判断的建名 - * @return boolean 如果已经被注册则返回true,否则返回false - */ - public function isRegistered($key); + /** + * 删除容器中的值 + * + * @param string $key + */ + public function delete($key); + /** + * 检测变量是否已经被注册 + * + * @param string $key 需要进行判断的建名 + * @return bool 如果已经被注册则返回true,否则返回false + */ + public function isRegistered($key); } - -?> \ No newline at end of file diff --git a/wind/http/cookie/WindNormalCookie.php b/wind/http/cookie/WindNormalCookie.php index f92910bf..82470c75 100644 --- a/wind/http/cookie/WindNormalCookie.php +++ b/wind/http/cookie/WindNormalCookie.php @@ -1,142 +1,156 @@ - - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ + + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id: WindNormalCookie.php 3583 2012-05-28 03:35:10Z yishuo $ * @package http - * @subpackage cookie - */ -class WindNormalCookie extends WindModule implements IWindHttpContainer { - protected $prefix = null; - protected $encode = false; - protected $path = null; - protected $domain = null; - protected $secure = false; - protected $httponly = false; - - /** - * 构造函数 - * - * 根据传入的cookie数据初始化cookie数据 - * - * @param boolean $encode 是否使用 MIME base64 对数据进行编码,默认是false即不进行编码 - * @param string $prefix cookie前缀,默认为null即没有前缀 - * @param string $path cookie保存的路径,默认为null即采用默认 - * @param string $domain cookie所属域,默认为null即不设置 - * @param boolean $secure 是否安全连接,默认为false即不采用安全链接 - * @param boolean $httponly 是否可通过客户端脚本访问,默认为false即客户端脚本可以访问cookie - * @return void - */ - public function __construct($prefix = null, $encode = false, $path = null, $domain = null, $secure = false, $httponly = false) { - $this->prefix = $prefix; - $this->encode = $encode; - $this->domain = $domain; - $this->path = $path; - $this->secure = $secure; - $this->httponly = $httponly; - } - - /** - * 配置设置 - * - * @param array|string $config - * @see WindModule::setConfig() - * @return void - */ - public function setConfig($config) { - parent::setConfig($config); - $this->prefix = $this->getConfig('prefix'); - $this->encode = $this->getConfig('encode'); - $this->domain = $this->getConfig('domain'); - $this->path = $this->getConfig('path'); - $this->secure = $this->getConfig('secure'); - $this->httponly = $this->getConfig('httponly'); - } - - /** - * 设置cookie - * - * @param string $name - * @param mixed $value - * @param int|null $expires 过期时间 - * @return boolean - */ - public function set($name, $value, $expires = null) { - $this->prefix && $name = $this->prefix . $name; - return WindCookie::set($name, $value, $this->encode, $expires, $this->path, $this->domain, - $this->secure, $this->httponly); - } - - /** - * 获取cookie值 - * - * @param string $name - * @return void - */ - public function get($name) { - $this->prefix && $name = $this->prefix . $name; - return WindCookie::get($name, $this->encode); - } - - /** - * 移除cookie值 - * - * @param string $name - * @return boolean - * @see IWindHttpContainer::delete() - */ - public function delete($name) { - $this->prefix && $name = $this->prefix . $name; - return WindCookie::delete($name); - } - - /* (non-PHPdoc) - * @see IWindHttpContainer::isRegistered() - */ - public function isRegistered($name) { - $this->prefix && $name = $this->prefix . $name; - return WindCookie::exist($name); - } - - /** - * 移除全部cookie值 - * - * @return boolean - */ - public function deleteAll() { - return WindCookie::deleteAll(); - } - - /** - * 判断cookie值是否存在 - * - * @param string $name - */ - public function exist($name) { - $this->prefix && $name = $this->prefix . $name; - return WindCookie::exist($name); - } - - /** - * 获取cookie的域 - * - * @return string 获得cookie域 - */ - public function getDomain() { - return $this->domain; - } - - /** - * 获取cookie的路径 - * - * @return string 获得cookie保存路径 - */ - public function getPath() { - return $this->path; - } -} \ No newline at end of file + * @subpackage cookie + */ +class WindNormalCookie extends WindModule implements IWindHttpContainer +{ + protected $prefix = null; + protected $encode = false; + protected $path = null; + protected $domain = null; + protected $secure = false; + protected $httponly = false; + + /** + * 构造函数 + * + * 根据传入的cookie数据初始化cookie数据 + * + * @param bool $encode 是否使用 MIME base64 对数据进行编码,默认是false即不进行编码 + * @param string $prefix cookie前缀,默认为null即没有前缀 + * @param string $path cookie保存的路径,默认为null即采用默认 + * @param string $domain cookie所属域,默认为null即不设置 + * @param bool $secure 是否安全连接,默认为false即不采用安全链接 + * @param bool $httponly 是否可通过客户端脚本访问,默认为false即客户端脚本可以访问cookie + */ + public function __construct($prefix = null, $encode = false, $path = null, $domain = null, $secure = false, $httponly = false) + { + $this->prefix = $prefix; + $this->encode = $encode; + $this->domain = $domain; + $this->path = $path; + $this->secure = $secure; + $this->httponly = $httponly; + } + + /** + * 配置设置 + * + * @param array|string $config + * @see WindModule::setConfig() + */ + public function setConfig($config) + { + parent::setConfig($config); + $this->prefix = $this->getConfig('prefix'); + $this->encode = $this->getConfig('encode'); + $this->domain = $this->getConfig('domain'); + $this->path = $this->getConfig('path'); + $this->secure = $this->getConfig('secure'); + $this->httponly = $this->getConfig('httponly'); + } + + /** + * 设置cookie + * + * @param string $name + * @param mixed $value + * @param int|null $expires 过期时间 + * @return bool + */ + public function set($name, $value, $expires = null) + { + $this->prefix && $name = $this->prefix.$name; + + return WindCookie::set($name, $value, $this->encode, $expires, $this->path, $this->domain, + $this->secure, $this->httponly); + } + + /** + * 获取cookie值 + * + * @param string $name + */ + public function get($name) + { + $this->prefix && $name = $this->prefix.$name; + + return WindCookie::get($name, $this->encode); + } + + /** + * 移除cookie值 + * + * @param string $name + * @return bool + * @see IWindHttpContainer::delete() + */ + public function delete($name) + { + $this->prefix && $name = $this->prefix.$name; + + return WindCookie::delete($name); + } + + /* (non-PHPdoc) + * @see IWindHttpContainer::isRegistered() + */ + public function isRegistered($name) + { + $this->prefix && $name = $this->prefix.$name; + + return WindCookie::exist($name); + } + + /** + * 移除全部cookie值 + * + * @return bool + */ + public function deleteAll() + { + return WindCookie::deleteAll(); + } + + /** + * 判断cookie值是否存在 + * + * @param string $name + */ + public function exist($name) + { + $this->prefix && $name = $this->prefix.$name; + + return WindCookie::exist($name); + } + + /** + * 获取cookie的域 + * + * @return string 获得cookie域 + */ + public function getDomain() + { + return $this->domain; + } + + /** + * 获取cookie的路径 + * + * @return string 获得cookie保存路径 + */ + public function getPath() + { + return $this->path; + } +} diff --git a/wind/http/mime/WindMimeType.php b/wind/http/mime/WindMimeType.php index 345941be..22439cd9 100644 --- a/wind/http/mime/WindMimeType.php +++ b/wind/http/mime/WindMimeType.php @@ -7,38 +7,40 @@ * @package http * @subpackage mime */ -class WindMimeType { - /** - * @var array - */ - protected static $mimes = null; +class WindMimeType +{ + /** + * @var array + */ + protected static $mimes = null; - /** - * 根据内容的类型返回mime类型 - * - * @param string $type - * @return array - */ - public static function getMime($type) { - if (self::$mimes === null) { - self::$mimes = @include (Wind::getRealPath('WIND:http.mime.mime', false)); - } - return isset(self::$mimes[$type]) ? self::$mimes[$type] : ''; - } + /** + * 根据内容的类型返回mime类型 + * + * @param string $type + * @return array + */ + public static function getMime($type) + { + if (self::$mimes === null) { + self::$mimes = @include Wind::getRealPath('WIND:http.mime.mime', false); + } - /** - * 根据请求的mime类型获得返回内容类型 - * - * @param string $mime mime类型 - * @return string - */ - public static function getType($mime) { - if (self::$mimes === null) { - self::$mimes = @include (Wind::getRealPath('WIND:http.mime.mime.php', true)); - } - return array_search($mime, self::$mimes); - } + return isset(self::$mimes[$type]) ? self::$mimes[$type] : ''; + } -} + /** + * 根据请求的mime类型获得返回内容类型 + * + * @param string $mime mime类型 + * @return string + */ + public static function getType($mime) + { + if (self::$mimes === null) { + self::$mimes = @include Wind::getRealPath('WIND:http.mime.mime.php', true); + } -?> \ No newline at end of file + return array_search($mime, self::$mimes); + } +} diff --git a/wind/http/session/WindSession.php b/wind/http/session/WindSession.php index 24f3642e..0d791613 100644 --- a/wind/http/session/WindSession.php +++ b/wind/http/session/WindSession.php @@ -1,5 +1,6 @@ * 【使用】调用时使用: *
    - * $session = Wind::getApp()->getComponent('WindSession');
    - * 
    + * $session = Wind::getComponent('WindSession');
    + *
      * $session->set('name', 'test');    //等同:$_SESSION['name'] = 'test';
      * echo $session->get('name');       //等同:echo $_SESSION['name'];
    - * 
    + *
      * $session->delete('name');         //等同: unset($_SESSION['name');
      * echo $session->getCurrentName();     //等同: echo session_name();
      * echo $session->getCurrentId();       //等同: echo session_id();
    @@ -36,151 +37,160 @@
      * 'destroy' => 'commit',
      * ),
      * 
    - * + * * * @author xiaoxia.xu * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindSession.php 3791 2012-10-30 04:01:29Z liusanbian $ * @package http * @subpackage session */ -class WindSession extends WindModule implements IWindHttpContainer { +class WindSession extends WindModule implements IWindHttpContainer +{ + /** + * 构造函数 + * + * @param AbstractWindCache $dataStoreHandler 数据缓存对象,默认为null + * @param object $sessionHandler session操作设置类,默认为null + */ + public function __construct($dataStoreHandler = null, $sessionHandler = null) + { + $this->setDataStoreHandler($dataStoreHandler, $sessionHandler); + } - /** - * 构造函数 - * - * @param AbstractWindCache $dataStoreHandler 数据缓存对象,默认为null - * @param object $sessionHandler session操作设置类,默认为null - * @return void - */ - public function __construct($dataStoreHandler = null, $sessionHandler = null) { - $this->setDataStoreHandler($dataStoreHandler, $sessionHandler); - } + /** + * 开启session + * + */ + public function start() + { + '' === $this->getCurrentId() && session_start(); + } - /** - * 开启session - * - * @return void - */ - public function start() { - '' === $this->getCurrentId() && session_start(); - } + /** + * 设置数据 + * + * @param string $key 保存在session中的键名 + * @param mixed $value 保存在session中的值 + */ + public function set($key, $value) + { + $key && $_SESSION[$key] = $value; + } - /** - * 设置数据 - * - * @param string $key 保存在session中的键名 - * @param mixed $value 保存在session中的值 - * @return void - */ - public function set($key, $value) { - $key && $_SESSION[$key] = $value; - } + /** + * 获得数据 + * + * @param string $key 保存在session中的键名 + * @return mixed 返回保存在session中该键名对应的键值 + */ + public function get($key) + { + return $this->isRegistered($key) ? $_SESSION[$key] : ''; + } - /** - * 获得数据 - * - * @param string $key 保存在session中的键名 - * @return mixed 返回保存在session中该键名对应的键值 - */ - public function get($key) { - return $this->isRegistered($key) ? $_SESSION[$key] : ''; - } + /** + * 删除数据 + * + * @param string $key + */ + public function delete($key) + { + $_SESSION[$key] = null; + unset($_SESSION[$key]); - /** - * 删除数据 - * - * @param string $key - */ - public function delete($key) { - $_SESSION[$key] = null; - unset($_SESSION[$key]); - return true; - } + return true; + } - /** - * 清除会话信息 - * - * @return boolean - */ - public function destroy() { - return session_destroy(); - } + /** + * 清除会话信息 + * + * @return bool + */ + public function destroy() + { + return session_destroy(); + } - /** - * 检测变量是否已经被注册 - * - * @param string $key 需要进行判断的建名 - * @return boolean 如果已经被注册则返回true,否则返回false - */ - public function isRegistered($key) { - return isset($_SESSION[$key]); - } + /** + * 检测变量是否已经被注册 + * + * @param string $key 需要进行判断的建名 + * @return bool 如果已经被注册则返回true,否则返回false + */ + public function isRegistered($key) + { + return isset($_SESSION[$key]); + } - /** - * 获得当前session的名字 - * - * @return string - */ - public function getCurrentName() { - return session_name(); - } + /** + * 获得当前session的名字 + * + * @return string + */ + public function getCurrentName() + { + return session_name(); + } - /** - * 设置当前session的名字 - * - * @param string $name session的名字 - * @return boolean 设置成功将返回true - */ - public function setCurrentName($name) { - return session_name($name); - } + /** + * 设置当前session的名字 + * + * @param string $name session的名字 + * @return bool 设置成功将返回true + */ + public function setCurrentName($name) + { + return session_name($name); + } - /** - * 获得sessionId - * - * @return string - */ - public function getCurrentId() { - return session_id(); - } + /** + * 获得sessionId + * + * @return string + */ + public function getCurrentId() + { + return session_id(); + } - /** - * 设置当前session的Id - * - * @param string $id 需要设置的id名 - * @return boolean 设置成功返回true - */ - public function setCurrentId($id) { - return session_id($id); - } + /** + * 设置当前session的Id + * + * @param string $id 需要设置的id名 + * @return bool 设置成功返回true + */ + public function setCurrentId($id) + { + return session_id($id); + } - /** - * 写入session之后关闭session - * - * 同session_write_close - * - * @return void - */ - public function commit() { - return session_commit(); - } + /** + * 写入session之后关闭session + * + * 同session_write_close + * + */ + public function commit() + { + return session_commit(); + } - /** - * 设置链接对象 - * - * @param AbstractWindCache $handler session数据的缓存介质 - * @param object $sessionHandler session操作接口的定义类 - */ - public function setDataStoreHandler($dataStoreHandler = null, $sessionHandler = null) { - if ($dataStoreHandler) { - if ($sessionHandler === null) { - Wind::import('WIND:http.session.handler.WindSessionHandler'); - $sessionHandler = new WindSessionHandler(); - } - $sessionHandler->registerHandler($dataStoreHandler); - } - $this->start(); - } -} \ No newline at end of file + /** + * 设置链接对象 + * + * @param AbstractWindCache $handler session数据的缓存介质 + * @param object $sessionHandler session操作接口的定义类 + */ + public function setDataStoreHandler($dataStoreHandler = null, $sessionHandler = null) + { + if ($dataStoreHandler) { + if ($sessionHandler === null) { + $sessionHandler = new WindSessionHandler(); + } + $sessionHandler->registerHandler($dataStoreHandler); + } + $this->start(); + } +} diff --git a/wind/http/session/handler/WindSessionHandler.php b/wind/http/session/handler/WindSessionHandler.php index b4b71e31..eaea6b89 100644 --- a/wind/http/session/handler/WindSessionHandler.php +++ b/wind/http/session/handler/WindSessionHandler.php @@ -5,58 +5,66 @@ * @author xiaoxia.xu * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindSessionHandler.php 2973 2011-10-15 19:22:48Z yishuo $ * @package http * @subpackage session.handler */ -class WindSessionHandler extends AbstractWindSessionHandler { +class WindSessionHandler extends AbstractWindSessionHandler +{ + /* (non-PHPdoc) + * @see AbstractWindSessionHandler::open() + */ + public function open($savePath, $sessionName) + { + if ('0' == ($expire = $this->dataStore->getExpire())) { + $lifeTime = get_cfg_var('session.gc_maxlifetime'); + $this->dataStore->setExpire((int) $lifeTime); + } else { + session_cache_expire($expire); + } - /* (non-PHPdoc) - * @see AbstractWindSessionHandler::open() - */ - public function open($savePath, $sessionName) { - if ('0' == ($expire = $this->dataStore->getExpire())) { - $lifeTime = get_cfg_var("session.gc_maxlifetime"); - $this->dataStore->setExpire((int) $lifeTime); - } else - session_cache_expire($expire); - return true; - } + return true; + } - /* (non-PHPdoc) - * @see AbstractWindSessionHandler::close() - */ - public function close() { - return true; - } + /* (non-PHPdoc) + * @see AbstractWindSessionHandler::close() + */ + public function close() + { + return true; + } - /* (non-PHPdoc) - * @see AbstractWindSessionHandler::write() - */ - public function write($sessID, $sessData) { - return $this->dataStore->set($sessID, $sessData); - } + /* (non-PHPdoc) + * @see AbstractWindSessionHandler::write() + */ + public function write($sessID, $sessData) + { + return $this->dataStore->set($sessID, $sessData); + } - /* (non-PHPdoc) - * @see AbstractWindSessionHandler::read() - */ - public function read($sessID) { - return $this->dataStore->get($sessID); - } + /* (non-PHPdoc) + * @see AbstractWindSessionHandler::read() + */ + public function read($sessID) + { + return $this->dataStore->get($sessID); + } - /* (non-PHPdoc) - * @see AbstractWindSessionHandler::gc() - */ - public function gc($maxlifetime) { - return true; - } + /* (non-PHPdoc) + * @see AbstractWindSessionHandler::gc() + */ + public function gc($maxlifetime) + { + return true; + } - /* (non-PHPdoc) - * @see AbstractWindSessionHandler::destroy() - */ - public function destroy($sessID) { - return $this->dataStore->delete($sessID); - } + /* (non-PHPdoc) + * @see AbstractWindSessionHandler::destroy() + */ + public function destroy($sessID) + { + return $this->dataStore->delete($sessID); + } } /** @@ -65,96 +73,93 @@ public function destroy($sessID) { * @author xiaoxia.xu * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindSessionHandler.php 2973 2011-10-15 19:22:48Z yishuo $ * @package http * @subpackage session.handler */ -abstract class AbstractWindSessionHandler { - /** - * 保存session数据的实例 - * - * @var AbstractWindCache - */ - protected $dataStore = null; +abstract class AbstractWindSessionHandler +{ + /** + * 保存session数据的实例 + * + * @var AbstractWindCache + */ + protected $dataStore = null; - /** - * 在开始会话时调用初始化会话信息 - * - * 用以从从保存的介质中获取session数据 - * - * @param string $savePath 保存的地址 - * @param string $sessionName 会话的名字 - * @return boolean - */ - abstract public function open($savePath, $sessionName); + /** + * 在开始会话时调用初始化会话信息 + * + * 用以从从保存的介质中获取session数据 + * + * @param string $savePath 保存的地址 + * @param string $sessionName 会话的名字 + * @return bool + */ + abstract public function open($savePath, $sessionName); - /** - * 关闭会话存储存储机制 - * - * 在页面执行完的时候执行 - * - * @return boolean - */ - abstract public function close(); + /** + * 关闭会话存储存储机制 + * + * 在页面执行完的时候执行 + * + * @return bool + */ + abstract public function close(); - /** - * 将sessionID对应的数据写到存储 - * - * 在sessionClose之前执行写入session数据的 - * - * @param string $sessID 会话ID - * @param mixed $sessData 该会话产生的数据 - * @return void - */ - abstract public function write($sessID, $sessData); + /** + * 将sessionID对应的数据写到存储 + * + * 在sessionClose之前执行写入session数据的 + * + * @param string $sessID 会话ID + * @param mixed $sessData 该会话产生的数据 + */ + abstract public function write($sessID, $sessData); - /** - * 从存储中装载session数据 - * - * 在执行session_start的时候执行在open之后 - * - * @param string $sessid 会话ID - * @return void - */ - abstract public function read($sessID); + /** + * 从存储中装载session数据 + * + * 在执行session_start的时候执行在open之后 + * + * @param string $sessid 会话ID + */ + abstract public function read($sessID); - /** - * 对存储系统中的数据进行垃圾收集 - * - * 在执行session过期策略的时候执行,注意,session的过期并不是时时的,需要根据php.ini中的配置项: - * session.gc_probability = 1 - * session.gc_divisor = 1000 - * 执行的概率是gc_probability/gc_divisor . - * session.gc_maxlifetime = 1440 设置的session的过期时间 - * - * @param int $maxlifetime 过期时间单位秒 - * @return void - */ - abstract public function gc($maxlifetime); + /** + * 对存储系统中的数据进行垃圾收集 + * + * 在执行session过期策略的时候执行,注意,session的过期并不是时时的,需要根据php.ini中的配置项: + * session.gc_probability = 1 + * session.gc_divisor = 1000 + * 执行的概率是gc_probability/gc_divisor . + * session.gc_maxlifetime = 1440 设置的session的过期时间 + * + * @param int $maxlifetime 过期时间单位秒 + */ + abstract public function gc($maxlifetime); - /** - * 销毁与指定的会话ID相关联的数据 - * - * 在执行session_destroy的时候执行。 - * - * @param string $sessID 会话ID - * @return void - */ - abstract public function destroy($sessID); + /** + * 销毁与指定的会话ID相关联的数据 + * + * 在执行session_destroy的时候执行。 + * + * @param string $sessID 会话ID + */ + abstract public function destroy($sessID); - /** - * 设置session的存储方法及注册session中各个handler - * - * @param AbstractWindCache $dataStore 存储方式 - * @return void - */ - public function registerHandler($dataStore) { - if (!$dataStore instanceof AbstractWindCache) { - throw new WindException('[http.session.WindSessionHandler.registerHandler] register session save handler fail.', WindException::ERROR_PARAMETER_TYPE_ERROR); - } - $this->dataStore = $dataStore; - session_set_save_handler(array($this, 'open'), array($this, 'close'), array($this, 'read'), array( - $this, - 'write'), array($this, 'destroy'), array($this, 'gc')); - } -} \ No newline at end of file + /** + * 设置session的存储方法及注册session中各个handler + * + * @param AbstractWindCache $dataStore 存储方式 + */ + public function registerHandler($dataStore) + { + if (!$dataStore instanceof AbstractWindCache) { + throw new WindException('[http.session.WindSessionHandler.registerHandler] register session save handler fail.', WindException::ERROR_PARAMETER_TYPE_ERROR); + } + $this->dataStore = $dataStore; + session_set_save_handler(array($this, 'open'), array($this, 'close'), array($this, 'read'), array( + $this, + 'write', ), array($this, 'destroy'), array($this, 'gc')); + } +} diff --git a/wind/http/transfer/AbstractWindHttp.php b/wind/http/transfer/AbstractWindHttp.php index 67e49df5..e470d01f 100644 --- a/wind/http/transfer/AbstractWindHttp.php +++ b/wind/http/transfer/AbstractWindHttp.php @@ -1,205 +1,328 @@ - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package http - * @subpackage transfer +/** + * @author Qian Su + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id: AbstractWindHttp.php 3912 2013-01-22 06:36:30Z yishuo $ + * @package http + * @subpackage transfer */ -abstract class AbstractWindHttp { - /** - * 发送的cookie - * - * @var string - */ - protected $cookie = array(); - /** - * 发送的http头 - * - * @var array - */ - protected $header = array(); - /** - * 发送的数据 - * - * @var array - */ - protected $data = array(); - /** - * 错误信息 - * - * @var string - */ - protected $err = ''; - /** - * 错误编码 - * - * @var string - */ - protected $eno = 0; - - /** - * 超时时间 - * - * @var string - */ - protected $timeout = 0; - /** - * 访问的URL地址 - * - * @var array - */ - protected $url = ''; - - /** - * http连接句柄 - */ - protected $httpHandler = null; - - /** - * 声明受保护的构造函数,避免在类的外界实例化 - * - * @param string $url - * @param int $timeout - */ - public function __construct($url = '', $timeout = 30) { - $this->url = $url; - $this->timeout = $timeout; - $this->httpHandler = $this->createHttpHandler(); - } - - /** - * 发送请求底层操作 - * - * @param string $method 请求方式 - * @param array $options 额外的主求参数 - * @return string 返回页根据请求的响应页面 - */ - abstract public function send($method = self::GET, $options = array()); - - /** - * 发送post请求 - * - * @param array $data 请求的数据 - * @param array $header 发送请求的头 - * @param array $cookie 发送的cookie - * @param array $options 额外的请求头 - * @return string 返回页根据请求的响应页面 - */ - public function post($data = array(), $header = array(), $cookie = array(), $options = array()) { - $this->setHeader($header); - $this->setCookie($cookie); - $this->setData($data); - return $this->send('POST', $options); - } - - /** - * get方式传值 - * - * @param array $data 请求的数据 - * @param array $header 发送请求的头 - * @param array $cookie 发送的cookie - * @param array $options 额外的请求头 - * @return string 返回页根据请求的响应页面 - */ - public function get($data = array(), $header = array(), $cookie = array(), $options = array()) { - $this->setHeader($header); - $this->setCookie($cookie); - $this->setData($data); - return $this->send('GET', $options); - } - - /** - * 发送请求 - * - * @param string $key 请求的名称 - * @param string $value 请求的值 - * @return boolean - */ - abstract public function request($key, $value = null); - - /** - * 响应用户的请求 - * - * @return string 返回响应 - */ - abstract public function response(); - - /** - * 创建http链接句柄并返回 - * - * @return handler 返回链接句柄 - */ - abstract protected function createHttpHandler(); - - /** - * 取得http通信中的错误 - */ - abstract public function getError(); - - /** - * 关闭请求 - * - * @return boolean - */ - abstract public function close(); - - /** - * 打开一个http请求,返回 http请求句柄 - * - * @return httpResource - */ - protected function getHttpHandler() { - return $this->httpHandler; - } - - /** - * 清理链接 - */ - public function __destruct() { - $this->close(); - } - - /** - * 设置http头,支持单个值设置和批量设置 - * - * @param string|array $key - * @param string $value - * @return void - */ - public function setHeader($value, $key = null) { - if (is_array($value)) return $this->header = array_merge($this->header, $value); - - if ($key === null) $key = count($this->header); - if (!isset($this->header[$key])) $this->header[$key] = $value; - } - - /** - * 设置cookie,支持单个值设置和批量设置 - * - * @param string|array $key - * @param string $value - */ - public function setCookie($key, $value = null) { - if (!$key) return; - if (is_array($key)) - $this->cookie = array_merge($this->cookie, $key); - else - $this->cookie[$key] = $value; - } - - /** - * 设置data,支持单个值设置和批量设置 - * - * @param string|array $key - * @param string $value - */ - public function setData($key, $value = null) { - if (!$key) return; - if (is_array($key)) - $this->data = array_merge($this->data, $key); - else - $this->data[$key] = $value; - } -} \ No newline at end of file +abstract class AbstractWindHttp +{ + /** + * 发送的cookie + * + * @var string + */ + protected $cookie = array(); + /** + * 发送的http头 + * + * @var array + */ + protected $header = array(); + /** + * 发送的数据 + * + * @var array + */ + protected $data = array(); + + /** + * 错误信息 + * + * @var string + */ + protected $err = ''; + /** + * 错误编码 + * + * @var string + */ + protected $eno = 0; + /** + * 响应的状态信息 + * + * @var string + */ + protected $status; + + /** + * 超时时间 + * + * @var string + */ + protected $timeout = 0; + /** + * 访问的URL地址 + * + * @var array + */ + protected $url = ''; + /** + * 重定向次数 + * + * @var int + */ + protected $_maxRedirs = 1; + /** + * 是否支持重定向 + * + * @var bool + */ + protected $_redirects = false; + /** + * 是否读取头信息,false 不读取,true 读取 + * + * @var bool + */ + protected $_header = false; + /** + * 是否读取内容体信息,false 不读取,true 读取 + * + * @var bool + */ + protected $_body = true; + /** + * Enter description here ... + * + * @var unknown_type + */ + protected $_waitResponse = true; + + /** + * http连接句柄 + */ + protected $httpHandler = null; + + /** + * 声明受保护的构造函数,避免在类的外界实例化 + * + * @param string $url + * @param int $timeout + */ + public function __construct($url = '', $timeout = 30) + { + $this->url = $url; + $this->timeout = $timeout; + $this->httpHandler = $this->createHttpHandler(); + } + + /** + * 发送请求底层操作 + * + * @param string $method 请求方式 + * @param array $options 额外的主求参数 + * @return string 返回页根据请求的响应页面 + */ + abstract public function send($method = self::GET, $options = array()); + + /** + * 发送post请求 + * + * @param array $data 请求的数据 + * @param array $header 发送请求的头 + * @param array $cookie 发送的cookie + * @param array $options 额外的请求头 + * @return string 返回页根据请求的响应页面 + */ + public function post($data = array(), $header = array(), $cookie = array(), $options = array()) + { + $this->setHeader($header); + $this->setCookie($cookie); + $this->setData($data); + + return $this->send('POST', $options); + } + + /** + * get方式传值 + * + * @param array $data 请求的数据 + * @param array $header 发送请求的头 + * @param array $cookie 发送的cookie + * @param array $options 额外的请求头 + * @return string 返回页根据请求的响应页面 + */ + public function get($data = array(), $header = array(), $cookie = array(), $options = array()) + { + $this->setHeader($header); + $this->setCookie($cookie); + $this->setData($data); + + return $this->send('GET', $options); + } + + /** + * 发送请求 + * + * @param string $key 请求的名称 + * @param string $value 请求的值 + * @return bool + */ + abstract public function request($key, $value = null); + + /** + * 响应用户的请求 + * + * @return string 返回响应 + */ + abstract public function response(); + + /** + * 创建http链接句柄并返回 + * + * @return handler 返回链接句柄 + */ + abstract protected function createHttpHandler(); + + /** + * 取得http通信中的错误 + */ + abstract public function getError(); + + /** + * 关闭请求 + * + * @return bool + */ + abstract public function close(); + + /** + * 打开一个http请求,返回 http请求句柄 + * + * @return httpResource + */ + protected function getHttpHandler() + { + return $this->httpHandler; + } + + /** + * 清理链接 + */ + public function __destruct() + { + $this->close(); + } + + /** + * 设置http头,支持单个值设置和批量设置 + * + * @param string|array $key + * @param string $value + */ + public function setHeader($value, $key = null) + { + if (is_array($value)) { + return $this->header = array_merge($this->header, $value); + } + + if ($key === null) { + $key = count($this->header); + } + if (!isset($this->header[$key])) { + $this->header[$key] = $value; + } + } + + /** + * 设置cookie,支持单个值设置和批量设置 + * + * @param string|array $key + * @param string $value + */ + public function setCookie($key, $value = null) + { + if (!$key) { + return; + } + if (is_array($key)) { + $this->cookie = array_merge($this->cookie, $key); + } else { + $this->cookie[$key] = $value; + } + } + + /** + * 设置data,支持单个值设置和批量设置 + * + * @param string|array $key + * @param string $value + */ + public function setData($key, $value = null) + { + if (!$key) { + return; + } + if (is_array($key)) { + $this->data = array_merge($this->data, $key); + } else { + $this->data[$key] = $value; + } + } + + /** + * @param number $_maxRedirs + */ + public function setMaxRedirs($_maxRedirs) + { + $this->_maxRedirs = $_maxRedirs; + } + + /** + * @param bool $_redirects + */ + public function setRedirects($_redirects) + { + $this->_redirects = $_redirects; + } + + /** + * 设置响应信息中是否包含头信息 + * + * 默认不包含头信息 + * @param bool $_header + */ + public function setResponseHasHeader($_header) + { + $this->_header = $_header; + } + + /** + * 设置响应信息中是否包含内容体信息 + * + * 默认只包含内容体信息 + * @param bool $_body + */ + public function setResponseHasBody($_body) + { + $this->_body = $_body; + } + + /** + * @return string + */ + public function getStatus() + { + return $this->status; + } + + /** + * @return multitype: + */ + public function getUrl() + { + return $this->url; + } + + /** + * 是否等待响应 + * + * @param bool $_waitResponse + */ + public function setWaitResponse($_waitResponse) + { + $this->_waitResponse = $_waitResponse; + } +} diff --git a/wind/http/transfer/WindHttpCurl.php b/wind/http/transfer/WindHttpCurl.php index 6b7c2ec7..91ee11ec 100644 --- a/wind/http/transfer/WindHttpCurl.php +++ b/wind/http/transfer/WindHttpCurl.php @@ -1,96 +1,202 @@ - * @copyright ©2003-2103 phpwind.com - * @license http://www.phpwind.com/license.php - * @version $Id$ - * @package http - * @subpackage transfer + + +/** + * @author Qian Su + * @copyright ©2003-2103 phpwind.com + * @license http://www.phpwind.com/license.php + * @version $Id: WindHttpCurl.php 3928 2013-01-29 10:21:53Z yishuo $ + * @package http + * @subpackage transfer */ -final class WindHttpCurl extends AbstractWindHttp { - - /* (non-PHPdoc) - * @see AbstractWindHttp::createHttpHandler() - */ - protected function createHttpHandler() { - return curl_init(); - } - - /* (non-PHPdoc) - * @see AbstractWindHttp::request() - */ - public function request($name, $value = null) { - return curl_setopt($this->getHttpHandler(), $name, $value); - } - - /* (non-PHPdoc) - * @see AbstractWindHttp::response() - */ - public function response() { - return curl_exec($this->getHttpHandler()); - } - - /* (non-PHPdoc) - * @see AbstractWindHttp::close() - */ - public function close() { - if (null === $this->httpHandler) return; - curl_close($this->httpHandler); - $this->httpHandler = null; - } - - /* (non-PHPdoc) - * @see AbstractWindHttp::getError() - */ - public function getError() { - $this->err = curl_error($this->getHttpHandler()); - $this->eno = curl_errno($this->getHttpHandler()); - return $this->err ? $this->eno . ':' . $this->err : ''; - } - - /* (non-PHPdoc) - * @see AbstractWindHttp::send() - */ - public function send($method = 'GET', $options = array()) { - if ($this->data) { - switch (strtoupper($method)) { - case 'GET': - $_url = WindUrlHelper::argsToUrl($this->data); - $url = parse_url($this->url); - $this->url .= (isset($url['query']) ? '&' : '?') . $_url; - break; - case 'POST': - $this->request(CURLOPT_POST, 1); - $_url = WindUrlHelper::argsToUrl($this->data, false); - $this->request(CURLOPT_POSTFIELDS, $_url); - break; - default: - break; - } - } - - $this->request(CURLOPT_HEADER, 0); - $this->request(CURLOPT_FOLLOWLOCATION, 1); - $this->request(CURLOPT_RETURNTRANSFER, 1); - $this->request(CURLOPT_TIMEOUT, $this->timeout); - if ($options && is_array($options)) { - curl_setopt_array($this->getHttpHandler(), $options); - } - $_cookie = ''; - foreach ($this->cookie as $key => $value) { - $_cookie .= ($_cookie !== '' ? "" : "; ") . $key . "=" . $value; - } - $this->request(CURLOPT_COOKIE, $_cookie); - - $this->setHeader('Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.1)', 'User-Agent'); - $_header = array(); - foreach ($this->header as $key => $value) { - $_header[] = $key . ": " . $value; - } - $_header && $this->request(CURLOPT_HTTPHEADER, $_header); - $this->request(CURLOPT_URL, $this->url); - return $this->response(); - } -} - +final class WindHttpCurl extends AbstractWindHttp +{ + /** + * @return mixed + */ + public function getInfo() + { + return curl_getinfo($this->httpHandler); + } + + /* (non-PHPdoc) + * @see AbstractWindHttp::createHttpHandler() + */ + protected function createHttpHandler() + { + return curl_init(); + } + + /* (non-PHPdoc) + * @see AbstractWindHttp::request() + */ + public function request($name, $value = null) + { + return curl_setopt($this->getHttpHandler(), $name, $value); + } + + /* (non-PHPdoc) + * @see AbstractWindHttp::response() + */ + public function response() + { + return curl_exec($this->getHttpHandler()); + } + + /* (non-PHPdoc) + * @see AbstractWindHttp::close() + */ + public function close() + { + if (null === $this->httpHandler) { + return; + } + curl_close($this->httpHandler); + $this->httpHandler = null; + } + + /* (non-PHPdoc) + * @see AbstractWindHttp::getError() + */ + public function getError() + { + $this->err = curl_error($this->getHttpHandler()); + $this->eno = curl_errno($this->getHttpHandler()); + + return $this->err ? $this->eno.':'.$this->err : ''; + } + + /* (non-PHPdoc) + * @see AbstractWindHttp::send() + */ + public function send($method = 'GET', $options = array()) + { + if ($this->data) { + switch (strtoupper($method)) { + case 'GET': + $_url = WindUrlHelper::argsToUrl($this->data); + $url = parse_url($this->url); + $this->url .= (isset($url['query']) ? '&' : '?').$_url; + break; + case 'POST': + $this->request(CURLOPT_POST, 1); + $data = array(); + $this->_resolvedData($this->data, $data); + $this->request(CURLOPT_POSTFIELDS, $data); + break; + default: + break; + } + } + + $this->request(CURLOPT_HEADER, $this->_header); + $this->request(CURLOPT_NOBODY, !$this->_body); + $this->request(CURLOPT_TIMEOUT, $this->timeout); + $this->request(CURLOPT_FOLLOWLOCATION, 0); + $this->request(CURLOPT_RETURNTRANSFER, 1); + if ($options && is_array($options)) { + curl_setopt_array($this->httpHandler, $options); + } + if (!isset($options[CURLOPT_USERAGENT])) { + $this->request(CURLOPT_USERAGENT, + 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.1)'); + } + + $_cookie = ''; + foreach ($this->cookie as $key => $value) { + $_cookie .= ($_cookie !== '' ? '' : '; ').$key.'='.$value; + } + $this->request(CURLOPT_COOKIE, $_cookie); + + $_header = array(); + foreach ($this->header as $key => $value) { + $_header[] = $key.': '.$value; + } + $_header && $this->request(CURLOPT_HTTPHEADER, $_header); + $this->request(CURLOPT_URL, $this->url); + if (isset($options[CURLOPT_FOLLOWLOCATION])) { + $this->_redirects = $options[CURLOPT_FOLLOWLOCATION]; + } + if (isset($options[CURLOPT_MAXREDIRS])) { + $this->_maxRedirs = intval($options[CURLOPT_MAXREDIRS]); + } + $this->followLocation(); + + return $this->response(); + } + + /** + * 解析post data使其支持数组格式传递 + * + * @param array $args + * @param array $value + * @param string $key + * @return array + */ + private function _resolvedData($args, &$value, $key = null) + { + foreach ((array) $args as $_k => $_v) { + if ($key !== null) { + $_k = $key.'['.$_k.']'; + } + if (is_array($_v)) { + $this->_resolvedData($_v, $value, $_k); + } else { + $value[$_k] = $_v; + } + } + + return $value; + } + + /* (non-PHPdoc) + * @see AbstractWindHttp::getStatus() + */ + public function getStatus() + { + return curl_getinfo(CURLINFO_HTTP_CODE); + } + + /** + * url forward 兼容处理 + */ + private function followLocation() + { + $_safeMode = ini_get('safe_mode'); + if (ini_get('open_basedir') == '' && ($_safeMode == '' || strcasecmp($_safeMode, 'off') == 0)) { + return; + } + if (!$this->_redirects) { + return; + } + if ($this->_maxRedirs <= 0) { + return; + } + $maxRedirs = $this->_maxRedirs; + + $newurl = curl_getinfo($this->httpHandler, CURLINFO_EFFECTIVE_URL); + $rch = curl_copy_handle($this->httpHandler); + curl_setopt($rch, CURLOPT_HEADER, true); + curl_setopt($rch, CURLOPT_NOBODY, true); + curl_setopt($rch, CURLOPT_FORBID_REUSE, false); + curl_setopt($rch, CURLOPT_RETURNTRANSFER, true); + do { + curl_setopt($rch, CURLOPT_URL, $newurl); + $header = curl_exec($rch); + + if (curl_errno($rch)) { + $code = 0; + } else { + $code = curl_getinfo($rch, CURLINFO_HTTP_CODE); + if ($code == 301 || $code == 302) { + preg_match('/Location:(.*?)\n/', $header, $matches); + $newurl = trim(array_pop($matches)); + } else { + $code = 0; + } + } + } while ($code && --$maxRedirs); + curl_close($rch); + curl_setopt($this->httpHandler, CURLOPT_URL, $newurl); + } +} diff --git a/wind/http/transfer/WindHttpSocket.php b/wind/http/transfer/WindHttpSocket.php index 54254f3b..f8adcc11 100644 --- a/wind/http/transfer/WindHttpSocket.php +++ b/wind/http/transfer/WindHttpSocket.php @@ -1,113 +1,229 @@ - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package http - * @subpackage transfer + + +/** + * socket操作 + * + * @author Qian Su + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id: WindHttpSocket.php 3918 2013-01-23 10:37:40Z yishuo $ + * @package http + * @subpackage transfer */ -final class WindHttpSocket extends AbstractWindHttp { - private $host = ''; - private $port = 80; - private $path = ''; - private $query = ''; - - /* (non-PHPdoc) - * @see AbstractWindHttp::createHttpHandler() - */ - protected function createHttpHandler() { - $url = parse_url($this->url); - - $this->host = isset($url['host']) ? $url['host'] : ''; - $this->port = isset($url['port']) ? $url['port'] : 80; - $this->path = isset($url['path']) ? $url['path'] : '/'; - $this->query = isset($url['query']) ? '?' . $url['query'] : ''; - $this->path .= $this->query; - return fsockopen($this->host, $this->port, $this->eno, $this->err, $this->timeout); - } - - /* (non-PHPdoc) - * @see AbstractWindHttp::request() - */ - public function request($name, $value = null) { - return fputs($this->getHttpHandler(), ($value ? $name . ': ' . $value : $name)); - } - - /* (non-PHPdoc) - * @see AbstractWindHttp::response() - */ - public function response() { - $response = ''; - while (!feof($this->getHttpHandler())) { - $response .= fgets($this->getHttpHandler()); - } - return $response; - } - - /* (non-PHPdoc) - * @see AbstractWindHttp::close() - */ - public function close() { - if ($this->httpHandler === null) return; - fclose($this->httpHandler); - $this->httpHandler = null; - } - - /* (non-PHPdoc) - * @see AbstractWindHttp::getError() - */ - public function getError() { - return $this->err ? $this->eno . ':' . $this->err : ''; - } - - /* (non-PHPdoc) - * @see AbstractWindHttp::send() - */ - public function send($method = 'GET', $options = array()) { - $method = strtoupper($method); - if ($this->data) { - switch ($method) { - case 'GET': - $_url = WindUrlHelper::argsToUrl($this->data); - $getData = ($this->query ? $this->query . '&' : '?') . $_url; - $this->path .= $getData; - break; - case 'POST': - $postData = WindUrlHelper::argsToUrl($this->data, false); - $this->setHeader('application/x-www-form-urlencoded', 'Content-Type'); - $this->setHeader(strlen($postData) . "\r\n\r\n" . $postData, 'Content-Length'); - break; - default: - break; - } - } - - $this->setHeader($method . " " . $this->path . " HTTP/1.1"); - $this->setHeader($this->host, "Host"); - $this->setHeader('Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.1)', 'User-Agent'); - $this->setHeader('Close', 'Connection'); - if ($this->cookie) { - $_cookit = WindUrlHelper::argsToUrl($this->cookie, false, ';='); - $this->setHeader($_cookit, "Cookie"); - } - $options && $this->setHeader($options); - if (!empty($data)) $this->setHeader($data); - - $_request = ''; - foreach ($this->header as $key => $value) { - if (is_string($key)) { - $_request .= $key . ': ' . $value; - } elseif (is_int($key)) { - $_request .= $value; - } - $_request .= "\r\n"; - } - - $_request && $this->request($_request . "\r\n"); - return $this->response(); - } -} \ No newline at end of file +final class WindHttpSocket extends AbstractWindHttp +{ + private $host = ''; + private $port = 80; + private $path = ''; + private $query = ''; + private $responseHeader = array(); + + /* (non-PHPdoc) + * @see AbstractWindHttp::createHttpHandler() + */ + protected function createHttpHandler() + { + $url = parse_url($this->url); + + $this->host = isset($url['host']) ? $url['host'] : ''; + $this->port = isset($url['port']) ? $url['port'] : (isset($url['scheme']) ? ($url['scheme'] == 'https' ? 443 : 80) : 80); + $this->path = isset($url['path']) ? $url['path'] : '/'; + $this->query = isset($url['query']) ? '?'.$url['query'] : ''; + $this->path .= $this->query; + + if ($this->port == 443) { + $this->host = 'ssl:'.$this->host; + } + + return fsockopen($this->host, $this->port, $this->eno, $this->err, $this->timeout); + } + + /* (non-PHPdoc) + * @see AbstractWindHttp::request() + */ + public function request($name, $value = null) + { + return fwrite($this->httpHandler, ($value ? $name.': '.$value : $name)); + } + + /* (non-PHPdoc) + * @see AbstractWindHttp::response() + */ + public function response() + { + $response = $_body = ''; + $_start = $_header = true; + $_chunked = false; + $_len = $num = 0; + while (!feof($this->httpHandler)) { + $line = fgets($this->httpHandler, 4096); + if ($_start) { + $_start = false; + if (!preg_match('/HTTP\/(\\d\\.\\d)\\s*(\\d+)\\s*(.*)/', $line, $matchs)) { + $this->err = 'Status code line invalid: '.htmlentities($line); + + return false; + } + $this->status = $matchs[2]; + } + if ($_header) { + if (trim($line) == '') { + if (!$this->_body) { + break; + } + $_header = false; + } + $_chunked || $_chunked = (strcasecmp(trim($line), 'Transfer-Encoding: chunked') == 0); + if (!$this->_header) { + continue; + } + } elseif ($_chunked) { + if ($_len >= $num) { + $num = hexdec(trim($line)); + $line = ''; + $_len = 0; + } + $_len += strlen($line); + } + $response .= $line; + } + + return $response; + } + + /** + * 分块收取数据处理 + * + * @param string $data + * @return string + */ + private function _unchunk($data) + { + $fp = 0; + $len = strlen($data); + $outData = ''; + while ($fp < $len) { + $rawnum = substr($data, $fp, strpos(substr($data, $fp), "\r\n") + 2); + $num = hexdec(trim($rawnum)); + $fp += strlen($rawnum); + $chunk = substr($data, $fp, $num); + $outData .= $chunk; + $fp += strlen($chunk); + } + + return $outData; + } + + /* (non-PHPdoc) + * @see AbstractWindHttp::close() + */ + public function close() + { + if ($this->httpHandler === null) { + return; + } + fclose($this->httpHandler); + $this->httpHandler = null; + } + + /* (non-PHPdoc) + * @see AbstractWindHttp::getError() + */ + public function getError() + { + return $this->err ? $this->eno.':'.$this->err : ''; + } + + /* (non-PHPdoc) + * @see AbstractWindHttp::send() + */ + public function send($method = 'GET', $options = array()) + { + $this->followLocation(); + + $method = strtoupper($method); + if ($this->data) { + switch ($method) { + case 'GET': + $_url = WindUrlHelper::argsToUrl($this->data); + $getData = ($this->query ? '&' : '?').$_url; + $this->path .= $getData; + break; + case 'POST': + $postData = WindUrlHelper::argsToUrl($this->data, false); + $_header['Content-Type'] = 'application/x-www-form-urlencoded'; + $_header['Content-Length'] = strlen($postData); + $_body = $postData; + break; + default: + break; + } + } + + $this->setHeader($method.' '.$this->path.' HTTP/1.1'); + $this->setHeader($this->host.($this->port == 80 || $this->port == 443 ? '' : ':'.$this->port), 'Host'); + !empty($_header) && $this->setHeader($_header); + $this->setHeader('Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.1)', 'User-Agent'); + $this->setHeader('Close', 'Connection'); + if ($this->cookie) { + $_cookit = WindUrlHelper::argsToUrl($this->cookie, false, ';='); + $this->setHeader($_cookit, 'Cookie'); + } + $options && $this->setHeader($options); + + $_request = ''; + foreach ($this->header as $key => $value) { + if (is_string($key)) { + $_request .= $key.': '.$value; + } elseif (is_int($key)) { + $_request .= $value; + } + $_request .= "\r\n"; + } + $_request && $this->request($_request."\r\n"); + isset($_body) && $this->request($_body); + + return $this->_waitResponse ? $this->response() : true; + } + + /** + * url forward 兼容处理 + * 获取真正的请求链接,并初始化socket句柄 + * + * @param array $options + */ + private function followLocation() + { + if (!$this->_redirects) { + return; + } + if ($this->_maxRedirs <= 0) { + return; + } + $maxRedirs = $this->_maxRedirs; + $newurl = $this->url; + do { + /* @var $socket WindHttpSocket */ + $socket = new WindHttpSocket($newurl, $this->timeout); + $socket->setResponseHasBody(false); + $socket->setResponseHasHeader(true); + $header = $socket->send(); + $code = $socket->getStatus(); + $socket->close(); + + if ($code == 301 || $code == 302) { + preg_match('/Location:(.*?)\n/', $header, $matches); + $newurl = trim(array_pop($matches)); + } else { + $code = 0; + } + } while ($code && --$maxRedirs); + + if ($newurl == $this->url) { + return; + } + $this->url = $newurl; + $this->httpHandler = $this->createHttpHandler(); + } +} diff --git a/wind/http/transfer/WindHttpStream.php b/wind/http/transfer/WindHttpStream.php index 6eef1b90..705b1817 100644 --- a/wind/http/transfer/WindHttpStream.php +++ b/wind/http/transfer/WindHttpStream.php @@ -1,123 +1,186 @@ - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package http - * @subpackage transfer + + +/** + * @author Qian Su + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id: WindHttpStream.php 3912 2013-01-22 06:36:30Z yishuo $ + * @package http + * @subpackage transfer */ -final class WindHttpStream extends AbstractWindHttp { - /** - * @var string 字节流对象 - */ - private $context = null; - /** - * @var string 通信协议 - */ - private $wrapper = 'http'; - private $host = ''; - private $port = 80; - private $path = ''; - private $query = ''; +final class WindHttpStream extends AbstractWindHttp +{ + /** + * @var string 字节流对象 + */ + private $context = null; + /** + * @var string 通信协议 + */ + private $wrapper = 'http'; + private $host = ''; + private $port = 80; + private $path = ''; + private $query = ''; + + /** + * 设置通信协议 + * @param string $wrapper + */ + public function setWrapper($wrapper = 'http') + { + $this->wrapper = $wrapper; + } + + /* (non-PHPdoc) + * @see AbstractWindHttp::createHttpHandler() + */ + protected function createHttpHandler() + { + $url = parse_url($this->url); + isset($url['scheme']) && $this->wrapper = $url['scheme']; + isset($url['host']) && $this->host = $url['host']; + isset($url['path']) && $this->path = $url['path']; + isset($url['query']) && $this->query = $url['query']; + $this->context = stream_context_create(); + } + + /* (non-PHPdoc) + * @see AbstractWindHttp::request() + */ + public function request($name, $value = null) + { + return stream_context_set_option($this->context, $this->wrapper, $name, $value); + } + + /* (non-PHPdoc) + * @see AbstractWindHttp::response() + */ + public function response() + { + $response = ''; + if ($this->_header) { + $header = stream_get_meta_data($this->httpHandler); + $header = isset($header['wrapper_data']) ? $header['wrapper_data'] : array(); + foreach ($header as $value) { + $response .= $value."\r\n"; + } + } + if ($this->_body) { + $response && $response .= "\r\n"; + $response .= stream_get_contents($this->httpHandler); + } + + return $response; + } + + /** + * 释放资源 + */ + public function close() + { + if ($this->httpHandler) { + fclose($this->httpHandler); + $this->httpHandler = null; + $this->context = null; + } + } + + /* (non-PHPdoc) + * @see AbstractWindHttp::getError() + */ + public function getError() + { + return $this->err ? $this->eno.':'.$this->err : ''; + } + + /* (non-PHPdoc) + * @see AbstractWindHttp::send() + */ + public function send($method = 'GET', $options = array()) + { + $method = strtoupper($method); + if ($this->data) { + switch ($method) { + case 'GET': + $_url = WindUrlHelper::argsToUrl($this->data); + $this->url .= ($this->query ? '&' : '?').$_url; + break; + case 'POST': + $data = WindUrlHelper::argsToUrl($this->data, false); + $_header['Content-Type'] = 'application/x-www-form-urlencoded'; + $_header['Content-Length'] = strlen($data); + $_body = $data; + break; + default: + break; + } + } + $this->setHeader($this->host, 'Host'); + !empty($_header) && $this->setHeader($_header); + $this->setHeader('Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.1)', + 'User-Agent'); + $this->setHeader('Close', 'Connection'); + if ($options) { + $this->setHeader($options); + } + if ($this->cookie) { + $_cookie = WindUrlHelper::argsToUrl($this->cookie, false, ';='); + $this->setHeader($_cookie, 'Cookie'); + } + $_header = ''; + foreach ($this->header as $key => $value) { + $_header .= $key.': '.$value."\r\n"; + } + $_header && $this->request('header', $_header); + $this->request('follow_location', $this->_redirects); + $this->request('max_redirects', $this->_maxRedirs); + $this->request('method', $method); + $this->request('timeout', $this->timeout); + isset($_body) && $this->request('content', $_body); + $this->httpHandler = fopen($this->url, 'r', false, $this->context); + + return $this->_waitResponse ? $this->response() : true; + } + + /** + * url forward 兼容处理 + * 获取真正的请求链接,并初始化socket句柄 + * + * @param array $options + */ + private function followLocation() + { + if (!$this->_redirects) { + return; + } + if ($this->_maxRedirs <= 0) { + return; + } + $maxRedirs = $this->_maxRedirs; + $newurl = $this->url; + do { + /* @var $socket WindHttpStream */ + $handler = new WindHttpStream($newurl, $this->timeout); + $handler->setResponseHasBody(false); + $handler->setResponseHasHeader(true); + $header = $handler->send(); + $code = $handler->getStatus(); + $handler->close(); - /** - * 设置通信协议 - * @param string $wrapper - */ - public function setWrapper($wrapper = 'http') { - $this->wrapper = $wrapper; - } - - /* (non-PHPdoc) - * @see AbstractWindHttp::createHttpHandler() - */ - protected function createHttpHandler() { - $url = parse_url($this->url); - isset($url['scheme']) && $this->wrapper = $url['scheme']; - isset($url['host']) && $this->host = $url['host']; - isset($url['path']) && $this->path = $url['path']; - isset($url['query']) && $this->query = $url['query']; - $this->context = stream_context_create(); - } - - /* (non-PHPdoc) - * @see AbstractWindHttp::request() - */ - public function request($name, $value = null) { - return stream_context_set_option($this->context, $this->wrapper, $name, $value); - } - - /* (non-PHPdoc) - * @see AbstractWindHttp::response() - */ - public function response() { - $response = ''; - while (!feof($this->getHttpHandler())) { - $response .= fgets($this->getHttpHandler()); - } - return $response; - } + if ($code == 301 || $code == 302) { + preg_match('/Location:(.*?)\n/', $header, $matches); + $newurl = trim(array_pop($matches)); + } else { + $code = 0; + } + } while ($code && --$maxRedirs); - /** - * 释放资源 - */ - public function close() { - if ($this->httpHandler) { - fclose($this->httpHandler); - $this->httpHandler = null; - $this->context = null; - } - } - - /* (non-PHPdoc) - * @see AbstractWindHttp::getError() - */ - public function getError() { - return $this->err ? $this->eno . ':' . $this->err : ''; - } - - /* (non-PHPdoc) - * @see AbstractWindHttp::send() - */ - public function send($method = 'GET', $options = array()) { - $method = strtoupper($method); - if ($this->data) { - switch ($method) { - case 'GET': - $_url = WindUrlHelper::argsToUrl($this->data); - $this->url .= ($this->query ? '&' : '?') . $_url; - break; - case 'POST': - $data = WindUrlHelper::argsToUrl($this->data, false); - $this->setHeader('application/x-www-form-urlencoded', 'Content-Type'); - $this->setHeader(strlen($data), 'Content-Length'); - $this->request('content', $data); - break; - default: - break; - } - } - $this->httpHandler = fopen($this->url, 'r', false, $this->context); - - $this->setHeader($this->host, "Host"); - $this->setHeader('Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.1)', 'User-Agent'); - $this->setHeader('Close', 'Connection'); - if ($options) $this->setHeader($options); - if ($this->cookie) { - $_cookie = WindUrlHelper::argsToUrl($this->cookie, false, ';='); - $this->setHeader($_cookie, "Cookie"); - } - $_header = ''; - foreach ($this->header as $key => $value) { - $_header .= $key . ': ' . $value . "\r\n"; - } - $_header && $this->request('header', $_header); - $this->request('method', $method); - $this->request('timeout', $this->timeout); - return $this->response(); - } -} \ No newline at end of file + if ($newurl == $this->url) { + return; + } + $this->url = $newurl; + $this->httpHandler = $this->createHttpHandler(); + } +} diff --git a/wind/http/transfer/WindHttpTransferException.php b/wind/http/transfer/WindHttpTransferException.php index 37e7fe2f..ed842cb5 100644 --- a/wind/http/transfer/WindHttpTransferException.php +++ b/wind/http/transfer/WindHttpTransferException.php @@ -7,8 +7,6 @@ * @package http * @subpackage transfer */ -class WindHttpTransferException extends WindException { - +class WindHttpTransferException extends WindException +{ } - -?> \ No newline at end of file diff --git a/wind/i18n/IWindLangResource.php b/wind/i18n/IWindLangResource.php index 3f9228c8..f321b366 100644 --- a/wind/i18n/IWindLangResource.php +++ b/wind/i18n/IWindLangResource.php @@ -1,20 +1,20 @@ - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package i18n +/** + * 翻译器接口 + * + * @author Shi Long + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id: IWindLangResource.php 3131 2011-11-17 02:48:33Z yishuo $ + * @package i18n */ -interface IWindLangResource { - - /** - * 翻译接口 - * - * @param string $message - * @param array $params - */ - public function getMessage($message, $params = array()); -} +interface IWindLangResource +{ + /** + * 翻译接口 + * + * @param string $message + * @param array $params + */ + public function getMessage($message, $params = array()); +} diff --git a/wind/i18n/WindI18nException.php b/wind/i18n/WindI18nException.php index f03a68a4..5a446a2f 100644 --- a/wind/i18n/WindI18nException.php +++ b/wind/i18n/WindI18nException.php @@ -6,9 +6,6 @@ * @version $Id$ * @package i18n */ -class WindI18nException extends WindException { - - +class WindI18nException extends WindException +{ } - -?> \ No newline at end of file diff --git a/wind/i18n/WindLangResource.php b/wind/i18n/WindLangResource.php index be7162a7..23feade3 100644 --- a/wind/i18n/WindLangResource.php +++ b/wind/i18n/WindLangResource.php @@ -1,132 +1,149 @@ - - * LANG 为包名,如果不填写则默认没有分包处理,资源类将自动在language包下面寻找 - * 支持解析格式: LANG:login.fail.expty = 'xxx' - * - * @author Shi Long - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package i18n - */ -class WindLangResource extends WindModule implements IWindLangResource { - /** - * 缓存key前缀 - * - * @var string - */ - protected $_cachePrefix = 'Wind.i18n.WindLangResource'; - /** - * 消息存储池 - * - * @var array - */ - protected $_messages = array(); - /** - * 默认资源文件 - * - * @var string - */ - protected $default; - /** - * 资源文件后缀名定义 - * - * @var string - */ - protected $suffix; - /** - * 语言包目录 - * - * @var string - */ - protected $path; - /** - * 语言 - * - * @var string - */ - protected $language; - - /** - * @var WindLocale - */ - protected $locale = null; - - /* (non-PHPdoc) - * @see IWindLangResource::lang() - */ - public function getMessage($message, $params = array()) { - $message = $this->translate($message); - return empty($params) ? $message : WindUtility::strtr($message, $params); - } - - /** - * 获取一条message信息 - * - * @param array $messages - * @return string - */ - protected function translate($message) { - $package = $file = ''; - $_message = $message; - if (strpos($_message, ':') != false) list($package, $_message) = explode(':', $_message, 2); - if (strpos($_message, '.') != false) list($file, $key) = explode('.', $_message, 2); - $path = $this->resolvedPath($package); - if (is_file($path . '/' . $file . $this->suffix)) { - $path = $path . '/' . $file . $this->suffix; - } elseif (is_file($path . '/' . $this->default . $this->suffix)) { - $path = $path . '/' . $this->default . $this->suffix; - $key = $_message; - $file = $this->default; - } else - return $message; - - if (!isset($this->_messages[$path])) { - /* @var $cache AbstractWindCache */ - $cache = Wind::getApp()->getComponent('windCache'); - $cacheKey = $this->_cachePrefix . $package . $file . filemtime($path); - $messages = null; - if ($cache) $messages = $cache->get($cacheKey); - if (!$messages) { - $messages = parse_ini_file($path); - if ($cache) $cache->set($cacheKey, $messages); - } - $this->_messages[$path] = $messages; - } - return isset($this->_messages[$path][$key]) ? $this->_messages[$path][$key] : $message; - } - - /** - * 解析资源文件路径信息 - * - * @param string $package - * @return string - */ - protected function resolvedPath($package) { - $this->path || $this->path = Wind::getRootPath(Wind::getAppName()); - $this->language || $this->language = Wind::getApp()->getRequest()->getAcceptLanguage(); - $path = $this->path . '/' . $this->language . '/' . strtolower($package); - $path = Wind::getRealDir(trim($path, '/'), true); - return $path; - } - - /* (non-PHPdoc) - * @see WindModule::setConfig() - */ - public function setConfig($config) { - parent::setConfig($config); - $this->suffix = $this->getConfig('suffix', '', ''); - $this->default = $this->getConfig('default', '', 'message'); - $this->path = $this->getConfig('path', '', ''); - $this->language = $this->getConfig('language', '', 'zh_cn'); - } -} - -?> \ No newline at end of file + * LANG 为包名,如果不填写则默认没有分包处理,资源类将自动在language包下面寻找 + * 支持解析格式: LANG:login.fail.expty = 'xxx' + * + * @author Shi Long + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id: WindLangResource.php 3850 2012-12-04 07:30:02Z yishuo $ + * @package i18n + */ +class WindLangResource extends WindModule implements IWindLangResource +{ + /** + * 缓存key前缀 + * + * @var string + */ + protected $_cachePrefix = 'Wind.i18n.WindLangResource'; + /** + * 消息存储池 + * + * @var array + */ + protected $_messages = array(); + /** + * 默认资源文件 + * + * @var string + */ + protected $default; + /** + * 资源文件后缀名定义 + * + * @var string + */ + protected $suffix; + /** + * 语言包目录 + * + * @var string + */ + protected $path; + /** + * 语言 + * + * @var string + */ + protected $language; + + /** + * + * @var WindLocale + */ + protected $locale = null; + + /* + * (non-PHPdoc) @see IWindLangResource::lang() + */ + public function getMessage($message, $params = array()) + { + $message = $this->translate($message); + + return empty($params) ? $message : WindUtility::strtr($message, $params); + } + + /** + * 获取一条message信息 + * + * @param array $messages + * @return string + */ + protected function translate($message) + { + $package = $file = ''; + $_message = $message; + if (strpos($_message, ':') != false) { + list($package, $_message) = explode(':', $_message, 2); + } + if (strpos($_message, '.') != false) { + list($file, $key) = explode('.', $_message, 2); + } + $path = $this->resolvedPath($package); + if (is_file($path.'/'.$file.$this->suffix)) { + $path = $path.'/'.$file.$this->suffix; + } elseif (is_file($path.'/'.$this->default.$this->suffix)) { + $path = $path.'/'.$this->default.$this->suffix; + $key = $_message; + $file = $this->default; + } else { + return $message; + } + + if (!isset($this->_messages[$path])) { + /* @var $cache AbstractWindCache */ + $cache = Wind::getComponent('windCache'); + $cacheKey = $this->_cachePrefix.$package.$file.filemtime($path); + $messages = null; + if ($cache) { + $messages = $cache->get($cacheKey); + } + if (!$messages) { + $messages = parse_ini_file($path); + if ($cache) { + $cache->set($cacheKey, $messages); + } + } + $this->_messages[$path] = $messages; + } + + return isset($this->_messages[$path][$key]) ? $this->_messages[$path][$key] : $message; + } + + /** + * 解析资源文件路径信息 + * + * @param string $package + * @return string + */ + protected function resolvedPath($package) + { + $this->path || $this->path = Wind::getRootPath(Wind::getAppName()); + $this->language || $this->language = $this->getRequest()->getAcceptLanguage(); + $path = $this->path.'/'.$this->language.'/'.strtolower($package); + $path = Wind::getRealDir(trim($path, '/'), true); + + return $path; + } + + /* + * (non-PHPdoc) @see WindModule::setConfig() + */ + public function setConfig($config) + { + parent::setConfig($config); + $this->suffix = $this->getConfig('suffix', '', ''); + $this->default = $this->getConfig('default', '', 'message'); + $this->path = $this->getConfig('path', '', ''); + $this->language = $this->getConfig('language', '', 'zh_cn'); + } +} diff --git a/wind/license b/wind/license deleted file mode 100644 index 1c1a2a93..00000000 --- a/wind/license +++ /dev/null @@ -1,31 +0,0 @@ -License of WindFramework - -The WindFramework is free software. It is released under the terms of the following BSD License. - -Copyright (c) 2003-2012, phpwind.com -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of phpwind.com nor the names of its - contributors may be used to endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/wind/log/WindDebug.php b/wind/log/WindDebug.php index 81ead4e4..d6467eb8 100644 --- a/wind/log/WindDebug.php +++ b/wind/log/WindDebug.php @@ -1,4 +1,5 @@ * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindDebug.php 2973 2011-10-15 19:22:48Z yishuo $ * @package log */ -class WindDebug { - - /** - * @var array 调试点 - */ - private static $breakpoint = array(); - - /** - * @var int 保留的小数位数 - */ - const DECIMAL_DIGITS = 4; - - /** - * @var int 记录内存使用标记 - */ - const MEMORY = 'mem'; - - /** - * @var int 记录程序运行时时间使用标记 - */ - const RUN_TIME = 'time'; - - /** - * 设置调试点 - * @param string $point 调试点 - */ - public static function setBreakPoint($point = '') { - if (isset(self::$breakpoint[$point])) return false; - self::$breakpoint[$point][self::RUN_TIME] = microtime(true); - self::$breakpoint[$point][self::MEMORY] = memory_get_usage(); - return true; - } - - /** - * 移除调试点 - * @param string $point 调试点 - */ - public static function removeBreakPoint($point = '') { - if ($point) { - if (isset(self::$breakpoint[$point])) unset(self::$breakpoint[$point]); - } else { - self::$breakpoint = array(); - } - } - - /** - * 取得系统运行所耗内存 - */ - public static function getMemUsage() { - $useMem = memory_get_usage() - USEMEM_START; - return $useMem ? round($useMem / 1024, self::DECIMAL_DIGITS) : 0; - } - - /** - * 取得系统运行所耗时间 - */ - public static function getExecTime() { - $useTime = microtime(true) - RUNTIME_START; - return $useTime ? round($useTime, self::DECIMAL_DIGITS) : 0; - } - - /** - * 获取调试点 - * @param $point - * @param $label - */ - public static function getBreakPoint($point, $label = '') { - if (!isset(self::$breakpoint[$point])) return array(); - return $label ? self::$breakpoint[$point][$label] : self::$breakpoint[$point]; - } - - /** - * 调试点之间系统运行所耗内存 - * @param string $beginPoint 开始调试点 - * @param string $endPoint 结束调试点 - * @return float - */ - public static function getMemUsageOfp2p($beginPoint, $endPoint = '') { - if (!isset(self::$breakpoint[$beginPoint])) return 0; - $endMemUsage = isset(self::$breakpoint[$endPoint]) ? self::$breakpoint[$endPoint][self::MEMORY] : memory_get_usage(); - $useMemUsage = $endMemUsage - self::$breakpoint[$beginPoint][self::MEMORY]; - return round($useMemUsage / 1024, self::DECIMAL_DIGITS); - } - - /** - * 调试点之间的系统运行所耗时间 - * @param string $beginPoint 开始调试点 - * @param string $endPoint 结束调试点 - * @return float - */ - public static function getExecTimeOfp2p($beginPoint, $endPoint = '') { - if (!isset(self::$breakpoint[$beginPoint])) return 0; - $endTime = self::$breakpoint[$endPoint] ? self::$breakpoint[$endPoint][self::RUN_TIME] : microtime(true); - $useTime = $endTime - self::$breakpoint[$beginPoint][self::RUN_TIME]; - return round($useTime, self::DECIMAL_DIGITS); - } - - /** - * 堆栈情况 - * @param array $trace 堆栈引用,如异常 - * @return array - */ - public static function trace($trace = array()) { - $debugTrace = $trace ? $trace : debug_backtrace(); - $traceInfo = array(); - foreach ($debugTrace as $info) { - $info['args'] = self::traceArgs($info['args']); - $file = isset($info['file']) ? $info['file'] : ''; - $line = isset($info['line']) ? $info['line'] : ''; - $str = '[' . date("Y-m-d H:i:m") . '] ' . $file . ' (line:' . $line . ') '; - $str .= $info['class'] . $info['type'] . $info['function'] . '('; - $str .= implode(', ', $info['args']); - $str .= ")"; - $traceInfo[] = $str; - } - return $traceInfo; - } - - /** - * 获取系统所加载的文件 - */ - public static function loadFiles() { - return get_included_files(); - } - - public static function debug($message = '', $trace = array(), $begin = '', $end = '') { - $runtime = self::getExecTime(); - $useMem = self::getMemUsage(); - $separate = "
    "; - $trace = implode("{$separate}", self::trace($trace)); - $debug = ''; - $debug .= "{$message}{$separate}"; - $debug .= "Runtime:{$runtime}s{$separate}"; - $debug .= "Memory consumption:{$useMem}byte{$separate}"; - $debug .= "Stack conditions:{$separate}{$trace}{$separate}"; - if ($begin && $end) { - $PointUseTime = self::getExecTimeOfp2p($begin, $end); - $PointUseMem = self::getMemUsageOfp2p($begin, $end); - $debug .= "Between points {$begin} and {$end} debugging system conditions:{$separate}"; - $debug .= "Runtime:{$PointUseTime}s{$separate}"; - $debug .= "Memory consumption:{$PointUseMem}byte{$separate}"; - } - return $debug; - } - - private static function traceArgs($args = array()) { - foreach ($args as $key => $arg) { - if (is_array($arg)) - $args[$key] = 'array(' . implode(',', $arg) . ')'; - elseif (is_object($arg)) - $args[$key] = 'class ' . get_class($arg); - else - $args[$key] = $arg; - } - return $args; - } - +class WindDebug +{ + /** + * @var array 调试点 + */ + private static $breakpoint = array(); + + /** + * @var int 保留的小数位数 + */ + const DECIMAL_DIGITS = 4; + + /** + * @var int 记录内存使用标记 + */ + const MEMORY = 'mem'; + + /** + * @var int 记录程序运行时时间使用标记 + */ + const RUN_TIME = 'time'; + + /** + * 设置调试点 + * @param string $point 调试点 + */ + public static function setBreakPoint($point = '') + { + if (isset(self::$breakpoint[$point])) { + return false; + } + self::$breakpoint[$point][self::RUN_TIME] = microtime(true); + self::$breakpoint[$point][self::MEMORY] = memory_get_usage(); + + return true; + } + + /** + * 移除调试点 + * @param string $point 调试点 + */ + public static function removeBreakPoint($point = '') + { + if ($point) { + if (isset(self::$breakpoint[$point])) { + unset(self::$breakpoint[$point]); + } + } else { + self::$breakpoint = array(); + } + } + + /** + * 取得系统运行所耗内存 + */ + public static function getMemUsage() + { + $useMem = memory_get_usage() - USEMEM_START; + + return $useMem ? round($useMem / 1024, self::DECIMAL_DIGITS) : 0; + } + + /** + * 取得系统运行所耗时间 + */ + public static function getExecTime() + { + $useTime = microtime(true) - RUNTIME_START; + + return $useTime ? round($useTime, self::DECIMAL_DIGITS) : 0; + } + + /** + * 获取调试点 + * @param $point + * @param $label + */ + public static function getBreakPoint($point, $label = '') + { + if (!isset(self::$breakpoint[$point])) { + return array(); + } + + return $label ? self::$breakpoint[$point][$label] : self::$breakpoint[$point]; + } + + /** + * 调试点之间系统运行所耗内存 + * @param string $beginPoint 开始调试点 + * @param string $endPoint 结束调试点 + * @return float + */ + public static function getMemUsageOfp2p($beginPoint, $endPoint = '') + { + if (!isset(self::$breakpoint[$beginPoint])) { + return 0; + } + $endMemUsage = isset(self::$breakpoint[$endPoint]) ? self::$breakpoint[$endPoint][self::MEMORY] : memory_get_usage(); + $useMemUsage = $endMemUsage - self::$breakpoint[$beginPoint][self::MEMORY]; + + return round($useMemUsage / 1024, self::DECIMAL_DIGITS); + } + + /** + * 调试点之间的系统运行所耗时间 + * @param string $beginPoint 开始调试点 + * @param string $endPoint 结束调试点 + * @return float + */ + public static function getExecTimeOfp2p($beginPoint, $endPoint = '') + { + if (!isset(self::$breakpoint[$beginPoint])) { + return 0; + } + $endTime = self::$breakpoint[$endPoint] ? self::$breakpoint[$endPoint][self::RUN_TIME] : microtime(true); + $useTime = $endTime - self::$breakpoint[$beginPoint][self::RUN_TIME]; + + return round($useTime, self::DECIMAL_DIGITS); + } + + /** + * 堆栈情况 + * @param array $trace 堆栈引用,如异常 + * @return array + */ + public static function trace($trace = array()) + { + $debugTrace = $trace ? $trace : debug_backtrace(); + $traceInfo = array(); + foreach ($debugTrace as $info) { + $info['args'] = self::traceArgs($info['args']); + $file = isset($info['file']) ? $info['file'] : ''; + $line = isset($info['line']) ? $info['line'] : ''; + $str = '['.date('Y-m-d H:i:m').'] '.$file.' (line:'.$line.') '; + $str .= $info['class'].$info['type'].$info['function'].'('; + $str .= implode(', ', $info['args']); + $str .= ')'; + $traceInfo[] = $str; + } + + return $traceInfo; + } + + /** + * 获取系统所加载的文件 + */ + public static function loadFiles() + { + return get_included_files(); + } + + public static function debug($message = '', $trace = array(), $begin = '', $end = '') + { + $runtime = self::getExecTime(); + $useMem = self::getMemUsage(); + $separate = '
    '; + $trace = implode("{$separate}", self::trace($trace)); + $debug = ''; + $debug .= "{$message}{$separate}"; + $debug .= "Runtime:{$runtime}s{$separate}"; + $debug .= "Memory consumption:{$useMem}byte{$separate}"; + $debug .= "Stack conditions:{$separate}{$trace}{$separate}"; + if ($begin && $end) { + $PointUseTime = self::getExecTimeOfp2p($begin, $end); + $PointUseMem = self::getMemUsageOfp2p($begin, $end); + $debug .= "Between points {$begin} and {$end} debugging system conditions:{$separate}"; + $debug .= "Runtime:{$PointUseTime}s{$separate}"; + $debug .= "Memory consumption:{$PointUseMem}byte{$separate}"; + } + + return $debug; + } + + private static function traceArgs($args = array()) + { + foreach ($args as $key => $arg) { + if (is_array($arg)) { + $args[$key] = 'array('.implode(',', $arg).')'; + } elseif (is_object($arg)) { + $args[$key] = 'class '.get_class($arg); + } else { + $args[$key] = $arg; + } + } + + return $args; + } } -?> \ No newline at end of file diff --git a/wind/log/WindLogger.php b/wind/log/WindLogger.php index fa2459c4..88137dcf 100644 --- a/wind/log/WindLogger.php +++ b/wind/log/WindLogger.php @@ -1,7 +1,7 @@ *
  • WindLogger::LEVEL_INFO = 1: 信息记录,只记录需要记录的信息。
  • @@ -20,520 +20,570 @@ * @author Qian Su * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindLogger.php 3904 2013-01-08 07:01:26Z yishuo $ * @package log */ -class WindLogger extends WindModule { - - /** - * 级别1: 只是记录信息不记录trace信息 - * - * @var int - */ - const LEVEL_INFO = 1; - - /** - * 级别2:将会打印出堆栈中trace信息 - * - * @var int - */ - const LEVEL_TRACE = 2; - - /** - * 级别3:标志该信息是一个debug - * - * debug信息将会导出trace信息和debug详细信息 - * - * @var int - */ - const LEVEL_DEBUG = 3; - - /** - * 级别4:记录错误信息,不包含trace信息 - * - * @var int - */ - const LEVEL_ERROR = 4; - - /** - * 级别5:分析信息记录,包含详细的时间及内存使用情况等 - * - * @var int - */ - const LEVEL_PROFILE = 5; - - /** - * 日志的方式 - * - * @var int - */ - const WRITE_TYPE = 2; - - /** - * 日志记录中profile信息开始的标志 - * - * @var string - */ - const TOKEN_BEGIN = 'begin:'; - - /** - * 日志记录中profile信息结束的标志 - * - * @var string - */ - const TOKEN_END = 'end:'; - - /** - * 每次当日志数量达到1000条的时候,就写入文件一次 - * - * @var int - */ - private $_autoFlush = 1000; - - /** - * 日志内容 - * - * @var array - */ - private $_logs = array(); - - /** - * 日志条数统计 - * - * @var int - */ - private $_logCount = 0; - - /** - * 日志的详细信息 - * - * @var array - */ - private $_profiles = array(); - - /** - * 日志记录的地址 - * - * @var string - */ - private $_logDir; - - /** - * 日志文件的最大长度 - * - * @var int - */ - private $_maxFileSize = 100; - - /** - * 日志打印形式 - * - * 0: 打印全部日志信息结果 - * 1: 按照level分文件存储日志记录 - * 2: 按照type分文件存储日志记录 - * - * @var int - */ - private $_writeType = 0; - - /** - * 存放日志打印形式 - * - * @var array - */ - private $_types = array(); - - /** - * 构造函数 - * - * @param string $logDir 日志文件存放的目录 - * @param int $writeType 日志文件的保存方式 - * @return void - */ - public function __construct($logDir = '', $writeType = 0) { - $this->setLogDir($logDir); - $this->_writeType = $writeType; - } - - /** - * 添加info级别的日志信息 - * - * @param string $msg 日志信息 - * @param string $type 日志的类型,默认为wind.system - * @param boolean $flush 是否将日志输出到文件,为true的时候将写入文件,默认为false - * @return void - */ - public function info($msg, $type = 'wind.system', $flush = false) { - $this->log($msg, self::LEVEL_INFO, $type, $flush); - } - - /** - * 添加trace级别的日志信息 - * - * @param string $msg 日志信息 - * @param string $type 日志的类型,默认为wind.system - * @param boolean $flush 是否将日志输出到文件,为true的时候将写入文件,默认为false - * @return void - */ - public function trace($msg, $type = 'wind.system', $flush = false) { - $this->log($msg, self::LEVEL_TRACE, $type, $flush); - } - - /** - * 添加debug级别的日志信息 - * - * @param string $msg 日志信息 - * @param string $type 日志的类型,默认为wind.system - * @param boolean $flush 是否将日志输出到文件,为true的时候将写入文件,默认为false - * @return void - */ - public function debug($msg, $type = 'wind.system', $flush = false) { - $this->log($msg, self::LEVEL_DEBUG, $type, $flush); - } - - /** - * 添加error级别的日志信息 - * - * @param string $msg 日志信息 - * @param string $type 日志的类型,默认为wind.core - * @param boolean $flush 是否将日志输出到文件,为true的时候将写入文件,默认为false - * @return void - */ - public function error($msg, $type = 'wind.core', $flush = false) { - $this->log($msg, self::LEVEL_ERROR, $type, $flush); - } - - /** - * 添加profile级别的开始位置日志信息 - * - * 通过该接口添加的日志信息将是记录一个开始位置的信息 - * - * @param string $msg 日志信息 - * @param string $type 日志的类型,默认为wind.core - * @param boolean $flush 是否将日志输出到文件,为true的时候将写入文件,默认为false - * @return void - */ - public function profileBegin($msg, $type = 'wind.core', $flush = false) { - $this->log('begin:' . trim($msg), self::LEVEL_PROFILE, $type, $flush); - } - - /** - * 添加profile级别的结束位置日志信息 - * - * 通过该接口添加的日志信息将是记录一个结束位置的信息 - * - * @param string $msg 日志信息 - * @param string $type 日志的类型,默认为wind.core - * @param boolean $flush 是否将日志输出到文件,为true的时候将写入文件,默认为false - * @return void - */ - public function profileEnd($msg, $type = 'wind.core', $flush = false) { - $this->log('end:' . trim($msg), self::LEVEL_PROFILE, $type, $flush); - } - - /** - * 添加info级别的日志信息 - * - * @param string $msg 日志信息 - * @param int $level 日志记录的级别,默认为INFO级别即为1 - * @param string $type 日志的类型,默认为wind.system - * @param boolean $flush 是否将日志输出到文件,为true则将会写入文件,默认为false - * @return void - */ - public function log($msg, $level = self::LEVEL_INFO, $type = 'wind.system', $flush = false) { - if (!$this->_logDir) return; - if ($this->_writeType & self::WRITE_TYPE) - (count($this->_types) >= 5 || $this->_logCount >= $this->_autoFlush) && $this->flush(); - else - $this->_logCount >= $this->_autoFlush && $this->flush(); - if ($level === self::LEVEL_PROFILE) - $message = $this->_build($msg, $level, $type, microtime(true), $this->getMemoryUsage(false)); - elseif ($level === self::LEVEL_DEBUG) - $message = $this->_build($msg, $level, $type, microtime(true)); - else - $message = $this->_build($msg, $level, $type); - $this->_logs[] = array($level, $type, $message); - $this->_logCount++; - if ($this->_writeType == self::WRITE_TYPE && !in_array($type, $this->_types)) $this->_types[] = $type; - if ($flush) $this->flush(); - } - - /** - * 将记录的日志列表信息写入文件 - * - * @return boolean - */ - public function flush() { - if (empty($this->_logs)) return false; - Wind::import('WIND:utility.WindFile'); - $_l = $_logTypes = $_logLevels = array(); - $_map = array(self::LEVEL_INFO => 'info', self::LEVEL_ERROR => 'error', self::LEVEL_DEBUG => 'debug', - self::LEVEL_TRACE => 'trace', self::LEVEL_PROFILE => 'profile'); - - foreach ($this->_logs as $key => $value) { - $_l[] = $value[2]; - $_logTypes[$value[1]][] = $value[2]; - $_logLevels[$value[0]][] = $value[2]; - } - if ($this->_writeType & 1) { - foreach ($_logLevels as $key => $value) { - if (!$fileName = $this->_getFileName($_map[$key])) continue; - WindFile::write($fileName, join("", $value), 'a'); - } - } - if ($this->_writeType & 2) { - foreach ($_logTypes as $key => $value) { - if (!$fileName = $this->_getFileName($key)) continue; - WindFile::write($fileName, join("", $value), 'a'); - } - } - if ($fileName = $this->_getFileName()) { - WindFile::write($fileName, join("", $_l), 'a'); - } - $this->_logs = array(); - $this->_logCount = 0; - return true; - } - - /** - * 返回内存使用量 - * - * @param boolean $peak 是否是内存峰值,默认为true - * @return int - */ - public function getMemoryUsage($peak = true) { - if ($peak && function_exists('memory_get_peak_usage')) - return memory_get_peak_usage(); - elseif (function_exists('memory_get_usage')) - return memory_get_usage(); - $pid = getmypid(); - if (strncmp(PHP_OS, 'WIN', 3) === 0) { - exec('tasklist /FI "PID eq ' . $pid . '" /FO LIST', $output); - return isset($output[5]) ? preg_replace('/[\D]/', '', $output[5]) * 1024 : 0; - } else { - exec("ps -eo%mem,rss,pid | grep $pid", $output); - $output = explode(" ", $output[0]); - return isset($output[1]) ? $output[1] * 1024 : 0; - } - } - - /** - * 组装日志信息 - * - * @param string $msg 日志信息 - * @param int $level 日志级别 - * @param string $type 日志类型 - * @param int $timer 日志记录的时间,默认为0 - * @param int $mem 日志记录的时候内容使用情况,默认为0 - * @return string 构造好的信息字符串 - */ - private function _build($msg, $level, $type, $timer = 0, $mem = 0) { - $result = ''; - switch ($level) { - case self::LEVEL_INFO: - $result = $this->_buildInfo($msg); - break; - case self::LEVEL_ERROR: - $result = $this->_buildError($msg); - break; - case self::LEVEL_DEBUG: - $result = $this->_buildDebug($msg); - break; - case self::LEVEL_TRACE: - $result = $this->_buildTrace($msg); - break; - case self::LEVEL_PROFILE: - $result = $this->_buildProfile($msg, $type, $timer, $mem); - break; - default: - break; - } - return $result ? '[' . date('Y-m-d H:i:s') . '] ' . $result . "\r\n" : ''; - } - - /** - * 构造profile信息格式 - * - * @param string $msg 记录的信息 - * @param string $type 记录的信息类型 - * @param int $timer 记录的信息的时间 - * @param int $mem 记录的信息的时候内容使用情况 - * @return string 返回构造好的profile信息 - */ - private function _buildProfile($msg, $type, $timer, $mem) { - $_msg = ''; - if (strncasecmp($msg, self::TOKEN_BEGIN, strlen(self::TOKEN_BEGIN)) == 0) { - $_token = substr($msg, strlen(self::TOKEN_BEGIN)); - $_token = substr($_token, 0, strpos($_token, ':')); - $this->_profiles[] = array($_token, substr($msg, strpos($msg, ':', strlen(self::TOKEN_BEGIN)) + 1), $type, - $timer, $mem); - } elseif (strncasecmp(self::TOKEN_END, $msg, strlen(self::TOKEN_END)) == 0) { - $_msg = "PROFILE! Message:"; - $_token = substr($msg, strlen(self::TOKEN_END)); - $_token = substr($_token, 0, strpos($_token, ':')); - foreach ($this->_profiles as $key => $profile) { - if ($profile[0] !== $_token) continue; - if ($profile[1]) - $_msg .= "\r\n\t" . $profile[1]; - else - $_msg .= "\r\n\t" . substr($msg, strpos($msg, ':', strlen(self::TOKEN_END)) + 1); - $_msg .= "\r\n\tTime:" . ($timer - $profile[3]) . "\r\n\tMem:" . ($mem - $profile[4]) . "\r\n\tType:$profile[2]"; - break; - unset($this->_profiles[$key]); - } - } - return $_msg; - } - - /** - * 组装info级别的信息输出格式 - * - * - * INFO! Message: $msg - * - * - * @param string $msg 输出的信息 - * @return string - */ - private function _buildInfo($msg) { - return "INFO! Message: " . $msg; - } - - /** - * 组装堆栈trace的信息输出格式 - * - * - * TRACE! Message: $msg - * #1 trace1 - * #2 trace2 - * - * - * @param string $msg 输出的信息 - * @return string - */ - private function _buildTrace($msg) { - return "TRACE! Message: " . $msg . implode("\r\n", $this->_getTrace()); - } - - /** - * 组装debug信息输出 - * - * - * DEBUG! Message: $msg - * #1 trace1 - * #2 trace2 - * - * - * @param string $msg 输出的信息 - * @return string - */ - private function _buildDebug($msg) { - return 'DEBUG! Message: ' . $msg . implode("\r\n", $this->_getTrace()); - } - - /** - *组装Error信息输出 - * - * - * ERROR! Message: $msg - * #1 trace1 - * #2 trace2 - * - * - * @param string $msg 输出的错误信息 - * @return string - */ - private function _buildError($msg) { - return 'ERROR! Message: ' . $msg; - } - - /** - * 错误堆栈信息的获取及组装输出 - * - * - * #1 trace - * #2 trace - * - * - * @return string - */ - private function _getTrace() { - $num = 0; - $info[] = 'Stack trace:'; - $traces = debug_backtrace(); - foreach ($traces as $traceKey => $trace) { - if ($num >= 7) break; - if ((isset($trace['class']) && $trace['class'] == __CLASS__) || isset($trace['file']) && strrpos($trace['file'], __CLASS__ . '.php') !== false) continue; - $file = isset($trace['file']) ? $trace['file'] . '(' . $trace['line'] . '): ' : '[internal function]: '; - $function = isset($trace['class']) ? $trace['class'] . $trace['type'] . $trace['function'] : $trace['function']; - if ($function == 'WindBase::log') continue; - $args = array_map(array($this, '_buildArg'), $trace['args']); - $info[] = '#' . ($num++) . ' ' . $file . $function . '(' . implode(',', $args) . ')'; - } - return $info; - } - - /** - * 组装输出的trace中的参数组装 - * - * @param mixed $arg 需要组装的信息 - * @return string 返回组装好的信息 - *
      - *
    • 如果是array: 返回 Array
    • - *
    • 如果是Object: 返回 Object classname
    • - *
    • 其他格式: 返回 $arg
    • - *
    - */ - private function _buildArg($arg) { - switch (gettype($arg)) { - case 'array': - return 'Array'; - break; - case 'object': - return 'Object ' . get_class($arg); - break; - default: - return "'" . $arg . "'"; - break; - } - } - - /** - * 取得日志文件名 - * - * @param string $suffix 日志文件的后缀,默认为空 - * @return string 返回日志文件名 - */ - private function _getFileName($suffix = '') { - $_maxsize = ($this->_maxFileSize ? $this->_maxFileSize : 100) * 1024; - $_logfile = $this->_logDir . '/log' . ($suffix ? '_' . $suffix : '') . '.txt'; - if (is_file($_logfile) && $_maxsize <= filesize($_logfile)) { - do { - $_newFile = $this->_logDir . '/log' . ($suffix ? '_' . $suffix : '') . '_' . time() . '.txt'; - } while (is_file($_newFile)); - @rename($_logfile, $_newFile); - } - return $_logfile; - } - - /** - * 设置日志保存的路径 - * - * @param string $logFile 日志保存的路径 - * @return void - */ - public function setLogDir($logDir) { - if (!is_dir($logDir)) $logDir = Wind::getRealDir($logDir); - $this->_logDir = realpath($logDir); - } - - /** - * 设置日志文件最大的大小 - * - * @param int $_maxFileSize 文件的最大值 - * @return void - */ - public function setMaxFileSize($maxFileSize) { - $this->_maxFileSize = (int) $maxFileSize; - } -} \ No newline at end of file +class WindLogger extends WindModule +{ + /** + * 级别1: 只是记录信息不记录trace信息 + * + * @var int + */ + const LEVEL_INFO = 1; + + /** + * 级别2:将会打印出堆栈中trace信息 + * + * @var int + */ + const LEVEL_TRACE = 2; + + /** + * 级别3:标志该信息是一个debug + * + * debug信息将会导出trace信息和debug详细信息 + * + * @var int + */ + const LEVEL_DEBUG = 3; + + /** + * 级别4:记录错误信息,不包含trace信息 + * + * @var int + */ + const LEVEL_ERROR = 4; + + /** + * 级别5:分析信息记录,包含详细的时间及内存使用情况等 + * + * @var int + */ + const LEVEL_PROFILE = 5; + + /** + * 日志的方式 + * + * @var int + */ + const WRITE_TYPE = 2; + + /** + * 日志记录中profile信息开始的标志 + * + * @var string + */ + const TOKEN_BEGIN = 'begin:'; + + /** + * 日志记录中profile信息结束的标志 + * + * @var string + */ + const TOKEN_END = 'end:'; + + /** + * 每次当日志数量达到1000条的时候,就写入文件一次 + * + * @var int + */ + private $_autoFlush = 1000; + + /** + * 日志内容 + * + * @var array + */ + private $_logs = array(); + + /** + * 日志条数统计 + * + * @var int + */ + private $_logCount = 0; + + /** + * 日志的详细信息 + * + * @var array + */ + private $_profiles = array(); + + /** + * 日志记录的地址 + * + * @var string + */ + private $_logDir; + + /** + * 日志文件的最大长度 + * + * @var int + */ + private $_maxFileSize = 100; + + /** + * 日志打印形式 + * + * 0: 打印全部日志信息结果 + * 1: 按照level分文件存储日志记录 + * 2: 按照type分文件存储日志记录 + * + * @var int + */ + private $_writeType = 0; + + /** + * 存放日志打印形式 + * + * @var array + */ + private $_types = array(); + + /** + * 构造函数 + * + * @param string $logDir 日志文件存放的目录 + * @param int $writeType 日志文件的保存方式 + */ + public function __construct($logDir = '', $writeType = 0, $maxFileSize = 100) + { + $this->setLogDir($logDir); + $this->_writeType = $writeType; + $this->setMaxFileSize($maxFileSize); + } + + /** + * 添加info级别的日志信息 + * + * @param string $msg 日志信息 + * @param string $type 日志的类型,默认为wind.system + * @param bool $flush 是否将日志输出到文件,为true的时候将写入文件,默认为false + */ + public function info($msg, $type = 'wind.system', $flush = false) + { + $this->log($msg, self::LEVEL_INFO, $type, $flush); + } + + /** + * 添加trace级别的日志信息 + * + * @param string $msg 日志信息 + * @param string $type 日志的类型,默认为wind.system + * @param bool $flush 是否将日志输出到文件,为true的时候将写入文件,默认为false + */ + public function trace($msg, $type = 'wind.system', $flush = false) + { + $this->log($msg, self::LEVEL_TRACE, $type, $flush); + } + + /** + * 添加debug级别的日志信息 + * + * @param string $msg 日志信息 + * @param string $type 日志的类型,默认为wind.system + * @param bool $flush 是否将日志输出到文件,为true的时候将写入文件,默认为false + */ + public function debug($msg, $type = 'wind.system', $flush = false) + { + $this->log($msg, self::LEVEL_DEBUG, $type, $flush); + } + + /** + * 添加error级别的日志信息 + * + * @param string $msg 日志信息 + * @param string $type 日志的类型,默认为wind.core + * @param bool $flush 是否将日志输出到文件,为true的时候将写入文件,默认为false + */ + public function error($msg, $type = 'wind.core', $flush = false) + { + $this->log($msg, self::LEVEL_ERROR, $type, $flush); + } + + /** + * 添加profile级别的开始位置日志信息 + * + * 通过该接口添加的日志信息将是记录一个开始位置的信息 + * + * @param string $msg 日志信息 + * @param string $type 日志的类型,默认为wind.core + * @param bool $flush 是否将日志输出到文件,为true的时候将写入文件,默认为false + */ + public function profileBegin($msg, $type = 'wind.core', $flush = false) + { + $this->log('begin:'.trim($msg), self::LEVEL_PROFILE, $type, $flush); + } + + /** + * 添加profile级别的结束位置日志信息 + * + * 通过该接口添加的日志信息将是记录一个结束位置的信息 + * + * @param string $msg 日志信息 + * @param string $type 日志的类型,默认为wind.core + * @param bool $flush 是否将日志输出到文件,为true的时候将写入文件,默认为false + */ + public function profileEnd($msg, $type = 'wind.core', $flush = false) + { + $this->log('end:'.trim($msg), self::LEVEL_PROFILE, $type, $flush); + } + + /** + * 添加info级别的日志信息 + * + * @param string $msg 日志信息 + * @param int $level 日志记录的级别,默认为INFO级别即为1 + * @param string $type 日志的类型,默认为wind.system + * @param bool $flush 是否将日志输出到文件,为true则将会写入文件,默认为false + */ + public function log($msg, $level = self::LEVEL_INFO, $type = 'wind.system', $flush = false) + { + if ($this->_writeType & self::WRITE_TYPE) { + (count($this->_types) >= 5 || $this->_logCount >= $this->_autoFlush) && $this->flush(); + } else { + $this->_logCount >= $this->_autoFlush && $this->flush(); + } + if ($level === self::LEVEL_PROFILE) { + $message = $this->_build($msg, $level, $type, microtime(true), + $this->getMemoryUsage(false)); + } elseif ($level === self::LEVEL_DEBUG) { + $message = $this->_build($msg, $level, $type, microtime(true)); + } else { + $message = $this->_build($msg, $level, $type); + } + $this->_logs[] = array($level, $type, $message); + $this->_logCount++; + if ($this->_writeType == self::WRITE_TYPE && !in_array($type, $this->_types)) { + $this->_types[] = $type; + } + if ($flush) { + $this->flush(); + } + } + + /** + * 将记录的日志列表信息写入文件 + * + * @return bool + */ + public function flush() + { + if (empty($this->_logs)) { + return false; + } + + $_l = $_logTypes = $_logLevels = array(); + $_map = array( + self::LEVEL_INFO => 'info', + self::LEVEL_ERROR => 'error', + self::LEVEL_DEBUG => 'debug', + self::LEVEL_TRACE => 'trace', + self::LEVEL_PROFILE => 'profile', ); + + foreach ($this->_logs as $key => $value) { + $_l[] = $value[2]; + $_logTypes[$value[1]][] = $value[2]; + $_logLevels[$value[0]][] = $value[2]; + } + if ($this->_writeType & 1) { + foreach ($_logLevels as $key => $value) { + if (!$fileName = $this->_getFileName($_map[$key])) { + continue; + } + WindFile::write($fileName, implode('', $value), 'a'); + } + } + if ($this->_writeType & 2) { + foreach ($_logTypes as $key => $value) { + if (!$fileName = $this->_getFileName($key)) { + continue; + } + WindFile::write($fileName, implode('', $value), 'a'); + } + } + if ($fileName = $this->_getFileName()) { + WindFile::write($fileName, implode('', $_l), 'a'); + } + $this->_logs = array(); + $this->_logCount = 0; + + return true; + } + + /** + * 返回内存使用量 + * + * @param bool $peak 是否是内存峰值,默认为true + * @return int + */ + public function getMemoryUsage($peak = true) + { + if ($peak && function_exists('memory_get_peak_usage')) { + return memory_get_peak_usage(); + } elseif (function_exists('memory_get_usage')) { + return memory_get_usage(); + } + $pid = getmypid(); + if (strncmp(PHP_OS, 'WIN', 3) === 0) { + exec('tasklist /FI "PID eq '.$pid.'" /FO LIST', $output); + + return isset($output[5]) ? preg_replace('/[\D]/', '', $output[5]) * 1024 : 0; + } else { + exec("ps -eo%mem,rss,pid | grep $pid", $output); + $output = explode(' ', $output[0]); + + return isset($output[1]) ? $output[1] * 1024 : 0; + } + } + + /** + * 组装日志信息 + * + * @param string $msg 日志信息 + * @param int $level 日志级别 + * @param string $type 日志类型 + * @param int $timer 日志记录的时间,默认为0 + * @param int $mem 日志记录的时候内容使用情况,默认为0 + * @return string 构造好的信息字符串 + */ + private function _build($msg, $level, $type, $timer = 0, $mem = 0) + { + $result = ''; + switch ($level) { + case self::LEVEL_INFO: + $result = $this->_buildInfo($msg); + break; + case self::LEVEL_ERROR: + $result = $this->_buildError($msg); + break; + case self::LEVEL_DEBUG: + $result = $this->_buildDebug($msg); + break; + case self::LEVEL_TRACE: + $result = $this->_buildTrace($msg); + break; + case self::LEVEL_PROFILE: + $result = $this->_buildProfile($msg, $type, $timer, $mem); + break; + default: + break; + } + + return $result ? '['.date('Y-m-d H:i:s').'] '.$result."\r\n" : ''; + } + + /** + * 构造profile信息格式 + * + * @param string $msg 记录的信息 + * @param string $type 记录的信息类型 + * @param int $timer 记录的信息的时间 + * @param int $mem 记录的信息的时候内容使用情况 + * @return string 返回构造好的profile信息 + */ + private function _buildProfile($msg, $type, $timer, $mem) + { + $_msg = ''; + if (strncasecmp($msg, self::TOKEN_BEGIN, strlen(self::TOKEN_BEGIN)) == 0) { + $_token = substr($msg, strlen(self::TOKEN_BEGIN)); + $_token = substr($_token, 0, strpos($_token, ':')); + $this->_profiles[] = array( + $_token, + substr($msg, strpos($msg, ':', strlen(self::TOKEN_BEGIN)) + 1), + $type, + $timer, + $mem, ); + } elseif (strncasecmp(self::TOKEN_END, $msg, strlen(self::TOKEN_END)) == 0) { + $_msg = 'PROFILE! Message:'; + $_token = substr($msg, strlen(self::TOKEN_END)); + $_token = substr($_token, 0, strpos($_token, ':')); + foreach ($this->_profiles as $key => $profile) { + if ($profile[0] !== $_token) { + continue; + } + if ($profile[1]) { + $_msg .= "\r\n\t".$profile[1]; + } else { + $_msg .= "\r\n\t".substr($msg, strpos($msg, ':', strlen(self::TOKEN_END)) + 1); + } + $_msg .= "\r\n\tTime:".($timer - $profile[3])."\r\n\tMem:".($mem - $profile[4])."\r\n\tType:$profile[2]"; + break; + unset($this->_profiles[$key]); + } + } + + return $_msg; + } + + /** + * 组装info级别的信息输出格式 + * + * + * INFO! Message: $msg + * + * + * @param string $msg 输出的信息 + * @return string + */ + private function _buildInfo($msg) + { + return 'INFO! Message: '.$msg; + } + + /** + * 组装堆栈trace的信息输出格式 + * + * + * TRACE! Message: $msg + * #1 trace1 + * #2 trace2 + * + * + * @param string $msg 输出的信息 + * @return string + */ + private function _buildTrace($msg) + { + return 'TRACE! Message: '.$msg.implode("\r\n", $this->_getTrace()); + } + + /** + * 组装debug信息输出 + * + * + * DEBUG! Message: $msg + * #1 trace1 + * #2 trace2 + * + * + * @param string $msg 输出的信息 + * @return string + */ + private function _buildDebug($msg) + { + return 'DEBUG! Message: '.$msg.implode("\r\n", $this->_getTrace()); + } + + /** + *组装Error信息输出 + * + * + * ERROR! Message: $msg + * #1 trace1 + * #2 trace2 + * + * + * @param string $msg 输出的错误信息 + * @return string + */ + private function _buildError($msg) + { + return 'ERROR! Message: '.$msg; + } + + /** + * 错误堆栈信息的获取及组装输出 + * + * + * #1 trace + * #2 trace + * + * + * @return string + */ + private function _getTrace() + { + $num = 0; + $info[] = 'Stack trace:'; + $traces = debug_backtrace(); + foreach ($traces as $traceKey => $trace) { + if ($num >= 7) { + break; + } + if ((isset($trace['class']) && $trace['class'] == __CLASS__) || isset($trace['file']) && strrpos( + $trace['file'], __CLASS__.'.php') !== false) { + continue; + } + $file = isset($trace['file']) ? $trace['file'].'('.$trace['line'].'): ' : '[internal function]: '; + $function = isset($trace['class']) ? $trace['class'].$trace['type'].$trace['function'] : $trace['function']; + if ($function == 'WindBase::log') { + continue; + } + $args = array_map(array($this, '_buildArg'), $trace['args']); + $info[] = '#'.($num++).' '.$file.$function.'('.implode(',', $args).')'; + } + + return $info; + } + + /** + * 组装输出的trace中的参数组装 + * + * @param mixed $arg 需要组装的信息 + * @return string 返回组装好的信息 + *
      + *
    • 如果是array: 返回 Array
    • + *
    • 如果是Object: 返回 Object classname
    • + *
    • 其他格式: 返回 $arg
    • + *
    + */ + private function _buildArg($arg) + { + switch (gettype($arg)) { + case 'array': + return 'Array'; + break; + case 'object': + return 'Object '.get_class($arg); + break; + default: + return "'".$arg."'"; + break; + } + } + + /** + * 取得日志文件名 + * + * @param string $suffix 日志文件的后缀,默认为空 + * @return string 返回日志文件名 + */ + private function _getFileName($suffix = '') + { + $_maxsize = ($this->_maxFileSize ? $this->_maxFileSize : 100) * 1024; + $_logfile = $this->_logDir.'/log'.($suffix ? '_'.$suffix : '').'.txt'; + if (is_file($_logfile) && $_maxsize <= filesize($_logfile)) { + do { + $_newFile = $this->_logDir.'/log'.($suffix ? '_'.$suffix : '').'_'.time().'.txt'; + } while (is_file($_newFile)); + @rename($_logfile, $_newFile); + } + + return $_logfile; + } + + /** + * 设置日志保存的路径 + * + * @param string $logFile 日志保存的路径 + */ + public function setLogDir($logDir) + { + $this->_logDir = Wind::getRealDir($logDir); + WindFolder::mkRecur($this->_logDir); + } + + /** + * 设置日志文件最大的大小 + * + * @param int $_maxFileSize 文件的最大值 + */ + public function setMaxFileSize($maxFileSize) + { + $this->_maxFileSize = (int) $maxFileSize; + } +} diff --git a/wind/mail/IWindMailEncoder.php b/wind/mail/IWindMailEncoder.php index 4c8be383..b9b819bf 100644 --- a/wind/mail/IWindMailEncoder.php +++ b/wind/mail/IWindMailEncoder.php @@ -8,46 +8,43 @@ * @version $Id$ * @package wind */ -interface IWindMailEncoder { +interface IWindMailEncoder +{ + /** + * 编码邮件内容 + * + * @param string $string + * @param int $length + * @param string $linebreak + */ + public function encode($string, $length, $linebreak); - /** - * 编码邮件内容 - * - * @param string $string - * @param int $length - * @param string $linebreak - */ - public function encode($string, $length, $linebreak); + /** + * 解码邮件内容 + * + * @param string $string + * @param int $length + * @param string $linebreak + */ + public function decode($string, $length, $linebreak); - /** - * 解码邮件内容 - * - * @param string $string - * @param int $length - * @param string $linebreak - */ - public function decode($string, $length, $linebreak); - - /** - * 编码邮件头 - * - * @param string $string - * @param string $charset - * @param int $length - * @param string $linebreak - */ - public function encodeHeader($string, $charset, $length, $linebread); - - /** - * 解码邮件头 - * - * @param string $string - * @param string $charset - * @param int $length - * @param string $linebread - */ - public function decodeHeader($string, $charset, $length, $linebread); + /** + * 编码邮件头 + * + * @param string $string + * @param string $charset + * @param int $length + * @param string $linebreak + */ + public function encodeHeader($string, $charset, $length, $linebread); + /** + * 解码邮件头 + * + * @param string $string + * @param string $charset + * @param int $length + * @param string $linebread + */ + public function decodeHeader($string, $charset, $length, $linebread); } - -?> \ No newline at end of file diff --git a/wind/mail/WindMail.php b/wind/mail/WindMail.php index 64fed51b..939773e8 100644 --- a/wind/mail/WindMail.php +++ b/wind/mail/WindMail.php @@ -1,570 +1,662 @@ * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindMail.php 3904 2013-01-08 07:01:26Z yishuo $ * @package mail */ -class WindMail { - /** - * @var array 邮件头 - */ - private $mailHeader = array(); - /** - * @var array 邮件附件 - */ - private $attachment = array(); - /** - * @var string 邮件字符集 - */ - private $charset = 'utf-8'; - /** - * @var string 是否是内嵌资源 - */ - private $embed = false; - /** - * @var array 邮件收件人 - */ - private $recipients = null; - /** - * @var string 邮件发件人 - */ - private $from = ''; - /** - * @var string 邮件消息体html展现方式 - */ - private $bodyHtml = ''; - /** - * @var string 邮件消息体文本展现方式 - */ - private $bodyText = ''; - /** - * @var array 邮件边界线 - */ - private $boundary; - /** - * @var string 邮件编码方式 - */ - private $encode = self::ENCODE_BASE64; - /** - * @var 内容类型 - */ - private $contentType; - - //常用邮件MIME - const CRLF = "\n"; - const TO = 'To'; - const CC = 'Cc'; - const BCC = 'Bcc'; - const FROM = 'From'; - const SUBJECT = 'Subject'; - const MESSAGEID = 'Message-Id'; - const CONTENTTYPE = 'Content-Type'; - const CONTENTENCODE = 'Content-Transfer-Encoding'; - const CONTENTID = 'Content-ID'; - const CONTENTPOSITION = 'Content-Disposition'; - const CONTENTDESCRIPT = 'Content-Description'; - const CONTENTLOCATION = 'Content-Location'; - const CONTENTLANGUAGE = 'Content-Language'; - const DATE = 'Date'; - - //邮件MIME类型 - const MIME_OCTETSTREAM = 'application/octet-stream'; - const MIME_TEXT = 'text/plain'; - const MIME_HTML = 'text/html'; - const MIME_ALTERNATIVE = 'multipart/alternative'; - const MIME_MIXED = 'multipart/mixed'; - const MIME_RELATED = 'multipart/related'; - - //邮件编码 - const ENCODE_7BIT = '7bit'; - const ENCODE_8BIT = '8bit'; - const ENCODE_QP = 'qp'; - const ENCODE_BASE64 = 'base64'; - const ENCODE_BINARY = 'binary'; - - //邮件编码内容 - const DIS_ATTACHMENT = 'attachment'; - const DIS_INLINE = 'inline'; - const LINELENGTH = 72; - - //邮件发送方式 - const SEND_SMTP = 'smtp'; - const SEND_PHP = 'php'; - const SEND_SEND = 'send'; - - /** - * 发送邮件 - * - * @param string $type 发送类型 - * @param array $config 邮件发送器需要的配置数据 - * @return boolean - */ - public function send($type = self::SEND_SMTP, $config = array()) { - try { - $class = Wind::import('Wind:mail.sender.Wind' . ucfirst($type) . 'Mail'); - /* @var $sender IWindSendMail */ - $sender = WindFactory::createInstance($class); - return $sender->send($this, $config); - } catch (Exception $e) { - if (WIND_DEBUG & 2) Wind::getApp()->getComponent('windLogger')->info( - '[mail.WindMail.send] send mail fail. ' . $e->getMessage(), 'windmail'); - if (WIND_DEBUG & 1) throw new WindMailException('[mail.WindMail.send] send mail fail.' . $e->getMessage()); - return false; - } - } - - /** - * 创建邮件头信息 - * - * @return string - */ - public function createHeader() { - if (!isset($this->mailHeader[self::CONTENTTYPE])) { - $type = self::MIME_TEXT; - if ($this->attachment) - $type = $this->embed ? self::MIME_RELATED : self::MIME_MIXED; - elseif ($this->bodyHtml) - $type = $this->bodyText ? self::MIME_ALTERNATIVE : self::MIME_HTML; - $this->setContentType($type); - } - if (!isset($this->mailHeader[self::CONTENTENCODE])) $this->setContentEncode(); - $header = ''; - foreach ($this->mailHeader as $key => $value) { - if (!$value) continue; - $header .= $key . ': '; - if (is_array($value)) { - foreach ($value as $_key => $_value) - $header .= (is_string($_key) ? $_key . ' ' . $_value : $_value) . ','; - $header = trim($header, ','); - } else - $header .= $value; - $header .= self::CRLF; - } - return $header . self::CRLF; - } - - /** - * 创建邮件消息体 - * - * @return string - */ - public function createBody() { - $body = ''; - switch ($this->contentType) { - case self::MIME_TEXT: - $body = $this->_encode($this->bodyText) . self::CRLF; - break; - case self::MIME_HTML: - $body = $this->_encode($this->bodyHtml) . self::CRLF; - break; - case self::MIME_ALTERNATIVE: - $body = $this->_createBoundary($this->_boundary(), 'text/plain'); - $body .= $this->_encode($this->bodyText) . self::CRLF; - $body .= $this->_createBoundary($this->_boundary(), 'text/html'); - $body .= $this->_encode($this->bodyHtml) . self::CRLF; - $body .= $this->_boundaryEnd($this->_boundary()); - break; - default: - $body .= $this->_boundaryStart($this->_boundary()); - $body .= sprintf("Content-Type: %s;%s" . "\tboundary=\"%s\"%s", 'multipart/alternative', self::CRLF, - $this->_boundary(1), self::CRLF . self::CRLF); - $body .= $this->_createBoundary($this->_boundary(1), 'text/plain') . self::CRLF; - $body .= $this->_encode($this->bodyText) . self::CRLF . self::CRLF; - $body .= $this->_createBoundary($this->_boundary(1), 'text/html') . self::CRLF; - $body .= $this->_encode($this->bodyHtml) . self::CRLF . self::CRLF; - $body .= $this->_boundaryEnd($this->_boundary(1)); - $body .= $this->_attach(); - break; - } - return $body; - } - - /** - * 设置发件人 - * - * @param string $email 发件人邮箱 - * @param string $name 发件人姓名 - * @return void - */ - public function setFrom($email, $name = null) { - if (!$email || !is_string($email)) return; - $this->from = $email; - $name && $email = $this->_encodeHeader($name) . ' <' . $email . '>'; - $this->setMailHeader(self::FROM, $email, false); - } - - /** - * 取得发件人 - * - * @return string - */ - public function getFrom() { - return $this->from; - } - - /** - * 设置收件人 - * - * @param string|array $email 收件人邮箱 - * @param string $name 收件人姓名 - */ - public function setTo($email, $name = null) { - if (!$email) return; - $email = $this->_setRecipientMail($email, $name); - $this->setMailHeader(self::TO, $email); - } - - /** - * 取得收件人 - * - * @return array - */ - public function getTo() { - return $this->getMailHeader(self::TO); - } - - /** - * 设置抄送人 - * - * @param string $email 抄送人邮箱 - * @param string $name 抄送人姓名 - */ - public function setCc($email, $name = null) { - if (!$email) return; - $email = $this->_setRecipientMail($email, $name); - $this->setMailHeader(self::CC, $email); - } - - /** - * 取得抄送的对象 - * - * @return array - */ - public function getCc() { - return $this->getMailHeader(self::CC); - } - - /** - * 设置暗送人 - * - * @param string $email 暗送人邮箱 - * @param string $name 暗送人姓名 - */ - public function setBcc($email, $name = null) { - if (!$email) return; - $email = $this->_setRecipientMail($email, $name); - $this->setMailHeader(self::BCC, $email); - } - - /** - * 取得暗送对象 - * - * @return array - */ - public function getBcc() { - return $this->getMailHeader(self::BCC); - } - - /** - * 设置邮件主题 - * - * @param string $subject 主题 - */ - public function setSubject($subject) { - $this->setMailHeader(self::SUBJECT, $this->_encodeHeader($subject), false); - } - - /** - * 取得邮件主题 - * - * @return string - */ - public function getSubject() { - $subject = $this->getMailHeader(self::SUBJECT); - is_array($subject) && $subject = $subject[0]; - return str_replace(array("\r", "\n"), array('', ' '), $subject); - } - - /** - * 设置邮件日期 - * - * @param string $data - */ - public function setDate($date) { - $this->setMailHeader(self::DATE, $date); - } - - /** - * 设置邮件头 - * - * @param string $name 邮件头名称 - * @param string $value 邮件头对应的值 - * @param boolean $append 是否是追加 - * @return void - */ - public function setMailHeader($name, $value, $append = true) { - is_array($value) || $value = array($value); - if (false === $append || !isset($this->mailHeader[$name])) { - $this->mailHeader[$name] = $value; - } else { - foreach ($value as $key => $_value) { - if (is_string($key)) - $this->mailHeader[$name][$key] = $_value; - else - $this->mailHeader[$name][] = $_value; - } - } - } - - /** - * 返回邮件头信息值 - * - * @param string $name - */ - public function getMailHeader($name) { - if (!$name) return $this->mailHeader; - return isset($this->mailHeader[$name]) ? $this->mailHeader[$name] : array(); - } - - /** - * 设置邮件消息ID - */ - public function setMessageId() { - $user = array_pop($this->getFrom()); - $user || $user = getmypid(); - if ($recipient = $this->getRecipients()) { - $recipient = array_rand($recipient); - } else - $recipient = 'No recipient'; - $host = isset($_SERVER["SERVER_NAME"]) ? $_SERVER["SERVER_NAME"] : php_uname('n'); - $message = sha1(time() . $user . mt_rand() . $recipient) . '@' . $host; - $this->setMailHeader(self::MESSAGEID, '<' . $message . '>'); - } - - /** - * 设置邮件编码 - * - * @param string $encode - */ - public function setContentEncode($encode = self::ENCODE_BASE64) { - $this->encode = $encode; - $this->setMailHeader(self::CONTENTENCODE, $encode); - } - - /** - * 设置邮件类型 - * - * @param string $type - */ - public function setContentType($type = self::MIME_TEXT) { - if (self::MIME_TEXT == $type || self::MIME_HTML == $type) - $contentType = sprintf("%s; charset=\"%s\"", $type, $this->charset); - elseif (self::MIME_RELATED == $type) - $contentType = sprintf("%s;%s type=\"text/html\";%s boundary=\"%s\"", self::MIME_RELATED, self::CRLF, - self::CRLF, $this->_boundary()); - else - $contentType = sprintf("%s;%s boundary=\"%s\"", $type, self::CRLF, $this->_boundary()); - $this->contentType = $type; - $this->setMailHeader(self::CONTENTTYPE, $contentType, false); - } - - /** - * 上传附件 - * - * @return string - */ - private function _attach() { - $attach = ''; - foreach ($this->attachment as $key => $value) { - list($stream, $mime, $disposition, $encode, $filename, $cid) = $value; - $filename || $filename = 'attachment_' . $key; - $attach .= $this->_boundaryStart($this->_boundary()); - $attach .= sprintf(self::CONTENTTYPE . ": %s; name=\"%s\"%s", $mime, $filename, self::CRLF); - $attach .= sprintf(self::CONTENTENCODE . ": %s%s", $encode, self::CRLF); - if ($disposition == 'inline') { - $attach .= sprintf(self::CONTENTID . ": <%s>%s", $cid, self::CRLF); - } - $attach .= sprintf(self::CONTENTPOSITION . ": %s; filename=\"%s\"%s%s", $disposition, $filename, self::CRLF, - self::CRLF); - $attach .= $this->_encode($stream, $encode) . self::CRLF; - } - $attach .= $this->_boundaryEnd($this->_boundary()); - return $attach; - } - - /** - * 取得下一个quoted-printable - * @param string $string - * @return string - */ - private static function getNextQpToken($string) { - return '=' == substr($string, 0, 1) ? substr($string, 0, 3) : substr($string, 0, 1); - } - - /** - * 获取边界线 - * - * @return string - */ - private function _createBoundary($boundary, $contentType, $charset = '', $encode = '') { - $result = ''; - $charset || $charset = $this->charset; - $encode || $encode = $this->encode; - $result .= $this->_boundaryStart($boundary); - $result .= sprintf(self::CONTENTTYPE . ": %s; charset=\"%s\"", $contentType, $charset); - $result .= self::CRLF; - $result .= sprintf(self::CONTENTENCODE . ": %s%s", $encode, self::CRLF); - $result .= self::CRLF; - return $result; - } - - /** - * @param boundary - * @return string - */ - private function _boundaryStart($boundary) { - return '--' . $boundary . self::CRLF; - } - - /** - * 获取结束边界线 - * - * @return string - */ - private function _boundaryEnd($boundary) { - return self::CRLF . '--' . $boundary . '--' . self::CRLF; - } - - /** - * 设置并返回边界线 - * - * @param int $i 默认值为0 - * @return string - */ - private function _boundary($i = 0) { - if (!$this->boundary) { - $uniq_id = md5(uniqid(time())); - $this->boundary[0] = 'b1_' . $uniq_id; - $this->boundary[1] = 'b2_' . $uniq_id; - } - return $i == 1 ? $this->boundary[1] : $this->boundary[0]; - } - - /** - * 编码邮件内容 - * - * @param string $message - * @param string $encode - * @return string - */ - private function _encode($message, $encode = '') { - $encode || $encode = $this->encode; - if (in_array($encode, array(self::ENCODE_7BIT, self::ENCODE_8BIT))) - $encode = self::ENCODE_BINARY; - $mailEncoder = Wind::import("WIND:mail.encode.WindMail" . ucfirst($encode)); - if (!class_exists($mailEncoder)) throw new WindMailException( - '[mail.WindMail._encode] encod class for ' . $encode . ' is not exist.'); - /* @var $mailEncoder IWindMailEncoder */ - $mailEncoder = new $mailEncoder(); - return $mailEncoder->encode(trim($message), self::LINELENGTH, self::CRLF); - } - - /** - * 编码邮件头部 - * - * @param string $message - * @param string $encode - * @return string - */ - private function _encodeHeader($message, $encode = '') { - $encode || $encode = $this->encode; - if (in_array($encode, array(self::ENCODE_7BIT, self::ENCODE_8BIT))) - $encode = self::ENCODE_BINARY; - $mailEncoder = Wind::import("WIND:mail.encode.WindMail" . ucfirst($encode)); - if (!class_exists($mailEncoder)) throw new WindMailException( - '[mail.WindMail._encode] encod class for ' . $encode . ' is not exist.'); - /* @var $mailEncoder IWindMailEncoder */ - $mailEncoder = new $mailEncoder(); - $message = strtr(trim($message), array("\r" => '', "\n" => '', "\r\n" => '')); - return $mailEncoder->encodeHeader($message, $this->charset, self::LINELENGTH, self::CRLF); - } - - /** - * @param string $email - * @param string $name - */ - private function _setRecipientMail($email, $name) { - $_email = ''; - if (is_array($email)) { - foreach ($email as $_e => $_n) { - $_email .= $_n ? $this->_encodeHeader($_n) . ' <' . $_e . '>' : $_e; - $this->recipients[] = $_e; - } - } else { - $_email = $name ? $this->_encodeHeader($name) . ' <' . $email . '>' : $email; - $this->recipients[] = $email; - } - return $_email; - } - - /** - * 取得真实的收件人 - * - * @return array - */ - public function getRecipients() { - return $this->recipients; - } - - /** - * 设置附件 - * - * @param string $stream 附件名或者附件内容 - * @param string $mime 附件类型 - * @param string $disposition 附件展现方式 - * @param string $encode 附件编码 - * @param string $filename 文件名 - * @param string $cid 内容ID - */ - public function setAttachment($stream, $mime = self::MIME_OCTETSTREAM, $disposition = self::DIS_ATTACHMENT, $encode = self::ENCODE_BASE64, $filename = null, $cid = 0) { - $this->attachment[] = array($stream, $mime, $disposition, $encode, $filename, $cid); - } - - /** - * 设置邮件展示内容 - * - * @param string $body - */ - public function setBody($body) { - $this->bodyHtml = $body; - } - - /** - * 设置邮件文本展示内容 - * @param string $bodyText - */ - public function setBodyText($bodyText) { - $this->bodyText = $bodyText; - } - - /** - * 设置邮件字符 - * @param string $charset - */ - public function setCharset($charset) { - $this->charset = $charset; - } - - /** - * 设置是否是内嵌资源 - * @param boolean $embed - */ - public function setEmbed($embed = false) { - $this->embed = $embed; - } -} \ No newline at end of file +class WindMail +{ + /** + * + * @var array 邮件头 + */ + private $mailHeader = array(); + /** + * + * @var array 邮件附件 + */ + private $attachment = array(); + /** + * + * @var string 邮件字符集 + */ + private $charset = 'utf-8'; + /** + * + * @var string 是否是内嵌资源 + */ + private $embed = false; + /** + * + * @var array 邮件收件人 + */ + private $recipients = null; + /** + * + * @var string 邮件发件人 + */ + private $from = ''; + /** + * + * @var string 邮件消息体html展现方式 + */ + private $bodyHtml = ''; + /** + * + * @var string 邮件消息体文本展现方式 + */ + private $bodyText = ''; + /** + * + * @var array 邮件边界线 + */ + private $boundary; + /** + * + * @var string 邮件编码方式 + */ + private $encode = self::ENCODE_BASE64; + /** + * + * @var 内容类型 + */ + private $contentType; + + // 常用邮件MIME + const CRLF = "\n"; + const TO = 'To'; + const CC = 'Cc'; + const BCC = 'Bcc'; + const FROM = 'From'; + const SUBJECT = 'Subject'; + const MESSAGEID = 'Message-Id'; + const CONTENTTYPE = 'Content-Type'; + const CONTENTENCODE = 'Content-Transfer-Encoding'; + const CONTENTID = 'Content-ID'; + const CONTENTPOSITION = 'Content-Disposition'; + const CONTENTDESCRIPT = 'Content-Description'; + const CONTENTLOCATION = 'Content-Location'; + const CONTENTLANGUAGE = 'Content-Language'; + const DATE = 'Date'; + + // 邮件MIME类型 + const MIME_OCTETSTREAM = 'application/octet-stream'; + const MIME_TEXT = 'text/plain'; + const MIME_HTML = 'text/html'; + const MIME_ALTERNATIVE = 'multipart/alternative'; + const MIME_MIXED = 'multipart/mixed'; + const MIME_RELATED = 'multipart/related'; + + // 邮件编码 + const ENCODE_7BIT = '7bit'; + const ENCODE_8BIT = '8bit'; + const ENCODE_QP = 'quoted-printable'; + const ENCODE_BASE64 = 'base64'; + const ENCODE_BINARY = 'binary'; + + // 邮件编码内容 + const DIS_ATTACHMENT = 'attachment'; + const DIS_INLINE = 'inline'; + const LINELENGTH = 72; + + // 邮件发送方式 + const SEND_SMTP = 'smtp'; + const SEND_PHP = 'php'; + const SEND_SEND = 'send'; + + /** + * 发送邮件 + * + * @param string $type 发送类型 + * @param array $config 邮件发送器需要的配置数据 + * @return bool + * @throws Exception + */ + public function send($type = self::SEND_SMTP, $config = array()) + { + $class = 'Wind'.ucfirst($type).'Mail'; + /* @var $sender IWindSendMail */ + $sender = WindFactory::createInstance($class); + + return $sender->send($this, $config); + } + + /** + * 创建邮件头信息 + * + * @return string + */ + public function createHeader() + { + if (!isset($this->mailHeader[self::CONTENTTYPE])) { + $type = self::MIME_TEXT; + if ($this->attachment) { + $type = $this->embed ? self::MIME_RELATED : self::MIME_MIXED; + } elseif ($this->bodyHtml) { + $type = $this->bodyText ? self::MIME_ALTERNATIVE : self::MIME_HTML; + } + $this->setContentType($type); + } + if (!isset($this->mailHeader[self::CONTENTENCODE])) { + $this->setContentEncode(); + } + $header = ''; + foreach ($this->mailHeader as $key => $value) { + if (!$value) { + continue; + } + $header .= $key.': '; + if (is_array($value)) { + foreach ($value as $_key => $_value) { + $header .= (is_string($_key) ? $_key.' '.$_value : $_value).','; + } + $header = trim($header, ','); + } else { + $header .= $value; + } + $header .= self::CRLF; + } + + return $header.self::CRLF; + } + + /** + * 创建邮件消息体 + * + * @return string + */ + public function createBody() + { + $body = ''; + switch ($this->contentType) { + case self::MIME_TEXT: + $body = $this->_encode($this->bodyText).self::CRLF; + break; + case self::MIME_HTML: + $body = $this->_encode($this->bodyHtml).self::CRLF; + break; + case self::MIME_ALTERNATIVE: + $body = $this->_createBoundary($this->_boundary(), 'text/plain'); + $body .= $this->_encode($this->bodyText).self::CRLF; + $body .= $this->_createBoundary($this->_boundary(), 'text/html'); + $body .= $this->_encode($this->bodyHtml).self::CRLF; + $body .= $this->_boundaryEnd($this->_boundary()); + break; + default: + $body .= $this->_boundaryStart($this->_boundary()); + $body .= sprintf('Content-Type: %s;%s'."\tboundary=\"%s\"%s", + 'multipart/alternative', self::CRLF, $this->_boundary(1), + self::CRLF.self::CRLF); + $body .= $this->_createBoundary($this->_boundary(1), 'text/plain').self::CRLF; + $body .= $this->_encode($this->bodyText).self::CRLF.self::CRLF; + $body .= $this->_createBoundary($this->_boundary(1), 'text/html').self::CRLF; + $body .= $this->_encode($this->bodyHtml).self::CRLF.self::CRLF; + $body .= $this->_boundaryEnd($this->_boundary(1)); + $body .= $this->_attach(); + break; + } + + return $body; + } + + /** + * 设置发件人 + * + * @param string $email 发件人邮箱 + * @param string $name 发件人姓名 + */ + public function setFrom($email, $name = null) + { + if (!$email || !is_string($email)) { + return; + } + $this->from = $email; + $name && $email = $this->_encodeHeader($name).' <'.$email.'>'; + $this->setMailHeader(self::FROM, $email, false); + } + + /** + * 取得发件人 + * + * @return string + */ + public function getFrom() + { + return $this->from; + } + + /** + * 设置收件人 + * + * @param string|array $email 收件人邮箱 + * @param string $name 收件人姓名 + */ + public function setTo($email, $name = null) + { + if (!$email) { + return; + } + $email = $this->_setRecipientMail($email, $name); + $this->setMailHeader(self::TO, $email); + } + + /** + * 取得收件人 + * + * @return array + */ + public function getTo() + { + return $this->getMailHeader(self::TO); + } + + /** + * 设置抄送人 + * + * @param string $email 抄送人邮箱 + * @param string $name 抄送人姓名 + */ + public function setCc($email, $name = null) + { + if (!$email) { + return; + } + $email = $this->_setRecipientMail($email, $name); + $this->setMailHeader(self::CC, $email); + } + + /** + * 取得抄送的对象 + * + * @return array + */ + public function getCc() + { + return $this->getMailHeader(self::CC); + } + + /** + * 设置暗送人 + * + * @param string $email 暗送人邮箱 + * @param string $name 暗送人姓名 + */ + public function setBcc($email, $name = null) + { + if (!$email) { + return; + } + $email = $this->_setRecipientMail($email, $name); + $this->setMailHeader(self::BCC, $email); + } + + /** + * 取得暗送对象 + * + * @return array + */ + public function getBcc() + { + return $this->getMailHeader(self::BCC); + } + + /** + * 设置邮件主题 + * + * @param string $subject 主题 + */ + public function setSubject($subject) + { + $this->setMailHeader(self::SUBJECT, $this->_encodeHeader($subject), false); + } + + /** + * 取得邮件主题 + * + * @return string + */ + public function getSubject() + { + $subject = $this->getMailHeader(self::SUBJECT); + is_array($subject) && $subject = $subject[0]; + + return str_replace(array("\r", "\n"), array('', ' '), $subject); + } + + /** + * 设置邮件日期 + * + * @param string $data + */ + public function setDate($date) + { + $this->setMailHeader(self::DATE, $date); + } + + /** + * 设置邮件头 + * + * @param string $name 邮件头名称 + * @param string $value 邮件头对应的值 + * @param bool $append 是否是追加 + */ + public function setMailHeader($name, $value, $append = true) + { + is_array($value) || $value = array($value); + if (false === $append || !isset($this->mailHeader[$name])) { + $this->mailHeader[$name] = $value; + } else { + foreach ($value as $key => $_value) { + if (is_string($key)) { + $this->mailHeader[$name][$key] = $_value; + } else { + $this->mailHeader[$name][] = $_value; + } + } + } + } + + /** + * 返回邮件头信息值 + * + * @param string $name + */ + public function getMailHeader($name) + { + if (!$name) { + return $this->mailHeader; + } + + return isset($this->mailHeader[$name]) ? $this->mailHeader[$name] : array(); + } + + /** + * 设置邮件消息ID + */ + public function setMessageId() + { + $user = array_pop($this->getFrom()); + $user || $user = getmypid(); + if ($recipient = $this->getRecipients()) { + $recipient = array_rand($recipient); + } else { + $recipient = 'No recipient'; + } + $host = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : php_uname('n'); + $message = sha1(time().$user.mt_rand().$recipient).'@'.$host; + $this->setMailHeader(self::MESSAGEID, '<'.$message.'>'); + } + + /** + * 设置邮件编码 + * + * @param string $encode + */ + public function setContentEncode($encode = self::ENCODE_BASE64) + { + $this->encode = $encode; + $this->setMailHeader(self::CONTENTENCODE, $encode); + } + + /** + * 设置邮件类型 + * + * @param string $type + */ + public function setContentType($type = self::MIME_TEXT) + { + if (self::MIME_TEXT == $type || self::MIME_HTML == $type) { + $contentType = sprintf('%s; charset="%s"', $type, $this->charset); + } elseif (self::MIME_RELATED == $type) { + $contentType = sprintf('%s;%s type="text/html";%s boundary="%s"', + self::MIME_RELATED, self::CRLF, self::CRLF, $this->_boundary()); + } else { + $contentType = sprintf('%s;%s boundary="%s"', $type, self::CRLF, $this->_boundary()); + } + $this->contentType = $type; + $this->setMailHeader(self::CONTENTTYPE, $contentType, false); + } + + /** + * 上传附件 + * + * @return string + */ + private function _attach() + { + $attach = ''; + foreach ($this->attachment as $key => $value) { + list($stream, $mime, $disposition, $encode, $filename, $cid) = $value; + $filename || $filename = 'attachment_'.$key; + $attach .= $this->_boundaryStart($this->_boundary()); + $attach .= sprintf(self::CONTENTTYPE.': %s; name="%s"%s', $mime, $filename, + self::CRLF); + $attach .= sprintf(self::CONTENTENCODE.': %s%s', $encode, self::CRLF); + if ($disposition == 'inline') { + $attach .= sprintf(self::CONTENTID.': <%s>%s', $cid, self::CRLF); + } + $attach .= sprintf(self::CONTENTPOSITION.': %s; filename="%s"%s%s', $disposition, + $filename, self::CRLF, self::CRLF); + $attach .= $this->_encode($stream, $encode).self::CRLF; + } + $attach .= $this->_boundaryEnd($this->_boundary()); + + return $attach; + } + + /** + * 取得下一个quoted-printable + * + * @param string $string + * @return string + */ + private static function getNextQpToken($string) + { + return '=' == substr($string, 0, 1) ? substr($string, 0, 3) : substr($string, 0, 1); + } + + /** + * 获取边界线 + * + * @return string + */ + private function _createBoundary($boundary, $contentType, $charset = '', $encode = '') + { + $result = ''; + $charset || $charset = $this->charset; + $encode || $encode = $this->encode; + $result .= $this->_boundaryStart($boundary); + $result .= sprintf(self::CONTENTTYPE.': %s; charset="%s"', $contentType, $charset); + $result .= self::CRLF; + $result .= sprintf(self::CONTENTENCODE.': %s%s', $encode, self::CRLF); + $result .= self::CRLF; + + return $result; + } + + /** + * + * @param boundary + * @return string + */ + private function _boundaryStart($boundary) + { + return '--'.$boundary.self::CRLF; + } + + /** + * 获取结束边界线 + * + * @return string + */ + private function _boundaryEnd($boundary) + { + return self::CRLF.'--'.$boundary.'--'.self::CRLF; + } + + /** + * 设置并返回边界线 + * + * @param int $i 默认值为0 + * @return string + */ + private function _boundary($i = 0) + { + if (!$this->boundary) { + $uniq_id = md5(uniqid(time())); + $this->boundary[0] = 'b1_'.$uniq_id; + $this->boundary[1] = 'b2_'.$uniq_id; + } + + return $i == 1 ? $this->boundary[1] : $this->boundary[0]; + } + + /** + * 编码邮件内容 + * + * @param string $message + * @param string $encode + * @return string + */ + private function _encode($message, $encode = '') + { + return $this->_getEncoder($encode)->encode(trim($message), self::LINELENGTH, self::CRLF); + } + + /** + * 编码邮件头部 + * + * @param string $message + * @param string $encode + * @return string + */ + private function _encodeHeader($message, $encode = '') + { + $message = strtr(trim($message), array("\r" => '', "\n" => '', "\r\n" => '')); + + return $this->_getEncoder($encode)->encodeHeader($message, $this->charset, self::LINELENGTH, + self::CRLF); + } + + /** + * 根据当前编码获取邮件编码器,并返回邮件编码器对象 + * + * @param encode + * @return IWindMailEncoder + */ + private function _getEncoder($encode) + { + $encode || $encode = $this->encode; + switch ($encode) { + case self::ENCODE_QP: + $mailEncoder = 'WindMailQp'; + break; + case self::ENCODE_BASE64: + $mailEncoder = 'WindMailBase64'; + break; + case self::ENCODE_7BIT: + case self::ENCODE_8BIT: + default: + $mailEncoder = 'WindMailBinary'; + break; + } + if (!class_exists($mailEncoder)) { + throw new WindMailException( + '[mail.WindMail._encode] encod class for '.$encode.' is not exist.'); + } + + return new $mailEncoder(); + } + + /** + * + * @param string $email + * @param string $name + */ + private function _setRecipientMail($email, $name) + { + $_email = ''; + if (is_array($email)) { + foreach ($email as $_e => $_n) { + $_email .= $_n ? $this->_encodeHeader($_n).' <'.$_e.'>' : $_e; + $this->recipients[] = $_e; + } + } else { + $_email = $name ? $this->_encodeHeader($name).' <'.$email.'>' : $email; + $this->recipients[] = $email; + } + + return $_email; + } + + /** + * 取得真实的收件人 + * + * @return array + */ + public function getRecipients() + { + return $this->recipients; + } + + /** + * 设置附件 + * + * @param string $stream 附件名或者附件内容 + * @param string $mime 附件类型 + * @param string $disposition 附件展现方式 + * @param string $encode 附件编码 + * @param string $filename 文件名 + * @param string $cid 内容ID + */ + public function setAttachment($stream, $mime = self::MIME_OCTETSTREAM, $disposition = self::DIS_ATTACHMENT, $encode = self::ENCODE_BASE64, $filename = null, $cid = 0) + { + $this->attachment[] = array($stream, $mime, $disposition, $encode, $filename, $cid); + } + + /** + * 设置邮件展示内容 + * + * @param string $body + */ + public function setBody($body) + { + $this->bodyHtml = $body; + } + + /** + * 设置邮件文本展示内容 + * + * @param string $bodyText + */ + public function setBodyText($bodyText) + { + $this->bodyText = $bodyText; + } + + /** + * 设置邮件字符 + * + * @param string $charset + */ + public function setCharset($charset) + { + $this->charset = $charset; + } + + /** + * 设置是否是内嵌资源 + * + * @param bool $embed + */ + public function setEmbed($embed = false) + { + $this->embed = $embed; + } +} diff --git a/wind/mail/encode/WindMailBase64.php b/wind/mail/encode/WindMailBase64.php index d6d4de0b..bf5bd6a4 100644 --- a/wind/mail/encode/WindMailBase64.php +++ b/wind/mail/encode/WindMailBase64.php @@ -1,8 +1,9 @@ encode($string, $length, $linebreak); - /** - * 用Base64方式编码邮件头 - * - * @param string $string - * @param int $length - * @param string $linebreak - */ - public function encodeHeader($string, $charset, $length, $linebreak) { - $prefix = '=?' . $charset . '?B?'; - $suffix = '?='; - $length = $length - strlen($prefix) - strlen($suffix); - $string = $this->encode($string, $length, $linebreak); - return $prefix . strtr($string, array($linebreak => $suffix . $linebreak . $prefix)) . $suffix; - } + return $prefix.strtr($string, array($linebreak => $suffix.$linebreak." $prefix")).$suffix; + } } - -?> \ No newline at end of file diff --git a/wind/mail/encode/WindMailBinary.php b/wind/mail/encode/WindMailBinary.php index 50281361..0cb3cf5b 100644 --- a/wind/mail/encode/WindMailBinary.php +++ b/wind/mail/encode/WindMailBinary.php @@ -1,5 +1,6 @@ \ No newline at end of file diff --git a/wind/mail/encode/WindMailQp.php b/wind/mail/encode/WindMailQp.php index d0c3b44a..37dff8eb 100644 --- a/wind/mail/encode/WindMailQp.php +++ b/wind/mail/encode/WindMailQp.php @@ -1,9 +1,10 @@ 126)) { + $h2 = floor($dec / 16); + $h1 = floor($dec % 16); + $c = $escape.$hex["$h2"].$hex["$h1"]; + $length += 2; + $addtl_chars += 2; + } + if ($length >= $line_max) { + $cur_conv_line .= $c; + $whitesp_diff = $i - $whitespace_pos + $addtl_chars; + if (($i + $addtl_chars) > $whitesp_diff) { + $output .= substr($cur_conv_line, 0, (strlen($cur_conv_line) - $whitesp_diff)).$linebreak; + $i = $i - $whitesp_diff + $addtl_chars; + } else { + $output .= $cur_conv_line.$linebreak; + } + $cur_conv_line = ''; + $length = 0; + $whitespace_pos = 0; + } else { + $cur_conv_line .= $c; + } + } + $length = 0; + $whitespace_pos = 0; + $output .= $cur_conv_line; + if ($j <= count($lines) - 1) { + $output .= $linebreak; + } + $cur_conv_line = ''; + } - /* (non-PHPdoc) - * @see IWindMailEncoder::decodeHeader() - */ - public function decodeHeader($string, $charset, $length, $linebread) {} + return trim($output); + } - /** - * 用Base64方式编码邮件内容 - * - * @param string $string - * @param int $line_max - * @param string $linebreak - */ - public function encode($string, $line_max, $linebreak) { - $hex = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'); - $lines = preg_split("/(?:\r\n|\r|\n)/", $string); - $line_max = $line_max - strlen($linebreak); - $escape = "="; - $output = ""; - $cur_conv_line = ""; - $length = 0; - $whitespace_pos = 0; - $addtl_chars = 0; - for ($j = 0; $j < count($lines); $j++) { - $line = $lines[$j]; - $linlen = strlen($line); - for ($i = 0; $i < $linlen; $i++) { - $c = substr($line, $i, 1); - $dec = ord($c); - $length++; - if ($dec == 32) { - if (($i == ($linlen - 1))) { - $c = "=20"; - $length += 2; - } - $addtl_chars = 0; - $whitespace_pos = $i; - } else if (($dec == 61) || ($dec < 32) || ($dec > 126)) { - $h2 = floor($dec / 16); - $h1 = floor($dec % 16); - $c = $escape . $hex["$h2"] . $hex["$h1"]; - $length += 2; - $addtl_chars += 2; - } - if ($length >= $line_max) { - $cur_conv_line .= $c; - $whitesp_diff = $i - $whitespace_pos + $addtl_chars; - if (($i + $addtl_chars) > $whitesp_diff) { - $output .= substr($cur_conv_line, 0, (strlen($cur_conv_line) - $whitesp_diff)) . $linebreak; - $i = $i - $whitesp_diff + $addtl_chars; - } else { - $output .= $cur_conv_line . '=' . $linebreak; - } - $cur_conv_line = ""; - $length = 0; - $whitespace_pos = 0; - } else - $cur_conv_line .= $c; - } - $length = 0; - $whitespace_pos = 0; - $output .= $cur_conv_line; - if ($j <= count($lines) - 1) { - $output .= $linebreak; - } - $cur_conv_line = ""; - } - return trim($output); - } + /** + * 编码邮件头 + * + * @param string $string + * @param string $charset + * @param int $length + * @param string $linebreak + */ + public function encodeHeader($string, $charset, $length, $linebreak) + { + $prefix = '=?'.$charset.'?Q?'; + $suffix = '?='; + $length = $length - strlen($prefix) - strlen($suffix); + $string = $this->encode($string, $length, $linebreak); - /** - * 编码邮件头 - * - * @param string $string - * @param string $charset - * @param int $length - * @param string $linebreak - */ - public function encodeHeader($string, $charset, $length, $linebreak) { - $prefix = '=?' . $charset . '?B?'; - $suffix = '?='; - $length = $length - strlen($prefix) - strlen($suffix); - $string = $this->encode($string, $length, $linebreak); - return $prefix . strtr($string, array($linebreak => $suffix . $linebreak . $prefix)) . $suffix; - } + return $prefix.strtr($string, array($linebreak => $suffix.$linebreak." $prefix")).$suffix; + } } -?> \ No newline at end of file diff --git a/wind/mail/exception/WindMailException.php b/wind/mail/exception/WindMailException.php index c3a77b7e..50cc8064 100644 --- a/wind/mail/exception/WindMailException.php +++ b/wind/mail/exception/WindMailException.php @@ -7,8 +7,13 @@ * @package mail * @subpackage exception */ -class WindMailException extends WindException { - +class WindMailException extends WindException +{ + /* (non-PHPdoc) + * @see WindException::messageMapper() + */ + protected function messageMapper($code) + { + return ''; + } } - -?> \ No newline at end of file diff --git a/wind/mail/protocol/WindImap.php b/wind/mail/protocol/WindImap.php index f408093d..5a131b94 100644 --- a/wind/mail/protocol/WindImap.php +++ b/wind/mail/protocol/WindImap.php @@ -1,735 +1,785 @@ - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ + + +/** + * imap协议封装 + * + * @author Qian Su + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id: WindImap.php 3904 2013-01-08 07:01:26Z yishuo $ * @package mail - * @subpackage protocol + * @subpackage protocol */ -class WindImap { - - const CRLF = "\r\n"; - - /** - * @var string w命令标签 - */ - const TAG = 'Tag'; - - /*--------imap中邮件标记---------*/ - - /** - * @var string 已被阅读 - */ - const SEEN = '\seen'; - - /** - * @var string 已被回复 - */ - const ANSWERED = '\Answered'; - - /** - * @var string 标识为紧急 - */ - const FLAGGED = '\Flagged'; - - /** - * @var string 标识为已删除 - */ - const DELETED = '\Deleted'; - - /** - * @var string 草稿 - */ - const DRAFT = '\Draft'; - - /** - * @var string 新邮件 - */ - const RECENT = '\Recent'; - - /*--------imap中邮件标记--------*/ - - /*---------imap中邮件标记类型(store/stripstore方法flags参数)--------*/ - /** - * @var string 邮件的一组标志 - */ - const FLAGS = 'FLAGS'; - - /** - * @var string 表示一组邮件的标志 - */ - const SLIENT = 'FLAGS.SLIENT'; - - /*---------imap中邮件标记类型(store/stripstore方法flags参数)--------*/ - - /*--------fetch函数中参数$dataname的值---------*/ - /** - * @var string 按照一定格式的邮件摘要,包括邮件标志、RFC822.SIZE、自身的时间和信封信息。 - */ - const ALL = 'ALL'; - - /** - * @var string 返回邮件体文本格式和大小的摘要信息 - */ - const BODY = 'BODY'; - - /** - * @var string 返回邮件的一些摘要,包括邮件标志、RFC822.SIZE、和自身的时间 - */ - const FAST = 'FAST'; - - /** - * @var string 要信息,包括邮件标志、RFC822.SIZE、自身的时间和BODYSTRUCTURE的信息。 - */ - const FULL = 'FULL'; - - /** - * @var string 此邮件的标志 - */ - const FLAG = 'FLAGS'; - - /** - * @var string 邮件的[MIME-IMB]的体结构。 - */ - const BODYSTRUCTUR = 'BODYSTRUCTUR'; - - /** - * @var string 自身的时间。 - */ - const INTERNALDATE = 'INTERNALDATE'; - - /** - * @var string 等同于BODY[]。 - */ - const RFC822 = 'RFC822'; - - /** - * @var string 邮件的[RFC-2822]大小 - */ - const RFC822SIZE = 'RFC822.SIZE'; - - /** - * @var string 等同于BODY.PEEK[HEADER], - */ - const RFC822HEADER = 'RFC822.HEADER'; - - /** - * @var string 功能上等同于BODY[TEXT] - */ - const RFC822TEXT = 'RFC822.TEXT'; - - /** - * @var string 返回邮件的UID号,UID号是唯一标识邮件的一个号码。 - */ - const UID = 'UID'; - - /*--------fetch函数中参数$dataname的值---------*/ - - /*--------header中的field--------*/ - /** - * @var string 日期 - */ - const DATE = 'Date'; - - /** - * @var string 发件人 - */ - const FROM = 'From'; - - /** - * @var string 收件人 - */ - const TO = 'To'; - - /** - * @var string 抄送地址 - */ - const CC = 'Cc'; - - /** - * @var string 抄送地址 - */ - const BCC = 'Bcc'; - - /** - * @var string 发送地址 - */ - const DELIVERED = 'Delivered-To'; - - /** - * @var string 回复地址 - */ - const REPLY = 'Reply-To'; - - /** - * @var string 主题 - */ - const SUBEJCT = 'Subject'; - - /** - * @var string MIME内容的类型 - */ - const CONTENTTYPE = 'Content-Type'; - - /** - * @var string 内容的传输编码方式 - */ - const CONTENTENCODE = 'Content-Transfer-Encoding'; - - /** - * @var string MIME版本 - */ - const MIMEVERSION = 'MIME-Version'; - - /** - * @var string 消息ID - */ - const MESSAGEID = 'Message-Id'; - - /** - * @var string 传输路径 - */ - const RECEIVED = 'Received'; - - /** - * @var string 回复地址 - */ - const RETURNPATH = 'Return-Path'; - - /*--------header中的field--------*/ - - /*--------status命令中所用参数--------*/ - /** - * @var string 邮箱中的邮件总数 - */ - const S_MESSAGES = 'MESSAGES'; - - /** - * @var string 邮箱中标志为\RECENT的邮件数 - */ - const S_RECENT = 'RECENT'; - - /** - * @var string 可以分配给新邮件的下一个UID - */ - const S_UIDNEXT = 'UIDNEXT'; - - /** - * @var string 邮箱的UID有效性标志 - */ - const S_UIDVALIDITY = 'UIDVALIDITY'; - - /** - * @var string 邮箱中没有被标志为\UNSEEN的邮件数 - */ - const S_UNSEEN = 'UNSEEN'; - - /*--------status命令中所用参数--------*/ - - /*--------search命令中所用参数--------*/ - /** - * @var string 返回所有的匹配 - */ - CONST SH_ALL = 'ALL'; - - /** - * @var string 返回新的邮件 - */ - CONST SH_NEW = 'NEW'; - - /** - * @var string 返回邮件中打了\Answered标记的邮件 - */ - CONST SH_ANSWERED = 'ANSWERED'; - - /** - * @var string 返回邮件中指字暗送的邮件 - */ - CONST SH_BCC = 'BCC'; - - /** - * @var string 返回指定日期已前的邮件 - */ - CONST SH_BEFORE = 'BEFORE'; - - /** - * @var string 返回有主体的邮件 - */ - CONST SH_BODY = 'BODY'; - - /** - * @var string 返回邮件中打了\Deleted标记的邮件 - */ - CONST SH_DELETED = 'DELETED'; - - /** - * @var string 返回邮件中打了\Flagged标记的邮件 - */ - CONST SH_FLAGGED = 'FLAGGED'; - - /** - * @var string 返回指定发件人字段的邮件 - */ - CONST SH_FROM = 'FROM'; - - /** - * @var string 返回邮件消息中指定keywork的邮件 - */ - CONST SH_KEYWORD = 'KEYWORD'; - - /** - * @var string 返回邮件中打了\Recent标记的邮件 - */ - CONST SH_RECENT = 'RECENT'; - - /** - * @var string 返回邮件中打了\Seen标记的邮件 - */ - CONST SH_SEEN = 'SEEN'; - - /** - * @var string 返回指定日期之后的邮件 - */ - CONST SH_SINCE = 'SINCE'; - - /** - * @var string 返回邮件中文本指定字符串的邮件 - */ - CONST SH_TEXT = 'TEXT'; - - /** - * @var string 返回指定收件人字段的邮件 - */ - CONST SH_TO = 'TO'; - - /** - * @var string 返回邮件中没有打\Answered标记的邮件 - */ - CONST SH_UNANSWERED = 'UNANSWERED'; - - /** - * @var string 返回邮件中没有打\Deleted标记的邮件 - */ - CONST SH_UNDELETED = 'UNDELETED'; - - /** - * @var string 返回邮件中没有指定关键字的邮件 - */ - CONST SH_UNKEYWORD = 'UNKEYWORD'; - - /** - * @var string 返回邮件中没有打\Seen标记的邮件 - */ - CONST SH_UNSEEN = 'UNSEEN'; - - /** - * @var string 返回邮件中没有打\UNFLAGGED标记的邮件 - */ - CONST SH_UNFLAGGED = 'UNFLAGGED'; - - /*--------search命令中所用参数--------*/ - - /******body中的section********/ - const TEXT = 'TEXT'; - - const HEADER = 'HEADER'; - - /******body中的section********/ - /** - * @var WindSocket imap邮件服务器 - */ - protected $imap = null; - - protected $seperate = ' '; - - protected $request = array(); - - protected $resonse = array(); - - private $tag = 0; - - public function __construct($host, $port) { - $this->imap = new WindSocket($host, $port); - } - - /** - * 打开一个imap连接 - * @return string - */ - public function open() { - $this->imap->open(); - return $this->response('*'); - } - - /** - * 登陆 - * @param string $username - * @param string $password - * @return string - */ - public function login($username, $password) { - return $this->communicate("LOGIN {$username} {$password}"); - } - - /** - * 创建指定名字的新邮箱。邮箱名称通常是带路径的文件夹全名。 - * @param string $folder; - * @param string - */ - public function create($folder) { - return $this->communicate("CREATE {$folder}"); - } - - /** - * 除指定名字的文件夹。文件夹名字通常是带路径的文件夹全名, - * 当邮箱被删除后,其中的邮件也不复存在。 - * @param string $folder - * @return string - */ - public function delete($folder) { - return $this->communicate("DELETE {$folder}"); - } - - /** - * RENAME命令可以修改文件夹的名称,它使用两个参数:当前邮箱名和新邮箱名, - * 两个参数的命名符合标准路径命名规则。 - * @param string $old 当前邮箱名 - * @param string $new 新邮箱名, - * @return string - */ - public function rename($old, $new) { - return $this->communicate("RENAME {$old} {$new}"); - } - - /** - * LIST命令用于列出邮箱中已有的文件夹,有点像操作系统的列目录命令 - * @param string $base 用户登陆目录 - * @param string $template 显示的邮箱名。可以使用通配符"*"。 - * @return string - */ - public function folderOfmail($base = '', $template = '*') { - return $this->communicate("LIST {$base} {$template}"); - } - - /** - * 选定某个邮箱(Folder),表示即将对该邮箱(Folder)内的邮件作操作。 - * 邮箱标志的当前状态也返回给了用户,同时返回的还有一些关于邮件和邮箱的附加信息。 - * @param string $folder - */ - public function select($folder) { - return $this->communicate("SELECT $folder"); - } - - /** - * 读取邮件的文本信息,且仅用于显示的目的。 - * @param int|string $mail 希望读取的邮件号或者邮冒号分隔的区段 - * @param string $datanames - */ - public function fetch($mail, $datanames = self::ALL) { - return $this->communicate("FETCH {$mail} {$datanames}"); - } - - /** - * 读取邮件的头信息 - * @param int|string $mail 希望读取的邮件号或者邮冒号分隔的区段 - * @return string - */ - public function fetchHeader($mail) { - return $this->communicate("FETCH {$mail} BODY[HEADER]"); - } - - /** - * 读取邮件的头的字段信息,可能造成不安全,慎用 - * @param int|string $mail 希望读取的邮件号或者邮冒号分隔的区段 - * @param string $field 头字段(DATE\SUBJECT\FROM\TO\MESSAGEID\CONTENTTYPE) - * @return string - */ - public function fetchHeaderFields($mail, $field = self::DATE) { - $field = is_array($field) ? implode(' ', $field) : $field; - return $this->communicate("FETCH {$mail} BODY[HEADER.FIELDS ({$field})]"); - } - - /** - * 读取邮件的头已排除字段信息 - * @param int|string $mail 希望读取的邮件号或者邮冒号分隔的区段 - * @param string $field 头字段(DATE\SUBJECT\FROM\TO\MESSAGEID\CONTENTTYPE) - * @return string - */ - public function fetchHeaderNotFields($mail, $field = self::DATE) { - $field = is_array($field) ? implode(' ', $field) : $field; - return $this->communicate("FETCH {$mail} BODY[HEADER.FIELDS.NOT ({$field})]"); - } - - /** - * 读取邮件的MIME - * @param int|string $mail 希望读取的邮件号或者邮冒号分隔的区段 - * @return string - */ - public function fetchMime($mail) { - return $this->communicate("FETCH {$mail} BODY[MIME]"); - } - - /** - * 读取邮件的Text - * @param int|string $mail 希望读取的邮件号或者邮冒号分隔的区段 - * @return string - */ - public function fetchText($mail) { - return $this->communicate("FETCH {$mail} BODY[TEXT]"); - } - - /** - * 返回邮件的中的某一指定部分,返回的部分用section来表示, - * section部分包含的信息通常是代表某一部分的一个数字或者是下面的某一个部分: - * HEADER, HEADER.FIELDS, HEADER.FIELDS.NOT, MIME, and TEXT。 - * 如果section部分是空的话,那就代表返回全部的信息,包括头信息。 - * @param int|string $mail 希望读取的邮件号或者邮冒号分隔的区段 - * @param int|string $section 返回的部分 - * @return string - */ - public function fetchBySection($mail, $section = self::TEXT) { - return $this->communicate("FETCH {$mail} BODY[$section]"); - } - - /** - * 返回邮件的中的某一指定部分,返回的部分用section来表示, - * section部分包含的信息通常是代表某一部分的一个数字或者是下面的某一个部分: - * HEADER, HEADER.FIELDS, HEADER.FIELDS.NOT, MIME, and TEXT。 - * 如果section部分是空的话,那就代表返回全部的信息,包括头信息。 - * @param int|string $mail 希望读取的邮件号或者邮冒号分隔的区段 - * @param int $start 返回的部分的开始 - * @param int $end 返回的部分的结束 - * @param int:string $section 返回的部分 - * @return string - */ - public function fetchPartialOfSection($mail, $start, $end, $section = self::TEXT) { - return $this->communicate("FETCH {$mail} BODY[$section]<{$start}.{$end}>"); - } - - /** - * 修改指定邮件的属性,包括给邮件打上已读标记、删除标记等 - * @param INT|string $mail - * @param string $flags imap中的邮件标记,值为SLIENT和FLAGS两种类型 - * @param STRING|ARRAY $attribute 标记属性(DELETED\ANSWERED\RECENT\DRAFT\FLAGGED) - * @return string - */ - public function store($mail, $flags = self::FLAGS, $attribute = self::ANSWERED) { - $attribute = is_array($attribute) ? implode(' ', $attribute) : $attribute; - return $this->communicate("STORE {$mail} +" . self::FLAGS . " ($attribute)"); - } - - /** - * 修改指定邮件的属性,包括给邮件打上已读标记、删除标记等 - * @param INT|string $mail - * @param string $flags imap中的邮件标记,值为SLIENT和FLAGS两种类型 - * @param STRING|ARRAY $attribute 标记属性(DELETED\ANSWERED\RECENT\DRAFT\FLAGGED) - * @return string - */ - public function stripStore($mail, $flags = self::FLAGS, $attribute = self::DELETED) { - $attribute = is_array($attribute) ? implode(' ', $attribute) : $attribute; - return $this->communicate("STORE {$mail} -" . self::FLAGS . " ($attribute)"); - } - - /** - * 结束对当前Folder(文件夹/邮箱)的访问, - * 关闭邮箱该邮箱中所有标志为DELETED的邮件就被从物理上删除 - */ - public function close() { - return $this->communicate("CLOSE"); - } - - /** - * 不关闭邮箱的情况下删除所有的标志为、DELETED的邮件。 - * EXPUNGE删除的邮件将不可以恢复。 - */ - public function expunge() { - return $this->communicate("EXPUNGE"); - } - - /** - * 以只读方式打开邮箱 - * @param string $mailbox 邮箱 - * @return string - */ - public function examine($mailbox) { - return $this->communicate("EXAMINE $mailbox"); - } - - /** - * 在客户机的活动邮箱列表中增加一个邮箱 - * @param string $mailbox 希望添加的邮箱名。 - */ - public function subscribe($mailbox) { - return $this->communicate("SUBSCRIBE $mailbox"); - } - - /** - * 来从活动列表中去掉一个邮箱 - * @param string $mailbox 希望去掉的邮箱名。 - */ - public function unsubscribe($mailbox) { - return $this->communicate("UNSUBSCRIBE $mailbox"); - } - - /** - * 修正了LIST命令,LIST返回用户$HOME目录下所有的文件, - * 但LSUB命令只显示那些使用SUBSCRIBE命令设置为活动邮箱的文件 - * @param string $folder 邮箱路径 - * @param string $mailbox 邮箱名。 - * @return string - */ - public function lsub($folder, $mailbox) { - return $this->communicate("LSUB {$mailbox} {$mailbox}"); - } - - /** - * 查询邮箱的当前状态 - * @param string $mailbox 需要查询的邮箱名 - * @param string $params 客户机需要查询的项目列表,S_MESSAGES\S_RECENT\S_UIDNEXT\S_UIDVALIDITY\S_UNSEEN - * @return string - */ - public function status($mailbox, $params = self::S_MESSAGES) { - - $params = is_array($params) ? implode(' ', $params) : $params; - return $this->communicate("STATUS {$mailbox} ({$params})"); - } - - /** - * 在邮箱设置一个检查点,确保内存中的磁盘缓冲数据都被写到了磁盘上。 - */ - public function check() { - return $this->communicate("CHECK"); - } - - /** - * 根据搜索条件在处于活动状态的邮箱中搜索邮件,然后显示匹配的邮件编号。 - * @param string $criteria 查询条件参数,明确查询的关键字 - * @param string $value 查询条件参数,明确查询的关键字的值 - * @param string $charset 字符集标志,缺省的标志符是US-ASCⅡ - * @return string - */ - public function search($criteria = self::SH_ALL, $value = null) { - $search = $criteria; - if ($value) { - $search .= ' ' . $value; - } - return $this->communicate("SEARCH {$search}"); - } - - /** - * UID号是唯一标识邮件系统中邮件的32位证书。 - * 通常这些命令都使用顺序号来标识邮箱中的邮件, - * 使用UID可以使IMAP客户机记住不同IMAP会话中的邮件。 - */ - public function uid() { - return $this->communicate("UID"); - } - - /** - * 把邮件从一个邮箱复制到另一个邮箱 - * @param int $soruce 希望从活动邮箱中复制的邮件的标号 - * @param string $dst 望邮件被复制到的邮箱 - * @return string - */ - public function copy($soruce, $dst) { - return $this->communicate("COPY {$soruce} {$dst}"); - } - - /** - * 返回IMAP服务器支持的功能列表, - * 服务器收到客户机发送的CAPABILITY命令后将返回该服务器所支持的功能。 - */ - public function capability() { - return $this->communicate("CAPABILITY"); - } - - /** - * 结束本次IMAP会话。 - */ - public function logout() { - $this->communicate("LOGOUT"); - } - - /** - * 发送imap会话请求命令 - * @param string $request - */ - public function request($request) { - $this->request[] = $request; - $this->setTag(); - return $this->imap->request($this->getTag() . ' ' . $request . self::CRLF); - } - - /** - * imap会话响应请求 - * @param int $timeout - */ - public function responseLine($timeout = null) { - if (null !== $timeout) { - $this->imap->setSocketTimeOut((int) $timeout); - } - return $this->imap->responseLine(); - } - - /** - * 验证请求 - * @param boolean $multi - * @param int $timeout - * @return string - */ - public function response($endTag = '*', $timeout = null) { - $response = ''; - while ('' != ($_response = $this->responseLine($timeout))) { - list($tag, $status, $info) = explode(' ', $_response, 3); - if (in_array($status, array('NO', "BAD"))) { - throw new WindException($_response); - } - $response .= $_response; - $this->resonse[] = $_response; - if ($endTag == $tag) { - break; - } - } - if (empty($response)) throw new WindException('No response'); - return $response; - } - - /** - * 一次imap会号 - * @param string $request 请求 - * @param string $response 响应 - * @return string - */ - public function communicate($request, &$response = null) { - $this->request($request); - return $response = $this->response($this->getTag()); - } - - /** - * 在imap会话中设置新标答 - */ - public function setTag() { - $this->tag++; - } - - /** - * 取得imap会号中的标签 - * @return string - */ - public function getTag() { - return self::TAG . $this->tag; - } - - public function __destruct() { - if ($this->imap) { - $this->logout(); - $this->imap->close(); - $this->imap = null; - } - } - -} \ No newline at end of file +class WindImap +{ + const CRLF = "\r\n"; + + /** + * @var string w命令标签 + */ + const TAG = 'Tag'; + + /*--------imap中邮件标记---------*/ + + /** + * @var string 已被阅读 + */ + const SEEN = '\seen'; + + /** + * @var string 已被回复 + */ + const ANSWERED = '\Answered'; + + /** + * @var string 标识为紧急 + */ + const FLAGGED = '\Flagged'; + + /** + * @var string 标识为已删除 + */ + const DELETED = '\Deleted'; + + /** + * @var string 草稿 + */ + const DRAFT = '\Draft'; + + /** + * @var string 新邮件 + */ + const RECENT = '\Recent'; + + /*--------imap中邮件标记--------*/ + + /*---------imap中邮件标记类型(store/stripstore方法flags参数)--------*/ + /** + * @var string 邮件的一组标志 + */ + const FLAGS = 'FLAGS'; + + /** + * @var string 表示一组邮件的标志 + */ + const SLIENT = 'FLAGS.SLIENT'; + + /*---------imap中邮件标记类型(store/stripstore方法flags参数)--------*/ + + /*--------fetch函数中参数$dataname的值---------*/ + /** + * @var string 按照一定格式的邮件摘要,包括邮件标志、RFC822.SIZE、自身的时间和信封信息。 + */ + const ALL = 'ALL'; + + /** + * @var string 返回邮件体文本格式和大小的摘要信息 + */ + const BODY = 'BODY'; + + /** + * @var string 返回邮件的一些摘要,包括邮件标志、RFC822.SIZE、和自身的时间 + */ + const FAST = 'FAST'; + + /** + * @var string 要信息,包括邮件标志、RFC822.SIZE、自身的时间和BODYSTRUCTURE的信息。 + */ + const FULL = 'FULL'; + + /** + * @var string 此邮件的标志 + */ + const FLAG = 'FLAGS'; + + /** + * @var string 邮件的[MIME-IMB]的体结构。 + */ + const BODYSTRUCTUR = 'BODYSTRUCTUR'; + + /** + * @var string 自身的时间。 + */ + const INTERNALDATE = 'INTERNALDATE'; + + /** + * @var string 等同于BODY[]。 + */ + const RFC822 = 'RFC822'; + + /** + * @var string 邮件的[RFC-2822]大小 + */ + const RFC822SIZE = 'RFC822.SIZE'; + + /** + * @var string 等同于BODY.PEEK[HEADER], + */ + const RFC822HEADER = 'RFC822.HEADER'; + + /** + * @var string 功能上等同于BODY[TEXT] + */ + const RFC822TEXT = 'RFC822.TEXT'; + + /** + * @var string 返回邮件的UID号,UID号是唯一标识邮件的一个号码。 + */ + const UID = 'UID'; + + /*--------fetch函数中参数$dataname的值---------*/ + + /*--------header中的field--------*/ + /** + * @var string 日期 + */ + const DATE = 'Date'; + + /** + * @var string 发件人 + */ + const FROM = 'From'; + + /** + * @var string 收件人 + */ + const TO = 'To'; + + /** + * @var string 抄送地址 + */ + const CC = 'Cc'; + + /** + * @var string 抄送地址 + */ + const BCC = 'Bcc'; + + /** + * @var string 发送地址 + */ + const DELIVERED = 'Delivered-To'; + + /** + * @var string 回复地址 + */ + const REPLY = 'Reply-To'; + + /** + * @var string 主题 + */ + const SUBEJCT = 'Subject'; + + /** + * @var string MIME内容的类型 + */ + const CONTENTTYPE = 'Content-Type'; + + /** + * @var string 内容的传输编码方式 + */ + const CONTENTENCODE = 'Content-Transfer-Encoding'; + + /** + * @var string MIME版本 + */ + const MIMEVERSION = 'MIME-Version'; + + /** + * @var string 消息ID + */ + const MESSAGEID = 'Message-Id'; + + /** + * @var string 传输路径 + */ + const RECEIVED = 'Received'; + + /** + * @var string 回复地址 + */ + const RETURNPATH = 'Return-Path'; + + /*--------header中的field--------*/ + + /*--------status命令中所用参数--------*/ + /** + * @var string 邮箱中的邮件总数 + */ + const S_MESSAGES = 'MESSAGES'; + + /** + * @var string 邮箱中标志为\RECENT的邮件数 + */ + const S_RECENT = 'RECENT'; + + /** + * @var string 可以分配给新邮件的下一个UID + */ + const S_UIDNEXT = 'UIDNEXT'; + + /** + * @var string 邮箱的UID有效性标志 + */ + const S_UIDVALIDITY = 'UIDVALIDITY'; + + /** + * @var string 邮箱中没有被标志为\UNSEEN的邮件数 + */ + const S_UNSEEN = 'UNSEEN'; + + /*--------status命令中所用参数--------*/ + + /*--------search命令中所用参数--------*/ + /** + * @var string 返回所有的匹配 + */ + const SH_ALL = 'ALL'; + + /** + * @var string 返回新的邮件 + */ + const SH_NEW = 'NEW'; + + /** + * @var string 返回邮件中打了\Answered标记的邮件 + */ + const SH_ANSWERED = 'ANSWERED'; + + /** + * @var string 返回邮件中指字暗送的邮件 + */ + const SH_BCC = 'BCC'; + + /** + * @var string 返回指定日期已前的邮件 + */ + const SH_BEFORE = 'BEFORE'; + + /** + * @var string 返回有主体的邮件 + */ + const SH_BODY = 'BODY'; + + /** + * @var string 返回邮件中打了\Deleted标记的邮件 + */ + const SH_DELETED = 'DELETED'; + + /** + * @var string 返回邮件中打了\Flagged标记的邮件 + */ + const SH_FLAGGED = 'FLAGGED'; + + /** + * @var string 返回指定发件人字段的邮件 + */ + const SH_FROM = 'FROM'; + + /** + * @var string 返回邮件消息中指定keywork的邮件 + */ + const SH_KEYWORD = 'KEYWORD'; + + /** + * @var string 返回邮件中打了\Recent标记的邮件 + */ + const SH_RECENT = 'RECENT'; + + /** + * @var string 返回邮件中打了\Seen标记的邮件 + */ + const SH_SEEN = 'SEEN'; + + /** + * @var string 返回指定日期之后的邮件 + */ + const SH_SINCE = 'SINCE'; + + /** + * @var string 返回邮件中文本指定字符串的邮件 + */ + const SH_TEXT = 'TEXT'; + + /** + * @var string 返回指定收件人字段的邮件 + */ + const SH_TO = 'TO'; + + /** + * @var string 返回邮件中没有打\Answered标记的邮件 + */ + const SH_UNANSWERED = 'UNANSWERED'; + + /** + * @var string 返回邮件中没有打\Deleted标记的邮件 + */ + const SH_UNDELETED = 'UNDELETED'; + + /** + * @var string 返回邮件中没有指定关键字的邮件 + */ + const SH_UNKEYWORD = 'UNKEYWORD'; + + /** + * @var string 返回邮件中没有打\Seen标记的邮件 + */ + const SH_UNSEEN = 'UNSEEN'; + + /** + * @var string 返回邮件中没有打\UNFLAGGED标记的邮件 + */ + const SH_UNFLAGGED = 'UNFLAGGED'; + + /*--------search命令中所用参数--------*/ + + /******body中的section********/ + const TEXT = 'TEXT'; + + const HEADER = 'HEADER'; + + /******body中的section********/ + /** + * @var WindSocket imap邮件服务器 + */ + protected $imap = null; + + protected $seperate = ' '; + + protected $request = array(); + + protected $resonse = array(); + + private $tag = 0; + + public function __construct($host, $port) + { + $this->imap = new WindSocket($host, $port); + } + + /** + * 打开一个imap连接 + * @return string + */ + public function open() + { + $this->imap->open(); + + return $this->response('*'); + } + + /** + * 登陆 + * @param string $username + * @param string $password + * @return string + */ + public function login($username, $password) + { + return $this->communicate("LOGIN {$username} {$password}"); + } + + /** + * 创建指定名字的新邮箱。邮箱名称通常是带路径的文件夹全名。 + * @param string $folder; + * @param string + */ + public function create($folder) + { + return $this->communicate("CREATE {$folder}"); + } + + /** + * 除指定名字的文件夹。文件夹名字通常是带路径的文件夹全名, + * 当邮箱被删除后,其中的邮件也不复存在。 + * @param string $folder + * @return string + */ + public function delete($folder) + { + return $this->communicate("DELETE {$folder}"); + } + + /** + * RENAME命令可以修改文件夹的名称,它使用两个参数:当前邮箱名和新邮箱名, + * 两个参数的命名符合标准路径命名规则。 + * @param string $old 当前邮箱名 + * @param string $new 新邮箱名, + * @return string + */ + public function rename($old, $new) + { + return $this->communicate("RENAME {$old} {$new}"); + } + + /** + * LIST命令用于列出邮箱中已有的文件夹,有点像操作系统的列目录命令 + * @param string $base 用户登陆目录 + * @param string $template 显示的邮箱名。可以使用通配符"*"。 + * @return string + */ + public function folderOfmail($base = '', $template = '*') + { + return $this->communicate("LIST {$base} {$template}"); + } + + /** + * 选定某个邮箱(Folder),表示即将对该邮箱(Folder)内的邮件作操作。 + * 邮箱标志的当前状态也返回给了用户,同时返回的还有一些关于邮件和邮箱的附加信息。 + * @param string $folder + */ + public function select($folder) + { + return $this->communicate("SELECT $folder"); + } + + /** + * 读取邮件的文本信息,且仅用于显示的目的。 + * @param int|string $mail 希望读取的邮件号或者邮冒号分隔的区段 + * @param string $datanames + */ + public function fetch($mail, $datanames = self::ALL) + { + return $this->communicate("FETCH {$mail} {$datanames}"); + } + + /** + * 读取邮件的头信息 + * @param int|string $mail 希望读取的邮件号或者邮冒号分隔的区段 + * @return string + */ + public function fetchHeader($mail) + { + return $this->communicate("FETCH {$mail} BODY[HEADER]"); + } + + /** + * 读取邮件的头的字段信息,可能造成不安全,慎用 + * @param int|string $mail 希望读取的邮件号或者邮冒号分隔的区段 + * @param string $field 头字段(DATE\SUBJECT\FROM\TO\MESSAGEID\CONTENTTYPE) + * @return string + */ + public function fetchHeaderFields($mail, $field = self::DATE) + { + $field = is_array($field) ? implode(' ', $field) : $field; + + return $this->communicate("FETCH {$mail} BODY[HEADER.FIELDS ({$field})]"); + } + + /** + * 读取邮件的头已排除字段信息 + * @param int|string $mail 希望读取的邮件号或者邮冒号分隔的区段 + * @param string $field 头字段(DATE\SUBJECT\FROM\TO\MESSAGEID\CONTENTTYPE) + * @return string + */ + public function fetchHeaderNotFields($mail, $field = self::DATE) + { + $field = is_array($field) ? implode(' ', $field) : $field; + + return $this->communicate("FETCH {$mail} BODY[HEADER.FIELDS.NOT ({$field})]"); + } + + /** + * 读取邮件的MIME + * @param int|string $mail 希望读取的邮件号或者邮冒号分隔的区段 + * @return string + */ + public function fetchMime($mail) + { + return $this->communicate("FETCH {$mail} BODY[MIME]"); + } + + /** + * 读取邮件的Text + * @param int|string $mail 希望读取的邮件号或者邮冒号分隔的区段 + * @return string + */ + public function fetchText($mail) + { + return $this->communicate("FETCH {$mail} BODY[TEXT]"); + } + + /** + * 返回邮件的中的某一指定部分,返回的部分用section来表示, + * section部分包含的信息通常是代表某一部分的一个数字或者是下面的某一个部分: + * HEADER, HEADER.FIELDS, HEADER.FIELDS.NOT, MIME, and TEXT。 + * 如果section部分是空的话,那就代表返回全部的信息,包括头信息。 + * @param int|string $mail 希望读取的邮件号或者邮冒号分隔的区段 + * @param int|string $section 返回的部分 + * @return string + */ + public function fetchBySection($mail, $section = self::TEXT) + { + return $this->communicate("FETCH {$mail} BODY[$section]"); + } + + /** + * 返回邮件的中的某一指定部分,返回的部分用section来表示, + * section部分包含的信息通常是代表某一部分的一个数字或者是下面的某一个部分: + * HEADER, HEADER.FIELDS, HEADER.FIELDS.NOT, MIME, and TEXT。 + * 如果section部分是空的话,那就代表返回全部的信息,包括头信息。 + * @param int|string $mail 希望读取的邮件号或者邮冒号分隔的区段 + * @param int $start 返回的部分的开始 + * @param int $end 返回的部分的结束 + * @param int:string $section 返回的部分 + * @return string + */ + public function fetchPartialOfSection($mail, $start, $end, $section = self::TEXT) + { + return $this->communicate("FETCH {$mail} BODY[$section]<{$start}.{$end}>"); + } + + /** + * 修改指定邮件的属性,包括给邮件打上已读标记、删除标记等 + * @param INT|string $mail + * @param string $flags imap中的邮件标记,值为SLIENT和FLAGS两种类型 + * @param STRING|ARRAY $attribute 标记属性(DELETED\ANSWERED\RECENT\DRAFT\FLAGGED) + * @return string + */ + public function store($mail, $flags = self::FLAGS, $attribute = self::ANSWERED) + { + $attribute = is_array($attribute) ? implode(' ', $attribute) : $attribute; + + return $this->communicate("STORE {$mail} +".self::FLAGS." ($attribute)"); + } + + /** + * 修改指定邮件的属性,包括给邮件打上已读标记、删除标记等 + * @param INT|string $mail + * @param string $flags imap中的邮件标记,值为SLIENT和FLAGS两种类型 + * @param STRING|ARRAY $attribute 标记属性(DELETED\ANSWERED\RECENT\DRAFT\FLAGGED) + * @return string + */ + public function stripStore($mail, $flags = self::FLAGS, $attribute = self::DELETED) + { + $attribute = is_array($attribute) ? implode(' ', $attribute) : $attribute; + + return $this->communicate("STORE {$mail} -".self::FLAGS." ($attribute)"); + } + + /** + * 结束对当前Folder(文件夹/邮箱)的访问, + * 关闭邮箱该邮箱中所有标志为DELETED的邮件就被从物理上删除 + */ + public function close() + { + return $this->communicate('CLOSE'); + } + + /** + * 不关闭邮箱的情况下删除所有的标志为、DELETED的邮件。 + * EXPUNGE删除的邮件将不可以恢复。 + */ + public function expunge() + { + return $this->communicate('EXPUNGE'); + } + + /** + * 以只读方式打开邮箱 + * @param string $mailbox 邮箱 + * @return string + */ + public function examine($mailbox) + { + return $this->communicate("EXAMINE $mailbox"); + } + + /** + * 在客户机的活动邮箱列表中增加一个邮箱 + * @param string $mailbox 希望添加的邮箱名。 + */ + public function subscribe($mailbox) + { + return $this->communicate("SUBSCRIBE $mailbox"); + } + + /** + * 来从活动列表中去掉一个邮箱 + * @param string $mailbox 希望去掉的邮箱名。 + */ + public function unsubscribe($mailbox) + { + return $this->communicate("UNSUBSCRIBE $mailbox"); + } + + /** + * 修正了LIST命令,LIST返回用户$HOME目录下所有的文件, + * 但LSUB命令只显示那些使用SUBSCRIBE命令设置为活动邮箱的文件 + * @param string $folder 邮箱路径 + * @param string $mailbox 邮箱名。 + * @return string + */ + public function lsub($folder, $mailbox) + { + return $this->communicate("LSUB {$mailbox} {$mailbox}"); + } + + /** + * 查询邮箱的当前状态 + * @param string $mailbox 需要查询的邮箱名 + * @param string $params 客户机需要查询的项目列表,S_MESSAGES\S_RECENT\S_UIDNEXT\S_UIDVALIDITY\S_UNSEEN + * @return string + */ + public function status($mailbox, $params = self::S_MESSAGES) + { + $params = is_array($params) ? implode(' ', $params) : $params; + + return $this->communicate("STATUS {$mailbox} ({$params})"); + } + + /** + * 在邮箱设置一个检查点,确保内存中的磁盘缓冲数据都被写到了磁盘上。 + */ + public function check() + { + return $this->communicate('CHECK'); + } + + /** + * 根据搜索条件在处于活动状态的邮箱中搜索邮件,然后显示匹配的邮件编号。 + * @param string $criteria 查询条件参数,明确查询的关键字 + * @param string $value 查询条件参数,明确查询的关键字的值 + * @param string $charset 字符集标志,缺省的标志符是US-ASCⅡ + * @return string + */ + public function search($criteria = self::SH_ALL, $value = null) + { + $search = $criteria; + if ($value) { + $search .= ' '.$value; + } + + return $this->communicate("SEARCH {$search}"); + } + + /** + * UID号是唯一标识邮件系统中邮件的32位证书。 + * 通常这些命令都使用顺序号来标识邮箱中的邮件, + * 使用UID可以使IMAP客户机记住不同IMAP会话中的邮件。 + */ + public function uid() + { + return $this->communicate('UID'); + } + + /** + * 把邮件从一个邮箱复制到另一个邮箱 + * @param int $soruce 希望从活动邮箱中复制的邮件的标号 + * @param string $dst 望邮件被复制到的邮箱 + * @return string + */ + public function copy($soruce, $dst) + { + return $this->communicate("COPY {$soruce} {$dst}"); + } + + /** + * 返回IMAP服务器支持的功能列表, + * 服务器收到客户机发送的CAPABILITY命令后将返回该服务器所支持的功能。 + */ + public function capability() + { + return $this->communicate('CAPABILITY'); + } + + /** + * 结束本次IMAP会话。 + */ + public function logout() + { + $this->communicate('LOGOUT'); + } + + /** + * 发送imap会话请求命令 + * @param string $request + */ + public function request($request) + { + $this->request[] = $request; + $this->setTag(); + + return $this->imap->request($this->getTag().' '.$request.self::CRLF); + } + + /** + * imap会话响应请求 + * @param int $timeout + */ + public function responseLine($timeout = null) + { + if (null !== $timeout) { + $this->imap->setSocketTimeOut((int) $timeout); + } + + return $this->imap->responseLine(); + } + + /** + * 验证请求 + * @param bool $multi + * @param int $timeout + * @return string + */ + public function response($endTag = '*', $timeout = null) + { + $response = ''; + while ('' != ($_response = $this->responseLine($timeout))) { + list($tag, $status, $info) = explode(' ', $_response, 3); + if (in_array($status, array('NO', 'BAD'))) { + throw new WindException('[mail.protocol.WindImap.response] '.$_response); + } + $response .= $_response; + $this->resonse[] = $_response; + if ($endTag == $tag) { + break; + } + } + if (empty($response)) { + throw new WindException('[mail.protocol.WindImap.response] No response'); + } + + return $response; + } + + /** + * 一次imap会号 + * @param string $request 请求 + * @param string $response 响应 + * @return string + */ + public function communicate($request, &$response = null) + { + $this->request($request); + + return $response = $this->response($this->getTag()); + } + + /** + * 在imap会话中设置新标答 + */ + public function setTag() + { + $this->tag++; + } + + /** + * 取得imap会号中的标签 + * @return string + */ + public function getTag() + { + return self::TAG.$this->tag; + } + + public function __destruct() + { + if ($this->imap) { + $this->logout(); + $this->imap->close(); + $this->imap = null; + } + } +} diff --git a/wind/mail/protocol/WindPop3.php b/wind/mail/protocol/WindPop3.php index 2d77385c..0b23799e 100644 --- a/wind/mail/protocol/WindPop3.php +++ b/wind/mail/protocol/WindPop3.php @@ -1,264 +1,296 @@ * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindPop3.php 3904 2013-01-08 07:01:26Z yishuo $ * @package mail * @subpackage protocol */ -class WindPop3 { - - const CRLF = "\r\n"; - - /** - * @var WindSocket pop3邮件服务器 - */ - protected $pop3 = null; - - protected $seperate = ' '; - - protected $request = array(); - - protected $resonse = array(); - - public function __construct($host, $port) { - $this->pop3 = new WindSocket($host, $port); - } - - /** - * 打开pop3服务器,建立连接 - * @return string - */ - public function open() { - $this->pop3->open(); - return $this->response(); - } - - /** - * 登陆pop3 - * @param string $username 用户名 - * @param string $password 密码 - * @return string - */ - public function login($username, $password) { - $this->communicate("USER $username"); - return $this->communicate("PASS $password"); - } - - /** - * 处理请求 server 回送邮箱统计资料,如邮件数、 邮件总字节数 - * @return string - */ - public function stat() { - return $this->communicate('STAT', false, true); - } - - /** - * 处理 server 返回用于该指定邮件的唯一标识, 如果没有指定,返回所有的。 - * @param int $n 指定邮件 - * @return string - */ - public function uidl($n = null) { - $request = $n ? "UIDL $n" : 'UIDL'; - $ifmulti = $n ? false : true; - return $this->communicate($request, $ifmulti, true); - } - - /** - * 处理 server 返回指定邮件的大小等 - * @param int $n 指定邮件 - * @return string - */ - public function getList($n = null) { - $request = $n ? "LIST $n" : 'LIST'; - $ifmulti = $n ? false : true; - return $this->communicate($request, $ifmulti, true); - } - - /** - * 处处理 server 返回邮件的全部文本 - * @param int $n 指定邮件 - * @return string - */ - public function retr($n) { - return $this->communicate("RETR $n", true); - } - - /** - * 处理 server 标记删除,QUIT 命令执行时才真正删除 - * @param int $n 指定邮件 - * @return string - */ - public function dele($n) { - return $this->communicate("DELE $n"); - } - - /** - * 处理撤消所有的 DELE 命令 - * @return string - */ - public function rset() { - return $this->communicate("RSET"); - } - - /** - * 处理 返回 n 号邮件的前 m 行内容,m 必须是自然数 - * @param int $n 指定邮件 - * @param int $m 指定邮件前多少行 - * @return string - */ - public function top($n, $m = null) { - $request = $m ? 'TOP ' . (int) $n . ' ' . (int) $m : 'TOP ' . (int) $n; - return $this->communicate($request, true); - } - - /** - * 处理 server 返回一个肯定的响应 - * @return string - */ - public function noop() { - return $this->communicate("NOOP"); - } - - /** - * 希望结束会话。如果 server 处于"处理" 状态, - * 则现在进入"更新"状态,删除那些标记成删除的邮件。 - * 如果 server 处于"认可"状态,则结束会话时 server - * 不进入"更新"状态 。 - * @return string - */ - public function quit() { - return $this->communicate("QUIT"); - } - - /** - * 结否会话,关闭pop3服务器 - */ - public function close() { - $this->quit(); - $this->pop3->close(); - $this->pop3 = null; - } - - /** - * pop3响应请求 - * @param int $timeout - */ - public function responseLine($timeout = null) { - if (null !== $timeout) { - $this->pop3->setSocketTimeOut((int) $timeout); - } - return $this->pop3->responseLine(); - } - - /** - * 外理响应内容 - * @param string $response - * @return Array - */ - public function buildResponse($response) { - if (empty($response)) { - return array(); - } - $response = explode("\n", $response); - $_response = array(); - foreach ($response as $line) { - if (empty($line)) { - continue; - } - list($key, $value) = explode($this->seperate, trim($line), 2); - $key ? $_response[(int) $key] = $value : $_response[] = $value; - } - return $_response; - } - - /** - * 进行一次网络传输通信 - * @param string $request 发竤的请求命令 - * @param boolean $ifmulti 是否返回多行响应文本,否则为一行 - * @param baoolean $ifbuild 是否对响应进行处理 - * @return array - */ - public function communicate($request, $ifmulti = false, $ifbuild = false) { - $this->request($request); - return $ifbuild ? $this->buildResponse($this->response($ifmulti)) : $this->response($ifmulti); - } - - /** - * 发送pop3命令 - * @param string $request - */ - public function request($request) { - $this->request[] = $request; - return $this->pop3->request($request . self::CRLF); - } - - /** - * 验证请求 - * @param boolean $multi - * @param int $timeout - * @return string - */ - public function response($multi = false, $timeout = null) { - $ok = $this->responseLine($timeout); - if (empty($ok) || !is_string($ok)) { - throw new WindException('Read Failed'); - } - if ('+OK' !== substr($ok, 0, 3)) { - throw new WindException('Request Failed!Pleae See Failed Info:' . $ok); - } - if (true === $multi) { - $response = ''; - while ('' != ($_response = $this->responseLine($timeout))) { - if ('.' === trim($_response)) { - break; - } - $response .= $_response; - $this->resonse[] = $_response; - } - } else { - $this->resonse[] = $ok; - if (strpos($ok, $this->seperate)) { - list(, $response) = explode($this->seperate, $ok, 2); - } else { - $response = $ok; - } - } - if (empty($response)) throw new WindException('No response'); - return $response; - } - - /** - * 获取解析后的内容 - * @param $content - * @param $sep - */ - public function getMailContent($content, $sep = "\n\n") { - $content = explode($sep, $content); - $content[0] = explode("\n", $content[0]); - $headers = array(); - foreach ($content[0] as $value) { - $_value = explode(':', $value); - $headers[$_value[0]] = trim($_value[1]); - } - $encode = $headers['Content-Transfer-Encoding']; - if ('base64' == $encode) { - $content = base64_decode($content[1]); - } else { - $content = $content[1]; - } - return array($headers, $content); - } - - public function __destruct() { - if ($this->pop3) { - $this->close(); - } - } +class WindPop3 +{ + const CRLF = "\r\n"; + + /** + * @var WindSocket pop3邮件服务器 + */ + protected $pop3 = null; + + protected $seperate = ' '; + + protected $request = array(); + + protected $resonse = array(); + + public function __construct($host, $port) + { + $this->pop3 = new WindSocket($host, $port); + } + + /** + * 打开pop3服务器,建立连接 + * @return string + */ + public function open() + { + $this->pop3->open(); + + return $this->response(); + } + + /** + * 登陆pop3 + * @param string $username 用户名 + * @param string $password 密码 + * @return string + */ + public function login($username, $password) + { + $this->communicate("USER $username"); + + return $this->communicate("PASS $password"); + } + + /** + * 处理请求 server 回送邮箱统计资料,如邮件数、 邮件总字节数 + * @return string + */ + public function stat() + { + return $this->communicate('STAT', false, true); + } + + /** + * 处理 server 返回用于该指定邮件的唯一标识, 如果没有指定,返回所有的。 + * @param int $n 指定邮件 + * @return string + */ + public function uidl($n = null) + { + $request = $n ? "UIDL $n" : 'UIDL'; + $ifmulti = $n ? false : true; + + return $this->communicate($request, $ifmulti, true); + } + + /** + * 处理 server 返回指定邮件的大小等 + * @param int $n 指定邮件 + * @return string + */ + public function getList($n = null) + { + $request = $n ? "LIST $n" : 'LIST'; + $ifmulti = $n ? false : true; + + return $this->communicate($request, $ifmulti, true); + } + + /** + * 处处理 server 返回邮件的全部文本 + * @param int $n 指定邮件 + * @return string + */ + public function retr($n) + { + return $this->communicate("RETR $n", true); + } + + /** + * 处理 server 标记删除,QUIT 命令执行时才真正删除 + * @param int $n 指定邮件 + * @return string + */ + public function dele($n) + { + return $this->communicate("DELE $n"); + } + + /** + * 处理撤消所有的 DELE 命令 + * @return string + */ + public function rset() + { + return $this->communicate('RSET'); + } + + /** + * 处理 返回 n 号邮件的前 m 行内容,m 必须是自然数 + * @param int $n 指定邮件 + * @param int $m 指定邮件前多少行 + * @return string + */ + public function top($n, $m = null) + { + $request = $m ? 'TOP '.(int) $n.' '.(int) $m : 'TOP '.(int) $n; + + return $this->communicate($request, true); + } + + /** + * 处理 server 返回一个肯定的响应 + * @return string + */ + public function noop() + { + return $this->communicate('NOOP'); + } + + /** + * 希望结束会话。如果 server 处于"处理" 状态, + * 则现在进入"更新"状态,删除那些标记成删除的邮件。 + * 如果 server 处于"认可"状态,则结束会话时 server + * 不进入"更新"状态 。 + * @return string + */ + public function quit() + { + return $this->communicate('QUIT'); + } + + /** + * 结否会话,关闭pop3服务器 + */ + public function close() + { + $this->quit(); + $this->pop3->close(); + $this->pop3 = null; + } + + /** + * pop3响应请求 + * @param int $timeout + */ + public function responseLine($timeout = null) + { + if (null !== $timeout) { + $this->pop3->setSocketTimeOut((int) $timeout); + } + + return $this->pop3->responseLine(); + } + + /** + * 外理响应内容 + * @param string $response + * @return Array + */ + public function buildResponse($response) + { + if (empty($response)) { + return array(); + } + $response = explode("\n", $response); + $_response = array(); + foreach ($response as $line) { + if (empty($line)) { + continue; + } + list($key, $value) = explode($this->seperate, trim($line), 2); + $key ? $_response[(int) $key] = $value : $_response[] = $value; + } + + return $_response; + } + + /** + * 进行一次网络传输通信 + * @param string $request 发竤的请求命令 + * @param bool $ifmulti 是否返回多行响应文本,否则为一行 + * @param baoolean $ifbuild 是否对响应进行处理 + * @return array + */ + public function communicate($request, $ifmulti = false, $ifbuild = false) + { + $this->request($request); + + return $ifbuild ? $this->buildResponse($this->response($ifmulti)) : $this->response($ifmulti); + } + + /** + * 发送pop3命令 + * @param string $request + */ + public function request($request) + { + $this->request[] = $request; + + return $this->pop3->request($request.self::CRLF); + } + + /** + * 验证请求 + * @param bool $multi + * @param int $timeout + * @return string + */ + public function response($multi = false, $timeout = null) + { + $ok = $this->responseLine($timeout); + if (empty($ok) || !is_string($ok)) { + throw new WindException('[mail.protocol.WindPop3.response] Read Failed'); + } + if ('+OK' !== substr($ok, 0, 3)) { + throw new WindException('[mail.protocol.WindPop3.response] Request Failed!Pleae See Failed Info:'.$ok); + } + if (true === $multi) { + $response = ''; + while ('' != ($_response = $this->responseLine($timeout))) { + if ('.' === trim($_response)) { + break; + } + $response .= $_response; + $this->resonse[] = $_response; + } + } else { + $this->resonse[] = $ok; + if (strpos($ok, $this->seperate)) { + list(, $response) = explode($this->seperate, $ok, 2); + } else { + $response = $ok; + } + } + if (empty($response)) { + throw new WindException('[mail.protocol.WindPop3.response] No response'); + } + + return $response; + } + + /** + * 获取解析后的内容 + * @param $content + * @param $sep + */ + public function getMailContent($content, $sep = "\n\n") + { + $content = explode($sep, $content); + $content[0] = explode("\n", $content[0]); + $headers = array(); + foreach ($content[0] as $value) { + $_value = explode(':', $value); + $headers[$_value[0]] = trim($_value[1]); + } + $encode = $headers['Content-Transfer-Encoding']; + if ('base64' == $encode) { + $content = base64_decode($content[1]); + } else { + $content = $content[1]; + } + + return array($headers, $content); + } + public function __destruct() + { + if ($this->pop3) { + $this->close(); + } + } } -?> \ No newline at end of file diff --git a/wind/mail/protocol/WindSmtp.php b/wind/mail/protocol/WindSmtp.php index abb108e3..522fc0bc 100644 --- a/wind/mail/protocol/WindSmtp.php +++ b/wind/mail/protocol/WindSmtp.php @@ -1,213 +1,248 @@ - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ + + +/** + * 邮件传输协议操作 + * + * @author Qian Su + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id: WindSmtp.php 3904 2013-01-08 07:01:26Z yishuo $ * @package mail - * @subpackage protocol + * @subpackage protocol */ -class WindSmtp { - - const CRLF = "\r\n"; - - /** - * @var WindSocket - */ - protected $smtp = null; - - protected $request = array(); - - protected $resonse = array(); - - public function __construct($host, $port, $timeout = 60) { - $this->smtp = new WindSocket($host, $port, $timeout); - } - - /** - * 打开smtp服务器,建立连接 - * @return string - */ - public function open() { - $this->smtp->open(); - return $this->checkResponse(220); - } - - /** - * 向服务器标识用户身份 - * @param string $host 身份 - * @return string - */ - public function ehlo($host) { - $this->request('EHLO ' . $host); - return $this->checkResponse(250); - } - - /** - * 进行用户身份认证 - * @param string $username 用户名 - * @param string $password 密码 - * @return string - */ - public function authLogin($username, $password) { - $this->request('AUTH LOGIN'); - $this->checkResponse(array(334)); - $this->request(base64_encode($username)); - $this->checkResponse(array(334)); - $this->request(base64_encode($password)); - return $this->checkResponse(array(235)); - } - - /** - * 指定的地址是发件人地址 - * @param string $from 邮件发送者 - * @return string - */ - public function mailFrom($from) { - $this->request('MAIL FROM:' . '<' . $from . '>'); - return $this->checkResponse(250); - } - - /** - * 指定的地址是收件人地址 - * @param string $to 邮件发送者 - * @return string - */ - public function rcptTo($to) { - $this->request('RCPT TO:' . '<' . $to . '>'); - return $this->checkResponse(array(250, 251)); - } - - /** - * 用于验证指定的用户/邮箱是否存在;由于安全方面的原因,服务器常禁止此命令 - * @param string $user - * @return string - */ - public function very($user) { - $this->request('VRFY ' . $user); - return $this->checkResponse(array(250, 251, 252)); - } - - /** - * 验证给定的邮箱列表是否存在,扩充邮箱列表,也常被禁用 - * @param string $name - * @return string - */ - public function expn($name) { - $this->request('EXPN ' . $name); - $response = $this->checkResponse(250); - $entries = explode(self::CRLF, $response); - while (list(, $l) = each($entries)) { - $list[] = substr($l, 4); - } - return $list; - } - - /** - * 无操作,服务器应响应 OK - * @return string - */ - public function noop() { - $this->request('NOOP'); - return $this->checkResponse(250); - } - - /** - * 在单个或多个 RCPT 命令后,表示所有的邮件接收人已标识,并初始化数据传输,以 CRLF.CRLF 结束 - * @param string $data 发送的数据 - * @return string - */ - public function data($data) { - $this->request('DATA'); - $this->checkResponse(354); - $data = str_replace("\r\n", "\n", $data); - $data = str_replace("\r", "\n", $data); - $lines = explode("\n", $data); - foreach ($lines as $line) { - if (0 === strpos($line, '.')) { - $line = '.' . $line; - } - $this->request($line); - } - $this->request('.'); - return $this->checkResponse(250); - } - - /** - * 重置会话,当前传输被取消 - * @return string - */ - public function rset() { - $this->request('RSET'); - return $this->checkResponse(array(250, 220)); - } - - /** - * 结束会话 - * @return string - */ - public function quit() { - $this->request('QUIT'); - return $this->checkResponse(221); - } - - /** - * 关闭smtp服务器 - */ - public function close() { - $this->smtp->close(); - $this->smtp = null; - } - - /** - * smtp响应请求 - * @param int $timeout - */ - public function responseLine($timeout = null) { - if (null !== $timeout) { - $this->smtp->setSocketTimeOut((int) $timeout); - } - return $this->smtp->responseLine(); - } - - /** - * 发送smtp命令 - * @param string $request - */ - public function request($request) { - $this->request[] = $request . self::CRLF; - return $this->smtp->request($request . self::CRLF); - } - - /** - * 验证请求 - * @param string $expect - * @param int $timeout - * @return string - */ - public function checkResponse($expect, $timeout = null) { - $response = ''; - $expect = is_array($expect) ? $expect : array($expect); - while ('' != ($_response = $this->responseLine($timeout))) { - $response .= $_response; - $this->resonse[] = $_response; - list($code, $info) = preg_split('/([\s-]+)/', $_response, 2); - if (null === $code || !in_array($code, $expect)) throw new WindException($info); - if (" " == substr($_response, 3, 1)) { - break; - } - } - if (empty($response)) throw new WindException('No response'); - return $response; - } - - public function __destruct() { - if ($this->smtp) { - $this->close(); - } - } - -} \ No newline at end of file +class WindSmtp +{ + const CRLF = "\r\n"; + + /** + * @var WindSocket + */ + protected $smtp = null; + + protected $request = array(); + + protected $resonse = array(); + + public function __construct($host, $port, $timeout = 60) + { + $this->smtp = new WindSocket($host, $port, $timeout); + } + + /** + * 打开smtp服务器,建立连接 + * @return string + */ + public function open() + { + $this->smtp->open(); + + return $this->checkResponse(220); + } + + /** + * 向服务器标识用户身份 + * @param string $host 身份 + * @return string + */ + public function ehlo($host) + { + $this->request('EHLO '.$host); + + return $this->checkResponse(250); + } + + /** + * 进行用户身份认证 + * @param string $username 用户名 + * @param string $password 密码 + * @return string + */ + public function authLogin($username, $password) + { + $this->request('AUTH LOGIN'); + $this->checkResponse(array(334)); + $this->request(base64_encode($username)); + $this->checkResponse(array(334)); + $this->request(base64_encode($password)); + + return $this->checkResponse(array(235)); + } + + /** + * 指定的地址是发件人地址 + * @param string $from 邮件发送者 + * @return string + */ + public function mailFrom($from) + { + $this->request('MAIL FROM:'.'<'.$from.'>'); + + return $this->checkResponse(250); + } + + /** + * 指定的地址是收件人地址 + * @param string $to 邮件发送者 + * @return string + */ + public function rcptTo($to) + { + $this->request('RCPT TO:'.'<'.$to.'>'); + + return $this->checkResponse(array(250, 251)); + } + + /** + * 用于验证指定的用户/邮箱是否存在;由于安全方面的原因,服务器常禁止此命令 + * @param string $user + * @return string + */ + public function very($user) + { + $this->request('VRFY '.$user); + + return $this->checkResponse(array(250, 251, 252)); + } + + /** + * 验证给定的邮箱列表是否存在,扩充邮箱列表,也常被禁用 + * @param string $name + * @return string + */ + public function expn($name) + { + $this->request('EXPN '.$name); + $response = $this->checkResponse(250); + $entries = explode(self::CRLF, $response); + while (list(, $l) = each($entries)) { + $list[] = substr($l, 4); + } + + return $list; + } + + /** + * 无操作,服务器应响应 OK + * @return string + */ + public function noop() + { + $this->request('NOOP'); + + return $this->checkResponse(250); + } + + /** + * 在单个或多个 RCPT 命令后,表示所有的邮件接收人已标识,并初始化数据传输,以 CRLF.CRLF 结束 + * @param string $data 发送的数据 + * @return string + */ + public function data($data) + { + $this->request('DATA'); + $this->checkResponse(354); + $data = str_replace("\r\n", "\n", $data); + $data = str_replace("\r", "\n", $data); + $lines = explode("\n", $data); + foreach ($lines as $line) { + if (0 === strpos($line, '.')) { + $line = '.'.$line; + } + $this->request($line); + } + $this->request('.'); + + return $this->checkResponse(250); + } + + /** + * 重置会话,当前传输被取消 + * @return string + */ + public function rset() + { + $this->request('RSET'); + + return $this->checkResponse(array(250, 220)); + } + + /** + * 结束会话 + * @return string + */ + public function quit() + { + $this->request('QUIT'); + + return $this->checkResponse(221); + } + + /** + * 关闭smtp服务器 + */ + public function close() + { + $this->smtp->close(); + $this->smtp = null; + } + + /** + * smtp响应请求 + * @param int $timeout + */ + public function responseLine($timeout = null) + { + if (null !== $timeout) { + $this->smtp->setSocketTimeOut((int) $timeout); + } + + return $this->smtp->responseLine(); + } + + /** + * 发送smtp命令 + * @param string $request + */ + public function request($request) + { + $this->request[] = $request.self::CRLF; + + return $this->smtp->request($request.self::CRLF); + } + + /** + * 验证请求 + * @param string $expect + * @param int $timeout + * @return string + */ + public function checkResponse($expect, $timeout = null) + { + $response = ''; + $expect = is_array($expect) ? $expect : array($expect); + while ('' != ($_response = $this->responseLine($timeout))) { + $response .= $_response; + $this->resonse[] = $_response; + list($code, $info) = preg_split('/([\s-]+)/', $_response, 2); + if (null === $code || !in_array($code, $expect)) { + throw new WindException('[mail.protocol.WindSmtp.checkResponse] '.$info); + } + if (' ' == substr($_response, 3, 1)) { + break; + } + } + if (empty($response)) { + throw new WindException('[mail.protocol.WindSmtp.checkResponse] No response'); + } + + return $response; + } + + public function __destruct() + { + if ($this->smtp) { + $this->close(); + } + } +} diff --git a/wind/mail/protocol/WindSocket.php b/wind/mail/protocol/WindSocket.php index d02f4bc0..40ed4581 100644 --- a/wind/mail/protocol/WindSocket.php +++ b/wind/mail/protocol/WindSocket.php @@ -1,124 +1,137 @@ - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ +/** + * socket套接字操作 + * + * @author Qian Su + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id: WindSocket.php 3904 2013-01-08 07:01:26Z yishuo $ * @package mail - * @subpackage protocol + * @subpackage protocol */ -class WindSocket { - - protected $host = '127.0.0.1'; - - protected $port = 80; - - protected $timeout = 5; - - protected $errno = 0; - - protected $errstr = ''; - - protected $socket = null; - - public function __construct($host = '127.0.0.1', $port = 80, $timeout = 5) { - $this->setHost($host); - $this->setPort($port); - $this->setTimeout($timeout); - } - - /** - * 打开一个连接 - */ - public function open() { - if (null == $this->socket) { - $this->socket = fsockopen($this->host, $this->port, $this->errno, $this->errstr, $this->timeout); - } - } - - /** - * 发送请求 - * @param string $request - */ - public function request($request) { - return fputs($this->socket, $request); - } - - /** - * 响应请求 - * @return string - */ - public function response() { - $response = ''; - while (!feof($this->socket)) { - $response .= fgets($this->socket); - } - return $response; - } - - /** - * 响应请求,只返回一行 - * @return string - */ - public function responseLine() { - return feof($this->socket) ? '' : fgets($this->socket); - } - - /** - *关闭连接 - */ - public function close() { - if ($this->socket) { - fclose($this->socket); - $this->socket = null; - } - return true; - } - - /** - * 获取请求中的错误 - * @return string - */ - public function getError() { - return $this->errstr ? $this->errno . ':' . $this->errstr : ''; - } - - /** - * 取得socket操作对象 - * @return resource - */ - public function getSocket() { - return $this->socket; - } - - /** - * 设置主机 - * @param string $host - */ - public function setHost($host) { - $this->host = $host; - - } - - /** - * 设置端口 - * @param string $port - */ - public function setPort($port) { - $this->port = $port; - } - - /** - * 设置超时 - * @param int $timeout - */ - public function setTimeout($timeout) { - $this->timeout = $timeout; - } - - public function setSocketTimeOut($timeout) { - return stream_set_timeout($this->socket, $timeout); - } -} \ No newline at end of file +class WindSocket +{ + protected $host = '127.0.0.1'; + protected $port = 80; + protected $timeout = 5; + protected $errno = 0; + protected $errstr = ''; + protected $socket = null; + + public function __construct($host = '127.0.0.1', $port = 80, $timeout = 5) + { + $this->setHost($host); + $this->setPort($port); + $this->setTimeout($timeout); + } + + /** + * 打开一个连接 + */ + public function open() + { + if (null == $this->socket) { + $this->socket = fsockopen($this->host, $this->port, $this->errno, $this->errstr, + $this->timeout); + if ($this->socket == false) { + throw new WindMailException( + '[mail.protocol.WindSocket.open] Initiates a socket connection fail, '.$this->host.' is not a valid domain.'); + } + } + } + + /** + * 发送请求 + * @param string $request + */ + public function request($request) + { + return fwrite($this->socket, $request); + } + + /** + * 响应请求 + * @return string + */ + public function response() + { + $response = ''; + while (!feof($this->socket)) { + $response .= fgets($this->socket); + } + + return $response; + } + + /** + * 响应请求,只返回一行 + * @return string + */ + public function responseLine() + { + return feof($this->socket) ? '' : fgets($this->socket); + } + + /** + *关闭连接 + */ + public function close() + { + if ($this->socket) { + fclose($this->socket); + $this->socket = null; + } + + return true; + } + + /** + * 获取请求中的错误 + * @return string + */ + public function getError() + { + return $this->errstr ? $this->errno.':'.$this->errstr : ''; + } + + /** + * 取得socket操作对象 + * @return resource + */ + public function getSocket() + { + return $this->socket; + } + + /** + * 设置主机 + * @param string $host + */ + public function setHost($host) + { + $this->host = $host; + } + + /** + * 设置端口 + * @param string $port + */ + public function setPort($port) + { + $this->port = $port; + } + + /** + * 设置超时 + * @param int $timeout + */ + public function setTimeout($timeout) + { + $this->timeout = $timeout; + } + + public function setSocketTimeOut($timeout) + { + return stream_set_timeout($this->socket, $timeout); + } +} diff --git a/wind/mail/sender/IWindSendMail.php b/wind/mail/sender/IWindSendMail.php index 6667b89f..4747b2e6 100644 --- a/wind/mail/sender/IWindSendMail.php +++ b/wind/mail/sender/IWindSendMail.php @@ -1,19 +1,19 @@ - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ +/** + * @author Qian Su + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id: IWindSendMail.php 3298 2012-01-06 12:48:26Z yishuo $ * @package mail - * @subpackage sender + * @subpackage sender */ -interface IWindSendMail { - - /** - * 发送邮件 - * - * @param WindMail $mail 邮件消息封装对象 - * @return boolean - */ - public function send($mail, $config = array()); -} \ No newline at end of file +interface IWindSendMail +{ + /** + * 发送邮件 + * + * @param WindMail $mail 邮件消息封装对象 + * @return bool + */ + public function send($mail, $config = array()); +} diff --git a/wind/mail/sender/WindPhpMail.php b/wind/mail/sender/WindPhpMail.php index cc6801b7..d6b3fedd 100644 --- a/wind/mail/sender/WindPhpMail.php +++ b/wind/mail/sender/WindPhpMail.php @@ -1,24 +1,28 @@ - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ + + +/** + * 使用php内部函数发送邮件 + * + * @author Qian Su + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id: WindPhpMail.php 3583 2012-05-28 03:35:10Z yishuo $ * @package mail - * @subpackage sender + * @subpackage sender */ -class WindPhpMail implements IWindSendMail { +class WindPhpMail implements IWindSendMail +{ + /* (non-PHPdoc) + * @see IWindSendMail::send() + */ + public function send($mail, $config = array()) + { + $to = ''; + foreach ($mail->getRecipients() as $key => $value) { + $to .= $to ? ', '.$value : $value; + } - /* (non-PHPdoc) - * @see IWindSendMail::send() - */ - public function send($mail, $config = array()) { - $to = ''; - foreach ($mail->getRecipients() as $key => $value) - $to .= $to ? ', ' . $value : $value; - return mail($to, $mail->getSubject(), $mail->createBody(), $mail->createHeader()); - } -} \ No newline at end of file + return mail($to, $mail->getSubject(), $mail->createBody(), $mail->createHeader()); + } +} diff --git a/wind/mail/sender/WindSendMail.php b/wind/mail/sender/WindSendMail.php index 80c41fad..8016fe9d 100644 --- a/wind/mail/sender/WindSendMail.php +++ b/wind/mail/sender/WindSendMail.php @@ -1,49 +1,55 @@ - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ + + +/** + * 使用sendmail发送邮件 + * + * @author Qian Su + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id: WindSendMail.php 3904 2013-01-08 07:01:26Z yishuo $ * @package mail - * @subpackage sender + * @subpackage sender */ -class WindSendMail extends WindModule implements IWindSendMail { - - /** - * @var string sendmail命令路径 - */ - private $sendMail = '/usr/sbin/sendmail'; - - /** - * @var string 发送者 - */ - private $sender = ''; +class WindSendMail extends WindModule implements IWindSendMail +{ + /** + * @var string sendmail命令路径 + */ + private $sendMail = '/usr/sbin/sendmail'; + + /** + * @var string 发送者 + */ + private $sender = ''; + + /* (non-PHPdoc) + * @see IWindSendMail::send() + */ + public function send($mail, $config = array()) + { + $this->_init($config); + $mailCmd = escapeshellcmd($this->sendMail).' -oi '.($this->sender ? '-f '.escapeshellarg($this->sender).' ' : '').'-t'; + $process = popen($mailCmd, 'w'); + if (!$process) { + throw new WindMailException( + '[mail.sender.WindSendMail.send] send mail fail,can not open the sender process.'); + } + fwrite($process, $mail->createHeader()); + fwrite($process, $mail->createBody()); - /* (non-PHPdoc) - * @see IWindSendMail::send() - */ - public function send($mail, $config = array()) { - $this->_init($config); - $mailCmd = escapeshellcmd($this->sendMail) . " -oi " . ($this->sender ? "-f " . escapeshellarg($this->sender) . " " : "") . "-t"; - $process = popen($mailCmd, 'w'); - if (!$process) throw new WindMailException( - '[mail.sender.WindSendMail] send mail fail,can not open the sender process.'); - fputs($process, $mail->createHeader()); - fputs($process, $mail->createBody()); - return pclose($process); - } + return pclose($process); + } - /** - * 初始化系统配置 - * - * @param array $config - */ - private function _init($config) { - parent::setConfig($config); - $this->sender = $this->getConfig('sender', '', ''); - $this->sendMail = $this->getConfig('sendMail', '', '/usr/sbin/sendmail'); - } -} \ No newline at end of file + /** + * 初始化系统配置 + * + * @param array $config + */ + private function _init($config) + { + parent::setConfig($config); + $this->sender = $this->getConfig('sender', '', ''); + $this->sendMail = $this->getConfig('sendMail', '', '/usr/sbin/sendmail'); + } +} diff --git a/wind/mail/sender/WindSmtpMail.php b/wind/mail/sender/WindSmtpMail.php index 173e3834..7e418c51 100644 --- a/wind/mail/sender/WindSmtpMail.php +++ b/wind/mail/sender/WindSmtpMail.php @@ -1,15 +1,16 @@ * $config = array( * 'host' => '', 主机 * 'port' => '', 端口号 - * 'name' => '', - * 'auth' => '', + * 'name' => '', + * 'auth' => '', * 'user' => '', * 'password' => '', * 'timeout' => '', 超时时间,默认60秒 @@ -19,83 +20,90 @@ * @author Qian Su * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindSmtpMail.php 3298 2012-01-06 12:48:26Z yishuo $ * @package mail * @subpackage sender */ -class WindSmtpMail extends WindModule implements IWindSendMail { - /** - * @var WindSmtp 邮件发送服务器 - */ - protected $smtp = null; - /** - * 邮件发送服务器 - * - * @var string - */ - protected $host; - /** - * 邮件发送端口 - * - * @var int - */ - protected $port; - /** - * @var string 邮件主机名 - */ - protected $name; - /** - * 是否启用验证 - * - * @var boolean - */ - protected $auth; - /** - * @var string 邮件用户名 - */ - protected $username; - /** - * @var string 邮件密码 - */ - protected $password; - /** - * 请求超时时间 - * - * @var string - */ - protected $timeout = 60; +class WindSmtpMail extends WindModule implements IWindSendMail +{ + /** + * @var WindSmtp 邮件发送服务器 + */ + protected $smtp = null; + /** + * 邮件发送服务器 + * + * @var string + */ + protected $host; + /** + * 邮件发送端口 + * + * @var int + */ + protected $port; + /** + * @var string 邮件主机名 + */ + protected $name; + /** + * 是否启用验证 + * + * @var bool + */ + protected $auth; + /** + * @var string 邮件用户名 + */ + protected $username; + /** + * @var string 邮件密码 + */ + protected $password; + /** + * 请求超时时间 + * + * @var string + */ + protected $timeout = 60; + + /** + * @param WindMail $mail + * @see IWindSendMail::send() + */ + public function send($mail, $config = array()) + { + if ($this->smtp === null) { + $this->_init($config); + $this->smtp = new WindSmtp($this->host, $this->port, $this->timeout); + } + $this->smtp->open(); + $this->smtp->ehlo($this->name); + if ($this->auth) { + $this->smtp->authLogin($this->username, $this->password); + } + $this->smtp->mailFrom($mail->getFrom()); + foreach ($mail->getRecipients() as $rcpt) { + $this->smtp->rcptTo($rcpt); + } + $this->smtp->data($mail->createHeader().$mail->createBody()); + $this->smtp->quit(); - /** - * @param WindMail $mail - * @see IWindSendMail::send() - */ - public function send($mail, $config = array()) { - if ($this->smtp === null) { - $this->_init($config); - $this->smtp = new WindSmtp($this->host, $this->port, $this->timeout); - } - $this->smtp->open(); - $this->smtp->ehlo($this->name); - if ($this->auth) $this->smtp->authLogin($this->username, $this->password); - $this->smtp->mailFrom($mail->getFrom()); - foreach ($mail->getRecipients() as $rcpt) - $this->smtp->rcptTo($rcpt); - $this->smtp->data($mail->createHeader() . $mail->createBody()); - $this->smtp->quit(); - return true; - } + return true; + } - /** - * @param array() $config - */ - private function _init($config) { - parent::setConfig($config); - $this->host = $this->getConfig('host', '', '127.0.0.1'); - $this->port = $this->getConfig('port', '', '25'); - $this->name = $this->getConfig('name', '', 'localhost'); - $this->auth = $this->getConfig('auth', '', true); - $this->username = $this->getConfig('user'); - $this->password = $this->getConfig('password'); - $this->timeout = $this->getConfig('timeout', '', 60); - } -} \ No newline at end of file + /** + * @param array() $config + */ + private function _init($config) + { + parent::setConfig($config); + $this->host = $this->getConfig('host', '', '127.0.0.1'); + $this->port = $this->getConfig('port', '', '25'); + $this->name = $this->getConfig('name', '', 'localhost'); + $this->auth = $this->getConfig('auth', '', true); + $this->username = $this->getConfig('user'); + $this->password = $this->getConfig('password'); + $this->timeout = $this->getConfig('timeout', '', 60); + } +} diff --git a/wind/parser/IWindConfigParser.php b/wind/parser/IWindConfigParser.php index 3f48487b..562180ef 100644 --- a/wind/parser/IWindConfigParser.php +++ b/wind/parser/IWindConfigParser.php @@ -5,30 +5,29 @@ * @author xiaoxia.xu * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: IWindConfigParser.php 2973 2011-10-15 19:22:48Z yishuo $ * @package parser */ -interface IWindConfigParser { - - /** - * 解析组件的配置文件 - * - * 根据配置文件路径$configPath解析配置返回一个数组, - * 如果设置了$cache,则将解析出来的数据保存到$cache中,保存规则如下: - *
      - *
    • 如果没有设置$alias或是没有设置$cache,则将不保存数据
    • - *
    • 如果没有设置$append: 则将会以$alias为名将$data保存在缓存$cache中
    • - *
    • 如果设置了$append和$alias: 则先去从$cache中获得名为$append的缓存内容,并且将$data以$alias为键名保存到该缓存内容中, - * 然后仍然以$append之名写回到$cache中
    • - *
    - * 如果没有设置$cache,将直接返回解析结果. - * - * @param string $configPath 待解析的文件路径 - * @param string $alias 解析后保存的key名,默认为空,及不保存 - * @param string $append 追加的文件,默认为空 - * @param AbstractWindCache $cache 缓存策略默认为null及不保存 - * @return array 解析结果 - */ - public function parse($configPath, $alias = '', $append = '', AbstractWindCache $cache = null); - -} \ No newline at end of file +interface IWindConfigParser +{ + /** + * 解析组件的配置文件 + * + * 根据配置文件路径$configPath解析配置返回一个数组, + * 如果设置了$cache,则将解析出来的数据保存到$cache中,保存规则如下: + *
      + *
    • 如果没有设置$alias或是没有设置$cache,则将不保存数据
    • + *
    • 如果没有设置$append: 则将会以$alias为名将$data保存在缓存$cache中
    • + *
    • 如果设置了$append和$alias: 则先去从$cache中获得名为$append的缓存内容,并且将$data以$alias为键名保存到该缓存内容中, + * 然后仍然以$append之名写回到$cache中
    • + *
    + * 如果没有设置$cache,将直接返回解析结果. + * + * @param string $configPath 待解析的文件路径 + * @param string $alias 解析后保存的key名,默认为空,及不保存 + * @param string $append 追加的文件,默认为空 + * @param AbstractWindCache $cache 缓存策略默认为null及不保存 + * @return array 解析结果 + */ + public function parse($configPath, $alias = '', $append = '', AbstractWindCache $cache = null); +} diff --git a/wind/parser/WindConfigParser.php b/wind/parser/WindConfigParser.php index 607f411b..9ca991bf 100644 --- a/wind/parser/WindConfigParser.php +++ b/wind/parser/WindConfigParser.php @@ -1,97 +1,117 @@ * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindConfigParser.php 3904 2013-01-08 07:01:26Z yishuo $ * @package parser */ -class WindConfigParser implements IWindConfigParser { - const CONFIG_XML = '.XML'; - const CONFIG_PHP = '.PHP'; - const CONFIG_INI = '.INI'; - const CONFIG_PROPERTIES = '.PROPERTIES'; - private $configs = array(); - - /* (non-PHPdoc) +class WindConfigParser implements IWindConfigParser +{ + const CONFIG_XML = '.XML'; + const CONFIG_PHP = '.PHP'; + const CONFIG_INI = '.INI'; + const CONFIG_PROPERTIES = '.PROPERTIES'; + private $configs = array(); + + /* (non-PHPdoc) * @see IWindConfigParser::parse() */ - public function parse($configPath, $alias = '', $append = '', AbstractWindCache $cache = null) { - if ($alias && $cache && ($config = $this->getCache($alias, $append, $cache))) return $config; - if (!is_file($configPath)) throw new WindException( - '[component.parser.WindConfigParser.parse] The file \'' . $configPath . '\' is not exists'); - $ext = strtoupper(strrchr($configPath, '.')); - $config = ($ext == self::CONFIG_PHP) ? @include ($configPath) : $this->createParser($ext)->parse($configPath); - if ($alias && $cache) $this->setCache($alias, $append, $cache, $config); - return $config; - } + public function parse($configPath, $alias = '', $append = '', AbstractWindCache $cache = null) + { + if ($alias && $cache && ($config = $this->getCache($alias, $append, $cache))) { + return $config; + } + if (!is_file($configPath)) { + throw new WindException( + '[parser.WindConfigParser.parse] The file \''.$configPath.'\' is not exists'); + } + $ext = strtoupper(strrchr($configPath, '.')); + $config = ($ext == self::CONFIG_PHP) ? @include($configPath) : $this->createParser($ext)->parse($configPath); + if ($alias && $cache) { + $this->setCache($alias, $append, $cache, $config); + } + + return $config; + } + + /** + * 设置配置缓存 + * + * $alias和$append的关系如下: + *
      + *
    • 如果没有设置$alias或是没有设置$cache,则将不保存数据
    • + *
    • 如果没有设置$append: 则将会以$alias为名将$data保存在缓存$cache中
    • + *
    • 如果设置了$append和$alias: 则先去从$cache中获得名为$append的缓存内容,并且将$data以$alias为键名保存到该缓存内容中, + * 然后仍然以$append之名写回到$cache中
    • + *
    + * + * @param string $alias 配置文件的缓存别名 + * @param string $append 配置文件的追加的配置 + * @param AbstractWindCache $cache 配置文件使用的缓存介质 + */ + private function setCache($alias, $append, $cache, $data) + { + if ($append) { + $this->configs[$alias] = $data; + $cache->set($append, $this->configs); + } else { + $cache->set($alias, $data); + } + } + + /** + * 返回配置缓存 + * + * @param string $alias 配置保存用的名字 + * @param string $append 配置追加的配置 + * @param AbstractWindCache $cache 配置保存的缓存介质 + * @return array + */ + private function getCache($alias, $append, $cache) + { + if (!$append) { + return $cache->get($alias); + } + if (isset($this->configs[$alias])) { + return $this->configs[$alias]; + } + $this->configs = $cache->get($append); + + return isset($this->configs[$alias]) ? $this->configs[$alias] : array(); + } + + /** + * 创建配置文件解析器 + * + * @param string $type 配置文件的类型 + * @return object 解析器 + */ + private function createParser($type) + { + switch ($type) { + case self::CONFIG_XML: + + + return new WindXmlParser(); + case self::CONFIG_INI: + - /** - * 设置配置缓存 - * - * $alias和$append的关系如下: - *
      - *
    • 如果没有设置$alias或是没有设置$cache,则将不保存数据
    • - *
    • 如果没有设置$append: 则将会以$alias为名将$data保存在缓存$cache中
    • - *
    • 如果设置了$append和$alias: 则先去从$cache中获得名为$append的缓存内容,并且将$data以$alias为键名保存到该缓存内容中, - * 然后仍然以$append之名写回到$cache中
    • - *
    - * - * @param string $alias 配置文件的缓存别名 - * @param string $append 配置文件的追加的配置 - * @param AbstractWindCache $cache 配置文件使用的缓存介质 - * @return void - */ - private function setCache($alias, $append, $cache, $data) { - if ($append) { - $this->configs[$alias] = $data; - $cache->set($append, $this->configs); - } else { - $cache->set($alias, $data); - } - } + return new WindIniParser(); + case self::CONFIG_PROPERTIES: - /** - * 返回配置缓存 - * - * @param string $alias 配置保存用的名字 - * @param string $append 配置追加的配置 - * @param AbstractWindCache $cache 配置保存的缓存介质 - * @return array - */ - private function getCache($alias, $append, $cache) { - if (!$append) return $cache->get($alias); - if (isset($this->configs[$alias])) return $this->configs[$alias]; - $this->configs = $cache->get($append); - return isset($this->configs[$alias]) ? $this->configs[$alias] : array(); - } - /** - * 创建配置文件解析器 - * - * @param string $type 配置文件的类型 - * @return object 解析器 - */ - private function createParser($type) { - switch ($type) { - case self::CONFIG_XML: - Wind::import("WIND:parser.WindXmlParser"); - return new WindXmlParser(); - case self::CONFIG_INI: - Wind::import("WIND:parser.WindIniParser"); - return new WindIniParser(); - case self::CONFIG_PROPERTIES: - Wind::import("WIND:parser.WindPropertiesParser"); - return new WindPropertiesParser(); - default: - throw new WindException('\'ConfigParser\' failed to initialize.'); - } - } -} \ No newline at end of file + return new WindPropertiesParser(); + default: + throw new WindException('[parser.WindConfigParser.createParser] \'ConfigParser\' failed to initialize.'); + } + } +} diff --git a/wind/parser/WindIniParser.php b/wind/parser/WindIniParser.php index 90dee4a5..e641d599 100644 --- a/wind/parser/WindIniParser.php +++ b/wind/parser/WindIniParser.php @@ -1,7 +1,7 @@ 注意:有些保留字不能作为 ini 文件中的键名,
    * 包括:null,yes,no,true 和 false。值为 null,no 和 false 等效于 "",
    * 值为 yes 和 true 等效于 "1"。
    @@ -21,147 +21,167 @@ * 'isadd' => '1', //string 类型 * ) * ) - * - * - * @author Qian Su - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package parser + * + * + * @author Qian Su + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id: WindIniParser.php 2973 2011-10-15 19:22:48Z yishuo $ + * @package parser */ -class WindIniParser { +class WindIniParser +{ + /** + * ini中分割数组的标识 + * + * @var string + */ + const ARRAY_SEP = '.'; + + /** + * 解析数据 + * + * @param string $filename ini格式文件 + * @param bool $build 是否解析,默认为true + * @return bool + */ + public function parse($filename, $build = true) + { + if (!is_file($filename)) { + return array(); + } + $data = parse_ini_file($filename, true); + + return $build ? $this->buildData($data) : $data; + } + + /** + * 构建数据 + * + * @param array $data 将解析出来的数据进行值解析 + * @return array 解析后的数组 + */ + private function buildData(&$data) + { + foreach ((array) $data as $key => $value) { + if (is_array($value)) { + $data[$key] = $this->formatDataArray($value); + } else { + $this->formatDataFromString($key, $value, $data); + } + } + + return $data; + } + + /** + * 将每行ini文件转换成数组 + * + * @param string $key ini文件中的键 + * @param string $value ini文件中的值 + * @param array $data 操作数据,默认为array() + * @return array + */ + private function toArray($key, $value, &$data = array()) + { + if (empty($key)) { + return array(); + } + if (strpos($key, self::ARRAY_SEP)) { + $start = substr($key, 0, strpos($key, self::ARRAY_SEP)); + $end = substr($key, strpos($key, self::ARRAY_SEP) + 1); + $data[$start] = array(); + $this->toArray($end, $value, $data[$start]); + } else { + $__tmp = strtolower($value); + $data[$key] = 'false' === $__tmp ? false : ('true' === $__tmp ? true : $value); + } + + return $data; + } + + /** + * 解析ini格式文件成数组 + * + * @param array $original 原始数组 + * @param array $data 解析后的数组 + * @return array + */ + private function formatDataArray(&$original, &$data = array()) + { + foreach ((array) $original as $key => $value) { + $tmp = $this->toArray($key, $value); + foreach ($tmp as $tkey => $tValue) { + if (is_array($tValue)) { + (!isset($data[$tkey])) && $data[$tkey] = array(); + $this->formatDataArray($tValue, $data[$tkey]); + } else { + $data[$tkey] = $tValue; + } + } + } + + return $data; + } - /** - * ini中分割数组的标识 - * - * @var string - */ - const ARRAY_SEP = '.'; + /** + * 从字符串中合并数组 + * + * @param string $key 待合并的键值 + * @param string $value 待合并的数据 + * @param array $data 操作数组 + * @return array + */ + private function formatDataFromString($key, $value, &$data) + { + $tmp = $this->toArray($key, $value); + if (false === strpos($key, self::ARRAY_SEP)) { + return $tmp; + } + $start = substr($key, 0, strpos($key, self::ARRAY_SEP)); + if ((!isset($data[$start]) || !is_array($data[$start])) && isset($tmp[$start])) { + $data[$start] = $tmp[$start]; + unset($data[$key]); - /** - * 解析数据 - * - * @param string $filename ini格式文件 - * @param boolean $build 是否解析,默认为true - * @return boolean - */ - public function parse($filename, $build = true) { - if (!is_file($filename)) return array(); - $data = parse_ini_file($filename, true); - return $build ? $this->buildData($data) : $data; - } + return $data; + } - /** - * 构建数据 - * - * @param array $data 将解析出来的数据进行值解析 - * @return array 解析后的数组 - */ - private function buildData(&$data) { - foreach ((array) $data as $key => $value) { - if (is_array($value)) { - $data[$key] = $this->formatDataArray($value); - } else { - $this->formatDataFromString($key, $value, $data); - } - } - return $data; - } + foreach ($data as $d_key => $d_value) { + if (!isset($tmp[$d_key]) || !is_array($tmp[$d_key])) { + continue; + } + foreach ($tmp[$d_key] as $a => $b) { + $this->merge($a, $b, $data[$start]); + } + } + unset($data[$key]); - /** - * 将每行ini文件转换成数组 - * - * @param string $key ini文件中的键 - * @param string $value ini文件中的值 - * @param array $data 操作数据,默认为array() - * @return array - */ - private function toArray($key, $value, &$data = array()) { - if (empty($key)) return array(); - if (strpos($key, self::ARRAY_SEP)) { - $start = substr($key, 0, strpos($key, self::ARRAY_SEP)); - $end = substr($key, strpos($key, self::ARRAY_SEP) + 1); - $data[$start] = array(); - $this->toArray($end, $value, $data[$start]); - } else { - $__tmp = strtolower($value); - $data[$key] = 'false' === $__tmp ? false : ('true' === $__tmp ? true : $value); - } - return $data; - } + return $data; + } - /** - * 解析ini格式文件成数组 - * - * @param array $original 原始数组 - * @param array $data 解析后的数组 - * @return array - */ - private function formatDataArray(&$original, &$data = array()) { - foreach ((array) $original as $key => $value) { - $tmp = $this->toArray($key, $value); - foreach ($tmp as $tkey => $tValue) { - if (is_array($tValue)) { - (!isset($data[$tkey])) && $data[$tkey] = array(); - $this->formatDataArray($tValue, $data[$tkey]); - } else { - $data[$tkey] = $tValue; - } - } - } - return $data; - } + /** + * 合并格式化的数组 + * + * @param string $key 待合并的键值 + * @param mixed $value 待合并的数据 + * @param array $data 合并到的数据 + * @return array + */ + private function merge($key, $value, &$data = array()) + { + if (!is_array($value)) { + $data[$key] = $value; - /** - * 从字符串中合并数组 - * - * @param string $key 待合并的键值 - * @param string $value 待合并的数据 - * @param array $data 操作数组 - * @return array - */ - private function formatDataFromString($key, $value, &$data) { - $tmp = $this->toArray($key, $value); - if (false === strpos($key, self::ARRAY_SEP)) return $tmp; - $start = substr($key, 0, strpos($key, self::ARRAY_SEP)); - if ((!isset($data[$start]) || !is_array($data[$start])) && isset($tmp[$start])) { - $data[$start] = $tmp[$start]; - unset($data[$key]); - return $data; - } - - foreach ($data as $d_key => $d_value) { - if (!isset($tmp[$d_key]) || !is_array($tmp[$d_key])) { - continue; - } - foreach ($tmp[$d_key] as $a => $b) { - $this->merge($a, $b, $data[$start]); - } - } - unset($data[$key]); - return $data; - } + return $data; + } + $v_key = array_keys($value); + $c_key = $v_key[0]; + if (is_array($value[$c_key])) { + $this->merge($c_key, $value[$c_key], $data[$key]); + } else { + $data[$key][$c_key] = $value[$c_key]; + } - /** - * 合并格式化的数组 - * - * @param string $key 待合并的键值 - * @param mixed $value 待合并的数据 - * @param array $data 合并到的数据 - * @return array - */ - private function merge($key, $value, &$data = array()) { - if (!is_array($value)) { - $data[$key] = $value; - return $data; - } - $v_key = array_keys($value); - $c_key = $v_key[0]; - if (is_array($value[$c_key])) { - $this->merge($c_key, $value[$c_key], $data[$key]); - } else { - $data[$key][$c_key] = $value[$c_key]; - } - return $data; - } -} \ No newline at end of file + return $data; + } +} diff --git a/wind/parser/WindPropertiesParser.php b/wind/parser/WindPropertiesParser.php index 203bc52a..3502f786 100644 --- a/wind/parser/WindPropertiesParser.php +++ b/wind/parser/WindPropertiesParser.php @@ -1,7 +1,7 @@ @@ -21,207 +21,231 @@ * ) * ) *) - * - * - * @author Qian Su - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package parser + * + * + * @author Qian Su + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id: WindPropertiesParser.php 2973 2011-10-15 19:22:48Z yishuo $ + * @package parser */ -class WindPropertiesParser { - - const COMMENT = '#'; - - const LPROCESS = '['; - - const RPROCESS = ']'; - - const ARRAY_SEP = '.'; - - public function __construct() {} - - /** - * 解析properties文件里的内容 - * - * @param string $filename 文件名 - * @param boolean $build 是否按格式解析数据默认为true - * @return array - */ - public function parse($filename, $build = true) { - $data = $this->parse_properties_file($filename); - return $build ? $this->buildData($data) : $data; - } - - /** - * 解析properties文件并返回一个多维数组 - * - * 载入一个由 filename 指定的 properties 文件, - * 并将其中的设置作为一个联合数组返回。 - * - * @param string $filename 文件名 - * @return array - */ - private function parse_properties_file($filename) { - if (!is_file($filename) || !in_array(substr($filename, strrpos($filename, '.') + 1), array('properties'))) { - return array(); - } - $content = explode("\n", WindFile::read($filename)); - $data = array(); - $last_process = $current_process = ''; - foreach ($content as $key => $value) { - $value = str_replace(array("\n", "\r"), '', trim($value)); - if (0 === strpos(trim($value), self::COMMENT) || in_array(trim($value), array('', "\t", "\n"))) { - continue; - } - $tmp = explode('=', $value, 2); - if (0 === strpos(trim($value), self::LPROCESS) && (strlen($value) - 1) === strrpos($value, self::RPROCESS)) { - $current_process = $this->trimChar(trim($value), array(self::LPROCESS, self::RPROCESS)); - $data[$current_process] = array(); - $last_process = $current_process; - continue; - } - $tmp[0] = trim($tmp[0]); - if (count($tmp) == 1 ) { - $last_process ? $data[$last_process][$tmp[0]] = '' : $data[$tmp[0]] = ''; - continue; - } - $tmp[1] = trim($tmp[1], '\'"'); - $__tmpValue = strtolower($tmp[1]); - $tmp[1] = 'false' === $__tmpValue ? false : ('true' === $__tmpValue ? true : $tmp[1]); - - $last_process ? $data[$last_process][$tmp[0]] = $tmp[1] : $data[$tmp[0]] = $tmp[1]; - } - return $data; - } - - /** - * 解析配置数据 - * - * @param array $data 源数据 - * @return array - */ - private function buildData(&$data) { - foreach ((array) $data as $key => $value) { - if (is_array($value)) { - $data[$key] = $this->formatDataArray($value); - } else { - $this->formatDataFromString($key, $value, $data); - } - } - return $data; - } - - /** - * 将每行properties文件转换成数组 - * - * @param string $key properties文件中的键 - * @param string $value properties文件中的值 - * @param array $data 操作数据,默认为array() - * @return array - */ - private function toArray($key, $value, &$data = array()) { - if (empty($key) && empty($value)) return array(); - if (strpos($key, self::ARRAY_SEP)) { - $start = substr($key, 0, strpos($key, self::ARRAY_SEP)); - $end = substr($key, strpos($key, self::ARRAY_SEP) + 1); - $data[$start] = array(); - $this->toArray($end, $value, $data[$start]); - } else { - $data[$key] = $value; - } - return $data; - } - - /** - * 将原始数组合并成新的数组 - * - * @param array $original 原始数组 - * @param array $data 合并后的数组 - * @return array - */ - private function formatDataArray(&$original, &$data = array()) { - foreach ((array) $original as $key => $value) { - $tmp = $this->toArray($key, $value); - foreach ($tmp as $tkey => $tValue) { - if (is_array($tValue)) { - if (!isset($data[$tkey])) { - $data[$tkey] = array(); - } - $this->formatDataArray($tValue, $data[$tkey]); - } else { - $data[$tkey] = $tValue; - } - } - } - return $data; - } - - /** - * 从字符串中合并数组 - * - * @param string $key 待合并的键值 - * @param string $value 待合并的数据 - * @param array $data 操作数组 - * @return array - */ - private function formatDataFromString($key, $value, &$data) { - $tmp = $this->toArray($key, $value); - if (false == strpos($key, self::ARRAY_SEP)) return $tmp; - $start = substr($key, 0, strpos($key, self::ARRAY_SEP)); - if ((!isset($data[$start]) || !is_array($data[$start])) && isset($tmp[$start])) { - $data[$start] = $tmp[$start]; - unset($data[$key]); - return $data; - } - foreach ($data as $d_key => $d_value) { - if (!isset($tmp[$d_key]) || !is_array($tmp[$d_key])) { - continue; - } - foreach ($tmp[$d_key] as $a => $b) { - $this->merge($a, $b, $data[$start]); - } - } - unset($data[$key]); - return $data; - } - - /** - * 合并格式化的数组 - * - * @param string $key 待合并的键值 - * @param mixed $value 待合并的数据 - * @param array $data 合并到的数据 - * @return array - */ - private function merge($key, $value, &$data = array()) { - if (!is_array($value)) { - $data[$key] = $value; - return $data; - } - - $v_key = array_keys($value); - $c_key = $v_key[0]; - if (is_array($value[$c_key])) { - $this->merge($c_key, $value[$c_key], $data[$key]); - } else { - $data[$key][$c_key] = $value[$c_key]; - } - return $data; - } - - /** - * 去除字符串头和尾中指定字符 - * - * @param string $str 待处理的数据 - * @param mixed $char 需要取出的字符 - * @return string 处理后的数据 - */ - private function trimChar($str, $char = ' ') { - $char = is_array($char) ? $char : array($char); - foreach ($char as $value) { - $str = trim($str, $value); - } - return $str; - } -} \ No newline at end of file +class WindPropertiesParser +{ + const COMMENT = '#'; + + const LPROCESS = '['; + + const RPROCESS = ']'; + + const ARRAY_SEP = '.'; + + public function __construct() + { + } + + /** + * 解析properties文件里的内容 + * + * @param string $filename 文件名 + * @param bool $build 是否按格式解析数据默认为true + * @return array + */ + public function parse($filename, $build = true) + { + $data = $this->parse_properties_file($filename); + + return $build ? $this->buildData($data) : $data; + } + + /** + * 解析properties文件并返回一个多维数组 + * + * 载入一个由 filename 指定的 properties 文件, + * 并将其中的设置作为一个联合数组返回。 + * + * @param string $filename 文件名 + * @return array + */ + private function parse_properties_file($filename) + { + if (!is_file($filename) || !in_array(substr($filename, strrpos($filename, '.') + 1), array('properties'))) { + return array(); + } + $content = explode("\n", WindFile::read($filename)); + $data = array(); + $last_process = $current_process = ''; + foreach ($content as $key => $value) { + $value = str_replace(array("\n", "\r"), '', trim($value)); + if (0 === strpos(trim($value), self::COMMENT) || in_array(trim($value), array('', "\t", "\n"))) { + continue; + } + $tmp = explode('=', $value, 2); + if (0 === strpos(trim($value), self::LPROCESS) && (strlen($value) - 1) === strrpos($value, self::RPROCESS)) { + $current_process = $this->trimChar(trim($value), array(self::LPROCESS, self::RPROCESS)); + $data[$current_process] = array(); + $last_process = $current_process; + continue; + } + $tmp[0] = trim($tmp[0]); + if (count($tmp) == 1) { + $last_process ? $data[$last_process][$tmp[0]] = '' : $data[$tmp[0]] = ''; + continue; + } + $tmp[1] = trim($tmp[1], '\'"'); + $__tmpValue = strtolower($tmp[1]); + $tmp[1] = 'false' === $__tmpValue ? false : ('true' === $__tmpValue ? true : $tmp[1]); + + $last_process ? $data[$last_process][$tmp[0]] = $tmp[1] : $data[$tmp[0]] = $tmp[1]; + } + + return $data; + } + + /** + * 解析配置数据 + * + * @param array $data 源数据 + * @return array + */ + private function buildData(&$data) + { + foreach ((array) $data as $key => $value) { + if (is_array($value)) { + $data[$key] = $this->formatDataArray($value); + } else { + $this->formatDataFromString($key, $value, $data); + } + } + + return $data; + } + + /** + * 将每行properties文件转换成数组 + * + * @param string $key properties文件中的键 + * @param string $value properties文件中的值 + * @param array $data 操作数据,默认为array() + * @return array + */ + private function toArray($key, $value, &$data = array()) + { + if (empty($key) && empty($value)) { + return array(); + } + if (strpos($key, self::ARRAY_SEP)) { + $start = substr($key, 0, strpos($key, self::ARRAY_SEP)); + $end = substr($key, strpos($key, self::ARRAY_SEP) + 1); + $data[$start] = array(); + $this->toArray($end, $value, $data[$start]); + } else { + $data[$key] = $value; + } + + return $data; + } + + /** + * 将原始数组合并成新的数组 + * + * @param array $original 原始数组 + * @param array $data 合并后的数组 + * @return array + */ + private function formatDataArray(&$original, &$data = array()) + { + foreach ((array) $original as $key => $value) { + $tmp = $this->toArray($key, $value); + foreach ($tmp as $tkey => $tValue) { + if (is_array($tValue)) { + if (!isset($data[$tkey])) { + $data[$tkey] = array(); + } + $this->formatDataArray($tValue, $data[$tkey]); + } else { + $data[$tkey] = $tValue; + } + } + } + + return $data; + } + + /** + * 从字符串中合并数组 + * + * @param string $key 待合并的键值 + * @param string $value 待合并的数据 + * @param array $data 操作数组 + * @return array + */ + private function formatDataFromString($key, $value, &$data) + { + $tmp = $this->toArray($key, $value); + if (false == strpos($key, self::ARRAY_SEP)) { + return $tmp; + } + $start = substr($key, 0, strpos($key, self::ARRAY_SEP)); + if ((!isset($data[$start]) || !is_array($data[$start])) && isset($tmp[$start])) { + $data[$start] = $tmp[$start]; + unset($data[$key]); + + return $data; + } + foreach ($data as $d_key => $d_value) { + if (!isset($tmp[$d_key]) || !is_array($tmp[$d_key])) { + continue; + } + foreach ($tmp[$d_key] as $a => $b) { + $this->merge($a, $b, $data[$start]); + } + } + unset($data[$key]); + + return $data; + } + + /** + * 合并格式化的数组 + * + * @param string $key 待合并的键值 + * @param mixed $value 待合并的数据 + * @param array $data 合并到的数据 + * @return array + */ + private function merge($key, $value, &$data = array()) + { + if (!is_array($value)) { + $data[$key] = $value; + + return $data; + } + + $v_key = array_keys($value); + $c_key = $v_key[0]; + if (is_array($value[$c_key])) { + $this->merge($c_key, $value[$c_key], $data[$key]); + } else { + $data[$key][$c_key] = $value[$c_key]; + } + + return $data; + } + + /** + * 去除字符串头和尾中指定字符 + * + * @param string $str 待处理的数据 + * @param mixed $char 需要取出的字符 + * @return string 处理后的数据 + */ + private function trimChar($str, $char = ' ') + { + $char = is_array($char) ? $char : array($char); + foreach ($char as $value) { + $str = trim($str, $value); + } + + return $str; + } +} diff --git a/wind/parser/WindXmlParser.php b/wind/parser/WindXmlParser.php index a5a8f75a..9544c4e0 100644 --- a/wind/parser/WindXmlParser.php +++ b/wind/parser/WindXmlParser.php @@ -1,189 +1,213 @@ * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindXmlParser.php 3904 2013-01-08 07:01:26Z yishuo $ * @package parser */ -class WindXmlParser { - - /** - * @var string 节点名称 - */ - const NAME = 'name'; - - /** - * @var Domdocument DOM解析器 - */ - private $dom = null; - - /** - * 初始化xml解析器 - * - * @param string $version xml版本 - * @param string $encode xml编码 - * @return void - */ - public function __construct($version = '1.0', $encode = 'utf-8') { - if (!class_exists('DOMDocument')) throw new WindException('DOMDocument is not exist.'); - $this->dom = new DOMDocument($version, $encode); - } - - /** - * 解析xml文件 - * - * @param string $filename 待解析文件名 - * @param int $option 解析选项,默认为0 - * @return array - */ - public function parse($filename, $option = 0) { - if (!is_file($filename)) return array(); - $this->dom->load($filename, $option); - return $this->getChilds($this->dom->documentElement); - } +class WindXmlParser +{ + /** + * @var string 节点名称 + */ + const NAME = 'name'; + + /** + * @var Domdocument DOM解析器 + */ + private $dom = null; + + /** + * 初始化xml解析器 + * + * @param string $version xml版本 + * @param string $encode xml编码 + */ + public function __construct($version = '1.0', $encode = 'utf-8') + { + if (!class_exists('DOMDocument')) { + throw new WindException('[parser.WindXmlParser] DOMDocument is not exist.'); + } + $this->dom = new DOMDocument($version, $encode); + } + + /** + * 解析xml文件 + * + * @param string $filename 待解析文件名 + * @param int $option 解析选项,默认为0 + * @return array + */ + public function parse($filename, $option = 0) + { + if (!is_file($filename)) { + return array(); + } + $this->dom->load($filename, $option); + + return $this->getChilds($this->dom->documentElement); + } /** * 将数据内容解析成数组格式 * - * @param string $stream 数据内容 - * @param int $option 解析选项,默认为0 - * @return array + * @param string $stream 数据内容 + * @param int $option 解析选项,默认为0 + * @return array + */ + public function parseXmlStream($stream, $option = 0) + { + if (!$stream) { + return array(); + } + $this->dom->loadXML($stream, $option); + + return $this->getChilds($this->dom->documentElement); + } + + /** + * 将数据转换成xml格式 + * + * + * 数组中key为数值型时,则转为value + * 普通string或其他基本类型,则转为string + * + * + * @param mixed $source 待转换的数据 + * @param string $charset 待转换数据的编码 + * @return string + */ + public function parseToXml($source, $charset = 'utf8') + { + switch (gettype($source)) { + case 'object': + $source = get_object_vars($source); + case 'array': + $this->arrayToXml($source, $charset, $this->dom); + break; + case 'string': + $source = WindConvert::convert($source, 'utf8', $charset); + default: + $item = $this->dom->createElement('item'); + $text = $this->dom->createTextNode($source); + $item->appendChild($text); + $this->dom->appendChild($item); + break; + } + + return $this->dom->saveXML(); + } + + /** + * 获得节点的所有子节点 + * + * 子节点包括属性和子节点(及文本节点), + * 子节点的属性将会根据作为该节点的一个属性元素存放,如果该子节点中含有标签列表,则会进行一次合并。 + * 每个被合并的列表项都作为一个单独的数组元素存在。 + * + * @param DOMElement $node 要解析的XMLDOM节点 + * @return array 返回解析后该节点的数组 + */ + public function getChilds($node) + { + if (!$node instanceof DOMElement) { + return array(); + } + $childs = array(); + foreach ($node->childNodes as $_node) { + $tempChilds = $attributes = array(); + $_node->hasAttributes() && $attributes = $this->getAttributes($_node); + if (3 == $_node->nodeType) { + $value = trim($_node->nodeValue); + (is_numeric($value) || $value) && $childs['__value'] = $value; //值为0的情况 + $__tmp = strtolower($value); + ('false' === $__tmp) && $childs['__value'] = false; //为false的配置值 + ('true' === $__tmp) && $childs['__value'] = true; //为false的配置值 + } + if (1 !== $_node->nodeType) { + continue; + } + + $tempChilds = $this->getChilds($_node); + $tempChilds = array_merge($attributes, $tempChilds); + + if (empty($tempChilds)) { + $tempChilds = ''; + } else { + $tempChilds = (isset($tempChilds['__value']) && count($tempChilds) == 1) ? $tempChilds['__value'] : $tempChilds; + } + + $nodeName = '' !== ($name = $_node->getAttribute(self::NAME)) ? $name : $_node->nodeName; + if (!isset($childs[$nodeName])) { + $childs[$nodeName] = $tempChilds; + } else { + $element = $childs[$nodeName]; + $childs[$nodeName] = (is_array($element) && !is_numeric(implode('', array_keys($element)))) ? array_merge( + array($element), array($tempChilds)) : array_merge((array) $element, array($tempChilds)); + } + } + + return $childs; + } + + /** + * 获得节点的属性 + * + * 该属性将不包含属性为name的值--规则(name的值将作为解析后数组的key值索引存在) + * + * @param DOMElement $node 节点 + * @return array 返回属性数组 + */ + public function getAttributes($node) + { + if (!$node instanceof DOMElement || !$node->hasAttributes()) { + return array(); + } + $attributes = array(); + foreach ($node->attributes as $attribute) { + if (self::NAME != $attribute->nodeName) { + $value = (string) $attribute->nodeValue; + $__tmp = strtolower($value); + $attributes[$attribute->nodeName] = 'false' === $__tmp ? false : ('true' === $__tmp ? true : $value); + } + } + + return $attributes; + } + + /** + * 将一个数组转换为xml + * + * @param array $arr 待转换的数组 + * @param string $charset 编码 + * @param DOMDocument $dom 根节点 + * @return DOMDocument */ - public function parseXmlStream($stream, $option = 0) { - if (!$stream) return array(); - $this->dom->loadXML($stream, $option); - return $this->getChilds($this->dom->documentElement); + protected function arrayToXml($arr, $charset, $dom = null) + { + foreach ($arr as $key => $val) { + if (is_numeric($key)) { + $itemx = $this->dom->createElement('item'); + $id = $this->dom->createAttribute('id'); + $id->appendChild($this->dom->createTextNode($key)); + $itemx->appendChild($id); + } else { + $itemx = $this->dom->createElement($key); + } + $dom->appendChild($itemx); + if (is_string($val)) { + $val = WindConvert::convert($val, 'utf8', $charset); + $itemx->appendChild($this->dom->createTextNode($val)); + } elseif (is_object($val)) { + $this->arrayToXml(get_object_vars($val), $charset, $itemx); + } else { + $this->arrayToXml($val, $charset, $itemx); + } + } } - - /** - * 将数据转换成xml格式 - * - * - * 数组中key为数值型时,则转为value - * 普通string或其他基本类型,则转为string - * - * - * @param mixed $source 待转换的数据 - * @param string $charset 待转换数据的编码 - * @return string - */ - public function parseToXml($source, $charset = 'utf8') { - switch (gettype($source)) { - case 'object': - $source = get_object_vars($source); - case 'array': - $this->arrayToXml($source, $charset, $this->dom); - break; - case 'string': - $source = WindConvert::convert($source, 'utf8', $charset); - default: - $item = $this->dom->createElement("item"); - $text = $this->dom->createTextNode($source); - $item->appendChild($text); - $this->dom->appendChild($item); - break; - } - return $this->dom->saveXML(); - } - - /** - * 获得节点的所有子节点 - * - * 子节点包括属性和子节点(及文本节点), - * 子节点的属性将会根据作为该节点的一个属性元素存放,如果该子节点中含有标签列表,则会进行一次合并。 - * 每个被合并的列表项都作为一个单独的数组元素存在。 - * - * @param DOMElement $node 要解析的XMLDOM节点 - * @return array 返回解析后该节点的数组 - */ - public function getChilds($node) { - if (!$node instanceof DOMElement) return array(); - $childs = array(); - foreach ($node->childNodes as $_node) { - $tempChilds = $attributes = array(); - $_node->hasAttributes() && $attributes = $this->getAttributes($_node); - if (3 == $_node->nodeType) { - $value = trim($_node->nodeValue); - (is_numeric($value) || $value) && $childs['__value'] = $value; //值为0的情况 - $__tmp = strtolower($value); - ('false' === $__tmp) && $childs['__value'] = false; //为false的配置值 - ('true' === $__tmp) && $childs['__value'] = true; //为false的配置值 - } - if (1 !== $_node->nodeType) continue; - - $tempChilds = $this->getChilds($_node); - $tempChilds = array_merge($attributes, $tempChilds); - - if (empty($tempChilds)) - $tempChilds = ''; - else - $tempChilds = (isset($tempChilds['__value']) && count($tempChilds) == 1) ? $tempChilds['__value'] : $tempChilds; - - $nodeName = "" !== ($name = $_node->getAttribute(self::NAME)) ? $name : $_node->nodeName; - if (!isset($childs[$nodeName])) - $childs[$nodeName] = $tempChilds; - else { - $element = $childs[$nodeName]; - $childs[$nodeName] = (is_array($element) && !is_numeric(implode('', array_keys($element)))) ? array_merge( - array($element), array($tempChilds)) : array_merge((array) $element, array($tempChilds)); - } - } - return $childs; - } - - /** - * 获得节点的属性 - * - * 该属性将不包含属性为name的值--规则(name的值将作为解析后数组的key值索引存在) - * - * @param DOMElement $node 节点 - * @return array 返回属性数组 - */ - public function getAttributes($node) { - if (!$node instanceof DOMElement || !$node->hasAttributes()) return array(); - $attributes = array(); - foreach ($node->attributes as $attribute) { - if (self::NAME != $attribute->nodeName) { - $value = (string) $attribute->nodeValue; - $__tmp = strtolower($value); - $attributes[$attribute->nodeName] = 'false' === $__tmp ? false : ('true' === $__tmp ? true : $value); - } - } - return $attributes; - } - - /** - * 将一个数组转换为xml - * - * @param array $arr 待转换的数组 - * @param string $charset 编码 - * @param DOMDocument $dom 根节点 - * @return DOMDocument - */ - protected function arrayToXml($arr, $charset, $dom = null) { - foreach ($arr as $key => $val) { - if (is_numeric($key)) { - $itemx = $this->dom->createElement("item"); - $id = $this->dom->createAttribute("id"); - $id->appendChild($this->dom->createTextNode($key)); - $itemx->appendChild($id); - } else { - $itemx = $this->dom->createElement($key); - } - $dom->appendChild($itemx); - if (is_string($val)) { - $val = WindConvert::convert($val, 'utf8', $charset); - $itemx->appendChild($this->dom->createTextNode($val)); - } elseif (is_object($val)) { - $this->arrayToXml(get_object_vars($val), $charset, $itemx); - } else { - $this->arrayToXml($val, $charset, $itemx); - } - } - } - -} \ No newline at end of file +} diff --git a/wind/router/AbstractWindRouter.php b/wind/router/AbstractWindRouter.php index 3eae5f1b..5c87a174 100644 --- a/wind/router/AbstractWindRouter.php +++ b/wind/router/AbstractWindRouter.php @@ -1,227 +1,277 @@ 2011-9-23 * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: AbstractWindRouter.php 3928 2013-01-29 10:21:53Z yishuo $ * @package router */ -abstract class AbstractWindRouter extends WindHandlerInterceptorChain { - protected $moduleKey = 'm'; - protected $controllerKey = 'c'; - protected $actionKey = 'a'; - protected $module = 'default'; - protected $controller = 'index'; - protected $action = 'run'; - protected $defaultRoute = ''; - protected $_action; - protected $_controller; - protected $_module; - - /** - * 路由解析 - * - * @param WindHttpRequest $request - * @return string - */ - abstract public function route($request); - - /** - * 创建Url,并返回构建好的Url值 - * - * @param string $action 操作信息 - * @param array $args 参数信息 - * @param string $route 路由协议别名 - * @return string - */ - abstract public function assemble($action, $args = array(), $route = ''); - - /* (non-PHPdoc) - * @see WindModule::setConfig() - */ - public function setConfig($config) { - parent::setConfig($config); - if ($this->_config) { - $this->module = $this->getConfig('module', 'default-value', $this->module); - $this->controller = $this->getConfig('controller', 'default-value', $this->controller); - $this->action = $this->getConfig('action', 'default-value', $this->action); - $this->moduleKey = $this->getConfig('module', 'url-param', $this->moduleKey); - $this->controllerKey = $this->getConfig('controller', 'url-param', $this->controllerKey); - $this->actionKey = $this->getConfig('action', 'url-param', $this->actionKey); - foreach ($this->getConfig('routes', '', array()) as $routeName => $route) { - if (!isset($route['class'])) continue; - $instance = WindFactory::createInstance(Wind::import($route['class'])); - $instance->setConfig($route); - $this->addRoute($routeName, $instance, (isset($route['default']) && $route['default'] === true)); - } - } - } - - /** - * 将路由解析到的url参数信息保存早系统变量中 - * - * @param string $params - * @param WindHttpRequest $requeset - * @return void - */ - protected function setParams($params, $request) { - foreach ($params as $key => $value) { - if ($key === $this->actionKey) { - $this->setAction($value); - } elseif ($key === $this->controllerKey) { - $this->setController($value); - } elseif ($key === $this->moduleKey) { - $this->setModule($value); - } - $_GET[$key] = $value; - } - } - - /** - * 添加路由协议对象,如果添加的路由协议已经存在则抛出异常 - * - * @param string - * @param AbstractWindRoute $route - * @param boolean $default 是否为默认 - * @return void - * @throws WindException - */ - public function addRoute($alias, $route, $default = false) { - $this->addInterceptors(array($alias => $route)); - if ($default) $this->defaultRoute = $alias; - } - - /** - * 根据rule的规则名称,从路由链中获得该路由的对象 - * - * @param string $ruleName 路由协议别名 - * @return AbstractWindRoute - */ - public function getRoute($ruleName) { - return isset($this->_interceptors[$ruleName]) ? $this->_interceptors[$ruleName] : null; - } - - /** - * 返回action - * - * @return string - */ - public function getAction() { - return $this->action; - } - - /** - * 返回controller - * - * @return string - */ - public function getController() { - return $this->controller; - } - - /** - * 设置action - * - * @param string $action - * @return void - */ - public function setAction($action) { - $this->action = $action; - } - - /** - * 设置controller - * - * @param string $controller - * @return void - */ - public function setController($controller) { - $this->controller = $controller; - } - - /** - * @return string - */ - public function getModule() { - return $this->module; - } - - /** - * @param string - */ - public function setModule($module) { - $this->module = $module; - } - - /** - * @return string - */ - public function getModuleKey() { - return $this->moduleKey; - } - - /** - * @return string - */ - public function getControllerKey() { - return $this->controllerKey; - } - - /** - * @return string - */ - public function getActionKey() { - return $this->actionKey; - } - - /** - * @param string $moduleKey - */ - public function setModuleKey($moduleKey) { - $this->moduleKey = $moduleKey; - } - - /** - * @param string $controllerKey - */ - public function setControllerKey($controllerKey) { - $this->controllerKey = $controllerKey; - } - - /** - * @param string $actionKey - */ - public function setActionKey($actionKey) { - $this->actionKey = $actionKey; - } - - /** - * 返回默认的module值 - * - * @return string - */ - public function getDefaultModule() { - return $this->_module; - } - - /** - * 返回默认的controller值 - * - * @return string - */ - public function getDefaultController() { - return $this->_controller; - } - - /** - * 返回默认的action值 - * - * @return string - */ - public function getDefaultAction() { - return $this->_action; - } -} \ No newline at end of file +abstract class AbstractWindRouter extends WindHandlerInterceptorChain +{ + protected $moduleKey = 'm'; + protected $controllerKey = 'c'; + protected $actionKey = 'a'; + protected $module; + protected $controller; + protected $action; + protected $_action = 'run'; + protected $_controller = 'index'; + protected $_module = 'default'; + protected $defaultRoute = ''; + + /** + * 路由解析 + * + * @param WindHttpRequest $request + * @return string + */ + abstract public function route($request); + + /** + * 创建Url,并返回构建好的Url值 + * + * @param string $action 操作信息 + * @param array $args 参数信息 + * @param string $route 路由协议别名 + * @return string + */ + abstract public function assemble($action, $args = array(), $route = ''); + + /* (non-PHPdoc) + * @see WindModule::setConfig() + */ + public function setConfig($config) + { + parent::setConfig($config); + if ($this->_config) { + $this->_module = $this->getConfig('module', 'default-value', $this->_module); + $this->_controller = $this->getConfig('controller', 'default-value', $this->_controller); + $this->_action = $this->getConfig('action', 'default-value', $this->_action); + $this->moduleKey = $this->getConfig('module', 'url-param', $this->moduleKey); + $this->controllerKey = $this->getConfig('controller', 'url-param', $this->controllerKey); + $this->actionKey = $this->getConfig('action', 'url-param', $this->actionKey); + foreach ($this->getConfig('routes', '', array()) as $routeName => $route) { + if (!isset($route['class'])) { + continue; + } + $instance = WindFactory::createInstance(Wind::import($route['class'])); + $instance->setConfig($route); + $this->addRoute($routeName, $instance, (isset($route['default']) && $route['default'] === true)); + } + } + } + + /** + * 将路由解析到的url参数信息保存早系统变量中 + * + * @param string $params + * @param WindHttpRequest $requeset + */ + protected function setParams($params, $request) + { + foreach ($params as $key => $value) { + if ($key === $this->actionKey) { + $this->setAction($value); + } elseif ($key === $this->controllerKey) { + $this->setController($value); + } elseif ($key === $this->moduleKey) { + $this->setModule($value); + } else { + $_GET[$key] = $value; + } + } + } + + /** + * 添加路由协议对象,如果添加的路由协议已经存在则抛出异常 + * + * @param string + * @param AbstractWindRoute $route + * @param bool $default 是否为默认 + */ + public function addRoute($alias, $route, $default = false) + { + $this->addInterceptors(array($alias => $route)); + if ($default) { + $this->defaultRoute = $alias; + } + } + + /** + * 根据rule的规则名称,从路由链中获得该路由的对象 + * + * @param string $ruleName 路由协议别名 + * @return AbstractWindRoute + */ + public function getRoute($ruleName) + { + return isset($this->_interceptors[$ruleName]) ? $this->_interceptors[$ruleName] : null; + } + + /** + * 返回action + * + * @return string + */ + public function getAction() + { + return $this->action; + } + + /** + * 返回controller + * + * @return string + */ + public function getController() + { + return $this->controller; + } + + /** + * 设置action + * + * @param string $action + */ + public function setAction($action) + { + $this->action = $action; + } + + /** + * 设置controller + * + * @param string $controller + */ + public function setController($controller) + { + $this->controller = $controller; + } + + /** + * @return string + */ + public function getModule() + { + return $this->module; + } + + /** + * @param string + */ + public function setModule($module) + { + $this->module = $module; + } + + /** + * @return string + */ + public function getModuleKey() + { + return $this->moduleKey; + } + + /** + * @return string + */ + public function getControllerKey() + { + return $this->controllerKey; + } + + /** + * @return string + */ + public function getActionKey() + { + return $this->actionKey; + } + + /** + * @param string $moduleKey + */ + public function setModuleKey($moduleKey) + { + $this->moduleKey = $moduleKey; + } + + /** + * @param string $controllerKey + */ + public function setControllerKey($controllerKey) + { + $this->controllerKey = $controllerKey; + } + + /** + * @param string $actionKey + */ + public function setActionKey($actionKey) + { + $this->actionKey = $actionKey; + } + + /** + * 返回默认的module值 + * + * @return string + */ + public function getDefaultModule() + { + return $this->_module; + } + + /** + * 设置默认module + * + * @param string $module + */ + public function setDefaultModule($module) + { + $this->_module = $module; + } + + /** + * 返回默认的controller值 + * + * @return string + */ + public function getDefaultController() + { + return $this->_controller; + } + + /** + * 设置默认的controller + * + * @param string $controller + */ + public function setDefaultController($controller) + { + $this->_controller = $controller; + } + + /** + * 返回默认的action值 + * + * @return string + */ + public function getDefaultAction() + { + return $this->_action; + } + + /** + * 设置默认的action值 + * + * @param string $action + */ + public function setDefaultAction($action) + { + $this->_action = $action; + } +} diff --git a/wind/router/WindCommandRouter.php b/wind/router/WindCommandRouter.php new file mode 100644 index 00000000..64b7194d --- /dev/null +++ b/wind/router/WindCommandRouter.php @@ -0,0 +1,107 @@ + + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id: WindCommandRouter.php 3859 2012-12-18 09:25:51Z yishuo $ + * @package command + */ +class WindCommandRouter extends AbstractWindRouter +{ + protected $moduleKey = '-m,module,--module'; + protected $controllerKey = '-c,controller,--controller'; + protected $actionKey = '-a,action,--action'; + protected $helpKey = '-h,help,--help'; + protected $paramKey = '-p,param,--param'; + protected $help = false; + protected $cmd = ''; + /** + * @var WindCommandRequest + */ + private $request = null; + + /* (non-PHPdoc) + * @see AbstractWindRouter::route() + */ + public function route($request) + { + $this->request = $request; + $this->_action = $this->action; + $this->_controller = $this->controller; + $this->_module = $this->module; + if (!empty($this->_config['routes'])) { + $params = $this->getHandler()->handle($request); + $this->setParams($params, $request); + } else { + $args = $request->getRequest('argv', array()); + $this->cmd = $args[0]; + $_count = count($args); + for ($i = 1; $i < $_count; $i++) { + if (in_array($args[$i], explode(',', $this->helpKey))) { + $this->help = true; + } elseif (in_array($args[$i], explode(',', $this->moduleKey))) { + $this->module = $args[++$i]; + } elseif (in_array($args[$i], explode(',', $this->controllerKey))) { + $this->controller = $args[++$i]; + } elseif (in_array($args[$i], explode(',', $this->actionKey))) { + $this->action = $args[++$i]; + } elseif (in_array($args[$i], explode(',', $this->paramKey))) { + $_SERVER['argv'] = array_slice($args, $i + 1); + break; + } + } + } + } + + /* (non-PHPdoc) + * @see AbstractWindRouter::assemble() + */ + public function assemble($action, $args = array(), $route = '') + { + return ''; + } + + /* (non-PHPdoc) + * @see AbstractWindRouter::setParams() + */ + protected function setParams($params, $request) + { + /* @var $request WindCommandRequest */ + $_SERVER['argv'] = isset($params[$this->paramKey]) ? $params[$this->paramKey] : array(); + isset($params[$this->moduleKey]) && $this->setModule($params[$this->moduleKey]); + isset($params[$this->controllerKey]) && $this->setController($params[$this->controllerKey]); + isset($params[$this->actionKey]) && $this->setAction($params[$this->actionKey]); + } + + /** + * 是否是请求帮助 + * + * @return bool + */ + public function isHelp() + { + return $this->help; + } + + /** + * 返回当前命令 + * + * @return string + */ + public function getCmd() + { + return $this->cmd; + } + + /** + * @return string + */ + public function getParamKey() + { + return $this->paramKey; + } +} diff --git a/wind/router/WindMultiAppRouter.php b/wind/router/WindMultiAppRouter.php new file mode 100644 index 00000000..0ece47c6 --- /dev/null +++ b/wind/router/WindMultiAppRouter.php @@ -0,0 +1,124 @@ + 2012-1-12 + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id: WindMultiAppRouter.php 3772 2012-10-19 08:58:57Z yishuo $ + * @package router + */ +class WindMultiAppRouter extends WindRouter +{ + protected $appKey = 'p'; + protected $app = 'default'; + + protected $_app; + + /* (non-PHPdoc) + * @see WindRouter::route() + */ + public function route($request) + { + $this->_app = $this->app; + parent::route($request); + } + + /* (non-PHPdoc) + * @see WindRouter::assemble() + */ + public function assemble($action, $args = array(), $route = null) + { + $route || $route = $this->defaultRoute; + if ($route && (null !== $route = $this->getRoute($route))) { + $_url = $route->build($this, $action, $args); + } else { + list($_a, $_c, $_m, $_p, $args) = WindUrlHelper::resolveAction($action, $args); + $_p || $_p = $this->getApp(); + if ($_p && $_p !== $this->_app) { + $args[$this->appKey] = $_p; + } + if ($_m && $_m !== $this->_module) { + $args[$this->moduleKey] = $_m; + } + if ($_c && $_c !== $this->_controller) { + $args[$this->controllerKey] = $_c; + } + if ($_a && $_a !== $this->_action) { + $args[$this->actionKey] = $_a; + } + $_url = $this->request->getScript().'?'.WindUrlHelper::argsToUrl($args); + } + + return $_url; + } + + /* (non-PHPdoc) + * @see AbstractWindRouter::setConfig() + */ + public function setConfig($config) + { + parent::setConfig($config); + if ($this->_config) { + $this->app = $this->getConfig('app', 'default-value', $this->app); + $this->appKey = $this->getConfig('app', 'url-param', $this->appKey); + } + } + + /* (non-PHPdoc) + * @see AbstractWindRouter::setParams() + */ + protected function setParams($params, $request) + { + parent::setParams($params, $request); + $app = isset($params[$this->appKey]) ? $params[$this->appKey] : $request->getRequest( + $this->appKey); + $app && $this->setApp($app); + } + + /** + * @return string + */ + public function getApp() + { + return $this->app; + } + + /** + * 设置当前要访问的appname + * + * @param string $appName + */ + public function setApp($appName) + { + $this->app = $appName; + } + + /** + * @return string + */ + public function getAppKey() + { + return $this->appKey; + } + + /** + * @param string $appKey + */ + public function setAppKey($appKey) + { + $this->appKey = $appKey; + } + + /** + * 返回默认的app值 + * + * @return string + */ + public function getDefaultApp() + { + return $this->_app; + } +} diff --git a/wind/router/WindMutilAppRouter.php b/wind/router/WindMutilAppRouter.php deleted file mode 100644 index 5b598655..00000000 --- a/wind/router/WindMutilAppRouter.php +++ /dev/null @@ -1,106 +0,0 @@ - 2012-1-12 - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package router - */ -class WindMutilAppRouter extends WindRouter { - protected $appKey = 'p'; - protected $app = 'default'; - - protected $_app; - - /* (non-PHPdoc) - * @see WindRouter::route() - */ - public function route($request) { - $this->_app = $this->app; - parent::route($request); - } - - /* (non-PHPdoc) - * @see WindRouter::assemble() - */ - public function assemble($action, $args = array(), $route = null) { - $route || $route = $this->defaultRoute; - if ($route && (null !== $route = $this->getRoute($route))) { - $_url = $route->build($this, $action, $args); - } else { - list($_a, $_c, $_m, $_p, $args) = WindUrlHelper::resolveAction($action, $args); - $_p || $_p = $this->getApp(); - if ($_p && $_p !== $this->_app) $args[$this->appKey] = $_p; - if ($_m && $_m !== $this->_module) $args[$this->moduleKey] = $_m; - if ($_c && $_c !== $this->_controller) $args[$this->controllerKey] = $_c; - if ($_a && $_a !== $this->_action) $args[$this->actionKey] = $_a; - $_url = $this->request->getScript() . '?' . WindUrlHelper::argsToUrl($args); - } - return $_url; - } - - /* (non-PHPdoc) - * @see AbstractWindRouter::setConfig() - */ - public function setConfig($config) { - parent::setConfig($config); - if ($this->_config) { - $this->app = $this->getConfig('app', 'default-value', $this->app); - $this->appKey = $this->getConfig('app', 'url-param', $this->appKey); - } - } - - /* (non-PHPdoc) - * @see AbstractWindRouter::setParams() - */ - protected function setParams($params, $request) { - parent::setParams($params, $request); - $app = isset($params[$this->appKey]) ? $params[$this->appKey] : $request->getRequest( - $this->appKey); - $app && $this->setApp($app); - } - - /** - * @return string - */ - public function getApp() { - return $this->app; - } - - /** - * 设置当前要访问的appname - * - * @param string $appName - */ - public function setApp($appName) { - $this->app = $appName; - } - - /** - * @return string - */ - public function getAppKey() { - return $this->appKey; - } - - /** - * @param string $appKey - */ - public function setAppKey($appKey) { - $this->appKey = $appKey; - } - - /** - * 返回默认的app值 - * - * @return string - */ - public function getDefaultApp() { - return $this->_app; - } -} - -?> \ No newline at end of file diff --git a/wind/router/WindRouter.php b/wind/router/WindRouter.php index 4bda7704..cd81340d 100644 --- a/wind/router/WindRouter.php +++ b/wind/router/WindRouter.php @@ -1,8 +1,9 @@ @@ -27,52 +28,70 @@ * 'params' => array(), //参数mapping * 'reverse' => '')), //反向解析 * - * + * * @author Qiong Wu 2011-9-23 * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindRouter.php 3928 2013-01-29 10:21:53Z yishuo $ * @package router */ -class WindRouter extends AbstractWindRouter { - /** - * @var WindHttpRequest - */ - private $request = null; - - /* (non-PHPdoc) - * @see IWindRouter::route() - */ - public function route($request) { - $this->_action = $this->action; - $this->_controller = $this->controller; - $this->_module = $this->module; - $this->request = $request; - if (!empty($this->_config['routes'])) { - $params = $this->getHandler()->handle($request); - $params && $this->setParams($params, $request); - } else { - $this->action = $request->getRequest($this->actionKey, $this->_action); - $this->controller = $request->getRequest($this->controllerKey, $this->_controller); - $this->module = $request->getRequest($this->moduleKey, $this->_module); - } - } - - /* (non-PHPdoc) - * @see AbstractWindRouter::assemble() - */ - public function assemble($action, $args = array(), $route = null) { - $route || $route = $this->defaultRoute; - if ($route && (null !== $route = $this->getRoute($route))) { - $_url = $route->build($this, $action, $args); - } else { - list($_a, $_c, $_m, $_p, $args) = WindUrlHelper::resolveAction($action, $args); - if ($_m && $_m !== $this->_module) $args[$this->moduleKey] = $_m; - if ($_c && $_c !== $this->_controller) $args[$this->controllerKey] = $_c; - if ($_a && $_a !== $this->_action) $args[$this->actionKey] = $_a; - $_url = $this->request->getScript() . '?' . WindUrlHelper::argsToUrl($args); - } - return $_url; - } +class WindRouter extends AbstractWindRouter +{ + /** + * @var WindHttpRequest + */ + private $request = null; + + /* (non-PHPdoc) + * @see IWindRouter::route() + */ + public function route($request) + { + $this->request = $request; + if (!empty($this->_config['routes'])) { + $this->setCallBack(array($this, 'defaultRoute')); + $params = $this->getHandler()->handle($request); + $params && $this->setParams($params, $request); + $this->action || $this->action = $this->_action; + $this->controller || $this->controller = $this->_controller; + $this->module || $this->module = $this->_module; + } else { + $this->defaultRoute(); + } + } + + /** + * 默认路由处理 + */ + public function defaultRoute() + { + $this->action = $this->request->getRequest($this->actionKey, $this->_action); + $this->controller = $this->request->getRequest($this->controllerKey, $this->_controller); + $this->module = $this->request->getRequest($this->moduleKey, $this->_module); + } + + /* (non-PHPdoc) + * @see AbstractWindRouter::assemble() + */ + public function assemble($action, $args = array(), $route = null) + { + $route || $route = $this->defaultRoute; + if ($route && (null !== $route = $this->getRoute($route))) { + $_url = $route->build($this, $action, $args); + } else { + list($_a, $_c, $_m, $args) = WindUrlHelper::resolveAction($action, $args); + if ($_m && $_m !== $this->_module) { + $args[$this->moduleKey] = $_m; + } + if ($_c && $_c !== $this->_controller) { + $args[$this->controllerKey] = $_c; + } + if ($_a && $_a !== $this->_action) { + $args[$this->actionKey] = $_a; + } + $_url = $this->request->getScript().'?'.WindUrlHelper::argsToUrl($args); + } + + return $_url; + } } -?> \ No newline at end of file diff --git a/wind/router/route/AbstractWindRoute.php b/wind/router/route/AbstractWindRoute.php index 58d39fac..8c624881 100644 --- a/wind/router/route/AbstractWindRoute.php +++ b/wind/router/route/AbstractWindRoute.php @@ -1,59 +1,63 @@ 注意:路由协议类是继承了拦截过滤器的接口实现,实现多路由协议支持 * @author Qiong Wu 2011-9-23 * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: AbstractWindRoute.php 3330 2012-01-15 13:49:24Z yishuo $ * @package router * @subpackage route */ -abstract class AbstractWindRoute extends WindHandlerInterceptor { - protected $pattern = ''; - protected $reverse = ''; - protected $params = array(); +abstract class AbstractWindRoute extends WindHandlerInterceptor +{ + protected $pattern = ''; + protected $reverse = ''; + protected $params = array(); - /** - * 根据匹配的路由规则,构建Url - * - * @param AbstractWindRouter $router - * @param string $action - * @param array $args - * @return string - */ - abstract public function build($router, $action, $args = array()); + /** + * 根据匹配的路由规则,构建Url + * + * @param AbstractWindRouter $router + * @param string $action + * @param array $args + * @return string + */ + abstract public function build($router, $action, $args = array()); - /** - * 路由规则匹配方法,返回匹配到的参数列表 - * - * @param WindHttpRequest $request - * @return array - */ - abstract public function match($request); + /** + * 路由规则匹配方法,返回匹配到的参数列表 + * + * @param WindHttpRequest $request + * @return array + */ + abstract public function match($request); - /* (non-PHPdoc) - * @see WindHandlerInterceptor::preHandle() - */ - public function preHandle($request = null) { - return $this->match($request); - } + /* (non-PHPdoc) + * @see WindHandlerInterceptor::preHandle() + */ + public function preHandle($request = null) + { + return $this->match($request); + } - /* (non-PHPdoc) - * @see WindHandlerInterceptor::postHandle() - */ - public function postHandle() {} + /* (non-PHPdoc) + * @see WindHandlerInterceptor::postHandle() + */ + public function postHandle() + { + } - /* (non-PHPdoc) - * @see WindModule::setConfig() - */ - public function setConfig($config) { - parent::setConfig($config); - $this->pattern = $this->getConfig('pattern', '', $this->pattern); - $this->reverse = $this->getConfig('reverse', '', $this->reverse); - $this->params = $this->getConfig('params', '', $this->params); - } + /* (non-PHPdoc) + * @see WindModule::setConfig() + */ + public function setConfig($config) + { + parent::setConfig($config); + $this->pattern = $this->getConfig('pattern', '', $this->pattern); + $this->reverse = $this->getConfig('reverse', '', $this->reverse); + $this->params = $this->getConfig('params', '', $this->params); + } } -?> \ No newline at end of file diff --git a/wind/router/route/WindRewriteRoute.php b/wind/router/route/WindRewriteRoute.php index 81f85fc7..1ffad2b2 100644 --- a/wind/router/route/WindRewriteRoute.php +++ b/wind/router/route/WindRewriteRoute.php @@ -1,144 +1,101 @@ ^http[s]?:\/\/[^\/]+\/(\w+)?(\/\w+)?(\/\w+)?(\/|\/?\?.*)*$ - * 例如:请求http://blog.p9.com/myModule/myController/myAction?id=1&name=2, - * 则解析为app => blog, module => myModule, controller => myController, action => myAction, - * GET参数id => 1, name => 2 - * - * - * @author Shi Long - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package router - * @subpackage route + + +/** + * 基于rewrite和二级域名的路由协议 + * + * 该类继承了抽象类{@see AbstractWindRoute},实现了{@see AbstractWindRoute::match()}, + * {@see AbstractWindRoute::build()}. + * 要启用此路由协议,需要开启服务器的rewrite功能 + * 默认路由规则:/^(\w+)(\/\w+)(\/\w+)(.*)$/i + * 例如:请求http://blog.p9.com/myModule/myController/myAction/id/1/name/2, + * 则解析为module => myModule, controller => myController, action => myAction, + * GET参数id => 1, name => 2 + * + * + * @author Shi Long + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id: WindRewriteRoute.php 3677 2012-06-13 06:30:01Z yishuo $ + * @package router + * @subpackage route */ -class WindRewriteRoute extends AbstractWindRoute { - - //protected $pattern = '^http[s]?:\/\/[^\/]+(\/\w+)?(\/\w+)?(\/\w+)?(\/|\/?\?.*)*$'; - protected $pattern = '^http[s]?:\/\/[^\/]+(\/\w+)?(\/\w+)?(\/\w+)?.*$'; - protected $reverse = '/%s'; - protected $separator = '&='; - protected $params = array('a' => array('map' => 3), 'c' => array('map' => 2), 'm' => array('map' => 1)); +class WindRewriteRoute extends AbstractWindRoute +{ + protected $pattern = '/^(\w+)(\/\w+)(\/\w+)(.*)$/i'; + protected $reverse = '/%s/%s/%s'; + protected $separator = '//'; + protected $params = array('a' => 3, 'c' => 2, 'm' => 1); - /** - * 路由解析 - * - * 匹配这个patten时,将试图去解析module、controller和action值,并解析二级域名。 - * @see AbstractWindRoute::match() - */ - public function match($request) { - $fullUrl = $request->getHostInfo() . $request->getRequestUri(); - $_pathInfo = trim(str_replace($request->getBaseUrl(), '', $fullUrl), '/'); - if (!$_pathInfo || !preg_match_all('/' . $this->pattern . '/i', trim($_pathInfo, '/'), $matches) || strpos( - $_pathInfo, '.php') !== false) return null; - - list(, $_args) = explode('?', $_pathInfo . '?', 2); - $_args = trim($_args, '?'); - $_args = WindUrlHelper::urlToArgs($_args, true, $this->separator); - - foreach ($this->params as $_n => $_p) { - if (isset($_p['map']) && isset($matches[$_p['map']][0])) - $_value = $matches[$_p['map']][0]; - else - $_value = isset($_p['default']) ? $_p['default'] : ''; - $this->params[$_n]['value'] = $params[$_n] = trim($_value, '-/'); - unset($_args[$_n]); //去掉参数中的m,c,a - } - $host = $request->getHostInfo(); - if ($host != '' && ($pos1 = strpos($host, '://')) !== false && ($pos2 = strpos($host, '.')) !== false) - $host = substr($host, $pos1 + 3, $pos2 - $pos1 - 3); - else - return null; - $params['p'] = $host == 'www' ? '' : $host; - unset($_args['p']); //去掉参数中的p - $_args && $params = array_merge($params, $_args); - return $params; - } + /** + * 路由解析 + * + * 匹配这个patten时,将试图去解析module、controller和action值,并解析二级域名。 + * + * @see AbstractWindRoute::match() + */ + public function match($request) + { + $_pathInfo = trim($request->getPathInfo(), '/'); + if (!$_pathInfo || !preg_match($this->pattern, $_pathInfo, $matches) || strpos($_pathInfo, + '.php') !== false) { + return null; + } + $params = array(); + $_args = WindUrlHelper::urlToArgs($matches[4], true, $this->separator); - /** - * 在此路由协议的基础上组装url - * - * @param AbstractWindRouter $router - * @param string $action 格式为app/module/controller/action - * @param array $args 附带的参数 - * @return string - * @see AbstractWindRoute::build() - */ - public function build($router, $action, $args = array()) { - list($_a, $_c, $_m, $_p, $args) = WindUrlHelper::resolveAction($action, $args); - $flag = 0; - foreach ($this->params as $key => $val) { - if (!isset($val['map'])) continue; - if ($key === $router->getModuleKey()) { - $m = $_m ? $_m : $router->getModule(); - if ($m === $router->getDefaultModule() && $flag & 2) - $flag = 7; - else - $_args[$val['map']] = $m; - } elseif ($key === $router->getControllerKey()) { - $c = $_c ? $_c : $router->getController(); - if ($c === $router->getDefaultController() && $flag & 1) - $flag = 3; - else - $_args[$val['map']] = $c; - } elseif ($key === $router->getActionKey()) { - $a = $_a ? $_a : $router->getAction(); - if ($a === $router->getDefaultAction()) - $flag = 1; - else - $_args[$val['map']] = $a; - } else { - if (isset($args[$key])) - $_args[$val['map']] = $args[$key]; - elseif (isset($val['value'])) - $_args[$val['map']] = $val['value']; - else - $_args[$val['map']] = ''; - } - unset($args[$key]); - } - $mulitipyTime = count($_args); - $_args[0] = str_repeat($this->reverse, $mulitipyTime); - ksort($_args); - $url = call_user_func_array("sprintf", $_args); - $args && $url .= '?' . WindUrlHelper::argsToUrl($args, true, $this->separator); - - $baseUrl = Wind::getApp()->getRequest()->getBaseUrl(true); - $_baseUrl = $_p ? $this->replaceStr($baseUrl, $_p) : $baseUrl; - - return trim($_baseUrl, '/') . '/' . trim($url, '/'); - } + // 解析m,c,a + foreach ($this->params as $k => $v) { + if (isset($matches[$v])) { + $params[$k] = trim($matches[$v], '-/'); + } + unset($_args[$k]); // 去掉参数中的m,c,a + } - /** - * 替换二级域名,生成baseurl - * - * @param string $url - * @param string $str - */ - private function replaceStr($url, $str) { - $host = Wind::getApp()->getRequest()->getHostInfo(); - if (strpos($host, '://') === false || strpos($host, '.') === false) return $url; - $arr = explode('.', $host, 2); - $arr1 = explode('://', $arr[0]); - $_host = $arr1[0] . '://' . $str . '.' . $arr[1]; - return str_replace($host, $_host, $url); - } + return $_args + $params; + } - /* (non-PHPdoc) - * @see AbstractWindRoute::setConfig() - */ - public function setConfig($config) { - parent::setConfig($config); - $this->separator = $this->getConfig('separator', '', $this->separator); - } + /** + * 在此路由协议的基础上组装url + * + * @param AbstractWindRouter $router + * @param string $action + * 格式为app/module/controller/action + * @param array $args + * 附带的参数 + * @return string + * @see AbstractWindRoute::build() + */ + public function build($router, $action, $args = array()) + { + list($_a, $_c, $_m, $_p, $args) = WindUrlHelper::resolveAction($action, $args); + foreach ($this->params as $key => $val) { + if ($key === $router->getModuleKey()) { + $_m || $_m = $router->getModule(); + $_args[$val] = $_m; + } elseif ($key === $router->getControllerKey()) { + $_c || $_c = $router->getController(); + $_args[$val] = $_c; + } elseif ($key === $router->getActionKey()) { + $_a || $_a = $router->getAction(); + $_args[$val] = $_a; + } + unset($args[$key]); + } + $_args[0] = $this->reverse; + ksort($_args); + $url = call_user_func_array('sprintf', $_args); + $args && $url .= '/'.WindUrlHelper::argsToUrl($args, true, $this->separator); -} + return trim($url, '/'); + } -?> \ No newline at end of file + /* + * (non-PHPdoc) @see AbstractWindRoute::setConfig() + */ + public function setConfig($config) + { + parent::setConfig($config); + $this->separator = $this->getConfig('separator', '', $this->separator); + } +} diff --git a/wind/security/IWindSecurity.php b/wind/security/IWindSecurity.php index f9f3467b..30cc755c 100644 --- a/wind/security/IWindSecurity.php +++ b/wind/security/IWindSecurity.php @@ -8,25 +8,23 @@ * @version $Id$ * @package security */ -interface IWindSecurity { +interface IWindSecurity +{ + /** + * 加密算法实现接口 + * + * @param string $string + * @param string $key + * @return string 加密后的结果 + */ + public function encrypt($string, $key); - /** - * 加密算法实现接口 - * - * @param string $string - * @param string $key - * @return string 加密后的结果 - */ - public function encrypt($string, $key); - - /** - * 解密算法实现 - * - * @param string $string - * @param string $key - * @return string 解密后的结果 - */ - public function decrypt($string, $key); + /** + * 解密算法实现 + * + * @param string $string + * @param string $key + * @return string 解密后的结果 + */ + public function decrypt($string, $key); } - -?> \ No newline at end of file diff --git a/wind/security/WindMcryptCbc.php b/wind/security/WindMcryptCbc.php index 7af441b2..8ed75eae 100644 --- a/wind/security/WindMcryptCbc.php +++ b/wind/security/WindMcryptCbc.php @@ -1,5 +1,6 @@ strlen($str)) return false; - if (strspn($str, chr($pad), strlen($str) - $pad) != $pad) return false; - return substr($str, 0, -1 * $pad); - } -} + return mcrypt_cbc(MCRYPT_DES, $key, $string, MCRYPT_ENCRYPT, $iv); + } -?> \ No newline at end of file + /* (non-PHPdoc) + * @see IWindSecurity::decrypt() + */ + public function decrypt($string, $key, $iv = '') + { + if ($string === '') { + return ''; + } + if (!extension_loaded('mcrypt')) { + throw new WindException('[security.WindMcryptCbc.decrypt] extension \'mcrypt\' is not loaded.'); + } + if (!$key || !is_string($key)) { + throw new WindException('[security.WindMcryptCbc.decrypt] security key is required.', + WindException::ERROR_PARAMETER_TYPE_ERROR); + } + + $size = mcrypt_get_block_size(MCRYPT_DES, MCRYPT_MODE_CBC); + $iv = substr(md5($iv ? $iv : $key), -$size); + $str = mcrypt_cbc(MCRYPT_DES, $key, $string, MCRYPT_DECRYPT, $iv); + $pad = ord($str{strlen($str) - 1}); + if ($pad > strlen($str)) { + return false; + } + if (strspn($str, chr($pad), strlen($str) - $pad) != $pad) { + return false; + } + + return substr($str, 0, -1 * $pad); + } +} diff --git a/wind/security/WindXxtea.php b/wind/security/WindXxtea.php index 448b923c..54c4f8bb 100644 --- a/wind/security/WindXxtea.php +++ b/wind/security/WindXxtea.php @@ -1,5 +1,6 @@ str2long($str, true); + $k = $this->str2long($key, false); + if (count($k) < 4) { + for ($i = count($k); $i < 4; $i++) { + $k[$i] = 0; + } + } + $n = count($v) - 1; - /* (non-PHPdoc) - * @see IWindSecurity::encrypt() - */ - public function encrypt($str, $key) { - if ($str == '') return ''; - if (!$key || !is_string($key)) { - throw new WindException('[security.WindXxtea.decrypt] security key is required.', - WindException::ERROR_PARAMETER_TYPE_ERROR); - } - $v = $this->str2long($str, true); - $k = $this->str2long($key, false); - if (count($k) < 4) { - for ($i = count($k); $i < 4; $i++) { - $k[$i] = 0; - } - } - $n = count($v) - 1; - - $z = $v[$n]; - $y = $v[0]; - $delta = 0x9E3779B9; - $q = floor(6 + 52 / ($n + 1)); - $sum = 0; - while (0 < $q--) { - $sum = $this->int32($sum + $delta); - $e = $sum >> 2 & 3; - for ($p = 0; $p < $n; $p++) { - $y = $v[$p + 1]; - $mx = $this->int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ $this->int32( - ($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z)); - $z = $v[$p] = $this->int32($v[$p] + $mx); - } - $y = $v[0]; - $mx = $this->int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ $this->int32( - ($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z)); - $z = $v[$n] = $this->int32($v[$n] + $mx); - } - return $this->long2str($v, false); - } + $z = $v[$n]; + $y = $v[0]; + $delta = 0x9E3779B9; + $q = floor(6 + 52 / ($n + 1)); + $sum = 0; + while (0 < $q--) { + $sum = $this->int32($sum + $delta); + $e = $sum >> 2 & 3; + for ($p = 0; $p < $n; $p++) { + $y = $v[$p + 1]; + $mx = $this->int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ $this->int32( + ($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z)); + $z = $v[$p] = $this->int32($v[$p] + $mx); + } + $y = $v[0]; + $mx = $this->int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ $this->int32( + ($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z)); + $z = $v[$n] = $this->int32($v[$n] + $mx); + } - /* (non-PHPdoc) - * @see IWindSecurity::decrypt() - */ - public function decrypt($str, $key) { - if ($str == '') return ''; - if (!$key || !is_string($key)) { - throw new WindException('[security.WindXxtea.decrypt] security key is required.', - WindException::ERROR_PARAMETER_TYPE_ERROR); - } - $v = $this->str2long($str, false); - $k = $this->str2long($key, false); - if (count($k) < 4) { - for ($i = count($k); $i < 4; $i++) { - $k[$i] = 0; - } - } - $n = count($v) - 1; - - $z = $v[$n]; - $y = $v[0]; - $delta = 0x9E3779B9; - $q = floor(6 + 52 / ($n + 1)); - $sum = $this->int32($q * $delta); - while ($sum != 0) { - $e = $sum >> 2 & 3; - for ($p = $n; $p > 0; $p--) { - $z = $v[$p - 1]; - $mx = $this->int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ $this->int32( - ($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z)); - $y = $v[$p] = $this->int32($v[$p] - $mx); - } - $z = $v[$n]; - $mx = $this->int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ $this->int32( - ($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z)); - $y = $v[0] = $this->int32($v[0] - $mx); - $sum = $this->int32($sum - $delta); - } - return $this->long2str($v, true); - } + return $this->long2str($v, false); + } - /** - * 长整型转换为字符串 - * - * @param long $v - * @param boolean $w - * @return string - */ - private function long2str($v, $w) { - $len = count($v); - $s = array(); - for ($i = 0; $i < $len; $i++) - $s[$i] = pack("V", $v[$i]); - return $w ? substr(join('', $s), 0, $v[$len - 1]) : join('', $s); - } + /* (non-PHPdoc) + * @see IWindSecurity::decrypt() + */ + public function decrypt($str, $key) + { + if ($str == '') { + return ''; + } + if (!$key || !is_string($key)) { + throw new WindException('[security.WindXxtea.decrypt] security key is required.', + WindException::ERROR_PARAMETER_TYPE_ERROR); + } + $v = $this->str2long($str, false); + $k = $this->str2long($key, false); + if (count($k) < 4) { + for ($i = count($k); $i < 4; $i++) { + $k[$i] = 0; + } + } + $n = count($v) - 1; - /** - * 字符串转化为长整型 - * - * @param string $s - * @param boolean $w - * @return Ambigous - */ - private function str2long($s, $w) { - $v = unpack("V*", $s . str_repeat("\0", (4 - strlen($s) % 4) & 3)); - $v = array_values($v); - if ($w) $v[count($v)] = strlen($s); - return $v; - } + $z = $v[$n]; + $y = $v[0]; + $delta = 0x9E3779B9; + $q = floor(6 + 52 / ($n + 1)); + $sum = $this->int32($q * $delta); + while ($sum != 0) { + $e = $sum >> 2 & 3; + for ($p = $n; $p > 0; $p--) { + $z = $v[$p - 1]; + $mx = $this->int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ $this->int32( + ($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z)); + $y = $v[$p] = $this->int32($v[$p] - $mx); + } + $z = $v[$n]; + $mx = $this->int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ $this->int32( + ($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z)); + $y = $v[0] = $this->int32($v[0] - $mx); + $sum = $this->int32($sum - $delta); + } - /** - * @param int $n - * @return number - */ - private function int32($n) { - while ($n >= 2147483648) - $n -= 4294967296; - while ($n <= -2147483649) - $n += 4294967296; - return (int) $n; - } + return $this->long2str($v, true); + } -} + /** + * 长整型转换为字符串 + * + * @param long $v + * @param bool $w + * @return string + */ + private function long2str($v, $w) + { + $len = count($v); + $s = array(); + for ($i = 0; $i < $len; $i++) { + $s[$i] = pack('V', $v[$i]); + } + + return $w ? substr(implode('', $s), 0, $v[$len - 1]) : implode('', $s); + } -?> \ No newline at end of file + /** + * 字符串转化为长整型 + * + * @param string $s + * @param bool $w + * @return Ambigous + */ + private function str2long($s, $w) + { + $v = unpack('V*', $s.str_repeat("\0", (4 - strlen($s) % 4) & 3)); + $v = array_values($v); + if ($w) { + $v[count($v)] = strlen($s); + } + + return $v; + } + + /** + * @param int $n + * @return number + */ + private function int32($n) + { + while ($n >= 2147483648) { + $n -= 4294967296; + } + while ($n <= -2147483649) { + $n += 4294967296; + } + + return (int) $n; + } +} diff --git a/wind/token/IWindSecurityToken.php b/wind/token/IWindSecurityToken.php index 479ea48b..4af03226 100644 --- a/wind/token/IWindSecurityToken.php +++ b/wind/token/IWindSecurityToken.php @@ -1,54 +1,52 @@ - * 1. + * 1. * * * @author Qiong Wu 2011-10-19 * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: IWindSecurityToken.php 3113 2011-11-11 07:28:09Z yishuo $ * @package token */ -interface IWindSecurityToken { +interface IWindSecurityToken +{ + /** + * 获取当前tokenName保存的值,如果获取的值为空则代表token不存在,或者已经失效 + * + * @param string $tokenName + */ + public function getToken($tokenName); - /** - * 获取当前tokenName保存的值,如果获取的值为空则代表token不存在,或者已经失效 - * - * @param string $tokenName - */ - public function getToken($tokenName); + /** + * 根据TokenName删除token值 + * + * @param string $tokenName + */ + public function deleteToken($tokenName); - /** - * 根据TokenName删除token值 - * - * @param string $tokenName - */ - public function deleteToken($tokenName); - - /** - * 保存token - * - * @param string $tokenName token名称,默认名称为_tokenAppName - * @return string 返回token值 - */ - public function saveToken($tokenName = ''); - - /** - * 验证token的有效性 - * - * 验证token的有效性. - * 当token有效时则返回true,同时删除token. - * 当coken无效时则返回false. - * - * @param string $token - * @param string $tokenName token名称,默认名称为_tokenAppName - */ - public function validateToken($token, $tokenName = ''); + /** + * 保存token + * + * @param string $tokenName token名称,默认名称为_tokenAppName + * @return string 返回token值 + */ + public function saveToken($tokenName = ''); + /** + * 验证token的有效性 + * + * 验证token的有效性. + * 当token有效时则返回true,同时删除token. + * 当coken无效时则返回false. + * + * @param string $token + * @param string $tokenName token名称,默认名称为_tokenAppName + */ + public function validateToken($token, $tokenName = ''); } - -?> \ No newline at end of file diff --git a/wind/token/WindSecurityToken.php b/wind/token/WindSecurityToken.php index 5d289fb1..4b947b38 100644 --- a/wind/token/WindSecurityToken.php +++ b/wind/token/WindSecurityToken.php @@ -1,8 +1,9 @@ tokenContainer可以是WindCookie或者WindSeesion类型:
      * 'windToken' => array(
    @@ -10,7 +11,7 @@
      * 'scope' => 'singleton',
      * 'properties' => array(
      * 'tokenContainer' => array('ref' => 'windCookie'))),
    - * 
    + *
      * 'windCookie' => array(
      * 'path' => 'WIND:http.cookie.WindNormalCookie',
      * 'scope' => 'singleton',
    @@ -19,84 +20,93 @@
      * @author Qiong Wu  2011-10-19
      * @copyright ©2003-2103 phpwind.com
      * @license http://www.windframework.com
    - * @version $Id$
    + * @version $Id: WindSecurityToken.php 3533 2012-05-08 08:24:20Z yishuo $
      * @package utility
      */
    -class WindSecurityToken extends WindModule implements IWindSecurityToken {
    -	/**
    -	 * url token
    -	 *
    -	 * @var string
    -	 */
    -	protected $token = null;
    -	/**
    -	 * 令牌容器
    -	 * 
    -	 * 可以通过组件配置方式配置不同的容器类型
    -	 * @var IWindHttpContainer
    -	 */
    -	protected $tokenContainer = null;
    +class WindSecurityToken extends WindModule implements IWindSecurityToken
    +{
    +    /**
    +     * url token
    +     *
    +     * @var string
    +     */
    +    protected $token = null;
    +    /**
    +     * 令牌容器
    +     *
    +     * 可以通过组件配置方式配置不同的容器类型
    +     * @var IWindHttpContainer
    +     */
    +    protected $tokenContainer = null;
     
    -	/* (non-PHPdoc)
    -	 * @see IWindSecurityToken::saveToken($tokenName)
    -	 */
    -	public function saveToken($tokenName = '') {
    -		if ($this->token === null) {
    -			/* @var $tokenContainer IWindHttpContainer */
    -			$tokenContainer = $this->_getTokenContainer();
    -			$tokenName = $this->getTokenName($tokenName);
    -			if ($tokenContainer->isRegistered($tokenName)) {
    -				$_token = $tokenContainer->get($tokenName);
    -			} else {
    -				$_token = WindSecurity::generateGUID();
    -				$tokenContainer->set($tokenName, $_token);
    -			}
    -			$this->token = $_token;
    -		}
    -		return $this->token;
    -	}
    +    /* (non-PHPdoc)
    +     * @see IWindSecurityToken::saveToken($tokenName)
    +     */
    +    public function saveToken($tokenName = '')
    +    {
    +        if ($this->token === null) {
    +            /* @var $tokenContainer IWindHttpContainer */
    +            $tokenContainer = $this->_getTokenContainer();
    +            $tokenName = $this->getTokenName($tokenName);
    +            if ($tokenContainer->isRegistered($tokenName)) {
    +                $_token = $tokenContainer->get($tokenName);
    +            } else {
    +                $_token = WindSecurity::generateGUID();
    +                $tokenContainer->set($tokenName, $_token);
    +            }
    +            $this->token = $_token;
    +        }
     
    -	/* (non-PHPdoc)
    -	 * @see IWindSecurityToken::validateToken()
    -	 */
    -	public function validateToken($token, $tokenName = '') {
    -		/* @var $tokenContainer IWindHttpContainer */
    -		$tokenContainer = $this->_getTokenContainer();
    -		$tokenName = $this->getTokenName($tokenName);
    -		$_token = $tokenContainer->get($tokenName);
    -		return $_token && $_token === $token;
    -	}
    +        return $this->token;
    +    }
     
    -	/* (non-PHPdoc)
    -	 * @see IWindSecurityToken::deleteToken()
    -	 */
    -	public function deleteToken($tokenName) {
    -		/* @var $tokenContainer IWindHttpContainer */
    -		$tokenContainer = $this->_getTokenContainer();
    -		$tokenName = $this->getTokenName($tokenName);
    -		return $tokenContainer->delete($tokenName);
    -	}
    +    /* (non-PHPdoc)
    +     * @see IWindSecurityToken::validateToken()
    +     */
    +    public function validateToken($token, $tokenName = '')
    +    {
    +        /* @var $tokenContainer IWindHttpContainer */
    +        $tokenContainer = $this->_getTokenContainer();
    +        $tokenName = $this->getTokenName($tokenName);
    +        $_token = $tokenContainer->get($tokenName);
     
    -	/* (non-PHPdoc)
    -	 * @see IWindSecurityToken::getToken()
    -	 */
    -	public function getToken($tokenName) {
    -		/* @var $tokenContainer IWindHttpContainer */
    -		$tokenContainer = $this->_getTokenContainer();
    -		$tokenName = $this->getTokenName($tokenName);
    -		return $tokenContainer->get($tokenName);
    -	}
    +        return $_token && $_token === $token;
    +    }
     
    -	/**
    -	 * token名称处理
    -	 * 
    -	 * @param string $tokenName
    -	 * @return string
    -	 */
    -	protected function getTokenName($tokenName) {
    -		$tokenName || $tokenName = Wind::getAppName();
    -		return substr(md5('_token' . $tokenName . '_csrf'), -16);
    -	}
    -}
    +    /* (non-PHPdoc)
    +     * @see IWindSecurityToken::deleteToken()
    +     */
    +    public function deleteToken($tokenName)
    +    {
    +        /* @var $tokenContainer IWindHttpContainer */
    +        $tokenContainer = $this->_getTokenContainer();
    +        $tokenName = $this->getTokenName($tokenName);
    +
    +        return $tokenContainer->delete($tokenName);
    +    }
     
    -?>
    \ No newline at end of file
    +    /* (non-PHPdoc)
    +     * @see IWindSecurityToken::getToken()
    +     */
    +    public function getToken($tokenName)
    +    {
    +        /* @var $tokenContainer IWindHttpContainer */
    +        $tokenContainer = $this->_getTokenContainer();
    +        $tokenName = $this->getTokenName($tokenName);
    +
    +        return $tokenContainer->get($tokenName);
    +    }
    +
    +    /**
    +     * token名称处理
    +     *
    +     * @param  string $tokenName
    +     * @return string
    +     */
    +    protected function getTokenName($tokenName)
    +    {
    +        $tokenName || $tokenName = Wind::getAppName();
    +
    +        return substr(md5('_token'.$tokenName.'_csrf'), -16);
    +    }
    +}
    diff --git a/wind/upload/AbstractWindUpload.php b/wind/upload/AbstractWindUpload.php
    index a8a80097..6041d1ef 100644
    --- a/wind/upload/AbstractWindUpload.php
    +++ b/wind/upload/AbstractWindUpload.php
    @@ -1,273 +1,305 @@
     
      * @copyright ©2003-2103 phpwind.com
      * @license http://www.windframework.com
    - * @version $Id$
    + * @version $Id: AbstractWindUpload.php 3172 2011-11-24 07:57:52Z yishuo $
      * @package upload
      */
    -abstract class AbstractWindUpload {
    -	
    -	/**
    -	 * 是否有错误产生
    -	 * 
    -	 * @var boolean
    -	 */
    -	protected $hasError = false;
    -	
    -	/**
    -	 * 错误信息
    -	 * 
    -	 * @var array
    -	 */
    -	protected $errorInfo = array('type' => array(), 'size' => array(), 'upload' => array());
    -	
    -	/** 
    -	 * 允许的类型
    -	 * 
    -	 * @var array
    -	 */
    -	protected $allowType = array();//允许上传的类型及对应的大小,array(ext=>size);
    -
    -	/**
    -	 * 上传文件
    -	 * 
    -	 * @param string $saveDir 文件保存的目录
    -	 * @param string $preFileName 文件保存的前缀
    -	 * @param array  $allowType  允许的格式array(ext=>size) size单位为b
    -	 * 
    -	 * array(
    -	 *  'jpg' => 1024,
    -	 *  'gif => 1000,
    -	 *  
    -	 * @return array 返回上传成功的文件
    -	 */
    -	public function upload($saveDir, $preFileName = '', $allowType = array()) {
    -		$this->setAllowType($allowType);
    -		$uploaddb = array();
    -		foreach ($_FILES as $key => $value) {
    -			if (is_array($value['name'])) {
    -				$temp = $this->multiUpload($key, $saveDir, $preFileName);
    -				$uploaddb[$key] = isset($uploaddb[$key]) ? array_merge((array)$uploaddb[$key], $temp) : $temp;
    -			} else {
    -				$uploaddb[$key][] = $this->simpleUpload($key, $saveDir, $preFileName);
    -			}
    -		}
    -		return 1 == count($uploaddb) ? array_shift($uploaddb) : $uploaddb;
    -	}
    -	
    -	/**
    -	 * 多文件上传
    -	 * 
    -	 * 多个控件
    -	 * 一个表单中拥有多个上传文件的控件
    -	 * 
    -	 * @param string $key 文件的key
    -	 * @param string $saveDir 文件保存的目录
    -	 * @param string $preFileName 保存文件的前缀默认为空字串
    -	 * @return array 返回上传成功之后的文件信息
    -	 */
    -	private function simpleUpload($key, $saveDir, $preFileName = '') {
    -		return $this->doUp($key, $_FILES[$key], $saveDir, $preFileName);
    -	}
    -	
    -	/**
    -	 * 多文件上传
    -	 * 
    -	 * 多个控件
    -	 * 一个表单中拥有多个上传文件的控件
    -	 * 
    -	 * @param string $key 文件的key
    -	 * @param string $saveDir 文件保存的目录
    -	 * @param string $preFileName 保存文件的前缀默认为空字串
    -	 * @return array 返回上传成功之后的文件信息
    -	 */
    -	private function multiUpload($key, $saveDir, $preFileName = '') {
    -		$uploaddb = array();
    -		$files = $_FILES[$key];
    -		$num = count($files['name']);
    -		for($i = 0; $i < $num; $i ++) {
    -			$one = array();
    -			$one['name'] = $files['name'][$i];
    -			$one['tmp_name'] = $files['tmp_name'][$i];
    -			$one['error'] = $files['error'][$i];
    -			$one['size'] = $files['size'][$i];
    -			$one['type'] = $files['type'][$i];
    -			if (!($upload = $this->doUp($key, $one, $saveDir, $preFileName))) continue;
    -			$uploaddb[] = $upload;
    -		}
    -		return $uploaddb;
    -	}
    -	
    -	/**
    -	 * 执行上传操作
    -	 * 
    -	 * @param string $tmp_name 临时文件
    -	 * @param string $filename 目的文件名
    -	 * @return bool 
    -	 */
    -	abstract protected function postUpload($tmp_name, $filename);
    -	
    -	/**
    -	 * 返回是否含有错误
    -	 * 
    -	 * @return boolean
    -	 */
    -	public function hasError() {
    -		return $this->hasError;
    -	}
    -	
    -	/**
    -	 * 返回错误信息
    -	 * 
    -	 * @param string $errorType 错误类型,可选参数为:
    -	 * 
      - *
    • 'type': 类型出错而不能上传的文件信息,
    • - *
    • 'size': 超过指定大小而上传失败的文件信息
    • - *
    • 'upload': 文件不能上传过程出现错误的文件信息
    • - *
    默认为空,则返回所有上述类型的错误信息 - * @return array - */ - public function getErrorInfo($errorType = '') { - return isset($this->errorInfo[$errorType]) ? $this->errorInfo[$errorType] : $this->errorInfo; - } - - /** - * 设置允许上传的类型 - * - * @param array $allowType 允许上传的格式配置 - * @return void - */ - public function setAllowType($allowType) { - $allowType && $this->allowType = $allowType; - } - - /** - * 检查文件是否允许上传 - * - * @param string $ext 文件的后缀 - * @return bool 如果在允许的范围则返回true,否则返回false - */ - protected function checkAllowType($ext) { - $allowType = array_keys((array)$this->allowType); - return $allowType ? in_array($ext, $allowType) : true; - } - - /** - * 检查上传文件的大小 - * - * @param string $type 文件的类型 - * @param string $uploadSize 上传文件的大小 - * @return bool 如果上传文件超过指定允许上传的大小则返回false,否则返回true - */ - protected function checkAllowSize($type, $uploadSize) { - if ($uploadSize < 0) return false; - if (!$this->allowType || !$this->allowType[$type]) return true; - return $uploadSize < $this->allowType[$type]; - } - - - /** - * 获得文件名字 - * - * @param array $attInfo 上传文件的信息 - * @param string $preFileName 文件的前缀 - * @return string 上传文件的名字 - */ - protected function getFileName($attInfo, $preFileName = '') { - $fileName = mt_rand(1, 10) . time() . substr(md5(time() . $attInfo['attname'] . mt_rand(1, 10)), 10, 15) . '.' . $attInfo['ext']; - return $preFileName ? $preFileName . $fileName : $fileName; - } - - /** - * 获得保存路径 - * - * @param string $fileName 保存的文件名字 - * @param string $saveDir 保存文件的路径 - * @return string 上传后的保存文件的完整路径 - */ - protected function getSavePath($fileName, $saveDir) { - return $saveDir ? rtrim($saveDir, '\\/') . '/' . $fileName : $fileName; - } - - /** - * 判断是否有上传文件 - * - * @param string $tmp_name 临时上传文件 - * @return boolean 如果该文件可以被上传则返回true,否则返回false - */ - protected function isUploadFile($tmp_name) { - if (!$tmp_name || $tmp_name == 'none') { - return false; - } elseif (function_exists('is_uploaded_file') && !is_uploaded_file($tmp_name) && !is_uploaded_file(str_replace('\\\\', '\\', $tmp_name))) { - return false; - } else { - return true; - } - } - - /** - * 初始化上传的文件信息 - * - * @param string $key 上传文件的key - * @param string $value 上传文件的信息 - * @param string $preFileName 上传文件的前缀 - * @param string $saveDir 上传文件保存路径 - * @return array 返回文件上传的信息 - */ - protected function initUploadInfo($key, $value, $preFileName, $saveDir) { - $arr = array('attname' => $key, 'name' => $value['name'], 'size' => $value['size'], 'type' => $value['type'], 'ifthumb' => 0, 'fileuploadurl' => ''); - $arr['ext'] = strtolower(substr(strrchr($arr['name'], '.'), 1)); - $arr['filename'] = $this->getFileName($arr, $preFileName); - $arr['fileuploadurl'] = $this->getSavePath($arr['filename'], $saveDir); - return $arr; - } - - - /** - * 判断是否使图片,如果使图片则返回 - * - * @param string $ext 文件后缀 - * @return boolean 如果该文件允许被上传则返回true,否则返回false - */ - protected function isImage($ext) { - return in_array($ext, array('gif', 'jpg', 'jpeg', 'png', 'bmp', 'swf')); - } - - /** - * 执行上传操作 - * - * @param string $key 上传文件的Key值 - * @param array $value 文件的上传信息 - * @param string $saveDir 上传文件的保存路径 - * @param string $preFileName 上传文件的前缀 - * @return array 上传成功后的文件信息 - */ - protected function doUp($key, $value, $saveDir, $preFileName) { - if (!$this->isUploadFile($value['tmp_name'])) return array(); - $upload = $this->initUploadInfo($key, $value, $preFileName, $saveDir); - - if (empty($upload['ext']) || !$this->checkAllowType($upload['ext'])) { - $this->errorInfo['type'][$key][] = $upload; - $this->hasError = true; - return array(); - } - if (!$this->checkAllowSize($upload['ext'], $upload['size'])) { - $upload['maxSize'] = $this->allowType[$upload['ext']]; - $this->errorInfo['size'][$key][] = $upload; - $this->hasError = true; - return array(); - } - if (!($uploadSize = $this->postUpload($value['tmp_name'], $upload['fileuploadurl']))) { - $this->errorInfo['upload'][$key][] = $upload; - $this->hasError = true; - return array(); - } - $upload['size'] = intval($uploadSize); - return $upload; - } -} \ No newline at end of file +abstract class AbstractWindUpload +{ + /** + * 是否有错误产生 + * + * @var bool + */ + protected $hasError = false; + + /** + * 错误信息 + * + * @var array + */ + protected $errorInfo = array('type' => array(), 'size' => array(), 'upload' => array()); + + /** + * 允许的类型 + * + * @var array + */ + protected $allowType = array(); //允许上传的类型及对应的大小,array(ext=>size); + + /** + * 上传文件 + * + * @param string $saveDir 文件保存的目录 + * @param string $preFileName 文件保存的前缀 + * @param array $allowType 允许的格式array(ext=>size) size单位为b + * + * array( + * 'jpg' => 1024, + * 'gif => 1000, + * + * @return array 返回上传成功的文件 + */ + public function upload($saveDir, $preFileName = '', $allowType = array()) + { + $this->setAllowType($allowType); + $uploaddb = array(); + foreach ($_FILES as $key => $value) { + if (is_array($value['name'])) { + $temp = $this->multiUpload($key, $saveDir, $preFileName); + $uploaddb[$key] = isset($uploaddb[$key]) ? array_merge((array) $uploaddb[$key], $temp) : $temp; + } else { + $uploaddb[$key][] = $this->simpleUpload($key, $saveDir, $preFileName); + } + } + + return 1 == count($uploaddb) ? array_shift($uploaddb) : $uploaddb; + } + + /** + * 多文件上传 + * + * 多个控件 + * 一个表单中拥有多个上传文件的控件 + * + * @param string $key 文件的key + * @param string $saveDir 文件保存的目录 + * @param string $preFileName 保存文件的前缀默认为空字串 + * @return array 返回上传成功之后的文件信息 + */ + private function simpleUpload($key, $saveDir, $preFileName = '') + { + return $this->doUp($key, $_FILES[$key], $saveDir, $preFileName); + } + + /** + * 多文件上传 + * + * 多个控件 + * 一个表单中拥有多个上传文件的控件 + * + * @param string $key 文件的key + * @param string $saveDir 文件保存的目录 + * @param string $preFileName 保存文件的前缀默认为空字串 + * @return array 返回上传成功之后的文件信息 + */ + private function multiUpload($key, $saveDir, $preFileName = '') + { + $uploaddb = array(); + $files = $_FILES[$key]; + $num = count($files['name']); + for ($i = 0; $i < $num; $i ++) { + $one = array(); + $one['name'] = $files['name'][$i]; + $one['tmp_name'] = $files['tmp_name'][$i]; + $one['error'] = $files['error'][$i]; + $one['size'] = $files['size'][$i]; + $one['type'] = $files['type'][$i]; + if (!($upload = $this->doUp($key, $one, $saveDir, $preFileName))) { + continue; + } + $uploaddb[] = $upload; + } + + return $uploaddb; + } + + /** + * 执行上传操作 + * + * @param string $tmp_name 临时文件 + * @param string $filename 目的文件名 + * @return bool + */ + abstract protected function postUpload($tmp_name, $filename); + + /** + * 返回是否含有错误 + * + * @return bool + */ + public function hasError() + { + return $this->hasError; + } + + /** + * 返回错误信息 + * + * @param string $errorType 错误类型,可选参数为: + *
      + *
    • 'type': 类型出错而不能上传的文件信息,
    • + *
    • 'size': 超过指定大小而上传失败的文件信息
    • + *
    • 'upload': 文件不能上传过程出现错误的文件信息
    • + *
    默认为空,则返回所有上述类型的错误信息 + * @return array + */ + public function getErrorInfo($errorType = '') + { + return isset($this->errorInfo[$errorType]) ? $this->errorInfo[$errorType] : $this->errorInfo; + } + + /** + * 设置允许上传的类型 + * + * @param array $allowType 允许上传的格式配置 + */ + public function setAllowType($allowType) + { + $allowType && $this->allowType = $allowType; + } + + /** + * 检查文件是否允许上传 + * + * @param string $ext 文件的后缀 + * @return bool 如果在允许的范围则返回true,否则返回false + */ + protected function checkAllowType($ext) + { + $allowType = array_keys((array) $this->allowType); + + return $allowType ? in_array($ext, $allowType) : true; + } + + /** + * 检查上传文件的大小 + * + * @param string $type 文件的类型 + * @param string $uploadSize 上传文件的大小 + * @return bool 如果上传文件超过指定允许上传的大小则返回false,否则返回true + */ + protected function checkAllowSize($type, $uploadSize) + { + if ($uploadSize < 0) { + return false; + } + if (!$this->allowType || !$this->allowType[$type]) { + return true; + } + + return $uploadSize < $this->allowType[$type]; + } + + + /** + * 获得文件名字 + * + * @param array $attInfo 上传文件的信息 + * @param string $preFileName 文件的前缀 + * @return string 上传文件的名字 + */ + protected function getFileName($attInfo, $preFileName = '') + { + $fileName = mt_rand(1, 10).time().substr(md5(time().$attInfo['attname'].mt_rand(1, 10)), 10, 15).'.'.$attInfo['ext']; + + return $preFileName ? $preFileName.$fileName : $fileName; + } + + /** + * 获得保存路径 + * + * @param string $fileName 保存的文件名字 + * @param string $saveDir 保存文件的路径 + * @return string 上传后的保存文件的完整路径 + */ + protected function getSavePath($fileName, $saveDir) + { + return $saveDir ? rtrim($saveDir, '\\/').'/'.$fileName : $fileName; + } + + /** + * 判断是否有上传文件 + * + * @param string $tmp_name 临时上传文件 + * @return bool 如果该文件可以被上传则返回true,否则返回false + */ + protected function isUploadFile($tmp_name) + { + if (!$tmp_name || $tmp_name == 'none') { + return false; + } elseif (function_exists('is_uploaded_file') && !is_uploaded_file($tmp_name) && !is_uploaded_file(str_replace('\\\\', '\\', $tmp_name))) { + return false; + } else { + return true; + } + } + + /** + * 初始化上传的文件信息 + * + * @param string $key 上传文件的key + * @param string $value 上传文件的信息 + * @param string $preFileName 上传文件的前缀 + * @param string $saveDir 上传文件保存路径 + * @return array 返回文件上传的信息 + */ + protected function initUploadInfo($key, $value, $preFileName, $saveDir) + { + $arr = array('attname' => $key, 'name' => $value['name'], 'size' => $value['size'], 'type' => $value['type'], 'ifthumb' => 0, 'fileuploadurl' => ''); + $arr['ext'] = strtolower(substr(strrchr($arr['name'], '.'), 1)); + $arr['filename'] = $this->getFileName($arr, $preFileName); + $arr['fileuploadurl'] = $this->getSavePath($arr['filename'], $saveDir); + + return $arr; + } + + + /** + * 判断是否使图片,如果使图片则返回 + * + * @param string $ext 文件后缀 + * @return bool 如果该文件允许被上传则返回true,否则返回false + */ + protected function isImage($ext) + { + return in_array($ext, array('gif', 'jpg', 'jpeg', 'png', 'bmp', 'swf')); + } + + /** + * 执行上传操作 + * + * @param string $key 上传文件的Key值 + * @param array $value 文件的上传信息 + * @param string $saveDir 上传文件的保存路径 + * @param string $preFileName 上传文件的前缀 + * @return array 上传成功后的文件信息 + */ + protected function doUp($key, $value, $saveDir, $preFileName) + { + if (!$this->isUploadFile($value['tmp_name'])) { + return array(); + } + $upload = $this->initUploadInfo($key, $value, $preFileName, $saveDir); + + if (empty($upload['ext']) || !$this->checkAllowType($upload['ext'])) { + $this->errorInfo['type'][$key][] = $upload; + $this->hasError = true; + + return array(); + } + if (!$this->checkAllowSize($upload['ext'], $upload['size'])) { + $upload['maxSize'] = $this->allowType[$upload['ext']]; + $this->errorInfo['size'][$key][] = $upload; + $this->hasError = true; + + return array(); + } + if (!($uploadSize = $this->postUpload($value['tmp_name'], $upload['fileuploadurl']))) { + $this->errorInfo['upload'][$key][] = $upload; + $this->hasError = true; + + return array(); + } + $upload['size'] = intval($uploadSize); + + return $upload; + } +} diff --git a/wind/upload/WindFormUpload.php b/wind/upload/WindFormUpload.php index 37159193..3618d739 100644 --- a/wind/upload/WindFormUpload.php +++ b/wind/upload/WindFormUpload.php @@ -1,52 +1,58 @@ * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindFormUpload.php 3228 2011-12-02 06:49:38Z yishuo $ * @package upload */ -class WindFormUpload extends AbstractWindUpload { +class WindFormUpload extends AbstractWindUpload +{ + /** + * 初始化允许用户上传的类型 + * + * @param array $allowType + */ + public function __construct($allowType = array()) + { + $this->setAllowType($allowType); + } + + /* + * (non-PHPdoc) + * @see AbstractWindUpload::postUpload() + */ + protected function postUpload($tmp_name, $filename) + { + if (strpos($filename, '..') !== false || strpos($filename, '.php.') !== false || preg_match('/\.php$/', + $filename)) { + exit('illegal file type!'); + } + WindFolder::mkRecur(dirname($filename)); + if (function_exists('move_uploaded_file') && @move_uploaded_file($tmp_name, $filename)) { + @unlink($tmp_name); + @chmod($filename, 0777); + + return filesize($filename); + } elseif (@copy($tmp_name, $filename)) { + @unlink($tmp_name); + @chmod($filename, 0777); + + return filesize($filename); + } elseif (is_readable($tmp_name)) { + WindFile::write($filename, WindFile::read($tmp_name)); + @unlink($tmp_name); + if (file_exists($filename)) { + @chmod($filename, 0777); - /** - * 初始化允许用户上传的类型 - * - * @param array $allowType - */ - public function __construct($allowType = array()) { - $this->setAllowType($allowType); - } + return filesize($filename); + } + } - /* - * (non-PHPdoc) - * @see AbstractWindUpload::postUpload() - */ - protected function postUpload($tmp_name, $filename) { - if (strpos($filename, '..') !== false || strpos($filename, '.php.') !== false || preg_match('/\.php$/', - $filename)) { - exit('illegal file type!'); - } - WindFolder::mkRecur(dirname($filename)); - if (function_exists("move_uploaded_file") && @move_uploaded_file($tmp_name, $filename)) { - @unlink($tmp_name); - @chmod($filename, 0777); - return filesize($filename); - } elseif (@copy($tmp_name, $filename)) { - @unlink($tmp_name); - @chmod($filename, 0777); - return filesize($filename); - } elseif (is_readable($tmp_name)) { - Wind::import('WIND:utility.WindFile'); - WindFile::write($filename, WindFile::read($tmp_name)); - @unlink($tmp_name); - if (file_exists($filename)) { - @chmod($filename, 0777); - return filesize($filename); - } - } - return false; - } -} \ No newline at end of file + return false; + } +} diff --git a/wind/upload/WindFtpUpload.php b/wind/upload/WindFtpUpload.php index f5e0f17b..e0358465 100644 --- a/wind/upload/WindFtpUpload.php +++ b/wind/upload/WindFtpUpload.php @@ -1,65 +1,79 @@ * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindFtpUpload.php 2973 2011-10-15 19:22:48Z yishuo $ * @package upload */ -class WindFtpUpload extends AbstractWindUpload { +class WindFtpUpload extends AbstractWindUpload +{ + private $config = array(); + + private $ftp = null; + + /** + * 构造函数设置远程ftp链接信息 + * + * @param array $config + */ + public function __construct($config) + { + $this->setConfig($config); + } + + /* (non-PHPdoc) + * @see AbstractWindUpload::postUpload() + */ + protected function postUpload($tmp_name, $filename) + { + $ftp = $this->getFtpConnection(); + if (!($size = $ftp->upload($tmp_name, $filename))) { + return false; + } + @unlink($tmp_name); + + return $size; + } - private $config = array(); + /** + * 设置ftp链接配置文件 + * + * @param array $config ftp链接信息 + * @return bool + */ + public function setConfig($config) + { + if (!is_array($config)) { + return false; + } + $this->config = $config; - private $ftp = null; + return true; + } - /** - * 构造函数设置远程ftp链接信息 - * - * @param array $config - */ - public function __construct($config) { - $this->setConfig($config); - } + /** + * 获得ftp链接对象 + * + * @return AbstractWindFtp + */ + private function getFtpConnection() + { + if (is_object($this->ftp)) { + return $this->ftp; + } + if (function_exists('ftp_connect')) { + $this->ftp = new WindFtp($this->config); - /* (non-PHPdoc) - * @see AbstractWindUpload::postUpload() - */ - protected function postUpload($tmp_name, $filename) { - $ftp = $this->getFtpConnection(); - if (!($size = $ftp->upload($tmp_name, $filename))) return false; - @unlink($tmp_name); - return $size; - } + return $this->ftp; + } - /** - * 设置ftp链接配置文件 - * - * @param array $config ftp链接信息 - * @return bool - */ - public function setConfig($config) { - if (!is_array($config)) return false; - $this->config = $config; - return true; - } + $this->ftp = new WindSocketFtp($this->config); - /** - * 获得ftp链接对象 - * - * @return AbstractWindFtp - */ - private function getFtpConnection() { - if (is_object($this->ftp)) return $this->ftp; - if (function_exists('ftp_connect')) { - Wind::import("WIND:ftp.WindFtp"); - $this->ftp = new WindFtp($this->config); - return $this->ftp; - } - Wind::import("WIND:ftp.WindSocketFtp"); - $this->ftp = new WindSocketFtp($this->config); - return $this->ftp; - } -} \ No newline at end of file + return $this->ftp; + } +} diff --git a/wind/utility/WindArray.php b/wind/utility/WindArray.php index cd386424..f3a5a697 100644 --- a/wind/utility/WindArray.php +++ b/wind/utility/WindArray.php @@ -1,81 +1,87 @@ - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package utility +/** + * 数组工具类 + * + * @author Qiong Wu + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id: WindArray.php 2973 2011-10-15 19:22:48Z yishuo $ + * @package utility */ -class WindArray { +class WindArray +{ + /** + * 按指定key合并两个数组 + * + * @param string key 合并数组的参照值 + * @param array $array1 要合并数组 + * @param array $array2 要合并数组 + * @return array 返回合并的数组 + */ + public static function mergeArrayWithKey($key, array $array1, array $array2) + { + if (!$key || !$array1 || !$array2) { + return array(); + } + $array1 = self::rebuildArrayWithKey($key, $array1); + $array2 = self::rebuildArrayWithKey($key, $array2); + $tmp = array(); + foreach ($array1 as $key => $array) { + if (isset($array2[$key])) { + $tmp[$key] = array_merge($array, $array2[$key]); + unset($array2[$key]); + } else { + $tmp[$key] = $array; + } + } - /** - * 按指定key合并两个数组 - * - * @param string key 合并数组的参照值 - * @param array $array1 要合并数组 - * @param array $array2 要合并数组 - * @return array 返回合并的数组 - */ - public static function mergeArrayWithKey($key, array $array1, array $array2) { - if (!$key || !$array1 || !$array2) { - return array(); - } - $array1 = self::rebuildArrayWithKey($key, $array1); - $array2 = self::rebuildArrayWithKey($key, $array2); - $tmp = array(); - foreach ($array1 as $key => $array) { - if (isset($array2[$key])) { - $tmp[$key] = array_merge($array, $array2[$key]); - unset($array2[$key]); - } else { - $tmp[$key] = $array; - } - } - return array_merge($tmp, (array) $array2); - } + return array_merge($tmp, (array) $array2); + } - /** - * 按指定key合并两个数组 - * - * @param string key 合并数组的参照值 - * @param array $array1 要合并数组 - * @param array $array2 要合并数组 - * @return array 返回合并的数组 - */ - public static function filterArrayWithKey($key, array $array1, array $array2) { - if (!$key || !$array1 || !$array2) { - return array(); - } - $array1 = self::rebuildArrayWithKey($key, $array1); - $array2 = self::rebuildArrayWithKey($key, $array2); - $tmp = array(); - foreach ($array1 as $key => $array) { - if (isset($array2[$key])) { - $tmp[$key] = array_merge($array, $array2[$key]); - } - } - return $tmp; - } + /** + * 按指定key合并两个数组 + * + * @param string key 合并数组的参照值 + * @param array $array1 要合并数组 + * @param array $array2 要合并数组 + * @return array 返回合并的数组 + */ + public static function filterArrayWithKey($key, array $array1, array $array2) + { + if (!$key || !$array1 || !$array2) { + return array(); + } + $array1 = self::rebuildArrayWithKey($key, $array1); + $array2 = self::rebuildArrayWithKey($key, $array2); + $tmp = array(); + foreach ($array1 as $key => $array) { + if (isset($array2[$key])) { + $tmp[$key] = array_merge($array, $array2[$key]); + } + } - /** - * 按指定KEY重新生成数组 - * - * @param string key 重新生成数组的参照值 - * @param array $array 要重新生成的数组 - * @return array 返回重新生成后的数组 - */ - public static function rebuildArrayWithKey($key, array $array) { - if (!$key || !$array) { - return array(); - } - $tmp = array(); - foreach ($array as $_array) { - if (isset($_array[$key])) { - $tmp[$_array[$key]] = $_array; - } - } - return $tmp; - } -} \ No newline at end of file + return $tmp; + } + + /** + * 按指定KEY重新生成数组 + * + * @param string key 重新生成数组的参照值 + * @param array $array 要重新生成的数组 + * @return array 返回重新生成后的数组 + */ + public static function rebuildArrayWithKey($key, array $array) + { + if (!$key || !$array) { + return array(); + } + $tmp = array(); + foreach ($array as $_array) { + if (isset($_array[$key])) { + $tmp[$_array[$key]] = $_array; + } + } + + return $tmp; + } +} diff --git a/wind/utility/WindConvert.php b/wind/utility/WindConvert.php index b56f6a65..6d8a122f 100644 --- a/wind/utility/WindConvert.php +++ b/wind/utility/WindConvert.php @@ -1,9 +1,9 @@ - * 1. utf16be转化为utf8 + * 1. + * utf16be转化为utf8 * 2. utf8转化为utf16be * 3. utf8转化为unicode * 4. unicode转化为utf8 @@ -12,189 +12,209 @@ * @author Qiong Wu 2011-10-19 * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindConvert.php 3829 2012-11-19 11:13:22Z yishuo $ * @package utility */ -class WindConvert { - /** - * 编码转换 - * - * @param string $str 内容字符串 - * @param string $toEncoding 转为新编码 - * @param string $fromEncoding 原编码 - * @param bool $ifMb 是否使用mb函数 - * @return string - */ - public static function convert($str, $toEncoding, $fromEncoding, $ifMb = true) { - if (!strcasecmp($toEncoding, $fromEncoding)) return $str; - switch (gettype($str)) { - case 'string': - if ($ifMb && function_exists('mb_convert_encoding')) - $str = mb_convert_encoding($str, $toEncoding, $fromEncoding); - else { - !$toEncoding && $toEncoding = 'GBK'; - !$fromEncoding && $fromEncoding = 'GBK'; - Wind::getApp()->getWindFactory()->addClassDefinitions('windConverter', - array('path' => 'WIND:convert.WindGeneralConverter', 'scope' => 'singleton')); - /* @var $converter WindGeneralConverter */ - $converter = Wind::getApp()->getComponent('windConverter'); - $str = $converter->convert($str, $fromEncoding, $toEncoding); - } - break; - case 'array': - foreach ($str as $key => $value) { - is_object($value) && $value = get_object_vars($value); - $str[$key] = self::convert($value, $toEncoding, $fromEncoding, $ifMb); - } - break; - default: - break; - } - return $str; - } +class WindConvert +{ + /** + * 编码转换 + * + * @param string $str + * 内容字符串 + * @param string $toEncoding + * 转为新编码 + * @param string $fromEncoding + * 原编码 + * @param bool $ifMb + * 是否使用mb函数 + * @return string + */ + public static function convert($str, $toEncoding, $fromEncoding, $ifMb = true) + { + if (!strcasecmp($toEncoding, $fromEncoding)) { + return $str; + } + switch (gettype($str)) { + case 'string': + if ($ifMb && function_exists('mb_convert_encoding')) { + $str = mb_convert_encoding($str, $toEncoding, $fromEncoding); + } else { + !$toEncoding && $toEncoding = 'GBK'; + !$fromEncoding && $fromEncoding = 'GBK'; + Wind::registeComponent(array('path' => 'WIND:convert.WindGeneralConverter', 'scope' => 'singleton'), + 'windConverter'); - /** - * gbk转为utf8编码 - * - * @param mixed $srcText - */ - public static function gbkToUtf8($srcText) { - return iconv('GBK', 'UTF-8', $srcText); - $this->getTableIndex(); - $tarText = ''; - for ($i = 0; $i < strlen($srcText); $i += 2) { - $h = ord($srcText[$i]); - if ($h > 127 && isset($this->TableIndex[$this->EncodeLang][$h])) { - $l = ord($srcText[$i + 1]); - if (!isset($this->TableEncode[$this->EncodeLang][$h][$l])) { - fseek($this->TableHandle, $l * 2 + $this->TableIndex[$this->EncodeLang][$h]); - $this->TableEncode[$this->EncodeLang][$h][$l] = $this->UNICODEtoUTF8( - hexdec(bin2hex(fread($this->TableHandle, 2)))); - } - $tarText .= $this->TableEncode[$this->EncodeLang][$h][$l]; - } elseif ($h < 128) { - $tarText .= $srcText[$i]; - $i--; - } - } - return $tarText; - } + /* @var $converter WindGeneralConverter */ + $converter = Wind::getComponent('windConverter'); + $str = $converter->convert($str, $fromEncoding, $toEncoding); + } + break; + case 'array': + foreach ($str as $key => $value) { + is_object($value) && $value = get_object_vars($value); + $str[$key] = self::convert($value, $toEncoding, $fromEncoding, $ifMb); + } + break; + default: + break; + } - /** - * utf16be编码转化为utf8编码 - * - * @param string $str - * @return string - */ - public static function utf16beToUTF8(&$str) { - return self::unicodeToUTF8(unpack('n*', $str)); - } + return $str; + } - /** - * utf8编码转为utf16BE - * - * @param string $string - * @param boolean $bom 是否Big-Endian - */ - public static function utf8ToUTF16BE(&$string, $bom = false) { - $out = $bom ? "\xFE\xFF" : ''; - if (function_exists('mb_convert_encoding')) { - return $out . mb_convert_encoding($string, 'UTF-16BE', 'UTF-8'); - } - $uni = self::utf8ToUnicode($string); - foreach ($uni as $cp) { - $out .= pack('n', $cp); - } - return $out; - } + /** + * gbk转为utf8编码 + * + * @param mixed $srcText + */ + public static function gbkToUtf8($srcText) + { + return iconv('GBK', 'UTF-8', $srcText); + $this->getTableIndex(); + $tarText = ''; + for ($i = 0; $i < strlen($srcText); $i += 2) { + $h = ord($srcText[$i]); + if ($h > 127 && isset($this->TableIndex[$this->EncodeLang][$h])) { + $l = ord($srcText[$i + 1]); + if (!isset($this->TableEncode[$this->EncodeLang][$h][$l])) { + fseek($this->TableHandle, $l * 2 + $this->TableIndex[$this->EncodeLang][$h]); + $this->TableEncode[$this->EncodeLang][$h][$l] = $this->UNICODEtoUTF8( + hexdec(bin2hex(fread($this->TableHandle, 2)))); + } + $tarText .= $this->TableEncode[$this->EncodeLang][$h][$l]; + } elseif ($h < 128) { + $tarText .= $srcText[$i]; + $i--; + } + } - /** - * unicode编码转化为utf8编码 - * - * @param string $str - * @return string - */ - public static function unicodeToUTF8(&$str) { - $utf8 = ''; - foreach ($str as $unicode) { - if ($unicode < 128) { - $utf8 .= chr($unicode); - } elseif ($unicode < 2048) { - $utf8 .= chr(192 + (($unicode - ($unicode % 64)) / 64)); - $utf8 .= chr(128 + ($unicode % 64)); - } else { - $utf8 .= chr(224 + (($unicode - ($unicode % 4096)) / 4096)); - $utf8 .= chr(128 + ((($unicode % 4096) - ($unicode % 64)) / 64)); - $utf8 .= chr(128 + ($unicode % 64)); - } - } - return $utf8; - } + return $tarText; + } - /** - * utf8编码转化为unicode - * - * @param string $string - * @return Ambigous - */ - public static function utf8ToUnicode(&$string) { - $unicode = $values = array(); - $lookingFor = 1; - for ($i = 0, $length = strlen($string); $i < $length; $i++) { - $thisValue = ord($string[$i]); - if ($thisValue < 128) { - $unicode[] = $thisValue; - } else { - if (count($values) == 0) { - $lookingFor = ($thisValue < 224) ? 2 : 3; - } - $values[] = $thisValue; - if (count($values) == $lookingFor) { - $unicode[] = ($lookingFor == 3) ? ($values[0] % 16) * 4096 + ($values[1] % 64) * 64 + $values[2] % 64 : ($values[0] % 32) * 64 + $values[1] % 64; - $values = array(); - $lookingFor = 1; - } - } - } - return $unicode; - } + /** + * utf16be编码转化为utf8编码 + * + * @param string $str + * @return string + */ + public static function utf16beToUTF8($str) + { + return self::unicodeToUTF8(unpack('n*', $str)); + } - /** - * 获取输入编码 - * - * @param string $lang - * @return string - */ - private static function _getCharset($lang) { - switch (strtoupper(substr($lang, 0, 2))) { - case 'GB': - $lang = 'GBK'; - break; - case 'UT': - $lang = 'UTF8'; - break; - case 'UN': - $lang = 'UNICODE'; - break; - case 'BI': - $lang = 'BIG5'; - break; - default: - $lang = ''; - } - return $lang; - } + /** + * utf8编码转为utf16BE + * + * @param string $string + * @param bool $bom + * 是否Big-Endian + */ + public static function utf8ToUTF16BE($string, $bom = false) + { + $out = $bom ? "\xFE\xFF" : ''; + if (function_exists('mb_convert_encoding')) { + return $out.mb_convert_encoding($string, 'UTF-16BE', 'UTF-8'); + } + $uni = self::utf8ToUnicode($string); + foreach ($uni as $cp) { + $out .= pack('n', $cp); + } - /** - * iconv 是否开启 - * - * @param 目标编码 $targeLang - * @return boolean - */ - private static function _isIconv($targeLang) { - return function_exists('iconv') && $targeLang != 'BIG5'; - } + return $out; + } -} + /** + * unicode编码转化为utf8编码 + * + * @param string $str + * @return string + */ + public static function unicodeToUTF8($str) + { + $utf8 = ''; + foreach ($str as $unicode) { + if ($unicode < 128) { + $utf8 .= chr($unicode); + } elseif ($unicode < 2048) { + $utf8 .= chr(192 + (($unicode - ($unicode % 64)) / 64)); + $utf8 .= chr(128 + ($unicode % 64)); + } else { + $utf8 .= chr(224 + (($unicode - ($unicode % 4096)) / 4096)); + $utf8 .= chr(128 + ((($unicode % 4096) - ($unicode % 64)) / 64)); + $utf8 .= chr(128 + ($unicode % 64)); + } + } + + return $utf8; + } + + /** + * utf8编码转化为unicode + * + * @param string $string + * @return Ambigous + */ + public static function utf8ToUnicode($string) + { + $unicode = $values = array(); + $lookingFor = 1; + for ($i = 0, $length = strlen($string); $i < $length; $i++) { + $thisValue = ord($string[$i]); + if ($thisValue < 128) { + $unicode[] = $thisValue; + } else { + if (count($values) == 0) { + $lookingFor = ($thisValue < 224) ? 2 : 3; + } + $values[] = $thisValue; + if (count($values) == $lookingFor) { + $unicode[] = ($lookingFor == 3) ? ($values[0] % 16) * 4096 + ($values[1] % 64) * 64 + $values[2] % 64 : ($values[0] % 32) * 64 + $values[1] % 64; + $values = array(); + $lookingFor = 1; + } + } + } + + return $unicode; + } -?> \ No newline at end of file + /** + * 获取输入编码 + * + * @param string $lang + * @return string + */ + private static function _getCharset($lang) + { + switch (strtoupper(substr($lang, 0, 2))) { + case 'GB': + $lang = 'GBK'; + break; + case 'UT': + $lang = 'UTF8'; + break; + case 'UN': + $lang = 'UNICODE'; + break; + case 'BI': + $lang = 'BIG5'; + break; + default: + $lang = ''; + } + + return $lang; + } + + /** + * iconv 是否开启 + * + * @param 目标编码 $targeLang + * @return bool + */ + private static function _isIconv($targeLang) + { + return function_exists('iconv') && $targeLang != 'BIG5'; + } +} diff --git a/wind/utility/WindCookie.php b/wind/utility/WindCookie.php index 33e3194c..9d9e3c60 100644 --- a/wind/utility/WindCookie.php +++ b/wind/utility/WindCookie.php @@ -1,90 +1,102 @@ - - * Wind::import('WIND:http.cookie.WindCookie'); + * * WindCookie::set('name', 'test'); *
    - * + * * @author Qian Su * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindCookie.php 3760 2012-10-11 08:02:25Z yishuo $ * @package http * @subpackage cookie - */ -class WindCookie { - - /** - * 设置cookie - * - * @param string $name cookie名称 - * @param string $value cookie值,默认为null - * @param boolean $encode 是否使用 MIME base64 对数据进行编码,默认是false即不进行编码 - * @param string|int $expires 过期时间,默认为null即会话cookie,随着会话结束将会销毁 - * @param string $path cookie保存的路径,默认为null即采用默认 - * @param string $domain cookie所属域,默认为null即不设置 - * @param boolean $secure 是否安全连接,默认为false即不采用安全链接 - * @param boolean $httponly 是否可通过客户端脚本访问,默认为false即客户端脚本可以访问cookie - * @return boolean 设置成功返回true,失败返回false - */ - public static function set($name, $value = null, $encode = false, $expires = null, $path = null, $domain = null, $secure = false, $httponly = false) { - if (empty($name)) return false; - $encode && $value && $value = base64_encode(serialize($value)); - $path = $path ? $path : '/'; - setcookie($name, $value, $expires, $path, $domain, $secure, $httponly); - return true; - } - - /** - * 根据cookie的名字删除cookie - * - * @param string $name cookie名称 - * @return boolean 删除成功返回true - */ - public static function delete($name) { - if (self::exist($name)) { - self::set($name, ''); - unset($_COOKIE[$name]); - } - return true; - } - - /** - * 取得指定名称的cookie值 - * - * @param string $name cookie名称 - * @param boolean $dencode 是否对cookie值进行过解码,默认为false即不用解码 - * @return mixed 获取成功将返回保存的cookie值,获取失败将返回false - */ - public static function get($name, $dencode = false) { - if (self::exist($name)) { - $value = $_COOKIE[$name]; - $value && $dencode && $value = unserialize(base64_decode($value)); - return $value ? $value : $value; - } - return false; - } - - /** - * 移除全部cookie - * - * @return boolean 移除成功将返回true - */ - public static function deleteAll() { - $_COOKIE = array(); - return true; - } - - /** - * 判断cookie是否存在 - * - * @param string $name cookie名称 - * @return boolean 如果不存在则返回false,否则返回true - */ - public static function exist($name) { - return isset($_COOKIE[$name]); - } -} \ No newline at end of file + */ +class WindCookie +{ + /** + * 设置cookie + * + * @param string $name cookie名称 + * @param string $value cookie值,默认为null + * @param bool $encode 是否使用 MIME base64 对数据进行编码,默认是false即不进行编码 + * @param string|int $expires 过期时间,默认为null即会话cookie,随着会话结束将会销毁 + * @param string $path cookie保存的路径,默认为null即采用默认 + * @param string $domain cookie所属域,默认为null即不设置 + * @param bool $secure 是否安全连接,默认为false即不采用安全链接 + * @param bool $httponly 是否可通过客户端脚本访问,默认为false即客户端脚本可以访问cookie + * @return bool 设置成功返回true,失败返回false + */ + public static function set($name, $value = null, $encode = false, $expires = null, $path = null, $domain = null, $secure = false, $httponly = false) + { + if (empty($name)) { + return false; + } + $encode && $value && $value = base64_encode($value); + $path = $path ? $path : '/'; + setcookie($name, $value, $expires, $path, $domain, $secure, $httponly); + + return true; + } + + /** + * 根据cookie的名字删除cookie + * + * @param string $name cookie名称 + * @return bool 删除成功返回true + */ + public static function delete($name) + { + if (self::exist($name)) { + self::set($name, ''); + unset($_COOKIE[$name]); + } + + return true; + } + + /** + * 取得指定名称的cookie值 + * + * @param string $name cookie名称 + * @param bool $dencode 是否对cookie值进行过解码,默认为false即不用解码 + * @return mixed 获取成功将返回保存的cookie值,获取失败将返回false + */ + public static function get($name, $dencode = false) + { + if (self::exist($name)) { + $value = $_COOKIE[$name]; + $value && $dencode && $value = base64_decode($value); + + return $value ? $value : $value; + } + + return false; + } + + /** + * 移除全部cookie + * + * @return bool 移除成功将返回true + */ + public static function deleteAll() + { + $_COOKIE = array(); + + return true; + } + + /** + * 判断cookie是否存在 + * + * @param string $name cookie名称 + * @return bool 如果不存在则返回false,否则返回true + */ + public static function exist($name) + { + return isset($_COOKIE[$name]); + } +} diff --git a/wind/utility/WindDate.php b/wind/utility/WindDate.php index eed51bd9..dafacc61 100644 --- a/wind/utility/WindDate.php +++ b/wind/utility/WindDate.php @@ -1,332 +1,362 @@ - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package utility +/** + * 日期的换算与计算 + * + * @author Qian Su + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id: WindDate.php 2973 2011-10-15 19:22:48Z yishuo $ + * @package utility */ -class WindDate { +class WindDate +{ + /** + * 获取时区 + * + * @return string + */ + public static function getTimeZone() + { + return function_exists('date_default_timezone_get') ? date_default_timezone_get() : date('e'); + } - /** - * 获取时区 - * - * @return string - */ - public static function getTimeZone() { - return function_exists('date_default_timezone_get') ? date_default_timezone_get() : date('e'); - } + /** + * 设置时区 + * + * @param string $timezone 时区 + */ + public static function setTimezone($timezone) + { + function_exists('date_default_timezone_set') ? date_default_timezone_set($timezone) : putenv("TZ={$timezone}"); + } - /** - * 设置时区 - * - * @param string $timezone 时区 - */ - public static function setTimezone($timezone) { - function_exists('date_default_timezone_set') ? date_default_timezone_set($timezone) : putenv("TZ={$timezone}"); - } + /** + * 格式化输出 + * + * @param string $format 目标格式,默认为null则以Y-m-d H:i:s格式输出 + * @param int $dateTime unix时间戳,默认为null则用当前时间 + * @return string + */ + public static function format($format = null, $dateTime = null) + { + return date($format ? $format : 'Y-m-d H:i:s', self::getTimeStamp($dateTime)); + } - /** - * 格式化输出 - * - * @param string $format 目标格式,默认为null则以Y-m-d H:i:s格式输出 - * @param int $dateTime unix时间戳,默认为null则用当前时间 - * @return string - */ - public static function format($format = null, $dateTime = null) { - return date($format ? $format : 'Y-m-d H:i:s', self::getTimeStamp($dateTime)); - } + /** + * 获取日期的某部分 + * + * @param string $interval 字符串表达式 ,时间间隔类型 + * @param mixed $dateTime 表示日期的文字,默认为null则用当前时间 + * @return string 返回日期的某部分 + */ + public static function datePart($interval, $dateTime = null) + { + return date($interval, self::getTimeStamp($dateTime)); + } - /** - * 获取日期的某部分 - * - * @param string $interval 字符串表达式 ,时间间隔类型 - * @param mixed $dateTime 表示日期的文字,默认为null则用当前时间 - * @return string 返回日期的某部分 - */ - public static function datePart($interval, $dateTime = null) { - return date($interval, self::getTimeStamp($dateTime)); - } + /** + * 获取两个日期的差 + * + * @param string $interval 返回两个日期差的间隔类型 + * @param mixed $startDateTime 开始日期 + * @param mixed $endDateTime 结束日期 + * @return string + */ + public static function dateDiff($interval, $startDateTime, $endDateTime) + { + $diff = self::getTimeStamp($endDateTime) - self::getTimeStamp($startDateTime); + $retval = 0; + switch ($interval) { + case 'y': + $retval = bcdiv($diff, (60 * 60 * 24 * 365)); + break; + case 'm': + $retval = bcdiv($diff, (60 * 60 * 24 * 30)); + break; + case 'w': + $retval = bcdiv($diff, (60 * 60 * 24 * 7)); + break; + case 'd': + $retval = bcdiv($diff, (60 * 60 * 24)); + break; + case 'h': + $retval = bcdiv($diff, (60 * 60)); + break; + case 'n': + $retval = bcdiv($diff, 60); + break; + case 's': + default: + $retval = $diff; + break; + } - /** - * 获取两个日期的差 - * - * @param string $interval 返回两个日期差的间隔类型 - * @param mixed $startDateTime 开始日期 - * @param mixed $endDateTime 结束日期 - * @return string - */ - public static function dateDiff($interval, $startDateTime, $endDateTime) { - $diff = self::getTimeStamp($endDateTime) - self::getTimeStamp($startDateTime); - $retval = 0; - switch ($interval) { - case "y": - $retval = bcdiv($diff, (60 * 60 * 24 * 365)); - break; - case "m": - $retval = bcdiv($diff, (60 * 60 * 24 * 30)); - break; - case "w": - $retval = bcdiv($diff, (60 * 60 * 24 * 7)); - break; - case "d": - $retval = bcdiv($diff, (60 * 60 * 24)); - break; - case "h": - $retval = bcdiv($diff, (60 * 60)); - break; - case "n": - $retval = bcdiv($diff, 60); - break; - case "s": - default: - $retval = $diff; - break; - } - return $retval; - } + return $retval; + } - /** - * 返回向指定日期追加指定间隔类型的一段时间间隔后的日期 - * - * @param string $interval 字符串表达式,是所要加上去的时间间隔类型。 - * @param int $value 数值表达式,是要加上的时间间隔的数目。其数值可以为正数(得到未来的日期),也可以为负数(得到过去的日期)。 - * @param string $dateTime 表示日期的文字,这一日期还加上了时间间隔。 - * @param mixed $format 格式化输出 - * @return string 返回追加后的时间 - */ - public static function dateAdd($interval, $value, $dateTime, $format = null) { - $date = getdate(self::getTimeStamp($dateTime)); - switch ($interval) { - case "y": - $date["year"] += $value; - break; - case "q": - $date["mon"] += ($value * 3); - break; - case "m": - $date["mon"] += $value; - break; - case "w": - $date["mday"] += ($value * 7); - break; - case "d": - $date["mday"] += $value; - break; - case "h": - $date["hours"] += $value; - break; - case "n": - $date["minutes"] += $value; - break; - case "s": - default: - $date["seconds"] += $value; - break; - } - return self::format($format, mktime($date["hours"], $date["minutes"], $date["seconds"], $date["mon"], $date["mday"], $date["year"])); - } + /** + * 返回向指定日期追加指定间隔类型的一段时间间隔后的日期 + * + * @param string $interval 字符串表达式,是所要加上去的时间间隔类型。 + * @param int $value 数值表达式,是要加上的时间间隔的数目。其数值可以为正数(得到未来的日期),也可以为负数(得到过去的日期)。 + * @param string $dateTime 表示日期的文字,这一日期还加上了时间间隔。 + * @param mixed $format 格式化输出 + * @return string 返回追加后的时间 + */ + public static function dateAdd($interval, $value, $dateTime, $format = null) + { + $date = getdate(self::getTimeStamp($dateTime)); + switch ($interval) { + case 'y': + $date['year'] += $value; + break; + case 'q': + $date['mon'] += ($value * 3); + break; + case 'm': + $date['mon'] += $value; + break; + case 'w': + $date['mday'] += ($value * 7); + break; + case 'd': + $date['mday'] += $value; + break; + case 'h': + $date['hours'] += $value; + break; + case 'n': + $date['minutes'] += $value; + break; + case 's': + default: + $date['seconds'] += $value; + break; + } - /** - * 得到一年中每个月真实的天数 - * - * @param string $year 需要获得的月份天数的年份 - * @return array 每月的天数组成的数组 - */ - public static function getRealDaysInMonthsOfYear($year) { - $months = array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31); - if (self::isLeapYear($year)) { - $months[1] = 29; - } - return $months; - } + return self::format($format, mktime($date['hours'], $date['minutes'], $date['seconds'], $date['mon'], $date['mday'], $date['year'])); + } - /** - * 获取该月的天数 - * - * @param int $month 月份 - * @param int $year 年份 - * @return int - */ - public static function getDaysInMonth($month, $year) { - if (1 > $month || 12 < $month) { - return 0; - } - if (!($daysInmonths = self::getRealDaysInMonthsOfYear($year))) { - return 0; - } - return $daysInmonths[$month - 1]; - } + /** + * 得到一年中每个月真实的天数 + * + * @param string $year 需要获得的月份天数的年份 + * @return array 每月的天数组成的数组 + */ + public static function getRealDaysInMonthsOfYear($year) + { + $months = array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31); + if (self::isLeapYear($year)) { + $months[1] = 29; + } - /** - * 获取该年的天数 - * - * @return int - */ - public static function getDaysInYear($year) { - return self::isLeapYear($year) ? 366 : 365; - } + return $months; + } - /** - * 取得RFC格式的日期与时间 - * - * @param string $data 需要获取的时间,默认为null则获取当前时间 - * @return string - */ - public static function getRFCDate($date = null) { - $time = $date ? is_int($date) ? $date : strtotime($date) : time(); - $tz = date('Z', $time); - $tzs = ($tz < 0) ? '-' : '+'; - $tz = abs($tz); - $tz = (int) ($tz / 3600) * 100 + ($tz % 3600) / 60; - return sprintf("%s %s%04d", date('D, j M Y H:i:s', $time), $tzs, $tz); - } + /** + * 获取该月的天数 + * + * @param int $month 月份 + * @param int $year 年份 + * @return int + */ + public static function getDaysInMonth($month, $year) + { + if (1 > $month || 12 < $month) { + return 0; + } + if (!($daysInmonths = self::getRealDaysInMonthsOfYear($year))) { + return 0; + } - /** - * 取得中国日期时间 - * - * @param int $time 需要使用的时间戳,默认为null则获取当前时间戳 - * @return string - */ - public static function getChinaDate($time = null) { - list($y, $m, $d, $w, $h, $_h, $i) = explode(' ', date('Y n j w G g i', $time ? $time : time())); - return sprintf('%s年%s月%s日(%s) %s%s:%s', $y, $m, $d, self::getChinaWeek($w), self::getPeriodOfTime($h), $_h, $i); - } + return $daysInmonths[$month - 1]; + } - /** - * 取得中国的星期 - * - * @param int $week 处国人的星期,是一个数值,默认为null则使用当前时间 - * @return string - */ - public static function getChinaWeek($week = null) { - $week = $week ? $week : (int) date('w', time()); - $weekMap = array("星期天", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"); - return $weekMap[$week]; - } + /** + * 获取该年的天数 + * + * @return int + */ + public static function getDaysInYear($year) + { + return self::isLeapYear($year) ? 366 : 365; + } - /** - * 取得一天中的时段 - * - * @param int $hour 小时,默认为null则获取当前时间 - * @return string - */ - public static function getPeriodOfTime($hour = null) { - $hour = $hour ? $hour : (int) date('G', time()); - $period = ''; - if (0 <= $hour && 6 > $hour) { - $period = '凌晨'; - } elseif (6 <= $hour && 8 > $hour) { - $period = '早上'; - } elseif (8 <= $hour && 11 > $hour) { - $period = '上午'; - } elseif (11 <= $hour && 13 > $hour) { - $period = '中午'; - } elseif (13 <= $hour && 15 > $hour) { - $period = '响午'; - } elseif (15 <= $hour && 18 > $hour) { - $period = '下午'; - } elseif (18 <= $hour && 20 > $hour) { - $period = '傍晚'; - } elseif (20 <= $hour && 22 > $hour) { - $period = '晚上'; - } elseif (22 <= $hour && 23 >= $hour) { - $period = '深夜'; - } - return $period; - } + /** + * 取得RFC格式的日期与时间 + * + * @param string $data 需要获取的时间,默认为null则获取当前时间 + * @return string + */ + public static function getRFCDate($date = null) + { + $time = $date ? is_int($date) ? $date : strtotime($date) : time(); + $tz = date('Z', $time); + $tzs = ($tz < 0) ? '-' : '+'; + $tz = abs($tz); + $tz = (int) ($tz / 3600) * 100 + ($tz % 3600) / 60; - /** - * 获取UTC日期格式 - * - * @param mixed $dateTime 时间,默认为null则获取当前时间 - * @return string - */ - public static function getUTCDate($dateTime = null) { - $oldTimezone = self::getTimezone(); - if ('UTC' !== strtoupper($oldTimezone)) { - self::setTimezone('UTC'); - } - $date = date('D, d M y H:i:s e', self::getTimeStamp($dateTime)); - if ('UTC' !== strtoupper($oldTimezone)) { - self::setTimezone($oldTimezone); - } - return $date; - } + return sprintf('%s %s%04d', date('D, j M Y H:i:s', $time), $tzs, $tz); + } - /** - * 获取微秒数 - * - * @param string $mircrotime 微妙时间,默认为null则获取当前时间 - * @param string $get_as_float 获取微妙时间是否以浮点数返回,默认为false即不以浮点数方式返回 - * @return int - */ - public static function getMicroTime($mircrotime = null, $get_as_float = false) { - return array_sum(explode(' ', $mircrotime ? $mircrotime : microtime($get_as_float))); - } + /** + * 取得中国日期时间 + * + * @param int $time 需要使用的时间戳,默认为null则获取当前时间戳 + * @return string + */ + public static function getChinaDate($time = null) + { + list($y, $m, $d, $w, $h, $_h, $i) = explode(' ', date('Y n j w G g i', $time ? $time : time())); - /** - * 判断是否是闰年 - * - * @param int $year 需要判断的年份 - * @return boolean 如果是润年则返回true - */ - public static function isLeapYear($year) { - return (0 == $year % 4 && 0 != $year % 100 || 0 == $year % 400); - } + return sprintf('%s年%s月%s日(%s) %s%s:%s', $y, $m, $d, self::getChinaWeek($w), self::getPeriodOfTime($h), $_h, $i); + } - /** - * 获得时间戳 - * - * @param int $dateTime 时间戳,默认为null则以当前时间戳返回 - * @return int - */ - public static function getTimeStamp($dateTime = null) { - return $dateTime ? is_int($dateTime) ? $dateTime : strtotime($dateTime) : time(); - } + /** + * 取得中国的星期 + * + * @param int $week 处国人的星期,是一个数值,默认为null则使用当前时间 + * @return string + */ + public static function getChinaWeek($week = null) + { + $week = $week ? $week : (int) date('w', time()); + $weekMap = array('星期天', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'); - /** - * 比较两个时间返回离现在最近的一个时间 - * - * @param int $time 当前时间戳 - * @param int $timestamp 比较的时间戳,默认为null则获取当前时间戳 - * @param string $format 格式化当前时间戳,默认为null则转化为格式Y-m-d H:i:s - * @param array $type 要返回的时间类型,默认为 1则只返回Y-m-d否则返回Y-m-d m-d H:i - * @return array - */ - public static function getLastDate($time, $timestamp = null, $format = null, $type = 1) { - $timelang = array('second' => '秒前', 'yesterday' => '昨天', 'hour' => '小时前', 'minute' => '分钟前', 'qiantian' => '前天'); - $timestamp = $timestamp ? $timestamp : time(); - $compareTime = strtotime(self::format('Y-m-d', $timestamp)); - $currentTime = strtotime(self::format('Y-m-d', $time)); - $decrease = $timestamp - $time; - $result = self::format($format, $time); - if (0 >= $decrease) { - return 1 == $type ? array(self::format('Y-m-d', $time), $result) : array( - self::format('Y-m-d m-d H:i', $time), $result); - } - if ($currentTime == $compareTime) { - if (1 == $type) { - if (60 >= $decrease) { - return array($decrease . $timelang['second'], $result); - } - return 3600 >= $decrease ? array(ceil($decrease / 60) . $timelang['minute'], $result) : array( - ceil($decrease / 3600) . $timelang['hour'], $result); - } - return array(self::format('H:i', $time), $result); - } elseif ($currentTime == $compareTime - 86400) { - return 1 == $type ? array($timelang['yesterday'] . " " . self::format('H:i', $time), $result) : array( - self::format('m-d H:i', $time), $result); - } elseif ($currentTime == $compareTime - 172800) { - return 1 == $type ? array($timelang['qiantian'] . " " . self::format('H:i', $time), $result) : array( - self::format('m-d H:i', $time), $result); - } elseif (strtotime(self::format('Y', $time)) == strtotime(self::format('Y', $timestamp))) { - return 1 == $type ? array(self::format('m-d', $time), $result) : array(self::format('m-d H:i', $time), - $result); - } - return 1 == $type ? array(self::format('Y-m-d', $time), $result) : array(self::format('Y-m-d m-d H:i', $time), - $result); - } -} \ No newline at end of file + return $weekMap[$week]; + } + + /** + * 取得一天中的时段 + * + * @param int $hour 小时,默认为null则获取当前时间 + * @return string + */ + public static function getPeriodOfTime($hour = null) + { + $hour = $hour ? $hour : (int) date('G', time()); + $period = ''; + if (0 <= $hour && 6 > $hour) { + $period = '凌晨'; + } elseif (6 <= $hour && 8 > $hour) { + $period = '早上'; + } elseif (8 <= $hour && 11 > $hour) { + $period = '上午'; + } elseif (11 <= $hour && 13 > $hour) { + $period = '中午'; + } elseif (13 <= $hour && 15 > $hour) { + $period = '响午'; + } elseif (15 <= $hour && 18 > $hour) { + $period = '下午'; + } elseif (18 <= $hour && 20 > $hour) { + $period = '傍晚'; + } elseif (20 <= $hour && 22 > $hour) { + $period = '晚上'; + } elseif (22 <= $hour && 23 >= $hour) { + $period = '深夜'; + } + + return $period; + } + + /** + * 获取UTC日期格式 + * + * @param mixed $dateTime 时间,默认为null则获取当前时间 + * @return string + */ + public static function getUTCDate($dateTime = null) + { + $oldTimezone = self::getTimezone(); + if ('UTC' !== strtoupper($oldTimezone)) { + self::setTimezone('UTC'); + } + $date = date('D, d M y H:i:s e', self::getTimeStamp($dateTime)); + if ('UTC' !== strtoupper($oldTimezone)) { + self::setTimezone($oldTimezone); + } + + return $date; + } + + /** + * 获取微秒数 + * + * @param string $mircrotime 微妙时间,默认为null则获取当前时间 + * @param string $get_as_float 获取微妙时间是否以浮点数返回,默认为false即不以浮点数方式返回 + * @return int + */ + public static function getMicroTime($mircrotime = null, $get_as_float = false) + { + return array_sum(explode(' ', $mircrotime ? $mircrotime : microtime($get_as_float))); + } + + /** + * 判断是否是闰年 + * + * @param int $year 需要判断的年份 + * @return bool 如果是润年则返回true + */ + public static function isLeapYear($year) + { + return 0 == $year % 4 && 0 != $year % 100 || 0 == $year % 400; + } + + /** + * 获得时间戳 + * + * @param int $dateTime 时间戳,默认为null则以当前时间戳返回 + * @return int + */ + public static function getTimeStamp($dateTime = null) + { + return $dateTime ? is_int($dateTime) ? $dateTime : strtotime($dateTime) : time(); + } + + /** + * 比较两个时间返回离现在最近的一个时间 + * + * @param int $time 当前时间戳 + * @param int $timestamp 比较的时间戳,默认为null则获取当前时间戳 + * @param string $format 格式化当前时间戳,默认为null则转化为格式Y-m-d H:i:s + * @param array $type 要返回的时间类型,默认为 1则只返回Y-m-d否则返回Y-m-d m-d H:i + * @return array + */ + public static function getLastDate($time, $timestamp = null, $format = null, $type = 1) + { + $timelang = array('second' => '秒前', 'yesterday' => '昨天', 'hour' => '小时前', 'minute' => '分钟前', 'qiantian' => '前天'); + $timestamp = $timestamp ? $timestamp : time(); + $compareTime = strtotime(self::format('Y-m-d', $timestamp)); + $currentTime = strtotime(self::format('Y-m-d', $time)); + $decrease = $timestamp - $time; + $result = self::format($format, $time); + if (0 >= $decrease) { + return 1 == $type ? array(self::format('Y-m-d', $time), $result) : array( + self::format('Y-m-d m-d H:i', $time), $result, ); + } + if ($currentTime == $compareTime) { + if (1 == $type) { + if (60 >= $decrease) { + return array($decrease.$timelang['second'], $result); + } + + return 3600 >= $decrease ? array(ceil($decrease / 60).$timelang['minute'], $result) : array( + ceil($decrease / 3600).$timelang['hour'], $result, ); + } + + return array(self::format('H:i', $time), $result); + } elseif ($currentTime == $compareTime - 86400) { + return 1 == $type ? array($timelang['yesterday'].' '.self::format('H:i', $time), $result) : array( + self::format('m-d H:i', $time), $result, ); + } elseif ($currentTime == $compareTime - 172800) { + return 1 == $type ? array($timelang['qiantian'].' '.self::format('H:i', $time), $result) : array( + self::format('m-d H:i', $time), $result, ); + } elseif (strtotime(self::format('Y', $time)) == strtotime(self::format('Y', $timestamp))) { + return 1 == $type ? array(self::format('m-d', $time), $result) : array(self::format('m-d H:i', $time), + $result, ); + } + + return 1 == $type ? array(self::format('Y-m-d', $time), $result) : array(self::format('Y-m-d m-d H:i', $time), + $result, ); + } +} diff --git a/wind/utility/WindFile.php b/wind/utility/WindFile.php index d04d1e85..66f0e317 100644 --- a/wind/utility/WindFile.php +++ b/wind/utility/WindFile.php @@ -1,150 +1,172 @@ * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindFile.php 3298 2012-01-06 12:48:26Z yishuo $ * @package utility */ -class WindFile { - /** - * 以读的方式打开文件,具有较强的平台移植性 - * - * @var string - */ - const READ = 'rb'; - /** - * 以读写的方式打开文件,具有较强的平台移植性 - * - * @var string - */ - const READWRITE = 'rb+'; - /** - * 以写的方式打开文件,具有较强的平台移植性 - * - * @var string - */ - const WRITE = 'wb'; - /** - * 以读写的方式打开文件,具有较强的平台移植性 - * - * @var string - */ - const WRITEREAD = 'wb+'; - /** - * 以追加写入方式打开文件,具有较强的平台移植性 - * - * @var string - */ - const APPEND_WRITE = 'ab'; - /** - * 以追加读写入方式打开文件,具有较强的平台移植性 - * - * @var string - */ - const APPEND_WRITEREAD = 'ab+'; - - /** - * 删除文件 - * - * @param string $filename 文件名称 - * @return boolean - */ - public static function del($filename) { - return @unlink($filename); - } +class WindFile +{ + /** + * 以读的方式打开文件,具有较强的平台移植性 + * + * @var string + */ + const READ = 'rb'; + /** + * 以读写的方式打开文件,具有较强的平台移植性 + * + * @var string + */ + const READWRITE = 'rb+'; + /** + * 以写的方式打开文件,具有较强的平台移植性 + * + * @var string + */ + const WRITE = 'wb'; + /** + * 以读写的方式打开文件,具有较强的平台移植性 + * + * @var string + */ + const WRITEREAD = 'wb+'; + /** + * 以追加写入方式打开文件,具有较强的平台移植性 + * + * @var string + */ + const APPEND_WRITE = 'ab'; + /** + * 以追加读写入方式打开文件,具有较强的平台移植性 + * + * @var string + */ + const APPEND_WRITEREAD = 'ab+'; + + /** + * 删除文件 + * + * @param string $filename 文件名称 + * @return bool + */ + public static function del($filename) + { + return @unlink($filename); + } + + /** + * 保存文件 + * + * @param string $fileName 保存的文件名 + * @param mixed $data 保存的数据 + * @param bool $isBuildReturn 是否组装保存的数据是return $params的格式,如果没有则以变量声明的方式保存,默认为true则以return的方式保存 + * @param string $method 打开文件方式,默认为rb+的形式 + * @param bool $ifLock 是否对文件加锁,默认为true即加锁 + */ + public static function savePhpData($fileName, $data, $isBuildReturn = true, $method = self::READWRITE, $ifLock = true) + { + $temp = " $value) { + if (!preg_match('/^\w+$/', $key)) { + continue; + } + $temp .= '$'.$key.' = '.WindString::varToString($value).";\r\n"; + } + $temp .= "\r\n?>"; + } else { + ($isBuildReturn) && $temp .= ' return '; + $temp .= WindString::varToString($data).";\r\n?>"; + } + + return self::write($fileName, $temp, $method, $ifLock); + } + + /** + * 写文件 + * + * @param string $fileName 文件绝对路径 + * @param string $data 数据 + * @param string $method 读写模式,默认模式为rb+ + * @param bool $ifLock 是否锁文件,默认为true即加锁 + * @param bool $ifCheckPath 是否检查文件名中的“..”,默认为true即检查 + * @param bool $ifChmod 是否将文件属性改为可读写,默认为true + * @return int 返回写入的字节数 + */ + public static function write($fileName, $data, $method = self::READWRITE, $ifLock = true, $ifCheckPath = true, $ifChmod = true) + { + touch($fileName); + if (!$handle = fopen($fileName, $method)) { + return false; + } + $ifLock && flock($handle, LOCK_EX); + $writeCheck = fwrite($handle, $data); + $method == self::READWRITE && ftruncate($handle, strlen($data)); + fclose($handle); + $ifChmod && chmod($fileName, 0777); + + return $writeCheck; + } - /** - * 保存文件 - * - * @param string $fileName 保存的文件名 - * @param mixed $data 保存的数据 - * @param boolean $isBuildReturn 是否组装保存的数据是return $params的格式,如果没有则以变量声明的方式保存,默认为true则以return的方式保存 - * @param string $method 打开文件方式,默认为rb+的形式 - * @param boolean $ifLock 是否对文件加锁,默认为true即加锁 - */ - public static function savePhpData($fileName, $data, $isBuildReturn = true, $method = self::READWRITE, $ifLock = true) { - $temp = " $value) { - if (!preg_match('/^\w+$/', $key)) continue; - $temp .= "\$" . $key . " = " . WindString::varToString($value) . ";\r\n"; - } - $temp .= "\r\n?>"; - } else { - ($isBuildReturn) && $temp .= " return "; - $temp .= WindString::varToString($data) . ";\r\n?>"; - } - return self::write($fileName, $temp, $method, $ifLock); - } + /** + * 读取文件 + * + * @param string $fileName 文件绝对路径 + * @param string $method 读取模式默认模式为rb + * @return string 从文件中读取的数据 + */ + public static function read($fileName, $method = self::READ) + { + $data = ''; + if (!$handle = fopen($fileName, $method)) { + return false; + } + while (!feof($handle)) { + $data .= fgets($handle, 4096); + } + fclose($handle); - /** - * 写文件 - * - * @param string $fileName 文件绝对路径 - * @param string $data 数据 - * @param string $method 读写模式,默认模式为rb+ - * @param bool $ifLock 是否锁文件,默认为true即加锁 - * @param bool $ifCheckPath 是否检查文件名中的“..”,默认为true即检查 - * @param bool $ifChmod 是否将文件属性改为可读写,默认为true - * @return int 返回写入的字节数 - */ - public static function write($fileName, $data, $method = self::READWRITE, $ifLock = true, $ifCheckPath = true, $ifChmod = true) { - touch($fileName); - if (!$handle = fopen($fileName, $method)) return false; - $ifLock && flock($handle, LOCK_EX); - $writeCheck = fwrite($handle, $data); - $method == self::READWRITE && ftruncate($handle, strlen($data)); - fclose($handle); - $ifChmod && chmod($fileName, 0777); - return $writeCheck; - } + return $data; + } - /** - * 读取文件 - * - * @param string $fileName 文件绝对路径 - * @param string $method 读取模式默认模式为rb - * @return string 从文件中读取的数据 - */ - public static function read($fileName, $method = self::READ) { - $data = ''; - if (!$handle = fopen($fileName, $method)) return false; - while (!feof($handle)) - $data .= fgets($handle, 4096); - fclose($handle); - return $data; - } + /** + * @param string $fileName + * @return bool + */ + public static function isFile($fileName) + { + return $fileName ? is_file($fileName) : false; + } - /** - * @param string $fileName - * @return boolean - */ - public static function isFile($fileName) { - return $fileName ? is_file($fileName) : false; - } + /** + * 取得文件信息 + * + * @param string $fileName 文件名字 + * @return array 文件信息 + */ + public static function getInfo($fileName) + { + return self::isFile($fileName) ? stat($fileName) : array(); + } - /** - * 取得文件信息 - * - * @param string $fileName 文件名字 - * @return array 文件信息 - */ - public static function getInfo($fileName) { - return self::isFile($fileName) ? stat($fileName) : array(); - } + /** + * 取得文件后缀 + * + * @param string $filename 文件名称 + * @return string + */ + public static function getSuffix($filename) + { + if (false === ($rpos = strrpos($filename, '.'))) { + return ''; + } - /** - * 取得文件后缀 - * - * @param string $filename 文件名称 - * @return string - */ - public static function getSuffix($filename) { - if (false === ($rpos = strrpos($filename, '.'))) return ''; - return substr($filename, $rpos + 1); - } -} \ No newline at end of file + return substr($filename, $rpos + 1); + } +} diff --git a/wind/utility/WindFolder.php b/wind/utility/WindFolder.php index 9e6d6113..9f1643b7 100644 --- a/wind/utility/WindFolder.php +++ b/wind/utility/WindFolder.php @@ -1,139 +1,179 @@ 2011-12-2 * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindFolder.php 3772 2012-10-19 08:58:57Z yishuo $ * @package utility */ -class WindFolder { - const READ_ALL = '0'; - const READ_FILE = '1'; - const READ_DIR = '2'; +class WindFolder +{ + const READ_ALL = '0'; + const READ_FILE = '1'; + const READ_DIR = '2'; - /** - * 获取文件列表 - * - * @param string $dir - * @param boolean $mode 只读取文件列表,不包含文件夹 - * @return array - */ - public static function read($dir, $mode = self::READ_ALL) { - if (!$handle = @opendir($dir)) return array(); - $files = array(); - while (false !== ($file = @readdir($handle))) { - if ('.' === $file || '..' === $file) continue; - if ($mode === self::READ_DIR) { - if (self::isDir($dir . '/' . $file)) $files[] = $file; - } elseif ($mode === self::READ_FILE) { - if (WindFile::isFile($dir . '/' . $file)) $files[] = $file; - } else - $files[] = $file; - } - @closedir($handle); - return $files; - } + /** + * 获取文件列表 + * + * @param string $dir + * @param bool $mode 只读取文件列表,不包含文件夹 + * @return array + */ + public static function read($dir, $mode = self::READ_ALL) + { + if (!$handle = @opendir($dir)) { + return array(); + } + $files = array(); + while (false !== ($file = @readdir($handle))) { + if ('.' === $file || '..' === $file) { + continue; + } + if ($mode === self::READ_DIR) { + if (self::isDir($dir.'/'.$file)) { + $files[] = $file; + } + } elseif ($mode === self::READ_FILE) { + if (WindFile::isFile($dir.'/'.$file)) { + $files[] = $file; + } + } else { + $files[] = $file; + } + } + @closedir($handle); - /** - * 删除目录 - * - * @param string $dir - * @param boolean $f 是否强制删除 - * @return boolean - */ - public static function rm($dir, $f = false) { - return $f ? self::clearRecur($dir, true) : @rmdir($dir); - } + return $files; + } - /** - * 删除指定目录下的文件 - * - * @param string $dir 目录 - * @param boolean $delFolder 是否删除目录 - * @return boolean - */ - public static function clear($dir, $delFolder = false) { - if (!self::isDir($dir)) return false; - if (!$handle = @opendir($dir)) return false; - while (false !== ($file = readdir($handle))) { - if ('.' === $file[0] || '..' === $file[0]) continue; - $filename = $dir . '/' . $file; - if (WindFile::isFile($filename)) WindFile::del($filename); - } - $delFolder && @rmdir($dir); - @closedir($handle); - return true; - } + /** + * 删除目录 + * + * @param string $dir + * @param bool $f 是否强制删除 + * @return bool + */ + public static function rm($dir, $f = false) + { + return $f ? self::clearRecur($dir, true) : @rmdir($dir); + } - /** - * 递归的删除目录 - * - * @param string $dir 目录 - * @param Boolean $delFolder 是否删除目录 - */ - public static function clearRecur($dir, $delFolder = false) { - if (!self::isDir($dir)) return false; - if (!$handle = @opendir($dir)) return false; - while (false !== ($file = readdir($handle))) { - if ('.' === $file || '..' === $file) continue; - $_path = $dir . '/' . $file; - if (self::isDir($_path)) { - self::clearRecur($_path, $delFolder); - } elseif (WindFile::isFile($_path)) - WindFile::del($_path); - } - $delFolder && @rmdir($dir); - @closedir($handle); - return true; - } + /** + * 删除指定目录下的文件 + * + * @param string $dir 目录 + * @param bool $delFolder 是否删除目录 + * @return bool + */ + public static function clear($dir, $delFolder = false) + { + if (!self::isDir($dir)) { + return false; + } + if (!$handle = @opendir($dir)) { + return false; + } + while (false !== ($file = readdir($handle))) { + if ('.' === $file[0] || '..' === $file[0]) { + continue; + } + $filename = $dir.'/'.$file; + if (WindFile::isFile($filename)) { + WindFile::del($filename); + } + } + @closedir($handle); + $delFolder && @rmdir($dir); - /** - * 判断输入是否为目录 - * - * @param string $dir - * @return boolean - */ - public static function isDir($dir) { - return $dir ? is_dir($dir) : false; - } + return true; + } - /** - * 取得目录信息 - * - * @param string $dir 目录路径 - * @return array - */ - public static function getInfo($dir) { - return self::isDir($dir) ? stat($dir) : array(); - } + /** + * 递归的删除目录 + * + * @param string $dir 目录 + * @param Boolean $delFolder 是否删除目录 + */ + public static function clearRecur($dir, $delFolder = false) + { + if (!self::isDir($dir)) { + return false; + } + if (!$handle = @opendir($dir)) { + return false; + } + while (false !== ($file = readdir($handle))) { + if ('.' === $file || '..' === $file) { + continue; + } + $_path = $dir.'/'.$file; + if (self::isDir($_path)) { + self::clearRecur($_path, $delFolder); + } elseif (WindFile::isFile($_path)) { + WindFile::del($_path); + } + } + @closedir($handle); + $delFolder && @rmdir($dir); - /** - * 创建目录 - * - * @param string $path 目录路径 - * @param int $permissions 权限 - * @return boolean - */ - public static function mk($path, $permissions = 0777) { - return @mkdir($path, $permissions); - } + return true; + } - /** - * 递归的创建目录 - * - * @param string $path 目录路径 - * @param int $permissions 权限 - * @return boolean - */ - public static function mkRecur($path, $permissions = 0777) { - if (is_dir($path)) return true; - $_path = dirname($path); - if ($_path !== $path) self::mkRecur($_path, $permissions); - return self::mk($path, $permissions); - } -} + /** + * 判断输入是否为目录 + * + * @param string $dir + * @return bool + */ + public static function isDir($dir) + { + return $dir ? is_dir($dir) : false; + } + + /** + * 取得目录信息 + * + * @param string $dir 目录路径 + * @return array + */ + public static function getInfo($dir) + { + return self::isDir($dir) ? stat($dir) : array(); + } -?> \ No newline at end of file + /** + * 创建目录 + * + * @param string $path 目录路径 + * @param int $permissions 权限 + * @return bool + */ + public static function mk($path, $permissions = 0777) + { + return @mkdir($path, $permissions); + } + + /** + * 递归的创建目录 + * + * @param string $path 目录路径 + * @param int $permissions 权限 + * @return bool + */ + public static function mkRecur($path, $permissions = 0777) + { + if (is_dir($path)) { + return true; + } + $_path = dirname($path); + if ($_path !== $path) { + self::mkRecur($_path, $permissions); + } + + return self::mk($path, $permissions); + } +} diff --git a/wind/utility/WindGeneralDate.php b/wind/utility/WindGeneralDate.php index 2dc80f3a..77a50d97 100644 --- a/wind/utility/WindGeneralDate.php +++ b/wind/utility/WindGeneralDate.php @@ -1,302 +1,325 @@ - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package utility +/** + * 是将日期转化为一个对象去操作 + * + * @author Qian Su + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id: WindGeneralDate.php 2973 2011-10-15 19:22:48Z yishuo $ + * @package utility */ -class WindGeneralDate { +class WindGeneralDate +{ + /** + * 填充展示 + * + * @var int + */ + const FILL = 0; - /** - * 填充展示 - * - * @var int - */ - const FILL = 0; + /** + * 数字展示 + * + * @var int + */ + const DIGIT = 1; - /** - * 数字展示 - * - * @var int - */ - const DIGIT = 1; + /** + * 文本展示 + * + * @var int + */ + const TEXT = 2; - /** - * 文本展示 - * - * @var int - */ - const TEXT = 2; + /** + * 默认格式化 + * + * @var string + */ + const DEFAULT_FORMAT = 'Y-m-d H:i:s'; - /** - * 默认格式化 - * - * @var string - */ - const DEFAULT_FORMAT = 'Y-m-d H:i:s'; + /** + * unix时间戳 + * + * @var int + */ + private $time = 0; - /** - * unix时间戳 - * - * @var int - */ - private $time = 0; + /** + * 根据输入的日期格式转化为时间戳进行属性time初始化 + * + * mktime函数,在只有输入一个年份的时候,就会默认转化为上一年的最后一天,输入一个月份并且缺省输入day的时候, + * 会转化为上个月的最后一天。所以这种情况需要注意。 + * 如果该构造函数没有参数传入的时候,得到的日期不是期望的当前日期,而是上两年的11月的30日 + * + * 如果月份为空:如果年份为空,则取当前月份;否则取1 + * 如果日期为空:如果年份为空,则取当前日期,否则取1 + * 如果小时为空:如果年份为空,则取当前小时 + * 如果分为空:如果年份为空,则取当前分 + * 如果秒为空:如果年份为空,则取当前秒 + * 如果年份为空:取当前年份 + * + * @param int $year 年,默认为null,获取当前年 + * @param int $month 月,默认为null获取当前月 + * @param int $day 日,默认为null获取当前日期 + * @param int $hours 小时,默认为null获取当前小时 + * @param int $minutes 分,默认为null获取当前分钟 + * @param int $second 秒,默认为null获取当前秒 + */ + public function __construct($year = null, $month = null, $day = null, $hours = null, $minutes = null, $second = null) + { + $time = time(); + !$month && ((!$year) ? $month = date('m', $time) : $month = 1); + !$day && ((!$year) ? $day = date('d', $time) : $day = 1); + !$hours && !$year && $hours = date('H', $time); + !$minutes && !$year && $minutes = date('i', $time); + !$second && !$year && $second = date('s', $time); + !$year && $year = date('Y', $time); + $this->time = mktime($hours, $minutes, $second, $month, $day, $year); + } - /** - * 根据输入的日期格式转化为时间戳进行属性time初始化 - * - * mktime函数,在只有输入一个年份的时候,就会默认转化为上一年的最后一天,输入一个月份并且缺省输入day的时候, - * 会转化为上个月的最后一天。所以这种情况需要注意。 - * 如果该构造函数没有参数传入的时候,得到的日期不是期望的当前日期,而是上两年的11月的30日 - * - * 如果月份为空:如果年份为空,则取当前月份;否则取1 - * 如果日期为空:如果年份为空,则取当前日期,否则取1 - * 如果小时为空:如果年份为空,则取当前小时 - * 如果分为空:如果年份为空,则取当前分 - * 如果秒为空:如果年份为空,则取当前秒 - * 如果年份为空:取当前年份 - * - * @param int $year 年,默认为null,获取当前年 - * @param int $month 月,默认为null获取当前月 - * @param int $day 日,默认为null获取当前日期 - * @param int $hours 小时,默认为null获取当前小时 - * @param int $minutes 分,默认为null获取当前分钟 - * @param int $second 秒,默认为null获取当前秒 - * @return void - */ - public function __construct($year = null, $month = null, $day = null, $hours = null, $minutes = null, $second = null) { - $time = time(); - !$month && ((!$year) ? $month = date('m', $time) : $month = 1); - !$day && ((!$year) ? $day = date('d', $time) : $day = 1); - !$hours && !$year && $hours = date('H', $time); - !$minutes && !$year && $minutes = date('i', $time); - !$second && !$year && $second = date('s', $time); - !$year && $year = date('Y', $time); - $this->time = mktime($hours, $minutes, $second, $month, $day, $year); - } + /** + * 获取当前时间所在月的天数 + * + * @return string + */ + public function getDaysInMonth() + { + return date('t', $this->time); + } - /** - * 获取当前时间所在月的天数 - * - * @return string - */ - public function getDaysInMonth() { - return date('t', $this->time); - } + /** + * 获取当前时间所在年的天数 + * + * @return int 如果是闰年返回366否则返回365 + */ + public function getDaysInYear() + { + return $this->isLeapYear() ? 366 : 365; + } - /** - * 获取当前时间所在年的天数 - * - * @return int 如果是闰年返回366否则返回365 - */ - public function getDaysInYear() { - return $this->isLeapYear() ? 366 : 365; - } + /** + * 所表示当前日期是该年中的第几天。 + * + * @return int 返回时该年中的第几天 + */ + public function getDayOfYear() + { + return date('z', $this->time) + 1; + } - /** - * 所表示当前日期是该年中的第几天。 - * - * @return int 返回时该年中的第几天 - */ - public function getDayOfYear() { - return date('z', $this->time) + 1; - } + /** + * 表示当前日期为该月中的第几天。 + * + * @return int + */ + public function getDayOfMonth() + { + return date('j', $this->time); + } - /** - * 表示当前日期为该月中的第几天。 - * - * @return int - */ - public function getDayOfMonth() { - return date('j', $this->time); - } + /** + * 表示当前日期是该星期中的第几天。 + * + * @return int + */ + public function getDayOfWeek() + { + return date('w', $this->time) + 1; + } - /** - * 表示当前日期是该星期中的第几天。 - * - * @return int - */ - public function getDayOfWeek() { - return date('w', $this->time) + 1; - } + /** + * 判断当前日期所在年的第几周 + * + * @return int + */ + public function getWeekOfYear() + { + return date('W', $this->time); + } - /** - * 判断当前日期所在年的第几周 - * - * @return int - */ - public function getWeekOfYear() { - return date('W', $this->time); - } + /** + * 获取当前日期的年份 + * + * @param bool $format 是否返回四位格式的年份或是两位格式的年份,默认为true则以Y返回四位数 + * @return string + */ + public function getYear($format = true) + { + return date($format ? 'Y' : 'y', $this->time); + } - /** - * 获取当前日期的年份 - * - * @param boolean $format 是否返回四位格式的年份或是两位格式的年份,默认为true则以Y返回四位数 - * @return string - */ - public function getYear($format = true) { - return date($format ? 'Y' : 'y', $this->time); - } + /** + * 获当前日期的取月份 + * + * @param int $display 显示类型,默认为0,则显示两位的月份 + * @return string + */ + public function getMonth($display = self::FILL) + { + if (self::FILL == $display) { + return date('m', $this->time); + } elseif (self::DIGIT == $display) { + return date('n', $this->time); + } elseif (self::TEXT == $display) { + return date('M', $this->time); + } - /** - * 获当前日期的取月份 - * - * @param int $display 显示类型,默认为0,则显示两位的月份 - * @return string - */ - public function getMonth($display = self::FILL) { - if (self::FILL == $display) { - return date('m', $this->time); - } elseif (self::DIGIT == $display) { - return date('n', $this->time); - } elseif (self::TEXT == $display) { - return date('M', $this->time); - } - return date('n', $this->time); - } + return date('n', $this->time); + } - /** - * 获取当前日期的天数 - * - * @param string $display 显示类型,默认为0,显示两位的日期 - * @return string - */ - public function getDay($display = self::FILL) { - if (self::FILL == $display) { - return date('d', $this->time); - } elseif (self::DIGIT == $display) { - return date('j', $this->time); - } elseif (self::TEXT == $display) { - return date('jS', $this->time); - } - return date('j', $this->time); - } + /** + * 获取当前日期的天数 + * + * @param string $display 显示类型,默认为0,显示两位的日期 + * @return string + */ + public function getDay($display = self::FILL) + { + if (self::FILL == $display) { + return date('d', $this->time); + } elseif (self::DIGIT == $display) { + return date('j', $this->time); + } elseif (self::TEXT == $display) { + return date('jS', $this->time); + } - /** - * 获取当前日期的星期 - * - * @param string $display 显示类型,默认为0,返回数字表示的星期中的第几天 - * @return string - */ - public function getWeek($display = self::FILL) { - if (self::FILL == $display || self::DIGIT == $display) { - return date('w', $this->time); - } elseif (self::TEXT == $display) { - return date('D', $this->time); - } - return date('N', $this->time); - } + return date('j', $this->time); + } - /** - * 获取当前日期的12小时制时间 - * - * @param string $display 显示类型,默认为0,显示两位的小时 - * @return string - */ - public function get12Hours($display = self::FILL) { - if (self::FILL == $display) { - return date('h', $this->time); - } elseif (self::DIGIT == $display) { - return date('g', $this->time); - ; - } - return date('h', $this->time); - } + /** + * 获取当前日期的星期 + * + * @param string $display 显示类型,默认为0,返回数字表示的星期中的第几天 + * @return string + */ + public function getWeek($display = self::FILL) + { + if (self::FILL == $display || self::DIGIT == $display) { + return date('w', $this->time); + } elseif (self::TEXT == $display) { + return date('D', $this->time); + } - /** - * 获取当前日期的24小时制时间 - * - * @param string $display 显示类型,默认为0,显示两位的小时 - * @return string - */ - public function get24Hours($display = self::FILL) { - if (self::FILL == $display) { - return date('H', $this->time); - } elseif (self::DIGIT == $display) { - return date('G', $this->time); - ; - } - return date('H', $this->time); - } + return date('N', $this->time); + } - /** - * 获取当前日期的分钟 - * - * @return string - */ - public function getMinutes() { - return date('i', $this->time); - } + /** + * 获取当前日期的12小时制时间 + * + * @param string $display 显示类型,默认为0,显示两位的小时 + * @return string + */ + public function get12Hours($display = self::FILL) + { + if (self::FILL == $display) { + return date('h', $this->time); + } elseif (self::DIGIT == $display) { + return date('g', $this->time); + } - /** - * 获取当前日期的秒数 - * - * @return string - */ - public function getSeconds() { - return date('s', $this->time); - } + return date('h', $this->time); + } - /** - * 获取当前日期的本地时区 - * - * @return string - */ - public function getLocalTimeZone() { - return date('T', $this->time); - } + /** + * 获取当前日期的24小时制时间 + * + * @param string $display 显示类型,默认为0,显示两位的小时 + * @return string + */ + public function get24Hours($display = self::FILL) + { + if (self::FILL == $display) { + return date('H', $this->time); + } elseif (self::DIGIT == $display) { + return date('G', $this->time); + } - /** - * 重新设置当前日期与时间 - * - * @param string $time 时间戳 - * @return void - */ - public function setTime($time) { - if (is_int($time) || (is_string($time) && ($time = strtotime($time)))) { - $this->time = $time; - } - } + return date('H', $this->time); + } - /** - * 取得当前日期时间对象 - * - * @return WindGeneralDate - */ - public function getNow() { - $date = getdate($this->time); - return new self($date["year"], $date["mon"], $date["mday"], $date["hours"], $date["minutes"], $date["seconds"]); - } + /** + * 获取当前日期的分钟 + * + * @return string + */ + public function getMinutes() + { + return date('i', $this->time); + } - /** - * 对象转化为字符串,魔术方法 - * - * @return string - */ - public function __toString() { - return $this->toString(); - } + /** + * 获取当前日期的秒数 + * + * @return string + */ + public function getSeconds() + { + return date('s', $this->time); + } - /** - * 格式化时间输出 - * - * @param string $format 需要输出的格式,默认为null,则采用格式Y-m-d H:i:s - * @return string - */ - public function toString($format = null) { - return date($format ? $format : self::DEFAULT_FORMAT, $this->time); - } + /** + * 获取当前日期的本地时区 + * + * @return string + */ + public function getLocalTimeZone() + { + return date('T', $this->time); + } - /** - * 判断是否是闰年 - * - * @return int 返回1或是0 - */ - public function isLeapYear() { - return date('L', $this->time); - } -} \ No newline at end of file + /** + * 重新设置当前日期与时间 + * + * @param string $time 时间戳 + */ + public function setTime($time) + { + if (is_int($time) || (is_string($time) && ($time = strtotime($time)))) { + $this->time = $time; + } + } + + /** + * 取得当前日期时间对象 + * + * @return WindGeneralDate + */ + public function getNow() + { + $date = getdate($this->time); + + return new self($date['year'], $date['mon'], $date['mday'], $date['hours'], $date['minutes'], $date['seconds']); + } + + /** + * 对象转化为字符串,魔术方法 + * + * @return string + */ + public function __toString() + { + return $this->toString(); + } + + /** + * 格式化时间输出 + * + * @param string $format 需要输出的格式,默认为null,则采用格式Y-m-d H:i:s + * @return string + */ + public function toString($format = null) + { + return date($format ? $format : self::DEFAULT_FORMAT, $this->time); + } + + /** + * 判断是否是闰年 + * + * @return int 返回1或是0 + */ + public function isLeapYear() + { + return date('L', $this->time); + } +} diff --git a/wind/utility/WindImage.php b/wind/utility/WindImage.php index 696545b9..0f32ec5e 100644 --- a/wind/utility/WindImage.php +++ b/wind/utility/WindImage.php @@ -1,318 +1,372 @@ * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindImage.php 2973 2011-10-15 19:22:48Z yishuo $ * @package utility */ -class WindImage { - - /** - * 生成略缩图 - * - * @param string $srcFile 源图片 - * @param string $dstFile 略缩图保存位置 - * @param int $dstW 略缩图宽度 - * @param string $dstH 略缩图高度 - * @param string $isProportion 略缩图是否等比略缩,默认为false - * @return array|boolean - */ - public static function makeThumb($srcFile, $dstFile, $dstW, $dstH, $isProportion = FALSE) { - if (false === ($minitemp = self::getThumbInfo($srcFile, $dstW, $dstH, $isProportion))) return false; - list($imagecreate, $imagecopyre) = self::getImgcreate($minitemp['type']); - if (!$imagecreate) return false; - $imgwidth = $minitemp['width']; - $imgheight = $minitemp['height']; - - $srcX = $srcY = $dstX = $dstY =0; - if (!$isProportion) { - $dsDivision = $imgheight / $imgwidth; - $fixDivision = $dstH / $dstW; - if ($dsDivision > $fixDivision) { - $tmp = $imgwidth * $fixDivision; - $srcY = round(($imgheight - $tmp) / 2); - $imgheight = $tmp; - } else { - $tmp = $imgheight / $fixDivision; - $srcX = round(($imgwidth - $tmp) / 2); - $imgwidth = $tmp; - } - } - $thumb = $imagecreate($minitemp['dstW'], $minitemp['dstH']); - - if (function_exists('imagecolorallocate') && function_exists('imagecolortransparent')) { - $black = imagecolorallocate($thumb, 0, 0, 0); - imagecolortransparent($thumb, $black); - } - $imagecopyre($thumb, $minitemp['source'], $dstX, $dstY, $srcX, $srcY, $minitemp['dstW'], $minitemp['dstH'], $imgwidth, $imgheight); - self::makeImg($minitemp['type'], $thumb, $dstFile); - imagedestroy($thumb); - return array('width' => $minitemp['dstW'], 'height' => $minitemp['dstH'], 'type' => $minitemp['type']); - } +class WindImage +{ + /** + * 生成略缩图 + * + * @param string $srcFile 源图片 + * @param string $dstFile 略缩图保存位置 + * @param int $dstW 略缩图宽度 + * @param string $dstH 略缩图高度 + * @param string $isProportion 略缩图是否等比略缩,默认为false + * @return array|bool + */ + public static function makeThumb($srcFile, $dstFile, $dstW, $dstH, $isProportion = false) + { + if (false === ($minitemp = self::getThumbInfo($srcFile, $dstW, $dstH, $isProportion))) { + return false; + } + list($imagecreate, $imagecopyre) = self::getImgcreate($minitemp['type']); + if (!$imagecreate) { + return false; + } + $imgwidth = $minitemp['width']; + $imgheight = $minitemp['height']; + + $srcX = $srcY = $dstX = $dstY = 0; + if (!$isProportion) { + $dsDivision = $imgheight / $imgwidth; + $fixDivision = $dstH / $dstW; + if ($dsDivision > $fixDivision) { + $tmp = $imgwidth * $fixDivision; + $srcY = round(($imgheight - $tmp) / 2); + $imgheight = $tmp; + } else { + $tmp = $imgheight / $fixDivision; + $srcX = round(($imgwidth - $tmp) / 2); + $imgwidth = $tmp; + } + } + $thumb = $imagecreate($minitemp['dstW'], $minitemp['dstH']); + + if (function_exists('imagecolorallocate') && function_exists('imagecolortransparent')) { + $black = imagecolorallocate($thumb, 0, 0, 0); + imagecolortransparent($thumb, $black); + } + $imagecopyre($thumb, $minitemp['source'], $dstX, $dstY, $srcX, $srcY, $minitemp['dstW'], $minitemp['dstH'], $imgwidth, $imgheight); + self::makeImg($minitemp['type'], $thumb, $dstFile); + imagedestroy($thumb); + + return array('width' => $minitemp['dstW'], 'height' => $minitemp['dstH'], 'type' => $minitemp['type']); + } + + /** + * 给图片制作水印 + * + * 水印的位置可以为: + * + * array(0 => '随机位置', 1 => '顶部居左', 2 => '顶部居中', 3 => '顶部居右', 4 => '底部居左', 5 => '底部居中', 6 => '底部居右', 7 => '中心位置') + * + * + * @param string $source 图片的源文件 + * @param int|array $waterPos 水印的位置,可以选择从0-7或是制定开始位置x,y,默认为0,随机位置 + * @param string $waterImg 作为水印的图片,默认为空 + * @param string $waterText 作为水印的文字,默认为空 + * @param array $attribute 文字水印的属性,只对文字水印有效 + * + * array(0 => '字体文件',1 => '系统编码', 2 => '字体颜色', 3 => '字体大小') + * + * @param string $waterPct 水印透明度,从0到100,0完全透明,100完全不透明,默认为50 + * @param string $waterQuality 图片质量--jpeg,默认为75 + * @param string $dstsrc 目标文件位置,默认为null即不保存 + * @return bool + */ + public static function makeWatermark($source, $waterPos = 0, $waterImg = '', $waterText = '', $attribute = '', $waterPct = 50, $waterQuality = 75, $dstsrc = null) + { + $sourcedb = $waterdb = array(); + if (false === ($sourcedb = self::getImgInfo($source))) { + return false; + } + if (!$waterImg && !$waterText) { + return false; + } + imagealphablending($sourcedb['source'], true); + if ($waterImg) { + $waterdb = self::getImgInfo($waterImg); + list($wX, $wY) = self::getWaterPos($waterPos, $sourcedb, $waterdb, 1); + if ($waterdb['type'] == 'png') { + $tmp = imagecreatetruecolor($sourcedb['width'], $sourcedb['height']); + imagecopy($tmp, $sourcedb['source'], 0, 0, 0, 0, $sourcedb['width'], $sourcedb['height']); + imagecopy($tmp, $waterdb['source'], $wX, $wY, 0, 0, $waterdb['width'], $waterdb['height']); + $sourcedb['source'] = $tmp; + } else { + imagecopymerge($sourcedb['source'], $waterdb['source'], $wX, $wY, 0, 0, $waterdb['width'], $waterdb['height'], $waterPct); + } + } elseif ($waterText) { + list($fontFile, $charset, $color, $waterFont) = self::checkAttribute($attribute); + empty($waterFont) && $waterFont = 12; + $temp = imagettfbbox($waterFont, 0, $fontFile, $waterText); //取得使用 TrueType 字体的文本的范围 + $waterdb['width'] = $temp[2] - $temp[6]; + $waterdb['height'] = $temp[3] - $temp[7]; + unset($temp); + list($wX, $wY) = self::getWaterPos($waterPos, $sourcedb, $waterdb, 2); + if (strlen($color) != 7) { + return false; + } + $R = hexdec(substr($color, 1, 2)); + $G = hexdec(substr($color, 3, 2)); + $B = hexdec(substr($color, 5)); + self::changeCharset($charset) && $waterText = mb_convert_encoding($waterText, 'UTF-8', $charset); + imagettftext($sourcedb['source'], $waterFont, 0, $wX, $wY, imagecolorallocate($sourcedb['source'], $R, $G, $B), $fontFile, $waterText); + } + $dstsrc && $source = $dstsrc; + self::makeImg($sourcedb['type'], $sourcedb['source'], $source, $waterQuality); + isset($waterdb['source']) && imagedestroy($waterdb['source']); + imagedestroy($sourcedb['source']); + + return true; + } + + /** + * 文字水印的属性设置过滤 + * + * 返回为: + * + * array(0 => '字体文件',1 => '系统编码', 2 => '字体颜色', 3 => '字体大小') + * + * @param array $attribute 设置的属性 + * @return array + */ + private static function checkAttribute($attribute) + { + $attribute = is_string($attribute) ? array($attribute) : $attribute; + if (!isset($attribute[1]) || !$attribute[1]) { + $attribute[1] = 'UTF-8'; + } + if (!isset($attribute[2]) || !$attribute[2]) { + $attribute[2] = '#FF0000'; + } + if (!isset($attribute[3]) || !$attribute[3]) { + $attribute[3] = 12; + } + + return $attribute; + } + + /** + * 判断是否需要转编码 + * + * 判断依据为,编码格式为utf-8 + * + * @param string $charset 编码方式 + * @return bool + */ + private static function changeCharset($charset) + { + $charset = strtolower($charset); + + return !in_array($charset, array('utf8', 'utf-8')); + } + + /** + * 获得打水印的位置 + * + * 如果传入的是数组,则两个元素分别为水印的宽度x和高度y + * + * @param int|array $pos 获得水印的位置 + * @param array $sourcedb 原图片的信息 + * @param array $waterdb 水印图片的信息 + * @param int $markType 水印类型,1为图片水印,2为文字水印 + * @return array + */ + private static function getWaterPos($waterPos, $sourcedb, $waterdb, $markType) + { + if (is_array($waterPos)) { + return $waterPos; + } + $wX = $wY = 0; + switch (intval($waterPos)) { + case 0: + $wX = rand(0, ($sourcedb['width'] - $waterdb['width'])); + $wY = $markType == 1 ? rand(0, ($sourcedb['height'] - $waterdb['height'])) : rand($waterdb['height'], $sourcedb['height']); + break; + case 1: + $wX = 5; + $wY = $markType == 1 ? 5 : $waterdb['height']; + break; + case 2: + $wX = ($sourcedb['width'] - $waterdb['width']) / 2; + $wY = $markType == 1 ? 5 : $waterdb['height']; + break; + case 3: + $wX = $sourcedb['width'] - $waterdb['width'] - 5; + $wY = $markType == 1 ? 5 : $waterdb['height']; + break; + case 4: + $wX = 5; + $wY = $markType == 1 ? $sourcedb['height'] - $waterdb['height'] - 5 : $sourcedb['height'] - 5; + break; + case 5: + $wX = ($sourcedb['width'] - $waterdb['width']) / 2; + $wY = $markType == 1 ? $sourcedb['height'] - $waterdb['height'] - 5 : $sourcedb['height'] - 5; + break; + case 6: + $wX = $sourcedb['width'] - $waterdb['width'] - 5; + $wY = $markType == 1 ? $sourcedb['height'] - $waterdb['height'] - 5 : $sourcedb['height'] - 5; + break; + default: + $wX = ($sourcedb['width'] - $waterdb['width']) / 2; + $wY = $markType == 1 ? ($sourcedb['height'] - $waterdb['height']) / 2 : ($sourcedb['height'] + $waterdb['height']) / 2; + break; + } + + return array($wX, $wY); + } + + /** + * 获得略缩图的信息 + * + * @param string $srcFile 源文件 + * @param int $dstW 目标文件的宽度 + * @param int $dstH 目标文件的高度 + * @param bool $isProportion 是否定比略缩 + * @return array|bool + */ + private static function getThumbInfo($srcFile, $dstW, $dstH, $isProportion = false) + { + if (false === ($imgdata = self::getImgInfo($srcFile))) { + return false; + } + if ($imgdata['width'] <= $dstW && $imgdata['height'] <= $dstH) { + return false; + } + + $imgdata['dstW'] = $dstW; + $imgdata['dstH'] = $dstH; + if (empty($dstW) && $dstH > 0 && $imgdata['height'] > $dstH) { + $imgdata['dstW'] = !$isProportion ? $dstH : round($dstH / $imgdata['height'] * $imgdata['width']); + } elseif (empty($dstH) && $dstW > 0 && $imgdata['width'] > $dstW) { + $imgdata['dstH'] = !$isProportion ? $dstW : round($dstW / $imgdata['width'] * $imgdata['height']); + } elseif ($dstW > 0 && $dstH > 0) { + if (($imgdata['width'] / $dstW) < ($imgdata['height'] / $dstH)) { + $imgdata['dstW'] = !$isProportion ? $dstW : round($dstH / $imgdata['height'] * $imgdata['width']); + } + if (($imgdata['width'] / $dstW) > ($imgdata['height'] / $dstH)) { + $imgdata['dstH'] = !$isProportion ? $dstH : round($dstW / $imgdata['width'] * $imgdata['height']); + } + } else { + $imgdata = false; + } + + return $imgdata; + } + + /** + * 获得图片的信息,返回图片的源及图片的高度和宽度 + * + * @param string $srcFile 图像地址 + * @return array|bool + */ + public static function getImgInfo($srcFile) + { + if (false === ($imgdata = self::getImgSize($srcFile))) { + return false; + } + $imgdata['type'] = self::getTypes($imgdata['type']); + if (empty($imgdata) || !function_exists('imagecreatefrom'.$imgdata['type'])) { + return false; + } + $imagecreatefromtype = 'imagecreatefrom'.$imgdata['type']; + $imgdata['source'] = $imagecreatefromtype($srcFile); + !$imgdata['width'] && $imgdata['width'] = imagesx($imgdata['source']); + !$imgdata['height'] && $imgdata['height'] = imagesy($imgdata['source']); + + return $imgdata; + } + + /** + * 获得图片的类型及宽高 + * + *
    +     * 图片type:
    +     * 1 = GIF,2 = JPG,3 = PNG,4 = SWF,5 = PSD,6 = BMP,7 = TIFF(intel byte order),8 = TIFF(motorola byte order),9 = JPC,10 = JP2,
    +     * 11 = JPX,12 = JB2,13 = SWC,14 = IFF,15 = WBMP,16 = XBM
    +     * 
    、 + * + * @param string $srcFile 图像地址 + * @param string $srcExt 图像后缀,默认为null则将会从图片地址中分析获取 + * @return array|bool 返回图像的类型及高度和宽度 + */ + private static function getImgSize($srcFile, $srcExt = null) + { + empty($srcExt) && $srcExt = strtolower(substr(strrchr($srcFile, '.'), 1)); + $srcdata = array(); + $exts = array('jpg', 'jpeg', 'jpe', 'jfif'); + in_array($srcExt, $exts) && $srcdata['type'] = 2; + if (false === ($info = getimagesize($srcFile))) { + return false; + } + list($srcdata['width'], $srcdata['height'], $srcdata['type']) = $info; + if (!$srcdata['type'] || ($srcdata['type'] == 1 && in_array($srcExt, $exts))) { + return false; + } + + return $srcdata; + } + + /** + * 获得创建图像的方法 + * + * @param string $imagetype 图片类型 + * @return array + */ + private static function getImgcreate($imagetype) + { + if ($imagetype != 'gif' && function_exists('imagecreatetruecolor') && function_exists('imagecopyresampled')) { + return array('imagecreatetruecolor', 'imagecopyresampled'); + } + if (function_exists('imagecreate') && function_exists('imagecopyresized')) { + return array('imagecreate', 'imagecopyresized'); + } + + return array('', ''); + } + + /** + * 创建图像 + * + * @param string $type 图像类型 + * @param resource $image 图像源 + * @param string $filename 图像保存名字 + * @param int $quality 创建jpeg的时候用到,默认为75 + * @return bool + */ + private static function makeImg($type, $image, $filename, $quality = '75') + { + $makeimage = 'image'.$type; + if (!function_exists($makeimage)) { + return false; + } + if ($type == 'jpeg') { + $makeimage($image, $filename, $quality); + } else { + $makeimage($image, $filename); + } + + return true; + } + + /** + * 图片的对应类型 + * + * @param int $id 图片类型ID + * @return string + */ + private static function getTypes($id) + { + $imageTypes = array(1 => 'gif', 2 => 'jpeg', '3' => 'png', 6 => 'bmp'); - /** - * 给图片制作水印 - * - * 水印的位置可以为: - * - * array(0 => '随机位置', 1 => '顶部居左', 2 => '顶部居中', 3 => '顶部居右', 4 => '底部居左', 5 => '底部居中', 6 => '底部居右', 7 => '中心位置') - * - * - * @param string $source 图片的源文件 - * @param int|array $waterPos 水印的位置,可以选择从0-7或是制定开始位置x,y,默认为0,随机位置 - * @param string $waterImg 作为水印的图片,默认为空 - * @param string $waterText 作为水印的文字,默认为空 - * @param array $attribute 文字水印的属性,只对文字水印有效 - * - * array(0 => '字体文件',1 => '系统编码', 2 => '字体颜色', 3 => '字体大小') - * - * @param string $waterPct 水印透明度,从0到100,0完全透明,100完全不透明,默认为50 - * @param string $waterQuality 图片质量--jpeg,默认为75 - * @param string $dstsrc 目标文件位置,默认为null即不保存 - * @return boolean - */ - public static function makeWatermark($source, $waterPos = 0, $waterImg = '', $waterText = '', $attribute = '', $waterPct = 50, $waterQuality = 75, $dstsrc = null) { - $sourcedb = $waterdb = array(); - if (false === ($sourcedb = self::getImgInfo($source))) return false; - if (!$waterImg && !$waterText) return false; - imagealphablending($sourcedb['source'], true); - if ($waterImg) { - $waterdb = self::getImgInfo($waterImg); - list($wX, $wY) = self::getWaterPos($waterPos, $sourcedb, $waterdb, 1); - if ($waterdb['type'] == 'png') { - $tmp = imagecreatetruecolor($sourcedb['width'], $sourcedb['height']); - imagecopy($tmp, $sourcedb['source'], 0, 0, 0, 0, $sourcedb['width'], $sourcedb['height']); - imagecopy($tmp, $waterdb['source'], $wX, $wY, 0, 0, $waterdb['width'], $waterdb['height']); - $sourcedb['source'] = $tmp; - } else { - imagecopymerge($sourcedb['source'], $waterdb['source'], $wX, $wY, 0, 0, $waterdb['width'], $waterdb['height'], $waterPct); - } - } elseif ($waterText) { - list($fontFile, $charset, $color, $waterFont) = self::checkAttribute($attribute); - empty($waterFont) && $waterFont = 12; - $temp = imagettfbbox($waterFont, 0, $fontFile, $waterText); //取得使用 TrueType 字体的文本的范围 - $waterdb['width'] = $temp[2] - $temp[6]; - $waterdb['height'] = $temp[3] - $temp[7]; - unset($temp); - list($wX, $wY) = self::getWaterPos($waterPos, $sourcedb, $waterdb, 2); - if (strlen($color) != 7) return false; - $R = hexdec(substr($color, 1, 2)); - $G = hexdec(substr($color, 3, 2)); - $B = hexdec(substr($color, 5)); - self::changeCharset($charset) && $waterText = mb_convert_encoding($waterText, 'UTF-8', $charset); - imagettftext($sourcedb['source'], $waterFont, 0, $wX, $wY, imagecolorallocate($sourcedb['source'], $R, $G, $B), $fontFile, $waterText); - } - $dstsrc && $source = $dstsrc; - self::makeImg($sourcedb['type'], $sourcedb['source'], $source, $waterQuality); - isset($waterdb['source']) && imagedestroy($waterdb['source']); - imagedestroy($sourcedb['source']); - return true; - } - - /** - * 文字水印的属性设置过滤 - * - * 返回为: - * - * array(0 => '字体文件',1 => '系统编码', 2 => '字体颜色', 3 => '字体大小') - * - * @param array $attribute 设置的属性 - * @return array - */ - private static function checkAttribute($attribute) { - $attribute = is_string($attribute) ? array($attribute) : $attribute; - if (!isset($attribute[1]) || !$attribute[1]) $attribute[1] = 'UTF-8'; - if (!isset($attribute[2]) || !$attribute[2]) $attribute[2] = '#FF0000'; - if (!isset($attribute[3]) || !$attribute[3]) $attribute[3] = 12; - return $attribute; - } - - /** - * 判断是否需要转编码 - * - * 判断依据为,编码格式为utf-8 - * - * @param string $charset 编码方式 - * @return boolean - */ - private static function changeCharset($charset) { - $charset = strtolower($charset); - return !in_array($charset, array('utf8', 'utf-8')); - } - - /** - * 获得打水印的位置 - * - * 如果传入的是数组,则两个元素分别为水印的宽度x和高度y - * - * @param int|array $pos 获得水印的位置 - * @param array $sourcedb 原图片的信息 - * @param array $waterdb 水印图片的信息 - * @param int $markType 水印类型,1为图片水印,2为文字水印 - * @return array - */ - private static function getWaterPos($waterPos, $sourcedb, $waterdb, $markType) { - if (is_array($waterPos)) return $waterPos; - $wX = $wY = 0; - switch (intval($waterPos)) { - case 0 : - $wX = rand(0, ($sourcedb['width'] - $waterdb['width'])); - $wY = $markType == 1 ? rand(0, ($sourcedb['height'] - $waterdb['height'])) : rand($waterdb['height'], $sourcedb['height']); - break; - case 1 : - $wX = 5; - $wY = $markType == 1 ? 5 : $waterdb['height']; - break; - case 2: - $wX = ($sourcedb['width'] - $waterdb['width']) / 2; - $wY = $markType == 1 ? 5 : $waterdb['height']; - break; - case 3: - $wX = $sourcedb['width'] - $waterdb['width'] - 5; - $wY = $markType == 1 ? 5 : $waterdb['height']; - break; - case 4: - $wX = 5; - $wY = $markType == 1 ? $sourcedb['height'] - $waterdb['height'] - 5 : $sourcedb['height'] - 5; - break; - case 5: - $wX = ($sourcedb['width'] - $waterdb['width']) / 2; - $wY = $markType == 1 ? $sourcedb['height'] - $waterdb['height'] - 5 : $sourcedb['height'] - 5; - break; - case 6: - $wX = $sourcedb['width'] - $waterdb['width'] - 5; - $wY = $markType == 1 ? $sourcedb['height'] - $waterdb['height'] - 5 : $sourcedb['height'] - 5; - break; - default: - $wX = ($sourcedb['width'] - $waterdb['width']) / 2; - $wY = $markType == 1 ? ($sourcedb['height'] - $waterdb['height']) / 2 : ($sourcedb['height'] + $waterdb['height']) / 2; - break; - } - return array($wX, $wY); - } - - /** - * 获得略缩图的信息 - * - * @param string $srcFile 源文件 - * @param int $dstW 目标文件的宽度 - * @param int $dstH 目标文件的高度 - * @param boolean $isProportion 是否定比略缩 - * @return array|boolean - */ - private static function getThumbInfo($srcFile, $dstW, $dstH, $isProportion= FALSE) { - if (false === ($imgdata = self::getImgInfo($srcFile))) return false; - if ($imgdata['width'] <= $dstW && $imgdata['height'] <= $dstH) return false; - - $imgdata['dstW'] = $dstW; - $imgdata['dstH'] = $dstH; - if (empty($dstW) && $dstH > 0 && $imgdata['height'] > $dstH) { - $imgdata['dstW'] = !$isProportion ? $dstH : round($dstH / $imgdata['height'] * $imgdata['width']); - } elseif (empty($dstH) && $dstW > 0 && $imgdata['width'] > $dstW) { - $imgdata['dstH'] = !$isProportion ? $dstW : round($dstW / $imgdata['width'] * $imgdata['height']); - } elseif ($dstW > 0 && $dstH > 0) { - if (($imgdata['width'] / $dstW) < ($imgdata['height'] / $dstH)) { - $imgdata['dstW'] = !$isProportion ? $dstW : round($dstH / $imgdata['height'] * $imgdata['width']); - } - if (($imgdata['width'] / $dstW) > ($imgdata['height'] / $dstH)) { - $imgdata['dstH'] = !$isProportion ? $dstH : round($dstW / $imgdata['width'] * $imgdata['height']); - } - } else { - $imgdata = false; - } - return $imgdata; - } - - /** - * 获得图片的信息,返回图片的源及图片的高度和宽度 - * - * @param string $srcFile 图像地址 - * @return array|boolean - */ - public static function getImgInfo($srcFile) { - if (false === ($imgdata = self::getImgSize($srcFile))) return false; - $imgdata['type'] = self::getTypes($imgdata['type']); - if (empty($imgdata) || !function_exists('imagecreatefrom' . $imgdata['type'])) return false; - $imagecreatefromtype = 'imagecreatefrom' . $imgdata['type']; - $imgdata['source'] = $imagecreatefromtype($srcFile); - !$imgdata['width'] && $imgdata['width'] = imagesx($imgdata['source']); - !$imgdata['height'] && $imgdata['height'] = imagesy($imgdata['source']); - return $imgdata; - } - - /** - * 获得图片的类型及宽高 - * - *
    -	 * 图片type:
    -	 * 1 = GIF,2 = JPG,3 = PNG,4 = SWF,5 = PSD,6 = BMP,7 = TIFF(intel byte order),8 = TIFF(motorola byte order),9 = JPC,10 = JP2,
    -	 * 11 = JPX,12 = JB2,13 = SWC,14 = IFF,15 = WBMP,16 = XBM
    -	 * 
    、 - * - * @param string $srcFile 图像地址 - * @param string $srcExt 图像后缀,默认为null则将会从图片地址中分析获取 - * @return array|boolean 返回图像的类型及高度和宽度 - */ - private static function getImgSize($srcFile, $srcExt = null) { - empty($srcExt) && $srcExt = strtolower(substr(strrchr($srcFile, '.'), 1)); - $srcdata = array(); - $exts = array('jpg', 'jpeg', 'jpe', 'jfif'); - in_array($srcExt, $exts) && $srcdata['type'] = 2; - if (false === ($info = getimagesize($srcFile))) return false; - list($srcdata['width'], $srcdata['height'], $srcdata['type']) = $info; - if (!$srcdata['type'] || ($srcdata['type'] == 1 && in_array($srcExt, $exts))) return false; - return $srcdata; - } - - /** - * 获得创建图像的方法 - * - * @param string $imagetype 图片类型 - * @return array - */ - private static function getImgcreate($imagetype) { - if ($imagetype != 'gif' && function_exists('imagecreatetruecolor') && function_exists('imagecopyresampled')) { - return array('imagecreatetruecolor', 'imagecopyresampled'); - } - if (function_exists('imagecreate') && function_exists('imagecopyresized')) { - return array('imagecreate', 'imagecopyresized'); - } - return array('', ''); - } - - /** - * 创建图像 - * - * @param string $type 图像类型 - * @param resource $image 图像源 - * @param string $filename 图像保存名字 - * @param int $quality 创建jpeg的时候用到,默认为75 - * @return boolean - */ - private static function makeImg($type, $image, $filename, $quality = '75') { - $makeimage = 'image' . $type; - if (!function_exists($makeimage)) return false; - if ($type == 'jpeg') { - $makeimage($image, $filename, $quality); - } else { - $makeimage($image, $filename); - } - return true; - } - - /** - * 图片的对应类型 - * - * @param int $id 图片类型ID - * @return string - */ - private static function getTypes($id) { - $imageTypes = array(1 => 'gif', 2 => 'jpeg', '3' => 'png', 6 => 'bmp'); - return isset($imageTypes[$id]) ? $imageTypes[$id] : ''; - } -} \ No newline at end of file + return isset($imageTypes[$id]) ? $imageTypes[$id] : ''; + } +} diff --git a/wind/utility/WindJson.php b/wind/utility/WindJson.php index 48a9c3e6..81d7e105 100644 --- a/wind/utility/WindJson.php +++ b/wind/utility/WindJson.php @@ -1,317 +1,348 @@ 2011-10-19 - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package utility + * + * 支持json转php类型,以及php类型转json. + * @author Long.shi 2011-10-19 + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id: WindJson.php 3859 2012-12-18 09:25:51Z yishuo $ + * @package utility */ -class WindJson { - const JSON_SLICE = 1; - const JSON_IN_STR = 2; - const JSON_IN_ARR = 4; - const JSON_IN_OBJ = 8; - const JSON_IN_CMT = 16; +class WindJson +{ + const JSON_SLICE = 1; + const JSON_IN_STR = 2; + const JSON_IN_ARR = 4; + const JSON_IN_OBJ = 8; + const JSON_IN_CMT = 16; - /** - * 将数据用json加密 - * - * @param mixed $value 要加密的值 - * @param string $charset - * @return string - */ - public static function encode($source, $charset = 'utf8') { - switch (gettype($source)) { - case 'boolean': - $source = $source ? 'true' : 'false'; - break; - case 'NULL': - $source = 'null'; - break; - case 'integer': - $source = (int) $source; - break; - case 'double': - case 'float': - $source = (float) $source; - break; - case 'string': - $source = WindConvert::convert($source, 'utf8', $charset); - $source = self::stringToJson($source); - break; - case 'array': - $source = WindConvert::convert($source, 'utf8', $charset); - $source = self::arrayToJson($source); - break; - case 'object': - $source = WindConvert::convert($source, 'utf8', $charset); - $source = self::objectToJson($source); - break; - default: - break; - } - return $source; - } + /** + * 将数据用json加密 + * + * @param mixed $value 要加密的值 + * @param string $charset + * @return string + */ + public static function encode($source, $charset = 'utf-8') + { + switch (gettype($source)) { + case 'boolean': + $source = $source ? 'true' : 'false'; + break; + case 'NULL': + $source = 'null'; + break; + case 'integer': + $source = (int) $source; + break; + case 'double': + case 'float': + $source = (float) $source; + break; + case 'string': + $source = self::stringToJson($source, $charset); + break; + case 'array': + $source = self::arrayToJson($source, $charset); + break; + case 'object': + $source = self::objectToJson($source, $charset); + break; + default: + break; + } - /** - * 将json格式数据解密 - * - * @param string $str - * @param boolean $toArray - * @param string $charset - * @return mixed - */ - public static function decode($str, $toArray = true, $charset = 'utf8') { - $str = self::_reduceString($str); - $_str = strtolower($str); - if ('true' == $_str) { - return true; - } elseif ('false' == $_str) { - return false; - } elseif ('null' == $_str) { - return null; - } elseif (is_numeric($str)) { - return (float) $str == (integer) $str ? (integer) $str : (float) $str; - } elseif (preg_match('/^("|\').+(\1)$/s', $_str, $matche) && $matche[1] == $matche[2]) { - $str = self::jsonToString($str); - } elseif (preg_match('/^\[.*\]$/s', $_str) || preg_match('/^\{.*\}$/s', $_str)) { - $str = self::complexConvert($str, $toArray); - } - WindConvert::convert($str, $charset, 'utf8'); - return $str; - } + return $source; + } - /** - * 将json格式转成php string类型 - * - * @param string $string json字符串 - * @return Ambigous - */ - protected static function jsonToString($string) { - $delim = substr($string, 0, 1); - $chrs = substr($string, 1, -1); - $decodeStr = ''; - for ($c = 0, $length = strlen($chrs); $c < $length; ++$c) { - $compare = substr($chrs, $c, 2); - $ordCode = ord($chrs{$c}); - if ('\b' == $compare) { - $decodeStr .= chr(0x08); - ++$c; - } elseif ('\t' == $compare) { - $decodeStr .= chr(0x09); - ++$c; - } elseif ('\n' == $compare) { - $decodeStr .= chr(0x0A); - ++$c; - } elseif ('\f' == $compare) { - $decodeStr .= chr(0x0C); - ++$c; - } elseif ('\r' == $compare) { - $decodeStr .= chr(0x0D); - ++$c; - } elseif (in_array($compare, array('\\"', '\\\'', '\\\\', '\\/'))) { - if (('"' == $delim && '\\\'' != $compare) || ("'" == $delim && '\\"' != $compare)) { - $decodeStr .= $chrs{++$c}; - } - } elseif (preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6))) { - $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2))) . chr(hexdec(substr($chrs, ($c + 4), 2))); - $decodeStr .= WindConvert::utf16beToUTF8($utf16); //self::utf16beToUTF8($utf16); - $c += 5; - } elseif (0x20 <= $ordCode && 0x7F >= $ordCode) { - $decodeStr .= $chrs{$c}; - } elseif (0xC0 == ($ordCode & 0xE0)) { - $decodeStr .= substr($chrs, $c, 2); - ++$c; - } elseif (0xE0 == ($ordCode & 0xF0)) { - $decodeStr .= substr($chrs, $c, 3); - $c += 2; - } elseif (0xF0 == ($ordCode & 0xF8)) { - $decodeStr .= substr($chrs, $c, 4); - $c += 3; - } elseif (0xF8 == ($ordCode & 0xFC)) { - $decodeStr .= substr($chrs, $c, 5); - $c += 4; - } elseif (0xFC == ($ordCode & 0xFE)) { - $decodeStr .= substr($chrs, $c, 6); - $c += 5; - } - } - return $decodeStr; - } + /** + * 将json格式数据解密 + * + * @param string $str + * @param bool $toArray + * @param string $charset + * @return mixed + */ + public static function decode($str, $toArray = true, $charset = 'utf8') + { + $str = self::_reduceString($str); + $_str = strtolower($str); + if ('true' == $_str) { + return true; + } elseif ('false' == $_str) { + return false; + } elseif ('null' == $_str) { + return null; + } elseif (is_numeric($str)) { + return $str; + } elseif (preg_match('/^("|\').*(\1)$/s', $_str, $matche) && $matche[1] == $matche[2]) { + $str = self::jsonToString($str); + } elseif (preg_match('/^\[.*\]$/s', $_str) || preg_match('/^\{.*\}$/s', $_str)) { + $str = self::complexConvert($str, $toArray); + } - /** - * 复杂的json格式转换,支持object array格式 - * - * @param string $str - * @param boolean $toArray - * @return Ambigous |multitype:|Ambigous |boolean - */ - protected static function complexConvert($str, $toArray = true) { - if ('[' == $str{0}) { - $stk = array(self::JSON_IN_ARR); - $arr = array(); - } else { - $obj = $toArray ? array() : new stdClass(); - $stk = array(self::JSON_IN_OBJ); - } - array_push($stk, array('what' => self::JSON_SLICE, 'where' => 0, 'delim' => false)); - $chrs = substr($str, 1, -1); - $chrs = self::_reduceString($chrs); - if ('' == $chrs) { - return self::JSON_IN_ARR == reset($stk) ? $arr : $obj; - } - for ($c = 0, $length = strlen($chrs); $c <= $length; ++$c) { - $top = end($stk); - $substr_chrs_c_2 = substr($chrs, $c, 2); - if (($c == $length) || (($chrs{$c} == ',') && ($top['what'] == self::JSON_SLICE))) { - $slice = substr($chrs, $top['where'], ($c - $top['where'])); - array_push($stk, array('what' => self::JSON_SLICE, 'where' => ($c + 1), 'delim' => false)); - if (reset($stk) == self::JSON_IN_ARR) { - array_push($arr, self::decode($slice, $toArray)); - } elseif (reset($stk) == self::JSON_IN_OBJ) { - if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) { - $key = self::decode($parts[1], $toArray); - $toArray ? $obj[$key] = self::decode($parts[2], $toArray) : $obj->$key = self::decode($parts[2], - $toArray); - } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) { - $toArray ? $obj[$parts[1]] = self::decode($parts[2], $toArray) : $obj->$parts[1] = self::decode( - $parts[2], $toArray); - } - } - - } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != self::JSON_IN_STR)) { - array_push($stk, array('what' => self::JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c})); - } elseif (($chrs{$c} == $top['delim']) && ($top['what'] == self::JSON_IN_STR) && (($chrs{$c - 1} != "\\") || ($chrs{$c - 1} == "\\" && $chrs{$c - 2} == "\\"))) { - array_pop($stk); - } elseif (($chrs{$c} == '[') && in_array($top['what'], - array(self::JSON_SLICE, self::JSON_IN_ARR, self::JSON_IN_OBJ))) { - array_push($stk, array('what' => self::JSON_IN_ARR, 'where' => $c, 'delim' => false)); - } elseif (($chrs{$c} == ']') && ($top['what'] == self::JSON_IN_ARR)) { - array_pop($stk); - } elseif (($chrs{$c} == '{') && in_array($top['what'], - array(self::JSON_SLICE, self::JSON_IN_ARR, self::JSON_IN_OBJ))) { - array_push($stk, array('what' => self::JSON_IN_OBJ, 'where' => $c, 'delim' => false)); - } elseif (($chrs{$c} == '}') && ($top['what'] == self::JSON_IN_OBJ)) { - array_pop($stk); - } elseif (($substr_chrs_c_2 == '/*') && in_array($top['what'], - array(self::JSON_SLICE, self::JSON_IN_ARR, self::JSON_IN_OBJ))) { - array_push($stk, array('what' => self::JSON_IN_CMT, 'where' => ++$c, 'delim' => false)); - } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == self::JSON_IN_CMT)) { - array_pop($stk); - for ($i = $top['where']; $i <= ++$c; ++$i) { - $chrs = substr_replace($chrs, ' ', $i, 1); - } - } - - } - if (self::JSON_IN_ARR == reset($stk)) { - return $arr; - } elseif (self::JSON_IN_OBJ == reset($stk)) { - return $obj; - } - return false; - } + return WindConvert::convert($str, $charset, 'utf8'); + } - /** - * 将字符串转化成json格式对象 - * - * @param string $string - * @return string - */ - protected static function stringToJson($string) { - $ascii = ''; - $strlen = strlen($string); - for ($c = 0; $c < $strlen; ++$c) { - $b = $string{$c}; - $ordVar = ord($string{$c}); - if (0x08 == $ordVar) { - $ascii .= '\b'; - } elseif (0x09 == $ordVar) { - $ascii .= '\t'; - } elseif (0x0A == $ordVar) { - $ascii .= '\n'; - } elseif (0x0C == $ordVar) { - $ascii .= '\f'; - } elseif (0x0D == $ordVar) { - $ascii .= '\r'; - } elseif (in_array($ordVar, array(0x22, 0x2F, 0x5C))) { - $ascii .= '\\' . $string{$c}; - } elseif (0x20 <= $ordVar && 0x7F >= $ordVar) { - $ascii .= $string{$c}; //ASCII - } elseif (0xC0 == ($ordVar & 0xE0)) { - $char = pack('C*', $ordVar, ord($string{++$c})); - $ascii .= sprintf('\u%04s', bin2hex(WindConvert::utf8ToUTF16BE($char))); - } elseif (0xE0 == ($ordVar & 0xF0)) { - $char = pack('C*', $ordVar, ord($string{++$c}), ord($string{++$c})); - $ascii .= sprintf('\u%04s', bin2hex(WindConvert::utf8ToUTF16BE($char))); - } elseif (0xF0 == ($ordVar & 0xF8)) { - $char = pack('C*', $ordVar, ord($string{++$c}), ord($string{++$c}), ord($string{++$c})); - $ascii .= sprintf('\u%04s', bin2hex(WindConvert::utf8ToUTF16BE($char))); - } elseif (0xF8 == ($ordVar & 0xFC)) { - $char = pack('C*', $ordVar, ord($string{++$c}), ord($string{++$c}), ord($string{++$c}), - ord($string{++$c})); - $ascii .= sprintf('\u%04s', bin2hex(WindConvert::utf8ToUTF16BE($char))); - } elseif (0xFC == ($ordVar & 0xFE)) { - $char = pack('C*', $ordVar, ord($string{++$c}), ord($string{++$c}), ord($string{++$c}), - ord($string{++$c}), ord($string{++$c})); - $ascii .= sprintf('\u%04s', bin2hex(WindConvert::utf8ToUTF16BE($char))); - } - } - return '"' . $ascii . '"'; - } + /** + * 将json格式转成php string类型 + * + * @param string $string json字符串 + * @return Ambigous + */ + protected static function jsonToString($string) + { + $delim = substr($string, 0, 1); + $chrs = substr($string, 1, -1); + $decodeStr = ''; + for ($c = 0, $length = strlen($chrs); $c < $length; ++$c) { + $compare = substr($chrs, $c, 2); + $ordCode = ord($chrs{$c}); + if ('\b' == $compare) { + $decodeStr .= chr(0x08); + ++$c; + } elseif ('\t' == $compare) { + $decodeStr .= chr(0x09); + ++$c; + } elseif ('\n' == $compare) { + $decodeStr .= chr(0x0A); + ++$c; + } elseif ('\f' == $compare) { + $decodeStr .= chr(0x0C); + ++$c; + } elseif ('\r' == $compare) { + $decodeStr .= chr(0x0D); + ++$c; + } elseif (in_array($compare, array('\\"', '\\\'', '\\\\', '\\/'))) { + if (('"' == $delim && '\\\'' != $compare) || ("'" == $delim && '\\"' != $compare)) { + $decodeStr .= $chrs{++$c}; + } + } elseif (preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6))) { + $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2))).chr(hexdec(substr($chrs, ($c + 4), 2))); + $decodeStr .= WindConvert::utf16beToUTF8($utf16); //self::utf16beToUTF8($utf16); + $c += 5; + } elseif (0x20 <= $ordCode && 0x7F >= $ordCode) { + $decodeStr .= $chrs{$c}; + } elseif (0xC0 == ($ordCode & 0xE0)) { + $decodeStr .= substr($chrs, $c, 2); + ++$c; + } elseif (0xE0 == ($ordCode & 0xF0)) { + $decodeStr .= substr($chrs, $c, 3); + $c += 2; + } elseif (0xF0 == ($ordCode & 0xF8)) { + $decodeStr .= substr($chrs, $c, 4); + $c += 3; + } elseif (0xF8 == ($ordCode & 0xFC)) { + $decodeStr .= substr($chrs, $c, 5); + $c += 4; + } elseif (0xFC == ($ordCode & 0xFE)) { + $decodeStr .= substr($chrs, $c, 6); + $c += 5; + } + } - /** - * 将数组转化成json格式对象 - * - * @param array $array - * @return string - */ - protected static function arrayToJson(array $array) { - if (is_array($array) && count($array) && (array_keys($array) !== range(0, sizeof($array) - 1))) { - return '{' . join(',', array_map(array('WindJson', '_nameValue'), array_keys($array), array_values($array))) . '}'; - } - return '[' . join(',', array_map(array('WindJson', 'encode'), $array)) . ']'; - } + return $decodeStr; + } - /** - * 将对象转化成json格式对象 - * - * @param string $object - * @return string - */ - protected static function objectToJson($object) { - if ($object instanceof Traversable) { - $vars = array(); - foreach ($object as $k => $v) { - $vars[$k] = $v; - } - } else { - $vars = get_object_vars($object); - } - return '{' . join(',', array_map(array('WindJson', '_nameValue'), array_keys($vars), array_values($vars))) . '}'; - } + /** + * 复杂的json格式转换,支持object array格式 + * + * @param string $str + * @param bool $toArray + * @return Ambigous |multitype:|Ambigous |boolean + */ + protected static function complexConvert($str, $toArray = true) + { + if ('[' == $str{0}) { + $stk = array(self::JSON_IN_ARR); + $arr = array(); + } else { + $obj = $toArray ? array() : new stdClass(); + $stk = array(self::JSON_IN_OBJ); + } + array_push($stk, array('what' => self::JSON_SLICE, 'where' => 0, 'delim' => false)); + $chrs = substr($str, 1, -1); + $chrs = self::_reduceString($chrs); + if ('' == $chrs) { + return self::JSON_IN_ARR == reset($stk) ? $arr : $obj; + } + for ($c = 0, $length = strlen($chrs); $c <= $length; ++$c) { + $top = end($stk); + $substr_chrs_c_2 = substr($chrs, $c, 2); + if (($c == $length) || (($chrs{$c} == ',') && ($top['what'] == self::JSON_SLICE))) { + $slice = substr($chrs, $top['where'], ($c - $top['where'])); + array_push($stk, array('what' => self::JSON_SLICE, 'where' => ($c + 1), 'delim' => false)); + if (reset($stk) == self::JSON_IN_ARR) { + array_push($arr, self::decode($slice, $toArray)); + } elseif (reset($stk) == self::JSON_IN_OBJ) { + if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) { + $key = self::decode($parts[1], $toArray); + $toArray ? $obj[$key] = self::decode($parts[2], $toArray) : $obj->$key = self::decode($parts[2], + $toArray); + } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) { + $toArray ? $obj[$parts[1]] = self::decode($parts[2], $toArray) : $obj->$parts[1] = self::decode( + $parts[2], $toArray); + } + } + } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != self::JSON_IN_STR)) { + array_push($stk, array('what' => self::JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c})); + } elseif (($chrs{$c} == $top['delim']) && ($top['what'] == self::JSON_IN_STR) && (($chrs{$c - 1} != '\\') || ($chrs{$c - 1} == '\\' && $chrs{$c - 2} == '\\'))) { + array_pop($stk); + } elseif (($chrs{$c} == '[') && in_array($top['what'], + array(self::JSON_SLICE, self::JSON_IN_ARR, self::JSON_IN_OBJ))) { + array_push($stk, array('what' => self::JSON_IN_ARR, 'where' => $c, 'delim' => false)); + } elseif (($chrs{$c} == ']') && ($top['what'] == self::JSON_IN_ARR)) { + array_pop($stk); + } elseif (($chrs{$c} == '{') && in_array($top['what'], + array(self::JSON_SLICE, self::JSON_IN_ARR, self::JSON_IN_OBJ))) { + array_push($stk, array('what' => self::JSON_IN_OBJ, 'where' => $c, 'delim' => false)); + } elseif (($chrs{$c} == '}') && ($top['what'] == self::JSON_IN_OBJ)) { + array_pop($stk); + } elseif (($substr_chrs_c_2 == '/*') && in_array($top['what'], + array(self::JSON_SLICE, self::JSON_IN_ARR, self::JSON_IN_OBJ))) { + array_push($stk, array('what' => self::JSON_IN_CMT, 'where' => ++$c, 'delim' => false)); + } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == self::JSON_IN_CMT)) { + array_pop($stk); + for ($i = $top['where']; $i <= ++$c; ++$i) { + $chrs = substr_replace($chrs, ' ', $i, 1); + } + } + } + if (self::JSON_IN_ARR == reset($stk)) { + return $arr; + } elseif (self::JSON_IN_OBJ == reset($stk)) { + return $obj; + } - /** - * @param string $str - * @return string - */ - private static function _reduceString($str) { - return trim(preg_replace(array('#^\s*//(.+)$#m', '#^\s*/\*(.+)\*/#Us', '#/\*(.+)\*/\s*$#Us'), '', $str)); - } + return false; + } - /** - * callback函数,用于数组或对象加密 - * - * @param mixed $name - * @param mixed $value - */ - private static function _nameValue($name, $value) { - return self::encode(strval($name)) . ':' . self::encode($value); - } -} + /** + * 将字符串转化成json格式对象 + * + * @param string $string + * @param string $charset + * @return string + */ + protected static function stringToJson($string, $charset = 'utf-8') + { + $string = WindConvert::convert($string, 'utf-8', $charset); + $ascii = ''; + $strlen = strlen($string); + for ($c = 0; $c < $strlen; ++$c) { + $b = $string{$c}; + $ordVar = ord($string{$c}); + if (0x08 == $ordVar) { + $ascii .= '\b'; + } elseif (0x09 == $ordVar) { + $ascii .= '\t'; + } elseif (0x0A == $ordVar) { + $ascii .= '\n'; + } elseif (0x0C == $ordVar) { + $ascii .= '\f'; + } elseif (0x0D == $ordVar) { + $ascii .= '\r'; + } elseif (in_array($ordVar, array(0x22, 0x2F, 0x5C))) { + $ascii .= '\\'.$string{$c}; + } elseif (0x20 <= $ordVar && 0x7F >= $ordVar) { + $ascii .= $string{$c}; //ASCII + } elseif (0xC0 == ($ordVar & 0xE0)) { + $char = pack('C*', $ordVar, ord($string{++$c})); + $ascii .= sprintf('\u%04s', bin2hex(WindConvert::utf8ToUTF16BE($char))); + } elseif (0xE0 == ($ordVar & 0xF0)) { + $char = pack('C*', $ordVar, ord($string{++$c}), ord($string{++$c})); + $ascii .= sprintf('\u%04s', bin2hex(WindConvert::utf8ToUTF16BE($char))); + } elseif (0xF0 == ($ordVar & 0xF8)) { + $char = pack('C*', $ordVar, ord($string{++$c}), ord($string{++$c}), ord($string{++$c})); + $ascii .= sprintf('\u%04s', bin2hex(WindConvert::utf8ToUTF16BE($char))); + } elseif (0xF8 == ($ordVar & 0xFC)) { + $char = pack('C*', $ordVar, ord($string{++$c}), ord($string{++$c}), ord($string{++$c}), + ord($string{++$c})); + $ascii .= sprintf('\u%04s', bin2hex(WindConvert::utf8ToUTF16BE($char))); + } elseif (0xFC == ($ordVar & 0xFE)) { + $char = pack('C*', $ordVar, ord($string{++$c}), ord($string{++$c}), ord($string{++$c}), + ord($string{++$c}), ord($string{++$c})); + $ascii .= sprintf('\u%04s', bin2hex(WindConvert::utf8ToUTF16BE($char))); + } + } + + return '"'.$ascii.'"'; + } + + /** + * 将数组转化成json格式对象 + * + * @param array $array + * @param string $charset + * @return string + */ + protected static function arrayToJson(array $array, $charset = 'utf-8') + { + if (is_array($array) && count($array) && (array_keys($array) !== range(0, count($array) - 1))) { + array_walk($array, array('WindJson', '_nameValue'), $charset); + + return '{'.implode(',', $array).'}'; + } + array_walk($array, array('WindJson', '_value'), $charset); -?> \ No newline at end of file + return '['.implode(',', $array).']'; + } + + /** + * 将对象转化成json格式对象 + * + * @param string $object + * @param string $charset + * @return string + */ + protected static function objectToJson($object, $charset = 'utf-8') + { + if ($object instanceof Traversable) { + $vars = array(); + foreach ($object as $k => $v) { + $vars[$k] = $v; + } + } else { + $vars = get_object_vars($object); + } + array_walk($vars, array('WindJson', '_nameValue'), $charset); + + return '{'.implode(',', $vars).'}'; + } + + /** + * @param string $str + * @return string + */ + private static function _reduceString($str) + { + return trim(preg_replace(array('#^\s*//(.+)$#m', '#^\s*/\*(.+)\*/#Us', '#/\*(.+)\*/\s*$#Us'), '', $str)); + } + + /** + * callback函数,用于数组或对象加密 + * + * @param mixed $name + * @param mixed $value + * @param string $charset + */ + private static function _nameValue(&$value, $name, $charset) + { + $value = self::encode(strval($name), $charset).':'.self::encode($value, $charset); + } + + /** + * callback函数,用于数组加密(无key) + * + * @param mixed $value + * @param mixed $name + * @param string $charset + */ + private static function _value(&$value, $name, $charset) + { + $value = self::encode($value, $charset); + } +} diff --git a/wind/utility/WindPack.php b/wind/utility/WindPack.php index 7b6f1517..0a2c901e 100644 --- a/wind/utility/WindPack.php +++ b/wind/utility/WindPack.php @@ -1,294 +1,328 @@ * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindPack.php 3647 2012-06-08 04:14:06Z yishuo $ * @package utility */ -class WindPack { - - /** - * 使用正则打包 - * - * @var string - */ - const STRIP_SELF = 'stripWhiteSpaceBySelf'; - - /** - * 利用php自身的函数打包 - * - * @var string - */ - const STRIP_PHP = 'stripWhiteSpaceByPhp'; - - /** - * 通过token方式打包 - * - * @var string - */ - const STRIP_TOKEN = 'stripWhiteSpaceByToken'; - private $packList = array(); - private $contentInjectionPosition; - private $contentInjectionCallBack = ''; +class WindPack +{ + /** + * 使用正则打包 + * + * @var string + */ + const STRIP_SELF = 'stripWhiteSpaceBySelf'; + + /** + * 利用php自身的函数打包 + * + * @var string + */ + const STRIP_PHP = 'stripWhiteSpaceByPhp'; + + /** + * 通过token方式打包 + * + * @var string + */ + const STRIP_TOKEN = 'stripWhiteSpaceByToken'; + private $packList = array(); + private $contentInjectionPosition; + private $contentInjectionCallBack = ''; + + /** + * 将给出的文件列表进行打包 + * + * @param mixed $fileList 文件列表 + * @param string $dst 打包文件的存放位置 + * @param method $packMethod 打包的方式,默认为stripWhiteSpaceByPhp + * @param bool $compress 打包是否采用压缩的方式,默认为true + * @return bool + */ + public function packFromFileList($fileList, $dst, $packMethod = WindPack::STRIP_PHP, $compress = true) + { + if (empty($dst) || empty($fileList)) { + return false; + } + $content = array(); + $this->readContentFromFileList($fileList, $packMethod, $content); + $replace = $compress ? ' ' : "\n"; + $content = implode($replace, $content); + $content = $this->callBack($content, $replace); + $content = $this->stripNR($content, $replace); + $content = $this->stripPhpIdentify($content, ''); + + return WindFile::write($dst, ''); + } + + /** + * 通过php自身方式去除指定文件的注释及空白 + * + * @param string $filename 文件名 + * @return string + */ + public function stripWhiteSpaceByPhp($filename) + { + return php_strip_whitespace($filename); + } + + /** + * 通过正则方式去除指定文件的注释及空白 + * + * @param string $filename 文件名字 + * @param bool $compress 是否采用压缩,默认为true + * @return string + */ + public function stripWhiteSpaceBySelf($filename, $compress = true) + { + $content = $this->getContentFromFile($filename); + $content = $this->stripComment($content, ''); + + return $this->stripSpace($content, ' '); + } + + /** + * 通过token方式去除指定文件的注释及空白 + * + * @param string $filename 文件名称 + * @return string + */ + public function stripWhiteSpaceByToken($filename) + { + $content = $this->getContentFromFile($filename); + $compressContent = ''; + $lastToken = 0; + foreach (token_get_all($content) as $key => $token) { + if (is_array($token)) { + if (in_array($token[0], array(T_COMMENT, T_WHITESPACE, T_DOC_COMMENT))) { + continue; + } + $compressContent .= ' '.$token[1]; + } else { + $compressContent .= $token; + } + $lastToken = $token[0]; + } + + return $compressContent; + } + + /** + * 从文件列表中取得对应的每个文件的内容 + * + * @param mixed $fileList 文件列表 + * @param method $packMethod 打包方式,默认为stripWhiteSpaceByPhp + * @param array $content 保存文件内容,默认为空数组 + * @return array: + */ + public function readContentFromFileList(array $fileList, $packMethod = WindPack::STRIP_PHP, &$content = array()) + { + if (empty($fileList) || false === $this->isValidatePackMethod($packMethod)) { + return array(); + } + + foreach ($fileList as $key => $value) { + $parents = class_parents($key); + $_fileList = $this->buildFileList($parents, $fileList); + $this->readContentFromFileList($_fileList, $packMethod, $content); + $implements = class_implements($key); + $_fileList = $this->buildFileList($implements, $fileList); + $this->readContentFromFileList($_fileList, $packMethod, $content); + if (in_array($key, $this->packList)) { + continue; + } + if (is_file($value)) { + $content[] = $this->$packMethod($value); + $this->packList[] = $key; + } + } + } - /** - * 将给出的文件列表进行打包 - * - * @param mixed $fileList 文件列表 - * @param string $dst 打包文件的存放位置 - * @param method $packMethod 打包的方式,默认为stripWhiteSpaceByPhp - * @param boolean $compress 打包是否采用压缩的方式,默认为true - * @return boolean - */ - public function packFromFileList($fileList, $dst, $packMethod = WindPack::STRIP_PHP, $compress = true) { - if (empty($dst) || empty($fileList)) return false; - $content = array(); - $this->readContentFromFileList($fileList, $packMethod, $content); - $replace = $compress ? ' ' : "\n"; - $content = implode($replace, $content); - $content = $this->callBack($content, $replace); - $content = $this->stripNR($content, $replace); - $content = $this->stripPhpIdentify($content, ''); - return WindFile::write($dst, ''); - } + /** + * 去除注释 + * + * @param string $content 要去除的内容 + * @param mixed $replace 要替换的文本 + * @return string + */ + public function stripComment($content, $replace = '') + { + return preg_replace('/(?:\/\*.*\*\/)*|(?:\/\/[^\r\n]*[\r\n])*/Us', $replace, $content); + } - /** - * 通过php自身方式去除指定文件的注释及空白 - * - * @param string $filename 文件名 - * @return string - */ - public function stripWhiteSpaceByPhp($filename) { - return php_strip_whitespace($filename); - } + /** + * 去除换行 + * + * @param string $content 要去除的内容 + * @param mixed $replace 要替换的文本 + * @return string + */ + public function stripNR($content, $replace = array('\n', '\r\n', '\r')) + { + return preg_replace('/[\n\r]+/', $replace, $content); + } - /** - * 通过正则方式去除指定文件的注释及空白 - * - * @param string $filename 文件名字 - * @param boolean $compress 是否采用压缩,默认为true - * @return string - */ - public function stripWhiteSpaceBySelf($filename, $compress = true) { - $content = $this->getContentFromFile($filename); - $content = $this->stripComment($content, ''); - return $this->stripSpace($content, ' '); - } + /** + * 去除空格符 + * + * @param string $content 要去除的内容 + * @param mixed $replace 要替换的文本,默认为空 + * @return string + */ + public function stripSpace($content, $replace = ' ') + { + return preg_replace('/[ ]+/', $replace, $content); + } - /** - * 通过token方式去除指定文件的注释及空白 - * - * @param string $filename 文件名称 - * @return string - */ - public function stripWhiteSpaceByToken($filename) { - $content = $this->getContentFromFile($filename); - $compressContent = ''; - $lastToken = 0; - foreach (token_get_all($content) as $key => $token) { - if (is_array($token)) { - if (in_array($token[0], array(T_COMMENT, T_WHITESPACE, T_DOC_COMMENT))) { - continue; - } - $compressContent .= ' ' . $token[1]; - } else { - $compressContent .= $token; - } - $lastToken = $token[0]; - } - return $compressContent; - } + /** + * 去除php标识 + * + * @param string $content 需要处理的内容 + * @param mixed $replace 将php标识替换为该值,默认为空 + * @return string + */ + public function stripPhpIdentify($content, $replace = '') + { + return preg_replace('/(?:<\?(?:php)*)|(\?>)/i', $replace, $content); + } - /** - * 从文件列表中取得对应的每个文件的内容 - * - * @param mixed $fileList 文件列表 - * @param method $packMethod 打包方式,默认为stripWhiteSpaceByPhp - * @param array $content 保存文件内容,默认为空数组 - * @return array: - */ - public function readContentFromFileList(array $fileList, $packMethod = WindPack::STRIP_PHP, &$content = array()) { - if (empty($fileList) || false === $this->isValidatePackMethod($packMethod)) return array(); - - foreach ($fileList as $key => $value) { - $parents = class_parents($key); - $_fileList = $this->buildFileList($parents, $fileList); - $this->readContentFromFileList($_fileList, $packMethod, $content); - $implements = class_implements($key); - $_fileList = $this->buildFileList($implements, $fileList); - $this->readContentFromFileList($_fileList, $packMethod, $content); - if (in_array($key, $this->packList)) continue; - if (is_file($value)) { - $content[] = $this->$packMethod($value); - $this->packList[] = $key; - } - } - } + /** + * 根据指定规则替换指定内容中相应的内容 + * + * @param string $content 需要处理的内容 + * @param string $rule 需要匹配的正则 + * @param $mixed $replace 用来替换将匹配出来的结果,默认为空 + * @return string + */ + public function stripStrByRule($content, $rule, $replace = '') + { + return preg_replace("/$rule/", $replace, $content); + } - /** - * 去除注释 - * - * @param string $content 要去除的内容 - * @param mixed $replace 要替换的文本 - * @return string - */ - public function stripComment($content, $replace = '') { - return preg_replace('/(?:\/\*.*\*\/)*|(?:\/\/[^\r\n]*[\r\n])*/Us', $replace, $content); - } + /** + * 去除多余的文件导入信息 + * + * @param string $content 需要处理的内容 + * @param mixed $replace 用来替换将匹配出来的结果,默认为空 + * @return string + */ + public function stripImport($content, $replace = '') + { + $str = preg_match_all('/L[\t ]*::[\t ]*import[\t ]*\([\t ]*[\'\"]([^$][\w\.:]+)[\"\'][\t ]*\)[\t ]*/', $content, + $matchs); + if ($matchs[1]) { + foreach ($matchs[1] as $key => $value) { + $name = substr($value, strrpos($value, '.') + 1); + if (preg_match("/(abstract[\t ]*|class|interface)[\t ]+$name/i", $content)) { + $strip = str_replace(array('(', ')'), array('\(', '\)'), addslashes($matchs[0][$key])).'[\t ]*;'; + $content = $this->stripStrByRule($content, $strip, $replace); + } + } + } - /** - * 去除换行 - * - * @param string $content 要去除的内容 - * @param mixed $replace 要替换的文本 - * @return string - */ - public function stripNR($content, $replace = array('\n','\r\n','\r')) { - return preg_replace('/[\n\r]+/', $replace, $content); - } + return $content; + } - /** - * 去除空格符 - * - * @param string $content 要去除的内容 - * @param mixed $replace 要替换的文本,默认为空 - * @return string - */ - public function stripSpace($content, $replace = ' ') { - return preg_replace('/[ ]+/', $replace, $content); - } + /** + * 从文件读取内容 + * + * @param string $filename 文件名 + * @return string 如果给出的文件不是一个有效文件则返回false + */ + public function getContentFromFile($filename) + { + if (is_file($filename)) { + $content = ''; + $fp = fopen($filename, 'r'); + while (!feof($fp)) { + $line = fgets($fp); + if (in_array(strlen($line), array(2, 3)) && in_array(ord($line), array(9, 10, 13))) { + continue; + } + $content .= $line; + } + fclose($fp); - /** - * 去除php标识 - * - * @param string $content 需要处理的内容 - * @param mixed $replace 将php标识替换为该值,默认为空 - * @return string - */ - public function stripPhpIdentify($content, $replace = '') { - return preg_replace('/(?:<\?(?:php)*)|(\?>)/i', $replace, $content); - } + return $content; + } - /** - * 根据指定规则替换指定内容中相应的内容 - * - * @param string $content 需要处理的内容 - * @param string $rule 需要匹配的正则 - * @param $mixed $replace 用来替换将匹配出来的结果,默认为空 - * @return string - */ - public function stripStrByRule($content, $rule, $replace = '') { - return preg_replace("/$rule/", $replace, $content); - } + return false; + } - /** - * 去除多余的文件导入信息 - * - * @param string $content 需要处理的内容 - * @param mixed $replace 用来替换将匹配出来的结果,默认为空 - * @return string - */ - public function stripImport($content, $replace = '') { - $str = preg_match_all('/L[\t ]*::[\t ]*import[\t ]*\([\t ]*[\'\"]([^$][\w\.:]+)[\"\'][\t ]*\)[\t ]*/', $content, - $matchs); - if ($matchs[1]) { - foreach ($matchs[1] as $key => $value) { - $name = substr($value, strrpos($value, '.') + 1); - if (preg_match("/(abstract[\t ]*|class|interface)[\t ]+$name/i", $content)) { - $strip = str_replace(array('(', ')'), array('\(', '\)'), addslashes($matchs[0][$key])) . '[\t ]*;'; - $content = $this->stripStrByRule($content, $strip, $replace); - } - } - } - return $content; - } + /** + * 构造文件列表 + * + * @param array $list 需要处理的文件列表 + * @param array $fileList 文件列表 + * @return array 保存$list中存在于$fileList中的文件列表 + */ + private function buildFileList(array $list, $fileList) + { + $_temp = array(); + foreach ($list as $fileName) { + foreach ($fileList as $key => $value) { + if ($key == $fileName) { + $_temp[$key] = $value; + break; + } + } + } - /** - * 从文件读取内容 - * - * @param string $filename 文件名 - * @return string 如果给出的文件不是一个有效文件则返回false - */ - public function getContentFromFile($filename) { - if (is_file($filename)) { - $content = ''; - $fp = fopen($filename, "r"); - while (!feof($fp)) { - $line = fgets($fp); - if (in_array(strlen($line), array(2, 3)) && in_array(ord($line), array(9, 10, 13))) continue; - $content .= $line; - } - fclose($fp); - return $content; - } - return false; - } + return $_temp; + } - /** - * 构造文件列表 - * - * @param array $list 需要处理的文件列表 - * @param array $fileList 文件列表 - * @return array 保存$list中存在于$fileList中的文件列表 - */ - private function buildFileList(array $list, $fileList) { - $_temp = array(); - foreach ($list as $fileName) { - foreach ($fileList as $key => $value) { - if ($key == $fileName) { - $_temp[$key] = $value; - break; - } - } - } - return $_temp; - } + /** + * 设置回调 + * + * @author Qiong Wu + * @param array $contentInjectionCallBack 回调函数 + * @param string $position 调用位置(before|after)默认为before + */ + public function setContentInjectionCallBack($contentInjectionCallBack, $position = 'before') + { + if (!in_array($position, array('before', 'after'))) { + $position = 'before'; + } + $this->contentInjectionPosition = $position; + $this->contentInjectionCallBack = $contentInjectionCallBack; + } - /** - * 设置回调 - * - * @author Qiong Wu - * @param array $contentInjectionCallBack 回调函数 - * @param string $position 调用位置(before|after)默认为before - * @return void - */ - public function setContentInjectionCallBack($contentInjectionCallBack, $position = 'before') { - if (!in_array($position, array('before', 'after'))) $position = 'before'; - $this->contentInjectionPosition = $position; - $this->contentInjectionCallBack = $contentInjectionCallBack; - } + /** + * 回调函数调用 + * + * @param string $content 被回调的内容 + * @param string $replace 替换内容,默认为空 + * @return string + */ + public function callBack($content, $replace = '') + { + if ($this->contentInjectionCallBack !== '') { + $_content = call_user_func_array($this->contentInjectionCallBack, array($this->packList)); + if ($this->contentInjectionPosition == 'before') { + $content = $replace.$_content.$content; + } elseif ($this->contentInjectionPosition == 'after') { + $content .= $replace.$_content.$replace; + } + } - /** - * 回调函数调用 - * - * @param string $content 被回调的内容 - * @param string $replace 替换内容,默认为空 - * @return string - */ - public function callBack($content, $replace = '') { - if ($this->contentInjectionCallBack !== '') { - $_content = call_user_func_array($this->contentInjectionCallBack, array($this->packList)); - if ($this->contentInjectionPosition == 'before') { - $content = $replace . $_content . $content; - } elseif ($this->contentInjectionPosition == 'after') { - $content .= $replace . $_content . $replace; - } - } - return $content; - } + return $content; + } - /** - * 检查打包方法的有效性 - * - * @param string $packMethod 被检查的方法 - * @return boolean - */ - private function isValidatePackMethod($packMethod) { - return method_exists($this, $packMethod) && in_array($packMethod, - array(WindPack::STRIP_PHP, WindPack::STRIP_SELF, WindPack::STRIP_TOKEN)); - } -} \ No newline at end of file + /** + * 检查打包方法的有效性 + * + * @param string $packMethod 被检查的方法 + * @return bool + */ + private function isValidatePackMethod($packMethod) + { + return method_exists($this, $packMethod) && in_array($packMethod, + array(WindPack::STRIP_PHP, WindPack::STRIP_SELF, WindPack::STRIP_TOKEN)); + } +} diff --git a/wind/utility/WindSecurity.php b/wind/utility/WindSecurity.php index 0cfde2e4..976620cc 100644 --- a/wind/utility/WindSecurity.php +++ b/wind/utility/WindSecurity.php @@ -1,124 +1,166 @@ * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindSecurity.php 3939 2013-05-29 06:22:57Z xiaoxia.xuxx $ * @package utility */ -class WindSecurity { - - /** - * 转义输出字符串 - * - * @param string $str 被转义的字符串 - * @return string - */ - public static function escapeHTML($str) { - if (!is_string($str)) return $str; - return htmlspecialchars($str, ENT_QUOTES); - } - - /** - * 转义字符串 - * - * @param array $array 被转移的数组 - * @return array - */ - public static function escapeArrayHTML($array) { - if (!is_array($array) || count($array) > 100) return $array; - $_tmp = array(); - foreach ($array as $key => $value) { - is_string($key) && $key = self::escapeHTML($key); - $_tmp[$key] = self::escapeHTML($value); - } - return $_tmp; - } - - /** - * 字符串加密 - * - * @param string $str 需要加密的字符串 - * @param string $key 密钥 - * @return string 加密后的结果 - */ - public static function encrypt($str, $key, $iv = '') { - if (!$key || !is_string($key)) throw new WindException( - '[utility.WindSecurity.encrypt] security key is required. ', WindException::ERROR_PARAMETER_TYPE_ERROR); - if (!$str || !is_string($str)) throw new WindException( - '[utility.WindSecurity.encrypt] security string is required.', WindException::ERROR_PARAMETER_TYPE_ERROR); - - $size = mcrypt_get_block_size(MCRYPT_DES, MCRYPT_MODE_CBC); - $iv = substr(md5($iv ? $iv : $key), -$size); - $pad = $size - (strlen($str) % $size); - $str .= str_repeat(chr($pad), $pad); - @$data = mcrypt_cbc(MCRYPT_DES, $key, $str, MCRYPT_ENCRYPT, $iv); - return base64_encode($data); - } - - /** - * 解密字符串 - * - * @param string $str 解密的字符串 - * @param string $key 密钥 - * @return string 解密后的结果 - */ - public static function decrypt($str, $key, $iv = '') { - if (!$str || !is_string($str)) throw new WindException( - '[utility.WindSecurity.dncrypt] security string is required.', WindException::ERROR_PARAMETER_TYPE_ERROR); - if (!$key || !is_string($key)) throw new WindException('[utility.WindSecurity.decrypt] security key is required.', - WindException::ERROR_PARAMETER_TYPE_ERROR); - - $size = mcrypt_get_block_size(MCRYPT_DES, MCRYPT_MODE_CBC); - $iv = substr(md5($iv ? $iv : $key), -$size); - $str = base64_decode($str); - @$str = mcrypt_cbc(MCRYPT_DES, $key, $str, MCRYPT_DECRYPT, $iv); - $pad = ord($str{strlen($str) - 1}); - if ($pad > strlen($str)) return false; - if (strspn($str, chr($pad), strlen($str) - $pad) != $pad) return false; - return substr($str, 0, -1 * $pad); - } - - /** - * 创建token令牌串 - * - * 创建token令牌串,用于避免表单重复提交等. - * 使用当前的sessionID以及当前时间戳,生成唯一一串令牌串,并返回. - * @deprecated - * @return string - */ - public static function createToken() { - return self::generateGUID(); - } - - /** - * 获取唯一标识符串,标识符串的长度为16个字节,128位. - * - * 根据当前时间与sessionID,混合生成一个唯一的串. - * @return string GUID串,16个字节 - */ - public static function generateGUID() { - return substr(md5(WindUtility::generateRandStr(8) . microtime()), -16); - } - - /** - * 路径检查转义 - * - * @param string $fileName 被检查的路径 - * @param boolean $ifCheck 是否需要检查文件名,默认为false - * @return string - */ - public static function escapePath($filePath, $ifCheck = false) { - $_tmp = array("'" => '', '#' => '', '=' => '', '`' => '', '$' => '', '%' => '', '&' => '', ';' => ''); - $_tmp['://'] = $_tmp["\0"] = ''; - $ifCheck && $_tmp['..'] = ''; - if (strtr($filePath, $_tmp) == $filePath) return preg_replace('/[\/\\\]{1,}/i', '/', $filePath); - if (WIND_DEBUG & 2) { - Wind::getApp()->getComponent('windLogger')->info( - "[utility.WindSecurity.escapePath] file path is illegal.\r\n\tFilePath:" . $filePath); - } - throw new WindException('[utility.WindSecurity.escapePath] file path is illegal'); - } -} \ No newline at end of file +class WindSecurity +{ + /** + * 输出json到页面 + * 添加转义 + * + * @param mixed $source + * @param string $charset + * @return string + */ + public static function escapeEncodeJson($source, $charset = 'utf-8') + { + return WindJson::encode(is_string($source) ? self::escapeHTML($source) : self::escapeArrayHTML($source), $charset); + } + + /** + * 转义输出字符串 + * + * @param string $str 被转义的字符串 + * @return string + */ + public static function escapeHTML($str, $charset = 'ISO-8859-1') + { + if (!is_string($str)) { + return $str; + } + + return htmlspecialchars($str, ENT_QUOTES, $charset); + } + + /** + * 转义字符串 + * + * @param array $array 被转移的数组 + * @return array + */ + public static function escapeArrayHTML($array) + { + if (!is_array($array)) { + return self::escapeHTML($array); + } + $_tmp = array(); + foreach ($array as $key => $value) { + is_string($key) && $key = self::escapeHTML($key); + $_tmp[$key] = is_array($value) ? self::escapeArrayHTML($value) : self::escapeHTML($value); + } + + return $_tmp; + } + + /** + * 字符串加密 + * + * @param string $str 需要加密的字符串 + * @param string $key 密钥 + * @return string 加密后的结果 + */ + public static function encrypt($str, $key, $iv = '') + { + if (!$key || !is_string($key)) { + throw new WindException( + '[utility.WindSecurity.encrypt] security key is required. ', WindException::ERROR_PARAMETER_TYPE_ERROR); + } + if (!$str || !is_string($str)) { + throw new WindException( + '[utility.WindSecurity.encrypt] security string is required.', WindException::ERROR_PARAMETER_TYPE_ERROR); + } + + $size = mcrypt_get_block_size(MCRYPT_DES, MCRYPT_MODE_CBC); + $iv = substr(md5($iv ? $iv : $key), -$size); + $pad = $size - (strlen($str) % $size); + $str .= str_repeat(chr($pad), $pad); + @$data = mcrypt_cbc(MCRYPT_DES, $key, $str, MCRYPT_ENCRYPT, $iv); + + return base64_encode($data); + } + + /** + * 解密字符串 + * + * @param string $str 解密的字符串 + * @param string $key 密钥 + * @return string 解密后的结果 + */ + public static function decrypt($str, $key, $iv = '') + { + if (!$str || !is_string($str)) { + throw new WindException( + '[utility.WindSecurity.decrypt] security string is required.', WindException::ERROR_PARAMETER_TYPE_ERROR); + } + if (!$key || !is_string($key)) { + throw new WindException( + '[utility.WindSecurity.decrypt] security key is required.', WindException::ERROR_PARAMETER_TYPE_ERROR); + } + + $size = mcrypt_get_block_size(MCRYPT_DES, MCRYPT_MODE_CBC); + $iv = substr(md5($iv ? $iv : $key), -$size); + $str = base64_decode($str); + @$str = mcrypt_cbc(MCRYPT_DES, $key, $str, MCRYPT_DECRYPT, $iv); + $pad = ord($str{strlen($str) - 1}); + if ($pad > strlen($str)) { + return false; + } + if (strspn($str, chr($pad), strlen($str) - $pad) != $pad) { + return false; + } + + return substr($str, 0, -1 * $pad); + } + + /** + * 创建token令牌串 + * 创建token令牌串,用于避免表单重复提交等. + * 使用当前的sessionID以及当前时间戳,生成唯一一串令牌串,并返回. + * + * @deprecated + * + * @return string + */ + public static function createToken() + { + return self::generateGUID(); + } + + /** + * 获取唯一标识符串,标识符串的长度为16个字节,128位. + * 根据当前时间与sessionID,混合生成一个唯一的串. + * + * @return string GUID串,16个字节 + */ + public static function generateGUID() + { + return substr(md5(WindUtility::generateRandStr(8).microtime()), -16); + } + + /** + * 路径检查转义 + * + * @param string $fileName 被检查的路径 + * @param bool $ifCheck 是否需要检查文件名,默认为false + * @return string + */ + public static function escapePath($filePath, $ifCheck = false) + { + $_tmp = array("'" => '', '#' => '', '=' => '', '`' => '', '$' => '', '%' => '', '&' => '', ';' => ''); + $_tmp['://'] = $_tmp["\0"] = ''; + $ifCheck && $_tmp['..'] = ''; + if (strtr($filePath, $_tmp) == $filePath) { + return preg_replace('/[\/\\\]{1,}/i', '/', $filePath); + } + throw new WindException('[utility.WindSecurity.escapePath] file path is illegal'); + } +} diff --git a/wind/utility/WindString.php b/wind/utility/WindString.php index dfebef0d..25a78d2a 100644 --- a/wind/utility/WindString.php +++ b/wind/utility/WindString.php @@ -5,237 +5,276 @@ * @author Qian Su * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindString.php 3760 2012-10-11 08:02:25Z yishuo $ * @package utility */ -class WindString { - - const UTF8 = 'utf-8'; - - const GBK = 'gbk'; - - /** - * 截取字符串,支持字符编码,默认为utf-8 - * - * @param string $string 要截取的字符串编码 - * @param int $start 开始截取 - * @param int $length 截取的长度 - * @param string $charset 原妈编码,默认为UTF8 - * @param boolean $dot 是否显示省略号,默认为false - * @return string 截取后的字串 - */ - public static function substr($string, $start, $length, $charset = self::UTF8, $dot = false) { - switch (strtolower($charset)) { - case self::GBK: - $string = self::substrForGbk($string, $start, $length, $dot); - break; - default: - $string = self::substrForUtf8($string, $start, $length, $dot); - break; - } - return $string; - } - - /** - * 求取字符串长度 - * - * @param string $string 要计算的字符串编码 - * @param string $charset 原始编码,默认为UTF8 - * @return int - */ - public static function strlen($string, $charset = self::UTF8) { - $len = strlen($string); - $i = $count = 0; - $charset = strtolower(substr($charset, 0, 3)); - while ($i < $len) { - if (ord($string[$i]) <= 129) - $i++; - else - switch ($charset) { - case 'utf': - $i += 3; - break; - default: - $i += 2; - break; - } - $count++; - } - return $count; - } - - /** - * 将变量的值转换为字符串 - * - * @param mixed $input 变量 - * @param string $indent 缩进,默认为'' - * @return string - */ - public static function varToString($input, $indent = '') { - switch (gettype($input)) { - case 'string': - return "'" . str_replace(array("\\", "'"), array("\\\\", "\\'"), $input) . "'"; - case 'array': - $output = "array(\r\n"; - foreach ($input as $key => $value) { - $output .= $indent . "\t" . self::varToString($key, $indent . "\t") . ' => ' . self::varToString( - $value, $indent . "\t"); - $output .= ",\r\n"; - } - $output .= $indent . ')'; - return $output; - case 'boolean': - return $input ? 'true' : 'false'; - case 'NULL': - return 'NULL'; - case 'integer': - case 'double': - case 'float': - return "'" . (string) $input . "'"; - } - return 'NULL'; - } - - /** - * 将数据用json加密 - * - * @param mixed $value 需要加密的数据 - * @param string $charset 字符编码 - * @return string 加密后的数据 - */ - public static function jsonEncode($value, $charset = self::UTF8) { - Wind::import('Wind:utility.WindJson'); - return WindJson::encode($value, $charset); - } - - /** - * 将json格式数据解密 - * - * @param string $value 待解密的数据 - * @param string $charset 解密后字符串编码 - * @return mixed 解密后的数据 - */ - public static function jsonDecode($value, $charset = self::UTF8) { - Wind::import('Wind:utility.WindJson'); - return WindJson::decode($value, true, $charset); - } - - /** - * 以utf8格式截取的字符串编码 - * - * @param string $string 要截取的字符串编码 - * @param int $start 开始截取 - * @param int $length 截取的长度,默认为null,取字符串的全长 - * @param boolean $dot 是否显示省略号,默认为false - * @return string - */ - public static function substrForUtf8($string, $start, $length = null, $dot = false) { - if (empty($string)) return ''; - $strlen = strlen($string); - $length = $length ? (int) $length : $strlen; - $substr = ''; - $chinese = $word = 0; - for ($i = 0, $j = 0; $i < (int) $start; $i++) { - if (0xa0 < ord(substr($string, $j, 1))) { - $chinese++; - $j += 2; - } else { - $word++; - } - $j++; - } - $start = $word + 3 * $chinese; - for ($i = $start, $j = $start; $i < $start + $length; $i++) { - if (0xa0 < ord(substr($string, $j, 1))) { - $substr .= substr($string, $j, 3); - $j += 2; - } else { - $substr .= substr($string, $j, 1); - } - $j++; - } - (strlen($substr) < $strlen) && $dot && $substr .= "..."; - return $substr; - } - - /** - * 以gbk格式截取的字符串编码 - * - * @param string $string 要截取的字符串编码 - * @param int $start 开始截取 - * @param int $length 截取的长度,默认为null,取字符串的全长 - * @param boolean $dot 是否显示省略号,默认为false - * @return string - */ - public static function substrForGbk($string, $start, $length = null, $dot = false) { - if (empty($string) || !is_int($start) || ($length && !is_int($length))) { - return ''; - } - $strlen = strlen($string); - $length = $length ? $length : $strlen; - $substr = ''; - $chinese = $word = 0; - for ($i = 0, $j = 0; $i < $start; $i++) { - if (0xa0 < ord(substr($string, $j, 1))) { - $chinese++; - $j++; - } else { - $word++; - } - $j++; - } - $start = $word + 2 * $chinese; - for ($i = $start, $j = $start; $i < $start + $length; $i++) { - if (0xa0 < ord(substr($string, $j, 1))) { - $substr .= substr($string, $j, 2); - $j++; - } else { - $substr .= substr($string, $j, 1); - } - $j++; - } - (strlen($substr) < $strlen) && $dot && $substr .= "..."; - return $substr; - } - - /** - * 以utf8求取字符串长度 - * - * @param string $str 要计算的字符串编码 - * @return int - */ - public static function strlenForUtf8($str) { - $i = $count = 0; - $len = strlen($str); - while ($i < $len) { - $chr = ord($str[$i]); - $count++; - $i++; - if ($i >= $len) break; - if ($chr & 0x80) { - $chr <<= 1; - while ($chr & 0x80) { - $i++; - $chr <<= 1; - } - } - } - return $count; - } - - /** - * 以gbk求取字符串长度 - * - * @param string $str 要计算的字符串编码 - * @return int - */ - public static function strlenForGbk($string) { - $len = strlen($string); - $i = $count = 0; - while ($i < $len) { - ord($string[$i]) > 129 ? $i += 2 : $i++; - $count++; - } - return $count; - } -} \ No newline at end of file +class WindString +{ + const UTF8 = 'utf-8'; + const GBK = 'gbk'; + + /** + * 截取字符串,支持字符编码,默认为utf-8 + * + * @param string $string 要截取的字符串编码 + * @param int $start 开始截取 + * @param int $length 截取的长度 + * @param string $charset 原妈编码,默认为UTF8 + * @param bool $dot 是否显示省略号,默认为false + * @return string 截取后的字串 + */ + public static function substr($string, $start, $length, $charset = self::UTF8, $dot = false) + { + switch (strtolower($charset)) { + case self::GBK: + $string = self::substrForGbk($string, $start, $length, $dot); + break; + case self::UTF8: + $string = self::substrForUtf8($string, $start, $length, $dot); + break; + default: + $string = substr($string, $start, $length); + } + + return $string; + } + + /** + * 求取字符串长度 + * + * @param string $string 要计算的字符串编码 + * @param string $charset 原始编码,默认为UTF8 + * @return int + */ + public static function strlen($string, $charset = self::UTF8) + { + switch (strtolower($charset)) { + case self::GBK: + $count = self::strlenForGbk($string); + break; + case self::UTF8: + $count = self::strlenForUtf8($string); + break; + default: + $count = strlen($string); + } + + return $count; + } + + /** + * 将变量的值转换为字符串 + * + * @param mixed $input 变量 + * @param string $indent 缩进,默认为'' + * @return string + */ + public static function varToString($input, $indent = '') + { + switch (gettype($input)) { + case 'string': + return "'".str_replace(array('\\', "'"), array('\\\\', "\\'"), $input)."'"; + case 'array': + $output = "array(\r\n"; + foreach ($input as $key => $value) { + $output .= $indent."\t".self::varToString($key, $indent."\t").' => '.self::varToString( + $value, $indent."\t"); + $output .= ",\r\n"; + } + $output .= $indent.')'; + + return $output; + case 'boolean': + return $input ? 'true' : 'false'; + case 'NULL': + return 'NULL'; + case 'integer': + case 'double': + case 'float': + return "'".(string) $input."'"; + } + + return 'NULL'; + } + + /** + * 将数据用json加密 + * + * @param mixed $value 需要加密的数据 + * @param string $charset 字符编码 + * @return string 加密后的数据 + */ + public static function jsonEncode($value, $charset = self::UTF8) + { + return WindJson::encode($value, $charset); + } + + /** + * 将json格式数据解密 + * + * @param string $value 待解密的数据 + * @param string $charset 解密后字符串编码 + * @return mixed 解密后的数据 + */ + public static function jsonDecode($value, $charset = self::UTF8) + { + return WindJson::decode($value, true, $charset); + } + + /** + * 以utf8格式截取的字符串编码 + * + * @param string $string 要截取的字符串编码 + * @param int $start 开始截取 + * @param int $length 截取的长度,默认为null,取字符串的全长 + * @param bool $dot 是否显示省略号,默认为false + * @return string + */ + public static function substrForUtf8($string, $start, $length = null, $dot = false) + { + $l = strlen($string); + $p = $s = 0; + if (0 !== $start) { + while ($start-- && $p < $l) { + $c = $string[$p]; + if ($c < "\xC0") { + $p++; + } elseif ($c < "\xE0") { + $p += 2; + } elseif ($c < "\xF0") { + $p += 3; + } elseif ($c < "\xF8") { + $p += 4; + } elseif ($c < "\xFC") { + $p += 5; + } else { + $p += 6; + } + } + $s = $p; + } + + if (empty($length)) { + $t = substr($string, $s); + } else { + $i = $length; + while ($i-- && $p < $l) { + $c = $string[$p]; + if ($c < "\xC0") { + $p++; + } elseif ($c < "\xE0") { + $p += 2; + } elseif ($c < "\xF0") { + $p += 3; + } elseif ($c < "\xF8") { + $p += 4; + } elseif ($c < "\xFC") { + $p += 5; + } else { + $p += 6; + } + } + $t = substr($string, $s, $p - $s); + } + + $dot && ($p < $l) && $t .= '...'; + + return $t; + } + + /** + * 以gbk格式截取的字符串编码 + * + * @param string $string 要截取的字符串编码 + * @param int $start 开始截取 + * @param int $length 截取的长度,默认为null,取字符串的全长 + * @param bool $dot 是否显示省略号,默认为false + * @return string + */ + public static function substrForGbk($string, $start, $length = null, $dot = false) + { + $l = strlen($string); + $p = $s = 0; + if (0 !== $start) { + while ($start-- && $p < $l) { + if ($string[$p] > "\x80") { + $p += 2; + } else { + $p++; + } + } + $s = $p; + } + + if (empty($length)) { + $t = substr($string, $s); + } else { + $i = $length; + while ($i-- && $p < $l) { + if ($string[$p] > "\x80") { + $p += 2; + } else { + $p++; + } + } + $t = substr($string, $s, $p - $s); + } + + $dot && ($p < $l) && $t .= '...'; + + return $t; + } + + /** + * 以utf8求取字符串长度 + * + * @param string $string 要计算的字符串编码 + * @return int + */ + public static function strlenForUtf8($string) + { + $l = strlen($string); + $p = $c = 0; + while ($p < $l) { + $a = $string[$p]; + if ($a < "\xC0") { + $p++; + } elseif ($a < "\xE0") { + $p += 2; + } elseif ($a < "\xF0") { + $p += 3; + } elseif ($a < "\xF8") { + $p += 4; + } elseif ($a < "\xFC") { + $p += 5; + } else { + $p += 6; + } + $c++; + } + + return $c; + } + + /** + * 以gbk求取字符串长度 + * + * @param string $string 要计算的字符串编码 + * @return int + */ + public static function strlenForGbk($string) + { + $l = strlen($string); + $p = $c = 0; + while ($p < $l) { + if ($string[$p] > "\x80") { + $p += 2; + } else { + $p++; + } + $c++; + } + + return $c; + } +} diff --git a/wind/utility/WindUrlHelper.php b/wind/utility/WindUrlHelper.php new file mode 100644 index 00000000..7a54bdbd --- /dev/null +++ b/wind/utility/WindUrlHelper.php @@ -0,0 +1,154 @@ + + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id: WindUrlHelper.php 3928 2013-01-29 10:21:53Z yishuo $ + * @package web + */ +class WindUrlHelper +{ + /** + * url检查 + * + * 当$absolute === true且url不包含协议部分时,默认加上当前应用的协议部分. + * @param string $url 需要检查合法性的url + * @param bool $absolute 是否为绝对路径 + * @return string + */ + public static function checkUrl($url, $absolute = true) + { + if ($absolute) { + $_baseUrl = $absolute === true ? Wind::getComponent('request')->getBaseUrl(true) : $absolute; + if (strpos($url, '://') === false) { + $url = trim($_baseUrl, '/').'/'.trim($url, '/'); + } + } + + return $url; + } + + /** + * url字符串转化为数组格式 + * + * 效果同'argsToUrl'相反 + * @param string $url + * @param bool $decode 是否需要进行url反编码处理 + * @param string $separator url的分隔符 + * @return array + */ + public static function urlToArgs($url, $decode = true, $separator = '&=') + { + if (strlen($separator) !== 2) { + return array(); + } + if (false !== $pos = strpos($url, '?')) { + $url = substr($url, $pos + 1); + } + $url = explode($separator[0], trim($url, $separator[0])); + $args = array(); + if ($separator[0] === $separator[1]) { + $_count = count($url); + for ($i = 0; $i < $_count; $i += 2) { + if (!isset($url[$i + 1])) { + $args[] = $decode ? rawurldecode($url[$i]) : $url[$i]; + continue; + } + $_k = $decode ? rawurldecode($url[$i]) : $url[$i]; + $_v = $decode ? rawurldecode($url[$i + 1]) : $url[$i + 1]; + $args[$_k] = $_v; + } + } else { + foreach ($url as $value) { + if (strpos($value, $separator[1]) === false) { + $args[] = $decode ? rawurldecode($value) : $value; + continue; + } + list($__k, $__v) = explode($separator[1], $value); + $args[$__k] = $decode && $__v ? rawurldecode($__v) : $__v; + } + } + + return $args; + } + + /** + * 将数组格式的参数列表转换为Url格式,并将url进行编码处理 + * + * 参数:array('b'=>'b','c'=>'index','d'=>'d') + * 分割符: '&=' + * 转化结果:&b=b&c=index&d=d + * 如果分割符为: '/' 则转化结果为: /b/b/c/index/d/d/ + * @param array $args + * @param bool $encode 是否进行url编码 默认值为true + * @param string $separator url分隔符 支持双字符,前一个字符用于分割参数对,后一个字符用于分割键值对 + * @return string + */ + public static function argsToUrl($args, $encode = true, $separator = '&=', $key = null) + { + if (strlen($separator) !== 2) { + return; + } + $_tmp = ''; + foreach ((array) $args as $_k => $_v) { + if ($key !== null) { + $_k = $key.'['.$_k.']'; + } + if (is_array($_v)) { + $_tmp .= self::argsToUrl($_v, $encode, $separator, $_k).$separator[0]; + continue; + } + $_v = $encode ? rawurlencode($_v) : $_v; + if (is_int($_k)) { + $_v && $_tmp .= $_v.$separator[0]; + continue; + } + $_k = ($encode ? rawurlencode($_k) : $_k); + $_tmp .= $_k.$separator[1].$_v.$separator[0]; + } + + return trim($_tmp, $separator[0]); + } + + /** + * 解析ControllerPath,并返回解析后的结果集 + * + * 返回值:array(action,controller,module,args) + * action格式:'/module/controller/action/?a=a&b=b&c=c&',前边用斜线分割mca信息,后边用问号分割参数列表. + * @param string $controllerPath + * @param array $args 默认值为空数组 + * @return array + */ + public static function resolveAction($action, $args = array()) + { + list($action, $_args) = explode('?', $action.'?'); + $args = array_merge($args, ($_args ? self::urlToArgs($_args, false) : array())); + $action = explode('/', trim($action, '/').'/'); + end($action); + + return array(prev($action), prev($action), prev($action), $args); + } + + /** + * 构造并返回Url地址 + * + * 将根据是否开启url重写来分别构造相对应的url + * @param string $action 执行的操作 + * @param array $args 附带的参数 + * @param string $anchor url锚点 + * @param AbstractWindRoute $route + * @param bool $absolute 是否返回绝对地址 + * @return string 返回url地址 + */ + public static function createUrl($action, $args = array(), $anchor = '', $route = null, $absolute = true) + { + /* @var $router AbstractWindRouter */ + $router = Wind::getComponent('router'); + $url = $router->assemble($action, $args, $route); + $url .= $anchor ? '#'.$anchor : ''; + + return self::checkUrl($url, $absolute); + } +} diff --git a/wind/utility/WindUtility.php b/wind/utility/WindUtility.php index 54f311ef..1f8d0f09 100644 --- a/wind/utility/WindUtility.php +++ b/wind/utility/WindUtility.php @@ -1,245 +1,209 @@ - * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindUtility.php 3859 2012-12-18 09:25:51Z yishuo $ * @package utility - */ -class WindUtility { - - /** - * 解析表达式 - * - * 表达式格式: namespace:arg1.arg2.arg3.arg4.arg5==value - * 返回: array($namespace, $param1, $operator, $param1) - * - * @param string $expression 待解析的表达式 - * @return array 返回解析后的表达式,由表达式的各项组成的数组: - *
      - *
    • 第一个元素: 命名空间
    • - *
    • 第二个元素: 表达式的左边操作数
    • - *
    • 第三个元素: 表达式的操作符
    • - *
    • 第四个元素: 表达式的右边操作数
    • - *
    - */ - public static function resolveExpression($expression) { - $operators = array('==', '!=', '<', '>', '<=', '>='); - $operatorsReplace = array('#==#', '#!=#', '#<#', '#>#', '#<=#', '#>=#'); - list($p, $o, $v2) = explode('#', str_replace($operators, $operatorsReplace, $expression)); - if (strpos($p, ":") !== false) - list($_namespace, $p) = explode(':', trim($p, ':')); - else - $_namespace = ''; - return array($_namespace, $p, $o, $v2); - } - - /** - * 执行简单的条件表达式 - * - * 只能执行==、!=、<、>、<=、>=简单的比较 - * - * @param string $v1 左边的操作数 - * @param string $v2 右边的操作数 - * @param string $operator 操作符号 - * @return boolean - */ - public static function evalExpression($v1, $v2, $operator) { - switch ($operator) { - case '==': - return $v1 == $v2; - case '!=': - return $v1 != $v2; - case '<': - return $v1 < $v2; - case '>': - return $v1 > $v2; - case '<=': - return $v1 <= $v2; - case '>=': - return $v1 >= $v2; - default: - return false; - } - return false; - } - - /** - * 递归合并两个数组 - * - * @param array $array1 数组1 - * @param array $array2 数组2 - * @return array 合并后的数组 - */ - public static function mergeArray($array1, $array2) { - foreach ($array2 as $key => $value) { - if (empty($value)) { - $array1[$key] = $value; - } else if (!isset($array1[$key])) { - $array1[$key] = $value; - } elseif (is_array($array1[$key]) && is_array($value)) { - $array1[$key] = self::mergeArray($array1[$key], $array2[$key]); - } elseif (is_numeric($key) && $array1[$key] !== $array2[$key]) { - $array1[] = $value; - } else - $array1[$key] = $value; - } - return $array1; - } - - /** - * 将字符串首字母小写 - * - * @param string $str 待处理的字符串 - * @return string 返回处理后的字符串 - */ - public static function lcfirst($str) { - $str[0] = strtolower($str[0]); - return $str; - } - - /** - * 获得随机数字符串 - * - * @param int $length 随机数的长度 - * @return string 随机获得的字串 - */ - public static function generateRandStr($length) { - $randstr = ""; - for ($i = 0; $i < (int) $length; $i++) { - $randnum = mt_rand(0, 61); - if ($randnum < 10) { - $randstr .= chr($randnum + 48); - } else if ($randnum < 36) { - $randstr .= chr($randnum + 55); - } else { - $randstr .= chr($randnum + 61); - } - } - return $randstr; - } - - /** - * 通用组装测试验证规则 - * - * @param string $field 验证字段名称 - * @param string $validator 验证方法 - * @param array $args 验证方法中传递的其他参数,需在待验证字段值的后面,默认为空数组 - * @param string $default 验证失败是设置的默认值,默认为null - * @param string $message 验证失败是返回的错误信息,默认为空字串 - * @return array 返回验证规则 - *
      - *
    • field: 验证字段名称
    • - *
    • validator: 验证方法
    • - *
    • args: 验证方法中传递的其他参数,需在待验证字段值的后面,缺省为空数组
    • - *
    • default: 验证失败是设置的默认值,缺省为null
    • - *
    • message: 验证失败是返回的错误信息,默认为'提示:XX验证失败'
    • - *
    - */ - public static function buildValidateRule($field, $validator, $args = array(), $default = null, $message = '') { - return array( - 'field' => $field, - 'validator' => $validator, - 'args' => (array) $args, - 'default' => $default, - 'message' => ($message ? $message : '提示:\'' . $field . '\'验证失败')); - } - - /** - * 对字符串中的参数进行替换 - * - * 该函优化了php strtr()实现, 在进行数组方式的字符替换时支持了两种模式的字符替换: - * @example
    -	 * 1. echo WindUtility::strtr("I Love {you}",array('{you}' => 'lili')); 
    -	 * 结果: I Love lili
    -	 * 2. echo WindUtility::strtr("I Love #0,#1",array('lili','qiong')); 
    -	 * 结果: I Love lili,qiong
    -	 * 
    -	 * @see WindLangResource::getMessage()
    -	 * @param string $str
    -	 * @param string $from
    -	 * @param string $to 可选参数,默认值为''
    -	 * @return string
    -	 */
    -	public static function strtr($str, $from, $to = '') {
    -		if (is_string($from)) return strtr($str, $from, $to);
    -		if (isset($from[0])) {
    -			foreach ($from as $key => $value) {
    -				$from['#' . $key] = $value;
    -				unset($from[$key]);
    -			}
    -		}
    -		return !empty($from) ? strtr($str, $from) : $str;
    -	}
    -
    -	/**
    -	 * 错误信息处理方法
    -	 *
    -	 * @param string $file
    -	 * @param string $line
    -	 * @param array $trace
    -	 */
    -	public static function crash($file, $line, $trace) {
    -		$msg = '';
    -		$count = count($trace);
    -		$padLen = strlen($count);
    -		foreach ($trace as $key => $call) {
    -			if (!isset($call['file']) || $call['file'] == '') {
    -				$call['file'] = '~Internal Location~';
    -				$call['line'] = 'N/A';
    -			}
    -			$traceLine = '#' . str_pad(($count - $key), $padLen, "0", STR_PAD_LEFT) . '  ' . self::getCallLine(
    -				$call);
    -			$trace[$key] = $traceLine;
    -		}
    -		$fileLines = array();
    -		if (is_file($file)) {
    -			$currentLine = $line - 1;
    -			$fileLines = explode("\n", file_get_contents($file, null, null, 0, 10000000));
    -			$topLine = $currentLine - 5;
    -			$fileLines = array_slice($fileLines, $topLine > 0 ? $topLine : 0, 10, true);
    -			if (($count = count($fileLines)) > 0) {
    -				$padLen = strlen($count);
    -				foreach ($fileLines as $line => &$fileLine)
    -					$fileLine = " " . htmlspecialchars(
    -						str_pad($line + 1, $padLen, "0", STR_PAD_LEFT) . ": " . str_replace("\t", 
    -							"    ", rtrim($fileLine)), null, "UTF-8");
    -			}
    -		}
    -		return array($fileLines, $trace);
    -	}
    -
    -	/**
    -	 * @param array $call
    -	 * @return string
    -	 */
    -	private static function getCallLine($call) {
    -		$call_signature = "";
    -		if (isset($call['file'])) $call_signature .= $call['file'] . " ";
    -		if (isset($call['line'])) $call_signature .= "(" . $call['line'] . ") ";
    -		if (isset($call['function'])) {
    -			$call_signature .= $call['function'] . "(";
    -			if (isset($call['args'])) {
    -				foreach ($call['args'] as $arg) {
    -					if (is_string($arg))
    -						$arg = '"' . (strlen($arg) <= 64 ? $arg : substr($arg, 0, 64) . "…") . '"';
    -					else if (is_object($arg))
    -						$arg = "[Instance of '" . get_class($arg) . "']";
    -					else if ($arg === true)
    -						$arg = "true";
    -					else if ($arg === false)
    -						$arg = "false";
    -					else if ($arg === null)
    -						$arg = "null";
    -					else
    -						$arg = strval($arg);
    -					$call_signature .= $arg . ',';
    -				}
    -			}
    -			$call_signature = trim($call_signature, ',') . ")";
    -		}
    -		return $call_signature;
    -	}
    -}
    \ No newline at end of file
    + */
    +class WindUtility
    +{
    +    /**
    +     * 解析表达式
    +     *
    +     * 表达式格式: namespace:arg1.arg2.arg3.arg4.arg5==value
    +     * 返回: array($namespace, $param1, $operator, $param1)
    +     *
    +     * @param  string $expression
    +     *                            待解析的表达式
    +     * @return array  返回解析后的表达式,由表达式的各项组成的数组:
    +     *                           
      + *
    • 第一个元素: 命名空间
    • + *
    • 第二个元素: 表达式的左边操作数
    • + *
    • 第三个元素: 表达式的操作符
    • + *
    • 第四个元素: 表达式的右边操作数
    • + *
    + */ + public static function resolveExpression($expression) + { + $operators = array('==', '!=', '<', '>', '<=', '>='); + $operatorsReplace = array('#==#', '#!=#', '#<#', '#>#', '#<=#', '#>=#'); + list($p, $o, $v2) = explode('#', str_replace($operators, $operatorsReplace, $expression)); + if (strpos($p, ':') !== false) { + list($_namespace, $p) = explode(':', trim($p, ':')); + } else { + $_namespace = ''; + } + + return array($_namespace, $p, $o, $v2); + } + + /** + * 执行简单的条件表达式 + * + * 只能执行==、!=、<、>、<=、>=简单的比较 + * + * @param string $v1 + * 左边的操作数 + * @param string $v2 + * 右边的操作数 + * @param string $operator + * 操作符号 + * @return bool + */ + public static function evalExpression($v1, $v2, $operator) + { + switch ($operator) { + case '==': + return $v1 == $v2; + case '!=': + return $v1 != $v2; + case '<': + return $v1 < $v2; + case '>': + return $v1 > $v2; + case '<=': + return $v1 <= $v2; + case '>=': + return $v1 >= $v2; + default: + return false; + } + + return false; + } + + /** + * 递归合并两个数组 + * + * @param array $array1 + * 数组1 + * @param array $array2 + * 数组2 + * @return array 合并后的数组 + */ + public static function mergeArray($array1, $array2) + { + foreach ($array2 as $key => $value) { + if (!isset($array1[$key])) { + $array1[$key] = $value; + } elseif (is_array($array1[$key]) && is_array($value)) { + $array1[$key] = self::mergeArray($array1[$key], $array2[$key]); + } elseif (is_numeric($key) && $array1[$key] !== $array2[$key]) { + $array1[] = $value; + } else { + $array1[$key] = $value; + } + } + + return $array1; + } + + /** + * 将字符串首字母小写 + * + * @param string $str + * 待处理的字符串 + * @return string 返回处理后的字符串 + */ + public static function lcfirst($str) + { + $str[0] = strtolower($str[0]); + + return $str; + } + + /** + * 获得随机数字符串 + * + * @param int $length + * 随机数的长度 + * @return string 随机获得的字串 + */ + public static function generateRandStr($length) + { + $mt_string = 'AzBy0CxDwEv1FuGtHs2IrJqK3pLoM4nNmOlP5kQjRi6ShTgU7fVeW8dXcY9bZa'; + $randstr = ''; + for ($i = 0; $i < $length; $i++) { + $randstr .= $mt_string[mt_rand(0, 61)]; + } + + return $randstr; + } + + /** + * 通用组装测试验证规则 + * + * @param string $field + * 验证字段名称 + * @param string $validator + * 验证方法 + * @param array $args + * 验证方法中传递的其他参数,需在待验证字段值的后面,默认为空数组 + * @param string $default + * 验证失败是设置的默认值,默认为null + * @param string $message + * 验证失败是返回的错误信息,默认为空字串 + * @return array 返回验证规则 + *
      + *
    • field: 验证字段名称
    • + *
    • validator: 验证方法
    • + *
    • args: 验证方法中传递的其他参数,需在待验证字段值的后面,缺省为空数组
    • + *
    • default: 验证失败是设置的默认值,缺省为null
    • + *
    • message: 验证失败是返回的错误信息,默认为'提示:XX验证失败'
    • + *
    + */ + public static function buildValidateRule($field, $validator, $args = array(), $default = null, $message = '') + { + return array( + 'field' => $field, + 'validator' => $validator, + 'args' => (array) $args, + 'default' => $default, + 'message' => ($message ? $message : '提示:\''.$field.'\'验证失败'), ); + } + + /** + * 对字符串中的参数进行替换 + * + * 该函优化了php strtr()实现, 在进行数组方式的字符替换时支持了两种模式的字符替换: + * + * @example
    +     *          1. echo WindUtility::strtr("I Love {you}",array('{you}' =>
    +     *          'lili'));
    +     *          结果: I Love lili
    +     *          2. echo WindUtility::strtr("I Love
    +     *          #0,#1",array('lili','qiong'));
    +     *          结果: I Love lili,qiong
    +     *          
    +     * @see WindLangResource::getMessage()
    +     * @param  string $str
    +     * @param  string $from
    +     * @param  string $to
    +     *                      可选参数,默认值为''
    +     * @return string
    +     */
    +    public static function strtr($str, $from, $to = '')
    +    {
    +        if (is_string($from)) {
    +            return strtr($str, $from, $to);
    +        }
    +        if (isset($from[0])) {
    +            foreach ($from as $key => $value) {
    +                $from['#'.$key] = $value;
    +                unset($from[$key]);
    +            }
    +        }
    +
    +        return !empty($from) ? strtr($str, $from) : $str;
    +    }
    +
    +    public static function dump(/* $a, $b, ... */)
    +    {
    +        foreach (func_get_args() as $var) {
    +            error_log(var_export($var, true));
    +        }
    +    }
    +}
    diff --git a/wind/utility/WindValidator.php b/wind/utility/WindValidator.php
    index f478be60..936890ca 100644
    --- a/wind/utility/WindValidator.php
    +++ b/wind/utility/WindValidator.php
    @@ -5,204 +5,221 @@
      * @author Qian Su 
      * @copyright ©2003-2103 phpwind.com
      * @license http://www.windframework.com
    - * @version $Id$
    + * @version $Id: WindValidator.php 2973 2011-10-15 19:22:48Z yishuo $
      * @package utility
      */
    -class WindValidator {
    +class WindValidator
    +{
    +    /**
    +     * 验证是否是电话号码
    +     *
    +     * 国际区号-地区号-电话号码的格式(在国际区号前可以有前导0和前导+号),
    +     * 国际区号支持0-4位
    +     * 地区号支持0-6位
    +     * 电话号码支持4到12位
    +     *
    +     * @param  string $phone 被验证的电话号码
    +     * @return bool   如果验证通过则返回true,否则返回false
    +     */
    +    public static function isTelPhone($phone)
    +    {
    +        return 0 < preg_match('/^\+?[0\s]*[\d]{0,4}[\-\s]?\d{0,6}[\-\s]?\d{4,12}$/', $phone);
    +    }
     
    -	/**
    -	 * 验证是否是电话号码
    -	 * 
    -	 * 国际区号-地区号-电话号码的格式(在国际区号前可以有前导0和前导+号),
    -	 * 国际区号支持0-4位
    -	 * 地区号支持0-6位
    -	 * 电话号码支持4到12位
    -	 * 
    -	 * @param string $phone 被验证的电话号码
    -	 * @return boolean 如果验证通过则返回true,否则返回false
    -	 */
    -	public static function isTelPhone($phone) {
    -		return 0 < preg_match('/^\+?[0\s]*[\d]{0,4}[\-\s]?\d{0,6}[\-\s]?\d{4,12}$/', $phone);
    -	}
    +    /**
    +     * 验证是否是手机号码
    +     *
    +     * 国际区号-手机号码
    +     *
    +     * @param  string $number 待验证的号码
    +     * @return bool   如果验证失败返回false,验证成功返回true
    +     */
    +    public static function isTelNumber($number)
    +    {
    +        return 0 < preg_match('/^\+?[0\s]*[\d]{0,4}[\-\s]?\d{4,12}$/', $number);
    +    }
     
    -	/**
    -	 * 验证是否是手机号码
    -	 * 
    -	 * 国际区号-手机号码
    -	 *
    -	 * @param string $number 待验证的号码
    -	 * @return boolean 如果验证失败返回false,验证成功返回true
    -	 */
    -	public static function isTelNumber($number) {
    -		return 0 < preg_match('/^\+?[0\s]*[\d]{0,4}[\-\s]?\d{4,12}$/', $number);
    -	}
    +    /**
    +     * 验证是否是QQ号码
    +     *
    +     * QQ号码必须是以1-9的数字开头,并且长度5-15为的数字串
    +     *
    +     * @param  string $qq 待验证的qq号码
    +     * @return bool   如果验证成功返回true,否则返回false
    +     */
    +    public static function isQQ($qq)
    +    {
    +        return 0 < preg_match('/^[1-9]\d{4,14}$/', $qq);
    +    }
     
    -	/**
    -	 * 验证是否是QQ号码
    -	 * 
    -	 * QQ号码必须是以1-9的数字开头,并且长度5-15为的数字串
    -	 *
    -	 * @param string $qq 待验证的qq号码
    -	 * @return boolean 如果验证成功返回true,否则返回false
    -	 */
    -	public static function isQQ($qq) {
    -		return 0 < preg_match('/^[1-9]\d{4,14}$/', $qq);
    -	}
    +    /**
    +     * 验证是否是邮政编码
    +     *
    +     * 邮政编码是4-8个长度的数字串
    +     *
    +     * @param  string $zipcode 待验证的邮编
    +     * @return bool   如果验证成功返回true,否则返回false
    +     */
    +    public static function isZipcode($zipcode)
    +    {
    +        return 0 < preg_match('/^\d{4,8}$/', $zipcode);
    +    }
     
    -	/**
    -	 * 验证是否是邮政编码
    -	 * 
    -	 * 邮政编码是4-8个长度的数字串
    -	 *
    -	 * @param string $zipcode 待验证的邮编
    -	 * @return boolean 如果验证成功返回true,否则返回false
    -	 */
    -	public static function isZipcode($zipcode) {
    -		return 0 < preg_match('/^\d{4,8}$/', $zipcode);
    -	}
    +    /**
    +     * 验证是否是有合法的email
    +     *
    +     * @param  string $string  被搜索的 字符串
    +     * @param  array  $matches 会被搜索的结果,默认为array()
    +     * @param  bool   $ifAll   是否进行全局正则表达式匹配,默认为false即仅进行一次匹配
    +     * @return bool   如果匹配成功返回true,否则返回false
    +     */
    +    public static function hasEmail($string, &$matches = array(), $ifAll = false)
    +    {
    +        return 0 < self::validateByRegExp("/\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/", $string);
    +    }
     
    -	/**
    -	 * 验证是否是有合法的email
    -	 * 
    -	 * @param string $string  被搜索的 字符串
    -	 * @param array $matches  会被搜索的结果,默认为array()
    -	 * @param boolean $ifAll  是否进行全局正则表达式匹配,默认为false即仅进行一次匹配
    -	 * @return boolean 如果匹配成功返回true,否则返回false
    -	 */
    -	public static function hasEmail($string, &$matches = array(), $ifAll = false) {
    -		return 0 < self::validateByRegExp("/\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/", $string);
    -	}
    +    /**
    +     * 验证是否是合法的email
    +     *
    +     * @param  string $string 待验证的字串
    +     * @return bool   如果是email则返回true,否则返回false
    +     */
    +    public static function isEmail($string)
    +    {
    +        return 0 < preg_match("/^\w+(?:[-+.']\w+)*@\w+(?:[-.]\w+)*\.\w+(?:[-.]\w+)*$/", $string);
    +    }
     
    -	/**
    -	 * 验证是否是合法的email
    -	 * 
    -	 * @param string $string 待验证的字串
    -	 * @return boolean 如果是email则返回true,否则返回false
    -	 */
    -	public static function isEmail($string) {
    -		return 0 < preg_match("/^\w+(?:[-+.']\w+)*@\w+(?:[-.]\w+)*\.\w+(?:[-.]\w+)*$/", $string);
    -	}
    +    /**
    +     * 验证是否有合法的身份证号
    +     *
    +     * @param  string $string  被搜索的 字符串
    +     * @param  array  $matches 会被搜索的结果,默认为array()
    +     * @param  bool   $ifAll   是否进行全局正则表达式匹配,默认为false即仅进行一次匹配
    +     * @return bool   如果匹配成功返回true,否则返回false
    +     */
    +    public static function hasIdCard($string, &$matches = array(), $ifAll = false)
    +    {
    +        return 0 < self::validateByRegExp("/\d{17}[\d|X]|\d{15}/", $string, $matches, $ifAll);
    +    }
     
    -	/**
    -	 * 验证是否有合法的身份证号
    -	 * 
    -	 * @param string $string  被搜索的 字符串
    -	 * @param array $matches  会被搜索的结果,默认为array()
    -	 * @param boolean $ifAll  是否进行全局正则表达式匹配,默认为false即仅进行一次匹配
    -	 * @return boolean 如果匹配成功返回true,否则返回false
    -	 */
    -	public static function hasIdCard($string, &$matches = array(), $ifAll = false) {
    -		return 0 < self::validateByRegExp("/\d{17}[\d|X]|\d{15}/", $string, $matches, $ifAll);
    -	}
    +    /**
    +     * 验证是否是合法的身份证号
    +     *
    +     * @param  string $string 待验证的字串
    +     * @return bool   如果是合法的身份证号则返回true,否则返回false
    +     */
    +    public static function isIdCard($string)
    +    {
    +        return 0 < preg_match("/^(?:\d{17}[\d|X]|\d{15})$/", $string);
    +    }
     
    -	/**
    -	 * 验证是否是合法的身份证号
    -	 * 
    -	 * @param string $string 待验证的字串
    -	 * @return boolean 如果是合法的身份证号则返回true,否则返回false
    -	 */
    -	public static function isIdCard($string) {
    -		return 0 < preg_match("/^(?:\d{17}[\d|X]|\d{15})$/", $string);
    -	}
    +    /**
    +     * 验证是否有合法的URL
    +     *
    +     * @param  string $string  被搜索的 字符串
    +     * @param  array  $matches 会被搜索的结果,默认为array()
    +     * @param  bool   $ifAll   是否进行全局正则表达式匹配,默认为false即仅进行一次匹配
    +     * @return bool   如果匹配成功返回true,否则返回false
    +     */
    +    public static function hasUrl($string, &$matches = array(), $ifAll = false)
    +    {
    +        return 0 < self::validateByRegExp('/http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/', $string, $matches, $ifAll);
    +    }
     
    -	/**
    -	 * 验证是否有合法的URL
    -	 * 
    -	 * @param string $string  被搜索的 字符串
    -	 * @param array $matches  会被搜索的结果,默认为array()
    -	 * @param boolean $ifAll  是否进行全局正则表达式匹配,默认为false即仅进行一次匹配
    -	 * @return boolean 如果匹配成功返回true,否则返回false
    -	 */
    -	public static function hasUrl($string, &$matches = array(), $ifAll = false) {
    -		return 0 < self::validateByRegExp('/http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/', $string, $matches, $ifAll);
    -	}
    +    /**
    +     * 验证是否是合法的url
    +     *
    +     * @param  string $string 待验证的字串
    +     * @return bool   如果是合法的url则返回true,否则返回false
    +     */
    +    public static function isUrl($string)
    +    {
    +        return 0 < preg_match('/^(?:http(?:s)?:\/\/(?:[\w-]+\.)+[\w-]+(?:\:\d+)*+(?:\/[\w- .\/?%&=]*)?)$/', $string);
    +    }
     
    -	/**
    -	 * 验证是否是合法的url
    -	 * 
    -	 * @param string $string 待验证的字串
    -	 * @return boolean 如果是合法的url则返回true,否则返回false
    -	 */
    -	public static function isUrl($string) {
    -		return 0 < preg_match('/^(?:http(?:s)?:\/\/(?:[\w-]+\.)+[\w-]+(?:\:\d+)*+(?:\/[\w- .\/?%&=]*)?)$/', $string);
    -	}
    +    /**
    +     * 验证是否有中文
    +     *
    +     * @param  string $string  被搜索的 字符串
    +     * @param  array  $matches 会被搜索的结果,默认为array()
    +     * @param  bool   $ifAll   是否进行全局正则表达式匹配,默认为false即仅进行一次匹配
    +     * @return bool   如果匹配成功返回true,否则返回false
    +     */
    +    public static function hasChinese($string, &$matches = array(), $ifAll = false)
    +    {
    +        return 0 < self::validateByRegExp('/[\x{4e00}-\x{9fa5}]+/u', $string, $matches, $ifAll);
    +    }
     
    -	/**
    -	 * 验证是否有中文
    -	 * 
    -	 * @param string $string  被搜索的 字符串
    -	 * @param array $matches  会被搜索的结果,默认为array()
    -	 * @param boolean $ifAll  是否进行全局正则表达式匹配,默认为false即仅进行一次匹配
    -	 * @return boolean 如果匹配成功返回true,否则返回false
    -	 */
    -	public static function hasChinese($string, &$matches = array(), $ifAll = false) {
    -		return 0 < self::validateByRegExp('/[\x{4e00}-\x{9fa5}]+/u', $string, $matches, $ifAll);
    -	}
    +    /**
    +     * 验证是否是中文
    +     *
    +     * @param  string $string 待验证的字串
    +     * @return bool   如果是中文则返回true,否则返回false
    +     */
    +    public static function isChinese($string)
    +    {
    +        return 0 < preg_match('/^[\x{4e00}-\x{9fa5}]+$/u', $string);
    +    }
     
    -	/**
    -	 * 验证是否是中文
    -	 * 
    -	 * @param string $string 待验证的字串
    -	 * @return boolean 如果是中文则返回true,否则返回false
    -	 */
    -	public static function isChinese($string) {
    -		return 0 < preg_match('/^[\x{4e00}-\x{9fa5}]+$/u', $string);
    -	}
    +    /**
    +     * 验证是否有html标记
    +     *
    +     * @param  string $string  被搜索的 字符串
    +     * @param  array  $matches 会被搜索的结果,默认为array()
    +     * @param  bool   $ifAll   是否进行全局正则表达式匹配,默认为false即仅进行一次匹配
    +     * @return bool   如果匹配成功返回true,否则返回false
    +     */
    +    public static function hasHtml($string, &$matches = array(), $ifAll = false)
    +    {
    +        return 0 < self::validateByRegExp('/<(.*)>.*|<(.*)\/>/', $string, $matches, $ifAll);
    +    }
     
    -	/**
    -	 * 验证是否有html标记
    -	 * 
    -	 * @param string $string  被搜索的 字符串
    -	 * @param array $matches  会被搜索的结果,默认为array()
    -	 * @param boolean $ifAll  是否进行全局正则表达式匹配,默认为false即仅进行一次匹配
    -	 * @return boolean 如果匹配成功返回true,否则返回false
    -	 */
    -	public static function hasHtml($string, &$matches = array(), $ifAll = false) {
    -		return 0 < self::validateByRegExp('/<(.*)>.*|<(.*)\/>/', $string, $matches, $ifAll);
    -	}
    +    /**
    +     * 验证是否是合法的html标记
    +     *
    +     * @param  string $string 待验证的字串
    +     * @return bool   如果是合法的html标记则返回true,否则返回false
    +     */
    +    public static function isHtml($string)
    +    {
    +        return 0 < preg_match('/^<(.*)>.*|<(.*)\/>$/', $string);
    +    }
     
    -	/**
    -	 * 验证是否是合法的html标记
    -	 * 
    -	 * @param string $string 待验证的字串
    -	 * @return boolean 如果是合法的html标记则返回true,否则返回false
    -	 */
    -	public static function isHtml($string) {
    -		return 0 < preg_match('/^<(.*)>.*|<(.*)\/>$/', $string);
    -	}
    +    /**
    +     * 验证是否有合法的ipv4地址
    +     *
    +     * @param  string $string  被搜索的 字符串
    +     * @param  array  $matches 会被搜索的结果,默认为array()
    +     * @param  bool   $ifAll   是否进行全局正则表达式匹配,默认为false即仅进行一次匹配
    +     * @return bool   如果匹配成功返回true,否则返回false
    +     */
    +    public static function hasIpv4($string, &$matches = array(), $ifAll = false)
    +    {
    +        return 0 < self::validateByRegExp('/((25[0-5]|2[0-4]\d|1\d{2}|0?[1-9]\d|0?0?\d)\.){3}(25[0-5]|2[0-4]\d|1\d{2}|0?[1-9]\d|0?0?\d)/', $string, $matches, $ifAll);
    +    }
     
    -	/**
    -	 * 验证是否有合法的ipv4地址
    -	 * 
    -	 * @param string $string   被搜索的 字符串
    -	 * @param array $matches   会被搜索的结果,默认为array()
    -	 * @param boolean $ifAll   是否进行全局正则表达式匹配,默认为false即仅进行一次匹配
    -	 * @return boolean 如果匹配成功返回true,否则返回false
    -	 */
    -	public static function hasIpv4($string, &$matches = array(), $ifAll = false) {
    -		return 0 < self::validateByRegExp('/((25[0-5]|2[0-4]\d|1\d{2}|0?[1-9]\d|0?0?\d)\.){3}(25[0-5]|2[0-4]\d|1\d{2}|0?[1-9]\d|0?0?\d)/', $string, $matches, $ifAll);
    -	}
    +    /**
    +     * 验证是否是合法的IP
    +     *
    +     * @param  string $string 待验证的字串
    +     * @return bool   如果是合法的IP则返回true,否则返回false
    +     */
    +    public static function isIpv4($string)
    +    {
    +        return 0 < preg_match('/(?:(?:25[0-5]|2[0-4]\d|1\d{2}|0?[1-9]\d|0?0?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|0?[1-9]\d|0?0?\d)/', $string);
    +    }
     
    -	/**
    -	 * 验证是否是合法的IP
    -	 * 
    -	 * @param string $string 待验证的字串
    -	 * @return boolean 如果是合法的IP则返回true,否则返回false
    -	 */
    -	public static function isIpv4($string) {
    -		return 0 < preg_match('/(?:(?:25[0-5]|2[0-4]\d|1\d{2}|0?[1-9]\d|0?0?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|0?[1-9]\d|0?0?\d)/', $string);
    -	}
    -
    -	/**
    -	 * 验证是否有合法的ipV6
    -	 *
    -	 * @param string $string 被搜索的 字符串
    -	 * @param array $matches 会被搜索的结果,默认为array()
    -	 * @param boolean $ifAll 是否进行全局正则表达式匹配,默认为false即仅进行一次匹配
    -	 * @return boolean 如果匹配成功返回true,否则返回false
    -	 */
    -	public static function hasIpv6($string, &$matches = array(), $ifAll = false) {
    -		return 0 < self::validateByRegExp('/\A((([a-f0-9]{1,4}:){6}|
    +    /**
    +     * 验证是否有合法的ipV6
    +     *
    +     * @param  string $string  被搜索的 字符串
    +     * @param  array  $matches 会被搜索的结果,默认为array()
    +     * @param  bool   $ifAll   是否进行全局正则表达式匹配,默认为false即仅进行一次匹配
    +     * @return bool   如果匹配成功返回true,否则返回false
    +     */
    +    public static function hasIpv6($string, &$matches = array(), $ifAll = false)
    +    {
    +        return 0 < self::validateByRegExp('/\A((([a-f0-9]{1,4}:){6}|
     										::([a-f0-9]{1,4}:){5}|
     										([a-f0-9]{1,4})?::([a-f0-9]{1,4}:){4}|
     										(([a-f0-9]{1,4}:){0,1}[a-f0-9]{1,4})?::([a-f0-9]{1,4}:){3}|
    @@ -216,16 +233,17 @@ public static function hasIpv6($string, &$matches = array(), $ifAll = false) {
     										(([a-f0-9]{1,4}:){0,6}[a-f0-9]{1,4})?::
     									)
     								)\Z/ix', $string, $matches, $ifAll);
    -	}
    +    }
     
    -	/**
    -	 * 验证是否是合法的ipV6
    -	 *
    -	 * @param string $string 待验证的字串
    -	 * @return boolean 如果是合法的ipV6则返回true,否则返回false
    -	 */
    -	public static function isIpv6($string) {
    -		return 0 < preg_match('/\A(?:(?:(?:[a-f0-9]{1,4}:){6}|
    +    /**
    +     * 验证是否是合法的ipV6
    +     *
    +     * @param  string $string 待验证的字串
    +     * @return bool   如果是合法的ipV6则返回true,否则返回false
    +     */
    +    public static function isIpv6($string)
    +    {
    +        return 0 < preg_match('/\A(?:(?:(?:[a-f0-9]{1,4}:){6}|
     										::(?:[a-f0-9]{1,4}:){5}|
     										(?:[a-f0-9]{1,4})?::(?:[a-f0-9]{1,4}:){4}|
     										(?:(?:[a-f0-9]{1,4}:){0,1}[a-f0-9]{1,4})?::(?:[a-f0-9]{1,4}:){3}|
    @@ -239,93 +257,100 @@ public static function isIpv6($string) {
     										(?:(?:[a-f0-9]{1,4}:){0,6}[a-f0-9]{1,4})?::
     									)
     								)\Z/ix', $string);
    -	}
    +    }
     
    -	/**
    -	 * 验证是否有客户端脚本
    -	 * 
    -	 * @param string $string 被搜索的 字符串
    -	 * @param array $matches 会被搜索的结果,默认为array()
    -	 * @param boolean $ifAll 是否进行全局正则表达式匹配,默认为false即仅进行一次匹配
    -	 * @return boolean 如果匹配成功返回true,否则返回false
    -	 */
    -	public static function hasScript($string, &$matches = array(), $ifAll = false) {
    -		return 0 < self::validateByRegExp('/([^\x00]*?)<\/script>/', $string, $matches, $ifAll);
    -	}
    +    /**
    +     * 验证是否有客户端脚本
    +     *
    +     * @param  string $string  被搜索的 字符串
    +     * @param  array  $matches 会被搜索的结果,默认为array()
    +     * @param  bool   $ifAll   是否进行全局正则表达式匹配,默认为false即仅进行一次匹配
    +     * @return bool   如果匹配成功返回true,否则返回false
    +     */
    +    public static function hasScript($string, &$matches = array(), $ifAll = false)
    +    {
    +        return 0 < self::validateByRegExp('/([^\x00]*?)<\/script>/', $string, $matches, $ifAll);
    +    }
     
    -	/**
    -	 * 验证是否是合法的客户端脚本
    -	 * 
    -	 * @param string $string 待验证的字串
    -	 * @return boolean 如果是合法的客户端脚本则返回true,否则返回false
    -	 */
    -	public static function isScript($string) {
    -		return 0 < preg_match('/(?:[^\x00]*?)<\/script>/', $string);
    -	}
    +    /**
    +     * 验证是否是合法的客户端脚本
    +     *
    +     * @param  string $string 待验证的字串
    +     * @return bool   如果是合法的客户端脚本则返回true,否则返回false
    +     */
    +    public static function isScript($string)
    +    {
    +        return 0 < preg_match('/(?:[^\x00]*?)<\/script>/', $string);
    +    }
     
    -	/**
    -	 * 验证是否是非负数
    -	 * 
    -	 * @param int $number 需要被验证的数字 
    -	 * @return boolean 如果大于等于0的整数数字返回true,否则返回false
    -	 */
    -	public static function isNonNegative($number) {
    -		return is_numeric($number) && 0 <= $number;
    -	}
    +    /**
    +     * 验证是否是非负数
    +     *
    +     * @param  int  $number 需要被验证的数字
    +     * @return bool 如果大于等于0的整数数字返回true,否则返回false
    +     */
    +    public static function isNonNegative($number)
    +    {
    +        return is_numeric($number) && 0 <= $number;
    +    }
     
    -	/**
    -	 * 验证是否是正数
    -	 * 
    -	 * @param int $number 需要被验证的数字
    -	 * @return boolean 如果数字大于0则返回true否则返回false
    -	 */
    -	public static function isPositive($number) {
    -		return is_numeric($number) && 0 < $number;
    -	}
    +    /**
    +     * 验证是否是正数
    +     *
    +     * @param  int  $number 需要被验证的数字
    +     * @return bool 如果数字大于0则返回true否则返回false
    +     */
    +    public static function isPositive($number)
    +    {
    +        return is_numeric($number) && 0 < $number;
    +    }
     
    -	/**
    -	 * 验证是否是负数
    -	 * 
    -	 * @param int $number  需要被验证的数字
    -	 * @return boolean 如果数字小于于0则返回true否则返回false
    -	 */
    -	public static function isNegative($number) {
    -		return is_numeric($number) && 0 > $number;
    -	}
    +    /**
    +     * 验证是否是负数
    +     *
    +     * @param  int  $number 需要被验证的数字
    +     * @return bool 如果数字小于于0则返回true否则返回false
    +     */
    +    public static function isNegative($number)
    +    {
    +        return is_numeric($number) && 0 > $number;
    +    }
     
    -	/**
    -	 * 验证是否是不能为空
    -	 *
    -	 * @param mixed $value 待判断的数据
    -	 * @return boolean 如果为空则返回false,不为空返回true
    -	 */
    -	public static function isRequired($value) {
    -		return !empty($value);
    -	}
    +    /**
    +     * 验证是否是不能为空
    +     *
    +     * @param  mixed $value 待判断的数据
    +     * @return bool  如果为空则返回false,不为空返回true
    +     */
    +    public static function isRequired($value)
    +    {
    +        return !empty($value);
    +    }
     
    -	/**
    -	 * 验证字符串的长度
    -	 * 
    -	 * @param string $string 要验证的字符串
    -	 * @param string $length 指定的合法的长度
    -	 * @param string $charset 字符编码默认为utf-8编码
    -	 * @return boolean 如果长度大于给定的长度则返回true,否则返回false
    -	 */
    -	public static function isLegalLength($string, $length, $charset = 'utf8') {
    -		Wind::import('WIND:utility.WindString');
    -		return WindString::strlen($string, $charset) > (int) $length;
    -	}
    +    /**
    +     * 验证字符串的长度
    +     *
    +     * @param  string $string  要验证的字符串
    +     * @param  string $length  指定的合法的长度
    +     * @param  string $charset 字符编码默认为utf-8编码
    +     * @return bool   如果长度大于给定的长度则返回true,否则返回false
    +     */
    +    public static function isLegalLength($string, $length, $charset = 'utf8')
    +    {
    +        return WindString::strlen($string, $charset) > (int) $length;
    +    }
     
    -	/**
    -	 * 在 $string 字符串中搜索与 $regExp 给出的正则表达式相匹配的内容。
    -	 * 
    -	 * @param string $regExp  搜索的规则(正则) 
    -	 * @param string $string  被搜索的 字符串
    -	 * @param array $matches 会被搜索的结果,默认为array()
    -	 * @param boolean $ifAll   是否进行全局正则表达式匹配,默认为false不进行完全匹配
    -	 * @return int 返回匹配的次数
    -	 */
    -	private static function validateByRegExp($regExp, $string, &$matches = array(), $ifAll = false) {
    -		return $ifAll ? preg_match_all($regExp, $string, $matches) : preg_match($regExp, $string, $matches);
    -	}
    -}
    \ No newline at end of file
    +    /**
    +     * 在 $string 字符串中搜索与 $regExp 给出的正则表达式相匹配的内容。
    +     *
    +     * @param  string $regExp  搜索的规则(正则)
    +     * @param  string $string  被搜索的 字符串
    +     * @param  array  $matches 会被搜索的结果,默认为array()
    +     * @param  bool   $ifAll   是否进行全局正则表达式匹配,默认为false不进行完全匹配
    +     * @return int    返回匹配的次数
    +     */
    +    private static function validateByRegExp($regExp, $string, &$matches = array(), $ifAll = false)
    +    {
    +        return $ifAll ? preg_match_all($regExp, $string, $matches) : preg_match($regExp, $string, $matches);
    +    }
    +}
    diff --git a/wind/viewer/AbstractWindTemplateCompiler.php b/wind/viewer/AbstractWindTemplateCompiler.php
    index b2c32970..e21b0762 100644
    --- a/wind/viewer/AbstractWindTemplateCompiler.php
    +++ b/wind/viewer/AbstractWindTemplateCompiler.php
    @@ -1,145 +1,159 @@
     
      * @copyright ©2003-2103 phpwind.com
      * @license http://www.windframework.com
    - * @version $Id$
    + * @version $Id: AbstractWindTemplateCompiler.php 3533 2012-05-08 08:24:20Z yishuo $
      * @package viewer
      */
    -abstract class AbstractWindTemplateCompiler extends WindHandlerInterceptor {
    -	/**
    -	 * @var array
    -	 */
    -	protected $tags= array();
    -	/**
    -	 * @var WindViewTemplate
    -	 */
    -	protected $windViewTemplate = null;
    -	/**
    -	 * @var WindViewerResolver
    -	 */
    -	protected $windViewerResolver = null;
    -	/**
    -	 * @var WindHttpRequest
    -	 */
    -	protected $request = null;
    -	/**
    -	 * @var WindHttpResponse
    -	 */
    -	protected $response = null;
    -	/**
    -	 * @var array
    -	 */
    -	protected $_propertiesCache = array();
    +abstract class AbstractWindTemplateCompiler extends WindHandlerInterceptor
    +{
    +    /**
    +     * @var array
    +     */
    +    protected $tags = array();
    +    /**
    +     * @var WindViewTemplate
    +     */
    +    protected $windViewTemplate = null;
    +    /**
    +     * @var WindViewerResolver
    +     */
    +    protected $windViewerResolver = null;
    +    /**
    +     * @var WindHttpRequest
    +     */
    +    protected $request = null;
    +    /**
    +     * @var WindHttpResponse
    +     */
    +    protected $response = null;
    +    /**
    +     * @var array
    +     */
    +    protected $_propertiesCache = array();
     
    -	/**
    -	 * 初始化标签解析器
    -	 * 
    -	 * @param string $tags
    -	 * @param WindViewTemplate $windViewTemplate
    -	 * @param WindViewerResolver $windViewerResolver
    -	 * @param WindHttpRequest $request
    -	 * @param WindHttpResponse $response
    -	 */
    -	public function __construct($tags, $windViewTemplate, $windViewerResolver, $request, $response) {
    -		$this->tags = $tags;
    -		$this->windViewTemplate = $windViewTemplate;
    -		$this->windViewerResolver = $windViewerResolver;
    -		$this->request = $request;
    -		$this->response = $response;
    -	}
    +    /**
    +     * 初始化标签解析器
    +     *
    +     * @param string             $tags
    +     * @param WindViewTemplate   $windViewTemplate
    +     * @param WindViewerResolver $windViewerResolver
    +     * @param WindHttpRequest    $request
    +     * @param WindHttpResponse   $response
    +     */
    +    public function __construct($tags, $windViewTemplate, $windViewerResolver, $request, $response)
    +    {
    +        $this->tags = $tags;
    +        $this->windViewTemplate = $windViewTemplate;
    +        $this->windViewerResolver = $windViewerResolver;
    +        $this->request = $request;
    +        $this->response = $response;
    +    }
     
    -	/**
    -	 * 内容编译,接受一段落内容进行编译处理并返回编译内容
    -	 * 
    -	 * @param string $key 
    -	 * @param string $content 模板内容
    -	 * @return string 输出编译后结果
    -	 */
    -	abstract public function compile($key, $content);
    +    /**
    +     * 内容编译,接受一段落内容进行编译处理并返回编译内容
    +     *
    +     * @param  string $key
    +     * @param  string $content 模板内容
    +     * @return string 输出编译后结果
    +     */
    +    abstract public function compile($key, $content);
     
    -	/**
    -	 * 编译前预处理
    -	 * 
    -	 * @return void
    -	 */
    -	protected function preCompile() {}
    +    /**
    +     * 编译前预处理
    +     *
    +     */
    +    protected function preCompile()
    +    {
    +    }
     
    -	/**
    -	 * 编译后处理结果
    -	 * 
    -	 * @return void
    -	 */
    -	protected function postCompile() {}
    +    /**
    +     * 编译后处理结果
    +     *
    +     */
    +    protected function postCompile()
    +    {
    +    }
     
    -	/**
    -	 * 返回该标签支持的属性列表,需要覆盖该方法实现对标签的解析支持
    -	 * 
    -	 * @return array
    -	 */
    -	protected function getProperties() {
    -		return array();
    -	}
    +    /**
    +     * 返回该标签支持的属性列表,需要覆盖该方法实现对标签的解析支持
    +     *
    +     * @return array
    +     */
    +    protected function getProperties()
    +    {
    +        return array();
    +    }
     
    -	/**
    -	 * 解析标签属性值
    -	 * 
    -	 * @param string $content
    -	 */
    -	protected function compileProperty($content) {
    -		foreach ($this->getProperties() as $value) {
    -			if (!$value || !property_exists($this, $value)) continue;
    -			if (!isset($this->_propertiesCache[$value])) {
    -				$this->_propertiesCache[$value] = $this->$value;
    -			}
    -			preg_match('/(?<=' . preg_quote($value) . '=([\'\"]))(.*?)(?=\1)/ie', $content, $result);
    -			$this->$value = $result ? $result[0] : $this->_propertiesCache[$value];
    -		}
    -	}
    +    /**
    +     * 解析标签属性值
    +     *
    +     * @param string $content
    +     */
    +    protected function compileProperty($content)
    +    {
    +        foreach ($this->getProperties() as $value) {
    +            if (!$value || !property_exists($this, $value)) {
    +                continue;
    +            }
    +            if (!isset($this->_propertiesCache[$value])) {
    +                $this->_propertiesCache[$value] = $this->$value;
    +            }
    +            preg_match('/(?<='.preg_quote($value).'=([\'\"]))(.*?)(?=\1)/ie', $content, $result);
    +            $this->$value = $result ? $result[0] : $this->_propertiesCache[$value];
    +        }
    +    }
     
    -	/* (non-PHPdoc)
    -	 * @see WindHandlerInterceptor::preHandle()
    -	 */
    -	public function preHandle() {
    -		if ($this->windViewTemplate === null) return;
    -		$this->preCompile();
    -		foreach ($this->tags as $key => $value) {
    -			if (!$value[0] || !$value[1]) continue;
    -			$this->compileProperty($value[1]);
    -			$_output = $this->compile($value[0], $value[1]);
    -			$this->windViewTemplate->setCompiledBlockData($value[0], $_output);
    -		}
    -		$this->postCompile();
    -	}
    +    /* (non-PHPdoc)
    +     * @see WindHandlerInterceptor::preHandle()
    +     */
    +    public function preHandle()
    +    {
    +        if ($this->windViewTemplate === null) {
    +            return;
    +        }
    +        $this->preCompile();
    +        foreach ($this->tags as $key => $value) {
    +            if (!$value[0] || !$value[1]) {
    +                continue;
    +            }
    +            $this->compileProperty($value[1]);
    +            $_output = $this->compile($value[0], $value[1]);
    +            $this->windViewTemplate->setCompiledBlockData($value[0], $_output);
    +        }
    +        $this->postCompile();
    +    }
     
    -	/* (non-PHPdoc)
    -	 * @see WindHandlerInterceptor::postHandle()
    -	 */
    -	public function postHandle() {}
    +    /* (non-PHPdoc)
    +     * @see WindHandlerInterceptor::postHandle()
    +     */
    +    public function postHandle()
    +    {
    +    }
     
    -	/* (non-PHPdoc)
    -	 * @see WindHandlerInterceptor::handle()
    -	 */
    -	public function handle() {
    -		$args = func_get_args();
    -		call_user_func_array(array($this, 'preHandle'), $args);
    -		if (null !== ($handler = $this->interceptorChain->getHandler())) {
    -			call_user_func_array(array($handler, 'handle'), $args);
    -		}
    -		call_user_func_array(array($this, 'postHandle'), $args);
    -	}
    -
    -	/**
    -	 * @return WindViewTemplate
    -	 */
    -	protected function getWindViewTemplate() {
    -		return $this->windViewTemplate;
    -	}
    +    /* (non-PHPdoc)
    +     * @see WindHandlerInterceptor::handle()
    +     */
    +    public function handle()
    +    {
    +        $args = func_get_args();
    +        call_user_func_array(array($this, 'preHandle'), $args);
    +        if (null !== ($handler = $this->interceptorChain->getHandler())) {
    +            call_user_func_array(array($handler, 'handle'), $args);
    +        }
    +        call_user_func_array(array($this, 'postHandle'), $args);
    +    }
     
    +    /**
    +     * @return WindViewTemplate
    +     */
    +    protected function getWindViewTemplate()
    +    {
    +        return $this->windViewTemplate;
    +    }
     }
    -
    -?>
    \ No newline at end of file
    diff --git a/wind/viewer/AbstractWindViewTemplate.php b/wind/viewer/AbstractWindViewTemplate.php
    index 68c609c5..d18eac8c 100644
    --- a/wind/viewer/AbstractWindViewTemplate.php
    +++ b/wind/viewer/AbstractWindViewTemplate.php
    @@ -1,75 +1,83 @@
     doCompile,模板编译类只有一个对外的公开接口compile.
      * @author Qiong Wu 
      * @copyright ©2003-2103 phpwind.com
      * @license http://www.windframework.com
    - * @version $Id$
    + * @version $Id: AbstractWindViewTemplate.php 3904 2013-01-08 07:01:26Z yishuo $
      * @package viewer
      */
    -abstract class AbstractWindViewTemplate extends WindModule {
    +abstract class AbstractWindViewTemplate extends WindModule
    +{
    +    /**
    +     * 模板内容编译实现,返回编译后模板内容内容
    +     *
    +     * @param  string             $content            模板内容
    +     * @param  WindViewerResolver $windViewerResolver
    +     * @return string
    +     */
    +    abstract protected function doCompile($content, $windViewerResolver = null);
    +
    +    /**
    +     * 进行视图渲染
    +     *
    +     * @param string             $templateFile       | 模板文件
    +     * @param WindViewerResolver $windViewerResolver
    +     */
    +    public function compile($templateFile, $windViewerResolver)
    +    {
    +        $_output = $this->getTemplateFileContent($templateFile);
    +        $_output = $this->compileDelimiter($_output);
    +        $_output = $this->doCompile($_output, $windViewerResolver);
    +
    +        return $_output;
    +    }
    +
    +    /**
    +     * 渲染流
    +     *
    +     * @param string             $stream
    +     * @param WindViewerResolver $windViewerResolver
    +     */
    +    public function compileStream($stream, $windViewerResolver)
    +    {
    +        $_output = $this->compileDelimiter($stream);
    +        $_output = $this->doCompile($_output, $windViewerResolver);
     
    -	/**
    -	 * 模板内容编译实现,返回编译后模板内容内容
    -	 * 
    -	 * @param string $content 模板内容
    -	 * @param WindViewerResolver $windViewerResolver
    -	 * @return string
    -	 */
    -	abstract protected function doCompile($content, $windViewerResolver = null);
    +        return $_output;
    +    }
     
    -	/**
    -	 * 进行视图渲染
    -	 * 
    -	 * @param string $templateFile | 模板文件
    -	 * @param WindViewerResolver $windViewerResolver
    -	 */
    -	public function compile($templateFile, $windViewerResolver) {
    -		$_output = $this->getTemplateFileContent($templateFile);
    -		$_output = $this->compileDelimiter($_output);
    -		$_output = $this->doCompile($_output, $windViewerResolver);
    -		return $_output;
    -	}
    +    /**
    +     * @param string content
    +     * @return string
    +     */
    +    protected function compileDelimiter($content)
    +    {
    +        $content = preg_replace('//i', '?>', $content);
     
    -	/**
    -	 * 渲染流
    -	 *
    -	 * @param string $stream
    -	 * @param WindViewerResolver $windViewerResolver
    -	 */
    -	public function compileStream($stream, $windViewerResolver) {
    -		$_output = $this->compileDelimiter($stream);
    -		$_output = $this->doCompile($_output, $windViewerResolver);
    -		return $_output;
    -	}
    +        /*$content = str_replace(array('', '#-->'), '?>', $content);*/
    +        return $content;
    +    }
     
    -	/**
    -	 * @param string content
    -	 * @return string
    -	 */
    -	protected function compileDelimiter($content) {
    -		$content = preg_replace('/\s*/i', "?>", $content);
    -		/*$content = str_replace(array('', '#-->'), '?>', $content);*/
    -		return $content;
    -	}
    +    /**
    +     * 获得模板文件内容,目前只支持本地文件获取
    +     *
    +     * @param  string $templateFile
    +     * @return string
    +     */
    +    private function getTemplateFileContent($templateFile)
    +    {
    +        if (false === ($content = WindFile::read($templateFile))) {
    +            throw new WindViewException('[viewer.AbstractWindViewTemplate.getTemplateFileContent] Unable to open the template file \''.$templateFile.'\'.');
    +        }
     
    -	/**
    -	 * 获得模板文件内容,目前只支持本地文件获取
    -	 * 
    -	 * @param string $templateFile
    -	 * @return string
    -	 */
    -	private function getTemplateFileContent($templateFile) {
    -		if (false === ($content = WindFile::read($templateFile))) {
    -			throw new WindViewException('Unable to open the template file \'' . $templateFile . '\'.');
    -		}
    -		return $content;
    -	}
    +        return $content;
    +    }
     }
    -?>
    \ No newline at end of file
    diff --git a/wind/viewer/IWindView.php b/wind/viewer/IWindView.php
    index f9ce46fc..96868725 100644
    --- a/wind/viewer/IWindView.php
    +++ b/wind/viewer/IWindView.php
    @@ -1,27 +1,23 @@
     WindView是基础的视图处理器,职责:进行视图渲染.
    * @author Qiong Wu * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: IWindView.php 2973 2011-10-15 19:22:48Z yishuo $ * @package viewer */ -interface IWindView { - - /** - * 视图渲染方法 - * - * 通过该方法进行视图渲染,并将视图内容设置到response对象中以备输出 - * $this->getResponse()->setBody($viewContent, $templateName); - * - * @return void - * @throws WindViewException - */ - public function render(); - +interface IWindView +{ + /** + * 视图渲染方法 + * + * 通过该方法进行视图渲染,并将视图内容设置到response对象中以备输出 + * $this->getResponse()->setBody($viewContent, $templateName); + * + * @throws WindViewException + */ + public function render(); } - -?> \ No newline at end of file diff --git a/wind/viewer/IWindViewerResolver.php b/wind/viewer/IWindViewerResolver.php index a9b0deea..4f772ef3 100644 --- a/wind/viewer/IWindViewerResolver.php +++ b/wind/viewer/IWindViewerResolver.php @@ -1,7 +1,9 @@ windAssign和windFetch
      * IWindViewerResolver接口是框架定义的基础的视图渲染器接口,通过实现该接口类来自定义视图渲染器
      * WindViewerResolver类是该接口的基本实现
    @@ -9,55 +11,52 @@
      * @author Qiong Wu 
      * @copyright ©2003-2103 phpwind.com
      * @license http://www.windframework.com
    - * @version $Id$
    + * @version $Id: IWindViewerResolver.php 3904 2013-01-08 07:01:26Z yishuo $
      * @package viewer
      */
    -interface IWindViewerResolver {
    -
    -	/**
    -	 * 设置视图变量设置进当前模板
    -	 * 
    -	 * @param array|string|object $vars
    -	 * @param string $key 可选 默认值为空
    -	 * @return void
    -	 */
    -	public function windAssign($vars, $key = '');
    -
    -	/**
    -	 * 获取模板内容与变量信息
    -	 * 
    -	 * @param string $template 可选 默认值为空
    -	 * @return void
    -	 */
    -	public function windFetch($template = '');
    +interface IWindViewerResolver
    +{
    +    /**
    +     * 设置视图变量设置进当前模板
    +     *
    +     * @param array|string|object $vars
    +     * @param string              $key  可选 默认值为空
    +     */
    +    public function windAssign($vars, $key = '');
     
    +    /**
    +     * 获取模板内容与变量信息
    +     *
    +     * @param string $template 可选 默认值为空
    +     */
    +    public function windFetch($template = '');
     }
     
     /**
      * 辅助WindViewerResolver完成视图渲染工作
    - * 
    + *
      * @author Qiong Wu 
      * @copyright ©2003-2103 phpwind.com
      * @license http://www.windframework.com
    - * @version $Id$
    + * @version $Id: IWindViewerResolver.php 3904 2013-01-08 07:01:26Z yishuo $
      * @package viewer
      */
    -class WindRender {
    -
    -	/**
    -	 * 视图渲染
    -	 * 
    -	 * @param string $__tpl
    -	 * @param array $__vars
    -	 * @param WindViewerResolver $__viewer
    -	 * @return void
    -	 * @throws WindViewException
    -	 */
    -	public static function render($__tpl, $__vars, $__viewer) {
    -		@extract($__vars, EXTR_REFS);
    -		if (!include ($__tpl)) {
    -			throw new WindViewException('[component.viewer.WindRender.render] template name ' . $__tpl, 
    -				WindViewException::VIEW_NOT_EXIST);
    -		}
    -	}
    -}
    \ No newline at end of file
    +class WindRender
    +{
    +    /**
    +     * 视图渲染
    +     *
    +     * @param  string             $__tpl
    +     * @param  array              $__vars
    +     * @param  WindViewerResolver $__viewer
    +     * @throws WindViewException
    +     */
    +    public static function render($__tpl, $__vars, $__viewer)
    +    {
    +        @extract($__vars, EXTR_REFS);
    +        if (!include($__tpl)) {
    +            throw new WindViewException('[viewer.WindRender.render] template name '.$__tpl,
    +                WindViewException::VIEW_NOT_EXIST);
    +        }
    +    }
    +}
    diff --git a/wind/viewer/WindLayout.php b/wind/viewer/WindLayout.php
    index 11a79fa4..09167571 100644
    --- a/wind/viewer/WindLayout.php
    +++ b/wind/viewer/WindLayout.php
    @@ -1,7 +1,6 @@
     
      * $layout = layoutFile;	//return $templateDir/layoutFile
    @@ -29,58 +28,57 @@
      * @author Qiong Wu 
      * @copyright ©2003-2103 phpwind.com
      * @license http://www.windframework.com
    - * @version $Id$
    + * @version $Id: WindLayout.php 3904 2013-01-08 07:01:26Z yishuo $
      * @package viewer
      */
    -class WindLayout extends WindModule {
    -	/**
    -	 * 视图渲染器对象
    -	 * 
    -	 * @var WindViewerResolver
    -	 */
    -	private $viewer = null;
    -	
    -	private $segments = array();
    +class WindLayout extends WindModule
    +{
    +    /**
    +     * 视图渲染器对象
    +     *
    +     * @var WindViewerResolver
    +     */
    +    private $viewer = null;
    +    private $segments = array();
     
    -	/**
    -	 * 解析布局文件
    -	 * 
    -	 * @param string $layout
    -	 * @param WindViewerResolver $viewer
    -	 * @return void
    -	 */
    -	public function parser($layout, $__viewer) {
    -		$this->viewer = $__viewer;
    -		if (method_exists($this->viewer, 'compile')) {
    -			list($__tpl) = $this->viewer->compile($layout);
    -		} else
    -			$__tpl = $this->viewer->getWindView()->getViewTemplate($layout);
    -		
    -		ob_start();
    -		if (!@include ($__tpl)) {
    -			throw new WindViewException('[component.viewer.WindLayout.parser] layout file ' . $__tpl, 
    -				WindViewException::VIEW_NOT_EXIST);
    -		}
    -		return ob_get_clean();
    -	}
    +    /**
    +     * 解析布局文件
    +     *
    +     * @param string             $layout
    +     * @param WindViewerResolver $viewer
    +     */
    +    public function parser($layout, $__viewer)
    +    {
    +        $this->viewer = $__viewer;
    +        if (method_exists($this->viewer, 'compile')) {
    +            list($__tpl) = $this->viewer->compile($layout);
    +        } else {
    +            list($__tpl) = $this->viewer->getWindView()->getViewTemplate($layout);
    +        }
     
    -	/**
    -	 * 输出模板切片内容
    -	 * 
    -	 * @param string $template 模板切片名称
    -	 * @return void
    -	 */
    -	private function segment($template) {
    -		echo $this->viewer->windFetch($template);
    -	}
    +        if (!@include($__tpl)) {
    +            throw new WindViewException('[viewer.WindLayout.parser] layout file '.$__tpl,
    +                WindViewException::VIEW_NOT_EXIST);
    +        }
    +    }
     
    -	/**
    -	 * 输出当前模板的内容
    -	 * 
    -	 * @return void
    -	 */
    -	private function content() {
    -		$this->segment($this->viewer->getWindView()->templateName);
    -	}
    -}
    +    /**
    +     * 输出模板切片内容
    +     *
    +     * @param string $template
    +     *                         模板切片名称
    +     */
    +    private function segment($template)
    +    {
    +        $this->viewer->windFetch($template);
    +    }
     
    +    /**
    +     * 输出当前模板的内容
    +     *
    +     */
    +    private function content()
    +    {
    +        $this->segment($this->viewer->getWindView()->templateName);
    +    }
    +}
    diff --git a/wind/viewer/WindView.php b/wind/viewer/WindView.php
    index d6859390..023fe06e 100644
    --- a/wind/viewer/WindView.php
    +++ b/wind/viewer/WindView.php
    @@ -1,9 +1,10 @@
     WindView是基础的视图处理器,职责:进行视图渲染.
    * 他实现自接口IWindView,该类依赖WindViewerResolver完成视图渲染工作
    * WindView支持丰富的配置信息,可以通过修改相关配置来改变视图输出行为.template-dir @@ -37,197 +38,208 @@ * 'viewResolver' => array('ref' => 'viewResolver') * ))
    * 注意:框架默认视图组件,通过修改组件配置修改默认视图组件.(详细操作参考组件配置定义) - * + * * @author Qiong Wu * @copyright ©2003-2103 phpwind.com * @license {@link http://www.windframework.com} - * @version $Id$ + * @version $Id: WindView.php 3904 2013-01-08 07:01:26Z yishuo $ * @package viewer */ -class WindView extends WindModule implements IWindView { - /** - * 模板目录 - * - * 支持命名空间格式:WIND:template, - * 当命名空间为空时以当前approotpath为默认命名空间 - * @var string - */ - public $templateDir; - /** - * 模板文件的扩展名 - * - * @var string - */ - public $templateExt; - /** - * 模板名称 - * - * @var string - */ - public $templateName; - /** - * 是否对模板变量进行html字符过滤 - * - * @var boolean - */ - public $htmlspecialchars = true; - /** - * 是否开启模板自动编译 - * - * 接受两种输入值0和1
      - *
    1. 0 关闭,不进行模板编译
    2. - *
    3. 1 进行模板编译
    - * @var int - */ - public $isCompile = 0; - /** - * 模板编译文件生成目录,目录定义规则同templateDir - * - * @var string - */ - public $compileDir; - /** - * 模板编译文件生成后缀,默认值为'tpl' - * - * @var string - */ - public $compileExt = 'tpl'; - /** - * 模板布局文件 - * - * @var string - */ - public $layout; - /** - * 主题包目录 - * - * @var string - */ - protected $theme = array('theme' => '', 'package' => ''); - /** - * 视图解析引擎,通过组件配置改变该类型 - * - * @var WindViewerResolver - */ - protected $viewResolver = null; - /** - * 视图布局管理器 - * - * @var WindLayout - */ - protected $windLayout = null; +class WindView extends WindModule implements IWindView +{ + /** + * 模板目录 + * + * 支持命名空间格式:WIND:template, + * 当命名空间为空时以当前approotpath为默认命名空间 + * @var string + */ + public $templateDir; + /** + * 模板文件的扩展名 + * + * @var string + */ + public $templateExt; + /** + * 模板名称 + * + * @var string + */ + public $templateName; + /** + * 是否对模板变量进行html字符过滤 + * + * @var bool + */ + public $htmlspecialchars = true; + /** + * 是否开启模板自动编译 + * + * 接受两种输入值0和1
      + *
    1. 0 关闭,不进行模板编译
    2. + *
    3. 1 进行模板编译
    + * @var int + */ + public $isCompile = 0; + /** + * 模板编译文件生成目录,目录定义规则同templateDir + * + * @var string + */ + public $compileDir; + /** + * 模板编译文件生成后缀,默认值为'tpl' + * + * @var string + */ + public $compileExt = 'tpl'; + /** + * 模板布局文件 + * + * @var string + */ + public $layout; + /** + * 更个包的结构 + * + * @var string + */ + public $themePackPattern = '{pack}.{theme}'; + + /** + * 主题包目录 + * array('theme' => '', 'package' => ''); + * @var string + */ + protected $theme = array(); + /** + * 视图解析引擎,通过组件配置改变该类型 + * + * @var WindViewerResolver + */ + protected $viewResolver = null; + /** + * 视图布局管理器 + * + * @var WindLayout + */ + protected $windLayout = null; - /* (non-PHPdoc) - * @see IWindView::render() - */ - public function render($display = false) { - if (!$this->templateName) return; - - /* @var $viewResolver WindViewerResolver */ - $viewResolver = $this->_getViewResolver(); - $viewResolver->setWindView($this); - if ($viewResolver === null) throw new WindException( - '[view.WindView.render] View renderer initialization failure.'); - $viewResolver->windAssign(Wind::getApp()->getResponse()->getData($this->templateName)); - if ($display === false) { - if ($this->layout) { - /* @var $layout WindLayout */ - $layout = $this->_getWindLayout(); - $content = $layout->parser($this->layout, $viewResolver); - } else - $content = $viewResolver->windFetch(); - Wind::getApp()->getResponse()->setBody($content, $this->templateName); - } else { - echo $viewResolver->windFetch(); - } - } + /* (non-PHPdoc) + * @see IWindView::render() + */ + public function render($display = false) + { + if (!$this->templateName) { + return; + } - /* (non-PHPdoc) - * @see WindModule::setConfig() - */ - public function setConfig($config) { - parent::setConfig($config); - if ($this->_config) { - $this->templateDir = $this->getConfig('template-dir', '', $this->templateDir); - $this->templateExt = $this->getConfig('template-ext', '', $this->templateExt); - $this->compileDir = $this->getConfig('compile-dir', '', $this->compileDir); - $this->compileExt = $this->getConfig('compile-ext', '', $this->compileExt); - $this->isCompile = $this->getConfig('is-compile', '', $this->isCompile); - $this->layout = $this->getConfig('layout', '', $this->layout); - $this->htmlspecialchars = $this->getConfig('htmlspecialchars', '', - $this->htmlspecialchars); - $this->setThemePackage($this->getConfig('theme-package')); - } - } + /* @var $viewResolver WindViewerResolver */ + $viewResolver = $this->_getViewResolver(); + $viewResolver->setWindView($this); + if ($viewResolver === null) { + throw new WindException( + '[viewer.WindView.render] View renderer initialization failure.'); + } + $viewResolver->windAssign($this->getResponse()->getData($this->templateName)); + if ($display === false) { + if ($this->layout) { + /* @var $layout WindLayout */ + $layout = $this->_getWindLayout(); + $layout->parser($this->layout, $viewResolver); + } else { + $viewResolver->windFetch(); + } + } else { + $viewResolver->windFetch(); + } + } - /** - * 返回模板绝对路径信息 - * - * 根据模板的逻辑名称,返回模板的绝对路径信息,支持命名空间方式定义模板信息. - * $template='templateName'; //return $templateDir/templateName.$ext - * $template='subTemplateDir.templateName'; //return $templateDir/subTemplateDir/templateName.$ext - * $template='namespace:templateName'; //return namespace:templateName.$ext - * 注意:$template为空则返回当前的模板的路径信息.模板文件后缀名可以通过修改配置进行修改. - * @param string $template 模板名称, 默认值为空 , 为空则返回当前模板的绝对地址 - * @param string $ext 模板后缀, 默认值为空, 为空则返回使用默认的后缀 - * @return string - */ - public function getViewTemplate($template = '', $ext = '') { - !$template && $template = $this->templateName; - !$ext && $ext = $this->templateExt; - if (false === strpos($template, ':')) $template = $this->templateDir . '.' . $template; - if (!empty($this->theme['package']) && !empty($this->theme['theme'])) { - list(, $_template) = explode(':', $template, 2); - $_template = $this->theme['package'] . '.' . $this->theme['theme'] . '.' . $_template; - $realPath = Wind::getRealPath($_template, ($ext ? $ext : false), true); - if (is_file($realPath)) return $realPath; - } - return Wind::getRealPath($template, ($ext ? $ext : false), true); - } + /* (non-PHPdoc) + * @see WindModule::setConfig() + */ + public function setConfig($config) + { + parent::setConfig($config); + if ($this->_config) { + $this->templateDir = $this->getConfig('template-dir', '', $this->templateDir); + $this->templateExt = $this->getConfig('template-ext', '', $this->templateExt); + $this->compileDir = $this->getConfig('compile-dir', '', $this->compileDir); + $this->compileExt = $this->getConfig('compile-ext', '', $this->compileExt); + $this->isCompile = $this->getConfig('is-compile', '', $this->isCompile); + $this->layout = $this->getConfig('layout', '', $this->layout); + $this->themePackPattern = $this->getConfig('themePackPattern', '', + $this->themePackPattern); + $this->htmlspecialchars = $this->getConfig('htmlspecialchars', '', + $this->htmlspecialchars); + $this->setThemePackage($this->getConfig('theme-package')); + } + } - /** - * 返回模板的编译文件绝对路径地址 - * - * 根据模板的逻辑名称,返回模板的绝对路径信息,支持命名空间方式定义模板信息. - * $template='templateName'; //return $compileDir/templateName.$ext - * $template='subTemplateDir.templateName'; //return $compileDir/subTemplateDir_templateName.$ext - * $template='namespace:templateName'; //return $compileDir/__external_subDir_templateName.$ext - * 注意:$template为空则返回当前的模板的路径信息. - * @param string $template 模板名称, 默认值为空, 为空则返回当前模板的编译文件 - * @return string - */ - public function getCompileFile($template = '') { - if (!$this->compileDir) return; - if ($this->compileDir == $this->templateDir) throw new WindViewException( - '[wind.viewer.WindView.getCompileFile] the same directory compile and template.'); - if (!$template) $template = $this->templateName; - if (false !== ($pos = strpos($template, ':'))) { - $template = str_replace('.', '_', '__external.' . substr($template, $pos + 1)); - } - if (!empty($this->theme['theme']) && !empty($this->theme['package'])) { - $template = $this->compileDir . '.' . $this->theme['theme'] . '.' . $template; - } else { - $template = $this->compileDir . '.' . $template; - } - $dir = Wind::getRealPath($template, false, true); - WindFolder::mkRecur(dirname($dir)); - return $this->compileExt ? $dir . '.' . $this->compileExt : $dir; - } + /** + * 返回模板绝对路径信息 + * + * 根据模板的逻辑名称,返回模板的绝对路径信息,支持命名空间方式定义模板信息. + * $template='templateName'; //return $templateDir/templateName.$ext + * $template='subTemplateDir.templateName'; //return $templateDir/subTemplateDir/templateName.$ext + * $template='namespace:templateName'; //return namespace:templateName.$ext + * 注意:$template为空则返回当前的模板的路径信息.模板文件后缀名可以通过修改配置进行修改. + * @param string $template 模板名称, 默认值为空 , 为空则返回当前模板的绝对地址 + * @param string $ext 模板后缀, 默认值为空, 为空则返回使用默认的后缀 + * @param bool $createCompileDir true + * @return array(templatePath, compilePath, currentThemeKey) + */ + public function getViewTemplate($template = '', $ext = '') + { + $template || $template = $this->templateName; + $ext || $ext = $this->templateExt; + $compilePath = $templatePath = ''; + if ($this->templateDir && false === strpos($template, ':')) { + $template = $this->templateDir.'.'.$template; + } + $_template = false !== ($pos = strpos($template, ':')) ? substr($template, $pos + 1) : $template; + $currentThemeKey = null; + foreach ($this->theme as $currentThemeKey => $theme) { + $_templatePath = strtr($this->themePackPattern, + array('{pack}' => $theme[1], '{theme}' => $theme[0])).'.'.$_template; + $_templatePath = Wind::getRealPath($_templatePath, $ext, true); + isset($_compileDir) || $_compileDir = $theme[0]; + if (is_file($_templatePath)) { + $templatePath = $_templatePath; + break; + } + } + $templatePath === '' && $templatePath = Wind::getRealPath($template, $ext, true); + $compilePath = $this->compileDir.'.'.(isset($_compileDir) ? $_compileDir.'.' : '').$_template; + $compilePath = Wind::getRealPath($compilePath, $this->compileExt, true); + //WindFolder::mkRecur(dirname($compilePath)); + return array($templatePath, $compilePath, $currentThemeKey); + } - /** - * 设置当前主题包的位置 - * - * @param string $package - */ - public function setThemePackage($package) { - $this->theme['package'] = $package; - } + /** + * 获取当前风格定义 + * + * @param string $type (all) + * @return array(theme,package) + */ + public function getTheme($key = 'all') + { + if ($key === 'all') { + return $this->theme; + } - /** - * @param string $theme - */ - public function setTheme($theme) { - $this->theme['theme'] = $theme; - } + return $this->theme[$key]; + } -} \ No newline at end of file + /** + * 设置风格主题信息 + * + * @param string $theme + * @param string $package + */ + public function setTheme($theme, $package) + { + array_unshift($this->theme, array($theme, $package)); + } +} diff --git a/wind/viewer/compiler/WindTemplateCompilerAction.php b/wind/viewer/compiler/WindTemplateCompilerAction.php index 0560b04b..04fa254a 100644 --- a/wind/viewer/compiler/WindTemplateCompilerAction.php +++ b/wind/viewer/compiler/WindTemplateCompilerAction.php @@ -1,8 +1,9 @@ 标签解析脚本 - * 支持属性: + * 支持属性: * action: 处理操作,支持格式 /module/controller/action/?args * args: 参数列表 * isRedirect: 是否用url重定向模式进行跳转 @@ -13,32 +14,38 @@ * @author Qiong Wu * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindTemplateCompilerAction.php 2917 2011-10-09 02:48:19Z + * xiaoxia.xuxx $ * @package viewer * @subpackage compiler */ -class WindTemplateCompilerAction extends AbstractWindTemplateCompiler { - protected $action = ''; - protected $args = array(); - protected $isRedirect = 'false'; +class WindTemplateCompilerAction extends AbstractWindTemplateCompiler +{ + protected $action = ''; + protected $args = array(); + protected $isRedirect = 'false'; - /* (non-PHPdoc) - * @see AbstractWindTemplateCompiler::compile() - */ - public function compile($key, $content) { - $content = 'getComponent(\'forward\');'; - !$this->args && $this->args = 'array()'; - if (!preg_match('/^{?\$(\w+)}?$/Ui', $this->action, $_tmp)) $this->action = '\'' . $this->action . '\''; - $content .= '$_tpl_forward->forwardAction(' . $this->action . ',' . $this->args . ',' . $this->isRedirect . ',false);'; - $content .= 'Wind::getApp()->doDispatch($_tpl_forward, true); ?>'; - return $content; - } + /* + * (non-PHPdoc) @see AbstractWindTemplateCompiler::compile() + */ + public function compile($key, $content) + { + $content = 'args && $this->args = 'array()'; + if (!preg_match('/^{?\$(\w+)}?$/Ui', $this->action, $_tmp)) { + $this->action = '\''.$this->action.'\''; + } + $content .= '$_tpl_forward->forwardAction('.$this->action.','.$this->args.','.$this->isRedirect.',false);'; + $content .= 'Wind::getApp()->doDispatch($_tpl_forward, true); ?>'; - /* (non-PHPdoc) - * @see AbstractWindTemplateCompiler::getProperties() - */ - public function getProperties() { - return array('action', 'args', 'isRedirect'); - } + return $content; + } -} \ No newline at end of file + /* + * (non-PHPdoc) @see AbstractWindTemplateCompiler::getProperties() + */ + public function getProperties() + { + return array('action', 'args', 'isRedirect'); + } +} diff --git a/wind/viewer/compiler/WindTemplateCompilerComponent.php b/wind/viewer/compiler/WindTemplateCompilerComponent.php index 830b6e06..6316ff87 100644 --- a/wind/viewer/compiler/WindTemplateCompilerComponent.php +++ b/wind/viewer/compiler/WindTemplateCompilerComponent.php @@ -1,132 +1,150 @@ - * * @author xiaoxiao * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindTemplateCompilerComponent.php 3904 2013-01-08 07:01:26Z yishuo $ * @package viewer * @subpackage compiler */ -class WindTemplateCompilerComponent extends AbstractWindTemplateCompiler { - protected $name = ''; //组件名字 - protected $args = ''; //传递给组件的参数 - protected $templateDir = ''; //组件调用的模板路径 - protected $appConfig = ''; //组件的配置文件 - protected $appConfigSuffix = 'php'; //配置文件的缺省格式 - protected $componentPath = ''; //组件的入口地址 +class WindTemplateCompilerComponent extends AbstractWindTemplateCompiler +{ + protected $name = ''; //组件名字 + protected $args = ''; //传递给组件的参数 + protected $templateDir = ''; //组件调用的模板路径 + protected $appConfig = ''; //组件的配置文件 + protected $appConfigSuffix = 'php'; //配置文件的缺省格式 + protected $componentPath = ''; //组件的入口地址 - - /* (non-PHPdoc) - * @see AbstractWindTemplateCompiler::compile() - */ - public function compile($key, $content) { - return $this->getScript($content); - } - /** - * @return string - */ - private function getScript($content) { - $params = $this->matchConfig($content); - if (!isset($params['name']) || !isset($params['componentPath'])) throw new WindException('组件编译错误!'); - $content = "rebuildConfig($params) . (isset($params['args']) ? $this->registerUrlParams($params) : '') . "\$componentPath = Wind::getRealDir('" . $params['componentPath'] . "');\r\n" . "Wind::register(\$componentPath, '" . $params['name'] . "');\r\n" . "Wind::run('" . $params['name'] . "', \$config);\r\n?>"; - return $content; - } + /* (non-PHPdoc) + * @see AbstractWindTemplateCompiler::compile() + */ + public function compile($key, $content) + { + return $this->getScript($content); + } - /** - * 编译获得配置文件 - * - * @param array $params - * @return array - */ - private function rebuildConfig($params) { - $temp = "\$configParser = new WindConfigParser();\r\n" . "\$configPath = Wind::getRealPath('" . $params['appConfig'] . "', '" . $params['suffix'] . "');\r\n" . "\$config = \$configParser->parse(\$configPath);\r\n" . "\$config = \$config['" . $params['name'] . "'];\r\n"; - if (!isset($params['templateDir'])) return $temp; - if (isset($params['args']['m'])) - $temp .= "\$config['modules']['" . $params['args']['m'] . "']['view']['config']['template-dir'] = '" . $params['templateDir'] . "';\r\n"; - else { - $temp .= "foreach(\$config['modules'] as \$key => \$value) {\r\n" . "\t\$config['modules'][\$key]['view']['config']['template-dir'] = '" . $params['templateDir'] . "';\r\n" . "}\r\n"; - } - return $temp; - } + /** + * @return string + */ + private function getScript($content) + { + $params = $this->matchConfig($content); + if (!isset($params['name']) || !isset($params['componentPath'])) { + throw new WindException('[viewer.compiler.WindTemplateCompilerComponent.getScript] component config error!'); + } + $content = "rebuildConfig($params).(isset($params['args']) ? $this->registerUrlParams($params) : '')."\$componentPath = Wind::getRealDir('".$params['componentPath']."');\r\n"."Wind::register(\$componentPath, '".$params['name']."');\r\n"."Wind::run('".$params['name']."', \$config);\r\n?>"; - /** - * 注册变量信息 - * - * @param array $params - */ - private function registerUrlParams($params) { - $temp = "\$routerConfig = \$config['router']['config'];\r\n" . "\$mKey = isset(\$routerConfig['module']['url-param']) ? \$routerConfig['module']['url-param'] : 'm';\r\n" . "\$cKey = isset(\$routerConfig['controller']['url-param']) ? \$routerConfig['controller']['url-param'] : 'c';\r\n" . "\$aKey = isset(\$routerConfig['action']['url-param']) ? \$routerConfig['action']['url-param'] : 'a';\r\n" . "\$_GET[\$mKey] = '" . $params['args']['m'] . "';\r\n" . "\$_GET[\$cKey] = '" . $params['args']['c'] . "';\r\n" . "\$_GET[\$aKey] = '" . $params['args']['a'] . "';\r\n"; - unset($params['args']['a'], $params['args']['c'], $params['args']['m']); - foreach ($params['args'] as $key => $value) { - $temp .= "\$_GET['" . $key . "'] = " . (is_array($value) ? $value : "'" . $value . "'") . ";\r\n"; - } - return $temp; - } + return $content; + } - /** - * 匹配配置信息 - * - * @param string $content - * @return array - */ - private function matchConfig($content) { - preg_match_all('/(\w+=[\'|"]?[\w|.|:]+[\'|"]?)/', $content, $mathcs); - list($config, $key, $val) = array(array(), '', ''); - foreach ($mathcs[0] as $value) { - list($key, $val) = explode('=', $value); - if (!in_array($key, $this->getProperties()) || !$val) continue; - switch ($key) { - case 'args': - $config['args'] = $this->compileArgs(trim($val, '\'"')); - break; - default: - $config[$key] = trim($val, '\'"'); - break; - } - } - return $config; - } + /** + * 编译获得配置文件 + * + * @param array $params + * @return array + */ + private function rebuildConfig($params) + { + $temp = "\$configParser = new WindConfigParser();\r\n"."\$configPath = Wind::getRealPath('".$params['appConfig']."', '".$params['suffix']."');\r\n"."\$config = \$configParser->parse(\$configPath);\r\n"."\$config = \$config['".$params['name']."'];\r\n"; + if (!isset($params['templateDir'])) { + return $temp; + } + if (isset($params['args']['m'])) { + $temp .= "\$config['modules']['".$params['args']['m']."']['view']['config']['template-dir'] = '".$params['templateDir']."';\r\n"; + } else { + $temp .= "foreach(\$config['modules'] as \$key => \$value) {\r\n"."\t\$config['modules'][\$key]['view']['config']['template-dir'] = '".$params['templateDir']."';\r\n"."}\r\n"; + } - /** - * 解析传递给url的参数信息 - * - * @param string $arg - * @return array - */ - private function compileArgs($arg) { - $args = explode(':', $arg); - $urlParams = array(); - list($urlParams['a'], $urlParams['c'], $urlParams['m']) = array('', '', ''); - switch (count($args)) { - case 1: - $urlParams['a'] = $args[0]; - break; - case 2: - list($urlParams['c'], $urlParams['a']) = $args; - break; - case 3: - list($urlParams['m'], $urlParams['c'], $urlParams['a']) = $args; - break; - default: - break; - } - return $urlParams; - } + return $temp; + } - /* (non-PHPdoc) - * @see AbstractWindTemplateCompiler::getProperties() - */ - protected function getProperties() { - return array('name', 'templateDir', 'appConfig', 'args', 'componentPath', 'suffix'); - } -} + /** + * 注册变量信息 + * + * @param array $params + */ + private function registerUrlParams($params) + { + $temp = "\$routerConfig = \$config['router']['config'];\r\n"."\$mKey = isset(\$routerConfig['module']['url-param']) ? \$routerConfig['module']['url-param'] : 'm';\r\n"."\$cKey = isset(\$routerConfig['controller']['url-param']) ? \$routerConfig['controller']['url-param'] : 'c';\r\n"."\$aKey = isset(\$routerConfig['action']['url-param']) ? \$routerConfig['action']['url-param'] : 'a';\r\n"."\$_GET[\$mKey] = '".$params['args']['m']."';\r\n"."\$_GET[\$cKey] = '".$params['args']['c']."';\r\n"."\$_GET[\$aKey] = '".$params['args']['a']."';\r\n"; + unset($params['args']['a'], $params['args']['c'], $params['args']['m']); + foreach ($params['args'] as $key => $value) { + $temp .= "\$_GET['".$key."'] = ".(is_array($value) ? $value : "'".$value."'").";\r\n"; + } + + return $temp; + } + + /** + * 匹配配置信息 + * + * @param string $content + * @return array + */ + private function matchConfig($content) + { + preg_match_all('/(\w+=[\'|"]?[\w|.|:]+[\'|"]?)/', $content, $mathcs); + list($config, $key, $val) = array(array(), '', ''); + foreach ($mathcs[0] as $value) { + list($key, $val) = explode('=', $value); + if (!in_array($key, $this->getProperties()) || !$val) { + continue; + } + switch ($key) { + case 'args': + $config['args'] = $this->compileArgs(trim($val, '\'"')); + break; + default: + $config[$key] = trim($val, '\'"'); + break; + } + } -?> \ No newline at end of file + return $config; + } + + /** + * 解析传递给url的参数信息 + * + * @param string $arg + * @return array + */ + private function compileArgs($arg) + { + $args = explode(':', $arg); + $urlParams = array(); + list($urlParams['a'], $urlParams['c'], $urlParams['m']) = array('', '', ''); + switch (count($args)) { + case 1: + $urlParams['a'] = $args[0]; + break; + case 2: + list($urlParams['c'], $urlParams['a']) = $args; + break; + case 3: + list($urlParams['m'], $urlParams['c'], $urlParams['a']) = $args; + break; + default: + break; + } + + return $urlParams; + } + + /* (non-PHPdoc) + * @see AbstractWindTemplateCompiler::getProperties() + */ + protected function getProperties() + { + return array('name', 'templateDir', 'appConfig', 'args', 'componentPath', 'suffix'); + } +} diff --git a/wind/viewer/compiler/WindTemplateCompilerCss.php b/wind/viewer/compiler/WindTemplateCompilerCss.php index 67816259..6c94ee69 100644 --- a/wind/viewer/compiler/WindTemplateCompilerCss.php +++ b/wind/viewer/compiler/WindTemplateCompilerCss.php @@ -1,27 +1,28 @@ * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindTemplateCompilerCss.php 2973 2011-10-15 19:22:48Z yishuo $ * @package viewer * @subpackage compiler */ -class WindTemplateCompilerCss extends AbstractWindTemplateCompiler { +class WindTemplateCompilerCss extends AbstractWindTemplateCompiler +{ + /* (non-PHPdoc) + * @see AbstractWindTemplateCompiler::compile() + */ + public function compile($key, $content) + { + foreach ($this->windViewTemplate->getCompiledBlockData() as $key => $value) { + $content = str_replace('#'.$key.'#', ($value ? $value : ' '), $content); + } + $this->windViewerResolver->getWindLayout()->setcss($content); - /* (non-PHPdoc) - * @see AbstractWindTemplateCompiler::compile() - */ - public function compile($key, $content) { - foreach ($this->windViewTemplate->getCompiledBlockData() as $key => $value) { - $content = str_replace('#' . $key . '#', ($value ? $value : ' '), $content); - } - $this->windViewerResolver->getWindLayout()->setcss($content); - return ''; - } + return ''; + } } - -?> \ No newline at end of file diff --git a/wind/viewer/compiler/WindTemplateCompilerEcho.php b/wind/viewer/compiler/WindTemplateCompilerEcho.php index dc3a05d2..4eae158b 100644 --- a/wind/viewer/compiler/WindTemplateCompilerEcho.php +++ b/wind/viewer/compiler/WindTemplateCompilerEcho.php @@ -1,57 +1,65 @@ * 变量名称|变量格式(html,text) - * {$var|html} //不执行编译 - * {@$var->a|text} //执行编译 + * {$var|html} //不执行编译 + * {@$var->a|text} //执行编译 * {@templateName:var|html} + * * @author Qiong Wu * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindTemplateCompilerEcho.php 3773 2012-10-19 09:53:40Z long.shi + * $ * @package viewer * @subpackage compiler */ -class WindTemplateCompilerEcho extends AbstractWindTemplateCompiler { - - /* (non-PHPdoc) - * @see AbstractWindTemplateCompiler::compile() - */ - public function compile($key, $content) { - $_output = preg_replace(array('/^[\n\s{\@]+/i', '/[\n\s}\;]+$/i'), array('', ''), $content); - list($_output, $type) = explode('|', $_output . '|'); - preg_match('/^[\w\s]*:[\w\s\._]*$/i', $_output, $matchs); - if ($matchs) { - list($_namespace, $_var) = explode(':', $_output); - $_args = explode('.', $_var . '.'); - $_output = 'Wind::getApp()->getResponse()->getData(\'' . $_namespace . '\''; - foreach ($_args as $_arg) { - $_arg && $_output .= ',\'' . $_arg . '\''; - } - $_output .= ')'; - } - - switch (strtolower($type)) { - case 'json': - $content = ''; - break; - case 'url': - case 'html': - case 'js': - $content = ''; - break; - case 'text': - $content = ''; - break; - default: - $content = ''; - } - return $content; - } +class WindTemplateCompilerEcho extends AbstractWindTemplateCompiler +{ + /* + * (non-PHPdoc) @see AbstractWindTemplateCompiler::compile() + */ + public function compile($key, $content) + { + preg_match('/^({@|{)([^}{@\n]*);?(\|(\w+))?}$/iU', $content, $matchs); + if (empty($matchs[2])) { + return $content; + } + $_type = isset($matchs[4]) ? $matchs[4] : ''; + $_output = $matchs[2]; + preg_match('/^([\w_]+):([\w\s\._]+)$/i', $_output, $matchs); + if ($matchs) { + $_args = explode('.', $matchs[2].'.'); + $_output = 'Wind::getComponent(\'response\')->getData(\''.$matchs[1].'\''; + foreach ($_args as $_arg) { + $_arg && $_output .= ',\''.$_arg.'\''; + } + $_output .= ')'; + } + + $charset = Wind::getComponent('response')->getCharset(); + switch (strtolower($_type)) { + case 'json': + /* $content = ''; */ + $content = ''; + break; + case 'html': + case 'js': + $content = ''; + break; + case 'text': + $content = ''; + break; + case 'url': + default: + $charset == 'GBK' && $charset = 'ISO-8859-1'; + $content = ''; + } + + return $content; + } } -?> \ No newline at end of file diff --git a/wind/viewer/compiler/WindTemplateCompilerInternal.php b/wind/viewer/compiler/WindTemplateCompilerInternal.php index 9a6aff5d..f749ae26 100644 --- a/wind/viewer/compiler/WindTemplateCompilerInternal.php +++ b/wind/viewer/compiler/WindTemplateCompilerInternal.php @@ -1,22 +1,21 @@ * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindTemplateCompilerInternal.php 2973 2011-10-15 19:22:48Z yishuo $ * @package viewer * @subpackage compiler */ -class WindTemplateCompilerInternal extends AbstractWindTemplateCompiler { - - /* (non-PHPdoc) - * @see AbstractWindTemplateCompiler::compile() - */ - public function compile($key, $content) { - return $content; - } - +class WindTemplateCompilerInternal extends AbstractWindTemplateCompiler +{ + /* (non-PHPdoc) + * @see AbstractWindTemplateCompiler::compile() + */ + public function compile($key, $content) + { + return $content; + } } - -?> \ No newline at end of file diff --git a/wind/viewer/compiler/WindTemplateCompilerLang.php b/wind/viewer/compiler/WindTemplateCompilerLang.php index 465daa0a..6920a9c1 100644 --- a/wind/viewer/compiler/WindTemplateCompilerLang.php +++ b/wind/viewer/compiler/WindTemplateCompilerLang.php @@ -1,39 +1,46 @@ - * - * - * - * @author Shi Long - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package viewer - * @subpackage compiler + + +/** + * 输出翻译后的语言信息 + * + * + * + * + * @author Shi Long + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id: WindTemplateCompilerLang.php 3791 2012-10-30 04:01:29Z liusanbian $ + * @package viewer + * @subpackage compiler */ -class WindTemplateCompilerLang extends AbstractWindTemplateCompiler { - - protected $message = ''; - protected $params = ''; +class WindTemplateCompilerLang extends AbstractWindTemplateCompiler +{ + protected $message = ''; + protected $params = ''; + + /* + * (non-PHPdoc) @see AbstractWindTemplateCompiler::compile() + */ + public function compile($key, $content) + { + if (!$this->message) { + return $content; + } + $resource = Wind::getComponent('i18n'); + $resource !== null && $this->message = $resource->getMessage($this->message); + if (!$this->params) { + return $this->message; + } - /* (non-PHPdoc) - * @see AbstractWindTemplateCompiler::compile() - */ - public function compile($key, $content) { - if (!$this->message) return $content; - $resource = Wind::getApp()->getComponent('i18n'); - $resource !== null && $this->message = $resource->getMessage($this->message); - if (!$this->params) return $this->message; - return 'message . '", ' . $this->params . ');?>'; - } + return 'message.'", '.$this->params.');?>'; + } - /* (non-PHPdoc) - * @see AbstractWindTemplateCompiler::getProperties() - */ - protected function getProperties() { - return array('message', 'params'); - } -} + /* + * (non-PHPdoc) @see AbstractWindTemplateCompiler::getProperties() + */ + protected function getProperties() + { + return array('message', 'params'); + } +} diff --git a/wind/viewer/compiler/WindTemplateCompilerScript.php b/wind/viewer/compiler/WindTemplateCompilerScript.php index 90c27857..ae21ca21 100644 --- a/wind/viewer/compiler/WindTemplateCompilerScript.php +++ b/wind/viewer/compiler/WindTemplateCompilerScript.php @@ -1,37 +1,41 @@ * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindTemplateCompilerScript.php 2973 2011-10-15 19:22:48Z yishuo $ * @package viewer * @subpackage compiler */ -class WindTemplateCompilerScript extends AbstractWindTemplateCompiler { - protected $compile = 'true'; +class WindTemplateCompilerScript extends AbstractWindTemplateCompiler +{ + protected $compile = 'true'; - /* (non-PHPdoc) - * @see AbstractWindTemplateCompiler::compile() - */ - public function compile($key, $content) { - if ($this->compile === 'false') return $content; - foreach ($this->windViewTemplate->getCompiledBlockData() as $key => $value) { - $content = str_replace('#' . $key . '#', ($value ? $value : ' '), $content); - } - $this->windViewerResolver->getWindLayout()->setScript($content); - return ''; - } + /* (non-PHPdoc) + * @see AbstractWindTemplateCompiler::compile() + */ + public function compile($key, $content) + { + if ($this->compile === 'false') { + return $content; + } + foreach ($this->windViewTemplate->getCompiledBlockData() as $key => $value) { + $content = str_replace('#'.$key.'#', ($value ? $value : ' '), $content); + } + $this->windViewerResolver->getWindLayout()->setScript($content); - /* (non-PHPdoc) - * @see AbstractWindTemplateCompiler::getProperties() - */ - protected function getProperties() { - return array('compile'); - } + return ''; + } + /* (non-PHPdoc) + * @see AbstractWindTemplateCompiler::getProperties() + */ + protected function getProperties() + { + return array('compile'); + } } - -?> \ No newline at end of file diff --git a/wind/viewer/compiler/WindTemplateCompilerTemplate.php b/wind/viewer/compiler/WindTemplateCompilerTemplate.php index 23a1992b..fce861f8 100644 --- a/wind/viewer/compiler/WindTemplateCompilerTemplate.php +++ b/wind/viewer/compiler/WindTemplateCompilerTemplate.php @@ -1,8 +1,9 @@ * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindTemplateCompilerTemplate.php 3699 2012-06-27 03:43:23Z yishuo $ * @package viewer * @subpackage compiler */ -class WindTemplateCompilerTemplate extends AbstractWindTemplateCompiler { - protected $source = ''; - protected $suffix = ''; - protected $load = 'true'; +class WindTemplateCompilerTemplate extends AbstractWindTemplateCompiler +{ + protected $source = ''; + protected $suffix = ''; + protected $load = 'true'; - /* (non-PHPdoc) - * @see AbstractWindTemplateCompiler::compile() - */ - public function compile($key, $content) { - if (!$this->source) return $content; - - if (preg_match('/^{?\$(\w+)}?$/Ui', $this->source, $_tmp)) { - $content = 'source . '))'; - $content .= 'list($' . $this->source . ') = $__viewer->compile(' . $this->source . ', ' . $this->suffix . ');'; - $content .= 'include($' . $this->source . ');?>'; - } else { - if ($this->load === 'false') { - list($compileFile) = $this->windViewerResolver->compile($this->source, $this->suffix); - if (!empty($_tmp)) $compileFile = str_replace($this->source, '{$' . $_tmp[1] . '}', $compileFile); - $content = ''; - } else { - list(, $content) = $this->windViewerResolver->compile($this->source, $this->suffix, true); - } - } - return $content; - } + /* (non-PHPdoc) + * @see AbstractWindTemplateCompiler::compile() + */ + public function compile($key, $content) + { + if (!$this->source) { + return $content; + } + if ($this->load === 'false') { + list($compileFile) = $this->windViewerResolver->compile($this->source, $this->suffix); + $content = ''; + } else { + list(, $content) = $this->windViewerResolver->compile($this->source, $this->suffix, true); + } - /* (non-PHPdoc) - * @see AbstractWindTemplateCompiler::getProperties() - */ - public function getProperties() { - return array('source', 'suffix', 'load'); - } + return $content; + } + /* (non-PHPdoc) + * @see AbstractWindTemplateCompiler::getProperties() + */ + public function getProperties() + { + return array('source', 'suffix', 'load'); + } } - -?> \ No newline at end of file diff --git a/wind/viewer/compiler/WindTemplateCompilerToken.php b/wind/viewer/compiler/WindTemplateCompilerToken.php index 2ab26d29..0774ad81 100644 --- a/wind/viewer/compiler/WindTemplateCompilerToken.php +++ b/wind/viewer/compiler/WindTemplateCompilerToken.php @@ -1,36 +1,38 @@ * @author Qiong Wu 2011-10-19 * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindTemplateCompilerToken.php 3791 2012-10-30 04:01:29Z liusanbian $ * @package viewer * @subpackage compiler */ -class WindTemplateCompilerToken extends AbstractWindTemplateCompiler { - protected $name = ''; +class WindTemplateCompilerToken extends AbstractWindTemplateCompiler +{ + protected $name = ''; - /* (non-PHPdoc) - * @see AbstractWindTemplateCompiler::compile() - */ - public function compile($key, $content) { - $_content = 'getComponent(\'windToken\');'; - $_content .= '$__tpl_token_value = $__tpl_token->saveToken(\'' . $this->name . '\'); ?>'; - $_content .= 'name . '\' value=\'\'/>'; - return $_content; - } + /* (non-PHPdoc) + * @see AbstractWindTemplateCompiler::compile() + */ + public function compile($key, $content) + { + $_content = 'saveToken(\''.$this->name.'\'); ?>'; + $_content .= 'name.'\' value=\'\'/>'; - /* (non-PHPdoc) - * @see AbstractWindTemplateCompiler::getProperties() - */ - protected function getProperties() { - return array('name'); - } + return $_content; + } + /* (non-PHPdoc) + * @see AbstractWindTemplateCompiler::getProperties() + */ + protected function getProperties() + { + return array('name'); + } } - -?> \ No newline at end of file diff --git a/wind/viewer/compiler/WindViewTemplate.php b/wind/viewer/compiler/WindViewTemplate.php index e097f659..1e3a7d88 100644 --- a/wind/viewer/compiler/WindViewTemplate.php +++ b/wind/viewer/compiler/WindViewTemplate.php @@ -1,9 +1,10 @@ * 'template' => array( @@ -28,195 +29,220 @@ * @author Qiong Wu * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindViewTemplate.php 3904 2013-01-08 07:01:26Z yishuo $ * @package viewer * @subpackage compiler */ -class WindViewTemplate extends AbstractWindViewTemplate { - /** - * match后的模块文件块 - * - * @var array - */ - protected $compiledBlockData = array(); - /** - * @var WindHandlerInterceptorChain - */ - protected $windHandlerInterceptorChain = null; - protected $_compilerCache = array(); - - /* (non-PHPdoc) - * @see AbstractWindViewTemplate::doCompile() - */ - protected function doCompile($content, $windViewerResolver = null) { - try { - $content = $this->registerTags($content, $windViewerResolver); - if ($this->windHandlerInterceptorChain !== null) { - $this->windHandlerInterceptorChain->getHandler()->handle(); - } - foreach (array_reverse($this->compiledBlockData) as $key => $value) { - if (!$key) continue; - $content = str_replace($this->getBlockTag($key), ($value ? $value : ' '), $content); - } - $content = preg_replace('/\?>(\s|\n)*?<\?php/i', "\r\n", $content); - return $content; - } catch (Exception $e) { - throw new WindViewException( - '[component.viewer.WindViewTemplate.doCompile] compile fail.' . $e->getMessage(), - WindViewException::ERROR_SYSTEM_ERROR); - } - } - - /** - * 注册支持的标签并返回注册后的模板内容 - * - * 解析模板内容,并将匹配到的标签内容块注册到相应的标签编译器中并初始化标签解析器处理链. - * @param string $content - * @param WindViewerResolver $windViewerResolver - * @return string - */ - private function registerTags($content, $windViewerResolver = null) { - foreach ((array) $this->getTags() as $key => $value) { - $compiler = isset($value['compiler']) ? $value['compiler'] : ''; - $regex = isset($value['pattern']) ? $value['pattern'] : ''; - $tag = isset($value['tag']) ? $value['tag'] : ''; - if (!$compiler || !$tag) continue; - if ($regex === '') $regex = '/<(' . preg_quote($tag) . ')(.*?)(\/>|>(.*?)<\/\1>)/i'; - $content = $this->creatTagCompiler($content, $compiler, $regex, $windViewerResolver); - } - return $content; - } - - /** - * 创建对应标签的解析器类实例对象,并加载到处理链中. - * - * @param string content 模板内容 - * @param string compiler 标签编译器 - * @param string regex 正则表达式 - * @param WindViewerResolver $windViewerResolver 默认为null - * @return string 返回处理后的模板内容 - */ - private function creatTagCompiler($content, $compiler, $regex, $windViewerResolver = null) { - $content = preg_replace_callback($regex, array($this, '_creatTagCompiler'), $content); - if ($this->windHandlerInterceptorChain === null) { - $this->windHandlerInterceptorChain = new WindHandlerInterceptorChain(); - } - $_compilerClass = Wind::import($compiler); - $this->windHandlerInterceptorChain->addInterceptors( - new $_compilerClass($this->_compilerCache, $this, $windViewerResolver, - $this->getRequest(), $this->getResponse())); - $this->_compilerCache = array(); - return $content; - } - - /** - * 返回当前解析器中所有注册进来的标签集合 - * - * @return array - */ - protected function getTags() { - $_tags['internal'] = $this->createTag('internal', 'WIND:viewer.compiler.WindTemplateCompilerInternal', - '/<\?php.*?\?>/is'); - /*标签体增加在该位置*/ - $_tags['template'] = $this->createTag('template', - 'WIND:viewer.compiler.WindTemplateCompilerTemplate'); - //$_tags['page'] = $this->createTag('page', 'WIND:viewer.compiler.WindTemplateCompilerPage'); - $_tags['action'] = $this->createTag('action', - 'WIND:viewer.compiler.WindTemplateCompilerAction'); - //$_tags['component'] = $this->createTag('component', 'WIND:viewer.compiler.WindTemplateCompilerComponent'); - $_tags['token'] = $this->createTag('token', - 'WIND:viewer.compiler.WindTemplateCompilerToken'); - $_tags['lang'] = $this->createTag('lang', 'WIND:viewer.compiler.WindTemplateCompilerLang'); - $_tags = array_merge($_tags, $this->getConfig('support-tags', '', array())); - /*标签解析结束*/ - $_tags['expression'] = $this->createTag('expression', - 'WIND:viewer.compiler.WindTemplateCompilerEcho', '/({@|{\$[\w$]{1})[^}{@\n]*}/i'); - //$_tags['echo'] = $this->createTag('echo', 'WIND:viewer.compiler.WindTemplateCompilerEcho', '/\$[\w_]+/i'); - /* 块编译标签,嵌套变量处理 */ - //$_tags['script1'] = $this->createTag('script1', 'WIND:viewer.compiler.WindTemplateCompilerScript', '//Ui'); - //$_tags['script'] = $this->createTag('script', 'WIND:viewer.compiler.WindTemplateCompilerScript', '/<(script)[^<>\n]*(\/>|>(.|\n)*<\/\1>)/Ui'); - //$_tags['link'] = $this->createTag('link', 'WIND:viewer.compiler.WindTemplateCompilerCss'); - //$_tags['style'] = $this->createTag('style', 'WIND:viewer.compiler.WindTemplateCompilerCss'); - return $_tags; - } - - /** - * 创建tag编译解析的配置 - * - * @param string $tag 标签名称 - * @param string $class 编译器类新型 - * @param stirng $pattern 正则表达式,用于匹配标签 默认为空 - * @return array - */ - private function createTag($tag, $class, $pattern = '') { - return array('tag' => $tag, 'pattern' => $pattern, 'compiler' => $class); - } - - /** - * 将标签匹配到的模板内容设置到缓存中,并返回标识位设置到模板中进行内容占为 - * - * @param string $content - * @return mixed - */ - private function _creatTagCompiler($content) { - $_content = $content[0]; - if (!$_content) return ''; - - $key = $this->getCompiledBlockKey(); - $this->_compilerCache[] = array($key, $_content); - return $this->getBlockTag($key); - } - - /** - * 对模板块存储进行标签处理 - * 将Key串 'HhQWFLtU0LSA3nLPLHHXMtTP3EfMtN3FsxLOR1nfYC5OiZTQri' 处理为 - * - * 在模板中进行位置标识 - * - * @param string $key 索引 - * @return string|mixed 处理后结果 - */ - private function getBlockTag($key) { - return '#' . $key . '#'; - } - - /** - * 获得切分后块编译缓存Key值,Key值为一个50位的随机字符串,当产生重复串时继续查找 - * - * @return string - */ - protected function getCompiledBlockKey() { - $key = WindUtility::generateRandStr(50); - if (key_exists($key, $this->compiledBlockData)) { - return $this->getCompiledBlockKey(); - } - return $key; - } - - /** - * 返回编译后结果,根据Key值检索编译后结果,并返回.当key值为空时返回全部数据 - * - * @param string $key - * @return string|array - */ - public function getCompiledBlockData($key = '') { - if ($key) - return isset($this->compiledBlockData[$key]) ? $this->compiledBlockData[$key] : ''; - else - return $this->compiledBlockData; - } - - /** - * 根据key值保存编译后的模板块 - * - * @param string $key 索引 - * @param string $compiledBlockData 编译结果 - * @return void - */ - public function setCompiledBlockData($key, $compiledBlockData) { - if ($key) $this->compiledBlockData[$key] = $compiledBlockData; - } +class WindViewTemplate extends AbstractWindViewTemplate +{ + /** + * match后的模块文件块 + * + * @var array + */ + protected $compiledBlockData = array(); + /** + * @var WindHandlerInterceptorChain + */ + protected $windHandlerInterceptorChain = null; + protected $_compilerCache = array(); -} + /* (non-PHPdoc) + * @see AbstractWindViewTemplate::doCompile() + */ + protected function doCompile($content, $windViewerResolver = null) + { + try { + $content = $this->registerTags($content, $windViewerResolver); + if ($this->windHandlerInterceptorChain !== null) { + $this->windHandlerInterceptorChain->getHandler()->handle(); + } + foreach (array_reverse($this->compiledBlockData) as $key => $value) { + if (!$key) { + continue; + } + $content = str_replace($this->getBlockTag($key), ($value ? $value : ' '), $content); + } + $content = preg_replace('/\?>(\s|\n)*?<\?php/i', "\r\n", $content); + + return $content; + } catch (Exception $e) { + throw new WindViewException( + '[viewer.WindViewTemplate.doCompile] compile fail.'.$e->getMessage(), + WindViewException::ERROR_SYSTEM_ERROR); + } + } + + /** + * 注册支持的标签并返回注册后的模板内容 + * + * 解析模板内容,并将匹配到的标签内容块注册到相应的标签编译器中并初始化标签解析器处理链. + * @param string $content + * @param WindViewerResolver $windViewerResolver + * @return string + */ + private function registerTags($content, $windViewerResolver = null) + { + foreach ((array) $this->getTags() as $key => $value) { + $compiler = isset($value['compiler']) ? $value['compiler'] : ''; + $regex = isset($value['pattern']) ? $value['pattern'] : ''; + $tag = isset($value['tag']) ? $value['tag'] : ''; + if (!$compiler || !$tag) { + continue; + } + if ($regex === '') { + $regex = '/<('.preg_quote($tag).')(.*?)(\/>|>(.*?)<\/\1>)/is'; + } + $content = $this->creatTagCompiler($content, $compiler, $regex, $windViewerResolver); + } + + return $content; + } + + /** + * 创建对应标签的解析器类实例对象,并加载到处理链中. + * + * @param string content 模板内容 + * @param string compiler 标签编译器 + * @param string regex 正则表达式 + * @param WindViewerResolver $windViewerResolver 默认为null + * @return string 返回处理后的模板内容 + */ + private function creatTagCompiler($content, $compiler, $regex, $windViewerResolver = null) + { + $content = preg_replace_callback($regex, array($this, '_creatTagCompiler'), $content); + if ($this->windHandlerInterceptorChain === null) { + $this->windHandlerInterceptorChain = new WindHandlerInterceptorChain(); + } + $_compilerClass = Wind::import($compiler); + $this->windHandlerInterceptorChain->addInterceptors( + new $_compilerClass($this->_compilerCache, $this, $windViewerResolver, + $this->getRequest(), $this->getResponse())); + $this->_compilerCache = array(); + + return $content; + } + + /** + * 返回当前解析器中所有注册进来的标签集合 + * + * @return array + */ + protected function getTags() + { + $_tags['internal'] = $this->createTag('internal', 'WIND:viewer.compiler.WindTemplateCompilerInternal', + '/<\?php.*?\?>/is'); + /*标签体增加在该位置*/ + $_tags['template'] = $this->createTag('template', + 'WIND:viewer.compiler.WindTemplateCompilerTemplate'); + //$_tags['page'] = $this->createTag('page', 'WIND:viewer.compiler.WindTemplateCompilerPage'); + $_tags['action'] = $this->createTag('action', + 'WIND:viewer.compiler.WindTemplateCompilerAction'); + //$_tags['component'] = $this->createTag('component', 'WIND:viewer.compiler.WindTemplateCompilerComponent'); + $_tags['token'] = $this->createTag('token', + 'WIND:viewer.compiler.WindTemplateCompilerToken'); + $_tags['lang'] = $this->createTag('lang', 'WIND:viewer.compiler.WindTemplateCompilerLang'); + $_tags = array_merge($_tags, $this->getConfig('support-tags', '', array())); + /*标签解析结束*/ + $_tags['expression'] = $this->createTag('expression', + 'WIND:viewer.compiler.WindTemplateCompilerEcho', '/({@|{\$[\w$]{1})[^}{@\n]*}/i'); -?> \ No newline at end of file + $_tags = array_merge($_tags, $this->getConfig('support-tags-end', '', array())); + //$_tags['echo'] = $this->createTag('echo', 'WIND:viewer.compiler.WindTemplateCompilerEcho', '/\$[\w_]+/i'); + /* 块编译标签,嵌套变量处理 */ + //$_tags['script1'] = $this->createTag('script1', 'WIND:viewer.compiler.WindTemplateCompilerScript', '//Ui'); + //$_tags['script'] = $this->createTag('script', 'WIND:viewer.compiler.WindTemplateCompilerScript', '/<(script)[^<>\n]*(\/>|>(.|\n)*<\/\1>)/Ui'); + //$_tags['link'] = $this->createTag('link', 'WIND:viewer.compiler.WindTemplateCompilerCss'); + //$_tags['style'] = $this->createTag('style', 'WIND:viewer.compiler.WindTemplateCompilerCss'); + return $_tags; + } + + /** + * 创建tag编译解析的配置 + * + * @param string $tag 标签名称 + * @param string $class 编译器类新型 + * @param stirng $pattern 正则表达式,用于匹配标签 默认为空 + * @return array + */ + private function createTag($tag, $class, $pattern = '') + { + return array('tag' => $tag, 'pattern' => $pattern, 'compiler' => $class); + } + + /** + * 将标签匹配到的模板内容设置到缓存中,并返回标识位设置到模板中进行内容占为 + * + * @param string $content + * @return mixed + */ + private function _creatTagCompiler($content) + { + $_content = $content[0]; + if (!$_content) { + return ''; + } + + $key = $this->getCompiledBlockKey(); + $this->_compilerCache[] = array($key, $_content); + + return $this->getBlockTag($key); + } + + /** + * 对模板块存储进行标签处理 + * 将Key串 'HhQWFLtU0LSA3nLPLHHXMtTP3EfMtN3FsxLOR1nfYC5OiZTQri' 处理为 + * + * 在模板中进行位置标识 + * + * @param string $key 索引 + * @return string|mixed 处理后结果 + */ + private function getBlockTag($key) + { + return '#'.$key.'#'; + } + + /** + * 获得切分后块编译缓存Key值,Key值为一个50位的随机字符串,当产生重复串时继续查找 + * + * @return string + */ + protected function getCompiledBlockKey() + { + $key = WindUtility::generateRandStr(50); + if (array_key_exists($key, $this->compiledBlockData)) { + return $this->getCompiledBlockKey(); + } + + return $key; + } + + /** + * 返回编译后结果,根据Key值检索编译后结果,并返回.当key值为空时返回全部数据 + * + * @param string $key + * @return string|array + */ + public function getCompiledBlockData($key = '') + { + if ($key) { + return isset($this->compiledBlockData[$key]) ? $this->compiledBlockData[$key] : ''; + } else { + return $this->compiledBlockData; + } + } + + /** + * 根据key值保存编译后的模板块 + * + * @param string $key 索引 + * @param string $compiledBlockData 编译结果 + */ + public function setCompiledBlockData($key, $compiledBlockData) + { + if ($key) { + $this->compiledBlockData[$key] = $compiledBlockData; + } + } +} diff --git a/wind/viewer/exception/WindViewException.php b/wind/viewer/exception/WindViewException.php index 15cdd5d4..b2a41cc4 100644 --- a/wind/viewer/exception/WindViewException.php +++ b/wind/viewer/exception/WindViewException.php @@ -5,25 +5,26 @@ * @author Qiong Wu * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindViewException.php 3867 2012-12-21 15:23:37Z yishuo $ * @package viewer * @subpackage exception */ -class WindViewException extends WindException { - const VIEW_NOT_EXIST = '300'; - const COMPILE_NOT_EXIST = '400'; +class WindViewException extends WindException +{ + const VIEW_NOT_EXIST = '1300'; + const COMPILE_NOT_EXIST = '1400'; - /** - * 自定义异常号的对应异常信息 - * - * @param int $code 异常号 - * @return string 返回异常号对应的异常组装信息原型 - */ - protected function messageMapper($code) { - $messages[self::VIEW_NOT_EXIST] = 'Not exist view template file or Incorrect file path \'$message\''; - $messages[self::COMPILE_NOT_EXIST] = 'Not exist view compile file or Incorrect file path \'$message\''; - return isset($messages[$code]) ? $messages[$code] : '$message'; - } -} + /** + * 自定义异常号的对应异常信息 + * + * @param int $code 异常号 + * @return string 返回异常号对应的异常组装信息原型 + */ + protected function messageMapper($code) + { + $messages[self::VIEW_NOT_EXIST] = 'Not exist view template file or Incorrect file path \'$message\''; + $messages[self::COMPILE_NOT_EXIST] = 'Not exist view compile file or Incorrect file path \'$message\''; -?> \ No newline at end of file + return isset($messages[$code]) ? $messages[$code] : '$message'; + } +} diff --git a/wind/viewer/resolver/WindNormalViewerResolver.php b/wind/viewer/resolver/WindNormalViewerResolver.php index d8bfdf3c..0453df5d 100644 --- a/wind/viewer/resolver/WindNormalViewerResolver.php +++ b/wind/viewer/resolver/WindNormalViewerResolver.php @@ -1,5 +1,6 @@ vars = $vars; - elseif (!isset($this->vars[$key])) - $this->vars[$key] = $vars; - } + /* (non-PHPdoc) + * @see IWindViewerResolver::windAssign() + */ + public function windAssign($vars, $key = '') + { + if ($key === '') { + $this->vars = $vars; + } elseif (!isset($this->vars[$key])) { + $this->vars[$key] = $vars; + } + } - /* (non-PHPdoc) - * @see IWindViewerResolver::windFetch() - */ - public function windFetch($template = '') { - $template || $template = $this->windView->templateName; - if (!$template) return ''; - ob_start(); - $template = $this->windView->getViewTemplate($template); - WindRender::render($template, $this->vars, $this); - return ob_get_clean(); - } + /* (non-PHPdoc) + * @see IWindViewerResolver::windFetch() + */ + public function windFetch($template = '') + { + $template || $template = $this->windView->templateName; + if (!$template) { + return ''; + } + list($template) = $this->windView->getViewTemplate($template); + WindRender::render($template, $this->vars, $this); + } - /** - * @return WindView - */ - public function getWindView() { - return $this->windView; - } + /** + * @return WindView + */ + public function getWindView() + { + return $this->windView; + } - /** - * @param WindView $windView - * @return void - */ - public function setWindView($windView) { - $this->windView = $windView; - } + /** + * @param WindView $windView + */ + public function setWindView($windView) + { + $this->windView = $windView; + } } - -?> \ No newline at end of file diff --git a/wind/viewer/resolver/WindViewerResolver.php b/wind/viewer/resolver/WindViewerResolver.php index 0dbce082..faab1ee1 100644 --- a/wind/viewer/resolver/WindViewerResolver.php +++ b/wind/viewer/resolver/WindViewerResolver.php @@ -1,9 +1,9 @@ -IWindViewerResolver,主要职责是进行视图渲染,并返回渲染的视图内容. * 支持布局管理,主题管理以及通过WindViewTemplate支持视图模板编译。 * 组件定义: @@ -19,78 +19,107 @@ * 而ViewerResolver对象在进行视图渲染时的状态信息,模板信息,以及配置信息都来自于WindView对象.ViewerResolver对象中的WindView对象必须是创建ViewerResolver的那个对象. * 我们可以通过修改view的component配置来注入不同的ViewerResolver实现. * - * + * * @author Qiong Wu * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindViewerResolver.php 3908 2013-01-18 03:37:53Z yishuo $ * @package viewer - */ -class WindViewerResolver extends WindNormalViewerResolver implements IWindViewerResolver { - /* (non-PHPdoc) - * @see IWindViewerResolver::windFetch() - */ - public function windFetch($template = '') { - $template || $template = $this->windView->templateName; - if (!$template) return ''; - ob_start(); - list($compileFilePath) = $this->compile($template); - WindRender::render($compileFilePath, $this->vars, $this); - return ob_get_clean(); - } - - /** - * 编译模板并返回编译后模板地址及内容 - * - *
    -	 * $output==true返回编译文件绝对路径地址和内容,不生成编译文件;
    -	 * $output==false返回编译文件绝对路径地址和内容,生成编译文件
    -	 * 
    - * - * @param string $template 模板名称 必填 - * @param string $suffix 模板后缀 默认为空 - * @param boolean $readOnly 是否直接输出模板内容,接受两个值true,false 默认值为false - * @param boolean $forceOutput 是否强制返回模板内容,默认为不强制 - * @return array(compileFile,content)
    -	 * compileFile模板编译文件绝对地址,
    -	 * content编译后模板输出内容,当$output
    -	 * 为false时将content写入compileFile
    - */ - public function compile($template, $suffix = '', $readOnly = false, $forceOutput = false) { - $templateFile = $this->windView->getViewTemplate($template, $suffix); - if (!is_file($templateFile)) { - throw new WindViewException( - '[component.viewer.WindViewerResolver.compile] ' . $templateFile, - WindViewException::VIEW_NOT_EXIST); - } - $compileFile = $this->windView->getCompileFile($template); - if (!$this->checkReCompile($templateFile, $compileFile)) { - return array($compileFile, ($forceOutput ? WindFile::read($compileFile) : '')); - } - /* @var $_windTemplate WindViewTemplate */ - $_windTemplate = Wind::getApp()->getComponent('template'); - $_output = $_windTemplate->compile($templateFile, $this); - $readOnly === false && WindFile::write($compileFile, $_output); - return array($compileFile, $_output); - } - - /** - * 检查是否需要重新编译,需要编译返回false,不需要编译返回true - * - * 是否重新进行编译取决于两个变量'WIND_DEBUG'和'isCompile','WIND_DEBUG'是框架层面的'DEBUG'控制常量,当'DEBUG'开启时则总是重新生成编译模板. - * 'isCompile'是一个配置值来自'WindView'对象,用户可以通过配置进行修改.当'isCompile'为'1'时,程序会进一步判断,当编译文件不存在或者已经过期时对模板进行重新编译. - * 如果'isCompile'为'0',则不对模板文件进行重新编译. - * @param string $templateFilePath 模板路径 - * @param string $compileFilePath 编译路径 - * @return boolean - */ - private function checkReCompile($templateFilePath, $compileFilePath) { - if (WIND_DEBUG) return true; - if ($this->getWindView()->isCompile) { - if (!is_file($compileFilePath)) return true; - $_c_m_t = filemtime($compileFilePath); - if ((int) $_c_m_t <= (int) filemtime($templateFilePath)) return true; - } - return false; - } + */ +class WindViewerResolver extends WindNormalViewerResolver implements IWindViewerResolver +{ + private $currentThemeKey = null; + + /* + * (non-PHPdoc) @see IWindViewerResolver::windFetch() + */ + public function windFetch($template = '') + { + $template || $template = $this->windView->templateName; + if (!$template) { + return ''; + } + list($compileFilePath) = $this->compile($template); + WindRender::render($compileFilePath, $this->vars, $this); + } + + /** + * 编译模板并返回编译后模板地址及内容 + *
    +     * $output==true返回编译文件绝对路径地址和内容,不生成编译文件;
    +     * $output==false返回编译文件绝对路径地址和内容,生成编译文件
    +     * 
    + * + * @param string $template 模板名称 必填 + * @param string $suffix 模板后缀 默认为空 + * @param bool $readOnly 是否直接输出模板内容,接受两个值true,false 默认值为false + * @param bool $forceOutput 是否强制返回模板内容,默认为不强制 + * @return array(compileFile,content)
    +     *                                                compileFile模板编译文件绝对地址,
    +     *                                                content编译后模板输出内容,当$output
    +     *                                                为false时将content写入compileFile
    + */ + public function compile($template, $suffix = '', $readOnly = false, $forceOutput = false) + { + list($templateFile, $compileFile, $this->currentThemeKey) = $this->windView->getViewTemplate( + $template, $suffix); + if (!is_file($templateFile)) { + throw new WindViewException( + '[viewer.resolver.WindViewerResolver.compile] '.$templateFile, + WindViewException::VIEW_NOT_EXIST); + } + + if (!$this->checkReCompile($templateFile, $compileFile)) { + return array( + $compileFile, + ($forceOutput || $readOnly ? WindFile::read($compileFile) : ''), ); + } + /* @var $_windTemplate WindViewTemplate */ + $_windTemplate = Wind::getComponent('template'); + $_output = $_windTemplate->compile($templateFile, $this); + if (false === $readOnly) { + WindFolder::mkRecur(dirname($compileFile)); + WindFile::write($compileFile, $_output); + } + + return array($compileFile, $_output); + } + + /** + * 如果存在模板风格,该方法将返回当前风格值 + * + * @return NULL int + */ + public function getCurrentThemeKey() + { + return $this->currentThemeKey; + } + + /** + * 检查是否需要重新编译,需要编译返回false,不需要编译返回true + * 是否重新进行编译取决于两个变量'Wind::$isDebug'和'isCompile','Wind::$isDebug'是框架层面的'DEBUG'控制常量,当'DEBUG'开启时则总是重新生成编译模板. + * 'isCompile'是一个配置值来自'WindView'对象,用户可以通过配置进行修改.当'isCompile'为'1'时,程序会进一步判断,当编译文件不存在或者已经过期时对模板进行重新编译. + * 如果'isCompile'为'0',则不对模板文件进行重新编译. + * + * @param string $templateFilePath 模板路径 + * @param string $compileFilePath 编译路径 + * @return bool + */ + private function checkReCompile($templateFilePath, $compileFilePath) + { + if (Wind::$isDebug) { + return true; + } + if ($this->getWindView()->isCompile) { + if (!is_file($compileFilePath)) { + return true; + } + $_c_m_t = filemtime($compileFilePath); + if ((int) $_c_m_t <= (int) filemtime($templateFilePath)) { + return true; + } + } + + return false; + } } diff --git a/wind/web/WindController.php b/wind/web/WindController.php index a9b471d0..fc065c13 100644 --- a/wind/web/WindController.php +++ b/wind/web/WindController.php @@ -1,48 +1,58 @@ * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindController.php 3904 2013-01-08 07:01:26Z yishuo $ * @package web */ -abstract class WindController extends WindSimpleController { - - /* (non-PHPdoc) - * @see WindSimpleController::run() - */ - public function run() {} - - /* (non-PHPdoc) - * @see WindAction::resolvedActionMethod() - */ - protected function resolvedActionMethod($handlerAdapter) { - $action = $handlerAdapter->getAction(); - if ($action !== 'run') $action = $this->resolvedActionName($action); - if (in_array($action, array('doAction', 'beforeAction', 'afterAction', 'forwardAction')) || !method_exists( - $this, $action)) { - throw new WindException('[web.WindController.resolvedActionMethod] ', - WindException::ERROR_CLASS_METHOD_NOT_EXIST); - } - $method = new ReflectionMethod($this, $action); - if ($method->isProtected()) throw new WindException('[web.WindController.resolvedActionMethod]', - WindException::ERROR_CLASS_METHOD_NOT_EXIST); - return $action; - } +abstract class WindController extends WindSimpleController +{ + /* (non-PHPdoc) + * @see WindSimpleController::run() + */ + public function run() + { + } - /** - * 解析action操作方法名称 - * - * 默认解析规则,在请求的action名称后加'Action'后缀 - * 请求的action为 'add',则对应的处理方法名为 'addAction',可以通过覆盖本方法,修改解析规则 - * @param string $action - * @return void - */ - protected function resolvedActionName($action) { - return $action . 'Action'; - } -} \ No newline at end of file + /* (non-PHPdoc) + * @see WindAction::resolvedActionMethod() + */ + protected function resolvedActionMethod($handlerAdapter) + { + $action = $handlerAdapter->getAction(); + if ($action !== 'run') { + $action = $this->resolvedActionName($action); + } + if (in_array($action, array('doAction', 'beforeAction', 'afterAction', 'forwardAction')) || !method_exists( + $this, $action)) { + throw new WindException( + 'Your request action \''.get_class($this).'::'.$action.'()\' was not found on this server.', + 404); + } + $method = new ReflectionMethod($this, $action); + if ($method->isProtected()) { + throw new WindException( + 'Your request action \''.get_class($this).'::'.$action.'()\' was not found on this server.', + 404); + } + + return $action; + } + + /** + * 解析action操作方法名称 + * + * 默认解析规则,在请求的action名称后加'Action'后缀 + * 请求的action为 'add',则对应的处理方法名为 'addAction',可以通过覆盖本方法,修改解析规则 + * @param string $action + */ + protected function resolvedActionName($action) + { + return $action.'Action'; + } +} diff --git a/wind/web/WindDispatcher.php b/wind/web/WindDispatcher.php index 89762353..411ea3c5 100644 --- a/wind/web/WindDispatcher.php +++ b/wind/web/WindDispatcher.php @@ -1,89 +1,96 @@ * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindDispatcher.php 3904 2013-01-08 07:01:26Z yishuo $ * @package web */ -class WindDispatcher extends WindModule { - /** - * 存储请求的队列信息 - * - * @var array - */ - protected $maxForwrd = array(); - protected $display = false; +class WindDispatcher extends WindModule +{ + /** + * 存储请求的队列信息 + * + * @var array + */ + protected $maxForwrd = array(); + protected $display = false; - /** - * @param WindForward $forward - * @param WindRouter $router - * @param boolean $display - * @return void - */ - public function dispatch($forward, $router, $display) { - if ($forward->getIsRedirect()) - $this->dispatchWithRedirect($forward, $router); - elseif ($forward->getIsReAction()) { - if (count($this->maxForwrd) > 10) { - throw new WindFinalException( - '[web.WindDispatcher.dispatchWithAction] more than 10 times forward request. (' . implode(', ', - $this->maxForwrd) . ')'); - } - $token = $router->getModule() . '/' . $router->getController() . '/' . $router->getAction(); - array_push($this->maxForwrd, $token); - $this->dispatchWithAction($forward, $router, $display); - } else { - $view = $forward->getWindView(); - if ($view->templateName) { - $this->getResponse()->setData($forward->getVars(), $view->templateName); - $view->render($this->display || $display); - } - $this->display = false; - } - } + /** + * @param WindForward $forward + * @param WindRouter $router + * @param bool $display + */ + public function dispatch($forward, $router, $display) + { + if ($forward->getIsRedirect()) { + $this->dispatchWithRedirect($forward, $router); + } elseif ($forward->getIsReAction()) { + if (count($this->maxForwrd) > 10) { + throw new WindFinalException( + '[web.WindDispatcher.dispatch] more than 10 times forward request. ('.implode(', ', + $this->maxForwrd).')'); + } + $token = $router->getModule().'/'.$router->getController().'/'.$router->getAction(); + array_push($this->maxForwrd, $token); + $this->dispatchWithAction($forward, $router, $display); + } else { + $view = $forward->getWindView(); + if ($view->templateName) { + $this->getResponse()->setData($forward->getVars(), $view->templateName); + $view->render($this->display || $display); + } + $this->display = false; + } + } - /** - * 重定向请求到新的url地址 - * - * 重定向请求到新的url地址是通过head方式重新开启一个url访问请求. - * @param WindForward $forward - * @param AbstractWindRouter $router - * @return void - */ - protected function dispatchWithRedirect($forward, $router) { - if (!($_url = $forward->getUrl())) { - $_url = $router->assemble($forward->getAction(), $forward->getArgs()); - } - $_url = WindUrlHelper::checkUrl($_url, true); - $this->getResponse()->sendRedirect($_url); - } + /** + * 重定向请求到新的url地址 + * + * 重定向请求到新的url地址是通过head方式重新开启一个url访问请求. + * @param WindForward $forward + * @param AbstractWindRouter $router + */ + protected function dispatchWithRedirect($forward, $router) + { + if (!($_url = $forward->getUrl())) { + $_url = $router->assemble($forward->getAction(), $forward->getArgs()); + } + $_url = WindUrlHelper::checkUrl($_url, true); + $this->getResponse()->sendRedirect($_url); + } - /** - * 重定向请求到新的action操作 - * - * 该种重定向类型,是中断当前的请求执行过程,开启另外的action操作处理.是在一次请求内部进行重定向, - * 所以之前的一些处理的结果变量,在重定向后是会继续存在,并可通过forward变量进行访问的.也就是不仅仅是过程的重定向, - * 也是状态的重定向. - * @param WindForward $forward - * @param WindRouter $router - * @param boolean $display - * @return void - */ - protected function dispatchWithAction($forward, $router, $display) { - if (!$action = $forward->getAction()) { - throw new WindException('[web.WindDispatcher.dispatchWithAction] forward fail.', - WindException::ERROR_PARAMETER_TYPE_ERROR); - } - $this->display = $display; - list($_a, $_c, $_m) = WindUrlHelper::resolveAction($action); - if ($_var = $forward->getArgs()) $this->getResponse()->setData($_var, 'F'); - $_a && $router->setAction($_a); - $_c && $router->setController($_c); - $_m && $router->setModule($_m); - Wind::getApp()->run(); - } + /** + * 重定向请求到新的action操作 + * + * 该种重定向类型,是中断当前的请求执行过程,开启另外的action操作处理.是在一次请求内部进行重定向, + * 所以之前的一些处理的结果变量,在重定向后是会继续存在,并可通过forward变量进行访问的.也就是不仅仅是过程的重定向, + * 也是状态的重定向. + * @param WindForward $forward + * @param WindRouter $router + * @param bool $display + */ + protected function dispatchWithAction($forward, $router, $display) + { + if (!$action = $forward->getAction()) { + throw new WindException('[web.WindDispatcher.dispatchWithAction] forward fail.', + WindException::ERROR_PARAMETER_TYPE_ERROR); + } + $this->display = $display; + list($_a, $_c, $_m, $arg) = WindUrlHelper::resolveAction($action); + foreach ($arg as $key => $value) { + $_GET[$key] = $value; + } + foreach ($forward->getArgs() as $key => $value) { + $_POST[$key] = $value; + } + + $_a && $router->setAction($_a); + $_c && $router->setController($_c); + $_m && $router->setModule($_m); + Wind::getApp()->run(); + } } diff --git a/wind/web/WindErrorHandler.php b/wind/web/WindErrorHandler.php index 0985e3d3..e2504e68 100644 --- a/wind/web/WindErrorHandler.php +++ b/wind/web/WindErrorHandler.php @@ -1,7 +1,6 @@ - * @@ -9,36 +8,53 @@ * ... * *
    + * * @author Qiong Wu * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindErrorHandler.php 3861 2012-12-18 11:13:05Z yishuo $ * @package web - */ -class WindErrorHandler extends WindController { - protected $error = array(); - protected $errorCode = 0; - protected $errorDir = 'WIND:web.view'; - - /* (non-PHPdoc) - * @see WindAction::beforeAction() - */ - public function beforeAction($handlerAdapter) { - $error = $this->getForward()->getVars('__error'); - $this->error = $error['message']; - $this->errorCode = $error['code']; - $this->getForward()->setVars(array(), '__error'); - } - - /* (non-PHPdoc) - * @see WindAction::run() - */ - public function run() { - $this->setOutput("Error message", "errorHeader"); - $this->setOutput($this->error, "errors"); - $errDir = Wind::getApp()->getConfig('errorpage'); - !$errDir && $errDir = $this->errorDir; - $this->setTemplatePath($errDir); - $this->setTemplate('erroraction'); - } -} \ No newline at end of file + */ +class WindErrorHandler extends WindController +{ + protected $error = array(); + protected $errorCode = 0; + protected $errorDir; + + /* + * (non-PHPdoc) @see WindAction::beforeAction() + */ + public function beforeAction($handlerAdapter) + { + $this->errorDir = $this->getInput('__errorDir', 'post'); + $error = $this->getInput('__error', 'post'); + $this->error = $error['message']; + $this->errorCode = $error['code']; + } + + /* + * (non-PHPdoc) @see WindAction::run() + */ + public function run() + { + $title = $this->getResponse()->codeMap($this->errorCode); + $title = $title ? $this->errorCode.' '.$title : 'unknowen error'; + $title .= ' - wind error message'; + $title = ucwords($title); + + $this->setOutput($title, 'title'); + + $this->setOutput('Error message', 'errorHeader'); + $this->setOutput($this->error, 'errors'); + $this->setTemplatePath($this->errorDir); + $this->setTemplate('erroraction'); + } + + /* (non-PHPdoc) + * @see WindSimpleController::afterAction() + */ + public function afterAction($handlerAdapter) + { + $this->getResponse()->setStatus($this->errorCode); + } +} diff --git a/wind/web/WindForward.php b/wind/web/WindForward.php index ed57bab1..75c658e2 100644 --- a/wind/web/WindForward.php +++ b/wind/web/WindForward.php @@ -1,215 +1,239 @@ * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindForward.php 3533 2012-05-08 08:24:20Z yishuo $ * @package web */ -class WindForward extends WindModule { - /** - * 定义视图处理器 - * - * @var WindView - */ - protected $windView = null; - /** - * @see WindModule::_delayAttributes - */ - protected $_delayAttributes = array('windView' => array('ref' => 'windView')); - /** - * 存储变量 - * - * @var array - */ - private $vars = array(); - /** - * 是否为Action请求 - * - * @var boolean - */ - private $isReAction = false; - /** - * 是否是重定向请求 - * - * @var boolean - */ - private $isRedirect = false; - /** - * 跳转链接 - * - * @var string - */ - private $url; - private $action; - private $args = array(); - - /** - * 将请求重定向到另外一个Action操作 - * - * 参数支持格式:module/controller/action/?a=&b=&c= - * @param string $action $action 操作 - * @param array $args 参数 默认为空数组 - * @param boolean $isRedirect 是否重定向 默认为false - * @param boolean $immediately 是否理解重定向 默认为true - * @return void - * @throws WindForwardException - */ - public function forwardAction($action, $args = array(), $isRedirect = false, $immediately = true) { - $this->setIsReAction(true); - $this->setAction($action); - $this->setArgs($args); - $this->setIsRedirect($isRedirect); - if ($immediately) throw new WindForwardException($this); - } - - /** - * url重定向 - * - * 采用head方式,将当前的请求重定向到新的url地址 - * @param string $url 重定向的url地址 - * @return void - * @throws WindForwardException - */ - public function forwardRedirect($url) { - $this->setIsRedirect(true); - $this->setUrl($url); - throw new WindForwardException($this); - } - - /** - * 设置当前forward对象中存储的变量 - * - * 设置当前forward对象中存储的变量,设置到forward中的所有变量都可以在模板页面中被直接访问到 - * @param string|array|object $vars - * @param string $key 默认为空字符串 - * @return void - */ - public function setVars($vars, $key = '', $merge = false) { - if (!$key) { - if (is_object($vars)) $vars = get_object_vars($vars); - if (is_array($vars)) $this->vars = array_merge($this->vars, $vars); - } elseif ($merge && !empty($this->vars[$key])) { - $this->vars[$key] = WindUtility::mergeArray((array) $this->vars[$key], (array) $vars); - } else - $this->vars[$key] = $vars; - } - - /** - * 返回当前forward对象中存储的变量信息 - * - * 返回当前forward对象中存储的变量信息,支持多个参数,当参数为空时返回全部的变量信息 - * @return mixed - */ - public function getVars() { - $_tmp = $this->vars; - foreach (func_get_args() as $arg) { - if (is_array($_tmp) && isset($_tmp[$arg])) - $_tmp = $_tmp[$arg]; - else - return ''; - } - return $_tmp; - } - - /** - * @return WindView - */ - public function getWindView() { - if ($this->windView === null) { - $this->_getWindView(); - $module = Wind::getApp()->getModules(); - if (isset($module['template-path'])) { - $this->windView->templateDir = $module['template-path']; - } - if (isset($module['compile-path'])) { - $this->windView->compileDir = $module['compile-path']; - } - if (isset($module['theme-path'])) { - $this->windView->setThemePackage($module['theme-path']); - } - } - return $this->windView; - } - - /** - * @param WindView $windView - */ - public function setWindView($windView) { - $this->windView = $windView; - } - - /** - * @return boolean - */ - public function getIsRedirect() { - return $this->isRedirect; - } - - /** - * @param boolean $isRedirect - */ - public function setIsRedirect($isRedirect) { - $this->isRedirect = $isRedirect; - } - - /** - * @return boolean - */ - public function getIsReAction() { - return $this->isReAction; - } - - /** - * @param boolean $isReAction - */ - public function setIsReAction($isReAction) { - $this->isReAction = $isReAction; - } - - /** - * @return string - */ - public function getUrl() { - return $this->url; - } - - /** - * @param string $url - */ - public function setUrl($url) { - $this->url = $url; - } - - /** - * @return string - */ - public function getAction() { - return $this->action; - } - - /** - * @param string $action - */ - public function setAction($action) { - $this->action = $action; - } - - /** - * @return array - */ - public function getArgs() { - return $this->args; - } - - /** - * @param array - */ - public function setArgs($args) { - $this->args = $args; - } -} \ No newline at end of file +class WindForward extends WindModule +{ + /** + * 定义视图处理器 + * + * @var WindView + */ + protected $windView = null; + /** + * @see WindModule::_delayAttributes + */ + protected $_delayAttributes = array('windView' => array('ref' => 'windView')); + /** + * 存储变量 + * + * @var array + */ + private $vars = array(); + /** + * 是否为Action请求 + * + * @var bool + */ + private $isReAction = false; + /** + * 是否是重定向请求 + * + * @var bool + */ + private $isRedirect = false; + /** + * 跳转链接 + * + * @var string + */ + private $url; + private $action; + private $args = array(); + + /** + * 将请求重定向到另外一个Action操作 + * + * 参数支持格式:module/controller/action/?a=&b=&c= + * @param string $action $action 操作 + * @param array $args 参数 默认为空数组 + * @param bool $isRedirect 是否重定向 默认为false + * @param bool $immediately 是否理解重定向 默认为true + * @throws WindForwardException + */ + public function forwardAction($action, $args = array(), $isRedirect = false, $immediately = true) + { + $this->setIsReAction(true); + $this->setAction($action); + $this->setArgs($args); + $this->setIsRedirect($isRedirect); + if ($immediately) { + throw new WindForwardException($this); + } + } + + /** + * url重定向 + * + * 采用head方式,将当前的请求重定向到新的url地址 + * @param string $url 重定向的url地址 + * @throws WindForwardException + */ + public function forwardRedirect($url) + { + $this->setIsRedirect(true); + $this->setUrl($url); + throw new WindForwardException($this); + } + + /** + * 设置当前forward对象中存储的变量 + * + * 设置当前forward对象中存储的变量,设置到forward中的所有变量都可以在模板页面中被直接访问到 + * @param string|array|object $vars + * @param string $key 默认为空字符串 + */ + public function setVars($vars, $key = '', $merge = false) + { + if (!$key) { + if (is_object($vars)) { + $vars = get_object_vars($vars); + } + if (is_array($vars)) { + $this->vars = array_merge($this->vars, $vars); + } + } elseif ($merge && !empty($this->vars[$key])) { + $this->vars[$key] = WindUtility::mergeArray((array) $this->vars[$key], (array) $vars); + } else { + $this->vars[$key] = $vars; + } + } + + /** + * 返回当前forward对象中存储的变量信息 + * + * 返回当前forward对象中存储的变量信息,支持多个参数,当参数为空时返回全部的变量信息 + * @return mixed + */ + public function getVars() + { + $_tmp = $this->vars; + foreach (func_get_args() as $arg) { + if (is_array($_tmp) && isset($_tmp[$arg])) { + $_tmp = $_tmp[$arg]; + } else { + return ''; + } + } + + return $_tmp; + } + + /** + * @return WindView + */ + public function getWindView() + { + if ($this->windView === null) { + $this->_getWindView(); + $module = Wind::getApp()->getModules(); + if (isset($module['template-path'])) { + $this->windView->templateDir = $module['template-path']; + } + if (isset($module['compile-path'])) { + $this->windView->compileDir = $module['compile-path']; + } + if (isset($module['theme-path'])) { + $this->windView->setThemePackage($module['theme-path']); + } + } + + return $this->windView; + } + + /** + * @param WindView $windView + */ + public function setWindView($windView) + { + $this->windView = $windView; + } + + /** + * @return bool + */ + public function getIsRedirect() + { + return $this->isRedirect; + } + + /** + * @param bool $isRedirect + */ + public function setIsRedirect($isRedirect) + { + $this->isRedirect = $isRedirect; + } + + /** + * @return bool + */ + public function getIsReAction() + { + return $this->isReAction; + } + + /** + * @param bool $isReAction + */ + public function setIsReAction($isReAction) + { + $this->isReAction = $isReAction; + } + + /** + * @return string + */ + public function getUrl() + { + return $this->url; + } + + /** + * @param string $url + */ + public function setUrl($url) + { + $this->url = $url; + } + + /** + * @return string + */ + public function getAction() + { + return $this->action; + } + + /** + * @param string $action + */ + public function setAction($action) + { + $this->action = $action; + } + + /** + * @return array + */ + public function getArgs() + { + return $this->args; + } + + /** + * @param array + */ + public function setArgs($args) + { + $this->args = $args; + } +} diff --git a/wind/web/WindHttpRequest.php b/wind/web/WindHttpRequest.php index 22c991eb..ad1b2ee2 100644 --- a/wind/web/WindHttpRequest.php +++ b/wind/web/WindHttpRequest.php @@ -5,704 +5,822 @@ * @author Qiong Wu * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindHttpRequest.php 3904 2013-01-08 07:01:26Z yishuo $ * @package http * @subpackage request */ -class WindHttpRequest implements IWindRequest { - /** - * 访问的端口号 - * - * @var int - */ - protected $_port = null; - /** - * 请求路径信息 - * - * @var string - */ - protected $_hostInfo = null; - /** - * 客户端IP - * - * @var string - */ - protected $_clientIp = null; - - /** - * 语言 - * - * @var string - */ - protected $_language = null; - - /** - * 路径信息 - * - * @var string - */ - protected $_pathInfo = null; - - /** - * 请求参数信息 - * - * @var array - */ - protected $_attribute = array(); - /** - * 请求脚本url - * - * @var string - */ - private $_scriptUrl = null; - - /** - * 请求参数uri - * - * @var string - */ - private $_requestUri = null; - - /** - * 基础路径信息 - * - * @var string - */ - private $_baseUrl = null; - - /** - * 初始化Request对象 - * - */ - public function __construct() { - $this->normalizeRequest(); - } - - /** - * 初始化request对象 - * - * 对输入参数做转义处理 - */ - protected function normalizeRequest() { - if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) { - if (isset($_GET)) $_GET = $this->_stripSlashes($_GET); - if (isset($_POST)) $_POST = $this->_stripSlashes($_POST); - if (isset($_REQUEST)) $_REQUEST = $this->_stripSlashes($_REQUEST); - if (isset($_COOKIE)) $_COOKIE = $this->_stripSlashes($_COOKIE); - } - } - - /* (non-PHPdoc) - * @see IWindRequest::setAttribute() - */ - public function setAttribute($data, $key = '') { - if ($key) { - $this->_attribute[$key] = $data; - return; - } - if (is_object($data)) $data = get_object_vars($data); - if (is_array($data)) $this->_attribute = array_merge($this->_attribute, $data); - } - - /* (non-PHPdoc) - * @see IWindRequest::getAttribute() - */ - public function getAttribute($key, $defaultValue = '') { - if (isset($this->_attribute[$key])) - return $this->_attribute[$key]; - else if (isset($_GET[$key])) - return $_GET[$key]; - else if (isset($_POST[$key])) - return $_POST[$key]; - else if (isset($_COOKIE[$key])) - return $_COOKIE[$key]; - else if (isset($_REQUEST[$key])) - return $_REQUEST[$key]; - else if (isset($_ENV[$key])) - return $_ENV[$key]; - else if (isset($_SERVER[$key])) - return $_SERVER[$key]; - else - return $defaultValue; - } - - /** - * 获得用户请求的数据 - * - * 返回$_GET,$_POST的值,未设置则返回$defaultValue - * @param string $key 获取的参数name,默认为null将获得$_GET和$_POST两个数组的所有值 - * @param mixed $defaultValue 当获取值失败的时候返回缺省值,默认值为null - * @return mixed - */ - public function getRequest($key = null, $defaultValue = null) { - if (!$key) return array_merge($_POST, $_GET); - if (isset($_GET[$key])) return $_GET[$key]; - if (isset($_POST[$key])) return $_POST[$key]; - return $defaultValue; - } - - /** - * 获取请求的表单数据 - * - * 从$_POST获得值 - * @param string $name 获取的变量名,默认为null,当为null的时候返回$_POST数组 - * @param string $defaultValue 当获取变量失败的时候返回该值,默认为null - * @return mixed - */ - public function getPost($name = null, $defaultValue = null) { - if ($name === null) return $_POST; - return isset($_POST[$name]) ? $_POST[$name] : $defaultValue; - } - - /** - * 获得$_GET值 - * - * @param string $name 待获取的变量名,默认为空字串,当该值为null的时候将返回$_GET数组 - * @param string $defaultValue 当获取的变量不存在的时候返回该缺省值,默认值为null - * @return mixed - */ - public function getGet($name = '', $defaultValue = null) { - if ($name === null) return $_GET; - return (isset($_GET[$name])) ? $_GET[$name] : $defaultValue; - } - - /** - * 返回cookie的值 - * - * 如果$name=null则返回所有Cookie值 - * @param string $name 获取的变量名,如果该值为null则返回$_COOKIE数组,默认为null - * @param string $defaultValue 当获取变量失败的时候返回该值,默认该值为null - * @return mixed - */ - public function getCookie($name = null, $defaultValue = null) { - if ($name === null) return $_COOKIE; - return (isset($_COOKIE[$name])) ? $_COOKIE[$name] : $defaultValue; - } - - /** - * 返回session的值 - * - * 如果$name=null则返回所有SESSION值 - * @param string $name 获取的变量名,如果该值为null则返回$_SESSION数组,默认为null - * @param string $defaultValue 当获取变量失败的时候返回该值,默认该值为null - * @return mixed - */ - public function getSession($name = null, $defaultValue = null) { - if ($name === null) return $_SESSION; - return (isset($_SESSION[$name])) ? $_SESSION[$name] : $defaultValue; - } - - /** - * 返回Server的值 - * - * 如果$name为空则返回所有Server的值 - * @param string $name 获取的变量名,如果该值为null则返回$_SERVER数组,默认为null - * @param string $defaultValue 当获取变量失败的时候返回该值,默认该值为null - * @return mixed - */ - public function getServer($name = null, $defaultValue = null) { - if ($name === null) return $_SERVER; - return (isset($_SERVER[$name])) ? $_SERVER[$name] : $defaultValue; - } - - /** - * 返回ENV的值 - * - * 如果$name为null则返回所有$_ENV的值 - * @param string $name 获取的变量名,如果该值为null则返回$_ENV数组,默认为null - * @param string $defaultValue 当获取变量失败的时候返回该值,默认该值为null - * @return mixed - */ - public function getEnv($name = null, $defaultValue = null) { - if ($name === null) return $_ENV; - return (isset($_ENV[$name])) ? $_ENV[$name] : $defaultValue; - } - - /** - * 获取请求链接协议 - * - * 如果是安全链接请求则返回https否则返回http - * @return string - */ - public function getScheme() { - return ($this->getServer('HTTPS') == 'on') ? 'https' : 'http'; - } - - /** - * 返回请求页面时通信协议的名称和版本 - * @return string - */ - public function getProtocol() { - return $this->getServer('SERVER_PROTOCOL', 'HTTP/1.0'); - } - - /** - * 返回访问IP - * - * 如果获取请求IP失败,则返回0.0.0.0 - * @return string - */ - public function getClientIp() { - if (!$this->_clientIp) $this->_getClientIp(); - return $this->_clientIp; - } - - /** - * 获得请求的方法 - * - * 将返回POST\GET\DELETE等HTTP请求方式 - * @return string - */ - public function getRequestMethod() { - return strtoupper($this->getServer('REQUEST_METHOD')); - } - - /** - * 获得请求类型 - * - * 如果是web请求将返回web - * @return string - */ - public function getRequestType() { - return 'web'; - } - - /** - * 返回该请求是否为ajax请求 - * - * 如果是ajax请求将返回true,否则返回false - * @return boolean - */ - public function getIsAjaxRequest() { - return !strcasecmp($this->getServer('HTTP_X_REQUESTED_WITH'), 'XMLHttpRequest'); - } - - /** - * 请求是否使用的是HTTPS安全链接 - * - * 如果是安全请求则返回true否则返回false - * @return boolean - */ - public function isSecure() { - return !strcasecmp($this->getServer('HTTPS'), 'on'); - } - - /** - * 返回请求是否为GET请求类型 - * - * 如果请求是GET方式请求则返回true,否则返回false - * @return boolean - */ - public function isGet() { - return !strcasecmp($this->getRequestMethod(), 'GET'); - } - - /** - * 返回请求是否为POST请求类型 - * - * 如果请求是POST方式请求则返回true,否则返回false - * - * @return boolean - */ - public function isPost() { - return !strcasecmp($this->getRequestMethod(), 'POST'); - } - - /** - * 返回请求是否为PUT请求类型 - * - * 如果请求是PUT方式请求则返回true,否则返回false - * - * @return boolean - */ - public function isPut() { - return !strcasecmp($this->getRequestMethod(), 'PUT'); - } - - /** - * 返回请求是否为DELETE请求类型 - * - * 如果请求是DELETE方式请求则返回true,否则返回false - * - * @return boolean - */ - public function isDelete() { - return !strcasecmp($this->getRequestMethod(), 'Delete'); - } - - /** - * 初始化请求的资源标识符 - * - * 这里的uri是去除协议名、主机名的 - *
    Example:
    -	 * 请求: http://www.phpwind.net/example/index.php?a=test
    -	 * 则返回: /example/index.php?a=test
    -	 * 
    - * - * @return string - * @throws WindException 当获取失败的时候抛出异常 - */ - public function getRequestUri() { - if (!$this->_requestUri) $this->_initRequestUri(); - return $this->_requestUri; - } - - /** - * 返回当前执行脚本的绝对路径 - * - *
    Example:
    -	 * 请求: http://www.phpwind.net/example/index.php?a=test
    -	 * 返回: /example/index.php
    -	 * 
    - * - * @return string - * @throws WindException 当获取失败的时候抛出异常 - */ - public function getScriptUrl() { - if (!$this->_scriptUrl) $this->_initScriptUrl(); - return $this->_scriptUrl; - } - - /** - * 返回执行脚本名称 - * - *
    Example:
    -	 * 请求: http://www.phpwind.net/example/index.php?a=test
    -	 * 返回: index.php
    -	 * 
    - * - * @return string - * @throws WindException 当获取失败的时候抛出异常 - */ - public function getScript() { - if (($pos = strrpos($this->getScriptUrl(), '/')) === false) $pos = -1; - return substr($this->getScriptUrl(), $pos + 1); - } - - /** - * 获取Http头信息 - * - * @param string $header 头部名称 - * @param string $default 获取失败将返回该值,默认为null - * @return string - */ - public function getHeader($header, $default = null) { - $temp = strtoupper(str_replace('-', '_', $header)); - if (substr($temp, 0, 5) != 'HTTP_') $temp = 'HTTP_' . $temp; - if (($header = $this->getServer($temp)) != null) return $header; - if (function_exists('apache_request_headers')) { - $headers = apache_request_headers(); - if ($headers[$header]) return $headers[$header]; - } - return $default; - } - - /** - * 返回包含由客户端提供的、跟在真实脚本名称之后并且在查询语句(query string)之前的路径信息 - * - *
    Example:
    -	 * 请求: http://www.phpwind.net/example/index.php?a=test
    -	 * 返回: a=test
    -	 * 
    - * - * @see IWindRequest::getPathInfo() - * @return string - * @throws WindException - */ - public function getPathInfo() { - if (!$this->_pathInfo) $this->_initPathInfo(); - return $this->_pathInfo; - } - - /** - * 获取基础URL - * - * 这里是去除了脚本文件以及访问参数信息的URL地址信息: - * - *
    Example:
    -	 * 请求: http://www.phpwind.net/example/index.php?a=test 
    -	 * 1]如果: $absolute = false:
    -	 * 返回: example    
    -	 * 2]如果: $absolute = true:
    -	 * 返回: http://www.phpwind.net/example
    -	 * 
    - * @param boolean $absolute 是否返回主机信息 - * @return string - * @throws WindException 当返回信息失败的时候抛出异常 - */ - public function getBaseUrl($absolute = false) { - if ($this->_baseUrl === null) $this->_baseUrl = rtrim(dirname($this->getScriptUrl()), '\\/.'); - return $absolute ? $this->getHostInfo() . $this->_baseUrl : $this->_baseUrl; - } - - /** - * 获得主机信息,包含协议信息,主机名,访问端口信息 - * - *
    Example:
    -	 * 请求: http://www.phpwind.net/example/index.php?a=test
    -	 * 返回: http://www.phpwind.net/
    -	 * 
    - * @see IWindRequest::getHostInfo() - * @return string - * @throws WindException 获取主机信息失败的时候抛出异常 - */ - public function getHostInfo() { - if ($this->_hostInfo === null) $this->_initHostInfo(); - return $this->_hostInfo; - } - - /** - * 返回当前运行脚本所在的服务器的主机名。 - * - * 如果脚本运行于虚拟主机中 - * 该名称是由那个虚拟主机所设置的值决定 - * @return string - */ - public function getServerName() { - return $this->getServer('SERVER_NAME', ''); - } - - /* (non-PHPdoc) - * @see IWindRequest::getServerPort() - */ - public function getServerPort() { - if (!$this->_port) { - $_default = $this->isSecure() ? 443 : 80; - $this->setServerPort($this->getServer('SERVER_PORT', $_default)); - } - return $this->_port; - } - - /** - * 设置服务端口号 - * - * https链接的默认端口号为443 - * http链接的默认端口号为80 - * @param int $port 设置的端口号 - */ - public function setServerPort($port) { - $this->_port = (int) $port; - } - - /** - * 返回浏览当前页面的用户的主机名 - * - * DNS 反向解析不依赖于用户的 REMOTE_ADDR - * - * @return string - */ - public function getRemoteHost() { - return $this->getServer('REMOTE_HOST'); - } - - /** - * 返回浏览器发送Referer请求头 - * - * 可以让服务器了解和追踪发出本次请求的起源URL地址 - * - * @return string - */ - public function getUrlReferer() { - return $this->getServer('HTTP_REFERER'); - } - - /** - * 获得用户机器上连接到 Web 服务器所使用的端口号 - * - * @return number - */ - public function getRemotePort() { - return $this->getServer('REMOTE_PORT'); - } - - /** - * 返回User-Agent头字段用于指定浏览器或者其他客户端程序的类型和名字 - * - * 如果客户机是一种无线手持终端,就返回一个WML文件;如果发现客户端是一种普通浏览器, - * 则返回通常的HTML文件 - * - * @return string - */ - public function getUserAgent() { - return $this->getServer('HTTP_USER_AGENT', ''); - } - - /** - * 返回当前请求头中 Accept: 项的内容, - * - * Accept头字段用于指出客户端程序能够处理的MIME类型,例如 text/html,image/* - * - * @return string - */ - public function getAcceptTypes() { - return $this->getServer('HTTP_ACCEPT', ''); - } - - /** - * 返回客户端程序可以能够进行解码的数据编码方式 - * - * 这里的编码方式通常指某种压缩方式 - * @return string|'' - */ - public function getAcceptCharset() { - return $this->getServer('HTTP_ACCEPT_ENCODING', ''); - } - - /* (non-PHPdoc) - * @see IWindRequest::getAcceptLanguage() - */ - public function getAcceptLanguage() { - if (!$this->_language) { - $_language = explode(',', $this->getServer('HTTP_ACCEPT_LANGUAGE', '')); - $this->_language = $_language[0] ? $_language[0] : 'zh-cn'; - } - return $this->_language; - } - - /** - * @see IWindRequest::getResponse() - * @return WindHttpResponse - */ - public function getResponse() { - $response = new WindHttpResponse(); - $response->setHeader('Content-type', 'text/html;charset=utf8'); - return $response; - } - - /** - * 返回访问的IP地址 - * - *
    Example:
    -	 * 返回:127.0.0.1
    -	 * 
    - * @return string - */ - private function _getClientIp() { - if (($ip = $this->getServer('HTTP_CLIENT_IP')) != null) { - $this->_clientIp = $ip; - } elseif (($_ip = $this->getServer('HTTP_X_FORWARDED_FOR')) != null) { - $ip = strtok($_ip, ','); - do { - $ip = ip2long($ip); - if (!(($ip == 0) || ($ip == 0xFFFFFFFF) || ($ip == 0x7F000001) || (($ip >= 0x0A000000) && ($ip <= 0x0AFFFFFF)) || (($ip >= 0xC0A8FFFF) && ($ip <= 0xC0A80000)) || (($ip >= 0xAC1FFFFF) && ($ip <= 0xAC100000)))) { - $this->_clientIp = long2ip($ip); - return; - } - } while (($ip = strtok(','))); - } elseif (($ip = $this->getServer('HTTP_PROXY_USER')) != null) { - $this->_clientIp = $ip; - } elseif (($ip = $this->getServer('REMOTE_ADDR')) != null) { - $this->_clientIp = $ip; - } else { - $this->_clientIp = "0.0.0.0"; - } - } - - /** - * 初始化请求的资源标识符 - * - *
    这里的uri是去除协议名、主机名的
    -	 * Example:
    -	 * 请求: http://www.phpwind.net/example/index.php?a=test
    -	 * 则返回: /example/index.php?a=test
    -	 * 
    - * @throws WindException 处理错误抛出异常 - */ - private function _initRequestUri() { - if (($requestUri = $this->getServer('HTTP_X_REWRITE_URL')) != null) { - $this->_requestUri = $requestUri; - } elseif (($requestUri = $this->getServer('REQUEST_URI')) != null) { - $this->_requestUri = $requestUri; - if (strpos($this->_requestUri, $this->getServer('HTTP_HOST')) !== false) $this->_requestUri = preg_replace( - '/^\w+:\/\/[^\/]+/', '', $this->_requestUri); - } elseif (($requestUri = $this->getServer('ORIG_PATH_INFO')) != null) { - $this->_requestUri = $requestUri; - if (($query = $this->getServer('QUERY_STRING')) != null) $this->_requestUri .= '?' . $query; - } else - throw new WindException(__CLASS__ . ' is unable to determine the request URI.'); - } - - /** - * 返回当前执行脚本的绝对路径 - * - *
    Example:
    -	 * 请求: http://www.phpwind.net/example/index.php?a=test
    -	 * 返回: /example/index.php
    -	 * 
    - * @throws WindException 当获取失败的时候抛出异常 - */ - private function _initScriptUrl() { - if (($scriptName = $this->getServer('SCRIPT_FILENAME')) == null) { - throw new WindException(__CLASS__ . ' determine the entry script URL failed!!!'); - } - $scriptName = basename($scriptName); - if (($_scriptName = $this->getServer('SCRIPT_NAME')) != null && basename($_scriptName) === $scriptName) { - $this->_scriptUrl = $_scriptName; - } elseif (($_scriptName = $this->getServer('PHP_SELF')) != null && basename($_scriptName) === $scriptName) { - $this->_scriptUrl = $_scriptName; - } elseif (($_scriptName = $this->getServer('ORIG_SCRIPT_NAME')) != null && basename($_scriptName) === $scriptName) { - $this->_scriptUrl = $_scriptName; - } elseif (($pos = strpos($this->getServer('PHP_SELF'), '/' . $scriptName)) !== false) { - $this->_scriptUrl = substr($this->getServer('SCRIPT_NAME'), 0, $pos) . '/' . $scriptName; - } elseif (($_documentRoot = $this->getServer('DOCUMENT_ROOT')) != null && ($_scriptName = $this->getServer( - 'SCRIPT_FILENAME')) != null && strpos($_scriptName, $_documentRoot) === 0) { - $this->_scriptUrl = str_replace('\\', '/', str_replace($_documentRoot, '', $_scriptName)); - } else - throw new WindException(__CLASS__ . ' determine the entry script URL failed!!'); - } - - /** - * 获得主机信息,包含协议信息,主机名,访问端口信息 - * - *
    Example:
    -	 * 请求: http://www.phpwind.net/example/index.php?a=test
    -	 * 返回: http://www.phpwind.net/
    -	 * 
    - * @throws WindException 获取主机信息失败的时候抛出异常 - */ - private function _initHostInfo() { - $http = $this->isSecure() ? 'https' : 'http'; - if (($httpHost = $this->getServer('HTTP_HOST')) != null) - $this->_hostInfo = $http . '://' . $httpHost; - elseif (($httpHost = $this->getServer('SERVER_NAME')) != null) { - $this->_hostInfo = $http . '://' . $httpHost; - if (($port = $this->getServerPort()) != null) $this->_hostInfo .= ':' . $port; - } else - throw new WindException(__CLASS__ . ' determine the entry script URL failed!!'); - } - - /** - * 返回包含由客户端提供的、跟在真实脚本名称之后并且在查询语句(query string)之前的路径信息 - * - *
    Example:
    -	 * 请求: http://www.phpwind.net/example/index.php?a=test
    -	 * 返回: a=test
    -	 * 
    - * @throws WindException - */ - private function _initPathInfo() { - $requestUri = $this->getRequestUri(); - $scriptUrl = $this->getScriptUrl(); - $baseUrl = $this->getBaseUrl(); - if (strpos($requestUri, $scriptUrl) === 0) - $pathInfo = substr($requestUri, strlen($scriptUrl)); - elseif ($baseUrl === '' || strpos($requestUri, $baseUrl) === 0) - $pathInfo = substr($requestUri, strlen($baseUrl)); - elseif (strpos($_SERVER['PHP_SELF'], $scriptUrl) === 0) - $pathInfo = substr($_SERVER['PHP_SELF'], strlen($scriptUrl)); - else - throw new WindException(__CLASS__ . ' determine the entry path info failed!!'); - if (($pos = strpos($pathInfo, '?')) !== false) $pathInfo = substr($pathInfo, $pos + 1); - $this->_pathInfo = trim($pathInfo, '/'); - } - - /** - * 采用stripslashes反转义特殊字符 - * - * @param array|string $data 待反转义的数据 - * @return array|string 反转义之后的数据 - */ - private function _stripSlashes(&$data) { - return is_array($data) ? array_map(array($this, '_stripSlashes'), $data) : stripslashes($data); - } -} \ No newline at end of file +class WindHttpRequest implements IWindRequest +{ + /** + * 访问的端口号 + * + * @var int + */ + protected $_port = null; + /** + * 请求路径信息 + * + * @var string + */ + protected $_hostInfo = null; + /** + * 客户端IP + * + * @var string + */ + protected $_clientIp = null; + + /** + * 语言 + * + * @var string + */ + protected $_language = null; + + /** + * 路径信息 + * + * @var string + */ + protected $_pathInfo = null; + + /** + * 请求参数信息 + * + * @var array + */ + protected $_attribute = array(); + /** + * 请求脚本url + * + * @var string + */ + private $_scriptUrl = null; + + /** + * 请求参数uri + * + * @var string + */ + private $_requestUri = null; + + /** + * 基础路径信息 + * + * @var string + */ + private $_baseUrl = null; + + /** + * 初始化Request对象 + * + */ + public function __construct() + { + $this->normalizeRequest(); + } + + /** + * 初始化request对象 + * + * 对输入参数做转义处理 + */ + protected function normalizeRequest() + { + if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) { + if (isset($_GET)) { + $_GET = $this->_stripSlashes($_GET); + } + if (isset($_POST)) { + $_POST = $this->_stripSlashes($_POST); + } + if (isset($_REQUEST)) { + $_REQUEST = $this->_stripSlashes($_REQUEST); + } + if (isset($_COOKIE)) { + $_COOKIE = $this->_stripSlashes($_COOKIE); + } + } + } + + /* (non-PHPdoc) + * @see IWindRequest::setAttribute() + */ + public function setAttribute($data, $key = '') + { + if ($key) { + $this->_attribute[$key] = $data; + + return; + } + if (is_object($data)) { + $data = get_object_vars($data); + } + if (is_array($data)) { + $this->_attribute = array_merge($this->_attribute, $data); + } + } + + /* (non-PHPdoc) + * @see IWindRequest::getAttribute() + */ + public function getAttribute($key, $defaultValue = '') + { + if (isset($this->_attribute[$key])) { + return $this->_attribute[$key]; + } elseif (isset($_GET[$key])) { + return $_GET[$key]; + } elseif (isset($_POST[$key])) { + return $_POST[$key]; + } elseif (isset($_COOKIE[$key])) { + return $_COOKIE[$key]; + } elseif (isset($_REQUEST[$key])) { + return $_REQUEST[$key]; + } elseif (isset($_ENV[$key])) { + return $_ENV[$key]; + } elseif (isset($_SERVER[$key])) { + return $_SERVER[$key]; + } else { + return $defaultValue; + } + } + + /** + * 获得用户请求的数据 + * + * 返回$_GET,$_POST的值,未设置则返回$defaultValue + * @param string $key 获取的参数name,默认为null将获得$_GET和$_POST两个数组的所有值 + * @param mixed $defaultValue 当获取值失败的时候返回缺省值,默认值为null + * @return mixed + */ + public function getRequest($key = null, $defaultValue = null) + { + if (!$key) { + return array_merge($_POST, $_GET); + } + if (isset($_GET[$key])) { + return $_GET[$key]; + } + if (isset($_POST[$key])) { + return $_POST[$key]; + } + + return $defaultValue; + } + + /** + * 获取请求的表单数据 + * + * 从$_POST获得值 + * @param string $name 获取的变量名,默认为null,当为null的时候返回$_POST数组 + * @param string $defaultValue 当获取变量失败的时候返回该值,默认为null + * @return mixed + */ + public function getPost($name = null, $defaultValue = null) + { + if ($name === null) { + return $_POST; + } + + return isset($_POST[$name]) ? $_POST[$name] : $defaultValue; + } + + /** + * 获得$_GET值 + * + * @param string $name 待获取的变量名,默认为空字串,当该值为null的时候将返回$_GET数组 + * @param string $defaultValue 当获取的变量不存在的时候返回该缺省值,默认值为null + * @return mixed + */ + public function getGet($name = '', $defaultValue = null) + { + if ($name === null) { + return $_GET; + } + + return (isset($_GET[$name])) ? $_GET[$name] : $defaultValue; + } + + /** + * 返回cookie的值 + * + * 如果$name=null则返回所有Cookie值 + * @param string $name 获取的变量名,如果该值为null则返回$_COOKIE数组,默认为null + * @param string $defaultValue 当获取变量失败的时候返回该值,默认该值为null + * @return mixed + */ + public function getCookie($name = null, $defaultValue = null) + { + if ($name === null) { + return $_COOKIE; + } + + return (isset($_COOKIE[$name])) ? $_COOKIE[$name] : $defaultValue; + } + + /** + * 返回session的值 + * + * 如果$name=null则返回所有SESSION值 + * @param string $name 获取的变量名,如果该值为null则返回$_SESSION数组,默认为null + * @param string $defaultValue 当获取变量失败的时候返回该值,默认该值为null + * @return mixed + */ + public function getSession($name = null, $defaultValue = null) + { + if ($name === null) { + return $_SESSION; + } + + return (isset($_SESSION[$name])) ? $_SESSION[$name] : $defaultValue; + } + + /** + * 返回Server的值 + * + * 如果$name为空则返回所有Server的值 + * @param string $name 获取的变量名,如果该值为null则返回$_SERVER数组,默认为null + * @param string $defaultValue 当获取变量失败的时候返回该值,默认该值为null + * @return mixed + */ + public function getServer($name = null, $defaultValue = null) + { + if ($name === null) { + return $_SERVER; + } + + return (isset($_SERVER[$name])) ? $_SERVER[$name] : $defaultValue; + } + + /** + * 返回ENV的值 + * + * 如果$name为null则返回所有$_ENV的值 + * @param string $name 获取的变量名,如果该值为null则返回$_ENV数组,默认为null + * @param string $defaultValue 当获取变量失败的时候返回该值,默认该值为null + * @return mixed + */ + public function getEnv($name = null, $defaultValue = null) + { + if ($name === null) { + return $_ENV; + } + + return (isset($_ENV[$name])) ? $_ENV[$name] : $defaultValue; + } + + /** + * 获取请求链接协议 + * + * 如果是安全链接请求则返回https否则返回http + * @return string + */ + public function getScheme() + { + return ($this->getServer('HTTPS') == 'on') ? 'https' : 'http'; + } + + /** + * 返回请求页面时通信协议的名称和版本 + * @return string + */ + public function getProtocol() + { + return $this->getServer('SERVER_PROTOCOL', 'HTTP/1.0'); + } + + /** + * 返回访问IP + * + * 如果获取请求IP失败,则返回0.0.0.0 + * @return string + */ + public function getClientIp() + { + if (!$this->_clientIp) { + $this->_getClientIp(); + } + + return $this->_clientIp; + } + + /** + * 获得请求的方法 + * + * 将返回POST\GET\DELETE等HTTP请求方式 + * @return string + */ + public function getRequestMethod() + { + return strtoupper($this->getServer('REQUEST_METHOD')); + } + + /** + * 获得请求类型 + * + * 如果是web请求将返回web + * @return string + */ + public function getRequestType() + { + return 'web'; + } + + /** + * 返回该请求是否为ajax请求 + * + * 如果是ajax请求将返回true,否则返回false + * @return bool + */ + public function getIsAjaxRequest() + { + return !strcasecmp($this->getServer('HTTP_X_REQUESTED_WITH'), 'XMLHttpRequest'); + } + + /** + * 请求是否使用的是HTTPS安全链接 + * + * 如果是安全请求则返回true否则返回false + * @return bool + */ + public function isSecure() + { + return !strcasecmp($this->getServer('HTTPS'), 'on'); + } + + /** + * 返回请求是否为GET请求类型 + * + * 如果请求是GET方式请求则返回true,否则返回false + * @return bool + */ + public function isGet() + { + return !strcasecmp($this->getRequestMethod(), 'GET'); + } + + /** + * 返回请求是否为POST请求类型 + * + * 如果请求是POST方式请求则返回true,否则返回false + * + * @return bool + */ + public function isPost() + { + return !strcasecmp($this->getRequestMethod(), 'POST'); + } + + /** + * 返回请求是否为PUT请求类型 + * + * 如果请求是PUT方式请求则返回true,否则返回false + * + * @return bool + */ + public function isPut() + { + return !strcasecmp($this->getRequestMethod(), 'PUT'); + } + + /** + * 返回请求是否为DELETE请求类型 + * + * 如果请求是DELETE方式请求则返回true,否则返回false + * + * @return bool + */ + public function isDelete() + { + return !strcasecmp($this->getRequestMethod(), 'Delete'); + } + + /** + * 初始化请求的资源标识符 + * + * 这里的uri是去除协议名、主机名的 + *
    Example:
    +     * 请求: http://www.phpwind.net/example/index.php?a=test
    +     * 则返回: /example/index.php?a=test
    +     * 
    + * + * @return string + * @throws WindException 当获取失败的时候抛出异常 + */ + public function getRequestUri() + { + if (!$this->_requestUri) { + $this->_initRequestUri(); + } + + return $this->_requestUri; + } + + /** + * 返回当前执行脚本的绝对路径 + * + *
    Example:
    +     * 请求: http://www.phpwind.net/example/index.php?a=test
    +     * 返回: /example/index.php
    +     * 
    + * + * @return string + * @throws WindException 当获取失败的时候抛出异常 + */ + public function getScriptUrl() + { + if (!$this->_scriptUrl) { + $this->_initScriptUrl(); + } + + return $this->_scriptUrl; + } + + /** + * 返回执行脚本名称 + * + *
    Example:
    +     * 请求: http://www.phpwind.net/example/index.php?a=test
    +     * 返回: index.php
    +     * 
    + * + * @return string + * @throws WindException 当获取失败的时候抛出异常 + */ + public function getScript() + { + if (($pos = strrpos($this->getScriptUrl(), '/')) === false) { + $pos = -1; + } + + return substr($this->getScriptUrl(), $pos + 1); + } + + /** + * 获取Http头信息 + * + * @param string $header 头部名称 + * @param string $default 获取失败将返回该值,默认为null + * @return string + */ + public function getHeader($header, $default = null) + { + $temp = strtoupper(str_replace('-', '_', $header)); + if (substr($temp, 0, 5) != 'HTTP_') { + $temp = 'HTTP_'.$temp; + } + if (($header = $this->getServer($temp)) != null) { + return $header; + } + if (function_exists('apache_request_headers')) { + $headers = apache_request_headers(); + if ($headers[$header]) { + return $headers[$header]; + } + } + + return $default; + } + + /** + * 返回包含由客户端提供的、跟在真实脚本名称之后并且在查询语句(query string)之前的路径信息 + * + *
    Example:
    +     * 请求: http://www.phpwind.net/example/index.php?a=test
    +     * 返回: a=test
    +     * 
    + * + * @see IWindRequest::getPathInfo() + * @return string + * @throws WindException + */ + public function getPathInfo() + { + if (!$this->_pathInfo) { + $this->_initPathInfo(); + } + + return $this->_pathInfo; + } + + /** + * 获取基础URL + * + * 这里是去除了脚本文件以及访问参数信息的URL地址信息: + * + *
    Example:
    +     * 请求: http://www.phpwind.net/example/index.php?a=test
    +     * 1]如果: $absolute = false:
    +     * 返回: example
    +     * 2]如果: $absolute = true:
    +     * 返回: http://www.phpwind.net/example
    +     * 
    + * @param bool $absolute 是否返回主机信息 + * @return string + * @throws WindException 当返回信息失败的时候抛出异常 + */ + public function getBaseUrl($absolute = false) + { + if ($this->_baseUrl === null) { + $this->_baseUrl = rtrim(dirname($this->getScriptUrl()), '\\/.'); + } + + return $absolute ? $this->getHostInfo().$this->_baseUrl : $this->_baseUrl; + } + + /** + * 获得主机信息,包含协议信息,主机名,访问端口信息 + * + *
    Example:
    +     * 请求: http://www.phpwind.net/example/index.php?a=test
    +     * 返回: http://www.phpwind.net/
    +     * 
    + * @see IWindRequest::getHostInfo() + * @return string + * @throws WindException 获取主机信息失败的时候抛出异常 + */ + public function getHostInfo() + { + if ($this->_hostInfo === null) { + $this->_initHostInfo(); + } + + return $this->_hostInfo; + } + + /** + * 返回当前运行脚本所在的服务器的主机名。 + * + * 如果脚本运行于虚拟主机中 + * 该名称是由那个虚拟主机所设置的值决定 + * @return string + */ + public function getServerName() + { + return $this->getServer('SERVER_NAME', ''); + } + + /* (non-PHPdoc) + * @see IWindRequest::getServerPort() + */ + public function getServerPort() + { + if (!$this->_port) { + $_default = $this->isSecure() ? 443 : 80; + $this->setServerPort($this->getServer('SERVER_PORT', $_default)); + } + + return $this->_port; + } + + /** + * 设置服务端口号 + * + * https链接的默认端口号为443 + * http链接的默认端口号为80 + * @param int $port 设置的端口号 + */ + public function setServerPort($port) + { + $this->_port = (int) $port; + } + + /** + * 返回浏览当前页面的用户的主机名 + * + * DNS 反向解析不依赖于用户的 REMOTE_ADDR + * + * @return string + */ + public function getRemoteHost() + { + return $this->getServer('REMOTE_HOST'); + } + + /** + * 返回浏览器发送Referer请求头 + * + * 可以让服务器了解和追踪发出本次请求的起源URL地址 + * + * @return string + */ + public function getUrlReferer() + { + return $this->getServer('HTTP_REFERER'); + } + + /** + * 获得用户机器上连接到 Web 服务器所使用的端口号 + * + * @return number + */ + public function getRemotePort() + { + return $this->getServer('REMOTE_PORT'); + } + + /** + * 返回User-Agent头字段用于指定浏览器或者其他客户端程序的类型和名字 + * + * 如果客户机是一种无线手持终端,就返回一个WML文件;如果发现客户端是一种普通浏览器, + * 则返回通常的HTML文件 + * + * @return string + */ + public function getUserAgent() + { + return $this->getServer('HTTP_USER_AGENT', ''); + } + + /** + * 返回当前请求头中 Accept: 项的内容, + * + * Accept头字段用于指出客户端程序能够处理的MIME类型,例如 text/html,image/* + * + * @return string + */ + public function getAcceptTypes() + { + return $this->getServer('HTTP_ACCEPT', ''); + } + + /** + * 返回客户端程序可以能够进行解码的数据编码方式 + * + * 这里的编码方式通常指某种压缩方式 + * @return string|'' + */ + public function getAcceptCharset() + { + return $this->getServer('HTTP_ACCEPT_ENCODING', ''); + } + + /* (non-PHPdoc) + * @see IWindRequest::getAcceptLanguage() + */ + public function getAcceptLanguage() + { + if (!$this->_language) { + $_language = explode(',', $this->getServer('HTTP_ACCEPT_LANGUAGE', '')); + $this->_language = $_language[0] ? $_language[0] : 'zh-cn'; + } + + return $this->_language; + } + + /** + * 返回访问的IP地址 + * + *
    Example:
    +     * 返回:127.0.0.1
    +     * 
    + * @return string + */ + private function _getClientIp() + { + if (($ip = $this->getServer('HTTP_CLIENT_IP')) != null) { + $this->_clientIp = $ip; + } elseif (($_ip = $this->getServer('HTTP_X_FORWARDED_FOR')) != null) { + $ip = strtok($_ip, ','); + do { + $ip = ip2long($ip); + if (!(($ip == 0) || ($ip == 0xFFFFFFFF) || ($ip == 0x7F000001) || (($ip >= 0x0A000000) && ($ip <= 0x0AFFFFFF)) || (($ip >= 0xC0A8FFFF) && ($ip <= 0xC0A80000)) || (($ip >= 0xAC1FFFFF) && ($ip <= 0xAC100000)))) { + $this->_clientIp = long2ip($ip); + + return; + } + } while (($ip = strtok(','))); + } elseif (($ip = $this->getServer('HTTP_PROXY_USER')) != null) { + $this->_clientIp = $ip; + } elseif (($ip = $this->getServer('REMOTE_ADDR')) != null) { + $this->_clientIp = $ip; + } else { + $this->_clientIp = '0.0.0.0'; + } + } + + /** + * 初始化请求的资源标识符 + * + *
    这里的uri是去除协议名、主机名的
    +     * Example:
    +     * 请求: http://www.phpwind.net/example/index.php?a=test
    +     * 则返回: /example/index.php?a=test
    +     * 
    + * @throws WindException 处理错误抛出异常 + */ + private function _initRequestUri() + { + if (($requestUri = $this->getServer('HTTP_X_REWRITE_URL')) != null) { + $this->_requestUri = $requestUri; + } elseif (($requestUri = $this->getServer('REQUEST_URI')) != null) { + $this->_requestUri = $requestUri; + if (strpos($this->_requestUri, $this->getServer('HTTP_HOST')) !== false) { + $this->_requestUri = preg_replace( + '/^\w+:\/\/[^\/]+/', '', $this->_requestUri); + } + } elseif (($requestUri = $this->getServer('ORIG_PATH_INFO')) != null) { + $this->_requestUri = $requestUri; + if (($query = $this->getServer('QUERY_STRING')) != null) { + $this->_requestUri .= '?'.$query; + } + } else { + throw new WindException('[web.WindHttpRequest._initRequestUri] unable to determine the request URI.'); + } + } + + /** + * 返回当前执行脚本的绝对路径 + * + *
    Example:
    +     * 请求: http://www.phpwind.net/example/index.php?a=test
    +     * 返回: /example/index.php
    +     * 
    + * @throws WindException 当获取失败的时候抛出异常 + */ + private function _initScriptUrl() + { + if (($scriptName = $this->getServer('SCRIPT_FILENAME')) == null) { + throw new WindException('[web.WindHttpRequest._initScriptUrl] determine the entry script URL failed!!!'); + } + $scriptName = basename($scriptName); + if (($_scriptName = $this->getServer('SCRIPT_NAME')) != null && basename($_scriptName) === $scriptName) { + $this->_scriptUrl = $_scriptName; + } elseif (($_scriptName = $this->getServer('PHP_SELF')) != null && basename($_scriptName) === $scriptName) { + $this->_scriptUrl = $_scriptName; + } elseif (($_scriptName = $this->getServer('ORIG_SCRIPT_NAME')) != null && basename($_scriptName) === $scriptName) { + $this->_scriptUrl = $_scriptName; + } elseif (($pos = strpos($this->getServer('PHP_SELF'), '/'.$scriptName)) !== false) { + $this->_scriptUrl = substr($this->getServer('SCRIPT_NAME'), 0, $pos).'/'.$scriptName; + } elseif (($_documentRoot = $this->getServer('DOCUMENT_ROOT')) != null && ($_scriptName = $this->getServer( + 'SCRIPT_FILENAME')) != null && strpos($_scriptName, $_documentRoot) === 0) { + $this->_scriptUrl = str_replace('\\', '/', str_replace($_documentRoot, '', $_scriptName)); + } else { + throw new WindException('[web.WindHttpRequest._initScriptUrl] determine the entry script URL failed!!'); + } + } + + /** + * 获得主机信息,包含协议信息,主机名,访问端口信息 + * + *
    Example:
    +     * 请求: http://www.phpwind.net/example/index.php?a=test
    +     * 返回: http://www.phpwind.net/
    +     * 
    + * @throws WindException 获取主机信息失败的时候抛出异常 + */ + private function _initHostInfo() + { + $http = $this->isSecure() ? 'https' : 'http'; + if (($httpHost = $this->getServer('HTTP_HOST')) != null) { + $this->_hostInfo = $http.'://'.$httpHost; + } elseif (($httpHost = $this->getServer('SERVER_NAME')) != null) { + $this->_hostInfo = $http.'://'.$httpHost; + if (($port = $this->getServerPort()) != null) { + $this->_hostInfo .= ':'.$port; + } + } else { + throw new WindException('[web.WindHttpRequest._initHostInfo] determine the entry script URL failed!!'); + } + } + + /** + * 返回包含由客户端提供的、跟在真实脚本名称之后并且在查询语句(query string)之前的路径信息 + * + *
    Example:
    +     * 请求: http://www.phpwind.net/example/index.php?a=test
    +     * 返回: a=test
    +     * 
    + * @throws WindException + */ + private function _initPathInfo() + { + $requestUri = $this->getRequestUri(); + $scriptUrl = $this->getScriptUrl(); + $baseUrl = $this->getBaseUrl(); + if (strpos($requestUri, $scriptUrl) === 0) { + $pathInfo = substr($requestUri, strlen($scriptUrl)); + } elseif ($baseUrl === '' || strpos($requestUri, $baseUrl) === 0) { + $pathInfo = substr($requestUri, strlen($baseUrl)); + } elseif (strpos($_SERVER['PHP_SELF'], $scriptUrl) === 0) { + $pathInfo = substr($_SERVER['PHP_SELF'], strlen($scriptUrl)); + } else { + throw new WindException('[web.WindHttpRequest._initPathInfo] determine the entry path info failed!!'); + } + if (($pos = strpos($pathInfo, '?')) !== false) { + $pathInfo = substr($pathInfo, $pos + 1); + } + $this->_pathInfo = trim($pathInfo, '/'); + } + + /** + * 采用stripslashes反转义特殊字符 + * + * @param array|string $data 待反转义的数据 + * @return array|string 反转义之后的数据 + */ + private function _stripSlashes(&$data) + { + return is_array($data) ? array_map(array($this, '_stripSlashes'), $data) : stripslashes($data); + } +} diff --git a/wind/web/WindHttpResponse.php b/wind/web/WindHttpResponse.php index ac345658..6636fb2c 100644 --- a/wind/web/WindHttpResponse.php +++ b/wind/web/WindHttpResponse.php @@ -1,7 +1,7 @@ * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindHttpResponse.php 3904 2013-01-08 07:01:26Z yishuo $ * @package http * @subpackage response */ -class WindHttpResponse implements IWindResponse { - /** - * Status code (100) - * - * Server status codes; see RFC 2068. - * Status code (100) indicating the client can continue. - * - * @var int - */ - const W_CONTINUE = 100; - - /** - * Status code (101) indicating the server is switching protocols - * according to Upgrade header. - */ - const W_SWITCHING_PROTOCOLS = 101; - - /** - * Status code (200) - * - * Status code (200) indicating the request succeeded normally. - * - * @var int - */ - const W_OK = 200; - - /** - * Status code (201) - * - * Status code (201) indicating the request succeeded and created - * a new resource on the server. - * - * @var int - */ - const W_CREATED = 201; - - /** - * Status code (202) - * - * Status code (202) indicating that a request was accepted for - * processing, but was not completed. - * - * @var int - */ - const W_ACCEPTED = 202; - - /** - * Status code (203) - * - * Status code (203) indicating that the meta information presented - * by the client did not originate from the server. - * - * @var int - */ - const W_NON_AUTHORITATIVE_INFORMATION = 203; - - /** - * Status code (204) - * - * Status code (204) indicating that the request succeeded but that - * there was no new information to return. - * - * @var int - */ - const W_NO_CONTENT = 204; - - /** - * Status code (205) - * - * Status code (205) indicating that the agent SHOULD reset - * the document view which caused the request to be sent. - * - * @var int - */ - const W_RESET_CONTENT = 205; - - /** - * Status code (206) - * - * Status code (206) indicating that the server has fulfilled - * the partial GET request for the resource. - * - * @var int - */ - const W_PARTIAL_CONTENT = 206; - - /** - * Status code (300) - * - * Status code (300) indicating that the requested resource - * corresponds to any one of a set of representations, each with - * its own specific location. - * - * @var int - */ - const W_MULTIPLE_CHOICES = 300; - - /** - * Status code (301) - * - * Status code (301) indicating that the resource has permanently - * moved to a new location, and that future references should use a - * new URI with their requests. - * - * @var int - */ - const W_MOVED_PERMANENTLY = 301; - - /** - * Status code (302) - * - * Status code (302) indicating that the resource has temporarily - * moved to another location, but that future references should - * still use the original URI to access the resource. - * - * This definition is being retained for backwards compatibility. - * W_FOUND is now the preferred definition. - * - * @var int - */ - const W_MOVED_TEMPORARILY = 302; - - /** - * Status code (302) - * - * Status code (302) indicating that the resource reside - * temporarily under a different URI. Since the redirection might - * be altered on occasion, the client should continue to use the - * Request-URI for future requests.(HTTP/1.1) To represent the - * status code (302), it is recommended to use this variable. - * - * @var int - */ - const W_FOUND = 302; - - /** - * Status code (303) - * - * Status code (303) indicating that the response to the request - * can be found under a different URI. - * - * @var int - */ - const W_SEE_OTHER = 303; - - /** - * Status code (304) - * - * Status code (304) indicating that a conditional GET operation - * found that the resource was available and not modified. - * - * @var int - */ - const W_NOT_MODIFIED = 304; - - /** - * Status code (305) - * - * Status code (305) indicating that the requested resource - * MUST be accessed through the proxy given by the - * Location field. - * - * @var int - */ - const W_USE_PROXY = 305; - - /** - * Status code (307) - * - * Status code (307) indicating that the requested resource - * resides temporarily under a different URI. The temporary URI - * SHOULD be given by the Location - * field in the response. - * - * @var int - */ - const W_TEMPORARY_REDIRECT = 307; - - /** - * Status code (400) - * - * Status code (400) indicating the request sent by the client was - * syntactically incorrect. - * - * @var int - */ - const W_BAD_REQUEST = 400; - - /** - * Status code (401) - * - * Status code (401) indicating that the request requires HTTP - * authentication. - * - * @var int - */ - const W_UNAUTHORIZED = 401; - - /** - * Status code (402) - * - * Status code (402) reserved for future use. - * - * @var int - */ - const W_PAYMENT_REQUIRED = 402; - - /** - * Status code (403) - * - * Status code (403) indicating the server understood the request - * but refused to fulfill it. - * - * @var int - */ - const W_FORBIDDEN = 403; - - /** - * Status code (404) - * - * Status code (404) indicating that the requested resource is not - * available. - * - * @var int - */ - const W_NOT_FOUND = 404; - - /** - * Status code (405) - * - * Status code (405) indicating that the method specified in the - * Request-Line is not allowed for the resource - * identified by the Request-URI. - * - * @var int - */ - const W_METHOD_NOT_ALLOWED = 405; - - /** - * Status code (406) - * - * Status code (406) indicating that the resource identified by the - * request is only capable of generating response entities which have - * content characteristics not acceptable according to the accept - * headers sent in the request. - * - * @var int - */ - const W_NOT_ACCEPTABLE = 406; - - /** - * Status code (407) - * - * Status code (407) indicating that the client MUST first - * authenticate itself with the proxy. - * - * @var int - */ - const W_PROXY_AUTHENTICATION_REQUIRED = 407; - - /** - * Status code (408) - * - * Status code (408) indicating that the client did not produce a - * request within the time that the server was prepared to wait. - * - * @var int - */ - const W_REQUEST_TIMEOUT = 408; - - /** - * Status code (409) - * - * Status code (409) indicating that the request could not be - * completed due to a conflict with the current state of the - * resource. - * - * @var int - */ - const W_CONFLICT = 409; - - /** - * Status code (410) - * - * Status code (410) indicating that the resource is no longer - * available at the server and no forwarding address is known. - * This condition SHOULD be considered permanent. - * - * @var int - */ - const W_GONE = 410; - - /** - * Status code (411) - * - * Status code (411) indicating that the request cannot be handled - * without a defined Content-Length. - * - * @var int - */ - const W_LENGTH_REQUIRED = 411; - - /** - * Status code (412) - * - * Status code (412) indicating that the precondition given in one - * or more of the request-header fields evaluated to false when it - * was tested on the server. - * - * @var int - */ - const W_PRECONDITION_FAILED = 412; - - /** - * Status code (413) - * - * Status code (413) indicating that the server is refusing to process - * the request because the request entity is larger than the server is - * willing or able to process. - * - * @var int - */ - const W_REQUEST_ENTITY_TOO_LARGE = 413; - - /** - * Status code (414) - * - * Status code (414) indicating that the server is refusing to service - * the request because the Request-URI is longer - * than the server is willing to interpret. - * - * @var int - */ - const W_REQUEST_URI_TOO_LONG = 414; - - /** - * Status code (415) - * - * Status code (415) indicating that the server is refusing to service - * the request because the entity of the request is in a format not - * supported by the requested resource for the requested method. - * - * @var int - */ - const W_UNSUPPORTED_MEDIA_TYPE = 415; - - /** - * Status code (416) - * - * Status code (416) indicating that the server cannot serve the - * requested byte range. - * - * @var int - */ - const W_REQUESTED_RANGE_NOT_SATISFIABLE = 416; - - /** - * Status code (417) - * - * Status code (417) indicating that the server could not meet the - * expectation given in the Expect request header. - * - * @var int - */ - const W_EXPECTATION_FAILED = 417; - - /** - * Status code (500) - * - * Status code (500) indicating an error inside the HTTP server - * which prevented it from fulfilling the request. - * - * @var int - */ - const W_INTERNAL_SERVER_ERROR = 500; - - /** - * Status code (501) - * - * Status code (501) indicating the HTTP server does not support - * the functionality needed to fulfill the request. - * - * @var int - */ - const W_NOT_IMPLEMENTED = 501; - - /** - * Status code (502) - * - * Status code (502) indicating that the HTTP server received an - * invalid response from a server it consulted when acting as a - * proxy or gateway. - * - * @var int - */ - const W_BAD_GATEWAY = 502; - - /** - * Status code (503) - * - * Status code (503) indicating that the HTTP server is - * temporarily overloaded, and unable to handle the request. - * - * @var int - */ - const W_SERVICE_UNAVAILABLE = 503; - - /** - * Status code (504) - * - * Status code (504) indicating that the server did not receive - * a timely response from the upstream server while acting as - * a gateway or proxy. - * - * @var int - */ - const W_GATEWAY_TIMEOUT = 504; - - /** - * Status code (505) - * - * Status code (505) indicating that the server does not support - * or refuses to support the HTTP protocol version that was used - * in the request message. - * - * @var int - */ - const W_HTTP_VERSION_NOT_SUPPORTED = 505; - - /** - * 保存模板名字的顺序索引 - * - * @var array - */ - protected $_bodyIndex = array(); - - /** - * 设置输出的头部信息 - * - * @var array - */ - private $_headers = array(); - - /** - * 是否直接跳转 - * - * @var boolean - */ - private $_isRedirect = false; - - /** - * 设置相应状态码 - * - * @var string - */ - private $_status = ''; - - /** - * 返回类型 - * - * @var string - */ - private $_type = ''; - - /** - * 用以保存响应内容 - * - * @var array - */ - protected $_body = array(); - - /** - * 输出的编码 - * - * @var string - */ - protected $_charset = 'utf-8'; - - /** - * 输出数据的保存 - * - * @var array - */ - protected $_data = array(); - - /** - * @return string 返回当前请求的返回类型 - */ - public function getResponseType() { - return $this->_type; - } - - /** - * 设置当前请求的返回类型 - * - * @param string $responseType - */ - public function setResponseType($responseType) { - $this->_type = $responseType; - } - - /** - * 设置响应头信息,如果已经设置过同名的响应头,该方法将用新的设置取代原来的头字段 - * - * @param string $name 响应头的名称 - * @param string $value 响应头的字段取值 - * @param int $replace 响应头信息的replace项值 - * @return void - */ - public function setHeader($name, $value, $replace = false) { - if (!$name || !$value) return; - $name = $this->_normalizeHeader($name); - $setted = false; - foreach ($this->_headers as $key => $one) { - if ($one['name'] == $name) { - $this->_headers[$key] = array('name' => $name, 'value' => $value, 'replace' => $replace); - $setted = true; - break; - } - } - if ($setted === false) $this->_headers[] = array('name' => $name, 'value' => $value, 'replace' => $replace); - } - - /** - * 设置响应头信息,如果已经设置过同名的响应头,该方法将增加一个同名的响应头 - * - * @param string $name 响应头的名称 - * @param string $value 响应头的字段取值 - * @param int $replace 响应头信息的replace项值 - * @return void - */ - public function addHeader($name, $value, $replace = false) { - if ($name == '' || $value == '') return; - $name = $this->_normalizeHeader($name); - $this->_headers[] = array('name' => $name, 'value' => $value, 'replace' => $replace); - } - - /** - * 设置响应头状态码 - * - * @param int $status 响应状态码 - * @param string $message 相应状态信息,默认为空字串 - * @return void - */ - public function setStatus($status, $message = '') { - $status = intval($status); - if ($status < 100 || $status > 505) return; - $this->_status = (int) $status; - } - - /* (non-PHPdoc) - * @see IWindResponse::setBody() - */ - public function setBody($content, $name = 'default') { - if (!$content || !$name) return; - array_push($this->_bodyIndex, $name); - $this->_body[$name] = $content; - } - - /** - * 重定向一个响应信息 - * - * @param string $location 重定向的地址 - * @param int $status 状态码,默认为302 - * @return void - */ - public function sendRedirect($location, $status = 302) { - if (!is_int($status) || $status < 300 || $status > 399) return; - - $this->addHeader('Location', $location, true); - $this->setStatus($status); - $this->_isRedirect = true; - $this->sendHeaders(); - exit(); - } - - /* (non-PHPdoc) - * @see IWindResponse::sendError() - */ - public function sendError($status = self::W_NOT_FOUND, $message = '') { - if (!is_int($status) || $status < 400 || $status > 505) return; - $this->setBody($message, 'error'); - $this->setStatus($status); - $this->sendResponse(); - } - - /* (non-PHPdoc) - * @see IWindResponse::sendResponse() - */ - public function sendResponse() { - $this->sendHeaders(); - $this->sendBody(); - } - - /* (non-PHPdoc) - * @see IWindResponse::sendHeaders() - */ - public function sendHeaders() { - if ($this->isSendedHeader()) return; - foreach ($this->_headers as $header) { - header($header['name'] . ': ' . $header['value'], $header['replace']); - } - if ($this->_status) { - header('HTTP/1.x ' . $this->_status . ' ' . ucwords($this->codeMap($this->_status))); - header('Status: ' . $this->_status . ' ' . ucwords($this->codeMap($this->_status))); - } - } - - /* (non-PHPdoc) - * @see IWindResponse::sendBody() - */ - public function sendBody() { - foreach ($this->_bodyIndex as $key) - echo $this->_body[$key]; - } - - /** - * 获取响应内容 - * - * @param string $name 内容的名称,默认为false: - *
      - *
    • false: 字符串方式返回所有内容
    • - *
    • true: 返回响应内容的片段数组
    • - *
    • string类型: 响应内容中该片段的内容
    • - *
    • other: 返回null
    • - *
    - * @return mixed - */ - public function getBody($name = false) { - if ($name === false) { - ob_start(); - $this->sendBody(); - return ob_get_clean(); - } elseif ($name === true) { - return $this->_body; - } elseif (is_string($name) && isset($this->_body[$name])) - return $this->_body[$name]; - return null; - } - - /** - * 是否已经发送了响应头部 - * - * @param boolean $throw 是否抛出错误,默认为false: - *
      - *
    • true: 如果已经发送了头部则抛出异常信息
    • - *
    • false: 无论如何都不抛出异常信息
    • - *
    - * @return boolean 已经发送头部信息则返回true否则返回false - */ - public function isSendedHeader($throw = false) { - $sended = headers_sent($file, $line); - if ($throw && $sended) throw new WindException( - __CLASS__ . ' the headers are sent in file ' . $file . ' on line ' . $line); - return $sended; - } - - /** - * 获取响应头信息 - * - * @return array - */ - public function getHeaders() { - return $this->_headers; - } - - /** - * 清理响应体信息 - * - * @return void - */ - public function clearBody() { - $this->_body = array(); - } - - /** - * 清除响应头信息 - * - * @return void - */ - public function clearHeaders() { - $this->_headers = array(); - } - - /* (non-PHPdoc) - * @see IWindResponse::getCharset() - */ - public function getCharset() { - return $this->_charset; - } - - /* (non-PHPdoc) - * @see IWindResponse::setCharset() - */ - public function setCharset($_charset) { - $this->_charset = $_charset; - } - - /* (non-PHPdoc) - * @see IWindResponse::getData() - */ - public function getData() { - $_tmp = $this->_data; - foreach (func_get_args() as $arg) { - if (is_array($_tmp) && isset($_tmp[$arg])) - $_tmp = $_tmp[$arg]; - else - return ''; - } - return $_tmp; - } - - /* (non-PHPdoc) - * @see IWindResponse::setData() - */ - public function setData($data, $key = '', $merge = false) { - if ($key) { - if ($merge && !empty($this->_data[$key])) { - $this->_data[$key] = WindUtility::mergeArray((array) $this->_data[$key], (array) $data); - } else - $this->_data[$key] = $data; - } else { - if (is_object($data)) $data = get_object_vars($data); - if (is_array($data)) $this->_data = array_merge($this->_data, $data); - } - } - - /* (non-PHPdoc) - * @see IWindResponse::codeMap() - */ - public function codeMap($code) { - $maps = array( - 505 => 'http version not supported', - 504 => 'gateway timeout', - 503 => 'service unavailable', - 503 => 'bad gateway', - 502 => 'bad gateway', - 501 => 'not implemented', - 500 => 'internal server error', - 417 => 'expectation failed', - 416 => 'requested range not satisfiable', - 415 => 'unsupported media type', - 414 => 'request uri too long', - 413 => 'request entity too large', - 412 => 'precondition failed', - 411 => 'length required', - 410 => 'gone', - 409 => 'conflict', - 408 => 'request timeout', - 407 => 'proxy authentication required', - 406 => 'not acceptable', - 405 => 'method not allowed', - 404 => 'not found', - 403 => 'forbidden', - 402 => 'payment required', - 401 => 'unauthorized', - 400 => 'bad request', - 300 => 'multiple choices', - 301 => 'moved permanently', - 302 => 'moved temporarily', - 302 => 'found', - 303 => 'see other', - 304 => 'not modified', - 305 => 'use proxy', - 307 => 'temporary redirect', - 100 => 'continue', - 101 => 'witching protocols', - 200 => 'ok', - 201 => 'created', - 202 => 'accepted', - 203 => 'non authoritative information', - 204 => 'no content', - 205 => 'reset content', - 206 => 'partial content'); - return isset($maps[$code]) ? $maps[$code] : ''; - } - - /** - * 格式化响应头信息 - * - * @param string $name 响应头部名字 - * @return string - */ - private function _normalizeHeader($name) { - $filtered = str_replace(array('-', '_'), ' ', (string) $name); - $filtered = ucwords(strtolower($filtered)); - $filtered = str_replace(' ', '-', $filtered); - return $filtered; - } - -} \ No newline at end of file +class WindHttpResponse implements IWindResponse +{ + /** + * Status code (100) + * + * Server status codes; see RFC 2068. + * Status code (100) indicating the client can continue. + * + * @var int + */ + const W_CONTINUE = 100; + + /** + * Status code (101) indicating the server is switching protocols + * according to Upgrade header. + */ + const W_SWITCHING_PROTOCOLS = 101; + + /** + * Status code (200) + * + * Status code (200) indicating the request succeeded normally. + * + * @var int + */ + const W_OK = 200; + + /** + * Status code (201) + * + * Status code (201) indicating the request succeeded and created + * a new resource on the server. + * + * @var int + */ + const W_CREATED = 201; + + /** + * Status code (202) + * + * Status code (202) indicating that a request was accepted for + * processing, but was not completed. + * + * @var int + */ + const W_ACCEPTED = 202; + + /** + * Status code (203) + * + * Status code (203) indicating that the meta information presented + * by the client did not originate from the server. + * + * @var int + */ + const W_NON_AUTHORITATIVE_INFORMATION = 203; + + /** + * Status code (204) + * + * Status code (204) indicating that the request succeeded but that + * there was no new information to return. + * + * @var int + */ + const W_NO_CONTENT = 204; + + /** + * Status code (205) + * + * Status code (205) indicating that the agent SHOULD reset + * the document view which caused the request to be sent. + * + * @var int + */ + const W_RESET_CONTENT = 205; + + /** + * Status code (206) + * + * Status code (206) indicating that the server has fulfilled + * the partial GET request for the resource. + * + * @var int + */ + const W_PARTIAL_CONTENT = 206; + + /** + * Status code (300) + * + * Status code (300) indicating that the requested resource + * corresponds to any one of a set of representations, each with + * its own specific location. + * + * @var int + */ + const W_MULTIPLE_CHOICES = 300; + + /** + * Status code (301) + * + * Status code (301) indicating that the resource has permanently + * moved to a new location, and that future references should use a + * new URI with their requests. + * + * @var int + */ + const W_MOVED_PERMANENTLY = 301; + + /** + * Status code (302) + * + * Status code (302) indicating that the resource has temporarily + * moved to another location, but that future references should + * still use the original URI to access the resource. + * + * This definition is being retained for backwards compatibility. + * W_FOUND is now the preferred definition. + * + * @var int + */ + const W_MOVED_TEMPORARILY = 302; + + /** + * Status code (302) + * + * Status code (302) indicating that the resource reside + * temporarily under a different URI. Since the redirection might + * be altered on occasion, the client should continue to use the + * Request-URI for future requests.(HTTP/1.1) To represent the + * status code (302), it is recommended to use this variable. + * + * @var int + */ + const W_FOUND = 302; + + /** + * Status code (303) + * + * Status code (303) indicating that the response to the request + * can be found under a different URI. + * + * @var int + */ + const W_SEE_OTHER = 303; + + /** + * Status code (304) + * + * Status code (304) indicating that a conditional GET operation + * found that the resource was available and not modified. + * + * @var int + */ + const W_NOT_MODIFIED = 304; + + /** + * Status code (305) + * + * Status code (305) indicating that the requested resource + * MUST be accessed through the proxy given by the + * Location field. + * + * @var int + */ + const W_USE_PROXY = 305; + + /** + * Status code (307) + * + * Status code (307) indicating that the requested resource + * resides temporarily under a different URI. The temporary URI + * SHOULD be given by the Location + * field in the response. + * + * @var int + */ + const W_TEMPORARY_REDIRECT = 307; + + /** + * Status code (400) + * + * Status code (400) indicating the request sent by the client was + * syntactically incorrect. + * + * @var int + */ + const W_BAD_REQUEST = 400; + + /** + * Status code (401) + * + * Status code (401) indicating that the request requires HTTP + * authentication. + * + * @var int + */ + const W_UNAUTHORIZED = 401; + + /** + * Status code (402) + * + * Status code (402) reserved for future use. + * + * @var int + */ + const W_PAYMENT_REQUIRED = 402; + + /** + * Status code (403) + * + * Status code (403) indicating the server understood the request + * but refused to fulfill it. + * + * @var int + */ + const W_FORBIDDEN = 403; + + /** + * Status code (404) + * + * Status code (404) indicating that the requested resource is not + * available. + * + * @var int + */ + const W_NOT_FOUND = 404; + + /** + * Status code (405) + * + * Status code (405) indicating that the method specified in the + * Request-Line is not allowed for the resource + * identified by the Request-URI. + * + * @var int + */ + const W_METHOD_NOT_ALLOWED = 405; + + /** + * Status code (406) + * + * Status code (406) indicating that the resource identified by the + * request is only capable of generating response entities which have + * content characteristics not acceptable according to the accept + * headers sent in the request. + * + * @var int + */ + const W_NOT_ACCEPTABLE = 406; + + /** + * Status code (407) + * + * Status code (407) indicating that the client MUST first + * authenticate itself with the proxy. + * + * @var int + */ + const W_PROXY_AUTHENTICATION_REQUIRED = 407; + + /** + * Status code (408) + * + * Status code (408) indicating that the client did not produce a + * request within the time that the server was prepared to wait. + * + * @var int + */ + const W_REQUEST_TIMEOUT = 408; + + /** + * Status code (409) + * + * Status code (409) indicating that the request could not be + * completed due to a conflict with the current state of the + * resource. + * + * @var int + */ + const W_CONFLICT = 409; + + /** + * Status code (410) + * + * Status code (410) indicating that the resource is no longer + * available at the server and no forwarding address is known. + * This condition SHOULD be considered permanent. + * + * @var int + */ + const W_GONE = 410; + + /** + * Status code (411) + * + * Status code (411) indicating that the request cannot be handled + * without a defined Content-Length. + * + * @var int + */ + const W_LENGTH_REQUIRED = 411; + + /** + * Status code (412) + * + * Status code (412) indicating that the precondition given in one + * or more of the request-header fields evaluated to false when it + * was tested on the server. + * + * @var int + */ + const W_PRECONDITION_FAILED = 412; + + /** + * Status code (413) + * + * Status code (413) indicating that the server is refusing to process + * the request because the request entity is larger than the server is + * willing or able to process. + * + * @var int + */ + const W_REQUEST_ENTITY_TOO_LARGE = 413; + + /** + * Status code (414) + * + * Status code (414) indicating that the server is refusing to service + * the request because the Request-URI is longer + * than the server is willing to interpret. + * + * @var int + */ + const W_REQUEST_URI_TOO_LONG = 414; + + /** + * Status code (415) + * + * Status code (415) indicating that the server is refusing to service + * the request because the entity of the request is in a format not + * supported by the requested resource for the requested method. + * + * @var int + */ + const W_UNSUPPORTED_MEDIA_TYPE = 415; + + /** + * Status code (416) + * + * Status code (416) indicating that the server cannot serve the + * requested byte range. + * + * @var int + */ + const W_REQUESTED_RANGE_NOT_SATISFIABLE = 416; + + /** + * Status code (417) + * + * Status code (417) indicating that the server could not meet the + * expectation given in the Expect request header. + * + * @var int + */ + const W_EXPECTATION_FAILED = 417; + + /** + * Status code (500) + * + * Status code (500) indicating an error inside the HTTP server + * which prevented it from fulfilling the request. + * + * @var int + */ + const W_INTERNAL_SERVER_ERROR = 500; + + /** + * Status code (501) + * + * Status code (501) indicating the HTTP server does not support + * the functionality needed to fulfill the request. + * + * @var int + */ + const W_NOT_IMPLEMENTED = 501; + + /** + * Status code (502) + * + * Status code (502) indicating that the HTTP server received an + * invalid response from a server it consulted when acting as a + * proxy or gateway. + * + * @var int + */ + const W_BAD_GATEWAY = 502; + + /** + * Status code (503) + * + * Status code (503) indicating that the HTTP server is + * temporarily overloaded, and unable to handle the request. + * + * @var int + */ + const W_SERVICE_UNAVAILABLE = 503; + + /** + * Status code (504) + * + * Status code (504) indicating that the server did not receive + * a timely response from the upstream server while acting as + * a gateway or proxy. + * + * @var int + */ + const W_GATEWAY_TIMEOUT = 504; + + /** + * Status code (505) + * + * Status code (505) indicating that the server does not support + * or refuses to support the HTTP protocol version that was used + * in the request message. + * + * @var int + */ + const W_HTTP_VERSION_NOT_SUPPORTED = 505; + + /** + * 保存模板名字的顺序索引 + * + * @var array + */ + protected $_bodyIndex = array(); + + /** + * 设置输出的头部信息 + * + * @var array + */ + private $_headers = array(); + + /** + * 是否直接跳转 + * + * @var bool + */ + private $_isRedirect = false; + + /** + * 设置相应状态码 + * + * @var string + */ + private $_status = ''; + + /** + * 返回类型 + * + * @var string + */ + private $_type = ''; + + /** + * 用以保存响应内容 + * + * @var array + */ + protected $_body = array(); + + /** + * 输出的编码 + * + * @var string + */ + protected $_charset; + + /** + * 输出数据的保存 + * + * @var array + */ + protected $_data = array(); + + /** + * @return string 返回当前请求的返回类型 + */ + public function getResponseType() + { + return $this->_type; + } + + /** + * 设置当前请求的返回类型 + * + * @param string $responseType + */ + public function setResponseType($responseType) + { + $this->_type = $responseType; + } + + /** + * 设置响应头信息,如果已经设置过同名的响应头,该方法将用新的设置取代原来的头字段 + * + * @param string $name 响应头的名称 + * @param string $value 响应头的字段取值 + * @param int $replace 响应头信息的replace项值 + */ + public function setHeader($name, $value, $replace = false) + { + if (!$name || !$value) { + return; + } + $name = $this->_normalizeHeader($name); + $setted = false; + foreach ($this->_headers as $key => $one) { + if ($one['name'] == $name) { + $this->_headers[$key] = array('name' => $name, 'value' => $value, 'replace' => $replace); + $setted = true; + break; + } + } + if ($setted === false) { + $this->_headers[] = array('name' => $name, 'value' => $value, 'replace' => $replace); + } + } + + /** + * 设置响应头信息,如果已经设置过同名的响应头,该方法将增加一个同名的响应头 + * + * @param string $name 响应头的名称 + * @param string $value 响应头的字段取值 + * @param int $replace 响应头信息的replace项值 + */ + public function addHeader($name, $value, $replace = false) + { + if ($name == '' || $value == '') { + return; + } + $name = $this->_normalizeHeader($name); + $this->_headers[] = array('name' => $name, 'value' => $value, 'replace' => $replace); + } + + /** + * 设置响应头状态码 + * + * @param int $status 响应状态码 + * @param string $message 相应状态信息,默认为空字串 + */ + public function setStatus($status, $message = '') + { + $status = intval($status); + if ($status < 100 || $status > 505) { + return; + } + $this->_status = (int) $status; + } + + /* (non-PHPdoc) + * @see IWindResponse::setBody() + */ + public function setBody($content, $name = 'default') + { + if (!$content || !$name) { + return; + } + array_push($this->_bodyIndex, $name); + $this->_body[$name] = $content; + } + + /** + * 重定向一个响应信息 + * + * @param string $location 重定向的地址 + * @param int $status 状态码,默认为302 + */ + public function sendRedirect($location, $status = 302) + { + if (!is_int($status) || $status < 300 || $status > 399) { + return; + } + + $this->addHeader('Location', $location, true); + $this->setStatus($status); + $this->_isRedirect = true; + $this->sendHeaders(); + exit(); + } + + /* (non-PHPdoc) + * @see IWindResponse::sendError() + */ + public function sendError($status = self::W_NOT_FOUND, $message = '') + { + if (!is_int($status) || $status < 400 || $status > 505) { + return; + } + $this->setBody($message, 'error'); + $this->setStatus($status); + $this->sendResponse(); + } + + /* (non-PHPdoc) + * @see IWindResponse::sendResponse() + */ + public function sendResponse() + { + $this->sendHeaders(); + $this->sendBody(); + } + + /* (non-PHPdoc) + * @see IWindResponse::sendHeaders() + */ + public function sendHeaders() + { + if ($this->isSendedHeader()) { + return; + } + foreach ($this->_headers as $header) { + header($header['name'].': '.$header['value'], $header['replace']); + } + if ($this->_status) { + header('HTTP/1.x '.$this->_status.' '.ucwords($this->codeMap($this->_status))); + header('Status: '.$this->_status.' '.ucwords($this->codeMap($this->_status))); + } + } + + /* (non-PHPdoc) + * @see IWindResponse::sendBody() + */ + public function sendBody() + { + foreach ($this->_bodyIndex as $key) { + echo $this->_body[$key]; + } + } + + /** + * 获取响应内容 + * + * @param string $name 内容的名称,默认为false: + *
      + *
    • false: 字符串方式返回所有内容
    • + *
    • true: 返回响应内容的片段数组
    • + *
    • string类型: 响应内容中该片段的内容
    • + *
    • other: 返回null
    • + *
    + * @return mixed + */ + public function getBody($name = false) + { + if ($name === false) { + ob_start(); + $this->sendBody(); + + return ob_get_clean(); + } elseif ($name === true) { + return $this->_body; + } elseif (is_string($name) && isset($this->_body[$name])) { + return $this->_body[$name]; + } + + return null; + } + + /** + * 是否已经发送了响应头部 + * + * @param bool $throw 是否抛出错误,默认为false: + *
      + *
    • true: 如果已经发送了头部则抛出异常信息
    • + *
    • false: 无论如何都不抛出异常信息
    • + *
    + * @return bool 已经发送头部信息则返回true否则返回false + */ + public function isSendedHeader($throw = false) + { + $sended = headers_sent($file, $line); + if ($throw && $sended) { + throw new WindException( + '[web.WindHttpResponse.isSendedHeader] the headers are sent in file '.$file.' on line '.$line); + } + + return $sended; + } + + /** + * 获取响应头信息 + * + * @return array + */ + public function getHeaders() + { + return $this->_headers; + } + + /** + * 清理响应体信息 + * + */ + public function clearBody() + { + $this->_body = array(); + } + + /** + * 清除响应头信息 + * + */ + public function clearHeaders() + { + $this->_headers = array(); + } + + /* (non-PHPdoc) + * @see IWindResponse::getCharset() + */ + public function getCharset() + { + return $this->_charset; + } + + /* (non-PHPdoc) + * @see IWindResponse::setCharset() + */ + public function setCharset($_charset) + { + $_charset = strtoupper($_charset); + switch (substr($_charset, 0, 2)) { + case 'BI': + $_charset = 'BIG5'; + break; + case 'GB': + $_charset = 'GBK'; + break; + case 'UN': + case 'UT': + $_charset = 'UTF-8'; + break; + default: + break; + } + $this->_charset = $_charset; + } + + /* (non-PHPdoc) + * @see IWindResponse::getData() + */ + public function getData() + { + $_tmp = $this->_data; + foreach (func_get_args() as $arg) { + if (is_array($_tmp) && isset($_tmp[$arg])) { + $_tmp = $_tmp[$arg]; + } else { + return ''; + } + } + + return $_tmp; + } + + /* (non-PHPdoc) + * @see IWindResponse::setData() + */ + public function setData($data, $key = '', $merge = false) + { + if ($key) { + if ($merge && !empty($this->_data[$key])) { + $this->_data[$key] = WindUtility::mergeArray((array) $this->_data[$key], (array) $data); + } else { + $this->_data[$key] = $data; + } + } else { + if (is_object($data)) { + $data = get_object_vars($data); + } + if (is_array($data)) { + $this->_data = array_merge($this->_data, $data); + } + } + } + + /* (non-PHPdoc) + * @see IWindResponse::codeMap() + */ + public function codeMap($code) + { + $maps = array( + 505 => 'http version not supported', + 504 => 'gateway timeout', + 503 => 'service unavailable', + 503 => 'bad gateway', + 502 => 'bad gateway', + 501 => 'not implemented', + 500 => 'internal server error', + 417 => 'expectation failed', + 416 => 'requested range not satisfiable', + 415 => 'unsupported media type', + 414 => 'request uri too long', + 413 => 'request entity too large', + 412 => 'precondition failed', + 411 => 'length required', + 410 => 'gone', + 409 => 'conflict', + 408 => 'request timeout', + 407 => 'proxy authentication required', + 406 => 'not acceptable', + 405 => 'method not allowed', + 404 => 'not found', + 403 => 'forbidden', + 402 => 'payment required', + 401 => 'unauthorized', + 400 => 'bad request', + 300 => 'multiple choices', + 301 => 'moved permanently', + 302 => 'moved temporarily', + 302 => 'found', + 303 => 'see other', + 304 => 'not modified', + 305 => 'use proxy', + 307 => 'temporary redirect', + 100 => 'continue', + 101 => 'witching protocols', + 200 => 'ok', + 201 => 'created', + 202 => 'accepted', + 203 => 'non authoritative information', + 204 => 'no content', + 205 => 'reset content', + 206 => 'partial content', ); + + return isset($maps[$code]) ? $maps[$code] : ''; + } + + /** + * 格式化响应头信息 + * + * @param string $name 响应头部名字 + * @return string + */ + private function _normalizeHeader($name) + { + $filtered = str_replace(array('-', '_'), ' ', (string) $name); + $filtered = ucwords(strtolower($filtered)); + $filtered = str_replace(' ', '-', $filtered); + + return $filtered; + } +} diff --git a/wind/web/WindSimpleController.php b/wind/web/WindSimpleController.php index ff792600..1145318c 100644 --- a/wind/web/WindSimpleController.php +++ b/wind/web/WindSimpleController.php @@ -1,351 +1,334 @@ * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindSimpleController.php 3859 2012-12-18 09:25:51Z yishuo $ * @package web */ -abstract class WindSimpleController extends WindModule implements IWindController { - /** - * @var WindForward - */ - protected $forward = null; - /** - * @var WindErrorMessage - */ - protected $errorMessage = null; - /** - * @var WindHttpRequest - */ - protected $request = null; - /** - * @var WindHttpResponse - */ - protected $response = null; +abstract class WindSimpleController extends WindModule implements IWindController +{ + /** + * + * @var WindForward + */ + protected $forward = null; + /** + * + * @var WindErrorMessage + */ + protected $errorMessage = null; + /** + * + * @var WindHttpRequest + */ + protected $request = null; + /** + * + * @var WindHttpResponse + */ + protected $response = null; - /** - * 默认的操作处理方法 - * - * @return void - */ - abstract public function run(); - - /* (non-PHPdoc) - * @see IWindController::doAction() - */ - public function doAction($handlerAdapter) { - $_vars = $this->getResponse()->getData('F'); - if ($_vars) $this->getForward()->setVars($_vars); - - $this->beforeAction($handlerAdapter); - $this->setDefaultTemplateName($handlerAdapter); - $method = $this->resolvedActionMethod($handlerAdapter); - call_user_func_array(array($this, $method), array()); - if ($this->errorMessage !== null) $this->getErrorMessage()->sendError(); - $this->afterAction($handlerAdapter); - return $this->forward; - } + /** + * 默认的操作处理方法 + * + */ + abstract public function run(); - /** - * 保存token令牌 - * - * @return void - */ - protected function saveToken($tokenName = 'token') { - /* @var $token WindSecurityToken */ - $token = Wind::getApp()->getComponent('windToken'); - return $token->saveToken($tokenName); - } + /* + * (non-PHPdoc) @see IWindController::doAction() + */ + public function doAction($handlerAdapter) + { + $this->beforeAction($handlerAdapter); + $this->setDefaultTemplateName($handlerAdapter); + $method = $this->resolvedActionMethod($handlerAdapter); + $this->$method(); + if ($this->errorMessage !== null) { + $this->getErrorMessage()->sendError(); + } + $this->afterAction($handlerAdapter); - /** - * 验证令牌 - * - * @param string $tokenValue 当前获得的token值 - * @param string $tokenName token名称 - * @return void - */ - protected function validateToken($tokenValue, $tokenName = 'token') { - /* @var $token WindSecurityToken */ - $token = Wind::getApp()->getComponent('windToken'); - return $token->validateToken($tokenValue, $tokenName); - } + return $this->forward; + } - /** - * action过滤链策略部署 - * @example - *
    -	 * $filters = array(array('expression'=>'', 'class'=>'', args=array()));
    -	 * 
    - * - * @param array $filters - * @return void - */ - protected function resolveActionFilter($filters) { - if (!$filters) return; - $chain = WindFactory::createInstance('WindHandlerInterceptorChain'); - $args = array($this->getForward(), $this->getErrorMessage(), null); - foreach ((array) $filters as $value) { - $chain->addInterceptors( - WindFactory::createInstance(Wind::import($value['class']), - (empty($value['args']) ? $args : array_merge($args, array($value['args']))))); - } - $chain->getHandler()->handle(); - } + /** + * 保存token令牌 + * + */ + protected function saveToken($tokenName = 'token') + { + /* @var $token WindSecurityToken */ + $token = Wind::getComponent('windToken'); - /** - * action操作开始前调用 - * - * @param AbstractWindRouter $handlerAdapter - */ - protected function beforeAction($handlerAdapter) {} + return $token->saveToken($tokenName); + } - /** - * action操作结束后调用 - * - * @param AbstractWindRouter $handlerAdapter - */ - protected function afterAction($handlerAdapter) {} + /** + * 验证令牌 + * + * @param string $tokenValue 当前获得的token值 + * @param string $tokenName token名称 + */ + protected function validateToken($tokenValue, $tokenName = 'token') + { + /* @var $token WindSecurityToken */ + $token = Wind::getComponent('windToken'); - /** - * 重定向一个请求到另外的action - * - * @param string $action 支持格式:module/controller/action/?args - * @param array $args 参数信息 默认为空数组 - * @param boolean $isRedirect 是否是重定向请求 以url重定向方式跳转 - * @param boolean $immediately 是否立即forward - * @return void - */ - protected function forwardAction($action, $args = array(), $isRedirect = false, $immediately = true) { - $this->getForward()->forwardAction($action, $args, $isRedirect, $immediately); - } + return $token->validateToken($tokenValue, $tokenName); + } - /** - * 重定向一个请求到另外的URL - * - * @param string $url - * @return void - */ - protected function forwardRedirect($url) { - $this->getForward()->forwardRedirect($url); - } - - /* 数据处理 */ - /** - * 设置模板数据 - * - * @param string|array|object $data - * @param string $key - * @return void - */ - protected function setOutput($data, $key = '') { - $this->getForward()->setVars($data, $key); - } + /** + * action过滤链策略部署 + * + * @example
    +     *          $filters = array(array('expression'=>'', 'class'=>'',
    +     *          args=array()));
    +     *          
    + * @param array $filters + */ + protected function resolveActionFilter($filters) + { + if (!$filters) { + return; + } + $chain = WindFactory::createInstance('WindHandlerInterceptorChain'); + $args = array($this->getForward(), $this->getErrorMessage(), null); + foreach ((array) $filters as $value) { + $chain->addInterceptors( + WindFactory::createInstance(Wind::import($value['class']), + (empty($value['args']) ? $args : array_merge($args, array($value['args']))))); + } + $chain->getHandler()->handle(); + } - /** - * 设置模板数据 - * - * @param string|array|object $data - * @param string $key - * @return void - */ - protected function setGlobal($data, $key = '') { - Wind::getApp()->setGlobal($data, $key); - } + /** + * action操作开始前调用 + * + * @param AbstractWindRouter $handlerAdapter + */ + protected function beforeAction($handlerAdapter) + { + } - /** - * 获得输入数据 - * - * 如果输入了回调方法则返回数组:第一个值:value;第二个值:验证结果 - * @param string $name input name - * @param string $type input type (GET POST COOKIE) - * @param string $callback validation for input - * @return array|string - */ - protected function getInput($name, $type = '', $callback = null) { - if (is_array($name)) { - $result = array(); - foreach ($name as $key => $value) { - $result[$key] = $this->getInput($value, $type, $callback); - } - return $result; - } else { - $value = ''; - switch (strtolower($type)) { - case 'get': - $value = $this->getRequest()->getGet($name); - break; - case 'post': - $value = $this->getRequest()->getPost($name); - break; - case 'cookie': - $value = $this->getRequest()->getCookie($name); - break; - default: - $value = $this->getRequest()->getAttribute($name); - } - return $callback ? array($value, call_user_func_array($callback, array($value))) : $value; - } - } - - /* 模板处理 */ - /** - * 设置页面模板 - * - * @param string $template - * @return void - */ - protected function setTemplate($template) { - $this->getForward()->getWindView()->templateName = $template; - } + /** + * action操作结束后调用 + * + * @param AbstractWindRouter $handlerAdapter + */ + protected function afterAction($handlerAdapter) + { + } - /** - * 设置模板路径,模板目录地址,支持命名空间方式 - * - * @param string $templatePath - * @return void - */ - protected function setTemplatePath($templatePath) { - $this->getForward()->getWindView()->templateDir = $templatePath; - } + /** + * 重定向一个请求到另外的action + * + * @param string $action 支持格式:module/controller/action/?args + * @param array $args 参数信息 默认为空数组 + * @param bool $isRedirect 是否是重定向请求 以url重定向方式跳转 + * @param bool $immediately 是否立即forward + */ + protected function forwardAction($action, $args = array(), $isRedirect = false, $immediately = true) + { + $this->getForward()->forwardAction($action, $args, $isRedirect, $immediately); + } - /** - * 设置模板文件的扩展名 - * - * @param string $templateExt - * @return void - */ - protected function setTemplateExt($templateExt) { - $this->getForward()->getWindView()->templateExt = $templateExt; - } + /** + * 重定向一个请求到另外的URL + * + * @param string $url + */ + protected function forwardRedirect($url) + { + $this->getForward()->forwardRedirect($url); + } - /** - * 设置当前主题信息 - * - * @param string $theme - * @return void - */ - protected function setTheme($theme) { - $this->getForward()->getWindView()->setTheme($theme); - } + /* 数据处理 */ + /** + * 设置模板数据 + * + * @param string|array|object $data + * @param string $key + */ + protected function setOutput($data, $key = '') + { + $this->getForward()->setVars($data, $key); + } - /** - * 设置主题包 - * - * @param string $package - * @return void - */ - protected function setThemePackage($package) { - $this->getForward()->getWindView()->setThemePackage($package); - } + /** + * 获得输入数据 + * 如果输入了回调方法则返回数组:第一个值:value;第二个值:验证结果 + * + * @param string $name input name + * @param string $type input type (GET POST COOKIE) + * @return array string + */ + protected function getInput($name, $type = '', $bindKey = false) + { + if (is_array($name)) { + $result = array(); + foreach ($name as $key => $value) { + $_k = $bindKey ? $value : $key; + $result[$_k] = $this->getInput($value, $type); + } - /** - * 设置布局页面 - * - * @param string $layout - * @return void - */ - protected function setLayout($layout) { - $this->getForward()->getWindView()->layout = $layout; - } - - /* 错误处理 */ - /** - * 添加错误信息 - * - * @param string $message - * @param string $key 默认为空字符串 - * @return void - */ - protected function addMessage($message, $key = '') { - $this->getErrorMessage()->addError($message, $key); - } + return $result; + } elseif ($name) { + $value = ''; + switch (strtolower($type)) { + case 'get': + $value = $this->getRequest()->getGet($name); + break; + case 'post': + $value = $this->getRequest()->getPost($name); + break; + case 'cookie': + $value = $this->getRequest()->getCookie($name); + break; + default: + $value = $this->getRequest()->getRequest($name); + } - /** - * 发送一个错误请求 - * - * @param string $message 默认为空字符串 - * @param string $key 默认为空字符串 - * @param string $errorAction 默认为空字符串 - * @return void - */ - protected function showMessage($message = '', $key = '', $errorAction = '') { - $this->addMessage($message, $key); - $this->getErrorMessage()->setErrorAction($errorAction); - $this->getErrorMessage()->sendError(); - } + return $value; + } - /** - * 设置默认的模板名称 - * - * @param WindUrlBasedRouter $handlerAdapter - * @return void - */ - protected function setDefaultTemplateName($handlerAdapter) {} + return ''; + } - /** - * 解析action操作方法名称 - * - * 可以通过覆盖该方法,改变action解析规则 - * @param WindUrlBasedRouter $handlerAdapter - * @return string 返回解析到的action操作处理方法,默认只返回run - */ - protected function resolvedActionMethod($handlerAdapter) { - return 'run'; - } + /* 模板处理 */ + /** + * 设置页面模板 + * + * @param string $template + */ + protected function setTemplate($template) + { + $this->getForward()->getWindView()->templateName = $template; + } - /** - * @return WindForward - */ - public function getForward() { - return $this->_getForward(); - } + /** + * 设置模板路径,模板目录地址,支持命名空间方式 + * + * @param string $templatePath + */ + protected function setTemplatePath($templatePath) + { + $this->getForward()->getWindView()->templateDir = $templatePath; + } - /** - * @return WindErrorMessage - */ - public function getErrorMessage() { - return $this->_getErrorMessage(); - } + /** + * 设置模板文件的扩展名 + * + * @param string $templateExt + */ + protected function setTemplateExt($templateExt) + { + $this->getForward()->getWindView()->templateExt = $templateExt; + } - /** - * @param WindForward $forward - */ - public function setForward($forward) { - $this->forward = $forward; - } + /** + * 设置当前主题信息 + * + * @param string $theme + */ + protected function setTheme($theme, $package) + { + $this->getForward()->getWindView()->setTheme($theme, $package); + } - /** - * @param WindErrorMessage $errorMessage - */ - public function setErrorMessage($errorMessage) { - $this->errorMessage = $errorMessage; - } -} + /** + * 设置布局页面 + * + * @param string $layout + */ + protected function setLayout($layout) + { + $this->getForward()->getWindView()->layout = $layout; + } -/** - * 应用控制器接口定义类 - * - * 该类定义了一个唯一需要被实现的方法'doAction',该方法接收一个路由对象作为参数,进行操作处理并返回一个forward对象 - * @author Qiong Wu - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package web - */ -interface IWindController { + /* 错误处理 */ + /** + * 添加错误信息 + * + * @param string $message + * @param string $key 默认为空字符串 + */ + protected function addMessage($message, $key = '') + { + $this->getErrorMessage()->addError($message, $key); + } + + /** + * 发送一个错误请求 + * + * @param string $message 默认为空字符串 + * @param string $key 默认为空字符串 + * @param string $errorAction 默认为空字符串 + */ + protected function showMessage($message = '', $key = '', $errorAction = '') + { + $this->addMessage($message, $key); + $errorAction && $this->getErrorMessage()->setErrorAction($errorAction); + $this->getErrorMessage()->sendError(); + } + + /** + * 设置默认的模板名称 + * + * @param WindUrlBasedRouter $handlerAdapter + */ + protected function setDefaultTemplateName($handlerAdapter) + { + } + + /** + * 解析action操作方法名称 + * 可以通过覆盖该方法,改变action解析规则 + * + * @param WindUrlBasedRouter $handlerAdapter + * @return string 返回解析到的action操作处理方法,默认只返回run + */ + protected function resolvedActionMethod($handlerAdapter) + { + return 'run'; + } + + /** + * + * @return WindForward + */ + public function getForward() + { + return $this->_getForward(); + } + + /** + * + * @return WindErrorMessage + */ + public function getErrorMessage() + { + return $this->_getErrorMessage(); + } + + /** + * + * @param WindForward $forward + */ + public function setForward($forward) + { + $this->forward = $forward; + } - /** - * 处理请求并返回Forward对象 - * - * @param WindRouter $handlerAdapter - * @param WindHttpRequest $request - * @param WindHttpResponse $response - * @return WindForward|null - */ - public function doAction($handlerAdapter); + /** + * + * @param WindErrorMessage $errorMessage + */ + public function setErrorMessage($errorMessage) + { + $this->errorMessage = $errorMessage; + } } -?> \ No newline at end of file diff --git a/wind/web/WindUrlHelper.php b/wind/web/WindUrlHelper.php deleted file mode 100644 index 411dba2a..00000000 --- a/wind/web/WindUrlHelper.php +++ /dev/null @@ -1,133 +0,0 @@ - - * @copyright ©2003-2103 phpwind.com - * @license http://www.windframework.com - * @version $Id$ - * @package web - */ -class WindUrlHelper { - private static $_sep = '_array_'; - - /** - * url检查 - * - * 当$absolute === true且url不包含协议部分时,默认加上当前应用的协议部分. - * @param string $url 需要检查合法性的url - * @param boolean $absolute 是否为绝对路径 - * @return string - */ - public static function checkUrl($url, $absolute = true) { - if ($absolute) { - $_baseUrl = $absolute === true ? Wind::getApp()->getRequest()->getBaseUrl(true) : $absolute; - if (strpos($url, '://') === false) { - $url = trim($_baseUrl, '/') . '/' . trim($url, '/'); - } - } - return $url; - } - - /** - * url字符串转化为数组格式 - * - * 效果同'argsToUrl'相反 - * @param string $url - * @param boolean $decode 是否需要进行url反编码处理 - * @param string $separator url的分隔符 - * @return array - */ - public static function urlToArgs($url, $decode = true, $separator = '&=') { - if (strlen($separator) !== 2) return array(); - if (false !== $pos = strpos($url, '?')) $url = substr($url, $pos + 1); - $url = explode($separator[0], trim($url, $separator[0])); - $args = array(); - if ($separator[0] === $separator[1]) { - $_count = count($url); - for ($i = 0; $i < $_count; $i += 2) { - if (!isset($url[$i + 1])) { - $args[] = $decode ? rawurldecode($url[$i]) : $url[$i]; - continue; - } - $_k = $decode ? rawurldecode($url[$i]) : $url[$i]; - $_v = $decode ? rawurldecode($url[$i + 1]) : $url[$i + 1]; - $args[$_k] = $_v; - } - } else { - foreach ($url as $value) { - if (strpos($value, $separator[1]) === false) { - $args[] = $decode ? rawurldecode($value) : $value; - continue; - } - list($__k, $__v) = explode($separator[1], $value); - $args[$__k] = $decode && $__v ? rawurldecode($__v) : $__v; - } - } - return $args; - } - - /** - * 将数组格式的参数列表转换为Url格式,并将url进行编码处理 - * - * 参数:array('b'=>'b','c'=>'index','d'=>'d') - * 分割符: '&=' - * 转化结果:&b=b&c=index&d=d - * 如果分割符为: '/' 则转化结果为: /b/b/c/index/d/d/ - * @param array $args - * @param boolean $encode 是否进行url编码 默认值为true - * @param string $separator url分隔符 支持双字符,前一个字符用于分割参数对,后一个字符用于分割键值对 - * @return string - */ - public static function argsToUrl($args, $encode = true, $separator = '&=') { - if (strlen($separator) !== 2) return; - $_tmp = ''; - foreach ((array) $args as $key => $value) { - $value = $encode ? rawurlencode($value) : $value; - if (is_int($key)) { - $value && $_tmp .= $value . $separator[0]; - continue; - } - $key = ($encode ? rawurlencode($key) : $key); - $_tmp .= $key . $separator[1] . $value . $separator[0]; - } - return trim($_tmp, $separator[0]); - } - - /** - * 解析ControllerPath,并返回解析后的结果集 - * - * 返回值:array(action,controller,module,args) - * action格式:'/module/controller/action/?a=a&b=b&c=c&',前边用斜线分割mca信息,后边用问号分割参数列表. - * @param string $controllerPath - * @param array $args 默认值为空数组 - * @return array - */ - public static function resolveAction($action, $args = array()) { - list($action, $_args) = explode('?', $action . '?'); - $args = array_merge($args, ($_args ? self::urlToArgs($_args, false) : array())); - $action = explode('/', trim($action, '/') . '/'); - end($action); - return array(prev($action), prev($action), prev($action), prev($action), $args); - } - - /** - * 构造并返回Url地址 - * - * 将根据是否开启url重写来分别构造相对应的url - * @param string $action 执行的操作 - * @param array $args 附带的参数 - * @param string $anchor url锚点 - * @param AbstractWindRoute $route - * @param boolean $absolute 是否返回绝对地址 - * @return string 返回url地址 - */ - public static function createUrl($action, $args = array(), $anchor = '', $route = null, $absolute = true) { - /* @var $router AbstractWindRouter */ - $router = Wind::getApp()->getComponent('router'); - $url = $router->assemble($action, $args, $route); - $url .= $anchor ? '#' . $anchor : ''; - return self::checkUrl($url, $absolute); - } -} -?> \ No newline at end of file diff --git a/wind/web/WindWebApplication.php b/wind/web/WindWebApplication.php index c5340b46..99d3f027 100644 --- a/wind/web/WindWebApplication.php +++ b/wind/web/WindWebApplication.php @@ -5,310 +5,65 @@ * @author Qiong Wu * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindWebApplication.php 3859 2012-12-18 09:25:51Z yishuo $ * @package web */ -class WindWebApplication extends WindModule implements IWindApplication { - /** - * @var WindHttpRequest - */ - protected $request; - /** - * @var WindHttpResponse - */ - protected $response; - /** - * @var WindFactory - */ - protected $windFactory = null; - /** - * @var WindDispatcher - */ - protected $dispatcher = null; - /** - * @var WindRouter - */ - protected $handlerAdapter = null; - protected $defaultModule = array( - 'controller-path' => 'controller', - 'controller-suffix' => 'Controller', - 'error-handler' => 'WIND:web.WindErrorHandler'); +class WindWebApplication extends AbstractWindApplication +{ + /** + * 委派器 + * + * @var WindDispatcher + */ + protected $dispatcher = null; - /** - * 应用初始化操作 - * - * @param WindHttpRequest $request - * @param WindHttpResponse $response - * @param WindFactory $factory - */ - public function __construct($request, $factory) { - $this->response = $request->getResponse(); - $this->request = $request; - $this->windFactory = $factory; - } + /* (non-PHPdoc) + * @see AbstractWindApplication::doDispatch() + */ + public function doDispatch($forward, $display = false) + { + if ($forward === null) { + return; + } + if ($this->dispatcher === null) { + $this->dispatcher = $this->factory->getInstance( + 'dispatcher'); + } + $this->dispatcher->dispatch($forward, $this->handlerAdapter, $display); + } - /** - * 请求处理完毕后,进一步分发 - * - * @param WindForward $forward - * @param boolean $display - */ - public function doDispatch($forward, $display = false) { - if ($forward === null) return; - $this->_getDispatcher()->dispatch($forward, $this->handlerAdapter, $display); - } - - /* (non-PHPdoc) - * @see IWindApplication::run() - */ - public function run($filters = false) { - $module = $this->getModules($this->_getHandlerAdapter()->getModule()); - $handlerPath = $module['controller-path'] . '.' . ucfirst($this->handlerAdapter->getController()) . $module['controller-suffix']; - $className = Wind::import($handlerPath); - if (!class_exists($className)) throw new WindException( - 'Your requested \'' . $handlerPath . '\' was not found on this server.', 404); - $handler = new $className(); - $handler->setDelayAttributes( - array('errorMessage' => array('ref' => 'errorMessage'), 'forward' => array('ref' => 'forward'))); - $filters && $this->resolveActionFilters($handler); - - try { - $forward = $handler->doAction($this->handlerAdapter); - $this->doDispatch($forward); - } catch (WindForwardException $e) { - $this->doDispatch($e->getForward()); - } catch (WindActionException $e) { - $this->sendErrorMessage(($e->getError() ? $e->getError() : $e->getMessage()), $e->getCode()); - } catch (WindException $e) { - $this->sendErrorMessage($e->getMessage(), $e->getCode()); - } - } - - /* (non-PHPdoc) - * @see WindModule::setConfig() - */ - public function setConfig($config) { - parent::setConfig($config); - if ($default = $this->getConfig('modules', 'default', array())) { - $this->defaultModule = WindUtility::mergeArray($this->defaultModule, $default); - } - $charset = $this->getConfig('charset', '', 'utf-8'); - $this->getResponse()->setHeader('Content-type', 'text/html;charset=' . $charset); - $this->getResponse()->setCharset($charset); - } + /* (non-PHPdoc) + * @see AbstractWindApplication::sendErrorMessage() + */ + protected function sendErrorMessage($errorMessage, $errorcode) + { + if (!is_object($errorMessage)) { + $_tmp = $errorMessage; + /* @var $errorMessage WindErrorMessage */ + $errorMessage = Wind::getComponent('errorMessage'); + $errorMessage->addError($_tmp); + } + /* @var $router WindRouter */ + $moduleName = $this->handlerAdapter->getModule(); + if ($moduleName === 'error') { + throw new WindFinalException($errorMessage->getError(0)); + } - /** - * 设置全局变量 - * - * @param array|object|string $data - * @param string $key - * @return void - */ - public function setGlobal($data, $key = '') { - if ($key) - $_G[$key] = $data; - else { - if (is_object($data)) $data = get_object_vars($data); - $_G = $data; - } - $this->response->setData($_G, 'G', true); - } - - /** - * 获取全局变量 - * - * @return mixed - */ - public function getGlobal() { - $_args = func_get_args(); - array_unshift($_args, 'G'); - return call_user_func_array(array($this->response, 'getData'), $_args); - } - - /** - * 添加module配置 - * - * controller - * - * Controller - * - * WIND:web.WindErrorHandler - * - * - * - * template - * - * htm - * - * @param string $name module名称 - * @param array $config 配置数组 - * @param boolean $replace 如果module已经存在是否覆盖他 默认值为false不进行覆盖 - * @return array - */ - public function setModules($name, $config, $replace = false) { - if ($replace || !isset($this->_config['modules'][$name])) { - $this->_config['modules'][$name] = (array) $config; - } - return $this->_config['modules'][$name]; - } - - /** - * 获得module配置,$name为空时返回当前module配置 - * - * @param string $name module名称 默认为空 - * @param boolean $merge 合并默认值 - * @return array - * @throws WindActionException - * @throws WindException - */ - public function getModules($name = '') { - if ($name === '') $name = $this->handlerAdapter->getModule(); - $_module = $this->getConfig('modules', $name, array()); - if (!isset($_module['_verified']) || $_module['_verified'] !== true) { - if (empty($_module)) { - $_module = $this->getConfig('modules', 'pattern', array()); - $_pattern = !empty($_module); - } - $_module = WindUtility::mergeArray($this->defaultModule, $_module); - if (isset($_pattern) && $_pattern) { - $_keys = array_keys($_module); - $_replace = array( - '{' . $this->handlerAdapter->getModuleKey() . '}' => $this->handlerAdapter->getModule(), - '{' . $this->handlerAdapter->getControllerKey() . '}' => $this->handlerAdapter->getController(), - '{' . $this->handlerAdapter->getActionKey() . '}' => $this->handlerAdapter->getAction()); - foreach ($_keys as $_key) { - if (strrchr($_key, '-') !== '-path') continue; - $_module[$_key] = strtr($_module[$_key], $_replace); - } - } - $_module['_verified'] = true; - $this->_config['modules'][$name] = $_module; - } - return $_module; - } - - /** - * 获得组件对象 - * - * @param string $componentName 组件名称呢个 - * @return object - */ - public function getComponent($componentName, $args = array()) { - return $this->windFactory->getInstance($componentName, $args); - } - - /** - * 手动注册actionFilter - * - * 参数为数组格式: - * @param array $filters - */ - public function registeActionFilter($filters) { - if (!$filters) return; - if (empty($this->_config['filters'])) - $this->_config['filters'] = $filters; - else - $this->_config['filters'] += $filters; - } - - /** - * 解析action过滤链的配置信息 - * - * @param WindSimpleController $handler - * @return void - */ - protected function resolveActionFilters(&$handler) { - if (!$filters = $this->getConfig('filters')) return; - /* @var $cache AbstractWindCache */ - $_filters = array(); - if ($cache = $this->getComponent('windCache')) { - $_filters = $cache->get('filters'); - } - $_token = $this->handlerAdapter->getModule() . '/' . $this->handlerAdapter->getController() . '/' . $this->handlerAdapter->getAction(); - if (!isset($_filters[$_token])) { - foreach ($filters as $_filter) { - if (empty($_filter['class'])) continue; - $_pattern = empty($_filter['pattern']) ? '' : $_filter['pattern']; - unset($_filter['pattern']); - if ($_pattern) { - $_pattern = str_replace(array('*', '/'), array('\w*', '\/'), $_pattern); - if (in_array($_pattern[0], array('~', '!'))) { - $_pattern = substr($_pattern, 1); - if (preg_match('/^' . $_pattern . '$/i', $_token)) continue; - } else { - if (!preg_match('/^' . $_pattern . '$/i', $_token)) continue; - } - } - $_filters[$_token][] = $_filter; - } - $cache && $cache->set('filters', $_filters); - } - if (empty($_filters[$_token])) return; - /* @var $proxy WindClassProxy */ - $proxy = WindFactory::createInstance(Wind::import('WIND:factory.WindClassProxy')); - $proxy->registerTargetObject($handler); - foreach ($_filters[$_token] as $value) { - $proxy->registerEventListener('doAction', - $this->windFactory->createInstance(Wind::import($value['class']), - array($handler->getForward(), $handler->getErrorMessage(), $this->handlerAdapter, $value))); - } - $handler = $proxy; - } - - /** - * 处理错误请求 - * - * 根据错误请求的相关信息,将程序转向到错误处理句柄进行错误处理 - * @param WindErrorMessage $errorMessage - * @param int $errorcode - * @return void - */ - protected function sendErrorMessage($errorMessage, $errorcode) { - if (is_string($errorMessage)) { - $_tmp = $errorMessage; - /* @var $errorMessage WindErrorMessage */ - $errorMessage = $this->getComponent('errorMessage'); - $errorMessage->addError($_tmp); - } - /* @var $router WindRouter */ - $moduleName = $this->handlerAdapter->getModule(); - if ($moduleName === 'error') throw new WindFinalException($errorMessage->getError(0)); - - if (!$_errorAction = $errorMessage->getErrorAction()) { - $module = $this->getModules($moduleName); - $_errorClass = Wind::import(@$module['error-handler']); - $_errorAction = 'error/' . $_errorClass . '/run/'; - $this->setModules('error', - array( - 'controller-path' => array_search($_errorClass, Wind::$_imports), - 'controller-suffix' => '', - 'error-handler' => '')); - } - /* @var $forward WindForward */ - $forward = $this->getComponent('forward'); - $error = array('message' => $errorMessage->getError(), 'code' => $errorcode); - $forward->forwardAction($_errorAction, array('__error' => $error), false, false); - $this->doDispatch($forward); - } - - /** - * @return WindHttpRequest - */ - public function getRequest() { - return $this->request; - } - - /** - * @return WindHttpResponse - */ - public function getResponse() { - return $this->response; - } - - /** - * @return WindFactory - */ - public function getWindFactory() { - return $this->windFactory; - } -} \ No newline at end of file + if (!$_errorAction = $errorMessage->getErrorAction()) { + $module = $this->getModules($moduleName); + $_errorClass = Wind::import(@$module['error-handler']); + $_errorAction = 'error/'.$_errorClass.'/run/'; + $this->setModules('error', + array( + 'controller-path' => array_search($_errorClass, Wind::$_imports), + 'controller-suffix' => '', + 'error-handler' => '', )); + } + /* @var $forward WindForward */ + $forward = Wind::getComponent('forward'); + $error = array('message' => $errorMessage->getError(), 'code' => $errorcode); + $forward->forwardAction($_errorAction, + array('__error' => $error, '__errorDir' => $this->getConfig('error-dir')), false, false); + $this->doDispatch($forward); + } +} diff --git a/wind/web/WindWebError.php b/wind/web/WindWebError.php new file mode 100644 index 00000000..8a0bbbda --- /dev/null +++ b/wind/web/WindWebError.php @@ -0,0 +1,71 @@ + + * @copyright ©2003-2103 phpwind.com + * @license http://www.windframework.com + * @version $Id$ + * @package wind.web + */ +class WindWebError extends WindError +{ + /* (non-PHPdoc) + * @see WindError::showErrorMessage() + */ + protected function showErrorMessage($message, $file, $line, $trace, $errorcode) + { + list($fileLines, $trace) = $this->crash($file, $line, $trace); + + if (Wind::$isDebug & 2) { + $log = $message."\r\n".$file.':'.$line."\r\n"; + foreach ($trace as $key => $value) { + $log .= $value."\r\n"; + } + Wind::getComponent('windLogger')->error($log, 'error', true); + } + + $message = nl2br($message); + $errDir = Wind::getRealPath($this->errorDir, false); + if ($this->isClosed) { + $errPage = 'close'; + } elseif (is_file($errDir.'/'.$errorcode.'.htm')) { + $errPage = $errorcode; + } else { + $errPage = 'error'; + } + + $title = $this->getResponse()->codeMap($errorcode); + $title = $title ? $errorcode.' '.$title : 'unknowen error'; + $__vars['title'] = ucwords($title); + $__vars['message'] = $message; + + if (Wind::$isDebug & 1) { + $__vars['debug']['file'] = $file; + $__vars['debug']['line'] = $line; + $__vars['debug']['trace'] = $trace; + $__vars['debug']['fileLines'] = $fileLines; + } + $this->render($__vars, $errorcode, $errDir, $errPage); + } + + /** + * 错误视图渲染 + * + * @param array $__vars + */ + private function render($__vars, $errorcode, $errDir, $errPage) + { + @extract($__vars, EXTR_REFS); + unset($__vars); + ob_start(); + $this->getResponse()->setStatus($errorcode); + $this->getResponse()->sendHeaders(); + require $errDir.'/'.$errPage.'.htm'; + exit(); + } +} diff --git a/wind/web/WindWebFrontController.php b/wind/web/WindWebFrontController.php index 2f303629..22ecd8b7 100644 --- a/wind/web/WindWebFrontController.php +++ b/wind/web/WindWebFrontController.php @@ -1,7 +1,6 @@ 2011-10-12 @@ -10,140 +9,87 @@ * @version $Id: WindFrontController.php 2966 2011-10-14 06:41:59Z yishuo $ * @package wind */ -class WindWebFrontController extends AbstractWindFrontController { +class WindWebFrontController extends AbstractWindFrontController +{ + /* (non-PHPdoc) + * @see AbstractWindFrontController::run() + */ + public function run() + { + $_compress = $this->_config['web-apps'][$this->_appName]['compress']; + if (!$_compress || !ob_start('ob_gzhandler')) { + ob_start(); + } + parent::run(); + ob_end_flush(); + } - /** - * 创建并执行当前应用 - * - * @deprecated - * @param string $appName - * @param string|array $config - * @return void - */ - public function multiRun() { - $this->initConfig(); - - /* @var $router WindRouter */ - $router = $this->getFactory()->getInstance('router'); - $this->_appName && $router->setApp($this->_appName); - $router->route($this->getRequest()); - $this->_appName = $router->getApp(); - $this->_run(); - } - - /* - * (non-PHPdoc) @see AbstractWindFrontController::createApplication() - */ - protected function _createApplication() { - $application = new WindWebApplication($this->getRequest(), $this->getFactory()); - $application->setDelayAttributes( - array('dispatcher' => array('ref' => 'dispatcher'), 'handlerAdapter' => array('ref' => 'router'))); - return $application; - } - - /* (non-PHPdoc) - * @see AbstractWindFrontController::showErrorMessage() - */ - protected function showErrorMessage($message, $file, $line, $trace, $errorcode) { - parent::showErrorMessage($message, $file, $line, $trace, $errorcode); - if (!empty($this->_config[$this->_appName]['errorDir'])) { - $errDir = $this->_config[$this->_appName]['errorDir']; - } else - $errDir = 'WIND:web.view'; - $errDir = Wind::getRealPath($errDir, false); - if (is_file($errDir . '/' . $errorcode . '.htm')) $this->_errPage = $errorcode; - ob_start(); - require $errDir . '/' . $this->_errPage . '.htm'; - exit(ob_get_clean()); - } - - /* (non-PHPdoc) - * @see AbstractWindFrontController::_components() - */ - protected function _components() { - return array( - 'router' => array('path' => 'WIND:router.WindRouter', 'scope' => 'application'), - 'windView' => array( - 'path' => 'WIND:viewer.WindView', - 'scope' => 'application', - 'config' => array( - 'template-dir' => 'template', - 'template-ext' => 'htm', - 'is-compile' => '1', - 'compile-dir' => 'compile.template', - 'compile-ext' => 'tpl', - 'layout' => '', - 'theme' => '', - 'htmlspecialchars' => true), - 'properties' => array( - 'viewResolver' => array('path' => 'WIND:viewer.resolver.WindViewerResolver'), - 'windLayout' => array('path' => 'WIND:viewer.WindLayout'))), - 'template' => array('path' => 'WIND:viewer.compiler.WindViewTemplate', 'scope' => 'prototype'), - 'db' => array('path' => 'WIND:db.WindConnection', 'scope' => 'application'), - 'configParser' => array('path' => 'WIND:parser.WindConfigParser', 'scope' => 'singleton'), - 'dispatcher' => array('path' => 'WIND:web.WindDispatcher', 'scope' => 'application'), - 'forward' => array( - 'path' => 'WIND:web.WindForward', - 'scope' => 'prototype', - 'properties' => array('windView' => array('ref' => 'windView'))), - 'errorMessage' => array('path' => 'WIND:base.WindErrorMessage', 'scope' => 'prototype'), - 'windLogger' => array( - 'path' => 'WIND:log.WindLogger', - 'scope' => 'singleton', - 'destroy' => 'flush', - 'constructor-args' => array('0' => array('value' => 'DATA:log'), '1' => array('value' => '2'))), - 'i18n' => array( - 'path' => 'WIND:i18n.WindLangResource', - 'scope' => 'singleton', - 'config' => array('path' => 'i18n'))); - } - - /* (non-PHPdoc) - * @see AbstractWindFrontController::_loadBaseLib() - */ - protected function _loadBaseLib() { - Wind::$_imports += array( - 'WIND:i18n.WindLangResource' => 'WindLangResource', - 'WIND:log.WindLogger' => 'WindLogger', - 'WIND:core.web.WindErrorMessage' => 'WindErrorMessage', - 'WIND:web.WindForward' => 'WindForward', - 'WIND:web.WindDispatcher' => 'WindDispatcher', - 'WIND:parser.WindConfigParser' => 'WindConfigParser', - 'WIND:db.WindConnection' => 'WindConnection', - 'WIND:viewer.compiler.WindViewTemplate' => 'WindViewTemplate', - 'WIND:viewer.WindView' => 'WindView', - 'WIND:router.WindRouter' => 'WindRouter', - 'WIND:web.WindController' => 'WindController', - 'WIND:web.WindDispatcher' => 'WindDispatcher', - 'WIND:web.WindErrorHandler' => 'WindErrorHandler', - 'WIND:web.WindForward' => 'WindForward', - 'WIND:web.WindHttpRequest' => 'WindHttpRequest', - 'WIND:web.WindHttpResponse' => 'WindHttpResponse', - 'WIND:web.WindSimpleController' => 'WindSimpleController', - 'WIND:web.WindUrlHelper' => 'WindUrlHelper', - 'WIND:web.WindWebApplication' => 'WindWebApplication'); - - Wind::$_classes += array( - 'WindLangResource' => 'i18n/WindLangResource', - 'WindLogger' => 'log/WindLogger', - 'WindErrorMessage' => 'core/web/WindErrorMessage', - 'WindForward' => 'web/WindForward', - 'WindDispatcher' => 'web/WindDispatcher', - 'WindConfigParser' => 'parser/WindConfigParser', - 'WindConnection' => 'db/WindConnection', - 'WindViewTemplate' => 'viewer/compiler/WindViewTemplate', - 'WindView' => 'viewer/WindView', - 'WindRouter' => 'router/WindRouter', - 'WindController' => 'web/WindController', - 'WindDispatcher' => 'web/WindDispatcher', - 'WindErrorHandler' => 'web/WindErrorHandler', - 'WindForward' => 'web/WindForward', - 'WindHttpRequest' => 'web/WindHttpRequest', - 'WindHttpResponse' => 'web/WindHttpResponse', - 'WindSimpleController' => 'web/WindSimpleController', - 'WindUrlHelper' => 'web/WindUrlHelper', - 'WindWebApplication' => 'web/WindWebApplication'); - } -} + /* + * (non-PHPdoc) @see AbstractWindFrontController::createApplication() + */ + protected function createApplication($config, $factory) + { + $request = $factory->getInstance('request'); + $response = $factory->getInstance('response'); + $application = new WindWebApplication($request, $response, $factory); + + $response->setHeader('Content-type', 'text/html;charset='.$config['charset']); + $response->setCharset($config['charset']); + $application->setConfig($config); -?> \ No newline at end of file + return $application; + } + + /* + * (non-PHPdoc) @see AbstractWindFrontController::_components() + */ + protected function _components() + { + return array( + 'request' => array('path' => 'WIND:web.WindHttpRequest', 'scope' => 'application'), + 'response' => array('path' => 'WIND:web.WindHttpResponse', 'scope' => 'application'), + 'router' => array('path' => 'WIND:router.WindRouter', 'scope' => 'application'), + 'windView' => array( + 'path' => 'WIND:viewer.WindView', + 'scope' => 'application', + 'config' => array( + 'template-dir' => 'template', + 'template-ext' => 'htm', + 'is-compile' => '1', + 'compile-dir' => 'compile.template', + 'compile-ext' => 'tpl', + 'layout' => '', + 'theme' => '', + 'htmlspecialchars' => true, ), + 'properties' => array( + 'viewResolver' => array('path' => 'WIND:viewer.resolver.WindViewerResolver'), + 'windLayout' => array('path' => 'WIND:viewer.WindLayout'), ), ), + 'template' => array('path' => 'WIND:viewer.compiler.WindViewTemplate', 'scope' => 'prototype'), + 'db' => array('path' => 'WIND:db.WindConnection', 'scope' => 'application'), + 'sqlStatement' => array('path' => 'WIND:db.WindSqlStatement', 'scope' => 'prototype'), + 'configParser' => array('path' => 'WIND:parser.WindConfigParser', 'scope' => 'singleton'), + 'dispatcher' => array('path' => 'WIND:web.WindDispatcher', 'scope' => 'application'), + 'forward' => array( + 'path' => 'WIND:web.WindForward', + 'scope' => 'prototype', + 'properties' => array('windView' => array('ref' => 'windView')), ), + 'errorMessage' => array('path' => 'WIND:base.WindErrorMessage', 'scope' => 'prototype'), + 'error' => array('path' => 'WIND:web.WindWebError', 'scope' => 'application'), + 'windLogger' => array( + 'path' => 'WIND:log.WindLogger', + 'scope' => 'singleton', + 'destroy' => 'flush', + 'constructor-args' => array('0' => array('value' => 'data.log')), ), + 'i18n' => array( + 'path' => 'WIND:i18n.WindLangResource', + 'scope' => 'singleton', + 'config' => array('path' => 'i18n'), ), ); + } + + /* + * (non-PHPdoc) @see AbstractWindFrontController::_loadBaseLib() + */ + protected function _loadBaseLib() + { + } +} diff --git a/wind/web/filter/WindFormFilter.php b/wind/web/filter/WindFormFilter.php index 8fcfc379..3cfa2095 100644 --- a/wind/web/filter/WindFormFilter.php +++ b/wind/web/filter/WindFormFilter.php @@ -1,7 +1,7 @@ 注意: *
      @@ -11,15 +11,15 @@ *
    • 该表单在验证完成之后,会将该表单实例以[表单类名]为名字保存在Request中,在获取的时候只要通过request->getInput('表单类名')获取即可;
    • *
    * - * + * * 该formFilter接受一个配置form,该配置项指向需要过滤的表单类文件. * 例如: * * 'filters' => array( - * 'class' => 'WIND:filter.WindFilterChain', + * 'class' => 'WIND:filter.WindFilterChain', * 'filter1' => array( * 'class' => 'WIND:web.filter.WindFormFilter', //将filter指定为该formFilter - * 'pattern' => '*', + * 'pattern' => '*', * 'form' => 'MY:form.MyForm', * ) * ) @@ -27,60 +27,72 @@ * 在action中获取的时候使用: * * $this->getInput('myForm');//获得配置的过滤表单 - * + * * * * @author xiaoxia.xu * @copyright ©2003-2103 phpwind.com * @license http://www.windframework.com - * @version $Id$ + * @version $Id: WindFormFilter.php 3533 2012-05-08 08:24:20Z yishuo $ * @package web * @subpackage filter */ -class WindFormFilter extends WindActionFilter { - - /** - * 验证的表单类 - * - * @var string - */ - protected $form = ''; +class WindFormFilter extends WindActionFilter +{ + /** + * 验证的表单类 + * + * @var string + */ + protected $form = ''; - /* (non-PHPdoc) - * @see WindHandlerInterceptor::preHandle() - */ - public function preHandle() { - if (!$this->form) return null; - $className = Wind::import($this->form); - $form = WindFactory::createInstance($className); - $methods = get_class_methods($form); - foreach ($methods as $method) { - if ((0 !== strpos($method, 'set')) || ('' == ($_tmp = substr($method, 3)))) continue; - if (null === ($input = $this->getRequest()->getRequest(WindUtility::lcfirst($_tmp), null))) continue; - call_user_func_array(array($form, $method), array($input)); - } - $form->validate(); - $this->getRequest()->setAttribute($form, WindUtility::lcfirst($className)); - $this->sendError($form->getErrorAction(), $form->getErrors()); - } + /* (non-PHPdoc) + * @see WindHandlerInterceptor::preHandle() + */ + public function preHandle() + { + if (!$this->form) { + return null; + } + $className = Wind::import($this->form); + $form = WindFactory::createInstance($className); + $methods = get_class_methods($form); + foreach ($methods as $method) { + if ((0 !== strpos($method, 'set')) || ('' == ($_tmp = substr($method, 3)))) { + continue; + } + if (null === ($input = $this->getRequest()->getRequest(WindUtility::lcfirst($_tmp), null))) { + continue; + } + call_user_func_array(array($form, $method), array($input)); + } + $form->validate(); + $this->getRequest()->setAttribute($form, WindUtility::lcfirst($className)); + $this->sendError($form->getErrorAction(), $form->getErrors()); + } - /** - * 发送错误信息 - * - * @param string $errorAction 需要处理错误的action配置模式为module/controller/action - * @param array $errors 验证中产生的错误信息 - * @return void - */ - private function sendError($errorAction, $errors) { - if (empty($errors)) return; - $this->errorMessage->setErrorAction($errorAction); - foreach ($errors as $key => $value) - $this->errorMessage->addError($value, $key); - $this->errorMessage->sendError(); - } + /** + * 发送错误信息 + * + * @param string $errorAction 需要处理错误的action配置模式为module/controller/action + * @param array $errors 验证中产生的错误信息 + */ + private function sendError($errorAction, $errors) + { + if (empty($errors)) { + return; + } + $this->errorMessage->setErrorAction($errorAction); + foreach ($errors as $key => $value) { + $this->errorMessage->addError($value, $key); + } + $this->errorMessage->sendError(); + } - /* (non-PHPdoc) - * @see WindHandlerInterceptor::postHandle() - */ - public function postHandle() {} -} \ No newline at end of file + /* (non-PHPdoc) + * @see WindHandlerInterceptor::postHandle() + */ + public function postHandle() + { + } +} diff --git a/wind/web/view/close.htm b/wind/web/view/close.htm index 1e799194..265ccabf 100644 --- a/wind/web/view/close.htm +++ b/wind/web/view/close.htm @@ -1,7 +1,7 @@ -<?php echo $message; ?> +<?php echo WindSecurity::escapeHTML($message); ?> -
    -
    -

    {$errorHeader}:

    -
      - -
    • {$key}. {$error}
    • - -
    -
    getConfig('siteInfo', '', "http://www.windframework.com/") . ")" ; ?>
    -
    -
    +
  • {$key}. {$error}
  • + + +
    + The server encountered an internal error and failed to process your + request. Please try again later. If this error is temporary, + reloading the page might resolve the problem.
    If you are + able to contact the administrator report this error + message.(http://www.windframework.com/) +
    + + \ No newline at end of file