Test Failed
Push — CI ( 0f01dd...c95a04 )
by Adam
55:13
created

EmailTemplate   F

Complexity

Total Complexity 161

Size/Duplication

Total Lines 771
Duplicated Lines 0 %

Coupling/Cohesion

Components 8
Dependencies 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 161
lcom 8
cbo 6
dl 0
loc 771
rs 1.263
c 1
b 0
f 0

22 Methods

Rating   Name   Duplication   Size   Complexity  
A EmailTemplate() 0 4 1
C generateFieldDefsJS() 0 69 14
C generateFieldDefsJS2() 0 73 14
A get_summary_text() 0 4 1
A create_export_query() 0 4 1
A fill_in_additional_list_fields() 0 4 1
A fill_in_additional_detail_fields() 0 11 3
A fill_in_additional_parent_fields() 0 3 1
A get_list_view_data() 0 7 1
C parse_tracker_urls() 0 51 16
B _preg_match_tracker_url() 0 16 5
F parse_email_template() 0 85 18
A _convertToType() 0 9 2
D _parseUserValues() 0 27 9
F parse_template_bean() 0 194 54
A add_replacement() 0 11 3
C parse_template() 0 22 7
A bean_implements() 0 8 2
A getTypeOptionsForSearch() 0 10 3
A is_used_by_email_marketing() 0 9 2
A cleanBean() 0 7 1
A storeVariables() 0 7 2

How to fix   Complexity   

Complex Class

Complex classes like EmailTemplate 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 EmailTemplate, and based on these observations, apply Extract Interface, too.

1
<?php
2
if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3
/*********************************************************************************
4
 * SugarCRM Community Edition is a customer relationship management program developed by
5
 * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
6
 *
7
 * SuiteCRM is an extension to SugarCRM Community Edition developed by Salesagility Ltd.
8
 * Copyright (C) 2011 - 2016 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
 * Description:  TODO: To be written.
43
 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
44
 * All Rights Reserved.
45
 * Contributor(s): ______________________________________..
46
 ********************************************************************************/
