Version 5.1 - All the GraphQL #32

Closed
timw4mail wants to merge 1160 commits from develop into master
58 changed files with 282 additions and 3350 deletions
Showing only changes of commit 3335093e87 - Show all commits

278
RoboFile.php Normal file
View File

@ -0,0 +1,278 @@
<?php
if ( ! function_exists('glob_recursive'))
{
// Does not support flag GLOB_BRACE
function glob_recursive($pattern, $flags = 0)
{
$files = glob($pattern, $flags);
foreach (glob(dirname($pattern).'/*', GLOB_ONLYDIR|GLOB_NOSORT) as $dir)
{
$files = array_merge($files, glob_recursive($dir.'/'.basename($pattern), $flags));
}
return $files;
}
}
/**
* This is project's console commands configuration for Robo task runner.
*
* @see http://robo.li/
*/
class RoboFile extends \Robo\Tasks
{
protected $taskDirs = [
'build/api',
'build/coverage',
'build/logs',
'build/pdepend',
'build/phpdox',
];
/**
* Do static analysis tasks
*/
public function analyze()
{
$this->prepare();
$this->lint();
$this->phploc(TRUE);
$this->dependencyReport();
$this->phpcpdReport();
}
/**
* Run all tests, generate coverage, generate docs, generate code statistics
*/
public function build()
{
$this->analyze();
$this->coverage();
$this->docs();
}
/**
* Cleanup temporary files
*/
public function clean()
{
$cleanFiles = [
'build/humbug.json',
'build/humbug-log.txt',
];
array_map(function ($file) {
@unlink($file);
}, $cleanFiles);
$this->_cleanDir($this->taskDirs);
$this->_deleteDir($this->taskDirs);
}
/**
* Run unit tests and generate coverage reports
*/
public function coverage()
{
$this->taskPhpUnit()
->configFile('build/phpunit.xml')
->printed(true)
->run();
}
/**
* Generate documentation with phpdox
*/
public function docs()
{
$cmd_parts = [
'cd build',
'../vendor/bin/phpdox',
'cd ..'
];
$this->_run($cmd_parts, ' && ');
}
/**
* Verify that source files are valid
*/
public function lint()
{
$files = $this->getAllSourceFiles();
$chunks = array_chunk($files, 6);
$collection = $this->collection();
foreach($chunks as $chunk)
{
$this->parallelLint($collection, $chunk);
}
$collection->run();
}
/**
* Run mutation tests with humbug
*
* @param bool $stats - if true, generates stats rather than running mutation tests
*/
public function mutate($stats = FALSE)
{
$test_parts = [
'vendor/bin/humbug'
];
$stat_parts = [
'vendor/bin/humbug',
'--skip-killed=yes',
'-v',
'./build/humbug.json'
];
$cmd_parts = ($stats) ? $stat_parts : $test_parts;
$this->_run($cmd_parts);
}
/**
* Run the phploc tool
*
* @param bool $report - if true, generates reports instead of direct output
*/
public function phploc($report = FALSE)
{
// Command for generating reports
$report_cmd_parts = [
'vendor/bin/phploc',
'--log-csv=build/logs/phploc.csv',
'--log-xml=build/logs/phploc.xml',
'src',
'tests'
];
// Command for generating direct output
$normal_cmd_parts = [
'vendor/bin/phploc',
'--count-tests',
'src',
'tests'
];
$cmd_parts = ($report) ? $report_cmd_parts : $normal_cmd_parts;
$this->_run($cmd_parts);
}
/**
* Create temporary directories
*/
public function prepare()
{
$this->clean();
array_map([$this, '_mkdir'], $this->taskDirs);
}
/**
* Lint php files and run unit tests
*/
public function test()
{
$this->lint();
$this->taskPHPUnit()
->configFile('phpunit.xml')
->printed(true)
->run();
}
/**
* Watches for file updates, and automatically runs appropriate actions
*/
public function watch()
{
$this->taskWatch()
->monitor('composer.json', function() {
$this->taskComposerUpdate()->run();
})
->monitor('src', function () {
$this->taskExec('test')->run();
})->run();
}
/**
* Create pdepend reports
*/
protected function dependencyReport()
{
$cmd_parts = [
'vendor/bin/pdepend',
'--jdepend-xml=build/logs/jdepend.xml',
'--jdepend-chart=build/pdepend/dependencies.svg',
'--overview-pyramid=build/pdepend/overview-pyramid.svg',
'src'
];
$this->_run($cmd_parts);
}
/**
* Get the total list of source files, including tests
*
* @return array
*/
protected function getAllSourceFiles()
{
$files = array_merge(
glob_recursive('build/*.php'),
glob_recursive('src/*.php'),
glob_recursive('tests/*.php'),
glob('*.php')
);
sort($files);
return $files;
}
/**
* Run php's linter in one parallel task for the passed chunk
*
* @param Collection $collection
* @param array $chunk
*/
protected function parallelLint($collection, array $chunk)
{
$task = $this->taskParallelExec();
foreach($chunk as $file)
{
$task = $task->process("php -l {$file}");
}
$collection->add($task);
}
/**
* Generate copy paste detector report
*/
protected function phpcpdReport()
{
$cmd_parts = [
'vendor/bin/phpcpd',
'--log-pmd build/logs/pmd-cpd.xml',
'src'
];
$this->_run($cmd_parts);
}
/**
* Short cut for joining an array of command arguments
* and then running it
*
* @param array $cmd_parts - command arguments
* @param string $join_on - what to join the command arguments with
*/
protected function _run(array $cmd_parts, $join_on = ' ')
{
$this->_exec(implode($join_on, $cmd_parts));
}
}

View File

@ -1,10 +0,0 @@
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/

View File

@ -8,14 +8,10 @@
>
<filter>
<whitelist>
<directory suffix=".php">../src/Aviat/Ion</directory>
<directory suffix=".php">../src/Aviat/AnimeClient</directory>
</whitelist>
</filter>
<testsuites>
<testsuite name="Ion">
<directory>../tests/Ion</directory>
</testsuite>
<testsuite name="AnimeClient">
<directory>../tests/AnimeClient</directory>
</testsuite>

View File

@ -7,10 +7,6 @@ $animeclient_file_patterns = [
'src/Aviat/AnimeClient/*.php'
];
$ion_file_patterns = [
'src/Aviat/Ion/*.php'
];
if ( ! function_exists('glob_recursive'))
{
// Does not support flag GLOB_BRACE
@ -80,10 +76,4 @@ $loose_files = [
];
replace_files($loose_files, '/animeclient_header_comment.txt');
foreach ($ion_file_patterns as $glob)
{
$files = glob_recursive($glob);
replace_files($files, '/ion_header_comment.txt');
}
echo "Successfully updated headers \n";

View File

@ -7,13 +7,10 @@
"aura/html": "2.*",
"aura/router": "3.*",
"aura/session": "2.*",
"aviat4ion/query": "2.5.*",
"container-interop/container-interop": "1.*",
"danielstjules/stringy": "~2.1",
"aviat/ion": "dev-master",
"filp/whoops": "2.0.*",
"guzzlehttp/guzzle": "6.*",
"monolog/monolog": "1.*",
"predis/predis": "1.1.*",
"psr/http-message": "~1.0",
"psr/log": "~1.0",
"yosymfony/toml": "0.3.*",
@ -21,7 +18,6 @@
"maximebf/consolekit": "^1.0"
},
"require-dev": {
"codeclimate/php-test-reporter": "dev-master",
"pdepend/pdepend": "^2.2",
"sebastian/phpcpd": "^2.0",
"theseer/phpdox": "0.8.1.1",
@ -29,6 +25,8 @@
"phpmd/phpmd": "^2.4",
"phpunit/phpunit": "^5.4",
"robmorgan/phinx": "^0.6.4",
"humbug/humbug": "~1.0@dev"
"humbug/humbug": "~1.0@dev",
"consolidation/robo": "~1.0@dev",
"henrikbjorn/lurker": "^1.1.0"
}
}

View File

@ -7,14 +7,10 @@
>
<filter>
<whitelist>
<directory suffix=".php">src/Aviat/Ion</directory>
<directory suffix=".php">src/Aviat/AnimeClient</directory>
</whitelist>
</filter>
<testsuites>
<testsuite name="Ion">
<directory>tests/Ion</directory>
</testsuite>
<testsuite name="AnimeClient">
<directory>tests/AnimeClient</directory>
</testsuite>

