Completed
Push — master ( 5aacb3...58dc7e )
by ARCANEDEV
12s
created

LogViewerController   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 272
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 13

Test Coverage

Coverage 98.7%

Importance

Changes 0
Metric Value
dl 0
loc 272
ccs 76
cts 77
cp 0.987
rs 10
c 0
b 0
f 0
wmc 20
lcom 1
cbo 13

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A index() 0 8 1
A listLogs() 0 8 1
A show() 0 8 1
A showByLevel() 0 12 2
A download() 0 4 1
A view() 0 4 1
A getLogOrFail() 0 13 2
A delete() 0 11 3
A paginate() 0 14 1
A prepareChartData() 0 15 1
A calcPercentages() 0 15 3
A search() 0 13 2
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\Exceptions\LogNotFoundException;
6
use Arcanedev\LogViewer\Tables\StatsTable;
7
use Illuminate\Http\Request;
8
use Illuminate\Pagination\LengthAwarePaginator;
9
use Illuminate\Routing\Controller;
10
use Illuminate\Support\Arr;
11
use Illuminate\Support\Str;
12
13
/**
14
 * Class     LogViewerController
15
 *
16
 * @package  LogViewer\Http\Controllers
17
 * @author   ARCANEDEV <[email protected]>
18
 */
19
class LogViewerController extends Controller
20
{
21
    /* -----------------------------------------------------------------
22
     |  Properties
23
     | -----------------------------------------------------------------
24
     */
25
26
    /**
27
     * The log viewer instance
28
     *
29
     * @var \Arcanedev\LogViewer\Contracts\LogViewer
30
     */
31
    protected $logViewer;
32
33
    /** @var int */
34
    protected $perPage = 30;
35
36
    /** @var string */
37
    protected $showRoute = 'log-viewer::logs.show';
38
39
    /* -----------------------------------------------------------------
40
     |  Constructor
41
     | -----------------------------------------------------------------
42
     */
43
44
    /**
45
     * LogViewerController constructor.
46
     *
47
     * @param  \Arcanedev\LogViewer\Contracts\LogViewer  $logViewer
48
     */
49 22
    public function __construct(LogViewerContract $logViewer)
50
    {
51 22
        $this->logViewer = $logViewer;
52 22
        $this->perPage = config('log-viewer.per-page', $this->perPage);
53 22
    }
54
55
    /* -----------------------------------------------------------------
56
     |  Main Methods
57
     | -----------------------------------------------------------------
58
     */
59
60
    /**
61
     * Show the dashboard.
62
     *
63
     * @return \Illuminate\View\View
64
     */
65 2
    public function index()
66
    {
67 2
        $stats     = $this->logViewer->statsTable();
68 2
        $chartData = $this->prepareChartData($stats);
69 2
        $percents  = $this->calcPercentages($stats->footer(), $stats->header());
70
71 2
        return $this->view('dashboard', compact('chartData', 'percents'));
72
    }
73
74
    /**
75
     * List all logs.
76
     *
77
     * @param  \Illuminate\Http\Request  $request
78
     *
79
     * @return \Illuminate\View\View
80
     */
81 2
    public function listLogs(Request $request)
82
    {
83 2
        $stats   = $this->logViewer->statsTable();
84 2
        $headers = $stats->header();
85 2
        $rows    = $this->paginate($stats->rows(), $request);
86
87 2
        return $this->view('logs', compact('headers', 'rows', 'footer'));
88
    }
89
90
    /**
91
     * Show the log.
92
     *
93
     * @param  string  $date
94
     *
95
     * @return \Illuminate\View\View
96
     */
97 4
    public function show($date)
98
    {
99 4
        $log     = $this->getLogOrFail($date);
100 2
        $levels  = $this->logViewer->levelsNames();
101 2
        $entries = $log->entries($level = 'all')->paginate($this->perPage);
102
103 2
        return $this->view('show', compact('log', 'levels', 'level', 'search', 'entries'));
104
    }
105
106
    /**
107
     * Filter the log entries by level.
108
     *
109
     * @param  string  $date
110
     * @param  string  $level
111
     *
112
     * @return \Illuminate\View\View|\Illuminate\Http\RedirectResponse
113
     */
114 4
    public function showByLevel($date, $level)
115
    {
116 4
        $log = $this->getLogOrFail($date);
117
118 4
        if ($level === 'all')
119 2
            return redirect()->route($this->showRoute, [$date]);
120
121 2
        $levels  = $this->logViewer->levelsNames();
122 2
        $entries = $this->logViewer->entries($date, $level)->paginate($this->perPage);
123
124 2
        return $this->view('show', compact('log', 'levels', 'level', 'search', 'entries'));
125
    }
126
127
    /**
128
     * Show the log with the search query.
129
     *
130
     * @param  string                    $date
131
     * @param  string                    $level
132
     * @param  \Illuminate\Http\Request  $request
133
     *
134
     * @return \Illuminate\View\View
135
     */
136 2
    public function search($date, $level = 'all', Request $request) {
137 2
        $log   = $this->getLogOrFail($date);
138
139 2
        if (is_null($query = $request->get('query')))
140
            return redirect()->route('log-viewer::logs.show', [$date]);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return redirect()->route...s.show', array($date)); (Illuminate\Http\RedirectResponse) is incompatible with the return type documented by Arcanedev\LogViewer\Http...iewerController::search of type Illuminate\View\View.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
141
142 2
        $levels  = $this->logViewer->levelsNames();
143 2
        $entries = $log->entries($level)->filter(function (LogEntry $value) use ($query) {
144 2
            return Str::contains($value->header, $query);
145 2
        })->paginate($this->perPage);
146
147 2
        return $this->view('show', compact('log', 'levels', 'level', 'query', 'entries'));
148
    }
149
150
    /**
151
     * Download the log
152
     *
153
     * @param  string  $date
154
     *
155
     * @return \Symfony\Component\HttpFoundation\BinaryFileResponse
156
     */
157 2
    public function download($date)
158
    {
159 2
        return $this->logViewer->download($date);
160
    }
161
162
    /**
163
     * Delete a log.
164
     *
165
     * @param  \Illuminate\Http\Request  $request
166
     *
167
     * @return \Illuminate\Http\JsonResponse
168
     */
169 6
    public function delete(Request $request)
170
    {
171 6
        if ( ! $request->ajax())
172 2
            abort(405, 'Method Not Allowed');
173
174 4
        $date = $request->get('date');
175
176 4
        return response()->json([
177 4
            'result' => $this->logViewer->delete($date) ? 'success' : 'error'
178
        ]);
179
    }
180
181
    /* -----------------------------------------------------------------
182
     |  Other Methods
183
     | -----------------------------------------------------------------
184
     */
185
186
    /**
187
     * Get the evaluated view contents for the given view.
188
     *
189
     * @param  string  $view
190
     * @param  array   $data
191
     * @param  array   $mergeData
192
     *
193
     * @return \Illuminate\View\View
194
     */
195 10
    protected function view($view, $data = [], $mergeData = [])
196
    {
197 10
        return view('log-viewer::'.$view, $data, $mergeData);
0 ignored issues
show
Bug Compatibility introduced by
The expression view('log-viewer::' . $view, $data, $mergeData); of type Illuminate\View\View|Ill...\Contracts\View\Factory adds the type Illuminate\Contracts\View\Factory to the return on line 197 which is incompatible with the return type documented by Arcanedev\LogViewer\Http...gViewerController::view of type Illuminate\View\View.
Loading history...
198
    }
199
200
    /**
201
     * Paginate logs.
202
     *
203
     * @param  array                     $data
204
     * @param  \Illuminate\Http\Request  $request
205
     *
206
     * @return \Illuminate\Pagination\LengthAwarePaginator
207
     */
208 2
    protected function paginate(array $data, Request $request)
209
    {
210 2
        $data = collect($data);
211 2
        $page = $request->get('page', 1);
212 2
        $url  = $request->url();
213
214 2
        return new LengthAwarePaginator(
215 2
            $data->forPage($page, $this->perPage),
216 2
            $data->count(),
217 2
            $this->perPage,
218 2
            $page,
219 2
            compact('url')
220
        );
221
    }
222
223
    /**
224
     * Get a log or fail
225
     *
226
     * @param  string  $date
227
     *
228
     * @return \Arcanedev\LogViewer\Entities\Log|null
229
     */
230 10
    protected function getLogOrFail($date)
231
    {
232 10
        $log = null;
233
234
        try {
235 10
            $log = $this->logViewer->get($date);
236
        }
237 2
        catch (LogNotFoundException $e) {
238 2
            abort(404, $e->getMessage());
239
        }
240
241 8
        return $log;
242
    }
243
244
    /**
245
     * Prepare chart data.
246
     *
247
     * @param  \Arcanedev\LogViewer\Tables\StatsTable  $stats
248
     *
249
     * @return string
250
     */
251 2
    protected function prepareChartData(StatsTable $stats)
252
    {
253 2
        $totals = $stats->totals()->all();
254
255 2
        return json_encode([
256 2
            'labels'   => Arr::pluck($totals, 'label'),
257
            'datasets' => [
258
                [
259 2
                    'data'                 => Arr::pluck($totals, 'value'),
260 2
                    'backgroundColor'      => Arr::pluck($totals, 'color'),
261 2
                    'hoverBackgroundColor' => Arr::pluck($totals, 'highlight'),
262
                ],
263
            ],
264
        ]);
265
    }
266
267
    /**
268
     * Calculate the percentage.
269
     *
270
     * @param  array  $total
271
     * @param  array  $names
272
     *
273
     * @return array
274
     */
275 2
    protected function calcPercentages(array $total, array $names)
276
    {
277 2
        $percents = [];
278 2
        $all      = Arr::get($total, 'all');
279
280 2
        foreach ($total as $level => $count) {
281 2
            $percents[$level] = [
282 2
                'name'    => $names[$level],
283 2
                'count'   => $count,
284 2
                'percent' => $all ? round(($count / $all) * 100, 2) : 0,
285
            ];
286
        }
287
288 2
        return $percents;
289
    }
290
}
291