Passed
Push — master ( 698671...851994 )
by Tony
40:30 queued 28:04
created

AlertUtil::getContacts()   F

Complexity

Conditions 38
Paths > 20000

Size

Total Lines 97
Code Lines 62

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 62
c 0
b 0
f 0
dl 0
loc 97
rs 0
cc 38
nc 32403
nop 1

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
/**
3
 * AlertUtil.php
4
 *
5
 * Extending the built in logging to add an event logger function
6
 *
7
 * This program is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation, either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
 *
20
 * @package    LibreNMS
21
 * @link       http://librenms.org
22
 * @copyright  2019 KanREN, Inc.
23
 * @author     Heath Barnhart <[email protected]>
24
 */
25
26
namespace LibreNMS\Alert;
27
28
use App\Models\Device;
29
use LibreNMS\Authentication\LegacyAuth;
30
use LibreNMS\Config;
31
use PHPMailer\PHPMailer\PHPMailer;
32
33
class AlertUtil
34
{
35
    /**
36
     *
37
     * Get the rule_id for a specific alert
38
     *
39
     * @param $alert_id
40
     * @return mixed|null
41
     */
42
    private static function getRuleId($alert_id)
43
    {
44
        $query = "SELECT `rule_id` FROM `alerts` WHERE `id`=?";
45
        return dbFetchCell($query, [$alert_id]);
46
    }
47
48
    /**
49
     *
50
     * Get the transport for a given alert_id
51
     *
52
     * @param $alert_id
53
     * @return array
54
     */
55
    public static function getAlertTransports($alert_id)
56
    {
57
        $query = "SELECT b.transport_id, b.transport_type, b.transport_name FROM alert_transport_map AS a LEFT JOIN alert_transports AS b ON b.transport_id=a.transport_or_group_id WHERE a.target_type='single' AND a.rule_id=? UNION DISTINCT SELECT d.transport_id, d.transport_type, d.transport_name FROM alert_transport_map AS a LEFT JOIN alert_transport_groups AS b ON a.transport_or_group_id=b.transport_group_id LEFT JOIN transport_group_transport AS c ON b.transport_group_id=c.transport_group_id LEFT JOIN alert_transports AS d ON c.transport_id=d.transport_id WHERE a.target_type='group' AND a.rule_id=?";
58
        $rule_id = self::getRuleId($alert_id);
59
        return dbFetchRows($query, [$rule_id, $rule_id]);
60
    }
61
62
    /**
63
     *
64
     * Returns the default transports
65
     *
66
     * @return array
67
     */
68
    public static function getDefaultAlertTransports()
69
    {
70
        $query = "SELECT transport_id, transport_type, transport_name FROM alert_transports WHERE is_default=true";
71
        return dbFetchRows($query);
72
    }
73
74
     /**
75
     * Find contacts for alert
76
     * @param array $results Rule-Result
77
     * @return array
78
     */
79
    public static function getContacts($results)
80
    {
81
        if (empty($results)) {
82
            return [];
83
        }
84
        if (Config::get('alert.default_only') === true || Config::get('alerts.email.default_only') === true) {
85
            $email = Config::get('alert.default_mail', Config::get('alerts.email.default'));
86
            return $email ? [$email => ''] : [];
87
        }
88
        $users = LegacyAuth::get()->getUserlist();
89
        $contacts = array();
90
        $uids = array();
91
        foreach ($results as $result) {
92
            $tmp  = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $tmp is dead and can be removed.
Loading history...
93
            if (is_numeric($result["bill_id"])) {
94
                $tmpa = dbFetchRows("SELECT user_id FROM bill_perms WHERE bill_id = ?", array($result["bill_id"]));
95
                foreach ($tmpa as $tmp) {
96
                    $uids[$tmp['user_id']] = $tmp['user_id'];
97
                }
98
            }
99
            if (is_numeric($result["port_id"])) {
100
                $tmpa = dbFetchRows("SELECT user_id FROM ports_perms WHERE port_id = ?", array($result["port_id"]));
101
                foreach ($tmpa as $tmp) {
102
                    $uids[$tmp['user_id']] = $tmp['user_id'];
103
                }
104
            }
105
            if (is_numeric($result["device_id"])) {
106
                if (Config::get('alert.syscontact') == true) {
107
                    if (dbFetchCell("SELECT attrib_value FROM devices_attribs WHERE attrib_type = 'override_sysContact_bool' AND device_id = ?", [$result["device_id"]])) {
108
                        $tmpa = dbFetchCell("SELECT attrib_value FROM devices_attribs WHERE attrib_type = 'override_sysContact_string' AND device_id = ?", array($result["device_id"]));
109
                    } else {
110
                        $tmpa = dbFetchCell("SELECT sysContact FROM devices WHERE device_id = ?", array($result["device_id"]));
111
                    }
112
                    if (!empty($tmpa)) {
113
                        $contacts[$tmpa] = '';
114
                    }
115
                }
116
                $tmpa = dbFetchRows("SELECT user_id FROM devices_perms WHERE device_id = ?", array($result["device_id"]));
117
                foreach ($tmpa as $tmp) {
118
                    $uids[$tmp['user_id']] = $tmp['user_id'];
119
                }
120
            }
121
        }
122
        foreach ($users as $user) {
123
            if (empty($user['email'])) {
124
                continue; // no email, skip this user
125
            }
126
            if (empty($user['realname'])) {
127
                $user['realname'] = $user['username'];
128
            }
129
            if (empty($user['level'])) {
130
                $user['level'] = LegacyAuth::get()->getUserlevel($user['username']);
131
            }
132
            if (Config::get('alert.globals') && ( $user['level'] >= 5 && $user['level'] < 10 )) {
133
                            $contacts[$user['email']] = $user['realname'];
134
            } elseif (Config::get('alert.admins') && $user['level'] == 10) {
135
                $contacts[$user['email']] = $user['realname'];
136
            } elseif (Config::get('alert.users') == true && in_array($user['user_id'], $uids)) {
137
                $contacts[$user['email']] = $user['realname'];
138
            }
139
        }
140
141
        $tmp_contacts = array();
142
        foreach ($contacts as $email => $name) {
143
            if (strstr($email, ',')) {
144
                $split_contacts = preg_split('/[,\s]+/', $email);
145
                foreach ($split_contacts as $split_email) {
146
                    if (!empty($split_email)) {
147
                        $tmp_contacts[$split_email] = $name;
148
                    }
149
                }
150
            } else {
151
                $tmp_contacts[$email] = $name;
152
            }
153
        }
154
155
        if (!empty($tmp_contacts)) {
156
            // Validate contacts so we can fall back to default if configured.
157
            $mail = new PHPMailer();
158
            foreach ($tmp_contacts as $tmp_email => $tmp_name) {
159
                if ($mail->validateAddress($tmp_email) != true) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison !== instead.

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

Loading history...
160
                    unset($tmp_contacts[$tmp_email]);
161
                }
162
            }
163
        }
164
165
        # Copy all email alerts to default contact if configured.
166
        $default_mail = Config::get('alert.default_mail');
167
        if (!isset($tmp_contacts[$default_mail]) && Config::get('alert.default_copy')) {
168
            $tmp_contacts[$default_mail] = '';
169
        }
170
        # Send email to default contact if no other contact found
171
        if (empty($tmp_contacts) && Config::get('alert.default_if_none') && $default_mail) {
172
            $tmp_contacts[$default_mail] = '';
173
        }
174
175
        return $tmp_contacts;
176
    }
