Completed
Push — develop ( 695bbe )
by Adam
37:32 queued 21:39
created

AOR_Report::AOR_Report()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 7
nc 2
nop 0
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
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 - 2017 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
if (!defined('sugarEntry') || !sugarEntry) {
42
    die('Not A Valid Entry Point');
43
}
44
45
46
class AOR_Report extends Basic
47
{
48
    var $new_schema = true;
49
    var $module_dir = 'AOR_Reports';
50
    var $object_name = 'AOR_Report';
51
    var $table_name = 'aor_reports';
52
    var $importable = true;
53
    var $disable_row_level_security = true;
54
55
    var $id;
56
    var $name;
57
    var $date_entered;
58
    var $date_modified;
59
    var $modified_user_id;
60
    var $modified_by_name;
61
    var $created_by;
62
    var $created_by_name;
63
    var $description;
64
    var $deleted;
65
    var $created_by_link;
66
    var $modified_user_link;
67
    var $assigned_user_id;
68
    var $assigned_user_name;
69
    var $assigned_user_link;
70
    var $report_module;
71
72
    function __construct()
73
    {
74
        parent::__construct();
75
        $this->load_report_beans();
76
        require_once('modules/AOW_WorkFlow/aow_utils.php');
77
        require_once('modules/AOR_Reports/aor_utils.php');
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 AOR_Report()
84
    {
85
        $deprecatedMessage = 'PHP4 Style Constructors are deprecated and will be remove in 7.8, please update your code';
86
        if (isset($GLOBALS['log'])) {
87
            $GLOBALS['log']->deprecated($deprecatedMessage);
88
        } else {
89
            trigger_error($deprecatedMessage, E_USER_DEPRECATED);
90
        }
91
        self::__construct();
92
    }
93
94
95
    function bean_implements($interface)
96
    {
97
        switch ($interface) {
98
            case 'ACL':
99
                return true;
100
        }
101
102
        return false;
103
    }
104
105
    function save($check_notify = false)
106
    {
107
108
        // TODO: process of saveing the fields and conditions is too long so we will have to make some optimization on save_lines functions
109
        set_time_limit(3600);
110
111
        if (empty($this->id)) {
112
            unset($_POST['aor_conditions_id']);
113
            unset($_POST['aor_fields_id']);
114
        }
115
116
        parent::save($check_notify);
117
118
        require_once('modules/AOR_Fields/AOR_Field.php');
119
        $field = new AOR_Field();
120
        $field->save_lines($_POST, $this, 'aor_fields_');
121
122
        require_once('modules/AOR_Conditions/AOR_Condition.php');
123
        $condition = new AOR_Condition();
124
        $condition->save_lines($_POST, $this, 'aor_conditions_');
125
126
        require_once('modules/AOR_Charts/AOR_Chart.php');
127
        $chart = new AOR_Chart();
128
        $chart->save_lines($_POST, $this, 'aor_chart_');
129
    }
130
131
    /**
132
     * @param string $view
133
     * @param string $is_owner
134
     * @param string $in_group
135
     * @return bool
136
     */
137
    public function ACLAccess($view, $is_owner = 'not_set', $in_group = 'not_set')
138
    {
139
        $result = parent::ACLAccess($view, $is_owner, $in_group);
140
        if ($result && $this->report_module !== '') {
141
            $result = ACLController::checkAccess($this->report_module, 'list', true);
142
        }
143
144
        return $result;
145
    }
146
147
148
    function load_report_beans()
149
    {
150
        global $beanList, $app_list_strings;
151
152
        $app_list_strings['aor_moduleList'] = $app_list_strings['moduleList'];
153
154
        foreach ($app_list_strings['aor_moduleList'] as $mkey => $mvalue) {
155
            if (!isset($beanList[$mkey]) || str_begin($mkey, 'AOR_') || str_begin($mkey, 'AOW_')) {
156
                unset($app_list_strings['aor_moduleList'][$mkey]);
157
            }
158
        }
159
160
        $app_list_strings['aor_moduleList'] = array_merge((array)array('' => ''),
161
            (array)$app_list_strings['aor_moduleList']);
162
163
        asort($app_list_strings['aor_moduleList']);
164
    }
165
166
167
    function getReportFields()
168
    {
169
        $fields = array();
170
        foreach ($this->get_linked_beans('aor_fields', 'AOR_Fields') as $field) {
171
            $fields[] = $field;
172
        }
173
        usort($fields, function ($a, $b) {
174
            return $a->field_order - $b->field_order;
175
        });
176
177
        return $fields;
178
    }
179
180
    const CHART_TYPE_PCHART = 'pchart';
181
    const CHART_TYPE_CHARTJS = 'chartjs';
182
    const CHART_TYPE_RGRAPH = 'rgraph';
183
184
185
    function build_report_chart($chartIds = null, $chartType = self::CHART_TYPE_PCHART)
186
    {
187
        global $beanList;
188
        $linkedCharts = $this->get_linked_beans('aor_charts', 'AOR_Charts');
189
        if (!$linkedCharts) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $linkedCharts of type SugarBean[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
190
            //No charts to display
191
            return '';
192
        }
193
194
        $sql = "SELECT id FROM aor_fields WHERE aor_report_id = '" . $this->id . "' AND deleted = 0 ORDER BY field_order ASC";
195
        $result = $this->db->query($sql);
196
197
        $fields = array();
198
        $i = 0;
199
200
        $mainGroupField = null;
201
202
        while ($row = $this->db->fetchByAssoc($result)) {
203
204
            $field = new AOR_Field();
205
            $field->retrieve($row['id']);
206
207
            $path = unserialize(base64_decode($field->module_path));
208
209
            $field_bean = new $beanList[$this->report_module]();
210
211
            $field_module = $this->report_module;
212
            $field_alias = $field_bean->table_name;
213
            if ($path[0] != $this->report_module) {
214
                foreach ($path as $rel) {
215
                    if (empty($rel)) {
216
                        continue;
217
                    }
218
                    $field_module = getRelatedModule($field_module, $rel);
219
                    $field_alias = $field_alias . ':' . $rel;
220
                }
221
            }
222
            $label = str_replace(' ', '_', $field->label) . $i;
223
            $fields[$label]['field'] = $field->field;
224
            $fields[$label]['label'] = $field->label;
225
            $fields[$label]['display'] = $field->display;
226
            $fields[$label]['function'] = $field->field_function;
227
            $fields[$label]['module'] = $field_module;
228
            $fields[$label]['alias'] = $field_alias;
229
            $fields[$label]['link'] = $field->link;
230
            $fields[$label]['total'] = $field->total;
231
232
233
            $fields[$label]['params'] = $field->format;
234
235
            // get the main group
236
237
            if ($field->group_display) {
238
239
                // if we have a main group already thats wrong cause only one main grouping field possible
240
                if (!is_null($mainGroupField)) {
241
                    $GLOBALS['log']->fatal('main group already found');
242
                }
243
244
                $mainGroupField = $field;
245
            }
246
247
            ++$i;
248
        }
249
250
251
        $query = $this->build_report_query();
252
        $result = $this->db->query($query);
253
        $data = array();
254
        while ($row = $this->db->fetchByAssoc($result, false)) {
255
            foreach ($fields as $name => $att) {
256
257
                $currency_id = isset($row[$att['alias'] . '_currency_id']) ? $row[$att['alias'] . '_currency_id'] : '';
258
259
                if ($att['function'] != 'COUNT' && empty($att['params']) && !is_numeric($row[$name])) {
260
                    $row[$name] = trim(strip_tags(getModuleField($att['module'], $att['field'], $att['field'],
261
                        'DetailView', $row[$name], '', $currency_id)));
262
                }
263
            }
264
            $data[] = $row;
265
        }
266
        $fields = $this->getReportFields();
267
268
        switch ($chartType) {
269
            case self::CHART_TYPE_PCHART:
270
                $html = '<script src="modules/AOR_Charts/lib/pChart/imagemap.js"></script>';
271
                break;
272
            case self::CHART_TYPE_CHARTJS:
273
                $html = '<script src="modules/AOR_Reports/js/Chart.js"></script>';
274
                break;
275
            case self::CHART_TYPE_RGRAPH:
276
                if ($_REQUEST['module'] != 'Home') {
277
                    require_once('include/SuiteGraphs/RGraphIncludes.php');
278
                }
279
280
                break;
281
        }
282
        $x = 0;
283
        foreach ($linkedCharts as $chart) {
284
            if ($chartIds !== null && !in_array($chart->id, $chartIds)) {
285
                continue;
286
            }
287
            $html .= $chart->buildChartHTML($data, $fields, $x, $chartType, $mainGroupField);
288
            $x++;
289
        }
290
291
        return $html;
292
    }
293
294
295
    public function buildMultiGroupReport($offset = -1, $links = true, $level = 2, $path = array())
296
    {
297
        global $beanList;
298
299
        $rows = $this->getGroupDisplayFieldByReportId($this->id, $level);
300
301
        if (count($rows) > 1) {
302
            $GLOBALS['log']->fatal('ambiguous group display for report ' . $this->id);
303
        } else {
304
            if (count($rows) == 1) {
305
                $rows[0]['module_path'] = unserialize(base64_decode($rows[0]['module_path']));
306
                if (!$rows[0]['module_path'][0]) {
307
                    $module = new $beanList[$this->report_module]();
308
                    $rows[0]['field_id_name'] = $module->field_defs[$rows[0]['field']]['id_name'] ? $module->field_defs[$rows[0]['field']]['id_name'] : $module->field_defs[$rows[0]['field']]['name'];
309
                    $rows[0]['module_path'][0] = $module->table_name;
310
                } else {
311
                    $rows[0]['field_id_name'] = $rows[0]['field'];
312
                }
313
                $path[] = $rows[0];
314
315
                if ($level > 10) {
316
                    $msg = 'Too many nested groups';
317
                    $GLOBALS['log']->fatal($msg);
318
319
                    return null;
320
                }
321
322
                return $this->buildMultiGroupReport($offset, $links, $level + 1, $path);
323
            } else {
324
                if (!$rows) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $rows of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
325
                    if ($path) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $path of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
326
                        $html = '';
327
                        foreach ($path as $pth) {
328
                            $_fieldIdName = $this->db->quoteIdentifier($pth['field_id_name']);
329
                            $query = "SELECT $_fieldIdName FROM " . $this->db->quoteIdentifier($pth['module_path'][0]) . " GROUP BY $_fieldIdName;";
330
                            $values = $this->dbSelect($query);
331
332
                            foreach ($values as $value) {
333
                                $moduleFieldByGroupValue = $this->getModuleFieldByGroupValue($beanList,
334
                                    $value[$pth['field_id_name']]);
335
                                $moduleFieldByGroupValue = $this->addDataIdValueToInnertext($moduleFieldByGroupValue);
336
                                $html .= $this->getMultiGroupFrameHTML($moduleFieldByGroupValue,
337
                                    $this->build_group_report($offset, $links));
338
                            }
339
                        }
340
341
                        return $html;
342
                    } else {
343
                        return $this->build_group_report($offset, $links, array(), create_guid());
344
                    }
345
                } else {
346
                    throw new Exception('incorrect results');
347
                }
348
            }
349
        }
350
        throw new Exception('incorrect state');
351
    }
