Skip to content

Commit

Permalink
Merge pull request #10 from PhpGt/7-file
Browse files Browse the repository at this point in the history
Improve API design while moving towards FileUpload support
  • Loading branch information
g105b authored Feb 23, 2018
2 parents 10acdc1 + ebd8af3 commit 21d2477
Show file tree
Hide file tree
Showing 27 changed files with 504 additions and 189 deletions.
2 changes: 1 addition & 1 deletion src/Body.php → src/BodyStream.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@

use Gt\Http\Stream;

class Body extends Stream {}
class BodyStream extends Stream {}
126 changes: 96 additions & 30 deletions src/Input.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,79 +5,143 @@
use Countable;
use Iterator;
use Psr\Http\Message\StreamInterface;
use Gt\Input\Trigger\Trigger;
use Gt\Input\InputData\InputData;
use Gt\Input\InputData\InputDatum;
use Gt\Input\InputData\KeyValueArrayAccess;
use Gt\Input\InputData\KeyValueCountable;
use Gt\Input\InputData\KeyValueIterator;
use Gt\Input\InputData\BodyInputData;
use Gt\Input\InputData\CombinedInputData;
use Gt\Input\InputData\FileUploadInputData;
use Gt\Input\InputData\QueryStringInputData;

class Input implements ArrayAccess, Countable, Iterator {
use InputDataArrayAccess;
use InputDataCountable;
use InputDataIterator;
use KeyValueArrayAccess;
use KeyValueCountable;
use KeyValueIterator;

const DATA_QUERYSTRING = "get";
const DATA_POSTFIELDS = "post";
const DATA_COMBINED = "both";
const DATA_BODY = "post";
const DATA_FILES = "files";
const DATA_COMBINED = "combined";

/** @var Body */
protected $body;
/** @var BodyStream */
protected $bodyStream;

/** @var InputData */
/** @var QueryStringInputData */
protected $queryStringParameters;
/** @var InputData */
protected $postFields;
/** @var Upload */
protected $files;
/** @var BodyInputData */
protected $bodyParameters;
/** @var FileUploadInputData */
protected $fileUploadParameters;
/** @var CombinedInputData */
protected $parameters;

public function __construct(
array $get = [],
array $post = [],
array $files = [],
string $bodyPath = "php://input"
) {
$this->body = new Body($bodyPath);
$this->queryStringParameters = new InputData($get);
$this->postFields = new InputData($post);
$this->files = new Upload($files);
$this->data = new InputData($get, $post);
$this->dataKeys = $this->data->getKeys();
$this->bodyStream = new BodyStream($bodyPath);

$this->queryStringParameters = new QueryStringInputData($get);
$this->bodyParameters = new BodyInputData($post);
$this->fileUploadParameters = new FileUploadInputData($files);

$this->parameters = new CombinedInputData(
$this->queryStringParameters,
$this->bodyParameters,
$this->fileUploadParameters
);
}

/**
* Returns the input payload as a streamable HTTP request body.
*/
public function getStream():StreamInterface {
return $this->body;
return $this->bodyStream;
}

/**
* Get a particular input value by its key. To specify either GET or POST variables, pass
* Input::METHOD_GET or Input::METHOD_POST as the second parameter (defaults to
* Input::METHOD_BOTH).
*/
public function get(string $key, string $method = null):?string {
public function get(string $key, string $method = null):?InputDatum {
if(is_null($method)) {
$method = self::DATA_COMBINED;
}

$data = null;

switch($method) {
case self::DATA_QUERYSTRING:
$variable = $this->queryStringParameters;
$data = $this->queryStringParameters->get($key);
break;
case self::DATA_POSTFIELDS:
$variable = $this->postFields;

case self::DATA_BODY:
$data =$this->bodyParameters->get($key);
break;

case self::DATA_FILES:
$data = $this->fileUploadParameters->get($key);
break;

case self::DATA_COMBINED:
$variable = $this->data;
$data = $this->parameters->get($key);
break;

default:
throw new InvalidInputMethodException($method);
}

return $variable[$key];
return $data;
}

/**
* Does the input contain the specified key?
*/
public function has(string $key):bool {
return isset($this->data[$key]);
public function has(string $key, string $method = null):bool {
if(is_null($method)) {
$method = self::DATA_COMBINED;
}

switch($method) {
case self::DATA_QUERYSTRING:
$isset = $this->hasQueryStringParameter($key);
break;

case self::DATA_BODY:
$isset =$this->hasBodyParameter($key);
break;

case self::DATA_FILES:
$isset =$this->hasFileUploadParameter($key);
break;

case self::DATA_COMBINED:
$isset = isset($this->parameters[$key]);
break;

default:
throw new InvalidInputMethodException($method);
}

return $isset;
}

public function hasQueryStringParameter(string $key):bool {
return isset($this->queryStringParameters[$key]);
}

public function hasBodyParameter(string $key):bool {
return isset($this->bodyParameters[$key]);
}

public function hasFileUploadParameter(string $key):bool {
return isset($this->fileUploadParameters[$key]);
}

/**
Expand All @@ -92,10 +156,12 @@ public function getAll(string $method = null):InputData {
switch($method) {
case self::DATA_QUERYSTRING:
return $this->queryStringParameters;
case self::DATA_POSTFIELDS:
return $this->postFields;
case self::DATA_BODY:
return $this->bodyParameters;
case self::DATA_FILES:
return $this->fileUploadParameters;
case self::DATA_COMBINED:
return $this->data;
return $this->parameters;
default:
throw new InvalidInputMethodException($method);
}
Expand Down
56 changes: 0 additions & 56 deletions src/InputData.php

This file was deleted.

29 changes: 29 additions & 0 deletions src/InputData/AbstractInputData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php
namespace Gt\Input\InputData;

use ArrayAccess;
use Countable;
use Iterator;

abstract class AbstractInputData implements ArrayAccess, Countable, Iterator {
use KeyValueArrayAccess;
use KeyValueCountable;
use KeyValueIterator;

/** @var InputDatum[] */
protected $parameters = [];

public function get(string $key):?InputDatum {
return $this->parameters[$key] ?? null;
}

protected function set(string $key, InputDatum $value):void {
$this->parameters[$key] = $value;
}

public function withKeyValue(string $key, InputDatum $value):self {
$clone = clone($this);
$clone->parameters[$key] = $value;
return $clone;
}
}
4 changes: 4 additions & 0 deletions src/InputData/BodyInputData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?php
namespace Gt\Input\InputData;

class BodyInputData extends InputData {}
4 changes: 4 additions & 0 deletions src/InputData/CombinedInputData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?php
namespace Gt\Input\InputData;

class CombinedInputData extends InputData {}
34 changes: 34 additions & 0 deletions src/InputData/FileUploadInputData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php
namespace Gt\Input\InputData;

class FileUploadInputData extends InputData {

public function __construct(array $files) {
$files = $this->normalizeArray($files);

// TODO: Set $this->data with kvp of files ($files[filename] => FileUpload(data))
}

/**
* The files array is an associative array where the key is the name of the request
* parameter, and the value is another associative array with keys:
* + name
* + type
* + tmp_name
* + error
* + size
* Each key's value is string, unless the request parameter name ends with [], in which case
* each value is another array. This function normalises the array to the latter.
*/
protected function normalizeArray($files):array {
foreach($files as $parameterName => $fileDetailArray) {
foreach($fileDetailArray as $key => $value) {
if(!is_array($value)) {
$files[$parameterName][$key] = [$value];
}
}
}

return $files;
}
}
51 changes: 51 additions & 0 deletions src/InputData/InputData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php
namespace Gt\Input\InputData;

class InputData extends AbstractInputData {
public function __construct(iterable...$sources) {
$this->parameters = [];

foreach($sources as $source) {
foreach($source as $key => $value) {
if(!$value instanceof InputDatum) {
$value = new InputDatum($value);
}
$this->add($key, $value);
}
}
}

public function add(string $key, InputDatum $datum):self {
$this->parameters[$key] = $datum;
return $this;
}

public function addKeyValue(string $key, string $value):self {
$datum = new InputDatum($value);
return $this->add($key, $datum);
}

public function remove(string...$keys):self {
foreach($keys as $key) {
if(isset($this->parameters[$key])) {
unset($this->parameters[$key]);
}
}

return $this;
}

public function removeExcept(string...$keys):self {
foreach($this->parameters as $key => $value) {
if(!in_array($key, $keys)) {
unset($this->parameters[$key]);
}
}

return $this;
}

public function getKeys():array {
return array_keys($this->parameters);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
<?php
namespace Gt\Input;
namespace Gt\Input\InputData;

use Gt\Input\Input;
use Gt\Input\WithWithoutClashingException;

class InputDataFactory {
public static function create(Input $input, array $with = [], array $without = []):InputData {
Expand Down
Loading

0 comments on commit 21d2477

Please sign in to comment.