1
|
|
|
<?php |
2
|
|
|
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); |
3
|
|
|
/********************************************************************************* |
4
|
|
|
* SugarCRM Community Edition is a customer relationship management program developed by |
5
|
|
|
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc. |
6
|
|
|
|
7
|
|
|
* SuiteCRM is an extension to SugarCRM Community Edition developed by Salesagility Ltd. |
8
|
|
|
* Copyright (C) 2011 - 2014 Salesagility Ltd. |
9
|
|
|
* |
10
|
|
|
* This program is free software; you can redistribute it and/or modify it under |
11
|
|
|
* the terms of the GNU Affero General Public License version 3 as published by the |
12
|
|
|
* Free Software Foundation with the addition of the following permission added |
13
|
|
|
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK |
14
|
|
|
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY |
15
|
|
|
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. |
16
|
|
|
* |
17
|
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT |
18
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
19
|
|
|
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more |
20
|
|
|
* details. |
21
|
|
|
* |
22
|
|
|
* You should have received a copy of the GNU Affero General Public License along with |
23
|
|
|
* this program; if not, see http://www.gnu.org/licenses or write to the Free |
24
|
|
|
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
25
|
|
|
* 02110-1301 USA. |
26
|
|
|
* |
27
|
|
|
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road, |
28
|
|
|
* SW2-130, Cupertino, CA 95014, USA. or at email address [email protected]. |
29
|
|
|
* |
30
|
|
|
* The interactive user interfaces in modified source and object code versions |
31
|
|
|
* of this program must display Appropriate Legal Notices, as required under |
32
|
|
|
* Section 5 of the GNU Affero General Public License version 3. |
33
|
|
|
* |
34
|
|
|
* In accordance with Section 7(b) of the GNU Affero General Public License version 3, |
35
|
|
|
* these Appropriate Legal Notices must retain the display of the "Powered by |
36
|
|
|
* SugarCRM" logo and "Supercharged by SuiteCRM" logo. If the display of the logos is not |
37
|
|
|
* reasonably feasible for technical reasons, the Appropriate Legal Notices must |
38
|
|
|
* display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM". |
39
|
|
|
********************************************************************************/ |
40
|
|
|
|
41
|
|
|
/********************************************************************************* |
42
|
|
|
|
43
|
|
|
* Description: Defines the base class for new data type, Relationship, methods in the class will |
44
|
|
|
* be used to manipulate relationship between object instances. |
45
|
|
|
* Portions created by SugarCRM are Copyright (C) SugarCRM, Inc. |
46
|
|
|
* All Rights Reserved. |
47
|
|
|
* Contributor(s): ______________________________________.. |
48
|
|
|
********************************************************************************/ |
49
|
|
|
|
50
|
|
|
|
51
|
|
|
class Link { |
52
|
|
|
|
53
|
|
|
/* Private variables.*/ |
54
|
|
|
var $_log; |
55
|
|
|
var $_relationship_name; //relationship this attribute is tied to. |
56
|
|
|
var $_bean; //stores a copy of the bean. |
57
|
|
|
var $_relationship= ''; |
58
|
|
|
var $_bean_table_name; |
59
|
|
|
var $_bean_key_name='id'; |
60
|
|
|
private $relationship_fields = array(); |
61
|
|
|
var $_db; |
62
|
|
|
var $_swap_sides = false; |
63
|
|
|
var $_rhs_key_override = false; |
64
|
|
|
var $_bean_filter_field = ''; |
65
|
|
|
|
66
|
|
|
//if set to true role column will not be added to the filter criteria. |
67
|
|
|
var $ignore_role_filter=false; |
68
|
|
|
//if set to true distinct clause will be added to the select list. |
69
|
|
|
var $add_distinct=false; |
70
|
|
|
//value of this variable dictates the action to be taken when a duplicate relationship record is found. |
71
|
|
|
//1-ignore,2-update,3-delete. |
72
|
|
|
//var $when_dup_relationship_found=2; // deprecated - only used by Queues, which is also no longer used |
73
|
|
|
|
74
|
|
|
// a value for duplicate variable is stored by the _relatinship_exists method. |
75
|
|
|
var $_duplicate_key; |
76
|
|
|
var $_duplicate_where; |
77
|
|
|
|
78
|
|
|
/* Parameters: |
79
|
|
|
* $_rel_name: use this relationship key. |
80
|
|
|
* $_bean: reference of the bean that instantiated this class. |
81
|
|
|
* $_fieldDef: vardef entry for the field. |
82
|
|
|
* $_table_name: optional, fetch from the bean's table name property. |
83
|
|
|
* $_key_name: optional, name of the primary key column for _table_name |
84
|
|
|
*/ |
85
|
|
|
function Link($_rel_name, &$_bean, $fieldDef, $_table_name='', $_key_name=''){ |
86
|
|
|
global $dictionary; |
87
|
|
|
require_once("modules/TableDictionary.php"); |
88
|
|
|
$GLOBALS['log']->debug("Link Constructor, relationship name: ".$_rel_name); |
89
|
|
|
$GLOBALS['log']->debug("Link Constructor, Table name: ".$_table_name); |
90
|
|
|
$GLOBALS['log']->debug("Link Constructor, Key name: ".$_key_name); |
91
|
|
|
|
92
|
|
|
$this->_relationship_name=$_rel_name; |
93
|
|
|
$this->relationship_fields = (!empty($fieldDef['rel_fields']))?$fieldDef['rel_fields']: array(); |
94
|
|
|
$this->_bean=&$_bean; |
95
|
|
|
$this->_relationship=new Relationship(); |
96
|
|
|
//$this->_relationship->retrieve_by_string_fields(array('relationship_name'=>$this->_relationship_name)); |
97
|
|
|
$this->_relationship->retrieve_by_name($this->_relationship_name); |
98
|
|
|
|
99
|
|
|
$this->_db = DBManagerFactory::getInstance(); |
100
|
|
|
|
101
|
|
|
|
102
|
|
|
//Following behavior is tied to a property(ignore_role) value in the vardef. It alters the values of 2 properties, ignore_role_filter and add_distinct. |
103
|
|
|
//the property values can be altered again before any requests are made. |
104
|
|
|
if (!empty($fieldDef) && is_array($fieldDef)) { |
105
|
|
|
if (array_key_exists('ignore_role', $fieldDef)) { |
106
|
|
|
if ($fieldDef['ignore_role'] == true) { |
107
|
|
|
$this->ignore_role_filter=true; |
108
|
|
|
$this->add_distinct=true; |
109
|
|
|
} |
110
|
|
|
} |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
$this->_bean_table_name=(!empty($_table_name)) ? $_table_name : $_bean->table_name; |
114
|
|
|
if (!empty($key_name)) { |
|
|
|
|
115
|
|
|
$this->_bean_key_name=$_key_name; |
116
|
|
|
} else { |
117
|
|
|
|
118
|
|
|
if ($this->_relationship->lhs_table != $this->_relationship->rhs_table) { |
119
|
|
|
|
120
|
|
|
if ($_bean->table_name == $this->_relationship->lhs_table) |
121
|
|
|
$this->_bean_key_name=$this->_relationship->lhs_key; |
122
|
|
|
|
123
|
|
|
if ($_bean->table_name == $this->_relationship->rhs_table) |
124
|
|
|
$this->_bean_key_name=$this->_relationship->rhs_key; |
125
|
|
|
|
126
|
|
|
} |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
if ($this->_relationship->lhs_table == $this->_relationship->rhs_table && isset($fieldDef['side']) && $fieldDef['side'] == 'right'){ |
130
|
|
|
$this->_swap_sides = true; |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
if (!empty($fieldDef['rhs_key_override'])) { |
134
|
|
|
$this->_rhs_key_override = true; |
135
|
|
|
} |
136
|
|
|
if (!empty($fieldDef['bean_filter_field'])) { |
137
|
|
|
$this->_bean_filter_field = $fieldDef['bean_filter_field']; |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
//default to id if not set. |
141
|
|
|
if (empty($this->_bean_key_name))$this->_bean_key_name='id'; |
142
|
|
|
|
143
|
|
|
$GLOBALS['log']->debug("Link Constructor, _bean_table_name: ".$this->_bean_table_name); |
144
|
|
|
$GLOBALS['log']->debug("Link Constructor, _bean_key_name: ".$this->_bean_key_name); |
145
|
|
|
if (!empty($this->_relationship->id)) $GLOBALS['log']->debug("Link Constructor, relationship record found."); |
146
|
|
|
else $GLOBALS['log']->debug("Link Constructor, No relationship record.") ; |
147
|
|
|
|
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
function loadedSuccesfully() { |
151
|
|
|
return !empty($this->_relationship->id); |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
/* This method will return the following based on cardinality of the relationship. |
155
|
|
|
* # one-to-many, many-to-many: empty array if not data is found else array of keys. |
156
|
|
|
* # if many-to-many and $role set to true : empty array if not data is found else |
157
|
|
|
* array of array which contain id+other fields. |
158
|
|
|
* # many-to-one, one-to-one: null if no linked data is found, else key value. |
159
|
|
|
* |
160
|
|
|
* For a self referencing relationship the function will behave as if the user is trying |
161
|
|
|
* to access the child records. To get to the parent records use the getParent() method. |
162
|
|
|
*/ |
163
|
|
|
function get($role = false) { |
164
|
|
|
if($role){ |
165
|
|
|
$role_field = $this->_get_link_table_role_field($this->_relationship_name); |
166
|
|
|
if($role_field !== false){ |
167
|
|
|
$query = $this->getQuery(false, array(),0, "", false, "", $role_field); |
168
|
|
|
}else{ |
169
|
|
|
return array(); |
170
|
|
|
} |
171
|
|
|
}else{ |
172
|
|
|
$query = $this->getQuery(); |
173
|
|
|
} |
174
|
|
|
$result = $this->_db->query($query, true); |
175
|
|
|
$list = Array(); |
176
|
|
|
while($row = $this->_db->fetchByAssoc($result)) |
177
|
|
|
{ |
178
|
|
|
if($role){ |
179
|
|
|
$list[] = $row; |
180
|
|
|
}else{ |
181
|
|
|
$list[] = $row['id']; |
182
|
|
|
} |
183
|
|
|
} |
184
|
|
|
return $list; |
185
|
|
|
} |
186
|
|
|
|
187
|
|
|
function getRelatedTableName() { |
188
|
|
|
|
189
|
|
|
$bean_is_lhs=$this->_get_bean_position(); |
190
|
|
|
if (!isset($bean_is_lhs)) { |
191
|
|
|
$GLOBALS['log']->debug("Invalid relationship parameters. Exiting.."); |
192
|
|
|
return null; |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
if ($bean_is_lhs) { |
196
|
|
|
return $this->_relationship->rhs_table; |
197
|
|
|
} else { |
198
|
|
|
return $this->_relationship->lhs_table; |
199
|
|
|
} |
200
|
|
|
} |
201
|
|
|
|
202
|
|
|
function getRelatedModuleName() { |
203
|
|
|
|
204
|
|
|
$bean_is_lhs=$this->_get_bean_position(); |
205
|
|
|
if (!isset($bean_is_lhs)) { |
206
|
|
|
$GLOBALS['log']->debug("Invalid relationship parameters. Exiting.."); |
207
|
|
|
return null; |
208
|
|
|
} |
209
|
|
|
|
210
|
|
|
if ($bean_is_lhs) { |
211
|
|
|
return $this->_relationship->rhs_module; |
212
|
|
|
} else { |
213
|
|
|
return $this->_relationship->lhs_module; |
214
|
|
|
} |
215
|
|
|
} |
216
|
|
|
|
217
|
|
|
|
218
|
|
|
function getRelatedFields(){ |
219
|
|
|
return $this->relationship_fields; |
220
|
|
|
} |
221
|
|
|
|
222
|
|
|
function getRelatedField($name){ |
223
|
|
|
return (!empty($this->relationship_fields[$name]))? $this->relationship_fields[$name]: null; |
224
|
|
|
} |
225
|
|
|
|
226
|
|
|
function getRelationshipObject() { |
227
|
|
|
return $this->_relationship; |
228
|
|
|
} |
229
|
|
|
|
230
|
|
|
function _get_bean_position() { |
231
|
|
|
//current beans module and table are on the left side or the right side. |
232
|
|
|
$position = false; |
233
|
|
|
if ($this->_relationship->lhs_table == $this->_bean_table_name && $this->_relationship->lhs_key == $this->_bean_key_name) { |
234
|
|
|
$position = true; |
235
|
|
|
|
236
|
|
|
} |
237
|
|
|
if ($this->_relationship->rhs_table == $this->_bean_table_name && $this->_relationship->rhs_key == $this->_bean_key_name) { |
238
|
|
|
$position = false; |
239
|
|
|
} |
240
|
|
|
|
241
|
|
|
if($this->_swap_sides){ |
242
|
|
|
return !$position; |
243
|
|
|
} |
244
|
|
|
return $position; |
245
|
|
|
} |
246
|
|
|
|
247
|
|
|
function _is_self_relationship() { |
248
|
|
|
if ($this->_relationship->lhs_table == $this->_relationship->rhs_table) { |
249
|
|
|
return true; |
250
|
|
|
} |
251
|
|
|
return false; |
252
|
|
|
} |
253
|
|
|
|
254
|
|
|
function getJoin($params, $return_array =false) |
255
|
|
|
{ |
256
|
|
|
$join_type= ' INNER JOIN '; |
257
|
|
|
if(isset($params['join_type'])){ |
258
|
|
|
$join_type = $params['join_type']; |
259
|
|
|
} |
260
|
|
|
$id = -1; |
261
|
|
|
$join = ''; |
262
|
|
|
$bean_is_lhs=$this->_get_bean_position(); |
263
|
|
|
|
264
|
|
|
if ($this->_relationship->relationship_type=='one-to-one' or $this->_relationship->relationship_type=='many-to-one' or |
265
|
|
|
($this->_relationship->relationship_type=='one-to-many' && !$bean_is_lhs)) |
266
|
|
|
{ |
267
|
|
|
if ($bean_is_lhs) { |
268
|
|
|
$table = $this->_relationship->rhs_table; |
269
|
|
|
$key = $this->_relationship->rhs_key; |
270
|
|
|
// check right table alias |
271
|
|
|
$other_table = (empty($params['left_join_table_alias']) ? $this->_relationship->lhs_table : $params['left_join_table_alias']); |
272
|
|
|
$other_key = $this->_relationship->lhs_key; |
273
|
|
|
} else { |
274
|
|
|
$key = $this->_relationship->lhs_key; |
275
|
|
|
$table = $this->_relationship->lhs_table; |
276
|
|
|
|
277
|
|
|
if ( ! empty($params['join_table_alias'])) |
278
|
|
|
{ |
279
|
|
|
$table_with_alias = $table. " ".$params['join_table_alias']; |
280
|
|
|
$table = $params['join_table_alias']; |
281
|
|
|
} |
282
|
|
|
$other_table = (empty($params['right_join_table_alias']) ? $this->_relationship->rhs_table : $params['right_join_table_alias']); |
283
|
|
|
$other_key = $this->_relationship->rhs_key; |
284
|
|
|
} |
285
|
|
|
|
286
|
|
|
$join = $join_type . ' '. $table_with_alias . " ON\n".$table.'.'.$key.'= '.$other_table.'.'.$other_key ." AND ". $table.".deleted=0\n"; |
287
|
|
|
|
288
|
|
|
} |
289
|
|
|
if ($this->_relationship->relationship_type == 'one-to-many' && $bean_is_lhs) { |
290
|
|
|
|
291
|
|
|
$table = $this->_relationship->rhs_table; |
292
|
|
|
$key = $this->_relationship->rhs_key; |
293
|
|
|
$other_table = (empty($params['left_join_table_alias']) ? $this->_relationship->lhs_table : $params['left_join_table_alias']); |
294
|
|
|
$other_key = $this->_relationship->lhs_key; |
295
|
|
|
if ( ! empty($params['join_table_alias'])) |
296
|
|
|
{ |
297
|
|
|
$table_with_alias = $table. " ".$params['join_table_alias']; |
298
|
|
|
$table = $params['join_table_alias']; |
299
|
|
|
} |
300
|
|
|
|
301
|
|
|
$join = $join_type . ' '.$table_with_alias . " ON\n".$table.'.'.$key.'= '.$other_table.'.'.$other_key ." AND ". $table.".deleted=0\n"; |
302
|
|
|
|
303
|
|
|
} |
304
|
|
|
|
305
|
|
|
if ($this->_relationship->relationship_type=='many-to-many' ) |
306
|
|
|
{ |
307
|
|
|
if ( ! empty($params['join_table_alias'])) |
308
|
|
|
{ |
309
|
|
|
$table_with_alias = $this->_relationship->join_table. " ".$params['join_table_alias']; |
310
|
|
|
$table = $params['join_table_alias']; |
311
|
|
|
$rel_table_with_alias = |
312
|
|
|
$this->_relationship->join_table. " ". |
313
|
|
|
$params['join_table_link_alias']; |
314
|
|
|
$rel_table = $params['join_table_link_alias']; |
315
|
|
|
} |
316
|
|
|
|
317
|
|
|
if ( $bean_is_lhs ) |
318
|
|
|
{ |
319
|
|
|
$other_table = (empty($params['left_join_table_alias']) ? $this->_relationship->lhs_table : $params['left_join_table_alias']); |
320
|
|
|
$join .= $join_type . ' '.$rel_table_with_alias.' ON '.$other_table.".".$this->_relationship->lhs_key."=".$rel_table.".".$this->_relationship->join_key_lhs." AND ".$rel_table.".deleted=0\n"; |
321
|
|
|
} else |
322
|
|
|
{ |
323
|
|
|
$other_table = (empty($params['right_join_table_alias']) ? $this->_relationship->rhs_table : $params['right_join_table_alias']); |
324
|
|
|
$join .= $join_type . ' '.$rel_table_with_alias.' ON '.$other_table.".".$this->_relationship->rhs_key."=".$rel_table.".".$this->_relationship->join_key_rhs." AND ".$rel_table.".deleted=0\n"; |
325
|
|
|
} |
326
|
|
|
if (!empty($this->_relationship->relationship_role_column) && !$this->ignore_role_filter) |
327
|
|
|
{ |
328
|
|
|
$join.=" AND ".$rel_table.'.'.$this->_relationship->relationship_role_column; |
329
|
|
|
//role column value. |
330
|
|
|
if (empty($this->_relationship->relationship_role_column_value)) |
331
|
|
|
{ |
332
|
|
|
$join.=' IS NULL'; |
333
|
|
|
} else { |
334
|
|
|
$join.= "='".$this->_relationship->relationship_role_column_value."'"; |
335
|
|
|
} |
336
|
|
|
$join.= "\n"; |
337
|
|
|
} |
338
|
|
|
if ( ! empty($params['join_table_alias'])) |
339
|
|
|
{ |
340
|
|
|
if ( $bean_is_lhs ) |
341
|
|
|
{ |
342
|
|
|
$table_with_alias = $this->_relationship->rhs_table. " ".$params['join_table_alias']; |
343
|
|
|
} else { |
344
|
|
|
$table_with_alias = $this->_relationship->lhs_table. " ".$params['join_table_alias']; |
345
|
|
|
} |
346
|
|
|
$table = $params['join_table_alias']; |
347
|
|
|
} |
348
|
|
|
|
349
|
|
|
if ( $bean_is_lhs ) |
350
|
|
|
{ |
351
|
|
|
if($this->_rhs_key_override){ |
352
|
|
|
$join .= $join_type . ' '.$table_with_alias.' ON '.$table.".".$this->_relationship->rhs_key."=".$rel_table.".".$this->_relationship->join_key_rhs." AND ".$table.".deleted=0"; |
353
|
|
|
}else{ |
354
|
|
|
$join .= $join_type . ' '.$table_with_alias.' ON '.$table.".".$this->_relationship->lhs_key."=".$rel_table.".".$this->_relationship->join_key_rhs." AND ".$table.".deleted=0"; |
355
|
|
|
} |
356
|
|
|
} else { |
357
|
|
|
$join .= $join_type . ' '.$table_with_alias.' ON '.$table.".".$this->_relationship->rhs_key."=".$rel_table.".".$this->_relationship->join_key_lhs." AND ".$table.".deleted=0"; |
358
|
|
|
} |
359
|
|
|
$join.= "\n"; |
360
|
|
|
} |
361
|
|
|
|
362
|
|
|
if($return_array){ |
363
|
|
|
$ret_arr = array(); |
364
|
|
|
$ret_arr['join'] = $join; |
365
|
|
|
$ret_arr['type'] = $this->_relationship->relationship_type; |
366
|
|
|
if ( $bean_is_lhs ){ |
367
|
|
|
|
368
|
|
|
$ret_arr['rel_key'] = $this->_relationship->join_key_rhs; |
369
|
|
|
}else{ |
370
|
|
|
|
371
|
|
|
$ret_arr['rel_key'] = $this->_relationship->join_key_lhs; |
372
|
|
|
} |
373
|
|
|
return $ret_arr; |
374
|
|
|
} |
375
|
|
|
return $join; |
376
|
|
|
} |
377
|
|
|
|
378
|
|
|
|
379
|
|
|
function _add_deleted_clause($deleted=0,$add_and='',$prefix='') { |
380
|
|
|
|
381
|
|
|
if (!empty($prefix)) $prefix.='.'; |
382
|
|
|
if (!empty($add_and)) $add_and=' '.$add_and.' '; |
383
|
|
|
|
384
|
|
|
if ($deleted==0) return $add_and.$prefix.'deleted=0'; |
385
|
|
|
if ($deleted==1) return $add_and.$prefix.'deleted=1'; |
386
|
|
|
else return ''; |
387
|
|
|
} |
388
|
|
|
|
389
|
|
|
function _add_optional_where_clause($optional_array, $add_and='',$prefix='') { |
390
|
|
|
|
391
|
|
|
if (!empty($prefix)) $prefix.='.'; |
392
|
|
|
if (!empty($add_and)) $add_and=' '.$add_and.' '; |
393
|
|
|
|
394
|
|
|
if(!empty($optional_array)){ |
395
|
|
|
return $add_and.$prefix."".$optional_array['lhs_field']."".$optional_array['operator']."'".$optional_array['rhs_value']."'"; |
396
|
|
|
} |
397
|
|
|
return ''; |
398
|
|
|
//end function _add_optional_where_clause |
399
|
|
|
} |
400
|
|
|
|
401
|
|
|
|
402
|
|
|
|
403
|
|
|
function getQuery($return_as_array=false, $sort_array = array(),$deleted=0, $optional_where="", $return_join = false, $bean_filter="", $role="", $for_subpanels = false){ |
404
|
|
|
|
405
|
|
|
$select=''; |
406
|
|
|
$from=''; |
407
|
|
|
$join = ''; |
408
|
|
|
$where=''; |
409
|
|
|
$join_tables = array(); |
410
|
|
|
$bean_is_lhs=$this->_get_bean_position(); |
411
|
|
|
|
412
|
|
|
if (!isset($bean_is_lhs)) { |
413
|
|
|
$GLOBALS['log']->debug("Invalid relationship parameters. Exiting.."); |
414
|
|
|
return null; |
415
|
|
|
} |
416
|
|
|
|
417
|
|
|
if (empty($bean_filter)) { |
418
|
|
|
if(!empty($this->_bean_filter_field)){ |
419
|
|
|
$bean_filter_field = $this->_bean_filter_field; |
420
|
|
|
$bean_filter="= '".$this->_bean->$bean_filter_field."'"; |
421
|
|
|
}else{ |
422
|
|
|
$bean_filter="= '".$this->_bean->id."'"; |
423
|
|
|
} |
424
|
|
|
} |
425
|
|
|
|
426
|
|
|
$GLOBALS['log']->debug("getQuery, Bean is LHS: ".$bean_is_lhs); |
427
|
|
|
$GLOBALS['log']->debug("getQuery, Relationship type=".$this->_relationship->relationship_type); |
428
|
|
|
$GLOBALS['log']->debug("getQuery, Relationship role column name=".$this->_relationship->relationship_role_column); |
429
|
|
|
|
430
|
|
|
if ($this->_relationship->relationship_type=='one-to-one' or $this->_relationship->relationship_type=='many-to-one' or |
431
|
|
|
($this->_relationship->relationship_type=='one-to-many' && !$bean_is_lhs)) { |
432
|
|
|
|
433
|
|
|
$GLOBALS['log']->debug("Processing one-to-one,many-to-one,one-to-many."); |
434
|
|
|
|
435
|
|
|
if ($this->add_distinct) { |
436
|
|
|
$select='SELECT DISTINCT id'; |
437
|
|
|
} else { |
438
|
|
|
$select='SELECT id'; |
439
|
|
|
} |
440
|
|
|
|
441
|
|
|
if ($bean_is_lhs) { |
442
|
|
|
$from= 'FROM '.$this->_relationship->rhs_table; |
443
|
|
|
$where='WHERE '.$this->_relationship->rhs_table.'.'.$this->_relationship->rhs_key.$bean_filter; |
444
|
|
|
if (!empty($this->_relationship->relationship_role_column) && !$this->ignore_role_filter) { |
445
|
|
|
$where.=" AND ".$this->_relationship->rhs_table.'.'.$this->_relationship->relationship_role_column; |
446
|
|
|
|
447
|
|
|
//role column value. |
448
|
|
|
if (empty($this->_relationship->relationship_role_column_value)) { |
449
|
|
|
$where.=' IS NULL'; |
450
|
|
|
} else { |
451
|
|
|
$where.= "='".$this->_relationship->relationship_role_column_value."'"; |
452
|
|
|
} |
453
|
|
|
} |
454
|
|
|
|
455
|
|
|
//add deleted clause - but not if we're dealing with a Custom table which will lack the 'deleted' field |
456
|
|
|
if(substr_count($this->_relationship->rhs_table, '_cstm') == 0) |
457
|
|
|
$where.=$this->_add_deleted_clause($deleted,'AND',$this->_relationship->rhs_table ); |
458
|
|
|
|
459
|
|
|
if($optional_where!=""){ |
460
|
|
|
//process optional where |
461
|
|
|
$where.=$this->_add_optional_where_clause($optional_where,'AND'); |
462
|
|
|
} |
463
|
|
|
|
464
|
|
|
|
465
|
|
|
} |
466
|
|
|
else { |
467
|
|
|
$from= 'FROM '.$this->_relationship->lhs_table; |
468
|
|
|
$where='WHERE '.$this->_relationship->lhs_table.'.'.$this->_relationship->lhs_key."= '".$this->_bean->{$this->_relationship->rhs_key}."'"; |
469
|
|
|
//added deleted clause. |
470
|
|
|
$where.=$this->_add_deleted_clause($deleted,'AND', $this->_relationship->lhs_table); |
471
|
|
|
|
472
|
|
|
|
473
|
|
|
if($optional_where!=""){ |
474
|
|
|
//process optional where |
475
|
|
|
$where.=$this->_add_optional_where_clause($optional_where,'AND'); |
476
|
|
|
} |
477
|
|
|
|
478
|
|
|
} |
479
|
|
|
} |
480
|
|
|
if ($this->_relationship->relationship_type == 'one-to-many' && $bean_is_lhs) { |
481
|
|
|
|
482
|
|
|
$GLOBALS['log']->debug("Processing one-to-many."); |
483
|
|
|
|
484
|
|
|
if ($this->add_distinct) { |
485
|
|
|
$select='SELECT DISTINCT '.$this->_relationship->rhs_table.'.id'; |
486
|
|
|
} else { |
487
|
|
|
$select='SELECT '.$this->_relationship->rhs_table.'.id'; |
488
|
|
|
} |
489
|
|
|
$from= 'FROM '.$this->_relationship->rhs_table; |
490
|
|
|
$where='WHERE '.$this->_relationship->rhs_table.'.'.$this->_relationship->rhs_key.$bean_filter; |
491
|
|
|
if (!empty($this->_relationship->relationship_role_column) && !$this->ignore_role_filter) { |
492
|
|
|
$where.=" AND ".$this->_relationship->rhs_table.'.'.$this->_relationship->relationship_role_column; |
493
|
|
|
//role column value. |
494
|
|
|
if (empty($this->_relationship->relationship_role_column_value)) { |
495
|
|
|
$where.=' IS NULL'; |
496
|
|
|
} else { |
497
|
|
|
$where.= "='".$this->_relationship->relationship_role_column_value."'"; |
498
|
|
|
} |
499
|
|
|
} |
500
|
|
|
|
501
|
|
|
//add deleted clause - but not if we're dealing with a Custom table which will lack the 'deleted' field |
502
|
|
|
if(substr_count($this->_relationship->rhs_table, '_cstm') == 0) |
503
|
|
|
$where.=$this->_add_deleted_clause($deleted,'AND',$this->_relationship->rhs_table); |
504
|
|
|
|
505
|
|
|
if($optional_where!=""){ |
506
|
|
|
//process optional where |
507
|
|
|
$where.=$this->_add_optional_where_clause($optional_where,'AND'); |
508
|
|
|
} |
509
|
|
|
|
510
|
|
|
} |
511
|
|
|
|
512
|
|
|
if ($this->_relationship->relationship_type=='many-to-many' ) { |
513
|
|
|
$GLOBALS['log']->debug("Processing many-to-many."); |
514
|
|
|
|
515
|
|
|
$swap = !$for_subpanels && $this->_swap_sides; |
516
|
|
|
if (($bean_is_lhs && !$swap) || (!$bean_is_lhs && $swap)) { |
517
|
|
|
if ($this->add_distinct) { |
518
|
|
|
$select="SELECT DISTINCT ".$this->_relationship->rhs_table.".id"; |
519
|
|
|
} else { |
520
|
|
|
$select="SELECT ".$this->_relationship->rhs_table.".id"; |
521
|
|
|
} |
522
|
|
|
|
523
|
|
|
$from= 'FROM '.$this->_relationship->rhs_table; |
524
|
|
|
$subjoin=' INNER JOIN '.$this->_relationship->join_table.' ON ('.$this->_relationship->rhs_table.".".$this->_relationship->rhs_key."=".$this->_relationship->join_table.".".$this->_relationship->join_key_rhs." AND ".$this->_relationship->join_table.".".$this->_relationship->join_key_lhs.$bean_filter; |
525
|
|
|
$join_tables[] = $this->_relationship->join_table; |
526
|
|
|
if (!empty($this->_relationship->relationship_role_column) && !$this->ignore_role_filter) { |
527
|
|
|
$subjoin.=" AND ".$this->_relationship->join_table.'.'.$this->_relationship->relationship_role_column; |
528
|
|
|
|
529
|
|
|
//role column value. |
530
|
|
|
if (empty($this->_relationship->relationship_role_column_value)) { |
531
|
|
|
$subjoin.=' IS NULL'; |
532
|
|
|
} else { |
533
|
|
|
$subjoin.= "='".$this->_relationship->relationship_role_column_value."'"; |
534
|
|
|
} |
535
|
|
|
} |
536
|
|
|
$subjoin.=')'; |
537
|
|
|
$join .= $subjoin; |
538
|
|
|
$from .= $subjoin; |
539
|
|
|
|
540
|
|
|
|
541
|
|
|
//add deleted clause. |
542
|
|
|
if ($deleted == 0 or $deleted==1) { |
543
|
|
|
$where.=' WHERE '.$this->_add_deleted_clause($deleted,'',$this->_relationship->join_table).$this->_add_deleted_clause($deleted,'AND',$this->_relationship->rhs_table); |
544
|
|
|
} |
545
|
|
|
|
546
|
|
|
|
547
|
|
|
if($optional_where!=""){ |
548
|
|
|
//process optional where |
549
|
|
|
$where.=$this->_add_optional_where_clause($optional_where,'AND', $this->_relationship->rhs_table); |
550
|
|
|
} |
551
|
|
|
|
552
|
|
|
|
553
|
|
|
} |
554
|
|
|
else { |
555
|
|
|
if ($this->add_distinct) { |
556
|
|
|
$select="SELECT DISTINCT ".$this->_relationship->lhs_table.".id"; |
557
|
|
|
} else { |
558
|
|
|
$select="SELECT ".$this->_relationship->lhs_table.".id"; |
559
|
|
|
} |
560
|
|
|
|
561
|
|
|
$from= 'FROM '.$this->_relationship->lhs_table; |
562
|
|
|
$subjoin=' INNER JOIN '.$this->_relationship->join_table.' ON ('.$this->_relationship->lhs_table.".".$this->_relationship->lhs_key."=".$this->_relationship->join_table.".".$this->_relationship->join_key_lhs." AND ".$this->_relationship->join_table.".".$this->_relationship->join_key_rhs.$bean_filter; |
563
|
|
|
$join_tables[] = $this->_relationship->join_table; |
564
|
|
|
if (!empty($this->_relationship->relationship_role_column) && !$this->ignore_role_filter) { |
565
|
|
|
$subjoin.=" AND ".$this->_relationship->relationship_role_column; |
566
|
|
|
|
567
|
|
|
//role column value. |
568
|
|
|
if (empty($this->_relationship->relationship_role_column_value)) { |
569
|
|
|
$subjoin.=' IS NULL'; |
570
|
|
|
} else { |
571
|
|
|
$subjoin.= "='".$this->_relationship->relationship_role_column_value."'"; |
572
|
|
|
} |
573
|
|
|
} |
574
|
|
|
$subjoin.=')'; |
575
|
|
|
$join .= $subjoin; |
576
|
|
|
$from .= $subjoin; |
577
|
|
|
//add deleted clause. |
578
|
|
|
if ($deleted == 0 or $deleted==1) { |
579
|
|
|
$where.=' WHERE '.$this->_add_deleted_clause($deleted,'',$this->_relationship->join_table).$this->_add_deleted_clause($deleted,'AND',$this->_relationship->lhs_table); |
580
|
|
|
} |
581
|
|
|
|
582
|
|
|
|
583
|
|
|
if($optional_where!=""){ |
584
|
|
|
//process optional where |
585
|
|
|
$where.=$this->_add_optional_where_clause($optional_where,'AND', $this->_relationship->lhs_table); |
586
|
|
|
} |
587
|
|
|
|
588
|
|
|
} |
589
|
|
|
if (!empty($role)){ |
590
|
|
|
$select.=", ".$this->_relationship->join_table.".".$role; |
591
|
|
|
} |
592
|
|
|
} |
593
|
|
|
if ($return_as_array) { |
594
|
|
|
$query_as_array['select']=$select; |
595
|
|
|
$query_as_array['from']=$from; |
596
|
|
|
$query_as_array['where']=$where; |
597
|
|
|
if($return_join){ |
598
|
|
|
$query_as_array['join'] = $join; |
599
|
|
|
$query_as_array['join_tables'] = $join_tables; |
600
|
|
|
} |
601
|
|
|
return $query_as_array; |
602
|
|
|
} |
603
|
|
|
else { |
604
|
|
|
$query = $select.' '.$from.' '.$where; |
605
|
|
|
$GLOBALS['log']->debug("Link Query=".$query); |
606
|
|
|
return $query; |
607
|
|
|
} |
608
|
|
|
} |
609
|
|
|
|
610
|
|
|
function getBeans($template, $sort_array = array(), $begin_index = 0, $end_index = -1, $deleted=0, $optional_where="") { |
611
|
|
|
$query = $this->getQuery(false,array(), $deleted, $optional_where); //get array of IDs |
612
|
|
|
return $this->_bean->build_related_list($query, $template); |
613
|
|
|
} |
614
|
|
|
|
615
|
|
|
function _add_one_to_many_table_based($key,$bean_is_lhs) { |
616
|
|
|
|
617
|
|
|
if ($bean_is_lhs) { |
618
|
|
|
$set_key_value=$this->_bean->id; |
619
|
|
|
$where_key_value=$key; |
620
|
|
|
} |
621
|
|
|
else { |
622
|
|
|
$set_key_value=$key; |
623
|
|
|
$where_key_value=$this->_bean->id; |
624
|
|
|
} |
625
|
|
|
|
626
|
|
|
$query= 'UPDATE '.$this->_relationship->rhs_table; |
627
|
|
|
$query.=' SET '.$this->_relationship->rhs_table.'.'.$this->_relationship->rhs_key."='".$set_key_value."'"; |
628
|
|
|
|
629
|
|
|
//add role column to the query. |
630
|
|
|
if (!empty($this->_relationship->relationship_role_column)) { |
631
|
|
|
$query.=' ,'.$this->_relationship->relationship_role_column."='".$this->_relationship->relationship_role_column_value."'"; |
632
|
|
|
} |
633
|
|
|
$query.=' WHERE '.$this->_relationship->rhs_table.".id='".$where_key_value."'"; |
634
|
|
|
|
635
|
|
|
$GLOBALS['log']->fatal("Relationship Query ".$query); |
636
|
|
|
|
637
|
|
|
$result=$this->_db->query($query, true); |
638
|
|
|
} |
639
|
|
|
|
640
|
|
|
/* handles many to one*/ |
641
|
|
|
function _add_many_to_one_bean_based($key) { |
642
|
|
|
|
643
|
|
|
//make a copy of this bean to avoid recursion. |
644
|
|
|
$bean=new $this->_bean->object_name; |
645
|
|
|
$bean->retrieve($this->_bean->id); |
646
|
|
|
|
647
|
|
|
$bean->{$this->_relationship->lhs_key}=$key; |
648
|
|
|
|
649
|
|
|
//set relationship role. |
650
|
|
|
if (!empty($this->_relationship->relationship_role_column)) { |
651
|
|
|
$bean->{$this->_relationship->relationship_role_column}=$this->_relationship->relationship_role_column_value; |
652
|
|
|
} |
653
|
|
|
$GLOBALS['log']->fatal("Adding many to one bean based {$bean->module_dir} {$bean->id}"); |
654
|
|
|
$bean->save(); |
655
|
|
|
} |
656
|
|
|
|
657
|
|
|
|
658
|
|
|
/* use this function to create link between 2 objects |
659
|
|
|
* 1:1 will be treated like 1 to many. |
660
|
|
|
* todo handle self referencing relationships |
661
|
|
|
* the function also allows for setting of values for additional field in the table being |
662
|
|
|
* updated to save the relationship, in case of many-to-many relationships this would be the join table. |
663
|
|
|
* the values should be passed as key value pairs with column name as the key name and column value as key value. |
664
|
|
|
*/ |
665
|
|
|
function add($rel_keys,$additional_values=array()) { |
666
|
|
|
|
667
|
|
|
if (!isset($rel_keys) or empty($rel_keys)) { |
668
|
|
|
$GLOBALS['log']->fatal("Link.add, Null key passed, no-op, returning... "); |
669
|
|
|
return; |
670
|
|
|
} |
671
|
|
|
|
672
|
|
|
//check to ensure that we do in fact have an id on the bean. |
673
|
|
|
if(empty($this->_bean->id)){ |
674
|
|
|
$GLOBALS['log']->fatal("Link.add, No id on the bean... "); |
675
|
|
|
return; |
676
|
|
|
} |
677
|
|
|
|
678
|
|
|
if (!is_array($rel_keys)) { |
679
|
|
|
$keys[]=$rel_keys; |
680
|
|
|
} else { |
681
|
|
|
$keys=$rel_keys; |
682
|
|
|
} |
683
|
|
|
|
684
|
|
|
$bean_is_lhs=$this->_get_bean_position(); |
685
|
|
|
if (!isset($bean_is_lhs)) { |
686
|
|
|
$GLOBALS['log']->fatal("Invalid relationship parameters. Exiting.."); |
687
|
|
|
return null; |
688
|
|
|
} |
689
|
|
|
//if multiple keys are passed then check for unsupported relationship types. |
690
|
|
|
if (count($keys) > 1) { |
691
|
|
|
if (($this->_relationship->relationship_type == 'one-to-one') |
692
|
|
|
or ($this->_relationship->relationship_type == 'one-to-many' and !$bean_is_lhs) |
693
|
|
|
or ($this->_relationship->relationship_type == 'many-to-one')) { |
694
|
|
|
$GLOBALS['log']->fatal("Invalid parameters passed to function, the relationship does not support addition of multiple records."); |
695
|
|
|
return; |
696
|
|
|
} |
697
|
|
|
} |
698
|
|
|
$GLOBALS['log']->debug("Relationship type = {$this->_relationship->relationship_type}"); |
699
|
|
|
foreach($keys as $key) { |
700
|
|
|
|
701
|
|
|
//fetch the related record using the key and update. |
702
|
|
|
if ($this->_relationship->relationship_type=='one-to-one' || $this->_relationship->relationship_type == 'one-to-many' ) { |
703
|
|
|
$this->_add_one_to_many_table_based($key,$bean_is_lhs); |
704
|
|
|
} |
705
|
|
|
|
706
|
|
|
//updates the bean passed to the instance.... |
707
|
|
|
//todo remove this case. |
708
|
|
|
if ($this->_relationship->relationship_type=='many-to-one') { |
709
|
|
|
$this->_add_many_to_one_bean_based($key); |
710
|
|
|
} |
711
|
|
|
|
712
|
|
|
//insert record in the link table. |
713
|
|
|
if ($this->_relationship->relationship_type=='many-to-many' ) { |
714
|
|
|
//replace existing relationships for one-to-one |
715
|
|
|
if(!empty($GLOBALS['dictionary'][$this->_relationship_name]['true_relationship_type']) && |
716
|
|
|
($GLOBALS['dictionary'][$this->_relationship_name]['true_relationship_type'] == 'one-to-one')) |
717
|
|
|
{ |
718
|
|
|
//Remove all existing links with either bean. |
719
|
|
|
$old_rev = isset($this->_relationship->reverse) ? false : $this->_relationship->reverse; |
720
|
|
|
$this->_relationship->reverse = true; |
721
|
|
|
$this->delete($key); |
722
|
|
|
$this->delete($this->_bean->id); |
723
|
|
|
$this->_relationship->reverse = $old_rev; |
724
|
|
|
} |
725
|
|
|
|
726
|
|
|
//Swap the bean positions for self relationships not coming from subpanels. |
727
|
|
|
//such as one-to-many relationship fields generated in studio/MB |
728
|
|
|
$swap = !isset($_REQUEST['subpanel_id']) && $this->_swap_sides; |
729
|
|
|
//add keys from the 2 tables to the additional keys array.. |
730
|
|
|
if (($bean_is_lhs && !$swap) || (!$bean_is_lhs && $swap)) { |
731
|
|
|
$additional_values[$this->_relationship->join_key_lhs]=$this->_bean->id; |
732
|
|
|
$additional_values[$this->_relationship->join_key_rhs]=$key; |
733
|
|
|
} else { |
734
|
|
|
$additional_values[$this->_relationship->join_key_rhs]=$this->_bean->id; |
735
|
|
|
$additional_values[$this->_relationship->join_key_lhs]=$key; |
736
|
|
|
} |
737
|
|
|
//add the role condition. |
738
|
|
|
if (!empty($this->_relationship->relationship_role_column) && !empty($this->_relationship->relationship_role_column_value)) { |
739
|
|
|
$additional_values[$this->_relationship->relationship_role_column]=$this->_relationship->relationship_role_column_value; |
740
|
|
|
} |
741
|
|
|
//add deleted condition. |
742
|
|
|
$additional_values['deleted']=0; |
743
|
|
|
|
744
|
|
|
$this->_add_many_to_many($additional_values); |
745
|
|
|
|
746
|
|
|
//reverse will be set to true only for self-referencing many-to-many relationships. |
747
|
|
|
if ($this->_is_self_relationship() && !empty($GLOBALS['dictionary'][$this->_relationship_name]) && |
748
|
|
|
!empty($GLOBALS['dictionary'][$this->_relationship_name]['true_relationship_type']) && |
749
|
|
|
$GLOBALS['dictionary'][$this->_relationship_name]['true_relationship_type'] == 'many-to-many' || |
750
|
|
|
(!empty($this->_relationship->reverse) && $this->_relationship->reverse == true )){ |
751
|
|
|
//swap key values; |
752
|
|
|
$temp=$additional_values[$this->_relationship->join_key_lhs]; |
753
|
|
|
$additional_values[$this->_relationship->join_key_lhs]=$additional_values[$this->_relationship->join_key_rhs]; |
754
|
|
|
$additional_values[$this->_relationship->join_key_rhs]=$temp; |
755
|
|
|
|
756
|
|
|
$this->_add_many_to_many($additional_values); |
757
|
|
|
} |
758
|
|
|
} |
759
|
|
|
$custom_logic_arguments = array(); |
760
|
|
|
$custom_reverse_arguments = array(); |
761
|
|
|
$custom_logic_arguments['related_id'] = $key; |
762
|
|
|
$custom_logic_arguments['id'] = $this->_bean->id; |
763
|
|
|
$custom_reverse_arguments['related_id'] = $this->_bean->id; |
764
|
|
|
$custom_reverse_arguments['id'] = $key; |
765
|
|
|
if($bean_is_lhs) { |
766
|
|
|
$custom_logic_arguments['module'] = $this->_relationship->lhs_module; |
767
|
|
|
$custom_logic_arguments['related_module'] = $this->_relationship->rhs_module; |
768
|
|
|
$custom_reverse_arguments['module'] = $this->_relationship->rhs_module; |
769
|
|
|
$custom_reverse_arguments['related_module'] = $this->_relationship->lhs_module; |
770
|
|
|
} else { |
771
|
|
|
$custom_logic_arguments['related_module'] = $this->_relationship->lhs_module; |
772
|
|
|
$custom_reverse_arguments['related_module'] = $this->_relationship->rhs_module; |
773
|
|
|
$custom_logic_arguments['module'] = $this->_relationship->rhs_module; |
774
|
|
|
$custom_reverse_arguments['module'] = $this->_relationship->lhs_module; |
775
|
|
|
} |
776
|
|
|
/**** CALL IT FROM THE MAIN BEAN FIRST ********/ |
777
|
|
|
$this->_bean->call_custom_logic('after_relationship_add', $custom_logic_arguments); |
778
|
|
|
/**** NOW WE HAVE TO CALL THE LOGIC HOOK THE OTHER WAY SINCE IT TAKES TWO FOR A RELATIONSHIP****/ |
779
|
|
|
global $beanList; |
780
|
|
|
if ( isset($beanList[$custom_logic_arguments['related_module']]) ) { |
781
|
|
|
$class = $beanList[$custom_logic_arguments['related_module']]; |
782
|
|
|
if ( !empty($class) ) { |
783
|
|
|
$rbean = new $class(); |
784
|
|
|
$rbean->id = $key; |
785
|
|
|
$rbean->call_custom_logic('after_relationship_add', $custom_reverse_arguments); |
786
|
|
|
} |
787
|
|
|
} |
788
|
|
|
} |
789
|
|
|
} |
790
|
|
|
|
791
|
|
|
function _add_many_to_many($add_values) { |
792
|
|
|
|
793
|
|
|
//add date modified. |
794
|
|
|
$add_values['date_modified']= $GLOBALS['timedate']->nowDb(); |
795
|
|
|
|
796
|
|
|
//check whether duplicate exist or not. |
797
|
|
|
if ($this->relationship_exists($this->_relationship->join_table,$add_values)) { |
798
|
|
|
|
799
|
|
|
/* switch($this->when_dup_relationship_found) { |
800
|
|
|
|
801
|
|
|
case 1: //do nothing. |
802
|
|
|
$GLOBALS['log']->debug("Executing default option, no action."); |
803
|
|
|
break; |
804
|
|
|
|
805
|
|
|
case 3: //delete the record first, then create a new entry. |
806
|
|
|
$this->_delete_row($this->_relationship->join_table,$this->_duplicate_key); |
807
|
|
|
$this->_insert_row($add_values); |
808
|
|
|
break; |
809
|
|
|
|
810
|
|
|
default: |
811
|
|
|
case 2: //update the record. |
812
|
|
|
*/ $this->_update_row($add_values,$this->_relationship->join_table,$this->_duplicate_where); |
813
|
|
|
/* break; |
814
|
|
|
}*/ |
815
|
|
|
|
816
|
|
|
} else { |
817
|
|
|
$this->_insert_row($add_values); |
818
|
|
|
} |
819
|
|
|
} |
820
|
|
|
|
821
|
|
|
function _delete_row($table_name,$key) { |
822
|
|
|
$query="UPDATE $table_name SET deleted=1, date_modified='" .$GLOBALS['timedate']->nowDb()."' WHERE id='".$this->_db->quote($key)."'"; |
823
|
|
|
$GLOBALS['log']->debug("Relationship Delete Statement :".$query); |
824
|
|
|
|
825
|
|
|
$result=$this->_db->query($query, true); |
826
|
|
|
} |
827
|
|
|
|
828
|
|
|
function _update_row(&$value_array,$table_name,$where) { |
829
|
|
|
|
830
|
|
|
$query='UPDATE '.$table_name.' SET '; |
831
|
|
|
$delimiter=''; |
832
|
|
|
foreach ($value_array as $key=>$value) { |
833
|
|
|
$query.=$delimiter.$key."='".$this->_db->quote($value)."' "; |
834
|
|
|
$delimiter=","; |
835
|
|
|
} |
836
|
|
|
$query.=$where; |
837
|
|
|
$GLOBALS['log']->debug("Relationship Update Statement :".$query); |
838
|
|
|
|
839
|
|
|
$result=$this->_db->query($query, true); |
840
|
|
|
} |
841
|
|
|
|
842
|
|
|
function _insert_row(&$value_array) { |
843
|
|
|
//add key column |
844
|
|
|
$value_array['id']= create_guid(); |
845
|
|
|
|
846
|
|
|
$columns_list=''; |
847
|
|
|
$values_list=''; |
848
|
|
|
$delimiter=''; |
849
|
|
|
foreach ($value_array as $key=>$value) { |
850
|
|
|
$columns_list.=$delimiter.$key; |
851
|
|
|
$values_list .=$delimiter."'".$this->_db->quote($value)."'"; |
852
|
|
|
$delimiter=","; |
853
|
|
|
} |
854
|
|
|
$insert_string='INSERT into '.$this->_relationship->join_table.' ('.$columns_list.') VALUES ('.$values_list.')'; |
855
|
|
|
$GLOBALS['log']->debug("Relationship Insert String :".$insert_string); |
856
|
|
|
|
857
|
|
|
$result=$this->_db->query($insert_string, true); |
858
|
|
|
} |
859
|
|
|
|
860
|
|
|
|
861
|
|
|
|
862
|
|
|
/* This method operates on all related record, takes action based on cardinality of the relationship. |
863
|
|
|
* one-to-one, one-to-many: update the rhs table's parent id with null |
864
|
|
|
* many-to-one: update the lhs table's parent-id with null. |
865
|
|
|
* many-to-many: delete rows from the link table. related table must have deleted and date_modified column. |
866
|
|
|
* If related_id is null, the methods assumes that the parent bean (whose id is passed) is being deleted. |
867
|
|
|
* If both id and related_id are passed, the method unlinks a single relationship. |
868
|
|
|
* parameters: id of the bean being deleted. |
869
|
|
|
* |
870
|
|
|
*/ |
871
|
|
|
function delete($id,$related_id='') { |
872
|
|
|
$GLOBALS['log']->debug(sprintf("delete called with these parameter values. id=%s, related_id=%s",$id,$related_id)); |
873
|
|
|
|
874
|
|
|
$_relationship=&$this->_relationship; |
875
|
|
|
$_bean=&$this->_bean; |
876
|
|
|
|
877
|
|
|
$bean_is_lhs=$this->_get_bean_position(); |
878
|
|
|
if (!isset($bean_is_lhs)) { |
879
|
|
|
$GLOBALS['log']->debug("Invalid relationship parameters. Exiting.."); |
880
|
|
|
return null; |
881
|
|
|
} |
882
|
|
|
if ($_relationship->relationship_type=='one-to-many' or $_relationship->relationship_type=='one-to-one' ) { |
883
|
|
|
if ($bean_is_lhs) { |
884
|
|
|
//update rhs_table set rhs_key = null, relation_column_name = null where rhs_key= this_bean_id |
885
|
|
|
$query='UPDATE '.$_relationship->rhs_table.' SET '.$_relationship->rhs_key."=NULL, date_modified='".$GLOBALS['timedate']->nowDb()."'"; |
886
|
|
|
|
887
|
|
|
if (!empty($_relationship->relationship_role_column) && !empty($_relationship->relationship_role_column_value)) { |
888
|
|
|
$query.=','.$_relationship->relationship_role_column."= NULL "; |
889
|
|
|
$query.=' WHERE '.$_relationship->relationship_role_column."= '".$_relationship->relationship_role_column_value."' AND "; |
890
|
|
|
} else { |
891
|
|
|
$query.=' WHERE '; |
892
|
|
|
} |
893
|
|
|
$query.=$_relationship->rhs_key."= '".$id."' "; |
894
|
|
|
|
895
|
|
|
//restrict to one row if related_id is passed. |
896
|
|
|
if (!empty($related_id)) { |
897
|
|
|
$query.=" AND ".$_relationship->rhs_table.".id='".$related_id."'"; |
898
|
|
|
} |
899
|
|
|
|
900
|
|
|
} |
901
|
|
|
else { |
|
|
|
|
902
|
|
|
//do nothing because the row that stores the relationship keys is being deleted. |
903
|
|
|
//todo log an error message here. |
904
|
|
|
//if this is the case and related_id is passed then log a message asking the user |
905
|
|
|
//to clear the relationship using the bean. |
906
|
|
|
} |
907
|
|
|
} |
908
|
|
|
|
909
|
|
|
if ($_relationship->relationship_type=='many-to-one') { |
|
|
|
|
910
|
|
|
//do nothing because the row that stores the relationship keys is being deleted. |
911
|
|
|
//todo log an error message here. |
912
|
|
|
//if this is the case and related_id is passed then log a message asking the user |
913
|
|
|
//to clear the relationship using the bean. |
914
|
|
|
} |
915
|
|
|
|
916
|
|
|
if ($_relationship->relationship_type=='many-to-many' ) { |
917
|
|
|
$use_bean_is_lhs = isset($_REQUEST['ajaxSubpanel']) || $this->_swap_sides !== true; |
918
|
|
|
$query='UPDATE '.$_relationship->join_table." SET deleted=1, date_modified='".$GLOBALS['timedate']->nowDb()."'"; |
919
|
|
|
if ($bean_is_lhs && $use_bean_is_lhs) { |
920
|
|
|
if (!empty($this->_relationship->reverse) && ($this->_relationship->reverse == true or $this->_relationship->reverse == 1)){ |
921
|
|
|
if (empty($related_id)) { |
922
|
|
|
$query.=" WHERE (".$_relationship->join_key_lhs."= '". $id ."' or ".$_relationship->join_key_rhs."='". $id ."')" ; |
923
|
|
|
} else { |
924
|
|
|
$query.=" WHERE (".$_relationship->join_key_lhs."= '". $id ."' AND ".$_relationship->join_key_rhs."='".$related_id."') OR (".$_relationship->join_key_rhs."='". $id ."' AND ".$_relationship->join_key_lhs."='".$related_id."')"; |
925
|
|
|
} |
926
|
|
|
} else { |
927
|
|
|
if (empty($related_id)) { |
928
|
|
|
$query.=" WHERE ".$_relationship->join_key_lhs."= '". $id ."'"; |
929
|
|
|
} else { |
930
|
|
|
$query.=" WHERE ".$_relationship->join_key_lhs."= '". $id ."' AND ".$_relationship->join_key_rhs."= '". $related_id."'"; |
931
|
|
|
} |
932
|
|
|
} |
933
|
|
|
} else { |
934
|
|
|
if (!empty($this->_relationship->reverse) && ($this->_relationship->reverse == true or $this->_relationship->reverse == 1)) { |
935
|
|
|
if (empty($related_id)) { |
936
|
|
|
$query.=" WHERE (".$_relationship->join_key_rhs."= '". $id ."' or ".$_relationship->join_key_lhs."='". $id ."')" ; |
937
|
|
|
} else { |
938
|
|
|
$query.=" WHERE (".$_relationship->join_key_rhs."= '". $id ."' AND ".$_relationship->join_key_lhs."='".$related_id."') OR (".$_relationship->join_key_lhs."='". $id ."' AND ".$_relationship->join_key_rhs."='".$related_id."')"; |
939
|
|
|
} |
940
|
|
|
} else { |
941
|
|
|
if (empty($related_id)) { |
942
|
|
|
$query.=" WHERE ".$_relationship->join_key_rhs."= '". $id ."'" ; |
943
|
|
|
} else { |
944
|
|
|
$query.=" WHERE ".$_relationship->join_key_rhs."= '". $id ."' AND ".$_relationship->join_key_lhs."= '". $related_id."'" ; |
945
|
|
|
} |
946
|
|
|
} |
947
|
|
|
if (!empty($_relationship->relationship_role_column) && !empty($_relationship->relationship_role_column_value)) { |
948
|
|
|
$query.=' AND '.$_relationship->relationship_role_column."= '".$_relationship->relationship_role_column_value."'"; |
949
|
|
|
} |
950
|
|
|
} |
951
|
|
|
} |
952
|
|
|
//if query string is not empty execute it. |
953
|
|
|
if (isset($query)) { |
954
|
|
|
$GLOBALS['log']->fatal('Link.Delete:Delete Query: '.$query); |
955
|
|
|
$this->_db->query($query,true); |
956
|
|
|
} |
957
|
|
|
$custom_logic_arguments = array(); |
958
|
|
|
$custom_logic_arguments['id'] = $id; |
959
|
|
|
$custom_logic_arguments['related_id'] = $related_id; |
960
|
|
|
$custom_reverse_arguments = array(); |
961
|
|
|
$custom_reverse_arguments['related_id'] = $id; |
962
|
|
|
$custom_reverse_arguments['id'] = $related_id; |
963
|
|
|
if($bean_is_lhs) { |
964
|
|
|
$custom_logic_arguments['module'] = $this->_relationship->lhs_module; |
965
|
|
|
$custom_logic_arguments['related_module'] = $this->_relationship->rhs_module; |
966
|
|
|
$custom_reverse_arguments['module'] = $this->_relationship->lhs_module; |
967
|
|
|
$custom_reverse_arguments['related_module'] = $this->_relationship->rhs_module; |
968
|
|
|
} else { |
969
|
|
|
$custom_logic_arguments['module'] = $this->_relationship->rhs_module; |
970
|
|
|
$custom_logic_arguments['related_module'] = $this->_relationship->lhs_module; |
971
|
|
|
$custom_reverse_arguments['module'] = $this->_relationship->lhs_module; |
972
|
|
|
$custom_reverse_arguments['related_module'] = $this->_relationship->rhs_module; |
973
|
|
|
} |
974
|
|
|
|
975
|
|
|
if (empty($this->_bean->id)) { |
976
|
|
|
$this->_bean->retrieve($id);//!$bean_is_lhs || empty($related_id) ? $id : $related_id); |
977
|
|
|
} |
978
|
|
|
$this->_bean->call_custom_logic('after_relationship_delete', $custom_logic_arguments); |
979
|
|
|
//NOW THE REVERSE WAY SINCE A RELATIONSHIP TAKES TWO |
980
|
|
|
global $beanList; |
981
|
|
|
if ( isset($beanList[$custom_logic_arguments['related_module']]) ) { |
982
|
|
|
$class = $beanList[$custom_logic_arguments['related_module']]; |
983
|
|
|
if ( !empty($class) ) { |
984
|
|
|
$rbean = new $class(); |
985
|
|
|
$rbean->retrieve(empty($related_id) ? $id : $related_id); |
986
|
|
|
$rbean->call_custom_logic('after_relationship_delete', $custom_reverse_arguments); |
987
|
|
|
} |
988
|
|
|
} |
989
|
|
|
} |
990
|
|
|
|
991
|
|
|
function relationship_exists($table_name, $join_key_values) { |
992
|
|
|
|
993
|
|
|
//find the key values for the table. |
994
|
|
|
$dup_keys=$this->_get_alternate_key_fields($table_name); |
995
|
|
|
if (empty($dup_keys)) { |
996
|
|
|
$GLOBALS['log']->debug("No alternate key define, skipping duplicate check.."); |
997
|
|
|
return false; |
998
|
|
|
} |
999
|
|
|
|
1000
|
|
|
$delimiter=''; |
1001
|
|
|
$this->_duplicate_where=' WHERE '; |
1002
|
|
|
foreach ($dup_keys as $field) { |
1003
|
|
|
//look for key in $join_key_values, if found add to filter criteria else abort duplicate checking. |
1004
|
|
|
if (isset($join_key_values[$field])) { |
1005
|
|
|
|
1006
|
|
|
$this->_duplicate_where .= $delimiter.' '.$field."='".$join_key_values[$field]."'"; |
1007
|
|
|
$delimiter='AND'; |
1008
|
|
|
} else { |
1009
|
|
|
$GLOBALS['log']->error('Duplicate checking aborted, Please supply a value for this column '.$field); |
1010
|
|
|
return false; |
1011
|
|
|
} |
1012
|
|
|
} |
1013
|
|
|
//add deleted check. |
1014
|
|
|
$this->_duplicate_where .= $delimiter.' deleted=0'; |
1015
|
|
|
|
1016
|
|
|
$query='SELECT id FROM '.$table_name.$this->_duplicate_where; |
1017
|
|
|
|
1018
|
|
|
$GLOBALS['log']->debug("relationship_exists query(".$query.')'); |
1019
|
|
|
|
1020
|
|
|
$result=$this->_db->query($query, true); |
1021
|
|
|
$row = $this->_db->fetchByAssoc($result); |
1022
|
|
|
|
1023
|
|
|
if ($row == null) { |
1024
|
|
|
return false; |
1025
|
|
|
} |
1026
|
|
|
else { |
1027
|
|
|
$this->_duplicate_key=$row['id']; |
1028
|
|
|
return true; |
1029
|
|
|
} |
1030
|
|
|
} |
1031
|
|
|
|
1032
|
|
|
/* returns array of keys for duplicate checking, first check for an index of type alternate_key, if not found searches for |
1033
|
|
|
* primary key. |
1034
|
|
|
* |
1035
|
|
|
*/ |
1036
|
|
|
function _get_alternate_key_fields($table_name) { |
1037
|
|
|
$alternateKey=null; |
1038
|
|
|
$indices=Link::_get_link_table_definition($table_name,'indices'); |
1039
|
|
|
if (!empty($indices)) { |
1040
|
|
|
foreach ($indices as $index) { |
1041
|
|
|
if ( isset($index['type']) && $index['type'] == 'alternate_key' ) { |
1042
|
|
|
return $index['fields']; |
1043
|
|
|
} |
1044
|
|
|
} |
1045
|
|
|
} |
1046
|
|
|
$relationships=Link::_get_link_table_definition($table_name,'relationships'); |
1047
|
|
|
if (!empty($relationships)) {//bug 32623, when the relationship is built in old version, there is no alternate_key. we have to use join_key_lhs and join_key_lhs. |
1048
|
|
|
if(!empty($relationships[$this->_relationship_name]) && !empty($relationships[$this->_relationship_name]['join_key_lhs']) && !empty($relationships[$this->_relationship_name]['join_key_rhs'])) { |
1049
|
|
|
return array($relationships[$this->_relationship_name]['join_key_lhs'], $relationships[$this->_relationship_name]['join_key_rhs']); |
1050
|
|
|
} |
1051
|
|
|
} |
1052
|
|
|
} |
1053
|
|
|
|
1054
|
|
|
/* |
1055
|
|
|
*/ |
1056
|
|
|
function _get_link_table_definition($table_name,$def_name) { |
1057
|
|
|
global $dictionary; |
1058
|
|
|
|
1059
|
|
|
include_once('modules/TableDictionary.php'); |
1060
|
|
|
// first check to see if already loaded - assumes hasn't changed in the meantime |
1061
|
|
|
if (isset($dictionary[$table_name][$def_name])) |
1062
|
|
|
{ |
1063
|
|
|
return $dictionary[$table_name][$def_name]; |
1064
|
|
|
} |
1065
|
|
|
else { |
1066
|
|
|
if (isset($dictionary[$this->_relationship_name][$def_name])) { |
1067
|
|
|
return ($dictionary[$this->_relationship_name][$def_name]); |
1068
|
|
|
} |
1069
|
|
|
// custom metadata is found in custom/metadata (naturally) and the naming follows the convention $relationship_name_c, and $relationship_name = $table_name$locations = array( 'metadata/' , 'custom/metadata/' ) ; |
1070
|
|
|
$relationshipName = preg_replace( '/_c$/' , '' , $table_name ) ; |
1071
|
|
|
|
1072
|
|
|
$locations = array ( 'metadata/' , 'custom/metadata/' ) ; |
1073
|
|
|
|
1074
|
|
|
foreach ( $locations as $basepath ) |
1075
|
|
|
{ |
1076
|
|
|
$path = $basepath . $relationshipName . 'MetaData.php' ; |
1077
|
|
|
|
1078
|
|
|
if (file_exists($path)) |
1079
|
|
|
{ |
1080
|
|
|
include($path); |
1081
|
|
|
if (isset($dictionary[$relationshipName][$def_name])) { |
1082
|
|
|
return $dictionary[$relationshipName][$def_name]; |
1083
|
|
|
} |
1084
|
|
|
} |
1085
|
|
|
} |
1086
|
|
|
// couldn't find the metadata for the table in either the standard or custom locations |
1087
|
|
|
$GLOBALS['log']->debug('Error fetching field defs for join table '.$table_name); |
1088
|
|
|
|
1089
|
|
|
return null; |
1090
|
|
|
} |
1091
|
|
|
|
1092
|
|
|
|
1093
|
|
|
|
1094
|
|
|
} |
1095
|
|
|
/* |
1096
|
|
|
* Return the name of the role field for the passed many to many table. |
1097
|
|
|
* if there is no role filed : return false |
1098
|
|
|
*/ |
1099
|
|
|
function _get_link_table_role_field($table_name) { |
1100
|
|
|
$varDefs = $this->_get_link_table_definition($table_name, 'fields'); |
1101
|
|
|
$role_field = false; |
1102
|
|
|
if(!empty($varDefs)){ |
1103
|
|
|
$role_field = ''; |
1104
|
|
|
foreach($varDefs as $v){ |
1105
|
|
|
if(strpos($v['name'], '_role') !== false){ |
1106
|
|
|
$role_field = $v['name']; |
1107
|
|
|
} |
1108
|
|
|
} |
1109
|
|
|
} |
1110
|
|
|
return $role_field; |
1111
|
|
|
} |
1112
|
|
|
|
1113
|
|
|
|
1114
|
|
|
} |
1115
|
|
|
?> |
1116
|
|
|
|
This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.
The variable may have been renamed without also renaming all references.