Completed
Push — console-installer ( e2b50d...6ce748 )
by Adam
22:30
created

EmailTemplate::parse_template_bean()   F

Complexity

Conditions 54
Paths > 20000

Size

Total Lines 197
Code Lines 117

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 54
eloc 117
nc 91368
nop 3
dl 0
loc 197
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
    private $imageLinkReplaced = false;
115
116
    public function __construct()
117
    {
118
        parent::__construct();
119
    }
120
121
    /**
122
     * @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
123
     */
124
    public function EmailTemplate(){
125
        $deprecatedMessage = 'PHP4 Style Constructors are deprecated and will be remove in 7.8, please update your code';
126
        if(isset($GLOBALS['log'])) {
127
            $GLOBALS['log']->deprecated($deprecatedMessage);
128
        }
129
        else {
130
            trigger_error($deprecatedMessage, E_USER_DEPRECATED);
131
        }
132
        self::__construct();
133
    }
134
135
136
    /**
137
     * Generates the extended field_defs for creating macros
138
     * @return array
139
     */
140
    function generateFieldDefsJS()
141
    {
142
        global $current_user;
143
144
145
        $contact = new Contact();
146
        $account = new Account();
147
        $lead = new Lead();
148
        $prospect = new Prospect();
149
150
151
        $loopControl = array(
152
            'Contacts' => array(
153
                'Contacts' => $contact,
154
                'Leads' => $lead,
155
                'Prospects' => $prospect,
156
            ),
157
            'Accounts' => array(
158
                'Accounts' => $account,
159
            ),
160
            'Users' => array(
161
                'Users' => $current_user,
162
            ),
163
        );
164
165
        $prefixes = array(
166
            'Contacts' => 'contact_',
167
            'Accounts' => 'account_',
168
            'Users' => 'contact_user_',
169
        );
170
171
        $collection = array();
172
        foreach ($loopControl as $collectionKey => $beans) {
173
            $collection[$collectionKey] = array();
174
            foreach ($beans as $beankey => $bean) {
175
176
                foreach ($bean->field_defs as $key => $field_def) {
177
                    if (($field_def['type'] == 'relate' && empty($field_def['custom_type'])) ||
178
                        ($field_def['type'] == 'assigned_user_name' || $field_def['type'] == 'link') ||
179
                        ($field_def['type'] == 'bool') ||
180
                        (in_array($field_def['name'], $this->badFields))
181
                    ) {
182
                        continue;
183
                    }
184
                    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...
185
                        //echo $key;
186
                    }
187
                    // valid def found, process
188
                    $optionKey = strtolower("{$prefixes[$collectionKey]}{$key}");
189
                    $optionLabel = preg_replace('/:$/', "", translate($field_def['vname'], $beankey));
190
                    $dup = 1;
191
                    foreach ($collection[$collectionKey] as $value) {
192
                        if ($value['name'] == $optionKey) {
193
                            $dup = 0;
194
                            break;
195
                        }
196
                    }
197
                    if ($dup)
198
                        $collection[$collectionKey][] = array("name" => $optionKey, "value" => $optionLabel);
199
                }
200
            }
201
        }
202
203
        $json = getJSONobj();
204
        $ret = "var field_defs = ";
205
        $ret .= $json->encode($collection, false);
206
        $ret .= ";";
207
        return $ret;
208
    }
209
210
    function generateFieldDefsJS2()