177
178
    public static function getRules($device_id)
179
    {
180
        $query = "SELECT DISTINCT a.* FROM alert_rules a
181
        LEFT JOIN alert_device_map d ON a.id=d.rule_id
182
        LEFT JOIN alert_group_map g ON a.id=g.rule_id
183
        LEFT JOIN device_group_device dg ON g.group_id=dg.device_group_id
184
        WHERE a.disabled = 0 AND ((d.device_id IS NULL AND g.group_id IS NULL) OR d.device_id=? OR dg.device_id=?)";
185
186
        $params = [$device_id, $device_id];
187
        return dbFetchRows($query, $params);
188
    }
189
190
    /**
191
     * Check if device is under maintenance
192
     * @param int $device_id Device-ID
193
     * @return bool
194
     */
195
    public static function isMaintenance($device_id)
196
    {
197
        $device = Device::find($device_id);
198
        return !is_null($device) && $device->isUnderMaintenance();
199
    }
200
201
    /**
202
     * Process Macros
203
     * @param string $rule Rule to process
204
     * @param int $x Recursion-Anchor
205
     * @return string|boolean
206
     */
207
    public static function runMacros($rule, $x = 1)
208
    {
209
        $macros = Config::get('alert.macros.rule', []) .
0 ignored issues
show
Bug introduced by
Are you sure LibreNMS\Config::get('al....macros.rule', array()) of type array|mixed can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

209
        $macros = /** @scrutinizer ignore-type */ Config::get('alert.macros.rule', []) .
Loading history...
210
        krsort($macros);
211
        foreach ($macros as $macro => $value) {
0 ignored issues
show
Bug introduced by
The expression $macros of type string is not traversable.
Loading history...
212
            if (!strstr($macro, " ")) {
213
                $rule = str_replace('%macros.'.$macro, '('.$value.')', $rule);
214
            }
215
        }
216
        if (strstr($rule, "%macros.")) {
217
            if (++$x < 30) {
218
                $rule = self::runMacros($rule, $x);
219
            } else {
220
                return false;
221
            }
222
        }
223
        return $rule;
224
    }
225
}
226