352
353
    private function getGroupDisplayFieldByReportId($reportId = null, $level = 1)
354
    {
355
356
        // set the default values
357
358
        if (is_null($reportId)) {
359
            $reportId = $this->id;
360
        }
361
362
        if (!$level) {
363
            $level = 1;
364
        }
365
366
        // escape values for query
367
368
        $_id = $this->db->quote($reportId);
369
        $_level = (int)$level;
370
371
        // get results array
372
373
        $query = "SELECT id, field, module_path FROM aor_fields WHERE aor_report_id = '$_id' AND group_display = $_level AND deleted = 0;";
374
        $rows = $this->dbSelect($query);
375
376
        return $rows;
377
    }
378
379
380
    private function dbSelect($query)
381
    {
382
        $results = $this->db->query($query);
383
384
        $rows = array();
385
        while ($row = $this->db->fetchByAssoc($results)) {
386
            $rows[] = $row;
387
        }
388
389
        return $rows;
390
    }
391
392
    private function getMultiGroupFrameHTML($header, $body)
393
    {
394
        $html = '<div class="multi-group-list" style="border: 1px solid black; padding: 10px;">
395
                    <h3>' . $header . '</h3>
396
                    <div class="multi-group-list-inner">' . $body . '</div>
397
                </div>';
398
399
        return $html;
400
    }
401
402
    private function addDataIdValueToInnertext($html)
403
    {
404
        preg_match('/\sdata-id-value\s*=\s*"([^"]*)"/', $html, $match);
405
        $html = preg_replace('/(>)([^<]*)(<\/\w+>$)/', '$1$2' . $match[1] . '$3', $html);
406
407
        return $html;
408
    }
409
410
411
    function build_group_report($offset = -1, $links = true, $extra = array())
412
    {
413
        global $beanList, $timedate;
414
415
        $html = '';
416
        $query = '';
417
        $query_array = array();
418
        $module = new $beanList[$this->report_module]();
419
420
        $sql = "SELECT id FROM aor_fields WHERE aor_report_id = '" . $this->id . "' AND group_display = 1 AND deleted = 0 ORDER BY field_order ASC";
421
        $field_id = $this->db->getOne($sql);
422
423
        if (!$field_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $field_id of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
424
            $query_array['select'][] = $module->table_name . ".id AS '" . $module->table_name . "_id'";
425
        }
426
427
        if ($field_id != '') {
428
            $field = new AOR_Field();
429
            $field->retrieve($field_id);
430
431
            $field_label = str_replace(' ', '_', $field->label);
432
433
            $path = unserialize(base64_decode($field->module_path));
434
435
            $field_module = $module;
436
            $table_alias = $field_module->table_name;
437
            if (!empty($path[0]) && $path[0] != $module->module_dir) {
438
                foreach ($path as $rel) {
439
                    $new_field_module = new $beanList[getRelatedModule($field_module->module_dir, $rel)];
440
                    $oldAlias = $table_alias;
441
                    $table_alias = $table_alias . ":" . $rel;
442
443
                    $query_array = $this->build_report_query_join($rel, $table_alias, $oldAlias, $field_module,
444
                        'relationship', $query_array, $new_field_module);
445
                    $field_module = $new_field_module;
446
                }
447
            }
448
449
            $data = $field_module->field_defs[$field->field];
450
451
            if ($data['type'] == 'relate' && isset($data['id_name'])) {
452
                $field->field = $data['id_name'];
453
            }
454
455
            if ($data['type'] == 'currency' && !stripos($field->field,
456
                    '_USD') && isset($field_module->field_defs['currency_id'])
457
            ) {
458
                if ((isset($field_module->field_defs['currency_id']['source']) && $field_module->field_defs['currency_id']['source'] == 'custom_fields')) {
459
                    $query['select'][$table_alias . '_currency_id'] = $table_alias . '_cstm' . ".currency_id AS '" . $table_alias . "_currency_id'";
460
                } else {
461
                    $query_array['select'][$table_alias . '_currency_id'] = $table_alias . ".currency_id AS '" . $table_alias . "_currency_id'";
462
                }
463
            }
464
465
            if ((isset($data['source']) && $data['source'] == 'custom_fields')) {
466
                $select_field = $this->db->quoteIdentifier($table_alias . '_cstm') . '.' . $field->field;
467
                // Fix for #1251 - added a missing parameter to the function call
468
                $query_array = $this->build_report_query_join($table_alias . '_cstm', $table_alias . '_cstm',
469
                    $table_alias, $field_module, 'custom', $query);
470
            } else {
471
                $select_field = $this->db->quoteIdentifier($table_alias) . '.' . $field->field;
472
            }
473
474
            if ($field->sort_by != '') {
475
                $query_array['sort_by'][] = $field_label . ' ' . $field->sort_by;
476
            }
477
478
            if ($field->format && in_array($data['type'], array('date', 'datetime', 'datetimecombo'))) {
479
                if (in_array($data['type'], array('datetime', 'datetimecombo'))) {
480
                    $select_field = $this->db->convert($select_field, 'add_tz_offset');
481
                }
482
                $select_field = $this->db->convert($select_field, 'date_format',
483
                    array($timedate->getCalFormat($field->format)));
484
            }
485
486
            if ($field->field_function != null) {
487
                $select_field = $field->field_function . '(' . $select_field . ')';
488
            }
489
490
            if ($field->group_by == 1) {
491
                $query_array['group_by'][] = $select_field;
492
            }
493
494
            $query_array['select'][] = $select_field . " AS '" . $field_label . "'";
495
            if (isset($extra['select']) && $extra['select']) {
496
                foreach ($extra['select'] as $selectField => $selectAlias) {
497
                    if ($selectAlias) {
498
                        $query_array['select'][] = $selectField . " AS " . $selectAlias;
499
                    } else {
500
                        $query_array['select'][] = $selectField;
501
                    }
502
                }
503
            }
504
            $query_array['where'][] = $select_field . " IS NOT NULL AND ";
505
            if (isset($extra['where']) && $extra['where']) {
506
                $query_array['where'][] = implode(' AND ', $extra['where']) . ' AND ';
507
            }
508
509
            $query_array = $this->build_report_query_where($query_array);
510
511
            foreach ($query_array['select'] as $select) {
512
                $query .= ($query == '' ? 'SELECT ' : ', ') . $select;
513
            }
514
515
            $query .= ' FROM ' . $module->table_name . ' ';
516
517
            if (isset($query_array['join'])) {
518
                foreach ($query_array['join'] as $join) {
519
                    $query .= $join;
520
                }
521
            }
522
            if (isset($query_array['where'])) {
523
                $query_where = '';
524
                foreach ($query_array['where'] as $where) {
525
                    $query_where .= ($query_where == '' ? 'WHERE ' : ' ') . $where;
526
                }
527
528
                $query_where = $this->queryWhereRepair($query_where);
529
530
                $query .= ' ' . $query_where;
531
            }
532
533
            if (isset($query_array['group_by'])) {
534
                $query_group_by = '';
535
                foreach ($query_array['group_by'] as $group_by) {
536
                    $query_group_by .= ($query_group_by == '' ? 'GROUP BY ' : ', ') . $group_by;
537
                }
538
                $query .= ' ' . $query_group_by;
539
            }
540
541
            if (isset($query_array['sort_by'])) {
542
                $query_sort_by = '';
543
                foreach ($query_array['sort_by'] as $sort_by) {
544
                    $query_sort_by .= ($query_sort_by == '' ? 'ORDER BY ' : ', ') . $sort_by;
545
                }
546
                $query .= ' ' . $query_sort_by;
547
            }
548
            $result = $this->db->query($query);
549
550
            while ($row = $this->db->fetchByAssoc($result)) {
551
                if ($html != '') {
552
                    $html .= '<br />';
553
                }
554
555
                $html .= $this->build_report_html($offset, $links, $row[$field_label], create_guid(), $extra);
556
557
            }
558
        }
559
560
        if ($html == '') {
561
            $html = $this->build_report_html($offset, $links, '', create_guid(), $extra);
562
        }
563
564
        return $html;
565
566
    }
