jjwg_MapsController::action_geocode_addresses()   F
last analyzed

Complexity

Conditions 38
Paths > 20000

Size

Total Lines 144
Code Lines 66

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 1482
Metric Value
cc 38
eloc 66
nc 55326
nop 0
dl 0
loc 144
ccs 0
cts 85
cp 0
crap 1482
rs 2

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
3
if (!defined('sugarEntry') || !sugarEntry)
4
    die('Not A Valid Entry Point');
5
6
// modules/jjwg_Maps/controller.php
7
8
require_once('include/utils.php');
9
require_once('include/export_utils.php');
10
require_once("include/Sugar_Smarty.php");
11
require_once('modules/jjwg_Maps/jjwg_Maps.php');
12
13
class jjwg_MapsController extends SugarController {
14
15
    /**
16
     * @var settings array
17
     */
18
    var $settings = array();
19
20
    /**
21
     * $map_marker_data_points is used to store temporary data and prevent duplicate points
22
     * @var array
23
     */
24
    var $map_marker_data_points = array();
25
26
    /**
27
     * @var google_maps_response_codes
28
     *
29
     */
30
    var $google_maps_response_codes = array('OK', 'ZERO_RESULTS', 'INVALID_REQUEST', 'OVER_QUERY_LIMIT', 'REQUEST_DENIED');
31
32
    /**
33
     * Last Geocoding Status Message
34
     * @var string
35
     */
36
    var $last_status = '';
37
38
    /**
39
     * display_object - display module's object (dom field)
40
     * @var object
41
     */
42
    var $display_object;
43
44
    /**
45
     * relate_object - relate module's object
46
     * @var object
47
     */
48
    var $relate_object;
49
50
    /**
51
     * jjwg_Maps - Maps module's object
52
     * @var object
53
     */
54
    var $bean;
55
    var $jjwg_Maps; // Deprecated reference
56
57
    /**
58
     * jjwg_Address_Cache - Address cache module's object
59
     * @var object
60
     */
61
    var $jjwg_Address_Cache;
62
63
    /**
64
     * smarty object for the generic configuration template
65
     * @var object
66
     */
67
    var $sugarSmarty;
68
69
70
    /**
71
     * Constructor
72
     */
73
    function __construct() {
74
75
        parent::__construct();
76
        // Admin Config Setting
77
        $this->configuration();
78
    }
79
80
    /**
81
     * @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
82
     */
83
    function jjwg_MapsController(){
84
        $deprecatedMessage = 'PHP4 Style Constructors are deprecated and will be remove in 7.8, please update your code';
85
        if(isset($GLOBALS['log'])) {
86
            $GLOBALS['log']->deprecated($deprecatedMessage);
87
        }
88
        else {
89
            trigger_error($deprecatedMessage, E_USER_DEPRECATED);
90
        }
91
        self::__construct();
92
    }
93
94
95
    /**
96
     * Load Configuration Settings using Administration Module
97
     * See jjwg_Maps module for settings
98
     *
99
     * $GLOBALS['jjwg_config_defaults']
100
     * $GLOBALS['jjwg_config']
101
     */
102
    function configuration() {
103
104
        $this->bean = new jjwg_Maps();
105
        $this->jjwg_Maps = &$this->bean; // Set deprecated reference
106
        $this->settings = $GLOBALS['jjwg_config'];
107
    }
108
109
    /**
110
     * action geocoded_counts
111
     * Google Maps - Geocode the Addresses
112
     */
113
    function action_geocoded_counts() {
114
115
        $this->view = 'geocoded_counts';
116
        $GLOBALS['log']->debug(__METHOD__.' START');
117
118
        $this->bean->geocoded_counts = array();
119
        $this->bean->geocoded_headings = array('N/A');
120
        $this->bean->geocoded_module_totals = array();
121
122
        $responses = array('N/A' => '');
123
        foreach ($this->google_maps_response_codes as $code) {
124
            if (!in_array($code, array('OVER_QUERY_LIMIT', 'REQUEST_DENIED'))) {
125
                $responses[$code] = $code;
126
                $this->bean->geocoded_headings[] = $code;
127
            }
128
        }
129
        $responses['Approximate'] = 'APPROXIMATE';
130
        $responses['Empty'] = 'Empty';
131
        $this->bean->geocoded_headings[] = 'Approximate';
132
        $this->bean->geocoded_headings[] = 'Empty';
133
134
        // foreach module
135
        foreach ($this->settings['valid_geocode_modules'] as $module_type) {
136
137
            if (!isset($this->bean->geocoded_counts[$module_type])) {
138
                $this->bean->geocoded_module_totals[$module_type] = 0;
139
            }
140
141
            // Define display object from the necessary classes (utils.php)
142
            $this->display_object = get_module_info($module_type);
143
144
            foreach ($responses as $response => $code) {
145
146
                // Create Simple Count Query
147
                // 09/23/2010: Do not use create_new_list_query() and process_list_query()
148
                // as they will typically exceeded memory allowed.
149
                $query = "SELECT count(*) c FROM " . $this->display_object->table_name .
150
                        " LEFT JOIN " . $this->display_object->table_name . "_cstm " .
151
                        " ON " . $this->display_object->table_name . ".id = " . $this->display_object->table_name . "_cstm.id_c " .
152
                        " WHERE " . $this->display_object->table_name . ".deleted = 0 AND ";
153
                if ($response == 'N/A') {
154
                    $query .= "(" . $this->display_object->table_name . "_cstm.jjwg_maps_geocode_status_c = '' OR " .
155
                            $this->display_object->table_name . "_cstm.jjwg_maps_geocode_status_c IS NULL)";
156
                } else {
157
                    $query .= $this->display_object->table_name . "_cstm.jjwg_maps_geocode_status_c = '" . $code . "'";
158
                }
159
                //var_dump($query);
160
                $count_result = $this->bean->db->query($query);
161
                $count = $this->bean->db->fetchByAssoc($count_result);
162
                if (empty($count)) $count['c'] = 0;
163
                $this->bean->geocoded_counts[$module_type][$response] = $count['c'];
164
            } // end foreach response type
165
            // Get Totals
166
            $this->bean->geocoded_module_totals[$module_type]++;
167
            $query = "SELECT count(*) c FROM " . $this->display_object->table_name . " WHERE " . $this->display_object->table_name . ".deleted = 0";
168
            //var_dump($query);
169
            $count_result = $this->bean->db->query($query);
170
            $count = $this->bean->db->fetchByAssoc($count_result);
171
            $this->bean->geocoded_module_totals[$module_type] = $count['c'];
172
        } // end each module type
173
    }
174
175
    /**
176
     * action geocode_addresses
177
     * Google Maps - Geocode the Addresses
178
     */
179
    function action_geocode_addresses() {
180
181
        $GLOBALS['log']->debug(__METHOD__.' START');
182
183
        if (!empty($_REQUEST['display_module']) && in_array($_REQUEST['display_module'], $this->settings['valid_geocode_modules'])) {
184
            $geocode_modules = array($_REQUEST['display_module']);
185
        } else {
186
            $geocode_modules = $this->settings['valid_geocode_modules'];
187
        }
188
        $geocoding_inc = 0;
189
        $google_geocoding_inc = 0;
190
        // Define Address Cache Object
191
        $this->jjwg_Address_Cache = get_module_info('jjwg_Address_Cache');
192
193
194
        foreach ($geocode_modules as $module_type) {
195
196
            $GLOBALS['log']->debug(__METHOD__.' $module_type: '.$module_type);
197
            // Define display object from the necessary classes (utils.php)
198
            $this->display_object = get_module_info($module_type);
199
200
            // Find the Items to Geocode - Get Geocode Addresses Result
201
            $display_result = $this->bean->getGeocodeAddressesResult($this->display_object->table_name);
202
203
            /*
204
             * Iterate through the display rows
205
             * We build up an array here to prevent locking issues on some DBs (looking at you MSSQL)
206
             */
207
            $tmpDisplayResults = array();
208
            while ($display = $this->bean->db->fetchByAssoc($display_result)) {
209
                $tmpDisplayResults[] = $display;
210
            }
211
            foreach($tmpDisplayResults as $display){
212
213
                $GLOBALS['log']->debug(__METHOD__.' $display[\'id\': '.$display['id']);
214
                $geocoding_inc++;
215
                $aInfo = array();
216
                $cache_found = false;
217
218
                // Get address info array (address, status, lat, lng) from defineMapsAddress()
219
                // This will provide a related address & optionally a status, lat and lng from an account or other object
220
                $aInfo = $this->bean->defineMapsAddress($this->display_object->object_name, $display);
221
                //var_dump($aInfo);
222
223
                // Call Controller Method to Define Custom Address Logic
224
                $aInfo = $this->defineMapsAddressCustom($aInfo, $this->display_object->object_name, $display);
225
                //var_dump($aInfo);
226
227
                // If needed, check the Address Cache Module for Geocode Info
228
                if (!empty($aInfo['address']) && is_object($this->jjwg_Address_Cache)) {
229
                    $aInfoCache = $this->jjwg_Address_Cache->getAddressCacheInfo($aInfo);
230
                    if (!empty($aInfoCache['address'])) {
231
                        $cache_found = true;
232
                        $aInfo = $aInfoCache;
233
                    }
234
                }
235
236
                // If needed, Google Maps V3. Geocode the current address (status not set)
237
                if (!empty($aInfo['address']) && empty($aInfo['status'])) {
238
                    // Limit Geocode Requests to Google based on $this->settings['google_geocoding_limit']
239
                    if ($google_geocoding_inc < $this->settings['google_geocoding_limit']) {
240
                        $aInfoGoogle = $this->bean->getGoogleMapsGeocode($aInfo['address'], false, false);
241
                        if (!empty($aInfoGoogle)) {
242
                            $aInfo = $aInfoGoogle;
243
                            // Set last status
244
                            $this->last_status = $aInfo['status'];
245
                        }
246
                        $google_geocoding_inc++;
247
                    }
248
                }
249
250
                if (empty($aInfo['status'])) {
251
                    $aInfo['status'] = '';
252
                }
253
                if (empty($aInfo['lat']) || !is_numeric($aInfo['lat'])) {
254
                    $aInfo['lat'] = 0;
255
                }
256
                if (empty($aInfo['lng']) || !is_numeric($aInfo['lng'])) {
257
                    $aInfo['lng'] = 0;
258
                }
259
260
                // Successful geocode
261
                // 'OK' Status
262
                if (!empty($aInfo['address']) && $aInfo['status'] == 'OK' &&
263
                        !($aInfo['lng'] == 0 && $aInfo['lat'] == 0)) {
264
265
                    // Save Geocode $aInfo to custom fields
266
                    $update_result = $this->bean->updateGeocodeInfoByAssocQuery($this->display_object->table_name, $display, $aInfo);
267
268
                    // Save address, lng and lat to cache module - if not already found from cache
269
                    if (!$cache_found) {
270
                        $cache_save_result = $this->jjwg_Address_Cache->saveAddressCacheInfo($aInfo);
271
                    }
272
273
                // Bad Geocode Results - Recorded
274
                // Empty Address - indicates no address, no geocode response
275
                // 'ZERO_RESULTS' - indicates that the geocode was successful but returned no results.
276
                //     This may occur if the geocode was passed a non-existent address.
277
                // 'INVALID_REQUEST' - generally indicates that the query (address) is missing.
278
                // Also, capture empty $aInfo or address.
279
                } elseif (empty($aInfo) || empty($aInfo['address']) || (!empty($aInfo['address']) &&
280
                        ($aInfo['status'] == 'ZERO_RESULTS' || $aInfo['status'] == 'INVALID_REQUEST' ||
281
                        $aInfo['status'] == 'APPROXIMATE'))) {
282
283
                    if (empty($aInfo['status'])) {
284
                        $aInfo['status'] = 'Empty';
285
                    }
286
                    // Save Geocode $aInfo to custom fields
287
                    $update_result = $this->bean->updateGeocodeInfoByAssocQuery($this->display_object->table_name, $display, $aInfo);
288
289
                // Bad Geocode Results - Stop
290
                // 'OVER_QUERY_LIMIT' - indicates that you are over your quota.
291
                // 'REQUEST_DENIED' - indicates that your request was denied, generally because of lack of a sensor parameter.
292
                } elseif (!empty($aInfo['address']) &&
293
                        ($aInfo['status'] == 'OVER_QUERY_LIMIT' || $aInfo['status'] == 'REQUEST_DENIED')) {
294
295
                    // Set above limit to break/stop processing
296
                    $geocoding_inc = $this->settings['geocoding_limit'] + 1;
297
                } // end if/else
298
299
                // Wait 1 Second to Throttle Requests: Rate limit of 10 geocodings per second
300
                if ($geocoding_inc % 10 == 0)
301
                    sleep(1);
302
303
                if ($geocoding_inc > $this->settings['geocoding_limit'])
304
                    break;
305
            } // while
306
307
            if ($geocoding_inc > $this->settings['geocoding_limit'])
308
                break;
309
        } // end each module type
310
311
        // If not cron processing, then redirect.
312
        if (!isset($_REQUEST['cron'])) {
313
            // Redirect to the Geocoded Counts Display
314
            // contains header and exit
315
            $url = 'index.php?module=jjwg_Maps&action=geocoded_counts';
316
            if (!empty($this->last_status)) {
317
                $url .= '&last_status=' . urlencode($this->last_status);
318
            }
319
            SugarApplication::redirect($url);
320
        }
321
322
    }
323
324
325
    /**
326
     *  Add a number of display_module objects to a target list
327
     *  Return JSON encoded result count
328
     */
329
    function action_add_to_target_list() {
330
331
        $result = array('post' => $_POST);
332
333
        // Target List
334
        $list_id = (!empty($_POST['list_id'])) ? $_POST['list_id'] : '';
335
        $list = get_module_info('ProspectLists');
336
        if (!empty($list_id) && is_guid($list_id)) {
337
            $list->retrieve($list_id);
338
            $result['list'] = $list;
339
        }
340
        // Selected Area IDs - Validate
341
        $selected_ids = array();
342
        foreach ($_POST['selected_ids'] as $sel_id) {
343
            if (is_guid($sel_id)) {
344
                $selected_ids[] = $sel_id;
345
            }
346
        }
347
        $result['selected_ids'] = $selected_ids;
348
349
        // Display Module Type
350
        $module_type = '';
351
        if (!empty($_POST['display_module']) && in_array($_POST['display_module'], $this->settings['valid_geocode_modules'])) {
352
            $module_type = $_POST['display_module'];
353
            $result['module_type'] = $module_type;
354
            // Define display object
355
            $this->display_object = get_module_info($module_type);
356
        }
357
358
        if (!empty($list) && $list_id == $list->id && !empty($selected_ids) && !empty($this->display_object) &&
359
                in_array($this->display_object->module_name, array('Accounts', 'Contacts', 'Leads', 'Prospects', 'Users'))) {
360
361
            $object_name = $this->display_object->object_name;
362
            $result['object_name'] = $object_name;
363
364
            if ($object_name == 'Account') {
365
                $list->load_relationship('accounts');
366
                foreach ($selected_ids as $sel_id) {
367
                    $list->accounts->add($sel_id);
368
                }
369
            } elseif ($object_name == 'Contact') {
370
                $list->load_relationship('contacts');
371
                foreach ($selected_ids as $sel_id) {
372
                    $list->contacts->add($sel_id);
373
                }
374
            } elseif ($object_name == 'Lead') {
375
                $list->load_relationship('leads');
376
                foreach ($selected_ids as $sel_id) {
377
                    $list->leads->add($sel_id);
378
                }
379
            } elseif ($object_name == 'Prospect') {
380
                $list->load_relationship('prospects');
381
                foreach ($selected_ids as $sel_id) {
382
                    $list->prospects->add($sel_id);
383
                }
384
            } elseif ($object_name == 'User') {
385
                $list->load_relationship('users');
386
                foreach ($selected_ids as $sel_id) {
387
                    $list->users->add($sel_id);
388
                }
389
            }
390
            $result['message'] = 'Target List Updated';
391
        } else {
392
            $result['message'] = 'Target List NOT Updated';
393
        }
394
395
        // JSON Encoded $result
396
        header('Content-Type: application/json');
397
        echo @json_encode($result);
398
    }
399
400
    /**
401
     * export addresses in need of geocoding
402
     */
403
    function action_export_geocoding_addresses() {
404
405
        $address_data = array();
406
        $addresses = array();
407
408
        if (!empty($_REQUEST['display_module']) && in_array($_REQUEST['display_module'], $this->settings['valid_geocode_modules'])) {
409
            $module_type = $_REQUEST['display_module'];
410
        } else {
411
            $module_type = $this->settings['valid_geocode_modules'][0];
412
        }
413
        // Define display object
414
        $this->display_object = get_module_info($module_type);
415
416
        // Find the Items to Geocode - Get Geocode Addresses Result
417
        $display_result = $this->bean->getGeocodeAddressesResult($this->display_object->table_name, $this->settings['export_addresses_limit']);
418
419
        $address_data[] = array('address', 'lat', 'lng');
420
        // Iterate through the display rows
421
        while ($display = $this->bean->db->fetchByAssoc($display_result)) {
422
423
            // Get address info array (address, status, lat, lng) from defineMapsAddress()
424
            // This will provide a related address & optionally a status, lat and lng from an account or other object
425
            $aInfo = $this->bean->defineMapsAddress($this->display_object->object_name, $display);
426
            //var_dump($aInfo);
427
428
            // Call Method to Define Custom Address Logic
429
            $aInfo = $this->defineMapsAddressCustom($aInfo, $this->display_object->object_name, $display);
430
            //var_dump($aInfo);
431
432
            if (!empty($aInfo['address'])) {
433
                $addresses[] = trim($aInfo['address'], ' ,;."\'');
434
        }
435
        }
436
437
        $addresses = array_unique($addresses);
438
        foreach ($addresses as $address) {
439
            $address_data[] = array($address, '', '');
440
        }
441
442
        $filename = $module_type . '_Addresses_' . date("Ymd") . ".csv";
443
        $this->do_list_csv_output($address_data, $filename);
444
        exit;
445
    }
446
447
    /**
448
     * Custom Override for Defining Maps Address
449
     *
450
     * @param $aInfo        address info array(address, status, lat, lng)
451
     * @param $object_name  signular object name
452
     * @param $display      fetched row array
453
     */
454
    function defineMapsAddressCustom($aInfo, $object_name, $display) {
455
456
        // Use custom contoller.php with custom logic
457
        return $aInfo;
458
    }
459
460
    /**
461
     *
462
     * Export rows of data as a CSV file
463
     * @param unknown_type $rows
464
     * @param unknown_type $filename
465
     */
466
    private function do_list_csv_output($rows, $filename) {
467
468
        header("Content-type: application/octet-stream");
469
        header("Content-Disposition: attachment; filename=\"$filename\"");
470
        header("Content-Transfer-Encoding: binary");
471
        if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE')) {
472
            // IE cannot download from sessions without a cache
473
            header('Cache-Control: public');
474
        }
475
        foreach (array_keys($rows) as $key) {
476
            $row = $rows[$key];
477
            echo $this->list_row_to_csv($row);
478
        }
479
    }
