Commit: 624a2928f75607a10351c0e423379f88ee6772e2
Author: chawbacca | Date: 2011-03-23 19:42:57 +0000
diff --git a/app/config/bootstrap.php b/app/config/bootstrap.php
index eaca28f..e708745 100644
--- a/app/config/bootstrap.php
+++ b/app/config/bootstrap.php
@@ -5,47 +5,38 @@
* @copyright Copyright 2010, Union of RAD (http://union-of-rad.org)
* @license http://opensource.org/licenses/bsd-license.php The BSD License
*/
-/**
- * This is the primary bootstrap file of your application, and is loaded immediately after the front
- * controller (`index.php`) is invoked. The code below allows you to tell Lithium where to find
- * your application and support libraries (including the framework itself). It also includes
- * references to other feature-specific bootstrap files that you can turn on and off to configure
- * the services needed for your application.
- */
-
-/**
- * This is the path to the class libraries used by your application, and must contain a copy of the
- * Lithium core. By default, this directory is named `libraries`, and resides in the same
- * directory as your application. If you use the same libraries in multiple applications, you can
- * set this to a shared path on your server.
- */
-define('LITHIUM_LIBRARY_PATH', dirname(dirname(__DIR__)) . '/libraries');
/**
- * This is the path to your application's directory. It contains all the sub-folders for your
- * application's classes and files. You don't need to change this unless your webroot folder is
- * stored outside of your app folder.
+ * This is the primary bootstrap file of your application, and is loaded immediately after the front
+ * controller (`webroot/index.php`) is invoked. It includes references to other feature-specific
+ * bootstrap files that you can turn on and off to configure the services needed for your
+ * application.
+ *
+ * Besides global configuration of external application resources, these files also include
+ * configuration for various classes to interact with one another, usually through _filters_.
+ * Filters are Lithium's system of creating interactions between classes without tight coupling. See
+ * the `Filters` class for more information.
+ *
+ * If you have other services that must be configured globally for the entire application, create a
+ * new bootstrap file and `require` it here.
+ *
+ * @see lithium\util\collection\Filters
*/
-define('LITHIUM_APP_PATH', dirname(__DIR__));
/**
- * Locate and load Lithium core library files. Throws a fatal error if the core can't be found.
- * If your Lithium core directory is named something other than 'lithium', change the string below.
+ * 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.
*/
-if (!include LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php') {
- $message = "Lithium core could not be found. Check the value of LITHIUM_LIBRARY_PATH in ";
- $message .= __FILE__ . ". It should point to the directory containing your ";
- $message .= "/libraries directory.";
- throw new ErrorException($message);
-}
+require __DIR__ . '/bootstrap/libraries.php';
/**
- * This file contains the loading instructions for all 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. Also includes any statically-loaded
- * classes to improve bootstrap performance.
+ * 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.
*/
-require __DIR__ . '/bootstrap/libraries.php';
+// require __DIR__ . '/bootstrap/errors.php';
/**
* This file contains configurations for connecting to external caching resources, as well as
diff --git a/app/config/bootstrap/cache.php b/app/config/bootstrap/cache.php
index 3e124be..94fc4ef 100644
--- a/app/config/bootstrap/cache.php
+++ b/app/config/bootstrap/cache.php
@@ -23,10 +23,13 @@ if (PHP_SAPI === 'cli') {
* If APC is not available and the cache directory is not writeable, bail out. This block should be
* removed post-install, and the cache should be configured with the adapter you plan to use.
*/
-if (!($apcEnabled = Apc::enabled()) && !is_writable(LITHIUM_APP_PATH . '/resources/tmp/cache')) {
+$cachePath = Libraries::get(true, 'resources') . '/tmp/cache';
+
+if (!($apcEnabled = Apc::enabled()) && !is_writable($cachePath)) {
return;
}
+<<<<<<< HEAD
if ($apcEnabled) {
$default = array(
'adapter' => 'lithium\storage\cache\adapter\Apc',
@@ -36,18 +39,42 @@ if ($apcEnabled) {
'adapter' => 'lithium\storage\cache\adapter\File',
'strategies' => array('Serializer')
);
+=======
+/**
+ * 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.
+ */
+$default = array('adapter' => 'File', 'strategies' => array('Serializer'));
+
+if ($apcEnabled) {
+ $default = array('adapter' => 'Apc');
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
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)) {
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$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');
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
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/config/bootstrap/g11n.php b/app/config/bootstrap/g11n.php
index 1bf9d33..483acad 100644
--- a/app/config/bootstrap/g11n.php
+++ b/app/config/bootstrap/g11n.php
@@ -11,6 +11,10 @@
* including localization of text, validation rules, setting timezones and character inflections,
* and identifying a user's locale.
*/
+<<<<<<< HEAD
+=======
+use lithium\core\Libraries;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
use lithium\core\Environment;
use lithium\g11n\Locale;
use lithium\g11n\Catalog;
@@ -69,7 +73,11 @@ Catalog::config(array(
),
// 'app' => array(
// 'adapter' => 'Gettext',
+<<<<<<< HEAD
// 'path' => LITHIUM_APP_PATH . '/resources/g11n'
+=======
+ // 'path' => Libraries::get(true, 'resources') . '/g11n'
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
// ),
'lithium' => array(
'adapter' => 'Php',
diff --git a/app/config/bootstrap/libraries.php b/app/config/bootstrap/libraries.php
index cdb3b3f..e11a703 100644
--- a/app/config/bootstrap/libraries.php
+++ b/app/config/bootstrap/libraries.php
@@ -6,6 +6,72 @@
* @license http://opensource.org/licenses/bsd-license.php The BSD License
*/
+/**
+ * The libraries file is where you configure the various plugins, frameworks, and other libraries
+ * to be used by your application, including your application itself. This file also defines some
+ * global constants used to tell Lithium where to find your application and support libraries
+ * (including Lithium itself). It uses the `Libraries` class to add configurations for the groups of
+ * classes used in your app.
+ *
+ * In Lithium, a _library_ is any collection of classes located in a single base directory, which
+ * all share the same class-to-file naming convention, and usually a common class or namespace
+ * prefix. While all collections of classes are considered libraries, there are two special types of
+ * libraries:
+ *
+ * - **Applications**: Applications are libraries which follow the organizational conventions that
+ * Lithium defines for applications (see `Libraries::locate()` and `Libraries::paths()`), and
+ * which also include a web-accessible document root (i.e. the `webroot/` folder), and can
+ * dispatch HTTP requests (i.e. through `webroot/index.php`).
+ *
+ * - **Plugins**: Plugins are libraries which generally follow the same organizational conventions
+ * as applications, but are designed to be used within the context of another application. They
+ * _may_ include a public document root for supporting assets, but this requires a symlink from
+ * `libraries/<plugin-name>/webroot` to `<app-name>/webroot/<plugin-name>` (recommended for
+ * production), or a media filter to load plugin resources (see `/config/bootstrap/media.php`).
+ *
+ * Note that a library can be designed as both an application and a plugin, but this requires some
+ * special considerations in the bootstrap process, such as removing any `require` statements, and
+ * conditionally defining the constants below.
+ *
+ * By default, libraries are stored in the base `/libraries` directory, or in the
+ * application-specific `<app-name>/libraries` directory. Libraries can be loaded from either place
+ * without additional configuration, but note that if the same library is in both directories, the
+ * application-specific `libraries` directory will override the global one.
+ *
+ * The one exception to this is the _primary_ library, which is an application configured with
+ * `'default' => true` (see below); this library uses the `LITHIUM_APP_PATH` constant (also defined
+ * below) as its path. Note, however, that any library can be overridden with an arbitrary path by
+ * passing the `'path'` key to its configuration. See `Libraries::add()` for more options.
+ *
+ * @see lithium\core\Libraries
+ */
+
+/**
+ * This is the path to your application's directory. It contains all the sub-folders for your
+ * application's classes and files. You don't need to change this unless your webroot folder is
+ * stored outside of your app folder.
+ */
+define('LITHIUM_APP_PATH', dirname(dirname(__DIR__)));
+
+/**
+ * This is the path to the class libraries used by your application, and must contain a copy of the
+ * Lithium core. By default, this directory is named `libraries`, and resides in the same
+ * directory as your application. If you use the same libraries in multiple applications, you can
+ * set this to a shared path on your server.
+ */
+define('LITHIUM_LIBRARY_PATH', dirname(LITHIUM_APP_PATH) . '/libraries');
+
+/**
+ * Locate and load Lithium core library files. Throws a fatal error if the core can't be found.
+ * If your Lithium core directory is named something other than `lithium`, change the string below.
+ */
+if (!include LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php') {
+ $message = "Lithium core could not be found. Check the value of LITHIUM_LIBRARY_PATH in ";
+ $message .= __FILE__ . ". It should point to the directory containing your ";
+ $message .= "/libraries directory.";
+ throw new ErrorException($message);
+}
+
use lithium\core\Libraries;
/**
@@ -52,7 +118,7 @@ Libraries::add('lithium');
Libraries::add('app', array('default' => true));
/**
- * Add some plugins
+ * Add some plugins:
*/
// Libraries::add('li3_docs');
diff --git a/app/config/routes.php b/app/config/routes.php
index 1800d09..50604e1 100644
--- a/app/config/routes.php
+++ b/app/config/routes.php
@@ -6,6 +6,16 @@
* @license http://opensource.org/licenses/bsd-license.php The BSD License
*/
+/**
+ * The routes file is where you define your URL structure, which is an important part of the
+ * [information architecture](http://en.wikipedia.org/wiki/Information_architecture) of your
+ * application. Here, you can use _routes_ to match up URL pattern strings to a set of parameters,
+ * usually including a controller and action to dispatch matching requests to. For more information,
+ * see the `Router` and `Route` classes.
+ *
+ * @see lithium\net\http\Router
+ * @see lithium\net\http\Route
+ */
use lithium\net\http\Router;
use lithium\core\Environment;
@@ -26,7 +36,10 @@ Router::connect('/', 'Pages::view');
Router::connect('/pages/{:args}', 'Pages::view');
/**
- * Connect the testing routes.
+ * Add the testing routes. These routes are only connected in non-production environments, and allow
+ * browser-based access to the test suite for running unit and integration tests for the Lithium
+ * core, as well as your own application and any other loaded plugins or frameworks. Browse to
+ * [http://path/to/app/test](/test) to run tests.
*/
if (!Environment::is('production')) {
Router::connect('/test/{:args}', array('controller' => 'lithium\test\Controller'));
@@ -34,6 +47,11 @@ if (!Environment::is('production')) {
}
/**
+<<<<<<< HEAD
+=======
+ * ### Database object routes
+ *
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
* The routes below are used primarily for accessing database objects, where `{:id}` corresponds to
* the primary key of the database object, and can be accessed in the controller as
* `$this->request->id`.
diff --git a/app/controllers/HelloWorldController.php b/app/controllers/HelloWorldController.php
index 5f43d1c..8dad480 100644
--- a/app/controllers/HelloWorldController.php
+++ b/app/controllers/HelloWorldController.php
@@ -5,7 +5,7 @@ namespace app\controllers;
class HelloWorldController extends \lithium\action\Controller {
public function index() {
- $this->render(array('layout' => false));
+ return $this->render(array('layout' => false));
}
public function to_string() {
@@ -13,7 +13,7 @@ class HelloWorldController extends \lithium\action\Controller {
}
public function to_json() {
- $this->render(array('json' => 'Hello World'));
+ return $this->render(array('json' => 'Hello World'));
}
}
diff --git a/app/controllers/PagesController.php b/app/controllers/PagesController.php
index db1761e..90a8ddc 100644
--- a/app/controllers/PagesController.php
+++ b/app/controllers/PagesController.php
@@ -27,6 +27,7 @@ class PagesController extends \lithium\action\Controller {
public function view() {
<<<<<<< HEAD
+<<<<<<< HEAD
$path = func_get_args();
if (empty($path)) {
@@ -36,6 +37,10 @@ class PagesController extends \lithium\action\Controller {
$path = func_get_args() ?: array('home');
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
$this->render(array('template' => join('/', $path)));
+=======
+ $path = func_get_args() ?: array('home');
+ return $this->render(array('template' => join('/', $path)));
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
}
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/views/pages/home.html.php b/app/views/pages/home.html.php
index 64e15f5..279a798 100644
--- a/app/views/pages/home.html.php
+++ b/app/views/pages/home.html.php
@@ -6,6 +6,10 @@
* @license http://opensource.org/licenses/bsd-license.php The BSD License
*/
+<<<<<<< HEAD
+=======
+use lithium\core\Libraries;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
use lithium\data\Connections;
$checkName = null;
@@ -37,11 +41,11 @@ $notify = function($status, $message, $solution = null) use (&$checkName, &$chec
$sanityChecks = array(
'resourcesWritable' => function() use ($notify) {
- if (is_writable($path = realpath(LITHIUM_APP_PATH . '/resources'))) {
+ if (is_writable($path = realpath(Libraries::get(true, 'resources')))) {
return $notify(true, 'Resources directory is writable.');
}
return $notify(false, array(
- "Your resource path (<code>$path</code>) is not writeable. " .
+ "Your resource path (<code>{$path}</code>) is not writeable. " .
"To fix this on *nix and Mac OSX, run the following from the command line:",
"<code>chmod -R 0777 {$path}</code>"
));
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/app/webroot/css/lithium.css b/app/webroot/css/lithium.css
index c424ea1..7b643a6 100644
--- a/app/webroot/css/lithium.css
+++ b/app/webroot/css/lithium.css
@@ -266,7 +266,7 @@ code {
color: #666;
}
table, form, pre > code {
- margin-top: 12px;
+ margin-top: 0px;
margin-bottom: 12px;
}
table, form, pre > code, .shadow {
diff --git a/libraries/lithium/action/Controller.php b/libraries/lithium/action/Controller.php
index 721b1d0..d36d5a9 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;
@@ -182,6 +182,12 @@ class Controller extends \lithium\core\Object {
if (is_string($result)) {
$self->render(array('text' => $result));
return $self->response;
+<<<<<<< HEAD
+=======
+ }
+ if (is_array($result)) {
+ $self->set($result);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
$self->set($result);
}
@@ -208,9 +214,13 @@ class Controller extends \lithium\core\Object {
* a `Response` object.
*
<<<<<<< HEAD
+<<<<<<< HEAD
=======
* @see lithium\action\Controller::$_render
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ * @see lithium\action\Controller::$_render
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
* @param array $options An array of options, as follows:
* - `'data'`: An associative array of variables to be assigned to the template. These
* are merged on top of any variables set in `Controller::set()`.
@@ -270,6 +280,7 @@ class Controller extends \lithium\core\Object {
* @see lithium\net\http\Router::match()
* @see lithium\action\Controller::$response
<<<<<<< HEAD
+<<<<<<< HEAD
* @param mixed $url Either a string or an array representing the URL to redirect to.
* Post-processed by `Router::match()`.
=======
@@ -277,13 +288,24 @@ class Controller extends \lithium\core\Object {
* the application, a fully-qualified URL, or an array of routing parameters to be
* resolved to a URL. Post-processed by `Router::match()`.
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ * @param mixed $url The location to redirect to, provided as a string relative to the root of
+ * the application, a fully-qualified URL, or an array of routing parameters to be
+ * resolved to a URL. Post-processed by `Router::match()`.
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
* @param array $options Options when performing the redirect. Available options include:
* - `'status'` _integer_: The HTTP status code associated with the redirect.
* Defaults to `302`.
* - `'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.
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
* @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 fa7a857..d29ee66 100644
--- a/libraries/lithium/action/Dispatcher.php
+++ b/libraries/lithium/action/Dispatcher.php
@@ -14,12 +14,16 @@ use lithium\core\Libraries;
use lithium\action\DispatchException;
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
=======
use lithium\core\ClassNotFoundException;
>>>>>>> 25a362f706960b2becbf88e91cffc1b1638b7890
=======
use lithium\core\ClassNotFoundException;
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+use lithium\core\ClassNotFoundException;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
/**
* `Dispatcher` is the outermost layer of the framework, responsible for both receiving the initial
@@ -123,7 +127,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));
@@ -196,6 +200,7 @@ class Dispatcher extends \lithium\core\StaticObject {
$params = compact('request', 'params', 'options');
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
return static::_filter(__FUNCTION__, $params, function($self, $params, $chain) {
$request = $params['request'];
@@ -210,6 +215,9 @@ class Dispatcher extends \lithium\core\StaticObject {
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
return static::_filter(__FUNCTION__, $params, function($self, $params) {
$options = array('request' => $params['request']) + $params['options'];
$controller = $params['params']['controller'];
@@ -217,11 +225,15 @@ 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);
<<<<<<< HEAD
>>>>>>> 25a362f706960b2becbf88e91cffc1b1638b7890
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ throw new DispatchException("Controller `{$controller}` not found.", null, $e);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
});
}
@@ -232,7 +244,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/Request.php b/libraries/lithium/action/Request.php
index 8723ceb..b96fdf0 100644
--- a/libraries/lithium/action/Request.php
+++ b/libraries/lithium/action/Request.php
@@ -332,6 +332,7 @@ class Request extends \lithium\net\http\Message {
if ($type === true) {
return $this->_parseAccept();
<<<<<<< HEAD
+<<<<<<< HEAD
}
if (!$type && isset($this->params['type'])) {
return $this->params['type'];
@@ -348,6 +349,13 @@ class Request extends \lithium\net\http\Message {
return $this->params['type'];
}
$media = $this->_classes['media'];
+=======
+ }
+ if (!$type && isset($this->params['type'])) {
+ return $this->params['type'];
+ }
+ $media = $this->_classes['media'];
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
return $media::negotiate($this) ?: 'html';
}
@@ -357,6 +365,7 @@ class Request extends \lithium\net\http\Message {
}
$accept = $this->env('HTTP_ACCEPT');
$accept = (strpos($accept, ',') === false) ? array('text/html') : explode(',', $accept);
+<<<<<<< HEAD
foreach (array_reverse($accept) as $i => $type) {
unset($accept[$i]);
@@ -401,9 +410,29 @@ class Request extends \lithium\net\http\Message {
if ($type == '*/*') {
$q = 0.1;
+=======
+
+ foreach (array_reverse($accept) as $i => $type) {
+ unset($accept[$i]);
+ list($type, $q) = (explode(';q=', $type, 2) + array($type, 1.0 + $i / 100));
+ $accept[$type] = ($type == '*/*') ? 0.1 : floatval($q);
+ }
+ arsort($accept, SORT_NUMERIC);
+
+ if (isset($accept['application/xhtml+xml']) && $accept['application/xhtml+xml'] >= 1) {
+ unset($accept['application/xml']);
+ }
+ $media = $this->_classes['media'];
+
+ if (isset($this->params['type']) && ($handler = $media::type($this->params['type']))) {
+ if (isset($handler['content'])) {
+ $type = (array) $handler['content'];
+ $accept = array(current($type) => 1) + $accept;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
$accept[$type] = floatval($q);
}
+<<<<<<< HEAD
arsort($accept, SORT_NUMERIC);
if (isset($accept['text/html']) || isset($accept['application/xhtml+xml'])) {
@@ -422,6 +451,8 @@ class Request extends \lithium\net\http\Message {
$accept = array(current($type) => 1) + $accept;
}
}
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
return $this->_acceptContent = array_keys($accept);
}
@@ -438,11 +469,19 @@ class Request extends \lithium\net\http\Message {
* environment values, like `'env:base'`. See the `env()` method for more info.
* - `'http'`: Retrieves header values (i.e. `'http:accept'`), or the HTTP request method (i.e.
* `'http:method'`).
+<<<<<<< HEAD
+ *
+ * This method is used in several different places in the framework in order to provide the
+ * ability to act conditionally on different aspects of the request. See `Media::type()` (the
+ * section on content negotiation) and the routing system for more information.
+ *
+=======
*
* This method is used in several different places in the framework in order to provide the
* ability to act conditionally on different aspects of the request. See `Media::type()` (the
* section on content negotiation) and the routing system for more information.
*
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
* _Note_: All keys should be _lower-cased_, even when getting HTTP headers.
* @see lithium\action\Request::env()
* @see lithium\net\http\Media::type()
diff --git a/libraries/lithium/action/Response.php b/libraries/lithium/action/Response.php
index c6c3c35..fda4565 100644
--- a/libraries/lithium/action/Response.php
+++ b/libraries/lithium/action/Response.php
@@ -31,18 +31,26 @@ class Response extends \lithium\net\http\Response {
*/
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
protected $_classes = array('router' => 'lithium\net\http\Router');
=======
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
protected $_classes = array(
'router' => 'lithium\net\http\Router',
'media' => 'lithium\net\http\Media'
);
<<<<<<< HEAD
+<<<<<<< HEAD
>>>>>>> 25a362f706960b2becbf88e91cffc1b1638b7890
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+
+ protected $_autoConfig = array('classes' => 'merge');
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
public function __construct(array $config = array()) {
$defaults = array('buffer' => 8192, 'location' => null, 'status' => 0, 'request' => null);
@@ -50,6 +58,10 @@ class Response extends \lithium\net\http\Response {
}
protected function _init() {
+<<<<<<< HEAD
+=======
+ parent::_init();
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$config = $this->_config;
$this->status($config['status']);
unset($this->_config['status']);
@@ -59,7 +71,6 @@ class Response extends \lithium\net\http\Response {
$location = $classes['router']::match($config['location'], $config['request']);
$this->headers('location', $location);
}
- parent::_init();
}
/**
@@ -69,7 +80,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)`.';
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
throw new BadMethodCallException($message);
}
@@ -86,6 +101,7 @@ class Response extends \lithium\net\http\Response {
if ($expires === false) {
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
$headers = array(
=======
return $this->headers(array(
@@ -93,12 +109,16 @@ class Response extends \lithium\net\http\Response {
=======
return $this->headers(array(
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ return $this->headers(array(
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
'Expires' => 'Mon, 26 Jul 1997 05:00:00 GMT',
'Cache-Control' => array(
'no-store, no-cache, must-revalidate',
'post-check=0, pre-check=0',
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
'max-age=0'
),
'Pragma' => 'no-cache',
@@ -112,11 +132,14 @@ class Response extends \lithium\net\http\Response {
=======
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
'max-age=0',
),
'Pragma' => 'no-cache',
));
<<<<<<< HEAD
+<<<<<<< HEAD
>>>>>>> 25a362f706960b2becbf88e91cffc1b1638b7890
}
$expires = is_int($expires) ? $expires : strtotime($expires);
@@ -129,6 +152,11 @@ class Response extends \lithium\net\http\Response {
$expires = is_int($expires) ? $expires : strtotime($expires);
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ }
+ $expires = is_int($expires) ? $expires : strtotime($expires);
+
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
return $this->headers(array(
'Expires' => gmdate('D, d M Y H:i:s', $expires) . ' GMT',
'Cache-Control' => 'max-age=' . ($expires - time()),
@@ -149,10 +177,14 @@ class Response extends \lithium\net\http\Response {
if (isset($this->headers['location']) && $this->status['code'] === 200) {
$code = 302;
}
+<<<<<<< HEAD
if (!$status = $this->status($code)) {
throw new UnexpectedValueException('Invalid status code');
}
$this->_writeHeader($status);
+=======
+ $this->_writeHeader($this->status($code) ?: $this->status(500));
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
foreach ($this->headers as $name => $value) {
$key = strtolower($name);
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..ef6d5db 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;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
/**
* 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 d7b89ed..696e32b 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
@@ -65,6 +65,11 @@ class Logger extends \lithium\core\Adaptable {
*/
protected static $_adapters = 'adapter.analysis.logger';
+ /**
+ * An array of valid message priorities.
+ *
+ * @var array
+ */
protected static $_priorities = array(
'emergency' => 0,
'alert' => 1,
@@ -100,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);
@@ -109,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']);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
return $methods ? $result : false;
}
diff --git a/libraries/lithium/analysis/logger/adapter/File.php b/libraries/lithium/analysis/logger/adapter/File.php
index 41b0bf0..caa0e8e 100755
--- a/libraries/lithium/analysis/logger/adapter/File.php
+++ b/libraries/lithium/analysis/logger/adapter/File.php
@@ -8,59 +8,83 @@
namespace lithium\analysis\logger\adapter;
-use \SplFileInfo;
-use \DirectoryIterator;
+use lithium\util\String;
+use lithium\core\Libraries;
/**
* A simple log adapter that writes messages to files. By default, messages are written to
* `app/resources/tmp/logs/<type>.log`, where `<type>` is the log message priority level.
*
* {{{
- * lithium\analysis\Logger::config(array(
- * 'debug' => array('adapter' => 'File')
+ * use lithium\analysis\Logger;
+ *
+ * Logger::config(array(
+ * 'simple' => array('adapter' => 'File')
* ));
- * lithium\analysis\Logger::write('debug', 'Something happened!');
+ * Logger::write('debug', 'Something happened!');
* }}}
*
* This will cause the message and the timestamp of the log event to be written to
- * `app/resources/tmp/logs/debug.log`.
+ * `app/resources/tmp/logs/debug.log`. For available configuration options for this adapter, see
+ * the `__construct()` method.
+ *
+ * @see lithium\analysis\logger\adapter\File::__construct()
*/
class File extends \lithium\core\Object {
/**
* Class constructor.
*
+ * @see lithium\util\String::insert()
* @param array $config Settings used to configure the adapter. Available options:
* - `'path'` _string_: The directory to write log files to. Defaults to
- * `app/resources/tmp/logs`.
- * - `'timestamp'` _string_: The `date()`-compatible format of the timetstamp, or
- * `false` to disable timestamps. Defaults to `'Y-m-d H:i:s'`.
+ * `<app>/resources/tmp/logs`.
+ * - `'timestamp'` _string_: The `date()`-compatible timestamp format. Defaults to
+ * `'Y-m-d H:i:s'`.
+ * - `'file'` _closure_: A closure which accepts two parameters: an array
+ * containing the current log message details, and an array containing the `File`
+ * adapter's current configuration. It must then return a file name to write the
+ * log message to. The default will produce a log file name corresponding to the
+ * priority of the log message, i.e. `"debug.log"` or `"alert.log"`.
+ * - `'format'` _string_: A `String::insert()`-compatible string that specifies how
+ * the log message should be formatted. The default format is
+ * `"{:timestamp} {:message}\n"`.
* @return void
*/
public function __construct(array $config = array()) {
$defaults = array(
- 'path' => LITHIUM_APP_PATH . '/resources/tmp/logs',
+ 'path' => Libraries::get(true, 'resources') . '/tmp/logs',
'timestamp' => 'Y-m-d H:i:s',
+ 'file' => function($data, $config) { return "{$data['priority']}.log"; },
+ 'format' => "{:timestamp} {:message}\n",
);
parent::__construct($config + $defaults);
}
/**
- * Appends $data to file $type.
+ * Appends a message to a log file.
*
- * @param string $type
- * @param string $message
- * @return boolean `True` on successful write, `false` otherwise.
+ * @see lithium\analysis\Logger::$_priorities
+ * @param string $priority The message priority. See `Logger::$_priorities`.
+ * @param string $message The message to write to the log.
+ * @return closure Returns a closure that writes to the log, which can be wrapped in filters.
*/
- public function write($type, $message) {
+ public function write($priority, $message) {
$config = $this->_config;
return function($self, $params) use (&$config) {
+<<<<<<< HEAD
$type = $params['priority'];
$message = $params['message'];
$time = $config['timestamp'] ? date($config['timestamp']) . ' ' : '';
$path = $config['path'];
return file_put_contents("{$path}/{$type}.log", "{$time}{$message}\n", FILE_APPEND);
+=======
+ $path = $config['path'] . '/' . $config['file']($params, $config);
+ $params['timestamp'] = date($config['timestamp']);
+ $message = String::insert($config['format'], $params);
+ return file_put_contents($path, $message, FILE_APPEND);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
};
}
}
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..0d5aa91 100755
--- a/libraries/lithium/console/Dispatcher.php
+++ b/libraries/lithium/console/Dispatcher.php
@@ -40,11 +40,6 @@ class Dispatcher extends \lithium\core\StaticObject {
* elements array elements of the flag which are present in the route will be modified using a
* `lithium\util\String::insert()`-formatted string.
*
- * For example, to implement action prefixes (i.e. `admin_index()`), set a rule named 'admin',
- * with a value array containing a modifier key for the `action` element of a route, i.e.:
- * `array('action' => 'admin_{:action}')`. See `lithium\console\Dispatcher::config()` for
- * examples on setting rules.
- *
* @see lithium\console\Dispatcher::config()
* @see lithium\util\String::insert()
*/
@@ -76,11 +71,10 @@ class Dispatcher extends \lithium\core\StaticObject {
* If `$request` is `null`, a new request object is instantiated based on the value of the
* `'request'` key in the `$_classes` array.
*
- * @param object $request An instance of a request object with HTTP request information. If
+ * @param object $request An instance of a request object with console request information. If
* `null`, an instance will be created.
* @param array $options
* @return object The command action result which is an instance of `lithium\console\Response`.
- * @todo Add exception-handling/error page rendering
*/
public static function run($request = null, $options = array()) {
$defaults = array('request' => array());
@@ -130,7 +124,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 +185,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/Create.php b/libraries/lithium/console/command/Create.php
index af1079f..fdef733 100644
--- a/libraries/lithium/console/command/Create.php
+++ b/libraries/lithium/console/command/Create.php
@@ -8,9 +8,16 @@
namespace lithium\console\command;
+<<<<<<< HEAD
use lithium\core\Libraries;
use lithium\util\Inflector;
use lithium\util\String;
+=======
+use lithium\util\String;
+use lithium\core\Libraries;
+use lithium\util\Inflector;
+use lithium\core\ClassNotFoundException;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
/**
* The `create` command allows you to rapidly develop your models, views, controllers, and tests
@@ -112,7 +119,15 @@ class Create extends \lithium\console\Command {
* @return void
*/
protected function _execute($command) {
+<<<<<<< HEAD
if (!$class = $this->_instance($command)) {
+=======
+ try {
+ if (!$class = $this->_instance($command)) {
+ return false;
+ }
+ } catch (ClassNotFoundException $e) {
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
return false;
}
$data = 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/Route.php b/libraries/lithium/console/command/Route.php
new file mode 100644
index 0000000..86fd586
--- /dev/null
+++ b/libraries/lithium/console/command/Route.php
@@ -0,0 +1,139 @@
+<?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
+ */
+namespace lithium\console\command;
+
+use lithium\net\http\Router;
+use lithium\action\Request;
+use lithium\core\Environment;
+
+/**
+ * The route command lets you inspect your routes and issue requests against the router.
+ */
+class Route extends \lithium\console\Command {
+
+ /**
+ * Override the default 'development' environment.
+ *
+ * For example:
+ * {{{
+ * li3 route --env=production
+ * li3 route show /foo --env=test
+ * }}}
+ *
+ * @var string
+ */
+ public $env = 'development';
+
+ /**
+ * Load the routes file and set the environment.
+ *
+ * @param array $config The default configuration, wherein the absolute path to the routes file
+ * to load may be specified, using the `'routes_file'` key.
+ */
+ public function __construct($config = array()) {
+ $defaults = array('routes_file' => LITHIUM_APP_PATH . '/config/routes.php');
+ parent::__construct($config + $defaults);
+ }
+
+ protected function _init() {
+ parent::_init();
+ Environment::set($this->env);
+
+ if (file_exists($this->_config['routes_file'])) {
+ return require $this->_config['routes_file'];
+ }
+ $this->error("The routes file for this library doesn't exist or can't be found.");
+ }
+
+ /**
+ * Lists all connected routes to the router. See the `all()`
+ * method for details and examples.
+ *
+ * @return void
+ */
+ public function run() {
+ $this->all();
+ }
+
+ /**
+ * Lists all connected routes to the router. This is a convenience
+ * alias for the `show()` method.
+ *
+ * Example:
+ * {{{
+ * li3 route
+ * li3 route all
+ * }}}
+ *
+ * Will return an output similar to:
+ *
+ * {{{
+ * Template Params
+ * -------- ------
+ * / {"controller":"pages","action":"view"}
+ * /pages/{:args} {"controller":"pages","action":"view"}
+ * /{:slug:[\w\-]+} {"controller":"posts","action":"show"}
+ * /{:controller}/{:action}/{:args} {"action":"index"}
+ * }}}
+ *
+ * @return void
+ */
+ public function all() {
+ $routes = Router::get();
+ $columns = array(array('Template', 'Params'), array('--------', '------'));
+
+ foreach ($routes As $route) {
+ $info = $route->export();
+ $columns[] = array($info['template'], json_encode($info['params']));
+ }
+ $this->columns($columns);
+ }
+
+ /**
+ * Returns the corresponding params for a given URL and an optional request
+ * method.
+ *
+ * Examples:
+ * {{{
+ * 1: li3 route show /foo
+ * 2: li3 route show post /foo/bar/1
+ * 3: li3 route show /test
+ * 4: li3 route show /test --env=production
+ * }}}
+ *
+ * Will return outputs similar to:
+ *
+ * {{{
+ * 1: {"controller":"foo","action":"index" }
+ * 2: {"controller":"foo","action":"bar","args":["1"]}
+ * 3: {"controller":"lithium\\test\\Controller","action":"index"}
+ * 4: {"controller":"test","action":"index"}
+ * }}}
+ *
+ * @return void
+ */
+ public function show() {
+ $url = join(" ", $this->request->params['args']);
+ $method = 'GET';
+
+ if (!$url) {
+ $this->error('Please provide a valid URL');
+ }
+
+ if (preg_match('/^(GET|POST|PUT|DELETE|HEAD|OPTIONS) (.+)/i', $url, $matches)) {
+ $method = strtoupper($matches[1]);
+ $url = $matches[2];
+ }
+
+ $request = new Request(compact('url') + array('env' => array('REQUEST_METHOD' => $method)));
+ $result = Router::process($request);
+ $this->out($result->params ? json_encode($result->params) : "No route found.");
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/libraries/lithium/console/command/Test.php b/libraries/lithium/console/command/Test.php
index 21b0848..eaa4481 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;
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
/**
* Runs a given set of tests and outputs the results.
@@ -68,7 +71,8 @@ class Test extends \lithium\console\Command {
* lithium test --group=lithium.tests.cases.core
* }}}
*
- * @return void
+ * @param string $path Absolute or relative path to tests.
+ * @return boolean Will exit with status `1` if one or more tests failed otherwise with `0`.
*/
public function run() {
$this->header('Test');
@@ -87,9 +91,11 @@ class Test extends \lithium\console\Command {
'reporter' => 'console',
'format' => 'txt'
));
+ $stats = $report->stats();
+
$this->out('done.', 2);
$this->out('{:heading1}Results{:end}', 0);
- $this->out($report->render('stats'));
+ $this->out($report->render('stats', $stats));
foreach ($report->filters() as $filter => $options) {
$data = $report->results['filters'][$filter];
@@ -98,6 +104,8 @@ class Test extends \lithium\console\Command {
$this->hr();
$this->nl();
+
+ return $stats['success'];
}
/**
@@ -110,7 +118,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..219b2a3 100644
--- a/libraries/lithium/console/command/create/Test.php
+++ b/libraries/lithium/console/command/create/Test.php
@@ -11,6 +11,10 @@ namespace lithium\console\command\create;
use lithium\core\Libraries;
use lithium\util\Inflector;
use lithium\analysis\Inspector;
+<<<<<<< HEAD
+=======
+use lithium\core\ClassNotFoundException;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
/**
* Generate a Test class in the `--library` namespace
@@ -40,9 +44,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);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
/**
@@ -88,7 +96,17 @@ class Test extends \lithium\console\command\Create {
$type = $request->action;
$name = $request->args();
+<<<<<<< HEAD
if ($command = $this->_instance($type)) {
+=======
+ try {
+ $command = $this->_instance($type);
+ } catch (ClassNotFoundException $e) {
+ $command = null;
+ }
+
+ if ($command) {
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$request->params['action'] = $name;
$name = $command->invokeMethod('_class', array($request));
}
diff --git a/libraries/lithium/console/command/g11n/Extract.php b/libraries/lithium/console/command/g11n/Extract.php
index d458999..344d585 100644
--- a/libraries/lithium/console/command/g11n/Extract.php
+++ b/libraries/lithium/console/command/g11n/Extract.php
@@ -11,6 +11,10 @@ namespace lithium\console\command\g11n;
use DateTime;
use Exception;
use lithium\g11n\Catalog;
+<<<<<<< HEAD
+=======
+use lithium\core\Libraries;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
/**
* The `Extract` class is a command for extracting messages from files.
@@ -26,7 +30,7 @@ class Extract extends \lithium\console\Command {
public function _init() {
parent::_init();
$this->source = $this->source ?: LITHIUM_APP_PATH;
- $this->destination = $this->destination ?: LITHIUM_APP_PATH . '/resources/g11n';
+ $this->destination = $this->destination ?: Libraries::get(true, 'resources') . '/g11n';
}
/**
diff --git a/libraries/lithium/console/lithium.php b/libraries/lithium/console/lithium.php
index 1cfe4b3..89aea57 100644
--- a/libraries/lithium/console/lithium.php
+++ b/libraries/lithium/console/lithium.php
@@ -6,20 +6,26 @@
* @license http://opensource.org/licenses/bsd-license.php The BSD License
*/
+<<<<<<< HEAD
namespace lithium;
use lithium\core\Libraries;
use lithium\console\Dispatcher;
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
/**
- * Determine if we're in an application context by moving up the directory tree looking for
- * a `config` directory with a `bootstrap.php` file in it. If no application context is found,
- * just boot up the core framework.
+ * This console front-controller file is the gateway to your application
+ * through the command line. It is responsible for intercepting requests, and
+ * handing them off to the `Dispatcher` for processing.
+ *
+ * Determine if we're in an application context by moving up the directory tree
+ * looking for a `config` directory with a `bootstrap.php` file in it. If no
+ * application context is found, just boot up the core framework.
*/
-
$library = dirname(dirname(__DIR__));
-$app = null;
$working = getcwd() ?: __DIR__;
+$app = null;
while (!$app && $working) {
if (file_exists($working . '/config/bootstrap.php')) {
@@ -31,21 +37,54 @@ while (!$app && $working) {
}
}
+if ($app && is_dir("{$app}/config/bootstrap") && file_exists("{$app}/webroot/index.php")) {
+ include "{$app}/config/bootstrap.php";
+ exit(lithium\console\Dispatcher::run(new lithium\console\Request())->status);
+}
+
+define('LITHIUM_LIBRARY_PATH', $library);
+define('LITHIUM_APP_PATH', $app ? $working : dirname($library) . '/app');
+
+if (!include LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php') {
+ $message = "Lithium core could not be found. Check the value of LITHIUM_LIBRARY_PATH in ";
+ $message .= __FILE__ . ". It should point to the directory containing your ";
+ $message .= "/libraries directory.";
+ throw new ErrorException($message);
+}
+
+lithium\core\Libraries::add('lithium');
+
if ($app) {
- include $app . '/config/bootstrap.php';
-} else {
- define('LITHIUM_LIBRARY_PATH', $library);
- define('LITHIUM_APP_PATH', dirname($library) . '/app');
-
- if (!include LITHIUM_LIBRARY_PATH . '/lithium/core/Libraries.php') {
- $message = "Lithium core could not be found. Check the value of `LITHIUM_LIBRARY_PATH` ";
- $message .= "in `config/bootstrap.php`. It should point to the directory containing your ";
- $message .= "`/libraries` directory.";
- trigger_error($message, E_USER_ERROR);
- }
- Libraries::add('lithium');
+ lithium\core\Libraries::add(basename(LITHIUM_APP_PATH), array(
+ 'path' => LITHIUM_APP_PATH,
+ 'default' => true,
+ 'bootstrap' => !file_exists("{$app}/webroot/index.php")
+ ));
}
-exit(Dispatcher::run()->status);
+/**
+ * The following will dispatch the request and exit with the status code as
+ * provided by the `Response` object returned from `run()`.
+ *
+ * The following will instantiate a new `Request` object and pass it off to the
+ * `Dispatcher` class. By default, the `Request` will automatically aggregate
+ * all the server / environment settings, and request content (i.e. options and
+ * arguments passed to the command) information.
+ *
+ * The `Request` is then used by the `Dispatcher` (in conjunction with the
+ * `Router`) to determine the correct command to dispatch to. The response
+ * information is then encapsulated in a `Response` object, which is returned
+ * from the command to the `Dispatcher`.
+ *
+ * The `Response` object will contain information about the status code which
+ * is used as the exit code when ending the execution of this script and
+ * returned to the callee.
+ *
+ * @see lithium\console\Request
+ * @see lithium\console\Response
+ * @see lithium\console\Dispatcher
+ * @see lithium\console\Router
+ */
+exit(lithium\console\Dispatcher::run(new lithium\console\Request())->status);
?>
\ No newline at end of file
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..970104c 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;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
/**
* 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);
};
}
@@ -139,20 +139,44 @@ class ErrorHandler extends \lithium\core\StaticObject {
* This method (`ErrorHandler::run()`) needs to be called as early as possible in the bootstrap
* cycle; immediately after `require`-ing `bootstrap/libraries.php` is your best bet.
*
+ * @param array $config The configuration with which to start the error handler. Available
+ * options include:
+ * - `'trapErrors'` _boolean_: Defaults to `false`. If set to `true`, PHP errors
+ * will be caught by `ErrorHandler` and handled in-place. Execution will resume
+ * in the same context in which the error occurred.
+ * - `'convertErrors'` _boolean_: Defaults to `true`, and specifies that all PHP
+ * errors should be converted to `ErrorException`s and thrown from the point
+ * where the error occurred. The exception will be caught at the first point in
+ * the stack trace inside a matching `try`/`catch` block, or that has a matching
+ * error handler applied using the `apply()` method.
* @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 +236,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 +269,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.
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
* @return string Class where error/exception was generated.
*/
protected static function _origin(array $stack) {
@@ -256,22 +284,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) {
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
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);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
};
if (is_string($class)) {
+<<<<<<< HEAD
$class::applyFilter($method, $filter);
+=======
+ Filters::apply($class, $method, $filter);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
} else {
$class->applyFilter($method, $filter);
}
@@ -302,10 +348,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.
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
* @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 552038d..f9653f3 100644
--- a/libraries/lithium/core/Libraries.php
+++ b/libraries/lithium/core/Libraries.php
@@ -57,6 +57,13 @@ use lithium\core\ClassNotFoundException;
class Libraries {
/**
+ * Stores the closures that represent the method filters. They are indexed by method name.
+ *
+ * @var array
+ */
+ protected static $_methodFilters = array();
+
+ /**
* The list of class libraries registered with the class loader.
*
* @var array
@@ -98,9 +105,12 @@ class Libraries {
'data' => array(
'{:library}\extensions\data\{:namespace}\{:class}\{:name}',
<<<<<<< HEAD
+<<<<<<< HEAD
'{:library}\extensions\data\{:class}\{:name}',
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
'{:library}\data\{:namespace}\{:class}\adapter\{:name}' => array(
'libraries' => 'lithium'
),
@@ -131,6 +141,7 @@ class Libraries {
'test' => array(
'{:library}\extensions\test\{:namespace}\{:class}\{:name}',
<<<<<<< HEAD
+<<<<<<< HEAD
'{:library}\extensions\test\{:class}\{:name}',
'{:library}\test\{:namespace}\{:class}\{:name}' => array('libraries' => 'lithium'),
'{:library}\test\{:class}\{:name}' => array('libraries' => 'lithium')
@@ -139,11 +150,16 @@ class Libraries {
'{:library}\tests\{:namespace}\{:class}\{:name}Test',
'{:library}\tests\{:namespace}\{:name}Test'
=======
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
'{:library}\test\{:namespace}\{:class}\{:name}' => array('libraries' => 'lithium'),
),
'tests' => array(
'{:library}\tests\{:namespace}\{:class}\{:name}Test',
+<<<<<<< HEAD
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
)
);
@@ -249,25 +265,30 @@ class Libraries {
* that contains the `lithium` directory), however, you can change this on a case-by-case basis
* using the `'path'` key to specify an absolute path to the library's directory.
*
- * @param string $name Library name, i.e. `'app'`, `'lithium'`, `'pear'` or `'solar'`.
+ * @param string $name Library name, i.e. `'app'`, `'lithium'`, `'pear'` or `'aura'`.
* @param array $config Specifies where the library is in the filesystem, and how classes
* should be loaded from it. Allowed keys are:
- * - `'bootstrap'`: A file path (relative to `'path'`) to a bootstrap script that should
- * be run when the library is added.
- * - `'defer'`: If true, indicates that, when locating classes, this library should
- * defer to other libraries in order of preference.
- * - `'includePath'`: If `true`, appends the absolutely-resolved value of `'path'` to
- * the PHP include path.
+ * - `'bootstrap'` _mixed_: A file path (relative to `'path'`) to a bootstrap script that
+ * should be run when the library is added, or `true` to use the default bootstrap
+ * path, i.e. `config/bootstrap.php`.
+ * - `'defer'` _boolean_: If `true`, indicates that, when locating classes, this library
+ * should defer to other libraries in order of preference.
+ * - `'includePath'` _mixed_: If `true`, appends the absolutely-resolved value of
+ * `'path'` to the PHP include path. If a string, the value is appended to PHP's.
* - `'loader'`: An auto-loader method associated with the library, if any.
* - `'path'`: The directory containing the library.
- * - `'prefix'`: The class prefix this library uses, i.e. `'lithium\'`, `'Zend_'` or
- * `'Solar_'`.
- * - `'suffix'`: Gets appended to the end of the file name. For example, most libraries
- * end classes in `'.php'`, but some use `'.class.php'`, or `'.inc.php'`.
- * - `'transform'`: Defines a custom way to transform a class name into its
+ * - `'prefix'` _string_: The class prefix this library uses, i.e. `'lithium\'`,
+ * `'Zend_'` or `'Solar_'`. If the library has no global prefix, set to `false`.
+ * - `'suffix'` _string_: Gets appended to the end of the file name. For example, most
+ * libraries end classes in `'.php'`, but some use `'.class.php'`, or `'.inc.php'`.
+ * - `'transform'` _closure_: Defines a custom way to transform a class name into its
* corresponding file path. Accepts either an array of two strings which are
* interpreted as the pattern and replacement for a regex, or an anonymous function,
- * which receives the class name as a parameter, and returns a file path as output.
+ * which receives the class name and library configuration arrays as parameters, and
+ * returns the full physical file path as output.
+ * - `'resources'` _string_: If this is the default library, this maybe set to the
+ * absolute path to the write-enabled application resources directory, which is used
+ * for caching, log files, uploads, etc.
* @return array Returns the resulting set of options created for this library.
*/
public static function add($name, array $config = array()) {
@@ -292,12 +313,17 @@ class Libraries {
static::$_default = $name;
$defaults['path'] = LITHIUM_APP_PATH;
$defaults['bootstrap'] = false;
+ $defaults['resources'] = LITHIUM_APP_PATH . '/resources';
}
$config += $defaults;
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.");
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
}
$config['path'] = str_replace('\\', '/', $config['path']);
@@ -334,13 +360,22 @@ class Libraries {
* Returns configuration for given name.
*
* @param string $name Registered library to retrieve configuration for.
- * @return array Retrieved configuration.
+ * @param string $key Optional key name. If `$name` is set and is the name of a valid library,
+ * returns the given named configuration key, i.e. `'path'`, `'webroot'` or
+ * `'resources'`.
+ * @return mixed A configuation array for one or more libraries, or a string value if `$key` is
+ * specified.
*/
+<<<<<<< HEAD
public static function get($name = null) {
+=======
+ public static function get($name = null, $key = null) {
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$configs = static::$_configurations;
if (!$name) {
return $configs;
+<<<<<<< HEAD
}
if (is_array($name)) {
foreach ($name as $i => $key) {
@@ -348,11 +383,29 @@ class Libraries {
$name[$key] = isset($configs[$key]) ? $configs[$key] : null;
}
return $name;
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
if ($name === true) {
$name = static::$_default;
}
+<<<<<<< HEAD
return isset($configs[$name]) ? $configs[$name] : null;
+=======
+ if (is_array($name)) {
+ foreach ($name as $i => $key) {
+ unset($name[$i]);
+ $name[$key] = isset($configs[$key]) ? $configs[$key] : null;
+ }
+ return $name;
+ }
+ $config = isset($configs[$name]) ? $configs[$name] : null;
+
+ if (!$key) {
+ return $config;
+ }
+ return isset($config[$key]) ? $config[$key] : null;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
/**
@@ -445,7 +498,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}`.");
}
}
@@ -487,15 +540,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;
}
}
@@ -540,12 +628,61 @@ class Libraries {
* @return object If the class is found, returns an instance of it, otherwise throws an
* exception.
* @throws lithium\core\ClassNotFoundException Throws an exception if the class can't be found.
+ * @filter
*/
public static function instance($type, $name, array $options = array()) {
+<<<<<<< HEAD
if (!$class = (string) static::locate($type, $name)) {
throw new ClassNotFoundException("Class '{$name}' of type '{$type}' not found.");
}
return class_exists($class) ? new $class($options) : null;
+=======
+ $params = compact('type', 'name', 'options');
+ $_paths =& static::$_paths;
+
+ $implementation = function($self, $params) use (&$_paths) {
+ $name = $params['name'];
+ $type = $params['type'];
+
+ if (!$name && !$type) {
+ $message = "Invalid class lookup: `\$name` and `\$type` are empty.";
+ throw new ClassNotFoundException($message);
+ }
+ if (!is_string($type) && $type !== null && !isset($_paths[$type])) {
+ throw new ClassNotFoundException("Invalid class type `{$type}`.");
+ }
+ if (!$class = $self::locate($type, $name)) {
+ throw new ClassNotFoundException("Class `{$name}` of type `{$type}` not found.");
+ }
+ if (is_object($class)) {
+ return $class;
+ }
+ $success = (is_string($class) && class_exists($class));
+ return $success ? new $class($params['options']) : null;
+ };
+ if (!isset(static::$_methodFilters[__FUNCTION__])) {
+ return $implementation(get_called_class(), $params);
+ }
+ $class = get_called_class();
+ $method = __FUNCTION__;
+ $data = array_merge(static::$_methodFilters[__FUNCTION__], array($implementation));
+ return Filters::run($class, $params, compact('data', 'class', 'method'));
+ }
+
+ /**
+ * Apply a closure to a method in `Libraries`.
+ *
+ * @see lithium\util\collection\Filters
+ * @param string $method The name of the method to apply the closure to.
+ * @param closure $filter The closure that is used to filter the method.
+ * @return void
+ */
+ public static function applyFilter($method, $filter = null) {
+ if (!isset(static::$_methodFilters[$method])) {
+ static::$_methodFilters[$method] = array();
+ }
+ static::$_methodFilters[$method][] = $filter;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
/**
@@ -607,6 +744,10 @@ class Libraries {
return $name;
}
$ident = $name ? ($type . '.' . $name) : ($type . '.*');
+<<<<<<< HEAD
+=======
+ $ident .= $options ? '.' . md5(serialize($options)) : null;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
if (isset(static::$_cachedPaths[$ident])) {
return static::$_cachedPaths[$ident];
@@ -625,12 +766,17 @@ class Libraries {
return null;
}
<<<<<<< HEAD
+<<<<<<< HEAD
if (!$name) {
$result = static::_locateAll(array('name' => '*') + $params, $options);
=======
if ($params['name'] === '*') {
$result = static::_locateAll($params, $options);
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ if ($params['name'] === '*') {
+ $result = static::_locateAll($params, $options);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
return (static::$_cachedPaths[$ident] = $result);
}
if ($options['library']) {
@@ -687,10 +833,13 @@ class Libraries {
if (isset($options['library'])) {
$libraries = static::get((array) $options['library']);
<<<<<<< HEAD
+<<<<<<< HEAD
} else {
$libraries = static::$_configurations;
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
foreach ($libraries as $library => $config) {
if ($config['defer'] !== $defer && $defer !== null) {
@@ -718,6 +867,7 @@ class Libraries {
* @param array $params The parameters used in the service location lookup.
* @return array Returns an array of valid path template strings.
<<<<<<< HEAD
+<<<<<<< HEAD
*/
protected static function _searchPaths($paths, $library, $params) {
$result = array();
@@ -752,6 +902,9 @@ class Libraries {
$defaults = array('libraries' => null, 'recursive' => true, 'namespaces' => false);
=======
*/
+=======
+ */
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
protected static function _searchPaths($paths, $library, $params) {
$result = array();
$params = array('library' => null, 'type' => null) + $params;
@@ -777,6 +930,7 @@ class Libraries {
* @return array
*/
protected static function _locateAll(array $params, array $options = array()) {
+<<<<<<< HEAD
$defaults = array(
'libraries' => null, 'recursive' => true, 'namespaces' => false
);
@@ -790,6 +944,14 @@ class Libraries {
$libraries = $options['library'] ? $options['library'] : $options['libraries'];
$libraries = static::get((array) $libraries);
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ $defaults = array('libraries' => null, 'recursive' => true, 'namespaces' => false);
+ $options += $defaults;
+
+ $paths = (array) static::$_paths[$params['type']];
+ $libraries = $options['library'] ? $options['library'] : $options['libraries'];
+ $libraries = static::get((array) $libraries);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$flags = array('escape' => '/');
$classes = array();
@@ -799,9 +961,13 @@ class Libraries {
foreach (static::_searchPaths($paths, $library, $params) as $tpl) {
$options['path'] = str_replace('\\', '/', String::insert($tpl, $params, $flags));
<<<<<<< HEAD
+<<<<<<< HEAD
=======
$options['path'] = str_replace('*/', '', $options['path']);
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ $options['path'] = str_replace('*/', '', $options['path']);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$classes = array_merge($classes, static::_search($config, $options));
}
}
@@ -874,6 +1040,7 @@ 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;
@@ -883,6 +1050,13 @@ class Libraries {
=======
return static::_filter($libs, (array) $config, $options + compact('name'));
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ }
+ if ($suffix) {
+ $libs = $options['preFilter'] ? preg_grep($options['preFilter'], $libs) : $libs;
+ }
+ return static::_filter($libs, (array) $config, $options + compact('name'));
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
/**
@@ -927,15 +1101,21 @@ class Libraries {
*/
protected static function _params($type, $name = "*") {
<<<<<<< HEAD
+<<<<<<< HEAD
$namespace = $class = '*';
if (strpos($type, '.')) {
=======
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$name = $name ?: "*";
$library = $namespace = $class = '*';
if (strpos($type, '.') !== false) {
+<<<<<<< HEAD
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$parts = explode('.', $type);
$type = array_shift($parts);
diff --git a/libraries/lithium/core/Object.php b/libraries/lithium/core/Object.php
index f57fcbb..1ef4f3f 100644
--- a/libraries/lithium/core/Object.php
+++ b/libraries/lithium/core/Object.php
@@ -8,6 +8,10 @@
namespace lithium\core;
+<<<<<<< HEAD
+=======
+use lithium\core\Libraries;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
use lithium\util\collection\Filters;
/**
@@ -205,9 +209,10 @@ class Object {
* in `_init` to create the dependencies used in the current class.
*
* @param string|object $name A `classes` key or fully-namespaced class name.
- * @param array $config The configuration passed to the constructor.
- * @return void
+ * @param array $options The configuration passed to the constructor.
+ * @return object
*/
+<<<<<<< HEAD
protected function _instance($name, array $config = array()) {
if (is_object($name) || !$name) {
return $name;
@@ -218,6 +223,13 @@ class Object {
$name = $this->_classes[$name];
}
return (is_string($name) && class_exists($name)) ? new $name($config) : null;
+=======
+ protected function _instance($name, array $options = array()) {
+ if (is_string($name) && isset($this->_classes[$name])) {
+ $name = $this->_classes[$name];
+ }
+ return Libraries::instance(null, $name, $options);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
/**
diff --git a/libraries/lithium/core/StaticObject.php b/libraries/lithium/core/StaticObject.php
index abcf66e..1da75dc 100644
--- a/libraries/lithium/core/StaticObject.php
+++ b/libraries/lithium/core/StaticObject.php
@@ -8,6 +8,10 @@
namespace lithium\core;
+<<<<<<< HEAD
+=======
+use lithium\core\Libraries;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
use lithium\util\collection\Filters;
/**
@@ -87,17 +91,14 @@ class StaticObject {
* in `_init` to create the dependencies used in the current class.
*
* @param string|object $name A `classes` key or fully-namespaced class name.
- * @param array $config The configuration passed to the constructor.
- * @return void
+ * @param array $options The configuration passed to the constructor.
+ * @return object
*/
- protected static function _instance($name, array $config = array()) {
- if (is_object($name) || !$name) {
- return $name;
- }
- if (isset(static::$_classes[$name])) {
+ protected static function _instance($name, array $options = array()) {
+ if (is_string($name) && isset(static::$_classes[$name])) {
$name = static::$_classes[$name];
}
- return new $name($config);
+ return Libraries::instance(null, $name, $options);
}
/**
diff --git a/libraries/lithium/data/Collection.php b/libraries/lithium/data/Collection.php
index 4de3275..288f8b1 100644
--- a/libraries/lithium/data/Collection.php
+++ b/libraries/lithium/data/Collection.php
@@ -118,6 +118,7 @@ abstract class Collection extends \lithium\util\Collection {
if ($model = $this->_model) {
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
$pathKey = $this->_pathKey;
$this->_data = $model::connection()->cast($model, $this->_data, compact('pathKey'));
=======
@@ -125,13 +126,18 @@ abstract class Collection extends \lithium\util\Collection {
$this->_data = $model::connection()->cast($this, $this->_data, $options);
>>>>>>> 25a362f706960b2becbf88e91cffc1b1638b7890
=======
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$options = array(
'pathKey' => $this->_pathKey,
'schema' => $model::schema(),
'exists' => isset($this->_config['exists']) ? $this->_config['exists'] : null
);
$this->_data = $model::connection()->cast($this, $this->_data, $options);
+<<<<<<< HEAD
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
}
@@ -176,10 +182,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.
*/
@@ -281,6 +287,7 @@ abstract class Collection extends \lithium\util\Collection {
if (is_array($data) && ($model = $this->_model)) {
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
$data = $model::connection()->cast($model, $data);
=======
$data = $model::connection()->cast($this, $data);
@@ -288,6 +295,9 @@ abstract class Collection extends \lithium\util\Collection {
=======
$data = $model::connection()->cast($this, $data);
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ $data = $model::connection()->cast($this, $data);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
} elseif (is_object($data)) {
$data->assignTo($this);
}
diff --git a/libraries/lithium/data/Entity.php b/libraries/lithium/data/Entity.php
index cb9e1d0..2d2ac20 100644
--- a/libraries/lithium/data/Entity.php
+++ b/libraries/lithium/data/Entity.php
@@ -79,9 +79,28 @@ class Entity extends \lithium\core\Object {
/**
* Contains the values of updated fields. These values will be persisted to the backend data
* store when the document is saved.
+<<<<<<< HEAD
+ *
+ * @var array
+ */
+ protected $_updated = array();
+
+ /**
+ * An array of key/value pairs corresponding to fields that should be updated using atomic
+ * incrementing / decrementing operations. Keys match field names, and values indicate the value
+ * each field should be incremented or decrememnted by.
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
*
+ * @see lithium\data\Entity::increment()
+ * @see lithium\data\Entity::decrement()
* @var array
*/
+<<<<<<< HEAD
+ protected $_increment = array();
+
+ /**
+=======
protected $_updated = array();
/**
@@ -96,6 +115,7 @@ class Entity extends \lithium\core\Object {
protected $_increment = array();
/**
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
* A flag indicating whether or not this entity exists. Set to `false` if this is a
* newly-created entity, or if this entity has been loaded and subsequently deleted. Set to
* `true` if the entity has been loaded from the database, or has been created and subsequently
@@ -185,6 +205,7 @@ class Entity extends \lithium\core\Object {
public function __set($name, $value = null) {
if (is_array($name) && !$value) {
<<<<<<< HEAD
+<<<<<<< HEAD
foreach ($name as $key => $value) {
$this->__set($key, $value);
}
@@ -197,6 +218,11 @@ class Entity extends \lithium\core\Object {
}
$this->_updated[$name] = $value;
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ return array_map(array(&$this, '__set'), array_keys($name), array_values($name));
+ }
+ $this->_updated[$name] = $value;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
/**
@@ -221,7 +247,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}`.";
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
throw new BadMethodCallException($message);
}
array_unshift($params, $this);
@@ -349,9 +379,15 @@ class Entity extends \lithium\core\Object {
* @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.
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
* @throws UnexpectedValueException Throws an exception when `$field` is set to a non-numeric
* type.
*/
@@ -373,7 +409,11 @@ class Entity extends \lithium\core\Object {
* @see lithium\data\Entity::increment()
* @param string $field The name of the field to decrement.
* @param string $value The value by which to decrement the field. Defaults to `1`.
+<<<<<<< HEAD
* @return int Returns the new value of `$field`, after modification.
+=======
+ * @return integer Returns the new value of `$field`, after modification.
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
*/
public function decrement($field, $value = 1) {
return $this->increment($field, $value * -1);
@@ -468,10 +508,14 @@ class Entity extends \lithium\core\Object {
$exists = $this->_exists;
$options += compact('parent', 'exists', 'pathKey');
<<<<<<< HEAD
+<<<<<<< HEAD
return $model::connection()->cast($model, $data, $options);
=======
return $model::connection()->cast($this, $data, $options);
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ return $model::connection()->cast($this, $data, $options);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
}
}
diff --git a/libraries/lithium/data/Model.php b/libraries/lithium/data/Model.php
index f587c52..aaf9e7c 100755
--- a/libraries/lithium/data/Model.php
+++ b/libraries/lithium/data/Model.php
@@ -26,7 +26,11 @@ use BadMethodCallException;
* data mutation (saving/updating/deleting). All query-related operations may be done through the
* static `find()` method, along with some additional utility methods provided for convenience.
*
+<<<<<<< HEAD
* Classes extending this one should, conventionally, be named as Singular, CamelCase and be
+=======
+ * Classes extending this one should, conventionally, be named as Plural, CamelCase and be
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
* placed in the `app/models` directory. i.e. a posts model would be `app/model/Posts.php`.
*
* Examples:
@@ -170,10 +174,9 @@ class Model extends \lithium\core\StaticObject {
*/
protected $_relationTypes = array(
'belongsTo' => array('class', 'key', 'conditions', 'fields'),
- 'hasOne' => array('class', 'key', 'conditions', 'fields', 'dependent'),
+ 'hasOne' => array('class', 'key', 'conditions', 'fields'),
'hasMany' => array(
- 'class', 'key', 'conditions', 'fields', 'order', 'limit',
- 'dependent', 'exclusive', 'finder', 'counter'
+ 'class', 'key', 'conditions', 'fields', 'order', 'limit'
)
);
@@ -321,9 +324,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();
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$meta = array();
$schema = array();
$source = array();
@@ -342,6 +349,7 @@ class Model extends \lithium\core\StaticObject {
}
}
$tmp = $options + $self->_meta + $meta;
+<<<<<<< HEAD
if ($tmp['connection']) {
$conn = $classes['connections']::get($tmp['connection']);
@@ -352,6 +360,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;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$self->_meta = ($local + $source['meta'] + $meta);
$self->_meta['initialized'] = false;
$self->_schema += $schema + $source['schema'];
@@ -389,7 +409,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 +465,11 @@ class Model extends \lithium\core\StaticObject {
$type = 'first';
}
+<<<<<<< HEAD
$options += ((array) $self->_query + (array) $defaults);
+=======
+ $options = (array) $options + (array) $self->_query + (array) $defaults;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$meta = array('meta' => $self->_meta, 'name' => get_called_class());
$params = compact('type', 'options');
@@ -572,7 +596,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;
@@ -681,10 +705,14 @@ class Model extends \lithium\core\StaticObject {
* document in the database that corresponds to `$entity`.
*
<<<<<<< HEAD
+<<<<<<< HEAD
* For example:
=======
* For example, to create a new record or document:
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ * For example, to create a new record or document:
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
* {{{
* $post = Posts::create(); // Creates a new object, which doesn't exist in the database yet
* $post->title = "My post";
@@ -719,9 +747,13 @@ class Model extends \lithium\core\StaticObject {
* @see lithium\data\Model::$validates
* @see lithium\data\Model::validates()
<<<<<<< HEAD
+<<<<<<< HEAD
=======
* @see lithium\data\Model::errors()
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ * @see lithium\data\Model::errors()
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
* @param object $entity The record or document object to be saved in the database. This
* parameter is implicit and should not be passed under normal circumstances.
* In the above example, the call to `save()` on the `$post` object is
@@ -767,12 +799,17 @@ class Model extends \lithium\core\StaticObject {
}
}
<<<<<<< HEAD
+<<<<<<< HEAD
if ($options['whitelist'] || $options['locked']) {
$whitelist = $options['whitelist'] ?: array_keys($_schema);
=======
if (($whitelist = $options['whitelist']) || $options['locked']) {
$whitelist = $whitelist ?: array_keys($_schema);
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ if (($whitelist = $options['whitelist']) || $options['locked']) {
+ $whitelist = $whitelist ?: array_keys($_schema);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
$type = $entity->exists() ? 'update' : 'create';
@@ -782,18 +819,52 @@ class Model extends \lithium\core\StaticObject {
};
if (!$options['callbacks']) {
- return $filter($entity, $options);
+ return $filter($entity, $params);
}
return static::_filter(__FUNCTION__, $params, $filter);
}
/**
- * Indicates whether the `Model`'s current data validates, given the
- * current rules setup.
+ * An important part of describing the business logic of a model class is defining the
+ * validation rules. In Lithium models, rules are defined through the `$validates` class
+ * property, and are used by this method before saving to verify the correctness of the data
+ * being sent to the backend data source.
*
- * @param string $entity Model record to validate.
- * @param array $options Options.
- * @return boolean Success.
+ * Note that these are application-level validation rules, and do not
+ * interact with any rules or constraints defined in your data source. If such constraints fail,
+ * an exception will be thrown by the database layer. The `validates()` method only checks
+ * against the rules defined in application code.
+ *
+ * This method uses the `Validator` class to perform data validation. An array representation of
+ * the entity object to be tested is passed to the `check()` method, along with the model's
+ * validation rules. Any rules defined in the `Validator` class can be used to validate fields.
+ * See the `Validator` class to add custom rules, or override built-in rules.
+ *
+ * @see lithium\data\Model::$validates
+ * @see lithium\util\Validator::check()
+ * @see lithium\data\Entity::errors()
+ * @param string $entity Model entity to validate. Typically either a `Record` or `Document`
+ * object. In the following example:
+ * {{{
+ * $post = Posts::create($data);
+ * $success = $post->validates();
+ * }}}
+ * The `$entity` parameter is equal to the `$post` object instance.
+ * @param array $options Available options:
+ * - `'rules'` _array_: If specified, this array will _replace_ the default
+ * validation rules defined in `$validates`.
+ * - `'events'` _mixed_: A string or array defining one or more validation
+ * _events_. Events are different contexts in which data events can occur, and
+ * correspond to the optional `'on'` key in validation rules. For example, by
+ * default, `'events'` is set to either `'create'` or `'update'`, depending on
+ * whether `$entity` already exists. Then, individual rules can specify
+ * `'on' => 'create'` or `'on' => 'update'` to only be applied at certain times.
+ * Using this parameter, you can set up custom events in your rules as well, such
+ * as `'on' => 'login'`. Note that when defining validation rules, the `'on'` key
+ * can also be an array of multiple events.
+ * @return boolean Returns `true` if all validation rules on all fields succeed, otherwise
+ * `false`. After validation, the messages for any validation failures are assigned to
+ * the entity, and accessible through the `errors()` method of the entity object.
*/
public function validates($entity, array $options = array()) {
$defaults = array(
@@ -907,7 +978,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/Source.php b/libraries/lithium/data/Source.php
index 34d8a25..fc2de28 100644
--- a/libraries/lithium/data/Source.php
+++ b/libraries/lithium/data/Source.php
@@ -211,11 +211,16 @@ abstract class Source extends \lithium\core\Object {
* Casts data into proper format when added to a collection or entity object.
*
<<<<<<< HEAD
+<<<<<<< HEAD
* @param string $model The name of the model class to which the entity or collection is bound.
=======
* @param mixed $entity The entity or collection for which data is being cast, or the name of
* the model class to which the entity/collection is bound.
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ * @param mixed $entity The entity or collection for which data is being cast, or the name of
+ * the model class to which the entity/collection is bound.
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
* @param array $data An array of data being assigned.
* @param array $options Any associated options with, for example, instantiating new objects in
* which to wrap the data. Options implemented by `cast()` itself:
@@ -226,10 +231,14 @@ abstract class Source extends \lithium\core\Object {
* definition of the model class specified by `$model`.
*/
<<<<<<< HEAD
+<<<<<<< HEAD
public function cast($model, array $data, array $options = array()) {
=======
public function cast($entity, array $data, array $options = array()) {
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ public function cast($entity, array $data, array $options = array()) {
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$defaults = array('first' => false);
$options += $defaults;
return $options['first'] ? reset($data) : $data;
diff --git a/libraries/lithium/data/collection/DocumentArray.php b/libraries/lithium/data/collection/DocumentArray.php
index 11fe4ea..25b1a18 100644
--- a/libraries/lithium/data/collection/DocumentArray.php
+++ b/libraries/lithium/data/collection/DocumentArray.php
@@ -11,6 +11,7 @@ namespace lithium\data\collection;
use lithium\data\Source;
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
=======
use lithium\util\Collection;
>>>>>>> 25a362f706960b2becbf88e91cffc1b1638b7890
@@ -21,6 +22,8 @@ class DocumentArray extends \lithium\data\Collection {
<<<<<<< HEAD
=======
=======
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
use lithium\util\Collection;
class DocumentArray extends \lithium\data\Collection {
@@ -46,7 +49,10 @@ class DocumentArray extends \lithium\data\Collection {
}
/**
+<<<<<<< HEAD
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
* Adds conversions checks to ensure certain class types and embedded values are properly cast.
*
* @param string $format Currently only `array` is supported.
@@ -67,9 +73,12 @@ class DocumentArray extends \lithium\data\Collection {
/**
<<<<<<< HEAD
+<<<<<<< HEAD
>>>>>>> 25a362f706960b2becbf88e91cffc1b1638b7890
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
* PHP magic method used to check the presence of a field as document properties, i.e.
* `$document->_id`.
*
@@ -109,6 +118,7 @@ class DocumentArray extends \lithium\data\Collection {
public function offsetSet($offset, $data) {
if ($model = $this->_model) {
<<<<<<< HEAD
+<<<<<<< HEAD
$data = $model::connection()->cast($model, array($this->_pathKey => $data), array(
'first' => true
));
@@ -116,6 +126,10 @@ class DocumentArray extends \lithium\data\Collection {
$options = array('first' => true, 'schema' => $model::schema());
$data = $model::connection()->cast($this, array($this->_pathKey => $data), $options);
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ $options = array('first' => true, 'schema' => $model::schema());
+ $data = $model::connection()->cast($this, array($this->_pathKey => $data), $options);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
if ($offset) {
return $this->_data[$offset] = $data;
@@ -158,6 +172,7 @@ class DocumentArray extends \lithium\data\Collection {
}
<<<<<<< HEAD
+<<<<<<< HEAD
public function export(Source $dataSource, array $options = array()) {
$result = array();
@@ -170,13 +185,18 @@ class DocumentArray extends \lithium\data\Collection {
}
return $result;
=======
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
public function export() {
return array(
'exists' => $this->_exists,
'key' => $this->_pathKey,
'data' => $this->_data,
);
+<<<<<<< HEAD
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
protected function _populate($data = null, $key = null) {}
diff --git a/libraries/lithium/data/collection/DocumentSet.php b/libraries/lithium/data/collection/DocumentSet.php
index f2eb4bd..8da1b95 100644
--- a/libraries/lithium/data/collection/DocumentSet.php
+++ b/libraries/lithium/data/collection/DocumentSet.php
@@ -9,10 +9,13 @@
namespace lithium\data\collection;
<<<<<<< HEAD
+<<<<<<< HEAD
use lithium\data\Source;
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
class DocumentSet extends \lithium\data\Collection {
/**
@@ -43,10 +46,14 @@ class DocumentSet extends \lithium\data\Collection {
if (!is_object($next) && ($model = $this->_model)) {
<<<<<<< HEAD
+<<<<<<< HEAD
$next = $model::connection()->cast($model, $next);
=======
$next = $model::connection()->cast($this, $next);
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ $next = $model::connection()->cast($this, $next);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$current->_data[$key] = $next;
}
$current = $next;
@@ -117,10 +124,14 @@ class DocumentSet extends \lithium\data\Collection {
}
if (is_array($data = $this->_data[$offset]) && $model) {
<<<<<<< HEAD
+<<<<<<< HEAD
$this->_data[$offset] = $model::connection()->cast($model, $data);
=======
$this->_data[$offset] = $model::connection()->cast($this, $data);
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ $this->_data[$offset] = $model::connection()->cast($this, $data);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
if (isset($this->_data[$offset])) {
return $this->_data[$offset];
@@ -196,10 +207,14 @@ class DocumentSet extends \lithium\data\Collection {
}
$options = array('exists' => true, 'first' => true, 'pathKey' => $this->_pathKey);
<<<<<<< HEAD
+<<<<<<< HEAD
return $this->_data[] = $conn->cast($model, array($key => $data), $options);
=======
return $this->_data[] = $conn->cast($this, array($key => $data), $options);
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ return $this->_data[] = $conn->cast($this, array($key => $data), $options);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
/**
diff --git a/libraries/lithium/data/entity/Document.php b/libraries/lithium/data/entity/Document.php
index 5153975..f9adb32 100644
--- a/libraries/lithium/data/entity/Document.php
+++ b/libraries/lithium/data/entity/Document.php
@@ -9,12 +9,17 @@
namespace lithium\data\entity;
<<<<<<< HEAD
+<<<<<<< HEAD
use lithium\data\Source;
use lithium\util\Collection;
=======
use lithium\util\Collection;
use UnexpectedValueException;
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+use lithium\util\Collection;
+use UnexpectedValueException;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
/**
* `Document` is an alternative to the `entity\Record` class, which is optimized for
@@ -109,6 +114,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) {
@@ -126,6 +132,17 @@ class Document extends \lithium\data\Entity implements \Iterator, \ArrayAccess {
$this->_data = $model::connection()->cast($this, $this->_data, $options);
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
}
+=======
+ $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;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
unset($this->_autoConfig);
}
@@ -150,7 +167,10 @@ class Document extends \lithium\data\Entity implements \Iterator, \ArrayAccess {
}
<<<<<<< HEAD
+<<<<<<< HEAD
=======
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
if (isset($this->_removed[$name])) {
return $null;
}
@@ -158,7 +178,10 @@ class Document extends \lithium\data\Entity implements \Iterator, \ArrayAccess {
return $this->_updated[$name];
}
+<<<<<<< HEAD
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
if ($model && $conn) {
foreach ($model::relations() as $relation => $config) {
if ($config && (($linkKey = $config->data('fieldName')) === $name)) {
@@ -169,6 +192,7 @@ class Document extends \lithium\data\Entity implements \Iterator, \ArrayAccess {
}
if (!isset($this->_data[$name]) && $schema = $model::schema($name)) {
$schema = array($name => $schema);
+<<<<<<< HEAD
$pathKey = $this->_pathKey ? "{$this->_pathKey}.{$name}" : $name;
$options = compact('pathKey', 'schema') + array('first' => true);
<<<<<<< HEAD
@@ -191,6 +215,17 @@ class Document extends \lithium\data\Entity implements \Iterator, \ArrayAccess {
return $this->_data[$name];
}
}
+=======
+ $pathKey = $this->_pathKey ? $this->_pathKey : null;
+ $options = compact('pathKey', 'schema') + array('first' => true);
+
+ if (($value = $conn->cast($this, array($name => null), $options)) !== null) {
+ $this->_data[$name] = $value;
+ return $this->_data[$name];
+ }
+ }
+ }
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
if (isset($this->_data[$name])) {
return $this->_data[$name];
}
@@ -203,6 +238,7 @@ class Document extends \lithium\data\Entity implements \Iterator, \ArrayAccess {
$path = $this->_pathKey ? "{$this->_pathKey}." : '';
$this->_updated[$key]->_pathKey = "{$path}{$key}";
$this->_updated[$key]->_exists = false;
+<<<<<<< HEAD
}
}
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
@@ -232,6 +268,11 @@ class Document extends \lithium\data\Entity implements \Iterator, \ArrayAccess {
}
}
return array($data, $nested);
+=======
+ }
+ }
+ return parent::export() + array('key' => $this->_pathKey, 'remove' => $this->_removed);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
public function update($id = null, array $data = array()) {
@@ -242,6 +283,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();
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
/**
@@ -283,14 +328,20 @@ class Document extends \lithium\data\Entity implements \Iterator, \ArrayAccess {
if (is_array($current)) {
$current =& $current[$key];
<<<<<<< HEAD
+<<<<<<< HEAD
} else {
$current =& $current->{$key};
=======
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
} elseif (isset($current->{$key})) {
$current =& $current->{$key};
} else {
return $null;
+<<<<<<< HEAD
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
if (is_scalar($current) && $i < $length) {
@@ -321,6 +372,7 @@ class Document extends \lithium\data\Entity implements \Iterator, \ArrayAccess {
}
if ($model = $this->_model) {
<<<<<<< HEAD
+<<<<<<< HEAD
$pathKey = $this->_pathKey;
$options = compact('pathKey') + array('first' => true);
$value = $model::connection()->cast($model, array($name => $value), $options);
@@ -335,6 +387,14 @@ class Document extends \lithium\data\Entity implements \Iterator, \ArrayAccess {
$this->_updated[$name] = $value;
unset($this->_increment[$name], $this->_removed[$name]);
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ $pathKey = $this->_pathKey;
+ $options = compact('pathKey') + array('first' => true);
+ $value = $model::connection()->cast($this, array($name => $value), $options);
+ }
+ $this->_updated[$name] = $value;
+ unset($this->_increment[$name], $this->_removed[$name]);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
protected function _setNested($name, $value) {
@@ -346,9 +406,12 @@ class Document extends \lithium\data\Entity implements \Iterator, \ArrayAccess {
$key = $path[$i];
<<<<<<< HEAD
+<<<<<<< HEAD
if ($next === null && ($model = $this->_model)) {
$next = $current->_data[$key] = $model::connection()->item($model);
=======
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
if (is_array($current) && isset($current[$key])) {
$next =& $current[$key];
} elseif (isset($current->{$key})) {
@@ -356,6 +419,7 @@ class Document extends \lithium\data\Entity implements \Iterator, \ArrayAccess {
} else {
unset($next);
$next = null;
+<<<<<<< HEAD
}
if ($next === null && ($model = $this->_model)) {
@@ -370,12 +434,25 @@ class Document extends \lithium\data\Entity implements \Iterator, \ArrayAccess {
$current->__set(end($path), $value);
}
<<<<<<< HEAD
+=======
+ }
+
+ if ($next === null && ($model = $this->_model)) {
+ $current->__set($key, $model::connection()->item($model));
+ $next =& $current->{$key};
+ }
+ $current =& $next;
+ }
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
if (is_object($current)) {
$current->__set(end($path), $value);
}
+<<<<<<< HEAD
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
/**
@@ -404,6 +481,10 @@ class Document extends \lithium\data\Entity implements \Iterator, \ArrayAccess {
*/
public function __unset($name) {
$this->_removed[$name] = true;
+<<<<<<< HEAD
+=======
+ unset($this->_updated[$name]);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
/**
@@ -499,9 +580,12 @@ class Document extends \lithium\data\Entity implements \Iterator, \ArrayAccess {
/**
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
=======
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
* Adds conversions checks to ensure certain class types and embedded values are properly cast.
*
* @param string $format Currently only `array` is supported.
@@ -510,6 +594,7 @@ class Document extends \lithium\data\Entity implements \Iterator, \ArrayAccess {
*/
public function to($format, array $options = array()) {
<<<<<<< HEAD
+<<<<<<< HEAD
$defaults = array('handlers' => array('MongoId' => function($value) {
return (string) $value;
}));
@@ -518,6 +603,8 @@ class Document extends \lithium\data\Entity implements \Iterator, \ArrayAccess {
$options += $defaults;
return Collection::toArray($this->_data, $options);
=======
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$defaults = array('handlers' => array(
'MongoId' => function($value) { return (string) $value; },
'MongoDate' => function($value) { return $value->sec; }
@@ -527,16 +614,22 @@ class Document extends \lithium\data\Entity implements \Iterator, \ArrayAccess {
$options += $defaults;
$data = array_merge($this->_data, $this->_updated);
return Collection::toArray(array_diff_key($data, $this->_removed), $options);
+<<<<<<< HEAD
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
return parent::to($format, $options);
}
/**
<<<<<<< HEAD
+<<<<<<< HEAD
>>>>>>> 25a362f706960b2becbf88e91cffc1b1638b7890
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
* Returns the next `Document` in the set, and advances the object's internal pointer. If the
* end of the set is reached, a new document will be fetched from the data source connection
* handle (`$_handle`). If no more records can be fetched, returns `null`.
@@ -563,6 +656,7 @@ class Document extends \lithium\data\Entity implements \Iterator, \ArrayAccess {
*/
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
public function data($field = null) {
if ($field) {
return isset($this->_data[$field]) ? $this->_data[$field] : null;
@@ -583,6 +677,12 @@ class Document extends \lithium\data\Entity implements \Iterator, \ArrayAccess {
if ($name) {
return parent::data($name);
}
+=======
+ public function data($name = null) {
+ if ($name) {
+ return parent::data($name);
+ }
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$map = function($rel) { return $rel->data(); };
return $this->to('array') + array_map($map, $this->_relationships);
}
@@ -595,9 +695,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.
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
* @throws UnexpectedValueException Throws an exception when `$field` is set to a non-numeric
* type.
*/
@@ -608,10 +714,16 @@ 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.");
}
$this->_data[$field] += $value;
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ throw new UnexpectedValueException("Field `{$field}` cannot be incremented.");
+ }
+ $this->_data[$field] += $value;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
}
diff --git a/libraries/lithium/data/model/Query.php b/libraries/lithium/data/model/Query.php
index c976843..c456122 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);
+ }
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
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
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
* @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];
+ }
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
if ($name && !$join) {
$join = $name;
$name = null;
}
if ($join) {
+<<<<<<< HEAD
+=======
+ $join = is_array($join) ? $this->_instance(get_class($this), $join) : $join;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$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;
<<<<<<< HEAD
@@ -424,6 +449,18 @@ class Query extends \lithium\core\Object {
return $results;
}
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ }
+ 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;
+ }
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$created = array('fields', 'values');
if (is_array($results['fields']) && array_keys($results['fields']) == $created) {
@@ -432,6 +469,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;
+ }
+
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
public function schema($field = null) {
if (is_array($field)) {
$this->_config['schema'] = $field;
@@ -509,7 +575,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/model/Relationship.php b/libraries/lithium/data/model/Relationship.php
index 9d163b9..f559842 100644
--- a/libraries/lithium/data/model/Relationship.php
+++ b/libraries/lithium/data/model/Relationship.php
@@ -11,9 +11,13 @@ namespace lithium\data\model;
use lithium\core\Libraries;
use lithium\util\Inflector;
<<<<<<< HEAD
+<<<<<<< HEAD
=======
use lithium\core\ClassNotFoundException;
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+use lithium\core\ClassNotFoundException;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
/**
* The `Relationship` class encapsulates the data and functionality necessary to link two model
diff --git a/libraries/lithium/data/source/Database.php b/libraries/lithium/data/source/Database.php
index e940bb1..7a0340a 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}"
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
);
/**
@@ -249,10 +253,14 @@ abstract class Database extends \lithium\data\Source {
*/
public function read($query, array $options = array()) {
<<<<<<< HEAD
+<<<<<<< HEAD
$defaults = array('return' => 'item', 'schema' => array());
=======
$defaults = array('return' => is_string($query) ? 'array' : 'item', 'schema' => array());
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ $defaults = array('return' => is_string($query) ? 'array' : 'item', 'schema' => array());
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$options += $defaults;
return $this->_filter(__METHOD__, compact('query', 'options'), function($self, $params) {
@@ -277,8 +285,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);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
$records[] = array_combine($columns, $data);
}
@@ -394,7 +407,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)));
@@ -424,9 +437,13 @@ abstract class Database extends \lithium\data\Source {
$namespace = preg_replace('/\w+$/', '', $model);
$relations = $model ? $model::relations() : array();
<<<<<<< HEAD
+<<<<<<< HEAD
=======
$schema = $model::schema();
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ $schema = $model::schema();
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
foreach ($fields as $scope => $field) {
switch (true) {
@@ -676,10 +693,14 @@ abstract class Database extends \lithium\data\Source {
}
<<<<<<< HEAD
+<<<<<<< HEAD
public function cast($model, array $data, array $options = array()) {
=======
public function cast($entity, array $data, array $options = array()) {
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ public function cast($entity, array $data, array $options = array()) {
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
return $data;
}
diff --git a/libraries/lithium/data/source/MongoDb.php b/libraries/lithium/data/source/MongoDb.php
index 8e6683d..ccb466b 100644
--- a/libraries/lithium/data/source/MongoDb.php
+++ b/libraries/lithium/data/source/MongoDb.php
@@ -64,19 +64,25 @@ class MongoDb extends \lithium\data\Source {
*/
protected $_classes = array(
<<<<<<< HEAD
+<<<<<<< HEAD
'entity' => 'lithium\data\entity\Document',
'array' => 'lithium\data\collection\DocumentArray',
'set' => 'lithium\data\collection\DocumentSet',
'result' => 'lithium\data\source\mongo_db\Result',
'relationship' => 'lithium\data\model\Relationship'
=======
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
'entity' => 'lithium\data\entity\Document',
'array' => 'lithium\data\collection\DocumentArray',
'set' => 'lithium\data\collection\DocumentSet',
'result' => 'lithium\data\source\mongo_db\Result',
'exporter' => 'lithium\data\source\mongo_db\Exporter',
'relationship' => 'lithium\data\model\Relationship',
+<<<<<<< HEAD
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
);
/**
@@ -101,6 +107,7 @@ class MongoDb extends \lithium\data\Source {
* A closure or anonymous function which receives an instance of this class, a collection name
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
* and associated meta information, and returns an array defining the schema for that model,
* where the keys are field names, and the values are arrays defining the type information for
* the field. At a minimum, type arrays must contain a `'type'` key.
@@ -108,6 +115,8 @@ class MongoDb extends \lithium\data\Source {
=======
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
* and associated meta information, and returns an array defining the schema for an associated
* model, where the keys are field names, and the values are arrays defining the type
* information for each field. At a minimum, type arrays must contain a `'type'` key. For more
@@ -116,9 +125,12 @@ class MongoDb extends \lithium\data\Source {
*
* @see lithium\data\Model::$_schema
<<<<<<< HEAD
+<<<<<<< HEAD
>>>>>>> 25a362f706960b2becbf88e91cffc1b1638b7890
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
* @var Closure
*/
protected $_schema = null;
@@ -138,6 +150,7 @@ class MongoDb extends \lithium\data\Source {
*/
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
protected $_autoConfig = array('schema', 'handlers');
=======
protected $_autoConfig = array('schema', 'handlers', 'classes' => 'merge');
@@ -145,6 +158,9 @@ class MongoDb extends \lithium\data\Source {
=======
protected $_autoConfig = array('schema', 'handlers', 'classes' => 'merge');
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ protected $_autoConfig = array('schema', 'handlers', 'classes' => 'merge');
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
/**
* Instantiates the MongoDB adapter with the default connection information.
@@ -167,6 +183,7 @@ class MongoDb extends \lithium\data\Source {
* collections. Defaults to `'fs'`.
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
=======
* - `'replicaSet'` _boolean_: See the documentation for `Mongo::__construct()`. Defaults
* to `false`.
@@ -175,6 +192,10 @@ class MongoDb extends \lithium\data\Source {
* - `'replicaSet'` _boolean_: See the documentation for `Mongo::__construct()`. Defaults
* to `false`.
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ * - `'replicaSet'` _boolean_: See the documentation for `Mongo::__construct()`. Defaults
+ * to `false`.
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
*
* Typically, these parameters are set in `Connections::add()`, when adding the adapter to the
* list of active connections.
@@ -208,22 +229,33 @@ class MongoDb extends \lithium\data\Source {
},
'date' => function($v) {
<<<<<<< HEAD
+<<<<<<< HEAD
return new MongoDate(is_numeric($v) ? intval($v) : strtotime($v));
=======
$v = is_numeric($v) ? intval($v) : strtotime($v);
return (time() == $v) ? new MongoDate() : new MongoDate($v);
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ $v = is_numeric($v) ? intval($v) : strtotime($v);
+ return (time() == $v) ? new MongoDate() : new MongoDate($v);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
},
'regex' => function($v) { return new MongoRegex($v); },
'integer' => function($v) { return (integer) $v; },
'float' => function($v) { return (float) $v; },
<<<<<<< HEAD
+<<<<<<< HEAD
'boolean' => function($v) { return (boolean) $v; }
=======
'boolean' => function($v) { return (boolean) $v; },
'code' => function($v) { return new MongoCode($v); },
'binary' => function($v) { return new MongoBinData($v); },
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ 'boolean' => function($v) { return (boolean) $v; },
+ 'code' => function($v) { return new MongoCode($v); },
+ 'binary' => function($v) { return new MongoBinData($v); },
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
);
}
@@ -422,6 +454,7 @@ class MongoDb extends \lithium\data\Source {
<<<<<<< HEAD
$data = array();
+<<<<<<< HEAD
$params = $query->export($self);
=======
$data = $_exp::get('create', $query->entity()->export());
@@ -444,11 +477,27 @@ class MongoDb extends \lithium\data\Source {
$result = $self->connection->{$source}->insert($data['create'], $options);
}
+=======
+ $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'])) {
+ $result = array('ok' => true);
+ $data['create']['_id'] = $self->invokeMethod('_saveFile', array($data['create']));
+ } else {
+ $result = $self->connection->{$source}->insert($data['create'], $options);
+ }
+
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
if ($result === true || isset($result['ok']) && (boolean) $result['ok'] === true) {
if ($query->entity()) {
$query->entity()->update($data['create']['_id']);
}
+<<<<<<< HEAD
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
return true;
}
return false;
@@ -458,9 +507,12 @@ class MongoDb extends \lithium\data\Source {
protected function _saveFile($data) {
$uploadKeys = array('name', 'type', 'tmp_name', 'error', 'size');
<<<<<<< HEAD
+<<<<<<< HEAD
$data = $params['data'];
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$grid = $this->connection->getGridFS();
$file = null;
$method = null;
@@ -514,7 +566,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']) {
@@ -569,7 +620,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')));
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$source = $args['source'];
$data = $args['data'];
@@ -577,17 +632,28 @@ class MongoDb extends \lithium\data\Source {
$data = $_exp::get('update', $data);
}
<<<<<<< HEAD
+<<<<<<< HEAD
unset($args['data']['_id']);
$update = ($options['atomic']) ? array('$set' => $args['data']) : $args['data'];
=======
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
if ($source == "{$_config['gridPrefix']}.files" && isset($data['update']['file'])) {
$args['data']['_id'] = $self->invokeMethod('_saveFile', array($data['update']));
}
$update = $query->entity() ? $_exp::toCommand($data) : $data;
+<<<<<<< HEAD
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
if ($self->connection->{$source}->update($args['conditions'], $update)) {
+=======
+
+ if ($options['multiple'] && !preg_grep('/^\$/', array_keys($update))) {
+ $update = array('$set' => $update);
+ }
+ if ($self->connection->{$source}->update($args['conditions'], $update, $options)) {
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$query->entity() ? $query->entity()->update() : null;
return true;
}
@@ -612,6 +678,7 @@ class MongoDb extends \lithium\data\Source {
$options = $params['options'];
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
$params = $query->export($self);
$conditions = $params['conditions'];
@@ -624,6 +691,10 @@ class MongoDb extends \lithium\data\Source {
$args = $query->export($self, array('keys' => array('source', 'conditions')));
return $self->connection->{$args['source']}->remove($args['conditions'], $options);
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ $args = $query->export($self, array('keys' => array('source', 'conditions')));
+ return $self->connection->{$args['source']}->remove($args['conditions'], $options);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
});
}
@@ -710,6 +781,7 @@ class MongoDb extends \lithium\data\Source {
if (!$conditions) {
return array();
<<<<<<< HEAD
+<<<<<<< HEAD
}
if ($code = $this->_isMongoCode($conditions)) {
return $code;
@@ -727,6 +799,8 @@ class MongoDb extends \lithium\data\Source {
}
>>>>>>> 25a362f706960b2becbf88e91cffc1b1638b7890
=======
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
if ($code = $this->_isMongoCode($conditions)) {
return $code;
@@ -735,7 +809,10 @@ class MongoDb extends \lithium\data\Source {
$model = $context->model();
$schema = $context->schema();
}
+<<<<<<< HEAD
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
return $this->_conditions($conditions, $model, $schema, $context);
}
@@ -751,6 +828,7 @@ class MongoDb extends \lithium\data\Source {
$conditions['$or'] = $value;
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
continue;
}
if (is_object($value)) {
@@ -777,11 +855,21 @@ class MongoDb extends \lithium\data\Source {
if (is_object($value)) {
continue;
}
+=======
+ continue;
+ }
+ if (is_object($value)) {
+ continue;
+ }
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
if (!is_array($value)) {
$conditions[$key] = $this->cast(null, array($key => $value), $castOpts);
continue;
}
+<<<<<<< HEAD
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$current = key($value);
$isOpArray = (isset($this->_operators[$current]) || $current[0] === '$');
@@ -799,6 +887,7 @@ class MongoDb extends \lithium\data\Source {
}
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
}
$conditions[$key] = $result;
=======
@@ -811,6 +900,11 @@ class MongoDb extends \lithium\data\Source {
}
$conditions[$key] = $operations;
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ $operations += $this->_operator($model, $key, $op, $val, $schema);
+ }
+ $conditions[$key] = $operations;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
return $conditions;
}
@@ -901,6 +995,7 @@ class MongoDb extends \lithium\data\Source {
}
<<<<<<< HEAD
+<<<<<<< HEAD
public function cast($model, array $data, array $options = array()) {
$defaults = array('schema' => null, 'first' => false, 'pathKey' => null, 'arrays' => true);
$options += $defaults;
@@ -966,6 +1061,22 @@ class MongoDb extends \lithium\data\Source {
$entity = null;
$options['schema'] = $options['schema'] ?: $model::schema();
}
+=======
+ public function cast($entity, array $data, array $options = array()) {
+ $defaults = array('schema' => null, 'first' => false, 'pathKey' => null);
+ $options += $defaults;
+ $model = null;
+
+ if (!$data) {
+ return $data;
+ }
+
+ if (is_string($entity)) {
+ $model = $entity;
+ $entity = null;
+ $options['schema'] = $options['schema'] ?: $model::schema();
+ }
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
if ($entity && !$options['schema']) {
$options['schema'] = $entity->schema();
}
@@ -978,7 +1089,10 @@ class MongoDb extends \lithium\data\Source {
$options += compact('model') + array('handlers' => $this->_handlers);
return parent::cast($entity, $exporter::cast($data, $schema, $this, $options), $options);
+<<<<<<< HEAD
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
protected function _checkConnection() {
diff --git a/libraries/lithium/data/source/database/adapter/MySql.php b/libraries/lithium/data/source/database/adapter/MySql.php
index 8533658..ca960ce 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
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
* @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..6f24e31 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);
@@ -135,7 +136,7 @@ class Sqlite3 extends \lithium\data\source\Database {
$fields = array();
foreach ($columns as $column) {
- list($type, $length) = explode('(', $column['type']);
+ list($type, $length) = explode('(', $column['type']) + array('', '');
$length = trim($length, ')');
$fields[$column['name']] = array(
'type' => $type,
@@ -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..b5e29d9 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);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
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);
+ }
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
}
diff --git a/libraries/lithium/data/source/http/adapter/CouchDb.php b/libraries/lithium/data/source/http/adapter/CouchDb.php
index f4413e1..6034e7d 100644
--- a/libraries/lithium/data/source/http/adapter/CouchDb.php
+++ b/libraries/lithium/data/source/http/adapter/CouchDb.php
@@ -44,11 +44,16 @@ class CouchDb extends \lithium\data\source\Http {
'service' => 'lithium\net\http\Service',
'entity' => 'lithium\data\entity\Document',
<<<<<<< HEAD
+<<<<<<< HEAD
'set' => 'lithium\data\collection\DocumentSet',
=======
'array' => 'lithium\data\collection\DocumentArray',
'set' => 'lithium\data\collection\DocumentSet'
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ 'set' => 'lithium\data\collection\DocumentSet',
+ 'array' => 'lithium\data\collection\DocumentArray',
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
);
protected $_handlers = array();
@@ -104,6 +109,7 @@ class CouchDb extends \lithium\data\source\Http {
'schema' => array(
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
'id' => array('type' => 'integer'),
=======
'id' => array('type' => 'string'),
@@ -111,6 +117,9 @@ class CouchDb extends \lithium\data\source\Http {
=======
'id' => array('type' => 'string'),
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ 'id' => array('type' => 'string'),
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
'rev' => array('type' => 'string')
)
);
@@ -165,7 +174,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.");
}
}
@@ -240,6 +249,7 @@ class CouchDb extends \lithium\data\source\Http {
$conditions['include_docs'] = 'true';
}
<<<<<<< HEAD
+<<<<<<< HEAD
$args = (array) $conditions + (array) $limit + (array) $order;
$result = json_decode($conn->get("{$config['database']}/{$_path}", $args), true);
$data = array();
@@ -273,6 +283,26 @@ class CouchDb extends \lithium\data\source\Http {
$stats += array('total_rows' => null, 'offset' => null);
$opts = compact('stats') + array('class' => 'set', 'exists' => true);
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ $path = "{$config['database']}/{$_path}";
+
+ $args = (array) $conditions + (array) $limit + (array) $order;
+ $result = (array) json_decode($conn->get($path, $args), true);
+
+ $data = $stats = array();
+
+ if (isset($result['_id'])) {
+ $data = array($result);
+ } elseif (isset($result['rows'])) {
+ $data = array_map(function($row) { return $row['value']; }, $result['rows']);
+
+ unset($result['rows']);
+ $stats = $result;
+ }
+
+ $stats += array('total_rows' => null, 'offset' => null);
+ $opts = compact('stats') + array('class' => 'set', 'exists' => true);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
return $self->item($query->model(), $data, $opts);
});
}
@@ -530,6 +560,7 @@ class CouchDb extends \lithium\data\source\Http {
}
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
/**
* Handle the result from read
@@ -549,6 +580,8 @@ class CouchDb extends \lithium\data\source\Http {
>>>>>>> 25a362f706960b2becbf88e91cffc1b1638b7890
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
?>
\ No newline at end of file
diff --git a/libraries/lithium/data/source/mongo_db/Exporter.php b/libraries/lithium/data/source/mongo_db/Exporter.php
index d617610..c75c7d0 100644
--- a/libraries/lithium/data/source/mongo_db/Exporter.php
+++ b/libraries/lithium/data/source/mongo_db/Exporter.php
@@ -47,11 +47,21 @@ class Exporter extends \lithium\core\StaticObject {
$field = (isset($schema[$path]) ? $schema[$path] : array());
$field += array('type' => null, 'array' => null);
$type = isset($typeMap[$field['type']]) ? $typeMap[$field['type']] : $field['type'];
+<<<<<<< HEAD
$isObject = ($type == 'object');
$isArray = (is_array($value) && $field['array'] !== false && !$isObject);
if (isset($options['handlers'][$type]) && $handler = $options['handlers'][$type]) {
$value = $isArray ? array_map($handler, $value) : $handler($value);
+=======
+
+ $isObject = ($type == 'object');
+ $isArray = (is_array($value) && $field['array'] !== false && !$isObject);
+ $isArray = $field['array'] || $isArray;
+
+ if (isset($options['handlers'][$type]) && $handler = $options['handlers'][$type]) {
+ $value = $isArray ? array_map($handler, (array) $value) : $handler($value);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
if (!$options['arrays']) {
$data[$key] = $value;
@@ -63,8 +73,15 @@ class Exporter extends \lithium\core\StaticObject {
$data[$key] = $value;
continue;
}
+<<<<<<< HEAD
+ if ($field['array']) {
+ $opts = array('class' => 'array') + $options;
+=======
+
if ($field['array']) {
$opts = array('class' => 'array') + $options;
+ $value = ($value === null) ? array() : $value;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$value = is_array($value) ? $value : array($value);
} elseif (is_array($value)) {
$arrayType = !$isObject && (array_keys($value) === range(0, count($value) - 1));
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/g11n/resources/php/de/message/default.php b/libraries/lithium/g11n/resources/php/de/message/default.php
new file mode 100644
index 0000000..8617d0f
--- /dev/null
+++ b/libraries/lithium/g11n/resources/php/de/message/default.php
@@ -0,0 +1,21 @@
+<?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
+ */
+
+/**
+ * Message data for `de`.
+ *
+ * Plural rule and forms derived from the GNU gettext documentation.
+ *
+ * @link http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms
+ */
+return array(
+ 'pluralForms' => 2,
+ 'pluralRule' => function ($n) { return $n == 1 ? 0 : 1; }
+);
+
+?>
\ No newline at end of file
diff --git a/libraries/lithium/g11n/resources/php/fr/message/default.php b/libraries/lithium/g11n/resources/php/fr/message/default.php
new file mode 100644
index 0000000..18212ca
--- /dev/null
+++ b/libraries/lithium/g11n/resources/php/fr/message/default.php
@@ -0,0 +1,21 @@
+<?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
+ */
+
+/**
+ * Message data for `fr`.
+ *
+ * Plural rule and forms derived from the GNU gettext documentation.
+ *
+ * @link http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms
+ */
+return array(
+ 'pluralForms' => 2,
+ 'pluralRule' => function ($n) { return $n == 1 ? 0 : 1; }
+);
+
+?>
\ No newline at end of file
diff --git a/libraries/lithium/net/http/Media.php b/libraries/lithium/net/http/Media.php
index 9d27ff1..22c5241 100755
--- a/libraries/lithium/net/http/Media.php
+++ b/libraries/lithium/net/http/Media.php
@@ -59,6 +59,14 @@ class Media extends \lithium\core\StaticObject {
protected static $_assets = array();
/**
+ * Placeholder for class dependencies. This class' dependencies (i.e. templating classes) are
+ * typically specified through other configuration.
+ *
+ * @var array
+ */
+ protected static $_classes = array();
+
+ /**
* Returns the list of registered media types. New types can be set with the `type()` method.
*
* @return array Returns an array of media type extensions or short-names, which comprise the
@@ -222,16 +230,22 @@ class Media extends \lithium\core\StaticObject {
return;
}
<<<<<<< HEAD
+<<<<<<< HEAD
if (is_array($content) && isset($content['alias'])) {
$type = $content['alias'];
$content = static::_types($type);
=======
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
if (strpos($type, '/')) {
return $content;
}
if (is_array($content) && isset($content['alias'])) {
return static::type($content['alias']);
+<<<<<<< HEAD
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
return compact('content') + array('options' => static::_handlers($type));
}
@@ -469,8 +483,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'`.
@@ -557,6 +571,7 @@ class Media extends \lithium\core\StaticObject {
$result = null;
$type = $options['type'];
+<<<<<<< HEAD
if (!isset($handlers[$type])) {
throw new MediaException("Unhandled media type '{$type}'");
@@ -564,45 +579,127 @@ class Media extends \lithium\core\StaticObject {
$handler = $options + $handlers[$type] + $defaults;
$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;
if (isset($types[$type])) {
- $response->headers('Content-type', current((array) $types[$type]));
+ $header = current((array) $types[$type]);
+ $header .= $response->encoding ? "; charset={$response->encoding}" : '';
+ $response->headers('Content-type', $header);
}
$response->body($self::invokeMethod('_handle', array($handler, $data, $response)));
});
}
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
+
+ /**
+ * Configures a template object instance, based on a media handler configuration.
+ *
+ * @see lithium\net\http\Media::type()
+ * @see lithium\template\View::render()
+ * @see lithium\action\Response
+ * @param mixed $handler Either a string specifying the name of a media type for which a handler
+ * is defined, or an array representing a handler configuration. For more on types
+ * and type handlers, see the `type()` method.
+ * @param mixed $data The data to be rendered. Usually an array.
+ * @param object $response The `Response` object associated with this dispatch cycle. Usually an
+ * instance of `lithium\action\Response`.
+ * @param array $options Any options that will be passed to the `render()` method of the
+ * templating object.
+ * @return object Returns an instance of a templating object, usually `lithium\template\View`.
+ */
+ public static function view($handler, $data, &$response = null, array $options = array()) {
+ $params = array('response' => &$response) + compact('handler', 'data', 'options');
+
+ return static::_filter(__FUNCTION__, $params, function($self, $params) {
+ $data = $params['data'];
+ $options = $params['options'];
+ $handler = $params['handler'];
+ $response =& $params['response'];
+
+ if (!is_array($handler)) {
+ $handler = $self::invokeMethod('_handlers', array($handler));
+ }
+<<<<<<< HEAD
+ $response->body($self::invokeMethod('_handle', array($handler, $data, $response)));
+=======
+ $class = $handler['view'];
+ unset($handler['view']);
+
+ $config = $handler + array('response' => &$response);
+ return $self::invokeMethod('_instance', array($class, $config));
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
+ });
+ }
/**
* For media types registered in `$_handlers` which include an `'encode'` setting, encodes data
* according to the specified media type.
*
- * @param string $type Specifies the media type into which `$data` will be encoded. This media
- * type must have an `'encode'` setting specified in `Media::$_handlers`.
+ * @see lithium\net\http\Media::type()
+ * @param mixed $handler Specifies the media type into which `$data` will be encoded. This media
+ * type must have an `'encode'` setting specified in `Media::$_handlers`.
+ * Alternatively, `$type` can be an array, in which case it is used as the type
+ * handler configuration. See the `type()` method for information on adding type
+ * handlers, and the available configuration keys.
* @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
+ * @return mixed Returns the result of `$data`, encoded with the encoding configuration
+ * specified by `$type`, the result of which is usually a string.
+ * @filter
*/
+<<<<<<< HEAD
public static function encode($type, $data, &$response = null) {
$handler = is_array($type) ? $type : static::_handlers($type);
+=======
+ public static function encode($handler, $data, &$response = null) {
+ $params = array('response' => &$response) + compact('handler', 'data');
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
- if (!$handler || !isset($handler['encode'])) {
- return null;
- }
+ return static::_filter(__FUNCTION__, $params, function($self, $params) {
+ $data = $params['data'];
+ $handler = $params['handler'];
+ $response =& $params['response'];
- $cast = function($data) {
- if (is_object($data)) {
- return method_exists($data, 'to') ? $data->to('array') : get_object_vars($data);
+ if (!is_array($handler)) {
+ $handler = $self::invokeMethod('_handlers', array($handler));
}
- return $data;
- };
+<<<<<<< HEAD
if (!isset($handler['cast']) || $handler['cast']) {
$data = is_object($data) ? $cast($data) : $data;
$data = is_array($data) ? array_map($cast, $data) : $data;
}
$method = $handler['encode'];
return is_string($method) ? $method($data) : $method($data, $handler, $response);
+=======
+ if (!$handler || !isset($handler['encode'])) {
+ return null;
+ }
+
+ $cast = function($data) {
+ if (!is_object($data)) {
+ return $data;
+ }
+ return method_exists($data, 'to') ? $data->to('array') : get_object_vars($data);
+ };
+
+ if (!isset($handler['cast']) || $handler['cast']) {
+ $data = is_object($data) ? $cast($data) : $data;
+ $data = is_array($data) ? array_map($cast, $data) : $data;
+ }
+ $method = $handler['encode'];
+ return is_string($method) ? $method($data) : $method($data, $handler, $response);
+ });
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
/**
@@ -649,6 +746,10 @@ class Media extends \lithium\core\StaticObject {
*/
protected static function _handle($handler, $data, &$response) {
$params = array('response' => &$response) + compact('handler', 'data');
+<<<<<<< HEAD
+=======
+
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
return static::_filter(__FUNCTION__, $params, function($self, $params) {
$response = $params['response'];
$handler = $params['handler'];
@@ -663,15 +764,21 @@ class Media extends \lithium\core\StaticObject {
switch (true) {
case $handler['encode']:
return $self::encode($handler, $data, $response);
+<<<<<<< HEAD
case class_exists($handler['view']):
$view = new $handler['view']($handler + array('response' => &$response));
return $view->render('all', $data, $options);
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
case ($handler['template'] === false) && is_string($data):
return $data;
+ case $handler['view']:
+ unset($options['view']);
+ $instance = $self::view($handler, $data, $response, $options);
+ return $instance->render('all', (array) $data, $options);
default:
throw new MediaException("Could not interpret type settings for handler.");
}
- return $result;
});
}
@@ -736,6 +843,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',
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
)
),
'html' => array(),
diff --git a/libraries/lithium/net/http/Response.php b/libraries/lithium/net/http/Response.php
index 8898dd9..4d40b4a 100644
--- a/libraries/lithium/net/http/Response.php
+++ b/libraries/lithium/net/http/Response.php
@@ -106,7 +106,7 @@ class Response extends \lithium\net\http\Message {
}
if (isset($this->headers['Content-Type'])) {
- preg_match('/^(.*?);charset=(.+)/i', $this->headers['Content-Type'], $match);
+ preg_match('/^(.*?);\s*?charset=(.+)/i', $this->headers['Content-Type'], $match);
if ($match) {
$this->type = trim($match[1]);
diff --git a/libraries/lithium/net/http/Router.php b/libraries/lithium/net/http/Router.php
index fa36e76..d642864 100644
--- a/libraries/lithium/net/http/Router.php
+++ b/libraries/lithium/net/http/Router.php
@@ -12,12 +12,16 @@ use lithium\util\Inflector;
use lithium\util\Collection;
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
=======
use lithium\net\http\RoutingException;
>>>>>>> 25a362f706960b2becbf88e91cffc1b1638b7890
=======
use lithium\net\http\RoutingException;
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+use lithium\net\http\RoutingException;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
/**
* The two primary responsibilities of the `Router` class are to generate URLs from parameter lists,
@@ -196,12 +200,12 @@ class Router extends \lithium\core\StaticObject {
* prefixed with the base URL of the application.
*/
public static function match($url = array(), $context = null, array $options = array()) {
- if (is_string($path = $url)) {
- if (strpos($path, '#') === 0 || strpos($path, 'mailto') === 0 || strpos($path, '://')) {
- return $path;
+ if (is_string($url)) {
+ if (strpos($url, '#') === 0 || strpos($url, 'mailto') === 0 || strpos($url, '://')) {
+ return $url;
}
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))) {
@@ -224,7 +228,14 @@ class Router extends \lithium\core\StaticObject {
$path = ($options) ? static::_prefix($path, $context, $options) : $path;
return $path ?: '/';
}
+<<<<<<< HEAD
throw new RoutingException("No parameter match found for routes.");
+=======
+ $match = array("\n", 'array (', ',)', '=> NULL', '( \'', ', ');
+ $replace = array('', '(', ')', '=> null', '(\'', ', ');
+ $url = str_replace($match, $replace, var_export($url, true));
+ throw new RoutingException("No parameter match found for URL `{$url}`.");
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
/**
diff --git a/libraries/lithium/net/http/Service.php b/libraries/lithium/net/http/Service.php
index 376b6b4..022b0f6 100644
--- a/libraries/lithium/net/http/Service.php
+++ b/libraries/lithium/net/http/Service.php
@@ -79,9 +79,12 @@ class Service extends \lithium\core\Object {
parent::__construct($config + $defaults);
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
=======
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
/**
@@ -93,9 +96,12 @@ class Service extends \lithium\core\Object {
public function head(array $options = array()) {
return $this->send(__FUNCTION__, null, array(), $options);
<<<<<<< HEAD
+<<<<<<< HEAD
>>>>>>> 25a362f706960b2becbf88e91cffc1b1638b7890
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
/**
@@ -187,10 +193,14 @@ class Service extends \lithium\core\Object {
$conn->close();
$this->last = (object) compact('request', 'response');
<<<<<<< HEAD
+<<<<<<< HEAD
return ($options['return'] == 'body') ? $response->body() : $response;
=======
return ($options['return'] == 'body' && $response) ? $response->body() : $response;
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ return ($options['return'] == 'body' && $response) ? $response->body() : $response;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
/**
@@ -208,6 +218,7 @@ class Service extends \lithium\core\Object {
protected function _request($method, $path, $data, $options) {
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
$defaults = array('type' => 'form', 'scheme' => $this->_config['scheme']);
$options += $defaults;
@@ -215,14 +226,19 @@ class Service extends \lithium\core\Object {
=======
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$defaults = array('type' => 'form');
$options += $defaults + $this->_config;
$request = $this->_instance('request', $options);
<<<<<<< HEAD
+<<<<<<< HEAD
>>>>>>> 25a362f706960b2becbf88e91cffc1b1638b7890
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$request->path = str_replace('//', '/', "{$request->path}{$path}");
$request->method = $method = strtoupper($method);
diff --git a/libraries/lithium/net/socket/Stream.php b/libraries/lithium/net/socket/Stream.php
index 9bd52f4..467a241 100644
--- a/libraries/lithium/net/socket/Stream.php
+++ b/libraries/lithium/net/socket/Stream.php
@@ -30,11 +30,11 @@ class Stream extends \lithium\net\Socket {
public function open() {
$config = $this->_config;
- if (empty($config['scheme']) || empty($config['host'])) {
+ if (!$config['scheme'] || !$config['host']) {
return false;
}
$scheme = ($config['scheme'] !== 'udp') ? 'tcp' : 'udp';
- $port = ($config['port']) ?: 80;
+ $port = $config['port'] ?: 80;
$host = "{$scheme}://{$config['host']}:{$port}";
$flags = STREAM_CLIENT_CONNECT;
@@ -45,7 +45,7 @@ class Stream extends \lithium\net\Socket {
$host, $errorCode, $errorMessage, $config['timeout'], $flags
);
- if (!empty($errorCode) || !empty($errorMessage)) {
+ if ($errorCode || $errorMessage) {
throw new NetworkException($errorMessage);
}
$this->timeout($config['timeout']);
@@ -53,7 +53,6 @@ class Stream extends \lithium\net\Socket {
if (!empty($config['encoding'])) {
$this->encoding($config['encoding']);
}
-
return $this->_resource;
}
@@ -67,6 +66,7 @@ class Stream extends \lithium\net\Socket {
return true;
}
fclose($this->_resource);
+
if (is_resource($this->_resource)) {
$this->close();
}
@@ -76,13 +76,10 @@ class Stream extends \lithium\net\Socket {
/**
* Determines if the socket resource is at EOF.
*
- * @return boolean True if resource pointer is at EOF, false otherwise.
+ * @return boolean Returns `true` if resource pointer is at its EOF, `false` otherwise.
*/
public function eof() {
- if (!is_resource($this->_resource)) {
- return true;
- }
- return feof($this->_resource);
+ return is_resource($this->_resource) ? feof($this->_resource) : true;
}
/**
@@ -97,9 +94,10 @@ class Stream extends \lithium\net\Socket {
if (!is_resource($this->_resource)) {
return false;
}
- return is_null($length) ? stream_get_contents($this->_resource) : stream_get_contents(
- $this->_resource, $length, $offset
- );
+ if (!$length) {
+ return stream_get_contents($this->_resource);
+ }
+ return stream_get_contents($this->_resource, $length, $offset);
}
/**
@@ -144,14 +142,13 @@ class Stream extends \lithium\net\Socket {
if (!function_exists('stream_encoding')) {
return false;
}
- return is_resource($this->_resource)
- ? stream_encoding($this->_resource, $charset) : false;
+ return is_resource($this->_resource) ? stream_encoding($this->_resource, $charset) : false;
}
/**
* Aggregates read and write methods into a coherent request response
*
- * @param mixed $message array or object like `\lithium\net\http\Request`
+ * @param mixed $message array or object like `lithium\net\http\Request`
* @param array $options
* - path: path for the current request
* - classes: array of classes to use
@@ -164,7 +161,7 @@ class Stream extends \lithium\net\Socket {
if ($this->write($message)) {
$body = $this->read();
- $response = new $options['classes']['response'](compact('body'));
+ $response = new $options['response'](compact('body'));
return $response;
}
}
diff --git a/libraries/lithium/readme.wiki b/libraries/lithium/readme.wiki
new file mode 100755
index 0000000..b3e561d
--- /dev/null
+++ b/libraries/lithium/readme.wiki
@@ -0,0 +1,29 @@
+#### You asked for a better framework. Here it is.
+
+Lithium is the fast, flexible and most RAD development framework for PHP 5.3 and up.
+
+##### A framework of firsts
+
+Lithium is the first and only major PHP framework built from the ground up for PHP 5.3+, and the first to break ground into major new technologies, including bridging the gap between relational and non-relational databases through a single, unified API.
+
+##### Promiscuously opinionated
+
+Some frameworks give you a solid set of classes, but little or no default project organization, leaving you to fend for yourself on each project you create, and spend time wiring up framework classes that should just work together. Others provide you with great organizational conventions, but no way to break out of those conventions if you need to, and too often, no way to override or replace core framework classes.
+
+Lithium is the first framework to give you the best of both worlds, without compromising either. In fact, Lithium's API is intentionally designed to allow you to "grow out of" the framework and into your own custom code over the course of your application's lifecycle, if your needs require.
+
+#### Technology
+
+Lithium takes full advantage of the latest PHP 5.3 features, including namespaces, late static binding and closures. Lithium's innovative [method filter system](/docs/lithium/util/collection/Filters) makes extensive use of closures and anonymous functions to allow application developers to "wrap" framework method calls, intercepting parameters before, and return values after.
+
+Lithium also complies with the PHP 5.3 namespacing standard, allowing you to easily integrate other PHP 5.3 standard libraries and frameworks with Lithium applications, and vice-versa.
+
+Lithium integrates the latest storage technologies, including MongoDB, CouchDB and Redis, with plugin support for Cassandra, ElasticSearch and others.
+
+#### Flexibility
+
+Lithium gives you full control over your application, from filters to dynamically modify framework internals, to dynamic dependencies to extend and replace core classes with application or plugin classes, to heavy use of adapter-oriented configurations, to make it seamless to move between different technologies and options.
+
+Every component of the Lithium framework stack is replaceable through the robust plugin architecture. Swap out the default ORM / ODM implementation for [Doctrine 2](http://dev.lithify.me/li3_doctrine/) or [PHP ActiveRecord](http://dev.lithify.me/li3_activerecord). Don't like the templating? Use [ Twig](http://dev.lithify.me/li3_twig), [ Mustache](https://github.com/bobthecow/mustache.php), or roll your own.
+
+If you don't even need to write a full application, build a micro-app in a single file using the routing system, without giving up the maintainability of the framework's structure.
\ No newline at end of file
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/security/auth/adapter/Form.php b/libraries/lithium/security/auth/adapter/Form.php
index a57f503..685dbdf 100644
--- a/libraries/lithium/security/auth/adapter/Form.php
+++ b/libraries/lithium/security/auth/adapter/Form.php
@@ -19,17 +19,17 @@ use lithium\core\Libraries;
* apply any filters as appropriate (see the `'filters'` configuration setting below), and
* query a model class using using the filtered data.
*
- * By default, the adapter uses a model called `User`, and lookup fields called `'username'` and
+ * By default, the adapter uses a model called `Users`, and lookup fields called `'username'` and
* `'password'`. These can be customized by setting the `'model'` and `'fields'` configuration keys,
- * respectively. The `'model'` key accepts either a model name (i.e. `Customer`), or a
- * fully-namespaced path to a model class (i.e. `\app\models\Customer`). The `'fields'` setting
+ * respectively. The `'model'` key accepts either a model name (i.e. `Customers`), or a
+ * fully-namespaced path to a model class (i.e. `app\models\Customers`). The `'fields'` setting
* accepts an array of field names to use when looking up a user. An example configuration,
* including a custom model class and lookup fields might look like the following:
* {{{
* Auth::config(array(
* 'customer' => array(
* 'adapter' => 'Form',
- * 'model' => 'Customer',
+ * 'model' => 'Customers',
* 'fields' => array('email', 'password')
* )
* ));
@@ -44,7 +44,7 @@ use lithium\core\Libraries;
* Auth::config(array(
* 'customer' => array(
* 'adapter' => 'Form',
- * 'model' => 'Customer',
+ * 'model' => 'Customers',
* 'fields' => array('username' => 'login.username', 'password' => 'login.password'),
* 'scope' => array('active' => true)
* )
@@ -76,7 +76,7 @@ class Form extends \lithium\core\Object {
/**
* The name of the model class to query against. This can either be a model name (i.e.
- * `'User'`), or a fully-namespaced class reference (i.e. `'app\models\User'`). When
+ * `'Users'`), or a fully-namespaced class reference (i.e. `'app\models\Users'`). When
* authenticating users, the magic `first()` method is invoked against the model to return the
* first record found when combining the conditions in the `$_scope` property with the
* authentication data yielded from the `Request` object in `Form::check()`. (Note that the
@@ -141,7 +141,7 @@ class Form extends \lithium\core\Object {
* which model method to call, and this method will receive the authentication query. In return,
* the `Form` adapter expects a `Record` object which implements the `data()` method. See the
* constructor for more information on setting this property. Defaults to `'first'`, which
- * calls, for example, `User::first()`.
+ * calls, for example, `Users::first()`.
*
* @see lithium\security\auth\adapter\Form::__construct()
* @see lithium\data\entity\Record::data()
@@ -176,7 +176,7 @@ class Form extends \lithium\core\Object {
*/
public function __construct(array $config = array()) {
$defaults = array(
- 'model' => 'User', 'query' => 'first', 'filters' => array(), 'fields' => array(
+ 'model' => 'Users', 'query' => 'first', 'filters' => array(), 'fields' => array(
'username', 'password'
)
);
@@ -198,7 +198,7 @@ class Form extends \lithium\core\Object {
public function check($credentials, array $options = array()) {
$model = $this->_model;
$query = $this->_query;
- $conditions = $this->_scope + $this->_filters($credentials->data);
+ $conditions = $this->_scope + $this->_filters(array_map('strval', $credentials->data));
$user = $model::$query(compact('conditions'));
return $user ? $user->data() : false;
}
@@ -246,9 +246,10 @@ class Form extends \lithium\core\Object {
foreach ($this->_fields as $key => $field) {
$result[$field] = isset($data[$key]) ? $data[$key] : null;
- if (isset($this->_filters[$key])) {
- $result[$field] = call_user_func($this->_filters[$key], $result[$field]);
+ if (!isset($this->_filters[$key])) {
+ continue;
}
+ $result[$field] = call_user_func($this->_filters[$key], $result[$field]);
}
return isset($this->_filters[0]) ? call_user_func($this->_filters[0], $result) : $result;
}
diff --git a/libraries/lithium/storage/Session.php b/libraries/lithium/storage/Session.php
index 3baa386..8e25256 100644
--- a/libraries/lithium/storage/Session.php
+++ b/libraries/lithium/storage/Session.php
@@ -77,19 +77,6 @@ class Session extends \lithium\core\Adaptable {
}
/**
- * Checks the validity of a previously-started session by running several checks, including
- * comparing the session start time to the expiration time set in the configuration, and any
- * security settings.
- *
- * @todo Implement
- * @param string $name Named session configuration.
- * @return boolean Returns true if the current session is active and valid.
- */
- public static function isValid($name = null) {
-
- }
-
- /**
* Reads a value from a persistent session store.
*
* @param string $key Key to be read
diff --git a/libraries/lithium/storage/cache/adapter/Apc.php b/libraries/lithium/storage/cache/adapter/Apc.php
index 2ba9507..c16917a 100755
--- a/libraries/lithium/storage/cache/adapter/Apc.php
+++ b/libraries/lithium/storage/cache/adapter/Apc.php
@@ -71,6 +71,7 @@ class Apc extends \lithium\core\Object {
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
return function($self, $params, $chain) use ($expiry) {
=======
return function($self, $params) use ($expiry) {
@@ -78,6 +79,9 @@ class Apc extends \lithium\core\Object {
=======
return function($self, $params) use ($expiry) {
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ return function($self, $params) use ($expiry) {
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$cachetime = (is_int($expiry) ? $expiry : strtotime($expiry)) - time();
$key = $params['key'];
diff --git a/libraries/lithium/storage/cache/adapter/File.php b/libraries/lithium/storage/cache/adapter/File.php
index 8660987..1f165ab 100755
--- a/libraries/lithium/storage/cache/adapter/File.php
+++ b/libraries/lithium/storage/cache/adapter/File.php
@@ -11,6 +11,7 @@ namespace lithium\storage\cache\adapter;
use SplFileInfo;
use RecursiveIteratorIterator;
use RecursiveDirectoryIterator;
+use lithium\core\Libraries;
/**
* A minimal file-based cache.
@@ -28,7 +29,7 @@ use RecursiveDirectoryIterator;
* This adapter does *not* allow multi-key operations for any methods.
*
* The path that the cached files will be written to defaults to
- * `LITHIUM_APP_PATH/resources/tmp/cache`, but is user-configurable on cache configuration.
+ * `<app>/resources/tmp/cache`, but is user-configurable on cache configuration.
*
* Note that the cache expiration time is stored within the first few bytes
* of the cached data, and is transparently added and/or removed when values
@@ -45,14 +46,14 @@ class File extends \lithium\core\Object {
* @param array $config Configuration parameters for this cache adapter. These settings are
* indexed by name and queryable through `Cache::config('name')`.
* The defaults are:
- * - 'path' : Path where cached entries live `LITHIUM_APP_PATH . '/resources/tmp/cache'
+ * - 'path' : Path where cached entries live `LITHIUM_APP_PATH . '/resources/tmp/cache'`.
* - 'expiry' : Default expiry time used if none is explicitly set when calling
* `Cache::write()`.
* @return void
*/
public function __construct(array $config = array()) {
$defaults = array(
- 'path' => LITHIUM_APP_PATH . '/resources/tmp/cache',
+ 'path' => Libraries::get(true, 'resources') . '/tmp/cache',
'prefix' => '',
'expiry' => '+1 hour',
);
@@ -76,10 +77,8 @@ class File extends \lithium\core\Object {
$expiry = strtotime($expiry);
$data = "{:expiry:{$expiry}}\n{$params['data']}";
$path = "{$path}/{$params['key']}";
-
return file_put_contents($path, $data);
};
-
}
/**
@@ -109,9 +108,7 @@ class File extends \lithium\core\Object {
return false;
}
return preg_replace('/^\{\:expiry\:\d+\}\\n/', '', $data, 1);
-
};
-
}
/**
@@ -131,7 +128,6 @@ class File extends \lithium\core\Object {
if ($file->isFile() && $file->isReadable()) {
return unlink($path);
}
-
return false;
};
}
@@ -181,7 +177,6 @@ class File extends \lithium\core\Object {
}
}
return true;
-
}
/**
diff --git a/libraries/lithium/storage/session/adapter/Cookie.php b/libraries/lithium/storage/session/adapter/Cookie.php
index 993fc4e..33b362b 100755
--- a/libraries/lithium/storage/session/adapter/Cookie.php
+++ b/libraries/lithium/storage/session/adapter/Cookie.php
@@ -114,14 +114,19 @@ class Cookie extends \lithium\core\Object {
return function($self, $params) use (&$config) {
$key = $params['key'];
if (!$key) {
- return $_COOKIE;
+ if (isset($_COOKIE[$config['name']])) {
+ return $_COOKIE[$config['name']];
+ }
+ return array();
}
if (strpos($key, '.') !== false) {
$key = explode('.', $key);
- $result = $_COOKIE[$config['name']];
+ $result = (isset($_COOKIE[$config['name']])) ? $_COOKIE[$config['name']] : array();
foreach ($key as $k) {
- $result = $result[$k];
+ if (isset($result[$k])) {
+ $result = $result[$k];
+ }
}
return ($result !== array()) ? $result : null;
}
@@ -142,38 +147,36 @@ class Cookie extends \lithium\core\Object {
public function write($key, $value = null, array $options = array()) {
$expire = (!isset($options['expire']) && empty($this->_config['expire']));
$config = $this->_config;
+ $cookieClass = __CLASS__;
if ($expire && $key != $config['name']) {
return null;
}
$expires = (isset($options['expire'])) ? $options['expire'] : $config['expire'];
+<<<<<<< HEAD
return function($self, $params) use (&$config, &$expires) {
+=======
+ return function($self, $params) use (&$config, &$expires, $cookieClass) {
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$key = $params['key'];
$value = $params['value'];
- $key = is_array($key) ? Set::flatten($key) : array($key => $value);
+ $key = array($key => $value);
+ if (is_array($value)) {
+ $key = Set::flatten($key);
+ }
foreach ($key as $name => $val) {
- $name = explode('.', $name);
- $name = $config['name'] ? array_merge(array($config['name']), $name) : $name;
-
- if (count($name) == 1) {
- $name = current($name);
- } else {
- $name = (array_shift($name) . '[' . join('][', $name) . ']');
- }
- if (is_array($val)) {
- foreach ($val as $key => $v) {
- setcookie($name . "[$key]", $v, strtotime($expires), $config['path'],
- $config['domain'], $config['secure'], $config['httponly']
- );
- }
- return true;
- }
- setcookie($name, $val, strtotime($expires), $config['path'],
+ $name = $cookieClass::keyFormat($name, $config);
+ $result = setcookie($name, $val, strtotime($expires), $config['path'],
$config['domain'], $config['secure'], $config['httponly']
);
+
+ if (!$result) {
+ throw new RuntimeException("There was an error setting {$name} cookie.");
+ }
}
+ return true;
};
}
@@ -186,26 +189,79 @@ class Cookie extends \lithium\core\Object {
*/
public function delete($key, array $options = array()) {
$config = $this->_config;
+ $cookieClass = get_called_class();
+<<<<<<< HEAD
return function($self, $params) use (&$config) {
+=======
+ return function($self, $params) use (&$config, $cookieClass) {
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$key = $params['key'];
- $key = is_array($key) ? Set::flatten($key) : array($key);
+ $path = '/' . str_replace('.', '/', $config['name'] . '.' . $key) . '/.';
+ $cookies = current(Set::extract($_COOKIE, $path));
+ if (is_array($cookies)) {
+ $cookies = array_keys(Set::flatten($cookies));
+ foreach ($cookies as &$name) {
+ $name = $key . '.' . $name;
+ }
+ } else {
+ $cookies = array($key);
+ }
+ foreach ($cookies as &$name) {
+ $name = $cookieClass::keyFormat($name, $config);
+ $result = setcookie($name, "", 1, $config['path'],
+ $config['domain'], $config['secure'], $config['httponly']
+ );
+ if (!$result) {
+ throw new RuntimeException("There was an error deleting {$name} cookie.");
+ }
+ }
+ return true;
+ };
+ }
- foreach ($key as $name) {
- $name = explode('.', $name);
- $name = $config['name'] ? array_merge(array($config['name']), $name) : $name;
+ /**
+ * Clears all cookies.
+ *
+ * @param array $options Options array. Not used fro this adapter method.
+ * @return boolean True on successful clear, false otherwise.
+ */
+ public function clear(array $options = array()) {
+ $options += array('destroySession' => true);
+ $config = $this->_config;
+ $cookieClass = get_called_class();
- if (count($name) == 1) {
- $name = current($name);
- } else {
- $name = (array_shift($name) . '[' . join('][', $name) . ']');
- }
- setcookie($name, "", time() - 1, $config['path'],
+ return function($self, $params) use (&$config, $options, $cookieClass) {
+ if ($options['destroySession'] && session_id()) {
+ session_destroy();
+ }
+ if (!isset($_COOKIE[$config['name']])) {
+ return true;
+ }
+ $cookies = array_keys(Set::flatten($_COOKIE[$config['name']]));
+ foreach ($cookies as $name) {
+ $name = $cookieClass::keyFormat($name, $config);
+ $result = setcookie($name, "", 1, $config['path'],
$config['domain'], $config['secure'], $config['httponly']
);
+ if (!$result) {
+ throw new RuntimeException("There was an error clearing {$cookie} cookie.");
+ }
}
+ unset($_COOKIE[$config['name']]);
+ return true;
};
}
+
+ /**
+ * Formats the given `$name` argument for use in the cookie adapter.
+ *
+ * @param string $name The key to be formatted, e.g. `foo.bar.baz`.
+ * @return string The formatted key.
+ */
+ public static function keyFormat($name, $config) {
+ return $config['name'] . '[' . str_replace('.', '][', $name) . ']';
+ }
}
?>
\ No newline at end of file
diff --git a/libraries/lithium/storage/session/strategy/Hmac.php b/libraries/lithium/storage/session/strategy/Hmac.php
index cb3bdb4..4efdc2c 100644
--- a/libraries/lithium/storage/session/strategy/Hmac.php
+++ b/libraries/lithium/storage/session/strategy/Hmac.php
@@ -10,6 +10,7 @@ namespace lithium\storage\session\strategy;
use RuntimeException;
use lithium\core\ConfigException;
+use lithium\storage\session\strategy\MissingSignatureException;
/**
* This strategy allows you to sign your `Session` and/or `Cookie` data with a passphrase
@@ -91,6 +92,11 @@ class Hmac extends \lithium\core\Object {
* Validates the HMAC signature of the stored data. If the signatures match, then
* the data is safe, and the 'valid' key in the returned data will be
*
+ * If the store being read does not contain a `__signature` field, a `MissingSignatureException`
+ * is thrown. When catching this exception, you may choose to handle it by either writing
+ * out a signature (e.g. in cases where you know that no pre-existing signature may exist), or
+ * you can blackhole it as a possible tampering attempt.
+ *
* @param array $data the Data being read.
* @param array $options Options for this method.
* @return array validated data
@@ -98,20 +104,16 @@ class Hmac extends \lithium\core\Object {
public function read($data, array $options = array()) {
$class = $options['class'];
- $futureData = $class::read(null, array('strategies' => false));
- unset($futureData['__signature']);
+ $currentData = $class::read(null, array('strategies' => false));
- if (!isset($futureData['__signature'])) {
- $signature = hash_hmac('sha1', serialize($futureData), static::$_secret);
- $class::write('__signature', $signature, array('strategies' => false) + $options);
- return $data;
+ if (!isset($currentData['__signature'])) {
+ throw new MissingSignatureException('HMAC signature not found.');
}
-
- $currentSignature = $futureData['__signature'];
- $signature = static::_signature($futureData);
+ $currentSignature = $currentData['__signature'];
+ $signature = static::_signature($currentData);
if ($signature !== $currentSignature) {
- $message = "Possible data tampering - HMAC signature does not match data.";
+ $message = "Possible data tampering: HMAC signature does not match data.";
throw new RuntimeException($message);
}
return $data;
@@ -131,7 +133,7 @@ class Hmac extends \lithium\core\Object {
$class = $options['class'];
$futureData = $class::read(null, array('strategies' => false));
- unset($futureData[$options['key']], $futureData['__signature']);
+ unset($futureData[$options['key']]);
$signature = static::_signature($futureData);
$class::write('__signature', $signature, array('strategies' => false) + $options);
@@ -146,6 +148,7 @@ class Hmac extends \lithium\core\Object {
* @return string HMAC signature.
*/
protected static function _signature($data, $secret = null) {
+ unset($data['__signature']);
$secret = ($secret) ?: static::$_secret;
return hash_hmac('sha1', serialize($data), $secret);
}
diff --git a/libraries/lithium/storage/session/strategy/MissingSignatureException.php b/libraries/lithium/storage/session/strategy/MissingSignatureException.php
new file mode 100644
index 0000000..c4d9951
--- /dev/null
+++ b/libraries/lithium/storage/session/strategy/MissingSignatureException.php
@@ -0,0 +1,20 @@
+<?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\storage\session\strategy;
+
+/**
+ * A `MissingSignatureException` may be thrown when reading data from a session-based storage that
+ * is expecting an HMAC signature, but none is found..
+ */
+class MissingSignatureException extends \RuntimeException {
+
+ protected $code = 403;
+}
+
+?>
\ No newline at end of file
diff --git a/libraries/lithium/template/Helper.php b/libraries/lithium/template/Helper.php
index 8c69801..1fc97cc 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
+ );
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
$strings = $this->_context->strings();
}
diff --git a/libraries/lithium/template/View.php b/libraries/lithium/template/View.php
index 95bf695..bc23f42 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,85 @@ 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.
*/
+<<<<<<< HEAD
protected $_autoConfig = array('request', 'response');
+=======
+ protected $_autoConfig = array(
+ 'request', 'response', 'processes' => 'merge', 'steps' => 'merge'
+ );
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
/**
* 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 +208,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 +219,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 +244,57 @@ 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;
+<<<<<<< HEAD
$data = $data ?: array();
$template = null;
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
+
+ $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;
}
- $options['context'] += array('content' => $content);
- return $this->_layout($template, $data, $options);
+ if (is_string($conditions) && !(isset($options[$conditions]) && $options[$conditions])) {
+ return false;
+ }
+ return true;
}
+<<<<<<< HEAD
/**
* The 'element' render type handler.
*
@@ -226,11 +313,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;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
/**
- * 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 +379,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;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
}
diff --git a/libraries/lithium/template/helper/Form.php b/libraries/lithium/template/helper/Form.php
index 79e951a..71c87b8 100755
--- a/libraries/lithium/template/helper/Form.php
+++ b/libraries/lithium/template/helper/Form.php
@@ -17,10 +17,10 @@ use UnexpectedValueException;
* will simply generate HTML forms and widgets, but by creating a form with a _binding object_,
* the helper can pre-fill form input values, render error messages, and introspect column types.
*
- * For example, assuming you have created a `Post` model in your application:
+ * For example, assuming you have created a `Posts` model in your application:
* {{{// In controller code:
- * use \app\models\Post;
- * $post = Post::find(1);
+ * use app\models\Posts;
+ * $post = Posts::find(1);
* return compact('post');
*
* // In view code:
@@ -144,6 +144,7 @@ class Form extends \lithium\template\Helper {
if (in_array($method, array('create', 'end', 'label', 'error'))) {
return;
}
+<<<<<<< HEAD
if (!$name || ($method == 'hidden' && $name = '_method')) {
return;
}
@@ -156,6 +157,12 @@ class Form extends \lithium\template\Helper {
=======
$id = Inflector::camelize(Inflector::slug($name));
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ if (!$name || ($method == 'hidden' && $name == '_method')) {
+ return;
+ }
+ $id = Inflector::camelize(Inflector::slug($name));
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$model = ($binding = $self->binding()) ? $binding->model() : null;
return $model ? basename(str_replace('\\', '/', $model)) . $id : $id;
}
@@ -172,7 +179,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'));
+ }
}
/**
@@ -258,8 +268,13 @@ class Form extends \lithium\template\Helper {
* attributes passed in `$options`.
*/
public function create($binding = null, array $options = array()) {
+<<<<<<< HEAD
+=======
+ $request = $this->_context ? $this->_context->request() : null;
+
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$defaults = array(
- 'url' => $this->_context->request()->params,
+ 'url' => $request ? $request->params : array(),
'type' => null,
'action' => null,
'method' => $binding ? ($binding->exists() ? 'put' : 'post') : 'post'
@@ -275,6 +290,7 @@ class Form extends \lithium\template\Helper {
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
$filter = function($self, $params, $chain) use ($extra, &$_binding, &$_options) {
=======
$filter = function($self, $params) use ($extra, &$_binding, &$_options) {
@@ -282,6 +298,9 @@ class Form extends \lithium\template\Helper {
=======
$filter = function($self, $params) use ($extra, &$_binding, &$_options) {
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ $filter = function($self, $params) use ($extra, &$_binding, &$_options) {
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$scope = $params['scope'];
$options = $params['options'];
$_binding = $params['binding'];
@@ -325,6 +344,7 @@ class Form extends \lithium\template\Helper {
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
$filter = function($self, $params, $chain) use (&$_binding, &$_context, &$_options) {
=======
$filter = function($self, $params) use (&$_binding, &$_context, &$_options) {
@@ -332,6 +352,9 @@ class Form extends \lithium\template\Helper {
=======
$filter = function($self, $params) use (&$_binding, &$_context, &$_options) {
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ $filter = function($self, $params) use (&$_binding, &$_context, &$_options) {
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
unset($_binding);
$_options = array();
return $_context->strings('form-end');
@@ -411,6 +434,7 @@ class Form extends \lithium\template\Helper {
*/
public function field($name, array $options = array()) {
if (is_array($name)) {
+<<<<<<< HEAD
$return = '';
foreach ($name as $field => $label) {
if (is_numeric($field)) {
@@ -420,6 +444,9 @@ class Form extends \lithium\template\Helper {
$return .= $this->field($field, compact('label') + $options);
}
return $return;
+=======
+ return $this->_fields($name, $options);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
$defaults = array(
'label' => null,
@@ -443,7 +470,11 @@ class Form extends \lithium\template\Helper {
$type = $options['type'];
$label = $input = null;
+<<<<<<< HEAD
if ($options['label'] === null || $options['label']) {
+=======
+ if (($options['label'] === null || $options['label']) && $options['type'] != 'hidden') {
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$for = isset($options['id']) ? $options['id'] : '';
$label = $options['label'] ?: $options['label'] = Inflector::humanize($name);
$label = $this->label($for, $label);
@@ -462,6 +493,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.
@@ -579,7 +632,11 @@ class Form extends \lithium\template\Helper {
}
}
if ($scope['hidden']) {
+<<<<<<< HEAD
$out = $this->hidden($name, array('value' => ''));
+=======
+ $out = $this->hidden($name, array('value' => '', 'id' => false));
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
$options['value'] = $scope['value'];
return $out . $this->_render(__METHOD__, $template, compact('name', 'options'));
@@ -613,7 +670,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
@@ -685,6 +742,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'];
+ $options = $this->_generators($method, $name, $options);
foreach ($this->_config['attributes'] as $key => $generator) {
if (!isset($options[$key]) && $generator) {
@@ -708,22 +766,58 @@ class Form extends \lithium\template\Helper {
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
=======
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
if (strpos($name, '.')) {
$name = explode('.', $name);
$first = array_shift($name);
$name = $first . '[' . join('][', $name) . ']';
}
<<<<<<< HEAD
+<<<<<<< HEAD
>>>>>>> 25a362f706960b2becbf88e91cffc1b1638b7890
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$tplKey = isset($options['template']) ? $options['template'] : $method;
$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..eceacab 100644
--- a/libraries/lithium/template/view/Compiler.php
+++ b/libraries/lithium/template/view/Compiler.php
@@ -8,6 +8,7 @@
namespace lithium\template\view;
+use lithium\core\Libraries;
use lithium\template\TemplateException;
/**
@@ -51,7 +52,7 @@ class Compiler extends \lithium\core\StaticObject {
* @return string The compiled template.
*/
public static function template($file, array $options = array()) {
- $cachePath = LITHIUM_APP_PATH . '/resources/tmp/cache/templates';
+ $cachePath = Libraries::get(true, 'resources') . '/tmp/cache/templates';
$defaults = array('path' => $cachePath, 'fallback' => true);
$options += $defaults;
@@ -77,7 +78,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..f7e9fd7 100644
--- a/libraries/lithium/template/view/Renderer.php
+++ b/libraries/lithium/template/view/Renderer.php
@@ -10,6 +10,7 @@ namespace lithium\template\view;
use RuntimeException;
use lithium\core\Libraries;
+use lithium\core\ClassNotFoundException;
/**
* The `Renderer` abstract class serves as a base for all concrete `Renderer` adapters.
@@ -33,7 +34,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 +93,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 +152,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 +165,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,13 +192,16 @@ 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',
- 'content' => 'escape',
'title' => 'escape',
'scripts' => function($scripts) use (&$context) {
return "\n\t" . join("\n\t", $context['scripts']) . "\n";
@@ -277,11 +290,16 @@ abstract class Renderer extends \lithium\core\Object {
* @param array $config
* @return object
*/
- public function helper($name, $config = array()) {
- if ($class = Libraries::locate('helper', ucfirst($name))) {
- return $this->_helpers[$name] = new $class($config + array('context' => $this));
+ public function helper($name, array $config = array()) {
+ if (isset($this->_helpers[$name])) {
+ return $this->_helpers[$name];
+ }
+ try {
+ $config += array('context' => $this);
+ return $this->_helpers[$name] = Libraries::instance('helper', ucfirst($name), $config);
+ } catch (ClassNotFoundException $e) {
+ throw new RuntimeException("Helper `{$name}` not found.");
}
- throw new RuntimeException("Helper {$name} not found");
}
/**
@@ -312,7 +330,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;
@@ -370,7 +388,10 @@ abstract class Renderer extends \lithium\core\Object {
if (!(isset($this->_handlers[$name]) && $handler = $this->_handlers[$name])) {
return $value;
}
+
switch (true) {
+ case is_string($handler) && !$helper:
+ $helper = $this->helper('html');
case is_string($handler) && is_object($helper):
return $helper->invokeMethod($handler, array($value, $method, $options));
case is_array($handler) && is_object($handler[0]):
@@ -394,6 +415,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 +457,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..8c70409 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,9 +116,10 @@ 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
*/
+<<<<<<< HEAD
public function template($type, $options) {
if (!isset($this->_config['paths'][$type])) {
return null;
@@ -122,6 +129,12 @@ class File extends \lithium\template\view\Renderer implements \ArrayAccess {
$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);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
if ($this->_compile) {
$compiler = $this->_classes['compiler'];
@@ -153,21 +166,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..6bfedb5 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;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
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..ae17142 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.");
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
$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..7ce181d 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;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
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;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
/**
* 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;
}
@@ -526,9 +537,57 @@ class Unit extends \lithium\core\Object {
* @param array $headers When empty, value of `headers_list()` is used.
*/
public function assertCookie($expected, $headers = null) {
+<<<<<<< HEAD
$defaults = array('path' => '/', 'name' => '[\w.-]+');
$expected += $defaults;
+=======
+ $matched = $this->_cookieMatch($expected, $headers);
+ if (!$matched['match']) {
+ $message = sprintf('%s - Cookie not found in headers.', $matched['pattern']);
+ $this->assert(false, $message, compact('expected', 'result'));
+ return false;
+ }
+ return $this->assert(true, '%s');
+ }
+
+ /**
+ * Assert Cookie data is *not* set in headers.
+ *
+ * The value passed to `exepected` is an array of the cookie data, with at least the key and
+ * value expected, but can support any of the following keys:
+ * - `key`: the expected key
+ * - `value`: the expected value
+ * - `path`: optionally specifiy a path
+ * - `name`: optionally specify the cookie name
+ * - `expires`: optionally assert a specific expire time
+ *
+ * @param array $expected
+ * @param array $headers When empty, value of `headers_list()` is used.
+ */
+ public function assertNoCookie($expected, $headers = null) {
+ $matched = $this->_cookieMatch($expected, $headers);
+ if ($matched['match']) {
+ $message = sprintf('%s - Cookie not found in headers.', $matched['pattern']);
+ $this->assert(false, $message, compact('expected', 'result'));
+ return false;
+ }
+ return $this->assert(true, '%s');
+ }
+
+ /**
+ * Match an `$expected` cookie with the given headers. If no headers are provided, then
+ * the value of `headers_list()` will be used.
+ *
+ * @param array $expected
+ * @param array $headers When empty, value of `headers_list()` will be used.
+ * @return boolean True if cookie is found, false otherwise.
+ */
+ protected function _cookieMatch($expected, $headers) {
+ $defaults = array('path' => '/', 'name' => '[\w.-]+');
+ $expected += $defaults;
+
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$headers = ($headers) ?: headers_list();
$value = preg_quote(urlencode($expected['value']), '/');
@@ -553,15 +612,7 @@ class Unit extends \lithium\core\Object {
continue;
}
}
-
- if (!$match) {
- $this->assert(false,
- sprintf('{:message} - Cookie %s not found in headers.', $pattern),
- compact('expected', 'result')
- );
- return false;
- }
- return $this->assert(true, '%s');
+ return compact('match', 'pattern');
}
/**
@@ -726,18 +777,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 +801,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 +816,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 +833,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 +852,7 @@ class Unit extends \lithium\core\Object {
if (!empty($data)) {
return $data;
}
+<<<<<<< HEAD
}
if (!is_scalar($result)) {
@@ -797,15 +865,24 @@ class Unit extends \lithium\core\Object {
'result' => $data['expected']
);
}
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
+ 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');
@@ -887,13 +964,15 @@ class Unit extends \lithium\core\Object {
* @return void
*/
protected function _cleanUp($path = null) {
- $path = $path ?: LITHIUM_APP_PATH . '/resources/tmp/tests';
- $path = $path[0] !== '/' ? LITHIUM_APP_PATH . '/resources/tmp/' . $path : $path;
+ $path = $path ?: Libraries::get(true, 'resources') . '/tmp/tests';
+ $path = $path[0] !== '/' ? Libraries::get(true, 'resources') . '/tmp/' . $path : $path;
+
if (!is_dir($path)) {
return;
}
$dirs = new RecursiveDirectoryIterator($path);
$iterator = new RecursiveIteratorIterator($dirs, RecursiveIteratorIterator::CHILD_FIRST);
+
foreach ($iterator as $item) {
if ($item->getPathname() === "{$path}/empty" || $iterator->isDot()) {
continue;
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/test/templates/html/layout.html.php b/libraries/lithium/test/templates/html/layout.html.php
index b19d38d..7cf1640 100644
--- a/libraries/lithium/test/templates/html/layout.html.php
+++ b/libraries/lithium/test/templates/html/layout.html.php
@@ -1,11 +1,26 @@
<?php
+<<<<<<< HEAD
use lithium\util\Inflector;
$base = $request->env('base');
+=======
+/**
+ * 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
+ */
+
+use lithium\util\Inflector;
+
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
?>
<!doctype html>
<html>
<head>
+ <!-- Title intentionally left blank, forcing user agents use the current URL as title. -->
<title></title>
+ <?php $base = $request->env('base'); ?>
+ <meta charset="utf-8" />
<link rel="stylesheet" href="<?php echo $base; ?>/css/debug.css" />
<link href="<?php echo $base; ?>/favicon.ico" type="image/x-icon" rel="icon" />
<link href="<?php echo $base; ?>/favicon.ico" type="image/x-icon" rel="shortcut icon" />
diff --git a/libraries/lithium/tests/cases/action/ControllerTest.php b/libraries/lithium/tests/cases/action/ControllerTest.php
index e9e013f..c78ed9c 100644
--- a/libraries/lithium/tests/cases/action/ControllerTest.php
+++ b/libraries/lithium/tests/cases/action/ControllerTest.php
@@ -41,10 +41,8 @@ class ControllerTest extends \lithium\test\Unit {
$result = $postsController->__invoke(null, array('action' => 'index', 'args' => array()));
$this->assertTrue(is_a($result, 'lithium\action\Response'));
- $this->assertEqual($result->body(), 'List of posts');
-
- $headers = array('Content-type' => 'text/plain');
- $this->assertEqual($result->headers, $headers);
+ $this->assertEqual('List of posts', $result->body());
+ $this->assertEqual(array('Content-type' => 'text/plain; charset=UTF-8'), $result->headers);
$result2 = $postsController(null, array('action' => 'index', 'args' => array()));
$this->assertEqual($result2, $result);
@@ -56,7 +54,7 @@ class ControllerTest extends \lithium\test\Unit {
$this->assertTrue(is_a($result, 'lithium\action\Response'));
$this->assertEqual($result->body, '');
- $headers = array('Content-type' => 'text/html');
+ $headers = array('Content-type' => 'text/html; charset=UTF-8');
$this->assertEqual($result->headers, $headers);
$result = $postsController->access('_render');
@@ -68,7 +66,7 @@ class ControllerTest extends \lithium\test\Unit {
$this->assertTrue(is_a($result, 'lithium\action\Response'));
$this->assertEqual($result->body, "Array\n(\n [0] => This is a post\n)\n");
- $headers = array('status' => 200, 'Content-type' => 'text/plain');
+ $headers = array('status' => 200, 'Content-type' => 'text/plain; charset=UTF-8');
$this->assertEqual($result->headers(), $headers);
$result = $postsController->access('_render');
@@ -213,13 +211,11 @@ class ControllerTest extends \lithium\test\Unit {
$result = $postsController->access('_render');
$this->assertEqual($expected, $result);
- $expected = 'application/json';
$result = $postsController->response->headers('Content-type');
- $this->assertEqual($expected, $result);
+ $this->assertEqual('application/json; charset=UTF-8', $result);
- $expected = array('data' => 'test');
$result = json_decode($postsController->response->body(), true);
- $this->assertEqual($expected, $result);
+ $this->assertEqual(array('data' => 'test'), $result);
}
public function testResponseTypeBasedOnRequestParamsType() {
@@ -243,9 +239,8 @@ class ControllerTest extends \lithium\test\Unit {
$result = $postsController->access('_render');
$this->assertEqual($expected, $result);
- $expected = 'application/json';
$result = $postsController->response->headers('Content-type');
- $this->assertEqual($expected, $result);
+ $this->assertEqual('application/json; charset=UTF-8', $result);
$expected = array('data' => 'test');
$result = json_decode($postsController->response->body(), true);
@@ -275,11 +270,16 @@ class ControllerTest extends \lithium\test\Unit {
$postsController = new MockPostsController(array(
'request' => $request,
<<<<<<< HEAD
+<<<<<<< HEAD
'classes' => array('response' => 'lithium\tests\mocks\action\MockControllerResponse')
=======
'classes' => array('response' => 'lithium\tests\mocks\action\MockControllerResponse'),
'render' => array('negotiate' => true)
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ 'classes' => array('response' => 'lithium\tests\mocks\action\MockControllerResponse'),
+ 'render' => array('negotiate' => true)
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
));
$this->assertFalse($postsController->stopped);
@@ -292,13 +292,11 @@ class ControllerTest extends \lithium\test\Unit {
$result = $postsController->access('_render');
$this->assertEqual($expected, $result);
- $expected = 'application/json';
$result = $postsController->response->headers('Content-type');
- $this->assertEqual($expected, $result);
+ $this->assertEqual('application/json; charset=UTF-8', $result);
- $expected = array('data' => 'test');
$result = json_decode($postsController->response->body(), true);
- $this->assertEqual($expected, $result);
+ $this->assertEqual(array('data' => 'test'), $result);
}
/**
@@ -320,7 +318,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 dd17183..4d1d58a 100644
--- a/libraries/lithium/tests/cases/action/DispatcherTest.php
+++ b/libraries/lithium/tests/cases/action/DispatcherTest.php
@@ -47,6 +47,7 @@ class DispatcherTest extends \lithium\test\Unit {
public function testApplyRulesControllerCasing() {
<<<<<<< HEAD
+<<<<<<< HEAD
$result = Dispatcher::applyRules(array('controller' => 'test', 'action' => 'test'));
$expected = array('controller' => 'Test', 'action' => 'test');
$this->assertEqual($expected, $result);
@@ -107,6 +108,8 @@ class DispatcherTest extends \lithium\test\Unit {
);
$this->assertEqual($expected, $result);
=======
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$params = array('controller' => 'test', 'action' => 'test');
$expected = array('controller' => 'Test', 'action' => 'test');
$this->assertEqual($expected, Dispatcher::applyRules($params));
@@ -153,7 +156,10 @@ class DispatcherTest extends \lithium\test\Unit {
'library' => 'li3_one', 'controller' => 'li3_two\Test', 'action' => 'test'
);
$this->assertEqual($expected, Dispatcher::applyRules($params));
+<<<<<<< HEAD
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
public function testConfigManipulation() {
@@ -176,14 +182,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/RequestTest.php b/libraries/lithium/tests/cases/action/RequestTest.php
index 31579d2..8dc7b92 100644
--- a/libraries/lithium/tests/cases/action/RequestTest.php
+++ b/libraries/lithium/tests/cases/action/RequestTest.php
@@ -99,83 +99,57 @@ class RequestTest extends \lithium\test\Unit {
}
public function testScriptName() {
- $_SERVER['SCRIPT_NAME'] = 'index.php';
- $request = new Request();
-
- $expected = 'index.php';
- $result = $request->env('SCRIPT_NAME');
- $this->assertEqual($expected, $result);
+ $request = new Request(array(
+ 'env' => array('HTTPS' => true, 'SCRIPT_NAME' => 'index.php')
+ ));
+ $this->assertEqual('index.php', $request->env('SCRIPT_NAME'));
}
public function testHttps() {
- $_SERVER['HTTPS'] = true;
- $request = new Request();
-
- $expected = true;
- $result = $request->env('HTTPS');
- $this->assertEqual($expected, $result);
+ $request = new Request(array('env' => array('HTTPS' => true)));
+ $this->assertTrue($request->env('HTTPS'));
}
public function testHttpsFromScriptUri() {
- $_SERVER['SCRIPT_URI'] = 'https://lithium.com';
- unset($_SERVER['HTTPS']);
- $request = new Request();
-
- $expected = true;
- $result = $request->env('HTTPS');
- $this->assertEqual($expected, $result);
+ $request = new Request(array('env' => array(
+ 'SCRIPT_URI' => 'https://lithium.com',
+ 'HTTPS' => null
+ )));
+ $this->assertTrue($request->env('HTTPS'));
}
public function testRemoteAddr() {
- $_SERVER['REMOTE_ADDR'] = '123.456.789.000';
- $request = new Request();
-
- $expected = '123.456.789.000';
- $result = $request->env('REMOTE_ADDR');
- $this->assertEqual($expected, $result);
+ $request = new Request(array('env' => array('REMOTE_ADDR' => '123.456.789.000')));
+ $this->assertEqual('123.456.789.000', $request->env('REMOTE_ADDR'));
}
public function testRemoteAddrFromHttpPcRemoteAddr() {
$request = new MockIisRequest();
-
- $expected = '123.456.789.000';
- $result = $request->env('REMOTE_ADDR');
- $this->assertEqual($expected, $result);
+ $this->assertEqual('123.456.789.000', $request->env('REMOTE_ADDR'));
}
public function testBase() {
- $_SERVER['PHP_SELF'] = '/index.php';
- $request = new Request();
-
- $expected = null;
- $result = $request->env('base');
- $this->assertEqual($expected, $result);
+ $request = new Request(array('env' => array('PHP_SELF' => '/index.php')));
+ $this->assertFalse($request->env('base'));
}
public function testBaseWithDirectory() {
- $_SERVER['PHP_SELF'] = '/lithium.com/app/webroot/index.php';
- $request = new Request();
-
- $expected = '/lithium.com';
- $result = $request->env('base');
- $this->assertEqual($expected, $result);
+ $request = new Request(array('env' => array(
+ 'PHP_SELF' => '/lithium.com/app/webroot/index.php'
+ )));
+ $this->assertEqual('/lithium.com', $request->env('base'));
}
public function testBaseWithAppAndOtherDirectory() {
- $_SERVER['PHP_SELF'] = '/lithium.com/app/other/webroot/index.php';
- $request = new Request();
-
- $expected = '/lithium.com/app/other';
- $result = $request->env('base');
- $this->assertEqual($expected, $result);
+ $request = new Request(array('env' => array(
+ 'PHP_SELF' => '/lithium.com/app/other/webroot/index.php'
+ )));
+ $this->assertEqual('/lithium.com/app/other', $request->env('base'));
}
public function testPhpSelfTranslatedForIIS() {
$request = new MockIisRequest();
-
- $expected = '/index.php';
- $result = $request->env('PHP_SELF');
- $this->assertEqual($expected, $result);
+ $this->assertEqual('/index.php', $request->env('PHP_SELF'));
}
public function testServerHttpBase() {
@@ -190,9 +164,8 @@ class RequestTest extends \lithium\test\Unit {
public function testCgiPlatform() {
$request = new MockCgiRequest();
- $expected = true;
$result = $request->env('CGI_MODE');
- $this->assertEqual($expected, $result);
+ $this->assertTrue($result);
}
public function testCgiScriptUrl() {
@@ -215,9 +188,8 @@ class RequestTest extends \lithium\test\Unit {
$result = $request->get('data:Article');
$this->assertEqual($expected, $result);
- $expected = null;
$result = $request->get('not:Post');
- $this->assertEqual($expected, $result);
+ $this->assertNull($result);
$expected = '/lithium.com';
$result = $request->get('env:base');
@@ -259,18 +231,27 @@ class RequestTest extends \lithium\test\Unit {
return true;
}));
- $expected = true;
$result = $request->is('cool');
- $this->assertEqual($expected, $result);
+ $this->assertTrue($result);
}
public function testDetectWithArrayRegex() {
$request = new Request(array('env' => array('SOME_COOL_DETECTION' => 'this is cool')));
$request->detect('cool', array('SOME_COOL_DETECTION', '/cool/'));
- $expected = true;
$result = $request->is('cool');
- $this->assertEqual($expected, $result);
+ $this->assertTrue($result);
+ }
+
+ public function testDetectSsl() {
+ $request = new Request(array('env' => array('SCRIPT_URI' => null, 'HTTPS' => 'off')));
+ $this->assertFalse($request->env('HTTPS'));
+
+ $request = new Request(array('env' => array('SCRIPT_URI' => null, 'HTTPS' => 'on')));
+ $this->assertTrue($request->env('HTTPS'));
+
+ $request = new Request(array('env' => array('SCRIPT_URI' => null, 'HTTPS' => null)));
+ $this->assertFalse($request->env('HTTPS'));
}
public function testDetectSsl() {
@@ -870,7 +851,10 @@ class RequestTest extends \lithium\test\Unit {
}
<<<<<<< HEAD
+<<<<<<< HEAD
+=======
=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
/**
* Tests that accepted content-types without a `q` value are sorted in the order they appear in
* the `HTTP_ACCEPT` header.
@@ -890,7 +874,10 @@ class RequestTest extends \lithium\test\Unit {
$this->assertEqual($expected, $request->accepts(true));
}
+<<<<<<< HEAD
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
public function testParsingAcceptHeader() {
$chrome = array(
'application/xml',
@@ -924,6 +911,18 @@ class RequestTest extends \lithium\test\Unit {
'image/x-xbitmap',
'*/*;q=0.1'
);
+<<<<<<< HEAD
+=======
+ $android = array(
+ 'application/xml',
+ 'application/xhtml+xml',
+ 'text/html;q=0.9',
+ 'text/plain;q=0.8',
+ 'image/png',
+ '*/*;q=0.5',
+ 'application/youtube-client'
+ );
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$request = new Request(array('env' => array('HTTP_ACCEPT' => join(',', $chrome))));
$this->assertEqual('html', $request->accepts());
$this->assertTrue(array_search('text/plain', $request->accepts(true)), 4);
@@ -942,6 +941,12 @@ class RequestTest extends \lithium\test\Unit {
$result = $request->accepts(true);
$this->assertEqual('text/plain', $result[0]);
+<<<<<<< HEAD
+=======
+
+ $request = new Request(array('env' => array('HTTP_ACCEPT' => join(',', $android))));
+ $this->assertEqual('html', $request->accepts());
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
}
diff --git a/libraries/lithium/tests/cases/action/ResponseTest.php b/libraries/lithium/tests/cases/action/ResponseTest.php
index d6ba7c6..c661579 100644
--- a/libraries/lithium/tests/cases/action/ResponseTest.php
+++ b/libraries/lithium/tests/cases/action/ResponseTest.php
@@ -54,9 +54,13 @@ class ResponseTest extends \lithium\test\Unit {
'Expires: ' . gmdate('D, d M Y H:i:s', $expires) . ' GMT',
'Cache-Control: max-age=' . ($expires - time()),
<<<<<<< HEAD
+<<<<<<< HEAD
=======
'Pragma: cache'
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ 'Pragma: cache'
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
);
$this->assertEqual($headers, $this->response->testHeaders);
@@ -70,9 +74,13 @@ class ResponseTest extends \lithium\test\Unit {
'Expires: ' . gmdate('D, d M Y H:i:s', strtotime($expires)) . ' GMT',
'Cache-Control: max-age=' . (strtotime($expires) - time()),
<<<<<<< HEAD
+<<<<<<< HEAD
=======
'Pragma: cache'
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ 'Pragma: cache'
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
);
$this->assertEqual($headers, $this->response->testHeaders);
@@ -97,7 +105,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\)`/');
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$this->response->disableCache();
}
@@ -119,12 +131,12 @@ class ResponseTest extends \lithium\test\Unit {
$result = ob_get_clean();
$this->assertEqual(array('HTTP/1.1 303 See Other'), $this->response->testHeaders);
- $this->expectException('/Invalid status code/');
$this->response->status('foobar');
ob_start();
$this->response->render();
$result = ob_get_clean();
- $this->assertFalse($this->response->testHeaders);
+ $expected = array('HTTP/1.1 500 Internal Server Error');
+ $this->assertEqual($expected, $this->response->testHeaders);
}
/**
@@ -165,11 +177,18 @@ class ResponseTest extends \lithium\test\Unit {
$headers = array('HTTP/1.1 301 Moved Permanently', 'Location: /');
$this->assertEqual($headers, $this->response->testHeaders);
- $this->response = new Response(array('location' => array(
- 'controller' => 'foo_bar', 'action' => 'index'
- )));
+ $this->response = new Response(array(
+ 'classes' => array('router' => __CLASS__),
+ 'location' => array('controller' => 'foo_bar', 'action' => 'index')
+ ));
$this->assertEqual(array('location: /foo_bar'), $this->response->headers());
}
+
+ public static function match($url) {
+ if ($url == array('controller' => 'foo_bar', 'action' => 'index')) {
+ return '/foo_bar';
+ }
+ }
}
?>
\ No newline at end of file
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..45d5f69 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;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
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 74f3be5..f22ce35 100644
--- a/libraries/lithium/tests/cases/analysis/LoggerTest.php
+++ b/libraries/lithium/tests/cases/analysis/LoggerTest.php
@@ -8,6 +8,10 @@
namespace lithium\tests\cases\analysis;
+<<<<<<< HEAD
+=======
+use lithium\core\Libraries;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
use lithium\analysis\Logger;
use lithium\util\Collection;
use lithium\tests\mocks\analysis\MockLoggerAdapter;
@@ -18,7 +22,7 @@ use lithium\tests\mocks\analysis\MockLoggerAdapter;
class LoggerTest extends \lithium\test\Unit {
public function skip() {
- $this->_testPath = LITHIUM_APP_PATH . '/resources/tmp/tests';
+ $this->_testPath = Libraries::get(true, 'resources') . '/tmp/tests';
$this->skipIf(!is_writable($this->_testPath), "{$this->_testPath} is not readable.");
}
@@ -64,10 +68,12 @@ class LoggerTest extends \lithium\test\Unit {
}
public function testIntegrationWriteFile() {
- $base = LITHIUM_APP_PATH . '/resources/tmp/logs';
+ $base = Libraries::get(true, 'resources') . '/tmp/logs';
$this->skipIf(!is_writable($base), "{$base} is not writable.");
- $config = array('default' => array('adapter' => 'File', 'timestamp' => false));
+ $config = array('default' => array(
+ 'adapter' => 'File', 'timestamp' => false, 'format' => "{:message}\n"
+ ));
Logger::config($config);
$result = Logger::write('info', 'Message line 1');
@@ -88,16 +94,19 @@ 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");
}
public function testWriteByName() {
- $base = LITHIUM_APP_PATH . '/resources/tmp/logs';
+ $base = Libraries::get(true, 'resources') . '/tmp/logs';
$this->skipIf(!is_writable($base), "{$base} is not writable.");
Logger::config(array('default' => array(
- 'adapter' => 'File', 'timestamp' => false, 'priority' => false
+ 'adapter' => 'File',
+ 'timestamp' => false,
+ 'priority' => false,
+ 'format' => "{:message}\n"
)));
$this->assertFalse(file_exists($base . '/info.log'));
diff --git a/libraries/lithium/tests/cases/analysis/logger/adapter/FileTest.php b/libraries/lithium/tests/cases/analysis/logger/adapter/FileTest.php
index a809cbe..5b25f0a 100644
--- a/libraries/lithium/tests/cases/analysis/logger/adapter/FileTest.php
+++ b/libraries/lithium/tests/cases/analysis/logger/adapter/FileTest.php
@@ -8,6 +8,10 @@
namespace lithium\tests\cases\analysis\logger\adapter;
+<<<<<<< HEAD
+=======
+use lithium\core\Libraries;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
use lithium\util\collection\Filters;
use lithium\analysis\logger\adapter\File;
@@ -15,8 +19,13 @@ class FileTest extends \lithium\test\Unit {
public $subject;
+ public function skip() {
+ $path = realpath(Libraries::get(true, 'resources') . '/tmp/logs');
+ $this->skipIf(!is_writable($path), "Path `{$path}` is not writable.");
+ }
+
public function setUp() {
- $this->path = LITHIUM_APP_PATH . '/resources/tmp/logs';
+ $this->path = Libraries::get(true, 'resources') . '/tmp/logs';
$this->tearDown();
}
@@ -39,7 +48,9 @@ class FileTest extends \lithium\test\Unit {
}
public function testWithoutTimestamp() {
- $this->subject = new File(array('path' => $this->path, 'timestamp' => false));
+ $this->subject = new File(array(
+ 'path' => $this->path, 'timestamp' => false, 'format' => "{:message}\n"
+ ));
$priority = 'debug';
$message = 'This is a debug message';
$function = $this->subject->write($priority, $message);
diff --git a/libraries/lithium/tests/cases/console/DispatcherTest.php b/libraries/lithium/tests/cases/console/DispatcherTest.php
index 43eb3cc..0c44574 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')
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
)));
$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')
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
)));
$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/RequestTest.php b/libraries/lithium/tests/cases/console/RequestTest.php
index 141dace..c297f90 100644
--- a/libraries/lithium/tests/cases/console/RequestTest.php
+++ b/libraries/lithium/tests/cases/console/RequestTest.php
@@ -8,6 +8,10 @@
namespace lithium\tests\cases\console;
+<<<<<<< HEAD
+=======
+use lithium\core\Libraries;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
use lithium\console\Request;
class RequestTest extends \lithium\test\Unit {
@@ -18,7 +22,7 @@ class RequestTest extends \lithium\test\Unit {
public function setUp() {
$this->streams = array(
- 'input' => LITHIUM_APP_PATH . '/resources/tmp/tests/input.txt',
+ 'input' => Libraries::get(true, 'resources') . '/tmp/tests/input.txt'
);
$this->_backups['cwd'] = getcwd();
@@ -52,13 +56,13 @@ class RequestTest extends \lithium\test\Unit {
}
public function testEnvWorking() {
- $base = LITHIUM_APP_PATH . '/resources/tmp/tests';
+ $base = Libraries::get(true, 'resources') . '/tmp/tests';
$this->skipIf(!is_readable($base), "{$base} is not readable.");
- chdir(LITHIUM_APP_PATH . '/resources/tmp/tests');
+ chdir(Libraries::get(true, 'resources') . '/tmp/tests');
$request = new Request();
- $expected = LITHIUM_APP_PATH . '/resources/tmp/tests';
+ $expected = realpath(Libraries::get(true, 'resources') . '/tmp/tests');
$result = $request->env('working');
$this->assertEqual($expected, $result);
}
@@ -77,18 +81,14 @@ class RequestTest extends \lithium\test\Unit {
}
public function testConstructWithConfigArgv() {
- $request = new Request(array(
- 'args' => array('/path/to/lithium.php', 'wrong')
- ));
+ $request = new Request(array('args' => array('/path/to/lithium.php', 'wrong')));
$expected = array('/path/to/lithium.php', 'wrong');
$result = $request->argv;
$this->assertEqual($expected, $result);
$_SERVER['argv'] = array('/path/to/lithium.php');
- $request = new Request(array(
- 'args' => array('one', 'two')
- ));
+ $request = new Request(array('args' => array('one', 'two')));
$expected = '/path/to/lithium.php';
$result = $request->env('script');
@@ -120,13 +120,11 @@ class RequestTest extends \lithium\test\Unit {
}
public function testConstructWithEnv() {
- $base = LITHIUM_APP_PATH . '/resources/tmp/tests';
+ $base = Libraries::get(true, 'resources') . '/tmp/tests';
$this->skipIf(!is_readable($base), "{$base} is not writable.");
- chdir(LITHIUM_APP_PATH . '/resources/tmp');
- $request = new Request(array(
- 'env' => array('working' => '/some/other/path')
- ));
+ chdir(Libraries::get(true, 'resources') . '/tmp');
+ $request = new Request(array('env' => array('working' => '/some/other/path')));
$expected = '/some/other/path';
$result = $request->env('working');
@@ -134,37 +132,26 @@ class RequestTest extends \lithium\test\Unit {
}
public function testInput() {
- $base = LITHIUM_APP_PATH . '/resources/tmp/tests';
+ $base = Libraries::get(true, 'resources') . '/tmp/tests';
$this->skipIf(!is_writable($base), "{$base} is not writable.");
$stream = fopen($this->streams['input'], 'w+');
- $request = new Request(array(
- 'input' => $stream
- ));
+ $request = new Request(array('input' => $stream));
$this->assertTrue(is_resource($request->input));
$this->assertEqual($stream, $request->input);
-
- $expected = 2;
- $result = fwrite($request->input, 'ok');
- $this->assertEqual($expected, $result);
+ $this->assertEqual(2, fwrite($request->input, 'ok'));
rewind($request->input);
- $expected = 'ok';
- $result = $request->input();
- $this->assertEqual($expected, $result);
+ $this->assertEqual('ok', $request->input());
}
public function testArgs() {
$request = new Request();
$request->params = array(
- 'command' => 'one', 'action' => 'two',
- 'args' => array('three', 'four', 'five')
+ 'command' => 'one', 'action' => 'two', 'args' => array('three', 'four', 'five')
);
-
- $expected = 'five';
- $result = $request->args(2);
- $this->assertEqual($expected, $result);
+ $this->assertEqual('five', $request->args(2));
}
public function testShiftDefaultOne() {
@@ -176,8 +163,7 @@ class RequestTest extends \lithium\test\Unit {
$request->shift();
$expected = array('command' => 'two', 'action' => 'three', 'args' => array('four', 'five'));
- $result = $request->params;
- $this->assertEqual($expected, $result);
+ $this->assertEqual($expected, $request->params);
}
public function testShiftTwo() {
diff --git a/libraries/lithium/tests/cases/console/ResponseTest.php b/libraries/lithium/tests/cases/console/ResponseTest.php
index f2d1e23..2c3ea30 100644
--- a/libraries/lithium/tests/cases/console/ResponseTest.php
+++ b/libraries/lithium/tests/cases/console/ResponseTest.php
@@ -8,6 +8,10 @@
namespace lithium\tests\cases\console;
+<<<<<<< HEAD
+=======
+use lithium\core\Libraries;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
use lithium\console\Response;
use lithium\console\Request;
@@ -17,8 +21,8 @@ class ResponseTest extends \lithium\test\Unit {
public function setUp() {
$this->streams = array(
- 'output' => LITHIUM_APP_PATH . '/resources/tmp/tests/output.txt',
- 'error' => LITHIUM_APP_PATH . '/resources/tmp/tests/error.txt'
+ 'output' => Libraries::get(true, 'resources') . '/tmp/tests/output.txt',
+ 'error' => Libraries::get(true, 'resources') . '/tmp/tests/error.txt'
);
}
@@ -33,15 +37,14 @@ class ResponseTest extends \lithium\test\Unit {
public function testConstructWithoutConfig() {
$response = new Response();
$this->assertTrue(is_resource($response->output));
-
$this->assertTrue(is_resource($response->error));
}
public function testConstructWithConfigOutput() {
- $base = LITHIUM_APP_PATH . '/resources/tmp/tests';
+ $base = Libraries::get(true, 'resources') . '/tmp/tests';
$this->skipIf(!is_writable($base), "{$base} is not writable.");
-
$stream = fopen($this->streams['output'], 'w');
+
$response = new Response(array(
'output' => $stream
));
@@ -50,53 +53,36 @@ class ResponseTest extends \lithium\test\Unit {
}
- public function testConstructWithConfigErrror() {
- $base = LITHIUM_APP_PATH . '/resources/tmp/tests';
+ public function testConstructWithConfigError() {
+ $base = Libraries::get(true, 'resources') . '/tmp/tests';
$this->skipIf(!is_writable($base), "{$base} is not writable.");
$stream = fopen($this->streams['error'], 'w');
- $response = new Response(array(
- 'error' => $stream
- ));
+ $response = new Response(array('error' => $stream));
$this->assertTrue(is_resource($response->error));
$this->assertEqual($stream, $response->error);
-
}
public function testOutput() {
- $base = LITHIUM_APP_PATH . '/resources/tmp/tests';
+ $base = Libraries::get(true, 'resources') . '/tmp/tests';
$this->skipIf(!is_writable($base), "{$base} is not writable.");
- $response = new Response(array(
- 'output' => fopen($this->streams['output'], 'w+')
- ));
+ $response = new Response(array('output' => fopen($this->streams['output'], 'w+')));
$this->assertTrue(is_resource($response->output));
- $expected = 2;
- $result = $response->output('ok');
- $this->assertEqual($expected, $result);
- $expected = 'ok';
- $result = file_get_contents($this->streams['output']);
- $this->assertEqual($expected, $result);
+ $this->assertEqual(2, $response->output('ok'));
+ $this->assertEqual('ok', file_get_contents($this->streams['output']));
}
public function testError() {
- $base = LITHIUM_APP_PATH . '/resources/tmp/tests';
+ $base = Libraries::get(true, 'resources') . '/tmp/tests';
$this->skipIf(!is_writable($base), "{$base} is not writable.");
- $response = new Response(array(
- 'error' => fopen($this->streams['error'], 'w+')
- ));
+ $response = new Response(array('error' => fopen($this->streams['error'], 'w+')));
$this->assertTrue(is_resource($response->error));
-
- $expected = 2;
- $result = $response->error('ok');
- $this->assertEqual($expected, $result);
-
- $expected = 'ok';
- $result = file_get_contents($this->streams['error']);
- $this->assertEqual($expected, $result);
+ $this->assertEqual(2, $response->error('ok'));
+ $this->assertEqual('ok', file_get_contents($this->streams['error']));
}
}
diff --git a/libraries/lithium/tests/cases/console/command/CreateTest.php b/libraries/lithium/tests/cases/console/command/CreateTest.php
index f362397..deee0ca 100644
--- a/libraries/lithium/tests/cases/console/command/CreateTest.php
+++ b/libraries/lithium/tests/cases/console/command/CreateTest.php
@@ -22,7 +22,7 @@ class CreateTest extends \lithium\test\Unit {
protected $_testPath = null;
public function skip() {
- $this->_testPath = LITHIUM_APP_PATH . '/resources/tmp/tests';
+ $this->_testPath = Libraries::get(true, 'resources') . '/tmp/tests';
$this->skipIf(!is_writable($this->_testPath), "{$this->_testPath} is not writable.");
}
@@ -63,9 +63,8 @@ class CreateTest extends \lithium\test\Unit {
$this->request->params['args'] = array('does_not_exist', 'anywhere');
$create = new MockCreate(array('request' => $this->request));
- $expected = false;
$result = $create->run('does_not_exist');
- $this->assertEqual($expected, $result);
+ $this->assertFalse($result);
$expected = "does_not_exist could not be created.\n";
$result = $create->response->error;
@@ -106,9 +105,8 @@ class CreateTest extends \lithium\test\Unit {
public function testRunWithoutCommand() {
$create = new MockCreate(array('request' => $this->request));
- $expected = false;
$result = $create->run();
- $this->assertEqual($expected, $result);
+ $this->assertFalse($result);
$expected = "What would you like to create? (model/view/controller/test/mock) \n > ";
$result = $create->response->output;
@@ -122,9 +120,8 @@ class CreateTest extends \lithium\test\Unit {
);
$create = new MockCreate(array('request' => $this->request));
- $expected = false;
$result = $create->run('model');
- $this->assertEqual($expected, $result);
+ $this->assertFalse($result);
$expected = "model could not be created.\n";
$result = $create->response->error;
diff --git a/libraries/lithium/tests/cases/console/command/HelpTest.php b/libraries/lithium/tests/cases/console/command/HelpTest.php
index e8023b5..5fe4777 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,105 @@ class HelpTest extends \lithium\test\Unit {
}
public function testRun() {
- $help = new Help(array(
- 'request' => $this->request, 'classes' => $this->classes
- ));
- $expected = true;
- $result = $help->run();
- $this->assertEqual($expected, $result);
+ $command = new Help(array('request' => $this->request, 'classes' => $this->classes));
+ $this->assertTrue($command->run());
$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');
- $this->assertEqual($expected, $result);
+ $result = $command->run('Test');
+ $this->assertTrue($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');
- $this->assertEqual($expected, $result);
+ $result = $command->api('lithium.util.Inflector');
+ $this->assertNull($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');
- $this->assertEqual($expected, $result);
+ $result = $command->api('lithium.util.Inflector', 'method');
+ $this->assertNull($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');
- $this->assertEqual($expected, $result);
+ $result = $command->api('lithium.util.Inflector', 'method', 'rules');
+ $this->assertNull($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');
- $this->assertEqual($expected, $result);
+ $result = $command->api('lithium.net.Message', 'property');
+ $this->assertNull($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');
- $this->assertEqual($expected, $result);
+ $result = $command->api('lithium.net.Message', 'property');
+ $this->assertNull($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..7fc2082 100644
--- a/libraries/lithium/tests/cases/console/command/LibraryTest.php
+++ b/libraries/lithium/tests/cases/console/command/LibraryTest.php
@@ -22,7 +22,7 @@ class LibraryTest extends \lithium\test\Unit {
protected $_testPath = null;
public function skip() {
- $this->_testPath = LITHIUM_APP_PATH . '/resources/tmp/tests';
+ $this->_testPath = Libraries::get(true, 'resources') . '/tmp/tests';
$this->skipIf(!is_writable($this->_testPath), "{$this->_testPath} is not writable.");
}
@@ -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);
@@ -86,9 +84,8 @@ class LibraryTest extends \lithium\test\Unit {
$this->skipIf(!extension_loaded('zlib'), 'The zlib extension is not loaded.');
$this->library->library = 'library_test';
- $expected = true;
$result = $this->library->extract($this->_testPath . '/library_test');
- $this->assertEqual($expected, $result);
+ $this->assertTrue($result);
$expected = "library_test created in {$this->_testPath} from ";
$expected .= realpath(LITHIUM_LIBRARY_PATH)
@@ -106,10 +103,9 @@ class LibraryTest extends \lithium\test\Unit {
$this->library->library = 'library_test';
- $expected = true;
$testPath = "{$this->_testPath}/library_test";
$result = $this->library->archive($testPath, $testPath);
- $this->assertEqual($expected, $result);
+ $this->assertTrue($result);
$expected = "library_test.phar.gz created in {$this->_testPath} from ";
$expected .= "{$this->_testPath}/library_test\n";
@@ -126,11 +122,10 @@ class LibraryTest extends \lithium\test\Unit {
);
$this->library->library = 'library_test';
- $expected = true;
$result = $this->library->extract(
$this->_testPath . '/library_test.phar.gz', $this->_testPath . '/new'
);
- $this->assertEqual($expected, $result);
+ $this->assertTrue($result);
$this->assertTrue(file_exists($this->_testPath . '/new'));
@@ -156,22 +151,20 @@ class LibraryTest extends \lithium\test\Unit {
);
chdir('new');
- $app = new Library(array(
- 'request' => new Request(), 'classes' => $this->classes
- ));
+ $app = new Library(array('request' => new Request(), 'classes' => $this->classes));
$app->library = 'does_not_exist';
- $expected = true;
$result = $app->archive();
- $this->assertEqual($expected, $result);
+ $this->assertTrue($result);
- $expected = "new.phar.gz created in {$this->_testPath} from ";
- $expected .= "{$this->_testPath}/new\n";
+ $path = realpath($this->_testPath);
+ $expected = "new.phar.gz created in {$path} from {$path}/new\n";
$result = $app->response->output;
$this->assertEqual($expected, $result);
Phar::unlinkArchive($this->_testPath . '/new.phar');
Phar::unlinkArchive($this->_testPath . '/new.phar.gz');
+
$this->_cleanUp('tests/new');
rmdir($this->_testPath . '/new');
}
@@ -179,20 +172,17 @@ class LibraryTest extends \lithium\test\Unit {
public function testExtractWhenLibraryDoesNotExist() {
$this->skipIf(!extension_loaded('zlib'), 'The zlib extension is not loaded.');
chdir($this->_testPath);
- $app = new Library(array(
- 'request' => new Request(), 'classes' => $this->classes
- ));
+ $app = new Library(array('request' => new Request(), 'classes' => $this->classes));
$app->library = 'does_not_exist';
- $expected = true;
$result = $app->extract();
- $this->assertEqual($expected, $result);
+ $this->assertTrue($result);
$this->assertTrue(file_exists($this->_testPath . '/new'));
- $expected = "new created in {$this->_testPath} from ";
- $expected .= realpath(LITHIUM_LIBRARY_PATH)
- . "/lithium/console/command/create/template/app.phar.gz\n";
+ $path = realpath($this->_testPath);
+ $tplPath = realpath(LITHIUM_LIBRARY_PATH) . '/lithium/console/command/create/template';
+ $expected = "new created in {$path} from {$tplPath}/app.phar.gz\n";
$result = $app->response->output;
$this->assertEqual($expected, $result);
@@ -204,9 +194,8 @@ class LibraryTest extends \lithium\test\Unit {
$this->library->library = 'library_plugin_test';
$path = $this->_testPath;
- $expected = true;
$result = $this->library->extract('plugin', "{$path}/library_test_plugin");
- $this->assertEqual($expected, $result);
+ $this->assertTrue($result);
$expected = "library_test_plugin created in {$path} from " . realpath(LITHIUM_LIBRARY_PATH);
$expected .= "/lithium/console/command/create/template/plugin.phar.gz\n";
@@ -607,9 +596,8 @@ test;
$this->library->library = 'library_plugin_test';
$path = $this->_testPath;
- $expected = true;
$result = $this->library->extract('plugin', "{$path}/library_test_plugin");
- $this->assertEqual($expected, $result);
+ $this->assertTrue($result);
$this->library->response->output = null;
$file = $this->_testPath . '/library_test_plugin/config/library_test_plugin.json';
diff --git a/libraries/lithium/tests/cases/console/command/RouteTest.php b/libraries/lithium/tests/cases/console/command/RouteTest.php
new file mode 100644
index 0000000..ae3ae48
--- /dev/null
+++ b/libraries/lithium/tests/cases/console/command/RouteTest.php
@@ -0,0 +1,289 @@
+<?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\cases\console\command;
+
+use lithium\console\command\Route;
+use lithium\console\Request;
+use lithium\net\http\Router;
+
+/**
+ * The RouteTest class tests the "li3 route" command.
+ */
+class RouteTest extends \lithium\test\Unit {
+
+ /**
+ * Holds config params.
+ *
+ * @var array
+ */
+ protected $_config = array('routes_file' => '');
+
+ /**
+ * Holds the temporary test path.
+ *
+ * @var string
+ */
+ protected $_testPath = null;
+
+ /**
+ * Set the testPath and check if it is writable (skip if not).
+ */
+ public function skip() {
+ $this->_testPath = LITHIUM_APP_PATH . '/resources/tmp/tests';
+ $this->skipIf(!is_writable($this->_testPath), "{$this->_testPath} is not writable.");
+ }
+
+ /**
+ * Create a temporary routes.php file for testing and reset the router.
+ */
+ public function setUp() {
+ $this->_config['routes_file'] = "{$this->_testPath}/routes.php";
+
+ $testParams = 'array("controller" => "lithium\test\Controller")';
+ $content = array(
+ '<?php',
+ 'use lithium\net\http\Router;',
+ 'use lithium\core\Environment;',
+ 'Router::connect("/", "Pages::view");',
+ 'Router::connect("/pages/{:args}", "Pages::view");',
+ 'if (!Environment::is("production")) {',
+ 'Router::connect("/test/{:args}", ' . $testParams . ');',
+ 'Router::connect("/test", ' . $testParams . ');',
+ '}',
+ '?>'
+ );
+ file_put_contents($this->_config['routes_file'], join("\n", $content));
+
+ Router::reset();
+ }
+
+ /**
+ * Delete the temporary routes.php file.
+ */
+ public function tearDown() {
+ if (file_exists($this->_config['routes_file'])) {
+ unlink($this->_config['routes_file']);
+ }
+ }
+
+ /**
+ * Tests if the default environment is loaded correctly
+ * and if overriding works as expected.
+ */
+ public function testEnvironment() {
+ $command = new Route();
+ $expected = 'development';
+ $this->assertEqual($expected, $command->env);
+
+ $request = new Request();
+ $request->params['env'] = 'production';
+ $command = new Route(array('request' => $request));
+ $expected = 'production';
+ $this->assertEqual($expected, $command->env);
+ }
+
+ /**
+ * Test if the routes.php file is loaded correctly and the
+ * routes are connected to the router.
+ */
+ public function testRouteLoading() {
+ $this->assertFalse(Router::get());
+
+ $command = new Route(array('routes_file' => $this->_config['routes_file']));
+ $this->assertEqual(4, count(Router::get()));
+
+ Router::reset();
+
+ $request = new Request();
+ $request->params['env'] = 'production';
+ $command = new Route(array(
+ 'routes_file' => $this->_config['routes_file'],
+ 'request' => $request
+ ));
+ $this->assertEqual(2, count(Router::get()));
+ }
+
+ /**
+ * Tests the "all" command without an env param.
+ *
+ * Don't be confused if the expected output doesn't make sense here. We are
+ * stripping the whitespace away so that this source code is easier to read.
+ * Built-In methods are used for output formatting and are tested elsewhere.
+ */
+ public function testAllWithoutEnvironment() {
+ $command = new Route(array(
+ 'routes_file' => $this->_config['routes_file'],
+ 'classes' => array('response' => '\lithium\tests\mocks\console\MockResponse'),
+ 'request' => new Request()
+ ));
+
+ $command->all();
+
+ $expected = 'TemplateParams--------------
+ /{"controller":"pages","action":"view"}
+ /pages/{:args}{"controller":"pages","action":"view"}
+ /test/{:args}{"controller":"lithium\\test\\\\Controller","action":"index"}
+ /test{"controller":"lithium\\test\\\\Controller","action":"index"}';
+ $this->assertEqual($this->_strip($expected),$this->_strip($command->response->output));
+ }
+
+ /**
+ * Tests the "all" command with an env (production) param.
+ *
+ * Don't be confused if the expected output doesn't make sense here. We are
+ * stripping the whitespace away so that this source code is easier to read.
+ * Built-In methods are used for output formatting and are tested elsewhere.
+ */
+ public function testAllWithEnvironment() {
+ $request = new Request();
+ $request->params = array(
+ 'env' => 'production'
+ );
+ $command = new Route(array(
+ 'routes_file' => $this->_config['routes_file'],
+ 'classes' => array('response' => '\lithium\tests\mocks\console\MockResponse'),
+ 'request' => $request
+ ));
+
+ $command->all();
+
+ $expected = 'TemplateParams--------------
+ /{"controller":"pages","action":"view"}
+ /pages/{:args}{"controller":"pages","action":"view"}';
+ $this->assertEqual($this->_strip($expected),$this->_strip($command->response->output));
+ }
+
+ /**
+ * Test the alias method for "all".
+ */
+ public function testRun() {
+ $command = new Route(array(
+ 'routes_file' => $this->_config['routes_file'],
+ 'classes' => array('response' => '\lithium\tests\mocks\console\MockResponse'),
+ 'request' => new Request()
+ ));
+
+ $command->run();
+
+ $expected = 'TemplateParams--------------
+ /{"controller":"pages","action":"view"}
+ /pages/{:args}{"controller":"pages","action":"view"}
+ /test/{:args}{"controller":"lithium\\test\\\\Controller","action":"index"}
+ /test{"controller":"lithium\\test\\\\Controller","action":"index"}';
+ $this->assertEqual($this->_strip($expected),$this->_strip($command->response->output));
+ }
+
+ /**
+ * Test the show command with no route.
+ */
+ public function testShowWithNoRoute() {
+ $command = new Route(array(
+ 'routes_file' => $this->_config['routes_file'],
+ 'classes' => array('response' => '\lithium\tests\mocks\console\MockResponse'),
+ 'request' => new Request()
+ ));
+
+ $command->show();
+
+ $expected = "Please provide a valid URL\n";
+ $this->assertEqual($expected, $command->response->error);
+ }
+
+ /**
+ * Test the show command with an invalid route.
+ */
+ public function testShowWithInvalidRoute() {
+ $request = new Request();
+ $request->params = array(
+ 'args' => array('/foobar')
+ );
+ $command = new Route(array(
+ 'routes_file' => $this->_config['routes_file'],
+ 'classes' => array('response' => '\lithium\tests\mocks\console\MockResponse'),
+ 'request' => $request
+ ));
+ $command->show();
+
+ $expected = "No route found.\n";
+ $this->assertEqual($expected, $command->response->output);
+ }
+
+ /**
+ * Test the show command with a valid route.
+ */
+ public function testShowWithValidRoute() {
+ $request = new Request();
+ $request->params = array('args' => array('/'));
+ $command = new Route(array(
+ 'routes_file' => $this->_config['routes_file'],
+ 'classes' => array('response' => '\lithium\tests\mocks\console\MockResponse'),
+ 'request' => $request
+ ));
+ $command->show();
+
+ $expected = "{\"controller\":\"pages\",\"action\":\"view\"}\n";
+ $this->assertEqual($expected, $command->response->output);
+ }
+
+ /**
+ * Test the show command with a env param.
+ */
+ public function testShowWithEnvironment() {
+ $request = new Request();
+ $request->params = array(
+ 'env' => 'production',
+ 'args' => array('/test')
+ );
+ $command = new Route(array(
+ 'routes_file' => $this->_config['routes_file'],
+ 'classes' => array('response' => '\lithium\tests\mocks\console\MockResponse'),
+ 'request' => $request
+ ));
+
+ $command->show();
+
+ $expected = "No route found.\n";
+ $this->assertEqual($expected, $command->response->output);
+ }
+
+ /**
+ * Test the show command with http method.
+ *
+ * This tests a call similar to "li3 route GET /".
+ */
+ public function testShowWithHttpMethod() {
+ $request = new Request();
+ $request->params = array(
+ 'args' => array('post', '/')
+ );
+ $command = new Route(array(
+ 'routes_file' => $this->_config['routes_file'],
+ 'classes' => array('response' => '\lithium\tests\mocks\console\MockResponse'),
+ 'request' => $request
+ ));
+
+ $command->show();
+
+ $expected = "{\"controller\":\"pages\",\"action\":\"view\"}\n";
+ $this->assertEqual($expected, $command->response->output);
+ }
+
+ /**
+ * Remove formatting whitespace, tabs and newlines for better sourcecode
+ * readability.
+ *
+ * @param string $str A string from which to strip spaces
+ * @return string Returns the value of `$str` with all whitespace removed.
+ */
+ protected function _strip($str) {
+ return preg_replace('/\s/', '', $str);
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/libraries/lithium/tests/cases/console/command/create/ControllerTest.php b/libraries/lithium/tests/cases/console/command/create/ControllerTest.php
index 5d5d286..e455d97 100644
--- a/libraries/lithium/tests/cases/console/command/create/ControllerTest.php
+++ b/libraries/lithium/tests/cases/console/command/create/ControllerTest.php
@@ -21,7 +21,7 @@ class ControllerTest extends \lithium\test\Unit {
protected $_testPath = null;
public function skip() {
- $this->_testPath = LITHIUM_APP_PATH . '/resources/tmp/tests';
+ $this->_testPath = Libraries::get(true, 'resources') . '/tmp/tests';
$this->skipIf(!is_writable($this->_testPath), "{$this->_testPath} is not writable.");
}
@@ -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/MockTest.php b/libraries/lithium/tests/cases/console/command/create/MockTest.php
index b391d7e..d09b5e1 100644
--- a/libraries/lithium/tests/cases/console/command/create/MockTest.php
+++ b/libraries/lithium/tests/cases/console/command/create/MockTest.php
@@ -22,7 +22,7 @@ class MockTest extends \lithium\test\Unit {
protected $_testPath = null;
public function skip() {
- $this->_testPath = LITHIUM_APP_PATH . '/resources/tmp/tests';
+ $this->_testPath = Libraries::get(true, 'resources') . '/tmp/tests';
$this->skipIf(!is_writable($this->_testPath), "{$this->_testPath} is not writable.");
}
diff --git a/libraries/lithium/tests/cases/console/command/create/ModelTest.php b/libraries/lithium/tests/cases/console/command/create/ModelTest.php
index 2f9a34a..f85b413 100644
--- a/libraries/lithium/tests/cases/console/command/create/ModelTest.php
+++ b/libraries/lithium/tests/cases/console/command/create/ModelTest.php
@@ -21,7 +21,7 @@ class ModelTest extends \lithium\test\Unit {
protected $_testPath = null;
public function skip() {
- $this->_testPath = LITHIUM_APP_PATH . '/resources/tmp/tests';
+ $this->_testPath = Libraries::get(true, 'resources') . '/tmp/tests';
$this->skipIf(!is_writable($this->_testPath), "{$this->_testPath} is not readable.");
}
diff --git a/libraries/lithium/tests/cases/console/command/create/TestTest.php b/libraries/lithium/tests/cases/console/command/create/TestTest.php
index 9dd5ba3..f1983d7 100644
--- a/libraries/lithium/tests/cases/console/command/create/TestTest.php
+++ b/libraries/lithium/tests/cases/console/command/create/TestTest.php
@@ -22,7 +22,7 @@ class TestTest extends \lithium\test\Unit {
protected $_testPath = null;
public function skip() {
- $this->_testPath = LITHIUM_APP_PATH . '/resources/tmp/tests';
+ $this->_testPath = Libraries::get(true, 'resources') . '/tmp/tests';
$this->skipIf(!is_writable($this->_testPath), "{$this->_testPath} is not writable.");
}
@@ -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}"
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
));
+ $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/console/command/create/ViewTest.php b/libraries/lithium/tests/cases/console/command/create/ViewTest.php
index d30058f..875a913 100644
--- a/libraries/lithium/tests/cases/console/command/create/ViewTest.php
+++ b/libraries/lithium/tests/cases/console/command/create/ViewTest.php
@@ -22,7 +22,7 @@ class ViewTest extends \lithium\test\Unit {
protected $_testPath = null;
public function skip() {
- $this->_testPath = LITHIUM_APP_PATH . '/resources/tmp/tests';
+ $this->_testPath = Libraries::get(true, 'resources') . '/tmp/tests';
$this->skipIf(!is_writable($this->_testPath), "{$this->_testPath} is not writable.");
}
@@ -57,9 +57,8 @@ class ViewTest extends \lithium\test\Unit {
$result = $view->response->output;
$this->assertEqual($expected, $result);
- $expected = true;
$result = file_exists($this->_testPath . '/create_test/views/posts/index.html.php');
- $this->assertEqual($expected, $result);
+ $this->assertTrue($result);
}
}
diff --git a/libraries/lithium/tests/cases/console/command/g11n/ExtractTest.php b/libraries/lithium/tests/cases/console/command/g11n/ExtractTest.php
index 80d26f9..dfdfe7e 100644
--- a/libraries/lithium/tests/cases/console/command/g11n/ExtractTest.php
+++ b/libraries/lithium/tests/cases/console/command/g11n/ExtractTest.php
@@ -8,6 +8,10 @@
namespace lithium\tests\cases\console\command\g11n;
+<<<<<<< HEAD
+=======
+use lithium\core\Libraries;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
use lithium\console\Request;
use lithium\console\command\g11n\Extract;
@@ -18,7 +22,7 @@ class ExtractTest extends \lithium\test\Unit {
public $command;
public function skip() {
- $this->_path = LITHIUM_APP_PATH . '/resources/tmp/tests';
+ $this->_path = Libraries::get(true, 'resources') . '/tmp/tests';
$this->skipIf(!is_writable($this->_path), "{$this->_path} is not writable.");
}
@@ -38,7 +42,11 @@ class ExtractTest extends \lithium\test\Unit {
public function testInit() {
$command = new Extract();
$this->assertEqual(LITHIUM_APP_PATH, $command->source);
+<<<<<<< HEAD
$this->assertEqual(LITHIUM_APP_PATH . '/resources/g11n', $command->destination);
+=======
+ $this->assertEqual(Libraries::get(true, 'resources') . '/g11n', $command->destination);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
public function testFailRead() {
diff --git a/libraries/lithium/tests/cases/core/AdaptableTest.php b/libraries/lithium/tests/cases/core/AdaptableTest.php
index f2bf019..b99a5bd 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;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
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;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
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..9d858de 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;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
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,
@@ -105,6 +113,45 @@ class ErrorHandlerTest extends \lithium\test\Unit {
ErrorHandler::reset();
$this->assertEqual(array(), ErrorHandler::handlers());
}
+
+ public function testApply() {
+ $subject = new ErrorHandlerTest();
+ ErrorHandler::apply(array($subject, 'throwException'), array(), function($details) {
+ return $details['exception']->getMessage();
+ });
+ $this->assertEqual('foo', $subject->throwException());
+ }
+
+ public function throwException() {
+ return $this->_filter(__METHOD__, array(), function($self, $params) {
+ throw new Exception('foo');
+ return 'bar';
+ });
+ }
+
+ public function testTrace() {
+ $current = debug_backtrace();
+ $results = ErrorHandler::trace($current);
+ $this->assertEqual(count($current), count($results));
+ $this->assertEqual($results[0], 'lithium\tests\cases\core\ErrorHandlerTest::testTrace');
+ }
+
+ public function testRun() {
+ ErrorHandler::stop();
+ $this->assertEqual(ErrorHandler::isRunning(), false);
+ ErrorHandler::run();
+ $this->assertEqual(ErrorHandler::isRunning(), true);
+ ErrorHandler::stop();
+ $this->assertEqual(ErrorHandler::isRunning(), false);
+ }
+
+ public function testErrorTrapping() {
+ ErrorHandler::stop();
+ ErrorHandler::run(array('trapErrors' => true));
+
+ // Undefined offset error shouldn't surface.
+ list($foo, $bar) = array('baz');
+ }
}
?>
\ No newline at end of file
diff --git a/libraries/lithium/tests/cases/core/LibrariesTest.php b/libraries/lithium/tests/cases/core/LibrariesTest.php
index f81a13d..d526690 100644
--- a/libraries/lithium/tests/cases/core/LibrariesTest.php
+++ b/libraries/lithium/tests/cases/core/LibrariesTest.php
@@ -8,14 +8,32 @@
namespace lithium\tests\cases\core;
+<<<<<<< HEAD
use \SplFileInfo;
+=======
+use stdClass;
+use SplFileInfo;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
use lithium\util\Inflector;
use lithium\core\Libraries;
class LibrariesTest extends \lithium\test\Unit {
+<<<<<<< HEAD
+ public function tearDown() {
+ Libraries::cache(false);
+=======
+ protected $_cache = array();
+
+ public function setUp() {
+ $this->_cache = Libraries::cache();
+ Libraries::cache(false);
+ }
+
public function tearDown() {
Libraries::cache(false);
+ Libraries::cache($this->_cache);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
public function testNamespaceToFileTranslation() {
@@ -23,6 +41,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 +161,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');
}
@@ -148,7 +171,7 @@ class LibrariesTest extends \lithium\test\Unit {
* @return void
*/
public function testAddNonPrefixedLibrary() {
- $tmpDir = realpath(LITHIUM_APP_PATH . '/resources/tmp');
+ $tmpDir = realpath(Libraries::get(true, 'resources') . '/tmp');
$this->skipIf(!is_writable($tmpDir), "Can't write to resources directory.");
$fakeDir = $tmpDir . '/fake';
@@ -215,7 +238,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);
}
@@ -321,6 +344,7 @@ class LibrariesTest extends \lithium\test\Unit {
$this->assertTrue(in_array('lithium\test\filter\Coverage', $result));
$this->assertTrue(in_array('lithium\test\filter\Profiler', $result));
<<<<<<< HEAD
+<<<<<<< HEAD
foreach (Libraries::paths() as $type => $paths) {
if (count($paths) <= 1 || $type == 'libraries') {
@@ -330,12 +354,18 @@ class LibrariesTest extends \lithium\test\Unit {
}
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
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.");
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$result = Libraries::instance('adapter.template.view', 'Foo');
}
@@ -378,7 +408,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);
}
@@ -489,6 +519,7 @@ class LibrariesTest extends \lithium\test\Unit {
}
<<<<<<< HEAD
+<<<<<<< HEAD
public function testLocatePreFilter() {
$result = Libraries::locate('command', null, array('recursive' => false));
$this->assertFalse(preg_grep('/\.txt/', $result));
@@ -496,12 +527,18 @@ class LibrariesTest extends \lithium\test\Unit {
$result = Libraries::locate('command', null, array('recursive' => true));
$this->assertFalse(preg_grep('/\.txt/', $result));
=======
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
public function testLocateCommandInLithium() {
$expected = array(
'lithium\console\command\Create',
'lithium\console\command\G11n',
'lithium\console\command\Help',
'lithium\console\command\Library',
+<<<<<<< HEAD
+=======
+ 'lithium\console\command\Route',
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
'lithium\console\command\Test'
);
$result = Libraries::locate('command', null, array(
@@ -516,6 +553,10 @@ class LibrariesTest extends \lithium\test\Unit {
'lithium\console\command\G11n',
'lithium\console\command\Help',
'lithium\console\command\Library',
+<<<<<<< HEAD
+=======
+ 'lithium\console\command\Route',
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
'lithium\console\command\Test',
'lithium\console\command\g11n\Extract',
'lithium\console\command\create\Controller',
@@ -548,12 +589,21 @@ class LibrariesTest extends \lithium\test\Unit {
}
public function testLocateWithTestAppLibrary() {
+<<<<<<< HEAD
$test_app = LITHIUM_APP_PATH . '/resources/tmp/tests/test_app';
mkdir($test_app);
Libraries::add('test_app', array('path' => $test_app));
mkdir($test_app . '/tests/cases/models', 0777, true);
file_put_contents($test_app . '/tests/cases/models/UserTest.php',
+=======
+ $testApp = Libraries::get(true, 'resources') . '/tmp/tests/test_app';
+ mkdir($testApp);
+ Libraries::add('test_app', array('path' => $testApp));
+
+ mkdir($testApp . '/tests/cases/models', 0777, true);
+ file_put_contents($testApp . '/tests/cases/models/UserTest.php',
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
"<?php namespace test_app\\tests\\cases\\models;\n
class UserTest extends \\lithium\\test\\Unit { public function testMe() {
\$this->assertTrue(true);
@@ -566,7 +616,24 @@ class LibrariesTest extends \lithium\test\Unit {
$this->assertEqual($expected, $result);
$this->_cleanUp();
+<<<<<<< HEAD
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ }
+
+ /**
+ * Tests that `Libraries::realPath()` correctly resolves paths to files inside Phar archives.
+ *
+ * @return void
+ */
+ public function testPathsInPharArchives() {
+ $base = Libraries::get('lithium', 'path');
+ $path = "{$base}/console/command/create/template/app.phar.gz";
+
+ $expected = "phar://{$path}/controllers/HelloWorldController.php";
+ $result = Libraries::realPath($expected);
+ $this->assertEqual($expected, $result);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
}
diff --git a/libraries/lithium/tests/cases/core/ObjectTest.php b/libraries/lithium/tests/cases/core/ObjectTest.php
index bc80b7f..5c30fd2 100644
--- a/libraries/lithium/tests/cases/core/ObjectTest.php
+++ b/libraries/lithium/tests/cases/core/ObjectTest.php
@@ -9,6 +9,7 @@
namespace lithium\tests\cases\core;
use lithium\core\Object;
+use lithium\tests\mocks\core\MockRequest;
use lithium\tests\mocks\core\MockMethodFiltering;
use lithium\tests\mocks\core\MockExposed;
use lithium\tests\mocks\core\MockCallable;
@@ -193,7 +194,7 @@ class ObjectTest extends \lithium\test\Unit {
public function testInstanceWithObject() {
$object = new MockInstantiator();
- $request = new \lithium\tests\mocks\core\MockRequest();
+ $request = new MockRequest();
$expected = 'lithium\tests\mocks\core\MockRequest';
$result = get_class($object->instance($request));
$this->assertEqual($expected, $result);
@@ -201,8 +202,8 @@ class ObjectTest extends \lithium\test\Unit {
public function testInstanceFalse() {
$object = new MockInstantiator();
- $result = $object->instance(false);
- $this->assertFalse($result);
+ $this->expectException('/^Invalid class lookup/');
+ $object->instance(false);
}
}
diff --git a/libraries/lithium/tests/cases/core/StaticObjectTest.php b/libraries/lithium/tests/cases/core/StaticObjectTest.php
index a6c6fb9..085369c 100644
--- a/libraries/lithium/tests/cases/core/StaticObjectTest.php
+++ b/libraries/lithium/tests/cases/core/StaticObjectTest.php
@@ -9,6 +9,10 @@
namespace lithium\tests\cases\core;
use lithium\core\StaticObject;
+<<<<<<< HEAD
+=======
+use lithium\tests\mocks\core\MockRequest;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
use lithium\tests\mocks\core\MockStaticInstantiator;
class StaticObjectTest extends \lithium\test\Unit {
@@ -151,15 +155,15 @@ class StaticObjectTest extends \lithium\test\Unit {
}
public function testInstanceWithObject() {
- $request = new \lithium\tests\mocks\core\MockRequest();
+ $request = new MockRequest();
$expected = 'lithium\tests\mocks\core\MockRequest';
$result = get_class(MockStaticInstantiator::instance($request));
$this->assertEqual($expected, $result);
}
public function testInstanceFalse() {
- $result = MockStaticInstantiator::instance(false);
- $this->assertFalse($result);
+ $this->expectException('/^Invalid class lookup/');
+ MockStaticInstantiator::instance(false);
}
}
diff --git a/libraries/lithium/tests/cases/data/CollectionTest.php b/libraries/lithium/tests/cases/data/CollectionTest.php
index 748f82d..d2a342a 100644
--- a/libraries/lithium/tests/cases/data/CollectionTest.php
+++ b/libraries/lithium/tests/cases/data/CollectionTest.php
@@ -33,6 +33,79 @@ class CollectionTest extends \lithium\test\Unit {
$collection = new DocumentSet(compact('model'));
$this->assertEqual($model, $collection->model());
$this->assertEqual(compact('model'), $collection->meta());
+<<<<<<< HEAD
+=======
+ }
+
+ public function testOffsetExists() {
+ $collection = new DocumentSet();
+ $this->assertEqual($collection->offsetExists(0), false);
+ $collection->set(array('foo' => 'bar', 'bas' => 'baz'));
+ $this->assertEqual($collection->offsetExists(0), true);
+ $this->assertEqual($collection->offsetExists(1), true);
+ }
+
+ public function testNextRewindCurrent() {
+ $collection = new DocumentSet();
+ $collection->set(array(
+ 'title' => 'Lorem Ipsum',
+ 'value' => 42,
+ 'foo' => 'bar'
+ ));
+ $this->assertEqual('Lorem Ipsum', $collection->current());
+ $this->assertEqual(42, $collection->next());
+ $this->assertEqual('bar', $collection->next());
+ $this->assertEqual('Lorem Ipsum', $collection->rewind());
+ $this->assertEqual(42, $collection->next());
+ }
+
+ public function testEach() {
+ $collection = new DocumentSet();
+ $collection->set(array(
+ 'title' => 'Lorem Ipsum',
+ 'key' => 'value',
+ 'foo' => 'bar'
+ ));
+ $collection->each(function($value) {
+ return $value . ' test';
+ });
+ $expected = array(
+ 'Lorem Ipsum test',
+ 'value test',
+ 'bar test'
+ );
+ $this->assertEqual($collection->to('array'), $expected);
+ }
+
+ public function testMap() {
+ $collection = new DocumentSet();
+ $collection->set(array(
+ 'title' => 'Lorem Ipsum',
+ 'key' => 'value',
+ 'foo' => 'bar'
+ ));
+ $results = $collection->map(function($value) {
+ return $value . ' test';
+ });
+ $expected = array(
+ 'Lorem Ipsum test',
+ 'value test',
+ 'bar test'
+ );
+ $this->assertEqual($results->to('array'), $expected);
+ $this->assertNotEqual($results->to('array'), $collection->to('array'));
+ }
+
+ public function testData() {
+ $collection = new DocumentSet();
+ $data = array(
+ 'Lorem Ipsum',
+ 'value',
+ 'bar'
+ );
+ $collection->set($data);
+ $this->assertEqual($data, $collection->data());
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
}
diff --git a/libraries/lithium/tests/cases/data/EntityTest.php b/libraries/lithium/tests/cases/data/EntityTest.php
index 6c1f597..ee2ff87 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`.$/");
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$entity->foo();
}
diff --git a/libraries/lithium/tests/cases/data/ModelTest.php b/libraries/lithium/tests/cases/data/ModelTest.php
index 6f4f00f..950d85c 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;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
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;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
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/');
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
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() {
@@ -469,10 +494,14 @@ class ModelTest extends \lithium\test\Unit {
$keys = array_keys(array_filter($query->export(Connections::get('mock-source'))));
<<<<<<< HEAD
+<<<<<<< HEAD
$this->assertEqual(array('name', 'conditions', 'model', 'source', 'type'), $keys);
=======
$this->assertEqual(array('type', 'name', 'conditions', 'model', 'source'), $keys);
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ $this->assertEqual(array('type', 'name', 'conditions', 'model', 'source'), $keys);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
public function testFindFirst() {
@@ -506,6 +535,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..77bb4cc 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());
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
}
diff --git a/libraries/lithium/tests/cases/data/collection/DocumentSetTest.php b/libraries/lithium/tests/cases/data/collection/DocumentSetTest.php
index daef72c..12cfaa8 100644
--- a/libraries/lithium/tests/cases/data/collection/DocumentSetTest.php
+++ b/libraries/lithium/tests/cases/data/collection/DocumentSetTest.php
@@ -37,6 +37,7 @@ class DocumentSetTest extends \lithium\test\Unit {
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
Connections::add('mongo', array('type' => 'MongoDb'));
=======
Connections::add('mongo', array('type' => 'MongoDb', 'autoConnect' => false));
@@ -44,6 +45,9 @@ class DocumentSetTest extends \lithium\test\Unit {
=======
Connections::add('mongo', array('type' => 'MongoDb', 'autoConnect' => false));
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ Connections::add('mongo', array('type' => 'MongoDb', 'autoConnect' => false));
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
Connections::add('couch', array('type' => 'http', 'adapter' => 'CouchDb'));
MockDocumentPost::config(array('connection' => 'mongo'));
@@ -78,7 +82,10 @@ class DocumentSetTest extends \lithium\test\Unit {
$this->assertNull($doc->next());
}
<<<<<<< HEAD
+<<<<<<< HEAD
=======
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
public function testMappingToNewDocumentSet() {
$result = new MockResult();
@@ -90,7 +97,10 @@ class DocumentSetTest extends \lithium\test\Unit {
$this->assertEqual($model, $doc->model());
$this->assertEqual($model, $mapped->model());
}
+<<<<<<< HEAD
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
?>
\ No newline at end of file
diff --git a/libraries/lithium/tests/cases/data/entity/DocumentTest.php b/libraries/lithium/tests/cases/data/entity/DocumentTest.php
index ece9e28..901e2d5 100644
--- a/libraries/lithium/tests/cases/data/entity/DocumentTest.php
+++ b/libraries/lithium/tests/cases/data/entity/DocumentTest.php
@@ -9,11 +9,16 @@
namespace lithium\tests\cases\data\entity;
<<<<<<< HEAD
+<<<<<<< HEAD
use stdClass;
=======
use MongoId;
use MongoDate;
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+use MongoId;
+use MongoDate;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
use lithium\data\Connections;
use lithium\data\entity\Document;
use lithium\data\collection\DocumentSet;
@@ -38,6 +43,7 @@ class DocumentTest extends \lithium\test\Unit {
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
Connections::add('mongo', array('type' => 'MongoDb'));
=======
Connections::add('mongo', array('type' => 'MongoDb', 'autoConnect' => false));
@@ -45,6 +51,9 @@ class DocumentTest extends \lithium\test\Unit {
=======
Connections::add('mongo', array('type' => 'MongoDb', 'autoConnect' => false));
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ Connections::add('mongo', array('type' => 'MongoDb', 'autoConnect' => false));
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
Connections::add('couch', array('type' => 'http', 'adapter' => 'CouchDb'));
MockDocumentPost::config(array('connection' => 'mongo'));
@@ -361,7 +370,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);
}
@@ -451,9 +460,8 @@ class DocumentTest extends \lithium\test\Unit {
$result = $doc->data('title');
$this->assertEqual($expected, $result);
- $expected = false;
$result = $doc->data('permanent');
- $this->assertEqual($expected, $result);
+ $this->assertFalse($result);
$doc = new Document();
$this->assertNull($doc->data('field'));
@@ -545,7 +553,10 @@ class DocumentTest extends \lithium\test\Unit {
}
<<<<<<< HEAD
+<<<<<<< HEAD
+=======
=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
public function testExport() {
$data = array('foo' => 'bar', 'baz' => 'dib');
$doc = new Document(compact('data') + array('exists' => false));
@@ -561,7 +572,10 @@ class DocumentTest extends \lithium\test\Unit {
$this->assertEqual($expected, $doc->export());
}
+<<<<<<< HEAD
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
/**
* Tests that a modified `Document` exports the proper fields in a newly-appended nested
* `Document`.
@@ -570,6 +584,7 @@ class DocumentTest extends \lithium\test\Unit {
*/
public function testModifiedExport() {
<<<<<<< HEAD
+<<<<<<< HEAD
$database = new MockDocumentSource();
$model = $this->_model;
$data = array('foo' => 'bar', 'baz' => 'dib');
@@ -596,6 +611,21 @@ class DocumentTest extends \lithium\test\Unit {
$this->assertEqual(1, count($newData['update']));
$this->assertTrue($newData['update']['nested'] instanceof Document);
+=======
+ $model = $this->_model;
+ $data = array('foo' => 'bar', 'baz' => 'dib');
+ $doc = new Document(compact('model', 'data') + array('exists' => false));
+
+ $doc->nested = array('more' => 'data');
+ $newData = $doc->export();
+
+ $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);
+
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$result = $newData['update']['nested']->export();
$this->assertFalse($result['exists']);
$this->assertEqual(array('more' => 'data'), $result['data']);
@@ -603,7 +633,10 @@ class DocumentTest extends \lithium\test\Unit {
$this->assertEqual('nested', $result['key']);
$doc = new Document(compact('model') + array('exists' => true, 'data' => array(
+<<<<<<< HEAD
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
'foo' => 'bar', 'baz' => 'dib'
)));
@@ -631,6 +664,10 @@ class DocumentTest extends \lithium\test\Unit {
$doc->more = 'cowbell';
$doc->nested->evenMore = 'cowbell';
$modified = $doc->export();
+<<<<<<< HEAD
+=======
+
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$expected = array('more' => 'cowbell');
$this->assertEqual($expected, $modified['update']);
$this->assertEqual(array('nested', 'foo', 'baz'), array_keys($modified['data']));
@@ -660,6 +697,32 @@ 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()));
+ }
+
+ public function testIdGetDoesNotSet() {
+ $document = MockDocumentPost::create();
+ $message = 'The `_id` key should not be set.';
+ $this->assertFalse(array_key_exists('_id', $document->data()), $message);
+
+ $document->_id == "";
+ $this->assertFalse(array_key_exists('_id', $document->data()), $message);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
}
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 e4a8f1c..8e59fbc 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,11 +282,14 @@ 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);
<<<<<<< HEAD
=======
+=======
+ $this->assertEqual("{foo}", $result);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
public function testRestrictedKeyExport() {
@@ -324,15 +328,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()));
+
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$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());
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
/**
@@ -385,10 +408,14 @@ class QueryTest extends \lithium\test\Unit {
$this->assertEqual(array('title' => '..'), $result['data']);
<<<<<<< HEAD
+<<<<<<< HEAD
$this->assertEqual("WHERE title = 'FML'", $result['conditions']);
=======
$this->assertEqual("WHERE {title} = 'FML'", $result['conditions']);
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ $this->assertEqual("WHERE {title} = 'FML'", $result['conditions']);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
public function testEntityConditions() {
@@ -415,6 +442,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);
+ }
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
?>
\ No newline at end of file
diff --git a/libraries/lithium/tests/cases/data/source/DatabaseTest.php b/libraries/lithium/tests/cases/data/source/DatabaseTest.php
index 8980c87..5ba5d3d 100644
--- a/libraries/lithium/tests/cases/data/source/DatabaseTest.php
+++ b/libraries/lithium/tests/cases/data/source/DatabaseTest.php
@@ -387,7 +387,12 @@ class DatabaseTest extends \lithium\test\Unit {
'data' => array('published' => false),
'model' => $this->_model
));
+<<<<<<< HEAD
$sql = "UPDATE {mock_database_posts} SET {published} = 0 WHERE ({expires} >= '2010-05-13');";
+=======
+ $sql = "UPDATE {mock_database_posts} SET {published} = 0 WHERE ";
+ $sql .= "({expires} >= '2010-05-13');";
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$this->assertEqual($sql, $this->db->renderCommand($query));
}
@@ -396,12 +401,17 @@ class DatabaseTest extends \lithium\test\Unit {
'score' => array('between' => array(90, 100))
)));
<<<<<<< HEAD
+<<<<<<< HEAD
$sql = "SELECT * FROM {mock_database_posts} AS {MockDatabasePost} WHERE {score} ";
$sql .= "BETWEEN 90 AND 100;";
=======
$sql = "SELECT * FROM {mock_database_posts} AS {MockDatabasePost} WHERE ({score} ";
$sql .= "BETWEEN 90 AND 100);";
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ $sql = "SELECT * FROM {mock_database_posts} AS {MockDatabasePost} WHERE ({score} ";
+ $sql .= "BETWEEN 90 AND 100);";
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$this->assertEqual($sql, $this->db->renderCommand($query));
$query = new Query(array('type' => 'read', 'model' => $this->_model, 'conditions' => array(
@@ -409,7 +419,32 @@ class DatabaseTest extends \lithium\test\Unit {
)));
$sql = "SELECT * FROM {mock_database_posts} AS {MockDatabasePost} WHERE ";
<<<<<<< HEAD
+<<<<<<< HEAD
$sql .= "{score} > 90 AND {score} < 100;";
+=======
+ $sql .= "({score} > 90 AND {score} < 100);";
+ $this->assertEqual($sql, $this->db->renderCommand($query));
+
+ $query = new Query(array('type' => 'read', 'model' => $this->_model, 'conditions' => array(
+ 'score' => array('!=' => array(98, 99, 100))
+ )));
+ $sql = "SELECT * FROM {mock_database_posts} AS {MockDatabasePost} ";
+ $sql .= "WHERE ({score} NOT IN (98, 99, 100));";
+ $this->assertEqual($sql, $this->db->renderCommand($query));
+
+ $query = new Query(array('type' => 'read', 'model' => $this->_model, 'conditions' => array(
+ 'scorer' => array('like' => '%howard%')
+ )));
+ $sql = "SELECT * FROM {mock_database_posts} AS {MockDatabasePost} ";
+ $sql .= "WHERE ({scorer} like '%howard%');";
+ $this->assertEqual($sql, $this->db->renderCommand($query));
+
+ $conditions = "custom conditions string";
+ $query = new Query(compact('conditions') + array(
+ 'type' => 'read', 'model' => $this->_model
+ ));
+ $sql = "SELECT * FROM {mock_database_posts} AS {MockDatabasePost} WHERE {$conditions};";
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$this->assertEqual($sql, $this->db->renderCommand($query));
$query = new Query(array('type' => 'read', 'model' => $this->_model, 'conditions' => array(
@@ -455,7 +490,12 @@ class DatabaseTest extends \lithium\test\Unit {
'field' => array('like' => '%value%')
)
));
+<<<<<<< HEAD
$sql = "SELECT * FROM {mock_database_posts} AS {MockDatabasePost} WHERE ({field} like '%value%');";
+=======
+ $sql = "SELECT * FROM {mock_database_posts} AS {MockDatabasePost} WHERE ";
+ $sql .= "({field} like '%value%');";
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$this->assertEqual($sql, $this->db->renderCommand($query));
$query = new Query(array(
@@ -464,16 +504,26 @@ class DatabaseTest extends \lithium\test\Unit {
'or' => array(
'field1' => 'value1',
'field2' => 'value2',
+<<<<<<< HEAD
'and' => array(
'sField' => '1',
'sField2' => '2'
)
+=======
+ 'and' => array('sField' => '1', 'sField2' => '2')
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
),
'bField' => '3'
)
));
+<<<<<<< HEAD
$sql = "SELECT * FROM {mock_database_posts} AS {MockDatabasePost} WHERE ({field1} = 'value1' OR {field2} = 'value2' OR ({sField} = 1 AND {sField2} = 2)) AND {bField} = 3;";
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ $sql = "SELECT * FROM {mock_database_posts} AS {MockDatabasePost} WHERE ";
+ $sql .= "({field1} = 'value1' OR {field2} = 'value2' OR ({sField} = 1 AND {sField2} = 2))";
+ $sql .= " AND {bField} = 3;";
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$this->assertEqual($sql, $this->db->renderCommand($query));
}
diff --git a/libraries/lithium/tests/cases/data/source/MongoDbTest.php b/libraries/lithium/tests/cases/data/source/MongoDbTest.php
index 7277880..4764bdc 100644
--- a/libraries/lithium/tests/cases/data/source/MongoDbTest.php
+++ b/libraries/lithium/tests/cases/data/source/MongoDbTest.php
@@ -12,12 +12,16 @@ namespace lithium\tests\cases\data\source;
use lithium\data\source\MongoDb;
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
=======
use Exception;
>>>>>>> 25a362f706960b2becbf88e91cffc1b1638b7890
=======
use Exception;
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+use Exception;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
use MongoId;
use MongoCode;
use MongoDate;
@@ -29,10 +33,16 @@ use lithium\data\model\Query;
use lithium\data\entity\Document;
use lithium\tests\mocks\data\MockPost;
<<<<<<< HEAD
+<<<<<<< HEAD
=======
use lithium\data\collection\DocumentSet;
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
use lithium\data\collection\DocumentArray;
+=======
+use lithium\data\collection\DocumentSet;
+use lithium\data\collection\DocumentArray;
+use lithium\tests\mocks\data\source\MockMongoSource;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
use lithium\tests\mocks\data\source\MockMongoConnection;
class MongoDbTest extends \lithium\test\Unit {
@@ -65,6 +75,7 @@ class MongoDbTest extends \lithium\test\Unit {
'notifications.bar' => array('type' => 'boolean'),
'notifications.baz' => array('type' => 'boolean'),
<<<<<<< HEAD
+<<<<<<< HEAD
);
protected $_schema = array(
@@ -84,6 +95,8 @@ class MongoDbTest extends \lithium\test\Unit {
'notifications.baz' => array('type' => 'boolean'),
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
);
protected $_configs = array();
@@ -125,9 +138,13 @@ class MongoDbTest extends \lithium\test\Unit {
$model = $this->_model;
$model::config(array('key' => '_id'));
<<<<<<< HEAD
+<<<<<<< HEAD
=======
$model::resetConnection(false);
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ $model::resetConnection(false);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$this->query = new Query(compact('model') + array(
'entity' => new Document(compact('model'))
@@ -274,41 +291,59 @@ 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
+<<<<<<< HEAD
$this->assertTrue($result == true);
=======
$this->assertTrue($result instanceof DocumentSet);
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
$this->assertEqual(1, $result->count());
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
- $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() {
@@ -330,6 +365,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'])
@@ -337,6 +373,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();
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$this->assertEqual($original['_id'], $updated['_id']);
$this->assertEqual('New Post Title', $updated['title']);
}
@@ -486,17 +532,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());
@@ -542,7 +590,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(
@@ -572,6 +620,7 @@ class MongoDbTest extends \lithium\test\Unit {
}
<<<<<<< HEAD
+<<<<<<< HEAD
/**
* Tests handling type values based on specified schema settings.
*
@@ -625,6 +674,8 @@ class MongoDbTest extends \lithium\test\Unit {
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
public function testCastingConditionsValues() {
$query = new Query(array('schema' => $this->_schema));
@@ -636,7 +687,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);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$this->assertEqual($conditions['_id'], (string) $result['_id']);
$conditions = array('_id' => array(
@@ -644,9 +699,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);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$conditions = array('voters' => array('$all' => array(
"4c8f86167675abfabdbf0300", "4c8f86167675abfabdc00300"
@@ -654,8 +715,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);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$conditions = array('$or' => array(
array('_id' => "4c8f86167675abfabdbf0300"),
@@ -664,6 +730,7 @@ 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);
}
@@ -690,14 +757,23 @@ class MongoDbTest extends \lithium\test\Unit {
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ $this->assertTrue($result['$or'][0]['_id'] instanceof MongoId);
+ $this->assertTrue($result['$or'][1]['guid'] instanceof MongoId);
+ }
+
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
public function testMultiOperationConditions() {
$conditions = array('loc' => array('$near' => array(50, 50), '$maxDistance' => 5));
$result = $this->db->conditions($conditions, $this->query);
$this->assertEqual($conditions, $result);
}
<<<<<<< HEAD
+<<<<<<< HEAD
>>>>>>> 25a362f706960b2becbf88e91cffc1b1638b7890
=======
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
public function testCreateWithEmbeddedObjects() {
$data = array(
@@ -736,7 +812,10 @@ class MongoDbTest extends \lithium\test\Unit {
}));
$this->assertEqual($schema, $db->describe(null));
}
+<<<<<<< HEAD
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
?>
\ No newline at end of file
diff --git a/libraries/lithium/tests/cases/data/source/http/adapter/CouchDbTest.php b/libraries/lithium/tests/cases/data/source/http/adapter/CouchDbTest.php
index dd5c7b4..cd86375 100644
--- a/libraries/lithium/tests/cases/data/source/http/adapter/CouchDbTest.php
+++ b/libraries/lithium/tests/cases/data/source/http/adapter/CouchDbTest.php
@@ -108,9 +108,9 @@ class CouchDbTest extends \lithium\test\Unit {
public function testCreateNoId() {
$couchdb = new CouchDb($this->_testConfig);
$this->query->data(array('name' => 'Acme Inc.'));
- $expected = true;
+
$result = $couchdb->create($this->query);
- $this->assertEqual($expected, $result);
+ $this->assertTrue($result);
$expected = '/lithium-test';
$result = $couchdb->last->request->path;
@@ -124,9 +124,9 @@ class CouchDbTest extends \lithium\test\Unit {
public function testCreateWithId() {
$couchdb = new CouchDb($this->_testConfig);
$this->query->data(array('id' => 12345, 'name' => 'Acme Inc.'));
- $expected = true;
+
$result = $couchdb->create($this->query);
- $this->assertEqual($expected, $result);
+ $this->assertTrue($result);
$expected = '/lithium-test/12345';
$result = $couchdb->last->request->path;
@@ -139,12 +139,19 @@ class CouchDbTest extends \lithium\test\Unit {
public function testReadNoConditions() {
$couchdb = new CouchDb($this->_testConfig);
+<<<<<<< HEAD
$result = $couchdb->read($this->query);
$this->assertTrue($result);
$expected = array('total_rows' => null, 'offset' => null);
$result = $result->stats();
$this->assertEqual($expected, $result);
+=======
+
+ $result = $couchdb->read($this->query);
+ $this->assertTrue($result);
+ $this->assertEqual(array('total_rows' => null, 'offset' => null), $result->stats());
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$expected = '/lithium-test/_all_docs';
$result = $couchdb->last->request->path;
@@ -157,10 +164,10 @@ class CouchDbTest extends \lithium\test\Unit {
public function testReadWithConditions() {
$couchdb = new CouchDb($this->_testConfig);
- $expected = true;
+
$this->query->conditions(array('id' => 12345));
$result = $couchdb->read($this->query);
- $this->assertEqual($expected, $result);
+ $this->assertTrue($result);
$this->assertEqual(array('total_rows' => null, 'offset' => null), $result->stats());
$expected = '/lithium-test/12345';
@@ -170,17 +177,21 @@ class CouchDbTest extends \lithium\test\Unit {
$expected = '';
$result = $couchdb->last->request->params;
$this->assertEqual($expected, $result);
+
+ $this->query->conditions(array('id' => 12345, 'path' => '/lithium-test/12345'));
+ $result = $couchdb->read($this->query);
+ $this->assertTrue($result);
}
public function testReadWithViewConditions() {
$couchdb = new CouchDb($this->_testConfig);
- $expected = true;
+
$this->query->conditions(array(
'design' => 'latest', 'view' => 'all', 'limit' => 10, 'descending' => 'true'
));
$result = $couchdb->read($this->query);
$this->assertEqual(array('total_rows' => null, 'offset' => null), $result->stats());
- $this->assertEqual($expected, $result);
+ $this->assertTrue($result);
$expected = '/lithium-test/_design/latest/_view/all/';
$result = $couchdb->last->request->path;
@@ -300,18 +311,16 @@ class CouchDbTest extends \lithium\test\Unit {
public function testResultClose() {
$couchdb = new CouchDb($this->_testConfig);
- $expected = null;
$result = $couchdb->result('close', (object) array(), $this->query);
- $this->assertEqual($expected, $result);
+ $this->assertNull($result);
}
public function testUpdate() {
$couchdb = new CouchDb($this->_testConfig);
$this->query->data(array('id' => 12345, 'rev' => '1-1', 'title' => 'One'));
- $expected = true;
$result = $couchdb->update($this->query);
- $this->assertEqual($expected, $result);
+ $this->assertTrue($result);
$expected = '/lithium-test/12345';
$result = $couchdb->last->request->path;
@@ -326,9 +335,8 @@ class CouchDbTest extends \lithium\test\Unit {
$couchdb = new CouchDb($this->_testConfig);
$this->query->data(array('id' => 12345, 'rev'=> '1-1', 'name' => 'Acme Inc'));
- $expected = true;
$result = $couchdb->delete($this->query);
- $this->assertEqual($expected, $result);
+ $this->assertTrue($result);
$expected = '/lithium-test/12345';
$result = $couchdb->last->request->path;
@@ -338,6 +346,15 @@ class CouchDbTest extends \lithium\test\Unit {
$result = $couchdb->last->request->params;
$this->assertEqual($expected, $result);
}
+
+ public function testEnabled() {
+ $this->assertEqual(CouchDb::enabled(), true);
+
+ $this->assertEqual(CouchDb::enabled('arrays'), true);
+ $this->assertEqual(CouchDb::enabled('transactions'), false);
+ $this->assertEqual(CouchDb::enabled('booleans'), true);
+ $this->assertEqual(CouchDb::enabled('relationships'), false);
+ }
}
?>
\ No newline at end of file
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..85bf68b 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);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$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);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$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..28d5e29 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;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
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..c56b6df 100644
--- a/libraries/lithium/tests/cases/g11n/catalog/adapter/CodeTest.php
+++ b/libraries/lithium/tests/cases/g11n/catalog/adapter/CodeTest.php
@@ -8,7 +8,12 @@
namespace lithium\tests\cases\g11n\catalog\adapter;
+<<<<<<< HEAD
use \Exception;
+=======
+use Exception;
+use lithium\core\Libraries;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
use lithium\g11n\catalog\adapter\Code;
class CodeTest extends \lithium\test\Unit {
@@ -18,7 +23,7 @@ class CodeTest extends \lithium\test\Unit {
protected $_path;
public function setUp() {
- $this->_path = $path = LITHIUM_APP_PATH . '/resources/tmp/tests';
+ $this->_path = $path = Libraries::get(true, 'resources') . '/tmp/tests';
$this->skipIf(!is_writable($this->_path), "{$this->_path} is not writable.");
$this->adapter = new Code(compact('path'));
@@ -72,7 +77,7 @@ EOD;
}
public function testPathMustExist() {
- $path = LITHIUM_APP_PATH . '/resources/tmp/tests';
+ $path = Libraries::get(true, 'resources') . '/tmp/tests';
try {
new Code(array('path' => $this->_path));
diff --git a/libraries/lithium/tests/cases/g11n/catalog/adapter/GettextTest.php b/libraries/lithium/tests/cases/g11n/catalog/adapter/GettextTest.php
index 0c8d70d..212eb2a 100644
--- a/libraries/lithium/tests/cases/g11n/catalog/adapter/GettextTest.php
+++ b/libraries/lithium/tests/cases/g11n/catalog/adapter/GettextTest.php
@@ -8,7 +8,12 @@
namespace lithium\tests\cases\g11n\catalog\adapter;
+<<<<<<< HEAD
use \Exception;
+=======
+use Exception;
+use lithium\core\Libraries;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
use lithium\tests\mocks\g11n\catalog\adapter\MockGettext;
class GettextTest extends \lithium\test\Unit {
@@ -18,13 +23,13 @@ class GettextTest extends \lithium\test\Unit {
protected $_path;
public function skip() {
- $path = LITHIUM_APP_PATH . '/resources/tmp/tests';
+ $path = Libraries::get(true, 'resources') . '/tmp/tests';
$message = "Path {$path} is not writable.";
$this->skipIf(!is_writable($path), $message);
}
public function setUp() {
- $this->_path = $path = LITHIUM_APP_PATH . '/resources/tmp/tests';
+ $this->_path = $path = Libraries::get(true, 'resources') . '/tmp/tests';
mkdir("{$this->_path}/en/LC_MESSAGES", 0755, true);
mkdir("{$this->_path}/de/LC_MESSAGES", 0755, true);
$this->adapter = new MockGettext(compact('path'));
diff --git a/libraries/lithium/tests/cases/g11n/catalog/adapter/PhpTest.php b/libraries/lithium/tests/cases/g11n/catalog/adapter/PhpTest.php
index 37246c3..053ee98 100644
--- a/libraries/lithium/tests/cases/g11n/catalog/adapter/PhpTest.php
+++ b/libraries/lithium/tests/cases/g11n/catalog/adapter/PhpTest.php
@@ -8,7 +8,12 @@
namespace lithium\tests\cases\g11n\catalog\adapter;
+<<<<<<< HEAD
use \Exception;
+=======
+use Exception;
+use lithium\core\Libraries;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
use lithium\g11n\catalog\adapter\Php;
class PhpTest extends \lithium\test\Unit {
@@ -18,7 +23,7 @@ class PhpTest extends \lithium\test\Unit {
protected $_path;
public function skip() {
- $this->_path = $path = LITHIUM_APP_PATH . '/resources/tmp/tests';
+ $this->_path = $path = Libraries::get(true, 'resources') . '/tmp/tests';
$message = "{$path} is not writable.";
$this->skipIf(!is_writable($path), $message);
}
diff --git a/libraries/lithium/tests/cases/net/http/MediaTest.php b/libraries/lithium/tests/cases/net/http/MediaTest.php
index 6f4f03d..0689693 100644
--- a/libraries/lithium/tests/cases/net/http/MediaTest.php
+++ b/libraries/lithium/tests/cases/net/http/MediaTest.php
@@ -51,9 +51,13 @@ class MediaTest extends \lithium\test\Unit {
$this->assertEqual($expected, $result['options']);
<<<<<<< HEAD
+<<<<<<< HEAD
=======
// Add a custom media type with a custom view class:
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ // Add a custom media type with a custom view class:
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
Media::type('my', 'text/x-my', array('view' => 'my\custom\View', 'layout' => false));
$result = Media::types();
@@ -66,10 +70,14 @@ class MediaTest extends \lithium\test\Unit {
$expected = array(
'view' => 'my\custom\View', 'template' => null, 'layout' => null,
<<<<<<< HEAD
+<<<<<<< HEAD
'encode' => null, 'decode' => null, 'cast' => true
=======
'encode' => null, 'decode' => null, 'cast' => true, 'conditions' => array()
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ 'encode' => null, 'decode' => null, 'cast' => true, 'conditions' => array()
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
);
$this->assertEqual($expected, $result['options']);
@@ -245,13 +253,11 @@ class MediaTest extends \lithium\test\Unit {
$data = array('something');
Media::render($response, $data);
- $expected = array('Content-type: application/json');
$result = $response->headers();
- $this->assertEqual($expected, $result);
+ $this->assertEqual(array('Content-type: application/json; charset=UTF-8'), $result);
- $expected = json_encode($data);
$result = $response->body();
- $this->assertEqual($expected, $result);
+ $this->assertEqual(json_encode($data), $result);
}
/**
@@ -297,8 +303,7 @@ class MediaTest extends \lithium\test\Unit {
$this->assertEqual(array($expected), $result);
$result = $response->headers['Content-type'];
- $expected = 'application/csv';
- $this->assertEqual($expected, $result);
+ $this->assertEqual('application/csv; charset=UTF-8', $result);
}
/**
@@ -311,9 +316,8 @@ class MediaTest extends \lithium\test\Unit {
$response->type('text');
Media::render($response, "Hello, world!");
- $expected = array("Hello, world!");
$result = $response->body;
- $this->assertEqual($expected, $result);
+ $this->assertEqual(array("Hello, world!"), $result);
}
/**
@@ -326,7 +330,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;
@@ -343,7 +347,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;
@@ -415,7 +419,7 @@ class MediaTest extends \lithium\test\Unit {
}
public function testRenderWithOptionsMerging() {
- $base = LITHIUM_APP_PATH . '/resources/tmp';
+ $base = Libraries::get(true, 'resources') . '/tmp';
$this->skipIf(!is_writable($base), "{$base} is not writable.");
$request = new Request();
@@ -520,9 +524,12 @@ class MediaTest extends \lithium\test\Unit {
}
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
=======
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
/**
* Tests that `Media::asset()` will not prepend path strings with the base application path if
@@ -544,8 +551,11 @@ class MediaTest extends \lithium\test\Unit {
$this->assertEqual('/foo/bar/image.jpg', $result);
}
<<<<<<< HEAD
+<<<<<<< HEAD
>>>>>>> 25a362f706960b2becbf88e91cffc1b1638b7890
=======
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
public function testContentNegotiationByType() {
$this->assertEqual('html', Media::type('text/html'));
@@ -580,7 +590,10 @@ class MediaTest extends \lithium\test\Unit {
)));
$this->assertEqual('iphone', Media::negotiate($request));
}
+<<<<<<< HEAD
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
?>
\ No newline at end of file
diff --git a/libraries/lithium/tests/cases/net/http/MessageTest.php b/libraries/lithium/tests/cases/net/http/MessageTest.php
index a879e16..a95d406 100644
--- a/libraries/lithium/tests/cases/net/http/MessageTest.php
+++ b/libraries/lithium/tests/cases/net/http/MessageTest.php
@@ -29,9 +29,8 @@ class MessageTest extends \lithium\test\Unit {
$result = $this->message->headers('Host');
$this->assertEqual($expected, $result);
- $expected = null;
$result = $this->message->headers('Host', false);
- $this->assertEqual($expected, $result);
+ $this->assertFalse($result);
}
public function testHeaderKeyValue() {
diff --git a/libraries/lithium/tests/cases/net/http/ResponseTest.php b/libraries/lithium/tests/cases/net/http/ResponseTest.php
index cacd9cf..94ce1b2 100644
--- a/libraries/lithium/tests/cases/net/http/ResponseTest.php
+++ b/libraries/lithium/tests/cases/net/http/ResponseTest.php
@@ -43,9 +43,8 @@ class ResponseTest extends \lithium\test\Unit {
$result = $response->status('See Other');
$this->assertEqual($expected, $result);
- $expected = false;
$result = $response->status('foobar');
- $this->assertEqual($expected, $result);
+ $this->assertFalse($result);
}
public function testParsingContentTypeWithEncoding() {
@@ -90,6 +89,40 @@ class ResponseTest extends \lithium\test\Unit {
$this->assertEqual($expected, (string) $response);
}
+ public function testMessageContentTypeParsing() {
+ // Content type WITHOUT space between type and charset
+ $message = join("\r\n", array(
+ 'HTTP/1.1 200 OK',
+ 'Content-Type: application/json;charset=iso-8859-1',
+ '',
+ 'Test!'
+ ));
+ $response = new Response(array('message' => $message));
+ $this->assertEqual('application/json', $response->type);
+ $this->assertEqual('ISO-8859-1', $response->encoding);
+
+ // Content type WITH ONE space between type and charset
+ $message = join("\r\n", array(
+ 'HTTP/1.1 200 OK',
+ 'Content-Type: application/json; charset=iso-8859-1',
+ '',
+ 'Test!'
+ ));
+ $response = new Response(array('message' => $message));
+ $this->assertEqual('application/json', $response->type);
+ $this->assertEqual('ISO-8859-1', $response->encoding);
+
+ $message = join("\r\n", array(
+ 'HTTP/1.1 200 OK',
+ 'Content-Type: application/json; charset=iso-8859-1',
+ '',
+ 'Test!'
+ ));
+ $response = new Response(array('message' => $message));
+ $this->assertEqual('application/json', $response->type);
+ $this->assertEqual('ISO-8859-1', $response->encoding);
+ }
+
public function testEmptyResponse() {
$response = new Response(array('message' => "\n"));
$result = trim((string) $response);
diff --git a/libraries/lithium/tests/cases/net/http/RouterTest.php b/libraries/lithium/tests/cases/net/http/RouterTest.php
index 5cf5616..fd3c183 100644
--- a/libraries/lithium/tests/cases/net/http/RouterTest.php
+++ b/libraries/lithium/tests/cases/net/http/RouterTest.php
@@ -223,7 +223,13 @@ class RouterTest extends \lithium\test\Unit {
$result = Router::match("Posts::index");
$this->assertEqual('/posts', $result);
+<<<<<<< HEAD
$this->expectException('No parameter match found for routes.');
+=======
+ $ex = "No parameter match found for URL ";
+ $ex .= "`('controller' => 'sessions', 'action' => 'create', 'id' => 'foo')`.";
+ $this->expectException($ex);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$result = Router::match(array("Sessions::create", 'id' => 'foo'));
}
@@ -242,7 +248,14 @@ class RouterTest extends \lithium\test\Unit {
$expected = '/posts/4bbf25bd8ead0e5180130000';
$this->assertEqual($expected, $result);
+<<<<<<< HEAD
$this->expectException('No parameter match found for routes.');
+=======
+ $ex = "No parameter match found for URL `(";
+ $ex .= "'controller' => 'posts', 'action' => 'view', 'id' => '4bbf25bd8ead0e5180130000')`.";
+ $this->expectException($ex);
+
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$result = Router::match(array(
'controller' => 'posts', 'action' => 'view', 'id' => '4bbf25bd8ead0e5180130000'
));
@@ -292,7 +305,14 @@ class RouterTest extends \lithium\test\Unit {
Router::connect('/login', array('controller' => 'sessions', 'action' => 'add'));
$result = Router::match(array('controller' => 'sessions', 'action' => 'add'));
$this->assertEqual('/login', $result);
+<<<<<<< HEAD
$this->expectException('No parameter match found for routes.');
+=======
+
+ $this->expectException(
+ "No parameter match found for URL `('controller' => 'sessions', 'action' => 'index')`."
+ );
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
Router::match(array('controller' => 'sessions', 'action' => 'index'));
}
@@ -305,7 +325,13 @@ class RouterTest extends \lithium\test\Unit {
Router::connect('/{:controller}');
$this->assertEqual('/posts', Router::match(array('controller' => 'posts')));
+<<<<<<< HEAD
$this->expectException('No parameter match found for routes.');
+=======
+ $this->expectException(
+ "No parameter match found for URL `('controller' => 'posts', 'action' => 'view')`."
+ );
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
Router::match(array('controller' => 'posts', 'action' => 'view'));
}
@@ -330,7 +356,13 @@ class RouterTest extends \lithium\test\Unit {
$result = Router::match(array('controller' => 'posts', 'action' => 'view'));
$this->assertEqual('/posts/view', $result);
+<<<<<<< HEAD
$this->expectException('No parameter match found for routes.');
+=======
+ $ex = "No parameter match found for URL ";
+ $ex .= "`('controller' => 'posts', 'action' => 'view', 'id' => '2')`.";
+ $this->expectException($ex);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
Router::match(array('controller' => 'posts', 'action' => 'view', 'id' => '2'));
}
@@ -406,6 +438,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/net/http/ServiceTest.php b/libraries/lithium/tests/cases/net/http/ServiceTest.php
index 9c72aa0..2b98479 100644
--- a/libraries/lithium/tests/cases/net/http/ServiceTest.php
+++ b/libraries/lithium/tests/cases/net/http/ServiceTest.php
@@ -69,9 +69,12 @@ class ServiceTest extends \lithium\test\Unit {
$http = new Service($this->_testConfig);
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
=======
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$this->assertEqual('', $http->head());
$this->assertEqual('HTTP/1.1', $http->last->response->protocol);
$this->assertEqual('200', $http->last->response->status['code']);
@@ -84,9 +87,12 @@ class ServiceTest extends \lithium\test\Unit {
public function testGet() {
$http = new Service($this->_testConfig);
<<<<<<< HEAD
+<<<<<<< HEAD
>>>>>>> 25a362f706960b2becbf88e91cffc1b1638b7890
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$this->assertEqual('', $http->get());
$this->assertEqual('HTTP/1.1', $http->last->response->protocol);
$this->assertEqual('200', $http->last->response->status['code']);
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/security/auth/adapter/FormTest.php b/libraries/lithium/tests/cases/security/auth/adapter/FormTest.php
index 92e86dd..563eb4e 100644
--- a/libraries/lithium/tests/cases/security/auth/adapter/FormTest.php
+++ b/libraries/lithium/tests/cases/security/auth/adapter/FormTest.php
@@ -24,24 +24,47 @@ class FormTest extends \lithium\test\Unit {
$request->data = array('username' => 'Person', 'password' => 'password');
$result = $subject->check($request);
+<<<<<<< HEAD
$expected = array('username' => 'Person',
'password' => 'b109f3bbbc244eb82441917ed06d618b9008dd09b3befd1b5e07394c706a8bb980b1d7'.
'785e5976ec049b46df5f1326af5a2ea6d103fd07c95385ffab0cacbc86');
+=======
+ $password = 'b109f3bbbc244eb82441917ed06d618b9008dd09b3befd1b5e07394c706a8bb980b1d7';
+ $password .= '785e5976ec049b46df5f1326af5a2ea6d103fd07c95385ffab0cacbc86';
+ $expected = array('username' => 'Person') + compact('password');
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$this->assertEqual($expected, $result);
}
public function testLoginWithFilters() {
- $subject = new Form(array('model' => __CLASS__, 'filters' => array(
- 'username' => 'sha1'
- )));
+ $subject = new Form(array('model' => __CLASS__, 'filters' => array('username' => 'sha1')));
$request = new Request();
$request->data = array('username' => 'Person', 'password' => 'password');
+ $password = 'b109f3bbbc244eb82441917ed06d618b9008dd09b3befd1b5e07394c706a8bb980b1d7';
+ $password .= '785e5976ec049b46df5f1326af5a2ea6d103fd07c95385ffab0cacbc86';
+ $expected = array('username' => sha1('Person')) + compact('password');
+ $this->assertEqual($expected, $subject->check($request));
+ }
+
+ /**
+ * Tests that attempted exploitation via malformed credential submission.
+ *
+ * @return void
+ */
+ public function testLoginWithArray() {
+ $subject = new Form(array('model' => __CLASS__));
+ $request = new Request();
+ $request->data = array('username' => array('!=' => ''), 'password' => '');
$result = $subject->check($request);
+<<<<<<< HEAD
$expected = array('username' => sha1('Person'),
'password' => 'b109f3bbbc244eb82441917ed06d618b9008dd09b3befd1b5e07394c706a8bb980b1d7'.
'785e5976ec049b46df5f1326af5a2ea6d103fd07c95385ffab0cacbc86');
$this->assertEqual($expected, $result);
+=======
+ $this->assertEqual('Array', $result['username']);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
/**
diff --git a/libraries/lithium/tests/cases/storage/CacheTest.php b/libraries/lithium/tests/cases/storage/CacheTest.php
index e227d16..d52c110 100644
--- a/libraries/lithium/tests/cases/storage/CacheTest.php
+++ b/libraries/lithium/tests/cases/storage/CacheTest.php
@@ -8,9 +8,16 @@
namespace lithium\tests\cases\storage;
+<<<<<<< HEAD
use lithium\storage\Cache;
use lithium\util\Collection;
use \SplFileInfo;
+=======
+use SplFileInfo;
+use lithium\core\Libraries;
+use lithium\storage\Cache;
+use lithium\util\Collection;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
class CacheTest extends \lithium\test\Unit {
@@ -553,14 +560,14 @@ class CacheTest extends \lithium\test\Unit {
}
public function testIntegrationFileAdapterWrite() {
- $directory = new SplFileInfo(LITHIUM_APP_PATH . "/resources/tmp/cache/");
+ $directory = new SplFileInfo(Libraries::get(true, 'resources') . "/tmp/cache/");
$accessible = ($directory->isDir() && $directory->isReadable() && $directory->isWritable());
$message = "$directory does not have the proper permissions.";
$this->skipIf(!$accessible, $message);
$config = array('default' => array(
'adapter' => 'File',
- 'path' => LITHIUM_APP_PATH . '/resources/tmp/cache',
+ 'path' => Libraries::get(true, 'resources') . '/tmp/cache',
'filters' => array()
));
Cache::config($config);
@@ -569,24 +576,24 @@ class CacheTest extends \lithium\test\Unit {
$this->assertTrue($result);
$time = time() + 60;
- $result = file_get_contents(LITHIUM_APP_PATH . '/resources/tmp/cache/key');
+ $result = file_get_contents(Libraries::get(true, 'resources') . '/tmp/cache/key');
$expected = "{:expiry:$time}\nvalue";
$this->assertEqual($result, $expected);
- $result = unlink(LITHIUM_APP_PATH . '/resources/tmp/cache/key');
+ $result = unlink(Libraries::get(true, 'resources') . '/tmp/cache/key');
$this->assertTrue($result);
- $this->assertFalse(file_exists(LITHIUM_APP_PATH . '/resources/tmp/cache/key'));
+ $this->assertFalse(file_exists(Libraries::get(true, 'resources') . '/tmp/cache/key'));
}
public function testIntegrationFileAdapterWithStrategies() {
- $directory = new SplFileInfo(LITHIUM_APP_PATH . "/resources/tmp/cache/");
+ $directory = new SplFileInfo(Libraries::get(true, 'resources') . "/tmp/cache/");
$accessible = ($directory->isDir() && $directory->isReadable() && $directory->isWritable());
$message = "$directory does not have the proper permissions.";
$this->skipIf(!$accessible, $message);
$config = array('default' => array(
'adapter' => 'File',
- 'path' => LITHIUM_APP_PATH . '/resources/tmp/cache',
+ 'path' => Libraries::get(true, 'resources') . '/tmp/cache',
'filters' => array(),
'strategies' => array('Serializer')
));
@@ -597,7 +604,7 @@ class CacheTest extends \lithium\test\Unit {
$this->assertTrue($result);
$time = time() + 60;
- $result = file_get_contents(LITHIUM_APP_PATH . '/resources/tmp/cache/key');
+ $result = file_get_contents(Libraries::get(true, 'resources') . '/tmp/cache/key');
$expected = "{:expiry:$time}\na:1:{s:4:\"some\";s:4:\"data\";}";
$this->assertEqual($result, $expected);
@@ -605,20 +612,20 @@ class CacheTest extends \lithium\test\Unit {
$result = Cache::read('default', 'key');
$this->assertEqual($data, $result);
- $result = unlink(LITHIUM_APP_PATH . '/resources/tmp/cache/key');
+ $result = unlink(Libraries::get(true, 'resources') . '/tmp/cache/key');
$this->assertTrue($result);
- $this->assertFalse(file_exists(LITHIUM_APP_PATH . '/resources/tmp/cache/key'));
+ $this->assertFalse(file_exists(Libraries::get(true, 'resources') . '/tmp/cache/key'));
}
public function testIntegrationFileAdapterMultipleStrategies() {
- $directory = new SplFileInfo(LITHIUM_APP_PATH . "/resources/tmp/cache/");
+ $directory = new SplFileInfo(Libraries::get(true, 'resources') . "/tmp/cache/");
$accessible = ($directory->isDir() && $directory->isReadable() && $directory->isWritable());
$message = "$directory does not have the proper permissions.";
$this->skipIf(!$accessible, $message);
$config = array('default' => array(
'adapter' => 'File',
- 'path' => LITHIUM_APP_PATH . '/resources/tmp/cache',
+ 'path' => Libraries::get(true, 'resources') . '/tmp/cache',
'filters' => array(),
'strategies' => array('Serializer', 'Base64')
));
@@ -629,7 +636,7 @@ class CacheTest extends \lithium\test\Unit {
$this->assertTrue($result);
$time = time() + 60;
- $result = file_get_contents(LITHIUM_APP_PATH . '/resources/tmp/cache/key');
+ $result = file_get_contents(Libraries::get(true, 'resources') . '/tmp/cache/key');
$expected = "{:expiry:$time}\nYToxOntzOjQ6InNvbWUiO3M6NDoiZGF0YSI7fQ==";
$this->assertEqual($result, $expected);
@@ -637,9 +644,9 @@ class CacheTest extends \lithium\test\Unit {
$result = Cache::read('default', 'key');
$this->assertEqual($data, $result);
- $result = unlink(LITHIUM_APP_PATH . '/resources/tmp/cache/key');
+ $result = unlink(Libraries::get(true, 'resources') . '/tmp/cache/key');
$this->assertTrue($result);
- $this->assertFalse(file_exists(LITHIUM_APP_PATH . '/resources/tmp/cache/key'));
+ $this->assertFalse(file_exists(Libraries::get(true, 'resources') . '/tmp/cache/key'));
}
}
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..6a2f1ae 100644
--- a/libraries/lithium/tests/cases/storage/cache/adapter/FileTest.php
+++ b/libraries/lithium/tests/cases/storage/cache/adapter/FileTest.php
@@ -8,8 +8,14 @@
namespace lithium\tests\cases\storage\cache\adapter;
+<<<<<<< HEAD
use lithium\storage\cache\adapter\File;
use \SplFileInfo;
+=======
+use SplFileInfo;
+use lithium\core\Libraries;
+use lithium\storage\cache\adapter\File;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
class FileTest extends \lithium\test\Unit {
@@ -28,21 +34,21 @@ class FileTest extends \lithium\test\Unit {
* @return void
*/
public function skip() {
- $directory = new SplFileInfo(LITHIUM_APP_PATH . "/resources/tmp/cache/");
+ $directory = new SplFileInfo(Libraries::get(true, 'resources') . "/tmp/cache/");
$accessible = ($directory->isDir() && $directory->isReadable() && $directory->isWritable());
$message = 'The File cache adapter path does not have the proper permissions.';
$this->skipIf(!$accessible, $message);
}
public function setUp() {
- $this->_hasEmpty = file_exists(LITHIUM_APP_PATH . "/resources/tmp/cache/empty");
+ $this->_hasEmpty = file_exists(Libraries::get(true, 'resources') . "/tmp/cache/empty");
$this->File = new File();
}
public function tearDown() {
if ($this->_hasEmpty) {
- touch(LITHIUM_APP_PATH . "/resources/tmp/cache/empty");
- touch(LITHIUM_APP_PATH . "/resources/tmp/cache/templates/empty");
+ touch(Libraries::get(true, 'resources') . "/tmp/cache/empty");
+ touch(Libraries::get(true, 'resources') . "/tmp/cache/templates/empty");
}
unset($this->File);
}
@@ -66,14 +72,14 @@ class FileTest extends \lithium\test\Unit {
$expected = 25;
$this->assertEqual($expected, $result);
- $this->assertTrue(file_exists(LITHIUM_APP_PATH . "/resources/tmp/cache/$key"));
+ $this->assertTrue(file_exists(Libraries::get(true, 'resources') . "/tmp/cache/{$key}"));
$this->assertEqual(
- file_get_contents(LITHIUM_APP_PATH . "/resources/tmp/cache/$key"),
+ file_get_contents(Libraries::get(true, 'resources') . "/tmp/cache/{$key}"),
"{:expiry:$time}\ndata"
);
- $this->assertTrue(unlink(LITHIUM_APP_PATH . "/resources/tmp/cache/$key"));
- $this->assertFalse(file_exists(LITHIUM_APP_PATH . "/resources/tmp/cache/$key"));
+ $this->assertTrue(unlink(Libraries::get(true, 'resources') . "/tmp/cache/{$key}"));
+ $this->assertFalse(file_exists(Libraries::get(true, 'resources') . "/tmp/cache/{$key}"));
}
public function testWriteDefaultCacheExpiry() {
@@ -90,14 +96,14 @@ class FileTest extends \lithium\test\Unit {
$expected = 25;
$this->assertEqual($expected, $result);
- $this->assertTrue(file_exists(LITHIUM_APP_PATH . "/resources/tmp/cache/$key"));
+ $this->assertTrue(file_exists(Libraries::get(true, 'resources') . "/tmp/cache/{$key}"));
$this->assertEqual(
- file_get_contents(LITHIUM_APP_PATH . "/resources/tmp/cache/$key"),
- "{:expiry:$time}\ndata"
+ file_get_contents(Libraries::get(true, 'resources') . "/tmp/cache/{$key}"),
+ "{:expiry:{$time}}\ndata"
);
- $this->assertTrue(unlink(LITHIUM_APP_PATH . "/resources/tmp/cache/$key"));
- $this->assertFalse(file_exists(LITHIUM_APP_PATH . "/resources/tmp/cache/$key"));
+ $this->assertTrue(unlink(Libraries::get(true, 'resources') . "/tmp/cache/{$key}"));
+ $this->assertFalse(file_exists(Libraries::get(true, 'resources') . "/tmp/cache/{$key}"));
}
public function testRead() {
@@ -107,16 +113,15 @@ class FileTest extends \lithium\test\Unit {
$closure = $this->File->read($key);
$this->assertTrue(is_callable($closure));
- file_put_contents(LITHIUM_APP_PATH . "/resources/tmp/cache/$key", "{:expiry:$time}\ndata");
- $this->assertTrue(file_exists(LITHIUM_APP_PATH . "/resources/tmp/cache/$key"));
+ $path = Libraries::get(true, 'resources') . "/tmp/cache/{$key}";
+ file_put_contents($path, "{:expiry:$time}\ndata");
+ $this->assertTrue(file_exists($path));
$params = compact('key');
$result = $closure($this->File, $params, null);
- $expected = 'data';
- $this->assertEqual($expected, $result);
+ $this->assertEqual('data', $result);
- $this->assertTrue(unlink(LITHIUM_APP_PATH . "/resources/tmp/cache/$key"));
- $this->assertFalse(file_exists(LITHIUM_APP_PATH . "/resources/tmp/cache/$key"));
+ unlink($path);
$key = 'non_existent';
$params = compact('key');
@@ -133,47 +138,47 @@ class FileTest extends \lithium\test\Unit {
$closure = $this->File->read($key);
$this->assertTrue(is_callable($closure));
+ $path = Libraries::get(true, 'resources') . "/tmp/cache/{$key}";
- file_put_contents(LITHIUM_APP_PATH . "/resources/tmp/cache/$key", "{:expiry:$time}\ndata");
- $this->assertTrue(file_exists(LITHIUM_APP_PATH . "/resources/tmp/cache/$key"));
+ file_put_contents($path, "{:expiry:$time}\ndata");
+ $this->assertTrue(file_exists($path));
sleep(2);
$params = compact('key');
- $result = $closure($this->File, $params, null);
- $this->assertFalse($result);
+ $this->assertFalse($closure($this->File, $params, null));
}
public function testDelete() {
$key = 'key_to_delete';
$time = time() + 1;
+ $path = Libraries::get(true, 'resources') . "/tmp/cache/{$key}";
- file_put_contents(LITHIUM_APP_PATH . "/resources/tmp/cache/$key", "{:expiry:$time}\ndata");
- $this->assertTrue(file_exists(LITHIUM_APP_PATH . "/resources/tmp/cache/$key"));
+ file_put_contents($path, "{:expiry:$time}\ndata");
+ $this->assertTrue(file_exists($path));
$closure = $this->File->delete($key);
$this->assertTrue(is_callable($closure));
$params = compact('key');
- $result = $closure($this->File, $params, null);
- $this->assertTrue($result);
+ $this->assertTrue($closure($this->File, $params, null));
$key = 'non_existent';
$params = compact('key');
- $result = $closure($this->File, $params, null);
- $this->assertFalse($result);
+ $this->assertFalse($closure($this->File, $params, null));
}
public function testClear() {
$key = 'key_to_clear';
$time = time() + 1;
- file_put_contents(LITHIUM_APP_PATH . "/resources/tmp/cache/$key", "{:expiry:$time}\ndata");
+ $path = Libraries::get(true, 'resources') . "/tmp/cache/{$key}";
+ file_put_contents($path, "{:expiry:$time}\ndata");
$result = $this->File->clear();
$this->assertTrue($result);
- $this->assertFalse(file_exists(LITHIUM_APP_PATH . "/resources/tmp/cache/$key"));
+ $this->assertFalse(file_exists($path));
- $result = touch(LITHIUM_APP_PATH . "/resources/tmp/cache/empty");
+ $result = touch(Libraries::get(true, 'resources') . "/tmp/cache/empty");
$this->assertTrue($result);
}
@@ -188,8 +193,6 @@ class FileTest extends \lithium\test\Unit {
$result = $this->File->decrement($key);
$this->assertEqual(false, $result);
}
-
-
}
?>
\ No newline at end of file
diff --git a/libraries/lithium/tests/cases/storage/session/adapter/CookieTest.php b/libraries/lithium/tests/cases/storage/session/adapter/CookieTest.php
index e6174f7..849c7c3 100644
--- a/libraries/lithium/tests/cases/storage/session/adapter/CookieTest.php
+++ b/libraries/lithium/tests/cases/storage/session/adapter/CookieTest.php
@@ -31,7 +31,12 @@ class CookieTest extends \lithium\test\Unit {
}
public function tearDown() {
- $this->_destroyCookie();
+ $this->_destroyCookie($this->name);
+ $cookies = array_keys($_COOKIE);
+
+ foreach ($cookies as $cookie) {
+ setcookie($cookie, "", time()-1);
+ }
}
protected function _destroyCookie($name = null) {
@@ -84,7 +89,11 @@ class CookieTest extends \lithium\test\Unit {
public function testWriteArrayData() {
$key = 'user';
- $value = array('email' => 'test@localhost', 'name' => 'Testy McTesterson');
+ $value = array(
+ 'email' => 'test@localhost',
+ 'name' => 'Testy McTesterson',
+ 'address' => array('country' => 'Iran', 'city' => 'Mashhad')
+ );
$expires = "+2 days";
$path = '/';
@@ -95,7 +104,11 @@ class CookieTest extends \lithium\test\Unit {
$expected = compact('expires');
$expected += array('key' => 'user.email', 'value' => 'test@localhost');
- $this->assertCookie($expected, headers_list());
+ $this->assertCookie($expected);
+
+ $expected = compact('expires');
+ $expected += array('key' => 'user.address.country', 'value' => 'Iran');
+ $this->assertCookie($expected);
}
public function testReadDotSyntax() {
@@ -111,7 +124,11 @@ class CookieTest extends \lithium\test\Unit {
$this->assertEqual($value, $result);
$result = $closure($this->cookie, array('key' => null), null);
+<<<<<<< HEAD
$this->assertEqual($_COOKIE, $result);
+=======
+ $this->assertEqual($_COOKIE[$this->name], $result);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$key = 'does_not_exist';
$closure = $this->cookie->read($key);
@@ -152,10 +169,27 @@ class CookieTest extends \lithium\test\Unit {
$this->assertEqual($value, $result);
$result = $closure($this->cookie, array('key' => null), null);
+<<<<<<< HEAD
$this->assertEqual($_COOKIE, $result);
$key = 'does_not_exist';
$closure = $this->cookie->read($key);
+=======
+ $this->assertEqual($_COOKIE[$this->name], $result);
+
+ $key = 'does_not_exist';
+ $closure = $this->cookie->read($key);
+ $this->assertTrue(is_callable($closure));
+
+ $params = compact('key');
+ $result = $closure($this->cookie, $params, null);
+ $this->assertNull($result);
+ }
+
+ public function testReadNestedKey() {
+ $key = 'User.id';
+ $closure = $this->cookie->read($key);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$this->assertTrue(is_callable($closure));
$params = compact('key');
@@ -184,6 +218,47 @@ class CookieTest extends \lithium\test\Unit {
$this->assertFalse($result);
}
+ public function testClearCookie() {
+ $key = 'clear_key';
+ $value = 'clear_value';
+ $_COOKIE[$this->name][$key] = $value;
+
+ $closure = $this->cookie->check($key);
+ $this->assertTrue(is_callable($closure));
+
+ $params = compact('key');
+ $result = $closure($this->cookie, $params, null);
+ $this->assertTrue($result);
+
+ $closure = $this->cookie->clear();
+ $this->assertTrue(is_callable($closure));
+
+ $params = array();
+ $result = $closure($this->cookie, $params, null);
+ $this->assertTrue($result);
+ $this->assertNoCookie(compact('key', 'value'));
+
+ }
+
+ public function testDeleteArrayData() {
+ $key = 'user';
+ $value = array('email' => 'user@localhost', 'name' => 'Ali');
+ $_COOKIE[$this->name][$key] = $value;
+
+ $closure = $this->cookie->delete($key);
+ $this->assertTrue(is_callable($closure));
+
+ $params = compact('key');
+ $result = $closure($this->cookie, $params, null);
+ $this->assertTrue($result);
+
+ $expected = array('key' => 'user.name', 'value' => 'deleted');
+ $this->assertCookie($expected);
+
+ $expected = array('key' => 'user.email', 'value' => 'deleted');
+ $this->assertCookie($expected);
+ }
+
public function testDeleteNonExistentValue() {
$key = 'delete';
$value = 'deleted';
@@ -194,7 +269,11 @@ class CookieTest extends \lithium\test\Unit {
$params = compact('key');
$result = $closure($this->cookie, $params, null);
+<<<<<<< HEAD
$this->assertNull($result);
+=======
+ $this->assertTrue($result);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$this->assertCookie(compact('key', 'value', 'path'));
}
@@ -216,6 +295,10 @@ class CookieTest extends \lithium\test\Unit {
$result = $cookie->write($key, $value)->__invoke($cookie, compact('key', 'value'), null);
$this->assertCookie(compact('key', 'value'));
}
+<<<<<<< HEAD
+=======
+
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
?>
\ No newline at end of file
diff --git a/libraries/lithium/tests/cases/storage/session/adapter/PhpTest.php b/libraries/lithium/tests/cases/storage/session/adapter/PhpTest.php
index 709b984..33fb11f 100644
--- a/libraries/lithium/tests/cases/storage/session/adapter/PhpTest.php
+++ b/libraries/lithium/tests/cases/storage/session/adapter/PhpTest.php
@@ -8,6 +8,10 @@
namespace lithium\tests\cases\storage\session\adapter;
+<<<<<<< HEAD
+=======
+use lithium\core\Libraries;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
use lithium\storage\session\adapter\Php;
use lithium\tests\mocks\storage\session\adapter\MockPhp;
@@ -70,7 +74,7 @@ class PhpTest extends \lithium\test\Unit {
$config = array(
'session.name' => 'awesome_name', 'session.cookie_lifetime' => 1200,
'session.cookie_domain' => 'awesome.domain',
- 'session.save_path' => LITHIUM_APP_PATH . '/resources/tmp/',
+ 'session.save_path' => Libraries::get(true, 'resources') . '/tmp/',
'somebad.configuration' => 'whoops'
);
diff --git a/libraries/lithium/tests/cases/storage/session/strategy/HmacTest.php b/libraries/lithium/tests/cases/storage/session/strategy/HmacTest.php
new file mode 100644
index 0000000..43bfd95
--- /dev/null
+++ b/libraries/lithium/tests/cases/storage/session/strategy/HmacTest.php
@@ -0,0 +1,99 @@
+<?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\cases\storage\session\strategy;
+
+use lithium\storage\session\strategy\Hmac;
+use lithium\tests\mocks\storage\session\strategy\MockCookieSession;
+
+
+class HmacTest extends \lithium\test\Unit {
+
+ public function setUp() {
+ $this->secret = 'foobar';
+ $this->Hmac = new Hmac(array('secret' => $this->secret));
+ $this->mock = 'lithium\tests\mocks\storage\session\strategy\MockCookieSession';
+ MockCookieSession::reset();
+ }
+
+ public function testConstructException() {
+ $this->expectException('/HMAC strategy requires a secret key./');
+ $hmac = new Hmac();
+ }
+
+ public function testConstruct() {
+ $secret = 'foo';
+ $hmac = new Hmac(compact('secret'));
+ $this->assertTrue($hmac instanceof Hmac);
+ }
+
+ public function testWrite() {
+ $value = 'value';
+ $key = 'new_key';
+ $oldData = MockCookieSession::data();
+ $class = $this->mock;
+
+ $result = $this->Hmac->write($value, compact('key', 'class'));
+ $this->assertEqual($value, $result);
+
+ $signature = hash_hmac('sha1', serialize($oldData + array($key => $value)), $this->secret);
+ $signedData = MockCookieSession::data();
+ $this->assertEqual($signedData, $oldData + array('__signature' => $signature));
+ }
+
+ public function testReadWithValidSignature() {
+ $class = $this->mock;
+ $currentData = MockCookieSession::data();
+ $signature = hash_hmac('sha1', serialize($currentData), $this->secret);
+ $result = MockCookieSession::write('__signature', $signature);
+ $this->assertEqual($signature, $result);
+
+ $value = 'data_read';
+ $result = $this->Hmac->read($value, compact('class'));
+ $this->assertEqual($value, $result);
+ }
+
+ public function testReadWithNoSignature() {
+ $class = $this->mock;
+ $value = 'data_read';
+ $this->expectException('/HMAC signature not found./');
+ $result = $this->Hmac->read($value, compact('class'));
+ }
+
+ public function testReadWithInvalidSignature() {
+ $class = $this->mock;
+ $currentData = MockCookieSession::data();
+ $signature = 'some_invalid_signature';
+ $result = MockCookieSession::write('__signature', $signature);
+ $this->assertEqual($signature, $result);
+
+ $value = 'data_read_that_wont_match_signature';
+ $this->expectException('/Possible data tampering: HMAC signature does not match data./');
+ $result = $this->Hmac->read($value, compact('class'));
+ }
+
+ public function testDelete() {
+ $key = 'one';
+ $class = $this->mock;
+ $oldData = MockCookieSession::data();
+ $currentSignature = hash_hmac('sha1', serialize($oldData), $this->secret);
+ $result = MockCookieSession::write('__signature', $currentSignature);
+
+ $newData = $oldData;
+ unset($newData[$key]);
+
+ $expectedSignature = hash_hmac('sha1', serialize($newData), $this->secret);
+ $result = $this->Hmac->delete('foo', compact('class', 'key'));
+
+ $this->assertEqual('foo', $result);
+ $signature = MockCookieSession::read('__signature');
+ $this->assertEqual($expectedSignature, $signature);
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/libraries/lithium/tests/cases/template/ViewTest.php b/libraries/lithium/tests/cases/template/ViewTest.php
index 5bbde6f..461411e 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;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
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 fa02845..6041cdc 100755
--- a/libraries/lithium/tests/cases/template/helper/FormTest.php
+++ b/libraries/lithium/tests/cases/template/helper/FormTest.php
@@ -96,7 +96,15 @@ class FormTest extends \lithium\test\Unit {
$result = $this->form->create(null, array('id' => 'Registration'));
$this->assertTags($result, array(
+<<<<<<< HEAD
'form' => array('action' => "{$this->base}posts", 'method' => 'post', 'id' => 'Registration')
+=======
+ 'form' => array(
+ 'action' => "{$this->base}posts",
+ 'method' => 'post',
+ 'id' => 'Registration'
+ )
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
));
}
@@ -142,13 +150,17 @@ class FormTest extends \lithium\test\Unit {
'body' => 'This is the body of the saved post'
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
)));
$result = $this->form->create($record);
$this->assertTags($result, array(
'form' => array('action' => "{$this->base}posts", 'method' => 'post')
<<<<<<< HEAD
+<<<<<<< HEAD
=======
)));
$result = $this->form->create($record);
@@ -182,14 +194,32 @@ class FormTest extends \lithium\test\Unit {
'model' => $this->_model, 'data' => array('pass' => 'foobar')
)));
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ ));
+ }
+
+ /**
+ * Ensures that password fields aren't rendered with pre-populated values from bound record or
+ * document objects.
+ *
+ * @return void
+ */
+ public function testPasswordWithBindingValue() {
+ $this->form->create(new Record(array(
+ 'model' => $this->_model, 'data' => array('pass' => 'foobar')
+ )));
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$result = $this->form->password('pass');
$this->assertTags($result, array(
'input' => array('type' => 'password', 'name' => 'pass', 'id' => 'MockFormPostPass')
<<<<<<< HEAD
+<<<<<<< HEAD
>>>>>>> 25a362f706960b2becbf88e91cffc1b1638b7890
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
));
}
@@ -293,6 +323,16 @@ class FormTest extends \lithium\test\Unit {
$result = $this->form->file('upload');
$this->assertTags($result, array('input' => array(
'type' => 'file', 'name' => 'upload', 'id' => 'Upload'
+<<<<<<< HEAD
+=======
+ )));
+ }
+
+ public function testHiddenFieldWithId() {
+ $result = $this->form->hidden('my_field');
+ $this->assertTags($result, array('input' => array(
+ 'type' => 'hidden', 'name' => 'my_field', 'id' => 'MyField'
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
)));
}
@@ -659,8 +699,11 @@ class FormTest extends \lithium\test\Unit {
'/div'
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
));
$result = $this->form->field('name', array('type' => 'radio', 'value' => 'foo'));
@@ -670,6 +713,7 @@ class FormTest extends \lithium\test\Unit {
'label' => array('for' => 'Name'), 'Name', '/label',
'/div'
<<<<<<< HEAD
+<<<<<<< HEAD
));
=======
@@ -680,6 +724,30 @@ class FormTest extends \lithium\test\Unit {
'div' => array(),
'input' => array('type' => 'radio', 'name' => 'name', 'value' => 'foo', 'id' => 'Name'),
'label' => array('for' => 'Name'), 'Name', '/label',
+=======
+ ));
+
+ $result = $this->form->field('name', array('type' => 'checkbox'));
+ $expected = array(
+ '<div>',
+ '<input type="hidden" name="name" value="" />',
+ '<input type="checkbox" name="name" id="Name" value="1" />',
+ '<label for="Name">Name</label></div>'
+ );
+ $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'),
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
'/div'
));
@@ -718,6 +786,38 @@ class FormTest extends \lithium\test\Unit {
));
}
+<<<<<<< HEAD
+=======
+ /**
+ * Demonstrates that the options for a `<label />` element can be passed through the `field()`
+ * method, using the label text as a key.
+ *
+ * @return void
+ */
+ public function testFieldLabelWithOptions() {
+ $result = $this->form->field('name', array(
+ 'label' => array('Item Name' => array('class' => 'required'))
+ ));
+ $this->assertTags($result, array(
+ 'div' => array(),
+ 'label' => array('for' => 'Name', 'class' => 'required'), 'Item Name', '/label',
+ 'input' => array('type' => 'text', 'name' => 'name', 'id' => 'Name'),
+ ));
+
+ $result = $this->form->field('video_preview', array(
+ 'label' => array('<a href="http://www.youtube.com/">Youtube</a>' => array(
+ 'escape' => false
+ ))
+ ));
+ $this->assertTags($result, array(
+ 'div' => array(),
+ 'label' => array('for' => 'VideoPreview'),
+ 'a' => array('href' => 'http://www.youtube.com/'), 'Youtube', '/a', '/label',
+ 'input' => array('type' => 'text', 'name' => 'video_preview', 'id' => 'VideoPreview'),
+ ));
+ }
+
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
public function testMultipleFields() {
$result = $this->form->field(array(
'name' => 'Enter a name',
@@ -895,6 +995,7 @@ class FormTest extends \lithium\test\Unit {
'input' => array('type' => 'text', 'name' => 'name', 'id' => 'Name')
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
));
}
@@ -980,6 +1081,11 @@ class FormTest extends \lithium\test\Unit {
));
}
+=======
+ ));
+ }
+
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
public function testFieldAssumeSelectIfList() {
$result = $this->form->field('colors', array(
'list' => array('r' => 'red', 'g' => 'green', 'b' => 'blue')
@@ -1016,7 +1122,10 @@ class FormTest extends \lithium\test\Unit {
));
}
+<<<<<<< HEAD
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
/**
* Tests that inputs for nested objects can be assigned using dot syntax.
*
@@ -1032,9 +1141,18 @@ class FormTest extends \lithium\test\Unit {
)));
}
<<<<<<< HEAD
+<<<<<<< HEAD
>>>>>>> 25a362f706960b2becbf88e91cffc1b1638b7890
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+
+ 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")));
+ }
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
?>
\ No newline at end of file
diff --git a/libraries/lithium/tests/cases/template/helper/HtmlTest.php b/libraries/lithium/tests/cases/template/helper/HtmlTest.php
index ac06d93..274dd89 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;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
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')
+ ));
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$this->assertNull($result);
}
diff --git a/libraries/lithium/tests/cases/template/view/CompilerTest.php b/libraries/lithium/tests/cases/template/view/CompilerTest.php
index 93b2b57..56d328f 100644
--- a/libraries/lithium/tests/cases/template/view/CompilerTest.php
+++ b/libraries/lithium/tests/cases/template/view/CompilerTest.php
@@ -8,21 +8,31 @@
namespace lithium\tests\cases\template\view;
+<<<<<<< HEAD
+=======
+use lithium\core\Libraries;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
use lithium\template\view\Compiler;
class CompilerTest extends \lithium\test\Unit {
protected $_path;
- protected $_file = 'resources/tmp/tests/template.html.php';
+ protected $_file = 'template.html.php';
public function skip() {
- $path = LITHIUM_APP_PATH . '/resources/tmp/tests';
- $this->skipIf(!is_writable($path), "{$path} is not writable.");
+ $path = realpath(Libraries::get(true, 'resources') . '/tmp/tests');
+ $this->skipIf(!is_writable($path), "Path `{$path}` is not writable.");
+
+ $path = realpath(Libraries::get(true, 'resources') . '/tmp/cache/templates');
+ $this->skipIf(!is_writable($path), "Path `{$path}` is not writable.");
}
public function setUp() {
- $this->_path = str_replace('\\', '/', LITHIUM_APP_PATH);
+ $this->_path = realpath(
+ str_replace('\\', '/', Libraries::get(true, 'resources')) . '/tmp/tests'
+ );
+
file_put_contents("{$this->_path}/{$this->_file}", "
<?php echo 'this is unescaped content'; ?" . ">
<?='this is escaped content'; ?" . ">
@@ -41,7 +51,9 @@ class CompilerTest extends \lithium\test\Unit {
}
public function tearDown() {
- foreach (glob("{$this->_path}/resources/tmp/cache/templates/*.php") as $file) {
+ $path = realpath(Libraries::get(true, 'resources') . '/tmp/cache/templates');
+
+ foreach (glob("{$path}/*.php") as $file) {
unlink($file);
}
unlink("{$this->_path}/{$this->_file}");
@@ -49,7 +61,6 @@ class CompilerTest extends \lithium\test\Unit {
public function testTemplateContentRewriting() {
$template = Compiler::template("{$this->_path}/{$this->_file}");
-
$this->assertTrue(file_exists($template));
$expected = array(
@@ -88,7 +99,7 @@ class CompilerTest extends \lithium\test\Unit {
}
public function testTemplateCacheHit() {
- $path = LITHIUM_APP_PATH . '/resources/tmp/cache/templates';
+ $path = Libraries::get(true, 'resources') . '/tmp/cache/templates';
$original = Compiler::template("{$this->_path}/{$this->_file}", compact('path'));
$cache = glob("{$path}/*");
clearstatcache();
diff --git a/libraries/lithium/tests/cases/template/view/RendererTest.php b/libraries/lithium/tests/cases/template/view/RendererTest.php
index fadd99e..08ade36 100644
--- a/libraries/lithium/tests/cases/template/view/RendererTest.php
+++ b/libraries/lithium/tests/cases/template/view/RendererTest.php
@@ -8,13 +8,23 @@
namespace lithium\tests\cases\template\view;
+<<<<<<< HEAD
+use lithium\template\View;
+use lithium\action\Request;
+=======
+use stdClass;
use lithium\template\View;
use lithium\action\Request;
+use lithium\action\Response;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
use lithium\template\Helper;
use lithium\template\helper\Html;
use lithium\template\view\adapter\Simple;
use lithium\net\http\Router;
+<<<<<<< HEAD
use stdClass;
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
class RendererTest extends \lithium\test\Unit {
@@ -22,9 +32,18 @@ class RendererTest extends \lithium\test\Unit {
$this->_routes = Router::get();
Router::reset();
Router::connect('/{:controller}/{:action}');
+<<<<<<< HEAD
$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()
+ ));
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
public function tearDown() {
@@ -35,9 +54,13 @@ class RendererTest extends \lithium\test\Unit {
}
public function testInitialization() {
+<<<<<<< HEAD
$expected = array(
'url', 'path', 'options', 'content', 'title', 'scripts', 'styles', 'head'
);
+=======
+ $expected = array('url', 'path', 'options', 'title', 'scripts', 'styles', 'head');
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$result = array_keys($this->subject->handlers());
$this->assertEqual($expected, $result);
@@ -58,6 +81,12 @@ class RendererTest extends \lithium\test\Unit {
$this->assertNull($this->subject->foo());
$this->assertFalse(isset($this->subject->foo));
+ $result = $this->subject->title("<script>alert('XSS');</script>");
+ $this->assertEqual('<script>alert('XSS');</script>', $result);
+
+ $result = $this->subject->title();
+ $this->assertEqual('<script>alert('XSS');</script>', $result);
+
$this->subject = new Simple(array('context' => array(
'content' => '', 'title' => '', 'scripts' => array(), 'styles' => array(), 'foo' => '!'
)));
@@ -82,6 +111,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() {
@@ -91,9 +121,13 @@ class RendererTest extends \lithium\test\Unit {
$foo = function($value) { return "Foo: {$value}"; };
+<<<<<<< HEAD
$expected = array(
'url', 'path', 'options', 'content', 'title', 'scripts', 'styles', 'head', 'foo'
);
+=======
+ $expected = array('url', 'path', 'options', 'title', 'scripts', 'styles', 'head', 'foo');
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$result = array_keys($this->subject->handlers(compact('foo')));
$this->assertEqual($expected, $result);
@@ -180,8 +214,15 @@ class RendererTest extends \lithium\test\Unit {
public function testGetters() {
$this->assertTrue($this->subject->request() instanceof Request);
+<<<<<<< HEAD
+ $this->subject = new Simple();
+ $this->assertNull($this->subject->request());
+=======
+ $this->assertTrue($this->subject->response() instanceof Response);
$this->subject = new Simple();
$this->assertNull($this->subject->request());
+ $this->assertNull($this->subject->response());
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
public function testSetAndData() {
@@ -192,11 +233,11 @@ class RendererTest extends \lithium\test\Unit {
$result = $this->subject->data();
$this->assertEqual($data, $result);
- $result = $this->subject->set(array('more' => new StdClass()));
+ $result = $this->subject->set(array('more' => new stdClass()));
$this->assertNull($result);
$result = $this->subject->data();
- $this->assertEqual($data + array('more' => new StdClass()), $result);
+ $this->assertEqual($data + array('more' => new stdClass()), $result);
}
/**
@@ -228,18 +269,24 @@ class RendererTest extends \lithium\test\Unit {
$this->assertEqual('Bar', $this->subject->title());
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
=======
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$this->assertFalse(trim($this->subject->head()));
$this->assertEqual('foo', trim($this->subject->head('foo')));
$this->assertEqual("foo\n\tbar", trim($this->subject->head('bar')));
$this->assertEqual("foo\n\tbar", trim($this->subject->head()));
<<<<<<< HEAD
+<<<<<<< HEAD
>>>>>>> 25a362f706960b2becbf88e91cffc1b1638b7890
=======
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
}
diff --git a/libraries/lithium/tests/cases/template/view/adapter/FileTest.php b/libraries/lithium/tests/cases/template/view/adapter/FileTest.php
index b70296b..99faa8c 100644
--- a/libraries/lithium/tests/cases/template/view/adapter/FileTest.php
+++ b/libraries/lithium/tests/cases/template/view/adapter/FileTest.php
@@ -8,48 +8,47 @@
namespace lithium\tests\cases\template\view\adapter;
+<<<<<<< HEAD
+=======
+use lithium\core\Libraries;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
use lithium\template\view\adapter\File;
class FileTest extends \lithium\test\Unit {
- protected $_path = '/resources/tmp/tests';
+ protected $_path;
public function setUp() {
+ $this->_path = Libraries::get(true, 'resources') . '/tmp/tests';
+
$template1 = '<' . '?php echo $foo; ?' . '>';
$template2 = '<' . '?php echo $this["foo"]; ?' . '>';
- file_put_contents(LITHIUM_APP_PATH . "{$this->_path}/template1.html.php", $template1);
- file_put_contents(LITHIUM_APP_PATH . "{$this->_path}/template2.html.php", $template2);
+ file_put_contents("{$this->_path}/template1.html.php", $template1);
+ file_put_contents("{$this->_path}/template2.html.php", $template2);
}
public function tearDown() {
- unlink(LITHIUM_APP_PATH . "{$this->_path}/template1.html.php");
- unlink(LITHIUM_APP_PATH . "{$this->_path}/template2.html.php");
+ unlink("{$this->_path}/template1.html.php");
+ unlink("{$this->_path}/template2.html.php");
}
public function testRenderingWithExtraction() {
$file = new File();
- $content = $file->render(LITHIUM_APP_PATH . "{$this->_path}/template1.html.php", array(
- 'foo' => 'bar'
- ));
+
+ $content = $file->render("{$this->_path}/template1.html.php", array('foo' => 'bar'));
$this->assertEqual('bar', $content);
- $content = $file->render(LITHIUM_APP_PATH . "{$this->_path}/template2.html.php", array(
- 'foo' => 'bar'
- ));
+ $content = $file->render("{$this->_path}/template2.html.php", array('foo' => 'bar'));
$this->assertEqual('bar', $content);
}
public function testRenderingWithNoExtraction() {
$file = new File(array('extract' => false));
$this->expectException('Undefined variable: foo');
- $content = $file->render(LITHIUM_APP_PATH . "{$this->_path}/template1.html.php", array(
- 'foo' => 'bar'
- ));
+ $content = $file->render("{$this->_path}/template1.html.php", array('foo' => 'bar'));
$this->assertFalse($content);
- $content = $file->render(LITHIUM_APP_PATH . "{$this->_path}/template2.html.php", array(
- 'foo' => 'bar'
- ));
+ $content = $file->render("{$this->_path}/template2.html.php", array('foo' => 'bar'));
$this->assertEqual('bar', $content);
}
@@ -83,14 +82,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/GroupTest.php b/libraries/lithium/tests/cases/test/GroupTest.php
index 4de1e9f..1613a64 100644
--- a/libraries/lithium/tests/cases/test/GroupTest.php
+++ b/libraries/lithium/tests/cases/test/GroupTest.php
@@ -11,9 +11,13 @@ namespace lithium\tests\cases\test;
use lithium\test\Group;
use lithium\util\Collection;
<<<<<<< HEAD
+<<<<<<< HEAD
=======
use lithium\core\Libraries;
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+use lithium\core\Libraries;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
class GroupTest extends \lithium\test\Unit {
@@ -143,7 +147,11 @@ class GroupTest extends \lithium\test\Unit {
}
public function testAddTestAppGroup() {
+<<<<<<< HEAD
$test_app = LITHIUM_APP_PATH . '/resources/tmp/tests/test_app';
+=======
+ $test_app = Libraries::get(true, 'resources') . '/tmp/tests/test_app';
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
mkdir($test_app);
Libraries::add('test_app', array('path' => $test_app));
@@ -173,7 +181,11 @@ class GroupTest extends \lithium\test\Unit {
}
public function testRunGroupAllForTestApp() {
+<<<<<<< HEAD
$test_app = LITHIUM_APP_PATH . '/resources/tmp/tests/test_app';
+=======
+ $test_app = Libraries::get(true, 'resources') . '/tmp/tests/test_app';
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
mkdir($test_app);
Libraries::add('test_app', array('path' => $test_app));
@@ -195,7 +207,11 @@ class GroupTest extends \lithium\test\Unit {
}
public function testRunGroupForTestAppModel() {
+<<<<<<< HEAD
$test_app = LITHIUM_APP_PATH . '/resources/tmp/tests/test_app';
+=======
+ $test_app = Libraries::get(true, 'resources') . '/tmp/tests/test_app';
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
mkdir($test_app);
Libraries::add('test_app', array('path' => $test_app));
diff --git a/libraries/lithium/tests/cases/test/UnitTest.php b/libraries/lithium/tests/cases/test/UnitTest.php
index 3493f85..8ee0880 100644
--- a/libraries/lithium/tests/cases/test/UnitTest.php
+++ b/libraries/lithium/tests/cases/test/UnitTest.php
@@ -8,10 +8,11 @@
namespace lithium\tests\cases\test;
+use Exception;
+use lithium\core\Libraries;
use lithium\tests\mocks\test\MockUnitTest;
use lithium\tests\mocks\test\cases\MockSkipThrowsException;
use lithium\tests\mocks\test\cases\MockTestErrorHandling;
-use \Exception;
class UnitTest extends \lithium\test\Unit {
@@ -29,15 +30,13 @@ class UnitTest extends \lithium\test\Unit {
}
public function testCompareIsEqual() {
- $expected = true;
$result = $this->compare('equal', 'string', 'string');
- $this->assertEqual($expected, $result);
+ $this->assertTrue($result);
}
public function testCompareIsIdentical() {
- $expected = true;
$result = $this->compare('identical', 'string', 'string');
- $this->assertEqual($expected, $result);
+ $this->assertTrue($result);
}
public function testCompareTypes() {
@@ -65,19 +64,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 +103,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
)
)
)
@@ -381,7 +363,7 @@ class UnitTest extends \lithium\test\Unit {
}
public function testCleanUp() {
- $base = LITHIUM_APP_PATH . '/resources/tmp/tests';
+ $base = Libraries::get(true, 'resources') . '/tmp/tests';
$this->skipIf(!is_writable($base), "{$base} is not writable.");
$this->assertTrue(mkdir("{$base}/cleanup_test"));
@@ -393,7 +375,7 @@ class UnitTest extends \lithium\test\Unit {
}
public function testCleanUpWithFullPath() {
- $base = LITHIUM_APP_PATH . '/resources/tmp/tests';
+ $base = Libraries::get(true, 'resources') . '/tmp/tests';
$this->skipIf(!is_writable($base), "{$base} is not writable.");
$this->assertTrue(mkdir("{$base}/cleanup_test"));
@@ -409,7 +391,7 @@ class UnitTest extends \lithium\test\Unit {
}
public function testCleanUpWithRelativePath() {
- $base = LITHIUM_APP_PATH . '/resources/tmp/tests';
+ $base = Libraries::get(true, 'resources') . '/tmp/tests';
$this->skipIf(!is_writable($base), "{$base} is not writable.");
$this->assertTrue(mkdir("{$base}/cleanup_test"));
@@ -427,7 +409,7 @@ class UnitTest extends \lithium\test\Unit {
public function testSkipIf() {
try {
$this->skipIf(true, 'skip me');
- } catch (\Exception $e) {
+ } catch (Exception $e) {
$result = $e->getMessage();
}
$expected = 'skip me';
@@ -493,11 +475,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 +524,11 @@ class UnitTest extends \lithium\test\Unit {
public function testCompareIdenticalArray() {
$expected = array(
+<<<<<<< HEAD
'trace' => '[0]',
+=======
+ 'trace' => null,
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
'expected' => array(),
'result' => array('two', 'values')
);
@@ -550,12 +536,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);
+ }
+
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
/**
* Always keep second to last.
*
*/
public function testResults() {
+<<<<<<< HEAD
$expected = 87;
+=======
+ $expected = 89;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$result = count($this->results());
$this->assertEqual($expected, $result);
}
@@ -581,6 +590,10 @@ class UnitTest extends \lithium\test\Unit {
'testCompareWithEmptyResult',
'testExceptionCatching', 'testErrorHandling', 'testAssertObjects',
'testAssertArrayIdentical', 'testCompareIdenticalArray',
+<<<<<<< HEAD
+=======
+ 'testCompareEqualNullArray', 'testCompareIdenticalNullArray',
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
'testResults', 'testTestMethods'
);
$this->assertIdentical($expected, $this->methods());
diff --git a/libraries/lithium/tests/cases/test/filter/AffectedTest.php b/libraries/lithium/tests/cases/test/filter/AffectedTest.php
index 9b2ae50..756b0d5 100644
--- a/libraries/lithium/tests/cases/test/filter/AffectedTest.php
+++ b/libraries/lithium/tests/cases/test/filter/AffectedTest.php
@@ -77,6 +77,23 @@ class AffectedTest extends \lithium\test\Unit {
$result = $tests->map('get_class', array('collect' => false));
$this->assertEqual($expected, $result);
}
+
+ public function testAnalyze() {
+ $ns = 'lithium\tests\cases';
+
+ $expected = array(
+ 'lithium\g11n\Message' => "{$ns}\g11n\MessageTest",
+ 'lithium\console\command\g11n\Extract' => "{$ns}\console\command\g11n\ExtractTest"
+ );
+
+ $group = new Group();
+ $group->add('lithium\tests\cases\g11n\CatalogTest');
+ $this->report->group = $group;
+ $tests = Affected::apply($this->report, $group->tests());
+ $results = Affected::analyze($this->report);
+
+ $this->assertEqual($results, $expected);
+ }
}
?>
\ No newline at end of file
diff --git a/libraries/lithium/tests/cases/util/CollectionTest.php b/libraries/lithium/tests/cases/util/CollectionTest.php
index b5e4922..4a24605 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;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
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..e2d9828 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}");
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
return $info['value'];
}
}
diff --git a/libraries/lithium/tests/cases/util/StringTest.php b/libraries/lithium/tests/cases/util/StringTest.php
index dec17dc..bc595d3 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
**/
+=======
+ */
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
public function testRandomGenerator() {
// Disallow allow seeding twice
$this->assertFalse(String::seed() && String::seed());
@@ -431,8 +435,7 @@ class StringTest extends \lithium\test\Unit {
$this->assertEqual($expected, $result);
$result = String::tokenize(null);
- $expected = null;
- $this->assertEqual($expected, $result);
+ $this->assertNull($result);
}
/**
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..525a5df 100644
--- a/libraries/lithium/tests/integration/analysis/LoggerTest.php
+++ b/libraries/lithium/tests/integration/analysis/LoggerTest.php
@@ -8,6 +8,10 @@
namespace lithium\tests\integration\analysis;
+<<<<<<< HEAD
+=======
+use lithium\core\Libraries;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
use lithium\analysis\Logger;
use lithium\util\Collection;
use lithium\util\collection\Filters;
@@ -19,12 +23,19 @@ class LoggerTest extends \lithium\test\Unit {
public function testWriteFilter() {
+<<<<<<< HEAD
$base = LITHIUM_APP_PATH . '/resources/tmp/logs';
+=======
+ $base = Libraries::get(true, 'resources') . '/tmp/logs';
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$this->skipIf(!is_writable($base), "{$base} is not writable.");
Filters::apply('lithium\analysis\Logger', 'write', function($self, $params, $chain) {
$params['message'] = 'Filtered Message';
+<<<<<<< HEAD
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
return $chain->next($self, $params, $chain);
});
@@ -40,7 +51,10 @@ class LoggerTest extends \lithium\test\Unit {
unlink($base . '/info.log');
}
+<<<<<<< HEAD
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
?>
\ No newline at end of file
diff --git a/libraries/lithium/tests/integration/data/CrudTest.php b/libraries/lithium/tests/integration/data/CrudTest.php
index aeceedf..7ffc749 100644
--- a/libraries/lithium/tests/integration/data/CrudTest.php
+++ b/libraries/lithium/tests/integration/data/CrudTest.php
@@ -11,10 +11,14 @@ namespace lithium\tests\integration\data;
use Exception;
use lithium\data\Connections;
<<<<<<< HEAD
+<<<<<<< HEAD
use lithium\tests\mocks\data\Company;
=======
use lithium\tests\mocks\data\Companies;
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+use lithium\tests\mocks\data\Companies;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
class CrudTest extends \lithium\test\Integration {
@@ -29,6 +33,7 @@ class CrudTest extends \lithium\test\Integration {
public function setUp() {
<<<<<<< HEAD
+<<<<<<< HEAD
$this->_connection = Connections::get('test');
Company::config();
$this->_key = Company::meta('key');
@@ -37,6 +42,11 @@ class CrudTest extends \lithium\test\Integration {
$this->_key = Companies::key();
$this->_connection = Connections::get('test');
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ Companies::config();
+ $this->_key = Companies::key();
+ $this->_connection = Connections::get('test');
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
/**
@@ -60,6 +70,7 @@ class CrudTest extends \lithium\test\Integration {
*/
public function testCreate() {
<<<<<<< HEAD
+<<<<<<< HEAD
$new = Company::create(array($this->_key => 12345, 'name' => 'Acme, Inc.'));
$result = $new->data();
@@ -79,6 +90,8 @@ class CrudTest extends \lithium\test\Integration {
$this->assertEqual($expected[$this->_key], $result[$this->_key]);
$this->assertEqual($expected['name'], $result['name']);
=======
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
Companies::all()->delete();
$this->assertIdentical(0, Companies::count());
@@ -100,22 +113,31 @@ class CrudTest extends \lithium\test\Integration {
}
$this->assertEqual('Acme, Inc.', $existing->name);
$this->assertTrue($existing->active);
+<<<<<<< HEAD
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$this->assertTrue($existing->exists());
}
public function testUpdate() {
<<<<<<< HEAD
+<<<<<<< HEAD
$existing = Company::find(12345);
=======
$existing = Companies::first();
$this->assertEqual($existing->name, 'Acme, Inc.');
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ $existing = Companies::first();
+ $this->assertEqual($existing->name, 'Acme, Inc.');
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$existing->name = 'Big Brother and the Holding Company';
$result = $existing->save();
$this->assertTrue($result);
<<<<<<< HEAD
+<<<<<<< HEAD
$existing = Company::find(12345);
$result = $existing->data();
$expected = array($this->_key => 12345, 'name' => 'Big Brother and the Holding Company');
@@ -129,6 +151,8 @@ class CrudTest extends \lithium\test\Integration {
}
}
=======
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$existing = Companies::first();
foreach (Companies::key($existing) as $val) {
$this->assertTrue($val);
@@ -171,5 +195,9 @@ class CrudTest extends \lithium\test\Integration {
}
}
+<<<<<<< HEAD
?>
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+?>
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
diff --git a/libraries/lithium/tests/integration/data/FieldsTest.php b/libraries/lithium/tests/integration/data/FieldsTest.php
index 548959d..1adb9b7 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;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
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');
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$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)));
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$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(
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
'conditions' => array($key => $id),
'fields' => array($key)
));
diff --git a/libraries/lithium/tests/integration/data/SourceTest.php b/libraries/lithium/tests/integration/data/SourceTest.php
index 87d7d04..bf8287a 100644
--- a/libraries/lithium/tests/integration/data/SourceTest.php
+++ b/libraries/lithium/tests/integration/data/SourceTest.php
@@ -12,6 +12,7 @@ use Exception;
use lithium\data\Connections;
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
class Company extends \lithium\data\Model {
@@ -39,6 +40,10 @@ use lithium\tests\mocks\data\Employee;
use lithium\tests\mocks\data\Company;
use lithium\tests\mocks\data\Employee;
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+use lithium\tests\mocks\data\Company;
+use lithium\tests\mocks\data\Employee;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
class SourceTest extends \lithium\test\Unit {
diff --git a/libraries/lithium/tests/integration/data/source/CouchDbTest.php b/libraries/lithium/tests/integration/data/source/CouchDbTest.php
index eba1614..e4a731d 100644
--- a/libraries/lithium/tests/integration/data/source/CouchDbTest.php
+++ b/libraries/lithium/tests/integration/data/source/CouchDbTest.php
@@ -9,12 +9,16 @@
namespace lithium\tests\integration\data\source;
use lithium\data\Connections;
+<<<<<<< HEAD
class MockCouchModel extends \lithium\data\Model {
protected $_schema = array(
'someKey' => array()
);
}
+=======
+use lithium\tests\mocks\MockCouchModel;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
class CouchDbTest extends \lithium\test\Integration {
@@ -98,7 +102,10 @@ class CouchDbTest extends \lithium\test\Integration {
$this->assertEqual($data['id'], $updated['id']);
$this->assertNotEqual($data['rev'], $updated['rev']);
}
+<<<<<<< HEAD
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
?>
\ No newline at end of file
diff --git a/libraries/lithium/tests/integration/g11n/ResourcesMessageTest.php b/libraries/lithium/tests/integration/g11n/ResourcesMessageTest.php
index 84118a1..21311d3 100644
--- a/libraries/lithium/tests/integration/g11n/ResourcesMessageTest.php
+++ b/libraries/lithium/tests/integration/g11n/ResourcesMessageTest.php
@@ -28,7 +28,8 @@ class ResourcesMessageTest extends \lithium\test\Unit {
'lithium' => array(
'adapter' => 'Php',
'path' => LITHIUM_LIBRARY_PATH . '/lithium/g11n/resources/php'
- )));
+ )
+ ));
}
public function tearDown() {
@@ -46,13 +47,11 @@ class ResourcesMessageTest extends \lithium\test\Unit {
* @return void
*/
public function testPlurals1() {
- $locales = array(
- 'en'
- );
+ $locales = array('en');
+
foreach ($locales as $locale) {
- $expected = 2;
$result = Catalog::read('lithium', 'message.pluralForms', $locale);
- $this->assertEqual($expected, $result, "Locale: `{$locale}`\n{:message}");
+ $this->assertEqual(2, $result, "Locale: `{$locale}`\n{:message}");
$rule = Catalog::read('lithium', 'message.pluralRule', $locale);
diff --git a/libraries/lithium/tests/integration/net/http/ServiceTest.php b/libraries/lithium/tests/integration/net/http/ServiceTest.php
index 067611d..1509d84 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
+=======
+
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$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
+=======
+
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$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
+=======
+
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$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/integration/storage/CookieTest.php b/libraries/lithium/tests/integration/storage/CookieTest.php
new file mode 100644
index 0000000..8e02c98
--- /dev/null
+++ b/libraries/lithium/tests/integration/storage/CookieTest.php
@@ -0,0 +1,145 @@
+<?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\integration\storage;
+
+use lithium\storage\Session;
+
+class CookieTest extends \lithium\test\Unit {
+
+ public function setUp() {
+ Session::reset();
+ $cookies = array_keys($_COOKIE);
+
+ foreach ($cookies as $cookie) {
+ setcookie($cookie, "", time()-1);
+ }
+ }
+
+ public function tearDown() {
+ Session::reset();
+ $cookies = array_keys($_COOKIE);
+
+ foreach ($cookies as $cookie) {
+ setcookie($cookie, "", time()-1);
+ }
+ }
+
+ public function testCookieWriteReadDelete() {
+ Session::config(array(
+ 'li3' => array(
+ 'adapter' => 'Cookie',
+ 'expiry' => '+1 day',
+ )
+ ));
+
+ Session::write('ns.testkey1', 'value1', array('name' => 'li3'));
+ Session::write('ns.testkey2', 'value2', array('name' => 'li3'));
+ Session::write('ns.testkey3', 'value3', array('name' => 'li3'));
+
+ $this->assertCookie(
+ array('key' => 'ns.testkey1', 'value' => 'value1')
+ );
+ $this->assertCookie(
+ array('key' => 'ns.testkey2', 'value' => 'value2')
+ );
+ $this->assertCookie(
+ array('key' => 'ns.testkey3', 'value' => 'value3')
+ );
+
+ Session::delete('ns.testkey1', array('name' => 'li3'));
+ Session::delete('ns.testkey2', array('name' => 'li3'));
+ Session::delete('ns.testkey3', array('name' => 'li3'));
+
+ $params = array('exires' => '-1 second', 'path' => '/');
+
+ $this->assertNoCookie(array('key' => 'ns.testkey1'));
+ $this->assertNoCookie(array('key' => 'ns.testkey2'));
+ $this->assertNoCookie(array('key' => 'ns.testkey3'));
+ }
+
+ public function testStrategiesPhpAdapter() {
+ Session::config(array(
+ 'strategy' => array(
+ 'adapter' => 'Php',
+ 'strategies' => array('Hmac' => array('secret' => 'somesecretkey'))
+ )
+ ));
+
+ $key = 'test';
+ $value = 'value';
+
+ Session::write($key, $value, array('name' => 'strategy'));
+ $result = Session::read($key, array('name' => 'strategy'));
+
+ $this->assertEqual($value, $result);
+ $this->assertTrue(Session::delete($key, array('name' => 'strategy')));
+ $result = Session::read($key, array('name' => 'strategy'));
+ $this->assertNull($result);
+
+ Session::write($key, $value, array('name' => 'strategy'));
+ $result = Session::read($key, array('name' => 'strategy'));
+ $this->assertEqual($value, $result);
+
+ $cache = $_SESSION;
+ $_SESSION['injectedkey'] = 'hax0r';
+ $this->expectException('/Possible data tampering - HMAC signature does not match data./');
+ $result = Session::read($key, array('name' => 'strategy'));
+ $_SESSION = $cache;
+ }
+
+ public function testStrategiesCookieAdapter() {
+ $key = 'test_key';
+ $value = 'test_value';
+
+ Session::config(array(
+ 'default' => array(
+ 'adapter' => 'Cookie',
+ 'strategies' => array('Hmac' => array('secret' => 'somesecretkey')),
+ )
+ ));
+
+ $result = Session::write($key, $value);
+ $this->assertTrue($result);
+
+ $result = Session::read($key);
+ $this->assertEqual($value, $result);
+
+ $this->assertTrue(Session::delete($key));
+
+ $result = Session::read($key);
+ $this->assertNull($result);
+
+ Session::write($key, $value);
+ $result = Session::read($key);
+ $this->assertEqual($value, $result);
+ $this->assertTrue(Session::delete($key));
+ }
+
+ public function testHmacStrategy() {
+ $key = 'test';
+ $value = 'value';
+ $name = 'hmac_test';
+
+ Session::config(array(
+ 'default' => array(
+ 'adapter' => 'Cookie',
+ 'strategies' => array('Hmac' => array('secret' => 'somesecretkey')),
+ 'name' => $name
+ )
+ ));
+
+ $cache = $_COOKIE;
+ $_COOKIE[$name]['injectedkey'] = 'hax0r';
+ $this->expectException('/Possible data tampering - HMAC signature does not match data./');
+ $result = Session::read($key, array('name' => 'hmac'));
+ $_COOKIE = $cache;
+ }
+}
+
+?>
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/console/command/MockLibraryService.php b/libraries/lithium/tests/mocks/console/command/MockLibraryService.php
index 11b9c18..3da1b78 100644
--- a/libraries/lithium/tests/mocks/console/command/MockLibraryService.php
+++ b/libraries/lithium/tests/mocks/console/command/MockLibraryService.php
@@ -8,6 +8,7 @@
namespace lithium\tests\mocks\console\command;
+use lithium\core\Libraries;
use lithium\net\http\Response;
class MockLibraryService extends \lithium\net\http\Service {
@@ -58,6 +59,8 @@ class MockLibraryService extends \lithium\net\http\Service {
}
private function __data($type, $key = null) {
+ $resources = Libraries::get(true, 'resources');
+
$plugins = array(
array(
'name' => 'li3_lab', 'version' => '1.0',
@@ -89,7 +92,7 @@ class MockLibraryService extends \lithium\net\http\Service {
'created' => '2009-11-30', 'updated' => '2009-11-30',
'rating' => '9.9', 'downloads' => '1000',
'sources' => array(
- 'phar' => LITHIUM_APP_PATH . '/resources/tmp/tests/library_test_plugin.phar.gz'
+ 'phar' => "{$resources}/tmp/tests/library_test_plugin.phar.gz"
),
'requires' => array(
'li3_lab' => array('version' => '<=1.0')
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 1cc2bdd..2d96856 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(
@@ -130,10 +130,14 @@ class MockSource extends \lithium\data\Source {
}
<<<<<<< HEAD
+<<<<<<< HEAD
public function cast($model, array $data = array(), array $options = array()) {
=======
public function cast($entity, array $data = array(), array $options = array()) {
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ public function cast($entity, array $data = array(), array $options = array()) {
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$defaults = array('first' => false);
$options += $defaults;
return $options['first'] ? reset($data) : $data;
diff --git a/libraries/lithium/tests/mocks/data/model/MockDatabase.php b/libraries/lithium/tests/mocks/data/model/MockDatabase.php
index adefff9..3545c4b 100644
--- a/libraries/lithium/tests/mocks/data/model/MockDatabase.php
+++ b/libraries/lithium/tests/mocks/data/model/MockDatabase.php
@@ -42,10 +42,14 @@ class MockDatabase extends \lithium\data\source\Database {
}
<<<<<<< HEAD
+<<<<<<< HEAD
public function cast($model, array $data, array $options = array()) {
=======
public function cast($entity, array $data, array $options = array()) {
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ public function cast($entity, array $data, array $options = array()) {
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$defaults = array('first' => false);
$options += $defaults;
return $options['first'] ? reset($data) : $data;
diff --git a/libraries/lithium/tests/mocks/data/model/MockDocumentPost.php b/libraries/lithium/tests/mocks/data/model/MockDocumentPost.php
index 277e518..b3ed419 100644
--- a/libraries/lithium/tests/mocks/data/model/MockDocumentPost.php
+++ b/libraries/lithium/tests/mocks/data/model/MockDocumentPost.php
@@ -21,13 +21,19 @@ class MockDocumentPost extends \lithium\data\Model {
public static function schema($field = null) {
<<<<<<< HEAD
+<<<<<<< HEAD
return array('_id' => array('type' => 'id'));
=======
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
return array(
'_id' => array('type' => 'id'),
'foo.bar' => array('type' => 'int')
);
+<<<<<<< HEAD
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
public function ret($record, $param1 = null, $param2 = null) {
diff --git a/libraries/lithium/tests/mocks/data/model/MockDocumentSource.php b/libraries/lithium/tests/mocks/data/model/MockDocumentSource.php
index 5df0702..e8ec7fa 100644
--- a/libraries/lithium/tests/mocks/data/model/MockDocumentSource.php
+++ b/libraries/lithium/tests/mocks/data/model/MockDocumentSource.php
@@ -46,6 +46,7 @@ class MockDocumentSource extends \lithium\data\Source {
}
<<<<<<< HEAD
+<<<<<<< HEAD
public function cast($model, array $data, array $options = array()) {
$defaults = array('schema' => null, 'first' => false, 'pathKey' => null, 'arrays' => true);
$options += $defaults;
@@ -55,6 +56,8 @@ class MockDocumentSource extends \lithium\data\Source {
}
=======
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
public function cast($entity, array $data, array $options = array()) {
$defaults = array('schema' => null, 'first' => false, 'pathKey' => null, 'arrays' => true);
$options += $defaults;
@@ -73,13 +76,17 @@ class MockDocumentSource extends \lithium\data\Source {
$schema = $options['schema'];
unset($options['schema']);
+<<<<<<< HEAD
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$handlers = array(
'id' => function($v) {
return is_string($v) && preg_match('/^[0-9a-f]{24}$/', $v) ? new MongoId($v) : $v;
},
'date' => function($v) {
<<<<<<< HEAD
+<<<<<<< HEAD
return new MongoDate(is_numeric($v) ? intval($v) : strtotime($v));
},
'regex' => function($v) {
@@ -93,6 +100,8 @@ class MockDocumentSource extends \lithium\data\Source {
'datetime' => 'date',
'timestamp' => 'date',
=======
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$v = is_numeric($v) ? intval($v) : strtotime($v);
return (time() == $v) ? new MongoDate() : new MongoDate($v);
},
@@ -112,7 +121,10 @@ class MockDocumentSource extends \lithium\data\Source {
'datetime' => 'date',
'timestamp' => 'date',
'int' => 'integer'
+<<<<<<< HEAD
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
);
foreach ($data as $key => $value) {
@@ -120,11 +132,14 @@ class MockDocumentSource extends \lithium\data\Source {
continue;
}
<<<<<<< HEAD
+<<<<<<< HEAD
$schema = isset($options['schema'][$key]) ? $options['schema'][$key] : array();
$schema += array('type' => null, 'array' => null);
$type = isset($typeMap[$schema['type']]) ? $typeMap[$schema['type']] : $schema['type'];
$isArray = (is_array($value) && $schema['array'] !== false);
=======
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
$path = is_int($key) ? null : $key;
$path = $options['pathKey'] ? trim("{$options['pathKey']}.{$path}", '.') : $path;
$field = (isset($schema[$path]) ? $schema[$path] : array());
@@ -132,13 +147,17 @@ class MockDocumentSource extends \lithium\data\Source {
$type = isset($typeMap[$field['type']]) ? $typeMap[$field['type']] : $field['type'];
$isObject = ($type == 'object');
$isArray = (is_array($value) && $field['array'] !== false && !$isObject);
+<<<<<<< HEAD
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
if (isset($handlers[$type])) {
$handler = $handlers[$type];
$value = $isArray ? array_map($handler, $value) : $handler($value);
}
<<<<<<< HEAD
+<<<<<<< HEAD
if ($options['arrays']) {
if (is_array($value)) {
$arrayType = (array_keys($value) === range(0, count($value) - 1));
@@ -148,6 +167,8 @@ class MockDocumentSource extends \lithium\data\Source {
$value = $this->item($model, array($value), array('class' => 'array') + $options);
}
=======
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
if (!$options['arrays']) {
$data[$key] = $value;
continue;
@@ -161,7 +182,10 @@ class MockDocumentSource extends \lithium\data\Source {
} elseif ($field['array']) {
$opts = array('class' => 'array') + $options;
$value = $this->item($model, array($value), compact('pathKey') + $opts);
+<<<<<<< HEAD
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
$data[$key] = $value;
}
diff --git a/libraries/lithium/tests/mocks/data/source/MockMongoPost.php b/libraries/lithium/tests/mocks/data/source/MockMongoPost.php
index fd6413e..b2c1a86 100644
--- a/libraries/lithium/tests/mocks/data/source/MockMongoPost.php
+++ b/libraries/lithium/tests/mocks/data/source/MockMongoPost.php
@@ -18,12 +18,18 @@ class MockMongoPost extends \lithium\data\Model {
);
<<<<<<< HEAD
+<<<<<<< HEAD
+=======
=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
protected $_connection;
protected $_useRealConnection = true;
+<<<<<<< HEAD
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
public static function schema($field = null) {
if (is_array($field)) {
return static::_object()->_schema = $field;
@@ -31,7 +37,10 @@ class MockMongoPost extends \lithium\data\Model {
return parent::schema($field);
}
<<<<<<< HEAD
+<<<<<<< HEAD
+=======
=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
public static function &connection() {
$self = static::_object();
@@ -50,7 +59,10 @@ class MockMongoPost extends \lithium\data\Model {
$self->_connection = null;
$self->_useRealConnection = !$mock;
}
+<<<<<<< HEAD
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
?>
\ No newline at end of file
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..286b888 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(
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
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;
+ }
+
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
public function next() {
return $this->_next();
}
+<<<<<<< HEAD
+=======
+ public function __call($method, array $params) {
+ return $this;
+ }
+
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
protected function _close() {
}
protected function _next() {
+<<<<<<< HEAD
return next($this->_data) ?: null;
+=======
+ $result = current($this->_data) ?: null;
+ next($this->_data);
+ return $result;
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
}
diff --git a/libraries/lithium/tests/mocks/storage/session/strategy/MockCookieSession.php b/libraries/lithium/tests/mocks/storage/session/strategy/MockCookieSession.php
new file mode 100644
index 0000000..e19000d
--- /dev/null
+++ b/libraries/lithium/tests/mocks/storage/session/strategy/MockCookieSession.php
@@ -0,0 +1,43 @@
+<?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\storage\session\strategy;
+
+class MockCookieSession extends \lithium\core\Object {
+
+ protected static $_secret = 'foobar';
+
+ protected static $_data = array('one' => 'foo', 'two' => 'bar');
+
+ public static function read($key = null, array $options = array()) {
+ if (isset(static::$_data[$key])) {
+ return static::$_data[$key];
+ }
+ return static::$_data;
+ }
+
+ public static function write($key, $value = null, array $options = array()) {
+ static::$_data[$key] = $value;
+ return $value;
+ }
+
+ public static function reset() {
+ return static::$_data = array('one' => 'foo', 'two' => 'bar');
+ }
+
+ /**
+ * Method for returning data currently stored in this mock.
+ *
+ * @return array
+ */
+ public static function data() {
+ return static::$_data;
+ }
+}
+
+?>
\ No newline at end of file
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..57b8116 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);
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
}
foreach ($conditions as $condition) {
if ($condition === ':last') {
diff --git a/libraries/lithium/util/String.php b/libraries/lithium/util/String.php
index 4f0ed4e..0ec0ca6 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.
+ */
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
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 a5ecf2b..1f137bb 100644
--- a/libraries/lithium/util/Validator.php
+++ b/libraries/lithium/util/Validator.php
@@ -431,12 +431,16 @@ class Validator extends \lithium\core\StaticObject {
'format' => 'any',
<<<<<<< HEAD
<<<<<<< HEAD
+<<<<<<< HEAD
=======
'on' => null,
>>>>>>> 25a362f706960b2becbf88e91cffc1b1638b7890
=======
'on' => null,
>>>>>>> e7b4814f2d836aaca60e0b949a4ebcf5e1a3bdc9
+=======
+ 'on' => null,
+>>>>>>> 6192f606ef7502bd60e8f870d706a829e113bb20
);
$errors = array();
$events = (array) (isset($options['events']) ? $options['events'] : null);
@@ -553,7 +557,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'];