Merge pull request #90 from skipperbent/feature-input

Feature input
This commit is contained in:
Simon Sessingø
2016-04-15 23:12:40 +02:00
6 changed files with 450 additions and 0 deletions

View File

@@ -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 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.

View File

@@ -0,0 +1,189 @@
<?php
namespace Pecee\Http\Input;
class Input {
/**
* @var \Pecee\Http\Input\InputCollection
*/
public $get;
/**
* @var \Pecee\Http\Input\InputCollection
*/
public $post;
/**
* @var \Pecee\Http\Input\InputCollection
*/
public $file;
public function __construct() {
$this->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($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($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);
}
}
}
}

View File

@@ -0,0 +1,67 @@
<?php
namespace Pecee\Http\Input;
class InputCollection implements \IteratorAggregate {
protected $data = array();
/**
* Search for input element matching index.
* Useful for searching for finding items where $index doesn't contain form name.
*
* @param string $index
* @return mixed
*/
public function findFirst($index) {
if(count($this->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 InputItem
*/
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 <b>Iterator</b> or
* <b>Traversable</b>
* @since 5.0.0
*/
public function getIterator() {
return new \ArrayIterator($this->data);
}
}

View File

@@ -0,0 +1,68 @@
<?php
namespace Pecee\Http\Input;
class InputFile extends InputItem {
protected $name;
protected $size;
protected $type;
protected $error;
protected $tmpName;
/**
* @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 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;
}
}

View File

@@ -0,0 +1,53 @@
<?php
namespace Pecee\Http\Input;
class InputItem {
protected $index;
protected $name;
protected $value;
public function __construct($index, $value = null) {
$this->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();
}
}

View File

@@ -1,6 +1,8 @@
<?php
namespace Pecee\Http;
use Pecee\Http\Input\Input;
class Request {
protected static $instance;
@@ -24,6 +26,7 @@ class Request {
$this->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() {