480
481
    /**
482
     *
483
     * Create CSV row for export view
484
     * @param $fields name value pairs
485
     * @param $delimiter
486
     * @param $enclosure
487
     */
488
    private function list_row_to_csv($fields, $delimiter = ',', $enclosure = '"') {
489
490
        $delimiter_esc = preg_quote($delimiter, '/');
491
        $enclosure_esc = preg_quote($enclosure, '/');
492
        $output = array();
493
        foreach ($fields as $field) {
494
            $output[] = preg_match("/(?:${delimiter_esc}|${enclosure_esc}|\s)/", $field) ? (
495
                    $enclosure . str_replace($enclosure, $enclosure . $enclosure, $field) . $enclosure
496
                    ) : $field;
497
        }
498
499
        return (join($delimiter, $output) . "\n");
500
    }
501
502
    /**
503
     * action geocoding_test
504
     * Google Maps - Geocoding Test
505
     */
506
    function action_geocoding_test() {
507
508
        $this->view = 'geocoding_test';
509
510
        if (!empty($_REQUEST['geocoding_address']) && !empty($_REQUEST['process_trigger']) &&
511
                strlen($_REQUEST['geocoding_address']) <= 255) {
512
            $this->bean->geocoding_results = $this->bean->getGoogleMapsGeocode($_REQUEST['geocoding_address'], true, true);
513
        }
514
    }
