diff --git a/README.md b/README.md
index 58f4919..7b6a68d 100644
--- a/README.md
+++ b/README.md
@@ -341,9 +341,11 @@ By default all controller and resource routes will use a simplified version of t
SimpleRouter::get('/product-view/{id}', 'ProductsController@show', ['as' => 'product']);
url('product', ['id' => 22], ['category' => 'shoes']);
+url('product', null, ['category' => 'shoes']);
# output
# /product-view/22/?category=shoes
+# /product-view/?category=shoes
```
**Getting the url using the name (controller route)**
@@ -353,10 +355,12 @@ SimpleRouter::controller('/images', 'ImagesController', ['as' => 'picture']);
url('picture@getView', null, ['category' => 'shoes']);
url('picture', 'getView', ['category' => 'shoes']);
+url('picture', 'view');
# output
# /images/view/?category=shows
# /images/view/?category=shows
+# /images/view/
```
**Getting the url using class**
@@ -370,7 +374,7 @@ url('ImagesController@getImage', null, ['id' => 22]);
# output
# /product-view/22/?category=shoes
-# /images/image/?category=shows
+# /images/image/?id=22
```
**Using custom names for methods on a controller/resource route**
@@ -405,6 +409,11 @@ url('phones.edit');
**Return the current url**
```php
url();
+url(null, null, ['q' => 'cars']);
+
+# output
+# /CURRENT-URL/
+# /CURRENT-URL/?q=cars
```
## Custom CSRF verifier
@@ -466,7 +475,6 @@ class CustomRouterRules implement IRouterBootManager {
}
}
-
```
The above should be pretty self-explanatory and can easily be changed to loop through urls store in the database, file or cache.
@@ -526,7 +534,6 @@ class CustomMiddleware implements Middleware {
}
}
-
```
#### Changing callback
@@ -558,32 +565,78 @@ class CustomMiddleware implements Middleware {
## Using the Input class to manage parameters
-We've added the `Input` class to easy access parameters from your Controller-classes.
+We've added the `Input` class to easy access and manage parameters from your Controller-classes.
**Return single parameter value (matches both GET, POST, FILE):**
+If items is grouped in the html, it will return an array of items.
+
+**Note:** `get` will automatically trim the value and ensure that it's not empty. If it's empty the `$defaultValue` will be returned.
+
```php
-$value = input()->get('name');
+$value = input()->get($index, $defaultValue);
```
**Return parameter object (matches both GET, POST, FILE):**
+Will return an instance of `InputItem` or `InputFile` depending on the type.
+
+You can use this in your html as it will render the value of the item.
+However if you want to compare value in your if statements, you have to use
+the `getValue` or use the `input()->get()` instead.
+
+If items is grouped in the html, it will return an array of items.
+
+**Note:** `getObject` will only return `$defaultValue` if the item doesn't exist. If you want `$defaultValue` to be returned if the item is empty, please use `input()->get()` instead.
+
```php
-$object = input()->getObject('name');
+$object = input()->getObject($index);
```
**Return specific GET parameter (where name is the name of your parameter):**
```php
-$object = input()->get->name;
-$object = input()->post->name;
-$object = input()->file->name;
+# -- match any (default) --
+
+/*
+ * This is the recommended way to go for normal usage
+ * as it will strip empty values, ensuring that
+ * $defaultValue is returned if the value is empty.
+ */
+
+$id = input()->get($index, $defaultValue);
+
+# -- match specific --
+
+$object = input()->get($index, $defaultValue, 'get');
+$object = input()->get($index, $defaultValue, 'post');
+$object = input()->get($index, $defaultValue, 'file');
# -- or --
-$object = input()->get->get($key, $defaultValue);
-$object = input()->post->get($key, $defaultValue);
-$object = input()->file->get($key, $defaultValue);
+$object = input()->findGet($index, $defaultValue);
+$object = input()->findPost($index, $defaultValue);
+$object = input()->findFile($index, $defaultValue);
+
+# -- examples --
+
+/**
+ * In this small example we loop through a collection of files
+ * added on the page like this
+ *
+ */
+
+/* @var $image \Pecee\Http\Input\InputFile */
+foreach(input()->get('images', []) as $image)
+{
+ if($image->getMime() === 'image/jpeg') {
+
+ $destinationFilname = sprintf('%s.%s', uniqid(), $image->getExtension());
+
+ $image->move('/uploads/' . $destinationFilename);
+
+ }
+}
```
**Return all parameters:**
@@ -599,11 +652,11 @@ $values = input()->all([
]);
```
-All object inherits from `InputItem` class and will always contain these methods:
+All object implements the `IInputItem` interface 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).
+- `getValue()` - returns the value of the input.
`InputFile` has the same methods as above along with some other file-specific methods like:
- `getTmpName()` - get file temporary name.
@@ -612,6 +665,8 @@ All object inherits from `InputItem` class and will always contain these methods
- `getContents()` - get file content.
- `getType()` - get mime-type for file.
- `getError()` - get file upload error.
+- `hasError()` - returns `bool` if an error occurred while uploading (if getError is not 0).
+- `toArray()` - returns raw array
Below example requires you to have the helper functions added. Please refer to the helper functions section in the documentation.
diff --git a/src/Pecee/Http/Input/IInputItem.php b/src/Pecee/Http/Input/IInputItem.php
new file mode 100644
index 0000000..5846788
--- /dev/null
+++ b/src/Pecee/Http/Input/IInputItem.php
@@ -0,0 +1,15 @@
+request = $request;
- $this->post = new InputCollection();
- $this->get = new InputCollection();
- $this->file = new InputCollection();
-
if ($request->getMethod() !== 'get') {
$requestContentType = $request->getHeader('http-content-type');
@@ -60,6 +56,7 @@ class Input
if ($this->invalidContentType === false) {
$this->parseInputs();
}
+
}
protected function parseInputs()
@@ -76,7 +73,21 @@ class Input
$key = $keys[$i];
$value = $_GET[$key];
- $this->get->{$key} = new InputItem($key, $value);
+ // Handle array input
+ if (is_array($value) === false) {
+ $this->get[$key] = new InputItem($key, $value);
+ continue;
+ }
+
+ $subMax = count($value) - 1;
+ $keys = array_keys($value);
+ $output = [];
+
+ for ($i = $subMax; $i >= 0; $i--) {
+ $output[$keys[$i]] = new InputItem($key, $value[$keys[$i]]);
+ }
+
+ $this->get[$key] = $output;
}
}
@@ -99,7 +110,21 @@ class Input
$key = $keys[$i];
$value = $postVars[$key];
- $this->post->{strtolower($key)} = new InputItem($key, $value);
+ // Handle array input
+ if (is_array($value) === false) {
+ $this->post[$key] = new InputItem($key, $value);
+ continue;
+ }
+
+ $subMax = count($value) - 1;
+ $keys = array_keys($value);
+ $output = [];
+
+ for ($i = $subMax; $i >= 0; $i--) {
+ $output[$keys[$i]] = new InputItem($key, $value[$keys[$i]]);
+ }
+
+ $this->post[$key] = $output;
}
}
@@ -119,56 +144,66 @@ class Input
// Handle array input
if (is_array($value['name']) === false) {
$values['index'] = $key;
- $this->file->{strtolower($key)} = InputFile::createFromArray($values);
+ $this->file[$key] = InputFile::createFromArray(array_merge($value, $values));
continue;
}
- $output = new InputCollection();
+ $subMax = count($value['name']) - 1;
+ $keys = array_keys($value['name']);
+ $output = [];
- foreach ($value['name'] as $k => $val) {
+ for ($i = $subMax; $i >= 0; $i--) {
- $output->{$k} = InputFile::createFromArray([
+ $output[$keys[$i]] = InputFile::createFromArray([
'index' => $key,
- 'error' => $value['error'][$k],
- 'tmp_name' => $value['tmp_name'][$k],
- 'type' => $value['type'][$k],
- 'size' => $value['size'][$k],
- 'name' => $value['name'][$k],
+ 'error' => $value['error'][$keys[$i]],
+ 'tmp_name' => $value['tmp_name'][$keys[$i]],
+ 'type' => $value['type'][$keys[$i]],
+ 'size' => $value['size'][$keys[$i]],
+ 'name' => $value['name'][$keys[$i]],
]);
}
- $this->file->{strtolower($key)} = $output;
+ $this->file[$key] = $output;
}
}
}
- public function getObject($index, $default = null)
+ public function findPost($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;
+ return isset($this->post[$index]) ? $this->post[$index] : $default;
+ }
- $element = $this->get->findFirst($index);
+ public function findFile($index, $default = null)
+ {
+ return isset($this->file[$index]) ? $this->file[$index] : $default;
+ }
- if ($element !== null) {
- return ($key !== null) ? $element[$key] : $element;
+ public function findGet($index, $default = null)
+ {
+ return isset($this->get[$index]) ? $this->get[$index] : $default;
+ }
+
+ public function getObject($index, $default = null, $method = null)
+ {
+
+ $element = null;
+
+ if ($method === null || strtolower($method) === 'get') {
+ $element = $this->findGet($index);
}
- if ($this->request->getMethod() !== 'get') {
-
- $element = $this->post->findFirst($index);
- if ($element !== null) {
- return ($key !== null) ? $element[$key] : $element;
- }
-
- $element = $this->file->findFirst($index);
- if ($element !== null) {
- return ($key !== null) ? $element[$key] : $element;
- }
+ if ($element === null && $method === null || strtolower($method) === 'post') {
+ $element = $this->findPost($index);
}
- return $default;
+ if ($element === null && $method === null || strtolower($method) === 'file') {
+ $element = $this->findFile($index);
+ }
+
+ return ($element === null) ? $default : $element;
}
/**
@@ -180,18 +215,13 @@ class Input
*/
public function get($index, $default = null)
{
- $item = $this->getObject($index);
+ $input = $this->getObject($index, $default);
- if ($item !== null) {
-
- if ($item instanceof InputCollection || $item instanceof InputFile) {
- return $item;
- }
-
- return (!is_array($item->getValue()) && trim($item->getValue()) === '') ? $default : $item;
+ if ($input instanceof InputItem) {
+ return (trim($input->getValue()) === '') ? $default : $input->getValue();
}
- return $default;
+ return $input;
}
public function exists($index)
diff --git a/src/Pecee/Http/Input/InputCollection.php b/src/Pecee/Http/Input/InputCollection.php
deleted file mode 100644
index b4227c2..0000000
--- a/src/Pecee/Http/Input/InputCollection.php
+++ /dev/null
@@ -1,91 +0,0 @@
-data) > 0) {
-
- if (isset($this->data[$index])) {
- return $this->data[$index];
- }
-
- foreach ($this->data as $key => $input) {
- if (strtolower($index) === strtolower($key)) {
- return $input;
- }
- }
- }
-
- return $default;
- }
-
- /**
- * Get input element value matching index
- *
- * @param string $index
- * @param string|null $default
- * @return string|null
- */
- public function get($index, $default = null)
- {
- $input = $this->findFirst($index);
-
- if ($input !== null && trim($input->getValue()) !== '') {
- return $input->getValue();
- }
-
- return $default;
- }
-
- /**
- * @param string $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 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
index 6cd1b35..8a38794 100644
--- a/src/Pecee/Http/Input/InputFile.php
+++ b/src/Pecee/Http/Input/InputFile.php
@@ -1,13 +1,39 @@
index = $index;
+
+ // Make the name human friendly, by replace _ with space
+ $this->name = ucfirst(str_replace('_', ' ', $this->index));
+ }
+
+ /**
+ * @return string
+ */
+ public function getIndex()
+ {
+ return $this->index;
+ }
+
+ /**
+ * @return string
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
/**
* @return string
*/
@@ -60,6 +86,13 @@ class InputFile extends InputItem
return file_get_contents($this->tmpName);
}
+ public function setName($name)
+ {
+ $this->name = $name;
+
+ return $this;
+ }
+
/**
* Set file temp. name
* @param string $name
@@ -68,6 +101,7 @@ class InputFile extends InputItem
public function setTmpName($name)
{
$this->tmpName = $name;
+
return $this;
}
@@ -79,6 +113,7 @@ class InputFile extends InputItem
public function setSize($size)
{
$this->size = $size;
+
return $this;
}
@@ -90,6 +125,7 @@ class InputFile extends InputItem
public function setType($type)
{
$this->type = $type;
+
return $this;
}
@@ -101,6 +137,7 @@ class InputFile extends InputItem
public function setError($error)
{
$this->error = (int)$error;
+
return $this;
}
@@ -109,7 +146,8 @@ class InputFile extends InputItem
return $this->getTmpName();
}
- public function hasError() {
+ public function hasError()
+ {
return ($this->getError() !== 0);
}
@@ -120,28 +158,33 @@ class InputFile extends InputItem
*/
public static function createFromArray(array $values)
{
- if(!isset($values['index'])) {
+ if (!isset($values['index'])) {
throw new \InvalidArgumentException('Index key is required');
}
$input = new static($values['index']);
- $input->setError((isset($values['error']) ? $values['error'] : null));
- $input->setName((isset($values['name']) ? $values['name'] : null));
- $input->setSize((isset($values['size']) ? $values['size'] : null));
- $input->setType((isset($values['type']) ? $values['type'] : null));
- $input->setTmpName((isset($values['tmp_name']) ? $values['tmp_name'] : null));
+ $input->setError(isset($values['error']) ? $values['error'] : null);
+ $input->setName(isset($values['name']) ? $values['name'] : null);
+ $input->setSize(isset($values['size']) ? $values['size'] : null);
+ $input->setType(isset($values['type']) ? $values['type'] : null);
+ $input->setTmpName(isset($values['tmp_name']) ? $values['tmp_name'] : null);
return $input;
}
- public function toArray() {
+ public function toArray()
+ {
return [
'tmp_name' => $this->tmpName,
- 'type' => $this->type,
- 'size' => $this->size,
- 'name' => $this->name,
- 'error' => $this->error,
+ 'type' => $this->type,
+ 'size' => $this->size,
+ 'name' => $this->name,
+ 'error' => $this->error,
];
}
+ public function __toString()
+ {
+ return $this->getValue();
+ }
}
\ No newline at end of file
diff --git a/src/Pecee/Http/Input/InputItem.php b/src/Pecee/Http/Input/InputItem.php
index 71d0253..934477b 100644
--- a/src/Pecee/Http/Input/InputItem.php
+++ b/src/Pecee/Http/Input/InputItem.php
@@ -1,7 +1,7 @@
name = ucfirst(str_replace('_', ' ', $this->index));
}
+ /**
+ * @return string
+ */
+ public function getIndex()
+ {
+ return $this->index;
+ }
+
/**
* @return string
*/
@@ -32,14 +40,6 @@ class InputItem
return $this->value;
}
- /**
- * @return string
- */
- public function getIndex()
- {
- return $this->index;
- }
-
/**
* Set input name
* @param string $name
diff --git a/src/Pecee/Http/Middleware/BaseCsrfVerifier.php b/src/Pecee/Http/Middleware/BaseCsrfVerifier.php
index 14c6732..af58695 100644
--- a/src/Pecee/Http/Middleware/BaseCsrfVerifier.php
+++ b/src/Pecee/Http/Middleware/BaseCsrfVerifier.php
@@ -34,7 +34,11 @@ class BaseCsrfVerifier implements IMiddleware
return false;
}
- foreach ($this->except as $url) {
+ $max = count($this->except) - 1;
+
+ for ($i = $max; $i >= 0; $i--) {
+ $url = $this->except[$i];
+
$url = rtrim($url, '/');
if ($url[strlen($url) - 1] === '*') {
$url = rtrim($url, '*');
@@ -43,7 +47,7 @@ class BaseCsrfVerifier implements IMiddleware
$skip = ($url === rtrim($request->getUri(), '/'));
}
- if ($skip) {
+ if ($skip === true) {
return true;
}
}
@@ -56,14 +60,14 @@ class BaseCsrfVerifier implements IMiddleware
if ($request->getMethod() !== 'get' && !$this->skip($request)) {
- $token = $request->getInput()->post->get(static::POST_KEY);
+ $token = $request->getInput()->get(static::POST_KEY, null, 'post');
// If the token is not posted, check headers for valid x-csrf-token
if ($token === null) {
$token = $request->getHeader(static::HEADER_KEY);
}
- if (!$this->csrfToken->validate($token)) {
+ if ($this->csrfToken->validate($token) === false) {
throw new TokenMismatchException('Invalid csrf-token.');
}
diff --git a/src/Pecee/Http/Request.php b/src/Pecee/Http/Request.php
index 0f14387..4b2a06c 100644
--- a/src/Pecee/Http/Request.php
+++ b/src/Pecee/Http/Request.php
@@ -25,9 +25,15 @@ class Request
{
$this->headers = [];
- foreach ($_SERVER as $name => $value) {
- $this->headers[strtolower($name)] = $value;
- $this->headers[strtolower(str_replace('_', '-', $name))] = $value;
+ $max = count($_SERVER) - 1;
+ $keys = array_keys($_SERVER);
+
+ for($i = $max; $i >= 0; $i--) {
+ $key = $keys[$i];
+ $value = $_SERVER[$key];
+
+ $this->headers[strtolower($key)] = $value;
+ $this->headers[strtolower(str_replace('_', '-', $key))] = $value;
}
}
diff --git a/src/Pecee/SimpleRouter/Route/RouteController.php b/src/Pecee/SimpleRouter/Route/RouteController.php
index e62d1f3..f8657da 100644
--- a/src/Pecee/SimpleRouter/Route/RouteController.php
+++ b/src/Pecee/SimpleRouter/Route/RouteController.php
@@ -59,7 +59,12 @@ class RouteController extends LoadableRoute implements IControllerRoute
/* Remove requestType from method-name, if it exists */
if ($method !== null) {
- foreach (static::$requestTypes as $requestType) {
+ $max = count(static::$requestTypes);
+
+ for ($i = 0; $i < $max; $i++) {
+
+ $requestType = static::$requestTypes[$i];
+
if (stripos($method, $requestType) === 0) {
$method = substr($method, strlen($requestType));
break;
diff --git a/src/Pecee/SimpleRouter/Route/RouteGroup.php b/src/Pecee/SimpleRouter/Route/RouteGroup.php
index 13a83d8..0cbe242 100644
--- a/src/Pecee/SimpleRouter/Route/RouteGroup.php
+++ b/src/Pecee/SimpleRouter/Route/RouteGroup.php
@@ -19,8 +19,12 @@ class RouteGroup extends Route implements IGroupRoute
public function matchDomain(Request $request)
{
if (count($this->domains) > 0) {
- foreach ($this->domains as $domain) {
+ $max = count($this->domains);
+
+ for ($i = 0; $i < $max; $i++) {
+
+ $domain = $this->domains[$i];
$parameters = $this->parseParameters($domain, $request->getHost(), '.*');
if ($parameters !== null) {
diff --git a/src/Pecee/SimpleRouter/Router.php b/src/Pecee/SimpleRouter/Router.php
index a5c867c..a34e66c 100644
--- a/src/Pecee/SimpleRouter/Router.php
+++ b/src/Pecee/SimpleRouter/Router.php
@@ -140,8 +140,12 @@ class Router
protected function processRoutes(array $routes, IGroupRoute $group = null, IRoute $parent = null)
{
// Loop through each route-request
+ $max = count($routes) - 1;
+
/* @var $route IRoute */
- foreach ($routes as $route) {
+ for ($i = $max; $i >= 0; $i--) {
+
+ $route = $routes[$i];
if ($route instanceof IGroupRoute) {
@@ -238,10 +242,10 @@ class Router
$this->originalUrl = $this->request->getUri();
}
- $max = count($this->processedRoutes);
+ $max = count($this->processedRoutes) - 1;
/* @var $route IRoute */
- for ($i = 0; $i < $max; $i++) {
+ for ($i = $max; $i >= 0; $i--) {
$route = $this->processedRoutes[$i];