Passed
Push — scrutinizer-code-quality ( 09f5a1...c4c5fb )
by Adam
56:05 queued 14:08
created

ViewSugarFieldCollection   D

Complexity

Total Complexity 120

Size/Duplication

Total Lines 518
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 0%

Importance

Changes 3
Bugs 3 Features 1
Metric Value
c 3
b 3
f 1
dl 0
loc 518
ccs 0
cts 416
cp 0
rs 4.8717
wmc 120
lcom 1
cbo 2

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 17 2
A ViewSugarFieldCollection() 0 10 2
D setup() 0 42 10
D retrieve_values() 0 56 20
A process() 0 7 3
A process_detailview() 0 3 1
D process_editview() 0 106 29
A init_tpl() 0 20 4
A display() 0 14 3
A checkTemplate() 0 6 3
F createQuickSearchCode() 0 106 27
C createPopupCode() 0 27 7
D findTemplate() 0 40 9

How to fix   Complexity   

Complex Class

Complex classes like ViewSugarFieldCollection often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ViewSugarFieldCollection, and based on these observations, apply Extract Interface, too.

1
<?php
2
/*********************************************************************************
3
 * SugarCRM Community Edition is a customer relationship management program developed by
4
 * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
5
6
 * SuiteCRM is an extension to SugarCRM Community Edition developed by Salesagility Ltd.
7
 * Copyright (C) 2011 - 2014 Salesagility Ltd.
8
 *
9
 * This program is free software; you can redistribute it and/or modify it under
10
 * the terms of the GNU Affero General Public License version 3 as published by the
11
 * Free Software Foundation with the addition of the following permission added
12
 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
13
 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
14
 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
15
 *
16
 * This program is distributed in the hope that it will be useful, but WITHOUT
17
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18
 * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
19
 * details.
20
 *
21
 * You should have received a copy of the GNU Affero General Public License along with
22
 * this program; if not, see http://www.gnu.org/licenses or write to the Free
23
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24
 * 02110-1301 USA.
25
 *
26
 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
27
 * SW2-130, Cupertino, CA 95014, USA. or at email address [email protected].
28
 *
29
 * The interactive user interfaces in modified source and object code versions
30
 * of this program must display Appropriate Legal Notices, as required under
31
 * Section 5 of the GNU Affero General Public License version 3.
32
 *
33
 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
34
 * these Appropriate Legal Notices must retain the display of the "Powered by
35
 * SugarCRM" logo and "Supercharged by SuiteCRM" logo. If the display of the logos is not
36
 * reasonably feasible for  technical reasons, the Appropriate Legal Notices must
37
 * display the words  "Powered by SugarCRM" and "Supercharged by SuiteCRM".
38
 ********************************************************************************/
