JoinElement.php 4.76 KB
Newer Older
Qiang Xue committed
1 2
<?php
/**
Qiang Xue committed
3
 * JoinElement class file.
Qiang Xue committed
4 5 6 7 8 9 10 11 12 13 14 15 16 17
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @link http://www.yiiframework.com/
 * @copyright Copyright &copy; 2008-2012 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 */

namespace yii\db\ar;

use yii\base\VectorIterator;
use yii\db\dao\Query;
use yii\db\Exception;


Qiang Xue committed
18
class JoinElement
Qiang Xue committed
19 20
{
	/**
Qiang Xue committed
21
	 * @var integer ID of this join element
Qiang Xue committed
22
	 */
Qiang Xue committed
23 24 25 26 27
	public $id;
	/**
	 * @var BaseActiveQuery
	 */
	public $query;
Qiang Xue committed
28
	/**
Qiang Xue committed
29
	 * @var JoinElement the parent element that this element needs to join with
Qiang Xue committed
30 31
	 */
	public $parent;
Qiang Xue committed
32
	public $container;
Qiang Xue committed
33
	/**
Qiang Xue committed
34
	 * @var JoinElement[] the child elements that need to join with this element
Qiang Xue committed
35 36
	 */
	public $children = array();
Qiang Xue committed
37
	/**
Qiang Xue committed
38
	 * @var JoinElement[] the child elements that have corresponding relations declared in the AR class of this element
Qiang Xue committed
39
	 */
Qiang Xue committed
40
	public $relations = array();
Qiang Xue committed
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
	/**
	 * @var array column aliases (alias => original name)
	 */
	public $columnAliases = array();
	/**
	 * @var array primary key column aliases (original name => alias)
	 */
	public $pkAlias = array();
	/**
	 * @var string|array the column(s) used for index the query results
	 */
	public $key;
	/**
	 * @var array query results for this element (PK value => AR instance or data array)
	 */
Qiang Xue committed
56 57
	public $records = array();
	public $related = array();
Qiang Xue committed
58

Qiang Xue committed
59
	/**
Qiang Xue committed
60
	 * @param integer $id
Qiang Xue committed
61
	 * @param ActiveRelation|ActiveQuery $query
Qiang Xue committed
62 63
	 * @param null|JoinElement $parent
	 * @param null|JoinElement $container
Qiang Xue committed
64 65
	 */
	public function __construct($id, $query, $parent, $container)
Qiang Xue committed
66
	{
Qiang Xue committed
67 68
		$this->id = $id;
		$this->query = $query;
Qiang Xue committed
69 70
		if ($parent !== null) {
			$this->parent = $parent;
Qiang Xue committed
71
			$this->container = $container;
Qiang Xue committed
72
			$parent->children[$query->name] = $this;
Qiang Xue committed
73 74 75
			if ($query->select !== false) {
				$container->relations[$query->name] = $this;
			}
Qiang Xue committed
76 77 78
		}
	}

Qiang Xue committed
79
	public function populateData($rows)
Qiang Xue committed
80
	{
Qiang Xue committed
81 82 83 84 85
		if ($this->container === null) {
			foreach ($rows as $row) {
				if (($key = $this->getKeyValue($row)) !== null && !isset($this->records[$key])) {
					$this->records[$key] = $this->createRecord($row);
				}
Qiang Xue committed
86 87
			}
		} else {
Qiang Xue committed
88 89 90 91 92
			foreach ($rows as $row) {
				$key = $this->getKeyValue($row);
				$containerKey = $this->container->getKeyValue($row);
				if ($key === null || $containerKey === null || isset($this->related[$containerKey][$key])) {
					continue;
Qiang Xue committed
93
				}
Qiang Xue committed
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
				$this->related[$containerKey][$key] = true;
				if ($this->query->asArray) {
					if (isset($this->records[$key])) {
						if ($this->query->hasMany) {
							if ($this->query->index !== null) {
								$this->container->records[$containerKey][$this->query->name][$key] =& $this->records[$key];
							} else {
								$this->container->records[$containerKey][$this->query->name][] =& $this->records[$key];
							}
						} else {
							$this->container->records[$containerKey][$this->query->name] =& $this->records[$key];
						}
					} else {
						$record = $this->createRecord($row);
						if ($this->query->hasMany) {
							if ($this->query->index !== null) {
								$this->container->records[$containerKey][$this->query->name][$key] = $record;
								$this->records[$key] =& $this->container->records[$containerKey][$this->query->name][$key];
							} else {
								$count = count($this->container->records[$containerKey][$this->query->name]);
								$this->container->records[$containerKey][$this->query->name][] = $record;
								$this->records[$key] =& $this->container->records[$containerKey][$this->query->name][$count];
							}
						} else {
							$this->container->records[$containerKey][$this->query->name] = $record;
							$this->records[$key] =& $this->container->records[$containerKey][$this->query->name];
						}
					}
				} else {
					if (isset($this->records[$key])) {
						$record = $this->records[$key];
					} else {
						$this->records[$key] = $record = $this->createRecord($row);
					}
					$this->container->records[$containerKey]->addRelatedRecord($this->query, $record);
Qiang Xue committed
129 130 131 132
				}
			}
		}

Qiang Xue committed
133
		foreach ($this->relations as $child) {
Qiang Xue committed
134 135 136 137 138 139 140 141 142 143 144
			$child->populateData($rows);
		}
	}

	protected function getKeyValue($row)
	{
		if (is_array($this->key)) {
			$key = array();
			foreach ($this->key as $alias) {
				if (!isset($row[$alias])) {
					return null;
Qiang Xue committed
145
				}
Qiang Xue committed
146
				$key[] = $row[$alias];
Qiang Xue committed
147
			}
Qiang Xue committed
148 149 150
			return serialize($key);
		} else {
			return $row[$this->key];
Qiang Xue committed
151
		}
Qiang Xue committed
152
	}
Qiang Xue committed
153

Qiang Xue committed
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
	protected function createRecord($row)
	{
		$record = array();
		foreach ($this->columnAliases as $alias => $name) {
			$record[$name] = $row[$alias];
		}
		if ($this->query->asArray) {
			foreach ($this->relations as $child) {
				$record[$child->query->name] = $child->query->hasMany ? array() : null;
			}
		} else {
			$modelClass = $this->query->modelClass;
			$record = $modelClass::create($record);
			foreach ($this->relations as $child) {
				$record->{$child->query->name} = $child->query->hasMany ? array() : null;
			}
		}
Qiang Xue committed
171 172 173
		return $record;
	}
}