567
568
569
    function build_report_html($offset = -1, $links = true, $group_value = '', $tableIdentifier = '', $extra = array())
570
    {
571
572
        global $beanList, $sugar_config;
573
574
        $_group_value = $this->db->quote($group_value);
575
576
        $report_sql = $this->build_report_query($_group_value, $extra);
577
578
        // Fix for issue 1232 - items listed in a single report, should adhere to the same standard as ListView items.
579
        if ($sugar_config['list_max_entries_per_page'] != '') {
580
            $max_rows = $sugar_config['list_max_entries_per_page'];
581
        } else {
582
            $max_rows = 20;
583
        }
584
585
        $total_rows = 0;
586
        $count_sql = explode('ORDER BY', $report_sql);
587
        $count_query = 'SELECT count(*) c FROM (' . $count_sql[0] . ') as n';
588
589
        // We have a count query.  Run it and get the results.
590
        $result = $this->db->query($count_query);
591
        $assoc = $this->db->fetchByAssoc($result);
592
        if (!empty($assoc['c'])) {
593
            $total_rows = $assoc['c'];
594
        }
595
596
        $html = "<table class='list aor_reports' id='report_table_" . $tableIdentifier . "' width='100%' cellspacing='0' cellpadding='0' border='0' repeat_header='1'>";
597
598
        if ($offset >= 0) {
599
            $start = 0;
600
            $end = 0;
601
            $previous_offset = 0;
602
            $next_offset = 0;
603
            $last_offset = 0;
604
605
            if ($total_rows > 0) {
606
                $start = $offset + 1;
607
                $end = (($offset + $max_rows) < $total_rows) ? $offset + $max_rows : $total_rows;
608
                $previous_offset = ($offset - $max_rows) < 0 ? 0 : $offset - $max_rows;
609
                $next_offset = $offset + $max_rows;
610
                if (is_int($total_rows / $max_rows)) {
611
                    $last_offset = $max_rows * ($total_rows / $max_rows - 1);
612
                } else {
613
                    $last_offset = $max_rows * floor($total_rows / $max_rows);
614
                }
615
616
            }
617
618
            $html .= "<thead><tr class='pagination'>";
619
620
621
            $moduleFieldByGroupValue = $this->getModuleFieldByGroupValue($beanList, $group_value);
622
623
            $html .= "<td colspan='18'>
624
                       <table class='paginationTable' border='0' cellpadding='0' cellspacing='0' width='100%'>
625
                        <td style='text-align:left' ><H3><a href=\"javascript:void(0)\" class=\"collapseLink\" onclick=\"groupedReportToggler.toggleList(this);\"><img border=\"0\" id=\"detailpanel_1_img_hide\" src=\"themes/SuiteR/images/basic_search.gif\"></a>$moduleFieldByGroupValue</H3></td>
626
                        <td class='paginationChangeButtons' align='right' nowrap='nowrap' width='1%'>";
627
628
            if ($offset == 0) {
629
                $html .= "<button type='button' id='listViewStartButton_top' name='listViewStartButton' title='Start' class='button' disabled='disabled'>
630
                    <img src='" . SugarThemeRegistry::current()->getImageURL('start_off.gif') . "' alt='Start' align='absmiddle' border='0'>
631
                </button>
632
                <button type='button' id='listViewPrevButton_top' name='listViewPrevButton' class='button' title='Previous' disabled='disabled'>
633
                    <img src='" . SugarThemeRegistry::current()->getImageURL('previous_off.gif') . "' alt='Previous' align='absmiddle' border='0'>
634
                </button>";
635
            } else {
636
                $html .= "<button type='button' id='listViewStartButton_top' name='listViewStartButton' title='Start' class='button' onclick='changeReportPage(\"" . $this->id . "\",0,\"" . $group_value . "\",\"" . $tableIdentifier . "\")'>
637
                    <img src='" . SugarThemeRegistry::current()->getImageURL('start.gif') . "' alt='Start' align='absmiddle' border='0'>
638
                </button>
639
                <button type='button' id='listViewPrevButton_top' name='listViewPrevButton' class='button' title='Previous' onclick='changeReportPage(\"" . $this->id . "\"," . $previous_offset . ",\"" . $group_value . "\",\"" . $tableIdentifier . "\")'>
640
                    <img src='" . SugarThemeRegistry::current()->getImageURL('previous.gif') . "' alt='Previous' align='absmiddle' border='0'>
641
                </button>";
642
            }
643
            $html .= " <span class='pageNumbers'>(" . $start . " - " . $end . " of " . $total_rows . ")</span>";
644
            if ($next_offset < $total_rows) {
645
                $html .= "<button type='button' id='listViewNextButton_top' name='listViewNextButton' title='Next' class='button' onclick='changeReportPage(\"" . $this->id . "\"," . $next_offset . ",\"" . $group_value . "\",\"" . $tableIdentifier . "\")'>
646
                        <img src='" . SugarThemeRegistry::current()->getImageURL('next.gif') . "' alt='Next' align='absmiddle' border='0'>
647
                    </button>
648
                     <button type='button' id='listViewEndButton_top' name='listViewEndButton' title='End' class='button' onclick='changeReportPage(\"" . $this->id . "\"," . $last_offset . ",\"" . $group_value . "\",\"" . $tableIdentifier . "\")'>
649
                        <img src='" . SugarThemeRegistry::current()->getImageURL('end.gif') . "' alt='End' align='absmiddle' border='0'>
650
                    </button>";
651
            } else {
652
                $html .= "<button type='button' id='listViewNextButton_top' name='listViewNextButton' title='Next' class='button'  disabled='disabled'>
653
                        <img src='" . SugarThemeRegistry::current()->getImageURL('next_off.gif') . "' alt='Next' align='absmiddle' border='0'>
654
                    </button>
655
                     <button type='button' id='listViewEndButton_top$dashletPaginationButtons' name='listViewEndButton' title='End' class='button'  disabled='disabled'>
656
                        <img src='" . SugarThemeRegistry::current()->getImageURL('end_off.gif') . "' alt='End' align='absmiddle' border='0'>
657
                    </button>";
658
659
            }
660
661
            $html .= "</td>
662
                       </table>
663
                      </td>";
664
665
            $html .= "</tr></thead>";
666
        } else {
667
668
            $moduleFieldByGroupValue = $this->getModuleFieldByGroupValue($beanList, $group_value);
669
670
            $html = "<H3>$moduleFieldByGroupValue</H3>" . $html;
671
        }
672
673
        $sql = "SELECT id FROM aor_fields WHERE aor_report_id = '" . $this->id . "' AND deleted = 0 ORDER BY field_order ASC";
674
        $result = $this->db->query($sql);
675
676
        $html .= "<thead>";
677
        $html .= "<tr>";
678
679
        $fields = array();
680
        $i = 0;
681
        while ($row = $this->db->fetchByAssoc($result)) {
682
683
            $field = new AOR_Field();
684
            $field->retrieve($row['id']);
685
686
            $path = unserialize(base64_decode($field->module_path));
687
688
            $field_bean = new $beanList[$this->report_module]();
689
690
            $field_module = $this->report_module;
691
            $field_alias = $field_bean->table_name;
692
            if ($path[0] != $this->report_module) {
693
                foreach ($path as $rel) {
694
                    if (empty($rel)) {
695
                        continue;
696
                    }
697
                    $field_module = getRelatedModule($field_module, $rel);
698
                    $field_alias = $field_alias . ':' . $rel;
699
                }
700
            }
701
            $label = str_replace(' ', '_', $field->label) . $i;
702
            $fields[$label]['field'] = $field->field;
703
            $fields[$label]['label'] = $field->label;
704
            $fields[$label]['display'] = $field->display;
705
            $fields[$label]['function'] = $field->field_function;
706
            $fields[$label]['module'] = $field_module;
707
            $fields[$label]['alias'] = $field_alias;
708
            $fields[$label]['link'] = $field->link;
709
            $fields[$label]['total'] = $field->total;
710
711
            $fields[$label]['params'] = $field->format;
712
713
714
            if ($fields[$label]['display']) {
715
                $html .= "<th scope='col'>";
716
                $html .= "<div style='white-space: normal;' width='100%' align='left'>";
717
                $html .= $field->label;
718
                $html .= "</div></th>";
719
            }
720
            ++$i;
721
        }
722
723
        $html .= "</tr>";
724
        $html .= "</thead>";
725
        $html .= "<tbody>";
726
727
        if ($offset >= 0) {
728
            $result = $this->db->limitQuery($report_sql, $offset, $max_rows);
729
        } else {
730
            $result = $this->db->query($report_sql);
731
        }
732
733
        $row_class = 'oddListRowS1';
734
735
736
        $totals = array();
737
        while ($row = $this->db->fetchByAssoc($result)) {
738
            $html .= "<tr class='" . $row_class . "' height='20'>";
739
740
            foreach ($fields as $name => $att) {
741
                if ($att['display']) {
742
                    $html .= "<td class='' valign='top' align='left'>";
743
                    if ($att['link'] && $links) {
744
                        $html .= "<a href='" . $sugar_config['site_url'] . "/index.php?module=" . $att['module'] . "&action=DetailView&record=" . $row[$att['alias'] . '_id'] . "'>";
745
                    }
746
747
                    $currency_id = isset($row[$att['alias'] . '_currency_id']) ? $row[$att['alias'] . '_currency_id'] : '';
748
749
                    if ($att['function'] == 'COUNT' || !empty($att['params'])) {
750
                        $html .= $row[$name];
751
                    } else {
752
                        $html .= getModuleField($att['module'], $att['field'], $att['field'], 'DetailView', $row[$name],
753
                            '', $currency_id);
754
                    }
755
756
                    if ($att['total']) {
757
                        $totals[$name][] = $row[$name];
758
                    }
759
                    if ($att['link'] && $links) {
760
                        $html .= "</a>";
761
                    }
762
                    $html .= "</td>";
763
                }
764
            }
765
            $html .= "</tr>";
766
767
            $row_class = $row_class == 'oddListRowS1' ? 'evenListRowS1' : 'oddListRowS1';
768
        }
769
        $html .= "</tbody>";
770
771
        $html .= $this->getTotalHTML($fields, $totals);
772
773
        $html .= "</table>";
774
775
        $html .= "    <script type=\"text/javascript\">
776
                            groupedReportToggler = {
777
778
                                toggleList: function(elem) {
779
                                    $(elem).closest('table.list').find('thead, tbody').each(function(i, e){
780
                                        if(i>1) {
781
                                            $(e).toggle();
782
                                        }
783
                                    });
784
                                    if($(elem).find('img').first().attr('src') == 'themes/SuiteR/images/basic_search.gif') {
785
                                        $(elem).find('img').first().attr('src', 'themes/SuiteR/images/advanced_search.gif');
786
                                    }
787
                                    else {
788
                                        $(elem).find('img').first().attr('src', 'themes/SuiteR/images/basic_search.gif');
789
                                    }
790
                                }
791
792
                            };
793
                        </script>";
794
795
        return $html;
796
    }