View File

@ -1,34 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion;
use Aviat\Ion\Type\ArrayType;
/**
* Wrapper to shortcut creating ArrayType objects
*/
trait ArrayWrapper {
/**
* Convenience method for wrapping an array
* with the array type class
*
* @param array $arr
* @return ArrayType
*/
public function arr(array $arr)
{
return new ArrayType($arr);
}
}
// End of ArrayWrapper.php

View File

@ -1,48 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion\Cache;
/**
* Interface for retrieving values from cache
*/
interface CacheInterface {
/**
* Retrieve a cached value if it exists, otherwise, get the value
* from the passed arguments
*
* @param object $object - object to retrieve fresh value from
* @param string $method - method name to call
* @param [array] $args - the arguments to pass to the retrieval method
* @return mixed - the cached or fresh data
*/
public function get($object, $method, array $args=[]);
/**
* Retrieve a fresh value, and update the cache
*
* @param object $object - object to retrieve fresh value from
* @param string $method - method name to call
* @param [array] $args - the arguments to pass to the retrieval method
* @return mixed - the fresh data
*/
public function getFresh($object, $method, array $args=[]);
/**
* Clear the entire cache
*
* @return void
*/
public function purge();
}
// End of CacheInterface.php

View File

@ -1,117 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion\Cache;
use Aviat\Ion\ConfigInterface;
use Aviat\Ion\Cache\Driver\DriverInterface;
/**
* Class proxying cached and fresh values from the selected cache driver
*/
class CacheManager implements CacheInterface {
/**
* @var DriverInterface
*/
protected $driver;
/**
* Retrieve the appropriate driver from the container
*
* @param ConfigInterface $config The configuration management class
*/
public function __construct(ConfigInterface $config)
{
$driverConf = $config->get('cache_driver');
if (empty($driverConf))
{
$driverConf = 'NullDriver';
}
$driverClass = __NAMESPACE__ . "\\Driver\\{$driverConf}";
$driver = new $driverClass($config);
$this->driver = $driver;
}
/**
* Retrieve a cached value if it exists, otherwise, get the value
* from the passed arguments
*
* @param object $object - object to retrieve fresh value from
* @param string $method - method name to call
* @param [array] $args - the arguments to pass to the retrieval method
* @return mixed - the cached or fresh data
*/
public function get($object, $method, array $args=[])
{
$hash = $this->generateHashForMethod($object, $method, $args);
$data = $this->driver->get($hash);
if (empty($data))
{
$data = call_user_func_array([$object, $method], $args);
$this->driver->set($hash, $data);
}
return $data;
}
/**
* Retrieve a fresh value from the method, and update the cache
* @param object $object - object to retrieve fresh value from
* @param string $method - method name to call
* @param [array] $args - the arguments to pass to the retrieval method
* @return mixed - the fresh data
*/
public function getFresh($object, $method, array $args=[])
{
$hash = $this->generateHashForMethod($object, $method, $args);
$data = call_user_func_array([$object, $method], $args);
$this->driver->set($hash, $data);
return $data;
}
/**
* Clear the entire cache
*
* @return void
*/
public function purge()
{
$this->driver->invalidateAll();
}
/**
* Generate a hash as a cache key from the current method call
*
* @param object $object
* @param string $method
* @param array $args
* @return string
*/
protected function generateHashForMethod($object, $method, array $args)
{
$classname = get_class($object);
$keyObj = [
'class' => $classname,
'method' => $method,
'args' => $args,
];
$hash = sha1(json_encode($keyObj));
return $hash;
}
}
// End of CacheManager.php

View File

@ -1,51 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion\Cache\Driver;
/**
* Interface for cache drivers
*/
interface DriverInterface {
/**
* Retreive a value from the cache backend
*
* @param string $key
* @return mixed
*/
public function get($key);
/**
* Set a cached value
*
* @param string $key
* @param mixed $value
* @return DriverInterface
*/
public function set($key, $value);
/**
* Invalidate a cached value
*
* @param string $key
* @return DriverInterface
*/
public function invalidate($key);
/**
* Clear the contents of the cache
*
* @return void
*/
public function invalidateAll();
}
// End of DriverInterface.php

View File

@ -1,62 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion\Cache\Driver;
use Aviat\Ion\Json;
use Aviat\Ion\JsonException;
/**
* Abstract base for Cache drivers to share common functionality
*/
trait DriverTrait {
/**
* Key prefix for key / value cache stores
*/
protected static $CACHE_KEY_PREFIX = "hbac:cache:";
/**
* Set key prefix for cache drivers that have global keys
*
* @param string $key - the raw key name
* @return string - the prefixed key name
*/
protected function prefix($key)
{
return static::$CACHE_KEY_PREFIX . $key;
}
/**
* Converts data to cache to a string representation for storage in a cache
*
* @param mixed $data - data to store in the cache backend
* @return string
*/
protected function serialize($data)
{
return Json::encode($data);
}
/**
* Convert serialized data from cache backend to native types
*
* @param string $data - data from cache backend
* @return mixed
* @throws JsonException
*/
protected function unserialize($data)
{
return Json::decode($data);
}
}
// End of DriverTrait.php

View File

@ -1,74 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion\Cache\Driver;
use Aviat\Ion\ConfigInterface;
/**
* The Driver for no real cache
*/
class NullDriver implements DriverInterface {
/**
* 'Cache' for Null data store
*/
protected $data = [];
/**
* Retrieve a value from the cache backend
*
* @param string $key
* @return mixed
*/
public function get($key)
{
return (array_key_exists($key, $this->data))
? $this->data[$key]
: NULL;
}
/**
* Set a cached value
*
* @param string $key
* @param mixed $value
* @return DriverInterface
*/
public function set($key, $value)
{
$this->data[$key] = $value;
return $this;
}
/**
* Invalidate a cached value
*
* @param string $key
* @return DriverInterface
*/
public function invalidate($key)
{
unset($this->data[$key]);
return $this;
}
/**
* Clear the contents of the cache
*
* @return void
*/
public function invalidateAll()
{
$this->data = [];
}
}
// End of NullDriver.php

View File

@ -1,117 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion\Cache\Driver;
use Aviat\Ion\ConfigInterface;
use Predis\Client;
/**
* Cache Driver for a Redis backend
*/
class RedisDriver implements DriverInterface {
use DriverTrait;
/**
* THe Predis library instance
*
* @var Client
*/
protected $redis;
/**
* Create the Redis cache driver
*
* @param ConfigInterface $config The configuration management class
*/
public function __construct(ConfigInterface $config)
{
$redisConfig = $config->get('redis');
// If you don't have a redis password set, and you attempt to send an
// empty string, Redis will think you want to authenticate with a password
// that is an empty string. To work around this, empty string passwords
// are considered to be a lack of a password
if (array_key_exists('password', $redisConfig) && $redisConfig['password'] === '')
{
unset($redisConfig['password']);
}
$this->redis = new Client($redisConfig);
}
/**
* Disconnect from redis
*/
public function __destruct()
{
$this->redis = null;
}
/**
* Retrieve a value from the cache backend
*
* @param string $rawKey
* @return mixed
*/
public function get($rawKey)
{
$key = $this->prefix($rawKey);
$serializedData = $this->redis->get($key);
return $this->unserialize($serializedData);
}
/**
* Set a cached value
*
* @param string $rawKey
* @param mixed $value
* @return DriverInterface
*/
public function set($rawKey, $value)
{
$key = $this->prefix($rawKey);
$serializedData = $this->serialize($value);
$this->redis->set($key, $serializedData);
return $this;
}
/**
* Invalidate a cached value
*
* @param string $rawKey
* @return DriverInterface
*/
public function invalidate($rawKey)
{
$key = $this->prefix($rawKey);
$this->redis->del($key);
return $this;
}
/**
* Clear the contents of the cache
*
* @return void
*/
public function invalidateAll()
{
$this->redis->flushdb();
}
}
// End of RedisDriver.php

View File

