Issues (4069)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

data/Link2.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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
/*********************************************************************************
44
45
* Description:  Represents a relationship from a single bean's perspective.
46
* Does not actively do work but is used by sugarbean to manipulate relationships.
47
* Work is deferred to the relationship classes.
48
 *
49
* Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
50
* All Rights Reserved.
51
* Contributor(s): ______________________________________..
52
********************************************************************************/
53 1
global $dictionary;
54 1
require_once("data/Relationships/RelationshipFactory.php");
55
56
/**
57
 * Represents a relationship from a single beans perspective.
58
 * @api
59
 */
60
class Link2 {
61
62
    protected $relationship; //relationship object this link is tied to.
63
    protected $focus;  //SugarBean this link uses as the context for its calls.
64
    protected $def;  //Field def for this link
65
    protected $name;  //Field name for this link
66
    protected $beans;  //beans on the other side of the link
67
    protected $rows;   //any additional fields on the relationship
68
    protected $loaded; //true if this link has been loaded from the database
69
    protected $relationship_fields = array();
70
    //Used to store unsaved beans on this relationship that will be combined with the ones pulled from the DB if getBeans() is called.
71
    protected $tempBeans = array();
72
73
    /**
74
     * @param  $linkName String name of a link field in the module's vardefs
75
     * @param  $bean SugarBean focus bean for this link (one half of a relationship)
76
     * @param  $linkDef Array Optional vardef for the link in case it can't be found in the passed in bean for the global dictionary
77
     * @return void
78
     *
79
     */
80 126
    function __construct($linkName, $bean, $linkDef = false){
81 126
        $this->focus = $bean;
82
        //Try to load the link vardef from the beans field defs. Otherwise start searching
83 126
        if (empty($bean->field_defs) || empty($bean->field_defs[$linkName]) || empty($bean->field_defs[$linkName]['relationship']))
84
        {
85
            if (empty($linkDef))
86
            {
87
                //Assume $linkName is really relationship_name, and find the link name with the vardef manager
88
                $this->def = VardefManager::getLinkFieldForRelationship($bean->module_dir, $bean->object_name, $linkName);
89
            }
90
            else {
91
                $this->def = $linkDef;
92
            }
93
            //Check if multiple links were found for a given relationship
94
            if (is_array($this->def) && !isset($this->def['name']))
95
            {
96
                //More than one link found, we need to figure out if we are currently on the LHS or RHS
97
                //default to lhs for now
98
                if (isset($this->def[0]['side']) && $this->def[0]['side'] == 'left')
99
                {
100
                    $this->def = $this->def[0];
101
                }
102
                else if (isset($this->def[1]['side']) && $this->def[1]['side'] == 'left')
103
                {
104
                    $this->def = $this->def[1];
105
                }
106
                else {
107
                    $this->def = $this->def[0];
108
                }
109
            }
110
            if (empty($this->def['name']))
111
            {
112
                $GLOBALS['log']->fatal("failed to find link for $linkName");
113
                return false;
114
            }
115
116
            $this->name = $this->def['name'];
117
        }
118
        else {
119
            //Linkdef was found in the bean (this is the normal expectation)
120 126
            $this->def = $bean->field_defs[$linkName];
121 126
            $this->name = $linkName;
122
        }
123
        //Instantiate the relationship for this link.
124 126
        $this->relationship = SugarRelationshipFactory::getInstance()->getRelationship($this->def['relationship']);
125
126
        // Fix to restore functionality from Link.php that needs to be rewritten but for now this will do.
127 126
        $this->relationship_fields = (!empty($this->def['rel_fields']))?$this->def['rel_fields']: array();
128
129 126
        if (!$this->loadedSuccesfully())
130
        {
131 3
            $GLOBALS['log']->fatal("{$this->name} for {$this->def['relationship']} failed to load\n");
132
        }
133
        //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.
134
        //the property values can be altered again before any requests are made.
135 126
        if (!empty($this->def) && is_array($this->def)) {
136 126
            if ( isset($this->def['ignore_role']) ) {
137 1
                if ($this->def['ignore_role']) {
138 1
                    $this->ignore_role_filter=true;
139 1
                    $this->add_distinct=true;
140
                }
141
            }
142
        }
143 126
    }
144
145
    /**
146
     * Returns false if no relationship was found for this link
147
     * @return bool
148
     */
149 126
    public function loadedSuccesfully()
150
    {
151 126
        return !empty($this->relationship);
152
    }
153
154
    /**
155
     *  Forces the link to load the relationship rows.
156
     * Will be called internally when the $rows property is accessed or get() is called
157
     * @return void
158
     */
159 95
    public function load($params = array())
160
    {
161 95
        $data = $this->query($params);
162 95
        $this->rows = $data['rows'];
163 95
        $this->beans = null;
164 95
        $this->loaded = true;
165 95
    }
166
167
    /**
168
     *  Perform a query on this relationship.
169
     *
170
     * @param array $params An array that can contain the following parameters:<br/>
171
     * <ul><li><b>where:</b> An array with 3 key/value pairs.
172
     *  lhs_field: The name of the field to check search.
173
     *  operator: The operator to use in the search.
174
     *  rhs_value: The value to search for.<br/>
175
     *  Example:<pre>
176
     *  'where' => array(
177
             'lhs_field' => 'source',
178
             'operator' => '=',
179
             'rhs_value' => 'external'
180
         )</pre>
181
     *  </li>
182
     * <li><b>limit:</b> The maximum number of rows</li>
183
     * <li><b>deleted:</b> If deleted is set to 1, only deleted records related to the current record will be returned.</li></ul>
184
     */
185 95
    public function query($params){
186 95
        return $this->relationship->load($this, $params);
187
    }
188
189
    /**
190
     * @return array ids of records related through this link
191
     */
192 59
    public function get($role = false) {
193 59
        if (!$this->loaded)
194 59
            $this->load();
195
196 59
        return array_keys($this->rows);
197
    }
198
199
    /**
200
     * @deprecated
201
     *
202
     * @return string name of table for the relationship of this link
203
     */
204
    public function getRelatedTableName() {
205
        return BeanFactory::getBean($this->getRelatedModuleName())->table_name;
206
    }
207
208
    /**
209
     * @return string the name of the module on the other side of this link
210
     */
211 73
    public function getRelatedModuleName() {
212 73
        if (!$this->relationship) return false;
213
214 73
        if ($this->getSide() == REL_LHS) {
215 40
            return $this->relationship->getRHSModule();
216
        } else {
217 61
            return $this->relationship->getLHSModule();
218
        }
219
    }
220
221
    /**
222
     * @return string the name of the link field used on the other side of the rel
223
     */
224
    public function getRelatedModuleLinkName() {
225
        if (!$this->relationship) return false;
226
227
        if ($this->getSide() == REL_LHS) {
228
            return $this->relationship->getRHSLink();
229
        } else {
230
            return $this->relationship->getLHSLink();
231
        }
232
    }
233
234
    /**
235
     *
236
     * @return string "many" if multiple records can be related through this link
237
     * or "one" if at most, one record can be related.
238
     */
239
    public function getType()
240
    {
241
        switch ($this->relationship->type)
242
        {
243
            case REL_MANY_MANY:
244
                return "many";
245
            case REL_ONE_ONE:
246
                return "one";
247
            case REL_ONE_MANY:
248
                return $this->getSide() == REL_LHS ? "many" : "one";
249
        }
250
        return "many";
251
    }
252
253
    /**
254
     * @return SugarBean The parent Bean this link references
255
     */
256 104
    public function getFocus()
257
    {
258 104
        return $this->focus;
259
    }
260
261
    /**
262
     * @deprecated
263
     * @return list of fields that exist only on the relationship
264
     */
265
    public function getRelatedFields(){
266
        return $this->relationship_fields;
267
    }
268
269
    /**
270
     * @param $name
271
     * @return The value for the relationship field $name
272
     */
273
    public function getRelatedField($name){
274
        if (!empty($this->relationship_fields) && !empty($this->relationship_fields[$name]))
275
            return $this->relationship_fields[$name];
276
        else
277
            return null; //For now return null. Later try the relationship object directly.
278
    }
279
280
    /**
281
     * @return SugarRelationship the relationship object this link references
282
     */
283 1
    public function getRelationshipObject() {
284 1
       return $this->relationship;
285
    }
286
287
    /**
288
     * @return string "LHS" or "RHS" depending on the side of the relationship this link represents
289
     */
290 126
    public function getSide() {
291
        //First try the relationship
292 126
        if ($this->relationship->getLHSLink() == $this->name &&
293 126
            ($this->relationship->getLHSModule() == $this->focus->module_name)
294
        ){
295 48
            return REL_LHS;
296
        }
297
298 107
        if ($this->relationship->getRHSLink() == $this->name &&
299 107
            ($this->relationship->getRHSModule() == $this->focus->module_name)
300
        ){
301 103
            return REL_RHS;
302
        }
303
304
        //Next try the vardef
305 8
        if (!empty($this->def['side']))
306
        {
307 2
            if ((strtolower($this->def['side']) == 'left' || $this->def['side'] == REL_LHS)
308
                //Some relationships make have left in the vardef erroneously if generated by module builder
309 2
                && (empty($this->relationship->def['join_key_lhs']) || $this->name != $this->relationship->def['join_key_lhs']))
310
            {
311
                return REL_LHS ;
312
            }
313
            else {
314 2
                return REL_RHS;
315
            }
316
        }
317
        //Next try using the id_name and relationship join keys
318 6
        else if (!empty($this->def['id_name']))
319
        {
320 1
            if (isset($this->relationship->def['join_key_lhs']) && $this->def['id_name'] == $this->relationship->def['join_key_lhs'])
321
                return REL_RHS;
322 1
            else if (isset($this->relationship->def['join_key_rhs']) && $this->def['id_name'] == $this->relationship->def['join_key_rhs'])
323
                return REL_LHS;
324
        }
325
326 6
        $GLOBALS['log']->error("Unable to get proper side for link {$this->name}");
327 6
    }
328
329
    /**
330
     * @return bool true if LHSModule == RHSModule
331
     */
332
    protected function is_self_relationship() {
333
        return $this->relationship->isSelfReferencing();
334
    }
335
336
    /**
337
     * @return bool true if this link represents a relationship where the parent could be one of multiple modules. (ex. Activities parent)
338
     */
339
    public function isParentRelationship(){
340
        return $this->relationship->isParentRelationship();
341
    }
342
343
    /**
344
     * @param $params array of parameters. Possible parameters include:
345
     * 'join_table_link_alias': alias the relationship join table in the query (for M2M relationships),
346
     * 'join_table_alias': alias for the final table to be joined against (usually a module main table)
347
     * @param bool $return_array if true the query is returned as a array broken up into
348
     * select, join, where, type, rel_key, and joined_tables
349
     * @return string/array join query for this link
350
     */
351 41
    function getJoin($params, $return_array =false)
352
    {
353 41
        return $this->relationship->getJoin($this, $params, $return_array);
354
    }
355
356
    /**
357
     * @param array $params optional parameters. Possible Values;
358
     * 'return_as_array': returns the query broken into
359
     * @return String/Array query to grab just ids for this relationship
360
     */
361 5
    function getQuery($params = array())
362
    {
363 5
        return $this->relationship->getQuery($this, $params);
364
    }
365
366
    /**
367
     * This function is similair getJoin except for M2m relationships it won't join agaist the final table.
368
     * Its used to retrieve the ID of the related beans only
369
     * @param $params array of parameters. Possible parameters include:
370
     * 'return_as_array': returns the query broken into
371
     * @param bool $return_array same as passing 'return_as_array' into parameters
372
     * @return string/array query to use when joining for subpanels
373
     */
374
    public function getSubpanelQuery($params = array(), $return_array = false)
375
    {
376
        if (!empty($this->def['ignore_role']))
377
            $params['ignore_role'] = true;
378
        return $this->relationship->getSubpanelQuery($this, $params, $return_array);
379
    }
380
381
    /**
382
     * Use with caution as if you have a large list of beans in the relationship,
383
     * it can cause the app to timeout or run out of memory.
384
     *
385
     * @param array $params An array that can contain the following parameters:<br/>
386
     * <ul><li><b>where:</b> An array with 3 key/value pairs.
387
     *  lhs_field: The name of the field to check search.
388
     *  operator: The operator to use in the search.
389
     *  rhs_value: The value to search for.<br/>
390
     *  Example:<pre>
391
     *  'where' => array(
392
             'lhs_field' => 'source',
393
             'operator' => '=',
394
             'rhs_value' => 'external'
395
         )</pre>
396
     *  </li>
397
     * <li><b>limit:</b> The maximum number of beans to load.</li>
398
     * <li><b>deleted:</b> If deleted is set to 1, only deleted records related to the current record will be returned.</li></ul>
399
     * @return array of SugarBeans related through this link.
400
     */
401 45
    function getBeans($params = array()) {
402
        //Some depricated code attempts to pass in the old format to getBeans with a large number of useless paramters.
403
        //reset the parameters if they are not in the new array format.
404 45
    	if (!is_array($params))
405
            $params = array();
406
407 45
        if (!$this->loaded && empty($params)) {
408 45
            $this->load();
409
        }
410
411 45
        $rows = $this->rows;
412
        //If params is set, we are doing a query rather than a complete load of the relationship
413 45
        if (!empty($params)) {
414
            $data = $this->query($params);
415
            $rows = $data['rows'];
416
        }
417
418 45
        $result = array();
419 45
        if(!$this->beansAreLoaded() || !empty($params))
420
        {
421 45
            if (!is_array($this->beans))
422 45
                $this->beans = array();
423
424 45
            $rel_module = $this->getRelatedModuleName();
425
426
            //First swap in the temp loaded beans, only if we are doing a complete load (no params)
427 45
            if (empty($params)) {
428 45
                $result = $this->tempBeans;
429 45
                $this->tempBeans = array();
430
            }
431
432
            //now load from the rows
433 45
            foreach ($rows as $id => $vals)
434
            {
435 20
                if (empty($this->beans[$id]))
436
                {
437 20
                    $tmpBean = BeanFactory::getBean($rel_module, $id);
438 20
                    if($tmpBean !== FALSE)
439 20
                        $result[$id] = $tmpBean;
440
                } else {
441 20
                    $result[$id] = $this->beans[$id];
442
                }
443
            }
444
445
            //If we did a compelte load, cache the result in $this->beans
446 45
            if (empty($params))
447 45
                $this->beans = $result;
448
        } else {
449 7
            $result = $this->beans;
450
        }
451
452 45
        return $result;
453
    }
454
455
    /**
456
     * @return bool true if this link has initialized its related beans.
457
     */
458 45
    public function beansAreLoaded() {
459 45
        return is_array($this->beans);
460
    }
461
462
    /**
463
     * use this function to create link between 2 objects
464
     * 1:1 will be treated like 1 to many.
465
     *
466
     * the function also allows for setting of values for additional field in the table being
467
     * updated to save the relationship, in case of many-to-many relationships this would be the join table.
468
     *
469
     * @param array $rel_keys array of ids or SugarBean objects. If you have the bean in memory, pass it in.
470
     * @param array $additional_values the values should be passed as key value pairs with column name as the key name and column value as key value.
471
     *
472
     * @return boolean|array          Return true if all relationships were added.  Return an array with the failed keys if any of them failed.
473
     */
474 6
    function add($rel_keys,$additional_values=array()) {
475 6
        if (!is_array($rel_keys))
476 6
            $rel_keys = array($rel_keys);
477
478 6
        $failures = array();
479
480 6
        foreach($rel_keys as $key)
481
        {
482
            //We must use beans for LogicHooks and other business logic to fire correctly
483 6
            if (!($key instanceof SugarBean)) {
484 6
                $key = $this->getRelatedBean($key);
485 6
                if (!($key instanceof SugarBean)) {
486 4
                    $GLOBALS['log']->error("Unable to load related bean by id");
487 4
                    return false;
488
                }
489
            }
490
491 2
            if(empty($key->id) || empty($this->focus->id))
492 2
                return false;
493
494
            if ($this->getSide() == REL_LHS) {
495
                $success = $this->relationship->add($this->focus, $key, $additional_values);
496
            }
497
            else {
498
                $success = $this->relationship->add($key, $this->focus, $additional_values);
499
            }
500
501
            if($success == false) {
502
                $failures[] = $key->id;
503
            }
504
        }
505
506
        if(!empty($failures)) {
507
            return $failures;
508
        }
509
510
        return true;
511
    }
512
513
514
515
    /**
516
     * Marks the relationship delted for this given record pair.
517
     * @param $id id of the Parent/Focus SugarBean
518
     * @param string $related_id id or SugarBean to unrelate. Pass a SugarBean if you have it.
519
     * @return boolean          true if delete was successful or false if it was not
520
     */
521 38
    function delete($id, $related_id='') {
522 38
        if (empty($this->focus->id))
523 7
            $this->focus = BeanFactory::getBean($this->focus->module_name, $id);
524 38
        if (!empty($related_id))
525
        {
526
            if (!($related_id instanceof SugarBean)) {
527
                $related_id = $this->getRelatedBean($related_id);
528
            }
529
            if ($this->getSide() == REL_LHS) {
530
                return $this->relationship->remove($this->focus, $related_id);
531
            }
532
            else {
533
                return $this->relationship->remove($related_id, $this->focus);
534
            }
535
        }
536
        else
537
        {
538 38
            return $this->relationship->removeAll($this);
539
        }
540
    }
541
542
    /**
543
     * Returns a SugarBean with the given ID from the related module.
544
     * @param bool $id id of related record to retrieve
545
     * @return SugarBean
546
     */
547 6
    protected function getRelatedBean($id = false)
548
    {
549 6
        $params = array('encode' => true, 'deleted' => true);
550 6
        return BeanFactory::getBean($this->getRelatedModuleName(), $id, $params);
551
    }
552
553 5
    public function &__get($name)
554
    {
555
        switch($name)
556
        {
557 5
            case "relationship_type":
558 5
                return $this->relationship->type;
559
            case "_relationship":
560
                return $this->relationship;
561
            case "beans":
562
                if (!is_array($this->beans))
563
                    $this->getBeans();
564
                return $this->beans;
565
            case "rows":
566
                if (!is_array($this->rows))
567
                    $this->load();
568
                return $this->rows;
569
        }
570
        return $this->$name;
571
    }
572
573 2
    public function __set($name, $val)
574
    {
575 2
        if($name == "beans")
576
            $this->beans = $val;
577
578 2
    }
579
580
    /**
581
     * Add a bean object to the list of beans currently loaded to this relationship.
582
     * This for the most part should not need to be called except by the relatipnship implementation classes.
583
     * @param SugarBean $bean
584
     * @return void
585
     */
586
    public function addBean($bean)
587
    {
588
        if (!is_array($this->beans))
589
        {
590
            $this->tempBeans[$bean->id] = $bean;
591
        }
592
        else {
593
            $this->beans[$bean->id] = $bean;
594
        }
595
596
    }
597
598
    /**
599
     * Remove a bean object from the list of beans currently loaded to this relationship.
600
     * This for the most part should not need to be called except by the relatipnship implementation classes.
601
     *
602
     * @param SugarBean $bean
603
     * @return void
604
     */
605
    public function removeBean($bean)
606
    {
607
        if (!is_array($this->beans) && isset($this->tempBeans[$bean->id]))
608
        {
609
            unset($this->tempBeans[$bean->id]);
610
        } else {
611
            unset($this->beans[$bean->id]);
612
            unset($this->rows[$bean->id]);
613
        }
614
    }
615
616
617
    /**
618
     * Directly queries the databse for set of values. The relationship classes and not link should handle this.
619
     * @deprecated
620
     * @param $table_name string relationship table
621
     * @param $join_key_values array of key=>values to identify this relationship by
622
     * @return bool true if the given join key set exists in the relationship table
623
     */
624 1
    public function relationship_exists($table_name, $join_key_values) {
625
626
        //find the key values for the table.
627 1
        $dup_keys=$this->_get_alternate_key_fields($table_name);
628 1
        if (empty($dup_keys)) {
629
            $GLOBALS['log']->debug("No alternate key define, skipping duplicate check..");
630
            return false;
631
        }
632
633 1
        $delimiter='';
634 1
        $this->_duplicate_where=' WHERE ';
635 1
        foreach ($dup_keys as $field) {
636
            //look for key in  $join_key_values, if found add to filter criteria else abort duplicate checking.
637 1
            if (isset($join_key_values[$field])) {
638
639
                $this->_duplicate_where .= $delimiter.' '.$field."='".$join_key_values[$field]."'";
640
                $delimiter='AND';
641
            } else {
642 1
                $GLOBALS['log']->error('Duplicate checking aborted, Please supply a value for this column '.$field);
643 1
                return false;
644
            }
645
        }
646
        //add deleted check.
647
        $this->_duplicate_where .= $delimiter.' deleted=0';
648
649
        $query='SELECT id FROM '.$table_name.$this->_duplicate_where;
650
651
        $GLOBALS['log']->debug("relationship_exists query(".$query.')');
652
653
        $result=$this->_db->query($query, true);
654
        $row = $this->_db->fetchByAssoc($result);
655
656
        if ($row == null) {
657
            return false;
658
        }
659
        else {
660
            $this->_duplicate_key=$row['id'];
661
            return true;
662
        }
663
    }
664
665
    //Below are functions not used directly and exist for backwards compatibility with customizations, will be removed in a later version
666
667
    /* returns array of keys for duplicate checking, first check for an index of type alternate_key, if not found searches for
668
     * primary key.
669
     *
670
     */
671 1
    public function _get_alternate_key_fields($table_name) {
672 1
        $indices=Link::_get_link_table_definition($table_name,'indices');
673 1
        if (!empty($indices)) {
674
            foreach ($indices as $index) {
675
                if ( isset($index['type']) && $index['type'] == 'alternate_key' ) {
676
                    return $index['fields'];
677
                }
678
            }
679
        }
680
        //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.
681 1
        $relDef = $this->relationship->def;
682 1
        if (!empty($relDef['join_key_lhs']) && !empty($relDef['join_key_rhs']))
683 1
            return array($relDef['join_key_lhs'], $relDef['join_key_rhs']);
684
    }
685
686
    /**
687
     * @deprecated
688
     * Gets the vardef for the relationship of this link.
689
     */
690
    public function _get_link_table_definition($table_name, $def_name) {
691
692
        if (isset($this->relationship->def[$def_name]))
693
            return $this->relationship->def[$def_name];
694
695
        return null;
696
    }
697
698
    /**
699
     * @deprecated
700
     * Return the name of the role field for the passed many to many table.
701
     * if there is no role filed : return false
702
     * @param $table_name name of relationship table to inspect
703
     * @return bool|string
704
     */
705
    public function _get_link_table_role_field($table_name) {
706
        $varDefs = $this->_get_link_table_definition($table_name, 'fields');
0 ignored issues
show
Deprecated Code introduced by
The method Link2::_get_link_table_definition() has been deprecated with message: Gets the vardef for the relationship of this link.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
707
        $role_field = false;
708
        if(!empty($varDefs)){
709
            $role_field = '';
710
            foreach($varDefs as $v){
711
                if(strpos($v['name'], '_role') !== false){
712
                    $role_field = $v['name'];
713
                }
714
            }
715
        }
716
        return $role_field;
717
    }
718
719
    /**
720
     * @deprecated
721
     *
722
     * @return boolean returns true if this link is LHS
723
     */
724
    public function _get_bean_position()
725
    {
726
        return $this->getSide() == REL_LHS;
727
    }
728
}
729