797
798
    private function getModuleFieldByGroupValue($beanList, $group_value)
799
    {
800
        $moduleFieldByGroupValues = array();
801
802
        $sql = "SELECT id FROM aor_fields WHERE aor_report_id = '" . $this->id . "' AND group_display = 1 AND deleted = 0 ORDER BY field_order ASC";
803
        $result = $this->db->limitQuery($sql, 0, 1);
804
        while ($row = $this->db->fetchByAssoc($result)) {
805
806
            $field = new AOR_Field();
807
            $field->retrieve($row['id']);
808
809
            if ($field->field_function != 'COUNT' || $field->format != '') {
810
                $moduleFieldByGroupValues[] = $group_value;
811
                continue;
812
            }
813
814
            $path = unserialize(base64_decode($field->module_path));
815
816
            $field_bean = new $beanList[$this->report_module]();
817
818
            $field_module = $this->report_module;
819
            $field_alias = $field_bean->table_name;
820
            if ($path[0] != $this->report_module) {
821
                foreach ($path as $rel) {
822
                    if (empty($rel)) {
823
                        continue;
824
                    }
825
                    $field_module = getRelatedModule($field_module, $rel);
826
                    $field_alias = $field_alias . ':' . $rel;
827
                }
828
            }
829
830
            $currency_id = isset($row[$field_alias . '_currency_id']) ? $row[$field_alias . '_currency_id'] : '';
831
            $moduleFieldByGroupValues[] = getModuleField($this->report_module, $field->field, $field->field,
832
                'DetailView', $group_value, '', $currency_id);
833
834
        }
835
836
        $moduleFieldByGroupValue = implode(', ', $moduleFieldByGroupValues);
837
838
        return $moduleFieldByGroupValue;
839
    }
840
841
    function getTotalHTML($fields, $totals)
842
    {
843
        global $app_list_strings;
844
845
        $currency = new Currency();
846
        $currency->retrieve($GLOBALS['current_user']->getPreference('currency'));
847
848
        $html = '';
849
        $html .= "<tbody>";
850
        $html .= "<tr>";
851
        foreach ($fields as $label => $field) {
852
            if (!$field['display']) {
853
                continue;
854
            }
855
            if ($field['total']) {
856
                $totalLabel = $field['label'] . " " . $app_list_strings['aor_total_options'][$field['total']];
857
                $html .= "<th>{$totalLabel}</th>";
858
            } else {
859
                $html .= "<th></th>";
860
            }
861
        }
862
        $html .= "</tr>";
863
        $html .= "<tr>";
864
        foreach ($fields as $label => $field) {
865
            if (!$field['display']) {
866
                continue;
867
            }
868
            if ($field['total'] && isset($totals[$label])) {
869
                $type = $field['total'];
870
                $total = $this->calculateTotal($type, $totals[$label]);
871
                // Customise display based on the field type
872
                $moduleBean = BeanFactory::newBean($field['module']);
873
                $fieldDefinition = $moduleBean->field_defs[$field['field']];
874
                $fieldDefinitionType = $fieldDefinition['type'];
875
                switch ($fieldDefinitionType) {
876
                    case "currency":
877
                        // Customise based on type of function
878
                        switch ($type) {
879
                            case 'SUM':
880
                            case 'AVG':
881
                                if ($currency->id == -99) {
882
                                    $total = $currency->symbol . format_number($total, null, null);
883
                                } else {
884
                                    $total = $currency->symbol . format_number($total, null, null,
885
                                            array('convert' => true));
886
                                }
887
                                break;
888
                            case 'COUNT':
889
                            default:
890
                                break;
891
                        }
892
                        break;
893
                    default:
894
                        break;
895
                }
896
                $html .= "<td>" . $total . "</td>";
897
            } else {
898
                $html .= "<td></td>";
899
            }
900
        }
901
        $html .= "</tr>";
902
        $html .= "</tbody>";
903
904
        return $html;
905
    }
906
907
    function calculateTotal($type, $totals)
908
    {
909
        switch ($type) {
910
            case 'SUM':
911
                return array_sum($totals);
912
            case 'COUNT':
913
                return count($totals);
914
            case 'AVG':
915
                return array_sum($totals) / count($totals);
916
            default:
917
                return '';
918
        }
919
    }
920
921
    private function encloseForCSV($field)
922
    {
923
        return '"' . $field . '"';
924
    }
925
926
    function build_report_csv()
927
    {
928
        global $beanList;
929
        ini_set('zlib.output_compression', 'Off');
930
931
        ob_start();
932
        require_once('include/export_utils.php');
933
934
        $delimiter = getDelimiter();
935
        $csv = '';
936
        //text/comma-separated-values
937
938
        $sql = "SELECT id FROM aor_fields WHERE aor_report_id = '" . $this->id . "' AND deleted = 0 ORDER BY field_order ASC";
939
        $result = $this->db->query($sql);
940
941
        $fields = array();
942
        $i = 0;
943
        while ($row = $this->db->fetchByAssoc($result)) {
944
945
            $field = new AOR_Field();
946
            $field->retrieve($row['id']);
947
948
            $path = unserialize(base64_decode($field->module_path));
949
            $field_bean = new $beanList[$this->report_module]();
950
            $field_module = $this->report_module;
951
            $field_alias = $field_bean->table_name;
952
953
            if ($path[0] != $this->report_module) {
954
                foreach ($path as $rel) {
955
                    if (empty($rel)) {
956
                        continue;
957
                    }
958
                    $field_module = getRelatedModule($field_module, $rel);
959
                    $field_alias = $field_alias . ':' . $rel;
960
                }
961
            }
962
            $label = str_replace(' ', '_', $field->label) . $i;
963
            $fields[$label]['field'] = $field->field;
964
            $fields[$label]['display'] = $field->display;
965
            $fields[$label]['function'] = $field->field_function;
966
            $fields[$label]['module'] = $field_module;
967
            $fields[$label]['alias'] = $field_alias;
968
            $fields[$label]['params'] = $field->format;
969
970
            if ($field->display) {
971
                $csv .= $this->encloseForCSV($field->label);
972
                $csv .= $delimiter;
973
            }
974
            ++$i;
975
        }
976
977
        $sql = $this->build_report_query();
978
        $result = $this->db->query($sql);
979
980
        while ($row = $this->db->fetchByAssoc($result)) {
981
            $csv .= "\r\n";
982
            foreach ($fields as $name => $att) {
983
                $currency_id = isset($row[$att['alias'] . '_currency_id']) ? $row[$att['alias'] . '_currency_id'] : '';
984
                if ($att['display']) {
985
                    if ($att['function'] != '' || $att['params'] != '') {
986
                        $csv .= $this->encloseForCSV($row[$name]);
987
                    } else {
988
                        $csv .= $this->encloseForCSV(trim(strip_tags(getModuleField($att['module'], $att['field'],
989
                            $att['field'], 'DetailView', $row[$name], '', $currency_id))));
990
                    }
991
                    $csv .= $delimiter;
992
                }
993
            }
994
        }
995
996
        $csv = $GLOBALS['locale']->translateCharset($csv, 'UTF-8', $GLOBALS['locale']->getExportCharset());
997
998
        ob_clean();
999
        header("Pragma: cache");
1000
        header("Content-type: text/comma-separated-values; charset=" . $GLOBALS['locale']->getExportCharset());
1001
        header("Content-Disposition: attachment; filename=\"{$this->name}.csv\"");
1002
        header("Content-transfer-encoding: binary");
1003
        header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
1004
        header("Last-Modified: " . TimeDate::httpTime());
1005
        header("Cache-Control: post-check=0, pre-check=0", false);
1006
        header("Content-Length: " . mb_strlen($csv, '8bit'));
1007
        if (!empty($sugar_config['export_excel_compatible'])) {
0 ignored issues
show
Bug introduced by
The variable $sugar_config seems to never exist, and therefore empty should always return true. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
1008
            $csv = chr(255) . chr(254) . mb_convert_encoding($csv, 'UTF-16LE', 'UTF-8');
1009
        }
1010
        print $csv;
1011
1012
        sugar_cleanup(true);
1013
    }