@ -1,119 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion\Cache\Driver;
use Aviat\Ion\ConfigInterface;
use Aviat\Ion\Exception\ConfigException;
use Aviat\Ion\Model\DB;
/**
* Driver for caching via a traditional SQL database
*/
class SQLDriver extends DB implements DriverInterface {
use DriverTrait;
/**
* The query builder object
* @var object $db
*/
protected $db;
/**
* Create the driver object
*
* @param ConfigInterface $config
* @throws ConfigException
*/
public function __construct(ConfigInterface $config)
{
parent::__construct($config);
if ( ! array_key_exists('cache', $this->db_config))
{
throw new ConfigException("Missing '[cache]' section in database config.");
}
$this->db = \Query($this->db_config['cache']);
}
/**
* Retrieve a value from the cache backend
*
* @param string $key
* @return mixed
*/
public function get($key)
{
$query = $this->db->select('value')
->from('cache')
->where('key', $key)
->get();
$row = $query->fetch(\PDO::FETCH_ASSOC);
if (empty($row))
{
return NULL;
}
$serializedData = $row['value'];
return $this->unserialize($serializedData);
}
/**
* Set a cached value
*
* @param string $key
* @param mixed $value
* @return DriverInterface
*/
public function set($key, $value)
{
$serializedData = $this->serialize($value);
$this->db->set([
'key' => $key,
'value' => $serializedData,
]);
$this->db->insert('cache');
return $this;
}
/**
* Invalidate a cached value
*
* @param string $key
* @return DriverInterface
*/
public function invalidate($key)
{
$this->db->where('key', $key)
->delete('cache');
return $this;
}
/**
* Clear the contents of the cache
*
* @return void
*/
public function invalidateAll()
{
$this->db->truncate('cache');
}
}
// End of SQLDriver.php

View File

@ -1,106 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion;
use Aviat\Ion\Exception\ConfigException;
use InvalidArgumentException;
/**
* Wrapper for configuration values
*/
class Config implements ConfigInterface {
use ArrayWrapper;
/**
* Config object
*
* @var \Aviat\Ion\Type\ArrayType
*/
protected $map = [];
/**
* Constructor
*
* @param array $config_array
*/
public function __construct(array $config_array = [])
{
$this->map = $this->arr($config_array);
}
/**
* Get a config value
*
* @param array|string $key
* @return mixed
* @throws ConfigException
*/
public function get($key)
{
if (is_array($key))
{
return $this->map->get_deep_key($key);
}
return $this->map->get($key);
}
/**
* Remove a config value
*
* @param string|array $key
* @return void
*/
public function delete($key)
{
if (is_array($key))
{
$this->map->set_deep_key($key, NULL);
}
else
{
$pos =& $this->map->get($key);
$pos = NULL;
}
}
/**
* Set a config value
*
* @param integer|string|array $key
* @param mixed $value
* @throws InvalidArgumentException
* @return Config
*/
public function set($key, $value)
{
if (is_array($key))
{
$this->map->set_deep_key($key, $value);
}
else if (is_scalar($key) && ! empty($key))
{
$this->map->set($key, $value);
}
else
{
throw new InvalidArgumentException("Key must be integer, string, or array, and cannot be empty");
}
return $this;
}
}
// End of config.php

View File

@ -1,41 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion;
interface ConfigInterface {
/**
* Get a config value
*
* @param array|string $key
* @return mixed
*/
public function get($key);
/**
* Set a config value
*
* @param integer|string|array $key
* @param mixed $value
* @throws \InvalidArgumentException
* @return ConfigInterface
*/
public function set($key, $value);
/**
* Remove a config value
*
* @param string|array $key
* @return void
*/
public function delete($key);
}

View File

@ -1,134 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion\Di;
use Psr\Log\LoggerInterface;
/**
* Dependency container
*/
class Container implements ContainerInterface {
/**
* Array with class instances
*
* @var array
*/
protected $container = [];
/**
* Map of logger instances
*
* @var array
*/
protected $loggers = [];
/**
* Constructor
*
* @param array $values (optional)
*/
public function __construct(array $values = [])
{
$this->container = $values;
$this->loggers = [];
}
/**
* Finds an entry of the container by its identifier and returns it.
*
* @param string $id Identifier of the entry to look for.
*
* @throws NotFoundException No entry was found for this identifier.
* @throws ContainerException Error while retrieving the entry.
*
* @return mixed Entry.
*/
public function get($id)
{
if ( ! is_string($id))
{
throw new Exception\ContainerException("Id must be a string");
}
if ($this->has($id))
{
return $this->container[$id];
}
throw new Exception\NotFoundException("Item '{$id}' does not exist in container.");
}
/**
* Add a value to the container
*
* @param string $id
* @param mixed $value
* @return ContainerInterface
*/
public function set($id, $value)
{
$this->container[$id] = $value;
return $this;
}
/**
* Returns true if the container can return an entry for the given identifier.
* Returns false otherwise.
*
* @param string $id Identifier of the entry to look for.
*
* @return boolean
*/
public function has($id)
{
return array_key_exists($id, $this->container);
}
/**
* Determine whether a logger channel is registered
* @param string $key The logger channel
* @return boolean
*/
public function hasLogger($key = 'default')
{
return array_key_exists($key, $this->loggers);
}
/**
* Add a logger to the Container
*
* @param LoggerInterface $logger
* @param string $key The logger 'channel'
* @return ContainerInterface
*/
public function setLogger(LoggerInterface $logger, $key = 'default')
{
$this->loggers[$key] = $logger;
return $this;
}
/**
* Retrieve a logger for the selected channel
*
* @param string $key The logger to retreive
* @return LoggerInterface|null
*/
public function getLogger($key = 'default')
{
return ($this->hasLogger($key))
? $this->loggers[$key]
: NULL;
}
}
// End of Container.php

View File

@ -1,49 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion\Di;
/**
* Trait implementation of ContainerAwareInterface
*/
trait ContainerAware {
/**
* Di Container
*
* @var ContainerInterface
*/
protected $container;
/**
* Set the container for the current object
*
* @param ContainerInterface $container
* @return $this
*/
public function setContainer(ContainerInterface $container)
{
$this->container = $container;
return $this;
}
/**
* Get the container object
*
* @return ContainerInterface
*/
public function getContainer()
{
return $this->container;
}
}
// End of ContainerAware.php

View File

@ -1,36 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion\Di;
/**
* Interface for a class that is aware of the Di Container
*/
interface ContainerAwareInterface {
/**
* Set the container for the current object
*
* @param ContainerInterface $container
* @return void
*/
public function setContainer(ContainerInterface $container);
/**
* Get the container object
*
* @return ContainerInterface
*/
public function getContainer();
}
// End of ContainerAwareInterface.php

View File

@ -1,47 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion\Di;
use Psr\Log\LoggerInterface;
/**
* Interface for the Dependency Injection Container
*/
interface ContainerInterface extends \Interop\Container\ContainerInterface {
/**
* Add a value to the container
*
* @param string $key
* @param mixed $value
* @return ContainerInterface
*/
public function set($key, $value);
/**
* Add a logger to the Container
*
* @param LoggerInterface $logger
* @param string $key The logger 'channel'
* @return Container
*/
public function setLogger(LoggerInterface $logger, $key = 'default');
/**
* Retrieve a logger for the selected channel
*
* @param string $key The logger to retreive
* @return LoggerInterface|null
*/
public function getLogger($key = 'default');
}

View File

@ -1,21 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion\Di\Exception;
/**
* Generic exception for Di Container
*/
class ContainerException extends \Exception implements \Interop\Container\Exception\ContainerException {
}
// End of ContainerException.php

View File

@ -1,22 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion\Di\Exception;
/**
* Exception for Di Container when trying to access a
* key that doesn't exist in the container
*/
class NotFoundException extends ContainerException implements \Interop\Container\Exception\NotFoundException {
}
// End of NotFoundException.php

View File

@ -1,49 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion;
use ReflectionClass;
/**
* Class emulating an enumeration type
*
* @method bool isValid(mixed $key)
* @method array getConstList()
*/
abstract class Enum {
use StaticInstance;
/**
* Return the list of constant values for the Enum
*
* @return array
*/
protected function getConstList()
{
$reflect = new ReflectionClass($this);
return $reflect->getConstants();
}
/**
* Verify that a constant value is valid
* @param mixed $key
* @return boolean
*/
protected function isValid($key)
{
$values = array_values($this->getConstList());
return in_array($key, $values);
}
}
// End of Enum.php

View File

@ -1,20 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion\Exception;
/**
* Exception for bad configuration
*/
class ConfigException extends \InvalidArgumentException {
}

View File

