Completed
Pull Request — master (#364)
by ARCANEDEV
12:52
created

LogViewerController::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 5
rs 10
c 0
b 0
f 0
ccs 4
cts 4
cp 1
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Arcanedev\LogViewer\Http\Controllers;
6
7
use Arcanedev\LogViewer\Contracts\LogViewer as LogViewerContract;
8
use Arcanedev\LogViewer\Entities\{LogEntry, LogEntryCollection};
9
use Arcanedev\LogViewer\Exceptions\LogNotFoundException;
10
use Arcanedev\LogViewer\Tables\StatsTable;
11
use Illuminate\Http\Request;
12
use Illuminate\Pagination\LengthAwarePaginator;
13
use Illuminate\Routing\Controller;
14
use Illuminate\Support\{Arr, Collection, Str};
15
16
/**
17
 * Class     LogViewerController
18
 *
19
 * @package  LogViewer\Http\Controllers
20
 * @author   ARCANEDEV <[email protected]>
21
 */
22
class LogViewerController extends Controller
23
{
24
    /* -----------------------------------------------------------------
25
     |  Properties
26
     | -----------------------------------------------------------------
27
     */
28
29
    /**
30
     * The log viewer instance
31
     *
32
     * @var \Arcanedev\LogViewer\Contracts\LogViewer
33
     */
34
    protected $logViewer;
35
36
    /** @var int */
37
    protected $perPage = 30;
38
39
    /** @var string */
40
    protected $showRoute = 'log-viewer::logs.show';
41
42
    /* -----------------------------------------------------------------
43
     |  Constructor
44
     | -----------------------------------------------------------------
45
     */
46
47
    /**
48
     * LogViewerController constructor.
49
     *
50
     * @param  \Arcanedev\LogViewer\Contracts\LogViewer  $logViewer
51
     */
52 56
    public function __construct(LogViewerContract $logViewer)
53
    {
54 56
        $this->logViewer = $logViewer;
55 56
        $this->perPage = config('log-viewer.per-page', $this->perPage);
56 56
    }
57
58
    /* -----------------------------------------------------------------
59
     |  Main Methods
60
     | -----------------------------------------------------------------
61
     */
62
63
    /**
64
     * Show the dashboard.
65
     *
66
     * @return \Illuminate\View\View
67
     */
68 4
    public function index()
69
    {
70 4
        $stats     = $this->logViewer->statsTable();
71 4
        $chartData = $this->prepareChartData($stats);
72 4
        $percents  = $this->calcPercentages($stats->footer(), $stats->header());
73
74 4
        return $this->view('dashboard', compact('chartData', 'percents'));
75
    }
76
77
    /**
78
     * List all logs.
79
     *
80
     * @param  \Illuminate\Http\Request  $request
81
     *
82
     * @return \Illuminate\View\View
83
     */
84 4
    public function listLogs(Request $request)
85
    {
86 4
        $stats   = $this->logViewer->statsTable();
87 4
        $headers = $stats->header();
88 4
        $rows    = $this->paginate($stats->rows(), $request);
89
90 4
        return $this->view('logs', compact('headers', 'rows'));
91
    }
92
93
    /**
94
     * Show the log.
95
     *
96
     * @param  \Illuminate\Http\Request  $request
97
     * @param  string                    $date
98
     *
99
     * @return \Illuminate\View\View
100
     */
101 8
    public function show(Request $request, $date)
102
    {
103 8
        $level   = 'all';
104 8
        $log     = $this->getLogOrFail($date);
105 4
        $query   = $request->get('query');
106 4
        $levels  = $this->logViewer->levelsNames();
107 4
        $entries = $log->entries($level)->paginate($this->perPage);
108
109 4
        return $this->view('show', compact('level', 'log', 'query', 'levels', 'entries'));
110
    }
111
112
    /**
113
     * Filter the log entries by level.
114
     *
115
     * @param  \Illuminate\Http\Request  $request
116
     * @param  string                    $date
117
     * @param  string                    $level
118
     *
119
     * @return \Illuminate\View\View|\Illuminate\Http\RedirectResponse
120
     */
121 8
    public function showByLevel(Request $request, $date, $level)
122
    {
123 8
        if ($level === 'all')
124 4
            return redirect()->route($this->showRoute, [$date]);
125
126 4
        $log     = $this->getLogOrFail($date);
127 4
        $query   = $request->get('query');
128 4
        $levels  = $this->logViewer->levelsNames();
129 4
        $entries = $this->logViewer->entries($date, $level)->paginate($this->perPage);
130
131 4
        return $this->view('show', compact('level', 'log', 'query', 'levels', 'entries'));
132
    }
133
134
    /**
135
     * Show the log with the search query.
136
     *
137
     * @param  \Illuminate\Http\Request  $request
138
     * @param  string                    $date
139
     * @param  string                    $level
140
     *
141
     * @return \Illuminate\View\View|\Illuminate\Http\RedirectResponse
142
     */
143 16
    public function search(Request $request, $date, $level = 'all')
144
    {
145 16
        $query   = $request->get('query');
146
147 16
        if (is_null($query))
148
            return redirect()->route($this->showRoute, [$date]);
149
150 16
        $log     = $this->getLogOrFail($date);
151 16
        $levels  = $this->logViewer->levelsNames();
152 16
        $needles = array_map(function ($needle) {
153 16
            return Str::lower($needle);
154 16
        }, array_filter(explode(' ', $query)));
155 16
        $entries = $log->entries($level)
156 16
            ->unless(empty($needles), function (LogEntryCollection $entries) use ($needles) {
157 16
                return $entries->filter(function (LogEntry $entry) use ($needles) {
158 16
                    return Str::containsAll(Str::lower($entry->header), $needles);
159 16
                });
160 16
            })
161 16
            ->paginate($this->perPage);
162
163 16
        return $this->view('show', compact('level', 'log', 'query', 'levels', 'entries'));
164
    }
165
166
    /**
167
     * Download the log
168
     *
169
     * @param  string  $date
170
     *
171
     * @return \Symfony\Component\HttpFoundation\BinaryFileResponse
172
     */
173 4
    public function download($date)
174
    {
175 4
        return $this->logViewer->download($date);
176
    }
177
178
    /**
179
     * Delete a log.
180
     *
181
     * @param  \Illuminate\Http\Request  $request
182
     *
183
     * @return \Illuminate\Http\JsonResponse
184
     */
185 12
    public function delete(Request $request)
186
    {
187 12
        abort_unless($request->ajax(), 405, 'Method Not Allowed');
188
189 8
        $date = $request->input('date');
190
191 8
        return response()->json([
0 ignored issues
show
Bug introduced by
The method json does only exist in Illuminate\Contracts\Routing\ResponseFactory, but not in Illuminate\Http\Response.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
192 8
            'result' => $this->logViewer->delete($date) ? 'success' : 'error'
193
        ]);
194
    }
195
196
    /* -----------------------------------------------------------------
197
     |  Other Methods
198
     | -----------------------------------------------------------------
199
     */
200
201
    /**
202
     * Get the evaluated view contents for the given view.
203
     *
204
     * @param  string  $view
205
     * @param  array   $data
206
     * @param  array   $mergeData
207
     *
208
     * @return \Illuminate\View\View
209
     */
210 32
    protected function view($view, $data = [], $mergeData = [])
211
    {
212 32
        $theme = config('log-viewer.theme');
213
214 32
        return view()->make("log-viewer::{$theme}.{$view}", $data, $mergeData);
0 ignored issues
show
Bug introduced by
The method make does only exist in Illuminate\Contracts\View\Factory, but not in Illuminate\View\View.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
215
    }
216
217
    /**
218
     * Paginate logs.
219
     *
220
     * @param  array                     $data
221
     * @param  \Illuminate\Http\Request  $request
222
     *
223
     * @return \Illuminate\Pagination\LengthAwarePaginator
224
     */
225 4
    protected function paginate(array $data, Request $request)
226
    {
227 4
        $data = new Collection($data);
228 4
        $page = $request->get('page', 1);
229 4
        $path = $request->url();
230
231 4
        return new LengthAwarePaginator(
232 4
            $data->forPage($page, $this->perPage),
233 4
            $data->count(),
234 4
            $this->perPage,
235
            $page,
236 4
            compact('path')
237
        );
238
    }
239
240
    /**
241
     * Get a log or fail
242
     *
243
     * @param  string  $date
244
     *
245
     * @return \Arcanedev\LogViewer\Entities\Log|null
246
     */
247 28
    protected function getLogOrFail($date)
248
    {
249 28
        $log = null;
250
251
        try {
252 28
            $log = $this->logViewer->get($date);
253
        }
254 4
        catch (LogNotFoundException $e) {
255 4
            abort(404, $e->getMessage());
256
        }
257
258 24
        return $log;
259
    }
260
261
    /**
262
     * Prepare chart data.
263
     *
264
     * @param  \Arcanedev\LogViewer\Tables\StatsTable  $stats
265
     *
266
     * @return string
267
     */
268 4
    protected function prepareChartData(StatsTable $stats)
269
    {
270 4
        $totals = $stats->totals()->all();
271
272 4
        return json_encode([
273 4
            'labels'   => Arr::pluck($totals, 'label'),
0 ignored issues
show
Documentation introduced by
$totals is of type array, but the function expects a object<Illuminate\Support\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
274
            'datasets' => [
275
                [
276 4
                    'data'                 => Arr::pluck($totals, 'value'),
0 ignored issues
show
Documentation introduced by
$totals is of type array, but the function expects a object<Illuminate\Support\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
277 4
                    'backgroundColor'      => Arr::pluck($totals, 'color'),
0 ignored issues
show
Documentation introduced by
$totals is of type array, but the function expects a object<Illuminate\Support\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
278 4
                    'hoverBackgroundColor' => Arr::pluck($totals, 'highlight'),
0 ignored issues
show
Documentation introduced by
$totals is of type array, but the function expects a object<Illuminate\Support\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
279
                ],
280
            ],
281
        ]);
282
    }
283
284
    /**
285
     * Calculate the percentage.
286
     *
287
     * @param  array  $total
288
     * @param  array  $names
289
     *
290
     * @return array
291
     */
292 4
    protected function calcPercentages(array $total, array $names)
293
    {
294 4
        $percents = [];
295 4
        $all      = Arr::get($total, 'all');
296
297 4
        foreach ($total as $level => $count) {
298 4
            $percents[$level] = [
299 4
                'name'    => $names[$level],
300 4
                'count'   => $count,
301 4
                'percent' => $all ? round(($count / $all) * 100, 2) : 0,
302
            ];
303
        }
304
305 4
        return $percents;
306
    }
307
}
308