515
516
    /**
517
     * action config
518
     * Google Maps - Config
519
     */
520
    function action_config() {
521
522
        // Admin Only
523
        if (!empty($GLOBALS['current_user']->is_admin)) {
524
            if (!empty($_REQUEST['submit'])) {
525
                // Post-Get-Redirect
526
                $save_result = $this->bean->saveConfiguration($_REQUEST);
527
                $config_save_notice = ($save_result == true) ? '1' : '0';
528
                SugarApplication::redirect('index.php?module=jjwg_Maps&action=config&config_save_notice='.$config_save_notice);
529
            } else {
530
                $this->view = 'config';
531
            }
532
        } else {
533
            SugarApplication::redirect('index.php?module=jjwg_Maps&action=index');
534
        }
535
    }
536
537
    /**
538
     * action reset module geocode info
539
     * Google Maps - geocoded_counts
540
     */
541
    function action_reset_geocoding() {
542
543
        $display_module = $_REQUEST['display_module'];
544
545
        // Define display object from the necessary classes (utils.php)
546
        $this->display_object = get_module_info($display_module);
547
548
        // Admin Only
549
        if (!empty($GLOBALS['current_user']->is_admin)) {
550
            if (is_object($this->display_object)) {
551
                $delete_result = $this->bean->deleteAllGeocodeInfoByBeanQuery($this->display_object);
552
                SugarApplication::redirect('index.php?module=jjwg_Maps&action=geocoded_counts');
553
            } else {
554
                $this->view = 'geocoded_counts';
555
            }
556
        } else {
557
            SugarApplication::redirect('index.php?module=jjwg_Maps&action=index');
558
        }
559
    }