47
// EmailTemplate is used to store email email_template information.
48
class EmailTemplate extends SugarBean
49
{
50
    var $field_name_map = array();
51
    // Stored fields
52
    var $id;
53
    var $date_entered;
54
    var $date_modified;
55
    var $modified_user_id;
56
    var $created_by;
57
    var $created_by_name;
58
    var $modified_by_name;
59
    var $assigned_user_id;
60
    var $assigned_user_name;
61
    var $name;
62
    var $published;
63
    var $description;
64
    var $body;
65
    var $body_html;
66
    var $subject;
67
    var $attachments;
68
    var $from_name;
69
    var $from_address;
70
    var $table_name = "email_templates";
71
    var $object_name = "EmailTemplate";
72
    var $module_dir = "EmailTemplates";
73
    var $new_schema = true;
74
    // This is used to retrieve related fields from form posts.
75
    var $additional_column_fields = array();
76
    // add fields here that would not make sense in an email template
77
    var $badFields = array(
78
        'account_description',
79
        'contact_id',
80
        'lead_id',
81
        'opportunity_amount',
82
        'opportunity_id',
83
        'opportunity_name',
84
        'opportunity_role_id',
85
        'opportunity_role_fields',
86
        'opportunity_role',
87
        'campaign_id',
88
        // User objects
89
        'id',
90
        'date_entered',
91
        'date_modified',
92
        'user_preferences',
93
        'accept_status',
94
        'user_hash',
95
        'authenticate_id',
96
        'sugar_login',
97
        'reports_to_id',
98
        'reports_to_name',
99
        'is_admin',
100
        'receive_notifications',
101
        'modified_user_id',
102
        'modified_by_name',
103
        'created_by',
104
        'created_by_name',
105
        'accept_status_id',
106
        'accept_status_name',
107
    );
108
109
    /**
110
     * @var array temp storage for template variables while cleanBean
111
     */
112
    protected $storedVariables = array();
113
114
    function EmailTemplate()
115
    {
116
        parent::SugarBean();
117
    }
118
119
    /**
120
     * Generates the extended field_defs for creating macros
121
     * @param object $bean SugarBean
0 ignored issues
show
Bug introduced by
There is no parameter named $bean. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
122
     * @param string $prefix "contact_", "user_" etc.
0 ignored issues
show
Bug introduced by
There is no parameter named $prefix. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
123
     * @return
124
     */
125
    function generateFieldDefsJS()
126
    {
127
        global $current_user;
128
129
130
        $contact = new Contact();
131
        $account = new Account();
132
        $lead = new Lead();
133
        $prospect = new Prospect();
134
135
136
        $loopControl = array(
137
            'Contacts' => array(
138
                'Contacts' => $contact,
139
                'Leads' => $lead,
140
                'Prospects' => $prospect,
141
            ),
142
            'Accounts' => array(
143
                'Accounts' => $account,
144
            ),
145
            'Users' => array(
146
                'Users' => $current_user,
147
            ),
148
        );
149
150
        $prefixes = array(
151
            'Contacts' => 'contact_',
152
            'Accounts' => 'account_',
153
            'Users' => 'contact_user_',
154
        );
155
156
        $collection = array();
157
        foreach ($loopControl as $collectionKey => $beans) {
158
            $collection[$collectionKey] = array();
159
            foreach ($beans as $beankey => $bean) {
160
161
                foreach ($bean->field_defs as $key => $field_def) {
162
                    if (($field_def['type'] == 'relate' && empty($field_def['custom_type'])) ||
163
                        ($field_def['type'] == 'assigned_user_name' || $field_def['type'] == 'link') ||
164
                        ($field_def['type'] == 'bool') ||
165
                        (in_array($field_def['name'], $this->badFields))
166
                    ) {
167
                        continue;
168
                    }
169
                    if (!isset($field_def['vname'])) {
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...
170
                        //echo $key;
171
                    }
172
                    // valid def found, process
173
                    $optionKey = strtolower("{$prefixes[$collectionKey]}{$key}");
174
                    $optionLabel = preg_replace('/:$/', "", translate($field_def['vname'], $beankey));
175
                    $dup = 1;
176
                    foreach ($collection[$collectionKey] as $value) {
177
                        if ($value['name'] == $optionKey) {
178
                            $dup = 0;
179
                            break;
180
                        }
181
                    }
182
                    if ($dup)
183
                        $collection[$collectionKey][] = array("name" => $optionKey, "value" => $optionLabel);
184
                }
185
            }
186
        }
187
188
        $json = getJSONobj();
189
        $ret = "var field_defs = ";
190
        $ret .= $json->encode($collection, false);
191
        $ret .= ";";
192
        return $ret;
193
    }
194
195
    function generateFieldDefsJS2()
196
    {
197
        global $current_user;
198
199
        $contact = new Contact();
200
        $account = new Account();
201
        $lead = new Lead();
202
        $prospect = new Prospect();
203
        $event = new FP_events();
204
205
206
        $loopControl = array(
207
            'Contacts' => array(
208
                'Contacts' => $contact,
209
                'Leads' => $lead,
210
                'Prospects' => $prospect,
211
            ),
212
            'Accounts' => array(
213
                'Accounts' => $account,
214
            ),
215
            'Users' => array(
216
                'Users' => $current_user,
217
            ),
218
            'Events' => array(
219
                'Events' => $event,
220
            ),
221
        );
222
223
        $prefixes = array(
224
            'Contacts' => 'contact_',
225
            'Accounts' => 'account_',
226
            'Users' => 'contact_user_',
227
            'Events' => 'event_',
228
        );
229
230
        $collection = array();
231
        foreach ($loopControl as $collectionKey => $beans) {
232
            $collection[$collectionKey] = array();
233
            foreach ($beans as $beankey => $bean) {
234
235
                foreach ($bean->field_defs as $key => $field_def) {
236
                    if (($field_def['type'] == 'relate' && empty($field_def['custom_type'])) ||
237
                        ($field_def['type'] == 'assigned_user_name' || $field_def['type'] == 'link') ||
238
                        ($field_def['type'] == 'bool') ||
239
                        (in_array($field_def['name'], $this->badFields))
240
                    ) {
241
                        continue;
242
                    }
243
                    if (!isset($field_def['vname'])) {
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...
244
                        //echo $key;
245
                    }
246
                    // valid def found, process
247
                    $optionKey = strtolower("{$prefixes[$collectionKey]}{$key}");
248
                    $optionLabel = preg_replace('/:$/', "", translate($field_def['vname'], $beankey));
249
                    $dup = 1;
250
                    foreach ($collection[$collectionKey] as $value) {
251
                        if ($value['name'] == $optionKey) {
252
                            $dup = 0;
253
                            break;
254
                        }
255
                    }
256
                    if ($dup)
257
                        $collection[$collectionKey][] = array("name" => $optionKey, "value" => $optionLabel);
258
                }
259
            }
260
        }
261
262
        $json = getJSONobj();
263
        $ret = "var field_defs = ";
264
        $ret .= $json->encode($collection, false);
265
        $ret .= ";";
266
        return $ret;
267
    }
268
269
    function get_summary_text()
270
    {
271
        return "$this->name";
272
    }
273
274
    function create_export_query($order_by, $where)
275
    {
276
        return $this->create_new_list_query($order_by, $where);
277
    }
278
279
    function fill_in_additional_list_fields()
280
    {
281
        $this->fill_in_additional_parent_fields();
282
    }
283
284
    function fill_in_additional_detail_fields()
285
    {
286
        if (empty($this->body) && !empty($this->body_html)) {
287
            global $sugar_config;
288
            $this->body = strip_tags(html_entity_decode($this->body_html, ENT_COMPAT, $sugar_config['default_charset']));
0 ignored issues
show
Unused Code introduced by
The call to html_entity_decode() has too many arguments starting with $sugar_config['default_charset'].

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...
289
        }
290
        $this->created_by_name = get_assigned_user_name($this->created_by);
291
        $this->modified_by_name = get_assigned_user_name($this->modified_user_id);
292
        $this->assigned_user_name = get_assigned_user_name($this->assigned_user_id);
293
        $this->fill_in_additional_parent_fields();
294
    }
295
296
    function fill_in_additional_parent_fields()
297
    {
298
    }
299
300
    function get_list_view_data()
301
    {
302
        global $app_list_strings, $focus, $action, $currentModule;
303
        $fields = $this->get_list_view_array();
304
        $fields["DATE_MODIFIED"] = substr($fields["DATE_MODIFIED"], 0, 10);
305
        return $fields;
306
    }
307
308
//function all string that match the pattern {.} , also catches the list of found strings.
309
    //the cache will get refreshed when the template bean instance changes.
310
    //The found url key patterns are replaced with name value pairs provided as function parameter. $tracked_urls.
311
    //$url_template is used to construct the url for the email message. the template should have place holder for 1 variable parameter, represented by %1
312
    //$template_text_array is a list of text strings that need to be searched. usually the subject, html body and text body of the email message.
313
    //$removeme_url_template, if the url has is_optout property checked then use this template.
314
    function parse_tracker_urls($template_text_array, $url_template, $tracked_urls, $removeme_url_template)
315
    {
316
        global $beanFiles, $beanList, $app_list_strings, $sugar_config;
317
        if (!isset($this->parsed_urls))
318
            $this->parsed_urls = array();
319
320
        $return_array = $template_text_array;
321
        if (count($tracked_urls) > 0) {
322
            //parse the template and find all the dynamic strings that need replacement.
323
            foreach ($template_text_array as $key => $template_text) {
324
                if (!empty($template_text)) {
325
326
                    if (!isset($this->parsed_urls[$key]) || $this->parsed_urls[$key]['text'] != $template_text) {
327
                        // Fix for bug52014.
328
                        $template_text = urldecode($template_text);
329
                        $matches = $this->_preg_match_tracker_url($template_text);
330
                        $count = count($matches[0]);
331
                        $this->parsed_urls[$key] = array('matches' => $matches, 'text' => $template_text);
332
                    } else {
333
                        $matches = $this->parsed_urls[$key]['matches'];
334
                        if (!empty($matches[0])) {
335
                            $count = count($matches[0]);
336
                        } else {
337
                            $count = 0;
338
                        }
339
                    }
340
341
                    //navigate thru all the matched keys and replace the keys with actual strings.
342
343
                    if ($count > 0) {
344
                        for ($i = ($count - 1); $i >= 0; $i--) {
345
                            $url_key_name = $matches[0][$i][0];
346
                            if (!empty($tracked_urls[$url_key_name])) {
347
                                if ($tracked_urls[$url_key_name]['is_optout'] == 1) {
348
                                    $tracker_url = $removeme_url_template;
349
                                } else {
350
                                    $tracker_url = sprintf($url_template, $tracked_urls[$url_key_name]['id']);
351
                                }
352
                            }
353
                            if (!empty($tracker_url) && !empty($template_text) && !empty($matches[0][$i][0]) && !empty($tracked_urls[$matches[0][$i][0]])) {
354
                                $template_text = substr_replace($template_text, $tracker_url, $matches[0][$i][1], strlen($matches[0][$i][0]));
355
                                $template_text = str_replace($sugar_config['site_url'] . '/' . $sugar_config['site_url'], $sugar_config['site_url'], $template_text);
356
                            }
357
                        }
358
                    }
359
                }
360
                $return_array[$key] = $template_text;
361
            }
362
        }
363
        return $return_array;
364
    }
365
366
    /**
367
     *
368
     * Method for replace "preg_match_all" in method "parse_tracker_urls"
369
     * @param $text string String in which we need to search all string that match the pattern {.}
370
     * @return array result of search
371
     */
372
    private function _preg_match_tracker_url($text)
373
    {
374
        $result = array();
375
        $ind = 0;
376
        $switch = false;
377
        for ($i = 0; $i < strlen($text); $i++) {
378
            if ($text[$i] == '{') {
379
                $ind = $i;
380
                $switch = true;
381
            } elseif ($text[$i] == '}' && $switch === true) {
382
                $switch = false;
383
                array_push($result, array(substr($text, $ind, $i - $ind + 1), $ind));
384
            }
385
        }
386
        return array($result);
387
    }
388
389
    function parse_email_template($template_text_array, $focus_name, $focus, &$macro_nv)
390
    {
391
392
393
        global $beanFiles, $beanList, $app_list_strings;
394
395
        // generate User instance that owns this "Contact" for contact_user_* macros
396
        $user = new User();
397
        if (isset($focus->assigned_user_id) && !empty($focus->assigned_user_id)) {
398
            $user->retrieve($focus->assigned_user_id);
399
        }
400
401
        if (!isset($this->parsed_entities))
402
            $this->parsed_entities = array();
403
404
        //parse the template and find all the dynamic strings that need replacement.
405
        // Bug #48111 It's strange why prefix for User module is contact_user (see self::generateFieldDefsJS method)
406
        if ($beanList[$focus_name] == 'User') {
407
            $pattern_prefix = '$contact_user_';
408
        } else {
409
            $pattern_prefix = '$' . strtolower($beanList[$focus_name]) . '_';
410
        }
411
        $pattern_prefix_length = strlen($pattern_prefix);
412
        $pattern = '/\\' . $pattern_prefix . '[A-Za-z_0-9]*/';
413
414
        foreach ($template_text_array as $key => $template_text) {
415
            if (!isset($this->parsed_entities[$key])) {
416
                $matches = array();
417
                $count = preg_match_all($pattern, $template_text, $matches, PREG_OFFSET_CAPTURE);
418
419
                if ($count != 0) {
420
                    for ($i = ($count - 1); $i >= 0; $i--) {
421
                        if (!isset($matches[0][$i][2])) {
422
                            //find the field name in the bean.
423
                            $matches[0][$i][2] = substr($matches[0][$i][0], $pattern_prefix_length, strlen($matches[0][$i][0]) - $pattern_prefix_length);
424
425
                            //store the localized strings if the field is of type enum..
426
                            if (isset($focus->field_defs[$matches[0][$i][2]]) && $focus->field_defs[$matches[0][$i][2]]['type'] == 'enum' && isset($focus->field_defs[$matches[0][$i][2]]['options'])) {
427
                                $matches[0][$i][3] = $focus->field_defs[$matches[0][$i][2]]['options'];
428
                            }
429
                        }
430
                    }
431
                }
432
                $this->parsed_entities[$key] = $matches;
433
            } else {
434
                $matches = $this->parsed_entities[$key];
435
                if (!empty($matches[0])) {
436
                    $count = count($matches[0]);
437
                } else {
438
                    $count = 0;
439
                }
440
            }
441
442
            for ($i = ($count - 1); $i >= 0; $i--) {
443
                $field_name = $matches[0][$i][2];
444
445
                // cn: feel for User object attribute key and assign as found
446
                if (strpos($field_name, "user_") === 0) {
447
                    $userFieldName = substr($field_name, 5);
448
                    $value = $user->$userFieldName;
449
                    //_pp($userFieldName."[{$value}]");
450
                } else {
451
                    $value = $focus->{$field_name};
452
                }
453
454
                //check dom
455
                if (isset($matches[0][$i][3])) {
456
                    if (isset($app_list_strings[$matches[0][$i][3]][$value])) {
457
                        $value = $app_list_strings[$matches[0][$i][3]][$value];
458
                    }
459
                }
460
461
                //generate name value pair array of macros and corresponding values for the targed.
462
                $macro_nv[$matches[0][$i][0]] = $value;
463
464
                $template_text = substr_replace($template_text, $value, $matches[0][$i][1], strlen($matches[0][$i][0]));
465
            }
466
467
            //parse the template for tracker url strings. patter for these strings in {[a-zA-Z_0-9]+}
468
469
            $return_array[$key] = $template_text;
470
        }
471
472
        return $return_array;
473
    }
474
475
    /**
476
     * Convenience method to convert raw value into appropriate type format
477
     * @param string $type
478
     * @param string $value
479
     * @return string
480
     */
481
    function _convertToType($type, $value)
482
    {
483
        switch ($type) {
484
            case 'currency' :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
485
                return currency_format_number($value);
486
            default:
487
                return $value;
488
        }
489
    }
490
491
    /**
492
     * Convenience method to parse for user's values in a template
493
     * @param array $repl_arr
494
     * @param object $user
495
     * @return array
496
     */
497
    function _parseUserValues($repl_arr, &$user)
498
    {
499
        foreach ($user->field_defs as $field_def) {
500
            if (($field_def['type'] == 'relate' && empty($field_def['custom_type'])) || $field_def['type'] == 'assigned_user_name') {
501
                continue;
502
            }
503
504
            if ($field_def['type'] == 'enum') {
505
                $translated = translate($field_def['options'], 'Users', $user->$field_def['name']);
506
507
                if (isset($translated) && !is_array($translated)) {
508
                    $repl_arr["contact_user_" . $field_def['name']] = $translated;
509
                } else { // unset enum field, make sure we have a match string to replace with ""
510
                    $repl_arr["contact_user_" . $field_def['name']] = '';
511
                }
512
            } else {
513
                if (isset($user->$field_def['name'])) {
514
                    // bug 47647 - allow for fields to translate before adding to template
515
                    $repl_arr["contact_user_" . $field_def['name']] = self::_convertToType($field_def['type'], $user->$field_def['name']);
516
                } else {
517
                    $repl_arr["contact_user_" . $field_def['name']] = "";
518
                }
519
            }
520
        }
521
522
        return $repl_arr;
523
    }
524
525
526
    function parse_template_bean($string, $bean_name, &$focus)
527
    {
528
        global $current_user;
529
        global $beanFiles, $beanList;
530
        $repl_arr = array();
531
532
        // cn: bug 9277 - create a replace array with empty strings to blank-out invalid vars
533
        $acct = new Account();
534
        $contact = new Contact();
535
        $lead = new Lead();
536
        $prospect = new Prospect();
537
538
        foreach ($lead->field_defs as $field_def) {
539
            if (($field_def['type'] == 'relate' && empty($field_def['custom_type'])) || $field_def['type'] == 'assigned_user_name') {
540
                continue;
541
            }
542
            $repl_arr = EmailTemplate::add_replacement($repl_arr, $field_def, array(
543
                'contact_' . $field_def['name'] => '',
544
                'contact_account_' . $field_def['name'] => '',
545
            ));
546
        }
547
        foreach ($prospect->field_defs as $field_def) {
548
            if (($field_def['type'] == 'relate' && empty($field_def['custom_type'])) || $field_def['type'] == 'assigned_user_name') {
549
                continue;
550
            }
551
            $repl_arr = EmailTemplate::add_replacement($repl_arr, $field_def, array(
552
                'contact_' . $field_def['name'] => '',
553
                'contact_account_' . $field_def['name'] => '',
554
            ));
555
        }
556
        foreach ($contact->field_defs as $field_def) {
557
            if (($field_def['type'] == 'relate' && empty($field_def['custom_type'])) || $field_def['type'] == 'assigned_user_name') {
558
                continue;
559
            }
560
            $repl_arr = EmailTemplate::add_replacement($repl_arr, $field_def, array(
561
                'contact_' . $field_def['name'] => '',
562
                'contact_account_' . $field_def['name'] => '',
563
            ));
564
        }
565
        foreach ($acct->field_defs as $field_def) {
566
            if (($field_def['type'] == 'relate' && empty($field_def['custom_type'])) || $field_def['type'] == 'assigned_user_name') {
567
                continue;
568
            }
569
            $repl_arr = EmailTemplate::add_replacement($repl_arr, $field_def, array(
570
                'account_' . $field_def['name'] => '',
571
                'account_contact_' . $field_def['name'] => '',
572
            ));
573
        }
574
        // cn: end bug 9277 fix
575
576
577
        // feel for Parent account, only for Contacts traditionally, but written for future expansion
578
        if (isset($focus->account_id) && !empty($focus->account_id)) {
579
            $acct->retrieve($focus->account_id);
580
        }
581
582
        if ($bean_name == 'Contacts') {
583
            // cn: bug 9277 - email templates not loading account/opp info for templates
584
            if (!empty($acct->id)) {
585
                foreach ($acct->field_defs as $field_def) {
586
                    if (($field_def['type'] == 'relate' && empty($field_def['custom_type'])) || $field_def['type'] == 'assigned_user_name') {
587
                        continue;
588
                    }
589
590
                    if ($field_def['type'] == 'enum') {
591
                        $translated = translate($field_def['options'], 'Accounts', $acct->$field_def['name']);
592
593
                        if (isset($translated) && !is_array($translated)) {
594
                            $repl_arr = EmailTemplate::add_replacement($repl_arr, $field_def, array(
595
                                'account_' . $field_def['name'] => $translated,
596
                                'contact_account_' . $field_def['name'] => $translated,
597
                            ));
598
                        } else { // unset enum field, make sure we have a match string to replace with ""
599
                            $repl_arr = EmailTemplate::add_replacement($repl_arr, $field_def, array(
600
                                'account_' . $field_def['name'] => '',
601
                                'contact_account_' . $field_def['name'] => '',
602
                            ));
603
                        }
604
                    } else {
605
                        // bug 47647 - allow for fields to translate before adding to template
606
                        $translated = self::_convertToType($field_def['type'], $acct->$field_def['name']);
607
                        $repl_arr = EmailTemplate::add_replacement($repl_arr, $field_def, array(
608
                            'account_' . $field_def['name'] => $translated,
609
                            'contact_account_' . $field_def['name'] => $translated,
610
                        ));
611
                    }
612
                }
613
            }
614
615
            if (!empty($focus->assigned_user_id)) {
616
                $user = new User();
617
                $user->retrieve($focus->assigned_user_id);
618
                $repl_arr = EmailTemplate::_parseUserValues($repl_arr, $user);
619
            }
620
        } elseif ($bean_name == 'Users') {
621
            /**
622
             * This section of code will on do work when a blank Contact, Lead,
623
             * etc. is passed in to parse the contact_* vars.  At this point,
624
             * $current_user will be used to fill in the blanks.
625
             */
626
            $repl_arr = EmailTemplate::_parseUserValues($repl_arr, $current_user);
627
        } else {
628
            // assumed we have an Account in focus
629
            foreach ($contact->field_defs as $field_def) {
630
                if (($field_def['type'] == 'relate' && empty($field_def['custom_type'])) || $field_def['type'] == 'assigned_user_name' || $field_def['type'] == 'link') {
631
                    continue;
632
                }
633
634
                if ($field_def['type'] == 'enum') {
635
                    $translated = translate($field_def['options'], 'Accounts', $contact->$field_def['name']);
636
637
                    if (isset($translated) && !is_array($translated)) {
638
                        $repl_arr = EmailTemplate::add_replacement($repl_arr, $field_def, array(
639
                            'contact_' . $field_def['name'] => $translated,
640
                            'contact_account_' . $field_def['name'] => $translated,
641
                        ));
642
                    } else { // unset enum field, make sure we have a match string to replace with ""
643
                        $repl_arr = EmailTemplate::add_replacement($repl_arr, $field_def, array(
644
                            'contact_' . $field_def['name'] => '',
645
                            'contact_account_' . $field_def['name'] => '',
646
                        ));
647
                    }
648
                } else {
649
                    if (isset($contact->$field_def['name'])) {
650
                        // bug 47647 - allow for fields to translate before adding to template
651
                        $translated = self::_convertToType($field_def['type'], $contact->$field_def['name']);
652
                        $repl_arr = EmailTemplate::add_replacement($repl_arr, $field_def, array(
653
                            'contact_' . $field_def['name'] => $translated,
654
                            'contact_account_' . $field_def['name'] => $translated,
655
                        ));
656
                    } // if
657
                }
658
            }
659
        }
660
661
        ///////////////////////////////////////////////////////////////////////
662
        ////	LOAD FOCUS DATA INTO REPL_ARR
663
        foreach ($focus->field_defs as $field_def) {
664
            if (isset($focus->$field_def['name'])) {
665
                if (($field_def['type'] == 'relate' && empty($field_def['custom_type'])) || $field_def['type'] == 'assigned_user_name') {
666
                    continue;
667
                }
668
669
                if ($field_def['type'] == 'enum' && isset($field_def['options'])) {
670
                    $translated = translate($field_def['options'], $bean_name, $focus->$field_def['name']);
671
672
                    if (isset($translated) && !is_array($translated)) {
673
                        $repl_arr = EmailTemplate::add_replacement($repl_arr, $field_def, array(
674
                            strtolower($beanList[$bean_name]) . "_" . $field_def['name'] => $translated,
675
                        ));
676
                    } else { // unset enum field, make sure we have a match string to replace with ""
677
                        $repl_arr = EmailTemplate::add_replacement($repl_arr, $field_def, array(
678
                            strtolower($beanList[$bean_name]) . "_" . $field_def['name'] => '',
679
                        ));
680
                    }
681
                } else {
682
                    // bug 47647 - translate currencies to appropriate values
683
                    $repl_arr = EmailTemplate::add_replacement($repl_arr, $field_def, array(
684
                        strtolower($beanList[$bean_name]) . "_" . $field_def['name'] => self::_convertToType($field_def['type'], $focus->$field_def['name']),
685
                    ));
686
                }
687
            } else {
688
                if ($field_def['name'] == 'full_name') {
689
                    $repl_arr = EmailTemplate::add_replacement($repl_arr, $field_def, array(
690
                        strtolower($beanList[$bean_name]) . '_full_name' => $focus->get_summary_text(),
691
                    ));
692
                } else {
693
                    $repl_arr = EmailTemplate::add_replacement($repl_arr, $field_def, array(
694
                        strtolower($beanList[$bean_name]) . "_" . $field_def['name'] => '',
695
                    ));
696
                }
697
            }
698
        } // end foreach()
699
700
        krsort($repl_arr);
701
        reset($repl_arr);
702
        //20595 add nl2br() to respect the multi-lines formatting
703
        if (isset($repl_arr['contact_primary_address_street'])) {
704
            $repl_arr['contact_primary_address_street'] = nl2br($repl_arr['contact_primary_address_street']);
705
        }
706
        if (isset($repl_arr['contact_alt_address_street'])) {
707
            $repl_arr['contact_alt_address_street'] = nl2br($repl_arr['contact_alt_address_street']);
708
        }
709
710
        foreach ($repl_arr as $name => $value) {
711
            if ($value != '' && is_string($value)) {
712
                $string = str_replace("\$$name", $value, $string);
713
            } else {
714
                $string = str_replace("\$$name", ' ', $string);
715
            }
716
        }
717
718
        return $string;
719
    }
720
721
    /**
722
     * Add replacement(s) to the collection based on field definition
723
     *
724
     * @param array $data
725
     * @param array $field_def
726
     * @param array $replacement
727
     * @return array
728
     */
729
    protected static function add_replacement($data, $field_def, $replacement)
730
    {
731
        foreach ($replacement as $key => $value) {
732
            // @see defect #48641
733
            if ('multienum' == $field_def['type']) {
734
                $value = implode(', ', unencodeMultienum($value));
735
            }
736
            $data[$key] = $value;
737
        }
738
        return $data;
739
    }
740
741
    function parse_template($string, &$bean_arr)
742
    {
743
        global $beanFiles, $beanList;
744
745
        foreach ($bean_arr as $bean_name => $bean_id) {
746
            require_once($beanFiles[$beanList[$bean_name]]);
747
748
            $focus = new $beanList[$bean_name];
749
            $result = $focus->retrieve($bean_id);
750
751
            if ($bean_name == 'Leads' || $bean_name == 'Prospects') {
752
                $bean_name = 'Contacts';
753
            }
754
755
            if (isset($this) && isset($this->module_dir) && $this->module_dir == 'EmailTemplates') {
756
                $string = $this->parse_template_bean($string, $bean_name, $focus);
757
            } else {
758
                $string = EmailTemplate::parse_template_bean($string, $bean_name, $focus);
759
            }
760
        }
761
        return $string;
762
    }
763
764
    function bean_implements($interface)
765
    {
766
        switch ($interface) {
767
            case 'ACL':
768
                return true;
769
        }
770
        return false;
771
    }
772
773
    static function getTypeOptionsForSearch()
774
    {
775
        $template = new EmailTemplate();
776
        $optionKey = $template->field_defs['type']['options'];
777
        $options = $GLOBALS['app_list_strings'][$optionKey];
778
        if (!is_admin($GLOBALS['current_user']) && isset($options['workflow']))
779
            unset($options['workflow']);
780
781
        return $options;
782
    }
783
784
    function is_used_by_email_marketing()
785
    {
786
        $query = "select id from email_marketing where template_id='$this->id' and deleted=0";
787
        $result = $this->db->query($query);
788
        if ($this->db->fetchByAssoc($result)) {
789
            return true;
790
        }
791
        return false;
792
    }
793
794
    /**
795
     * Allows us to save variables of template as they are
796
     */
797
    public function cleanBean()
798
    {
799
        $this->storedVariables = array();
800
        $this->body_html = preg_replace_callback('/\{::[^}]+::\}/', array($this, 'storeVariables'), $this->body_html);
801
        parent::cleanBean();
802
        $this->body_html = str_replace(array_values($this->storedVariables), array_keys($this->storedVariables), $this->body_html);
803
    }
804
805
    /**
806
     * Replacing variables of templates by their md5 hash
807
     *
808
     * @param array $text result of preg_replace_callback
809
     * @return string md5 hash of result
810
     */
811
    protected function storeVariables($text)
812
    {
813
        if (isset($this->storedVariables[$text[0]]) == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
814
            $this->storedVariables[$text[0]] = md5($text[0]);
815
        }
816
        return $this->storedVariables[$text[0]];
817
    }
818
}
819
820
?>
821