SuperCommit 2
This commit is contained in:
parent
4280489558
commit
cc54862f2f
25
.scrutinizer.yml
Executable file
25
.scrutinizer.yml
Executable file
@ -0,0 +1,25 @@
|
||||
imports:
|
||||
- php
|
||||
|
||||
tools:
|
||||
external_code_coverage:
|
||||
timeout: 1000
|
||||
# PHP
|
||||
|
||||
# Don't like PSR standards, not going to get messages for them!
|
||||
php_code_sniffer: false
|
||||
|
||||
php_sim: true
|
||||
# Can't be used with similarity analyzer
|
||||
php_cpd: false
|
||||
|
||||
php_mess_detector: true
|
||||
php_pdepend: true
|
||||
php_loc: true
|
||||
php_analyzer:
|
||||
config:
|
||||
metrics_lack_of_cohesion_methods:
|
||||
enabled: true
|
||||
doc_comment_fixes:
|
||||
enabled: true
|
||||
php_hhvm: true
|
19
.travis.yml
Normal file
19
.travis.yml
Normal file
@ -0,0 +1,19 @@
|
||||
language: php
|
||||
|
||||
php:
|
||||
- 5.4
|
||||
- 5.5
|
||||
- 5.6
|
||||
- hhvm
|
||||
|
||||
script:
|
||||
- mkdir -p build/logs
|
||||
- cd tests && phpunit --coverage-clover build/logs/clover.xml
|
||||
|
||||
after_script:
|
||||
- wget https://scrutinizer-ci.com/ocular.phar
|
||||
- php ocular.phar code-coverage:upload --format=php-clover build/logs/clover.xml
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- hhvm
|
26
Sleepy/Core/aType.php → Sleepy/Core/Abstracts/Type.php
Executable file → Normal file
26
Sleepy/Core/aType.php → Sleepy/Core/Abstracts/Type.php
Executable file → Normal file
@ -7,17 +7,17 @@
|
||||
* but aiming to be as flexible as possible
|
||||
*
|
||||
* @author Timothy J. Warren
|
||||
* @package Sleepy/core
|
||||
*/
|
||||
|
||||
namespace Sleepy\Core;
|
||||
namespace Sleepy\Core\Abstracts;
|
||||
|
||||
use Sleepy\Core\Interfaces\Type as iType;
|
||||
use Sleepy\Exception\NotImplementedException;
|
||||
|
||||
/**
|
||||
* Abstract class with helpful functionality implementing type functionality
|
||||
*/
|
||||
abstract class aType implements iType {
|
||||
abstract class Type implements iType {
|
||||
|
||||
/**
|
||||
* The data in the current type wrapper
|
||||
@ -41,16 +41,32 @@ abstract class aType implements iType {
|
||||
*/
|
||||
public function __construct($data = NULL)
|
||||
{
|
||||
|
||||
if (empty($this->mime))
|
||||
{
|
||||
throw new NotImplementedException("Output types must have a mime type defined.");
|
||||
}
|
||||
|
||||
$this->set_data($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set data to serialize
|
||||
*
|
||||
* @param mixed $data
|
||||
* @return mixed
|
||||
*/
|
||||
protected function set_data(&$data)
|
||||
{
|
||||
if ( ! is_null($data))
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
else
|
||||
{
|
||||
$data = $this->data;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -75,4 +91,4 @@ abstract class aType implements iType {
|
||||
}
|
||||
|
||||
}
|
||||
// End of core/aType.php
|
||||
// End of Core/Abstracts/Type.php
|
66
Sleepy/Core/Config.php
Executable file
66
Sleepy/Core/Config.php
Executable file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
/**
|
||||
* Sleepy - a REST framework
|
||||
*
|
||||
*
|
||||
* A PHP Rest Framework valuing convention over configuration,
|
||||
* but aiming to be as flexible as possible
|
||||
*
|
||||
* @author Timothy J. Warren
|
||||
*/
|
||||
|
||||
namespace Sleepy\Core;
|
||||
|
||||
/**
|
||||
* Class for managing configuration values
|
||||
*/
|
||||
class Config {
|
||||
|
||||
/**
|
||||
* The config array
|
||||
* @var array
|
||||
*/
|
||||
protected $data = [];
|
||||
|
||||
/**
|
||||
* Load the specified config file and return
|
||||
* the config array
|
||||
*
|
||||
* @throws \InvalidArugmentException
|
||||
* @param string $name
|
||||
* @return array
|
||||
*/
|
||||
public function load($name)
|
||||
{
|
||||
$file = APPPATH . 'config/'. $name . '.php';
|
||||
|
||||
if (is_file($file))
|
||||
{
|
||||
$conf =require_once($file);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new \InvalidArgumentException("The config file doesn't exist");
|
||||
}
|
||||
|
||||
$this->data[$name] = $conf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specific parameter from the specified file
|
||||
*
|
||||
* @param string $file
|
||||
* @param string $key
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($file, $key=NULL)
|
||||
{
|
||||
if (is_null($key))
|
||||
{
|
||||
return $this->data[$file];
|
||||
}
|
||||
|
||||
return $this->data[$file][$key];
|
||||
}
|
||||
}
|
||||
// End of Core/Config.php
|
@ -7,13 +7,20 @@
|
||||
* but aiming to be as flexible as possible
|
||||
*
|
||||
* @author Timothy J. Warren
|
||||
* @package Sleepy/core
|
||||
*/
|
||||
|
||||
namespace Sleepy\Core;
|
||||
|
||||
/**
|
||||
* Class for accessing request data
|
||||
*
|
||||
* @method array server()
|
||||
* @method array env()
|
||||
* @method array get()
|
||||
* @method array post()
|
||||
* @method array put()
|
||||
* @method array delete()
|
||||
* @method array cookie()
|
||||
*/
|
||||
class Input {
|
||||
|
||||
@ -42,6 +49,13 @@ class Input {
|
||||
*/
|
||||
protected $delete = [];
|
||||
|
||||
/**
|
||||
* Class member for options data
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $options = [];
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// ! Working around PHP for nicer usability
|
||||
// --------------------------------------------------------------------------
|
||||
@ -82,6 +96,7 @@ class Input {
|
||||
$this->verb = \strtolower($_SERVER['REQUEST_METHOD']);
|
||||
|
||||
// Parse put and delete requests into input variables
|
||||
// @codeCoverageIgnoreStart
|
||||
if (isset($this->{$this->verb}))
|
||||
{
|
||||
$raw = \file_get_contents('php://input');
|
||||
@ -98,13 +113,17 @@ class Input {
|
||||
'env' => $_ENV,
|
||||
'cookie' => $_COOKIE
|
||||
];
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
// Parse request headers from $_SERVER
|
||||
foreach($_SERVER as $key => $val)
|
||||
{
|
||||
if (strpos($key, 'HTTP_') === 0)
|
||||
{
|
||||
$new_key = strtolower(str_replace('HTTP_', '', $key));
|
||||
$new_key = \strtolower(\strtr($key, [
|
||||
'HTTP_' => '',
|
||||
'_' => '-'
|
||||
]));
|
||||
$this->request_headers[$new_key] = $val;
|
||||
}
|
||||
}
|
||||
@ -119,7 +138,7 @@ class Input {
|
||||
* @param string $name - name of input array
|
||||
* @param array $args - function arguments
|
||||
* @return mixed
|
||||
* @throws DomainException
|
||||
* @throws \DomainException
|
||||
*/
|
||||
public function __call($name, $args=[])
|
||||
{
|
||||
@ -134,11 +153,12 @@ class Input {
|
||||
// Get a superglobal ($_VAR) value
|
||||
return $this->get_superglobal_var($name, $index, $filter);
|
||||
}
|
||||
else if(isset($this->$name))
|
||||
else if(isset($this->$name)) // @codeCoverageIgnoreStart
|
||||
{
|
||||
// Get a input variable not in a superglobal (eg. PUT/DELETE)
|
||||
return $this->get_request_var($name, $index, $filter);
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
// What kind of request are you trying to make?!
|
||||
throw new \DomainException('Invalid input array.');
|
||||
@ -154,7 +174,7 @@ class Input {
|
||||
{
|
||||
if ($index !== NULL)
|
||||
{
|
||||
$index = (str_replace([' ', '-'], '_', $index));
|
||||
$index = (\strtolower(\str_replace([' ', '_'], '-', $index)));
|
||||
|
||||
if (isset($this->request_headers[$index]))
|
||||
{
|
||||
@ -209,7 +229,7 @@ class Input {
|
||||
$has_eq = strpos($value, '=') !== FALSE;
|
||||
|
||||
// Parse the user agent separately
|
||||
if ($header === 'user_agent')
|
||||
if ($header === 'user-agent')
|
||||
{
|
||||
$this->parsed_headers[$header] = $this->parse_user_agent($value);
|
||||
continue;
|
||||
@ -231,21 +251,6 @@ class Input {
|
||||
parse_str($value, $this->parsed_headers[$header]);
|
||||
continue;
|
||||
}
|
||||
// For headers with commas and semicolons, break first on commas,
|
||||
// then on semicolons
|
||||
else if ($has_semi && $has_comma)
|
||||
{
|
||||
$values = explode(",", $value);
|
||||
foreach($values as &$v)
|
||||
{
|
||||
if (strpos($v, ";") !== FALSE)
|
||||
{
|
||||
$v = explode(";", $v);
|
||||
}
|
||||
}
|
||||
|
||||
$this->parsed_headers[$header] = $values;
|
||||
}
|
||||
// Anything else, just leave it as a string
|
||||
else
|
||||
{
|
||||
@ -308,29 +313,48 @@ class Input {
|
||||
*/
|
||||
protected function parse_accept_header($value)
|
||||
{
|
||||
$q_types = [];
|
||||
// A fake value so I can shift it off to have a 1-indexed array
|
||||
$high_types = [];
|
||||
$output = [];
|
||||
$index = 0;
|
||||
$count = 1;
|
||||
|
||||
// Split into segments of different values
|
||||
$groups = explode(',', $value);
|
||||
|
||||
foreach($groups as $group)
|
||||
{
|
||||
$group = \trim($group);
|
||||
$pair = explode(';q=', $group);
|
||||
|
||||
if (count($pair) === 2)
|
||||
{
|
||||
list($val, $q) = $pair;
|
||||
$output[$q] = $val;
|
||||
$q_types[$q] = $val;
|
||||
}
|
||||
else
|
||||
{
|
||||
$index++;
|
||||
$output[$index] = current($pair);
|
||||
$high_types[$count] = current($pair);
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
|
||||
ksort($output, SORT_NATURAL);
|
||||
// Add an additional fake value so we can
|
||||
// have a 1-indexed array
|
||||
$high_types[$count] = 'foo';
|
||||
$high_types = array_reverse($high_types);
|
||||
unset($high_types[0]);
|
||||
|
||||
$output = $q_types;
|
||||
|
||||
// Merge the arrays manually to maintain
|
||||
// keys, and thus ordering
|
||||
foreach($high_types as $k => $v)
|
||||
{
|
||||
$output[$k] = $v;
|
||||
}
|
||||
|
||||
krsort($output, SORT_NUMERIC);
|
||||
|
||||
return $output;
|
||||
}
|
||||
@ -338,6 +362,7 @@ class Input {
|
||||
/**
|
||||
* Get input var(s) from non-defined superglobal
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @param string $type - input array
|
||||
* @param string $index - variable in the input array
|
||||
* @param int $filter - PHP filter_var flag
|
||||
|
7
Sleepy/Core/iType.php → Sleepy/Core/Interfaces/Type.php
Executable file → Normal file
7
Sleepy/Core/iType.php → Sleepy/Core/Interfaces/Type.php
Executable file → Normal file
@ -7,15 +7,14 @@
|
||||
* but aiming to be as flexible as possible
|
||||
*
|
||||
* @author Timothy J. Warren
|
||||
* @package Sleepy/core
|
||||
*/
|
||||
|
||||
namespace Sleepy\core;
|
||||
namespace Sleepy\Core\Interfaces;
|
||||
|
||||
/**
|
||||
* Interface for output formats
|
||||
*/
|
||||
interface iType {
|
||||
interface Type {
|
||||
|
||||
/**
|
||||
* Convert the data to the output format
|
||||
@ -34,4 +33,4 @@ interface iType {
|
||||
public function unserialize($data_string);
|
||||
|
||||
}
|
||||
// End of core/iType.php
|
||||
// End of Core/Interfaces/Type.php
|
@ -7,10 +7,9 @@
|
||||
* but aiming to be as flexible as possible
|
||||
*
|
||||
* @author Timothy J. Warren
|
||||
* @package Sleepy/core
|
||||
*/
|
||||
|
||||
namespace Sleepy\core;
|
||||
namespace Sleepy\Core;
|
||||
|
||||
/**
|
||||
* Default output class
|
||||
@ -34,17 +33,24 @@ class Output {
|
||||
/**
|
||||
* The serialization object for the current data type
|
||||
*
|
||||
* @var Sleepy\core\aType
|
||||
* @var Sleepy\Core\aType
|
||||
*/
|
||||
protected $type_wrapper;
|
||||
|
||||
/**
|
||||
* The input object
|
||||
*
|
||||
* @var Sleepy\core\Input
|
||||
* @var Sleepy\Core\Input
|
||||
*/
|
||||
protected $input;
|
||||
|
||||
/**
|
||||
* Config object
|
||||
*
|
||||
* @var Sleepy\Core\Config;
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// ! Methods
|
||||
// --------------------------------------------------------------------------
|
||||
@ -52,10 +58,12 @@ class Output {
|
||||
/**
|
||||
* Create the output object
|
||||
*
|
||||
* @param array $config
|
||||
* @param Config $config
|
||||
* @param Input $input
|
||||
*/
|
||||
public function __construct(Input $input)
|
||||
public function __construct(Config $config, Input $input)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->input = $input;
|
||||
}
|
||||
|
||||
@ -92,15 +100,23 @@ class Output {
|
||||
/**
|
||||
* Set the data to be output to the endpoint
|
||||
*
|
||||
* @param string $type - The datatype to send
|
||||
* @param mixed $data
|
||||
* @param string $type - The data format to send
|
||||
* @param mixed $data - The data to send
|
||||
* @return void
|
||||
*/
|
||||
public function set_data($type = 'json', $data)
|
||||
public function set_data($type = 'html', $data = NULL)
|
||||
{
|
||||
if (is_null($data) && ! empty($this->data))
|
||||
{
|
||||
$data = $this->data;
|
||||
}
|
||||
|
||||
// Set instance data
|
||||
$this->data = $data;
|
||||
|
||||
// Get the appropriate output format for the client
|
||||
// And set the data
|
||||
$this->get_accepted_type($type, $data);
|
||||
$this->get_accepted_type($type, $this->data);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
@ -135,16 +151,32 @@ class Output {
|
||||
$type_map[$mime] = $type_class;
|
||||
}
|
||||
|
||||
foreach($accept as $type => $q)
|
||||
// Order type preference first by
|
||||
// input, then by accept flags
|
||||
foreach($type_map as $type => $obj)
|
||||
{
|
||||
if (array_key_exists($type, $type_map))
|
||||
if (\array_key_exists($type, $accept))
|
||||
{
|
||||
$accepted[$q] = $type;
|
||||
$q = $accept[$type];
|
||||
|
||||
if ($q >= 1)
|
||||
{
|
||||
$accepted[] = $type;
|
||||
}
|
||||
else
|
||||
{
|
||||
$accepted[$q] = $type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
krsort($accepted);
|
||||
// Default to html fow wildcard accept values
|
||||
if (empty($accepted) && \array_key_exists('*/*', $accept))
|
||||
{
|
||||
$accepted[1] = 'text/html';
|
||||
}
|
||||
|
||||
// Use the first output type to output the data
|
||||
$class = $type_map[current($accepted)];
|
||||
$this->type_wrapper = $classes[$class];
|
||||
|
||||
@ -178,4 +210,4 @@ class Output {
|
||||
}
|
||||
}
|
||||
}
|
||||
// End of core/Output.php
|
||||
// End of Core/Output.php
|
@ -7,7 +7,6 @@
|
||||
* but aiming to be as flexible as possible
|
||||
*
|
||||
* @author Timothy J. Warren
|
||||
* @package Sleepy/core
|
||||
*/
|
||||
|
||||
namespace Sleepy\Core;
|
||||
|
@ -7,7 +7,6 @@
|
||||
* but aiming to be as flexible as possible
|
||||
*
|
||||
* @author Timothy J. Warren
|
||||
* @package Sleepy/exceptions
|
||||
*/
|
||||
|
||||
namespace Sleepy\Exception;
|
||||
|
52
Sleepy/Traits/getSet.php
Normal file
52
Sleepy/Traits/getSet.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/**
|
||||
* Sleepy - a REST framework
|
||||
*
|
||||
*
|
||||
* A PHP Rest Framework valuing convention over configuration,
|
||||
* but aiming to be as flexible as possible
|
||||
*
|
||||
* @author Timothy J. Warren
|
||||
*/
|
||||
|
||||
namespace Sleepy\Traits;
|
||||
|
||||
/**
|
||||
* Trait to get rid of naive getter/setter boilerplate
|
||||
*/
|
||||
trait GetSet
|
||||
{
|
||||
|
||||
/**
|
||||
* Dynamically create getters/setters
|
||||
*
|
||||
* @param string $func
|
||||
* @param array $args
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($func, $args)
|
||||
{
|
||||
$type = substr($func, 0, 3);
|
||||
$val = strtolower(substr($func, 3));
|
||||
$valid_types = array(
|
||||
'get' => 'get',
|
||||
'set' => 'set'
|
||||
);
|
||||
|
||||
if ( ! property_exists($this, $val) || ! isset($valid_types[$type]))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Auto-magical getters and setters
|
||||
if ($type === 'get')
|
||||
{
|
||||
return $this->$val;
|
||||
}
|
||||
elseif ($type === 'set')
|
||||
{
|
||||
$this->$val = current($args);
|
||||
}
|
||||
}
|
||||
}
|
||||
// End of GetSet.php
|
@ -7,12 +7,11 @@
|
||||
* but aiming to be as flexible as possible
|
||||
*
|
||||
* @author Timothy J. Warren
|
||||
* @package Sleepy/types
|
||||
*/
|
||||
|
||||
namespace Sleepy\Type;
|
||||
|
||||
use Sleepy\Core\aType;
|
||||
use \Sleepy\Core\Abstracts\Type as aType;
|
||||
|
||||
/**
|
||||
* Class for HTML output
|
||||
@ -34,14 +33,7 @@ class HTML extends aType {
|
||||
*/
|
||||
public function serialize($data = NULL)
|
||||
{
|
||||
if ( ! is_null($data))
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
else
|
||||
{
|
||||
$data = $this->data;
|
||||
}
|
||||
$this->set_data($data);
|
||||
|
||||
if (is_string($data)) return $data;
|
||||
|
||||
@ -62,19 +54,4 @@ class HTML extends aType {
|
||||
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// ! Helper function
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Function to simplify type instantiation
|
||||
*
|
||||
* @param mixed $data
|
||||
* @return JSON
|
||||
*/
|
||||
function HTML($data = NULL)
|
||||
{
|
||||
return new JSON($data);
|
||||
}
|
||||
|
||||
// End of types/JSON.php
|
@ -7,12 +7,11 @@
|
||||
* but aiming to be as flexible as possible
|
||||
*
|
||||
* @author Timothy J. Warren
|
||||
* @package Sleepy/types
|
||||
*/
|
||||
|
||||
namespace Sleepy\Type;
|
||||
|
||||
use Sleepy\Core\aType;
|
||||
use \Sleepy\Core\Abstracts\Type as aType;
|
||||
|
||||
/**
|
||||
* Class for JSON output
|
||||
@ -34,15 +33,7 @@ class JSON extends aType {
|
||||
*/
|
||||
public function serialize($data = NULL)
|
||||
{
|
||||
if ( ! is_null($data))
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
else
|
||||
{
|
||||
$data = $this->data;
|
||||
}
|
||||
|
||||
$this->set_data($data);
|
||||
return json_encode($data, JSON_PRETTY_PRINT);
|
||||
}
|
||||
|
||||
@ -59,19 +50,4 @@ class JSON extends aType {
|
||||
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// ! Helper function
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Function to simplify type instantiation
|
||||
*
|
||||
* @param mixed $data
|
||||
* @return JSON
|
||||
*/
|
||||
function JSON($data = NULL)
|
||||
{
|
||||
return new JSON($data);
|
||||
}
|
||||
|
||||
// End of types/JSON.php
|
100
Sleepy/Type/XML.php
Normal file
100
Sleepy/Type/XML.php
Normal file
@ -0,0 +1,100 @@
|
||||
<?php
|
||||
/**
|
||||
* Sleepy - a REST framework
|
||||
*
|
||||
*
|
||||
* A PHP Rest Framework valuing convention over configuration,
|
||||
* but aiming to be as flexible as possible
|
||||
*
|
||||
* @author Timothy J. Warren
|
||||
*/
|
||||
|
||||
namespace Sleepy\Type;
|
||||
|
||||
use \Sleepy\Core\Abstracts\Type as aType;
|
||||
|
||||
/**
|
||||
* Implementation of XML data type
|
||||
*/
|
||||
class XML extends aType {
|
||||
|
||||
/**
|
||||
* The mime type for output
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $mime = 'application/xml';
|
||||
|
||||
/**
|
||||
* Convert php array/object to xml
|
||||
*
|
||||
* @param array|object $data
|
||||
* @return string
|
||||
*/
|
||||
public function serialize($data = NULL)
|
||||
{
|
||||
$this->set_data($data);
|
||||
|
||||
$xmlObject = new \SimpleXMLElement('<?xml version="1.0"?><root></root>');
|
||||
$this->array_to_xml($data, $xmlObject);
|
||||
|
||||
return $xmlObject->asXML();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert xml to php data
|
||||
*
|
||||
* @param string $string
|
||||
* @return object
|
||||
*/
|
||||
public function unserialize($string)
|
||||
{
|
||||
$xml = \simplexml_load_string($string);
|
||||
$json = json_encode($xml);
|
||||
$object = json_decode($json);
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively generate xml from an array or object
|
||||
*
|
||||
* @param array|object $array
|
||||
* @param \SimpleXMLElement $xmlObject
|
||||
*/
|
||||
private function array_to_xml($array, \SimpleXMLElement &$xmlObject)
|
||||
{
|
||||
foreach($array as $key => $val)
|
||||
{
|
||||
$key = $this->fix_xml_key($key);
|
||||
|
||||
if ( ! is_scalar($val))
|
||||
{
|
||||
$subnode = $xmlObject->addChild($key);
|
||||
$this->array_to_xml($val, $subnode);
|
||||
}
|
||||
else
|
||||
{
|
||||
$xmlObject->addChild($key, \htmlspecialchars($val, ENT_XML1, 'UTF-8'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an invalid xml key more valid
|
||||
*
|
||||
* @param string $key
|
||||
* @return string
|
||||
*/
|
||||
private function fix_xml_key($key)
|
||||
{
|
||||
if (is_numeric($key))
|
||||
{
|
||||
$key = "item_{$key}";
|
||||
}
|
||||
|
||||
return preg_replace('`[^a-zA-Z0-9_:]`', '_', $key);
|
||||
}
|
||||
|
||||
}
|
||||
// End of Type/XML.php
|
@ -7,13 +7,12 @@
|
||||
* but aiming to be as flexible as possible
|
||||
*
|
||||
* @author Timothy J. Warren
|
||||
* @package Sleepy/types
|
||||
*/
|
||||
|
||||
namespace Sleepy\types;
|
||||
namespace Sleepy\Type;
|
||||
|
||||
use Sleepy\core\aType;
|
||||
use Symfony\Component\Yaml as YML;
|
||||
use \Sleepy\Core\Abstracts\Type as aType;
|
||||
use Symfony\Component\Yaml\Yaml as YML;
|
||||
|
||||
/**
|
||||
* Class for YAML output
|
||||
@ -35,14 +34,7 @@ class YAML extends aType {
|
||||
*/
|
||||
public function serialize($data = null)
|
||||
{
|
||||
if ( ! is_null($data))
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
else
|
||||
{
|
||||
$data = $this->data;
|
||||
}
|
||||
$this->set_data($data);
|
||||
|
||||
// Yaml class doesn't support objects, cast them to arrays
|
||||
$data = (array) $data;
|
||||
|
40
Sleepy/autoload.php
Normal file
40
Sleepy/autoload.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/**
|
||||
* Sleepy - a REST framework
|
||||
*
|
||||
*
|
||||
* A PHP Rest Framework valuing convention over configuration,
|
||||
* but aiming to be as flexible as possible
|
||||
*
|
||||
* @author Timothy J. Warren
|
||||
* @package Sleepy
|
||||
*/
|
||||
|
||||
namespace Sleepy;
|
||||
|
||||
/**
|
||||
* Autoloader
|
||||
*/
|
||||
\spl_autoload_register(function($item) {
|
||||
$path_items = \explode('\\', \ltrim($item, '\\'));
|
||||
|
||||
// If the namespace is a straight mapping to the class, just load it
|
||||
$simple_path = \implode('/', $path_items);
|
||||
$file = BASEPATH . "{$simple_path}.php";
|
||||
|
||||
if (file_exists($file))
|
||||
{
|
||||
require_once($file);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the application folder
|
||||
$file = str_replace(SLEEPY_DIR, APP_DIR, $file);
|
||||
if (file_exists($file))
|
||||
{
|
||||
require_once($file);
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
// End of autoload.php
|
@ -10,7 +10,7 @@
|
||||
* @package Sleepy
|
||||
*/
|
||||
|
||||
$config = [
|
||||
return [
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// The default format of data to be sent. Can be overwritten in controllers
|
||||
|
@ -10,14 +10,13 @@
|
||||
* @package Sleepy
|
||||
*/
|
||||
|
||||
$routes = [
|
||||
return [
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// The index controller, called if not specified in the routes or url
|
||||
// --------------------------------------------------------------------------
|
||||
'default_controller' => 'index',
|
||||
|
||||
|
||||
];
|
||||
|
||||
// End of config/routes.php
|
26
application/config/type_class_map.php
Normal file
26
application/config/type_class_map.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/**
|
||||
* Sleepy - a REST framework
|
||||
*
|
||||
*
|
||||
* A PHP Rest Framework valuing convention over configuration,
|
||||
* but aiming to be as flexible as possible
|
||||
*
|
||||
* @author Timothy J. Warren
|
||||
* @package Sleepy
|
||||
*/
|
||||
|
||||
return [
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Map mime types to type classes
|
||||
// --------------------------------------------------------------------------
|
||||
'application/json' => 'JSON',
|
||||
'text/yaml' => 'YAML',
|
||||
'application/yaml' => 'YAML',
|
||||
'text/html' => 'HTML',
|
||||
'application/xhtml+xml' => 'HTML',
|
||||
'*/*' => 'HTML'
|
||||
];
|
||||
|
||||
// End of config/type_class_map.php
|
@ -9,6 +9,9 @@
|
||||
"phpunit/phpunit":"3.7.*"
|
||||
},
|
||||
"require": {
|
||||
"symfony/yaml": "2.4.*",
|
||||
"aura/router": "2.0.*@dev",
|
||||
"aura/di": "2.0.*@dev",
|
||||
"php": ">=5.4.0"
|
||||
}
|
||||
}
|
45
index.php
45
index.php
@ -10,41 +10,36 @@
|
||||
* @package Sleepy
|
||||
*/
|
||||
|
||||
namespace Sleepy;
|
||||
namespace Sleepy\Core;
|
||||
|
||||
// Include namespaces
|
||||
use Aura\Di\Container as DiContainer;
|
||||
use Aura\Di\Factory as DiFactory;
|
||||
use Aura\Router\RouterFactory;
|
||||
|
||||
define('BASEPATH', __DIR__ . '/');
|
||||
|
||||
define('SLEEPY_DIR', 'Sleepy');
|
||||
define('APP_DIR', 'application');
|
||||
define('APPPATH', __DIR__ . '/application/');
|
||||
|
||||
\spl_autoload_register(function($item) {
|
||||
$path_items = \explode('\\', \ltrim($item, '\\'));
|
||||
// Include 3rd party dependencies
|
||||
include BASEPATH . '/vendor/autoload.php';
|
||||
|
||||
// If the namespace is a straight mapping to the class, just load it
|
||||
$simple_path = \implode('/', $path_items);
|
||||
$file = BASEPATH . "{$simple_path}.php";
|
||||
if (file_exists($file))
|
||||
{
|
||||
require_once($file);
|
||||
return;
|
||||
}
|
||||
// Load the autoloader
|
||||
require BASEPATH . SLEEPY_DIR . '/autoload.php';
|
||||
|
||||
// Check the application folder
|
||||
$file = str_replace("Sleepy", 'application', $file);
|
||||
if (file_exists($file))
|
||||
{
|
||||
require_once($file);
|
||||
return;
|
||||
}
|
||||
});
|
||||
$di = new DiContainer(new DiFactory());
|
||||
$di->set('config', new Config());
|
||||
$di->set('input', new Input());
|
||||
$di->set('output', new Output($di->get('config'), $di->get('input')));
|
||||
|
||||
$i = new \Sleepy\Core\Input();
|
||||
$o = new \Sleepy\Core\Output($i);
|
||||
$browser = \get_browser(NULL);
|
||||
$browser->browser_name_regex = utf8_encode($browser->browser_name_regex);
|
||||
$o->set_data(['json','html'], [
|
||||
$browser->browser_name_regex = \utf8_encode($browser->browser_name_regex);
|
||||
$di->get('output')->set_data(['json','yaml','html'], [
|
||||
'$_SERVER' => $i->server(),
|
||||
'$_GET' => $i->get(),
|
||||
'$_POST' => $i->post(),
|
||||
'$_PUT' => $i->put(),
|
||||
'$_DELETE' => $i->delete(),
|
||||
'$_ENV' => $i->env(),
|
||||
'$_COOKIE' => $i->cookie(),
|
||||
'browser' => $browser,
|
||||
|
@ -1,27 +1,18 @@
|
||||
<?php
|
||||
|
||||
define('BASEPATH', realpath('../Sleepy/').'/');
|
||||
define('SPATH', realpath('../').'/');
|
||||
// Use the same autoloader as the app for consistency
|
||||
define('BASEPATH', '../');
|
||||
define('SLEEPY_DIR', 'Sleepy');
|
||||
define('APP_DIR', 'application');
|
||||
define('APPPATH', BASEPATH . 'application/');
|
||||
include BASEPATH . '/vendor/autoload.php';
|
||||
require BASEPATH . SLEEPY_DIR . '/autoload.php';
|
||||
|
||||
/**
|
||||
* Autoloader for Sleepy
|
||||
* Base testcase class
|
||||
*/
|
||||
\spl_autoload_register(function($item) {
|
||||
$path_items = \explode('\\', \ltrim($item, '\\'));
|
||||
|
||||
// If the namespace is a straight mapping to the class, just load it
|
||||
$simple_path = \implode('/', $path_items);
|
||||
$file = SPATH . "{$simple_path}.php";
|
||||
if (file_exists($file))
|
||||
{
|
||||
require_once($file);
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
class Sleepy_TestCase extends PHPUnit_Framework_TestCase {
|
||||
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
if ( ! isset($_SERVER['REQUEST_METHOD']))
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
require_once(BASEPATH . 'core/Input.php');
|
||||
|
||||
class InputTest extends Sleepy_TestCase {
|
||||
|
||||
public function setUp()
|
||||
@ -32,7 +30,7 @@ class InputTest extends Sleepy_TestCase {
|
||||
'tisket' => 'tasket'
|
||||
];
|
||||
|
||||
$this->input = new Sleepy\core\Input();
|
||||
$this->input = new Sleepy\Core\Input();
|
||||
}
|
||||
|
||||
public function dataTestHeader()
|
||||
@ -41,7 +39,7 @@ class InputTest extends Sleepy_TestCase {
|
||||
'all' => [
|
||||
'index' => NULL,
|
||||
'expected' => [
|
||||
'user_agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36 OPR/18.0.1284.49',
|
||||
'user-agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36 OPR/18.0.1284.49',
|
||||
'accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
||||
'cookie' => 'thp_tcms_session_id=9h4nvk15tjjegbeg8uvejncc9blkd81m',
|
||||
'host' => 'www.example.com',
|
||||
@ -65,7 +63,7 @@ class InputTest extends Sleepy_TestCase {
|
||||
'all' => [
|
||||
'index' => NULL,
|
||||
'expected' => [
|
||||
'user_agent' => [
|
||||
'user-agent' => [
|
||||
'versions' => [
|
||||
'Mozilla' => '5.0',
|
||||
'AppleWebKit' => '537.36',
|
||||
@ -80,10 +78,10 @@ class InputTest extends Sleepy_TestCase {
|
||||
'misc' => 'KHTML, like Gecko'
|
||||
],
|
||||
'accept' => [
|
||||
'text/html',
|
||||
'application/xhtml+xml',
|
||||
['application/xml', 'q=0.9'],
|
||||
['*/*', 'q=0.8']
|
||||
'0.8' => '*/*',
|
||||
'0.9' => 'application/xml',
|
||||
1 => 'application/xhtml+xml',
|
||||
2 => 'text/html'
|
||||
],
|
||||
'cookie' => [
|
||||
'thp_tcms_session_id' => '9h4nvk15tjjegbeg8uvejncc9blkd81m'
|
||||
@ -185,5 +183,15 @@ class InputTest extends Sleepy_TestCase {
|
||||
$result = $this->input->get($index);
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
public function testBadVar()
|
||||
{
|
||||
try {
|
||||
$foo = $this->input->applesauce();
|
||||
}
|
||||
catch (DomainException $e) {
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
// End of InputTest.php
|
28
tests/Core/OutputTest.php
Normal file
28
tests/Core/OutputTest.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
use Sleepy\Core\Input;
|
||||
use Sleepy\Core\Config;
|
||||
use Sleepy\Core\Output;
|
||||
|
||||
class OutputTest extends Sleepy_Testcase {
|
||||
|
||||
protected $output;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$c = new Config();
|
||||
$i = new Input();
|
||||
|
||||
$this->output = new Output($c, $i);
|
||||
}
|
||||
|
||||
public function testGetAcceptedType()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
// End of OutputTest.php
|
@ -1,17 +1,19 @@
|
||||
<?php
|
||||
|
||||
require_once(BASEPATH . 'core/iType.php');
|
||||
require_once(BASEPATH . 'core/aType.php');
|
||||
|
||||
use Sleepy\core\iType;
|
||||
use Sleepy\core\aType;
|
||||
use Sleepy\Core\Interfaces\Type as iType;
|
||||
use Sleepy\Core\Abstracts\Type as aType;
|
||||
|
||||
class aTypeTest extends Sleepy_TestCase {
|
||||
|
||||
public function testSanity()
|
||||
{
|
||||
$this->assertEquals(['Sleepy\\core\\iType' => 'Sleepy\\core\\iType'], class_implements('Sleepy\\core\\aType'));
|
||||
$this->assertEquals(
|
||||
['Sleepy\\Core\\Interfaces\\Type' => 'Sleepy\\Core\\Interfaces\\Type'],
|
||||
class_implements('Sleepy\\Core\\Abstracts\\Type')
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
// End of aTypeTest.php
|
@ -1,12 +1,6 @@
|
||||
<?php
|
||||
|
||||
require_once(BASEPATH . 'core/iType.php');
|
||||
require_once(BASEPATH . 'core/aType.php');
|
||||
require_once(BASEPATH . 'types/JSON.php');
|
||||
|
||||
use Sleepy\core;
|
||||
use Sleepy\types\JSON;
|
||||
use Sleepy\execeptions;
|
||||
use Sleepy\Type\JSON;
|
||||
|
||||
class MockJSON extends JSON {
|
||||
|
||||
@ -16,26 +10,31 @@ class MockJSON extends JSON {
|
||||
class JSONTest extends Sleepy_Testcase {
|
||||
|
||||
public function setUp() {
|
||||
$this->JSON = new JSON([]);
|
||||
$this->JSON = new JSON(['foo'=>'bar']);
|
||||
}
|
||||
|
||||
public function testSanity() {
|
||||
$this->assertTrue(is_a($this->JSON, 'Sleepy\\types\\JSON'));
|
||||
$this->assertTrue(is_a($this->JSON, 'Sleepy\\core\\aType'));
|
||||
$this->assertEquals(['Sleepy\\core\\iType' => 'Sleepy\\core\\iType'], class_implements('Sleepy\\types\\JSON'));
|
||||
$this->assertTrue(is_a($this->JSON, 'Sleepy\\Type\\JSON'));
|
||||
$this->assertTrue(is_a($this->JSON, 'Sleepy\\Core\\Abstracts\\Type'));
|
||||
$this->assertEquals(
|
||||
['Sleepy\\Core\\Interfaces\\Type' => 'Sleepy\\Core\\Interfaces\\Type'],
|
||||
class_implements('Sleepy\\Type\\JSON')
|
||||
);
|
||||
}
|
||||
|
||||
public function testFunction()
|
||||
|
||||
|
||||
public function testNIE() {
|
||||
try {
|
||||
$json = new MockJSON([]);
|
||||
}
|
||||
catch (Sleepy\exceptions\NotImplementedException $e) {
|
||||
catch (Sleepy\Exception\NotImplementedException $e) {
|
||||
$this->assertTrue(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
public function testGetMime()
|
||||
{
|
||||
$mime = $this->JSON->get_mime();
|
||||
$this->assertEquals('application/json', $mime);
|
||||
}
|
||||
}
|
||||
// End of JSONTest
|
62
tests/Type/XMLTest.php
Normal file
62
tests/Type/XMLTest.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
use Sleepy\Type\XML;
|
||||
|
||||
class MockXML extends XML {
|
||||
|
||||
protected $mime = '';
|
||||
}
|
||||
|
||||
class XMLTest extends Sleepy_Testcase {
|
||||
|
||||
public function setUp() {
|
||||
$test_array = [
|
||||
'foo' => 'bar',
|
||||
'baz' => [
|
||||
0 => ['x' => 'y']
|
||||
]
|
||||
];
|
||||
|
||||
$this->XML = new XML($test_array);
|
||||
}
|
||||
|
||||
public function testSanity() {
|
||||
$this->assertTrue(is_a($this->XML, 'Sleepy\\Type\\XML'));
|
||||
$this->assertTrue(is_a($this->XML, 'Sleepy\\Core\\Abstracts\\Type'));
|
||||
$this->assertEquals(
|
||||
['Sleepy\\Core\\Interfaces\\Type' => 'Sleepy\\Core\\Interfaces\\Type'],
|
||||
class_implements('Sleepy\\Type\\XML')
|
||||
);
|
||||
}
|
||||
|
||||
public function testNIE() {
|
||||
try {
|
||||
$xml = new MockXML([]);
|
||||
}
|
||||
catch (Sleepy\Exception\NotImplementedException $e) {
|
||||
$this->assertTrue(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
public function testSerialize()
|
||||
{
|
||||
$xml = $this->XML->serialize();
|
||||
$xml_tostring = $this->XML->__toString();
|
||||
$expected = '<?xml version="1.0"?>' .
|
||||
"\n<root><foo>bar</foo><baz><item_0><x>y</x></item_0></baz></root>\n";
|
||||
|
||||
$this->assertEquals($expected, $xml);
|
||||
$this->assertEquals($xml, $xml_tostring);
|
||||
}
|
||||
|
||||
public function testUnSerialize()
|
||||
{
|
||||
$object = $this->XML->unserialize('<?xml version="1.0"?>' . "\n<root><foo>bar</foo></root>\n");
|
||||
|
||||
$expected = (object) ['foo' => 'bar'];
|
||||
|
||||
$this->assertEquals($expected, $object);
|
||||
}
|
||||
|
||||
}
|
||||
// End of XMLTest
|
@ -11,12 +11,16 @@
|
||||
stopOnSkipped="false">
|
||||
<testsuites>
|
||||
<testsuite name="Sleepy Core Test Suite">
|
||||
<directory suffix="Test.php">./core</directory>
|
||||
<directory suffix="Test.php">./exceptions</directory>
|
||||
<directory suffix="Test.php">./types</directory>
|
||||
<directory suffix="Test.php">Core</directory>
|
||||
<directory suffix="Test.php">Exception</directory>
|
||||
<directory suffix="Test.php">Type</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory>../../sleepy/Sleepy</directory>
|
||||
<directory>../../sleepy/application</directory>
|
||||
</whitelist>
|
||||
<blacklist>
|
||||
<directory suffix=".php">PEAR_INSTALL_DIR</directory>
|
||||
<directory suffix=".php">PHP_LIBDIR</directory>
|
||||
|
Reference in New Issue
Block a user