560
561
    /**
562
     * delete all address cache
563
     * Google Maps - geocoded_counts
564
     */
565
    function action_delete_all_address_cache() {
566
567
        // Define Address Cache Object
568
        $this->jjwg_Address_Cache = get_module_info('jjwg_Address_Cache');
569
570
        // Admin Only
571
        if (!empty($GLOBALS['current_user']->is_admin)) {
572
            if (is_object($this->jjwg_Address_Cache)) {
573
                // Post-Get-Redirect
574
                $delete_result = $this->jjwg_Address_Cache->deleteAllAddressCache();
575
                SugarApplication::redirect('index.php?module=jjwg_Maps&action=geocoded_counts');
576
            } else {
577
                $this->view = 'geocoded_counts';
578
            }
579
        } else {
580
            SugarApplication::redirect('index.php?module=jjwg_Maps&action=index');
581
        }
582
    }
583
584
    /**
585
     * action quick_radius
586
     * Google Maps - Quick Radius Map
587
     */
588
    function action_quick_radius() {
589
590
        $this->view = 'quick_radius';
591
592
        if (!isset($_REQUEST['distance'])) $_REQUEST['distance'] = $this->settings['map_default_distance'];
593
        if (!isset($_REQUEST['unit_type'])) $_REQUEST['unit_type'] = $this->settings['map_default_unit_type'];
594
595
    }
596
597
    /**
598
     * action map_display
599
     * Google Maps - Output the Page with IFrame to Map Markers
600
     */
601
    function action_quick_radius_display() {
602
603
        $this->view = 'quick_radius_display';
604
    }
605
606
    /**
607
     * action map_display
608
     * Google Maps - Output the Page with IFrame to Map Markers
609
     */
610
    function action_map_display() {
611
612
        $this->view = 'map_display';
613
        if (!isset($_REQUEST['current_post'])) $_REQUEST['current_post'] = '';
614
615
        // Bug: 'current_post' too large for iFrame URL used in Google Library calls
616
        $_SESSION['jjwg_Maps']['current_post'] = $_REQUEST['current_post'];
617
        $_REQUEST['current_post'] = 'session';
618
    }
619
620
    /**
621
     * action donate
622
     * Google Maps - Output the Donate Page
623
     */
624
    function action_donate() {
625
626
        $this->view = 'donate';
627
    }
628
629
    /**
630
     * action map_markers
631
     * Google Maps - Output the Map Markers
632
     */
