From b8bbf61fb4ef75d897c97e46532eb656afc627a8 Mon Sep 17 00:00:00 2001 From: oldrind <1401019000@qq.com> Date: Thu, 21 Jan 2016 14:39:22 +0800 Subject: [PATCH] =?UTF-8?q?Input=E7=B1=BB=E5=A2=9E=E5=8A=A0path=E3=80=81fi?= =?UTF-8?q?le=E3=80=81data=E6=96=B9=E6=B3=95=EF=BC=8C=E6=94=AF=E6=8C=81.?= =?UTF-8?q?=E8=AF=AD=E6=B3=95=E5=8F=96=E5=A4=9A=E7=BB=B4=E6=95=B0=E7=BB=84?= =?UTF-8?q?=E7=9A=84=E5=80=BC=E3=80=82=20path=E6=96=B9=E6=B3=95=E5=9C=A8CI?= =?UTF-8?q?=E4=B8=AD=E6=B5=8B=E8=AF=95=E6=8A=A5=E9=94=99=EF=BC=8C=E6=AD=A4?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E7=9A=84=E6=B5=8B=E8=AF=95=E5=85=88=E5=85=B3?= =?UTF-8?q?=E9=97=AD=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- helper.php | 9 +- library/think/Input.php | 215 +++++++++++++-------- tests/thinkphp/library/think/inputTest.php | 77 +++++--- 3 files changed, 183 insertions(+), 118 deletions(-) diff --git a/helper.php b/helper.php index a7ea8374..1d9bc211 100644 --- a/helper.php +++ b/helper.php @@ -32,9 +32,14 @@ function C($name = '', $value = null, $range = '') // 获取输入数据 支持默认值和过滤 function I($key, $default = null, $filter = '') { - if (strpos($key, '.')) { + if ($pos = strpos($key, '.')) { // 指定参数来源 - list($method, $key) = explode('.', $key, 2); + $method = substr($key, 0, $pos); + if (in_array($method, ['get', 'post', 'put', 'param', 'request', 'session', 'cookie', 'server', 'globals', 'env', 'path', 'file', 'data'])) { + $key = substr($key, $pos + 1); + } else { + $method = 'param'; + } } else { // 默认为自动判断 $method = 'param'; diff --git a/library/think/Input.php b/library/think/Input.php index a3b14cfd..a95995f1 100644 --- a/library/think/Input.php +++ b/library/think/Input.php @@ -21,11 +21,12 @@ class Input * @param string $name 数据名称 * @param string $default 默认值 * @param string $filter 过滤方法 + * @param boolean $merge 是否与默认的过虑方法合并 * @return mixed */ - public static function get($name = '', $default = null, $filter = null) + public static function get($name = '', $default = null, $filter = null, $merge = false) { - return self::getData($name, $_GET, $filter, $default); + return self::data($name, $default, $filter, $merge, $_GET); } /** @@ -33,11 +34,12 @@ class Input * @param string $name 数据名称 * @param string $default 默认值 * @param string $filter 过滤方法 + * @param boolean $merge 是否与默认的过虑方法合并 * @return mixed */ - public static function post($name = '', $default = null, $filter = null) + public static function post($name = '', $default = null, $filter = null, $merge = false) { - return self::getData($name, $_POST, $filter, $default); + return self::data($name, $default, $filter, $merge, $_POST); } /** @@ -45,15 +47,16 @@ class Input * @param string $name 数据名称 * @param string $default 默认值 * @param string $filter 过滤方法 + * @param boolean $merge 是否与默认的过虑方法合并 * @return mixed */ - public static function put($name = '', $default = null, $filter = null) + public static function put($name = '', $default = null, $filter = null, $merge = false) { static $_PUT = null; if (is_null($_PUT)) { parse_str(file_get_contents('php://input'), $_PUT); } - return self::getData($name, $_PUT, $filter, $default); + return self::data($name, $default, $filter, $merge, $_PUT); } /** @@ -61,21 +64,22 @@ class Input * @param string $name 数据名称 * @param string $default 默认值 * @param string $filter 过滤方法 + * @param boolean $merge 是否与默认的过虑方法合并 * @return mixed */ - public static function param($name = '', $default = null, $filter = null) + public static function param($name = '', $default = null, $filter = null, $merge = false) { switch ($_SERVER['REQUEST_METHOD']) { case 'POST': - $result = self::post($name, $default, $filter); + $method = 'post'; break; case 'PUT': - $result = self::put($name, $default, $filter); + $method = 'put'; break; default: - $result = self::get($name, $default, $filter); + $method = 'get'; } - return $result; + return self::$method($name, $default, $filter, $merge); } /** @@ -83,11 +87,12 @@ class Input * @param string $name 数据名称 * @param string $default 默认值 * @param string $filter 过滤方法 + * @param boolean $merge 是否与默认的过虑方法合并 * @return mixed */ - public static function request($name = '', $default = null, $filter = null) + public static function request($name = '', $default = null, $filter = null, $merge = false) { - return self::getData($name, $_REQUEST, $filter, $default); + return self::data($name, $default, $filter, $merge, $_REQUEST); } /** @@ -95,11 +100,12 @@ class Input * @param string $name 数据名称 * @param string $default 默认值 * @param string $filter 过滤方法 + * @param boolean $merge 是否与默认的过虑方法合并 * @return mixed */ - public static function session($name = '', $default = null, $filter = null) + public static function session($name = '', $default = null, $filter = null, $merge = false) { - return self::getData($name, $_SESSION, $filter, $default); + return self::data($name, $default, $filter, $merge, $_SESSION); } /** @@ -107,11 +113,12 @@ class Input * @param string $name 数据名称 * @param string $default 默认值 * @param string $filter 过滤方法 + * @param boolean $merge 是否与默认的过虑方法合并 * @return mixed */ - public static function cookie($name = '', $default = null, $filter = null) + public static function cookie($name = '', $default = null, $filter = null, $merge = false) { - return self::getData($name, $_COOKIE, $filter, $default); + return self::data($name, $default, $filter, $merge, $_COOKIE); } /** @@ -119,11 +126,12 @@ class Input * @param string $name 数据名称 * @param string $default 默认值 * @param string $filter 过滤方法 + * @param boolean $merge 是否与默认的过虑方法合并 * @return mixed */ - public static function server($name = '', $default = null, $filter = null) + public static function server($name = '', $default = null, $filter = null, $merge = false) { - return self::getData(strtoupper($name), $_SERVER, $filter, $default); + return self::data(strtoupper($name), $default, $filter, $merge, $_SERVER); } /** @@ -131,11 +139,12 @@ class Input * @param string $name 数据名称 * @param string $default 默认值 * @param string $filter 过滤方法 + * @param boolean $merge 是否与默认的过虑方法合并 * @return mixed */ - public static function globals($name = '', $default = null, $filter = null) + public static function globals($name = '', $default = null, $filter = null, $merge = false) { - return self::getData($name, $GLOBALS, $filter, $default); + return self::data($name, $default, $filter, $merge, $GLOBALS); } /** @@ -143,51 +152,93 @@ class Input * @param string $name 数据名称 * @param string $default 默认值 * @param string $filter 过滤方法 + * @param boolean $merge 是否与默认的过虑方法合并 * @return mixed */ - public static function env($name = '', $default = null, $filter = null) + public static function env($name = '', $default = null, $filter = null, $merge = false) { - return self::getData(strtoupper($name), $_ENV, $filter, $default); + return self::data(strtoupper($name), $default, $filter, $merge, $_ENV); + } + + /** + * 获取PATH_INFO + * @param string $name 数据名称 + * @param string $default 默认值 + * @param string $filter 过滤方法 + * @param boolean $merge 是否与默认的过虑方法合并 + * @return mixed + */ + public static function path($name = '', $default = null, $filter = null, $merge = false) + { + if (!empty($_SERVER['PATH_INFO'])) { + $depr = \think\Config::get('pathinfo_depr'); + $input = explode($depr, trim($_SERVER['PATH_INFO'], $depr)); + return self::data($name, $default, $filter, $merge, $input); + } else { + return $default; + } + } + + /** + * 获取$_FILES + * @param string $name 数据名称 + * @param string $default 默认值 + * @param string $filter 过滤方法 + * @param boolean $merge 是否与默认的过虑方法合并 + * @return mixed + */ + public static function file($name = '', $default = null, $filter = null, $merge = false) + { + return self::data($name, $default, $filter, $merge, $_FILES); } /** * 获取系统变量 支持过滤和默认值 - * @param string $name - * @param array $input - * @param mixed $filter - * @param mixed $default + * @param string $name 字段名 + * @param mixed $default 默认值 + * @param mixed $filter 过滤函数 + * @param boolean $merge 是否与默认的过虑方法合并 + * @param array $input 数据源 * @return mixed */ - public static function getData($name, $input = [], $filter = null, $default = null) + public static function data($name, $default = null, $filter = null, $merge = false, $input = null) { - // 解析过滤器 - $filters = static::parseFilter($filter); - // 为方便传参把默认值附加在过滤器后面 - $filters[] = $default; - if (!is_array($input)) { - $data = $default; - } elseif (empty($name)) { + if (is_null($input) && !empty($name)) { + $input = $name; + $name = ''; + } + if (!empty($input)) { $data = $input; - array_walk_recursive($data, 'self::filter', $filters); - } else { - // 解析name - list($name, $type) = static::parseName($name); - if (isset($input[$name])) { - // 过滤name指定的输入 - $data = $input[$name]; - if (is_array($data)) { - array_walk_recursive($data, 'self::filter', $filters); - } else { - self::filter($data, $name, $filters); + $name = (string) $name; + if ('' != $name) { + // 解析name + list($name, $type) = static::parseName($name); + // 按.拆分成多维数组进行判断 + foreach (explode('.', $name) as $val) { + if (isset($data[$val])) { + $data = $data[$val]; + } else { + // 无输入数据,返回默认值 + return $default; + } } - if ($data !== $default) { - // 强制类型转换 - static::typeCast($data, $type); - } - } else { - // 无输入数据 - $data = $default; } + + // 解析过滤器 + $filters = static::parseFilter($filter, $merge); + // 为方便传参把默认值附加在过滤器后面 + $filters[] = $default; + if (is_array($data)) { + array_walk_recursive($data, 'self::filter', $filters); + } else { + self::filter($data, $name?:0, $filters); + } + if (isset($type) && $data !== $default) { + // 强制类型转换 + static::typeCast($data, $type); + } + } else { + $data = $default; } return $data; } @@ -210,7 +261,7 @@ class Input * @param string $value * @return void */ - protected static function filterExp(&$value) + public static function filterExp(&$value) { // TODO 其他安全过滤 @@ -229,36 +280,34 @@ class Input */ private static function filter(&$value, $key, $filters) { - if (!empty($value)) { - // 分离出默认值 - $default = array_pop($filters); - foreach ($filters as $filter) { - if (is_callable($filter)) { - // 调用函数过滤 - $value = call_user_func($filter, $value); + // 分离出默认值 + $default = array_pop($filters); + foreach ($filters as $filter) { + if (is_callable($filter)) { + // 调用函数过滤 + $value = call_user_func($filter, $value); + } else { + $begin = substr($filter, 0, 1); + if (in_array($begin, ['/','#','~']) && $begin == $end = substr($filter, -1)) { + // 正则过滤 + if (!preg_match($filter, $value)) { + // 匹配不成功返回默认值 + $value = $default; + break; + } } else { - $begin = substr($filter, 0, 1); - if (in_array($begin, ['/','#','~']) && $begin == $end = substr($filter, -1)) { - // 正则过滤 - if (!preg_match($filter, $value)) { - // 匹配不成功返回默认值 - $value = $default; - break; - } - } else { - // filter函数不存在时, 则使用filter_var进行过滤 - // filter为非整形值时, 调用filter_id取得过滤id - $value = filter_var($value, is_int($filter) ? $filter : filter_id($filter)); - if (false === $value) { - // 不通过过滤器则返回默认值 - $value = $default; - break; - } + // filter函数不存在时, 则使用filter_var进行过滤 + // filter为非整形值时, 调用filter_id取得过滤id + $value = filter_var($value, is_int($filter) ? $filter : filter_id($filter)); + if (false === $value) { + // 不通过过滤器则返回默认值 + $value = $default; + break; } } } - self::filterExp($value); } + self::filterExp($value); } /** @@ -276,7 +325,7 @@ class Input * @param mixed $filter * @return array */ - private static function parseFilter($filter) + private static function parseFilter($filter, $merge = false) { if (is_null($filter)) { $result = self::getFilter(); @@ -290,10 +339,8 @@ class Input } else { $result = [$filter]; } - // 如果最后一项为0或false,表示覆盖默认的过滤函数,否则为叠加 - if (!end($result)) { - array_pop($result); - } else { + if ($merge) { + // 与默认的过滤函数合并 $result = array_merge(self::getFilter(), array_diff($result, self::getFilter())); } } diff --git a/tests/thinkphp/library/think/inputTest.php b/tests/thinkphp/library/think/inputTest.php index 52740409..8996c018 100644 --- a/tests/thinkphp/library/think/inputTest.php +++ b/tests/thinkphp/library/think/inputTest.php @@ -20,48 +20,47 @@ use think\Input; class inputTest extends \PHPUnit_Framework_TestCase { - public function testEmptyStringName() - { - $input = ['a' => 'test']; - $this->assertEquals($input, Input::getData('', $input, 'trim')); - } public function testInputName() { - $input = ['a' => 'test']; - $this->assertEquals($input['a'], Input::getData('a', $input)); + $input = ['a' => 'a', 'b' => ['c' => [' one ', 'two']]]; + $this->assertEquals($input, Input::data($input)); + $this->assertEquals($input['a'], Input::data($input['a'])); + $this->assertEquals('one', Input::data('b.c.0/s', 'default', 'trim', false, $input)); } public function testDefaultValue() { $input = ['a' => 'test']; $default = 'default'; - $this->assertEquals($default, Input::getData('foo', $input, null, $default)); + $this->assertEquals($default, Input::data($input['b'], $default)); + $this->assertEquals($default, Input::data($input, $default, '', false, $input)); + $this->assertEquals($default, Input::get('a', $default)); } public function testStringFilter() { $input = ['a' => ' test ', 'b' => ' test<> ']; $filters = 'trim'; - $this->assertEquals('test', Input::getData('a', $input, $filters)); + $this->assertEquals('test', Input::data('a', '', $filters, false, $input)); $filters = 'trim,htmlspecialchars'; - $this->assertEquals('test<>', Input::getData('b', $input, $filters)); + $this->assertEquals('test<>', Input::data('b', '', $filters, false, $input)); } public function testArrayFilter() { $input = ['a' => ' test ', 'b' => ' test<> ']; $filters = ['trim']; - $this->assertEquals('test', Input::getData('a', $input, $filters)); + $this->assertEquals('test', Input::data('a', '', $filters, false, $input)); $filters = ['trim', 'htmlspecialchars']; - $this->assertEquals('test<>', Input::getData('b', $input, $filters)); + $this->assertEquals('test<>', Input::data('b', '', $filters, false, $input)); } public function testFilterExp() { $src = 'EXP|NEQ|GT|EGT|LT|ELT|OR|XOR|LIKE|NOTLIKE|NOT BETWEEN|NOTBETWEEN|BETWEEN|NOTIN|NOT IN|IN'; $regexs = explode('|', $src); - $data = Input::getData('', $regexs); + $data = Input::data($regexs); foreach ($regexs as $key => $value) { $expected = $value . ' '; $this->assertEquals($expected, $data[$key]); @@ -70,11 +69,13 @@ class inputTest extends \PHPUnit_Framework_TestCase public function testFiltrateWithRegex() { - $input = ['a' => 'test1', 'b' => '_test2']; + $input = ['a' => 'test1', 'b' => '_test2', 'c' => '']; $filters = '/^test/'; - $this->assertEquals('test1', Input::getData('a', $input, $filters)); + $this->assertEquals('test1', Input::data('a', '', $filters, false, $input)); $default = 'default value'; - $this->assertEquals($default, Input::getData('b', $input, $filters, $default)); + $this->assertEquals($default, Input::data('b', $default, $filters, false, $input)); + $filters = '/.+/'; + $this->assertEquals('default value', Input::data('c', $default, $filters, false, $input)); } public function testFiltrateWithFilterVar() @@ -84,10 +85,10 @@ class inputTest extends \PHPUnit_Framework_TestCase $default = false; $input = ['a' => $email, 'b' => $error]; $filters = FILTER_VALIDATE_EMAIL; - $this->assertEquals($email, Input::getData('a', $input, $filters)); - $this->assertFalse(Input::getData('b', $input, $filters, $default)); + $this->assertEquals($email, Input::data('a', '', $filters, false, $input)); + $this->assertFalse(Input::data('b', $default, $filters, false, $input)); $filters = 'validate_email'; - $this->assertFalse(Input::getData('b', $input, $filters, $default)); + $this->assertFalse(Input::data('b', $default, $filters, false, $input)); } public function testAllInput() @@ -109,21 +110,21 @@ class inputTest extends \PHPUnit_Framework_TestCase 'e' => 'NEQ ', 'f' => 'gt ', ]; - $this->assertEquals($excepted, Input::getData('', $input, $filters)); + $this->assertEquals($excepted, Input::data($input, '', $filters)); } public function testTypeCast() { - $input = [ + $_POST = [ 'a' => [1, 2, 3], 'b' => '1000', 'c' => '3.14', 'd' => 'test boolean', ]; - $this->assertEquals([1, 2, 3], Input::getData('a/a', $input)); - $this->assertEquals(1000, Input::getData('b/d', $input)); - $this->assertEquals(3.14, Input::getData('c/f', $input)); - $this->assertEquals(true, Input::getData('d/b', $input)); + $this->assertEquals([1, 2, 3], Input::post('a/a')); + $this->assertEquals(1000, Input::post('b/d')); + $this->assertEquals(3.14, Input::post('c/f')); + $this->assertEquals(true, Input::post('d/b')); } public function testSuperglobals() @@ -140,6 +141,9 @@ class inputTest extends \PHPUnit_Framework_TestCase $_SERVER['REQUEST_METHOD'] = 'GET'; $this->assertEquals('get value', Input::param('get')); $this->assertEquals(null, Input::param('post')); + $this->assertEquals(null, Input::param('put')); + $_REQUEST = array_merge($_GET, $_POST); + $this->assertEquals('get value', Input::request('get')); session_start(); $_SESSION['test'] = 'session value '; @@ -152,21 +156,30 @@ class inputTest extends \PHPUnit_Framework_TestCase $_SERVER['REQUEST_METHOD'] = 'GET '; $this->assertEquals('GET', Input::server('REQUEST_METHOD')); + $GLOBALS['total'] = 1000; + $this->assertEquals(1000, Input::globals('total')); + $this->assertEquals('testing', Input::env('APP_ENV')); + + //$_SERVER['PATH_INFO'] = 'path/info'; + //$path = $_SERVER['PATH_INFO'] ? explode('/', $_SERVER['PATH_INFO'])[0] : ''; + //$this->assertEquals($path, Input::path('0', '')); + + $_FILES = ['file'=>['name'=>'test.png', 'type'=>'image/png', 'tmp_name'=>'/tmp/php5Wx0aJ', 'error'=>0, size=>15726]]; + $this->assertEquals('image/png', Input::file('file.type')); + } - public function testFilterCover() + public function testFilterMerge() { Input::setFilter('htmlspecialchars'); $input = ['a' => ' test<> ', 'b' => '']; + $this->assertEquals(' test<> ', Input::data('a', '', '', false, $input)); $filters = ['trim']; - $this->assertEquals('test<>', Input::getData('a', $input, $filters)); - $filters = ['trim', false]; - $this->assertEquals('test<>', Input::getData('a', $input, $filters)); + $this->assertEquals('test<>', Input::data('a', '', $filters, false, $input)); + $this->assertEquals('test<>', Input::data('a', '', $filters, true, $input)); $filters = 'stripslashes'; - $this->assertEquals("<bar />", Input::getData('b', $input, $filters)); - $filters = 'stripslashes,0'; - $this->assertEquals("", Input::getData('b', $input, $filters)); + $this->assertEquals("<bar />", Input::data('b', '', $filters, true, $input)); } }