1014
1015
1016
    function build_report_query($group_value = '', $extra = array())
1017
    {
1018
        global $beanList;
1019
1020
        $module = new $beanList[$this->report_module]();
1021
1022
        $query = '';
1023
        $query_array = array();
1024
1025
        //Check if the user has access to the target module
1026
        if (!(ACLController::checkAccess($this->report_module, 'list', true))) {
1027
            return false;
1028
        }
1029
1030
        $query_array = $this->build_report_query_select($query_array, $group_value);
1031
        if (isset($extra['where']) && $extra['where']) {
1032
            $query_array['where'][] = implode(' AND ', $extra['where']) . ' AND ';
1033
        }
1034
        $query_array = $this->build_report_query_where($query_array);
1035
1036
        foreach ($query_array['select'] as $select) {
1037
            $query .= ($query == '' ? 'SELECT ' : ', ') . $select;
1038
        }
1039
1040
        if (empty($query_array['group_by'])) {
1041
            foreach ($query_array['id_select'] as $select) {
1042
                $query .= ', ' . $select;
1043
            }
1044
        }
1045
1046
        $query .= ' FROM ' . $this->db->quoteIdentifier($module->table_name) . ' ';
1047
1048
        if (isset($query_array['join'])) {
1049
            foreach ($query_array['join'] as $join) {
1050
                $query .= $join;
1051
            }
1052
        }
1053
        if (isset($query_array['where'])) {
1054
            $query_where = '';
1055
            foreach ($query_array['where'] as $where) {
1056
                $query_where .= ($query_where == '' ? 'WHERE ' : ' ') . $where;
1057
            }
1058
1059
            $query_where = $this->queryWhereRepair($query_where);
1060
1061
            $query .= ' ' . $query_where;
1062
        }
1063
1064
        if (isset($query_array['group_by'])) {
1065
            $query_group_by = '';
1066
            foreach ($query_array['group_by'] as $group_by) {
1067
                $query_group_by .= ($query_group_by == '' ? 'GROUP BY ' : ', ') . $group_by;
1068
            }
1069
            if (isset($query_array['second_group_by']) && $query_group_by != '') {
1070
                foreach ($query_array['second_group_by'] as $group_by) {
1071
                    $query_group_by .= ', ' . $group_by;
1072
                }
1073
            }
1074
            $query .= ' ' . $query_group_by;
1075
        }
1076
1077
        if (isset($query_array['sort_by'])) {
1078
            $query_sort_by = '';
1079
            foreach ($query_array['sort_by'] as $sort_by) {
1080
                $query_sort_by .= ($query_sort_by == '' ? 'ORDER BY ' : ', ') . $sort_by;
1081
            }
1082
            $query .= ' ' . $query_sort_by;
1083
        }
1084
1085
        return $query;
1086
1087
    }
1088
1089
    private function queryWhereRepair($query_where)
1090
    {
1091
1092
        // remove empty parenthesis and fix query syntax
1093
1094
        $safe = 0;
1095
        $query_where_clean = '';
1096
        while ($query_where_clean != $query_where) {
1097
            $query_where_clean = $query_where;
1098
            $query_where = preg_replace('/\b(AND|OR)\s*\(\s*\)|[^\w+\s*]\(\s*\)/i', '', $query_where_clean);
1099
            $safe++;
1100
            if ($safe > 100) {
1101
                $GLOBALS['log']->fatal('Invalid report query conditions');
1102
                break;
1103
            }
1104
        }
1105
1106
        return $query_where;
1107
    }
1108
1109
    function build_report_query_select($query = array(), $group_value = '')
1110
    {
1111
        global $beanList, $timedate;
1112
1113
        if ($beanList[$this->report_module]) {
1114
            $module = new $beanList[$this->report_module]();
1115
1116
            $query['id_select'][$module->table_name] = $this->db->quoteIdentifier($module->table_name) . ".id AS '" . $module->table_name . "_id'";
1117
            $query['id_select_group'][$module->table_name] = $this->db->quoteIdentifier($module->table_name) . ".id";
1118
1119
            $sql = "SELECT id FROM aor_fields WHERE aor_report_id = '" . $this->id . "' AND deleted = 0 ORDER BY field_order ASC";
1120
1121
            $result = $this->db->query($sql);
1122
            $i = 0;
1123
            while ($row = $this->db->fetchByAssoc($result)) {
1124
1125
                $field = new AOR_Field();
1126
                $field->retrieve($row['id']);
1127
1128
                $field->label = str_replace(' ', '_', $field->label) . $i;
1129
1130
                $path = unserialize(base64_decode($field->module_path));
1131
1132
                $field_module = $module;
1133
                $table_alias = $field_module->table_name;
1134
                $oldAlias = $table_alias;
1135
                if (!empty($path[0]) && $path[0] != $module->module_dir) {
1136
                    foreach ($path as $rel) {
1137
                        $new_field_module = new $beanList[getRelatedModule($field_module->module_dir, $rel)];
1138
                        $oldAlias = $table_alias;
1139
                        $table_alias = $table_alias . ":" . $rel;
1140
                        $query =
1141
                            $this->build_report_query_join(
1142
                                $rel,
1143
                                $table_alias,
1144
                                $oldAlias,
1145
                                $field_module,
1146
                                'relationship',
1147
                                $query,
1148
                                $new_field_module);
1149
                        $field_module = $new_field_module;
1150
                    }
1151
                }
1152
                $data = $field_module->field_defs[$field->field];
1153
1154
                if ($data['type'] == 'relate' && isset($data['id_name'])) {
1155
                    $field->field = $data['id_name'];
1156
                    $data_new = $field_module->field_defs[$field->field];
1157
                    if (isset($data_new['source']) && $data_new['source'] == 'non-db' && $data_new['type'] != 'link' && isset($data['link'])) {
1158
                        $data_new['type'] = 'link';
1159
                        $data_new['relationship'] = $data['link'];
1160
                    }
1161
                    $data = $data_new;
1162
                }
1163
1164
                if ($data['type'] == 'link' && $data['source'] == 'non-db') {
1165
                    $new_field_module = new $beanList[getRelatedModule($field_module->module_dir,
1166
                        $data['relationship'])];
1167
                    $table_alias = $data['relationship'];
1168
                    $query = $this->build_report_query_join($data['relationship'], $table_alias, $oldAlias,
1169
                        $field_module, 'relationship', $query, $new_field_module);
1170
                    $field_module = $new_field_module;
1171
                    $field->field = 'id';
1172
                }
1173
1174
                if ($data['type'] == 'currency' && isset($field_module->field_defs['currency_id'])) {
1175
                    if ((isset($field_module->field_defs['currency_id']['source']) && $field_module->field_defs['currency_id']['source'] == 'custom_fields')) {
1176
                        $query['select'][$table_alias . '_currency_id'] = $this->db->quoteIdentifier($table_alias . '_cstm') . ".currency_id AS '" . $table_alias . "_currency_id'";
1177
                        $query['second_group_by'][] = $this->db->quoteIdentifier($table_alias . '_cstm') . ".currency_id";
1178
                    } else {
1179
                        $query['select'][$table_alias . '_currency_id'] = $this->db->quoteIdentifier($table_alias) . ".currency_id AS '" . $table_alias . "_currency_id'";
1180
                        $query['second_group_by'][] = $this->db->quoteIdentifier($table_alias) . ".currency_id";
1181
                    }
1182
                }
1183
1184
                if ((isset($data['source']) && $data['source'] == 'custom_fields')) {
1185
                    $select_field = $this->db->quoteIdentifier($table_alias . '_cstm') . '.' . $field->field;
1186
                    $query = $this->build_report_query_join($table_alias . '_cstm', $table_alias . '_cstm',
1187
                        $table_alias, $field_module, 'custom', $query);
1188
                } else {
1189
                    $select_field = $this->db->quoteIdentifier($table_alias) . '.' . $field->field;
1190
                }
1191
1192
                if ($field->format && in_array($data['type'], array('date', 'datetime', 'datetimecombo'))) {
1193
                    if (in_array($data['type'], array('datetime', 'datetimecombo'))) {
1194
                        $select_field = $this->db->convert($select_field, 'add_tz_offset');
1195
                    }
1196
                    $select_field = $this->db->convert($select_field, 'date_format',
1197
                        array($timedate->getCalFormat($field->format)));
1198
                }
1199
1200
                if ($field->link && isset($query['id_select'][$table_alias])) {
1201
                    $query['select'][] = $query['id_select'][$table_alias];
1202
                    $query['second_group_by'][] = $query['id_select_group'][$table_alias];
1203
                    unset($query['id_select'][$table_alias]);
1204
                }
1205
1206
                if ($field->group_by == 1) {
1207
                    $query['group_by'][] = $select_field;
1208
                } elseif ($field->field_function != null) {
1209
                    $select_field = $field->field_function . '(' . $select_field . ')';
1210
                } else {
1211
                    $query['second_group_by'][] = $select_field;
1212
                }
1213
1214
                if ($field->sort_by != '') {
1215
                    $query['sort_by'][] = $select_field . " " . $field->sort_by;
1216
                }
1217
1218
                $query['select'][] = $select_field . " AS '" . $field->label . "'";
1219
1220
                if ($field->group_display == 1 && $group_value) {
1221
                    $query['where'][] = $select_field . " = '" . $group_value . "' AND ";
1222
                }
1223
1224
                ++$i;
1225
            }
1226
        }
1227
1228
        return $query;
1229
    }
