Permalink
Browse files

Merge remote-tracking branch 'upstream/dev' into dev

  • Loading branch information...
coogle committed Dec 26, 2012
2 parents f4586af + dda0ddf commit aafe115b132d5d8ead33bbe8ab5c13d64b8aa34c
View
@@ -1,38 +0,0 @@
-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](http://lithify.me/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](https://github.com/mariano/li3_doctrine2/) 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.
-
-Build status
------------
-[![Build Status](https://secure.travis-ci.org/UnionOfRAD/lithium.png?branch=master)](http://travis-ci.org/UnionOfRAD/lithium)
View
@@ -98,7 +98,7 @@ class Query extends \lithium\core\Object {
protected $_alias = array();
/**
- * Map the generated aliases to their corresponding relation path
+ * Map beetween generated aliases and corresponding relation paths
*
* @see lithium\data\model\Query::alias()
*
@@ -107,7 +107,16 @@ class Query extends \lithium\core\Object {
protected $_paths = array();
/**
- * Map the generated aliases to their corresponding model
+ * Map beetween relation paths and their corresponding fieldname paths
+ *
+ * @see lithium\data\model\Query::alias()
+ *
+ * @var array
+ */
+ protected $_relationNames = array();
+
+ /**
+ * Map beetween generated aliases and corresponding models.
*
* @see lithium\data\model\Query::alias()
*
@@ -720,23 +729,40 @@ public function alias($alias = true, $relpath = null) {
}
$this->_paths[$alias] = $relpath;
+ $fieldname = array();
foreach ($paths as $path) {
if (!$relation = $model::relations($path)) {
$model = null;
break;
}
+ $fieldname[] = $relation->fieldName();
$model = $relation->to();
}
$this->_models[$alias] = $model;
+ $this->_relationNames[$relpath] = join('.', $fieldname);
return $alias;
}
+ /**
+ * Return the relation paths mapped to their corredponding fieldname paths.
+ *
+ * @param object $source Instance of the data source (`lithium\data\Source`) to use for
+ * conversion.
+ * @return array Map between relation paths and their corresponding fieldname paths.
+ */
+ public function relationNames(Source $source = null) {
+ if ($source) {
+ $this->applyStrategy($source);
+ }
+ return $this->_relationNames;
+ }
+
/**
* Return the generated aliases mapped to their relation path
*
* @param object $source Instance of the data source (`lithium\data\Source`) to use for
* conversion.
- * @return array Map between alias and their corresponding dotted relation
+ * @return array Map between aliases and their corresponding dotted relation paths.
*/
public function paths(Source $source = null) {
if ($source) {
@@ -750,7 +776,7 @@ public function paths(Source $source = null) {
*
* @param object $source Instance of the data source (`lithium\data\Source`) to use for
* conversion.
- * @return array Map between alias and their corresponding model
+ * @return array Map between aliases and their corresponding fully-namespaced model names.
*/
public function models(Source $source = null) {
if ($source) {
View
@@ -182,7 +182,7 @@ public function __construct(array $config = array()) {
$with = $context->with();
- $strategy = function($me, $model, $tree, $path, $from, $needPks) use ($self, $context, $with) {
+ $strategy = function($me, $model, $tree, $path, $from, &$deps) use ($self, $context, $with) {
foreach ($tree as $name => $childs) {
if (!$rel = $model::relations($name)) {
throw new QueryException("Model relationship `{$name}` not found.");
@@ -205,9 +205,8 @@ public function __construct(array $config = array()) {
}
$to = $context->alias($alias, $relPath);
- if ($needPks) {
- $context->fields(array($to => (array) $model::meta('key')));
- }
+ $deps[$to] = $deps[$from];
+ $deps[$to][] = $from;
if ($context->relationships($relPath) === null) {
$context->relationships($relPath, array(
@@ -221,19 +220,27 @@ public function __construct(array $config = array()) {
}
if (!empty($childs)) {
- $me($me, $rel->to(), $childs, $relPath, $to, $needPks);
+ $me($me, $rel->to(), $childs, $relPath, $to, $deps);
}
}
};
$tree = Set::expand(Set::normalize(array_keys($with)));
$alias = $context->alias();
- $needPks = false;
- if ($context->fields()) {
- $needPks = true;
- $context->fields(array($alias => (array) $model::meta('key')));
+ $deps = array($alias => array());
+ $strategy($strategy, $model, $tree, '', $alias, $deps);
+
+ $models = $context->models();
+ foreach ($context->fields() as $field) {
+ list($alias, $field) = $self->invokeMethod('_splitFieldname', array($field));
+ $alias = $alias ?: $field;
+ if ($alias && isset($models[$alias])) {
+ foreach ($deps[$alias] as $depAlias) {
+ $depModel = $models[$depAlias];
+ $context->fields(array($depAlias => (array) $depModel::meta('key')));
+ }
+ }
}
- $strategy($strategy, $model, $tree, '', $context->alias(), $needPks);
},
'nested' => function($self, $model, $context) {
throw new QueryException("This strategy is not yet implemented.");
@@ -322,7 +329,7 @@ public function name($name) {
*/
protected function _splitFieldname($field) {
if (is_string($field)) {
- if (preg_match('/^[a-z0-9_-]+\.[a-z0-9_-]+$/i', $field)) {
+ if (preg_match('/^[a-z0-9_-]+\.([a-z0-9_-]+|\*)$/i', $field)) {
return explode('.', $field, 2);
}
}
@@ -465,18 +472,30 @@ public function read($query, array $options = array()) {
return $result;
case 'array':
$columns = $args['schema'] ?: $self->schema($query, $result);
- $records = array();
- if (is_array(reset($columns))) {
- $columns = reset($columns);
+
+ if (!isset($columns['']) || !is_array($columns[''])) {
+ $columns = array('' => $columns);
}
- while ($data = $result->next()) {
- // @hack: Fix this to support relationships
- if (count($columns) != count($data) && is_array(current($columns))) {
- $columns = current($columns);
+
+ $relationNames = is_object($query) ? $query->relationNames($self) : array();
+ $i = 0;
+ $records = array();
+ foreach ($result as $data) {
+ $offset = 0;
+ $records[$i] = array();
+ foreach ($columns as $path => $cols) {
+ $len = count($cols);
+ $values = array_combine($cols, array_slice($data, $offset, $len));
+ if ($path) {
+ $records[$i][$relationNames[$path]] = $values;
+ } else {
+ $records[$i] += $values;
+ }
+ $offset += $len;
}
- $records[] = array_combine($columns, $data);
+ $i++;
}
- return $records;
+ return Set::expand($records);
case 'item':
return $self->item($query->model(), array(), compact('query', 'result') + array(
'class' => 'set'
@@ -697,6 +716,7 @@ public function _schema($query, $fields = null) {
$model = $query->model();
$paths = $query->paths($this);
$models = $query->models($this);
+ $alias = $query->alias();
$result = array();
if (!$model) {
@@ -730,6 +750,8 @@ public function _schema($query, $fields = null) {
unset($fields[0]);
}
+ $fields = isset($fields[$alias]) ? array($alias => $fields[$alias]) + $fields : $fields;
+
foreach ($fields as $field => $value) {
if (is_array($value)) {
if (isset($value['*'])) {
@@ -901,6 +923,7 @@ public function _processConditions($key, $value, $context, $schema = null, $glue
public function fields($fields, $context) {
$type = $context->type();
$schema = $context->schema()->fields();
+ $alias = $context->alias();
if (!is_array($fields)) {
return $this->_fieldsReturn($type, $context, $fields, $schema);
@@ -918,6 +941,8 @@ public function fields($fields, $context) {
unset($fields[0]);
}
+ $fields = isset($fields[$alias]) ? array($alias => $fields[$alias]) + $fields : $fields;
+
foreach ($fields as $field => $value) {
if (is_array($value)) {
if (isset($value['*'])) {
@@ -965,6 +990,7 @@ protected function _fields($fields, $context) {
}
return $list;
}
+
protected function _fieldsQuote($alias, $field) {
$open = $this->_quotes[0];
$close = $this->_quotes[1];
Oops, something went wrong.

0 comments on commit aafe115

Please sign in to comment.