Commit: 7440fbd54c7b1e6e911f9489f1a5a06e138a3a7b
Author: chawbacca | Date: 2011-03-07 19:08:47 +0000
diff --git a/app/config/bootstrap.php b/app/config/bootstrap.php
index 9c036b2..0b45e42 100644
--- a/app/config/bootstrap.php
+++ b/app/config/bootstrap.php
@@ -21,6 +21,15 @@
* new bootstrap file and `require` it here.
*
* @see lithium\util\collection\Filters
+<<<<<<< HEAD
+ */
+
+/**
+ * The libraries file contains the loading instructions for all plugins, frameworks and other class
+ * libraries used in the application, including the Lithium core, and the application itself. These
+ * instructions include library names, paths to files, and any applicable class-loading rules. This
+ * file also statically loads common classes to improve bootstrap performance.
+=======
*/
/**
@@ -32,6 +41,14 @@
require __DIR__ . '/bootstrap/libraries.php';
/**
+ * The error configuration allows you to use the filter system along with the advanced matching
+ * rules of the `ErrorHandler` class to provide a high level of control over managing exceptions in
+ * your application, with no impact on framework or application code.
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
+ */
+// require __DIR__ . '/bootstrap/errors.php';
+
+/**
* This file contains configurations for connecting to external caching resources, as well as
* default caching rules for various systems within your application
*/
diff --git a/app/config/bootstrap/cache.php b/app/config/bootstrap/cache.php
index 3e124be..a929466 100644
--- a/app/config/bootstrap/cache.php
+++ b/app/config/bootstrap/cache.php
@@ -27,6 +27,14 @@ if (!($apcEnabled = Apc::enabled()) && !is_writable(LITHIUM_APP_PATH . '/resourc
return;
}
+<<<<<<< HEAD
+=======
+/**
+ * This configures the default cache, based on whether ot not APC user caching is enabled. If it is
+ * not, file caching will be used. Most of this code is for getting you up and running only, and
+ * should be replaced with a hard-coded configuration, based on the cache(s) you plan to use.
+ */
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
if ($apcEnabled) {
$default = array(
'adapter' => 'lithium\storage\cache\adapter\Apc',
@@ -39,15 +47,28 @@ if ($apcEnabled) {
}
Cache::config(compact('default'));
+/**
+ * Caches paths for auto-loaded and service-located classes.
+ */
Dispatcher::applyFilter('run', function($self, $params, $chain) {
+<<<<<<< HEAD
if ($cache = Cache::read('default', 'core.libraries')) {
+=======
+ $key = md5(LITHIUM_APP_PATH) . '.core.libraries';
+
+ if ($cache = Cache::read('default', $key)) {
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
$cache = (array) $cache + Libraries::cache();
Libraries::cache($cache);
}
$result = $chain->next($self, $params, $chain);
if ($cache != Libraries::cache()) {
+<<<<<<< HEAD
Cache::write('default', 'core.libraries', Libraries::cache(), '+1 day');
+=======
+ Cache::write('default', $key, Libraries::cache(), '+1 day');
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
}
return $result;
});
diff --git a/app/config/bootstrap/errors.php b/app/config/bootstrap/errors.php
new file mode 100644
index 0000000..27de2a2
--- /dev/null
+++ b/app/config/bootstrap/errors.php
@@ -0,0 +1,25 @@
+<?php
+/**
+ * Lithium: the most rad php framework
+ *
+ * @copyright Copyright 2011, Union of RAD (http://union-of-rad.org)
+ * @license http://opensource.org/licenses/bsd-license.php The BSD License
+ */
+
+use lithium\core\ErrorHandler;
+use lithium\action\Response;
+use lithium\net\http\Media;
+
+ErrorHandler::apply('lithium\action\Dispatcher::run', array(), function($info, $params) {
+ $response = new Response(array('request' => $params['request']));
+
+ Media::render($response, compact('info', 'params'), array(
+ 'controller' => '_errors',
+ 'template' => 'development',
+ 'layout' => 'error',
+ 'request' => $params['request']
+ ));
+ return $response;
+});
+
+?>
\ No newline at end of file
diff --git a/app/resources/g11n/empty b/app/resources/g11n/empty
old mode 100755
new mode 100644
diff --git a/app/resources/tmp/cache/templates/empty b/app/resources/tmp/cache/templates/empty
old mode 100755
new mode 100644
diff --git a/app/resources/tmp/logs/empty b/app/resources/tmp/logs/empty
old mode 100755
new mode 100644
diff --git a/app/resources/tmp/tests/empty b/app/resources/tmp/tests/empty
old mode 100755
new mode 100644
diff --git a/app/views/_errors/development.html.php b/app/views/_errors/development.html.php
new file mode 100644
index 0000000..18654f6
--- /dev/null
+++ b/app/views/_errors/development.html.php
@@ -0,0 +1,108 @@
+<?php
+/**
+ * Lithium: the most rad php framework
+ *
+ * @copyright Copyright 2011, Union of RAD (http://union-of-rad.org)
+ * @license http://opensource.org/licenses/bsd-license.php The BSD License
+ */
+
+use lithium\analysis\Debugger;
+use lithium\analysis\Inspector;
+
+$exception = $info['exception'];
+$replace = array('<?php', '?>', '<code>', '</code>', "\n");
+$context = 5;
+
+/**
+ * Set Lithium-esque colors for syntax highlighing.
+ */
+ini_set('highlight.string', '#4DDB4A');
+ini_set('highlight.comment', '#D42AAE');
+ini_set('highlight.keyword', '#D42AAE');
+ini_set('highlight.default', '#3C96FF');
+ini_set('highlight.htm', '#FFFFFF');
+
+$stack = Debugger::trace(array('format' => 'array', 'trace' => $exception->getTrace()));
+
+array_unshift($stack, array(
+ 'functionRef' => '[exception]',
+ 'file' => $exception->getFile(),
+ 'line' => $exception->getLine()
+));
+
+?>
+<h3>Exception</h3>
+
+<div class="lithium-exception-class">
+ <?=get_class($exception);?>
+
+ <?php if ($code = $exception->getCode()): ?>
+ <span class="code">(code <?=$code; ?>)</span>
+ <?php endif ?>
+</div>
+
+<div class="lithium-exception-message"><?=$exception->getMessage(); ?></div>
+
+<h3 id="source">Source</h3>
+
+<div id="sourceCode"></div>
+
+<h3>Stack Trace</h3>
+
+<div class="lithium-stack-trace">
+ <ol>
+ <?php foreach ($stack as $id => $frame): ?>
+ <?php
+ $location = "{$frame['file']}: {$frame['line']}";
+ $lines = range($frame['line'] - $context, $frame['line'] + $context);
+ $code = Inspector::lines($frame['file'], $lines);
+ ?>
+ <li>
+ <tt><a href="#source" id="<?=$id; ?>" class="display-source-excerpt">
+ <?=$frame['functionRef']; ?>
+ </a></tt>
+ <div id="sourceCode<?=$id; ?>" style="display: none;">
+
+ <div class="lithium-exception-location">
+ <?=$location; ?>
+ </div>
+
+ <div class="lithium-code-dump">
+ <pre><code><?php
+ foreach ($code as $num => $content):
+ $numPad = str_pad($num, 3, ' ');
+ $content = str_ireplace(array('<?php', '?>'), '', $content);
+ $content = highlight_string("<?php {$numPad}{$content} ?>", true);
+ $content = str_replace($replace, '', $content);
+
+ if ($frame['line'] === $num):
+ ?><span class="code-highlight"><?php
+ endif;?><?php echo "{$content}\n"; ?><?php
+ if ($frame['line'] === $num):
+ ?></span><?php
+ endif;
+
+ endforeach;
+ ?></code></pre>
+ </div>
+ </div>
+ </li>
+ <?php endforeach; ?>
+ </ol>
+</div>
+
+<script type="text/javascript">
+ window.onload = function() {
+ var $ = function() { return document.getElementById.apply(document, arguments); };
+ var links = document.getElementsByTagName('a');
+
+ for (i = 0; i < links.length; i++) {
+ if (links[i].className.indexOf('display-source-excerpt') >= 0) {
+ links[i].onclick = function() {
+ $('sourceCode').innerHTML = $('sourceCode' + this.id).innerHTML;
+ }
+ }
+ }
+ $('sourceCode').innerHTML = $('sourceCode0').innerHTML;
+ }
+</script>
\ No newline at end of file
diff --git a/app/views/layouts/error.html.php b/app/views/layouts/error.html.php
new file mode 100644
index 0000000..2f26d97
--- /dev/null
+++ b/app/views/layouts/error.html.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Lithium: the most rad php framework
+ *
+ * @copyright Copyright 2011, Union of RAD (http://union-of-rad.org)
+ * @license http://opensource.org/licenses/bsd-license.php The BSD License
+ */
+
+/**
+ * This layout is used to render error pages in both development and production. It is recommended
+ * that you maintain a separate, simplified layout for rendering errors that does not involve any
+ * complex logic or dynamic data, which could potentially trigger recursive errors.
+ */
+?>
+<!doctype html>
+<html>
+<head>
+ <?php echo $this->html->charset(); ?>
+ <title>Unhandled exception</title>
+ <?php echo $this->html->style(array('debug', 'lithium')); ?>
+ <?php echo $this->scripts(); ?>
+ <?php echo $this->html->link('Icon', null, array('type' => 'icon')); ?>
+</head>
+<body class="app">
+ <div id="container">
+ <div id="header">
+ <h1>An unhandled exception was thrown</h1>
+ <h3>Configuration</h3>
+ <p>
+ This layout can be changed by modifying
+ <code><?php
+ echo realpath(LITHIUM_APP_PATH . '/views/layouts/error.html.php');
+ ?></code>
+ </p><p>
+ To modify your error-handling configuration, see
+ <code><?php
+ echo realpath(LITHIUM_APP_PATH . '/config/bootstrap/errors.php');
+ ?></code>
+ </p>
+ </div>
+ <div id="content">
+ <?php echo $this->content(); ?>
+ </div>
+ </div>
+</body>
+</html>
\ No newline at end of file
diff --git a/app/webroot/css/debug.css b/app/webroot/css/debug.css
index a9ecb71..ed5c4b8 100644
--- a/app/webroot/css/debug.css
+++ b/app/webroot/css/debug.css
@@ -403,6 +403,16 @@ pre.lithium-debug {
position: relative;
}
+div.lithium-exception-class, div.lithium-exception-location {
+ font-weight: bold;
+}
+
+div.lithium-exception-message {
+ color: #000;
+ background: #f0f0f0;
+ padding: 1em;
+}
+
div.lithium-stack-trace {
background: #fff;
border: 4px dotted #ffcc00;
@@ -440,7 +450,6 @@ div.lithium-code-dump pre, div.lithium-code-dump pre code {
div.lithium-code-dump span.code-highlight {
background-color: #ff0;
- padding: 4px;
}
/*--- Code Coverage Analysis ---*/
diff --git a/libraries/lithium/action/Controller.php b/libraries/lithium/action/Controller.php
index 70f2f4d..db9ab55 100644
--- a/libraries/lithium/action/Controller.php
+++ b/libraries/lithium/action/Controller.php
@@ -174,7 +174,7 @@ class Controller extends \lithium\core\Object {
throw new DispatchException('Attempted to invoke a private method.');
}
if (!method_exists($self, $action)) {
- throw new DispatchException("Action '{$action}' not found.");
+ throw new DispatchException("Action `{$action}` not found.");
}
$render['template'] = $render['template'] ?: $action;
@@ -183,7 +183,9 @@ class Controller extends \lithium\core\Object {
$self->render(array('text' => $result));
return $self->response;
}
- $self->set($result);
+ if (is_array($result)) {
+ $self->set($result);
+ }
}
if (!$render['hasRendered'] && $render['auto']) {
@@ -275,7 +277,13 @@ class Controller extends \lithium\core\Object {
* - `'head'` _boolean_: Determines whether only headers are returned with the
* response. Defaults to `true`, in which case only headers and no body are
* returned. Set to `false` to render a body as well.
+<<<<<<< HEAD
* - `'exit'` _boolean_: Exit immediately after rendering. Defaults to `true`.
+=======
+ * - `'exit'` _boolean_: Exit immediately after rendering. Defaults to `false`.
+ * Because `redirect()` does not exit by default, you should always prefix calls
+ * with a `return` statement, so that the action is always immedately exited.
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
* @return object Returns the instance of the `Response` object associated with this controller.
* @filter This method can be filtered.
*/
diff --git a/libraries/lithium/action/Dispatcher.php b/libraries/lithium/action/Dispatcher.php
index d00dd7d..92a4024 100644
--- a/libraries/lithium/action/Dispatcher.php
+++ b/libraries/lithium/action/Dispatcher.php
@@ -116,7 +116,7 @@ class Dispatcher extends \lithium\core\StaticObject {
$params = $self::applyRules($result->params);
if (!$params) {
- throw new DispatchException('Could not route request');
+ throw new DispatchException('Could not route request.');
}
$callable = $self::invokeMethod('_callable', array($result, $params, $options));
return $self::invokeMethod('_call', array($callable, $result, $params));
@@ -195,7 +195,11 @@ class Dispatcher extends \lithium\core\StaticObject {
try {
return Libraries::instance('controllers', $controller, $options);
} catch (ClassNotFoundException $e) {
+<<<<<<< HEAD
throw new DispatchException("Controller '{$controller}' not found", null, $e);
+=======
+ throw new DispatchException("Controller `{$controller}` not found.", null, $e);
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
}
});
}
@@ -206,7 +210,7 @@ class Dispatcher extends \lithium\core\StaticObject {
if (is_callable($callable = $params['callable'])) {
return $callable($params['request'], $params['params']);
}
- throw new DispatchException('Result not callable');
+ throw new DispatchException('Result not callable.');
});
}
}
diff --git a/libraries/lithium/action/Response.php b/libraries/lithium/action/Response.php
index ab9caad..c64014a 100644
--- a/libraries/lithium/action/Response.php
+++ b/libraries/lithium/action/Response.php
@@ -59,7 +59,11 @@ class Response extends \lithium\net\http\Response {
* @deprecated
*/
public function disableCache() {
+<<<<<<< HEAD
$message = 'Request::disableCache() is deprecated. Please use Request::cache(false).';
+=======
+ $message = '`Request::disableCache()` is deprecated. Please use `Request::cache(false)`.';
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
throw new BadMethodCallException($message);
}
@@ -106,7 +110,7 @@ class Response extends \lithium\net\http\Response {
$code = 302;
}
if (!$status = $this->status($code)) {
- throw new UnexpectedValueException('Invalid status code');
+ throw new UnexpectedValueException('Invalid status code.');
}
$this->_writeHeader($status);
diff --git a/libraries/lithium/action/readme.wiki b/libraries/lithium/action/readme.wiki
old mode 100755
new mode 100644
diff --git a/libraries/lithium/analysis/Debugger.php b/libraries/lithium/analysis/Debugger.php
index 83cb75a..926aecc 100644
--- a/libraries/lithium/analysis/Debugger.php
+++ b/libraries/lithium/analysis/Debugger.php
@@ -8,7 +8,13 @@
namespace lithium\analysis;
+<<<<<<< HEAD
use lithium\util\String;
+=======
+use ReflectionClass;
+use lithium\util\String;
+use lithium\analysis\Inspector;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
/**
* The `Debugger` class provides basic facilities for generating and rendering meta-data about the
@@ -16,6 +22,8 @@ use lithium\util\String;
*/
class Debugger extends \lithium\core\Object {
+ protected static $_closureCache = array();
+
/**
* Outputs a stack trace based on the supplied options.
*
@@ -38,7 +46,8 @@ class Debugger extends \lithium\core\Object {
'start' => 0,
'scope' => array(),
'trace' => array(),
- 'includeScope' => true
+ 'includeScope' => true,
+ 'closures' => true,
);
$options += $defaults;
@@ -68,6 +77,9 @@ class Debugger extends \lithium\core\Object {
}
}
+ if ($options['closures'] && strpos($function, '{closure}') !== false) {
+ $function = static::_closureDef($backtrace[$i], $function);
+ }
if (in_array($function, array('call_user_func_array', 'trigger_error'))) {
continue;
}
@@ -116,6 +128,76 @@ class Debugger extends \lithium\core\Object {
}
return $export;
}
+
+ /**
+ * Locates original location of closures.
+ *
+ * @param mixed $reference File or class name to inspect.
+ * @param integer $callLine Line number of class reference.
+ */
+ protected static function _definition($reference, $callLine) {
+ if (file_exists($reference)) {
+ foreach (array_reverse(token_get_all(file_get_contents($reference))) as $token) {
+ if (!is_array($token) || $token[2] > $callLine) {
+ continue;
+ }
+ if ($token[0] === T_FUNCTION) {
+ return $token[2];
+ }
+ }
+ return;
+ }
+ list($class, $method) = explode('::', $reference);
+
+ if (!class_exists($class)) {
+ return;
+ }
+
+ $classRef = new ReflectionClass($class);
+ $methodInfo = Inspector::info($reference);
+ $methodDef = join("\n", Inspector::lines($classRef->getFileName(), range(
+ $methodInfo['start'] + 1, $methodInfo['end'] - 1
+ )));
+
+ foreach (array_reverse(token_get_all("<?php {$methodDef} ?>")) as $token) {
+ if (!is_array($token) || $token[2] > $callLine) {
+ continue;
+ }
+ if ($token[0] === T_FUNCTION) {
+ return $token[2] + $methodInfo['start'];
+ }
+ }
+ }
+
+ protected static function _closureDef($frame, $function) {
+ $reference = '::';
+ $frame += array('file' => '??', 'line' => '??');
+ $cacheKey = "{$frame['file']}@{$frame['line']}";
+
+ if (isset(static::$_closureCache[$cacheKey])) {
+ return static::$_closureCache[$cacheKey];
+ }
+
+ if ($class = Inspector::classes(array('file' => $frame['file']))) {
+ foreach (Inspector::methods(key($class), 'extents') as $method => $extents) {
+ $line = $frame['line'];
+
+ if (!($extents[0] <= $line && $line <= $extents[1])) {
+ continue;
+ }
+ $class = key($class);
+ $reference = "{$class}::{$method}";
+ $function = "{$reference}()::{closure}";
+ break;
+ }
+ } else {
+ $reference = $frame['file'];
+ $function = "{$reference}::{closure}";
+ }
+ $line = static::_definition($reference, $frame['line']) ?: '?';
+ $function .= " @ {$line}";
+ return static::$_closureCache[$cacheKey] = $function;
+ }
}
?>
\ No newline at end of file
diff --git a/libraries/lithium/analysis/Inspector.php b/libraries/lithium/analysis/Inspector.php
index 6684e9f..c84b5f2 100644
--- a/libraries/lithium/analysis/Inspector.php
+++ b/libraries/lithium/analysis/Inspector.php
@@ -383,18 +383,22 @@ class Inspector extends \lithium\core\StaticObject {
$options += $defaults;
$list = get_declared_classes();
+ $files = get_included_files();
$classes = array();
- if (!empty($options['file'])) {
+ if ($file = $options['file']) {
$loaded = static::_instance('collection', array('data' => array_map(
function($class) { return new ReflectionClass($class); }, $list
)));
+ $classFiles = $loaded->getFileName();
- if (!in_array($options['file'], $loaded->getFileName())) {
- include $options['file'];
+ if (in_array($file, $files) && !in_array($file, $classFiles)) {
+ return array();
+ }
+ if (!in_array($file, $classFiles)) {
+ include $file;
$list = array_diff(get_declared_classes(), $list);
} else {
- $file = $options['file'];
$filter = function($class) use ($file) { return $class->getFileName() == $file; };
$list = $loaded->find($filter)->getName();
}
@@ -468,7 +472,7 @@ class Inspector extends \lithium\core\StaticObject {
*/
protected static function _class($class) {
if (!class_exists($class)) {
- throw new RuntimeException(sprintf('Class "%s" could not be found.', $class));
+ throw new RuntimeException(sprintf('Class `%s` could not be found.', $class));
}
return unserialize(sprintf('O:%d:"%s":0:{}', strlen($class), $class));
}
diff --git a/libraries/lithium/analysis/Logger.php b/libraries/lithium/analysis/Logger.php
index 24567dc..453df80 100644
--- a/libraries/lithium/analysis/Logger.php
+++ b/libraries/lithium/analysis/Logger.php
@@ -8,7 +8,7 @@
namespace lithium\analysis;
-use \UnexpectedValueException;
+use UnexpectedValueException;
/**
* The `Logger` class provides a consistent, application-wide interface for configuring and writing
@@ -105,7 +105,7 @@ class Logger extends \lithium\core\Adaptable {
if ($name = $options['name']) {
$methods = array($name => static::adapter($name)->write($priority, $message, $options));
} elseif (!isset(static::$_priorities[$priority])) {
- $message = "Attempted to write log message with invalid priority '{$priority}'.";
+ $message = "Attempted to write log message with invalid priority `{$priority}`.";
throw new UnexpectedValueException($message);
} else {
$methods = static::_configsByPriority($priority, $message, $options);
@@ -114,7 +114,11 @@ class Logger extends \lithium\core\Adaptable {
foreach ($methods as $name => $method) {
$params = compact('priority', 'message', 'options');
$config = static::_config($name);
+<<<<<<< HEAD
$result = $result && static::_filter(__FUNCTION__, $params, $method, $config['filters']);
+=======
+ $result &= static::_filter(__FUNCTION__, $params, $method, $config['filters']);
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
}
return $methods ? $result : false;
}
diff --git a/libraries/lithium/analysis/logger/adapter/Growl.php b/libraries/lithium/analysis/logger/adapter/Growl.php
index 335fd50..907685d 100755
--- a/libraries/lithium/analysis/logger/adapter/Growl.php
+++ b/libraries/lithium/analysis/logger/adapter/Growl.php
@@ -90,7 +90,7 @@ class Growl extends \lithium\core\Object {
if ($conn = fsockopen($host, $port, $message, $code)) {
return $conn;
}
- throw new NetworkException("Growl connection failed: ({$code}) {$message}");
+ throw new NetworkException("Growl connection failed: (`{$code}`) `{$message}`.");
}
);
parent::__construct($config + $defaults);
diff --git a/libraries/lithium/console/Dispatcher.php b/libraries/lithium/console/Dispatcher.php
index 24152e3..435b01e 100755
--- a/libraries/lithium/console/Dispatcher.php
+++ b/libraries/lithium/console/Dispatcher.php
@@ -130,7 +130,7 @@ class Dispatcher extends \lithium\core\StaticObject {
if (class_exists($class = Libraries::locate('command', $name))) {
return new $class(compact('request'));
}
- throw new UnexpectedValueException("Command `{$name}` not found");
+ throw new UnexpectedValueException("Command `{$name}` not found.");
});
}
@@ -191,7 +191,7 @@ class Dispatcher extends \lithium\core\StaticObject {
}
return $callable($params['action'], $params['args']);
}
- throw new UnexpectedValueException("{$callable} not callable");
+ throw new UnexpectedValueException("Callable `{$callable}` is actually not callable.");
});
}
}
diff --git a/libraries/lithium/console/Request.php b/libraries/lithium/console/Request.php
index 2886776..dd4a1f4 100644
--- a/libraries/lithium/console/Request.php
+++ b/libraries/lithium/console/Request.php
@@ -44,7 +44,7 @@ class Request extends \lithium\core\Object {
* Enviroment variables.
*
* @var array
- **/
+ */
protected $_env = array();
/**
diff --git a/libraries/lithium/console/Response.php b/libraries/lithium/console/Response.php
index eeb1b6b..ba39290 100644
--- a/libraries/lithium/console/Response.php
+++ b/libraries/lithium/console/Response.php
@@ -21,14 +21,14 @@ class Response extends \lithium\core\Object {
* Output stream, STDOUT
*
* @var stream
- **/
+ */
public $output = null;
/**
* Error stream, STDERR
*
* @var stream
- **/
+ */
public $error = null;
/**
@@ -94,7 +94,7 @@ class Response extends \lithium\core\Object {
*
* @return void
*
- **/
+ */
public function __destruct() {
if ($this->output) {
fclose($this->output);
diff --git a/libraries/lithium/console/Router.php b/libraries/lithium/console/Router.php
index 398410c..1018169 100644
--- a/libraries/lithium/console/Router.php
+++ b/libraries/lithium/console/Router.php
@@ -21,7 +21,7 @@ class Router extends \lithium\core\Object {
* @param object $request lithium\console\Request
* @return array $params
*
- **/
+ */
public static function parse($request = null) {
$params = array(
'command' => null, 'action' => 'run', 'args' => array()
diff --git a/libraries/lithium/console/command/Library.php b/libraries/lithium/console/command/Library.php
index 1f9f47d..b89bd43 100644
--- a/libraries/lithium/console/command/Library.php
+++ b/libraries/lithium/console/command/Library.php
@@ -214,7 +214,7 @@ class Library extends \lithium\console\Command {
*/
public function archive($name = null, $result = null) {
if (ini_get('phar.readonly') == '1') {
- throw new RuntimeException('set phar.readonly = 0 in php.ini');
+ throw new RuntimeException('Set `phar.readonly` to `0` in `php.ini`.');
}
$from = $name;
$to = $name;
diff --git a/libraries/lithium/console/command/Test.php b/libraries/lithium/console/command/Test.php
index 21b0848..59b7609 100644
--- a/libraries/lithium/console/command/Test.php
+++ b/libraries/lithium/console/command/Test.php
@@ -11,7 +11,10 @@ namespace lithium\console\command;
use lithium\core\Libraries;
use lithium\test\Group;
use lithium\test\Dispatcher;
+<<<<<<< HEAD
use lithium\analysis\Inspector;
+=======
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
/**
* Runs a given set of tests and outputs the results.
@@ -110,7 +113,7 @@ class Test extends \lithium\console\Command {
$classes = Libraries::find(true, array(
'recursive' => true,
- 'exclude' => '/\w+Test$|webroot|index$|^app\\\\config|^app\\\\views/'
+ 'exclude' => '/tests|resources|webroot|index$|^app\\\\config|^app\\\\views/'
));
$tests = Group::all();
$classes = array_diff($classes, $tests);
diff --git a/libraries/lithium/console/command/create/Controller.php b/libraries/lithium/console/command/create/Controller.php
index 5aaaffb..e29ee03 100644
--- a/libraries/lithium/console/command/create/Controller.php
+++ b/libraries/lithium/console/command/create/Controller.php
@@ -27,7 +27,7 @@ class Controller extends \lithium\console\command\Create {
*/
protected function _use($request) {
$request->params['command'] = 'model';
- return '\\' . $this->_namespace($request) . '\\' . $this->_model($request);
+ return $this->_namespace($request) . '\\' . $this->_model($request);
}
/**
diff --git a/libraries/lithium/console/command/create/Test.php b/libraries/lithium/console/command/create/Test.php
index f76f685..74af250 100644
--- a/libraries/lithium/console/command/create/Test.php
+++ b/libraries/lithium/console/command/create/Test.php
@@ -40,9 +40,13 @@ class Test extends \lithium\console\command\Create {
* @return string
*/
protected function _use($request) {
+<<<<<<< HEAD
$namespace = parent::_namespace($request);
$name = $this->_name($request);
return "\\{$namespace}\\{$name}";
+=======
+ return parent::_namespace($request) . '\\' . $this->_name($request);
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
}
/**
diff --git a/libraries/lithium/core/Adaptable.php b/libraries/lithium/core/Adaptable.php
index 0e6a4bd..ee235e6 100644
--- a/libraries/lithium/core/Adaptable.php
+++ b/libraries/lithium/core/Adaptable.php
@@ -101,7 +101,7 @@ class Adaptable extends \lithium\core\StaticObject {
$config = static::_config($name);
if ($config === null) {
- throw new ConfigException("Configuration '{$name}' has not been defined.");
+ throw new ConfigException("Configuration `{$name}` has not been defined.");
}
if (isset($config['object'])) {
@@ -126,7 +126,7 @@ class Adaptable extends \lithium\core\StaticObject {
$config = static::_config($name);
if ($config === null) {
- throw new ConfigException("Configuration '{$name}' has not been defined.");
+ throw new ConfigException("Configuration `{$name}` has not been defined.");
}
if (!isset($config['strategies'])) {
return null;
@@ -213,11 +213,11 @@ class Adaptable extends \lithium\core\StaticObject {
protected static function _class($config, $paths = array()) {
if (!$name = $config['adapter']) {
$self = get_called_class();
- throw new ConfigException("No adapter set for configuration in class {$self}.");
+ throw new ConfigException("No adapter set for configuration in class `{$self}`.");
}
if (!$class = static::_locate($paths, $name)) {
$self = get_called_class();
- throw new ConfigException("Could not find adapter '{$name}' in class {$self}.");
+ throw new ConfigException("Could not find adapter `{$name}` in class `{$self}`.");
}
return $class;
}
@@ -233,11 +233,11 @@ class Adaptable extends \lithium\core\StaticObject {
protected static function _strategy($name, $paths = array()) {
if (!$name) {
$self = get_called_class();
- throw new ConfigException("No strategy set for configuration in class {$self}.");
+ throw new ConfigException("No strategy set for configuration in class `{$self}`.");
}
if (!$class = static::_locate($paths, $name)) {
$self = get_called_class();
- throw new ConfigException("Could not find strategy '{$name}' in class {$self}.");
+ throw new ConfigException("Could not find strategy `{$name}` in class `{$self}`.");
}
return $class;
}
@@ -281,6 +281,10 @@ class Adaptable extends \lithium\core\StaticObject {
}
$env = Environment::get();
$config = isset($settings[$env]) ? $settings[$env] : $settings;
+
+ if (isset($settings[$env]) && isset($settings[true])) {
+ $config += $settings[true];
+ }
static::$_configurations[$name] += array(static::_initConfig($name, $config));
return static::$_configurations[$name][0];
}
diff --git a/libraries/lithium/core/ErrorHandler.php b/libraries/lithium/core/ErrorHandler.php
index 9434bc5..650da84 100644
--- a/libraries/lithium/core/ErrorHandler.php
+++ b/libraries/lithium/core/ErrorHandler.php
@@ -9,8 +9,13 @@
namespace lithium\core;
use Exception;
+<<<<<<< HEAD
use lithium\util\Collection;
use lithium\core\Environment;
+=======
+use ErrorException;
+use lithium\util\collection\Filters;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
/**
* The `ErrorHandler` class allows PHP errors and exceptions to be handled in a uniform way. Using
@@ -61,6 +66,8 @@ class ErrorHandler extends \lithium\core\StaticObject {
*/
protected static $_isRunning = false;
+ protected static $_runOptions = array();
+
/**
* Setup basic error handling checks/types, as well as register the error and exception
* hanlders.
@@ -72,21 +79,15 @@ class ErrorHandler extends \lithium\core\StaticObject {
public static function __init() {
static::$_checks = array(
'type' => function($config, $info) {
- return (
- $config['type'] == $info['type'] ||
- is_subclass_of($info['type'], $config['type'])
- );
+ return (boolean) array_filter((array) $config['type'], function($type) use ($info) {
+ return $type == $info['type'] || is_subclass_of($info['type'], $type);
+ });
},
'code' => function($config, $info) {
return ($config['code'] & $info['code']);
},
'stack' => function($config, $info) {
- foreach ((array) $config['stack'] as $frame) {
- if (in_array($frame, $info['stack'])) {
- return true;
- }
- }
- return false;
+ return (boolean) array_intersect((array) $config['stack'], $info['stack']);
},
'message' => function($config, $info) {
return preg_match($config['message'], $info['message']);
@@ -95,16 +96,15 @@ class ErrorHandler extends \lithium\core\StaticObject {
$self = get_called_class();
static::$_exceptionHandler = function($exception, $return = false) use ($self) {
- $info = array('type' => get_class($exception)) + compact('exception');
-
+ $info = compact('exception') + array(
+ 'type' => get_class($exception),
+ 'stack' => $self::trace($exception->getTrace())
+ );
foreach (array('message', 'file', 'line', 'trace') as $key) {
$method = 'get' . ucfirst($key);
$info[$key] = $exception->{$method}();
}
- if ($return) {
- return $info;
- }
- $self::invokeMethod('handle', array($info));
+ return $return ? $info : $self::handle($info);
};
}
@@ -141,18 +141,32 @@ class ErrorHandler extends \lithium\core\StaticObject {
*
* @return void
*/
- public static function run() {
+ public static function run(array $config = array()) {
+ $defaults = array('trapErrors' => false, 'convertErrors' => true);
+
+ if (static::$_isRunning) {
+ return;
+ }
+ static::$_isRunning = true;
+ static::$_runOptions = $config + $defaults;
$self = get_called_class();
- set_error_handler(function($code, $message, $file, $line = 0, $context = null) use ($self) {
+ $trap = function($code, $message, $file, $line = 0, $context = null) use ($self) {
$trace = debug_backtrace();
$trace = array_slice($trace, 1, count($trace));
- $self::invokeMethod('handle', array(
- compact('type', 'code', 'message', 'file', 'line', 'trace', 'context')
- ));
- });
+ $self::handle(compact('type', 'code', 'message', 'file', 'line', 'trace', 'context'));
+ };
+
+ $convert = function($code, $message, $file, $line = 0, $context = null) use ($self) {
+ throw new ErrorException($message, 500, $code, $file, $line);
+ };
+
+ if (static::$_runOptions['trapErrors']) {
+ set_error_handler($trap);
+ } elseif (static::$_runOptions['convertErrors']) {
+ set_error_handler($convert);
+ }
set_exception_handler(static::$_exceptionHandler);
- static::$_isRunning = true;
}
/**
@@ -212,7 +226,7 @@ class ErrorHandler extends \lithium\core\StaticObject {
);
$info = (array) $info + $defaults;
- $info['stack'] = static::_trace($info['trace']);
+ $info['stack'] = static::trace($info['trace']);
$info['origin'] = static::_origin($info['trace']);
foreach ($rules as $config) {
@@ -245,7 +259,11 @@ class ErrorHandler extends \lithium\core\StaticObject {
/**
* Determine frame from the stack trace where the error/exception was first generated.
*
+<<<<<<< HEAD
* @var array $stack Stack trace from error/exception that was produced.
+=======
+ * @param array $stack Stack trace from error/exception that was produced.
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
* @return string Class where error/exception was generated.
*/
protected static function _origin(array $stack) {
@@ -256,22 +274,40 @@ class ErrorHandler extends \lithium\core\StaticObject {
}
}
+<<<<<<< HEAD
public static function apply($class, $method, array $conditions, $handler) {
$_self = get_called_class();
$filter = function($self, $params, $chain) use ($_self, $conditions, $handler) {
+=======
+ public static function apply($object, array $conditions, $handler) {
+ $conditions = $conditions ?: array('type' => 'Exception');
+ list($class, $method) = is_string($object) ? explode('::', $object) : $object;
+ $wrap = static::$_exceptionHandler;
+ $_self = get_called_class();
+
+ $filter = function($self, $params, $chain) use ($_self, $conditions, $handler, $wrap) {
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
try {
return $chain->next($self, $params, $chain);
} catch (Exception $e) {
if (!$_self::matches($e, $conditions)) {
throw $e;
}
+<<<<<<< HEAD
return $handler($e, $params);
+=======
+ return $handler($wrap($e, true), $params);
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
}
};
if (is_string($class)) {
+<<<<<<< HEAD
$class::applyFilter($method, $filter);
+=======
+ Filters::apply($class, $method, $filter);
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
} else {
$class->applyFilter($method, $filter);
}
@@ -302,10 +338,14 @@ class ErrorHandler extends \lithium\core\StaticObject {
/**
* Trim down a typical stack trace to class & method calls.
*
+<<<<<<< HEAD
* @var array $stack A `debug_backtrace()`-compatible stack trace output.
+=======
+ * @param array $stack A `debug_backtrace()`-compatible stack trace output.
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
* @return array Returns a flat stack array containing class and method references.
*/
- protected static function _trace(array $stack) {
+ public static function trace(array $stack) {
$result = array();
foreach ($stack as $frame) {
diff --git a/libraries/lithium/core/Libraries.php b/libraries/lithium/core/Libraries.php
index 79d6fc0..8e8a67a 100644
--- a/libraries/lithium/core/Libraries.php
+++ b/libraries/lithium/core/Libraries.php
@@ -280,7 +280,11 @@ class Libraries {
if (!$config['path']) {
if (!$config['path'] = static::_locatePath('libraries', compact('name'))) {
+<<<<<<< HEAD
throw new ConfigException("Library '{$name}' not found.");
+=======
+ throw new ConfigException("Library `{$name}` not found.");
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
}
}
$config['path'] = str_replace('\\', '/', $config['path']);
@@ -428,7 +432,7 @@ class Libraries {
static::$_cachedPaths[$class] = $path;
method_exists($class, '__init') ? $class::__init() : null;
} elseif ($require) {
- throw new RuntimeException("Failed to load {$class} from {$path}");
+ throw new RuntimeException("Failed to load class `{$class}` from path `{$path}`.");
}
}
@@ -470,15 +474,50 @@ class Libraries {
$fullPath = "{$params['path']}/{$path}";
if (!$options['dirs']) {
- return static::$_cachedPaths[$class] = realpath($fullPath . $suffix);
+ return static::$_cachedPaths[$class] = static::realPath($fullPath . $suffix);
}
$list = glob(dirname($fullPath) . '/*');
$list = array_map(function($i) { return str_replace('\\', '/', $i); }, $list);
if (in_array($fullPath . $suffix, $list)) {
- return static::$_cachedPaths[$class] = realpath($fullPath . $suffix);
+ return static::$_cachedPaths[$class] = static::realPath($fullPath . $suffix);
+ }
+ return is_dir($fullPath) ? static::realPath($fullPath) : null;
+ }
+ }
+
+ /**
+ * Wraps the PHP `realpath()` function to add support for finding paths to files inside Phar
+ * archives.
+ *
+ * @param string $path An unresolved path to a file inside a Phar archive which may or may not
+ * exist.
+ * @return string If `$path` is a valid path to a file inside a Phar archive, returns a string
+ * in the format `'phar://<path-to-phar>/<path-to-file>'`. Otherwise returns
+ * `null`.
+ */
+ public static function realPath($path) {
+ if (($absolutePath = realpath($path)) !== false) {
+ return $absolutePath;
+ }
+ if (!preg_match('%^phar://([^.]+\.phar(?:\.gz)?)(.+)%', $path, $pathComponents)) {
+ return;
+ }
+ list(, $relativePath, $pharPath) = $pathComponents;
+
+ $pharPath = implode('/', array_reduce(explode('/', $pharPath), function ($parts, $value) {
+ if ($value == '..') {
+ array_pop($parts);
+ } elseif ($value != '.') {
+ $parts[] = $value;
+ }
+ return $parts;
+ }));
+
+ if (($resolvedPath = realpath($relativePath)) !== false) {
+ if (file_exists($absolutePath = "phar://{$resolvedPath}{$pharPath}")) {
+ return $absolutePath;
}
- return is_dir($fullPath) ? realpath($fullPath) : null;
}
}
@@ -526,7 +565,7 @@ class Libraries {
*/
public static function instance($type, $name, array $options = array()) {
if (!$class = (string) static::locate($type, $name)) {
- throw new ClassNotFoundException("Class '{$name}' of type '{$type}' not found.");
+ throw new ClassNotFoundException("Class `{$name}` of type `{$type}` not found.");
}
return class_exists($class) ? new $class($options) : null;
}
@@ -590,6 +629,10 @@ class Libraries {
return $name;
}
$ident = $name ? ($type . '.' . $name) : ($type . '.*');
+<<<<<<< HEAD
+=======
+ $ident .= $options ? '.' . md5(serialize($options)) : null;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
if (isset(static::$_cachedPaths[$ident])) {
return static::$_cachedPaths[$ident];
@@ -804,10 +847,17 @@ class Libraries {
$queue = array_merge($queue, array_diff((array) glob("{$dir}/*", $dFlags), $libs));
}
$libs = preg_grep($match, $libs);
+<<<<<<< HEAD
+ }
+ if ($suffix) {
+ $libs = $options['preFilter'] ? preg_grep($options['preFilter'], $libs) : $libs;
+ }
+=======
}
if ($suffix) {
$libs = $options['preFilter'] ? preg_grep($options['preFilter'], $libs) : $libs;
}
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
return static::_filter($libs, (array) $config, $options + compact('name'));
}
diff --git a/libraries/lithium/data/Collection.php b/libraries/lithium/data/Collection.php
index 39e9b00..e2e9345 100644
--- a/libraries/lithium/data/Collection.php
+++ b/libraries/lithium/data/Collection.php
@@ -166,10 +166,10 @@ abstract class Collection extends \lithium\util\Collection {
}
/**
- * Returns a boolean indicating whether an offset exists for the
+ * Returns a boolean indicating whether an offset exists for the
* current `Collection`.
*
- * @param string $offset String or integer indicating the offset or
+ * @param string $offset String or integer indicating the offset or
* index of an entity in the set.
* @return boolean Result.
*/
diff --git a/libraries/lithium/data/Entity.php b/libraries/lithium/data/Entity.php
index 1f32c67..23903f3 100644
--- a/libraries/lithium/data/Entity.php
+++ b/libraries/lithium/data/Entity.php
@@ -211,7 +211,11 @@ class Entity extends \lithium\core\Object {
*/
public function __call($method, $params) {
if (!($model = $this->_model) || !method_exists($model, $method)) {
+<<<<<<< HEAD
$message = "No model bound or unhandled method call '{$method}'.";
+=======
+ $message = "No model bound or unhandled method call `{$method}`.";
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
throw new BadMethodCallException($message);
}
array_unshift($params, $this);
diff --git a/libraries/lithium/data/Model.php b/libraries/lithium/data/Model.php
index 810506f..15f58c8 100755
--- a/libraries/lithium/data/Model.php
+++ b/libraries/lithium/data/Model.php
@@ -321,9 +321,13 @@ class Model extends \lithium\core\StaticObject {
if (static::_isBase($class = get_called_class())) {
return;
}
+<<<<<<< HEAD
$self = static::_object();
$base = get_class_vars(__CLASS__);
+=======
+ $self = static::_object();
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
$meta = array();
$schema = array();
$source = array();
@@ -342,6 +346,7 @@ class Model extends \lithium\core\StaticObject {
}
}
$tmp = $options + $self->_meta + $meta;
+<<<<<<< HEAD
if ($tmp['connection']) {
$conn = $classes['connections']::get($tmp['connection']);
@@ -352,6 +357,18 @@ class Model extends \lithium\core\StaticObject {
$name = static::_name();
$local = compact('class', 'name') + $options + array_diff($self->_meta, $base['_meta']);
+=======
+ $source = array('meta' => array(), 'finders' => array(), 'schema' => array());
+
+ if ($tmp['connection']) {
+ $conn = $classes['connections']::get($tmp['connection']);
+ $source = (($conn) ? $conn->configureClass($class) : array()) + $source;
+ }
+ static::$_classes = $classes;
+ $name = static::_name();
+
+ $local = compact('class', 'name') + $options + $self->_meta;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
$self->_meta = ($local + $source['meta'] + $meta);
$self->_meta['initialized'] = false;
$self->_schema += $schema + $source['schema'];
@@ -389,7 +406,7 @@ class Model extends \lithium\core\StaticObject {
preg_match('/^findBy(?P<field>\w+)$|^find(?P<type>\w+)By(?P<fields>\w+)$/', $method, $args);
if (!$args) {
- $message = "Method %s not defined or handled in class %s";
+ $message = "Method `%s` not defined or handled in class `%s`.";
throw new BadMethodCallException(sprintf($message, $method, get_class($self)));
}
$field = Inflector::underscore($args['field'] ? $args['field'] : $args['fields']);
@@ -445,7 +462,11 @@ class Model extends \lithium\core\StaticObject {
$type = 'first';
}
+<<<<<<< HEAD
$options += ((array) $self->_query + (array) $defaults);
+=======
+ $options = (array) $options + (array) $self->_query + (array) $defaults;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
$meta = array('meta' => $self->_meta, 'name' => get_called_class());
$params = compact('type', 'options');
@@ -572,7 +593,7 @@ class Model extends \lithium\core\StaticObject {
$self = static::_object();
if (!isset($self->_relationTypes[$type])) {
- throw new ConfigException("Invalid relationship type '{$type}' specified.");
+ throw new ConfigException("Invalid relationship type `{$type}` specified.");
}
$rel = static::connection()->relationship(get_called_class(), $type, $name, $config);
return static::_object()->_relations[$name] = $rel;
@@ -770,7 +791,7 @@ class Model extends \lithium\core\StaticObject {
};
if (!$options['callbacks']) {
- return $filter($entity, $options);
+ return $filter($entity, $params);
}
return static::_filter(__FUNCTION__, $params, $filter);
}
@@ -895,7 +916,17 @@ class Model extends \lithium\core\StaticObject {
if ($conn = $connections::get($name)) {
return $conn;
}
- throw new ConfigException("The data connection {$name} is not configured");
+ throw new ConfigException("The data connection `{$name}` is not configured.");
+ }
+
+ /**
+ * Gets just the class name portion of a fully-name-spaced class name, i.e.
+ * `app\models\Posts::_name()` returns `'Posts'`.
+ *
+ * @return string
+ */
+ protected static function _name() {
+ return basename(str_replace('\\', '/', get_called_class()));
}
/**
diff --git a/libraries/lithium/data/entity/Document.php b/libraries/lithium/data/entity/Document.php
index 34187d2..78a4a5c 100644
--- a/libraries/lithium/data/entity/Document.php
+++ b/libraries/lithium/data/entity/Document.php
@@ -104,6 +104,7 @@ class Document extends \lithium\data\Entity implements \Iterator, \ArrayAccess {
protected function _init() {
parent::_init();
+<<<<<<< HEAD
$this->_data = (array) $this->_data;
if ($model = $this->_model) {
@@ -116,6 +117,17 @@ class Document extends \lithium\data\Entity implements \Iterator, \ArrayAccess {
$options = compact('pathKey', 'schema');
$this->_data = $model::connection()->cast($this, $this->_data, $options);
}
+=======
+ $data = (array) $this->_data;
+ $this->_data = array();
+ $this->set($data);
+ $exists = $this->_exists;
+
+ $this->_data = $this->_updated;
+ $this->_updated = array();
+ $this->update();
+ $this->_exists = $exists;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
unset($this->_autoConfig);
}
@@ -176,11 +188,15 @@ class Document extends \lithium\data\Entity implements \Iterator, \ArrayAccess {
$this->_updated[$key]->_exists = false;
}
}
+<<<<<<< HEAD
return parent::export() + array(
'key' => $this->_pathKey,
'remove' => $this->_removed,
);
+=======
+ return parent::export() + array('key' => $this->_pathKey, 'remove' => $this->_removed);
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
}
public function update($id = null, array $data = array()) {
@@ -191,6 +207,10 @@ class Document extends \lithium\data\Entity implements \Iterator, \ArrayAccess {
$this->_data[$key]->update(null, isset($data[$key]) ? $data[$key] : array());
}
}
+<<<<<<< HEAD
+=======
+ $this->_removed = array();
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
}
/**
@@ -264,7 +284,11 @@ class Document extends \lithium\data\Entity implements \Iterator, \ArrayAccess {
return $this->_setNested($name, $value);
}
if ($model = $this->_model) {
+<<<<<<< HEAD
$pathKey = $this->_pathKey ? $this->_pathKey . '.' : '';
+=======
+ $pathKey = $this->_pathKey;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
$options = compact('pathKey') + array('first' => true);
$value = $model::connection()->cast($this, array($name => $value), $options);
}
@@ -287,12 +311,21 @@ class Document extends \lithium\data\Entity implements \Iterator, \ArrayAccess {
} else {
unset($next);
$next = null;
+<<<<<<< HEAD
}
if ($next === null && ($model = $this->_model)) {
$current->_data[$key] = $model::connection()->item($model);
$next =& $current->_data[$key];
}
+=======
+ }
+
+ if ($next === null && ($model = $this->_model)) {
+ $current->__set($key, $model::connection()->item($model));
+ $next =& $current->{$key};
+ }
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
$current =& $next;
}
@@ -327,6 +360,10 @@ class Document extends \lithium\data\Entity implements \Iterator, \ArrayAccess {
*/
public function __unset($name) {
$this->_removed[$name] = true;
+<<<<<<< HEAD
+=======
+ unset($this->_updated[$name]);
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
}
/**
@@ -481,9 +518,15 @@ class Document extends \lithium\data\Entity implements \Iterator, \ArrayAccess {
* @param string $field The name of the field to be incrememnted.
* @param string $value The value to increment the field by. Defaults to `1` if this parameter
* is not specified.
+<<<<<<< HEAD
* @return int Returns the current value of `$field`, based on the value retrieved from the data
* source when the entity was loaded, plus any increments applied. Note that it may not
* reflect the most current value in the persistent backend data source.
+=======
+ * @return integer Returns the current value of `$field`, based on the value retrieved from the
+ * data source when the entity was loaded, plus any increments applied. Note that it
+ * may not reflect the most current value in the persistent backend data source.
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
* @throws UnexpectedValueException Throws an exception when `$field` is set to a non-numeric
* type.
*/
@@ -494,7 +537,11 @@ class Document extends \lithium\data\Entity implements \Iterator, \ArrayAccess {
$this->_increment[$field] += $value;
if (!is_numeric($this->_data[$field])) {
+<<<<<<< HEAD
throw new UnexpectedValueException("Field '{$field}' cannot be incremented.");
+=======
+ throw new UnexpectedValueException("Field `{$field}` cannot be incremented.");
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
}
$this->_data[$field] += $value;
}
diff --git a/libraries/lithium/data/model/Query.php b/libraries/lithium/data/model/Query.php
index 5989d4f..49a3ee8 100644
--- a/libraries/lithium/data/model/Query.php
+++ b/libraries/lithium/data/model/Query.php
@@ -84,6 +84,7 @@ class Query extends \lithium\core\Object {
'calculate' => null,
'conditions' => array(),
'fields' => array(),
+ 'data' => array(),
'model' => null,
'alias' => null,
'source' => null,
@@ -117,6 +118,15 @@ class Query extends \lithium\core\Object {
if ($this->_config['with']) {
$this->_associate($this->_config['with']);
}
+<<<<<<< HEAD
+=======
+ $joins = $this->_config['joins'];
+ $this->_config['joins'] = array();
+
+ foreach ($joins as $i => $join) {
+ $this->join($i, $join);
+ }
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
if ($this->_entity && !$this->_config['model']) {
$this->model($this->_entity->model());
}
@@ -136,6 +146,10 @@ class Query extends \lithium\core\Object {
* Generates a schema map of the query's result set, where the keys are fully-namespaced model
* class names, and the values are arrays of field names.
*
+<<<<<<< HEAD
+=======
+ * @param array $map
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
* @return array
*/
public function map($map = null) {
@@ -361,11 +375,21 @@ class Query extends \lithium\core\Object {
* @return array of query objects
*/
public function join($name = null, $join = null) {
+<<<<<<< HEAD
+=======
+ if (is_scalar($name) && !$join && isset($this->_config['joins'][$name])) {
+ return $this->_config['joins'][$name];
+ }
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
if ($name && !$join) {
$join = $name;
$name = null;
}
if ($join) {
+<<<<<<< HEAD
+=======
+ $join = is_array($join) ? $this->_instance(get_class($this), $join) : $join;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
$name ? $this->_config['joins'][$name] = $join : $this->_config['joins'][] = $join;
return $this;
}
@@ -397,6 +421,7 @@ class Query extends \lithium\core\Object {
if (in_array($item, $keys)) {
$results[$item] = $this->_config[$item];
}
+<<<<<<< HEAD
}
$entity =& $this->_entity;
$data = $this->_data;
@@ -415,6 +440,18 @@ class Query extends \lithium\core\Object {
if (!isset($results['fields'])) {
return $results;
}
+=======
+ }
+ if (in_array('data', $keys)) {
+ $results['data'] = $this->_exportData();
+ }
+ if (isset($results['source'])) {
+ $results['source'] = $dataSource->name($results['source']);
+ }
+ if (!isset($results['fields'])) {
+ return $results;
+ }
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
$created = array('fields', 'values');
if (is_array($results['fields']) && array_keys($results['fields']) == $created) {
@@ -423,6 +460,35 @@ class Query extends \lithium\core\Object {
return $results;
}
+<<<<<<< HEAD
+=======
+ /**
+ * Helper method used by `export()` to extract the data either from a bound entity, or from
+ * passed configuration, and filter it through a configured whitelist, if present.
+ *
+ * @return array
+ */
+ protected function _exportData() {
+ $data = $this->_entity ? $this->_entity->export() : $this->_data;
+
+ if (!$list = $this->_config['whitelist']) {
+ return $data;
+ }
+ $list = array_combine($list, $list);
+
+ if (!$this->_entity) {
+ return array_intersect_key($data, $list);
+ }
+ foreach ($data as $type => $values) {
+ if (!is_array($values)) {
+ continue;
+ }
+ $data[$type] = array_intersect_key($values, $list);
+ }
+ return $data;
+ }
+
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
public function schema($field = null) {
if (is_array($field)) {
$this->_config['schema'] = $field;
@@ -500,7 +566,7 @@ class Query extends \lithium\core\Object {
$config = array();
}
if (!$relation = $model::relations($name)) {
- throw new QueryException("Related model not found");
+ throw new QueryException("Related model not found.");
}
$config += $relation->data();
}
diff --git a/libraries/lithium/data/source/Database.php b/libraries/lithium/data/source/Database.php
index c1f40fb..1b09dae 100755
--- a/libraries/lithium/data/source/Database.php
+++ b/libraries/lithium/data/source/Database.php
@@ -43,7 +43,11 @@ abstract class Database extends \lithium\data\Source {
'update' => "UPDATE {:source} SET {:fields} {:conditions};{:comment}",
'delete' => "DELETE {:flags} FROM {:source} {:alias} {:conditions};{:comment}",
'schema' => "CREATE TABLE {:source} (\n{:columns}{:indexes});{:comment}",
+<<<<<<< HEAD
'join' => "{:type} JOIN {:source} {:alias} {:constraint} {:conditions}"
+=======
+ 'join' => "{:type} JOIN {:source} {:alias} {:constraint}"
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
);
/**
@@ -273,8 +277,13 @@ abstract class Database extends \lithium\data\Source {
while ($data = $result->next()) {
// @hack: Fix this to support relationships
+<<<<<<< HEAD
if ((count($columns) != count($data) && isset($columns[0])) || is_array($columns[0])) {
$columns = $columns[0];
+=======
+ if (count($columns) != count($data) && is_array(current($columns))) {
+ $columns = current($columns);
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
}
$records[] = array_combine($columns, $data);
}
@@ -390,7 +399,7 @@ abstract class Database extends \lithium\data\Source {
$type = $context->type();
}
if (!isset($this->_strings[$type])) {
- throw new InvalidArgumentException("Invalid query type '{$type}'");
+ throw new InvalidArgumentException("Invalid query type `{$type}`.");
}
$data = array_filter($data);
return trim(String::insert($this->_strings[$type], $data, array('clean' => true)));
diff --git a/libraries/lithium/data/source/MongoDb.php b/libraries/lithium/data/source/MongoDb.php
index 379dba7..c118e1b 100644
--- a/libraries/lithium/data/source/MongoDb.php
+++ b/libraries/lithium/data/source/MongoDb.php
@@ -374,11 +374,20 @@ class MongoDb extends \lithium\data\Source {
return $this->_filter(__METHOD__, $params, function($self, $params) use ($_config, $_exp) {
$query = $params['query'];
$options = $params['options'];
+<<<<<<< HEAD
$data = $_exp::get('create', $query->entity()->export());
$gridCol = "{$_config['gridPrefix']}.files";
$source = $query->source();
if ($source == $gridCol && isset($data['create']['file'])) {
+=======
+
+ $args = $query->export($self, array('keys' => array('source', 'data')));
+ $data = $_exp::get('create', $args['data']);
+ $source = $args['source'];
+
+ if ($source == "{$_config['gridPrefix']}.files" && isset($data['create']['file'])) {
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
$result = array('ok' => true);
$data['create']['_id'] = $self->invokeMethod('_saveFile', array($data['create']));
} else {
@@ -450,7 +459,6 @@ class MongoDb extends \lithium\data\Source {
$query = $params['query'];
$options = $params['options'];
$args = $query->export($self);
- $self->connection->resetError();
$source = $args['source'];
if ($group = $args['group']) {
@@ -505,7 +513,11 @@ class MongoDb extends \lithium\data\Source {
return $this->_filter(__METHOD__, $params, function($self, $params) use ($_config, $_exp) {
$options = $params['options'];
$query = $params['query'];
+<<<<<<< HEAD
$args = $query->export($self, array('keys' => array('conditions', 'source')));
+=======
+ $args = $query->export($self, array('keys' => array('conditions', 'source', 'data')));
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
$source = $args['source'];
$data = $args['data'];
@@ -518,6 +530,12 @@ class MongoDb extends \lithium\data\Source {
}
$update = $query->entity() ? $_exp::toCommand($data) : $data;
+<<<<<<< HEAD
+=======
+ if ($options['multiple'] && !preg_grep('/^\$/', array_keys($update))) {
+ $update = array('$set' => $update);
+ }
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
if ($self->connection->{$source}->update($args['conditions'], $update, $options)) {
$query->entity() ? $query->entity()->update() : null;
return true;
diff --git a/libraries/lithium/data/source/database/adapter/MySql.php b/libraries/lithium/data/source/database/adapter/MySql.php
index 8533658..69abcae 100755
--- a/libraries/lithium/data/source/database/adapter/MySql.php
+++ b/libraries/lithium/data/source/database/adapter/MySql.php
@@ -133,6 +133,10 @@ class MySql extends \lithium\data\source\Database {
return false;
}
+ if (!$this->connection) {
+ return false;
+ }
+
if (mysql_select_db($config['database'], $this->connection)) {
$this->_isConnected = true;
} else {
@@ -271,10 +275,10 @@ class MySql extends \lithium\data\source\Database {
}
$result = array();
- $count = mysql_num_fields($resource);
+ $count = mysql_num_fields($resource->resource());
for ($i = 0; $i < $count; $i++) {
- $result[] = mysql_field_name($resource, $i);
+ $result[] = mysql_field_name($resource->resource(), $i);
}
return $result;
}
@@ -301,9 +305,15 @@ class MySql extends \lithium\data\source\Database {
/**
* @todo Eventually, this will need to rewrite aliases for DELETE and UPDATE queries, same with
* order().
+<<<<<<< HEAD
* @param string $conditions
* @param string $context
* @param array $options
+=======
+ * @param string $conditions
+ * @param string $context
+ * @param array $options
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
* @return void
*/
public function conditions($conditions, $context, array $options = array()) {
diff --git a/libraries/lithium/data/source/database/adapter/Sqlite3.php b/libraries/lithium/data/source/database/adapter/Sqlite3.php
index e381951..e5c43aa 100755
--- a/libraries/lithium/data/source/database/adapter/Sqlite3.php
+++ b/libraries/lithium/data/source/database/adapter/Sqlite3.php
@@ -12,6 +12,7 @@ namespace lithium\data\source\database\adapter;
use SQLite3 as SQLite;
use SQLite3Result;
use lithium\data\model\QueryException;
+use \lithium\data\source\database\adapter\sqlite3\Result;
/**
* Sqlite database driver
@@ -63,7 +64,7 @@ class Sqlite3 extends \lithium\data\source\Database {
public function __construct(array $config = array()) {
$defaults = array(
'database' => '',
- 'flags' => NULL,
+ 'flags' => SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE,
'key' => NULL
);
parent::__construct($config + $defaults);
@@ -154,7 +155,9 @@ class Sqlite3 extends \lithium\data\source\Database {
* @param object $query The given query, usually an instance of `lithium\data\model\Query`.
* @return void
*/
- protected function _insertId($query) {}
+ protected function _insertId($query) {
+ return $this->connection->lastInsertRowID();
+ }
/**
* Gets or sets the encoding for the connection.
@@ -188,7 +191,7 @@ class Sqlite3 extends \lithium\data\source\Database {
if (is_array($value)) {
return parent::value($value, $schema);
}
- return $this->connection->escapeString($value);
+ return "'" . $this->connection->escapeString($value) . "'";
}
/**
@@ -255,9 +258,9 @@ class Sqlite3 extends \lithium\data\source\Database {
if (!($result = $conn->query($sql)) instanceof SQLite3Result) {
list($code, $error) = $self->error();
- throw new QueryException("$sql: $error", $code);
+ throw new QueryException("{$sql}: {$error}", $code);
}
- return $result;
+ return new Result(array('resource' => $result));
});
}
diff --git a/libraries/lithium/data/source/database/adapter/sqlite3/Result.php b/libraries/lithium/data/source/database/adapter/sqlite3/Result.php
index 6986a49..7214ff9 100644
--- a/libraries/lithium/data/source/database/adapter/sqlite3/Result.php
+++ b/libraries/lithium/data/source/database/adapter/sqlite3/Result.php
@@ -16,14 +16,32 @@ class Result extends \lithium\data\source\database\Result {
if (!$this->_resource instanceof SQLite3Result) {
return;
}
+<<<<<<< HEAD
return $resource->fetchArray(SQLITE3_ASSOC);
+=======
+ return $this->_resource->fetchArray(SQLITE3_ASSOC);
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
}
protected function _close() {
if (!$this->_resource instanceof SQLite3Result) {
return;
}
+<<<<<<< HEAD
$resource->finalize();
+=======
+ $this->_resource->finalize();
+ }
+
+ public function __call($name, $arguments) {
+ if (!$this->_resource instanceof SQLite3Result) {
+ return;
+ }
+
+ if(is_callable(array($this->_resource, $name))) {
+ return call_user_method_array($name, $this->_resource, $arguments);
+ }
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
}
}
diff --git a/libraries/lithium/data/source/http/adapter/CouchDb.php b/libraries/lithium/data/source/http/adapter/CouchDb.php
index 5004f21..8a1c535 100644
--- a/libraries/lithium/data/source/http/adapter/CouchDb.php
+++ b/libraries/lithium/data/source/http/adapter/CouchDb.php
@@ -43,8 +43,13 @@ class CouchDb extends \lithium\data\source\Http {
protected $_classes = array(
'service' => 'lithium\net\http\Service',
'entity' => 'lithium\data\entity\Document',
+<<<<<<< HEAD
'array' => 'lithium\data\collection\DocumentArray',
'set' => 'lithium\data\collection\DocumentSet'
+=======
+ 'set' => 'lithium\data\collection\DocumentSet',
+ 'array' => 'lithium\data\collection\DocumentArray',
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
);
protected $_handlers = array();
@@ -153,7 +158,7 @@ class CouchDb extends \lithium\data\source\Http {
}
}
if (!$this->_db) {
- throw new ConfigException("{$entity} is not available.");
+ throw new ConfigException("Database `{$entity}` is not available.");
}
}
diff --git a/libraries/lithium/g11n/Locale.php b/libraries/lithium/g11n/Locale.php
index 17bb845..3328a70 100644
--- a/libraries/lithium/g11n/Locale.php
+++ b/libraries/lithium/g11n/Locale.php
@@ -8,8 +8,8 @@
namespace lithium\g11n;
-use \BadMethodCallException;
-use \InvalidArgumentException;
+use BadMethodCallException;
+use InvalidArgumentException;
/**
* The `Locale` class provides methods to deal with locale identifiers. The locale
@@ -70,7 +70,7 @@ class Locale extends \lithium\core\StaticObject {
$tags = static::invokeMethod('decompose', $params);
if (!isset(static::$_tags[$method])) {
- throw new BadMethodCallException("Invalid locale tag `{$method}`");
+ throw new BadMethodCallException("Invalid locale tag `{$method}`.");
}
return isset($tags[$method]) ? $tags[$method] : null;
}
@@ -109,7 +109,7 @@ class Locale extends \lithium\core\StaticObject {
$regex .= '(?:[_-](?P<variant>[a-z]{5,}))?';
if (!preg_match("/^{$regex}$/i", $locale, $matches)) {
- throw new InvalidArgumentException("Locale `{$locale}` could not be parsed");
+ throw new InvalidArgumentException("Locale `{$locale}` could not be parsed.");
}
return array_filter(array_intersect_key($matches, static::$_tags));
}
diff --git a/libraries/lithium/g11n/catalog/adapter/Code.php b/libraries/lithium/g11n/catalog/adapter/Code.php
index ccbd7b0..ee90ba9 100644
--- a/libraries/lithium/g11n/catalog/adapter/Code.php
+++ b/libraries/lithium/g11n/catalog/adapter/Code.php
@@ -48,9 +48,8 @@ class Code extends \lithium\g11n\catalog\Adapter {
protected function _init() {
parent::_init();
if (!is_dir($this->_config['path'])) {
- throw new ConfigException(
- "Code directory does not exist at `{$this->_config['path']}`"
- );
+ $message = "Code directory does not exist at path `{$this->_config['path']}`.";
+ throw new ConfigException($message);
}
}
diff --git a/libraries/lithium/g11n/catalog/adapter/Gettext.php b/libraries/lithium/g11n/catalog/adapter/Gettext.php
index 4ade215..1ecd86e 100644
--- a/libraries/lithium/g11n/catalog/adapter/Gettext.php
+++ b/libraries/lithium/g11n/catalog/adapter/Gettext.php
@@ -92,7 +92,8 @@ class Gettext extends \lithium\g11n\catalog\Adapter {
protected function _init() {
parent::_init();
if (!is_dir($this->_config['path'])) {
- throw new ConfigException("Gettext directory does not exist at `{$this->_config['path']}`");
+ $message = "Gettext directory does not exist at path `{$this->_config['path']}`.";
+ throw new ConfigException($message);
}
}
@@ -265,7 +266,7 @@ class Gettext extends \lithium\g11n\catalog\Adapter {
$stat = fstat($stream);
if ($stat['size'] < self::MO_HEADER_SIZE) {
- throw new RangeException("MO stream caontent has an invalid format");
+ throw new RangeException("MO stream content has an invalid format.");
}
$magic = unpack('V1', fread($stream, 4));
$magic = hexdec(substr(dechex(current($magic)), -8));
@@ -275,7 +276,7 @@ class Gettext extends \lithium\g11n\catalog\Adapter {
} elseif ($magic == self::MO_BIG_ENDIAN_MAGIC) {
$isBigEndian = true;
} else {
- throw new RangeException("MO stream content has an invalid format");
+ throw new RangeException("MO stream content has an invalid format.");
}
$header = array(
diff --git a/libraries/lithium/g11n/catalog/adapter/Php.php b/libraries/lithium/g11n/catalog/adapter/Php.php
index 8435e62..464fdd4 100644
--- a/libraries/lithium/g11n/catalog/adapter/Php.php
+++ b/libraries/lithium/g11n/catalog/adapter/Php.php
@@ -71,7 +71,8 @@ class Php extends \lithium\g11n\catalog\Adapter {
protected function _init() {
parent::_init();
if (!is_dir($this->_config['path'])) {
- throw new ConfigException("Php directory does not exist at `{$this->_config['path']}`");
+ $message = "Php directory does not exist at path `{$this->_config['path']}`.";
+ throw new ConfigException($message);
}
}
diff --git a/libraries/lithium/net/http/Media.php b/libraries/lithium/net/http/Media.php
index b81ec36..a79b6ea 100755
--- a/libraries/lithium/net/http/Media.php
+++ b/libraries/lithium/net/http/Media.php
@@ -463,8 +463,8 @@ class Media extends \lithium\core\StaticObject {
/**
* Gets the physical path to the web assets (i.e. `/webroot`) directory of a library.
*
- * @param string $library The name of the library for which to find the path, or `true` for the
- * default library.
+ * @param string|boolean $library The name of the library for which to find the path, or `true`
+ * for the default library.
* @return string Returns the physical path to the web assets directory for a library. For
* example, the `/webroot` directory of the default library would be
* `LITHIUM_APP_PATH . '/webroot'`.
@@ -551,6 +551,7 @@ class Media extends \lithium\core\StaticObject {
$result = null;
$type = $options['type'];
+<<<<<<< HEAD
if (!isset($handlers[$type])) {
throw new MediaException("Unhandled media type '{$type}'");
@@ -559,6 +560,16 @@ class Media extends \lithium\core\StaticObject {
$filter = function($v) { return $v !== null; };
$handler = array_filter($handler, $filter) + $handlers['default'] + $defaults;
+=======
+
+ if (!isset($handlers[$type])) {
+ throw new MediaException("Unhandled media type `{$type}`.");
+ }
+ $handler = $options + $handlers[$type] + $defaults;
+ $filter = function($v) { return $v !== null; };
+ $handler = array_filter($handler, $filter) + $handlers['default'] + $defaults;
+
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
if (isset($types[$type])) {
$response->headers('Content-type', current((array) $types[$type]));
}
@@ -574,6 +585,7 @@ class Media extends \lithium\core\StaticObject {
* type must have an `'encode'` setting specified in `Media::$_handlers`.
* @param mixed $data Arbitrary data you wish to encode. Note that some encoders can only handle
* arrays or objects.
+ * @param object $response A reference to the `Response` object for this dispatch cycle.
* @param array $options Handler-specific options.
* @return mixed
*/
@@ -658,8 +670,10 @@ class Media extends \lithium\core\StaticObject {
case $handler['encode']:
return $self::encode($handler, $data, $response);
case class_exists($handler['view']):
- $view = new $handler['view']($handler + array('response' => &$response));
- return $view->render('all', $data, $options);
+ $class = $handler['view'];
+ unset($handler['view'], $options['view']);
+ $view = new $class($handler + array('response' => &$response));
+ return $view->render("all", (array) $data, $options);
case ($handler['template'] === false) && is_string($data):
return $data;
default:
@@ -730,6 +744,10 @@ class Media extends \lithium\core\StaticObject {
'paths' => array(
'template' => '{:library}/views/{:controller}/{:template}.{:type}.php',
'layout' => '{:library}/views/layouts/{:layout}.{:type}.php',
+<<<<<<< HEAD
+=======
+ 'element' => '{:library}/views/elements/{:template}.{:type}.php'
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
)
),
'html' => array(),
diff --git a/libraries/lithium/net/http/Router.php b/libraries/lithium/net/http/Router.php
index 6e20627..2a87677 100644
--- a/libraries/lithium/net/http/Router.php
+++ b/libraries/lithium/net/http/Router.php
@@ -194,7 +194,7 @@ class Router extends \lithium\core\StaticObject {
return $path;
}
if (is_string($url = static::_parseString($url, $context))) {
- return $url;
+ return static::_prefix($url, $context, $options);
}
}
if (isset($url[0]) && is_array($params = static::_parseString($url[0], $context))) {
diff --git a/libraries/lithium/security/Auth.php b/libraries/lithium/security/Auth.php
index c3b2ab8..9230c11 100644
--- a/libraries/lithium/security/Auth.php
+++ b/libraries/lithium/security/Auth.php
@@ -113,7 +113,7 @@ class Auth extends \lithium\core\Adaptable {
$config = $self::invokeMethod('_config', array($name));
if ($config === null) {
- throw new ConfigException("Configuration '{$name}' has not been defined.");
+ throw new ConfigException("Configuration `{$name}` has not been defined.");
}
$session = $config['session'];
diff --git a/libraries/lithium/template/Helper.php b/libraries/lithium/template/Helper.php
index 8c69801..b2cbae7 100644
--- a/libraries/lithium/template/Helper.php
+++ b/libraries/lithium/template/Helper.php
@@ -42,6 +42,13 @@ abstract class Helper extends \lithium\core\Object {
protected $_context = null;
/**
+ * This property can be overwritten with any class dependencies a helper subclass has.
+ *
+ * @var array
+ */
+ protected $_classes = array();
+
+ /**
* Auto configuration properties.
*
* @var array
@@ -133,7 +140,13 @@ abstract class Helper extends \lithium\core\Object {
if ($this->_context) {
foreach ($params as $key => $value) {
+<<<<<<< HEAD
$params[$key] = $this->_context->applyHandler($this, $method, $key, $value, $options);
+=======
+ $params[$key] = $this->_context->applyHandler(
+ $this, $method, $key, $value, $options
+ );
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
}
$strings = $this->_context->strings();
}
diff --git a/libraries/lithium/template/View.php b/libraries/lithium/template/View.php
index 95bf695..239bfcd 100644
--- a/libraries/lithium/template/View.php
+++ b/libraries/lithium/template/View.php
@@ -8,36 +8,47 @@
namespace lithium\template;
-use RuntimeException;
use lithium\core\Libraries;
+use lithium\template\TemplateException;
/**
* As one of the three pillars of the Model-View-Controller design pattern, the `View` class
* (along with other supporting classes) is responsible for taking the data passed from the
- * request and/or controller, inserting this into the requested view/layout, and then presenting
- * the rendered content in the appropriate content-type.
+ * request and/or controller, inserting this into the requested template/layout, and then returning
+ * the rendered content.
*
* The `View` class interacts with a variety of other classes in order to achieve maximum
* flexibility and configurability at all points in the view rendering and presentation
* process. The `Loader` class is tasked with locating and reading template files which are then
* passed to the `Renderer` adapter subclass.
*
- * It is also possible to instantiate and call `View` directly, in cases where you wish to bypass
- * all other parts of the framework and simply return rendered content.
+ * In the default configuration, the `File` adapter acts as both renderer and loader, loading files
+ * from paths defined in _process steps_ (described below) and rendering them as plain PHP files,
+ * augmented with [special syntax](../template).
+ *
+ * The `View` class operates on _processes_, which define the steps to render a completed view. For
+ * example, the default process, which renders a template wrapped in a layout, is comprised of two
+ * _steps_: the first step renders the main template and captures it to the rendering context, where
+ * it is embedded in the layout in the second step. See the `$_steps` and `$_processes` properties
+ * for more information.
+ *
+ * Using steps and processes, you can create rendering scenarios to suit very complex needs.
+ *
+ * By default, the `View` class is called during the course of the framework's dispatch cycle by the
+ * `Media` class. However, it is also possible to instantiate and call `View` directly, in cases
+ * where you wish to bypass all other parts of the framework and simply return rendered content.
*
* A simple example, using the `Simple` renderer/loader for string templates:
*
* {{{
* $view = new View(array('loader' => 'Simple', 'renderer' => 'Simple'));
- * echo $view->render(array('element' => 'Hello, {:name}!'), array(
- * 'name' => "Robert"
- * ));
+ * echo $view->render('element', array('name' => "Robert"), array('element' => 'Hello, {:name}!'));
*
* // Output:
* "Hello, Robert!";
* }}}
*
- * (note: This is easily adapted for XML templating).
+ * _Note_: This is easily adapted for XML templating.
*
* Another example, this time of something that could be used in an appliation
* error handler:
@@ -50,15 +61,17 @@ use lithium\core\Libraries;
* )
* ));
*
- * echo $View->render('all', array('content' => $info), array(
+ * $page = $View->render('all', array('content' => $info), array(
* 'template' => '404',
- * 'type' => 'html',
* 'layout' => 'error'
* ));
* }}}
*
- * @see lithium\view\Renderer
- * @see lithium\view\adapter
+ * To learn more about processes and process steps, see the `$_processes` and `$_steps` properties,
+ * respectively.
+ *
+ * @see lithium\template\view\Renderer
+ * @see lithium\template\view\adapter
* @see lithium\net\http\Media
*/
class View extends \lithium\core\Object {
@@ -105,21 +118,81 @@ class View extends \lithium\core\Object {
protected $_renderer = null;
/**
+ * View processes are aggregated lists of steps taken to to create a complete, rendered view.
+ * For example, the default process, `'all'`, renders a template, then renders a layout, using
+ * the rendered template content. A process can be defined using one or more steps defined in
+ * the `$_steps` property. Each process definition is a simple array of ordered values, where
+ * each value is a key in the `$_steps` array.
+ *
+ * @see lithium\template\View::$_steps
+ * @see lithium\template\View::render()
+ * @var array
+ */
+ protected $_processes = array(
+ 'all' => array('template', 'layout'),
+ 'template' => array('template'),
+ 'element' => array('element')
+ );
+
+ /**
+ * The list of available rendering steps. Each step contains instructions for how to render one
+ * piece of a multi-step view rendering. The `View` class combines multiple steps into
+ * _processes_ to create the final output.
+ *
+ * Each step is named by its key in the `$_steps` array, and can have the following options:
+ *
+ * - `'path'` _string_: Indicates the set of paths to use when loading templates.
+ *
+ * - `'conditions'` _mixed_: Make the step dependent on a value being present, or on some other
+ * arbitrary condition. If a `'conditions'` is a string, it indicates that a key with that
+ * name must be present in the `$options` passed to `render()`, and must be set to a
+ * non-empty value. If a closure, it will be executed with the rendering parameters, and must
+ * return `true` or `false`. In either case, if the condition is satisfied, the step is
+ * processed. Otherwise, it is skipped. See the `_conditions()` method for more information.
+ *
+ * - `'capture'` _array_: If specified, allows the results of this rendering step to be assigned
+ * to a template variable used in subsequent steps, or to the templating context for use in
+ * subsequent steps. If can be specified in the form of `array('context' => '<var-name>')` or
+ * `array('data' => '<var-name>')`. If the `'context'` key is used, the results are captured
+ * to the rendering context. Likewise with the `'data'` key, results are captured to a
+ * template variable.
+ *
+ * - `'multi'` _boolean_: If set to `true`, the rendering parameter matching the name of this
+ * step can be an array containing multiple values, in which case this step is executed
+ * multiple times, once for each value of the array.
+ *
+ * @see lithium\template\View::$_processes
+ * @see lithium\template\View::render()
+ * @var array
+ */
+ protected $_steps = array(
+ 'template' => array('path' => 'template', 'capture' => array('context' => 'content')),
+ 'layout' => array(
+ 'path' => 'layout', 'conditions' => 'layout', 'multi' => true, 'capture' => array(
+ 'context' => 'content'
+ )
+ ),
+ 'element' => array('path' => 'element')
+ );
+
+ /**
* Auto-configuration parameters.
*
* @var array Objects to auto-configure.
*/
- protected $_autoConfig = array('request', 'response');
+ protected $_autoConfig = array(
+ 'request', 'response', 'processes' => 'merge', 'steps' => 'merge'
+ );
/**
* Constructor.
*
* @param array $config Configuration parameters.
* The available options are:
- * - `loader`: For locating/reading view, layout and element
- * templates. Defaults to `File`.
- * - `renderer`: Populates the view/layout with the data set from the controller.
- * Defaults to `File`.
+ * - `'loader'` _mixed_: For locating/reading view, layout and element
+ * templates. Defaults to `File`.
+ * - `'renderer'` _mixed_: Populates the view/layout with the data set from the
+ * controller. Defaults to `'File'`.
* - `request`: The request object to be made available in the view. Defalts to `null`.
* - `vars`: Defaults to `array()`.
* @return void
@@ -131,6 +204,8 @@ class View extends \lithium\core\Object {
'vars' => array(),
'loader' => 'File',
'renderer' => 'File',
+ 'steps' => array(),
+ 'processes' => array(),
'outputFilters' => array()
);
parent::__construct($config + $defaults);
@@ -140,7 +215,6 @@ class View extends \lithium\core\Object {
* Perform initialization of the View.
*
* @return void
- * @throws RuntimeException when template adapter cannot be found.
*/
protected function _init() {
parent::_init();
@@ -166,48 +240,51 @@ class View extends \lithium\core\Object {
$this->outputFilters += compact('h') + $this->_config['outputFilters'];
}
- /**
- * Render a layout, template, view or element.
- *
- * @param string|array $type The view type. Possible values are `element`, `template`,
- * `layout` and `all`.
- * @param array $data The data to be made available in the rendered view.
- * @param array $options Rendering options:
- * - `context`: Render context
- * - `type`: The media type to render. Defaults to `html`.
- * - `layout`: The layout in which the rendered view should be wrapped in.
- * @return string The rendered view that was requested.
- */
- public function render($type, $data = null, array $options = array()) {
- $defaults = array('context' => array(), 'type' => 'html', 'layout' => null);
+ public function render($process, array $data = array(), array $options = array()) {
+ $defaults = array(
+ 'type' => 'html',
+ 'layout' => null,
+ 'template' => null,
+ 'context' => array(),
+ );
$options += $defaults;
- $data = $data ?: array();
- $template = null;
+ $data += isset($options['data']) ? (array) $options['data'] : array();
+ $paths = isset($options['paths']) ? (array) $options['paths'] : array();
+ unset($options['data'], $options['paths']);
+ $params = array_filter($options, function($val) { return $val && is_string($val); });
+ $result = null;
- if (is_array($type)) {
- list($type, $template) = each($type);
+ foreach ($this->_process($process, $params) as $name => $step) {
+ if (!$this->_conditions($step, $params, $data, $options)) {
+ continue;
+ }
+ if ($step['multi'] && isset($options[$name])) {
+ foreach ((array) $options[$name] as $value) {
+ $params[$name] = $value;
+ $result = $this->_step($step, $params, $data, $options);
+ }
+ continue;
+ }
+ $result = $this->_step((array) $step, $params, $data, $options);
}
- return $this->{"_" . $type}($template, $data, $options);
+ return $result;
}
- /**
- * The 'all' render type handler.
- *
- * @param string $template Not used in this handler. Can be specified as null.
- * @param array $data Template data.
- * @param array $options Layout rendering options.
- */
- protected function _all($template, $data, array $options = array()) {
- $content = $this->render('template', $data, $options);
-
- if (!$options['layout']) {
- return $content;
+ protected function _conditions($step, $params, $data, $options) {
+ if (!$conditions = $step['conditions']) {
+ return true;
+ }
+ if (is_callable($conditions) && !$conditions($params, $data, $options)) {
+ return false;
+ }
+ if (is_string($conditions) && !(isset($options[$conditions]) && $options[$conditions])) {
+ return false;
}
- $options['context'] += array('content' => $content);
- return $this->_layout($template, $data, $options);
+ return true;
}
+<<<<<<< HEAD
/**
* The 'element' render type handler.
*
@@ -226,11 +303,39 @@ class View extends \lithium\core\Object {
return $_renderer->render($params['template'], $params['data'], $params['options']);
};
return $this->_filter(__METHOD__, $params, $filter);
+=======
+ protected function _step(array $step, array $params, array &$data, array &$options = array()) {
+ $step += array('path' => null, 'capture' => null);
+ $_renderer = $this->_renderer;
+ $_loader = $this->_loader;
+ $filters = $this->outputFilters;
+ $params = compact('step', 'params', 'options') + array('data' => $data + $filters);
+
+ $filter = function($self, $params) use (&$_renderer, &$_loader) {
+ $template = $_loader->template($params['step']['path'], $params['params']);
+ return $_renderer->render($template, $params['data'], $params['options']);
+ };
+ $result = $this->_filter(__METHOD__, $params, $filter);
+
+ if (is_array($step['capture'])) {
+ switch (key($step['capture'])) {
+ case 'context':
+ $options['context'][current($step['capture'])] = $result;
+ break;
+ case 'data':
+ $data[current($step['capture'])] = $result;
+ break;
+ }
+ }
+ return $result;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
}
/**
- * The 'template' render type handler.
+ * Converts a process name to an array containing the rendering steps to be executed for each
+ * process.
*
+<<<<<<< HEAD
* @param string $template Template to be rendered.
* @param array $data Template data.
* @param array $options Renderer options.
@@ -264,6 +369,47 @@ class View extends \lithium\core\Object {
return $_renderer->render($params['template'], $params['data'], $params['options']);
};
return $this->_filter(__METHOD__, $params, $filter);
+=======
+ * @param string $process A named set of rendering steps.
+ * @param array $params
+ * @return array A 2-dimensional array that defines the rendering process. The first dimension
+ * is a numerically-indexed array containing each rendering step. The second dimension
+ * represents the parameters for each step.
+ */
+ protected function _process($process, &$params) {
+ $defaults = array('conditions' => null, 'multi' => false);
+
+ if (!is_array($process)) {
+ if (!isset($this->_processes[$process])) {
+ throw new TemplateException("Undefined rendering process '{$process}'.");
+ }
+ $process = $this->_processes[$process];
+ }
+ if (is_string(key($process))) {
+ return $this->_convertSteps($process, $params, $defaults);
+ }
+ $result = array();
+
+ foreach ($process as $step) {
+ if (is_array($step)) {
+ $result[] = $step + $defaults;
+ continue;
+ }
+ if (!isset($this->_steps[$step])) {
+ throw new TemplateException("Undefined rendering step '{$step}'.");
+ }
+ $result[$step] = $this->_steps[$step] + $defaults;
+ }
+ return $result;
+ }
+
+ protected function _convertSteps($command, &$params, $defaults) {
+ if (count($command) == 1) {
+ $params['template'] = current($command);
+ return array(array('path' => key($command)) + $defaults);
+ }
+ return $command;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
}
}
diff --git a/libraries/lithium/template/helper/Form.php b/libraries/lithium/template/helper/Form.php
index 5cfbd2d..837314c 100755
--- a/libraries/lithium/template/helper/Form.php
+++ b/libraries/lithium/template/helper/Form.php
@@ -19,7 +19,7 @@ use UnexpectedValueException;
*
* For example, assuming you have created a `Post` model in your application:
* {{{// In controller code:
- * use \app\models\Post;
+ * use app\models\Post;
* $post = Post::find(1);
* return compact('post');
*
@@ -144,7 +144,7 @@ class Form extends \lithium\template\Helper {
if (in_array($method, array('create', 'end', 'label', 'error'))) {
return;
}
- if (!$name || ($method == 'hidden' && $name = '_method')) {
+ if (!$name || ($method == 'hidden' && $name == '_method')) {
return;
}
$id = Inflector::camelize(Inflector::slug($name));
@@ -164,7 +164,10 @@ class Form extends \lithium\template\Helper {
*/
protected function _init() {
parent::_init();
- $this->_context->handlers(array('wrap' => '_attributes'));
+
+ if ($this->_context) {
+ $this->_context->handlers(array('wrap' => '_attributes'));
+ }
}
/**
@@ -250,8 +253,10 @@ class Form extends \lithium\template\Helper {
* attributes passed in `$options`.
*/
public function create($binding = null, array $options = array()) {
+ $request = $this->_context ? $this->_context->request() : null;
+
$defaults = array(
- 'url' => $this->_context->request()->params,
+ 'url' => $request ? $request->params : array(),
'type' => null,
'action' => null,
'method' => $binding ? ($binding->exists() ? 'put' : 'post') : 'post'
@@ -387,15 +392,7 @@ class Form extends \lithium\template\Helper {
*/
public function field($name, array $options = array()) {
if (is_array($name)) {
- $return = '';
- foreach ($name as $field => $label) {
- if (is_numeric($field)) {
- $field = $label;
- unset($label);
- }
- $return .= $this->field($field, compact('label') + $options);
- }
- return $return;
+ return $this->_fields($name, $options);
}
$defaults = array(
'label' => null,
@@ -419,7 +416,7 @@ class Form extends \lithium\template\Helper {
$type = $options['type'];
$label = $input = null;
- if ($options['label'] === null || $options['label']) {
+ if (($options['label'] === null || $options['label']) && $options['type'] != 'hidden') {
$for = isset($options['id']) ? $options['id'] : '';
$label = $options['label'] ?: $options['label'] = Inflector::humanize($name);
$label = $this->label($for, $label);
@@ -438,6 +435,28 @@ class Form extends \lithium\template\Helper {
}
/**
+ * Helper method used by `Form::field()` for iterating over an array of multiple fields.
+ *
+ * @see lithium\template\helper\Form::field()
+ * @param array $fields An array of fields to render.
+ * @param array $options The array of options to apply to all fields in the `$fields` array. See
+ * the `$options` parameter of the `field` method for more information.
+ * @return string Returns the fields rendered by `field()`, each separated by a newline.
+ */
+ protected function _fields(array $fields, array $options = array()) {
+ $result = array();
+
+ foreach ($fields as $field => $label) {
+ if (is_numeric($field)) {
+ $field = $label;
+ unset($label);
+ }
+ $result[] = $this->field($field, compact('label') + $options);
+ }
+ return join("\n", $result);
+ }
+
+ /**
* Generates an HTML `<input type="submit" />` object.
*
* @param string $title The title of the submit button.
@@ -555,7 +574,7 @@ class Form extends \lithium\template\Helper {
}
}
if ($scope['hidden']) {
- $out = $this->hidden($name, array('value' => ''));
+ $out = $this->hidden($name, array('value' => '', 'id' => false));
}
$options['value'] = $scope['value'];
return $out . $this->_render(__METHOD__, $template, compact('name', 'options'));
@@ -589,7 +608,7 @@ class Form extends \lithium\template\Helper {
/**
* Generates an HTML `<label></label>` object.
*
- * @param string $name The name of the field that the label is for.
+ * @param string $name The DOM ID of the field that the label is for.
* @param string $title The content inside the `<label></label>` object.
* @param array $options Besides HTML attributes, this parameter allows one additional flag:
* - `'escape'` _boolean_: Defaults to `true`. Indicates whether the title of the
@@ -661,14 +680,7 @@ class Form extends \lithium\template\Helper {
protected function _defaults($method, $name, $options) {
$methodConfig = isset($this->_config[$method]) ? $this->_config[$method] : array();
$options += $methodConfig + $this->_config['base'];
-
- foreach ($this->_config['attributes'] as $key => $generator) {
- if (!isset($options[$key]) && $generator) {
- if (($attr = $generator($method, $name, $options)) !== null) {
- $options[$key] = $attr;
- }
- }
- }
+ $options = $this->_generators($method, $name, $options);
$hasValue = (
(!isset($options['value']) || $options['value'] === null) &&
@@ -691,6 +703,36 @@ class Form extends \lithium\template\Helper {
$template = isset($this->_templateMap[$tplKey]) ? $this->_templateMap[$tplKey] : $tplKey;
return array($name, $options, $template);
}
+
+ /**
+ * Iterates over the configured attribute generators, and modifies the settings for a tag.
+ *
+ * @param string $method The name of the helper method which was called, i.e. `'text'`,
+ * `'select'`, etc.
+ * @param string $name The name of the field whose attributes are being generated. Some helper
+ * methods, such as `create()` and `end()`, are not field-based, and therefore
+ * will have no name.
+ * @param array $options The options and HTML attributes that will be used to generate the
+ * helper output.
+ * @return array Returns the value of the `$options` array, modified by the attribute generators
+ * added in the `'attributes'` key of the helper's configuration. Note that if a
+ * generator is present for a field whose value is `false`, that field will be removed
+ * from the array.
+ */
+ protected function _generators($method, $name, $options) {
+ foreach ($this->_config['attributes'] as $key => $generator) {
+ if ($generator && !isset($options[$key])) {
+ if (($attr = $generator($method, $name, $options)) !== null) {
+ $options[$key] = $attr;
+ }
+ continue;
+ }
+ if ($generator && $options[$key] === false) {
+ unset($options[$key]);
+ }
+ }
+ return $options;
+ }
}
?>
\ No newline at end of file
diff --git a/libraries/lithium/template/helper/Html.php b/libraries/lithium/template/helper/Html.php
index 4a243fd..54aab8d 100644
--- a/libraries/lithium/template/helper/Html.php
+++ b/libraries/lithium/template/helper/Html.php
@@ -25,7 +25,7 @@ class Html extends \lithium\template\Helper {
'block' => '<div{:options}>{:content}</div>',
'block-end' => '</div>',
'block-start' => '<div{:options}>',
- 'charset' => '<meta http-equiv="Content-Type" content="{:type}; charset={:charset}" />',
+ 'charset' => '<meta charset="{:encoding}" />',
'image' => '<img src="{:path}"{:options} />',
'js-block' => '<script type="text/javascript"{:options}>{:content}</script>',
'js-end' => '</script>',
@@ -83,15 +83,35 @@ class Html extends \lithium\template\Helper {
);
/**
- * Returns a charset meta-tag.
+ * Returns a charset meta-tag for declaring the encoding of the document.
*
- * @param string $charset The character set to be used in the meta tag. Example: `"utf-8"`.
- * @return string A meta tag containing the specified character set.
+ * The terms character set (here: charset) and character encoding (here:
+ * encoding) were historically synonymous. The terms now have related but
+ * distinct meanings. Whenever possible Lithium tries to use precise
+ * terminology. Since HTML uses the term `charset` we expose this method
+ * under the exact same name. This caters to the expectation towards a HTML
+ * helper. However the rest of the framework will use the term `encoding`
+ * when talking about character encoding.
+ *
+ * It is suggested that uppercase letters should be used when specifying
+ * the encoding. HTML specs don't require it to be uppercase and sites in
+ * the wild most often use the lowercase variant. On the other hand must
+ * XML parsers (those may not be relevant in this context anyway) not
+ * support lowercase encodings. This and the fact that IANA lists only
+ * encodings with uppercase characters led to the above suggestion.
+ *
+ * @see lithium\net\http\Response::$encoding
+ * @link http://www.iana.org/assignments/character-sets
+ * @param string $encoding The character encoding to be used in the meta tag.
+ * Defaults to the encoding of the `Response` object attached to the
+ * current context. The default encoding of that object is `UTF-8`.
+ * The string given here is not manipulated in any way, so that
+ * values are rendered literally. Also see above note about casing.
+ * @return string A meta tag containing the specified encoding (literally).
*/
- public function charset($charset = null) {
- $options = array('type' => 'text/html');
- $options['charset'] = $charset ?: 'utf-8';
- return $this->_render(__METHOD__, 'charset', $options);
+ public function charset($encoding = null) {
+ $encoding = $encoding ?: $this->_context->response()->encoding;
+ return $this->_render(__METHOD__, 'charset', compact('encoding'));
}
/**
@@ -223,6 +243,34 @@ class Html extends \lithium\template\Helper {
}
/**
+ * Creates a tag for the ```<head>``` section of your document.
+ *
+ * If there is a rendering context, then it also pushes the resulting tag to it.
+ *
+ * The ```$options``` must match the named parameters from ```$_strings``` for the
+ * given ```$tag```.
+ *
+ * @param string $tag the name of a key in ```$_strings```
+ * @param array $options the options required by ```$_strings[$tag]```
+ * @return mixed a string if successful, otherwise NULL
+ * @filter This method can be filtered.
+ */
+ public function head($tag, array $options) {
+ if(!isset($this->_strings[$tag])) {
+ return NULL;
+ }
+ $method = __METHOD__;
+ $filter = function($self, $options, $chain) use ($method, $tag) {
+ return $self->invokeMethod('_render', array($method, $tag, $options));
+ };
+ $head = $this->_filter($method, $options, $filter);
+ if($this->_context) {
+ $this->_context->head($head);
+ }
+ return $head;
+ }
+
+ /**
* Creates a formatted <img /> element.
*
* @param string $path Path to the image file, relative to the app/webroot/img/ directory.
diff --git a/libraries/lithium/template/view/Compiler.php b/libraries/lithium/template/view/Compiler.php
index 5a608eb..9f29304 100644
--- a/libraries/lithium/template/view/Compiler.php
+++ b/libraries/lithium/template/view/Compiler.php
@@ -77,7 +77,7 @@ class Compiler extends \lithium\core\StaticObject {
if ($options['fallback']) {
return $file;
}
- throw new TemplateException("Could not write compiled template {$template} to cache");
+ throw new TemplateException("Could not write compiled template `{$template}` to cache.");
}
/**
diff --git a/libraries/lithium/template/view/Renderer.php b/libraries/lithium/template/view/Renderer.php
index 31a732e..efc09f3 100644
--- a/libraries/lithium/template/view/Renderer.php
+++ b/libraries/lithium/template/view/Renderer.php
@@ -33,7 +33,7 @@ abstract class Renderer extends \lithium\core\Object {
* @var array
*/
protected $_autoConfig = array(
- 'request', 'context', 'strings', 'handlers', 'view', 'classes' => 'merge'
+ 'request', 'response', 'context', 'strings', 'handlers', 'view', 'classes' => 'merge'
);
/**
@@ -92,6 +92,13 @@ abstract class Renderer extends \lithium\core\Object {
protected $_request = null;
/**
+ * The `Response` object instance, if applicable.
+ *
+ * @var object The response object.
+ */
+ protected $_response = null;
+
+ /**
* Automatically matches up template strings by name to output handlers. A handler can either
* be a string, which represents a method name of the helper, or it can be a closure or callable
* object. A handler takes 3 parameters: the value to be filtered, the name of the helper
@@ -144,6 +151,7 @@ abstract class Renderer extends \lithium\core\Object {
* - `handlers`: An array of output handlers for string template inputs.
* - `request`: The `Request` object associated with this renderer and passed to the
* defined handlers.
+ * - `response`: The `Response` object associated with this renderer.
* - `context`: An array of the current rendering context data, including `content`,
* `title`, `scripts`, `head` and `styles`.
*
@@ -156,6 +164,7 @@ abstract class Renderer extends \lithium\core\Object {
'strings' => array(),
'handlers' => array(),
'request' => null,
+ 'response' => null,
'context' => array(
'content' => '', 'title' => '', 'scripts' => array(),
'styles' => array(), 'head' => array()
@@ -182,9 +191,13 @@ abstract class Renderer extends \lithium\core\Object {
},
'path' => function($path, $ref, array $options = array()) use (&$classes, &$request) {
$defaults = array('base' => $request ? $request->env('base') : '');
- list($helper, $methodRef) = $ref;
- list($class, $method) = explode('::', $methodRef);
- $type = $helper->contentMap[$method];
+ $type = 'generic';
+
+ if (is_array($ref) && $ref[0] && $ref[1]) {
+ list($helper, $methodRef) = $ref;
+ list($class, $method) = explode('::', $methodRef);
+ $type = $helper->contentMap[$method];
+ }
return $classes['media']::asset($path, $type, $options + $defaults);
},
'options' => '_attributes',
@@ -281,7 +294,7 @@ abstract class Renderer extends \lithium\core\Object {
if ($class = Libraries::locate('helper', ucfirst($name))) {
return $this->_helpers[$name] = new $class($config + array('context' => $this));
}
- throw new RuntimeException("Helper {$name} not found");
+ throw new RuntimeException("Helper `{$name}` not found.");
}
/**
@@ -312,7 +325,7 @@ abstract class Renderer extends \lithium\core\Object {
* @return mixed A string or array, depending on whether `$property` is specified.
*/
public function context($property = null) {
- if (!empty($property)) {
+ if ($property) {
return isset($this->_context[$property]) ? $this->_context[$property] : null;
}
return $this->_context;
@@ -394,6 +407,16 @@ abstract class Renderer extends \lithium\core\Object {
}
/**
+ * Returns the `Response` object associated with this rendering context.
+ *
+ * @return object Returns an instance of `lithium\action\Response`, which provides the i.e.
+ * the encoding for the document being the result of templates rendered by this context.
+ */
+ public function response() {
+ return $this->_response;
+ }
+
+ /**
* Retuns the `View` object that controls this rendering context's instance. This can be used,
* for example, to render view elements, i.e. `<?=$this->view()->render('element' $name); ?>`.
*
@@ -426,6 +449,28 @@ abstract class Renderer extends \lithium\core\Object {
$this->_data = $data + $this->_data;
$this->_vars = $data + $this->_vars;
}
+
+ /**
+ * Shortcut method used to render elements and other nested templates from inside the templating
+ * layer.
+ *
+ * @see lithium\template\View::$_processes
+ * @see lithium\template\View::render()
+ * @param string $type The type of template to render, usually either `'element'` or
+ * `'template'`. Indicates the process used to render the content. See
+ * `lithium\template\View::$_processes` for more info.
+ * @param string $template The template file name. For example, if `'header'` is passed, and
+ * `$type` is set to `'element'`, then the template rendered will be
+ * `views/elements/header.html.php` (assuming the default configuration).
+ * @param array $data An array of any other local variables that should be injected into the
+ * template. By default, only the values used to render the current template will
+ * be sent. If `$data` is non-empty, both sets of variables will be merged.
+ * @param array $options Any options accepted by `template\View::render()`.
+ * @return string Returns a the rendered template content as a string.
+ */
+ protected function _render($type, $template, array $data = array(), array $options = array()) {
+ return $this->_view->render($type, $data + $this->_data, compact('template') + $options);
+ }
}
?>
\ No newline at end of file
diff --git a/libraries/lithium/template/view/adapter/File.php b/libraries/lithium/template/view/adapter/File.php
index b7d0bf3..30a426f 100644
--- a/libraries/lithium/template/view/adapter/File.php
+++ b/libraries/lithium/template/view/adapter/File.php
@@ -13,8 +13,9 @@ use lithium\core\Libraries;
use lithium\template\TemplateException;
/**
- * The File adapter implements both template loading and rendering, and uses the `view\Stream` class
- * to auto-escape template output with short tags (i.e. <?=).
+ * The File adapter implements both template loading and rendering, and uses the
+ * `lithium\template\view\Stream` class or `lithium\template\view\Compiler` class to auto-escape
+ * template output with short tags (i.e. `<?=`).
*
* For more information about implementing your own template loaders or renderers, see the
* `lithium\template\View` class.
@@ -31,7 +32,8 @@ class File extends \lithium\template\view\Renderer implements \ArrayAccess {
* @var array
*/
protected $_autoConfig = array(
- 'classes' => 'merge', 'request', 'context', 'strings', 'handlers', 'view', 'compile'
+ 'classes' => 'merge', 'request', 'response', 'context',
+ 'strings', 'handlers', 'view', 'compile', 'paths'
);
/**
@@ -60,6 +62,8 @@ class File extends \lithium\template\view\Renderer implements \ArrayAccess {
*/
protected $_vars = array();
+ protected $_paths = array();
+
/**
* `File`'s dependencies. These classes are used by the output handlers to generate URLs
* for dynamic resources and static assets, as well as compiling the templates.
@@ -74,7 +78,9 @@ class File extends \lithium\template\view\Renderer implements \ArrayAccess {
);
public function __construct(array $config = array()) {
- $defaults = array('classes' => array(), 'compile' => true, 'extract' => true);
+ $defaults = array(
+ 'classes' => array(), 'compile' => true, 'extract' => true, 'paths' => array()
+ );
parent::__construct($config + $defaults);
}
@@ -110,18 +116,13 @@ class File extends \lithium\template\view\Renderer implements \ArrayAccess {
* Returns a template file name
*
* @param string $type
- * @param array $options
+ * @param array $params
* @return string
*/
- public function template($type, $options) {
- if (!isset($this->_config['paths'][$type])) {
- return null;
- }
- $options = array_filter($options, function($item) { return is_string($item); });
-
- $library = Libraries::get(isset($options['library']) ? $options['library'] : true);
- $options['library'] = $library['path'];
- $path = $this->_paths((array) $this->_config['paths'][$type], $options);
+ public function template($type, array $params) {
+ $library = Libraries::get(isset($params['library']) ? $params['library'] : true);
+ $params['library'] = $library['path'];
+ $path = $this->_paths($type, $params);
if ($this->_compile) {
$compiler = $this->_classes['compiler'];
@@ -153,21 +154,26 @@ class File extends \lithium\template\view\Renderer implements \ArrayAccess {
}
/**
- * Searches a series of path templates for a matching template file, and returns the file name.
+ * Searches one or more path templates for a matching template file, and returns the file name.
*
- * @param array $paths The array of path templates to search.
- * @param array $options The set of options keys to be interpolated into the path templates
+ * @param string $type
+ * @param array $params The set of options keys to be interpolated into the path templates
* when searching for the correct file to load.
* @return string Returns the first template file found. Throws an exception if no templates
* are available.
*/
- protected function _paths($paths, $options) {
- foreach ($paths as $path) {
- if (file_exists($path = String::insert($path, $options))) {
- return $path;
+ protected function _paths($type, array $params) {
+ if (!isset($this->_paths[$type])) {
+ throw new TemplateException("Invalid template type '{$type}'.");
+ }
+
+ foreach ((array) $this->_paths[$type] as $path) {
+ if (!file_exists($path = String::insert($path, $params))) {
+ continue;
}
+ return $path;
}
- throw new TemplateException("Template not found at {$path}");
+ throw new TemplateException("Template not found at path `{$path}`.");
}
}
diff --git a/libraries/lithium/template/view/adapter/Simple.php b/libraries/lithium/template/view/adapter/Simple.php
index ad9dbed..c5e58cc 100644
--- a/libraries/lithium/template/view/adapter/Simple.php
+++ b/libraries/lithium/template/view/adapter/Simple.php
@@ -8,8 +8,13 @@
namespace lithium\template\view\adapter;
+<<<<<<< HEAD
use \Closure;
use \Exception;
+=======
+use Closure;
+use Exception;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
use lithium\util\Set;
use lithium\util\String;
@@ -50,7 +55,10 @@ class Simple extends \lithium\template\view\Renderer {
* @return string
*/
public function template($type, $options) {
- return isset($options[$type]) ? $options[$type] : '';
+ if (isset($options[$type])) {
+ return $options[$type];
+ }
+ return isset($options['template']) ? $options['template'] : '';
}
protected function _toString($data) {
diff --git a/libraries/lithium/test/Group.php b/libraries/lithium/test/Group.php
index 47d2e8a..bb473b5 100644
--- a/libraries/lithium/test/Group.php
+++ b/libraries/lithium/test/Group.php
@@ -57,14 +57,11 @@ class Group extends \lithium\util\Collection {
*/
public static function all(array $options = array()) {
$defaults = array(
- 'library' => true,
'filter' => '/cases/',
'exclude' => '/mock/',
'recursive' => true,
);
- $options += $defaults;
- $classes = Libraries::locate('tests', null, $options);
- return $classes;
+ return Libraries::locate('tests', null, $options + $defaults);
}
/**
@@ -108,7 +105,11 @@ class Group extends \lithium\util\Collection {
foreach ($this->_data as $test) {
if (!class_exists($test)) {
+<<<<<<< HEAD
throw new Exception("Test case '{$test}' not found.");
+=======
+ throw new Exception("Test case `{$test}` not found.");
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
}
$tests[] = new $test;
}
diff --git a/libraries/lithium/test/Report.php b/libraries/lithium/test/Report.php
index d08dbe3..7b809d5 100644
--- a/libraries/lithium/test/Report.php
+++ b/libraries/lithium/test/Report.php
@@ -241,7 +241,7 @@ class Report extends \lithium\core\Object {
$results = array();
foreach ($filters as $filter => $options) {
if (!$class = Libraries::locate('test.filter', $filter)) {
- throw new ClassNotFoundException("{$class} is not a valid test filter.");
+ throw new ClassNotFoundException("`{$class}` is not a valid test filter.");
}
$options['name'] = strtolower(join('', array_slice(explode("\\", $class), -1)));
$results[$class] = $options + array('apply' => array(), 'analyze' => array());
diff --git a/libraries/lithium/test/Unit.php b/libraries/lithium/test/Unit.php
index eb7dab7..50185cc 100644
--- a/libraries/lithium/test/Unit.php
+++ b/libraries/lithium/test/Unit.php
@@ -8,14 +8,23 @@
namespace lithium\test;
+<<<<<<< HEAD
use \Exception;
+=======
+use Exception;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
use lithium\util\String;
use lithium\core\Libraries;
use lithium\util\Validator;
use lithium\analysis\Debugger;
use lithium\analysis\Inspector;
+<<<<<<< HEAD
use \RecursiveDirectoryIterator;
use \RecursiveIteratorIterator;
+=======
+use RecursiveDirectoryIterator;
+use RecursiveIteratorIterator;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
/**
* This is the base class for all test cases. Test are performed using an assertion method. If the
@@ -121,7 +130,7 @@ class Unit extends \lithium\core\Object {
* @param string $message Message to pass if the condition is met.
* @return mixed
*/
- public function skipIf($condition, $message = 'Skipped test {:class}::{:function}()') {
+ public function skipIf($condition, $message = 'Skipped test `{:class}::{:function}()`.') {
if (!$condition) {
return;
}
@@ -212,7 +221,9 @@ class Unit extends \lithium\core\Object {
$params['message'] = $this->_message($params);
$message = String::insert($message, $params);
}
- $trace = Debugger::trace(array('start' => 1, 'format' => 'array'));
+ $trace = Debugger::trace(array(
+ 'start' => 1, 'depth' => 4, 'format' => 'array', 'closures' => !$expression
+ ));
$methods = $this->methods();
$i = 1;
@@ -230,7 +241,7 @@ class Unit extends \lithium\core\Object {
'method' => $trace[$i]['function'],
'assertion' => $trace[$i - 1]['function'],
);
- $this->_result(($expression ? 'pass' : 'fail'), $result);
+ $this->_result($expression ? 'pass' : 'fail', $result);
return $expression;
}
@@ -726,18 +737,23 @@ class Unit extends \lithium\core\Object {
* @return array Data with the keys `trace'`, `'expected'` and `'result'`.
*/
protected function _compare($type, $expected, $result = null, $trace = null) {
- $types = array('expected' => gettype($expected), 'result' => gettype($result));
+ $compareTypes = function($expected, $result, $trace) {
+ $types = array('expected' => gettype($expected), 'result' => gettype($result));
- if ($types['expected'] !== $types['result']) {
- return array('trace' => $trace,
- 'expected' => trim("({$types['expected']}) " . print_r($expected, true)),
- 'result' => trim("({$types['result']}) " . print_r($result, true))
- );
+ if ($types['expected'] !== $types['result']) {
+ $expected = trim("({$types['expected']}) " . print_r($expected, true));
+ $result = trim("({$types['result']}) " . print_r($result, true));
+ return compact('trace', 'expected', 'result');
+ }
+ };
+ if ($types = $compareTypes($expected, $result, $trace)) {
+ return $types;
}
$data = array();
if (!is_scalar($expected)) {
foreach ($expected as $key => $value) {
+ $newTrace = "{$trace}[{$key}]";
$isObject = false;
if (is_object($expected)) {
@@ -745,8 +761,13 @@ class Unit extends \lithium\core\Object {
$expected = (array) $expected;
$result = (array) $result;
}
- $check = array_key_exists($key, $result) ? $result[$key] : array();
- $newTrace = "{$trace}[{$key}]";
+ if (!array_key_exists($key, $result)) {
+ $trace = (!$key) ? null : $newTrace;
+ $expected = (!$key) ? $expected : $value;
+ $result = ($key) ? null : $result;
+ return compact('trace', 'expected', 'result');
+ }
+ $check = $result[$key];
if ($isObject) {
$newTrace = ($trace) ? "{$trace}->{$key}" : $key;
@@ -755,6 +776,9 @@ class Unit extends \lithium\core\Object {
}
if ($type === 'identical') {
if ($value === $check) {
+ if ($types = $compareTypes($value, $check, $trace)) {
+ return $types;
+ }
continue;
}
if ($check === array()) {
@@ -769,6 +793,9 @@ class Unit extends \lithium\core\Object {
}
} else {
if ($value == $check) {
+ if ($types = $compareTypes($value, $check, $trace)) {
+ return $types;
+ }
continue;
}
if (!is_array($value)) {
@@ -785,6 +812,7 @@ class Unit extends \lithium\core\Object {
if (!empty($data)) {
return $data;
}
+<<<<<<< HEAD
}
if (!is_scalar($result)) {
@@ -797,15 +825,24 @@ class Unit extends \lithium\core\Object {
'result' => $data['expected']
);
}
+=======
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
}
+ if (!is_scalar($result)) {
+ $data = $this->_compare($type, $result, $expected);
- if ($type === 'identical') {
- if ($expected === $result) {
- return true;
+ if (!empty($data)) {
+ return array(
+ 'trace' => $data['trace'],
+ 'expected' => $data['result'],
+ 'result' => $data['expected']
+ );
}
- return compact('trace', 'expected', 'result');
}
- if ($expected == $result) {
+ if ((($type === 'identical') ? $expected === $result : $expected == $result)) {
+ if ($types = $compareTypes($expected, $result, $trace)) {
+ return $types;
+ }
return true;
}
return compact('trace', 'expected', 'result');
diff --git a/libraries/lithium/test/filter/Affected.php b/libraries/lithium/test/filter/Affected.php
index b368476..aea52a9 100644
--- a/libraries/lithium/test/filter/Affected.php
+++ b/libraries/lithium/test/filter/Affected.php
@@ -20,7 +20,6 @@ use lithium\analysis\Inspector;
* 1. Looking at the subject of a test case.
* 2. Searching the class tree for any classes that directly depend on that subject.
* 3. Assigning test cases to those classes.
- *
*/
class Affected extends \lithium\test\Filter {
diff --git a/libraries/lithium/tests/cases/action/ControllerTest.php b/libraries/lithium/tests/cases/action/ControllerTest.php
index c2e1d71..7eaa6ed 100644
--- a/libraries/lithium/tests/cases/action/ControllerTest.php
+++ b/libraries/lithium/tests/cases/action/ControllerTest.php
@@ -316,7 +316,7 @@ class ControllerTest extends \lithium\test\Unit {
public function testNonExistentFunction() {
$postsController = new MockPostsController();
- $this->expectException("Action 'foo' not found.");
+ $this->expectException("Action `foo` not found.");
$postsController(new Request(), array('action' => 'foo'));
}
}
diff --git a/libraries/lithium/tests/cases/action/DispatcherTest.php b/libraries/lithium/tests/cases/action/DispatcherTest.php
index 500b512..081eda8 100644
--- a/libraries/lithium/tests/cases/action/DispatcherTest.php
+++ b/libraries/lithium/tests/cases/action/DispatcherTest.php
@@ -135,14 +135,14 @@ class DispatcherTest extends \lithium\test\Unit {
public function testControllerLookupFail() {
Dispatcher::config(array('classes' => array('router' => __CLASS__)));
- $this->expectException("/Controller 'SomeNonExistentController' not found/");
+ $this->expectException("/Controller `SomeNonExistentController` not found/");
Dispatcher::run(new Request(array('url' => '/')));
}
public function testPluginControllerLookupFail() {
Dispatcher::config(array('classes' => array('router' => __CLASS__)));
- $this->expectException("/Controller 'some_invalid_plugin.Controller' not found/");
+ $this->expectException("/Controller `some_invalid_plugin.Controller` not found/");
Dispatcher::run(new Request(array('url' => '/plugin')));
}
diff --git a/libraries/lithium/tests/cases/action/ResponseTest.php b/libraries/lithium/tests/cases/action/ResponseTest.php
index f3b093c..9bbe435 100644
--- a/libraries/lithium/tests/cases/action/ResponseTest.php
+++ b/libraries/lithium/tests/cases/action/ResponseTest.php
@@ -91,7 +91,11 @@ class ResponseTest extends \lithium\test\Unit {
);
$this->assertEqual($headers, $this->response->testHeaders);
+<<<<<<< HEAD
$this->expectException('/^Request::disableCache\(\)/');
+=======
+ $this->expectException('/^`Request::disableCache\(\)`.+`Request::cache\(false\)`/');
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
$this->response->disableCache();
}
diff --git a/libraries/lithium/tests/cases/analysis/DocblockTest.php b/libraries/lithium/tests/cases/analysis/DocblockTest.php
index a326df5..a1bdec3 100644
--- a/libraries/lithium/tests/cases/analysis/DocblockTest.php
+++ b/libraries/lithium/tests/cases/analysis/DocblockTest.php
@@ -108,7 +108,7 @@ class DocblockTest extends \lithium\test\Unit {
/**
* This docblock has an extra * in the closing element.
*
- **/
+ */
public function testBadlyClosedDocblock() {
$info = Inspector::info(__METHOD__ . '()');
$description = 'This docblock has an extra * in the closing element.';
diff --git a/libraries/lithium/tests/cases/analysis/InspectorTest.php b/libraries/lithium/tests/cases/analysis/InspectorTest.php
index ba6586e..f2662a1 100644
--- a/libraries/lithium/tests/cases/analysis/InspectorTest.php
+++ b/libraries/lithium/tests/cases/analysis/InspectorTest.php
@@ -8,8 +8,13 @@
namespace lithium\tests\cases\analysis;
+<<<<<<< HEAD
use \ReflectionClass;
use \ReflectionMethod;
+=======
+use ReflectionClass;
+use ReflectionMethod;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
use lithium\core\Libraries;
use lithium\analysis\Inspector;
diff --git a/libraries/lithium/tests/cases/analysis/LoggerTest.php b/libraries/lithium/tests/cases/analysis/LoggerTest.php
index fb2f9b9..66b39c1 100644
--- a/libraries/lithium/tests/cases/analysis/LoggerTest.php
+++ b/libraries/lithium/tests/cases/analysis/LoggerTest.php
@@ -90,7 +90,7 @@ class LoggerTest extends \lithium\test\Unit {
}
public function testWriteWithInvalidPriority() {
- $this->expectException("Attempted to write log message with invalid priority 'foo'.");
+ $this->expectException("Attempted to write log message with invalid priority `foo`.");
Logger::foo("Test message");
}
diff --git a/libraries/lithium/tests/cases/console/DispatcherTest.php b/libraries/lithium/tests/cases/console/DispatcherTest.php
index 43eb3cc..fdf275d 100644
--- a/libraries/lithium/tests/cases/console/DispatcherTest.php
+++ b/libraries/lithium/tests/cases/console/DispatcherTest.php
@@ -57,10 +57,14 @@ class DispatcherTest extends \lithium\test\Unit {
public function testRunWithPassed() {
$response = Dispatcher::run(new Request(array(
+<<<<<<< HEAD
'args' => array(
'lithium\tests\mocks\console\MockDispatcherCommand',
'with param'
)
+=======
+ 'args' => array('lithium\tests\mocks\console\MockDispatcherCommand', 'with param')
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
)));
$expected = 'run';
@@ -74,10 +78,14 @@ class DispatcherTest extends \lithium\test\Unit {
public function testRunWithAction() {
$response = Dispatcher::run(new Request(array(
+<<<<<<< HEAD
'args' => array(
'lithium\tests\mocks\console\MockDispatcherCommand',
'testAction'
)
+=======
+ 'args' => array('lithium\tests\mocks\console\MockDispatcherCommand', 'testAction')
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
)));
$expected = 'testAction';
$result = $response->testAction;
@@ -85,7 +93,7 @@ class DispatcherTest extends \lithium\test\Unit {
}
public function testInvalidCommand() {
- $expected = (object) array('status' => "Command `\\this\\command\\is\\fake` not found\n");
+ $expected = (object) array('status' => "Command `\\this\\command\\is\\fake` not found.\n");
$result = Dispatcher::run(new Request(array(
'args' => array(
'\this\command\is\fake',
@@ -97,7 +105,7 @@ class DispatcherTest extends \lithium\test\Unit {
}
public function testRunWithCamelizingCommand() {
- $expected = (object) array('status' => "Command `FooBar` not found\n");
+ $expected = (object) array('status' => "Command `FooBar` not found.\n");
$result = Dispatcher::run(new Request(array(
'args' => array(
'foo-bar',
@@ -105,7 +113,7 @@ class DispatcherTest extends \lithium\test\Unit {
)));
$this->assertEqual($expected, $result);
- $expected = (object) array('status' => "Command `FooBar` not found\n");
+ $expected = (object) array('status' => "Command `FooBar` not found.\n");
$result = Dispatcher::run(new Request(array(
'args' => array('foo_bar')
)));
diff --git a/libraries/lithium/tests/cases/console/command/HelpTest.php b/libraries/lithium/tests/cases/console/command/HelpTest.php
index e8023b5..b76c6a2 100644
--- a/libraries/lithium/tests/cases/console/command/HelpTest.php
+++ b/libraries/lithium/tests/cases/console/command/HelpTest.php
@@ -12,8 +12,6 @@ class HelpTest extends \lithium\test\Unit {
protected $_backup = array();
- protected $_testPath = null;
-
public function setUp() {
$this->classes = array('response' => 'lithium\tests\mocks\console\MockResponse');
$this->_backup['cwd'] = getcwd();
@@ -30,116 +28,116 @@ class HelpTest extends \lithium\test\Unit {
}
public function testRun() {
- $help = new Help(array(
+ $command = new Help(array(
'request' => $this->request, 'classes' => $this->classes
));
$expected = true;
- $result = $help->run();
+ $result = $command->run();
$this->assertEqual($expected, $result);
$expected = "COMMANDS\n";
$expected = preg_quote($expected);
- $result = $help->response->output;
+ $result = $command->response->output;
$this->assertPattern("/{$expected}/", $result);
$expected = preg_quote($expected);
- $result = $help->response->output;
+ $result = $command->response->output;
$pattern = "/\s+test\s+Runs a given set of tests and outputs the results\./ms";
$this->assertPattern($pattern, $result);
}
public function testRunWithName() {
- $help = new Help(array(
+ $command = new Help(array(
'request' => $this->request, 'classes' => $this->classes
));
$expected = true;
- $result = $help->run('Test');
+ $result = $command->run('Test');
$this->assertEqual($expected, $result);
$expected = "li3 test --case=CASE --group=GROUP --filters=FILTERS [ARGS]";
$expected = preg_quote($expected);
- $result = $help->response->output;
+ $result = $command->response->output;
$this->assertPattern("/{$expected}/", $result);
$expected = "OPTIONS\n --case=CASE\n";
$expected = preg_quote($expected);
- $result = $help->response->output;
+ $result = $command->response->output;
$this->assertPattern("/{$expected}/", $result);
$expected = "missing\n";
$expected = preg_quote($expected);
- $result = $help->response->output;
+ $result = $command->response->output;
$this->assertPattern("/{$expected}/", $result);
}
public function testApiClass() {
- $help = new Help(array(
+ $command = new Help(array(
'request' => $this->request, 'classes' => $this->classes
));
$expected = null;
- $result = $help->api('lithium.util.Inflector');
+ $result = $command->api('lithium.util.Inflector');
$this->assertEqual($expected, $result);
$expected = "Utility for modifying format of words";
$expected = preg_quote($expected);
- $result = $help->response->output;
+ $result = $command->response->output;
$this->assertPattern("/{$expected}/", $result);
}
public function testApiMethod() {
- $help = new Help(array(
+ $command = new Help(array(
'request' => $this->request, 'classes' => $this->classes
));
$expected = null;
- $result = $help->api('lithium.util.Inflector', 'method');
+ $result = $command->api('lithium.util.Inflector', 'method');
$this->assertEqual($expected, $result);
$expected = "rules [type] [config]";
$expected = preg_quote($expected);
- $result = $help->response->output;
+ $result = $command->response->output;
$this->assertPattern("/{$expected}/", $result);
}
public function testApiMethodWithName() {
- $help = new Help(array(
+ $command = new Help(array(
'request' => $this->request, 'classes' => $this->classes
));
$expected = null;
- $result = $help->api('lithium.util.Inflector', 'method', 'rules');
+ $result = $command->api('lithium.util.Inflector', 'method', 'rules');
$this->assertEqual($expected, $result);
$expected = "rules [type] [config]";
$expected = preg_quote($expected);
- $result = $help->response->output;
+ $result = $command->response->output;
$this->assertPattern("/{$expected}/", $result);
}
public function testApiProperty() {
- $help = new Help(array(
+ $command = new Help(array(
'request' => $this->request, 'classes' => $this->classes
));
$expected = null;
- $result = $help->api('lithium.net.Message', 'property');
+ $result = $command->api('lithium.net.Message', 'property');
$this->assertEqual($expected, $result);
$expected = " --host=HOST\n The hostname for this endpoint.";
$expected = preg_quote($expected);
- $result = $help->response->output;
+ $result = $command->response->output;
$this->assertPattern("/{$expected}/", $result);
}
public function testApiPropertyWithName() {
- $help = new Help(array(
+ $command = new Help(array(
'request' => $this->request, 'classes' => $this->classes
));
$expected = null;
- $result = $help->api('lithium.net.Message', 'property');
+ $result = $command->api('lithium.net.Message', 'property');
$this->assertEqual($expected, $result);
$expected = " --host=HOST\n The hostname for this endpoint.";
$expected = preg_quote($expected);
- $result = $help->response->output;
+ $result = $command->response->output;
$this->assertPattern("/{$expected}/", $result);
}
}
diff --git a/libraries/lithium/tests/cases/console/command/LibraryTest.php b/libraries/lithium/tests/cases/console/command/LibraryTest.php
index f6c6a56..bbdf2c5 100644
--- a/libraries/lithium/tests/cases/console/command/LibraryTest.php
+++ b/libraries/lithium/tests/cases/console/command/LibraryTest.php
@@ -63,9 +63,7 @@ class LibraryTest extends \lithium\test\Unit {
$result = $this->library->config('server', 'lab.lithify.me');
$this->assertTrue($result);
- $expected = array('servers' => array(
- 'lab.lithify.me' => true
- ));
+ $expected = array('servers' => array('lab.lithify.me' => true));
$result = json_decode(file_get_contents($this->testConf), true);
$this->assertEqual($expected, $result);
diff --git a/libraries/lithium/tests/cases/console/command/create/ControllerTest.php b/libraries/lithium/tests/cases/console/command/create/ControllerTest.php
index 5d5d286..b445e89 100644
--- a/libraries/lithium/tests/cases/console/command/create/ControllerTest.php
+++ b/libraries/lithium/tests/cases/console/command/create/ControllerTest.php
@@ -63,7 +63,7 @@ class ControllerTest extends \lithium\test\Unit {
'request' => $this->request, 'classes' => $this->classes
));
- $expected = '\\create_test\\models\\Post';
+ $expected = 'create_test\\models\\Post';
$result = $model->invokeMethod('_use', array($this->request));
$this->assertEqual($expected, $result);
}
@@ -87,7 +87,7 @@ class ControllerTest extends \lithium\test\Unit {
namespace create_test\controllers;
-use \create_test\models\Post;
+use create_test\models\Post;
class PostsController extends \lithium\action\Controller {
diff --git a/libraries/lithium/tests/cases/console/command/create/TestTest.php b/libraries/lithium/tests/cases/console/command/create/TestTest.php
index 9dd5ba3..04add52 100644
--- a/libraries/lithium/tests/cases/console/command/create/TestTest.php
+++ b/libraries/lithium/tests/cases/console/command/create/TestTest.php
@@ -63,7 +63,7 @@ class TestTest extends \lithium\test\Unit {
namespace create_test\tests\cases\models;
-use \create_test\models\Post;
+use create_test\models\Post;
class PostTest extends \lithium\test\Unit {
@@ -86,36 +86,44 @@ test;
public function testTestModelWithMethods() {
$this->_cleanUp();
mkdir($this->_testPath . '/create_test/models/', 0755, true);
- file_put_contents($this->_testPath . '/create_test/models/Post.php',
+ $id = rand();
+ $path = "create_test/models/Post{$id}.php";
+ file_put_contents("{$this->_testPath}/{$path}",
"<?php
namespace create_test\models;
-class Post {
+class Post{$id} {
public function someMethod() {}
}"
);
+<<<<<<< HEAD
$this->request->params += array(
'command' => 'create', 'action' => 'test',
'args' => array('model', 'Post')
);
$test = new Test(array(
'request' => $this->request, 'classes' => $this->classes
+=======
+ $this->request->params += array('command' => 'create', 'action' => 'test', 'args' => array(
+ 'model', "Post{$id}"
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
));
+ $test = new Test(array('request' => $this->request, 'classes' => $this->classes));
$test->path = $this->_testPath;
$test->run('test');
- $expected = "PostTest created in create_test\\tests\\cases\\models.\n";
+ $expected = "Post{$id}Test created in create_test\\tests\\cases\\models.\n";
$result = $test->response->output;
$this->assertEqual($expected, $result);
- $expected = <<<'test'
+ $expected = <<<test
-namespace create_test\tests\cases\models;
+namespace create_test\\tests\\cases\\models;
-use \create_test\models\Post;
+use create_test\\models\\Post{$id};
-class PostTest extends \lithium\test\Unit {
+class Post{$id}Test extends \\lithium\\test\\Unit {
public function setUp() {}
@@ -127,9 +135,8 @@ class PostTest extends \lithium\test\Unit {
test;
$replace = array("<?php", "?>");
- $result = str_replace($replace, '',
- file_get_contents($this->_testPath . '/create_test/tests/cases/models/PostTest.php')
- );
+ $path = "create_test/tests/cases/models/Post{$id}Test.php";
+ $result = str_replace($replace, '', file_get_contents("{$this->_testPath}/{$path}"));
$this->assertEqual($expected, $result);
}
}
diff --git a/libraries/lithium/tests/cases/core/AdaptableTest.php b/libraries/lithium/tests/cases/core/AdaptableTest.php
index f2bf019..a11cbc4 100644
--- a/libraries/lithium/tests/cases/core/AdaptableTest.php
+++ b/libraries/lithium/tests/cases/core/AdaptableTest.php
@@ -8,12 +8,21 @@
namespace lithium\tests\cases\core;
+<<<<<<< HEAD
+=======
+use SplDoublyLinkedList;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
use lithium\util\Collection;
use lithium\core\Adaptable;
use lithium\storage\cache\adapter\Memory;
use lithium\tests\mocks\core\MockAdapter;
use lithium\tests\mocks\core\MockStrategy;
+<<<<<<< HEAD
use \SplDoublyLinkedList;
+=======
+use lithium\tests\mocks\storage\cache\strategy\MockSerializer;
+use lithium\tests\mocks\storage\cache\strategy\MockConfigurizer;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
class AdaptableTest extends \lithium\test\Unit {
@@ -25,7 +34,7 @@ class AdaptableTest extends \lithium\test\Unit {
$this->assertFalse($this->adaptable->config());
$items = array(array(
- 'adapter' => '\some\adapter',
+ 'adapter' => 'some\adapter',
'filters' => array('filter1', 'filter2')
));
$result = $this->adaptable->config($items);
@@ -36,7 +45,7 @@ class AdaptableTest extends \lithium\test\Unit {
$this->assertEqual($expected, $result);
$items = array(array(
- 'adapter' => '\some\adapter',
+ 'adapter' => 'some\adapter',
'filters' => array('filter1', 'filter2')
));
$this->adaptable->config($items);
@@ -62,17 +71,13 @@ class AdaptableTest extends \lithium\test\Unit {
public function testNonExistentConfig() {
$adapter = new MockAdapter();
- $this->expectException("Configuration 'non_existent_config' has not been defined.");
- $result = $adapter::adapter('non_existent_config');
- $this->assertNull($result);
+ $this->expectException("Configuration `non_existent_config` has not been defined.");
+ $adapter::adapter('non_existent_config');
}
public function testAdapter() {
$adapter = new MockAdapter();
- $items = array('default' => array(
- 'adapter' => 'Memory',
- 'filters' => array()
- ));
+ $items = array('default' => array('adapter' => 'Memory', 'filters' => array()));
$adapter::config($items);
$result = $adapter::config();
$expected = $items;
@@ -85,10 +90,7 @@ class AdaptableTest extends \lithium\test\Unit {
public function testConfigAndAdapter() {
$adapter = new MockAdapter();
- $items = array('default' => array(
- 'adapter' => 'Memory',
- 'filters' => array()
- ));
+ $items = array('default' => array('adapter' => 'Memory', 'filters' => array()));
$adapter::config($items);
$config = $adapter::config();
@@ -108,7 +110,7 @@ class AdaptableTest extends \lithium\test\Unit {
public function testStrategy() {
$strategy = new MockStrategy();
$items = array('default' => array(
- 'strategies' => array('\lithium\tests\mocks\storage\cache\strategy\MockSerializer'),
+ 'strategies' => array('lithium\tests\mocks\storage\cache\strategy\MockSerializer'),
'filters' => array(),
'adapter' => null
));
@@ -120,9 +122,7 @@ class AdaptableTest extends \lithium\test\Unit {
$result = $strategy::strategies('default');
$this->assertTrue($result instanceof SplDoublyLinkedList);
$this->assertEqual(count($result), 1);
- $this->assertTrue(
- $result->top() instanceof \lithium\tests\mocks\storage\cache\strategy\MockSerializer
- );
+ $this->assertTrue($result->top() instanceof MockSerializer);
}
public function testInvalidStrategy() {
@@ -135,7 +135,7 @@ class AdaptableTest extends \lithium\test\Unit {
$strategy::config($items);
$class = 'lithium\tests\mocks\core\MockStrategy';
- $message = "Could not find strategy 'InvalidStrategy' in class {$class}.";
+ $message = "Could not find strategy `InvalidStrategy` in class `{$class}`.";
$this->expectException($message);
$result = $strategy::strategies('default');
@@ -146,7 +146,7 @@ class AdaptableTest extends \lithium\test\Unit {
$strategy = new MockStrategy();
$items = array('default' => array(
'strategies' => array(
- '\lithium\tests\mocks\storage\cache\strategy\MockConfigurizer' => array(
+ 'lithium\tests\mocks\storage\cache\strategy\MockConfigurizer' => array(
'key1' => 'value1', 'key2' => 'value2'
)
),
@@ -161,21 +161,19 @@ class AdaptableTest extends \lithium\test\Unit {
$result = $strategy::strategies('default');
$this->assertTrue($result instanceof SplDoublyLinkedList);
$this->assertEqual(count($result), 1);
- $this->assertTrue(
- $result->top() instanceof \lithium\tests\mocks\storage\cache\strategy\MockConfigurizer
- );
+ $this->assertTrue($result->top() instanceof MockConfigurizer);
}
public function testNonExistentStrategyConfiguration() {
$strategy = new MockStrategy();
- $this->expectException("Configuration 'non_existent_config' has not been defined.");
+ $this->expectException("Configuration `non_existent_config` has not been defined.");
$result = $strategy::strategies('non_existent_config');
$this->assertNull($result);
}
public function testApplyStrategiesNonExistentConfiguration() {
$strategy = new MockStrategy();
- $this->expectException("Configuration 'non_existent_config' has not been defined.");
+ $this->expectException("Configuration `non_existent_config` has not been defined.");
$strategy::applyStrategies('method', 'non_existent_config', null);
}
@@ -184,7 +182,7 @@ class AdaptableTest extends \lithium\test\Unit {
$items = array('default' => array(
'filters' => array(),
'adapter' => null,
- 'strategies' => array('\lithium\tests\mocks\storage\cache\strategy\MockSerializer'),
+ 'strategies' => array('lithium\tests\mocks\storage\cache\strategy\MockSerializer'),
));
$strategy::config($items);
$result = $strategy::config();
@@ -203,7 +201,7 @@ class AdaptableTest extends \lithium\test\Unit {
'filters' => array(),
'adapter' => null,
'strategies' => array(
- '\lithium\tests\mocks\storage\cache\strategy\MockConfigurizer' => $params
+ 'lithium\tests\mocks\storage\cache\strategy\MockConfigurizer' => $params
)
));
$strategy::config($items);
@@ -221,8 +219,7 @@ class AdaptableTest extends \lithium\test\Unit {
'filters' => array(),
'adapter' => null,
'strategies' => array(
- '\lithium\tests\mocks\storage\cache\strategy\MockSerializer',
- 'Base64'
+ 'lithium\tests\mocks\storage\cache\strategy\MockSerializer', 'Base64'
)
));
$strategy::config($items);
@@ -274,10 +271,7 @@ class AdaptableTest extends \lithium\test\Unit {
public function testEnabled() {
$adapter = new MockAdapter();
- $items = array('default' => array(
- 'adapter' => 'Memory',
- 'filters' => array()
- ));
+ $items = array('default' => array('adapter' => 'Memory', 'filters' => array()));
$adapter::config($items);
$result = $adapter::config();
$expected = $items;
@@ -294,16 +288,14 @@ class AdaptableTest extends \lithium\test\Unit {
public function testNonExistentAdapter() {
$adapter = new MockAdapter();
- $items = array('default' => array(
- 'adapter' => 'NonExistent', 'filters' => array()
- ));
+ $items = array('default' => array('adapter' => 'NonExistent', 'filters' => array()));
$adapter::config($items);
$result = $adapter::config();
$expected = $items;
$this->assertEqual($expected, $result);
- $message = 'Could not find adapter \'NonExistent\' in ';
- $message .= 'class lithium\tests\mocks\core\MockAdapter.';
+ $message = 'Could not find adapter `NonExistent` in ';
+ $message .= 'class `lithium\tests\mocks\core\MockAdapter`.';
$this->expectException($message);
$result = $adapter::adapter('default');
@@ -336,7 +328,7 @@ class AdaptableTest extends \lithium\test\Unit {
$adapter::config($items);
$message = 'No adapter set for configuration in ';
- $message .= 'class lithium\tests\mocks\core\MockAdapter.';
+ $message .= 'class `lithium\tests\mocks\core\MockAdapter`.';
$this->expectException($message);
$result = $adapter::adapter('default');
}
diff --git a/libraries/lithium/tests/cases/core/ErrorHandlerTest.php b/libraries/lithium/tests/cases/core/ErrorHandlerTest.php
index b8df0c9..ab756db 100644
--- a/libraries/lithium/tests/cases/core/ErrorHandlerTest.php
+++ b/libraries/lithium/tests/cases/core/ErrorHandlerTest.php
@@ -8,9 +8,15 @@
namespace lithium\tests\cases\core;
+<<<<<<< HEAD
use \Closure;
use \Exception;
use \UnexpectedValueException;
+=======
+use Closure;
+use Exception;
+use UnexpectedValueException;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
use lithium\core\ErrorHandler;
class ErrorHandlerTest extends \lithium\test\Unit {
@@ -69,6 +75,8 @@ class ErrorHandlerTest extends \lithium\test\Unit {
}
public function testErrorCatching() {
+ $this->skipIf(true, 'Refactoring original error-handling iteration.');
+
$self = $this;
ErrorHandler::config(array(array(
'code' => E_WARNING | E_USER_WARNING,
diff --git a/libraries/lithium/tests/cases/core/LibrariesTest.php b/libraries/lithium/tests/cases/core/LibrariesTest.php
index 5edafa1..7123255 100644
--- a/libraries/lithium/tests/cases/core/LibrariesTest.php
+++ b/libraries/lithium/tests/cases/core/LibrariesTest.php
@@ -8,7 +8,12 @@
namespace lithium\tests\cases\core;
+<<<<<<< HEAD
use \SplFileInfo;
+=======
+use stdClass;
+use SplFileInfo;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
use lithium\util\Inflector;
use lithium\core\Libraries;
@@ -23,6 +28,11 @@ class LibrariesTest extends \lithium\test\Unit {
$this->assertTrue(strpos($result, '/lithium/core/Libraries.php'));
$this->assertTrue(file_exists($result));
$this->assertFalse(strpos($result, '\\'));
+
+ $result = Libraries::path('lithium\core\Libraries');
+ $this->assertTrue(strpos($result, '/lithium/core/Libraries.php'));
+ $this->assertTrue(file_exists($result));
+ $this->assertFalse(strpos($result, '\\'));
}
public function testPathTemplate() {
@@ -138,7 +148,7 @@ class LibrariesTest extends \lithium\test\Unit {
* @return void
*/
public function testAddInvalidLibrary() {
- $this->expectException("Library 'invalid_foo' not found.");
+ $this->expectException("Library `invalid_foo` not found.");
Libraries::add('invalid_foo');
}
@@ -215,7 +225,7 @@ class LibrariesTest extends \lithium\test\Unit {
* @return void
*/
public function testLibraryLoad() {
- $this->expectException('Failed to load SomeInvalidLibrary from ');
+ $this->expectException('Failed to load class `SomeInvalidLibrary` from path ``.');
Libraries::load('SomeInvalidLibrary', true);
}
@@ -325,7 +335,11 @@ class LibrariesTest extends \lithium\test\Unit {
public function testServiceLocateInstantiation() {
$result = Libraries::instance('adapter.template.view', 'Simple');
$this->assertTrue(is_a($result, 'lithium\template\view\adapter\Simple'));
+<<<<<<< HEAD
$this->expectException("Class 'Foo' of type 'adapter.template.view' not found.");
+=======
+ $this->expectException("Class `Foo` of type `adapter.template.view` not found.");
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
$result = Libraries::instance('adapter.template.view', 'Foo');
}
@@ -368,7 +382,7 @@ class LibrariesTest extends \lithium\test\Unit {
$expected = '\lithium\data\source\Database';
$this->assertEqual($expected, $result);
- $expected = new \stdClass();
+ $expected = new stdClass();
$result = Libraries::locate(null, $expected);
$this->assertEqual($expected, $result);
}
@@ -549,6 +563,23 @@ class LibrariesTest extends \lithium\test\Unit {
$this->_cleanUp();
}
+<<<<<<< HEAD
+=======
+
+ /**
+ * Tests that `Libraries::realPath()` correctly resolves paths to files inside Phar archives.
+ *
+ * @return void
+ */
+ public function testPathsInPharArchives() {
+ $config = Libraries::get('lithium');
+ $path = "{$config['path']}/console/command/create/template/app.phar.gz";
+
+ $expected = "phar://{$path}/controllers/HelloWorldController.php";
+ $result = Libraries::realPath($expected);
+ $this->assertEqual($expected, $result);
+ }
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
}
?>
\ No newline at end of file
diff --git a/libraries/lithium/tests/cases/data/EntityTest.php b/libraries/lithium/tests/cases/data/EntityTest.php
index 6c1f597..407e405 100644
--- a/libraries/lithium/tests/cases/data/EntityTest.php
+++ b/libraries/lithium/tests/cases/data/EntityTest.php
@@ -60,7 +60,11 @@ class EntityTest extends \lithium\test\Unit {
public function testMethodDispatch() {
$entity = new Entity(array('model' => $this->_model, 'data' => array('foo' => true)));
$this->assertTrue($entity->validates());
+<<<<<<< HEAD
$this->expectException("/^No model bound or unhandled method call 'foo'.$/");
+=======
+ $this->expectException("/^No model bound or unhandled method call `foo`.$/");
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
$entity->foo();
}
diff --git a/libraries/lithium/tests/cases/data/ModelTest.php b/libraries/lithium/tests/cases/data/ModelTest.php
index acb5280..37aae72 100644
--- a/libraries/lithium/tests/cases/data/ModelTest.php
+++ b/libraries/lithium/tests/cases/data/ModelTest.php
@@ -9,20 +9,42 @@
namespace lithium\tests\cases\data;
use lithium\data\Model;
+<<<<<<< HEAD
use lithium\data\model\Query;
use lithium\data\Connections;
use lithium\analysis\Inspector;
use lithium\tests\mocks\data\MockTag;
use lithium\tests\mocks\data\MockPost;
+=======
+use lithium\data\Entity;
+use lithium\data\model\Query;
+use lithium\data\Connections;
+use lithium\analysis\Inspector;
+use lithium\data\entity\Record;
+use lithium\tests\mocks\data\MockTag;
+use lithium\tests\mocks\data\MockPost;
+use lithium\tests\mocks\data\MockSource;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
use lithium\tests\mocks\data\MockComment;
use lithium\tests\mocks\data\MockTagging;
use lithium\tests\mocks\data\MockCreator;
use lithium\tests\mocks\data\MockPostForValidates;
+<<<<<<< HEAD
+=======
+use lithium\tests\mocks\data\source\MockMongoConnection;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
class ModelTest extends \lithium\test\Unit {
protected $_configs = array();
+ protected $_altSchema = array(
+ 'id' => array('type' => 'integer'),
+ 'author_id' => array('type' => 'integer'),
+ 'title' => array('type' => 'string'),
+ 'body' => array('type' => 'text')
+ );
+
public function setUp() {
$this->_configs = Connections::config();
Connections::config(array('mock-source' => array(
@@ -218,7 +240,11 @@ class ModelTest extends \lithium\test\Unit {
$this->assertEqual(array('foo' => 13), $result['query']->conditions());
$this->assertEqual(array('created_at' => 'desc'), $result['query']->order());
+<<<<<<< HEAD
$this->expectException('/Method findFoo not defined or handled in class/');
+=======
+ $this->expectException('/Method `findFoo` not defined or handled in class/');
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
MockPost::findFoo();
}
@@ -229,7 +255,7 @@ class ModelTest extends \lithium\test\Unit {
*/
public function testSimpleFindFirst() {
$result = MockComment::first();
- $this->assertTrue($result instanceof \lithium\data\entity\Record);
+ $this->assertTrue($result instanceof Record);
$expected = 'First comment';
$this->assertEqual($expected, $result->text);
@@ -397,25 +423,23 @@ class ModelTest extends \lithium\test\Unit {
$this->assertEqual('mock-source', MockPost::meta('connection'));
MockPost::config(array('connection' => false));
$this->assertFalse(MockPost::meta('connection'));
+ $schema = MockPost::schema();
- $schema = array(
- 'id' => array('type' => 'integer'),
- 'author_id' => array('type' => 'integer'),
- 'title' => array('type' => 'string'),
- 'body' => array('type' => 'text')
- );
- MockPost::overrideSchema($schema);
- $this->assertEqual($schema, MockPost::schema());
+ MockPost::overrideSchema($this->_altSchema);
+ $this->assertEqual($this->_altSchema, MockPost::schema());
$post = MockPost::create(array('title' => 'New post'));
- $this->assertTrue($post instanceof \lithium\data\Entity);
+ $this->assertTrue($post instanceof Entity);
$this->assertEqual('New post', $post->title);
+ MockPost::overrideSchema($schema);
$this->expectException('/Connection name not defined/');
$post->save();
}
public function testSave() {
+ $schema = MockPost::schema();
+ MockPost::overrideSchema($this->_altSchema);
$data = array('title' => 'New post', 'author_id' => 13);
$record = MockPost::create($data);
$result = $record->save();
@@ -423,6 +447,7 @@ class ModelTest extends \lithium\test\Unit {
$this->assertEqual('create', $result['query']->type());
$this->assertEqual($data, $result['query']->data());
$this->assertEqual('lithium\tests\mocks\data\MockPost', $result['query']->model());
+ MockPost::overrideSchema($schema);
}
public function testSaveWithFailedValidation() {
@@ -502,6 +527,20 @@ class ModelTest extends \lithium\test\Unit {
$result = MockPost::count(array('conditions' => array('email' => 'foo@example.com')));
$this->assertEqual($query, $result['query']);
}
+
+ public function testSettingNestedObjectDefaults() {
+ MockPost::$connection = new MockMongoConnection();
+ $schema = MockPost::schema();
+
+ MockPost::overrideSchema($schema + array('nested.value' => array(
+ 'type' => 'string',
+ 'default' => 'foo'
+ )));
+ $this->assertEqual('foo', MockPost::create()->nested->value);
+
+ MockPost::overrideSchema($schema);
+ MockPost::$connection = null;
+ }
}
?>
\ No newline at end of file
diff --git a/libraries/lithium/tests/cases/data/collection/DocumentArrayTest.php b/libraries/lithium/tests/cases/data/collection/DocumentArrayTest.php
index a0a48c0..4241bdb 100644
--- a/libraries/lithium/tests/cases/data/collection/DocumentArrayTest.php
+++ b/libraries/lithium/tests/cases/data/collection/DocumentArrayTest.php
@@ -33,8 +33,11 @@ class DocumentArrayTest extends \lithium\test\Unit {
'data' => array('5', '6', '7')
));
$array[] = 8;
+<<<<<<< HEAD
// var_dump($array);
// var_dump($array->export());
+=======
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
}
}
diff --git a/libraries/lithium/tests/cases/data/entity/DocumentTest.php b/libraries/lithium/tests/cases/data/entity/DocumentTest.php
index caf8e2e..2bbd31e 100644
--- a/libraries/lithium/tests/cases/data/entity/DocumentTest.php
+++ b/libraries/lithium/tests/cases/data/entity/DocumentTest.php
@@ -349,7 +349,7 @@ class DocumentTest extends \lithium\test\Unit {
public function testInvalidCall() {
$doc = new Document();
- $this->expectException("No model bound or unhandled method call 'medicin'.");
+ $this->expectException("No model bound or unhandled method call `medicin`.");
$result = $doc->medicin();
$this->assertNull($result);
}
@@ -560,6 +560,7 @@ class DocumentTest extends \lithium\test\Unit {
$doc->nested = array('more' => 'data');
$newData = $doc->export();
+<<<<<<< HEAD
$expected = array('foo' => 'bar', 'baz' => 'dib', 'nested.more' => 'data');
$this->assertFalse($newData['exists']);
@@ -573,6 +574,21 @@ class DocumentTest extends \lithium\test\Unit {
$this->assertFalse($result['update']);
$this->assertEqual('nested', $result['key']);
+=======
+
+ $expected = array('foo' => 'bar', 'baz' => 'dib', 'nested.more' => 'data');
+ $this->assertFalse($newData['exists']);
+ $this->assertEqual(array('foo' => 'bar', 'baz' => 'dib'), $newData['data']);
+ $this->assertEqual(1, count($newData['update']));
+ $this->assertTrue($newData['update']['nested'] instanceof Document);
+
+ $result = $newData['update']['nested']->export();
+ $this->assertFalse($result['exists']);
+ $this->assertEqual(array('more' => 'data'), $result['data']);
+ $this->assertFalse($result['update']);
+ $this->assertEqual('nested', $result['key']);
+
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
$doc = new Document(compact('model') + array('exists' => true, 'data' => array(
'foo' => 'bar', 'baz' => 'dib'
)));
@@ -601,6 +617,10 @@ class DocumentTest extends \lithium\test\Unit {
$doc->more = 'cowbell';
$doc->nested->evenMore = 'cowbell';
$modified = $doc->export();
+<<<<<<< HEAD
+=======
+
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
$expected = array('more' => 'cowbell');
$this->assertEqual($expected, $modified['update']);
$this->assertEqual(array('nested', 'foo', 'baz'), array_keys($modified['data']));
@@ -630,6 +650,23 @@ class DocumentTest extends \lithium\test\Unit {
$result = $doc->data();
$this->assertPattern('/^[a-f0-9]{24}$/', $result['id']);
$this->assertEqual(time(), $result['date']);
+<<<<<<< HEAD
+=======
+ }
+
+ public function testInitializationWithNestedFields() {
+ $doc = new Document(array('model' => $this->_model, 'data' => array(
+ 'simple' => 'value',
+ 'nested.foo' => 'first',
+ 'nested.bar' => 'second',
+ 'really.nested.key' => 'value'
+ )));
+ $this->assertEqual('value', $doc->simple);
+ $this->assertEqual('first', $doc->nested->foo);
+ $this->assertEqual('second', $doc->nested->bar);
+ $this->assertEqual('value', $doc->really->nested->key);
+ $this->assertEqual(array('simple', 'nested', 'really'), array_keys($doc->data()));
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
}
}
diff --git a/libraries/lithium/tests/cases/data/entity/RecordTest.php b/libraries/lithium/tests/cases/data/entity/RecordTest.php
index 055b9c8..da5569c 100644
--- a/libraries/lithium/tests/cases/data/entity/RecordTest.php
+++ b/libraries/lithium/tests/cases/data/entity/RecordTest.php
@@ -130,7 +130,7 @@ class RecordTest extends \lithium\test\Unit {
$this->assertEqual('create', $result['query']->type());
$this->assertEqual(array('title' => 'foo'), $result['query']->data());
- $this->expectException("No model bound or unhandled method call 'invalid'.");
+ $this->expectException("No model bound or unhandled method call `invalid`.");
$this->assertNull($this->record->invalid());
}
}
diff --git a/libraries/lithium/tests/cases/data/model/QueryTest.php b/libraries/lithium/tests/cases/data/model/QueryTest.php
index 0c7c5ae..55da84f 100644
--- a/libraries/lithium/tests/cases/data/model/QueryTest.php
+++ b/libraries/lithium/tests/cases/data/model/QueryTest.php
@@ -244,6 +244,7 @@ class QueryTest extends \lithium\test\Unit {
}
public function testExport() {
+ MockQueryPost::meta('source', 'foo');
$query = new Query($this->_queryArr);
$ds = new MockDatabase();
$export = $query->export($ds);
@@ -281,9 +282,12 @@ class QueryTest extends \lithium\test\Unit {
$result = $export['fields'];
$this->assertEqual($expected, $result);
- $expected = MockQueryPost::meta('source');
$result = $export['source'];
+<<<<<<< HEAD
$this->assertEqual("{{$expected}}", $result);
+=======
+ $this->assertEqual("{foo}", $result);
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
}
public function testRestrictedKeyExport() {
@@ -321,15 +325,34 @@ class QueryTest extends \lithium\test\Unit {
$query = new Query(array('joins' => array(array('foo' => 'bar'))));
$query->join(array('bar' => 'baz'));
$expected = array(array('foo' => 'bar'), array('bar' => 'baz'));
+<<<<<<< HEAD
$this->assertEqual($expected, $query->join());
$query->join('zim', array('dib' => 'gir'));
+=======
+ $joins = $query->join();
+
+ $this->assertEqual('bar', $joins[0]->foo());
+ $this->assertNull($joins[0]->bar());
+
+ $this->assertEqual('baz', $joins[1]->bar());
+ $this->assertNull($joins[1]->foo());
+
+ $query->join('zim', array('dib' => 'gir'));
+ $this->assertEqual(3, count($query->join()));
+
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
$expected = array(
array('foo' => 'bar'),
array('bar' => 'baz'),
'zim' => array('dib' => 'gir')
);
+<<<<<<< HEAD
$this->assertEqual($expected, $query->join());
+=======
+ $this->assertEqual(3, count($query->join()));
+ $this->assertEqual('gir', $query->join('zim')->dib());
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
}
/**
@@ -408,6 +431,31 @@ class QueryTest extends \lithium\test\Unit {
$this->assertEqual($fields, $query->fields());
$this->assertEqual($order, $query->order());
}
+<<<<<<< HEAD
+=======
+
+ public function testRenderArrayJoin() {
+ $model = 'lithium\tests\mocks\data\model\MockQueryComment';
+
+ $query = new Query(compact('model') + array(
+ 'type' => 'read',
+ 'source' => 'comments',
+ 'alias' => 'Comment',
+ 'conditions' => array('Comment.id' => 1),
+ 'joins' => array(array(
+ 'type' => 'INNER',
+ 'source' => 'posts',
+ 'alias' => 'Post',
+ 'constraint' => array('Comment.post_id' => 'Post.id')
+ ))
+ ));
+
+ $expected = "SELECT * FROM AS {Comment} INNER JOIN {posts} AS {Post} ON ";
+ $expected .= "{Comment}.{post_id} = {Post}.{id} WHERE Comment.id = 1;";
+ $result = Connections::get('mock-database-connection')->renderCommand($query);
+ $this->assertEqual($expected, $result);
+ }
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
}
?>
\ No newline at end of file
diff --git a/libraries/lithium/tests/cases/data/source/MongoDbTest.php b/libraries/lithium/tests/cases/data/source/MongoDbTest.php
index 8052647..9a4b623 100644
--- a/libraries/lithium/tests/cases/data/source/MongoDbTest.php
+++ b/libraries/lithium/tests/cases/data/source/MongoDbTest.php
@@ -23,6 +23,10 @@ use lithium\data\entity\Document;
use lithium\tests\mocks\data\MockPost;
use lithium\data\collection\DocumentSet;
use lithium\data\collection\DocumentArray;
+<<<<<<< HEAD
+=======
+use lithium\tests\mocks\data\source\MockMongoSource;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
use lithium\tests\mocks\data\source\MockMongoConnection;
class MongoDbTest extends \lithium\test\Unit {
@@ -241,37 +245,55 @@ class MongoDbTest extends \lithium\test\Unit {
}
public function testReadNoConditions() {
+ $this->db->connect();
+ $connection = $this->db->connection;
+ $this->db->connection = new MockMongoSource();
+ $this->db->connection->resultSets = array(array('ok' => true));
+
$data = array('title' => 'Test Post');
+ $options = array('safe' => false, 'fsync' => false);
$this->query->data($data);
- $this->db->create($this->query);
+ $this->assertIdentical(true, $this->db->create($this->query));
+ $this->assertEqual(compact('data', 'options'), end($this->db->connection->queries));
+ $this->db->connection->resultSets = array(array(array('_id' => new MongoId()) + $data));
$result = $this->db->read($this->query);
+<<<<<<< HEAD
$this->assertTrue($result instanceof DocumentSet);
$this->assertEqual(1, $result->count());
+=======
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
- $expected = $data['title'];
- $this->assertEqual($expected, $result->first()->title);
+ $this->assertTrue($result instanceof DocumentSet);
+ $this->assertEqual(1, $result->count());
+ $this->assertEqual('Test Post', $result->first()->title);
+ $this->db->connection = $connection;
}
public function testReadWithConditions() {
+ $this->db->connect();
+ $connection = $this->db->connection;
+ $this->db->connection = new MockMongoSource();
+ $this->db->connection->resultSets = array(array('ok' => true));
+
$data = array('title' => 'Test Post');
+ $options = array('safe' => false, 'fsync' => false);
$this->query->data($data);
- $this->db->create($this->query);
+ $this->assertTrue($this->db->create($this->query));
$this->query->data(null);
+ $this->db->connection->resultSets = array(array());
$this->query->conditions(array('title' => 'Nonexistent Post'));
$result = $this->db->read($this->query);
$this->assertTrue($result == true);
+ $this->assertEqual(0, $result->count());
- $expected = 0;
- $this->assertEqual($expected, $result->count());
-
+ $this->db->connection->resultSets = array(array($data));
$this->query->conditions($data);
$result = $this->db->read($this->query);
$this->assertTrue($result == true);
-
- $expected = 1;
- $this->assertEqual($expected, $result->count());
+ $this->assertEqual(1, $result->count());
+ $this->db->connection = $connection;
}
public function testUpdate() {
@@ -293,6 +315,7 @@ class MongoDbTest extends \lithium\test\Unit {
'conditions' => array('_id' => $original['_id'])
));
$this->assertTrue($this->db->update($this->query));
+<<<<<<< HEAD
$result = $this->db->read(new Query(compact('model') + array(
'conditions' => array('_id' => $original['_id'])
@@ -300,6 +323,16 @@ class MongoDbTest extends \lithium\test\Unit {
$this->assertEqual(1, $result->count());
$updated = $result->first()->to('array');
+=======
+
+ $result = $this->db->read(new Query(compact('model') + array(
+ 'conditions' => array('_id' => $original['_id'])
+ )));
+ $this->assertEqual(1, $result->count());
+
+ $updated = $result->first();
+ $updated = $updated ? $updated->to('array') : array();
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
$this->assertEqual($original['_id'], $updated['_id']);
$this->assertEqual('New Post Title', $updated['title']);
}
@@ -449,17 +482,19 @@ class MongoDbTest extends \lithium\test\Unit {
$to = 'lithium\tests\mocks\data\MockPost';
$from::config(array('connection' => 'mock-source'));
- $to::config(array('connection' => 'mock-source'));
+ $to::config(array('connection' => 'mock-source', 'key' => '_id'));
$result = $this->db->relationship($from, 'belongsTo', 'MockPost');
- $expected = compact('from', 'to') + array(
+ $expected = array(
'name' => 'MockPost',
'type' => 'belongsTo',
'keys' => array('mockComment' => '_id'),
+ 'from' => $from,
'link' => 'contained',
- 'conditions' => null,
+ 'to' => $to,
'fields' => true,
'fieldName' => 'mockPost',
+ 'constraint' => null,
'init' => true
);
$this->assertEqual($expected, $result->data());
@@ -505,7 +540,7 @@ class MongoDbTest extends \lithium\test\Unit {
$duplicate = $model::create(array('_id' => $document->_id), array('exists' => true));
$duplicate->values = 'new';
- $duplicate->save();
+ $this->assertTrue($duplicate->save());
$document = $model::find((string) $duplicate->_id);
$expected = array(
@@ -545,7 +580,11 @@ class MongoDbTest extends \lithium\test\Unit {
$result = $this->db->conditions($conditions, $query);
$this->assertEqual(array_keys($conditions), array_keys($result));
+<<<<<<< HEAD
$this->assertTrue($result['_id'] instanceOf MongoId);
+=======
+ $this->assertTrue($result['_id'] instanceof MongoId);
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
$this->assertEqual($conditions['_id'], (string) $result['_id']);
$conditions = array('_id' => array(
@@ -553,9 +592,15 @@ class MongoDbTest extends \lithium\test\Unit {
));
$result = $this->db->conditions($conditions, $query);
$this->assertEqual(3, count($result['_id']['$in']));
+<<<<<<< HEAD
$this->assertTrue($result['_id']['$in'][0] instanceOf MongoId);
$this->assertTrue($result['_id']['$in'][1] instanceOf MongoId);
$this->assertTrue($result['_id']['$in'][2] instanceOf MongoId);
+=======
+ $this->assertTrue($result['_id']['$in'][0] instanceof MongoId);
+ $this->assertTrue($result['_id']['$in'][1] instanceof MongoId);
+ $this->assertTrue($result['_id']['$in'][2] instanceof MongoId);
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
$conditions = array('voters' => array('$all' => array(
"4c8f86167675abfabdbf0300", "4c8f86167675abfabdc00300"
@@ -563,8 +608,13 @@ class MongoDbTest extends \lithium\test\Unit {
$result = $this->db->conditions($conditions, $query);
$this->assertEqual(2, count($result['voters']['$all']));
+<<<<<<< HEAD
$this->assertTrue($result['voters']['$all'][0] instanceOf MongoId);
$this->assertTrue($result['voters']['$all'][1] instanceOf MongoId);
+=======
+ $this->assertTrue($result['voters']['$all'][0] instanceof MongoId);
+ $this->assertTrue($result['voters']['$all'][1] instanceof MongoId);
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
$conditions = array('$or' => array(
array('_id' => "4c8f86167675abfabdbf0300"),
@@ -573,8 +623,13 @@ class MongoDbTest extends \lithium\test\Unit {
$result = $this->db->conditions($conditions, $query);
$this->assertEqual(array('$or'), array_keys($result));
$this->assertEqual(2, count($result['$or']));
+<<<<<<< HEAD
$this->assertTrue($result['$or'][0]['_id'] instanceOf MongoId);
$this->assertTrue($result['$or'][1]['guid'] instanceOf MongoId);
+=======
+ $this->assertTrue($result['$or'][0]['_id'] instanceof MongoId);
+ $this->assertTrue($result['$or'][1]['guid'] instanceof MongoId);
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
}
public function testMultiOperationConditions() {
diff --git a/libraries/lithium/tests/cases/data/source/mongo_db/ExporterTest.php b/libraries/lithium/tests/cases/data/source/mongo_db/ExporterTest.php
index 1a0f062..f5d9db6 100644
--- a/libraries/lithium/tests/cases/data/source/mongo_db/ExporterTest.php
+++ b/libraries/lithium/tests/cases/data/source/mongo_db/ExporterTest.php
@@ -245,6 +245,7 @@ class ExporterTest extends \lithium\test\Unit {
$result = Exporter::cast($data, $this->_schema, $model::connection(), $options);
$this->assertEqual(array_keys($data), array_keys($result));
+<<<<<<< HEAD
$this->assertTrue($result['_id'] instanceOf MongoId);
$this->assertEqual('4c8f86167675abfabd970300', (string) $result['_id']);
@@ -254,6 +255,17 @@ class ExporterTest extends \lithium\test\Unit {
$this->assertTrue($result['comments'][0] instanceOf MongoId);
$this->assertTrue($result['comments'][1] instanceOf MongoId);
$this->assertTrue($result['comments'][2] instanceOf MongoId);
+=======
+ $this->assertTrue($result['_id'] instanceof MongoId);
+ $this->assertEqual('4c8f86167675abfabd970300', (string) $result['_id']);
+
+ $this->assertTrue($result['comments'] instanceof DocumentArray);
+ $this->assertEqual(3, count($result['comments']));
+
+ $this->assertTrue($result['comments'][0] instanceof MongoId);
+ $this->assertTrue($result['comments'][1] instanceof MongoId);
+ $this->assertTrue($result['comments'][2] instanceof MongoId);
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
$this->assertEqual('4c8f86167675abfabdbe0300', (string) $result['comments'][0]);
$this->assertEqual('4c8f86167675abfabdbf0300', (string) $result['comments'][1]);
$this->assertEqual('4c8f86167675abfabdc00300', (string) $result['comments'][2]);
@@ -261,10 +273,17 @@ class ExporterTest extends \lithium\test\Unit {
$this->assertEqual($data['comments'], $result['comments']->data());
$this->assertEqual(array('test'), $result['tags']->data());
$this->assertEqual(array('4c8f86167675abfabdb00300'), $result['authors']->data());
+<<<<<<< HEAD
$this->assertTrue($result['authors'][0] instanceOf MongoId);
$this->assertTrue($result['modified'] instanceOf MongoDate);
$this->assertTrue($result['created'] instanceOf MongoDate);
+=======
+ $this->assertTrue($result['authors'][0] instanceof MongoId);
+
+ $this->assertTrue($result['modified'] instanceof MongoDate);
+ $this->assertTrue($result['created'] instanceof MongoDate);
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
$this->assertTrue($result['created']->usec > 0);
$this->assertEqual($time, $result['modified']->sec);
diff --git a/libraries/lithium/tests/cases/g11n/CatalogTest.php b/libraries/lithium/tests/cases/g11n/CatalogTest.php
index f761dc6..90fcea4 100644
--- a/libraries/lithium/tests/cases/g11n/CatalogTest.php
+++ b/libraries/lithium/tests/cases/g11n/CatalogTest.php
@@ -306,78 +306,70 @@ class CatalogTest extends \lithium\test\Unit {
$data = array('house' => 'Haus');
Catalog::write('runtime', 'message', 'de', $data);
$result = Catalog::read('runtime', 'message', 'de', array('lossy' => false));
- $expected = array(
- 'house' => array(
- 'id' => 'house',
- 'ids' => array(),
- 'translated' => 'Haus',
- 'flags' => array(),
- 'comments' => array(),
- 'occurrences' => array()
+ $expected = array('house' => array(
+ 'id' => 'house',
+ 'ids' => array(),
+ 'translated' => 'Haus',
+ 'flags' => array(),
+ 'comments' => array(),
+ 'occurrences' => array()
));
$this->assertEqual($expected, $result);
- $data = array(
- 'house' => array(
- 'id' => 'house',
- 'ids' => array(),
- 'translated' => 'Haus',
- 'flags' => array(),
- 'comments' => array(),
- 'occurrences' => array()
+ $data = array('house' => array(
+ 'id' => 'house',
+ 'ids' => array(),
+ 'translated' => 'Haus',
+ 'flags' => array(),
+ 'comments' => array(),
+ 'occurrences' => array()
));
Catalog::write('runtime', 'message', 'de', $data);
$result = Catalog::read('runtime', 'message', 'de', array('lossy' => false));
- $expected = array(
- 'house' => array(
- 'id' => 'house',
- 'ids' => array(),
- 'translated' => 'Haus',
- 'flags' => array(),
- 'comments' => array(),
- 'occurrences' => array()
+ $expected = array('house' => array(
+ 'id' => 'house',
+ 'ids' => array(),
+ 'translated' => 'Haus',
+ 'flags' => array(),
+ 'comments' => array(),
+ 'occurrences' => array()
));
$this->assertEqual($expected, $result);
}
public function testOutputLossyFormat() {
- $data = array(
- 'house' => array(
- 'id' => 'house',
- 'ids' => array('singular' => 'house'),
- 'translated' => 'Haus',
- 'flags' => array(),
- 'comments' => array(),
- 'occurrences' => array()
+ $data = array('house' => array(
+ 'id' => 'house',
+ 'ids' => array('singular' => 'house'),
+ 'translated' => 'Haus',
+ 'flags' => array(),
+ 'comments' => array(),
+ 'occurrences' => array()
));
Catalog::write('runtime', 'message', 'de', $data);
$result = Catalog::read('runtime', 'message', 'de');
- $expected = array(
- 'house' => 'Haus'
- );
+ $expected = array('house' => 'Haus');
$this->assertEqual($expected, $result);
}
public function testOutputLosslessFormat() {
- $data = array(
- 'house' => array(
- 'id' => 'house',
- 'ids' => array('singular' => 'house'),
- 'translated' => 'Haus',
- 'flags' => array(),
- 'comments' => array(),
- 'occurrences' => array()
+ $data = array('house' => array(
+ 'id' => 'house',
+ 'ids' => array('singular' => 'house'),
+ 'translated' => 'Haus',
+ 'flags' => array(),
+ 'comments' => array(),
+ 'occurrences' => array()
));
Catalog::write('runtime', 'message', 'de', $data);
$result = Catalog::read('runtime', 'message', 'de', array('lossy' => false));
- $expected = array(
- 'house' => array(
- 'id' => 'house',
- 'ids' => array('singular' => 'house'),
- 'translated' => 'Haus',
- 'flags' => array(),
- 'comments' => array(),
- 'occurrences' => array()
+ $expected = array('house' => array(
+ 'id' => 'house',
+ 'ids' => array('singular' => 'house'),
+ 'translated' => 'Haus',
+ 'flags' => array(),
+ 'comments' => array(),
+ 'occurrences' => array()
));
$this->assertEqual($expected, $result);
}
@@ -385,7 +377,7 @@ class CatalogTest extends \lithium\test\Unit {
public function testInvalidWrite() {
Catalog::reset();
$data = array('house' => array('id' => 'house'));
- $this->expectException("Configuration 'runtime' has not been defined.");
+ $this->expectException("Configuration `runtime` has not been defined.");
$this->assertFalse(Catalog::write('runtime', 'message', 'de', $data));
}
}
diff --git a/libraries/lithium/tests/cases/g11n/catalog/AdapterTest.php b/libraries/lithium/tests/cases/g11n/catalog/AdapterTest.php
index 1a144dc..c3475eb 100644
--- a/libraries/lithium/tests/cases/g11n/catalog/AdapterTest.php
+++ b/libraries/lithium/tests/cases/g11n/catalog/AdapterTest.php
@@ -8,7 +8,11 @@
namespace lithium\tests\cases\g11n\catalog;
+<<<<<<< HEAD
use \Exception;
+=======
+use Exception;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
use lithium\tests\mocks\g11n\catalog\MockAdapter;
class AdapterTest extends \lithium\test\Unit {
diff --git a/libraries/lithium/tests/cases/g11n/catalog/adapter/CodeTest.php b/libraries/lithium/tests/cases/g11n/catalog/adapter/CodeTest.php
index f414d48..6228fa6 100644
--- a/libraries/lithium/tests/cases/g11n/catalog/adapter/CodeTest.php
+++ b/libraries/lithium/tests/cases/g11n/catalog/adapter/CodeTest.php
@@ -8,7 +8,11 @@
namespace lithium\tests\cases\g11n\catalog\adapter;
+<<<<<<< HEAD
use \Exception;
+=======
+use Exception;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
use lithium\g11n\catalog\adapter\Code;
class CodeTest extends \lithium\test\Unit {
diff --git a/libraries/lithium/tests/cases/g11n/catalog/adapter/GettextTest.php b/libraries/lithium/tests/cases/g11n/catalog/adapter/GettextTest.php
index 0c8d70d..b58ed43 100644
--- a/libraries/lithium/tests/cases/g11n/catalog/adapter/GettextTest.php
+++ b/libraries/lithium/tests/cases/g11n/catalog/adapter/GettextTest.php
@@ -8,7 +8,11 @@
namespace lithium\tests\cases\g11n\catalog\adapter;
+<<<<<<< HEAD
use \Exception;
+=======
+use Exception;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
use lithium\tests\mocks\g11n\catalog\adapter\MockGettext;
class GettextTest extends \lithium\test\Unit {
diff --git a/libraries/lithium/tests/cases/g11n/catalog/adapter/PhpTest.php b/libraries/lithium/tests/cases/g11n/catalog/adapter/PhpTest.php
index 37246c3..ca89bb0 100644
--- a/libraries/lithium/tests/cases/g11n/catalog/adapter/PhpTest.php
+++ b/libraries/lithium/tests/cases/g11n/catalog/adapter/PhpTest.php
@@ -8,7 +8,11 @@
namespace lithium\tests\cases\g11n\catalog\adapter;
+<<<<<<< HEAD
use \Exception;
+=======
+use Exception;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
use lithium\g11n\catalog\adapter\Php;
class PhpTest extends \lithium\test\Unit {
diff --git a/libraries/lithium/tests/cases/net/http/MediaTest.php b/libraries/lithium/tests/cases/net/http/MediaTest.php
index 635c469..b045fb4 100644
--- a/libraries/lithium/tests/cases/net/http/MediaTest.php
+++ b/libraries/lithium/tests/cases/net/http/MediaTest.php
@@ -319,7 +319,7 @@ class MediaTest extends \lithium\test\Unit {
$response = new Response();
$response->type('bad');
- $this->expectException("Unhandled media type 'bad'");
+ $this->expectException("Unhandled media type `bad`.");
Media::render($response, array('foo' => 'bar'));
$result = $response->body;
@@ -336,7 +336,7 @@ class MediaTest extends \lithium\test\Unit {
$response = new Response();
$response->type('xml');
- $this->expectException("Unhandled media type 'xml'");
+ $this->expectException("Unhandled media type `xml`.");
Media::render($response, array('foo' => 'bar'));
$result = $response->body;
diff --git a/libraries/lithium/tests/cases/net/http/RouterTest.php b/libraries/lithium/tests/cases/net/http/RouterTest.php
index 5cf5616..03a58a5 100644
--- a/libraries/lithium/tests/cases/net/http/RouterTest.php
+++ b/libraries/lithium/tests/cases/net/http/RouterTest.php
@@ -406,6 +406,13 @@ class RouterTest extends \lithium\test\Unit {
$expected = '/my/web/path/posts';
$this->assertEqual($expected, $result);
+ $request = new Request(array('base' => '/my/web/path'));
+ $result = Router::match('/some/where', $request, array('absolute' => true));
+ $prefix = $this->request->env('HTTPS') ? 'https://' : 'http://';
+ $prefix .= $this->request->env('HTTP_HOST');
+ $this->assertEqual($prefix . '/my/web/path/some/where', $result);
+
+
$result = Router::match('mailto:foo@localhost');
$expected = 'mailto:foo@localhost';
$this->assertEqual($expected, $result);
diff --git a/libraries/lithium/tests/cases/security/AuthTest.php b/libraries/lithium/tests/cases/security/AuthTest.php
index bb4e4b2..32eac7b 100644
--- a/libraries/lithium/tests/cases/security/AuthTest.php
+++ b/libraries/lithium/tests/cases/security/AuthTest.php
@@ -20,7 +20,7 @@ class AuthTest extends \lithium\test\Unit {
Auth::config(array(
'test' => array(
- 'adapter' => '\lithium\tests\mocks\security\auth\adapter\MockAuthAdapter'
+ 'adapter' => 'lithium\tests\mocks\security\auth\adapter\MockAuthAdapter'
)
));
}
@@ -73,7 +73,7 @@ class AuthTest extends \lithium\test\Unit {
public function testNoConfigurations() {
Auth::reset();
$this->assertIdentical(array(), Auth::config());
- $this->expectException("Configuration 'user' has not been defined.");
+ $this->expectException("Configuration `user` has not been defined.");
Auth::check('user');
}
}
diff --git a/libraries/lithium/tests/cases/storage/CacheTest.php b/libraries/lithium/tests/cases/storage/CacheTest.php
index e227d16..30cafda 100644
--- a/libraries/lithium/tests/cases/storage/CacheTest.php
+++ b/libraries/lithium/tests/cases/storage/CacheTest.php
@@ -10,7 +10,11 @@ namespace lithium\tests\cases\storage;
use lithium\storage\Cache;
use lithium\util\Collection;
+<<<<<<< HEAD
use \SplFileInfo;
+=======
+use SplFileInfo;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
class CacheTest extends \lithium\test\Unit {
diff --git a/libraries/lithium/tests/cases/storage/SessionTest.php b/libraries/lithium/tests/cases/storage/SessionTest.php
index 79af4bd..726c4b3 100644
--- a/libraries/lithium/tests/cases/storage/SessionTest.php
+++ b/libraries/lithium/tests/cases/storage/SessionTest.php
@@ -189,7 +189,7 @@ class SessionTest extends \lithium\test\Unit {
public function testSessionState() {
$this->assertTrue(Session::isStarted());
$this->assertTrue(Session::isStarted('default'));
- $this->expectException("Configuration 'invalid' has not been defined.");
+ $this->expectException("Configuration `invalid` has not been defined.");
$this->assertFalse(Session::isStarted('invalid'));
}
@@ -200,7 +200,7 @@ class SessionTest extends \lithium\test\Unit {
public function testSessionStateResetNamed() {
Session::reset();
- $this->expectException("Configuration 'default' has not been defined.");
+ $this->expectException("Configuration `default` has not been defined.");
$this->assertFalse(Session::isStarted('default'));
}
diff --git a/libraries/lithium/tests/cases/storage/cache/adapter/FileTest.php b/libraries/lithium/tests/cases/storage/cache/adapter/FileTest.php
index eef9aa2..9aba8ec 100644
--- a/libraries/lithium/tests/cases/storage/cache/adapter/FileTest.php
+++ b/libraries/lithium/tests/cases/storage/cache/adapter/FileTest.php
@@ -9,7 +9,11 @@
namespace lithium\tests\cases\storage\cache\adapter;
use lithium\storage\cache\adapter\File;
+<<<<<<< HEAD
use \SplFileInfo;
+=======
+use SplFileInfo;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
class FileTest extends \lithium\test\Unit {
diff --git a/libraries/lithium/tests/cases/template/ViewTest.php b/libraries/lithium/tests/cases/template/ViewTest.php
index 5bbde6f..7e50180 100644
--- a/libraries/lithium/tests/cases/template/ViewTest.php
+++ b/libraries/lithium/tests/cases/template/ViewTest.php
@@ -9,6 +9,7 @@
namespace lithium\tests\cases\template;
use lithium\template\View;
+<<<<<<< HEAD
use lithium\g11n\catalog\adapter\Memory;
use lithium\template\view\adapter\Simple;
@@ -18,6 +19,12 @@ class TestViewClass extends \lithium\template\View {
return $this->_config['renderer'];
}
}
+=======
+use lithium\action\Response;
+use lithium\g11n\catalog\adapter\Memory;
+use lithium\template\view\adapter\Simple;
+use lithium\tests\mocks\template\MockView;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
class ViewTest extends \lithium\test\Unit {
@@ -29,15 +36,18 @@ class ViewTest extends \lithium\test\Unit {
public function testInitialization() {
$expected = new Simple();
- $this->_view = new TestViewClass(array('renderer' => $expected));
+ $this->_view = new MockView(array('renderer' => $expected));
$result = $this->_view->renderer();
$this->assertEqual($expected, $result);
}
- public function testInitializationWithBadClasses() {
- $this->expectException("Class 'Badness' of type 'adapter.template.view' not found.");
+ public function testInitializationWithBadLoader() {
+ $this->expectException("Class `Badness` of type `adapter.template.view` not found.");
new View(array('loader' => 'Badness'));
- $this->expectException("Class 'Badness' of type 'adapter.template.view' not found.");
+ }
+
+ public function testInitializationWithBadRenderer() {
+ $this->expectException("Class `Badness` of type `adapter.template.view` not found.");
new View(array('renderer' => 'Badness'));
}
@@ -48,6 +58,31 @@ class ViewTest extends \lithium\test\Unit {
$this->assertEqual($expected, $result);
}
+ /**
+ * Tests that the output-escaping handler correctly inherits its encoding from the `Response`
+ * object, if provided.
+ *
+ * @return void
+ */
+ public function testEscapeOutputFilterWithInjectedEncoding() {
+ $message = "Multibyte string support must be enabled to test character encodings.";
+ $this->skipIf(!function_exists('mb_convert_encoding'), $message);
+
+ $string = "Joël";
+
+ $response = new Response();
+ $response->encoding = 'UTF-8';
+ $view = new View(compact('response'));
+ $handler = $view->outputFilters['h'];
+ $this->assertTrue(mb_check_encoding($handler($string), "UTF-8"));
+
+ $response = new Response();
+ $response->encoding = 'ISO-8859-1';
+ $view = new View(compact('response'));
+ $handler = $view->outputFilters['h'];
+ $this->assertTrue(mb_check_encoding($handler($string), "ISO-8859-1"));
+ }
+
public function testBasicRenderModes() {
$view = new View(array('loader' => 'Simple', 'renderer' => 'Simple'));
@@ -63,6 +98,12 @@ class ViewTest extends \lithium\test\Unit {
$expected = "Logged in as: Cap'n Crunch.";
$this->assertEqual($expected, $result);
+ $result = $view->render('element', array('name' => "Cap'n Crunch"), array(
+ 'element' => 'Logged in as: {:name}.'
+ ));
+ $expected = "Logged in as: Cap'n Crunch.";
+ $this->assertEqual($expected, $result);
+
$xmlHeader = '<' . '?xml version="1.0" ?' . '>' . "\n";
$result = $view->render('all', array('type' => 'auth', 'success' => 'true'), array(
'layout' => $xmlHeader . "\n{:content}\n",
@@ -72,6 +113,20 @@ class ViewTest extends \lithium\test\Unit {
$this->assertEqual($expected, $result);
}
+ public function testTwoStepRenderWithVariableCapture() {
+ $view = new View(array('loader' => 'Simple', 'renderer' => 'Simple'));
+
+ $result = $view->render(
+ array(
+ array('path' => 'element', 'capture' => array('data' => 'foo')),
+ array('path' => 'template')
+ ),
+ array('name' => "Cap'n Crunch"),
+ array('element' => 'Logged in as: {:name}.', 'template' => '--{:foo}--')
+ );
+ $this->assertEqual('--Logged in as: Cap\'n Crunch.--', $result);
+ }
+
public function testFullRenderNoLayout() {
$view = new View(array('loader' => 'Simple', 'renderer' => 'Simple'));
$result = $view->render('all', array('type' => 'auth', 'success' => 'true'), array(
diff --git a/libraries/lithium/tests/cases/template/helper/FormTest.php b/libraries/lithium/tests/cases/template/helper/FormTest.php
index 573a92b..56e7aae 100755
--- a/libraries/lithium/tests/cases/template/helper/FormTest.php
+++ b/libraries/lithium/tests/cases/template/helper/FormTest.php
@@ -96,7 +96,11 @@ class FormTest extends \lithium\test\Unit {
$result = $this->form->create(null, array('id' => 'Registration'));
$this->assertTags($result, array(
- 'form' => array('action' => "{$this->base}posts", 'method' => 'post', 'id' => 'Registration')
+ 'form' => array(
+ 'action' => "{$this->base}posts",
+ 'method' => 'post',
+ 'id' => 'Registration'
+ )
));
}
@@ -267,6 +271,13 @@ class FormTest extends \lithium\test\Unit {
)));
}
+ public function testHiddenFieldWithId() {
+ $result = $this->form->hidden('my_field');
+ $this->assertTags($result, array('input' => array(
+ 'type' => 'hidden', 'name' => 'my_field', 'id' => 'MyField'
+ )));
+ }
+
public function testLabelGeneration() {
$result = $this->form->label('next', 'Enter the next value >>');
$this->assertTags($result, array(
@@ -648,6 +659,20 @@ class FormTest extends \lithium\test\Unit {
$this->assertEqual(join('', $expected), $result);
}
+ /**
+ * Verifies that calls to `field()` with `'type' => 'hidden'` do not produce `<label />`s.
+ *
+ * @return void
+ */
+ public function testHiddenFieldWithNoLabel() {
+ $result = $this->form->field('foo', array('type' => 'hidden'));
+ $this->assertTags($result, array(
+ 'div' => array(),
+ 'input' => array('type' => 'hidden', 'name' => 'foo', 'id' => 'Foo'),
+ '/div'
+ ));
+ }
+
public function testFormFieldWithCustomTemplate() {
$result = $this->form->field('name', array(
'template' => '<div{:wrap}>{:label}: {:input}{:error}</div>'
@@ -880,6 +905,7 @@ class FormTest extends \lithium\test\Unit {
'label' => array('for' => 'Name'), 'Name', '/label',
'input' => array('type' => 'text', 'name' => 'name', 'id' => 'Name'),
));
+<<<<<<< HEAD
}
/**
@@ -895,6 +921,29 @@ class FormTest extends \lithium\test\Unit {
$this->assertTags($result, array('input' => array(
'type' => 'text', 'name' => 'foo[bar]', 'id' => 'FooBar', 'value' => 'value'
)));
+=======
+ }
+
+ /**
+ * Tests that inputs for nested objects can be assigned using dot syntax.
+ *
+ * @return void
+ */
+ public function testNestedFieldAccess() {
+ $doc = new Document(array('data' => array('foo' => array('bar' => 'value'))));
+ $this->form->create($doc);
+
+ $result = $this->form->text('foo.bar');
+ $this->assertTags($result, array('input' => array(
+ 'type' => 'text', 'name' => 'foo[bar]', 'id' => 'FooBar', 'value' => 'value'
+ )));
+ }
+
+ public function testFormCreationWithNoContext() {
+ $this->form = new Form(array('context' => new MockFormRenderer()));
+ $result = $this->form->create(null, array('url' => '/foo'));
+ $this->assertTags($result, array('form' => array('action' => "/foo", 'method'=> "post")));
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
}
}
diff --git a/libraries/lithium/tests/cases/template/helper/HtmlTest.php b/libraries/lithium/tests/cases/template/helper/HtmlTest.php
index ac06d93..34119cc 100644
--- a/libraries/lithium/tests/cases/template/helper/HtmlTest.php
+++ b/libraries/lithium/tests/cases/template/helper/HtmlTest.php
@@ -10,6 +10,11 @@ namespace lithium\tests\cases\template\helper;
use lithium\net\http\Router;
use lithium\template\helper\Html;
+<<<<<<< HEAD
+=======
+use lithium\action\Request;
+use lithium\action\Response;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
use lithium\tests\mocks\template\helper\MockHtmlRenderer;
class HtmlTest extends \lithium\test\Unit {
@@ -34,7 +39,12 @@ class HtmlTest extends \lithium\test\Unit {
Router::connect('/{:controller}/{:action}/{:id}.{:type}');
Router::connect('/{:controller}/{:action}.{:type}');
- $this->context = new MockHtmlRenderer();
+ $this->context = new MockHtmlRenderer(array(
+ 'request' => new Request(array(
+ 'base' => '', 'env' => array('HTTP_HOST' => 'foo.local')
+ )),
+ 'response' => new Response()
+ ));
$this->html = new Html(array('context' => &$this->context));
}
@@ -53,21 +63,25 @@ class HtmlTest extends \lithium\test\Unit {
}
/**
- * Tests that character set declarations render the correct character set and meta tag.
+ * Tests that character set declarations render the
+ * correct character set and short meta tag.
*
* @return void
*/
public function testCharset() {
$result = $this->html->charset();
+ $this->assertTags($result, array('meta' => array(
+ 'charset' => 'UTF-8'
+ )));
+ $result = $this->html->charset('utf-8');
$this->assertTags($result, array('meta' => array(
- 'http-equiv' => 'Content-Type', 'content' => 'text/html; charset=utf-8'
+ 'charset' => 'utf-8'
)));
$result = $this->html->charset('UTF-7');
-
$this->assertTags($result, array('meta' => array(
- 'http-equiv' => 'Content-Type', 'content' => 'text/html; charset=UTF-7'
+ 'charset' => 'UTF-7'
)));
}
@@ -350,7 +364,13 @@ class HtmlTest extends \lithium\test\Unit {
$expected = array('meta' => array('author' => 'foo'));
$this->assertTags($result, $expected);
+<<<<<<< HEAD
$result = $this->html->head('unexisting-name', array('options' => array('author' => 'foo')));
+=======
+ $result = $this->html->head('unexisting-name', array(
+ 'options' => array('author' => 'foo')
+ ));
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
$this->assertNull($result);
}
diff --git a/libraries/lithium/tests/cases/template/view/RendererTest.php b/libraries/lithium/tests/cases/template/view/RendererTest.php
index a005033..815585b 100644
--- a/libraries/lithium/tests/cases/template/view/RendererTest.php
+++ b/libraries/lithium/tests/cases/template/view/RendererTest.php
@@ -10,6 +10,7 @@ namespace lithium\tests\cases\template\view;
use lithium\template\View;
use lithium\action\Request;
+use lithium\action\Response;
use lithium\template\Helper;
use lithium\template\helper\Html;
use lithium\template\view\adapter\Simple;
@@ -22,9 +23,12 @@ class RendererTest extends \lithium\test\Unit {
$this->_routes = Router::get();
Router::reset();
Router::connect('/{:controller}/{:action}');
- $this->subject = new Simple(array('request' => new Request(array(
- 'base' => '', 'env' => array('HTTP_HOST' => 'foo.local')
- ))));
+ $this->subject = new Simple(array(
+ 'request' => new Request(array(
+ 'base' => '', 'env' => array('HTTP_HOST' => 'foo.local')
+ )),
+ 'response' => new Response()
+ ));
}
public function tearDown() {
@@ -82,6 +86,7 @@ class RendererTest extends \lithium\test\Unit {
$class = get_class($helper);
$path = $this->subject->applyHandler($helper, "{$class}::script", 'path', 'foo/file');
$this->assertEqual('/js/foo/file.js', $path);
+ $this->assertEqual('/some/generic/path', $this->subject->path('some/generic/path'));
}
public function testHandlerInsertion() {
@@ -180,8 +185,10 @@ class RendererTest extends \lithium\test\Unit {
public function testGetters() {
$this->assertTrue($this->subject->request() instanceof Request);
+ $this->assertTrue($this->subject->response() instanceof Response);
$this->subject = new Simple();
$this->assertNull($this->subject->request());
+ $this->assertNull($this->subject->response());
}
public function testSetAndData() {
diff --git a/libraries/lithium/tests/cases/template/view/adapter/FileTest.php b/libraries/lithium/tests/cases/template/view/adapter/FileTest.php
index b70296b..800366e 100644
--- a/libraries/lithium/tests/cases/template/view/adapter/FileTest.php
+++ b/libraries/lithium/tests/cases/template/view/adapter/FileTest.php
@@ -83,14 +83,20 @@ class FileTest extends \lithium\test\Unit {
));
$this->assertPattern('/\/views\/pages\/home\.html\.php$/', $template);
- $template = $file->template('invalid', array('template' => 'foo'));
- $this->assertNull($template);
-
$this->expectException('/Template not found/');
$file->template('template', array(
'controller' => 'pages', 'template' => 'foo', 'type' => 'html'
));
}
+
+ public function testInvalidTemplateType() {
+ $file = new File(array('compile' => false, 'paths' => array(
+ 'template' => '{:library}/views/{:controller}/{:template}.{:type}.php'
+ )));
+
+ $this->expectException("Invalid template type 'invalid'.");
+ $template = $file->template('invalid', array('template' => 'foo'));
+ }
}
?>
\ No newline at end of file
diff --git a/libraries/lithium/tests/cases/test/UnitTest.php b/libraries/lithium/tests/cases/test/UnitTest.php
index 3493f85..0a7147b 100644
--- a/libraries/lithium/tests/cases/test/UnitTest.php
+++ b/libraries/lithium/tests/cases/test/UnitTest.php
@@ -11,7 +11,7 @@ namespace lithium\tests\cases\test;
use lithium\tests\mocks\test\MockUnitTest;
use lithium\tests\mocks\test\cases\MockSkipThrowsException;
use lithium\tests\mocks\test\cases\MockTestErrorHandling;
-use \Exception;
+use Exception;
class UnitTest extends \lithium\test\Unit {
@@ -65,19 +65,12 @@ class UnitTest extends \lithium\test\Unit {
'result' => 'fail', 'file' => __FILE__, 'line' => __LINE__ - 3,
'method' => 'testAssertEqualNumericFail', 'assertion' => 'assertEqual',
'class' => __CLASS__, 'message' =>
- "trace: [2]\nexpected: array (\n 0 => 1,\n 1 => 2,\n 2 => 3,\n)\n"
- . "result: array (\n 0 => 1,\n 1 => 2,\n)\n",
+ "trace: [2]\nexpected: 3\n"
+ . "result: NULL\n",
'data' => array(
'trace' => '[2]',
- 'expected' => array(
- 0 => 1,
- 1 => 2,
- 2 => 3,
- ),
- 'result' => array(
- 0 => 1,
- 1 => 2,
- )
+ 'expected' => 3,
+ 'result' => null
)
);
$result = array_pop($this->_results);
@@ -111,32 +104,22 @@ class UnitTest extends \lithium\test\Unit {
'result' => 'fail', 'file' => __FILE__, 'line' => __LINE__ - 3,
'method' => 'testAssertEqualThreeDFail', 'assertion' => 'assertEqual',
'class' => __CLASS__, 'message' =>
- "trace: [0][1][1]\nexpected: array (\n 0 => 1,\n 1 => 2,\n)\n"
- . "result: array (\n 0 => 1,\n)\n"
- . "trace: [1][1][1]\nexpected: array (\n 0 => 1,\n 1 => 2,\n)\n"
- . "result: array (\n 0 => 1,\n)\n",
+ "trace: [0][1][1]\nexpected: 2\n"
+ . "result: NULL\n"
+ . "trace: [1][1][1]\nexpected: 2\n"
+ . "result: NULL\n",
'data' => array(
array(
array(
'trace' => '[0][1][1]',
- 'expected' => array(
- 0 => 1,
- 1 => 2,
- ),
- 'result' => array(
- 0 => 1,
- )
+ 'expected' => 2,
+ 'result' => null
),
),
array(
array('trace' => '[1][1][1]',
- 'expected' => array(
- 0 => 1,
- 1 => 2,
- ),
- 'result' => array(
- 0 => 1,
- )
+ 'expected' => 2,
+ 'result' => null
)
)
)
@@ -493,11 +476,11 @@ class UnitTest extends \lithium\test\Unit {
public function testCompareWithEmptyResult() {
$result = $this->compare('equal', array('key' => array('val1', 'val2')), array());
- $expected = array(array(
- 'trace' => '[key][0]',
+ $expected = array(
+ 'trace' => '[key]',
'expected' => array('val1', 'val2'),
'result' => array()
- ));
+ );
$this->assertEqual($expected, $result);
}
@@ -542,7 +525,11 @@ class UnitTest extends \lithium\test\Unit {
public function testCompareIdenticalArray() {
$expected = array(
+<<<<<<< HEAD
'trace' => '[0]',
+=======
+ 'trace' => null,
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
'expected' => array(),
'result' => array('two', 'values')
);
@@ -550,12 +537,35 @@ class UnitTest extends \lithium\test\Unit {
$this->assertEqual($expected, $result);
}
+<<<<<<< HEAD
+=======
+ public function imethods() {
+ return array('testCompareIdenticalArray');
+ }
+
+ public function testCompareEqualNullArray() {
+ $expected = array('trace' => null, 'expected' => array(), 'result' => array(null));
+ $result = $this->compare('equal', array(), array(null));
+ $this->assertEqual($expected, $result);
+ }
+
+ public function testCompareIdenticalNullArray() {
+ $expected = array('trace' => null, 'expected' => array(), 'result' => array(null));
+ $result = $this->compare('identical', array(), array(null));
+ $this->assertEqual($expected, $result);
+ }
+
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
/**
* Always keep second to last.
*
*/
public function testResults() {
+<<<<<<< HEAD
$expected = 87;
+=======
+ $expected = 89;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
$result = count($this->results());
$this->assertEqual($expected, $result);
}
@@ -581,6 +591,10 @@ class UnitTest extends \lithium\test\Unit {
'testCompareWithEmptyResult',
'testExceptionCatching', 'testErrorHandling', 'testAssertObjects',
'testAssertArrayIdentical', 'testCompareIdenticalArray',
+<<<<<<< HEAD
+=======
+ 'testCompareEqualNullArray', 'testCompareIdenticalNullArray',
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
'testResults', 'testTestMethods'
);
$this->assertIdentical($expected, $this->methods());
diff --git a/libraries/lithium/tests/cases/util/CollectionTest.php b/libraries/lithium/tests/cases/util/CollectionTest.php
index b5e4922..ea60b27 100644
--- a/libraries/lithium/tests/cases/util/CollectionTest.php
+++ b/libraries/lithium/tests/cases/util/CollectionTest.php
@@ -8,7 +8,11 @@
namespace lithium\tests\cases\util;
+<<<<<<< HEAD
use \stdClass;
+=======
+use stdClass;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
use lithium\util\Collection;
use lithium\tests\mocks\util\MockCollectionMarker;
use lithium\tests\mocks\util\MockCollectionObject;
diff --git a/libraries/lithium/tests/cases/util/InflectorTest.php b/libraries/lithium/tests/cases/util/InflectorTest.php
index 9c6a0b3..6a72eb0 100644
--- a/libraries/lithium/tests/cases/util/InflectorTest.php
+++ b/libraries/lithium/tests/cases/util/InflectorTest.php
@@ -356,9 +356,18 @@ class InflectorTest extends \lithium\test\Unit {
/**
* This is a helper method for testStorageMechanism to fetch a private
* property of the Inflector class.
+<<<<<<< HEAD
*/
private function getProtectedValue($property) {
$info = Inspector::info("lithium\util\Inflector::$property");
+=======
+ *
+ * @param string $property
+ * @return string The value of the property.
+ */
+ private function getProtectedValue($property) {
+ $info = Inspector::info("lithium\util\Inflector::{$property}");
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
return $info['value'];
}
}
diff --git a/libraries/lithium/tests/cases/util/StringTest.php b/libraries/lithium/tests/cases/util/StringTest.php
index dec17dc..ec2cf1d 100644
--- a/libraries/lithium/tests/cases/util/StringTest.php
+++ b/libraries/lithium/tests/cases/util/StringTest.php
@@ -17,7 +17,11 @@ class StringTest extends \lithium\test\Unit {
* testRandomGenerator method
*
* @return void
+<<<<<<< HEAD
**/
+=======
+ */
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
public function testRandomGenerator() {
// Disallow allow seeding twice
$this->assertFalse(String::seed() && String::seed());
diff --git a/libraries/lithium/tests/cases/util/ValidatorTest.php b/libraries/lithium/tests/cases/util/ValidatorTest.php
index 480f165..3de3334 100644
--- a/libraries/lithium/tests/cases/util/ValidatorTest.php
+++ b/libraries/lithium/tests/cases/util/ValidatorTest.php
@@ -78,7 +78,7 @@ class ValidatorTest extends \lithium\test\Unit {
$this->assertTrue(in_array('foo', Validator::rules()));
$this->assertEqual('/^foo$/', Validator::rules('foo'));
- $this->expectException("Rule 'bar' is not a validation rule");
+ $this->expectException("Rule `bar` is not a validation rule.");
$this->assertNull(Validator::isBar('foo'));
}
diff --git a/libraries/lithium/tests/integration/analysis/LoggerTest.php b/libraries/lithium/tests/integration/analysis/LoggerTest.php
index 456add4..491b492 100644
--- a/libraries/lithium/tests/integration/analysis/LoggerTest.php
+++ b/libraries/lithium/tests/integration/analysis/LoggerTest.php
@@ -40,7 +40,10 @@ class LoggerTest extends \lithium\test\Unit {
unlink($base . '/info.log');
}
+<<<<<<< HEAD
+=======
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
}
?>
\ No newline at end of file
diff --git a/libraries/lithium/tests/integration/data/FieldsTest.php b/libraries/lithium/tests/integration/data/FieldsTest.php
index 548959d..b4bfe7b 100644
--- a/libraries/lithium/tests/integration/data/FieldsTest.php
+++ b/libraries/lithium/tests/integration/data/FieldsTest.php
@@ -4,6 +4,7 @@ namespace lithium\tests\integration\data;
use lithium\data\Connections;
use lithium\data\Entity;
+<<<<<<< HEAD
class MockCompany extends \lithium\data\Model {
@@ -13,11 +14,18 @@ class MockCompany extends \lithium\data\Model {
);
}
+=======
+use lithium\tests\mocks\data\Company;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
class FieldsTest extends \lithium\test\Unit {
public function setUp() {
- MockCompany::config();
+ Company::config();
+ }
+
+ public function tearDown() {
+ Company::remove();
}
public function tearDown() {
@@ -33,12 +41,17 @@ class FieldsTest extends \lithium\test\Unit {
}
public function testSingleField() {
+<<<<<<< HEAD
$new = MockCompany::create(array('name' => 'Acme, Inc.'));
$key = MockCompany::meta('key');
+=======
+ $new = Company::create(array('name' => 'Acme, Inc.'));
+ $key = Company::meta('key');
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
$new->save();
$id = is_object($new->{$key}) ? (string) $new->{$key} : $new->{$key};
- $entity = MockCompany::first($id);
+ $entity = Company::first($id);
$this->assertTrue($entity instanceof Entity);
$this->skipIf(!$entity instanceof Entity, 'Queried object is not an entity.');
@@ -47,7 +60,11 @@ class FieldsTest extends \lithium\test\Unit {
$result = $entity->data();
$this->assertEqual($expected, $result);
+<<<<<<< HEAD
$entity = MockCompany::first(array('fields' => array($key)));
+=======
+ $entity = Company::first(array('fields' => array($key)));
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
$this->assertTrue($entity instanceof Entity);
$this->skipIf(!$entity instanceof Entity, 'Queried object is not an entity.');
@@ -56,7 +73,11 @@ class FieldsTest extends \lithium\test\Unit {
$result = $entity->data();
$this->assertEqual($expected, $result);
+<<<<<<< HEAD
$entity = MockCompany::find('first',array(
+=======
+ $entity = Company::find('first',array(
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
'conditions' => array($key => $id),
'fields' => array($key)
));
diff --git a/libraries/lithium/tests/integration/data/source/CouchDbTest.php b/libraries/lithium/tests/integration/data/source/CouchDbTest.php
index eba1614..b10e3be 100644
--- a/libraries/lithium/tests/integration/data/source/CouchDbTest.php
+++ b/libraries/lithium/tests/integration/data/source/CouchDbTest.php
@@ -9,6 +9,7 @@
namespace lithium\tests\integration\data\source;
use lithium\data\Connections;
+<<<<<<< HEAD
class MockCouchModel extends \lithium\data\Model {
protected $_schema = array(
@@ -16,6 +17,10 @@ class MockCouchModel extends \lithium\data\Model {
);
}
+=======
+use lithium\tests\mocks\MockCouchModel;
+
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
class CouchDbTest extends \lithium\test\Integration {
public function setUp() {
@@ -98,7 +103,6 @@ class CouchDbTest extends \lithium\test\Integration {
$this->assertEqual($data['id'], $updated['id']);
$this->assertNotEqual($data['rev'], $updated['rev']);
}
-
}
?>
\ No newline at end of file
diff --git a/libraries/lithium/tests/integration/net/http/ServiceTest.php b/libraries/lithium/tests/integration/net/http/ServiceTest.php
index 067611d..cbf9ada 100644
--- a/libraries/lithium/tests/integration/net/http/ServiceTest.php
+++ b/libraries/lithium/tests/integration/net/http/ServiceTest.php
@@ -17,7 +17,11 @@ class ServiceTest extends \lithium\test\Integration {
'classes' => array('socket' => '\lithium\net\socket\Stream')
));
$service->head();
+<<<<<<< HEAD
+=======
+
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
$expected = array('code' => 200, 'message' => 'OK');
$result = $service->last->response->status;
$this->assertEqual($expected, $result);
@@ -28,7 +32,11 @@ class ServiceTest extends \lithium\test\Integration {
'classes' => array('socket' => '\lithium\net\socket\Context')
));
$service->head();
+<<<<<<< HEAD
+=======
+
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
$expected = array('code' => 200, 'message' => 'OK');
$result = $service->last->response->status;
$this->assertEqual($expected, $result);
@@ -39,9 +47,15 @@ class ServiceTest extends \lithium\test\Integration {
'classes' => array('socket' => '\lithium\net\socket\Curl')
));
$service->head();
+<<<<<<< HEAD
+=======
+
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
$expected = array('code' => 200, 'message' => 'OK');
$result = $service->last->response->status;
$this->assertEqual($expected, $result);
}
}
+
+?>
\ No newline at end of file
diff --git a/libraries/lithium/tests/mocks/action/MockDispatcher.php b/libraries/lithium/tests/mocks/action/MockDispatcher.php
index a7df326..8387a0c 100644
--- a/libraries/lithium/tests/mocks/action/MockDispatcher.php
+++ b/libraries/lithium/tests/mocks/action/MockDispatcher.php
@@ -8,7 +8,7 @@
namespace lithium\tests\mocks\action;
-use \stdClass;
+use stdClass;
class MockDispatcher extends \lithium\action\Dispatcher {
diff --git a/libraries/lithium/tests/mocks/data/Employees.php b/libraries/lithium/tests/mocks/data/Employees.php
new file mode 100644
index 0000000..5245ddb
--- /dev/null
+++ b/libraries/lithium/tests/mocks/data/Employees.php
@@ -0,0 +1,23 @@
+<?php
+/**
+ * Lithium: the most rad php framework
+ *
+ * @copyright Copyright 2010, Union of RAD (http://union-of-rad.org)
+ * @license http://opensource.org/licenses/bsd-license.php The BSD License
+ */
+
+namespace lithium\tests\mocks\data;
+
+class Employees extends \lithium\data\Model {
+
+ public $belongsTo = array('Companies');
+
+ protected $_meta = array('connection' => 'test');
+
+ public function lastName($entity) {
+ $name = explode(' ', $entity->name);
+ return $name[1];
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/libraries/lithium/tests/mocks/data/MockCouchModel.php b/libraries/lithium/tests/mocks/data/MockCouchModel.php
new file mode 100644
index 0000000..239be89
--- /dev/null
+++ b/libraries/lithium/tests/mocks/data/MockCouchModel.php
@@ -0,0 +1,18 @@
+<?php
+/**
+ * Lithium: the most rad php framework
+ *
+ * @copyright Copyright 2010, Union of RAD (http://union-of-rad.org)
+ * @license http://opensource.org/licenses/bsd-license.php The BSD License
+ */
+
+namespace lithium\tests\mocks\data;
+
+class MockCouchModel extends \lithium\data\Model {
+
+ protected $_schema = array(
+ 'someKey' => array()
+ );
+}
+
+?>
\ No newline at end of file
diff --git a/libraries/lithium/tests/mocks/data/MockPost.php b/libraries/lithium/tests/mocks/data/MockPost.php
index c7a445b..6a03eb4 100644
--- a/libraries/lithium/tests/mocks/data/MockPost.php
+++ b/libraries/lithium/tests/mocks/data/MockPost.php
@@ -12,6 +12,8 @@ class MockPost extends \lithium\tests\mocks\data\MockBase {
public $hasMany = array('MockComment');
+ public static $connection = null;
+
public static function resetSchema() {
static::_object()->_schema = array();
}
@@ -23,6 +25,13 @@ class MockPost extends \lithium\tests\mocks\data\MockBase {
public static function instances() {
return array_keys(static::$_instances);
}
+
+ public static function &connection() {
+ if (static::$connection) {
+ return static::$connection;
+ }
+ return parent::connection();
+ }
}
?>
\ No newline at end of file
diff --git a/libraries/lithium/tests/mocks/data/MockSource.php b/libraries/lithium/tests/mocks/data/MockSource.php
index 137016d..1024a6e 100644
--- a/libraries/lithium/tests/mocks/data/MockSource.php
+++ b/libraries/lithium/tests/mocks/data/MockSource.php
@@ -13,9 +13,9 @@ use lithium\util\Inflector;
class MockSource extends \lithium\data\Source {
protected $_classes = array(
- 'entity' => '\lithium\data\entity\Record',
- 'set' => '\lithium\data\collection\RecordSet',
- 'relationship' => '\lithium\data\model\Relationship'
+ 'entity' => 'lithium\data\entity\Record',
+ 'set' => 'lithium\data\collection\RecordSet',
+ 'relationship' => 'lithium\data\model\Relationship'
);
private $_mockPosts = array(
diff --git a/libraries/lithium/tests/mocks/data/source/MockMongoSource.php b/libraries/lithium/tests/mocks/data/source/MockMongoSource.php
new file mode 100644
index 0000000..45ac538
--- /dev/null
+++ b/libraries/lithium/tests/mocks/data/source/MockMongoSource.php
@@ -0,0 +1,40 @@
+<?php
+/**
+ * Lithium: the most rad php framework
+ *
+ * @copyright Copyright 2010, Union of RAD (http://union-of-rad.org)
+ * @license http://opensource.org/licenses/bsd-license.php The BSD License
+ */
+
+namespace lithium\tests\mocks\data\source;
+
+use MongoId;
+use lithium\tests\mocks\data\source\mongo_db\MockResult;
+
+class MockMongoSource extends \lithium\core\Object {
+
+ public $resultSets = array();
+
+ public $queries = array();
+
+ public function __get($name) {
+ return $this;
+ }
+
+ public function insert(&$data, $options) {
+ $this->queries[] = compact('data', 'options');
+ $result = current($this->resultSets);
+ next($this->resultSets);
+ $data['_id'] = new MongoId();
+ return $result;
+ }
+
+ public function find($conditions, $fields) {
+ $this->queries[] = compact('conditions', 'fields');
+ $result = new MockResult(array('data' => current($this->resultSets)));
+ next($this->resultSets);
+ return $result;
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/libraries/lithium/tests/mocks/data/source/mongo_db/MockResult.php b/libraries/lithium/tests/mocks/data/source/mongo_db/MockResult.php
index f4b6b65..47dcf09 100644
--- a/libraries/lithium/tests/mocks/data/source/mongo_db/MockResult.php
+++ b/libraries/lithium/tests/mocks/data/source/mongo_db/MockResult.php
@@ -10,22 +10,57 @@ namespace lithium\tests\mocks\data\source\mongo_db;
class MockResult extends \lithium\data\source\mongo_db\Result {
+<<<<<<< HEAD
protected $_data = array(
false,
+=======
+ protected $_autoConfig = array('data');
+
+ protected $_data = array(
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
array('_id' => '4c8f86167675abfabdbf0300', 'title' => 'bar'),
array('_id' => '5c8f86167675abfabdbf0301', 'title' => 'foo'),
array('_id' => '6c8f86167675abfabdbf0302', 'title' => 'dib')
);
+<<<<<<< HEAD
+=======
+ public function hasNext() {
+ if (!is_array($this->_data)) {
+ return false;
+ }
+ return key($this->_data) !== null && key($this->_data) < count($this->_data);
+ }
+
+ public function getNext() {
+ $result = current($this->_data);
+ next($this->_data);
+ return $result;
+ }
+
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
public function next() {
return $this->_next();
}
+<<<<<<< HEAD
+=======
+ public function __call($method, array $params) {
+ return $this;
+ }
+
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
protected function _close() {
}
protected function _next() {
+<<<<<<< HEAD
return next($this->_data) ?: null;
+=======
+ $result = current($this->_data) ?: null;
+ next($this->_data);
+ return $result;
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
}
}
diff --git a/libraries/lithium/tests/mocks/template/MockHelper.php b/libraries/lithium/tests/mocks/template/MockHelper.php
index d67a5aa..0b48229 100644
--- a/libraries/lithium/tests/mocks/template/MockHelper.php
+++ b/libraries/lithium/tests/mocks/template/MockHelper.php
@@ -11,6 +11,7 @@ namespace lithium\tests\mocks\template;
class MockHelper extends \lithium\template\Helper {
protected $_strings = array('link' => '<a href="{:url}"{:options}>{:title}</a>');
+
/**
* Hack to expose protected properties for testing.
*
diff --git a/libraries/lithium/tests/mocks/template/MockView.php b/libraries/lithium/tests/mocks/template/MockView.php
new file mode 100644
index 0000000..dfeacd4
--- /dev/null
+++ b/libraries/lithium/tests/mocks/template/MockView.php
@@ -0,0 +1,18 @@
+<?php
+/**
+ * Lithium: the most rad php framework
+ *
+ * @copyright Copyright 2010, Union of RAD (http://union-of-rad.org)
+ * @license http://opensource.org/licenses/bsd-license.php The BSD License
+ */
+
+namespace lithium\tests\mocks\template;
+
+class MockView extends \lithium\template\View {
+
+ public function renderer() {
+ return $this->_config['renderer'];
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/libraries/lithium/tests/mocks/test/cases/MockSkipThrowsException.php b/libraries/lithium/tests/mocks/test/cases/MockSkipThrowsException.php
index ee8fdb1..75719e1 100644
--- a/libraries/lithium/tests/mocks/test/cases/MockSkipThrowsException.php
+++ b/libraries/lithium/tests/mocks/test/cases/MockSkipThrowsException.php
@@ -8,7 +8,7 @@
namespace lithium\tests\mocks\test\cases;
-use \Exception;
+use Exception;
class MockSkipThrowsException extends \lithium\test\Unit {
diff --git a/libraries/lithium/tests/mocks/test/cases/MockTestErrorHandling.php b/libraries/lithium/tests/mocks/test/cases/MockTestErrorHandling.php
index 8caa9f4..31f5cdb 100644
--- a/libraries/lithium/tests/mocks/test/cases/MockTestErrorHandling.php
+++ b/libraries/lithium/tests/mocks/test/cases/MockTestErrorHandling.php
@@ -8,7 +8,7 @@
namespace lithium\tests\mocks\test\cases;
-use \Exception;
+use Exception;
class MockTestErrorHandling extends \lithium\test\Unit {
diff --git a/libraries/lithium/util/Set.php b/libraries/lithium/util/Set.php
index 156eeff..07a6ff1 100644
--- a/libraries/lithium/util/Set.php
+++ b/libraries/lithium/util/Set.php
@@ -547,7 +547,11 @@ class Set {
return true;
}
if (is_string($conditions)) {
+<<<<<<< HEAD
return (bool) static::extract($data, $conditions);
+=======
+ return (boolean) static::extract($data, $conditions);
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
}
foreach ($conditions as $condition) {
if ($condition === ':last') {
diff --git a/libraries/lithium/util/String.php b/libraries/lithium/util/String.php
index 4f0ed4e..c0a56dc 100644
--- a/libraries/lithium/util/String.php
+++ b/libraries/lithium/util/String.php
@@ -9,8 +9,8 @@
namespace lithium\util;
-use \Closure;
-use \Exception;
+use Closure;
+use Exception;
/**
* String manipulation utility class. Includes functionality for hashing, UUID generation,
@@ -25,6 +25,7 @@ class String {
const version4 = 64; // 01000000 Sets the version bit
const clearVar = 63; // 00111111 Clears relevant bits of variant byte
const varRFC = 128; // 10000000 The RFC 4122 variant
+<<<<<<< HEAD
/**
* A file pointer towards urandom if available, else false
@@ -411,6 +412,396 @@ class String {
*
* @return string The MD5 salt.
**/
+=======
+
+ /**
+ * A file pointer towards urandom if available, else false
+ *
+ * @var resource|false
+ */
+ protected static $_urandom;
+
+ /**
+ * Seeds the random generator if it has yet to be done.
+ *
+ * @return boolean Success.
+ */
+ public static function seed() {
+ // Seeding more than once means less entropy, not more, so bail
+ if (isset(static::$_urandom)) {
+ return false;
+ }
+
+ // Use urandom if the device is available
+ if (is_readable('/dev/urandom')) {
+ static::$_urandom = fopen('/dev/urandom', 'rb');
+ // Else seed PHP's mt_rand()
+ } else {
+ $seed = function() {
+ list($usec, $sec) = explode(' ', microtime());
+ $seed = (float) $sec + ((float) $usec * 100000);
+ if (function_exists('getmypid')) {
+ $seed .= getmypid();
+ }
+ return $seed;
+ };
+ mt_srand($seed());
+ static::$_urandom = false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Generates random bytes for use in UUIDs and password salts.
+ *
+ * The method seeds the random source automatically. It uses
+ * /dev/urandom if the latter is available; `md_rand()` if not.
+ *
+ * It can also be used to generate arbitrary bits:
+ *
+ * {{{
+ * $bits = bin2hex(String::random(8)); // 64 bits
+ * }}}
+ *
+ * @param integer $bytes The number of bytes to generate
+ * @param string Random bytes
+ */
+ public static function random($bytes) {
+ if (!isset(static::$_urandom)) {
+ static::seed();
+ }
+
+ if (static::$_urandom) {
+ $rand = fread(static::$_urandom, $bytes);
+ } else {
+ $rand = '';
+ for ($i = 0; $i < $bytes; $i++) {
+ $rand .= chr(mt_rand(0, 255));
+ }
+ }
+
+ return $rand;
+ }
+
+ /**
+ * Generates an RFC 4122-compliant version 4 UUID.
+ *
+ * @return string The string representation of an RFC 4122-compliant, version 4 UUID.
+ * @link http://www.ietf.org/rfc/rfc4122.txt
+ */
+ public static function uuid() {
+ $uuid = static::random(16);
+
+ // Set version
+ $uuid[6] = chr(ord($uuid[6]) & static::clearVer | static::version4);
+
+ // Set variant
+ $uuid[8] = chr(ord($uuid[8]) & static::clearVar | static::varRFC);
+
+ // Return the uuid's string representation
+ return bin2hex(substr($uuid, 0, 4)) . '-'
+ . bin2hex(substr($uuid, 4, 2)) . '-'
+ . bin2hex(substr($uuid, 6, 2)) . '-'
+ . bin2hex(substr($uuid, 8, 2)) . '-'
+ . bin2hex(substr($uuid, 10, 6));
+ }
+
+ /**
+ * Uses PHP's hashing functions to create a hash of the string provided, using the options
+ * specified. The default hash algorithm is SHA-512.
+ *
+ * @link http://php.net/manual/en/function.hash.php PHP Manual: hash()
+ * @link http://php.net/manual/en/function.hash-hmac.php PHP Manual: hash_hmac()
+ * @link http://php.net/manual/en/function.hash-algos.php PHP Manual: hash_algos()
+ * @param string $string The string to hash.
+ * @param array $options Supported options:
+ * - `'type'` _string_: Any valid hashing algorithm. See the `hash_algos()` function to
+ * determine which are available on your system.
+ * - `'salt'` _string_: A _salt_ value which, if specified, will be prepended to the
+ * string.
+ * - `'key'` _string_: If specified `hash_hmac()` will be used to hash the string,
+ * instead of `hash()`, with `'key'` being used as the message key.
+ * - `'raw'` _boolean_: If `true`, outputs the raw binary result of the hash operation.
+ * Defaults to `false`.
+ * @return string Returns a hashed string.
+ */
+ public static function hash($string, array $options = array()) {
+ $defaults = array(
+ 'type' => 'sha512',
+ 'salt' => false,
+ 'key' => false,
+ 'raw' => false,
+ );
+ $options += $defaults;
+
+ if ($options['salt']) {
+ $string = $options['salt'] . $string;
+ }
+
+ if ($options['key']) {
+ return hash_hmac($options['type'], $string, $options['key'], $options['raw']);
+ }
+ return hash($options['type'], $string, $options['raw']);
+ }
+
+ /**
+ * Hashes a password using PHP's `crypt()` and an optional salt. If no
+ * salt is supplied, a cryptographically strong salt will be generated
+ * using `String::genSalt()`.
+ *
+ * Using this function is the proper way to hash a password. Using naive
+ * methods such as `String::hash()` is fine to check a file's integrity,
+ * but fundamentally insecure for passwords, due to the invariable lack
+ * of a cryptographically strong salt.
+ *
+ * Moreover, `String::hashPassword()`'s cryptographically strong salts
+ * ensure that:
+ *
+ * - Two identical passwords will not be hashed the same way.
+ * - `String::genSalt()`'s count interator can later be increased (assuming
+ * BF or XDES is available) within Lithium or your application, without
+ * invalidating existing password hashes.
+ *
+ * Usage:
+ *
+ * {{{
+ * // Hash a password before storing it:
+ * $hashed = String::hashPassword($password);
+ *
+ * // Check a password by comparing it to its hashed value:
+ * $check = String::checkPassword($password, $hashed);
+ *
+ * // Use a stronger custom salt:
+ * $salt = String::genSalt('bf', 16); // 2^16 iterations
+ * $hashed = String::hashPassword($password, $salt); // Very slow
+ * $check = String::checkPassword($password, $hashed); // Very slow
+ *
+ * // Forward/backward compatibility
+ * $salt1 = String::genSalt('bf', 6);
+ * $salt2 = String::genSalt('bf', 12);
+ * $hashed1 = String::hashPassword($password, $salt1); // Fast
+ * $hashed2 = String::hashPassword($password, $salt2); // Slow
+ * $check1 = String::checkPassword($password, $hashed1); // True
+ * $check2 = String::checkPassword($password, $hashed2); // True
+ * }}}
+ *
+ * @see lithium\util\String::genSalt()
+ * @param string $password The password to hash.
+ * @param string $salt Optional. The salt string.
+ * @return string The hashed password.
+ * The result's length will be:
+ * - 60 chars for Blowfish hashes
+ * - 20 chars for XDES hashes
+ * - 34 chars for MD5 hashes
+ **/
+ public static function hashPassword($password, $salt = null) {
+ return crypt($password, $salt ?: static::genSalt());
+ }
+
+ /**
+ * Compares a password and its hashed value using PHP's `crypt()`.
+ *
+ * @see lithium\util\String::hashPassword()
+ * @see lithium\util\String::genSalt()
+ * @param string $password The password to check
+ * @param string $hash The hashed password to compare
+ * @return boolean Whether the password is correct or not
+ */
+ public static function checkPassword($password, $hash) {
+ return $hash == crypt($password, $hash);
+ }
+
+ /**
+ * Generates a cryptographically strong salt, using the best available
+ * method (tries Blowfish, then XDES, and fallbacks to MD5), for use in
+ * `String::hashPassword()`.
+ *
+ * Blowfish and XDES are adaptive hashing algorithms. MD5 is not. Adaptive
+ * hashing algorithms are designed in such a way that when computers get
+ * faster, you can tune the algorithm to be slower by increasing the number
+ * of hash iterations, without introducing incompatibility with existing
+ * passwords.
+ *
+ * To pick an appropriate iteration count for adaptive algorithms, consider
+ * that the original DES crypt was designed to have the speed of 4 hashes
+ * per second on the hardware of that time. Slower than 4 hashes per second
+ * would probably dampen usability. Faster than 100 hashes per second is
+ * probably too fast. The defaults generate about 10 hashes per second
+ * using a dual-core 2.2GHz CPU.
+ *
+ * Note1: this salt generator is different from naive salt implementations
+ * (e.g. `md5(microtime())`) that are invariably found in OSS PHP applications,
+ * in that it uses all of the available bits of entropy for the supplied salt
+ * method.
+ *
+ * Note2: this method should not be used as custom salts, for instance in a
+ * custom password hasher. Indeed, salts are prefixed with information expected
+ * by PHP's `crypt()`. To get an arbitrarily long, cryptographically strong salt
+ * consisting in random sequences of alpha numeric characters, combine
+ * `String::random()` and `String::encode64()` instead.
+ *
+ * @link http://php.net/manual/en/function.crypt.php
+ * @link http://www.postgresql.org/docs/9.0/static/pgcrypto.html
+ * @see lithium\util\String::hashPassword()
+ * @param string $type The hash type. Optional. Defaults to '`bf`'.
+ * Supported values include:
+ * - `'bf'`: Blowfish (128 salt bits, adaptive, max 72 chars)
+ * - `'xdes'`: XDES (24 salt bits, adaptive, max 8 chars)
+ * - `'md5'`: MD5 (48 salt bits, non-adaptive, unlimited length)
+ * @param integer $count Optional. The base-2 logarithm of the iteration
+ * count, for adaptive algorithms. Defaults to:
+ * - `10` for Blowfish
+ * - `18` for XDES
+ * @return string The salt string.
+ */
+ public static function genSalt($type = null, $count = null) {
+ switch (true) {
+ case CRYPT_BLOWFISH == 1 && (!$type || $type === 'bf'):
+ return static::_genSaltBF($count);
+ case CRYPT_EXT_DES == 1 && (!$type || $type === 'xdes'):
+ return static::_genSaltXDES($count);
+ default:
+ return static::_genSaltMD5();
+ }
+ }
+
+ /**
+ * Encodes bytes into an `./0-9A-Za-z` alphabet, for use as salt when
+ * hashing passwords.
+ *
+ * Note: this is not the same as RFC 1421, or `base64_encode()`, which
+ * uses an `+/0-9A-Za-z` alphabet.
+ *
+ * This function can be combined with `String::random()` to generate random
+ * sequences of `./0-9A-Za-z` characters:
+ *
+ * {{{
+ * $salt = String::encode64(String::random(8)); // 64 bits
+ * }}}
+ *
+ * @see lithium\util\String::random()
+ * @param string $input The input bytes.
+ * @return string The same bytes in the `/.0-9A-Za-z` alphabet.
+ */
+ public static function encode64($input) {
+ $base64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
+ $i = 0;
+
+ $count = strlen($input);
+ $output = '';
+
+ do {
+ $value = ord($input[$i++]);
+ $output .= $base64[$value & 0x3f];
+
+ if ($i < $count) {
+ $value |= ord($input[$i]) << 8;
+ }
+ $output .= $base64[($value >> 6) & 0x3f];
+
+ if ($i++ >= $count) {
+ break;
+ }
+ if ($i < $count) {
+ $value |= ord($input[$i]) << 16;
+ }
+ $output .= $base64[($value >> 12) & 0x3f];
+
+ if ($i++ >= $count) {
+ break;
+ }
+ $output .= $base64[($value >> 18) & 0x3f];
+ } while ($i < $count);
+
+ return $output;
+ }
+
+ /**
+ * Generates a Blowfish salt for use in `String::hashPassword()`.
+ *
+ * @param integer $count The base-2 logarithm of the iteration count.
+ * Defaults to `10`. Can be `4` to `31`.
+ * @return string $salt
+ */
+ protected static function _genSaltBf($count = 10) {
+ $count = (integer) $count;
+ if ($count < 4 || $count > 31) {
+ $count = 10;
+ }
+
+ // We don't use the encode64() method here because it could result
+ // in 2 bits less of entropy depending on the last char.
+ $base64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+ $i = 0;
+
+ $input = static::random(16); // 128 bits of salt
+ $output = '';
+
+ do {
+ $c1 = ord($input[$i++]);
+ $output .= $base64[$c1 >> 2];
+ $c1 = ($c1 & 0x03) << 4;
+ if ($i >= 16) {
+ $output .= $base64[$c1];
+ break;
+ }
+
+ $c2 = ord($input[$i++]);
+ $c1 |= $c2 >> 4;
+ $output .= $base64[$c1];
+ $c1 = ($c2 & 0x0f) << 2;
+
+ $c2 = ord($input[$i++]);
+ $c1 |= $c2 >> 6;
+ $output .= $base64[$c1];
+ $output .= $base64[$c2 & 0x3f];
+ } while (1);
+
+ return '$2a$'
+ // zeroize $count
+ . chr(ord('0') + $count / 10) . chr(ord('0') + $count % 10)
+ . '$' . $output;
+ }
+
+ /**
+ * Generates an Extended DES salt for use in `String::hashPassword()`.
+ *
+ * @param integer $count The base-2 logarithm of the iteration count.
+ * Defaults to `18`. Can be `1` to `24`. 1 will be stripped
+ * from the non-log value, e.g. 2^18 - 1, to ensure we don't
+ * use a weak DES key.
+ * @return string The XDES salt.
+ */
+ protected static function _genSaltXDES($count = 18) {
+ $count = (integer) $count;
+ if ($count < 1 || $count > 24) {
+ $count = 16;
+ }
+
+ // Count should be odd to not reveal weak DES keys
+ $count = (1 << $count) - 1;
+
+ $base64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
+
+ $output = '_'
+ // iterations
+ . $base64[$count & 0x3f]
+ . $base64[($count >> 6) & 0x3f]
+ . $base64[($count >> 12) & 0x3f]
+ . $base64[($count >> 18) & 0x3f]
+ // 24 bits of salt
+ . static::encode64(static::random(3));
+
+ return $output;
+ }
+
+ /**
+ * Generates an MD5 salt for use in `String::hashPassword()`.
+ *
+ * @return string The MD5 salt.
+ */
+>>>>>>> fbe85ef24e87a52a74ec9569f00666225c0a117e
protected static function _genSaltMD5() {
$output = '$1$'
// 48 bits of salt
diff --git a/libraries/lithium/util/Validator.php b/libraries/lithium/util/Validator.php
index dc195f0..48ad2d7 100644
--- a/libraries/lithium/util/Validator.php
+++ b/libraries/lithium/util/Validator.php
@@ -546,7 +546,7 @@ class Validator extends \lithium\core\StaticObject {
*/
public static function rule($rule, $value, $format = 'any', array $options = array()) {
if (!isset(static::$_rules[$rule])) {
- throw new InvalidArgumentException("Rule '{$rule}' is not a validation rule");
+ throw new InvalidArgumentException("Rule `{$rule}` is not a validation rule.");
}
$defaults = isset(static::$_options[$rule]) ? static::$_options[$rule] : array();
$options = (array) $options + $defaults + static::$_options['defaults'];