211
    {
212
        global $current_user;
213
214
        $contact = new Contact();
215
        $account = new Account();
216
        $lead = new Lead();
217
        $prospect = new Prospect();
218
        $event = new FP_events();
219
220
221
        $loopControl = array(
222
            'Contacts' => array(
223
                'Contacts' => $contact,
224
                'Leads' => $lead,
225
                'Prospects' => $prospect,
226
            ),
227
            'Accounts' => array(
228
                'Accounts' => $account,
229
            ),
230
            'Users' => array(
231
                'Users' => $current_user,
232
            ),
233
            'Events' => array(
234
                'Events' => $event,
235
            ),
236
        );
237
238
        $prefixes = array(
239
            'Contacts' => 'contact_',
240
            'Accounts' => 'account_',
241
            'Users' => 'contact_user_',
242
            'Events' => 'event_',
243
        );
244
245
        $collection = array();
246
        foreach ($loopControl as $collectionKey => $beans) {
247
            $collection[$collectionKey] = array();
248
            foreach ($beans as $beankey => $bean) {
249
250
                foreach ($bean->field_defs as $key => $field_def) {
251
                    if (($field_def['type'] == 'relate' && empty($field_def['custom_type'])) ||
252
                        ($field_def['type'] == 'assigned_user_name' || $field_def['type'] == 'link') ||
253
                        ($field_def['type'] == 'bool') ||
254
                        (in_array($field_def['name'], $this->badFields))
255
                    ) {
256
                        continue;
257
                    }
258
                    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...
259
                        //echo $key;
260
                    }
261
                    // valid def found, process
262
                    $optionKey = strtolower("{$prefixes[$collectionKey]}{$key}");
263
                    $optionLabel = preg_replace('/:$/', "", translate($field_def['vname'], $beankey));
264
                    $dup = 1;
265
                    foreach ($collection[$collectionKey] as $value) {
266
                        if ($value['name'] == $optionKey) {
267
                            $dup = 0;
268
                            break;
269
                        }
270
                    }
271
                    if ($dup)
272
                        $collection[$collectionKey][] = array("name" => $optionKey, "value" => $optionLabel);
273
                }
274
            }
275
        }
276
277
        $json = getJSONobj();
278
        $ret = "var field_defs = ";
279
        $ret .= $json->encode($collection, false);
280
        $ret .= ";";
281
        return $ret;
282
    }
283
284
    function get_summary_text()
285
    {
286
        return "$this->name";
287
    }
288
289
    function create_export_query($order_by, $where)
290
    {
291
        return $this->create_new_list_query($order_by, $where);
292
    }
293
294
    function fill_in_additional_list_fields()
295
    {
296
        $this->fill_in_additional_parent_fields();
297
    }
298
299
    function fill_in_additional_detail_fields()
300
    {
301
        if (empty($this->body) && !empty($this->body_html)) {
302
            global $sugar_config;
303
            $this->body = strip_tags(html_entity_decode($this->body_html, ENT_COMPAT, $sugar_config['default_charset']));
304
        }
305
        $this->created_by_name = get_assigned_user_name($this->created_by);
306
        $this->modified_by_name = get_assigned_user_name($this->modified_user_id);
307
        $this->assigned_user_name = get_assigned_user_name($this->assigned_user_id);
308
        $this->fill_in_additional_parent_fields();
309
    }
310
311
    function fill_in_additional_parent_fields()
312
    {
313
    }
314
315
    function get_list_view_data()
316
    {
317
        global $app_list_strings, $focus, $action, $currentModule;
318
        $fields = $this->get_list_view_array();
319
        //$fields["DATE_MODIFIED"] = substr($fields["DATE_MODIFIED"], 0, 10);
320
        $fields["DATE_MODIFIED"] = isset($fields["DATE_MODIFIED"]) && !empty($fields["DATE_MODIFIED"]) ? substr($fields["DATE_MODIFIED"], 0, 10) : false;
321
        return $fields;
322
    }
323
324
//function all string that match the pattern {.} , also catches the list of found strings.
325
    //the cache will get refreshed when the template bean instance changes.
326
    //The found url key patterns are replaced with name value pairs provided as function parameter. $tracked_urls.
327
    //$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
328
    //$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.
329
    //$removeme_url_template, if the url has is_optout property checked then use this template.
330
    function parse_tracker_urls($template_text_array, $url_template, $tracked_urls, $removeme_url_template)
