Subversion-Projekte lars-tiefland.prado

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/**
3
 * TActiveRecordRelationContext class.
4
 *
5
 * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
6
 * @link http://www.pradosoft.com/
7
 * @copyright Copyright &copy; 2005-2008 PradoSoft
8
 * @license http://www.pradosoft.com/license/
9
 * @version $Id$
10
 * @package System.Data.ActiveRecord.Relations
11
 */
12
 
13
/**
14
 * TActiveRecordRelationContext holds information regarding record relationships
15
 * such as record relation property name, query criteria and foreign object record
16
 * class names.
17
 *
18
 * This class is use internally by passing a context to the TActiveRecordRelation
19
 * constructor.
20
 *
21
 * @author Wei Zhuo <weizho[at]gmail[dot]com>
22
 * @version $Id$
23
 * @package System.Data.ActiveRecord.Relations
24
 * @since 3.1
25
 */
26
class TActiveRecordRelationContext
27
{
28
	private $_property;
29
	private $_record;
30
	private $_relation; //data from an entry of TActiveRecord::$RELATION
31
	private $_fkeys;
32
 
33
	public function __construct($record, $property=null, $relation=null)
34
	{
35
		$this->_record=$record;
36
		$this->_property=$property;
37
		$this->_relation=$relation;
38
	}
39
 
40
	/**
41
	 * @return boolean true if the relation is defined in TActiveRecord::$RELATIONS
42
	 * @since 3.1.2
43
	 */
44
	public function hasRecordRelation()
45
	{
46
		return $this->_relation!==null;
47
	}
48
 
49
	public function getPropertyValue()
50
	{
51
		$obj = $this->getSourceRecord();
52
		return $obj->getColumnValue($this->getProperty());
53
	}
54
 
55
	/**
56
	 * @return string name of the record property that the relationship results will be assigned to.
57
	 */
58
	public function getProperty()
59
	{
60
		return $this->_property;
61
	}
62
 
63
	/**
64
	 * @return TActiveRecord the active record instance that queried for its related records.
65
	 */
66
	public function getSourceRecord()
67
	{
68
		return $this->_record;
69
	}
70
 
71
	/**
72
	 * @return array foreign key of this relations, the keys is dependent on the
73
	 * relationship type.
74
	 * @since 3.1.2
75
	 */
76
	public function getRelationForeignKeys()
77
	{
78
		if($this->_fkeys===null)
79
			$this->_fkeys=$this->getRelationHandler()->getRelationForeignKeys();
80
		return $this->_fkeys;
81
	}
82
 
83
	/**
84
	 * @return string HAS_MANY, HAS_ONE, or BELONGS_TO
85
	 */
86
	public function getRelationType()
87
	{
88
		return $this->_relation[0];
89
	}
90
 
91
	/**
92
	 * @return string foreign record class name.
93
	 */
94
	public function getForeignRecordClass()
95
	{
96
		return $this->_relation[1];
97
	}
98
 
99
	/**
100
	 * @return string foreign key field names, comma delimited.
101
	 * @since 3.1.2
102
	 */
103
	public function getFkField()
104
	{
105
		return $this->_relation[2];
106
	}
107
 
108
	/**
109
	 * @return string the query condition for the relation as specified in RELATIONS
110
	 * @since 3.1.2
111
	 */
112
	public function getCondition()
113
	{
114
		return isset($this->_relation[3])?$this->_relation[3]:null;
115
	}
116
 
117
	/**
118
	 * @return array the query parameters for the relation as specified in RELATIONS
119
	 * @since 3.1.2
120
	 */
121
	public function getParameters()
122
	{
123
		return isset($this->_relation[4])?$this->_relation[4]:array();
124
	}
125
 
126
	/**
127
	 * @return boolean true if the 3rd element of an TActiveRecord::$RELATION entry is set.
128
	 * @since 3.1.2
129
	 */
130
	public function hasFkField()
131
	{
132
		$notManyToMany = $this->getRelationType() !== TActiveRecord::MANY_TO_MANY;
133
		return $notManyToMany && isset($this->_relation[2]) && !empty($this->_relation[2]);
134
	}
135
 
136
	/**
137
	 * @return string the M-N relationship association table name.
138
	 */
139
	public function getAssociationTable()
140
	{
141
		return $this->_relation[2];
142
	}
143
 
144
	/**
145
	 * @return boolean true if the relationship is HAS_MANY and requires an association table.
146
	 */
147
	public function hasAssociationTable()
148
	{
149
		$isManyToMany = $this->getRelationType() === TActiveRecord::MANY_TO_MANY;
150
		return $isManyToMany && isset($this->_relation[2]) && !empty($this->_relation[2]);
151
	}
152
 
153
	/**
154
	 * @return TActiveRecord corresponding relationship foreign object finder instance.
155
	 */
156
	public function getForeignRecordFinder()
157
	{
158
		return TActiveRecord::finder($this->getForeignRecordClass());
159
	}
160
 
161
	/**
162
	 * Creates and return the TActiveRecordRelation handler for specific relationships.
163
	 * An instance of TActiveRecordHasOne, TActiveRecordBelongsTo, TActiveRecordHasMany,
164
	 * or TActiveRecordHasManyAssocation will be returned.
165
	 * @param TActiveRecordCriteria search criteria
166
	 * @return TActiveRecordRelation record relationship handler instnace.
167
	 * @throws TActiveRecordException if property is not defined or missing.
168
	 */
169
	public function getRelationHandler($criteria=null)
170
	{
171
		if(!$this->hasRecordRelation())
172
		{
173
			throw new TActiveRecordException('ar_undefined_relation_prop',
174
				$this->_property, get_class($this->_record), 'RELATIONS');
175
		}
176
		if($criteria===null)
177
			$criteria = new TActiveRecordCriteria($this->getCondition(), $this->getParameters());
178
		switch($this->getRelationType())
179
		{
180
			case TActiveRecord::HAS_MANY:
181
				Prado::using('System.Data.ActiveRecord.Relations.TActiveRecordHasMany');
182
				return new TActiveRecordHasMany($this, $criteria);
183
			case TActiveRecord::MANY_TO_MANY:
184
				Prado::using('System.Data.ActiveRecord.Relations.TActiveRecordHasManyAssociation');
185
				return new TActiveRecordHasManyAssociation($this, $criteria);
186
			case TActiveRecord::HAS_ONE:
187
				Prado::using('System.Data.ActiveRecord.Relations.TActiveRecordHasOne');
188
				return new TActiveRecordHasOne($this, $criteria);
189
			case TActiveRecord::BELONGS_TO:
190
				Prado::using('System.Data.ActiveRecord.Relations.TActiveRecordBelongsTo');
191
				return new TActiveRecordBelongsTo($this, $criteria);
192
			default:
193
				throw new TActiveRecordException('ar_invalid_relationship');
194
		}
195
	}
196
 
197
	/**
198
	 * @return TActiveRecordRelationCommand
199
	 */
200
	public function updateAssociatedRecords($updateBelongsTo=false)
201
	{
202
		$success=true;
203
		foreach($this->_record->getRecordRelations() as $data)
204
		{
205
			list($property, $relation) = $data;
206
			$belongsTo = $relation[0]==TActiveRecord::BELONGS_TO;
207
			if(($updateBelongsTo && $belongsTo) || (!$updateBelongsTo && !$belongsTo))
208
			{
209
				$obj = $this->getSourceRecord();
210
				if(!$this->isEmptyFkObject($obj->getColumnValue($property)))
211
				{
212
					$context = new TActiveRecordRelationContext($this->getSourceRecord(),$property,$relation);
213
					$success = $context->getRelationHandler()->updateAssociatedRecords() && $success;
214
				}
215
			}
216
		}
217
		return $success;
218
	}
219
 
220
	protected function isEmptyFkObject($obj)
221
	{
222
		if(is_object($obj))
223
			return $obj instanceof TList ? $obj->count() === 0 : false;
224
		else if(is_array($obj))
225
			return count($obj)===0;
226
		else
227
			return empty($obj);
228
	}
229
}
230