@ -1,129 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion;
use ReflectionClass;
use ReflectionMethod;
use ReflectionProperty;
use InvalidArgumentException;
use BadMethodCallException;
/**
* Friend class for testing
*/
class Friend {
/**
* Object to create a friend of
* @var object
*/
private $_friend_;
/**
* Reflection class of the object
* @var object
*/
private $_reflect_;
/**
* Create a friend object
*
* @param object $obj
*/
public function __construct($obj)
{
if ( ! is_object($obj))
{
throw new InvalidArgumentException("Friend must be an object");
}
$this->_friend_ = $obj;
$this->_reflect_ = new ReflectionClass($obj);
}
/**
* Retrieve a friend's property
*
* @param string $key
* @return mixed
*/
public function __get($key)
{
if ($this->_reflect_->hasProperty($key))
{
$property = $this->_get_property($key);
return $property->getValue($this->_friend_);
}
return NULL;
}
/**
* Set a friend's property
*
* @param string $key
* @param mixed $value
* @return void
*/
public function __set($key, $value)
{
if ($this->_reflect_->hasProperty($key))
{
$property = $this->_get_property($key);
$property->setValue($this->_friend_, $value);
}
}
/**
* Calls a protected or private method on the friend
*
* @param string $method
* @param array $args
* @return mixed
*/
public function __call($method, $args)
{
if ( ! $this->_reflect_->hasMethod($method))
{
throw new BadMethodCallException("Method '{$method}' does not exist");
}
$friendMethod = new ReflectionMethod($this->_friend_, $method);
$friendMethod->setAccessible(TRUE);
return $friendMethod->invokeArgs($this->_friend_, $args);
}
/**
* Iterates over parent classes to get a ReflectionProperty
*
* @codeCoverageIgnore
* @param string $name
* @return ReflectionProperty|null
*/
private function _get_property($name)
{
try
{
$property = $this->_reflect_->getProperty($name);
$property->setAccessible(TRUE);
return $property;
}
// Return NULL on any exception, so no further logic needed
// in the catch block
catch (\Exception $e)
{
return NULL;
}
}
}
// End of Friend.php

View File

@ -1,130 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion;
use Aviat\Ion\Type\StringType;
/**
* Helper class for json convenience methods
*/
class Json {
/**
* Encode data in json format
*
* @param mixed $data
* @param int $options
* @param int $depth
* @return string
*/
public static function encode($data, $options = 0, $depth = 512)
{
$json = json_encode($data, $options, $depth);
self::check_json_error();
return $json;
}
/**
* Encode data in json format and save to a file
*
* @param string $filename
* @param mixed $data
* @param int $json_options - Options to pass to json_encode
* @param int $file_options - Options to pass to file_get_contents
* @return int
*/
public static function encodeFile($filename, $data, $json_options = 0, $file_options = 0)
{
$json = self::encode($data, $json_options);
return file_put_contents($filename, $json, $file_options);
}
/**
* Decode data from json
*
* @param string $json
* @param bool $assoc
* @param int $depth
* @param int $options
* @return mixed
*/
public static function decode($json, $assoc = TRUE, $depth = 512, $options = 0)
{
// Don't try to decode null
if (empty($json))
{
return NULL;
}
// cast json to string so that streams from guzzle are correctly decoded
$data = json_decode((string) $json, $assoc, $depth, $options);
self::check_json_error();
return $data;
}
/**
* Decode json data loaded from the passed filename
*
* @param string $filename
* @param bool $assoc
* @param int $depth
* @param int $options
* @return mixed
*/
public static function decodeFile($filename, $assoc = TRUE, $depth = 512, $options = 0)
{
$json = file_get_contents($filename);
return self::decode($json, $assoc, $depth, $options);
}
/**
* Determines whether a string is valid json
*
* @param string $string
* @return boolean
*/
public static function isJson($string)
{
return StringType::create($string)->isJson();
}
/**
* Call the json error functions to check for errors encoding/decoding
*
* @throws JsonException
*/
protected static function check_json_error()
{
$constant_map = [
JSON_ERROR_NONE => 'JSON_ERROR_NONE',
JSON_ERROR_DEPTH => 'JSON_ERROR_DEPTH',
JSON_ERROR_STATE_MISMATCH => 'JSON_ERROR_STATE_MISMATCH',
JSON_ERROR_CTRL_CHAR => 'JSON_ERROR_CTRL_CHAR',
JSON_ERROR_SYNTAX => 'JSON_ERROR_SYNTAX',
JSON_ERROR_UTF8 => 'JSON_ERROR_UTF8',
JSON_ERROR_RECURSION => 'JSON_ERROR_RECURSION',
JSON_ERROR_INF_OR_NAN => 'JSON_ERROR_INF_OR_NAN',
JSON_ERROR_UNSUPPORTED_TYPE => 'JSON_ERROR_UNSUPPORTED_TYPE'
];
$error = json_last_error();
$message = json_last_error_msg();
if (\JSON_ERROR_NONE !== $error)
{
throw new JsonException("{$constant_map[$error]} - {$message}", $error);
}
}
}
// End of JSON.php

View File

@ -1,18 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion;
class JsonException extends \InvalidArgumentException {
}
// End of JsonException.php

View File

@ -1,21 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion;
/**
* Common base for all Models
*/
class Model {
use StringWrapper;
}
// End of Model.php

View File

@ -1,51 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion\Model;
use Aviat\Ion\ConfigInterface;
use Aviat\Ion\Model as BaseModel;
/**
* Base model for database interaction
*/
class DB extends BaseModel {
/**
* The query builder object
* @var object $db
*/
protected $db;
/**
* The config manager
* @var ConfigInterface
*/
protected $config;
/**
* The database connection information array
* @var array $db_config
*/
protected $db_config;
/**
* Constructor
*
* @param ConfigInterface $config
*/
public function __construct(ConfigInterface $config)
{
$this->config = $config;
$this->db_config = (array)$config->get('database');
}
}
// End of DB.php

View File

@ -1,63 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion;
/**
* Trait to allow calling a method statically,
* as well as with an instance
*/
trait StaticInstance {
/**
* Instance for 'faking' static methods
*
* @var object
*/
private static $instance = [];
/**
* Call methods protected to allow for
* static and instance calling
*
* @codeCoverageIgnore
* @param string $method
* @param array $args
* @retun mixed
*/
public function __call($method, $args)
{
if (method_exists($this, $method))
{
return call_user_func_array([$this, $method], $args);
}
}
/**
* Call non-static methods statically, so that
* an instance of the class isn't required
*
* @param string $method
* @param array $args
* @return mixed
*/
public static function __callStatic($method, $args)
{
$class = get_called_class();
if ( ! array_key_exists($class, self::$instance))
{
self::$instance[$class] = new $class();
}
return call_user_func_array([self::$instance[$class], $method], $args);
}
}
// End of StaticInstance.php

View File

@ -1,33 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion;
use Aviat\Ion\Type\StringType;
/**
* Trait to add convenience method for creating StringType objects
*/
trait StringWrapper {
/**
* Wrap the String in the Stringy class
*
* @param string $str
* @return StringType
*/
public function string($str)
{
return StringType::create($str);
}
}
// End of StringWrapper.php

View File

@ -1,42 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion\Transformer;
/**
* Base class for data trasformation
*/
abstract class AbstractTransformer implements TransformerInterface {
use \Aviat\Ion\StringWrapper;
/**
* Mutate the data structure
*
* @param array|object $item
* @return mixed
*/
abstract public function transform($item);
/**
* Transform a set of structures
*
* @param array|object $collection
* @return array
*/
public function transform_collection($collection)
{
$list = (array)$collection;
return array_map([$this, 'transform'], $list);
}
}
// End of AbstractTransformer.php

View File

@ -1,27 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion\Transformer;
/**
* Interface for data transformation classes
*/
interface TransformerInterface {
/**
* Mutate the data structure
*
* @param array|object $item
* @return mixed
*/
public function transform($item);
}

View File