331
    {
332
        global $beanFiles, $beanList, $app_list_strings, $sugar_config;
333
        if (!isset($this->parsed_urls))
334
            $this->parsed_urls = array();
335
336
        $return_array = $template_text_array;
337
        if (count($tracked_urls) > 0) {
338
            //parse the template and find all the dynamic strings that need replacement.
339
            foreach ($template_text_array as $key => $template_text) {
340
                if (!empty($template_text)) {
341
342
                    if (!isset($this->parsed_urls[$key]) || $this->parsed_urls[$key]['text'] != $template_text) {
343
                        // Fix for bug52014.
344
                        $template_text = urldecode($template_text);
345
                        $matches = $this->_preg_match_tracker_url($template_text);
346
                        $count = count($matches[0]);
347
                        $this->parsed_urls[$key] = array('matches' => $matches, 'text' => $template_text);
348
                    } else {
349
                        $matches = $this->parsed_urls[$key]['matches'];
350
                        if (!empty($matches[0])) {
351
                            $count = count($matches[0]);
352
                        } else {
353
                            $count = 0;
354
                        }
355
                    }
356
357
                    //navigate thru all the matched keys and replace the keys with actual strings.
358
359
                    if ($count > 0) {
360
                        for ($i = ($count - 1); $i >= 0; $i--) {
361
                            $url_key_name = $matches[0][$i][0];
362
                            if (!empty($tracked_urls[$url_key_name])) {
363
                                if ($tracked_urls[$url_key_name]['is_optout'] == 1) {
364
                                    $tracker_url = $removeme_url_template;
365
                                } else {
366
                                    $tracker_url = sprintf($url_template, $tracked_urls[$url_key_name]['id']);
367
                                }
368
                            }
369
                            if (!empty($tracker_url) && !empty($template_text) && !empty($matches[0][$i][0]) && !empty($tracked_urls[$matches[0][$i][0]])) {
370
                                $template_text = substr_replace($template_text, $tracker_url, $matches[0][$i][1], strlen($matches[0][$i][0]));
371
                                $template_text = str_replace($sugar_config['site_url'] . '/' . $sugar_config['site_url'], $sugar_config['site_url'], $template_text);
372
                            }
373
                        }
374
                    }
375
                }
376
                $return_array[$key] = $template_text;
377
            }
378
        }
379
        return $return_array;
380
    }
381
382
    /**
383
     *
384
     * Method for replace "preg_match_all" in method "parse_tracker_urls"
385
     * @param $text string String in which we need to search all string that match the pattern {.}
386
     * @return array result of search
387
     */
388
    private function _preg_match_tracker_url($text)
389
    {
390
        $result = array();
391
        $ind = 0;
392
        $switch = false;
393
        for ($i = 0; $i < strlen($text); $i++) {
394
            if ($text[$i] == '{') {
395
                $ind = $i;
396
                $switch = true;
397
            } elseif ($text[$i] == '}' && $switch === true) {
398
                $switch = false;
399
                array_push($result, array(substr($text, $ind, $i - $ind + 1), $ind));
400
            }
401
        }
402
        return array($result);
403
    }
404
405
    function parse_email_template($template_text_array, $focus_name, $focus, &$macro_nv)
