GraphController::getSettingsView()   F
last analyzed

Complexity

Conditions 20
Paths 8192

Size

Total Lines 52
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 31
dl 0
loc 52
rs 0
c 0
b 0
f 0
cc 20
nc 8192
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
 * GraphController.php
4
 *
5
 * -Description-
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 <https://www.gnu.org/licenses/>.
19
 *
20
 * @link       https://www.librenms.org
21
 *
22
 * @copyright  2018 Tony Murray
23
 * @author     Tony Murray <[email protected]>
24
 */
25
26
namespace App\Http\Controllers\Widgets;
27
28
use App\Models\Application;
29
use App\Models\Bill;
30
use App\Models\Device;
31
use App\Models\MuninPlugin;
32
use App\Models\Port;
33
use App\Models\Service;
34
use Carbon\Carbon;
35
use Illuminate\Http\Request;
36
use Illuminate\View\View;
37
use LibreNMS\Config;
38
use LibreNMS\Util\Graph;
39
use LibreNMS\Util\Time;
40
41
class GraphController extends WidgetController
42
{
43
    protected $title = 'Graph';
44
    protected $defaults = [
45
        'title' => null,
46
        'refresh' => 60,
47
        'graph_type' => null,
48
        'graph_range' => 'oneday',
49
        'graph_legend' => 'yes',
50
        'graph_device' => null,
51
        'graph_port' => null,
52
        'graph_application' => null,
53
        'graph_munin' => null,
54
        'graph_service' => null,
55
        'graph_ports' => [],
56
        'graph_custom' => [],
57
        'graph_manual' => null,
58
        'graph_bill' => null,
59
    ];
60
61
    public function title()
62
    {
63
        $settings = $this->getSettings();
64
65
        if (! empty($settings['title'])) {
66
            return $settings['title'];
67
        }
68
69
        // automatic title
70
        $type = $this->getGraphType();
71
        if ($type == 'device') {
72
            $device = Device::find($settings['graph_device']);
73
74
            return ($device ? $device->displayName() : 'Device') . ' / ' . $settings['graph_type'];
75
        } elseif ($type == 'aggregate') {
76
            return 'Overall ' . $this->getGraphType(false) . ' Bits (' . $settings['graph_range'] . ')';
77
        } elseif ($type == 'port') {
78
            if ($port = Port::find($settings['graph_port'])) {
79
                return $port->device->displayName() . ' / ' . $port->getShortLabel() . ' / ' . $settings['graph_type'];
0 ignored issues
show
Bug introduced by
The method displayName() does not exist on null. ( Ignorable by Annotation )

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

79
                return $port->device->/** @scrutinizer ignore-call */ displayName() . ' / ' . $port->getShortLabel() . ' / ' . $settings['graph_type'];

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
80
            }
81
        } elseif ($type == 'application') {
82
            if ($application = Application::find($settings['graph_application'])) {
83
                return $application->device->displayName() . ' / ' . $application->app_type . ' / ' . $settings['graph_type'];
0 ignored issues
show
Bug Best Practice introduced by
The property device does not exist on App\Models\Application. Since you implemented __get, consider adding a @property annotation.
Loading history...
Bug Best Practice introduced by
The property app_type does not exist on App\Models\Application. Since you implemented __get, consider adding a @property annotation.
Loading history...
Bug introduced by
The method displayName() does not exist on null. ( Ignorable by Annotation )

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

83
                return $application->device->/** @scrutinizer ignore-call */ displayName() . ' / ' . $application->app_type . ' / ' . $settings['graph_type'];

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
84
            }
85
        } elseif ($type == 'bill') {
86
            if ($bill = Bill::find($settings['graph_bill'])) {
87
                return 'Bill: ' . $bill->bill_name;
88
            }
89
        } elseif ($type == 'munin') {
90
            if ($munin = MuninPlugin::find($settings['graph_munin'])) {
91
                return $munin->device->displayName() . ' / ' . $munin->mplug_type . ' / ' . $settings['graph_type'];
0 ignored issues
show
Bug introduced by
The method displayName() does not exist on null. ( Ignorable by Annotation )

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

91
                return $munin->device->/** @scrutinizer ignore-call */ displayName() . ' / ' . $munin->mplug_type . ' / ' . $settings['graph_type'];

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug Best Practice introduced by
The property mplug_type does not exist on App\Models\MuninPlugin. Since you implemented __get, consider adding a @property annotation.
Loading history...
Bug Best Practice introduced by
The property device does not exist on App\Models\MuninPlugin. Since you implemented __get, consider adding a @property annotation.
Loading history...
92
            }
93
        } elseif ($type == 'service') {
94
            if ($service = Service::find($settings['graph_service'])) {
95
                return $service->device->displayName() . ' / ' . $service->service_type . ' (' . $service->service_desc . ')' . ' / ' . $settings['graph_type'];
0 ignored issues
show
Bug Best Practice introduced by
The property device does not exist on App\Models\Service. Since you implemented __get, consider adding a @property annotation.
Loading history...
Bug Best Practice introduced by
The property service_desc does not exist on App\Models\Service. Since you implemented __get, consider adding a @property annotation.
Loading history...
Bug introduced by
The method displayName() does not exist on null. ( Ignorable by Annotation )

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

95
                return $service->device->/** @scrutinizer ignore-call */ displayName() . ' / ' . $service->service_type . ' (' . $service->service_desc . ')' . ' / ' . $settings['graph_type'];

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug Best Practice introduced by
The property service_type does not exist on App\Models\Service. Since you implemented __get, consider adding a @property annotation.
Loading history...
96
            }
97
        }
98
99
        // fall back for types where we couldn't find the item
100
        if ($settings['graph_type']) {
101
            return 'Device / ' . ucfirst($type) . ' / ' . $settings['graph_type'];
102
        }
103
104
        return $this->title;
105
    }
106
107
    public function getSettingsView(Request $request)
108
    {
109
        $data = $this->getSettings(true);
110
111
        // format display name for selected graph type
112
        $type_parts = explode('_', $data['graph_type']);
113
        $primary = array_shift($type_parts);
114
        $secondary = implode('_', $type_parts);
115
        $name = $primary . ' ' . (Graph::isMibGraph($primary, $secondary) ? $secondary : implode(' ', $type_parts));
116
117
        // format display for selected items
118
        if ($primary == 'device' && $data['graph_device']) {
119
            $device = Device::find($data['graph_device']);
120
        }
121
        $data['device_text'] = isset($device) ? $device->displayName() : __('Device does not exist');
122
123
        if ($primary == 'port' && $data['graph_port']) {
124
            $port = Port::find($data['graph_port']);
125
        }
126
        $data['port_text'] = isset($port) ? $port->getLabel() : __('Port does not exist');
127
128
        if ($primary == 'application' && $data['graph_application']) {
129
            $app = Application::find($data['graph_application']);
130
        }
131
        $data['application_text'] = isset($app) ? $app->displayName() . ' - ' . $app->device->displayName() : __('App does not exist');
132
133
        if ($primary == 'bill' && $data['graph_bill']) {
134
            $bill = Bill::find($data['graph_bill']);
135
        }
136
        $data['bill_text'] = isset($bill) ? $bill->bill_name : __('Bill does not exist');
137
138
        if ($primary == 'munin' && $data['graph_munin']) {
139
            $mplug = MuninPlugin::with('device')->find($data['graph_munin']);
140
        }
141
        $data['munin_text'] = isset($mplug) ? $mplug->device->displayName() . ' - ' . $mplug->mplug_type : __('Munin plugin does not exist');
142
143
        if ($primary == 'service' && $data['graph_service']) {
144
            $service = Service::with('device')->find($data['graph_service']);
145
        }
146
        $data['service_text'] = isset($service) ? $service->device->displayName() . ' - ' . $service->service_type . ' (' . $service->service_desc . ')' : __('Service does not exist');
147
148
        $data['graph_ports'] = Port::whereIn('port_id', $data['graph_ports'])
149
            ->select('ports.device_id', 'port_id', 'ifAlias', 'ifName', 'ifDescr')
150
            ->with(['device' => function ($query) {
151
                $query->select('device_id', 'hostname', 'sysName');
152
            }])->get();
153
154
        $data['graph_port_ids'] = $data['graph_ports']->pluck('port_id')->toJson();
155
156
        $data['graph_text'] = ucwords($name);
157
158
        return view('widgets.settings.graph', $data);
159
    }
160
161
    /**
162
     * @param  Request  $request
163
     * @return View
164
     */
165
    public function getView(Request $request)
166
    {
167
        $settings = $this->getSettings();
168
169
        // force settings if not initialized
170
        if ($this->hasInvalidSettings()) {
171
            return $this->getSettingsView($request);
172
        }
173
174
        $type = $this->getGraphType();
175
        $params = [];
176
177
        if ($type == 'device') {
178
            $params[] = 'device=' . $settings['graph_device'];
179
        } elseif ($type == 'application') {
180
            $params[] = 'id=' . $settings['graph_application'];
181
        } elseif ($type == 'munin') {
182
            if ($mplug = MuninPlugin::find($settings['graph_munin'])) {
183
                $params[] = 'device=' . $mplug->device_id;
0 ignored issues
show
Bug Best Practice introduced by
The property device_id does not exist on App\Models\MuninPlugin. Since you implemented __get, consider adding a @property annotation.
Loading history...
184
                $params[] = 'plugin=' . $mplug->mplug_type;
0 ignored issues
show
Bug Best Practice introduced by
The property mplug_type does not exist on App\Models\MuninPlugin. Since you implemented __get, consider adding a @property annotation.
Loading history...
185
            }
186
        } elseif ($type == 'service') {
187
            if ($service = Service::find($settings['graph_service'])) {
188
                $params[] = 'device=' . $service->device_id;
0 ignored issues
show
Bug Best Practice introduced by
The property device_id does not exist on App\Models\Service. Since you implemented __get, consider adding a @property annotation.
Loading history...
189
                $params[] = 'id=' . $service->service_id;
0 ignored issues
show
Bug Best Practice introduced by
The property service_id does not exist on App\Models\Service. Since you implemented __get, consider adding a @property annotation.
Loading history...
190
            }
191
        } elseif ($type == 'aggregate') {
192
            $aggregate_type = $this->getGraphType(false);
193
            if ($aggregate_type == 'custom') {
194
                $aggregate_type = $settings['graph_custom'];
195
            }
196
197
            if ($aggregate_type == 'ports') {
198
                $port_ids = $settings['graph_ports'];
199
            } else {
200
                $port_types = collect((array) $aggregate_type)->map(function ($type) {
201
                    // check for config definitions
202
                    if (Config::has("{$type}_descr")) {
203
                        return Config::get("{$type}_descr", []);
204
                    }
205
206
                    return $type;
207
                })->flatten();
208
209
                $port_ids = Port::hasAccess($request->user())->where(function ($query) use ($port_types) {
210
                    foreach ($port_types as $port_type) {
211
                        $port_type = str_replace('@', '%', $port_type);
212
                        $query->orWhere('port_descr_type', 'LIKE', $port_type);
213
                    }
214
                })->pluck('port_id')->all();
215
            }
216
217
            $params[] = 'id=' . implode(',', $port_ids);
218
            $settings['graph_type'] = 'multiport_bits_separate';
219
        } else {
220
            $params[] = 'id=' . $settings['graph_' . $type];
221
        }
222
223
        $data = $settings;
224
        $data['params'] = $params;
225
        $data['dimensions'] = $request->get('dimensions');
226
        $data['from'] = Carbon::now()->subSeconds(Time::legacyTimeSpecToSecs($settings['graph_range']))->timestamp;
227
        $data['to'] = Carbon::now()->timestamp;
228
229
        return view('widgets.graph', $data);
230
    }
231
232
    private function getGraphType($summarize = true)
233
    {
234
        $type = explode('_', $this->getSettings()['graph_type'], 2)[0];
235
236
        if ($summarize && in_array($type, ['transit', 'peering', 'core', 'ports', 'custom'])) {
237
            return 'aggregate';
238
        }
239
240
        return $type;
241
    }
242
243
    private function hasInvalidSettings()
244
    {
245
        $raw_type = $this->getGraphType(false);
246
        if ($raw_type == 'custom' || $this->getGraphType() != 'aggregate') {
247
            return empty($this->getSettings()['graph_' . $raw_type]);
248
        }
249
250
        return false; // non-custom aggregate types require no additional settings
251
    }
252
253
    public function getSettings($settingsView = false)
254
    {
255
        if (is_null($this->settings)) {
256
            $settings = parent::getSettings($settingsView);
257
258
            // legacy data conversions
259
            if ($settings['graph_type'] == 'manual') {
260
                $settings['graph_type'] = 'custom';
261
                $settings['graph_custom'] = explode(',', $settings['graph_manual']);
262
            }
263
            if ($settings['graph_type'] == 'transpeer') {
264
                $settings['graph_type'] = 'custom';
265
                $settings['graph_custom'] = ['transit', 'peer'];
266
            }
267
268
            $settings['graph_device'] = $this->convertLegacySettingId($settings['graph_device'], 'device_id');
269
            $settings['graph_port'] = $this->convertLegacySettingId($settings['graph_port'], 'port_id');
270
            $settings['graph_application'] = $this->convertLegacySettingId($settings['graph_application'], 'app_id');
271
            $settings['graph_munin'] = $this->convertLegacySettingId($settings['graph_munin'], 'mplug_id');
272
            $settings['graph_service'] = $this->convertLegacySettingId($settings['graph_service'], 'service_id');
273
            $settings['graph_bill'] = $this->convertLegacySettingId($settings['graph_bill'], 'bill_id');
274
275
            $settings['graph_custom'] = (array) $settings['graph_custom'];
276
            $settings['graph_ports'] = (array) $settings['graph_ports'];
277
278
            $this->settings = $settings;
279
        }
280
281
        return $this->settings;
282
    }
283
284
    private function convertLegacySettingId($setting, $key)
285
    {
286
        if ($setting && ! is_numeric($setting)) {
287
            $data = json_decode($setting, true);
288
289
            return isset($data[$key]) ? $data[$key] : 0;
290
        }
291
292
        return $setting;
293
    }
294
}
295