@ -1,261 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion\Type;
/**
* Wrapper class for native array methods for convenience
*
* @method array chunk(int $size, bool $preserve_keys = FALSE)
* @method array pluck(mixed $column_key, mixed $index_key = NULL)
* @method array filter(callable $callback = NULL, int $flag = 0)
*/
class ArrayType {
/**
* The current array
*
* @var array
*/
protected $arr;
/**
* Map generated methods to their native implementations
*
* @var array
*/
protected $native_methods = [
'chunk' => 'array_chunk',
'pluck' => 'array_column',
'key_diff' => 'array_diff_key',
'diff' => 'array_diff',
'filter' => 'array_filter',
'flip' => 'array_flip',
'intersect' => 'array_intersect',
'keys' => 'array_keys',
'merge' => 'array_merge',
'pad' => 'array_pad',
'product' => 'array_product',
'random' => 'array_rand',
'reduce' => 'array_reduce',
'reverse' => 'array_reverse',
'sum' => 'array_sum',
'unique' => 'array_unique',
'values' => 'array_values',
];
/**
* Native methods that modify the passed in array
*
* @var array
*/
protected $native_in_place_methods = [
'shuffle' => 'shuffle',
'shift' => 'array_shift',
'unshift' => 'array_unshift',
'push' => 'array_push',
'pop' => 'array_pop',
];
/**
* Create an ArrayType wrapper class
*
* @param array $arr
*/
public function __construct(array &$arr)
{
$this->arr =& $arr;
}
/**
* Call one of the dynamically created methods
*
* @param string $method
* @param array $args
* @return mixed
* @throws \InvalidArgumentException
*/
public function __call($method, $args)
{
// Simple mapping for the majority of methods
if (array_key_exists($method, $this->native_methods))
{
$func = $this->native_methods[$method];
// Set the current array as the first argument of the method
array_unshift($args, $this->arr);
return call_user_func_array($func, $args);
}
// Mapping for in-place methods
if (array_key_exists($method, $this->native_in_place_methods))
{
$func = $this->native_in_place_methods[$method];
$func($this->arr);
return $this->arr;
}
throw new \InvalidArgumentException("Method '{$method}' does not exist");
}
/**
* Does the passed key exist in the current array?
*
* @param string $key
* @return bool
*/
public function has_key($key)
{
return array_key_exists($key, $this->arr);
}
/**
* Fill an array with the specified value
*
* @param int $start_index
* @param int $num
* @param mixed $value
* @return array
*/
public function fill($start_index, $num, $value)
{
return array_fill($start_index, $num, $value);
}
/**
* Call a callback on each item of the array
*
* @param callable $callback
* @return array
*/
public function map(callable $callback)
{
return array_map($callback, $this->arr);
}
/**
* Find an array key by its associated value
*
* @param mixed $value
* @param bool $strict
* @return false|integer|string
*/
public function search($value, $strict = FALSE)
{
return array_search($value, $this->arr, $strict);
}
/**
* Determine if the array has the passed value
*
* @param mixed $value
* @param bool $strict
* @return bool
*/
public function has($value, $strict = FALSE)
{
return in_array($value, $this->arr, $strict);
}
/**
* Return the array, or a key
*
* @param string|integer|null $key
* @return mixed
*/
public function &get($key = NULL)
{
$value = NULL;
if (is_null($key))
{
$value =& $this->arr;
}
else
{
if ($this->has_key($key))
{
$value =& $this->arr[$key];
}
}
return $value;
}
/**
* Set a key on the array
*
* @param mixed $key
* @param mixed $value
* @return ArrayType
*/
public function set($key, $value)
{
$this->arr[$key] = $value;
return $this;
}
/**
* Return a reference to the value of an arbitrary key on the array
*
* @param array $key
* @return mixed
*/
public function &get_deep_key(array $key)
{
$pos =& $this->arr;
foreach ($key as $level)
{
if (empty($pos) || ! is_array($pos))
{
// Directly returning a NULL value here will
// result in a reference error. This isn't
// excess code, just what's required for this
// unique situation.
$pos = NULL;
return $pos;
}
$pos =& $pos[$level];
}
return $pos;
}
/**
* Sets the value of an arbitrarily deep key in the array
* and returns the modified array
*
* @param array $key
* @param mixed $value
* @return array
*/
public function set_deep_key(array $key, $value)
{
$pos =& $this->arr;
// Iterate through the levels of the array,
// create the levels if they don't exist
foreach ($key as $level)
{
if ( ! is_array($pos) && empty($pos))
{
$pos = [];
$pos[$level] = [];
}
$pos =& $pos[$level];
}
$pos = $value;
return $this->arr;
}
}
// End of ArrayType.php

View File

@ -1,23 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion\Type;
use Stringy\Stringy;
/**
* Wrapper around Stringy
*/
class StringType extends Stringy {
}
// End of StringType.php

View File

@ -1,137 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion;
use Aviat\Ion\Di\ContainerInterface;
use Aviat\Ion\Type\StringType;
/**
* Base view response class
*/
abstract class View {
use Di\ContainerAware;
use StringWrapper;
/**
* HTTP response Object
*
* @var Zend\Diactoros\Response
*/
public $response;
/**
* Redirect response object
*
* @var Zend\Diactoros\RedirectResponse
*/
protected $redirectResponse;
/**
* Response mime type
*
* @var string
*/
protected $contentType = '';
/**
* String of response to be output
*
* @var StringType
*/
protected $output;
/**
* If the view has sent output via
* __toString or send method
*
* @var boolean
*/
protected $hasRendered = FALSE;
/**
* Constructor
*
* @param ContainerInterface $container
*/
public function __construct(ContainerInterface $container)
{
$this->setContainer($container);
$this->response = $container->get('response');
$this->redirectResponse = NULL;
}
/**
* Send output to client
*/
public function __destruct()
{
if ( ! $this->hasRendered)
{
$this->send();
}
}
/**
* Return rendered output
*
* @return string
*/
public function __toString()
{
$this->hasRendered = TRUE;
return $this->getOutput();
}
/**
* Set the output string
*
* @param string $string
* @return View
*/
public function setOutput($string)
{
$this->response->getBody()->write($string);
return $this;
}
/**
* Append additional output
*
* @param string $string
* @return View
*/
public function appendOutput($string)
{
return $this->setOutput($string);
}
/**
* Get the current output string
*
* @return string
*/
public function getOutput()
{
return $this->response->getBody()->__toString();
}
/**
* Send output to client
*
* @return void
*/
abstract public function send();
}
// End of View.php

View File

@ -1,69 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion\View;
use Aviat\Ion\Di\ContainerInterface;
/**
* View class for outputting HTML
*/
class HtmlView extends HttpView {
/**
* HTML generator/escaper helper
*
* @var Aura\Html\HelperLocator
*/
protected $helper;
/**
* Create the Html View
*
* @param ContainerInterface $container
*/
public function __construct(ContainerInterface $container)
{
parent::__construct($container);
$this->helper = $container->get('html-helper');
}
/**
* Response mime type
*
* @var string
*/
protected $contentType = 'text/html';
/**
* Render a basic html Template
*
* @param string $path
* @param array $data
* @return string
*/
public function render_template($path, $data)
{
$data['helper'] = $this->helper;
$data['escape'] = $this->helper->escape();
$data['container'] = $this->container;
ob_start();
extract($data);
include_once $path;
$buffer = ob_get_contents();
ob_end_clean();
return $buffer;
}
}
// End of HtmlView.php

View File

@ -1,91 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion\View;
use Zend\Diactoros\Response;
use Zend\Diactoros\Response\SapiEmitter;
use Aviat\Ion\View as BaseView;
/**
* Base view class for Http output
*/
class HttpView extends BaseView {
/**
* Do a redirect
*
* @codeCoverageIgnore
* @param string $url
* @param int $code
* @return void
*/
public function redirect($url, $code)
{
ob_start();
$message = $this->response->getReasonPhrase($code);
$this->setStatusCode($code);
$this->response->withHeader('Location', $url);
if (PHP_SAPI !== 'cli')
{
header("HTTP/1.1 ${code} ${message}");
header("Location: {$url}");
}
$this->hasRendered = TRUE;
ob_end_clean();
}
/**
* Set the status code of the request
*
* @param int $code
* @return HttpView
*/
public function setStatusCode($code)
{
$this->response = $this->response->withStatus($code)
->withProtocolVersion('1.1');
return $this;
}
/**
* Send output to client
*
* @return void
*/
public function send()
{
$this->hasRendered = TRUE;
$this->output();
}
/**
* Send the appropriate response
*
* @codeCoverageIgnore
* @return void
*/
protected function output()
{
$this->response->withHeader('Content-type', "{$this->contentType};charset=utf-8")
->withHeader('Content-Security-Policy', "script-src 'self'")
->withHeader('X-Content-Type-Options', 'nosniff')
->withHeader('X-XSS-Protection', '1;mode=block')
->withHeader('X-Frame-Options', 'SAMEORIGIN');
$sender = new SapiEmitter($this->response);
$sender->emit($this->response);
}
}