633
    function action_map_markers() {
634
635
        header_remove('X-Frame-Options');
636
        $this->view = 'map_markers';
637
638
        // Define globals for use in the view.
639
        $this->bean->map_center = array();
640
        $this->bean->map_markers = array();
641
        $this->bean->map_markers_groups = array();
642
        $this->bean->custom_markers = array();
643
        $this->bean->custom_areas = array();
644
645
        // Create New Sugar_Smarty Object
646
        $this->sugarSmarty = new Sugar_Smarty();
647
        $this->sugarSmarty->assign("mod_strings", $GLOBALS['mod_strings']);
648
        $this->sugarSmarty->assign("app_strings", $GLOBALS['app_strings']);
649
        $this->sugarSmarty->assign('app_list_strings', $GLOBALS['app_list_strings']);
650
        $this->sugarSmarty->assign('moduleListSingular', $GLOBALS['app_list_strings']['moduleListSingular']);
651
        $this->sugarSmarty->assign('moduleList', $GLOBALS['app_list_strings']['moduleList']);
652
        //echo '<pre>';
653
        //var_dump($_REQUEST);
654
655
        // Related Map Record Defines the Map
656
        if (!empty($_REQUEST['record']) ||
657
                (!empty($_REQUEST['relate_id']) && !empty($_REQUEST['relate_module'])) ||
658
                (!empty($_REQUEST['quick_address']) && !empty($_REQUEST['display_module']))) {
659
660
            // If map 'record' then define map details from current module.
661
            if (@is_guid($_REQUEST['record'])) {
662
                // Get the map object
663
                $map = get_module_info($GLOBALS['currentModule']);
664
                $map->retrieve($_REQUEST['record']);
665
                // Define map variables
666
                $map_parent_type = $map->parent_type;
667
                $map_parent_id = $map->parent_id;
668
                $map_module_type = $map->module_type;
669
                $map_unit_type = $map->unit_type;
670
                $map_distance = $map->distance;
671
            }
672
            // Else if a 'relate_id' use it as the Relate Center Point (Lng/Lat)
673
            else if (@(is_guid($_REQUEST['relate_id']) && !empty($_REQUEST['relate_module']))) {
674
                // Define map variables
675
                $map_parent_type = $_REQUEST['relate_module'];
676
                $map_parent_id = $_REQUEST['relate_id'];
677
                $map_module_type = (!empty($_REQUEST['display_module'])) ? $_REQUEST['display_module'] : $_REQUEST['relate_module'];
678
                $map_distance = (!empty($_REQUEST['distance'])) ? $_REQUEST['distance'] : $this->settings['map_default_distance'];
679
                $map_unit_type = (!empty($_REQUEST['unit_type'])) ? $_REQUEST['unit_type'] : $this->settings['map_default_unit_type'];
680
            }
681
            // Else if a 'quick_address' use it as the Center Point (Lng/Lat)
682
            else if (!empty($_REQUEST['quick_address']) && !empty($_REQUEST['display_module'])) {
683
                // Define map variables / No Parent
684
                $map_parent_type = null;
685
                $map_parent_id = null;
686
                $map_module_type = (!empty($_REQUEST['display_module'])) ? $_REQUEST['display_module'] : $_REQUEST['relate_module'];
687
                $map_distance = (!empty($_REQUEST['distance'])) ? $_REQUEST['distance'] : $this->settings['map_default_distance'];
688
                $map_unit_type = (!empty($_REQUEST['unit_type'])) ? $_REQUEST['unit_type'] : $this->settings['map_default_unit_type'];
689
            }
690
691
            // Define display object, note - 'Accounts_Members' is a special display type
692
            $this->display_object = ($map_module_type == 'Accounts_Members') ? get_module_info('Accounts') : get_module_info($map_module_type);
693
            $mod_strings_display = return_module_language($GLOBALS['current_language'], $this->display_object->module_name);
694
            $mod_strings_display = array_merge($mod_strings_display, $GLOBALS['mod_strings']);
695
696
            // If relate module/id object
697
            if (!empty($map_parent_type) && !empty($map_parent_id)) {
698
699
                // Define relate objects
700
                $this->relate_object = get_module_info($map_parent_type);
701
                $this->relate_object->retrieve($map_parent_id);
702
                $mod_strings_related = return_module_language($GLOBALS['current_language'], $this->relate_object->module_name);
703
                $mod_strings_related = array_merge($mod_strings_related, $GLOBALS['mod_strings']);
704
705
                // Get the Relate object Assoc Data
706
                $where_conds = $this->relate_object->table_name . ".id = '" . $map_parent_id . "'";
707
                $query = $this->relate_object->create_new_list_query("" . $this->relate_object->table_name . ".assigned_user_id", $where_conds, array(), array(), 0, '', false, $this->relate_object, false);
708
                //var_dump($query);
709
                $relate_result = $this->bean->db->query($query);
710
                $relate = $this->bean->db->fetchByAssoc($relate_result);
711
                // Add Relate (Center Point) Marker
712
                $this->bean->map_center = $this->getMarkerData($map_parent_type, $relate, true, $mod_strings_related);
713
                // Define Center Point
714
                $center_lat = $this->relate_object->jjwg_maps_lat_c;
715
                $center_lng = $this->relate_object->jjwg_maps_lng_c;
716
            }
717
            // Use Quick Address as Center Point
718
            else {
719
                // Geocode 'quick_address'
720
                $aInfo = $this->bean->getGoogleMapsGeocode($_REQUEST['quick_address'], false, true);
721
                // If not status 'OK', then fail here and exit. Note: Inside of iFrame
722
                if (!empty($aInfo['status']) && $aInfo['status'] != 'OK' && preg_match('/[A-Z\_]/', $aInfo['status'])) {
723
                    echo '<br /><br /><div><b>'.$GLOBALS['mod_strings']['LBL_MAP_LAST_STATUS'].': '.$aInfo['status'].'</b></div><br /><br />';
724
                    exit;
725
                }
726
                //var_dump($aInfo);
727
                // Define Marker Data
728
                $aInfo['name'] = $_REQUEST['quick_address'];
729
                $aInfo['id'] = 0;
730
                $aInfo['module'] = ($map_module_type == 'Accounts_Members') ? 'Accounts' : $map_module_type;
731
                $aInfo['address'] = $_REQUEST['quick_address'];
732
                $aInfo['jjwg_maps_address_c'] = $_REQUEST['quick_address'];
733
                $aInfo['jjwg_maps_lat_c'] = $aInfo['lat'];
734
                $aInfo['jjwg_maps_lng_c'] = $aInfo['lng'];
735
                $this->bean->map_center = $this->getMarkerData($map_parent_type, $aInfo, true);
736
                // Define Center Point
737
                $center_lat = $aInfo['lat'];
738
                $center_lng = $aInfo['lng'];
739
            }
740
            //var_dump($aInfo);
741
            // Define $x and $y expressions
742
            $x = '(69.1*((' . $this->display_object->table_name . '_cstm.jjwg_maps_lat_c)-(' . $center_lat . ')))';
743
            $y = '(53.0*((' . $this->display_object->table_name . '_cstm.jjwg_maps_lng_c)-(' . $center_lng . ')) * COS((' . $center_lat . ')/57.1))';
744
            $calc_distance_expression = 'SQRT(' . $x . '*' . $x . '+' . $y . '*' . $y . ')';
745
            if (strtolower($map_unit_type) == 'km' || strtolower($map_unit_type) == 'kilometer') {
746
                $calc_distance_expression .= '*1.609'; // 1 mile = 1.609 km
747
            }
748
749
            // Find the Items to Display
750
            // Assume there is no address at 0,0; it's in the Atlantic Ocean!
751
            $where_conds = "(" . $this->display_object->table_name . "_cstm.jjwg_maps_lat_c != 0 OR " .
752
                    "" . $this->display_object->table_name . "_cstm.jjwg_maps_lng_c != 0) " .
753
                    " AND " .
754
                    "(" . $this->display_object->table_name . "_cstm.jjwg_maps_geocode_status_c = 'OK')" .
755
                    " AND " .
756
                    "(" . $calc_distance_expression . " < " . $map_distance . ")";
757
            $query = $this->display_object->create_new_list_query('display_object_distance', $where_conds, array(), array(), 0, '', false, $this->display_object, false);
758
            // Add the disply_object_distance into SELECT list
759
            $query = str_replace('SELECT ', 'SELECT (' . $calc_distance_expression . ') AS display_object_distance, ', $query);
760
            if ($map_module_type == 'Contacts') { // Contacts - Account Name
761
                $query = str_replace(' FROM contacts ', ' ,accounts.name AS account_name, accounts.id AS account_id  FROM contacts  ', $query);
762
                $query = str_replace(' FROM contacts ', ' FROM contacts LEFT JOIN accounts_contacts ON contacts.id=accounts_contacts.contact_id and accounts_contacts.deleted = 0 LEFT JOIN accounts ON accounts_contacts.account_id=accounts.id AND accounts.deleted=0 ', $query);
763
            } elseif ($map_module_type == 'Opportunities') { // Opps - Account Name
764
                $query = str_replace(' FROM opportunities ', ' ,accounts.name AS account_name, accounts.id AS account_id  FROM opportunities  ', $query);
765
                $query = str_replace(' FROM opportunities ', ' FROM opportunities LEFT JOIN accounts_opportunities ON opportunities.id=accounts_opportunities.opportunity_id and accounts_opportunities.deleted = 0 LEFT JOIN accounts ON accounts_opportunities.account_id=accounts.id AND accounts.deleted=0 ', $query);
766
            } elseif ($map_module_type == 'Accounts_Members') { // 'Accounts_Members' is a special display type
767
                $query = str_replace(' AND accounts.deleted=0', ' AND accounts.deleted=0 AND accounts.parent_id = \''.$this->bean->db->quote($map_parent_id).'\'', $query);
768
            }
769
            //var_dump($query);
770
            $display_result = $this->bean->db->limitQuery($query, 0, $this->settings['map_markers_limit']);
771
            while ($display = $this->bean->db->fetchByAssoc($display_result)) {
772
                if (!empty($map_distance) && !empty($display['id'])) {
773
                    $marker_data_module_type = ($map_module_type == 'Accounts_Members') ? 'Accounts' : $map_module_type;
774
                    $marker_data = $this->getMarkerData($marker_data_module_type, $display, false, $mod_strings_display);
775
                    if (!empty($marker_data)) {
776
                        $this->bean->map_markers[] = $marker_data;
777
                    }
778
                }
779
            }
780
            //var_dump($this->bean->map_markers);
781
            // Next define the Custom Markers and Areas related to this Map
782
            // Define relate and display objects from the necessary classes (utils.php)
783
            @$markers_object = get_module_info('jjwg_Markers');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
784
            @$areas_object = get_module_info('jjwg_Areas');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
785
786
            // Relationship Names: jjwg_maps_jjwg_areas and jjwg_maps_jjwg_markers
787
            // Find the Related Beans: Maps to Markers
788
            if (@(is_object($markers_object) && is_object($map))) {
789
                $related_custom_markers = $map->get_linked_beans('jjwg_maps_jjwg_markers', 'jjwg_Markers');
790
                if ($related_custom_markers) {
791
                    foreach ($related_custom_markers as $marker_bean) {
792
                        $marker_data = $this->getMarkerDataCustom($marker_bean);
793
                        if (!empty($marker_data)) {
794
                            $this->bean->custom_markers[] = $marker_data;
795
                        }
796
                    }
797
                }
798
            }
799
800
            // Find the Related Beans: Maps to Areas
801
            if (@(is_object($areas_object) && is_object($map))) {
802
                $related_custom_areas = $map->get_linked_beans('jjwg_maps_jjwg_areas', 'jjwg_Areas');
803
                if ($related_custom_areas) {
804
                    foreach ($related_custom_areas as $area_bean) {
805
                        $area_data = $this->getAreaDataCustom($area_bean);
806
                        if (!empty($area_data)) {
807
                            $this->bean->custom_areas[] = $area_data;
808
                        }
809
                    }
810
                }
811
            }
812
813
814
            // Map Target List (ProspectLists)
815
        } elseif (!empty($_REQUEST['list_id'])) {
816
817
            $this->bean->map_markers = array();
818
            $this->display_object = get_module_info('ProspectLists');
819
            // Use the Export Query
820
            if (!empty($_REQUEST['list_id'])) {
821
                $this->display_object->retrieve($_REQUEST['list_id']);
822
                if ($this->display_object->id == $_REQUEST['list_id']) {
823
                    $prospect_list_object = $this->display_object;
824
                    $list_id = $this->display_object->id;
825
                }
826
            }
827
828
            if (!empty($list_id)) {
829
830
                $list_modules = array('Accounts', 'Contacts', 'Leads', 'Users', 'Prospects');
831
                $temp_marker_groups = array();
832
833
                foreach ($list_modules as $display_module) {
834
835
                    $this->display_object = get_module_info($display_module);
836
                    $mod_strings_display = return_module_language($GLOBALS['current_language'], $this->display_object->module_name);
837
                    $mod_strings_display = array_merge($mod_strings_display, $GLOBALS['mod_strings']);
838
839
                    // Find the Items to Display
840
                    // Assume there is no address at 0,0; it's in the Atlantic Ocean!
841
                    $where_conds = "(" . $this->display_object->table_name . "_cstm.jjwg_maps_lat_c != 0 OR " .
842
                            "" . $this->display_object->table_name . "_cstm.jjwg_maps_lng_c != 0) " .
843
                            " AND " .
844
                            "(" . $this->display_object->table_name . "_cstm.jjwg_maps_geocode_status_c = 'OK')";
845
                    $query = $this->display_object->create_new_list_query('', $where_conds, array(), array(), 0, '', false, $this->display_object, false);
846
                    if ($display_module == 'Contacts') { // Contacts - Account Name
847
                        $query = str_replace(' FROM contacts ', ' ,accounts.name AS account_name, accounts.id AS account_id  FROM contacts  ', $query);
848
                        $query = str_replace(' FROM contacts ', ' FROM contacts LEFT JOIN accounts_contacts ON contacts.id=accounts_contacts.contact_id and accounts_contacts.deleted = 0 LEFT JOIN accounts ON accounts_contacts.account_id=accounts.id AND accounts.deleted=0 ', $query);
849
                    }
850
                    // Add List JOIN
851
                    $query = str_replace(' FROM '.$this->display_object->table_name.' ', ' FROM '.$this->display_object->table_name.' '.
852
                            'LEFT JOIN prospect_lists_prospects ON prospect_lists_prospects.related_id = '.$this->display_object->table_name.'.id AND prospect_lists_prospects.deleted=0 '.
853
                            'LEFT JOIN prospect_lists ON prospect_lists_prospects.prospect_list_id = prospect_lists.id AND prospect_lists.deleted=0 ',
854
                            $query);
855
                    // Restrict WHERE to related type and $list_id
856
                    $query .= ' AND prospect_lists_prospects.related_type = \''.$this->display_object->module_name.'\' AND '.
857
                            'prospect_lists.id = \''.$this->bean->db->quote($list_id).'\'';
858
                    //var_dump($query);
859
                    $display_result = $this->bean->db->limitQuery($query, 0, $this->settings['map_markers_limit']);
860
                    $display_type_found = false;
861
                    while ($display = $this->bean->db->fetchByAssoc($display_result)) {
862
                        if (!empty($display['id'])) {
863
                            $marker_data = $this->getMarkerData($display_module, $display, false, $mod_strings_display);
864
                            $marker_data['group'] = $GLOBALS['app_list_strings']['moduleList'][$display_module];
865
                            if (!empty($marker_data)) {
866
                                $this->bean->map_markers[] = $marker_data;
867
                            }
868
                            $display_type_found = true;
869
                        }
870
                    }
871
                    if ($display_type_found) {
872
                        $temp_marker_groups[] = $GLOBALS['app_list_strings']['moduleList'][$display_module];
873
                    }
874
875
                }
876
877
                $this->bean->map_markers_groups = $temp_marker_groups;
878
            }
879
880
881
            // Map Records
882
        } elseif (!empty($_REQUEST['uid']) || !empty($_REQUEST['current_post'])) {
883
884
            if (in_array($_REQUEST['display_module'], $this->settings['valid_geocode_modules'])) {
885
                $display_module = $_REQUEST['display_module'];
886
            } else {
887
                $display_module = 'Accounts';
888
            }
889
            if ($_REQUEST['current_post'] == 'session') {
890
                $current_post = $_SESSION['jjwg_Maps']['current_post'];
891
            } else {
892
                $current_post = $_REQUEST['current_post'];
893
            }
894
            $query = '';
895
            $selected_query = '';
896
            $records = array();
897
            $order_by = '';
898
899
            $this->display_object = get_module_info($display_module);
900
            $mod_strings_display = return_module_language($GLOBALS['current_language'], $this->display_object->module_name);
901
            $mod_strings_display = array_merge($mod_strings_display, $GLOBALS['mod_strings']);
902
903
            if (!empty($_REQUEST['uid'])) {
904
                // Several records selected or this page
905
                $records = explode(',', $_REQUEST['uid']);
906
            } elseif (!empty($current_post)) {
907
                // Select all records (advanced search)
908
                $search_array = generateSearchWhere($display_module, $current_post);
909
                //var_dump($search_array);
910
                if (!empty($search_array['where'])) {
911
                    // Related Field Bug: Get relate/link patched 'where' and 'join'
912
                    @$ret_array = create_export_query_relate_link_patch($display_module, $search_array['searchFields'], $search_array['where']);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
913
                    if(!empty($ret_array['join'])) {
914
                        @$selected_query = $this->display_object->create_export_query($order_by, $ret_array['where'], $ret_array['join']);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
915
                    } else {
916
                        @$selected_query = $this->display_object->create_export_query($order_by, $ret_array['where']);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
917
                    }
918
                    // SugarOnDemand JOIN Bug: If $ret_array['join'] is not included in query, force it in!
919
                    if (strpos($ret_array['join'], $selected_query) === false) {
920
                        $selected_query = str_replace(' where ', $ret_array['join'].' where ', $selected_query);
921
                    }
922
                    // Avoiding subquery. Let's just record the record ID's for later
923
                    $selected_result = $this->bean->db->limitQuery($selected_query, 0, $this->settings['map_markers_limit']);
924
                    while ($display = $this->bean->db->fetchByAssoc($selected_result)) {
925
                        $records[] = $display['id'];
926
                    }
927
                }
928
            }
929
            //var_dump($records);
930
931
            // Find the Items to Display
932
            // Assume there is no address at 0,0; it's in the Atlantic Ocean!
933
            $where_conds = "(" . $this->display_object->table_name . "_cstm.jjwg_maps_lat_c != 0 OR " .
934
                    "" . $this->display_object->table_name . "_cstm.jjwg_maps_lng_c != 0) " .
935
                    " AND " .
936
                    "(" . $this->display_object->table_name . "_cstm.jjwg_maps_geocode_status_c = 'OK')";
937
            $query = $this->display_object->create_new_list_query('', $where_conds, array(), array(), 0, '', false, $this->display_object, false);
938
            if ($display_module == 'Contacts') { // Contacts - Account Name
939
                $query = str_replace(' FROM contacts ', ' ,accounts.name AS account_name, accounts.id AS account_id  FROM contacts  ', $query);
940
                $query = str_replace(' FROM contacts ', ' FROM contacts LEFT JOIN accounts_contacts ON contacts.id=accounts_contacts.contact_id and accounts_contacts.deleted = 0 LEFT JOIN accounts ON accounts_contacts.account_id=accounts.id AND accounts.deleted=0 ', $query);
941
            } elseif ($display_module == 'Opportunities') { // Opps - Account Name
942
                $query = str_replace(' FROM opportunities ', ' ,accounts.name AS account_name, accounts.id AS account_id  FROM opportunities  ', $query);
943
                $query = str_replace(' FROM opportunities ', ' FROM opportunities LEFT JOIN accounts_opportunities ON opportunities.id=accounts_opportunities.opportunity_id and accounts_opportunities.deleted = 0 LEFT JOIN accounts ON accounts_opportunities.account_id=accounts.id AND accounts.deleted=0 ', $query);
944
            }
945
            //var_dump($query);
946
947
            $display_result = $this->bean->db->limitQuery($query, 0, $this->settings['map_markers_limit']);
948
            $this->bean->map_markers = array();
949
            while ($display = $this->bean->db->fetchByAssoc($display_result)) {
950
                if (!empty($search_array['where'])) { // Select all records (advanced search) with where clause
951
                    if (in_array($display['id'], $records)) {
952
                        $this->bean->map_markers[] = $this->getMarkerData($display_module, $display, false, $mod_strings_display);
953
                    }
954
                } elseif (!empty($_REQUEST['uid'])) { // Several records selected or this page selected
955
                    if (in_array($display['id'], $records)) {
956
                        $this->bean->map_markers[] = $this->getMarkerData($display_module, $display, false, $mod_strings_display);
957
                    }
958
                } else { // All
959
                    $this->bean->map_markers[] = $this->getMarkerData($display_module, $display, false, $mod_strings_display);
960
                }
961
            }
962
        }
963
964
        // Sort marker groups for the view
965
        sort($this->bean->map_markers_groups);
966
967
        // Set display object for later use
968
        $this->bean->display_object = $this->display_object;
969
970
        // Get Prospect List Array Dropdown
971
        $list = get_module_info('ProspectLists');
972
        $list_query = $list->create_list_query('prospect_lists.name', '1=1', 0);
973
        $list_result = $list->db->query($list_query);
974
        $list_array = array();
975
        while ($alist = $list->db->fetchByAssoc($list_result)) {
976
            if (!empty($alist['name']) && !empty($alist['id'])) {
977
                $list_array[$alist['id']] = $alist['name'];
978
            }
979
        }
980
        $this->bean->list_array = $list_array;
981
982
    }