39
40
require_once('include/SugarFields/Fields/Collection/SugarFieldCollection.php');
41
42
43
class ViewSugarFieldCollection{
44
    var $ss; // Sugar Smarty Object
45
    var $bean;
46
    var $bean_id;
47
    var $name;
48
    var $value_name;
49
    var $displayParams; // DisplayParams for the collection field (defined in the metadata)
50
    var $vardef; // vardef of the collection field.
51
    var $related_module; // module name of the related module
52
    var $module_dir; // name of the module where the collection field is.
53
    var $numFields;
54
    var $json;
55
    var $tpl_path;
56
    var $extra_var;
57
    var $skipModuleQuickSearch = false;
58
    var $field_to_name_array; //mapping of fields for the return of the select popup
59
    var $showSelectButton = true;
60
    var $hideShowHideButton = false;
61
    var $action_type;
62
    var $form_name;
63
64
    function __construct($fill_data = true){
65
    	$this->json = getJSONobj();
66
    	if($fill_data){
67
	        $this->displayParams = $this->json->decode(html_entity_decode($_REQUEST['displayParams']));
68
	        $this->vardef = $this->json->decode(html_entity_decode($_REQUEST['vardef']));
69
	        $this->module_dir = $_REQUEST['module_dir'];
70
	        $this->action_type = $_REQUEST['action_type'];
71
	        $this->name = $this->vardef['name'];
72
	        $this->value_name = $this->name . '_values';
73
	        $this->numFields = 1;
74
	        $this->ss = new Sugar_Smarty();
75
	        $this->edit_tpl_path = $this->findTemplate('CollectionEditView');
76
	        $this->detail_tpl_path = $this->findTemplate('CollectionDetailView');
77
	        $this->extra_var = array();
78
	        $this->field_to_name_array = array();
79
    	}
80
    }
81
82
    /**
83
     * @deprecated deprecated since version 7.6, PHP4 Style Constructors are deprecated and will be remove in 7.8, please update your code, use __construct instead
84
     */
85
    function ViewSugarFieldCollection($fill_data = true){
86
        $deprecatedMessage = 'PHP4 Style Constructors are deprecated and will be remove in 7.8, please update your code';
87
        if(isset($GLOBALS['log'])) {
88
            $GLOBALS['log']->deprecated($deprecatedMessage);
89
        }
90
        else {
91
            trigger_error($deprecatedMessage, E_USER_DEPRECATED);
92
        }
93
        self::__construct($fill_data);
94
    }
95
96
    /*
97
     * Retrieve the related module and load the bean and the relationship
98
     * call retrieve values()
99
     */
100
    function setup(){
101
        if(!class_exists('Relationship')){
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
102
103
        }
104
        $rel = new Relationship();
105
        if(!empty($this->vardef['relationship'])){
106
        	$rel->retrieve_by_name($this->vardef['relationship']);
107
        }
108
        if($rel->relationship_type == 'many-to-many'){
109
            if($rel->lhs_module == $this->module_dir){
110
                $this->related_module = $rel->rhs_module;
111
                $module_dir = $rel->lhs_module;
112
            }else if($rel->rhs_module == $this->module_dir){
113
                $this->related_module = $rel->lhs_module;
114
                $module_dir = $rel->rhs_module;
115
            }else{
116
                die("this field has no relationships mapped with this module");
117
            }
118
            if($module_dir != $this->module_dir){
119
                die('These modules do not match : '. $this->module_dir . ' and ' . $module_dir);
120
            }
121
            if(isset($GLOBALS['beanList'][$this->module_dir])){
122
                $class = $GLOBALS['beanList'][$this->module_dir];
123
                if(file_exists($GLOBALS['beanFiles'][$class])){
124
                    $this->bean = loadBean($this->module_dir);
0 ignored issues
show
Deprecated Code introduced by
The function loadBean() has been deprecated with message: use SugarModule::loadBean() instead

This function has been deprecated. The supplier of the file has supplied an explanatory message.

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

Loading history...
125
                    $this->bean->retrieve($_REQUEST['bean_id']);
126
                    if($this->bean->load_relationship($this->vardef['name'])){
127
                        $this->retrieve_values();
128
                    }else{
129
                        die('failed to load the relationship');
130
                    }
131
                }else{
132
                    die('class file do not exist');
133
                }
134
            }else{
135
                die($this->module_dir . ' is not in the beanList.');
136
            }
137
        }
138
        else{
139
            die("the relationship is not a many-to-many");
140
        }
141
    }
142
    /*
143
     * Retrieve the values from the DB using the get method of the link class
144
     * Organize and save the value into the bean
145
     */
146
    function retrieve_values(){
147
        if(empty($this->bean->{$this->value_name}) && isset($this->bean->{$this->name})){
148
            $values = array();
149
            $values = $this->bean->{$this->name}->get(true);
150
            $role_field = $this->bean->{$this->name}->_get_link_table_role_field($this->bean->{$this->name}->_relationship_name);
151
            foreach($values as $v){
152
                $role = '';
153
                foreach($v as $kk=>$vv){
154
                    if($kk == $role_field){
155
                        $role=$vv;
156
                    }
157
                }
158
                if($role == 'primary'){
159
                    $primary_id = $v['id'];
160
                }else{
161
                    $secondary_ids[] = array('id'=>$v['id'], 'role'=>$role);
162
                }
163
            }
164
            $this->bean->{$this->value_name} = array('role_field'=>$role_field);
165
            if(isset($primary_id) || isset($secondary_ids)){
166
                if(!isset($primary_id)){
167
                    $primary_id = $secondary_ids[0]['id'];
168
                    unset($secondary_ids[0]);
169
                }
170
                if(isset($GLOBALS['beanList'][ $this->related_module])){
171
                    $class = $GLOBALS['beanList'][$this->related_module];
172
                    if(file_exists($GLOBALS['beanFiles'][$class])){
173
                        $mod = loadBean($this->module_dir);
0 ignored issues
show
Deprecated Code introduced by
The function loadBean() has been deprecated with message: use SugarModule::loadBean() instead

This function has been deprecated. The supplier of the file has supplied an explanatory message.

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

Loading history...
174
                        $mod->relDepth = $this->bean->relDepth + 1;
175
                        $mod->retrieve($primary_id);
176
                        if (isset($mod->name)) {
177
                            $this->bean->{$this->value_name}=array_merge($this->bean->{$this->value_name}, array('primary'=>array('id'=>$primary_id, 'name'=>$mod->name)));
178
                        }
179
                        $secondaries = array();
180
                        if(isset($secondary_ids)){
181
                            foreach($secondary_ids as $v){
182
                                if($mod->retrieve($v['id'])){
183
                                    if (isset($mod->name)){
184
                                        $secondaries['secondaries'][]=array('id'=>$v['id'], 'name'=>$mod->name);
185
                                    }
186
                                }
187
                            }
188
                        }
189
                        $this->bean->{$this->value_name}=array_merge($this->bean->{$this->value_name}, $secondaries);
190
                        if(isset($field['additionalFields'])){
0 ignored issues
show
Bug introduced by
The variable $field seems only to be defined at a later point. As such the call to isset() seems to always evaluate to false.

This check marks calls to isset(...) or empty(...) that are found before the variable itself is defined. These will always have the same result.

This is likely the result of code being shifted around. Consider removing these calls.

Loading history...
191
                            foreach($field['additionalFields'] as $field=>$to){
192
                                if(isset($mod->$field)){
193
                                    $this->bean->$to = $mod->$field;
194
                                }
195
                            }
196
                        }
197
                    }
198
                }
199
            }
200
        }
201
    }
202
    /*
203
     * redirect to the good process method.
204
     */
205
    function process(){
206
        if($this->action_type == 'editview'){
207
            $this->process_editview();
208
        }else if($this->action_type == 'detailview'){
209
            $this->process_detailview();
210
        }
211
    }
212
    function process_detailview(){
213
214
    }
215
    /*
216
     * Build the DisplayParams array
217
     */
218
    function process_editview(){
219
        if(isset($this->bean->{$this->value_name}['secondaries'])){
220
            $this->numFields=count($this->bean->{$this->value_name}['secondaries'])+1;
221
        }
222
        if(!isset($this->displayParams['readOnly'])) {
223
           $this->displayParams['readOnly'] = '';
224
        } else {
225
           $this->displayParams['readOnly'] = $this->displayParams['readOnly'] == false ? '' : 'READONLY';
226
        }
227
        // If there is extra field to show.
228
        if(isset($this->displayParams['collection_field_list'])){
229
230
            $relatedObject = BeanFactory::getObjectName($this->related_module);
231
            vardefmanager::loadVardef($this->related_module, $relatedObject);
232
            foreach($this->displayParams['collection_field_list'] as $k=>$v){
0 ignored issues
show
Bug introduced by
The expression $this->displayParams['collection_field_list'] of type string|null is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
233
                $javascript='';
234
                $collection_field_vardef = $GLOBALS['dictionary'][$relatedObject]['fields'][$v['name']];
235
236
                // For each extra field the params which are not displayParams will be consider as params to override the vardefs values.
237
                foreach($v as $k_override=>$v_override){
238
                    if($k_override != 'displayParams'){
239
                        $collection_field_vardef[$k_override] = $v_override;
240
                    }
241
                }
242
243
                // If relate field : enable quick search by creating the sqs_object array.
244
                if($collection_field_vardef['type'] == 'relate'){
245
                    require_once('include/TemplateHandler/TemplateHandler.php');
246
                    $tph = new TemplateHandler();
247
                    $javascript = $tph->createQuickSearchCode(array($collection_field_vardef['name']=>$collection_field_vardef), array($v), $this->form_name);
248
                    $javascript = str_replace('<script language="javascript">'."if(typeof sqs_objects == 'undefined'){var sqs_objects = new Array;}sqs_objects['{$collection_field_vardef['name']}']=","",$javascript);
249
                    $javascript = substr($javascript, 0, -10);//remove ";</script>"
250
                    $javascriptPHP = $this->json->decode($javascript);
251
                    foreach($javascriptPHP['populate_list'] as $kk=>$vv){
0 ignored issues
show
Bug introduced by
The expression $javascriptPHP['populate_list'] of type string is not traversable.
Loading history...
252
                        $javascriptPHP['populate_list'][$kk] .= "_" . $this->vardef['name'] . "_collection_extra_0";
253
                    }
254
                    foreach($javascriptPHP['required_list'] as $kk=>$vv){
0 ignored issues
show
Bug introduced by
The expression $javascriptPHP['required_list'] of type string is not traversable.
Loading history...
255
                        $javascriptPHP['required_list'][$kk] .= "_" . $this->vardef['name'] . "_collection_extra_0";
256
                    }
257
                    foreach($javascriptPHP['field_list'] as $kk=>$vv){
0 ignored issues
show
Bug introduced by
The expression $javascriptPHP['field_list'] of type string is not traversable.
Loading history...
258
                        if($vv == 'id'){
259
                            $javascriptPHP['populate_list'][$kk];
260
                        }
261
                    }
262
                    $javascript = $this->json->encode($javascriptPHP);
263
                    $javascript = "<script language='javascript'>if(typeof sqs_objects == 'undefined'){var sqs_objects = new Array;}sqs_objects['{$collection_field_vardef['name']}_" . $this->vardef['name'] . "_collection_extra_0']=".$javascript.';</script>';
264
                }
265
266
                $collection_field_vardef['name'] .= "_" . $this->vardef['name'] . "_collection_extra_0";
267
                if(isset($collection_field_vardef['id_name'])){
268
                    $collection_field_vardef['id_name'] .= "_" . $this->vardef['name'] . "_collection_extra_0";
269
                }
270
                if(isset($this->displayParams['allow_update']) && ($this->displayParams['allow_update'] === false || $this->displayParams['allow_update'] === 'false')){
271
                    $this->displayParams['allow_update']='false';
272
                    $v['displayParams']['field']['disabled']='';
273
                }else{
274
                    $this->displayParams['allow_update']='true';
275
                    if(!isset($v['displayParams'])){
276
                        $v['displayParams']=array();
277
                    }
278
                }
279
                    $viewtype='EditView';
280
                $name = $collection_field_vardef['name'];
281
                // Rearranging the array with name as key instaead of number. This is required for displaySmarty() to assign the good variable.
282
                $this->displayParams['collection_field_list'][$name]['vardefName'] = $this->displayParams['collection_field_list'][$k]['name'];
283
                $this->displayParams['collection_field_list'][$name]['name'] = $name;
284
                if($collection_field_vardef['type'] == 'relate'){
285
                    $this->displayParams['collection_field_list'][$name]['id_name'] = $collection_field_vardef['id_name'];
286
                    $this->displayParams['collection_field_list'][$name]['module'] = $collection_field_vardef['module'];
287
                }
288
                $this->displayParams['collection_field_list'][$name]['label'] = "{sugar_translate label='{$collection_field_vardef['vname']}' module='{$this->related_module}'}";//translate($collection_field_vardef['vname'], $this->related_module);
289
                $this->displayParams['collection_field_list'][$name]['field'] = $sfh->displaySmarty('displayParams.collection_field_list', $collection_field_vardef, $viewtype, $v['displayParams'], 1);
290
                $this->displayParams['collection_field_list'][$name]['field'] .= '{literal}'.$javascript;
291
            // Handle update_field array ONCHANGE
292
                $this->displayParams['collection_field_list'][$name]['field'] .= <<<FRA
293
                <script language='javascript'>
294
                    var oldonchange = '';
295
                    if(typeof(document.getElementById('{$collection_field_vardef['name']}').attributes.onchange) != 'undefined')
296
                    {
297
                        oldonchange=document.getElementById('{$collection_field_vardef['name']}').attributes.onchange.value;
298
                    }
299
FRA;
300
                $this->displayParams['collection_field_list'][$name]['field'] .= "eval(\"document.getElementById('{$collection_field_vardef['name']}').onchange = function onchange(event){collection['{$this->vardef['name']}'].update_fields.{$collection_field_vardef['name']}=true;";
301
                if($collection_field_vardef['type'] == 'relate'){
302
                    // If relate add the ID field to the array
303
                    $this->displayParams['collection_field_list'][$name]['field'] .= "collection['{$this->vardef['name']}'].update_fields.{$collection_field_vardef['id_name']}=true;";
304
                }
305
                $this->displayParams['collection_field_list'][$name]['field'] .= "document.getElementById('update_fields_{$this->vardef['name']}_collection').value = YAHOO.lang.JSON.stringify(collection['{$this->vardef['name']}'].update_fields);\" + oldonchange + \"};\");</script>{/literal}";
306
                //we need to get rid of the old value;
307
                unset($this->displayParams['collection_field_list'][$k]);
308
            }
309
        }
310
        if(!isset($this->displayParams['class'])) $this->displayParams['class']='';
311
        if(isset($this->displayParams['allow_new']) && ($this->displayParams['allow_new'] === false || $this->displayParams['allow_new'] === 'false')){
312
            $this->displayParams['allow_new']='false';
313
            $this->displayParams['class']=str_replace('sqsNoAutofill','',$this->displayParams['class']);
314
        }else{
315
            $this->displayParams['allow_new']='true';
316
            $this->displayParams['class'].=' sqsNoAutofill';
317
        }
318
        if(isset($this->displayParams['new_on_update']) && ($this->displayParams['new_on_update'] !== false || $this->displayParams['new_on_update'] !== 'false' || $this->displayParams['new_on_update'] !== 'FALSE' || $this->displayParams['new_on_update'] !== '0')){
319
            $this->displayParams['new_on_update']='true';
320
        }else{
321
            $this->displayParams['new_on_update']='false';
322
        }
323
    }
324
325
    /*
326
     * Init the template with the variables
327
     */
328
    function init_tpl(){
329
        foreach($this->extra_var as $k=>$v){
330
            $this->ss->assign($k,$v);
331
        }
332
        if($this->action_type == 'editview'){
333
            $this->ss->assign('quickSearchCode',$this->createQuickSearchCode());
334
            $this->createPopupCode();// this code populate $this->displayParams with popupdata.
335
            $this->tpl_path = $this->edit_tpl_path;
336
        }else if($this->action_type == 'detailview'){
337
            $this->tpl_path = $this->detail_tpl_path;
338
        }
339
340
        $this->ss->assign('displayParams',$this->displayParams);
341
        $this->ss->assign('vardef',$this->vardef);
342
        $this->ss->assign('module',$this->related_module);
343
        $this->ss->assign('values',$this->bean->{$this->value_name});
344
        $this->ss->assign('showSelectButton',$this->showSelectButton);
345
        $this->ss->assign('hideShowHideButton',$this->hideShowHideButton);
346
        $this->ss->assign('APP',$GLOBALS['app_strings']);
347
    }
348
    /*
349
     * Display the collection field after retrieving the cached row.
350
     */
351
    function display(){
352
        $cacheRowFile = sugar_cached('modules/') . $this->module_dir .  '/collections/'. $this->name . '.tpl';
353
        if(!$this->checkTemplate($cacheRowFile)){
354
            $dir = dirname($cacheRowFile);
355
            if(!file_exists($dir)) {
356
357
               mkdir_recursive($dir, null, true);
0 ignored issues
show
Unused Code introduced by
The call to mkdir_recursive() has too many arguments starting with true.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
358
            }
359
            $cacheRow = $this->ss->fetch($this->findTemplate('CollectionEditViewRow'));
360
            file_put_contents($cacheRowFile, $cacheRow);
361
        }
362
        $this->ss->assign('cacheRowFile', $cacheRowFile);
363
        return $this->ss->fetch($this->tpl_path);
364
    }
365
    /*
366
     * Check if the template is cached
367
     * return a bool
368
     */
369
    function checkTemplate($cacheRowFile){
370
        if(inDeveloperMode() || !empty($_SESSION['developerMode'])){
371
            return false;
372
        }
373
        return file_exists($cacheRowFile);
374
    }
375
376
377
    /*
378
     * Create the quickSearch code for the collection field.
379
     * return the javascript code which define sqs_objects.
380
     */
381
    function createQuickSearchCode($returnAsJavascript = true){
382
        $sqs_objects = array();
383
        require_once('include/QuickSearchDefaults.php');
384
        $qsd = QuickSearchDefaults::getQuickSearchDefaults();
385
        $qsd->setFormName($this->form_name);
386
        for($i=0; $i<$this->numFields; $i++){
387
            $name1 = "{$this->form_name}_{$this->name}_collection_{$i}";
388
            if(!$this->skipModuleQuickSearch && preg_match('/(Campaigns|Teams|Users|Accounts)/si', $this->related_module, $matches)) {
389
                if($matches[0] == 'Users'){
390
                    $sqs_objects[$name1] = $qsd->getQSUser();
391
                } else if($matches[0] == 'Campaigns') {
392
                    $sqs_objects[$name1] = $qsd->getQSCampaigns();
393
394
                } else if($matches[0] == 'Users'){
395
                    $sqs_objects[$name1] = $qsd->getQSUser();
396
397
                } else if($matches[0] == 'Accounts') {
398
                    $nameKey = "{$this->name}_collection_{$i}";
399
                    $idKey = "id_{$this->name}_collection_{$i}";
400
401
                 //There are billingKey, shippingKey and additionalFields entries you can define in editviewdefs.php
402
                 //entry to allow quick search to autocomplete fields with a suffix value of the
403
                 //billing/shippingKey value (i.e. 'billingKey' => 'primary' in Contacts will populate
404
                 //primary_XXX fields with the Account's billing address values).
405
                 //addtionalFields are key/value pair of fields to fill from Accounts(key) to Contacts(value)
406
                    $billingKey = isset($this->displayParams['billingKey']) ? $this->displayParams['billingKey'] : null;
407
                    $shippingKey = isset($this->displayParams['shippingKey']) ? $this->displayParams['shippingKey'] : null;
408
                    $additionalFields = isset($this->displayParams['additionalFields']) ? $this->displayParams['additionalFields'] : null;
409
                    $sqs_objects[$name1] = $qsd->getQSAccount($nameKey, $idKey, $billingKey, $shippingKey, $additionalFields);
410
                } else if($matches[0] == 'Contacts'){
411
                    $sqs_objects[$name1] = $qsd->getQSContact($name1, "id_".$name1);
412
                }
413
414
415
				$temp_array = array('field_list'=>array(),'populate_list'=>array());
416
                foreach($sqs_objects[$name1]['field_list'] as $k=>$v){
417
                    if(!in_array($v, array('name','id'))){
418
                        $sqs_objects[$name1]['primary_field_list'][]=$v;
419
                        $sqs_objects[$name1]['primary_populate_list'][]=$sqs_objects[$name1]['populate_list'][$k];
420
                    }else{
421
                        $temp_array['field_list'][]=$v;
422
                        $temp_array['populate_list'][]=$sqs_objects[$name1]['populate_list'][$k];
423
                    }
424
                }
425
                $sqs_objects[$name1]['field_list'] = $temp_array['field_list'];
426
                $sqs_objects[$name1]['populate_list'] = $temp_array['populate_list'];
427
                if(isset($this->displayParams['collection_field_list'])){
428
                    foreach($this->displayParams['collection_field_list'] as $v){
0 ignored issues
show
Bug introduced by
The expression $this->displayParams['collection_field_list'] of type string is not traversable.
Loading history...
429
                        $sqs_objects[$name1]['populate_list'][]=  $v['vardefName']."_".$this->name."_collection_extra_".$i;
430
                        $sqs_objects[$name1]['field_list'][] = $v['vardefName'];
431
                    }
432
                }
433
            }else {
434
                $sqs_objects[$name1] = $qsd->getQSParent($this->related_module);
435
                $sqs_objects[$name1]['populate_list'] = array("{$this->vardef['name']}_collection_{$i}", "id_{$this->vardef['name']}_collection_{$i}");
436
                $sqs_objects[$name1]['field_list'] = array('name', 'id');
437
                if(isset($this->displayParams['collection_field_list'])){
438
                    foreach($this->displayParams['collection_field_list'] as $v){
0 ignored issues
show
Bug introduced by
The expression $this->displayParams['collection_field_list'] of type string is not traversable.
Loading history...
439
                        $sqs_objects[$name1]['populate_list'][] = $v['vardefName']."_".$this->name."_collection_extra_".$i;
440
                        $sqs_objects[$name1]['field_list'][] = $v['vardefName'];
441
                    }
442
                }
443
                if(isset($this->displayParams['field_to_name_array'])){
444
                    foreach($this->displayParams['field_to_name_array'] as $k=>$v){
0 ignored issues
show
Bug introduced by
The expression $this->displayParams['field_to_name_array'] of type string is not traversable.
Loading history...
445
                        /*
446
                         * "primary_populate_list" and "primary_field_list" are used when the field is selected as a primary.
447
                         * At this time the JS function changePrimary() will copy "primary_populate_list" and "primary_field_list"
448
                         * into "populate_list" and "field_list" and remove the values from all the others which are secondaries.
449
                         * "primary_populate_list" and "primary_field_list" contain the fields which has to be populated outside of
450
                         * the collection field. For example the "Address Information" are populated with the "billing address" of the
451
                         * selected account in a contact editview.
452
                         */
453
                        $sqs_objects[$name1]['primary_populate_list'][] = $v;
454
                        $sqs_objects[$name1]['primary_field_list'][] = $k;
455
                    }
456
                }else if(isset($field['field_list']) && isset($field['populate_list'])){
457
                    $sqs_objects[$name1]['primary_populate_list'] = array_merge($sqs_objects[$name1]['populate_list'], $field['field_list']);
458
                    $sqs_objects[$name1]['primary_field_list'] = array_merge($sqs_objects[$name1]['field_list'], $field['populate_list']);
459
                }else{
460
                    $sqs_objects[$name1]['primary_populate_list'] = array();
461
                    $sqs_objects[$name1]['primary_field_list'] = array();
462
                }
463
            }
464
        }
465
466
        $id = "{$this->form_name}_{$this->name}_collection_0";
467
468
        if(!empty($sqs_objects) && count($sqs_objects) > 0) {
469
            foreach($sqs_objects[$id]['field_list'] as $k=>$v){
470
                $this->field_to_name_array[$v] = $sqs_objects[$id]['populate_list'][$k];
471
            }
472
            if($returnAsJavascript){
473
	            $quicksearch_js = '<script language="javascript">';
474
	            $quicksearch_js.= "if(typeof sqs_objects == 'undefined'){var sqs_objects = new Array;}";
475
476
	            foreach($sqs_objects as $sqsfield=>$sqsfieldArray){
477
	               $quicksearch_js .= "sqs_objects['$sqsfield']={$this->json->encode($sqsfieldArray)};";
478
	            }
479
480
	            return $quicksearch_js .= '</script>';
481
            }else{
482
            	return $sqs_objects;
483
            }
484
       }
485
       return '';
486
    }
487
    /*
488
     * Always call createQuickSearchCode() before createPopupCode() to define field_to_name_array
489
     */
490
    function createPopupCode(){
491
        // TODO the 'select' button is not fully working. We should use the sqs_objects in open_popup instead of the parameter.
492
        if(isset($this->field_to_name_array) && !empty($this->field_to_name_array)){
493
            $call_back_function = 'set_return';
494
495
            if(isset($this->displayParams['formName'])) {
496
                $form = $this->displayParams['formName'];
497
            } else if($this->action_type == 'editview'){
498
                $form = 'EditView';
499
            } else if($this->action_type == 'quickcreate'){
500
                $form = "QuickCreate_{$this->module_dir}";
501
            }
502
503
            if(isset($this->displayParams['call_back_function'])) {
504
                $call_back_function = $this->displayParams['call_back_function'];
505
            }
506
507
            $popup_request_data= array(
508
                'call_back_function' => $call_back_function,
509
                'form_name' => $form,
510
                'field_to_name_array' => $this->field_to_name_array,
511
            );
512
513
            //Make sure to replace {{ and }} with spacing in between because Smarty template parsing will treat {{ or }} specially
514
            $this->displayParams['popupData'] = '{literal}'. str_replace(array('{{', '}}'), array('{ {', '} }'), $this->json->encode($popup_request_data)) . '{/literal}';
515
        }
516
    }
517
518
519
520
    function findTemplate($view){
521
        static $tplCache = array();
522
523
        if ( isset($tplCache[$this->type][$view]) ) {
524
            return $tplCache[$this->type][$view];
525
        }
526
527
        $lastClass = get_class($this);
528
        $classList = array($this->type,str_replace('ViewSugarField','',$lastClass));
529
        while ( $lastClass = get_parent_class($lastClass) ) {
530
            $classList[] = str_replace('ViewSugarField','',$lastClass);
531
        }
532
533
        $tplName = '';
534
        foreach ( $classList as $className ) {
535
            global $current_language;
536
            if(isset($current_language)) {
537
                $tplName = 'include/SugarFields/Fields/'. $className .'/'. $current_language . '.' . $view .'.tpl';
538
                if ( file_exists('custom/'.$tplName) ) {
539
                    $tplName = 'custom/'.$tplName;
540
                    break;
541
                }
542
                if ( file_exists($tplName) ) {
543
                    break;
544
                }
545
            }
546
            $tplName = 'include/SugarFields/Fields/'. $className .'/'. $view .'.tpl';
547
            if ( file_exists('custom/'.$tplName) ) {
548
                $tplName = 'custom/'.$tplName;
549
                break;
550
            }
551
            if ( file_exists($tplName) ) {
552
                break;
553
            }
554
        }
555
556
        $tplCache[$this->type][$view] = $tplName;
557
558
        return $tplName;
559
    }
560
}
561