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