983
984
    // end function action_map_markers
985
986
    /**
987
     * Define marker data for marker display view
988
     * @param $module_type bean name
989
     * @param $display bean fields array
990
     * $param $mod_strings_display mod_strings from display module
991
     * TODO: Use a custom defined field for the $marker['group']
992
     */
993
    function getMarkerData($module_type, $display, $center_marker = false, $mod_strings_display = array()) {
994
995
//        echo "<pre>";
996
//        print_r($display);
997
//        print_r($mod_strings_display);
998
//        echo "</pre>";
999
1000
        // Define Marker
1001
        $marker = array();
1002
        // Set only partial display data for efficiency
1003
        $marker['name'] = $display['name'];
1004
        // Or, Set all display data for flexibility
1005
        //$marker = $display;
1006
        if (empty($marker['name'])) {
1007
            $marker['name'] = 'N/A';
1008
        }
1009
        $marker['id'] = $display['id'];
1010
        $marker['module'] = $module_type;
1011
        $marker['address'] = $display['jjwg_maps_address_c'];
1012
        $marker['lat'] = $display['jjwg_maps_lat_c'];
1013
        if (!$this->is_valid_lat($marker['lat'])) {
1014
            $marker['lat'] = '0';
1015
        }
1016
        $marker['lng'] = $display['jjwg_maps_lng_c'];
1017
        if (!$this->is_valid_lng($marker['lng'])) {
1018
            $marker['lng'] = '0';
1019
        }
1020
        // Define a phone field: phone_office, phone_work, phone_mobile
1021
        if (!empty($display['phone_office'])) {
1022
            $marker['phone'] = $display['phone_office'];
1023
        } elseif (!empty($display['phone_work'])) {
1024
            $marker['phone'] = $display['phone_work'];
1025
        } elseif (!empty($display['phone_mobile'])) {
1026
            $marker['phone'] = $display['phone_mobile'];
1027
        } else {
1028
            $marker['phone'] = '';
1029
        }
1030
1031
        if ($marker['lat'] != '0' && $marker['lng'] != '0') {
1032
1033
            // Check to see if marker point already exists and apply offset if needed
1034
            // This often occurs when an address is only defined by city, state, zip.
1035
            $i = 0;
1036
            while (isset($this->map_marker_data_points[(string) $marker['lat']][(string) $marker['lng']]) &&
1037
            $i < $this->settings['map_markers_limit']) {
1038
                $marker['lat'] = (float) $marker['lat'] + (float) $this->settings['map_duplicate_marker_adjustment'];
1039
                $marker['lng'] = (float) $marker['lng'] + (float) $this->settings['map_duplicate_marker_adjustment'];
1040
                $i++;
1041
            }
1042
            // Set Marker Point as Used (true)
1043
            $this->map_marker_data_points[(string) $marker['lat']][(string) $marker['lng']] = true;
1044
1045
            if (isset($display['account_name'])) {
1046
                $marker['account_name'] = $display['account_name'];
1047
            }
1048
            if (isset($display['account_id'])) {
1049
                $marker['account_id'] = $display['account_id'];
1050
            }
1051
            $marker['assigned_user_name'] = (isset($display['assigned_user_name'])) ? $display['assigned_user_name'] : '';
1052
            $marker['image'] = (isset($display['marker_image'])) ? $display['marker_image'] : '';
1053
1054
            // Define Marker Group
1055
            if (!$center_marker) {
1056
                // Group Field for the Display Module
1057
                $group_field_name = $this->settings['map_markers_grouping_field'][$module_type];
1058
                $group_field_value = $display[$group_field_name];
1059
                // Check for DOM field types (enum type)
1060
                if (isset($this->display_object->field_name_map[$group_field_name]['type']) &&
1061
                        $this->display_object->field_name_map[$group_field_name]['type'] == 'enum') {
1062
                    $group_field_dom = $this->display_object->field_name_map[$group_field_name]['options'];
1063
                    $marker['group'] = $GLOBALS['app_list_strings'][$group_field_dom][$group_field_value];
1064
                } elseif (!empty($display[$group_field_name])) {
1065
                    $marker['group'] = $display[$group_field_name];
1066
                } else {
1067
                    $marker['group'] = $GLOBALS['mod_strings']['LBL_MAP_NULL_GROUP_NAME']; // null group
1068
                }
1069
                if (!in_array($marker['group'], $this->bean->map_markers_groups)) {
1070
                    $this->bean->map_markers_groups[] = $marker['group'];
1071
                }
1072
            }
1073
1074
            /**
1075
             *  Define Dates for Meetings
1076
             *  TimeDate.php to_display_date_time()
1077
             *  Note, date time fields are converted to the User's date time settings
1078
             */
1079
            if ($module_type == 'Meetings') {
1080
                require_once('modules/Meetings/Meeting.php');
1081
                require_once('include/TimeDate.php');
1082
                if (!isset($meetingTimeDate) || !is_object($meetingTimeDate)) {
0 ignored issues
show
Bug introduced by
The variable $meetingTimeDate 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...
1083
                    $meetingTimeDate = new TimeDate();
1084
                }
1085
                $display['date_start'] = $meetingTimeDate->to_display_date_time($display['date_start'], true, true, $GLOBALS['current_user']);
1086
                $display['date_end'] = $meetingTimeDate->to_display_date_time($display['date_end'], true, true, $GLOBALS['current_user']);
1087
            }
1088
            $current_user_data = get_object_vars($GLOBALS['current_user']);
1089
            $this->sugarSmarty->assign('current_user', $current_user_data);
1090
            $this->sugarSmarty->assign('current_user_address', $this->bean->defineMapsFormattedAddress($current_user_data, 'address'));
1091
            $this->sugarSmarty->assign("mod_strings", $mod_strings_display);
1092
            // Define Maps Info Window HTML by Sugar Smarty Template
1093
            $this->sugarSmarty->assign("module_type", $module_type);
1094
            $this->sugarSmarty->assign("address", $display['jjwg_maps_address_c']);
1095
            $this->sugarSmarty->assign("fields", $display); // display fields array
1096
            // Use @ error suppression to avoid issues with SugarCRM On-Demand
1097
            $marker['html'] = @$this->sugarSmarty->fetch('./custom/modules/jjwg_Maps/tpls/' . $module_type . 'InfoWindow.tpl');
1098
            if (empty($marker['html'])) {
1099
                $marker['html'] = $this->sugarSmarty->fetch('./modules/jjwg_Maps/tpls/' . $module_type . 'InfoWindow.tpl');
1100
            }
1101
            $marker['html'] = preg_replace('/\n\r/', ' ', $marker['html']);
1102
            //var_dump($marker['html']);
1103
            return $marker;
1104
1105
        } else {
1106
            return false;
1107
        }
1108
    }
