|
1
|
|
|
<?php |
|
2
|
1 |
|
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 __construct($_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
|
1 |
|
function _get_link_table_definition($table_name,$def_name) { |
|
1056
|
1 |
|
global $dictionary; |
|
1057
|
|
|
|
|
1058
|
|
|
/* |
|
1059
|
|
|
* If this method is called statically will throw FATAL error on php7 because of the $this usage |
|
1060
|
|
|
*/ |
|
1061
|
1 |
|
$staticContext = !isset($this); |
|
1062
|
1 |
|
if($staticContext) { |
|
1063
|
1 |
|
return null; |
|
1064
|
|
|
} |
|
1065
|
|
|
|
|
1066
|
|
|
include_once('modules/TableDictionary.php'); |
|
1067
|
|
|
// first check to see if already loaded - assumes hasn't changed in the meantime |
|
1068
|
|
|
if (isset($dictionary[$table_name][$def_name])) |
|
1069
|
|
|
{ |
|
1070
|
|
|
return $dictionary[$table_name][$def_name]; |
|
1071
|
|
|
} |
|
1072
|
|
|
else { |
|
1073
|
|
|
if (isset($dictionary[$this->_relationship_name][$def_name])) { |
|
1074
|
|
|
return ($dictionary[$this->_relationship_name][$def_name]); |
|
1075
|
|
|
} |
|
1076
|
|
|
// 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/' ) ; |
|
1077
|
|
|
$relationshipName = preg_replace( '/_c$/' , '' , $table_name ) ; |
|
1078
|
|
|
|
|
1079
|
|
|
$locations = array ( 'metadata/' , 'custom/metadata/' ) ; |
|
1080
|
|
|
|
|
1081
|
|
|
foreach ( $locations as $basepath ) |
|
1082
|
|
|
{ |
|
1083
|
|
|
$path = $basepath . $relationshipName . 'MetaData.php' ; |
|
1084
|
|
|
|
|
1085
|
|
|
if (file_exists($path)) |
|
1086
|
|
|
{ |
|
1087
|
|
|
include($path); |
|
1088
|
|
|
if (isset($dictionary[$relationshipName][$def_name])) { |
|
1089
|
|
|
return $dictionary[$relationshipName][$def_name]; |
|
1090
|
|
|
} |
|
1091
|
|
|
} |
|
1092
|
|
|
} |
|
1093
|
|
|
// couldn't find the metadata for the table in either the standard or custom locations |
|
1094
|
|
|
$GLOBALS['log']->debug('Error fetching field defs for join table '.$table_name); |
|
1095
|
|
|
|
|
1096
|
|
|
return null; |
|
1097
|
|
|
} |
|
1098
|
|
|
|
|
1099
|
|
|
|
|
1100
|
|
|
|
|
1101
|
|
|
} |
|
1102
|
|
|
/* |
|
1103
|
|
|
* Return the name of the role field for the passed many to many table. |
|
1104
|
|
|
* if there is no role filed : return false |
|
1105
|
|
|
*/ |
|
1106
|
|
|
function _get_link_table_role_field($table_name) { |
|
1107
|
|
|
$varDefs = $this->_get_link_table_definition($table_name, 'fields'); |
|
1108
|
|
|
$role_field = false; |
|
1109
|
|
|
if(!empty($varDefs)){ |
|
1110
|
|
|
$role_field = ''; |
|
1111
|
|
|
foreach($varDefs as $v){ |
|
1112
|
|
|
if(strpos($v['name'], '_role') !== false){ |
|
1113
|
|
|
$role_field = $v['name']; |
|
1114
|
|
|
} |
|
1115
|
|
|
} |
|
1116
|
|
|
} |
|
1117
|
|
|
return $role_field; |
|
1118
|
|
|
} |
|
1119
|
|
|
|
|
1120
|
|
|
|
|
1121
|
|
|
} |
|
1122
|
|
|
?> |
|
1123
|
|
|
|
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.