406
    {
407
        global $beanList, $app_list_strings;
408
409
        // generate User instance that owns this "Contact" for contact_user_* macros
410
        $user = new User();
411
        if (isset($focus->assigned_user_id) && !empty($focus->assigned_user_id)) {
412
            $user->retrieve($focus->assigned_user_id);
413
        }
414
415
        if (!isset($this->parsed_entities))
416
            $this->parsed_entities = array();
417
418
        //parse the template and find all the dynamic strings that need replacement.
419
        // Bug #48111 It's strange why prefix for User module is contact_user (see self::generateFieldDefsJS method)
420
        if ($beanList[$focus_name] == 'User') {
421
            $pattern_prefix = '$contact_user_';
422
        } else {
423
            $pattern_prefix = '$' . strtolower($beanList[$focus_name]) . '_';
424
        }
425
        $pattern_prefix_length = strlen($pattern_prefix);
426
        $pattern = '/\\' . $pattern_prefix . '[A-Za-z_0-9]*/';
427
428
        $return_array = array();
429
        foreach ($template_text_array as $key => $template_text) {
430
            if (!isset($this->parsed_entities[$key])) {
431
                $matches = array();
432
                $count = preg_match_all($pattern, $template_text, $matches, PREG_OFFSET_CAPTURE);
433
434
                if ($count != 0) {
435
                    for ($i = ($count - 1); $i >= 0; $i--) {
436
                        if (!isset($matches[0][$i][2])) {
437
                            //find the field name in the bean.
438
                            $matches[0][$i][2] = substr($matches[0][$i][0], $pattern_prefix_length, strlen($matches[0][$i][0]) - $pattern_prefix_length);
439
440
                            //store the localized strings if the field is of type enum..
441
                            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'])) {
442
                                $matches[0][$i][3] = $focus->field_defs[$matches[0][$i][2]]['options'];
443
                            }
444
                        }
445
                    }
446
                }
447
                $this->parsed_entities[$key] = $matches;
448
            } else {
449
                $matches = $this->parsed_entities[$key];
450
                if (!empty($matches[0])) {
451
                    $count = count($matches[0]);
452
                } else {
453
                    $count = 0;
454
                }
455
            }
456
457
            for ($i = ($count - 1); $i >= 0; $i--) {
458
                $field_name = $matches[0][$i][2];
459
460
                // cn: feel for User object attribute key and assign as found
461
                if (strpos($field_name, "user_") === 0) {
462
                    $userFieldName = substr($field_name, 5);
463
                    $value = $user->$userFieldName;
464
                    //_pp($userFieldName."[{$value}]");
465
                } else {
466
                    $value = $focus->{$field_name};
467
                }
468
469
                //check dom
470
                if (isset($matches[0][$i][3])) {
471
                    if (isset($app_list_strings[$matches[0][$i][3]][$value])) {
472
                        $value = $app_list_strings[$matches[0][$i][3]][$value];
473
                    }
474
                }
475
476
                //generate name value pair array of macros and corresponding values for the targed.
477
                $macro_nv[$matches[0][$i][0]] = $value;
478
479
                $template_text = substr_replace($template_text, $value, $matches[0][$i][1], strlen($matches[0][$i][0]));
480
            }
481
482
            //parse the template for tracker url strings. patter for these strings in {[a-zA-Z_0-9]+}
483
484
            $return_array[$key] = $template_text;
485
        }
486
487
        return $return_array;
488
    }
489
490
    /**
491
     * Convenience method to convert raw value into appropriate type format
492
     * @param string $type
493
     * @param string $value
494
     * @return string
495
     */
496
    function _convertToType($type, $value)
497
    {
498
        switch ($type) {
499
            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...
500
                return currency_format_number($value);
501
            default:
502
                return $value;
503
        }
504
    }
505
506
    /**
507
     * Convenience method to parse for user's values in a template
508
     * @param array $repl_arr
509
     * @param object $user
510
     * @return array
511
     */
512
    function _parseUserValues($repl_arr, &$user)
513
    {
514
        foreach ($user->field_defs as $field_def) {
515
            if (($field_def['type'] == 'relate' && empty($field_def['custom_type'])) || $field_def['type'] == 'assigned_user_name') {
516
                continue;
517
            }
518
519
            $fieldName = $field_def['name'];
520
            if ($field_def['type'] == 'enum') {
521
                $translated = translate($field_def['options'], 'Users', $user->$fieldName);
522
523
                if (isset($translated) && !is_array($translated)) {
524
                    $repl_arr["contact_user_" . $fieldName] = $translated;
525
                } else { // unset enum field, make sure we have a match string to replace with ""
526
                    $repl_arr["contact_user_" . $fieldName] = '';
527
                }
528
            } else {
529
                if (isset($user->$fieldName)) {
530
                    // bug 47647 - allow for fields to translate before adding to template
531
                    $repl_arr["contact_user_" . $fieldName] = self::_convertToType($field_def['type'], $user->$fieldName);
532
                } else {
533
                    $repl_arr["contact_user_" . $fieldName] = "";
534
                }
535
            }
536
        }
537
538
        return $repl_arr;
539
    }