1109
1110
    /**
1111
     * Get Marker Data Custom for Mapping
1112
     * @param $marker_object
1113
     */
1114
    function getMarkerDataCustom($marker_object) {
1115
1116
        // Define Marker
1117
        $marker = array();
1118
        $marker['name'] = $marker_object->name;
1119
        if (empty($marker['name'])) {
1120
            $marker['name'] = 'N/A';
1121
        }
1122
        $marker['id'] = $marker_object->id;
1123
        $marker['lat'] = $marker_object->jjwg_maps_lat;
1124
        if (!$this->is_valid_lat($marker['lat'])) {
1125
            $marker['lat'] = '0';
1126
        }
1127
        $marker['lng'] = $marker_object->jjwg_maps_lng;
1128
        if (!$this->is_valid_lng($marker['lng'])) {
1129
            $marker['lng'] = '0';
1130
        }
1131
        $marker['image'] = $marker_object->marker_image;
1132
        if (empty($marker['image'])) {
1133
            $marker['image'] = 'None';
1134
        }
1135
1136
        if ($marker['lat'] != '0' || $marker['lng'] != '0') {
1137
1138
            $fields = array();
1139
            foreach ($marker_object->column_fields as $field) {
1140
                $fields[$field] = $marker_object->$field;
1141
            }
1142
            // Define Maps Info Window HTML by Sugar Smarty Template
1143
            $this->sugarSmarty->assign("module_type", 'jjwg_Markers');
1144
            $this->sugarSmarty->assign("fields", $fields); // display fields array
1145
            // Use @ error suppression to avoid issues with SugarCRM On-Demand
1146
            $marker['html'] = @$this->sugarSmarty->fetch('./custom/modules/jjwg_Markers/tpls/MarkersInfoWindow.tpl');
1147
            if (empty($marker['html'])) {
1148
                $marker['html'] = $this->sugarSmarty->fetch('./modules/jjwg_Markers/tpls/MarkersInfoWindow.tpl');
1149
            }
1150
            $marker['html'] = preg_replace('/\n\r/', ' ', $marker['html']);
1151
            //var_dump($marker['html']);
1152
            return $marker;
1153
1154
        } else {
1155
            return false;
1156
        }
1157
    }
