Completed
Pull Request — master (#294)
by ARCANEDEV
04:34
created

LogViewerController::search()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 2.0017

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 3
dl 0
loc 20
ccs 12
cts 13
cp 0.9231
crap 2.0017
rs 9.6
c 0
b 0
f 0
1
<?php namespace Arcanedev\LogViewer\Http\Controllers;
2
3
use Arcanedev\LogViewer\Contracts\LogViewer as LogViewerContract;
4
use Arcanedev\LogViewer\Entities\LogEntry;
5
use Arcanedev\LogViewer\Entities\LogEntryCollection;
6
use Arcanedev\LogViewer\Exceptions\LogNotFoundException;
7
use Arcanedev\LogViewer\Tables\StatsTable;
8
use Illuminate\Http\Request;
9
use Illuminate\Pagination\LengthAwarePaginator;
10
use Illuminate\Routing\Controller;
11
use Illuminate\Support\Arr;
12
use Illuminate\Support\Collection;
13
use Illuminate\Support\Str;
14
15
/**
16
 * Class     LogViewerController
17
 *
18
 * @package  LogViewer\Http\Controllers
19
 * @author   ARCANEDEV <[email protected]>
20
 */
21
class LogViewerController extends Controller
22
{
23
    /* -----------------------------------------------------------------
24
     |  Properties
25
     | -----------------------------------------------------------------
26
     */
27
28
    /**
29
     * The log viewer instance
30
     *
31
     * @var \Arcanedev\LogViewer\Contracts\LogViewer
32
     */
33
    protected $logViewer;
34
35
    /** @var int */
36
    protected $perPage = 30;
37
38
    /** @var string */
39
    protected $showRoute = 'log-viewer::logs.show';
40
41
    /* -----------------------------------------------------------------
42
     |  Constructor
43
     | -----------------------------------------------------------------
44
     */
45
46
    /**
47
     * LogViewerController constructor.
48
     *
49
     * @param  \Arcanedev\LogViewer\Contracts\LogViewer  $logViewer
50
     */
51 24
    public function __construct(LogViewerContract $logViewer)
52
    {
53 24
        $this->logViewer = $logViewer;
54 24
        $this->perPage = config('log-viewer.per-page', $this->perPage);
55 24
    }
56
57
    /* -----------------------------------------------------------------
58
     |  Main Methods
59
     | -----------------------------------------------------------------
60
     */
61
62
    /**
63
     * Show the dashboard.
64
     *
65
     * @return \Illuminate\View\View
66
     */
67 2
    public function index()
68
    {
69 2
        $stats     = $this->logViewer->statsTable();
70 2
        $chartData = $this->prepareChartData($stats);
71 2
        $percents  = $this->calcPercentages($stats->footer(), $stats->header());
72
73 2
        return $this->view('dashboard', compact('chartData', 'percents'));
74
    }
75
76
    /**
77
     * List all logs.
78
     *
79
     * @param  \Illuminate\Http\Request  $request
80
     *
81
     * @return \Illuminate\View\View
82
     */
83 2
    public function listLogs(Request $request)
84
    {
85 2
        $stats   = $this->logViewer->statsTable();
86 2
        $headers = $stats->header();
87 2
        $rows    = $this->paginate($stats->rows(), $request);
88
89 2
        return $this->view('logs', compact('headers', 'rows'));
90
    }
91
92
    /**
93
     * Show the log.
94
     *
95
     * @param  \Illuminate\Http\Request  $request
96
     * @param  string                    $date
97
     *
98
     * @return \Illuminate\View\View
99
     */
100 4
    public function show(Request $request, $date)
101
    {
102 4
        $level   = 'all';
103 4
        $log     = $this->getLogOrFail($date);
104 2
        $query   = $request->get('query');
105 2
        $levels  = $this->logViewer->levelsNames();
106 2
        $entries = $log->entries($level)->paginate($this->perPage);
107
108 2
        return $this->view('show', compact('level', 'log', 'query', 'levels', 'entries'));
109
    }
110
111
    /**
112
     * Filter the log entries by level.
113
     *
114
     * @param  \Illuminate\Http\Request  $request
115
     * @param  string                    $date
116
     * @param  string                    $level
117
     *
118
     * @return \Illuminate\View\View|\Illuminate\Http\RedirectResponse
119
     */
120 4
    public function showByLevel(Request $request, $date, $level)
121
    {
122 4
        if ($level === 'all')
123 2
            return redirect()->route($this->showRoute, [$date]);
124
125 2
        $log     = $this->getLogOrFail($date);
126 2
        $query   = $request->get('query');
127 2
        $levels  = $this->logViewer->levelsNames();
128 2
        $entries = $this->logViewer->entries($date, $level)->paginate($this->perPage);
129
130 2
        return $this->view('show', compact('level', 'log', 'query', 'levels', 'entries'));
131
    }
132
133
    /**
134
     * Show the log with the search query.
135
     *
136
     * @param  \Illuminate\Http\Request  $request
137
     * @param  string                    $date
138
     * @param  string                    $level
139
     *
140
     * @return \Illuminate\View\View|\Illuminate\Http\RedirectResponse
141
     */
142 4
    public function search(Request $request, $date, $level = 'all')
143
    {
144 4
        $query   = $request->get('query');
145
146 4
        if (is_null($query))
147
            return redirect()->route($this->showRoute, [$date]);
148
149 4
        $log     = $this->getLogOrFail($date);
150 4
        $levels  = $this->logViewer->levelsNames();
151 4
        $needles = array_filter(explode(' ', $query));
152 4
        $entries = $log->entries($level)
153
            ->unless(empty($needles), function (LogEntryCollection $entries) use ($needles) {
154
                return $entries->filter(function (LogEntry $entry) use ($needles) {
155 4
                    return Str::containsAll($entry->header, $needles);
156 4
                });
157 4
            })
158 4
            ->paginate($this->perPage);
159
160 4
        return $this->view('show', compact('level', 'log', 'query', 'levels', 'entries'));
161
    }
162
163
    /**
164
     * Download the log
165
     *
166
     * @param  string  $date
167
     *
168
     * @return \Symfony\Component\HttpFoundation\BinaryFileResponse
169
     */
170 2
    public function download($date)
171
    {
172 2
        return $this->logViewer->download($date);
173
    }
174
175
    /**
176
     * Delete a log.
177
     *
178
     * @param  \Illuminate\Http\Request  $request
179
     *
180
     * @return \Illuminate\Http\JsonResponse
181
     */
182 6
    public function delete(Request $request)
183
    {
184 6
        abort_unless($request->ajax(), 405, 'Method Not Allowed');
185
186 4
        $date = $request->get('date');
187
188 4
        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...
189 4
            'result' => $this->logViewer->delete($date) ? 'success' : 'error'
190
        ]);
191
    }