540
541
542
    function parse_template_bean($string, $bean_name, &$focus)
543
    {
544
        global $current_user;
545
        global $beanList;
546
        $repl_arr = array();
547
548
        // cn: bug 9277 - create a replace array with empty strings to blank-out invalid vars
549
        $acct = new Account();
550
        $contact = new Contact();
551
        $lead = new Lead();
552
        $prospect = new Prospect();
553
554
        foreach ($lead->field_defs as $field_def) {
555
            if (($field_def['type'] == 'relate' && empty($field_def['custom_type'])) || $field_def['type'] == 'assigned_user_name') {
556
                continue;
557
            }
558
            $repl_arr = EmailTemplate::add_replacement($repl_arr, $field_def, array(
559
                'contact_' . $field_def['name'] => '',
560
                'contact_account_' . $field_def['name'] => '',
561
            ));
562
        }
563
        foreach ($prospect->field_defs as $field_def) {
564
            if (($field_def['type'] == 'relate' && empty($field_def['custom_type'])) || $field_def['type'] == 'assigned_user_name') {
565
                continue;
566
            }
567
            $repl_arr = EmailTemplate::add_replacement($repl_arr, $field_def, array(
568
                'contact_' . $field_def['name'] => '',
569
                'contact_account_' . $field_def['name'] => '',
570
            ));
571
        }
572
        foreach ($contact->field_defs as $field_def) {
573
            if (($field_def['type'] == 'relate' && empty($field_def['custom_type'])) || $field_def['type'] == 'assigned_user_name') {
574
                continue;
575
            }
576
            $repl_arr = EmailTemplate::add_replacement($repl_arr, $field_def, array(
577
                'contact_' . $field_def['name'] => '',
578
                'contact_account_' . $field_def['name'] => '',
579
            ));
580
        }
581
        foreach ($acct->field_defs as $field_def) {
582
            if (($field_def['type'] == 'relate' && empty($field_def['custom_type'])) || $field_def['type'] == 'assigned_user_name') {
583
                continue;
584
            }
585
            $repl_arr = EmailTemplate::add_replacement($repl_arr, $field_def, array(
586
                'account_' . $field_def['name'] => '',
587
                'account_contact_' . $field_def['name'] => '',
588
            ));
589
        }
590
        // cn: end bug 9277 fix
591
592
593
        // feel for Parent account, only for Contacts traditionally, but written for future expansion
594
        if (isset($focus->account_id) && !empty($focus->account_id)) {
595
            $acct->retrieve($focus->account_id);
596
        }
597
598
        if ($bean_name == 'Contacts') {
599
            // cn: bug 9277 - email templates not loading account/opp info for templates
600
            if (!empty($acct->id)) {
601
                foreach ($acct->field_defs as $field_def) {
602
                    if (($field_def['type'] == 'relate' && empty($field_def['custom_type'])) || $field_def['type'] == 'assigned_user_name') {
603
                        continue;
604
                    }
605
606
                    $fieldName = $field_def['name'];
607
                    if ($field_def['type'] == 'enum') {
608
                        $translated = translate($field_def['options'], 'Accounts', $acct->$fieldName);
609
610
                        if (isset($translated) && !is_array($translated)) {
611
                            $repl_arr = EmailTemplate::add_replacement($repl_arr, $field_def, array(
612
                                'account_' . $fieldName => $translated,
613
                                'contact_account_' . $fieldName => $translated,
614
                            ));
615
                        } else { // unset enum field, make sure we have a match string to replace with ""
616
                            $repl_arr = EmailTemplate::add_replacement($repl_arr, $field_def, array(
617
                                'account_' . $fieldName => '',
618
                                'contact_account_' . $fieldName => '',
619
                            ));
620
                        }
621
                    } else {
622
                        // bug 47647 - allow for fields to translate before adding to template
623
                        $translated = self::_convertToType($field_def['type'], $acct->$fieldName);
624
                        $repl_arr = EmailTemplate::add_replacement($repl_arr, $field_def, array(
625
                            'account_' . $fieldName => $translated,
626
                            'contact_account_' . $fieldName => $translated,
627
                        ));
628
                    }
629
                }
630
            }
631
632
            if (!empty($focus->assigned_user_id)) {
633
                $user = new User();
634
                $user->retrieve($focus->assigned_user_id);
635
                $repl_arr = EmailTemplate::_parseUserValues($repl_arr, $user);
636
            }
637
        } elseif ($bean_name == 'Users') {
638
            /**
639
             * This section of code will on do work when a blank Contact, Lead,
640
             * etc. is passed in to parse the contact_* vars.  At this point,
641
             * $current_user will be used to fill in the blanks.
642
             */
643
            $repl_arr = EmailTemplate::_parseUserValues($repl_arr, $current_user);
644
        } else {
645
            // assumed we have an Account in focus
646
            foreach ($contact->field_defs as $field_def) {
647
                if (($field_def['type'] == 'relate' && empty($field_def['custom_type'])) || $field_def['type'] == 'assigned_user_name' || $field_def['type'] == 'link') {
648
                    continue;
649
                }
650
651
                $fieldName = $field_def['name'];
652
                if ($field_def['type'] == 'enum') {
653
                    $translated = translate($field_def['options'], 'Accounts', $contact->$fieldName);
654
655
                    if (isset($translated) && !is_array($translated)) {
656
                        $repl_arr = EmailTemplate::add_replacement($repl_arr, $field_def, array(
657
                            'contact_' . $fieldName => $translated,
658
                            'contact_account_' . $fieldName => $translated,
659
                        ));
660
                    } else { // unset enum field, make sure we have a match string to replace with ""
661
                        $repl_arr = EmailTemplate::add_replacement($repl_arr, $field_def, array(
662
                            'contact_' . $fieldName => '',
663
                            'contact_account_' . $fieldName => '',
664
                        ));
665
                    }
666
                } else {
667
                    if (isset($contact->$fieldName)) {
668
                        // bug 47647 - allow for fields to translate before adding to template
669
                        $translated = self::_convertToType($field_def['type'], $contact->$fieldName);
670
                        $repl_arr = EmailTemplate::add_replacement($repl_arr, $field_def, array(
671
                            'contact_' . $fieldName => $translated,
672
                            'contact_account_' . $fieldName => $translated,
673
                        ));
674
                    } // if
675
                }
676
            }
677
        }
678
679
        ///////////////////////////////////////////////////////////////////////
680
        ////	LOAD FOCUS DATA INTO REPL_ARR
681
        foreach ($focus->field_defs as $field_def) {
682
            $fieldName = $field_def['name'];
683
            if (isset($focus->$fieldName)) {
684
                if (($field_def['type'] == 'relate' && empty($field_def['custom_type'])) || $field_def['type'] == 'assigned_user_name') {
685
                    continue;
686
                }
687
688
                if ($field_def['type'] == 'enum' && isset($field_def['options'])) {
689
                    $translated = translate($field_def['options'], $bean_name, $focus->$fieldName);
690
691
                    if (isset($translated) && !is_array($translated)) {
692
                        $repl_arr = EmailTemplate::add_replacement($repl_arr, $field_def, array(
693
                            strtolower($beanList[$bean_name]) . "_" . $fieldName => $translated,
694
                        ));
695
                    } else { // unset enum field, make sure we have a match string to replace with ""
696
                        $repl_arr = EmailTemplate::add_replacement($repl_arr, $field_def, array(
697
                            strtolower($beanList[$bean_name]) . "_" . $fieldName => '',
698
                        ));
699
                    }
700
                } else {
701
                    // bug 47647 - translate currencies to appropriate values
702
                    $repl_arr = EmailTemplate::add_replacement($repl_arr, $field_def, array(
703
                        strtolower($beanList[$bean_name]) . "_" . $fieldName => self::_convertToType($field_def['type'], $focus->$fieldName),
704
                    ));
705
                }
706
            } else {
707
                if ($fieldName == 'full_name') {
708
                    $repl_arr = EmailTemplate::add_replacement($repl_arr, $field_def, array(
709
                        strtolower($beanList[$bean_name]) . '_full_name' => $focus->get_summary_text(),
710
                    ));
711
                } else {
712
                    $repl_arr = EmailTemplate::add_replacement($repl_arr, $field_def, array(
713
                        strtolower($beanList[$bean_name]) . "_" . $fieldName => '',
714
                    ));
715
                }
716
            }
717
        } // end foreach()
718
719
        krsort($repl_arr);
720
        reset($repl_arr);
721
        //20595 add nl2br() to respect the multi-lines formatting
722
        if (isset($repl_arr['contact_primary_address_street'])) {
723
            $repl_arr['contact_primary_address_street'] = nl2br($repl_arr['contact_primary_address_street']);
724
        }
725
        if (isset($repl_arr['contact_alt_address_street'])) {
726
            $repl_arr['contact_alt_address_street'] = nl2br($repl_arr['contact_alt_address_street']);
727
        }
728
729
        foreach ($repl_arr as $name => $value) {
730
            if ($value != '' && is_string($value)) {
731
                $string = str_replace("\$$name", $value, $string);
732
            } else {
733
                $string = str_replace("\$$name", ' ', $string);
734
            }
735
        }
736
737
        return $string;
738
    }