1230
1231
    function build_report_query_join(
1232
        $name,
1233
        $alias,
1234
        $parentAlias,
1235
        SugarBean $module,
1236
        $type,
1237
        $query = array(),
1238
        SugarBean $rel_module = null
1239
    ) {
1240
        // Alias to keep lines short
1241
        $db = $this->db;
1242
        if (!isset($query['join'][$alias])) {
1243
1244
            switch ($type) {
1245
                case 'custom':
1246
                    $customTable = $module->get_custom_table_name();
1247
                    $query['join'][$alias] =
1248
                        'LEFT JOIN ' .
1249
                        $db->quoteIdentifier($customTable) .' '. $db->quoteIdentifier($alias) .
1250
                        ' ON ' .
1251
                        $db->quoteIdentifier($parentAlias) . '.id = ' . $db->quoteIdentifier($name) . '.id_c ';
1252
                    break;
1253
1254
                case 'relationship':
1255
                    if ($module->load_relationship($name)) {
1256
                        $params['join_type'] = 'LEFT JOIN';
1257
                        if ($module->$name->relationship_type != 'one-to-many') {
1258
                            if ($module->$name->getSide() == REL_LHS) {
1259
                                $params['right_join_table_alias'] = $db->quoteIdentifier($alias);
1260
                                $params['join_table_alias'] = $db->quoteIdentifier($alias);
1261
                                $params['left_join_table_alias'] = $db->quoteIdentifier($parentAlias);
1262
                            } else {
1263
                                $params['right_join_table_alias'] = $db->quoteIdentifier($parentAlias);
1264
                                $params['join_table_alias'] = $db->quoteIdentifier($alias);
1265
                                $params['left_join_table_alias'] = $db->quoteIdentifier($alias);
1266
                            }
1267
1268
                        } else {
1269
                            $params['right_join_table_alias'] = $db->quoteIdentifier($parentAlias);
1270
                            $params['join_table_alias'] = $db->quoteIdentifier($alias);
1271
                            $params['left_join_table_alias'] = $db->quoteIdentifier($parentAlias);
1272
                        }
1273
                        $linkAlias = $parentAlias . "|" . $alias;
1274
                        $params['join_table_link_alias'] = $db->quoteIdentifier($linkAlias);
1275
                        $join = $module->$name->getJoin($params, true);
1276
                        $query['join'][$alias] = $join['join'];
1277
                        if ($rel_module != null) {
1278
                            $query['join'][$alias] .= $this->build_report_access_query($rel_module,
1279
                                $db->quoteIdentifier($alias));
1280
                        }
1281
                        $query['id_select'][$alias] = $join['select'] . " AS '" . $alias . "_id'";
1282
                        $query['id_select_group'][$alias] = $join['select'];
1283
                    }
1284
                    break;
1285
                default:
1286
                    break;
1287
1288
            }
1289
1290
        }
1291
1292
        return $query;
1293
    }
1294
1295
    function build_report_access_query(SugarBean $module, $alias)
1296
    {
1297
1298
        $where = '';
1299
        if ($module->bean_implements('ACL') && ACLController::requireOwner($module->module_dir, 'list')) {
1300
            global $current_user;
1301
            $owner_where = $module->getOwnerWhere($current_user->id);
1302
            $where = ' AND ' . $owner_where;
1303
1304
        }
1305
1306
        if (file_exists('modules/SecurityGroups/SecurityGroup.php')) {
1307
            /* BEGIN - SECURITY GROUPS */
1308
            if ($module->bean_implements('ACL') && ACLController::requireSecurityGroup($module->module_dir, 'list')) {
1309
                require_once('modules/SecurityGroups/SecurityGroup.php');
1310
                global $current_user;
1311
                $owner_where = $module->getOwnerWhere($current_user->id);
1312
                $group_where = SecurityGroup::getGroupWhere($alias, $module->module_dir, $current_user->id);
1313
                if (!empty($owner_where)) {
1314
                    $where .= " AND (" . $owner_where . " or " . $group_where . ") ";
1315
                } else {
1316
                    $where .= ' AND ' . $group_where;
1317
                }
1318
            }
1319
            /* END - SECURITY GROUPS */
1320
        }
1321
1322
        return $where;
1323
    }
1324
1325
    /**
1326
     * @param array $query
1327
     * @return array
1328
     */
1329
    function build_report_query_where($query = array())