1158
1159
    /**
1160
     * Get Area Data Custom for Mapping
1161
     * @param $area_object
1162
     */
1163
    function getAreaDataCustom($area_object) {
1164
1165
        // Define Area
1166
        $area = array();
1167
        $area['name'] = $area_object->name;
1168
        if (empty($area['name'])) {
1169
            $area['name'] = 'N/A';
1170
        }
1171
        $area['id'] = $area_object->id;
1172
        $area['coordinates'] = $area_object->coordinates;
1173
1174
        // Check for proper coordinates pattern
1175
        if (preg_match('/^[0-9\s\(\)\,\.\-]+$/', $area_object->coordinates)) {
1176
1177
            $fields = array();
1178
            foreach ($area_object->column_fields as $field) {
1179
                $fields[$field] = $area_object->$field;
1180
            }
1181
            // Define Maps Info Window HTML by Sugar Smarty Template
1182
            $this->sugarSmarty->assign("module_type", 'jjwg_Areas');
1183
            $this->sugarSmarty->assign("fields", $fields); // display fields array
1184
            // Use @ error suppression to avoid issues with SugarCRM On-Demand
1185
            $area['html'] = @$this->sugarSmarty->fetch('./custom/modules/jjwg_Areas/tpls/AreasInfoWindow.tpl');
1186
            if (empty($area['html'])) {
1187
                $area['html'] = $this->sugarSmarty->fetch('./modules/jjwg_Areas/tpls/AreasInfoWindow.tpl');
1188
            }
1189
            $area['html'] = preg_replace('/\n\r/', ' ', $area['html']);
1190
            //var_dump($marker['html']);
1191
            return $area;
1192
1193
        } else {
1194
            return false;
1195
        }
1196
    }
1197
1198
    /**
1199
     * Check for valid longitude
1200
     * @param $lng float
1201
     */
1202
    function is_valid_lng($lng) {
1203
        return (is_numeric($lng) && $lng >= -180 && $lng <= 180);
1204
    }
1205
1206
    /**
1207
     * Check for valid latitude
1208
     * @param $lat float
1209
     */
1210
    function is_valid_lat($lat) {
1211
        return (is_numeric($lat) && $lat >= -90 && $lat <= 90);
1212
    }
1213
1214
}
1215