View File

@ -1,47 +0,0 @@
<?php
/**
* Ion
*
* Building blocks for web development
*
* @package Ion
* @author Timothy J. Warren
* @copyright Copyright (c) 2015 - 2016
* @license MIT
*/
namespace Aviat\Ion\View;
use Aviat\Ion\Json;
use Aviat\Ion\View\HttpView;
use Aviat\Ion\View as BaseView;
/**
* View class to serialize Json
*/
class JsonView extends HttpView {
/**
* Response mime type
*
* @var string
*/
protected $contentType = 'application/json';
/**
* Set the output string
*
* @param mixed $string
* @return BaseView
*/
public function setOutput($string)
{
if ( ! is_string($string))
{
$string = Json::encode($string);
}
return parent::setOutput($string);
}
}
// End of JsonView.php

View File

@ -1,12 +0,0 @@
<?php
use Aviat\Ion\Model as BaseModel;
class BaseModelTest extends AnimeClient_TestCase {
public function testBaseModelSanity()
{
$baseModel = new BaseModel();
$this->assertTrue(is_object($baseModel));
}
}

View File

@ -1,40 +0,0 @@
<?php
use Aviat\Ion\Friend;
use Aviat\Ion\Cache\CacheManager;
class CacheManagerText extends AnimeClient_TestCase {
protected $cachedTime;
public function __call($name, $args)
{
return call_user_func_array($name, $args);
}
public function setUp()
{
parent::setUp();
$this->cache = new CacheManager($this->container->get('config'), $this->container);
$this->friend = new Friend($this->cache);
}
public function testGet()
{
$this->cachedTime = $this->cache->get($this, 'time');
$this->assertEquals($this->cache->get($this, 'time'), $this->cachedTime);
}
public function testGetFresh()
{
$this->assertNotEquals($this->cache->getFresh($this, 'time'), $this->cachedTime);
}
public function testPurge()
{
$this->cachedTime = $this->cache->get($this, 'time');
$key = $this->friend->generateHashForMethod($this, 'time', []);
$this->cache->purge();
$this->assertEmpty($this->friend->driver->get($key));
}
}

View File

@ -1,43 +0,0 @@
<?php
trait CacheDriverBase {
protected $foo = [
'bar' => [
'baz' => 'foobar'
]
];
protected $bar = 'secondvalue';
public function testHasCacheDriver()
{
$this->assertTrue((bool) $this->driver);
}
public function testDriverGetSet()
{
$this->driver->set('foo', $this->foo);
$this->driver->set('bar', 'baz');
$this->assertEquals($this->driver->get('foo'), $this->foo);
$this->assertEquals($this->driver->get('bar'), 'baz');
}
public function testInvalidate()
{
$this->driver->set('foo', $this->foo);
$this->driver->invalidate('foo');
$this->assertEmpty($this->driver->get('foo'));
}
public function testInvalidateAll()
{
$this->driver->set('foo', $this->foo);
$this->driver->set('bar', $this->bar);
$this->driver->invalidateAll();
$this->assertEmpty($this->driver->get('foo'));
$this->assertEmpty($this->driver->get('bar'));
}
}

View File

@ -1,17 +0,0 @@
<?php
require_once('CacheDriverBase.php');
use Aviat\Ion\Cache\Driver\NullDriver;
class CacheNullDriverTest extends AnimeClient_TestCase {
use CacheDriverBase;
protected $driver;
public function setUp()
{
parent::setUp();
$this->driver = new NullDriver($this->container->get('config'));
}
}

View File

@ -1,38 +0,0 @@
<?php
require_once('CacheDriverBase.php');
use Aviat\Ion\Config;
use Aviat\Ion\Cache\Driver\RedisDriver;
class CacheRedisDriverTestTwo extends AnimeClient_TestCase {
use CacheDriverBase;
protected $driver;
public function setUp()
{
parent::setUp();
// Setup config with port and password
$config = new Config([
'redis' => [
'host' => (array_key_exists('REDIS_HOST', $_ENV)) ? $_ENV['REDIS_HOST'] : 'localhost',
'port' => 6379,
'password' => '',
'database' => 13,
]
]);
$this->driver = new RedisDriver($config);
}
public function tearDown()
{
parent::tearDown();
if ( ! is_null($this->driver))
{
$this->driver->__destruct();
}
}
}

View File

@ -1,29 +0,0 @@
<?php
require_once('CacheDriverBase.php');
use Aviat\Ion\Cache\Driver\RedisDriver;
class CacheRedisDriverTest extends AnimeClient_TestCase {
use CacheDriverBase;
protected $driver;
public function setUp()
{
parent::setUp();
$this->driver = new RedisDriver($this->container->get('config'));
}
public function tearDown()
{
parent::tearDown();
if ( ! is_null($this->driver))
{
$this->driver->__destruct();
}
}
}

View File

@ -1,20 +0,0 @@
<?php
require_once('CacheDriverBase.php');
use Aviat\Ion\Friend;
use Aviat\Ion\Cache\Driver\SQLDriver;
class CacheSQLDriverTest extends AnimeClient_TestCase {
use CacheDriverBase;
protected $driver;
public function setUp()
{
parent::setUp();
$this->driver = new SQLDriver($this->container->get('config'));
$friend = new Friend($this->driver);
$friend->db->query('CREATE TABLE IF NOT EXISTS "cache" ("key" TEXT NULL, "value" TEXT NULL, PRIMARY KEY ("key"))');
}
}

View File

@ -1,120 +0,0 @@
<?php
use Aviat\Ion\Config;
class ConfigTest extends AnimeClient_TestCase {
public function setUp()
{
$this->config = new Config([
'foo' => 'bar',
'asset_path' => '/assets',
'bar' => 'baz'
]);
}
public function testConfigGet()
{
$this->assertEquals('bar', $this->config->get('foo'));
$this->assertEquals('baz', $this->config->get('bar'));
$this->assertNull($this->config->get('baz'));
$this->assertNull($this->config->get(['apple', 'sauce', 'is']));
}
public function testConfigSet()
{
$ret = $this->config->set('foo', 'foobar');
$this->assertInstanceOf('Aviat\Ion\Config', $ret);
$this->assertEquals('foobar', $this->config->get('foo'));
$this->config->set(['apple', 'sauce', 'is'], 'great');
$apple = $this->config->get('apple');
$this->assertEquals('great', $apple['sauce']['is'], "Config value not set correctly");
$this->assertEquals('great', $this->config->get(['apple', 'sauce', 'is']), "Array argument get for config failed.");
}
public function testConfigBadSet()
{
$this->setExpectedException('InvalidArgumentException');
$this->config->set(NULL, FALSE);
}
public function dataConfigDelete()
{
return [
'top level delete' => [
'key' => 'apple',
'assertKeys' => [
[
'path' => ['apple', 'sauce', 'is'],
'expected' => NULL
],
[
'path' => ['apple', 'sauce'],
'expected' => NULL
],
[
'path' => 'apple',
'expected' => NULL
]
]
],
'mid level delete' => [
'key' => ['apple', 'sauce'],
'assertKeys' => [
[
'path' => ['apple', 'sauce', 'is'],
'expected' => NULL
],
[
'path' => ['apple', 'sauce'],
'expected' => NULL
],
[
'path' => 'apple',
'expected' => [
'sauce' => NULL
]
]
]
],
'deep delete' => [
'key' => ['apple', 'sauce', 'is'],
'assertKeys' => [
[
'path' => ['apple', 'sauce', 'is'],
'expected' => NULL
],
[
'path' => ['apple', 'sauce'],
'expected' => [
'is' => NULL
]
]
]
]
];
}
/**
* @dataProvider dataConfigDelete
*/
public function testConfigDelete($key, $assertKeys)
{
$config = new Config([]);
$config->set(['apple', 'sauce', 'is'], 'great');
$config->delete($key);
foreach($assertKeys as $pair)
{
$this->assertEquals($pair['expected'], $config->get($pair['path']));
}
}
public function testGetNonExistentConfigItem()
{
$this->assertNull($this->config->get('foobar'));
}
}

View File