1330
    {
1331
        global $beanList, $app_list_strings, $sugar_config, $current_user;
1332
1333
        $aor_sql_operator_list['Equal_To'] = '=';
1334
        $aor_sql_operator_list['Not_Equal_To'] = '!=';
1335
        $aor_sql_operator_list['Greater_Than'] = '>';
1336
        $aor_sql_operator_list['Less_Than'] = '<';
1337
        $aor_sql_operator_list['Greater_Than_or_Equal_To'] = '>=';
1338
        $aor_sql_operator_list['Less_Than_or_Equal_To'] = '<=';
1339
        $aor_sql_operator_list['Contains'] = 'LIKE';
1340
        $aor_sql_operator_list['Starts_With'] = 'LIKE';
1341
        $aor_sql_operator_list['Ends_With'] = 'LIKE';
1342
1343
        $closure = false;
1344
        if (!empty($query['where'])) {
1345
            $query['where'][] = '(';
1346
            $closure = true;
1347
        }
1348
1349
        if ($beanList[$this->report_module]) {
1350
            $module = new $beanList[$this->report_module]();
1351
1352
            $sql = "SELECT id FROM aor_conditions WHERE aor_report_id = '" . $this->id . "' AND deleted = 0 ORDER BY condition_order ASC";
1353
            $result = $this->db->query($sql);
1354
1355
            $tiltLogicOp = true;
1356
1357
            while ($row = $this->db->fetchByAssoc($result)) {
1358
                $condition = new AOR_Condition();
1359
                $condition->retrieve($row['id']);
1360
1361
                $path = unserialize(base64_decode($condition->module_path));
1362
1363
                $condition_module = $module;
1364
                $table_alias = $condition_module->table_name;
1365
                $oldAlias = $table_alias;
1366
                if (!empty($path[0]) && $path[0] != $module->module_dir) {
1367
                    foreach ($path as $rel) {
1368
                        if (empty($rel)) {
1369
                            continue;
1370
                        }
1371
                        // Bug: Prevents relationships from loading.
1372
                        $new_condition_module = new $beanList[getRelatedModule($condition_module->module_dir, $rel)];
1373
                        //Check if the user has access to the related module
1374
                        if (!(ACLController::checkAccess($new_condition_module->module_name, 'list', true))) {
1375
                            return false;
1376
                        }
1377
                        $oldAlias = $table_alias;
1378
                        $table_alias = $table_alias . ":" . $rel;
1379
                        $query = $this->build_report_query_join($rel, $table_alias, $oldAlias, $condition_module,
1380
                            'relationship', $query, $new_condition_module);
1381
                        $condition_module = $new_condition_module;
1382
                    }
1383
                }
1384
                if (isset($aor_sql_operator_list[$condition->operator])) {
1385
                    $where_set = false;
1386
1387
                    $data = $condition_module->field_defs[$condition->field];
1388
1389
                    if ($data['type'] == 'relate' && isset($data['id_name'])) {
1390
                        $condition->field = $data['id_name'];
1391
                        $data_new = $condition_module->field_defs[$condition->field];
1392
                        if (!empty($data_new['source']) && $data_new['source'] == 'non-db' && $data_new['type'] != 'link' && isset($data['link'])) {
1393
                            $data_new['type'] = 'link';
1394
                            $data_new['relationship'] = $data['link'];
1395
                        }
1396
                        $data = $data_new;
1397
                    }
1398
1399
                    if ($data['type'] == 'link' && $data['source'] == 'non-db') {
1400
                        $new_field_module = new $beanList[getRelatedModule($condition_module->module_dir,
1401
                            $data['relationship'])];
1402
                        $table_alias = $data['relationship'];
1403
                        $query = $this->build_report_query_join($data['relationship'], $table_alias, $oldAlias,
1404
                            $condition_module, 'relationship', $query, $new_field_module);
1405
                        $condition_module = $new_field_module;
1406
1407
                        // Debugging: security groups conditions - It's a hack to just get the query working
1408
                        if ($condition_module->module_dir = 'SecurityGroups' && count($path) > 1) {
0 ignored issues
show
Comprehensibility introduced by
Consider adding parentheses for clarity. Current Interpretation: $condition_module->modul...s' && count($path) > 1), Probably Intended Meaning: ($condition_module->modu...s') && count($path) > 1
Loading history...
1409
                            $table_alias = $oldAlias . ':' . $rel;
0 ignored issues
show
Bug introduced by
The variable $rel seems to be defined by a foreach iteration on line 1367. Are you sure the iterator is never empty, otherwise this variable is not defined?

It seems like you are relying on a variable being defined by an iteration:

foreach ($a as $b) {
}

// $b is defined here only if $a has elements, for example if $a is array()
// then $b would not be defined here. To avoid that, we recommend to set a
// default value for $b.


// Better
$b = 0; // or whatever default makes sense in your context
foreach ($a as $b) {
}

// $b is now guaranteed to be defined here.
Loading history...
1410
                        }
1411
                        $condition->field = 'id';
1412
                    }
1413
                    if ((isset($data['source']) && $data['source'] == 'custom_fields')) {
1414
                        $field = $this->db->quoteIdentifier($table_alias . '_cstm') . '.' . $condition->field;
1415
                        $query = $this->build_report_query_join($table_alias . '_cstm', $table_alias . '_cstm',
1416
                            $table_alias, $condition_module, 'custom', $query);
1417
                    } else {
1418
                        $field = $this->db->quoteIdentifier($table_alias) . '.' . $condition->field;
1419
                    }
1420
1421
                    if (!empty($this->user_parameters[$condition->id]) && $condition->parameter) {
1422
1423
1424
                        $condParam = $this->user_parameters[$condition->id];
1425
                        $condition->value = $condParam['value'];
1426
                        $condition->operator = $condParam['operator'];
1427
                        $condition->value_type = $condParam['type'];
1428
                    }
1429
1430
                    switch ($condition->value_type) {
1431
                        case 'Field':
1432
                            $data = $condition_module->field_defs[$condition->value];
1433
1434
                            if ($data['type'] == 'relate' && isset($data['id_name'])) {
1435
                                $condition->value = $data['id_name'];
1436
                                $data_new = $condition_module->field_defs[$condition->value];
1437
                                if ($data_new['source'] == 'non-db' && $data_new['type'] != 'link' && isset($data['link'])) {
1438
                                    $data_new['type'] = 'link';
1439
                                    $data_new['relationship'] = $data['link'];
1440
                                }
1441
                                $data = $data_new;
1442
                            }
1443
1444
                            if ($data['type'] == 'link' && $data['source'] == 'non-db') {
1445
                                $new_field_module = new $beanList[getRelatedModule($condition_module->module_dir,
1446
                                    $data['relationship'])];
1447
                                $table_alias = $data['relationship'];
1448
                                $query = $this->build_report_query_join($data['relationship'], $table_alias, $oldAlias,
1449
                                    $condition_module, 'relationship', $query, $new_field_module);
1450
                                $condition_module = $new_field_module;
1451
                                $condition->field = 'id';
1452
                            }
1453
                            if ((isset($data['source']) && $data['source'] == 'custom_fields')) {
1454
                                $value = $condition_module->table_name . '_cstm.' . $condition->value;
1455
                                $query = $this->build_report_query_join($condition_module->table_name . '_cstm',
1456
                                    $table_alias . '_cstm', $table_alias, $condition_module, 'custom', $query);
1457
                            } else {
1458
                                $value = ($table_alias ? $this->db->quoteIdentifier($table_alias) : $condition_module->table_name) . '.' . $condition->value;
1459
                            }
1460
                            break;
1461
1462
                        case 'Date':
1463
                            $params = unserialize(base64_decode($condition->value));
1464
1465
                            // Fix for issue #1272 - AOR_Report module cannot update Date type parameter.
1466
                            if ($params == false) {
1467
                                $params = $condition->value;
1468
                            }
1469
1470
                            if ($params[0] == 'now') {
1471
                                if ($sugar_config['dbconfig']['db_type'] == 'mssql') {
1472
                                    $value = 'GetDate()';
1473
                                } else {
1474
                                    $value = 'NOW()';
1475
                                }
1476
                            } else {
1477
                                if ($params[0] == 'today') {
1478
                                    if ($sugar_config['dbconfig']['db_type'] == 'mssql') {
1479
                                        //$field =
1480
                                        $value = 'CAST(GETDATE() AS DATE)';
1481
                                    } else {
1482
                                        $field = 'DATE(' . $field . ')';
1483
                                        $value = 'Curdate()';
1484
                                    }
1485
                                } else {
1486
                                    $data = $condition_module->field_defs[$params[0]];
1487
                                    if ((isset($data['source']) && $data['source'] == 'custom_fields')) {
1488
                                        $value = $condition_module->table_name . '_cstm.' . $params[0];
1489
                                        $query = $this->build_report_query_join($condition_module->table_name . '_cstm',
1490
                                            $table_alias . '_cstm', $table_alias, $condition_module, 'custom', $query);
1491
                                    } else {
1492
                                        $value = $condition_module->table_name . '.' . $params[0];
1493
                                    }
1494
                                }
1495
                            }
1496
1497
                            if ($params[1] != 'now') {
1498
                                switch ($params[3]) {
1499
                                    case 'business_hours';
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1500
                                        //business hours not implemented for query, default to hours
1501
                                        $params[3] = 'hours';
1502
                                    default:
1503
                                        if ($sugar_config['dbconfig']['db_type'] == 'mssql') {
1504
                                            $value = "DATEADD(" . $params[3] . ",  " . $app_list_strings['aor_date_operator'][$params[1]] . " $params[2], $value)";
1505
                                        } else {
1506
                                            $value = "DATE_ADD($value, INTERVAL " . $app_list_strings['aor_date_operator'][$params[1]] . " $params[2] " . $params[3] . ")";
1507
                                        }
1508
                                        break;
1509
                                }
1510
                            }
1511
                            break;
1512
1513
                        case 'Multi':
1514
                            $sep = ' AND ';
1515
                            if ($condition->operator == 'Equal_To') {
1516
                                $sep = ' OR ';
1517
                            }
1518
                            $multi_values = unencodeMultienum($condition->value);
1519
                            if (!empty($multi_values)) {
1520
                                $value = '(';
1521
                                foreach ($multi_values as $multi_value) {
1522
                                    if ($value != '(') {
1523
                                        $value .= $sep;
1524
                                    }
1525
                                    $value .= $field . ' ' . $aor_sql_operator_list[$condition->operator] . " '" . $multi_value . "'";
1526
                                }
1527
                                $value .= ')';
1528
                            }
1529
                            $query['where'][] = ($tiltLogicOp ? '' : ($condition->logic_op ? $condition->logic_op . ' ' : 'AND ')) . $value;
1530
                            $where_set = true;
1531
                            break;
1532
                        case "Period":
1533
                            if (array_key_exists($condition->value, $app_list_strings['date_time_period_list'])) {
1534
                                $params = $condition->value;
1535
                            } else {
1536
                                $params = base64_decode($condition->value);
1537
                            }
1538
                            $value = '"' . getPeriodDate($params)->format('Y-m-d H:i:s') . '"';
1539
                            break;
1540
                        case "CurrentUserID":
1541
                            global $current_user;
1542
                            $value = '"' . $current_user->id . '"';
1543
                            break;
1544
                        case 'Value':
1545
                            $utc = new DateTimeZone("UTC");
1546
                            $dateTime = DateTime::createFromFormat('Y-m-d H:i:s', $condition->value, $utc);
1547
1548
                            if ($condition->operator === 'Equal_To') {
1549
                                if ($dateTime !== false) {
1550
                                    $day_ahead = $dateTime->modify('+1 day');
1551
                                    $equal_query = "( $field  BETWEEN '" . $this->db->quote($condition->value) . "' AND '" . $this->db->quote($day_ahead->format('Y-m-d H:i:s')) . "' ) ";
1552
                                    $query['where'][] = ($tiltLogicOp ? '' : ($condition->logic_op ? $condition->logic_op . ' ' : 'AND ')) . $equal_query;
1553
                                } elseif ($dateTime === false && $data['type'] === 'datetime') { // check for incorrectly converted dateTime
1554
                                        $dateTime = convertToDateTime($condition->value);
1555
1556
                                        $query_date = $dateTime->format('Y-m-d H:i:s');
1557
                                        $equal_query = "( $field  BETWEEN '" . $this->db->quote($query_date);
1558
                                        $day_ahead = $dateTime->modify('+1 day');
1559
                                        $equal_query .= "' AND '" . $this->db->quote($day_ahead->format('Y-m-d H:i:s')) . "' ) ";
1560
                                        $query['where'][] = ($tiltLogicOp ? '' : ($condition->logic_op ? $condition->logic_op . ' ' : 'AND ')) . $equal_query;
1561
                                    } else {
1562
                                        $value = "'" . $this->db->quote($condition->value) . "'";
1563
                                        break;
1564
                                    }
1565
                                $where_set = true;
1566
                            } elseif ($condition->operator === 'Not_Equal_To') {
1567
                                    if ($dateTime !== false) {
1568
                                        $day_ahead = $dateTime->modify('+1 day');
1569
                                        $not_equal_query = "( $field NOT BETWEEN '" . $this->db->quote($condition->value) . "' AND '" . $this->db->quote($day_ahead->format('Y-m-d H:i:s')) . "' ) ";
1570
                                        $query['where'][] = ($tiltLogicOp ? '' : ($condition->logic_op ? $condition->logic_op . ' ' : 'AND ')) . $not_equal_query;
1571
                                    } elseif ($dateTime === false && $data['type'] === 'datetime') { // check for incorrectly converted dateTime
1572
                                            $dateTime = convertToDateTime($condition->value);
1573
1574
                                            $query_date = $dateTime->format('Y-m-d H:i:s');
1575
                                            $not_equal_query = "( $field NOT BETWEEN '" . $this->db->quote($query_date);
1576
                                            $day_ahead = $dateTime->modify('+1 day');
1577
                                            $not_equal_query .= "' AND '" . $this->db->quote($day_ahead->format('Y-m-d H:i:s')) . "' ) ";
1578
                                            $query['where'][] = ($tiltLogicOp ? '' : ($condition->logic_op ? $condition->logic_op . ' ' : 'AND ')) . $not_equal_query;
1579
                                        } else {
1580
                                            $value = "'" . $this->db->quote($condition->value) . "'";
1581
                                            break;
1582
                                        }
1583
                                    $where_set = true;
1584
                                } elseif ($condition->operator === 'Greater_Than') {
1585
                                        if ($dateTime !== false) {
1586
                                            $greater_than_query = "( $field > '" . $this->db->quote($condition->value) . "' ) ";
1587
                                            $query['where'][] = ($tiltLogicOp ? '' : ($condition->logic_op ? $condition->logic_op . ' ' : 'AND ')) . $greater_than_query;
1588
                                        } elseif ($dateTime === false && $data['type'] === 'datetime') { // check for incorrectly converted dateTime
1589
                                                $dateTime = convertToDateTime($condition->value);
1590
1591
                                                $query_date = $dateTime->format('Y-m-d H:i:s');
1592
                                                $greater_than_query = "( $field > '" . $this->db->quote($query_date) . "' ) ";
1593
                                                $query['where'][] = ($tiltLogicOp ? '' : ($condition->logic_op ? $condition->logic_op . ' ' : 'AND ')) . $greater_than_query;
1594
                                            } else {
1595
                                                $value = "'" . $this->db->quote($condition->value) . "'";
1596
                                                break;
1597
                                            }
1598
                                        $where_set = true;
1599
                                    } elseif ($condition->operator === 'Less_Than') {
1600
                                            if ($dateTime !== false) {
1601
                                                $less_than_query = "( $field < '" . $this->db->quote($condition->value) . "' ) ";
1602
                                                $query['where'][] = ($tiltLogicOp ? '' : ($condition->logic_op ? $condition->logic_op . ' ' : 'AND ')) . $less_than_query;
1603
                                            } elseif ($dateTime === false && $data['type'] === 'datetime') { // check for incorrectly converted dateTime
1604
                                                    $dateTime = convertToDateTime($condition->value);
1605
1606
                                                    $query_date = $dateTime->format('Y-m-d H:i:s');
1607
                                                    $less_than_query = "( $field < '" . $this->db->quote($query_date) . "' ) ";
1608
                                                    $query['where'][] = ($tiltLogicOp ? '' : ($condition->logic_op ? $condition->logic_op . ' ' : 'AND ')) . $less_than_query;
1609
                                                } else {
1610
                                                    $value = "'" . $this->db->quote($condition->value) . "'";
1611
                                                    break;
1612
                                                }
1613
                                            $where_set = true;
1614
                                        } elseif ($condition->operator === 'Greater_Than_or_Equal_To') {
1615
                                                if ($dateTime !== false) {
1616
                                                    $equal_greater_than_query = "( $field > '" . $this->db->quote($condition->value) . "'";
1617
                                                    $day_ahead = $dateTime->modify('+1 day');
1618
                                                    $equal_greater_than_query .= " OR $field  BETWEEN '" . $this->db->quote($condition->value) . "' AND '" . $this->db->quote($day_ahead->format('Y-m-d H:i:s')) . "' ) ";
1619
                                                    $query['where'][] = ($tiltLogicOp ? '' : ($condition->logic_op ? $condition->logic_op . ' ' : 'AND ')) . $equal_greater_than_query;
1620
                                                } elseif ($dateTime === false && $data['type'] === 'datetime') { // check for incorrectly converted dateTime
1621
                                                        $dateTime = convertToDateTime($condition->value);
1622
1623
                                                        $query_date = $dateTime->format('Y-m-d H:i:s');
1624
                                                        $equal_greater_than_query = "( $field > '" . $this->db->quote($query_date) . "'";
1625
                                                        $day_ahead = $dateTime->modify('+1 day');
1626
                                                        $equal_greater_than_query .= " OR $field  BETWEEN '" . $this->db->quote($query_date) . "' AND '" . $this->db->quote($day_ahead->format('Y-m-d H:i:s')) . "' ) ";
1627
                                                        $query['where'][] = ($tiltLogicOp ? '' : ($condition->logic_op ? $condition->logic_op . ' ' : 'AND ')) . $equal_greater_than_query;
1628
                                                    } else {
1629
                                                        $value = "'" . $this->db->quote($condition->value) . "'";
1630
                                                        break;
1631
                                                    }
1632
                                                $where_set = true;
1633
                                            } elseif ($condition->operator === 'Less_Than_or_Equal_To') {
1634
                                                    if ($dateTime !== false) {
1635
                                                        $equal_less_than_query = "( $field < '" . $this->db->quote($condition->value) . "'";
1636
                                                        $day_ahead = $dateTime->modify('+1 day');
1637
                                                        $equal_less_than_query .= " OR $field  BETWEEN '" . $this->db->quote($condition->value) . "' AND '" . $this->db->quote($day_ahead->format('Y-m-d H:i:s')) . "' ) ";
1638
                                                        $query['where'][] = ($tiltLogicOp ? '' : ($condition->logic_op ? $condition->logic_op . ' ' : 'AND ')) . $equal_less_than_query;
1639
                                                    } elseif ($dateTime === false && $data['type'] === 'datetime') { // check for incorrectly converted dateTime
1640
                                                            $dateTime = convertToDateTime($condition->value);
1641
1642
                                                            $query_date = $dateTime->format('Y-m-d H:i:s');
1643
                                                            $equal_less_than_query = "( $field < '" . $this->db->quote($query_date) . "'";
1644
                                                            $day_ahead = $dateTime->modify('+1 day');
1645
                                                            $equal_less_than_query .= " OR $field  BETWEEN '" . $this->db->quote($query_date) . "' AND '" . $this->db->quote($day_ahead->format('Y-m-d H:i:s')) . "' ) ";
1646
                                                            $query['where'][] = ($tiltLogicOp ? '' : ($condition->logic_op ? $condition->logic_op . ' ' : 'AND ')) . $equal_less_than_query;
1647
                                                        } else {
1648
                                                            $value = "'" . $this->db->quote($condition->value) . "'";
1649
                                                            break;
1650
                                                        }
1651
                                                    $where_set = true;
1652
                                                } else {
1653
                                                    $value = "'" . $this->db->quote($condition->value) . "'";
1654
                                                }
1655
                            break;
1656
                        default:
1657
                            $value = "'" . $this->db->quote($condition->value) . "'";
1658
                            break;
1659
                    }
1660
1661
                    //handle like conditions
1662
                    Switch ($condition->operator) {
1663
                        case 'Contains':
1664
                            $value = "CONCAT('%', " . $value . " ,'%')";
1665
                            break;
1666
                        case 'Starts_With':
1667
                            $value = "CONCAT(" . $value . " ,'%')";
1668
                            break;
1669
                        case 'Ends_With':
1670
                            $value = "CONCAT('%', " . $value . ")";
1671
                            break;
1672
                    }
1673
1674
                    if ($condition->value_type == 'Value' && !$condition->value && $condition->operator == 'Equal_To') {
1675
                        $value = "{$value} OR {$field} IS NULL)";
1676
                        $field = "(" . $field;
1677
                    }
1678
1679
                    if (!$where_set) {
1680
                        if ($condition->value_type == "Period") {
1681
                            if (array_key_exists($condition->value, $app_list_strings['date_time_period_list'])) {
1682
                                $params = $condition->value;
1683
                            } else {
1684
                                $params = base64_decode($condition->value);
1685
                            }
1686
                            $date = getPeriodEndDate($params)->format('Y-m-d H:i:s');
1687
                            $value = '"' . getPeriodDate($params)->format('Y-m-d H:i:s') . '"';
1688
1689
                            $query['where'][] = ($tiltLogicOp ? '' : ($condition->logic_op ? $condition->logic_op . ' ' : 'AND '));
1690
                            $tiltLogicOp = false;
1691
1692
                            switch ($aor_sql_operator_list[$condition->operator]) {
1693
                                case "=":
1694
                                    $query['where'][] = $field . ' BETWEEN ' . $value . ' AND ' . '"' . $date . '"';
1695
                                    break;
1696
                                case "!=":
1697
                                    $query['where'][] = $field . ' NOT BETWEEN ' . $value . ' AND ' . '"' . $date . '"';
1698
                                    break;
1699
                                case ">":
1700
                                case "<":
1701
                                case ">=":
1702
                                case "<=":
1703
                                    $query['where'][] = $field . ' ' . $aor_sql_operator_list[$condition->operator] . ' ' . $value;
1704
                                    break;
1705
                            }
1706
                        } else {
1707
                            if (!$where_set) {
1708
                                $query['where'][] = ($tiltLogicOp ? '' : ($condition->logic_op ? $condition->logic_op . ' ' : 'AND ')) . $field . ' ' . $aor_sql_operator_list[$condition->operator] . ' ' . $value;
1709
                            }
1710
                        }
1711
                    }
1712
                    $tiltLogicOp = false;
1713
                } else {
1714
                    if ($condition->parenthesis) {
1715
                        if ($condition->parenthesis == 'START') {
1716
                            $query['where'][] = ($tiltLogicOp ? '' : ($condition->logic_op ? $condition->logic_op . ' ' : 'AND ')) . '(';
1717
                            $tiltLogicOp = true;
1718
                        } else {
1719
                            $query['where'][] = ')';
1720
                            $tiltLogicOp = false;
1721
                        }
1722
                    } else {
1723
                        $GLOBALS['log']->debug('illegal condition');
1724
                    }
1725
                }
1726
1727
            }
1728
1729
            if (isset($query['where']) && $query['where']) {
1730
                array_unshift($query['where'], '(');
1731
                $query['where'][] = ') AND ';
1732
            }
1733
            $query['where'][] = $module->table_name . ".deleted = 0 " . $this->build_report_access_query($module,
1734
                    $module->table_name);
1735
1736
        }
1737
1738
        if ($closure) {
1739
            $query['where'][] = ')';
1740
        }
1741
1742
        return $query;
1743
    }
1744
1745
}
1746