739
740
    /**
741
     * Add replacement(s) to the collection based on field definition
742
     *
743
     * @param array $data
744
     * @param array $field_def
745
     * @param array $replacement
746
     * @return array
747
     */
748
    protected static function add_replacement($data, $field_def, $replacement)
749
    {
750
        foreach ($replacement as $key => $value) {
751
            // @see defect #48641
752
            if ('multienum' == $field_def['type']) {
753
                $value = implode(', ', unencodeMultienum($value));
754
            }
755
            $data[$key] = $value;
756
        }
757
        return $data;
758
    }
759
760
    function parse_template($string, &$bean_arr)
761
    {
762
        foreach ($bean_arr as $bean_name => $bean_id) {
763
764
            $focus = BeanFactory::getBean($bean_name,$bean_id);
765
766
            if ($bean_name == 'Leads' || $bean_name == 'Prospects') {
767
                $bean_name = 'Contacts';
768
            }
769
770
            if (isset($this) && isset($this->module_dir) && $this->module_dir == 'EmailTemplates') {
771
                $string = $this->parse_template_bean($string, $bean_name, $focus);
772
            } else {
773
                $string = EmailTemplate::parse_template_bean($string, $bean_name, $focus);
774
            }
775
        }
776
        return $string;
777
    }
778
779
    function bean_implements($interface)