@ -1,39 +0,0 @@
<?php
use Aviat\Ion\Di\Container;
use Aviat\Ion\Di\ContainerAware;
use Aviat\Ion\Di\ContainerInterface;
use Aviat\Ion\Di\Exception\ContainerException;
class Aware {
use ContainerAware;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
}
class ContainerAwareTest extends AnimeClient_TestCase {
public function setUp()
{
$this->container = new Container();
$this->aware = new Aware($this->container);
}
public function testContainerAwareTrait()
{
// The container was set in setup
// check that the get method returns the same
$this->assertSame($this->container, $this->aware->getContainer());
$container2 = new Container([
'foo' => 'bar',
'baz' => 'foobar'
]);
$this->aware->setContainer($container2);
$this->assertSame($container2, $this->aware->getContainer());
}
}

View File

@ -1,89 +0,0 @@
<?php
use Aviat\Ion\Di\Container;
use Aviat\Ion\Di\Exception\ContainerException;
use Monolog\Logger;
use Monolog\Handler\TestHandler;
use Monolog\Handler\NullHandler;
class ContainerTest extends AnimeClient_TestCase {
public function setUp()
{
$this->container = new Container();
}
public function dataGetWithException()
{
return [
'Bad index type: number' => [
'id' => 42,
'exception' => 'Aviat\Ion\Di\Exception\ContainerException',
'message' => 'Id must be a string'
],
'Bad index type: array' => [
'id' => [],
'exception' => 'Aviat\Ion\Di\Exception\ContainerException',
'message' => 'Id must be a string'
],
'Non-existent id' => [
'id' => 'foo',
'exception' => 'Aviat\Ion\Di\Exception\NotFoundException',
'message' => "Item 'foo' does not exist in container."
]
];
}
/**
* @dataProvider dataGetWithException
*/
public function testGetWithException($id, $exception, $message)
{
try
{
$this->container->get($id);
}
catch(ContainerException $e)
{
$this->assertInstanceOf($exception, $e);
$this->assertEquals($message, $e->getMessage());
}
}
public function testGetSet()
{
$container = $this->container->set('foo', function() {});
$this->assertInstanceOf('Aviat\Ion\Di\Container', $container);
$this->assertInstanceOf('Aviat\Ion\Di\ContainerInterface', $container);
$this->assertTrue(is_callable($container->get('foo')));
}
public function testLoggerMethods()
{
// Does the container have the default logger?
$this->assertFalse($this->container->hasLogger());
$this->assertFalse($this->container->hasLogger('default'));
$logger1 = new Logger('default');
$logger2 = new Logger('testing');
$logger1->pushHandler(new NullHandler());
$logger2->pushHandler(new TestHandler());
// Set the logger channels
$container = $this->container->setLogger($logger1);
$container2 = $this->container->setLogger($logger2, 'test');
$this->assertInstanceOf('Aviat\Ion\Di\ContainerInterface', $container);
$this->assertInstanceOf('Aviat\Ion\Di\Container', $container2);
$this->assertEquals($logger1, $this->container->getLogger('default'));
$this->assertEquals($logger2, $this->container->getLogger('test'));
$this->assertNull($this->container->getLogger('foo'));
$this->assertTrue($this->container->hasLogger());
$this->assertTrue($this->container->hasLogger('default'));
$this->assertTrue($this->container->hasLogger('test'));
}
}

View File

@ -1,68 +0,0 @@
<?php
use Aviat\Ion\Enum;
class EnumTest extends AnimeClient_TestCase {
protected $expectedConstList = [
'FOO' => 'bar',
'BAR' => 'foo',
'FOOBAR' => 'baz'
];
public function setUp()
{
parent::setUp();
$this->enum = new TestEnum();
}
public function testStaticGetConstList()
{
$actual = TestEnum::getConstList();
$this->assertEquals($this->expectedConstList, $actual);
}
public function testGetConstList()
{
$actual = $this->enum->getConstList();
$this->assertEquals($this->expectedConstList, $actual);
}
public function dataIsValid()
{
return [
'Valid' => [
'value' => 'baz',
'expected' => TRUE,
'static' => FALSE
],
'ValidStatic' => [
'value' => 'baz',
'expected' => TRUE,
'static' => TRUE
],
'Invalid' => [
'value' => 'foobar',
'expected' => FALSE,
'static' => FALSE
],
'InvalidStatic' => [
'value' => 'foobar',
'expected' => FALSE,
'static' => TRUE
]
];
}
/**
* @dataProvider dataIsValid
*/
public function testIsValid($value, $expected, $static)
{
$actual = ($static)
? TestEnum::isValid($value)
: $this->enum->isValid($value);
$this->assertEquals($expected, $actual);
}
}

View File

@ -1,56 +0,0 @@
<?php
use Aviat\Ion\Friend;
class FriendTest extends AnimeClient_TestCase {
public function setUp()
{
parent::setUp();
$obj = new FriendTestClass();
$this->friend = new Friend($obj);
}
public function testPrivateMethod()
{
$actual = $this->friend->getPrivate();
$this->assertEquals(23, $actual);
}
public function testProtectedMethod()
{
$actual = $this->friend->getProtected();
$this->assertEquals(4, $actual);
}
public function testGet()
{
$this->assertEquals(356, $this->friend->protected);
$this->assertNull($this->friend->foo); // Return NULL for non-existend properties
$this->assertEquals(47, $this->friend->parentProtected);
$this->assertEquals(84, $this->friend->grandParentProtected);
$this->assertNull($this->friend->parentPrivate); // Can't get a parent's privates
}
public function testSet()
{
$this->friend->private = 123;
$this->assertEquals(123, $this->friend->private);
$this->friend->foo = 32;
$this->assertNull($this->friend->foo);
}
public function testBadInvokation()
{
$this->setExpectedException('InvalidArgumentException', 'Friend must be an object');
$friend = new Friend('foo');
}
public function testBadMethod()
{
$this->setExpectedException('BadMethodCallException', "Method 'foo' does not exist");
$this->friend->foo();
}
}

View File

@ -1,68 +0,0 @@
<?php
use Aviat\Ion\Json;
use Aviat\Ion\JsonException;
class JsonTest extends AnimeClient_TestCase {
public function testEncode()
{
$data = (object) [
'foo' => [1, 2, 3, 4]
];
$expected = '{"foo":[1,2,3,4]}';
$this->assertEquals($expected, Json::encode($data));
}
public function dataEncodeDecode()
{
return [
'set1' => [
'data' => [
'apple' => [
'sauce' => ['foo','bar','baz']
]
],
'expected_size' => 39,
'expected_json' => '{"apple":{"sauce":["foo","bar","baz"]}}'
]
];
}
/**
* @dataProvider dataEncodeDecode
*/
public function testEncodeDecodeFile($data, $expected_size, $expected_json)
{
$target_file = _dir(self::TEST_DATA_DIR, 'json_write.json');
$actual_size = Json::encodeFile($target_file, $data);
$actual_json = file_get_contents($target_file);
$this->assertTrue(Json::isJson($actual_json));
$this->assertEquals($expected_size, $actual_size);
$this->assertEquals($expected_json, $actual_json);
$this->assertEquals($data, Json::decodeFile($target_file));
unlink($target_file);
}
public function testDecode()
{
$json = '{"foo":[1,2,3,4]}';
$expected = [
'foo' => [1, 2, 3, 4]
];
$this->assertEquals($expected, Json::decode($json));
$this->assertEquals((object)$expected, Json::decode($json, false));
$badJson = '{foo:{1|2}}';
$this->setExpectedException(
'Aviat\Ion\JsonException',
'JSON_ERROR_SYNTAX - Syntax error',
JSON_ERROR_SYNTAX
);
Json::decode($badJson);
}
}

View File

@ -1,12 +0,0 @@
<?php
use Aviat\Ion\Model\DB as BaseDBModel;
class BaseDBModelTest extends AnimeClient_TestCase {
public function testBaseDBModelSanity()
{
$baseDBModel = new BaseDBModel($this->container->get('config'));
$this->assertTrue(is_object($baseDBModel));
}
}

View File

