Built out new Display class with tests
Not hooked up to the Controller yet, wanted to get Travis setup.
This commit is contained in:
parent
99a04865e8
commit
07a95a7508
7 changed files with 386 additions and 73 deletions
|
@ -41,49 +41,12 @@ class Config extends Object
|
|||
* Constructor
|
||||
*
|
||||
* Calls the parent constructor and loads the passed file.
|
||||
*
|
||||
* @param string $filename optional Filename of the config
|
||||
*/
|
||||
public function __construct($filename = null)
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
// Try to fine the configuration
|
||||
if ($filename == null)
|
||||
{
|
||||
$filename = 'config.php';
|
||||
$loaded = false;
|
||||
$cwd = getcwd();
|
||||
|
||||
while ($loaded == false)
|
||||
{
|
||||
chdir(dirname($filename));
|
||||
|
||||
if (getcwd() == '/')
|
||||
{
|
||||
throw new Exception('Unable to load configuration.');
|
||||
}
|
||||
|
||||
chdir($cwd);
|
||||
|
||||
$filename = '../' . $filename;
|
||||
$loaded = $this->load($filename);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->load($filename);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a configuration file
|
||||
*
|
||||
* @param string $filename filename of the config file
|
||||
* @return boolean success of the load process
|
||||
*/
|
||||
public function load($filename)
|
||||
{
|
||||
$filename = '../config.php';
|
||||
$environments = false;
|
||||
$environment = false;
|
||||
|
||||
|
|
|
@ -236,11 +236,6 @@ class Controller extends Object
|
|||
}
|
||||
}
|
||||
|
||||
// Validates the rendering engine
|
||||
$engines = is_array($module->engine) ? array_values($module->engine) : array($module->engine);
|
||||
$engines = array_combine($engines, $engines);
|
||||
$engine = current($engines);
|
||||
|
||||
// Possibly overrides the engine with the passed return type
|
||||
if (isset($return_type))
|
||||
{
|
||||
|
@ -256,7 +251,7 @@ class Controller extends Object
|
|||
}
|
||||
|
||||
// Starts up the display engine
|
||||
$display_class = 'Display_' . $engine;
|
||||
$display_class = 'Display_PHP';
|
||||
$display = new $display_class();
|
||||
|
||||
// Assigns the template / template variables
|
||||
|
@ -476,18 +471,18 @@ class Controller extends Object
|
|||
$css_class = $module_class;
|
||||
$js_basename = $basename;
|
||||
|
||||
if (isset($action))
|
||||
{
|
||||
$module_class .= '_' . $action;
|
||||
$template_basename .= '/' . $action;
|
||||
$css_class .= '_' . $action;
|
||||
$js_basename .= '/' . $action;
|
||||
}
|
||||
|
||||
// Scrubs class names with hyphens
|
||||
// @todo Unsure this is even relevant anymore
|
||||
if (strpos($module_class, '-') !== false)
|
||||
{
|
||||
$module_class = preg_replace('/(-(.{1}))/e', 'strtoupper("$2")', $module_class);
|
||||
$module_class = preg_replace_callback(
|
||||
'/(-(.{1}))/',
|
||||
function ($matches)
|
||||
{
|
||||
return strtoupper($matches[2]);
|
||||
},
|
||||
$module_class
|
||||
);
|
||||
}
|
||||
|
||||
return array($module_class, $module_filename, $template_basename, $css_class, $js_basename);
|
||||
|
|
202
classes/Display.php
Normal file
202
classes/Display.php
Normal file
|
@ -0,0 +1,202 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
*Display Class File for PICKLES
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistribution of these files must retain the above copyright notice.
|
||||
*
|
||||
* @author Joshua Sherman <pickles@joshtronic.com>
|
||||
* @copyright Copyright 2007-2013, Joshua Sherman
|
||||
* @license http://www.opensource.org/licenses/mit-license.html
|
||||
* @package PICKLES
|
||||
* @link https://github.com/joshtronic/pickles
|
||||
*/
|
||||
|
||||
/**
|
||||
* Display Class
|
||||
*
|
||||
* If you can see it then it probably happened in here.
|
||||
*/
|
||||
class Display extends Object
|
||||
{
|
||||
/**
|
||||
* Return Type
|
||||
*
|
||||
* This class supports loading a PHP template, displaying JSON, XML and an
|
||||
* RSS flavored XML. Inside your modules you can specify either a string or
|
||||
* array. Possible values include "template", "json", "xml" and "rss".
|
||||
* Default behavior is to try to load a template and fallback to displaying
|
||||
* JSON. The "template" option always takes precedence when used with the
|
||||
* other types.
|
||||
*
|
||||
* @var mixed string or array to determine how to return
|
||||
*/
|
||||
public $return = ['template', 'json'];
|
||||
|
||||
/**
|
||||
* Template
|
||||
*
|
||||
* Templates are found in the ./templates directory of your site. The
|
||||
* template workflow is to load ./templates/__shared/index.phtml and you
|
||||
* would set that template up to require $this->template, the path and
|
||||
* filename for the module template (named based on the structure of the
|
||||
* requested URI. Inside your module you can specify the basename of the
|
||||
* parent template you would like to use or false to not use a parent
|
||||
* template.
|
||||
*
|
||||
* @var string or boolean false the basename of the parent template
|
||||
*/
|
||||
public $template = 'index';
|
||||
|
||||
/**
|
||||
* Meta Data
|
||||
*
|
||||
* An array of meta data that you want exposed to the template. Currently
|
||||
* you set the meta data from inside your module using the class variables
|
||||
* title, description and keywords. The newer [preferred] method is to
|
||||
* set an array in your module using the meta variable using title,
|
||||
* description and keywords as the keys. You can also specify any other
|
||||
* meta keys in the array that you would like to be exposed to your
|
||||
* templates. The meta data is only used by TEMPLATE and RSS return types.
|
||||
*/
|
||||
public $meta = [];
|
||||
|
||||
/**
|
||||
* Module Data
|
||||
*
|
||||
* Any data the module returns or is assigned inside of the module will
|
||||
* be available here and exposed to the template.
|
||||
*/
|
||||
public $module = null;
|
||||
|
||||
public function render()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Starts up the buffer so we can capture it
|
||||
ob_start();
|
||||
|
||||
if (!is_array($this->return))
|
||||
{
|
||||
$this->return = [ $this->return ];
|
||||
}
|
||||
|
||||
$return_json = $return_rss = $return_template = $return_xml = false;
|
||||
|
||||
foreach ($this->return as $return)
|
||||
{
|
||||
$variable = 'return_' . $return;
|
||||
$$variable = true;
|
||||
}
|
||||
|
||||
// Makes sure the return type is valid
|
||||
if (!$return_json && !$return_rss && !$return_template && !$return_xml)
|
||||
{
|
||||
throw new Exception('Invalid return type.');
|
||||
}
|
||||
|
||||
// Checks for the PHPSESSID in the query string
|
||||
if (stripos($_SERVER['REQUEST_URI'], '?PHPSESSID=') === false)
|
||||
{
|
||||
// XHTML compliancy stuff
|
||||
// @todo Wonder if this could be yanked now that we're in HTML5 land
|
||||
ini_set('arg_separator.output', '&');
|
||||
ini_set('url_rewriter.tags', 'a=href,area=href,frame=src,input=src,fieldset=');
|
||||
|
||||
header('Content-type: text/html; charset=UTF-8');
|
||||
}
|
||||
else
|
||||
{
|
||||
// Redirect so Google knows to index the page without the session ID
|
||||
list($request_uri, $phpsessid) = explode('?PHPSESSID=', $_SERVER['REQUEST_URI'], 2);
|
||||
header('HTTP/1.1 301 Moved Permanently');
|
||||
header('Location: ' . $request_uri);
|
||||
|
||||
throw new Exception('Requested URI contains PHPSESSID, redirecting.');
|
||||
}
|
||||
|
||||
// @todo Derrive CSS and JS from _REQUEST['request'] no need to pass around
|
||||
|
||||
$loaded = false;
|
||||
|
||||
if ($return_template)
|
||||
{
|
||||
// Determines if we're using a custom class or not
|
||||
$dynamic_class = (class_exists('CustomDynamic') ? 'CustomDynamic' : 'Dynamic');
|
||||
$form_class = (class_exists('CustomForm') ? 'CustomForm' : 'Form');
|
||||
$html_class = (class_exists('CustomHTML') ? 'CustomHTML' : 'HTML');
|
||||
|
||||
// Exposes some objects and variables to the local scope of the template
|
||||
$this->request = $this->js_file = $_REQUEST['request'];
|
||||
// @todo replace _ with - as it's more appropriate for CSS naming
|
||||
$this->css_class = strtr($this->request, '/', '_');
|
||||
|
||||
// @todo Remove the magic $__variable when all sites are ported
|
||||
$__config = $this->config;
|
||||
$__css_class = $this->css_class;
|
||||
$__js_file = $this->js_file;
|
||||
$__meta = $this->meta;
|
||||
$__module = $this->module;
|
||||
|
||||
$__dynamic = $this->dynamic = new $dynamic_class();
|
||||
$__form = $this->form = new $form_class();
|
||||
$__html = $this->html = new $html_class();
|
||||
|
||||
// Checks for the parent template and tries to load it
|
||||
if ($this->template)
|
||||
{
|
||||
$parent_file = SITE_TEMPLATE_PATH . '__shared/' . $this->template . '.phtml';
|
||||
$child_file = SITE_TEMPLATE_PATH . $_REQUEST['request'] . '.phtml';
|
||||
|
||||
// Assigns old and new variables
|
||||
// @todo Remove $__template when all sites are ported
|
||||
$__template = $this->template = $child_file;
|
||||
|
||||
if (file_exists($parent_file))
|
||||
{
|
||||
$loaded = require_once $parent_file;
|
||||
}
|
||||
}
|
||||
|
||||
// Checks for the module template and tries to load it
|
||||
if (file_exists($child_file))
|
||||
{
|
||||
$loaded = require_once $child_file;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$loaded)
|
||||
{
|
||||
if ($return_json)
|
||||
{
|
||||
echo json_encode($this->module, isset($_REQUEST['pretty']) ? JSON_PRETTY_PRINT : false);
|
||||
}
|
||||
elseif ($return_xml)
|
||||
{
|
||||
echo Convert::arrayToXML($this->module, isset($_REQUEST['pretty']));
|
||||
}
|
||||
}
|
||||
|
||||
// Grabs the buffer so we can massage it a bit
|
||||
$buffer = ob_get_clean();
|
||||
|
||||
// Kills any whitespace and HTML comments in templates
|
||||
if ($loaded)
|
||||
{
|
||||
// The BSA exception is because their system sucks and demands there be comments present
|
||||
$buffer = preg_replace(['/^[\s]+/m', '/<!--(?:(?!BuySellAds).)+-->/U'], '', $buffer);
|
||||
}
|
||||
|
||||
return $buffer;
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
return $e->getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -157,17 +157,6 @@ class Module extends Object
|
|||
*/
|
||||
protected $hash = null;
|
||||
|
||||
/**
|
||||
* Default Display Engine
|
||||
*
|
||||
* Defaults to PHP but could be set to JSON, XML or RSS. Value is
|
||||
* overwritten by the config value if not set by the module.
|
||||
*
|
||||
* @access protected
|
||||
* @var string, null by default
|
||||
*/
|
||||
protected $engine = DISPLAY_PHP;
|
||||
|
||||
/**
|
||||
* Default Template
|
||||
*
|
||||
|
|
13
pickles.php
13
pickles.php
|
@ -31,8 +31,11 @@ define('PICKLES_PATH', dirname(__FILE__) . '/');
|
|||
define('PICKLES_CLASS_PATH', PICKLES_PATH . 'classes/');
|
||||
define('PICKLES_VENDOR_PATH', PICKLES_PATH . 'vendors/');
|
||||
|
||||
// Establishes our site paths
|
||||
// Establishes our site paths, sanity check is to allow vfsStream in our tests
|
||||
if (!defined('SITE_PATH'))
|
||||
{
|
||||
define('SITE_PATH', getcwd() . '/../');
|
||||
}
|
||||
|
||||
define('SITE_CLASS_PATH', SITE_PATH . 'classes/');
|
||||
define('SITE_MODEL_PATH', SITE_PATH . 'models/');
|
||||
|
@ -42,12 +45,6 @@ define('SITE_TEMPLATE_PATH', SITE_PATH . 'templates/');
|
|||
define('PRIVATE_PATH', SITE_PATH . 'private/');
|
||||
define('LOG_PATH', PRIVATE_PATH . 'logs/');
|
||||
|
||||
// Sets up constants for the Display names
|
||||
define('DISPLAY_JSON', 'JSON');
|
||||
define('DISPLAY_PHP', 'PHP');
|
||||
define('DISPLAY_RSS', 'RSS');
|
||||
define('DISPLAY_XML', 'XML');
|
||||
|
||||
// Creates a variable to flag if we're on the command line
|
||||
define('IS_CLI', !isset($_SERVER['REQUEST_METHOD']));
|
||||
|
||||
|
@ -168,6 +165,8 @@ function __autoload($class)
|
|||
return $loaded;
|
||||
}
|
||||
|
||||
spl_autoload_register('__autoload');
|
||||
|
||||
// }}}
|
||||
// {{{ Error Handler
|
||||
|
||||
|
|
16
tests/bootstrap.php
Normal file
16
tests/bootstrap.php
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
ob_start();
|
||||
|
||||
require_once '/usr/local/Cellar/php55/5.5.7/lib/php/vfsStream/vfsStream.php';
|
||||
|
||||
$root = vfsStream::setup('site');
|
||||
define('SITE_PATH', vfsStream::url('site/'));
|
||||
|
||||
require_once 'classes/Object.php';
|
||||
require_once 'classes/Config.php';
|
||||
require_once 'classes/Display.php';
|
||||
require_once 'classes/File.php';
|
||||
require_once 'pickles.php';
|
||||
|
||||
?>
|
149
tests/classes/DisplayTest.php
Normal file
149
tests/classes/DisplayTest.php
Normal file
|
@ -0,0 +1,149 @@
|
|||
<?php
|
||||
|
||||
class DisplayTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $display, $shared_templates;
|
||||
|
||||
private $child_html = '<div>child template</div>';
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->shared_templates = SITE_TEMPLATE_PATH . '__shared/';
|
||||
|
||||
if (!file_exists($this->shared_templates))
|
||||
{
|
||||
mkdir($this->shared_templates, 0644, true);
|
||||
}
|
||||
|
||||
$_SERVER['REQUEST_URI'] = '/test';
|
||||
$_REQUEST['request'] = 'test';
|
||||
|
||||
$this->display = new Display();
|
||||
$this->display->module = [
|
||||
'pickles' => [
|
||||
'yummy' => 'gherkin',
|
||||
'delish' => 'kosher dill',
|
||||
'yucky' => 'bread & butter'
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
protected function tearDown()
|
||||
{
|
||||
unlink(SITE_TEMPLATE_PATH . 'test.phtml');
|
||||
unlink($this->shared_templates . 'index.phtml');
|
||||
}
|
||||
|
||||
public function testInvalidReturnType()
|
||||
{
|
||||
$this->display->return = 'invalid';
|
||||
$this->assertEquals('Invalid return type.', $this->display->render());
|
||||
}
|
||||
|
||||
public function testPHPSESSID()
|
||||
{
|
||||
$request_uri = $_SERVER['REQUEST_URI'];
|
||||
$_SERVER['REQUEST_URI'] .= '?PHPSESSID=session_id';
|
||||
$return = $this->display->render();
|
||||
|
||||
$this->assertTrue(in_array('Location: ' . $request_uri, xdebug_get_headers()));
|
||||
$this->assertEquals('Requested URI contains PHPSESSID, redirecting.', $return);
|
||||
}
|
||||
|
||||
public function testNoParentTemplate()
|
||||
{
|
||||
file_put_contents(SITE_TEMPLATE_PATH . 'test.phtml', $this->child_html);
|
||||
|
||||
$this->assertEquals($this->child_html, $this->display->render());
|
||||
}
|
||||
|
||||
public function testRenderTemplate()
|
||||
{
|
||||
file_put_contents(SITE_TEMPLATE_PATH . 'test.phtml', $this->child_html);
|
||||
|
||||
$child = '<?php require $this->template; ?>' . "\n";
|
||||
|
||||
$html = <<<HTML
|
||||
<!doctype html>
|
||||
<html>
|
||||
<body>
|
||||
<!-- BuySellAds Unstripped Comment -->
|
||||
<h1>parent template</h1>
|
||||
{$child}
|
||||
</body>
|
||||
</html>
|
||||
HTML;
|
||||
|
||||
file_put_contents($this->shared_templates . 'index.phtml', $html);
|
||||
|
||||
$html = str_replace($child, $this->child_html, $html);
|
||||
$html = preg_replace(['/^[\s]+/m', '/<!--(?:(?!BuySellAds).)+-->/U'], '', $html);
|
||||
|
||||
$this->assertEquals($html, $this->display->render());
|
||||
}
|
||||
|
||||
public function testRenderJSON()
|
||||
{
|
||||
$this->assertEquals(
|
||||
'{"pickles":{"yummy":"gherkin","delish":"kosher dill","yucky":"bread & butter"}}',
|
||||
$this->display->render()
|
||||
);
|
||||
}
|
||||
|
||||
public function testRenderJSONPrettyPrint()
|
||||
{
|
||||
$_REQUEST['pretty'] = 'true';
|
||||
|
||||
$pretty_json = <<<JSON
|
||||
{
|
||||
"pickles": {
|
||||
"yummy": "gherkin",
|
||||
"delish": "kosher dill",
|
||||
"yucky": "bread & butter"
|
||||
}
|
||||
}
|
||||
JSON;
|
||||
|
||||
$this->assertEquals($pretty_json, $this->display->render());
|
||||
}
|
||||
|
||||
public function testRenderXML()
|
||||
{
|
||||
$this->display->return = ['template', 'xml'];
|
||||
$this->assertEquals(
|
||||
'<yummy>gherkin</yummy><delish>kosher dill</delish><yucky><![CDATA[bread & butter]]></yucky>',
|
||||
$this->display->render()
|
||||
);
|
||||
}
|
||||
|
||||
public function testRenderXMLPrettyPrint()
|
||||
{
|
||||
$_REQUEST['pretty'] = 'true';
|
||||
|
||||
$pretty_xml = <<<XML
|
||||
<yummy>gherkin</yummy>
|
||||
<delish>kosher dill</delish>
|
||||
<yucky><![CDATA[bread & butter]]></yucky>
|
||||
|
||||
XML;
|
||||
|
||||
$this->display->return = ['template', 'xml'];
|
||||
$this->assertEquals($pretty_xml, $this->display->render());
|
||||
}
|
||||
|
||||
/*
|
||||
public function testRenderRSS()
|
||||
{
|
||||
$this->fail('Not yet implemented.');
|
||||
}
|
||||
|
||||
public function testRenderRSSPrettyPrint()
|
||||
{
|
||||
$this->fail('Not yet implemented.');
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
?>
|
Loading…
Add table
Add a link
Reference in a new issue