780
    {
781
        switch ($interface) {
782
            case 'ACL':
783
                return true;
784
        }
785
        return false;
786
    }
787
788
    static function getTypeOptionsForSearch()
789
    {
790
        $template = new EmailTemplate();
791
        $optionKey = $template->field_defs['type']['options'];
792
        $options = $GLOBALS['app_list_strings'][$optionKey];
793
        if (!is_admin($GLOBALS['current_user']) && isset($options['workflow']))
794
            unset($options['workflow']);
795
796
        return $options;
797
    }
798
799
    function is_used_by_email_marketing()
800
    {
801
        $query = "select id from email_marketing where template_id='$this->id' and deleted=0";
802
        $result = $this->db->query($query);
803
        if ($this->db->fetchByAssoc($result)) {
804
            return true;
805
        }
806
        return false;
807
    }
808
809
    /**
810
     * Allows us to save variables of template as they are
811
     */
812
    public function cleanBean()
813
    {
814
        $this->storedVariables = array();
815
        $this->body_html = preg_replace_callback('/\{::[^}]+::\}/', array($this, 'storeVariables'), $this->body_html);
816
        parent::cleanBean();
817
        $this->body_html = str_replace(array_values($this->storedVariables), array_keys($this->storedVariables), $this->body_html);
818
    }
