From 3da7c4b446ece4dc0aa4fd7aa24290aa6ad812cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Sessing=C3=B8?= Date: Mon, 11 Apr 2016 22:37:15 +0200 Subject: [PATCH 1/4] - Fixed getIp in HttpRequest class not picking up local-ip. - Made setdefaultNamespace method chainable. - Simplified SimpleRouter class. --- src/Pecee/Http/Request.php | 2 +- src/Pecee/SimpleRouter/RouterBase.php | 2 + src/Pecee/SimpleRouter/SimpleRouter.php | 78 +++++++++---------------- 3 files changed, 32 insertions(+), 50 deletions(-) diff --git a/src/Pecee/Http/Request.php b/src/Pecee/Http/Request.php index 69a3021..31c101e 100644 --- a/src/Pecee/Http/Request.php +++ b/src/Pecee/Http/Request.php @@ -93,7 +93,7 @@ class Request { * @return string */ public function getIp() { - return isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR']; + return ((isset($_SERVER['HTTP_X_FORWARDED_FOR']) && strlen($_SERVER['HTTP_X_FORWARDED_FOR'])) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR']); } /** diff --git a/src/Pecee/SimpleRouter/RouterBase.php b/src/Pecee/SimpleRouter/RouterBase.php index b7b775b..eb1264a 100644 --- a/src/Pecee/SimpleRouter/RouterBase.php +++ b/src/Pecee/SimpleRouter/RouterBase.php @@ -213,9 +213,11 @@ class RouterBase { /** * @param string $defaultNamespace + * @return static */ public function setDefaultNamespace($defaultNamespace) { $this->defaultNamespace = $defaultNamespace; + return $this; } /** diff --git a/src/Pecee/SimpleRouter/SimpleRouter.php b/src/Pecee/SimpleRouter/SimpleRouter.php index f8a7653..aca2cfb 100644 --- a/src/Pecee/SimpleRouter/SimpleRouter.php +++ b/src/Pecee/SimpleRouter/SimpleRouter.php @@ -19,9 +19,7 @@ class SimpleRouter { * @throws \Pecee\Exception\RouterException */ public static function start($defaultNamespace = null) { - $router = RouterBase::getInstance(); - $router->setDefaultNamespace($defaultNamespace); - $router->routeRequest(); + RouterBase::getInstance()->setDefaultNamespace($defaultNamespace)->routeRequest(); } /** @@ -37,47 +35,19 @@ class SimpleRouter { } public static function get($url, $callback, array $settings = null) { - $route = new RouterRoute($url, $callback); - $route->addSettings($settings); - $route->setRequestMethods(array(RouterRoute::REQUEST_TYPE_GET)); - - $router = RouterBase::getInstance(); - $router->addRoute($route); - - return $route; + return self::match(['get'], $url, $callback, $settings); } public static function post($url, $callback, array $settings = null) { - $route = new RouterRoute($url, $callback); - $route->addSettings($settings); - $route->setRequestMethods(array(RouterRoute::REQUEST_TYPE_POST)); - - $router = RouterBase::getInstance(); - $router->addRoute($route); - - return $route; + return self::match(['post'], $url, $callback, $settings); } public static function put($url, $callback, array $settings = null) { - $route = new RouterRoute($url, $callback); - $route->addSettings($settings); - $route->setRequestMethods(array(RouterRoute::REQUEST_TYPE_PUT, RouterRoute::REQUEST_TYPE_PATCH)); - - $router = RouterBase::getInstance(); - $router->addRoute($route); - - return $route; + return self::match(['put'], $url, $callback, $settings); } public static function delete($url, $callback, array $settings = null) { - $route = new RouterRoute($url, $callback); - $route->addSettings($settings); - $route->setRequestMethods(array(RouterRoute::REQUEST_TYPE_DELETE)); - - $router = RouterBase::getInstance(); - $router->addRoute($route); - - return $route; + return self::match(['delete'], $url, $callback, $settings); } public static function group($settings = array(), $callback) { @@ -88,8 +58,7 @@ class SimpleRouter { $group->setSettings($settings); } - $router = RouterBase::getInstance(); - $router->addRoute($group); + RouterBase::getInstance()->addRoute($group); return $group; } @@ -109,37 +78,48 @@ class SimpleRouter { public static function match(array $requestMethods, $url, $callback, array $settings = null) { $route = new RouterRoute($url, $callback); $route->setRequestMethods($requestMethods); - $route->addSettings($settings); - $router = RouterBase::getInstance(); - $router->addRoute($route); + if($settings !== null) { + $route->addSettings($settings); + } + + RouterBase::getInstance()->addRoute($route); return $route; } public static function all($url, $callback, array $settings = null) { $route = new RouterRoute($url, $callback); - $route->addSettings($settings); - $router = RouterBase::getInstance(); - $router->addRoute($route); + + if($settings !== null) { + $route->addSettings($settings); + } + + RouterBase::getInstance()->addRoute($route); return $route; } public static function controller($url, $controller, array $settings = null) { $route = new RouterController($url, $controller); - $route->addSettings($settings); - $router = RouterBase::getInstance(); - $router->addRoute($route); + + if($settings !== null) { + $route->addSettings($settings); + } + + RouterBase::getInstance()->addRoute($route); return $route; } public static function resource($url, $controller, array $settings = null) { $route = new RouterResource($url, $controller); - $route->addSettings($settings); - $router = RouterBase::getInstance(); - $router->addRoute($route); + + if($settings !== null) { + $route->addSettings($settings); + } + + RouterBase::getInstance()->addRoute($route); return $route; } From 7a429cec1db86ccd3e96598bc62288c45dac50c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Sessing=C3=B8?= Date: Thu, 14 Apr 2016 23:52:08 +0200 Subject: [PATCH 2/4] [BUGFIX] Fixed get-parameters as array (param[id]=value) causing array-to-string notice. --- src/Pecee/SimpleRouter/RouterBase.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Pecee/SimpleRouter/RouterBase.php b/src/Pecee/SimpleRouter/RouterBase.php index eb1264a..231e6d4 100644 --- a/src/Pecee/SimpleRouter/RouterBase.php +++ b/src/Pecee/SimpleRouter/RouterBase.php @@ -300,8 +300,8 @@ class RouterBase { public function arrayToParams(array $getParams = null, $includeEmpty = true) { if (is_array($getParams) && count($getParams) > 0) { foreach ($getParams as $key => $val) { - if (!empty($val) || empty($val) && $includeEmpty) { - $getParams[$key] = $key . '=' . $val; + if (!empty($val) || $includeEmpty) { + $getParams[$key] = (is_array($val) ? $this->arrayToParams($val, $includeEmpty) : $key . '=' . $val); } } return join('&', $getParams); From 17adfb8aa48e97d9432c551c241775ca19621224 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Sessing=C3=B8?= Date: Fri, 15 Apr 2016 23:07:51 +0200 Subject: [PATCH 3/4] [FEATURE] Added Input classes from pecee-framework. - Updated documentation to reflect new changes. --- README.md | 70 +++++++++ src/Pecee/Http/Input/Input.php | 191 +++++++++++++++++++++++ src/Pecee/Http/Input/InputCollection.php | 67 ++++++++ src/Pecee/Http/Input/InputFile.php | 88 +++++++++++ src/Pecee/Http/Input/InputItem.php | 53 +++++++ src/Pecee/Http/Request.php | 3 + 6 files changed, 472 insertions(+) create mode 100644 src/Pecee/Http/Input/Input.php create mode 100644 src/Pecee/Http/Input/InputCollection.php create mode 100644 src/Pecee/Http/Input/InputFile.php create mode 100644 src/Pecee/Http/Input/InputItem.php diff --git a/README.md b/README.md index 628aef2..010838e 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ The goal of this project is to create a router that is 100% compatible with the - Optional parameters - Sub-domain routing - Custom boot managers to redirect urls to other routes +- Input manager; to manage `GET`, `POST` params. ## Initialising the router @@ -325,6 +326,75 @@ $route->setClass('Example\MyCustomClass'); $route->setMethod('hello'); ``` +## Using the Input class to manage parameters + +We've added the `Input` class to easy access parameters from your Controller-classes. + +**Return single parameter value (matches both GET, POST, FILE):** +```php +$value = Request::getInstance()->getInput()->get('name'); +``` + +**Return parameter object (matches both GET, POST, FILE):** +```php +$object = Request::getInstance()->getInput()->getObject('name'); +``` + +**Return specific GET parameter (where name is the name of your parameter):** +```php +$object = Request::getInstance()->getInput()->get->name; +$object = Request::getInstance()->getInput()->post->name; +$object = Request::getInstance()->getInput()->file->name; +``` + +**Return all parameters:** +```php +// Get all +$objects = Request::getInstance()->getInput()->all(); + +// Only match certain keys +$objects = Request::getInstance()->getInput()->all([ + 'company_name', + 'user_id' +]); +``` + +All object inherits from `InputItem` class and will always contain these methods: +- `getValue()` - returns the value of the input. +- `getIndex()` - returns the index/key of the input. +- `getName()` - returns a human friendly name for the input (company_name will be Company Name etc). + +`InputFile` has some of the same methods as above along with some other file-specific methods like: +- `getTmpName()` - get file temporary name. +- `getSize()` - get file size. +- `move($destination)` - move file to destination. +- `getContents()` - get file content. +- `getType()` - get mime-type for file. +- `getError()` - get file upload error. + + +### Easy access your input +Create a helper function to easily get access to the input elements. + +Example: + +```php +/** + * Get input class + * @return \Pecee\Http\Input\Input + */ +function input() { + return new \Pecee\Http\Input\Input(); +} +``` + +Then you can easily do something like this in your controller: + +```php +// Get parameter site_id or default-value 2 +$value = input()->get('site_id', '2'); +``` + ## Sites This is some sites that uses the simple-router project in production. diff --git a/src/Pecee/Http/Input/Input.php b/src/Pecee/Http/Input/Input.php new file mode 100644 index 0000000..09872be --- /dev/null +++ b/src/Pecee/Http/Input/Input.php @@ -0,0 +1,191 @@ +setGet(); + $this->setPost(); + $this->setFile(); + } + + /** + * Get all get/post items + * @param array|null $filter Only take items in filter + * @return array + */ + public function all(array $filter = null) { + $output = $this->get->getData(); + $output = array_merge($output, $this->post->getData()); + + if($filter !== null) { + $tmp = array(); + foreach($output as $key => $val) { + if(in_array($key, $filter)) { + $tmp[$key] = $val; + } + } + return $tmp; + } + + return $output; + } + + public function getObject($index, $default = null) { + $index = (strpos($index, '[') > -1) ? substr($index, 0, strpos($index, '[')) : $index; + + $element = $this->get->findFirst($index); + + if($element !== null) { + return $element; + } + + $element = $this->post->findFirst($index); + + if($element !== null) { + return $element; + } + + $element = $this->file->findFirst($index); + + if($element !== null) { + return $element; + } + + return $default; + } + + /** + * Get input element value matching index + * @param string $index + * @param string|null $default + * @return string|null + */ + public function get($index, $default = null) { + + $key = (strpos($index, '[') > -1) ? substr($index, strpos($index, '[')+1, strpos($index, ']') - strlen($index)) : null; + $index = (strpos($index, '[') > -1) ? substr($index, 0, strpos($index, '[')) : $index; + + $item = $this->getObject($index); + + if($item !== null) { + + if (is_array($item->getValue())) { + return ($key !== null && isset($item->getValue()[$key])) ? $item->getValue()[$key] : $item->getValue(); + } + + return ($item->getValue() === null) ? $default : $item->getValue(); + } + + return $default; + } + + public function setGet() { + $this->get = new InputCollection(); + + if(count($_GET)) { + foreach($_GET as $key => $get) { + if(!is_array($get)) { + $this->get->{$key} = new InputItem($key, $get); + continue; + } + + $output = array(); + + foreach($get as $k => $g) { + $output[$k] = new InputItem($k, $g); + } + + $this->get->{$key} = new InputItem($key, $output); + } + } + } + + public function setPost() { + $this->post = new InputCollection(); + + $postVars = array(); + + if(in_array($_SERVER['REQUEST_METHOD'], ['PUT', 'PATCH', 'DELETE'])) { + parse_str(file_get_contents('php://input'), $postVars); + } else { + $postVars = $_POST; + } + + if(count($postVars)) { + + foreach($postVars as $key => $post) { + if(!is_array($post)) { + $this->post->{strtolower($key)} = new InputItem($key, $post); + continue; + } + + $output = array(); + + foreach($post as $k=>$p) { + $output[$k] = new InputItem($k, $p); + } + + $this->post->{strtolower($key)} = new InputItem($key, $output); + } + } + } + + public function setFile() { + $this->file = new InputCollection(); + + if(count($_FILES)) { + foreach($_FILES as $key => $value) { + // Multiple files + if(!is_array($value['name'])) { + // Strip empty values + if($value['error'] != '4') { + $file = new InputFile(); + $file->setIndex($key); + $file->setName($value['name']); + $file->setSize($value['size']); + $file->setType($value['type']); + $file->setTmpName($value['tmp_name']); + $file->setError($value['error']); + $this->file->{strtolower($key)} = $file; + } + continue; + } + + $output = array(); + + foreach($value['name'] as $k=>$val) { + // Strip empty values + if($value['error'][$k] != '4') { + $file = new InputFile(); + $file->setIndex($k); + $file->setName($value['name'][$k]); + $file->setSize($value['size'][$k]); + $file->setType($value['type'][$k]); + $file->setTmpName($value['tmp_name'][$k]); + $file->setError($value['error'][$k]); + $output[$k] = $file; + } + } + + $this->file->{strtolower($key)} = new InputItem($key, $output); + } + } + } + +} \ No newline at end of file diff --git a/src/Pecee/Http/Input/InputCollection.php b/src/Pecee/Http/Input/InputCollection.php new file mode 100644 index 0000000..d531aba --- /dev/null +++ b/src/Pecee/Http/Input/InputCollection.php @@ -0,0 +1,67 @@ +data)) { + + if(isset($this->data[$index])) { + return $this->data[$index]; + } + + foreach($this->data as $key => $value) { + if(strtolower($index) === strtolower($key)) { + return $value; + } + } + } + + return null; + } + + /** + * @param $index + * @throws \InvalidArgumentException + * @return IInputItem + */ + public function __get($index) { + $item = $this->findFirst($index); + // Ensure that item are always available + if($item === null) { + $this->data[$index] = new InputItem($index, null); + return $this->data[$index]; + } + + return $item; + } + + public function __set($index, $value) { + $this->data[$index] = $value; + } + + public function getData() { + return $this->data; + } + + /** + * Retrieve an external iterator + * @link http://php.net/manual/en/iteratoraggregate.getiterator.php + * @return \Traversable An instance of an object implementing Iterator or + * Traversable + * @since 5.0.0 + */ + public function getIterator() { + return new \ArrayIterator($this->data); + } + +} \ No newline at end of file diff --git a/src/Pecee/Http/Input/InputFile.php b/src/Pecee/Http/Input/InputFile.php new file mode 100644 index 0000000..734ffc5 --- /dev/null +++ b/src/Pecee/Http/Input/InputFile.php @@ -0,0 +1,88 @@ +index; + } + + /** + * @return string + */ + public function getName() { + return $this->name; + } + + /** + * @return string + */ + public function getSize() { + return $this->size; + } + + /** + * @return string + */ + public function getType() { + return $this->type; + } + + /** + * @return string + */ + public function getError() { + return $this->error; + } + + /** + * @return string + */ + public function getTmpName() { + return $this->tmpName; + } + + public function getExtension() { + return pathinfo($this->getName(), PATHINFO_EXTENSION); + } + + public function move($destination) { + return move_uploaded_file($this->tmpName, $destination); + } + + public function getContents() { + return file_get_contents($this->tmpName); + } + + public function setIndex($index) { + $this->index = $index; + } + + public function setName($name) { + $this->name = $name; + } + + public function setTmpName($name) { + $this->tmpName = $name; + } + + public function setSize($size) { + $this->size = $size; + } + + public function setType($type) { + $this->type = $type; + } + + public function setError($error) { + $this->error = $error; + } + +} \ No newline at end of file diff --git a/src/Pecee/Http/Input/InputItem.php b/src/Pecee/Http/Input/InputItem.php new file mode 100644 index 0000000..3d3e912 --- /dev/null +++ b/src/Pecee/Http/Input/InputItem.php @@ -0,0 +1,53 @@ +index = $index; + $this->value = $value; + + // Make the name human friendly, by replace _ with space + $this->name = ucfirst(str_replace('_', ' ', $this->index)); + } + + /** + * @return array + */ + public function getName() { + return $this->name; + } + + /** + * @return array + */ + public function getValue() { + return $this->value; + } + + /** + * @return string + */ + public function getIndex() { + return $this->index; + } + + /** + * Set input name + * @param string $name + * @return static $this + */ + public function setName($name) { + $this->name = $name; + return $this; + } + + public function __toString() { + return (string)$this->getValue(); + } + +} \ No newline at end of file diff --git a/src/Pecee/Http/Request.php b/src/Pecee/Http/Request.php index 31c101e..75417d8 100644 --- a/src/Pecee/Http/Request.php +++ b/src/Pecee/Http/Request.php @@ -1,6 +1,8 @@ uri = $_SERVER['REQUEST_URI']; $this->method = (isset($_POST['_method'])) ? strtolower($_POST['_method']) : strtolower($_SERVER['REQUEST_METHOD']); $this->headers = $this->getAllHeaders(); + $this->input = new Input(); } protected function getAllHeaders() { From 7fdeef74d6068aa030ee89be16d4a7de9e423cd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Sessing=C3=B8?= Date: Fri, 15 Apr 2016 23:10:49 +0200 Subject: [PATCH 4/4] InputFile now inherits from InputItem --- README.md | 2 +- src/Pecee/Http/Input/Input.php | 6 ++---- src/Pecee/Http/Input/InputCollection.php | 2 +- src/Pecee/Http/Input/InputFile.php | 22 +--------------------- src/Pecee/Http/Input/InputItem.php | 2 +- 5 files changed, 6 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 010838e..9cef4b9 100644 --- a/README.md +++ b/README.md @@ -364,7 +364,7 @@ All object inherits from `InputItem` class and will always contain these methods - `getIndex()` - returns the index/key of the input. - `getName()` - returns a human friendly name for the input (company_name will be Company Name etc). -`InputFile` has some of the same methods as above along with some other file-specific methods like: +`InputFile` has the same methods as above along with some other file-specific methods like: - `getTmpName()` - get file temporary name. - `getSize()` - get file size. - `move($destination)` - move file to destination. diff --git a/src/Pecee/Http/Input/Input.php b/src/Pecee/Http/Input/Input.php index 09872be..475b19c 100644 --- a/src/Pecee/Http/Input/Input.php +++ b/src/Pecee/Http/Input/Input.php @@ -155,8 +155,7 @@ class Input { if(!is_array($value['name'])) { // Strip empty values if($value['error'] != '4') { - $file = new InputFile(); - $file->setIndex($key); + $file = new InputFile($key); $file->setName($value['name']); $file->setSize($value['size']); $file->setType($value['type']); @@ -172,8 +171,7 @@ class Input { foreach($value['name'] as $k=>$val) { // Strip empty values if($value['error'][$k] != '4') { - $file = new InputFile(); - $file->setIndex($k); + $file = new InputFile($k); $file->setName($value['name'][$k]); $file->setSize($value['size'][$k]); $file->setType($value['type'][$k]); diff --git a/src/Pecee/Http/Input/InputCollection.php b/src/Pecee/Http/Input/InputCollection.php index d531aba..09d601b 100644 --- a/src/Pecee/Http/Input/InputCollection.php +++ b/src/Pecee/Http/Input/InputCollection.php @@ -32,7 +32,7 @@ class InputCollection implements \IteratorAggregate { /** * @param $index * @throws \InvalidArgumentException - * @return IInputItem + * @return InputItem */ public function __get($index) { $item = $this->findFirst($index); diff --git a/src/Pecee/Http/Input/InputFile.php b/src/Pecee/Http/Input/InputFile.php index 734ffc5..429d3f3 100644 --- a/src/Pecee/Http/Input/InputFile.php +++ b/src/Pecee/Http/Input/InputFile.php @@ -1,26 +1,14 @@ index; - } - - /** - * @return string - */ - public function getName() { - return $this->name; - } - /** * @return string */ @@ -61,14 +49,6 @@ class InputFile { return file_get_contents($this->tmpName); } - public function setIndex($index) { - $this->index = $index; - } - - public function setName($name) { - $this->name = $name; - } - public function setTmpName($name) { $this->tmpName = $name; } diff --git a/src/Pecee/Http/Input/InputItem.php b/src/Pecee/Http/Input/InputItem.php index 3d3e912..8df2c57 100644 --- a/src/Pecee/Http/Input/InputItem.php +++ b/src/Pecee/Http/Input/InputItem.php @@ -7,7 +7,7 @@ class InputItem { protected $name; protected $value; - public function __construct($index, $value) { + public function __construct($index, $value = null) { $this->index = $index; $this->value = $value;