192
193
    /* -----------------------------------------------------------------
194
     |  Other Methods
195
     | -----------------------------------------------------------------
196
     */
197
198
    /**
199
     * Get the evaluated view contents for the given view.
200
     *
201
     * @param  string  $view
202
     * @param  array   $data
203
     * @param  array   $mergeData
204
     *
205
     * @return \Illuminate\View\View
206
     */
207 12
    protected function view($view, $data = [], $mergeData = [])
208
    {
209 12
        $theme = config('log-viewer.theme');
210
211 12
        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...
212
    }
213
214
    /**
215
     * Paginate logs.
216
     *
217
     * @param  array                     $data
218
     * @param  \Illuminate\Http\Request  $request
219
     *
220
     * @return \Illuminate\Pagination\LengthAwarePaginator
221
     */
222 2
    protected function paginate(array $data, Request $request)
223
    {
224 2
        $data = new Collection($data);
225 2
        $page = $request->get('page', 1);
226 2
        $path = $request->url();
227
228 2
        return new LengthAwarePaginator(
229 2
            $data->forPage($page, $this->perPage),
230 2
            $data->count(),
231 2
            $this->perPage,
232 1
            $page,
233 2
            compact('path')
234
        );
235
    }
236
237
    /**
238
     * Get a log or fail
239
     *
240
     * @param  string  $date
241
     *
242
     * @return \Arcanedev\LogViewer\Entities\Log|null
243
     */
244 10
    protected function getLogOrFail($date)
245
    {
246 10
        $log = null;
247
248
        try {
249 10
            $log = $this->logViewer->get($date);
250
        }
251 2
        catch (LogNotFoundException $e) {
252 2
            abort(404, $e->getMessage());
253
        }
254
255 8
        return $log;
256
    }
257
258
    /**
259
     * Prepare chart data.
260
     *
261
     * @param  \Arcanedev\LogViewer\Tables\StatsTable  $stats
262
     *
263
     * @return string
264
     */
265 2
    protected function prepareChartData(StatsTable $stats)
266
    {
267 2
        $totals = $stats->totals()->all();
268
269 2
        return json_encode([
270 2
            'labels'   => Arr::pluck($totals, 'label'),
271
            'datasets' => [
272
                [
273 2
                    'data'                 => Arr::pluck($totals, 'value'),
274 2
                    'backgroundColor'      => Arr::pluck($totals, 'color'),
275 2
                    'hoverBackgroundColor' => Arr::pluck($totals, 'highlight'),
276
                ],
277
            ],
278
        ]);
279
    }
280
281
    /**
282
     * Calculate the percentage.
283
     *
284
     * @param  array  $total
285
     * @param  array  $names
286
     *
287
     * @return array
288
     */
289 2
    protected function calcPercentages(array $total, array $names)
290
    {
291 2
        $percents = [];
292 2
        $all      = Arr::get($total, 'all');
293
294 2
        foreach ($total as $level => $count) {
295 2
            $percents[$level] = [
296 2
                'name'    => $names[$level],
297 2
                'count'   => $count,
298 2
                'percent' => $all ? round(($count / $all) * 100, 2) : 0,
299
            ];
300
        }
301
302 2
        return $percents;
303
    }
304
}
305