819
820
    /**
821
     * Replacing variables of templates by their md5 hash
822
     *
823
     * @param array $text result of preg_replace_callback
824
     * @return string md5 hash of result
825
     */
826
    protected function storeVariables($text)
827
    {
828
        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...
829
            $this->storedVariables[$text[0]] = md5($text[0]);
830
        }
831
        return $this->storedVariables[$text[0]];
832
    }
833
834
    public function save($check_notify = FALSE)
835
    {
836
        $this->repairMozaikClears();
837
        return parent::save($check_notify);
838
    }
839
840
    public function retrieve($id = -1, $encode = true, $deleted = true)
841
    {
842
        $ret = parent::retrieve($id, $encode, $deleted);
843
        $this->repairMozaikClears();
844
        $this->imageLinkReplaced = false;
845
        $this->repairEntryPointImages();
846
        if($this->imageLinkReplaced) {
847
            $this->save();
848
        }
849
        return $ret;
850
    }
851
852
    private function repairMozaikClears() {
853
        // repair tinymce auto correction in mozaik clears
854
        $this->body_html = str_replace('&lt;div class=&quot;mozaik-clear&quot;&gt;&nbsp;&lt;br&gt;&lt;/div&gt;', '&lt;div class=&quot;mozaik-clear&quot;&gt;&lt;/div&gt;', $this->body_html);
855
    }
856
857
858
859
    private function repairEntryPointImages() {
860
        global $sugar_config;
861
862
        // repair the images url at entry points, change to a public direct link for remote email clients..
863
864
        $siteUrlQuoted = str_replace(array(':', '/'), array('\:', '\/'), $sugar_config['site_url']);
865
        $regex = '/&lt;img src=&quot;(' . $siteUrlQuoted . '\/index\.php\?entryPoint=download&type=Notes&id=([a-f0-9]{8}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{12})&filename=[^&]+)&quot;/';
866
867
        if(preg_match($regex, $this->body_html, $match)) {
868
            $splits = explode('.', $match[1]);
869
            $fileExtension = end($splits);
870
            $this->makePublicImage($match[2]);
871
            $directLink = '&lt;img src=&quot;' . $sugar_config['site_url'] . '/public/' . $match[2] . '.' . $fileExtension . '&quot;';
872
            $this->body_html = str_replace($match[0], $directLink, $this->body_html);
873
            $this->imageLinkReplaced = true;
874
            $this->repairEntryPointImages();
875
        }
876
877
    }
878
879
    private function makePublicImage($id) {
880
        $toFile = 'public/' . $id . '.jpg';
881
        if(file_exists($toFile)) {
882
            return;
883
        }
884
        $fromFile = 'upload://' . $id;
885
        if(!file_exists($fromFile)) {
886
            throw new Exceptin('file not found');
887
        }
888
        if(!file_exists('public')) {
889
            sugar_mkdir('public', 777);
890
        }
891
        $fdata = file_get_contents($fromFile);
892
        if(!file_put_contents($toFile, $fdata)) {
893
            throw new Exception('file write error');
894
        }
895
    }
896
897
    public function getAttachments() {
898
        return BeanFactory::getBean('Notes')->get_full_list('', "parent_id = '" . $this->id . "'");
899
    }
900
901
}
902
903
?>
904