Really ugly progress commit

This commit is contained in:
Timothy Warren 2016-08-26 17:21:50 -04:00
parent 9e6549a9f3
commit 6354a816db
52 changed files with 497 additions and 239 deletions

20
.editorconfig Normal file
View File

@ -0,0 +1,20 @@
# EditorConfig is awesome: http://EditorConfig.org
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = false
charset = utf-8
indent_style = tab
trim_trailing_whitespace = true
[*.{cpp,c,h,hpp,cxx}]
insert_final_newline = true
# Yaml files
[*.{yml,yaml}]
indent_style = space
indent_size = 4

View File

@ -20,8 +20,13 @@ if ( ! function_exists('glob_recursive'))
*
* @see http://robo.li/
*/
class RoboFile extends \Robo\Tasks
{
class RoboFile extends \Robo\Tasks {
/**
* Directories used by analysis tools
*
* @var array
*/
protected $taskDirs = [
'build/api',
'build/coverage',
@ -41,6 +46,7 @@ class RoboFile extends \Robo\Tasks
$this->phploc(TRUE);
$this->dependencyReport();
$this->phpcpdReport();
$this->phpcsReport();
}
/**
@ -135,6 +141,20 @@ class RoboFile extends \Robo\Tasks
$this->_run($cmd_parts);
}
/**
* Run the phpcs tool
*/
public function phpcs()
{
$cmd_parts = [
'vendor/bin/phpcs',
'--standard=./build/phpcs.xml',
'--report=summary'
];
$this->_run($cmd_parts);
}
/**
* Run the phploc tool
*
@ -145,6 +165,7 @@ class RoboFile extends \Robo\Tasks
// Command for generating reports
$report_cmd_parts = [
'vendor/bin/phploc',
'--count-tests',
'--log-csv=build/logs/phploc.csv',
'--log-xml=build/logs/phploc.xml',
'src',
@ -263,6 +284,19 @@ class RoboFile extends \Robo\Tasks
$this->_run($cmd_parts);
}
/**
* Generate code style report
*/
protected function phpcsReport()
{
$cmd_parts = [
'vendor/bin/phpcs',
'--standard=./build/phpcs.xml',
'--report-xml=./build/logs/phpcs.xml'
];
$this->_run($cmd_parts);
}
/**
* Short cut for joining an array of command arguments
* and then running it

@ -0,0 +1 @@
Subproject commit b501f01403216a917754e3f76ba7022d4ad37a4e

53
build/phpcs.xml Normal file
View File

@ -0,0 +1,53 @@
<?xml version="1.0"?>
<ruleset name="Tim's Coding Standard">
<description>A variation of the CodeIgniter standard</description>
<file>../src/</file>
<rule ref="Generic.Files.LineEndings">
<properties>
<property name="eolChar" value="\n"/>
</properties>
</rule>
<!-- PHP files should OMIT the closing PHP tag -->
<rule ref="Zend.Files.ClosingTag"/>
<!-- Always use full PHP opening tags -->
<rule ref="Generic.PHP.DisallowShortOpenTag"/>
<!-- Constants should always be fully uppercase -->
<rule ref="Generic.NamingConventions.UpperCaseConstantName"/>
<!-- TRUE, FALSE, and NULL keywords should always be fully uppercase -->
<rule ref="Generic.PHP.UpperCaseConstant"/>
<!-- One statement per line -->
<rule ref="Generic.Formatting.DisallowMultipleStatements"/>
<!-- Classes and functions should be commented -->
<rule ref="PEAR.Commenting.ClassComment"/>
<rule ref="PEAR.Commenting.FunctionComment"/>
<rule ref="Squiz.Commenting.FunctionCommentThrowTag"/>
<!-- Use warnings for docblock comments for files and variables, since nothing is cleary explained -->
<rule ref="PEAR.Commenting.FileComment">
<properties>
<property name="error" value="false"/>
</properties>
</rule>
<rule ref="Squiz.Commenting.VariableComment">
<properties>
<property name="error" value="false"/>
</properties>
</rule>
<!-- Use Allman style indenting. With the exception of Class declarations,
braces are always placed on a line by themselves, and indented at the same level as the control statement that "owns" them. -->
<rule ref="Generic.Functions.OpeningFunctionBraceBsdAllman"/>
<rule ref="PEAR.WhiteSpace.ScopeClosingBrace"/>
<rule ref="Generic.Functions.FunctionCallArgumentSpacing"/>
<rule ref="Generic.PHP.ForbiddenFunctions">
<properties>
<property name="forbiddenFunctions" type="array" value="create_function=>null,eval=>null" />
</properties>
</rule>
</ruleset>

View File

@ -48,6 +48,7 @@
<inheritance resolve="true">
<!-- @resolve - Flag to enable/disable resolving of inheritance -->
<!-- You can define multiple (external) dependencies to be included -->
<!-- <dependency path="" -->
<!-- @path - path to a directory containing an index.xml for a dependency project -->
@ -84,11 +85,9 @@
</source>
<!-- PHP Code Sniffer findings -->
<!--
<source type="phpcs">
<file name="logs/phpcs.xml" />
<file name="phpcs.xml" />
</source>
-->
<!-- PHPMessDetector -->
<!--
@ -99,7 +98,7 @@
<!-- PHPUnit Coverage XML -->
<source type="phpunit">
<coverage path="coverage" />
<coverage path="coverage/clover.xml" />
<!-- <coverage path="clover.xml" />-->
<!-- @path - the directory where the xml code coverage report can be found -->
<!--<filter directory="${phpDox.project.source}" />-->

View File

@ -8,7 +8,7 @@
>
<filter>
<whitelist>
<directory suffix=".php">../src/Aviat/Ion</directory>
<directory suffix=".php">../src/Ion</directory>
</whitelist>
</filter>
<testsuites>

View File

@ -1,7 +1,7 @@
<?php
$ion_file_patterns = [
'src/Aviat/Ion/*.php'
'src/*.php'
];
if ( ! function_exists('glob_recursive'))

View File

@ -4,7 +4,12 @@
"license":"MIT",
"autoload": {
"psr-4": {
"": "src/"
"Aviat\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Aviat\\Ion\\Tests\\": "tests/Ion/"
}
},
"require": {
@ -13,8 +18,6 @@
"container-interop/container-interop": "1.*",
"danielstjules/stringy": "~2.1",
"guzzlehttp/guzzle": "6.*",
"monolog/monolog": "1.*",
"predis/predis": "1.1.*",
"psr/http-message": "~1.0",
"psr/log": "~1.0",
"zendframework/zend-diactoros": "1.3.*"
@ -22,13 +25,22 @@
"require-dev": {
"pdepend/pdepend": "^2.2",
"sebastian/phpcpd": "^2.0",
"theseer/phpdox": "0.8.1.1",
"theseer/phpdox": "~0.9.0",
"phploc/phploc": "^3.0",
"phpmd/phpmd": "^2.4",
"phpunit/phpunit": "^5.4",
"robmorgan/phinx": "^0.6.4",
"humbug/humbug": "~1.0@dev",
"consolidation/robo": "~1.0@dev",
"henrikbjorn/lurker": "^1.1.0"
"consolidation/robo": "~1.0@RC",
"henrikbjorn/lurker": "^1.1.0",
"nikic/php-parser": "3.0.*@alpha",
"monolog/monolog": "1.*",
"predis/predis": "1.1.*",
"squizlabs/php_codesniffer": "^2.6"
},
"suggest": {
"monolog/monolog": "Provides implementation of psr/log",
"predis/predis": "Required for redis cache driver",
"zendframework/zend-diactoros": "Provides implementation of psr/http-message"
}
}

View File

@ -7,7 +7,7 @@
>
<filter>
<whitelist>
<directory suffix=".php">src/Aviat/Ion</directory>
<directory suffix=".php">src/Ion</directory>
</whitelist>
</filter>
<testsuites>

View File

@ -56,7 +56,7 @@ class RedisDriver implements DriverInterface {
*/
public function __destruct()
{
$this->redis = null;
$this->redis = NULL;
}
/**

View File

@ -0,0 +1,31 @@
<?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 called when a view is attempted to be sent twice
*/
class DoubleRenderException extends \LogicException {
/**
* DoubleRenderException constructor.
*
* @param string $message
* @param int $code
* @param null $previous
*/
public function __construct($message = 'A view can only be rendered once, because headers can only be sent once.', $code = 0, $previous = NULL)
{
parent::__construct($message, $code, $previous);
}
}

View File

@ -12,13 +12,16 @@
namespace Aviat\Ion;
use Psr\Http\Message\ResponseInterface;
use Aviat\Ion\Di\ContainerInterface;
use Aviat\Ion\Exception\DoubleRenderException;
use Aviat\Ion\Type\StringType;
/**
* Base view response class
*/
abstract class View {
abstract class View /* partially */ implements ViewInterface {
use Di\ContainerAware;
use StringWrapper;
@ -26,31 +29,10 @@ abstract class View {
/**
* HTTP response Object
*
* @var Zend\Diactoros\Response
* @var ResponseInterface
*/
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
@ -68,7 +50,6 @@ abstract class View {
{
$this->setContainer($container);
$this->response = $container->get('response');
$this->redirectResponse = NULL;
}
/**
@ -83,21 +64,20 @@ abstract class View {
}
/**
* Return rendered output
*
* @return string
* @inheritdoc
*/
public function __toString()
{
if ($this->hasRendered)
{
throw new DoubleRenderException();
}
$this->hasRendered = TRUE;
return $this->getOutput();
}
/**
* Set the output string
*
* @param string $string
* @return View
* @inheritdoc
*/
public function setOutput($string)
{
@ -107,10 +87,7 @@ abstract class View {
}
/**
* Append additional output
*
* @param string $string
* @return View
* @inheritdoc
*/
public function appendOutput($string)
{
@ -118,20 +95,11 @@ abstract class View {
}
/**
* Get the current output string
*
* @return string
* @inheritdoc
*/
public function getOutput()
{
return $this->response->getBody()->__toString();
}
/**
* Send output to client
*
* @return void
*/
abstract public function send();
}
// End of View.php

View File

@ -26,6 +26,13 @@ class HtmlView extends HttpView {
*/
protected $helper;
/**
* Response mime type
*
* @var string
*/
protected $contentType = 'text/html';
/**
* Create the Html View
*
@ -37,13 +44,6 @@ class HtmlView extends HttpView {
$this->helper = $container->get('html-helper');
}
/**
* Response mime type
*
* @var string
*/
protected $contentType = 'text/html';
/**
* Render a basic html Template
*

View File

@ -12,8 +12,9 @@
namespace Aviat\Ion\View;
use Zend\Diactoros\Response;
use Zend\Diactoros\Response\SapiEmitter;
use Aviat\Ion\Exception\DoubleRenderException;
use Aviat\Ion\View as BaseView;
/**
@ -21,6 +22,13 @@ use Aviat\Ion\View as BaseView;
*/
class HttpView extends BaseView {
/**
* Response mime type
*
* @var string
*/
protected $contentType = '';
/**
* Do a redirect
*
@ -60,13 +68,10 @@ class HttpView extends BaseView {
}
/**
* Send output to client
*
* @return void
* @inheritdoc
*/
public function send()
{
$this->hasRendered = TRUE;
$this->output();
}
@ -74,11 +79,17 @@ class HttpView extends BaseView {
* Send the appropriate response
*
* @codeCoverageIgnore
* @throws DoubleRenderException
* @return void
*/
protected function output()
{
$this->response->withHeader('Content-type', "{$this->contentType};charset=utf-8")
if ($this->hasRendered)
{
throw new DoubleRenderException();
}
$this->response = $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')
@ -86,6 +97,7 @@ class HttpView extends BaseView {
$sender = new SapiEmitter($this->response);
$sender->emit($this->response);
}
$this->hasRendered = TRUE;
}
}

View File

@ -13,8 +13,7 @@
namespace Aviat\Ion\View;
use Aviat\Ion\Json;
use Aviat\Ion\View\HttpView;
use Aviat\Ion\View as BaseView;
use Aviat\Ion\ViewInterface;
/**
* View class to serialize Json
@ -32,7 +31,7 @@ class JsonView extends HttpView {
* Set the output string
*
* @param mixed $string
* @return BaseView
* @return ViewInterface
*/
public function setOutput($string)
{

62
src/Ion/ViewInterface.php Normal file
View File

@ -0,0 +1,62 @@
<?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\DoubleRenderException;
/**
* View Interface abstracting a Response
*/
interface ViewInterface {
/**
* Return rendered output as string. Renders the view,
* and any attempts to call again will result in a DoubleRenderException
*
* @throws DoubleRenderException
* @return string
*/
public function __toString();
/**
* Set the output string
*
* @param string $string
* @return ViewInterface
*/
public function setOutput($string);
/**
* Append additional output.
*
* @param string $string
* @return ViewInterface
*/
public function appendOutput($string);
/**
* Get the current output as a string. Does not
* render view or send headers.
*
* @return string
*/
public function getOutput();
/**
* Send output to client. As it renders the view,
* any attempt to call again will result in a DoubleRenderException.
*
* @throws DoubleRenderException
* @return void
*/
public function send();
}

View File

@ -1,15 +1,17 @@
<?php
namespace Aviat\Ion\Tests\Cache;
use Aviat\Ion\Friend;
use Aviat\Ion\Cache\CacheManager;
class CacheManagerText extends Ion_TestCase {
class CacheManagerTest extends \Ion_TestCase {
protected $cachedTime;
public function __call($name, $args)
{
return call_user_func_array($name, $args);
return \call_user_func_array($name, $args);
}
public function setUp()

View File

@ -0,0 +1,14 @@
<?php
use Aviat\Ion\Exception\DoubleRenderException;
class DoubleRenderExceptionTest extends Ion_TestCase {
public function testDefaultMessage()
{
$this->expectException(DoubleRenderException::class);
$this->expectExceptionMessage('A view can only be rendered once, because headers can only be sent once.');
throw new DoubleRenderException();
}
}

View File

@ -1,9 +1,11 @@
<?php
namespace Aviat\Ion\Tests;
use Aviat\Ion\Json;
use Aviat\Ion\JsonException;
class JsonTest extends Ion_TestCase {
class JsonTest extends \Ion_TestCase {
public function testEncode()
{

View File

@ -1,6 +1,6 @@
<?php
include_once __DIR__ . "/HttpViewTest.php";
namespace Aviat\Ion\Tests\View;
class HtmlViewTest extends HttpViewTest {
@ -9,7 +9,7 @@ class HtmlViewTest extends HttpViewTest {
public function setUp()
{
parent::setUp();
$this->view = new TestHtmlView($this->container);
$this->view = new \TestHtmlView($this->container);
}
public function testRenderTemplate()

View File

@ -1,8 +1,11 @@
<?php
use Aviat\Ion\Friend;
namespace Aviat\Ion\Tests\View;
class HttpViewTest extends Ion_TestCase {
use Aviat\Ion\Friend;
use Aviat\Ion\Exception\DoubleRenderException;
class HttpViewTest extends \Ion_TestCase {
protected $view;
protected $friend;
@ -10,7 +13,7 @@ class HttpViewTest extends Ion_TestCase {
public function setUp()
{
parent::setUp();
$this->view = new TestHttpView($this->container);
$this->view = new \TestHttpView($this->container);
$this->friend = new Friend($this->view);
}
@ -43,4 +46,28 @@ class HttpViewTest extends Ion_TestCase {
$view = $this->view->setStatusCode(404);
$this->assertEquals(404, $view->response->getStatusCode());
}
public function testSendDoubleRenderException()
{
$this->expectException(DoubleRenderException::class);
$this->expectExceptionMessage('A view can only be rendered once, because headers can only be sent once.');
// First render
$this->view->__toString();
// Second render
$this->view->send();
}
public function test__toStringDoubleRenderException()
{
$this->expectException(DoubleRenderException::class);
$this->expectExceptionMessage('A view can only be rendered once, because headers can only be sent once.');
// First render
$this->view->send();
// Second render
$this->view->__toString();
}
}

View File

@ -1,8 +1,8 @@
<?php
use Aviat\Ion\Friend;
namespace Aviat\Ion\Tests\View;
include_once __DIR__ . "/HttpViewTest.php";
use Aviat\Ion\Friend;
class JsonViewTest extends HttpViewTest {
@ -10,14 +10,14 @@ class JsonViewTest extends HttpViewTest {
{
parent::setUp();
$this->view = new TestJsonView($this->container);
$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);
$view = new \TestJsonView($this->container);
// Json encode non-string
$content = ['foo' => 'bar'];
@ -29,7 +29,7 @@ class JsonViewTest extends HttpViewTest {
public function testSetOutput()
{
// Directly set string
$view = new TestJsonView($this->container);
$view = new \TestJsonView($this->container);
$content = '{}';
$expected = '{}';
$view->setOutput($content);

View File

@ -35,30 +35,13 @@ require 'Ion_TestCase.php';
// Composer autoload
require __DIR__ . '/../vendor/autoload.php';
/**
* Set up autoloaders
*
* @codeCoverageIgnore
* @return void
*/
spl_autoload_register(function ($class) {
$class_parts = explode('\\', $class);
$ns_path = realpath(__DIR__ . '/../src') . '/' . implode('/', $class_parts) . ".php";
if (file_exists($ns_path))
{
require_once($ns_path);
return;
}
});
// -----------------------------------------------------------------------------
// Ini Settings
// -----------------------------------------------------------------------------
ini_set('session.use_cookies', 0);
ini_set("session.use_only_cookies",0);
ini_set("session.use_trans_sid",1);
// Start session here to supress error about headers not sent
// Start session here to surpress error about headers not sent
session_start();
// -----------------------------------------------------------------------------

View File

@ -4,6 +4,7 @@
*/
use Aviat\Ion\Enum;
use Aviat\Ion\Exception\DoubleRenderException;
use Aviat\Ion\Friend;
use Aviat\Ion\Transformer\AbstractTransformer;
use Aviat\Ion\View;
@ -70,7 +71,7 @@ class TestTransformer extends AbstractTransformer {
}
trait MockViewOutputTrait {
protected function output() {
/*protected function output() {
$reflect = new ReflectionClass($this);
$properties = $reflect->getProperties();
$props = [];
@ -88,31 +89,69 @@ trait MockViewOutputTrait {
$friend->__set($name, $val);
}
$friend->output();
//$friend->output();
}*/
public function send()
{
if ($this->hasRendered)
{
throw new DoubleRenderException();
}
$this->hasRendered = TRUE;
}
}
class TestView extends View {
public function send() {}
protected function output()
public function send()
{
/*$content =& $this->response->content;
$content->set($this->output);
$content->setType($this->contentType);
$content->setCharset('utf-8');*/
if ($this->hasRendered)
{
throw new DoubleRenderException();
}
$this->hasRendered = TRUE;
}
public function output() {}
}
class TestHtmlView extends HtmlView {
use MockViewOutputTrait;
protected function output()
{
if ($this->hasRendered)
{
throw new DoubleRenderException();
}
$this->hasRendered = TRUE;
}
}
class TestHttpView extends HttpView {
use MockViewOutputTrait;
protected function output()
{
if ($this->hasRendered)
{
throw new DoubleRenderException();
}
$this->hasRendered = TRUE;
}
}
class TestJsonView extends JsonView {
public function __destruct() {}
protected function output()
{
if ($this->hasRendered)
{
throw new DoubleRenderException();
}
$this->hasRendered = TRUE;
}
}
// -----------------------------------------------------------------------------