@ -1,89 +0,0 @@
<?php
class AbstractTransformerTest extends AnimeClient_TestCase {
protected $transformer;
public function setUp()
{
$this->transformer = new TestTransformer();
}
public function dataTransformCollection()
{
return [
'object' => [
'original' => [
(object)[
['name' => 'Comedy'],
['name' => 'Romance'],
['name' => 'School'],
['name' => 'Harem']
],
(object)[
['name' => 'Action'],
['name' => 'Comedy'],
['name' => 'Magic'],
['name' => 'Fantasy'],
['name' => 'Mahou Shoujo']
],
(object)[
['name' => 'Comedy'],
['name' => 'Sci-Fi']
]
],
'expected' => [
['Comedy', 'Romance', 'School', 'Harem'],
['Action', 'Comedy', 'Magic', 'Fantasy', 'Mahou Shoujo'],
['Comedy', 'Sci-Fi']
]
],
'array' => [
'original' => [
[
['name' => 'Comedy'],
['name' => 'Romance'],
['name' => 'School'],
['name' => 'Harem']
],
[
['name' => 'Action'],
['name' => 'Comedy'],
['name' => 'Magic'],
['name' => 'Fantasy'],
['name' => 'Mahou Shoujo']
],
[
['name' => 'Comedy'],
['name' => 'Sci-Fi']
]
],
'expected' => [
['Comedy', 'Romance', 'School', 'Harem'],
['Action', 'Comedy', 'Magic', 'Fantasy', 'Mahou Shoujo'],
['Comedy', 'Sci-Fi']
]
],
];
}
public function testTransform()
{
$data = $this->dataTransformCollection();
$original = $data['object']['original'][0];
$expected = $data['object']['expected'][0];
$actual = $this->transformer->transform($original);
$this->assertEquals($expected, $actual);
}
/**
* @dataProvider dataTransformCollection
*/
public function testTransformCollection($original, $expected)
{
$actual = $this->transformer->transform_collection($original);
$this->assertEquals($expected, $actual);
}
}

View File

@ -1,173 +0,0 @@
<?php
class ArrayTypeTest extends AnimeClient_TestCase {
use Aviat\Ion\ArrayWrapper;
public function setUp()
{
parent::setUp();
}
public function dataCall()
{
$method_map = [
'chunk' => 'array_chunk',
'pluck' => 'array_column',
'assoc_diff' => 'array_diff_assoc',
'key_diff' => 'array_diff_key',
'diff' => 'array_diff',
'filter' => 'array_filter',
'flip' => 'array_flip',
'intersect' => 'array_intersect',
'keys' => 'array_keys',
'merge' => 'array_merge',
'pad' => 'array_pad',
'random' => 'array_rand',
'reduce' => 'array_reduce',
];
return [
'array_merge' => [
'method' => 'merge',
'array' => [1, 3, 5, 7],
'args' => [[2, 4, 6, 8]],
'expected' => [1, 3, 5, 7, 2, 4, 6, 8]
],
'array_product' => [
'method' => 'product',
'array' => [1, 2, 3],
'args' => [],
'expected' => 6
],
'array_reverse' => [
'method' => 'reverse',
'array' => [1, 2, 3, 4, 5],
'args' => [],
'expected' => [5, 4, 3, 2, 1]
],
'array_sum' => [
'method' => 'sum',
'array' => [1, 2, 3, 4, 5, 6],
'args' => [],
'expected' => 21
],
'array_unique' => [
'method' => 'unique',
'array' => [1, 1, 3, 2, 2, 2, 3, 3, 5],
'args' => [SORT_REGULAR],
'expected' => [0 => 1, 2 => 3, 3 => 2, 8 => 5]
],
'array_values' => [
'method' => 'values',
'array' => ['foo' => 'bar', 'baz' => 'foobar'],
'args' => [],
'expected' => ['bar', 'foobar']
]
];
}
/**
* Test the array methods defined for the __Call method
*
* @dataProvider dataCall
*/
public function testCall($method, $array, $args, $expected)
{
$obj = $this->arr($array);
$actual = $obj->__call($method, $args);
$this->assertEquals($expected, $actual);
}
public function testSet()
{
$obj = $this->arr([]);
$arraytype = $obj->set('foo', 'bar');
$this->assertInstanceOf('Aviat\Ion\Type\ArrayType', $arraytype);
$this->assertEquals('bar', $obj->get('foo'));
}
public function testGet()
{
$array = [1, 2, 3, 4, 5];
$obj = $this->arr($array);
$this->assertEquals($array, $obj->get());
$this->assertEquals(1, $obj->get(0));
$this->assertEquals(5, $obj->get(4));
}
public function testGetDeepKey()
{
$arr = [
'foo' => 'bar',
'baz' => [
'bar' => 'foobar'
]
];
$obj = $this->arr($arr);
$this->assertEquals('foobar', $obj->get_deep_key(['baz', 'bar']));
$this->assertNull($obj->get_deep_key(['foo', 'bar', 'baz']));
}
public function testMap()
{
$obj = $this->arr([1, 2, 3]);
$actual = $obj->map(function($item) {
return $item * 2;
});
$this->assertEquals([2, 4, 6], $actual);
}
public function testBadCall()
{
$obj = $this->arr([]);
$this->setExpectedException('InvalidArgumentException', "Method 'foo' does not exist");
$obj->foo();
}
public function testShuffle()
{
$original = [1, 2, 3, 4];
$test = [1, 2, 3, 4];
$obj = $this->arr($test);
$actual = $obj->shuffle();
//$this->assertNotEquals($actual, $original);
$this->assertTrue(is_array($actual));
}
public function testHasKey()
{
$obj = $this->arr([
'a' => 'b',
'z' => 'y'
]);
$this->assertTrue($obj->has_key('a'));
$this->assertFalse($obj->has_key('b'));
}
public function testHas()
{
$obj = $this->arr([1, 2, 6, 8, 11]);
$this->assertTrue($obj->has(8));
$this->assertFalse($obj->has(8745));
}
public function testSearch()
{
$obj = $this->arr([1, 2, 5, 7, 47]);
$actual = $obj->search(47);
$this->assertEquals(4, $actual);
}
public function testFill()
{
$obj = $this->arr([]);
$expected = ['?', '?', '?'];
$actual = $obj->fill(0, 3, '?');
$this->assertEquals($actual, $expected);
}
}

View File

@ -1,25 +0,0 @@
<?php
include_once __DIR__ . "/HttpViewTest.php";
class HtmlViewTest extends HttpViewTest {
protected $template_path;
public function setUp()
{
parent::setUp();
$this->view = new TestHtmlView($this->container);
}
public function testRenderTemplate()
{
$path = _dir(self::TEST_VIEW_DIR, 'test_view.php');
$expected = '<tag>foo</tag>';
$actual = $this->view->render_template($path, [
'var' => 'foo'
]);
$this->assertEquals($expected, $actual);
}
}

View File

@ -1,46 +0,0 @@
<?php
use Aviat\Ion\Friend;
class HttpViewTest extends AnimeClient_TestCase {
protected $view;
protected $friend;
public function setUp()
{
parent::setUp();
$this->view = new TestHttpView($this->container);
$this->friend = new Friend($this->view);
}
public function testGetOutput()
{
$this->friend->setOutput('foo');
$this->assertEquals('foo', $this->friend->getOutput());
$this->assertFalse($this->friend->hasRendered);
$this->assertEquals($this->friend->getOutput(), $this->friend->__toString());
$this->assertTrue($this->friend->hasRendered);
}
public function testSetOutput()
{
$same = $this->view->setOutput('<h1></h1>');
$this->assertEquals($same, $this->view);
$this->assertEquals('<h1></h1>', $this->view->getOutput());
}
public function testAppendOutput()
{
$this->view->setOutput('<h1>');
$this->view->appendOutput('</h1>');
$this->assertEquals('<h1></h1>', $this->view->getOutput());
}
public function testSetStatusCode()
{
$view = $this->view->setStatusCode(404);
$this->assertEquals(404, $view->response->getStatusCode());
}
}

View File

@ -1,43 +0,0 @@
<?php
use Aviat\Ion\Friend;
include_once __DIR__ . "/HttpViewTest.php";
class JsonViewTest extends HttpViewTest {
public function setUp()
{
parent::setUp();
$this->view = new TestJsonView($this->container);
$this->friend = new Friend($this->view);
}
public function testSetOutputJSON()
{
// Extend view class to remove destructor which does output
$view = new TestJsonView($this->container);
// Json encode non-string
$content = ['foo' => 'bar'];
$expected = json_encode($content);
$view->setOutput($content);
$this->assertEquals($expected, $this->view->getOutput());
}
public function testSetOutput()
{
// Directly set string
$view = new TestJsonView($this->container);
$content = '{}';
$expected = '{}';
$view->setOutput($content);
$this->assertEquals($expected, $view->getOutput());
}
public function testOutput()
{
$this->assertEquals('application/json', $this->friend->contentType);
}
}