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/ * @see http://robo.li/
*/ */
class RoboFile extends \Robo\Tasks class RoboFile extends \Robo\Tasks {
{
/**
* Directories used by analysis tools
*
* @var array
*/
protected $taskDirs = [ protected $taskDirs = [
'build/api', 'build/api',
'build/coverage', 'build/coverage',
@ -41,6 +46,7 @@ class RoboFile extends \Robo\Tasks
$this->phploc(TRUE); $this->phploc(TRUE);
$this->dependencyReport(); $this->dependencyReport();
$this->phpcpdReport(); $this->phpcpdReport();
$this->phpcsReport();
} }
/** /**
@ -135,6 +141,20 @@ class RoboFile extends \Robo\Tasks
$this->_run($cmd_parts); $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 * Run the phploc tool
* *
@ -145,6 +165,7 @@ class RoboFile extends \Robo\Tasks
// Command for generating reports // Command for generating reports
$report_cmd_parts = [ $report_cmd_parts = [
'vendor/bin/phploc', 'vendor/bin/phploc',
'--count-tests',
'--log-csv=build/logs/phploc.csv', '--log-csv=build/logs/phploc.csv',
'--log-xml=build/logs/phploc.xml', '--log-xml=build/logs/phploc.xml',
'src', 'src',
@ -263,6 +284,19 @@ class RoboFile extends \Robo\Tasks
$this->_run($cmd_parts); $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 * Short cut for joining an array of command arguments
* and then running it * 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"> <inheritance resolve="true">
<!-- @resolve - Flag to enable/disable resolving of inheritance --> <!-- @resolve - Flag to enable/disable resolving of inheritance -->
<!-- You can define multiple (external) dependencies to be included --> <!-- You can define multiple (external) dependencies to be included -->
<!-- <dependency path="" --> <!-- <dependency path="" -->
<!-- @path - path to a directory containing an index.xml for a dependency project --> <!-- @path - path to a directory containing an index.xml for a dependency project -->
@ -84,11 +85,9 @@
</source> </source>
<!-- PHP Code Sniffer findings --> <!-- PHP Code Sniffer findings -->
<!--
<source type="phpcs"> <source type="phpcs">
<file name="logs/phpcs.xml" /> <file name="phpcs.xml" />
</source> </source>
-->
<!-- PHPMessDetector --> <!-- PHPMessDetector -->
<!-- <!--
@ -99,7 +98,7 @@
<!-- PHPUnit Coverage XML --> <!-- PHPUnit Coverage XML -->
<source type="phpunit"> <source type="phpunit">
<coverage path="coverage" /> <coverage path="coverage/clover.xml" />
<!-- <coverage path="clover.xml" />--> <!-- <coverage path="clover.xml" />-->
<!-- @path - the directory where the xml code coverage report can be found --> <!-- @path - the directory where the xml code coverage report can be found -->
<!--<filter directory="${phpDox.project.source}" />--> <!--<filter directory="${phpDox.project.source}" />-->

View File

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

View File

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

View File

@ -4,7 +4,12 @@
"license":"MIT", "license":"MIT",
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"": "src/" "Aviat\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Aviat\\Ion\\Tests\\": "tests/Ion/"
} }
}, },
"require": { "require": {
@ -13,8 +18,6 @@
"container-interop/container-interop": "1.*", "container-interop/container-interop": "1.*",
"danielstjules/stringy": "~2.1", "danielstjules/stringy": "~2.1",
"guzzlehttp/guzzle": "6.*", "guzzlehttp/guzzle": "6.*",
"monolog/monolog": "1.*",
"predis/predis": "1.1.*",
"psr/http-message": "~1.0", "psr/http-message": "~1.0",
"psr/log": "~1.0", "psr/log": "~1.0",
"zendframework/zend-diactoros": "1.3.*" "zendframework/zend-diactoros": "1.3.*"
@ -22,13 +25,22 @@
"require-dev": { "require-dev": {
"pdepend/pdepend": "^2.2", "pdepend/pdepend": "^2.2",
"sebastian/phpcpd": "^2.0", "sebastian/phpcpd": "^2.0",
"theseer/phpdox": "0.8.1.1", "theseer/phpdox": "~0.9.0",
"phploc/phploc": "^3.0", "phploc/phploc": "^3.0",
"phpmd/phpmd": "^2.4", "phpmd/phpmd": "^2.4",
"phpunit/phpunit": "^5.4", "phpunit/phpunit": "^5.4",
"robmorgan/phinx": "^0.6.4", "robmorgan/phinx": "^0.6.4",
"humbug/humbug": "~1.0@dev", "humbug/humbug": "~1.0@dev",
"consolidation/robo": "~1.0@dev", "consolidation/robo": "~1.0@RC",
"henrikbjorn/lurker": "^1.1.0" "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> <filter>
<whitelist> <whitelist>
<directory suffix=".php">src/Aviat/Ion</directory> <directory suffix=".php">src/Ion</directory>
</whitelist> </whitelist>
</filter> </filter>
<testsuites> <testsuites>

View File

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

View File

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

View File

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

View File

@ -13,8 +13,7 @@
namespace Aviat\Ion\View; namespace Aviat\Ion\View;
use Aviat\Ion\Json; use Aviat\Ion\Json;
use Aviat\Ion\View\HttpView; use Aviat\Ion\ViewInterface;
use Aviat\Ion\View as BaseView;
/** /**
* View class to serialize Json * View class to serialize Json
@ -32,7 +31,7 @@ class JsonView extends HttpView {
* Set the output string * Set the output string
* *
* @param mixed $string * @param mixed $string
* @return BaseView * @return ViewInterface
*/ */
public function setOutput($string) 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 <?php
namespace Aviat\Ion\Tests\Cache;
use Aviat\Ion\Friend; use Aviat\Ion\Friend;
use Aviat\Ion\Cache\CacheManager; use Aviat\Ion\Cache\CacheManager;
class CacheManagerText extends Ion_TestCase { class CacheManagerTest extends \Ion_TestCase {
protected $cachedTime; protected $cachedTime;
public function __call($name, $args) public function __call($name, $args)
{ {
return call_user_func_array($name, $args); return \call_user_func_array($name, $args);
} }
public function setUp() 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 <?php
namespace Aviat\Ion\Tests;
use Aviat\Ion\Json; use Aviat\Ion\Json;
use Aviat\Ion\JsonException; use Aviat\Ion\JsonException;
class JsonTest extends Ion_TestCase { class JsonTest extends \Ion_TestCase {
public function testEncode() public function testEncode()
{ {

View File

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

View File

@ -1,8 +1,11 @@
<?php <?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 $view;
protected $friend; protected $friend;
@ -10,7 +13,7 @@ class HttpViewTest extends Ion_TestCase {
public function setUp() public function setUp()
{ {
parent::setUp(); parent::setUp();
$this->view = new TestHttpView($this->container); $this->view = new \TestHttpView($this->container);
$this->friend = new Friend($this->view); $this->friend = new Friend($this->view);
} }
@ -43,4 +46,28 @@ class HttpViewTest extends Ion_TestCase {
$view = $this->view->setStatusCode(404); $view = $this->view->setStatusCode(404);
$this->assertEquals(404, $view->response->getStatusCode()); $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 <?php
use Aviat\Ion\Friend; namespace Aviat\Ion\Tests\View;
include_once __DIR__ . "/HttpViewTest.php"; use Aviat\Ion\Friend;
class JsonViewTest extends HttpViewTest { class JsonViewTest extends HttpViewTest {
@ -10,14 +10,14 @@ class JsonViewTest extends HttpViewTest {
{ {
parent::setUp(); parent::setUp();
$this->view = new TestJsonView($this->container); $this->view = new \TestJsonView($this->container);
$this->friend = new Friend($this->view); $this->friend = new Friend($this->view);
} }
public function testSetOutputJSON() public function testSetOutputJSON()
{ {
// Extend view class to remove destructor which does output // Extend view class to remove destructor which does output
$view = new TestJsonView($this->container); $view = new \TestJsonView($this->container);
// Json encode non-string // Json encode non-string
$content = ['foo' => 'bar']; $content = ['foo' => 'bar'];
@ -29,7 +29,7 @@ class JsonViewTest extends HttpViewTest {
public function testSetOutput() public function testSetOutput()
{ {
// Directly set string // Directly set string
$view = new TestJsonView($this->container); $view = new \TestJsonView($this->container);
$content = '{}'; $content = '{}';
$expected = '{}'; $expected = '{}';
$view->setOutput($content); $view->setOutput($content);

View File

@ -35,30 +35,13 @@ require 'Ion_TestCase.php';
// Composer autoload // Composer autoload
require __DIR__ . '/../vendor/autoload.php'; 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 Settings
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
ini_set('session.use_cookies', 0); ini_set('session.use_cookies', 0);
ini_set("session.use_only_cookies",0); ini_set("session.use_only_cookies",0);
ini_set("session.use_trans_sid",1); 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(); session_start();
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

View File

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