1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35:
36:
37: 38: 39: 40: 41: 42: 43: 44: 45: 46:
47: class Relationships extends X2ActiveRecord {
48:
49: 50: 51: 52:
53: public static function model($className=__CLASS__) {
54: return parent::model($className);
55: }
56:
57: 58: 59: 60:
61: public static function getRelationshipTypeOptions () {
62: $options = X2Model::getModelTypesWhichSupportRelationships (true);
63: foreach ($options as $model => $title) {
64: $accessLevel = $model::model ()->getAccessLevel ();
65: if ($accessLevel === X2PermissionsBehavior::QUERY_NONE) {
66: unset ($options[$model]);
67: }
68: }
69: return $options;
70: }
71:
72: 73: 74:
75: public function tableName() {
76: return 'x2_relationships';
77: }
78:
79: 80: 81:
82: public function rules() {
83:
84:
85: return array(
86: array('firstId, secondId', 'numerical', 'integerOnly'=>true),
87: array('firstType, secondType, firstLabel, secondLabel', 'length', 'max'=>100),
88: array('firstType, secondType', 'linkables','on'=>'api'),
89: array('firstType, firstId, secondType, secondId','required','on'=>'api'),
90: array('firstType, secondType','validateType'),
91: array('firstId, secondId','validateModel'),
92:
93:
94: array(
95: 'firstType, firstId, firstLabel, secondType, secondId, secondLabel',
96: 'safe', 'on'=>'search,api'),
97: );
98: }
99:
100: 101: 102:
103: public function validateType ($attr) {
104: $value = $this->$attr;
105: $validTypes = X2Model::getModelTypesWhichSupportRelationships (true);
106: if (!class_exists ($value) || !isset ($validTypes[$value])) {
107: $this->addError ($attr, Yii::t('app', 'Invalid record type') );
108: }
109: }
110:
111: 112: 113:
114: public function validateModel ($attr) {
115: $value = $this->$attr;
116: $position = preg_replace ('/Id$/', '', $attr);
117: $type = $this->{$position.'Type'};
118: if (!$type::model ()->findByPk ($value)) {
119: $this->addError ($attr, Yii::t('app', 'Record could not be found'));
120: }
121: }
122:
123: 124: 125:
126: public function hasDuplicates () {
127: return ((int) Yii::app()->db->createCommand ()
128: ->select ('count(*)')
129: ->from ('x2_relationships')
130: ->where ('
131: firstType=:firstType0 AND firstId=:firstId0 AND secondType=:secondType0 AND
132: secondId=:secondId0',
133: array (
134: ':firstType0' => $this->firstType,
135: ':firstId0' => $this->firstId,
136: ':secondType0' => $this->secondType,
137: ':secondId0' => $this->secondId,
138: ))
139: ->orWhere ('
140: firstType=:firstType1 AND firstId=:firstId1 AND secondType=:secondType1 AND
141: secondId=:secondId1',
142: array (
143: ':firstType1' => $this->secondType,
144: ':firstId1' => $this->secondId,
145: ':secondType1' => $this->firstType,
146: ':secondId1' => $this->firstId,
147: ))
148: ->queryScalar ()) > 0;
149: }
150:
151: 152: 153:
154: public function beforeValidate () {
155: $valid = parent::beforeValidate ();
156: if ($valid) {
157: if ($this->hasDuplicates ()) {
158: $this->addError ('secondType', Yii::t('app', 'Relationship already exists'));
159: $this->addErrors (
160: array_map (
161: function () { return null; },
162: array_flip (array ('firstType', 'firstId', 'secondId'))));
163: $valid = false;
164: }
165: }
166: return $valid;
167: }
168:
169: 170: 171:
172: public function relations() {
173:
174:
175: return array(
176: );
177: }
178:
179: 180: 181:
182: public function attributeLabels() {
183: return array(
184: 'id' => 'ID',
185: 'firstType' => 'First Type',
186: 'firstId' => 'First',
187: 'firstLabel' => 'First Label',
188: 'secondType' => 'Second Type',
189: 'secondId' => 'Second',
190: 'secondLabel' => 'Second Label',
191: );
192: }
193:
194: 195: 196: 197: 198: 199:
200: public function getLabel ($myType, $myId) {
201: if ($this->firstType === $myType && $this->firstId == $myId) {
202: return $this->secondLabel;
203: } elseif ($this->secondType === $myType && $this->secondId == $myId) {
204: return $this->firstLabel;
205: }
206: throw new CException ('myType and myId don\'t match either related model');
207: }
208:
209: public function setFirstModel (X2Model $model) {
210: $this->firstType = get_class ($model);
211: $this->firstId = $model->id;
212: }
213:
214: public function setSecondModel (X2Model $model) {
215: $this->secondType = get_class ($model);
216: $this->secondId = $model->id;
217: }
218:
219: 220: 221: 222: 223: 224:
225: private $_otherModel = array ();
226: public function getOtherModel ($myType, $myId) {
227: if (!isset ($this->_otherModel[$myType.$myId])) {
228: if ($this->firstType === $myType && $this->firstId == $myId) {
229: $model = X2Model::model ($this->secondType)->findByPk ($this->secondId);
230: } elseif ($this->secondType === $myType && $this->secondId == $myId) {
231: $model = X2Model::model ($this->firstType)->findByPk ($this->firstId);
232: } else {
233: throw new CException ('myType and myId don\'t match either related model');
234: }
235: $this->_otherModel[$myType.$myId] = $model;
236: }
237: return $this->_otherModel[$myType.$myId];
238: }
239:
240: 241: 242: 243: 244:
245: public function search() {
246:
247:
248:
249: $criteria=new CDbCriteria;
250:
251: $criteria->compare('id',$this->id);
252: $criteria->compare('firstType',$this->firstType,true);
253: $criteria->compare('firstId',$this->firstId);
254: $criteria->compare('firstLabel',$this->firstLabel);
255: $criteria->compare('secondType',$this->secondType,true);
256: $criteria->compare('secondId',$this->secondId);
257: $criteria->compare('secondLabel',$this->secondLabel);
258:
259: return new CActiveDataProvider(get_class($this), array(
260: 'criteria'=>$criteria,
261: ));
262: }
263:
264: public function linkables($attribute, $params) {
265: if(!class_exists($this->$attribute))
266: $this->addError(
267: $attribute,
268: Yii::t('app','Class "{class}" specified for {attribute} does not exist, so cannot create relationships with it.',array('{class}'=>$this->$attribute)));
269:
270:
271: $staticModel = CActiveRecord::model($this->$attribute);
272: $has = false;
273: foreach($staticModel->behaviors() as $name=>$config){
274: if($config['class'] == 'X2LinkableBehavior'){
275: $has = true;
276: break;
277: }
278: }
279: if(!$has)
280: $this->addError(
281: $attribute,
282: Yii::t('app','Class "{class}" specified for {attribute} does not have X2LinkableBehavior, and thus cannot be used with relationships.',array('{class}'=>$this->$attribute)));
283:
284: $model = $staticModel->findByPk($attribute=='firstType' ? $this->firstId : $this->secondId);
285: if(!$model)
286: $this->addError($attribute,Yii::t('app','Model record not found for {attribute}.'));
287: }
288:
289: }
290: