Completed
Pull Request — master (#3)
by Valentin
11:14
created

SnapshotsController::removeBackURI()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 7

Duplication

Lines 11
Ratio 100 %

Importance

Changes 0
Metric Value
dl 11
loc 11
c 0
b 0
f 0
rs 9.4285
cc 2
eloc 7
nc 2
nop 1
1
<?php
2
3
namespace Spiral\Snapshotter\AggregationHandler\Controllers;
4
5
use Psr\Http\Message\ServerRequestInterface;
6
use Spiral\Database\Builders\SelectQuery;
7
use Spiral\Http\Exceptions\ClientExceptions\NotFoundException;
8
use Spiral\Http\Request\InputManager;
9
use Spiral\Http\Response\ResponseWrapper;
10
use Spiral\Snapshotter\AbstractController;
11
use Spiral\Snapshotter\AggregationHandler\Database\IncidentRecord;
12
use Spiral\Snapshotter\AggregationHandler\Database\SnapshotRecord;
13
use Spiral\Snapshotter\AggregationHandler\Database\Sources\IncidentSource;
14
use Spiral\Snapshotter\AggregationHandler\Database\Sources\SnapshotSource;
15
use Spiral\Snapshotter\AggregationHandler\Services\SnapshotService;
16
use Spiral\Snapshotter\Helpers\Names;
17
use Spiral\Snapshotter\Helpers\Timestamps;
18
19
use Spiral\Vault\Vault;
20
use Spiral\Views\ViewManager;
21
22
/**
23
 * @property InputManager    $input
24
 * @property ViewManager     $views
25
 * @property Vault           $vault
26
 * @property ResponseWrapper $response
27
 */
28
class SnapshotsController extends AbstractController
29
{
30
    /**
31
     * List of snapshots.
32
     *
33
     * @param SnapshotSource $source
34
     * @param Timestamps     $timestamps
35
     * @param Names          $names
36
     * @return string
37
     */
38
    public function indexAction(SnapshotSource $source, Timestamps $timestamps, Names $names)
39
    {
40
        $selector = $source->findWithLast()->orderBy(
41
            'last_incident.time_created',
42
            SelectQuery::SORT_DESC
43
        );
44
45
        return $this->views->render('snapshotter:aggregation/list', [
46
            'selector'     => $selector,
47
            'lastSnapshot' => $source->findLast(),
48
            'timestamps'   => $timestamps,
49
            'names'        => $names
50
        ]);
51
    }
52
53
    /**
54
     * View snapshot.
55
     *
56
     * @param string|int      $id
57
     * @param SnapshotService $service
58
     * @param IncidentSource  $source
59
     * @param Timestamps      $timestamps
60
     * @param Names           $names
61
     * @return string
62
     */
63
    public function viewAction(
64
        $id,
65
        SnapshotService $service,
66
        IncidentSource $source,
67
        Timestamps $timestamps,
68
        Names $names
69
    ) {
70
        /** @var SnapshotRecord $snapshot */
71
        $snapshot = $service->getSource()->findWithLastByPK($id);
72
        if (empty($snapshot)) {
73
            throw new NotFoundException;
74
        }
75
76
        $this->authorize('view', compact('snapshot'));
77
78
        $selector = $source->findSnapshotHistory($snapshot)->orderBy(
79
            'time_created',
80
            SelectQuery::SORT_DESC
81
        );
82
83
        $occurred = $service->countOccurred($snapshot, $source);
84
85
        return $this->views->render('snapshotter:aggregation/snapshot', [
86
            'selector'   => $selector,
87
            'occurred'   => $occurred,
88
            'snapshot'   => $snapshot,
89
            'timestamps' => $timestamps,
90
            'names'      => $names
91
        ]);
92
    }
93
94
    /**
95
     * Suppression snapshot state.
96
     *
97
     * @param string|int     $id
98
     * @param SnapshotSource $source
99
     * @return array
100
     */
101 View Code Duplication
    public function suppressAction($id, SnapshotSource $source)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
102
    {
103
        /** @var SnapshotRecord $snapshot */
104
        $snapshot = $source->findWithLastByPK($id);
105
        if (empty($snapshot)) {
106
            throw new NotFoundException;
107
        }
108
109
        $this->authorize('edit', compact('snapshot'));
110
111
        $snapshot->setSuppression($this->input->data('suppression', false));
112
        $snapshot->save();
113
114
        return [
115
            'status'  => 200,
116
            'message' => $this->say('Suppression status updated.')
117
        ];
118
    }
119
120
    /**
121
     * View last snapshot incident source.
122
     *
123
     * @param string|int     $id
124
     * @param SnapshotSource $source
125
     * @return string
126
     */
127
    public function iframeAction($id, SnapshotSource $source)
128
    {
129
        /** @var SnapshotRecord $snapshot */
130
        $snapshot = $source->findWithLastByPK($id);
131
        if (empty($snapshot)) {
132
            throw new NotFoundException;
133
        }
134
135
        $this->authorize('view', compact('snapshot'));
136
137
        return $snapshot->getLastIncident()->getExceptionSource();
138
    }
139
140
    /**
141
     * Remove all snapshots with all incident records.
142
     *
143
     * @param SnapshotService $service
144
     * @return array|\Psr\Http\Message\ResponseInterface
145
     */
146
    public function removeAllAction(SnapshotService $service)
147
    {
148
        $this->authorize('removeAll');
149
150
        foreach ($service->getSource()->findWithLast() as $snapshot) {
151
            $service->delete($snapshot);
152
        }
153
154
        $uri = $this->vault->uri('snapshots');
155
156
        if ($this->input->isAjax()) {
157
            return [
158
                'status'  => 200,
159
                'message' => $this->say('Snapshots deleted.'),
160
                'action'  => ['redirect' => $uri]
161
            ];
162
        } else {
163
            return $this->response->redirect($uri);
164
        }
165
    }
166
167
    /**
168
     * Remove single snapshot with all incident records.
169
     *
170
     * @param string|int             $id
171
     * @param SnapshotService        $service
172
     * @param ServerRequestInterface $request
173
     * @return array
174
     */
175 View Code Duplication
    public function removeAction(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
176
        $id,
177
        SnapshotService $service,
178
        ServerRequestInterface $request
179
    ) {
180
        /** @var SnapshotRecord $snapshot */
181
        $snapshot = $service->getSource()->findWithLastByPK($id);
182
        if (empty($snapshot)) {
183
            throw new NotFoundException;
184
        }
185
186
        $this->authorize('remove', compact('snapshot'));
187
188
        $service->delete($snapshot);
189
190
        $uri = $this->removeBackURI($request);
191
192
        if ($this->input->isAjax()) {
193
            return [
194
                'status'  => 200,
195
                'message' => $this->say('Snapshot deleted.'),
196
                'action'  => ['redirect' => $uri]
197
            ];
198
        } else {
199
            return $this->response->redirect($uri);
200
        }
201
    }
202
203
    /**
204
     * Build redirect URI for removal operation.
205
     *
206
     * @param ServerRequestInterface $request
207
     * @return \Psr\Http\Message\UriInterface
208
     */
209 View Code Duplication
    protected function removeBackURI(ServerRequestInterface $request)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
210
    {
211
        $query = $request->getQueryParams();
212
        if (array_key_exists('backToList', $query)) {
213
            $uri = $this->vault->uri('snapshots');
214
        } else {
215
            $uri = $request->getServerParams()['HTTP_REFERER'];
216
        }
217
218
        return $uri;
219
    }
220
221
    /**
222
     * Suppress snapshot incident. Can suppress only stored snapshots.
223
     *
224
     * @param string|int     $id
225
     * @param IncidentSource $incidentSource
226
     * @param SnapshotSource $snapshotSource
227
     * @return \Psr\Http\Message\ResponseInterface
228
     */
229 View Code Duplication
    public function suppressIncidentAction(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
230
        $id,
231
        IncidentSource $incidentSource,
232
        SnapshotSource $snapshotSource
233
    ) {
234
        /** @var SnapshotRecord $snapshot */
235
        $snapshot = $snapshotSource->findWithLastByPK($id);
236
        if (empty($snapshot)) {
237
            throw new NotFoundException;
238
        }
239
240
        /** @var IncidentRecord $incident */
241
        $incident = $incidentSource->findStoredBySnapshotByPK(
242
            $snapshot,
243
            $this->input->query('incident')
244
        );
245
        if (empty($incident)) {
246
            throw new NotFoundException;
247
        }
248
249
        $this->authorize('edit', compact('snapshot'));
250
251
        $incident->suppress();
252
        $incident->save();
253
254
        $uri = $this->vault
255
            ->uri('snapshots:edit', ['id' => $snapshot->primaryKey()])
256
            ->withFragment('history');
257
258
        if ($this->input->isAjax()) {
259
            return [
0 ignored issues
show
Bug Best Practice introduced by
The return type of return array('status' =>...y('redirect' => $uri)); (array<string,integer|str...\Message\UriInterface>>) is incompatible with the return type documented by Spiral\Snapshotter\Aggre...:suppressIncidentAction of type Psr\Http\Message\ResponseInterface.

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...
260
                'status'  => 200,
261
                'message' => $this->say('Snapshot incident suppressed.'),
262
                'action'  => ['redirect' => $uri]
263
            ];
264
        } else {
265
            return $this->response->redirect($uri);
266
        }
267
    }
268
269
    /**
270
     * View snapshot incident.
271
     *
272
     * @param string|int     $id
273
     * @param IncidentSource $incidentSource
274
     * @param SnapshotSource $snapshotSource
275
     * @return string
276
     */
277
    public function incidentAction(
278
        $id,
279
        IncidentSource $incidentSource,
280
        SnapshotSource $snapshotSource
281
    ) {
282
        /** @var SnapshotRecord $snapshot */
283
        $snapshot = $snapshotSource->findWithLastByPK($id);
284
        if (empty($snapshot)) {
285
            throw new NotFoundException;
286
        }
287
288
        /** @var IncidentRecord $incident */
289
        $incident = $incidentSource->findStoredBySnapshotByPK(
290
            $snapshot,
291
            $this->input->query('incident')
292
        );
293
        if (empty($incident)) {
294
            throw new NotFoundException;
295
        }
296
297
        $this->authorize('view', compact('snapshot'));
298
299
        return $this->views->render(
300
            'snapshotter:aggregation/incident',
301
            compact('incident', 'snapshot')
302
        );
303
    }
304
305
    /**
306
     * View snapshot incident source.
307
     *
308
     * @param string|int     $id
309
     * @param IncidentSource $incidentSource
310
     * @param SnapshotSource $snapshotSource
311
     * @return null|string
312
     */
313
    public function iframeIncidentAction(
314
        $id,
315
        IncidentSource $incidentSource,
316
        SnapshotSource $snapshotSource
317
    ) {
318
        /** @var SnapshotRecord $snapshot */
319
        $snapshot = $snapshotSource->findWithLastByPK($id);
320
        if (empty($snapshot)) {
321
            throw new NotFoundException;
322
        }
323
324
        /** @var IncidentRecord $incident */
325
        $incident = $incidentSource->findStoredBySnapshotByPK(
326
            $snapshot,
327
            $this->input->query('incident')
328
        );
329
        if (empty($incident)) {
330
            throw new NotFoundException;
331
        }
332
333
        $this->authorize('view', compact('snapshot'));
334
335
        return $incident->getExceptionSource();
336
    }
337
338
    /**
339
     * Remove snapshot incident. Clean source and delete.
340
     *
341
     * @param string|int     $id
342
     * @param IncidentSource $incidentSource
343
     * @param SnapshotSource $snapshotSource
344
     * @return array
345
     */
346 View Code Duplication
    public function removeIncidentAction(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
347
        $id,
348
        IncidentSource $incidentSource,
349
        SnapshotSource $snapshotSource
350
    ) {
351
        /** @var SnapshotRecord $snapshot */
352
        $snapshot = $snapshotSource->findWithLastByPK($id);
353
        if (empty($snapshot)) {
354
            throw new NotFoundException;
355
        }
356
357
        /** @var IncidentRecord $incident */
358
        $incident = $incidentSource->findBySnapshotByPK(
359
            $snapshot,
360
            $this->input->query('incident')
361
        );
362
        if (empty($incident)) {
363
            throw new NotFoundException;
364
        }
365
366
        $this->authorize('edit', compact('snapshot'));
367
368
        $incident->delete();
369
370
        $uri = $this->vault
371
            ->uri('snapshots:edit', ['id' => $snapshot->primaryKey()])
372
            ->withFragment('history');
373
374
        if ($this->input->isAjax()) {
375
            return [
376
                'status'  => 200,
377
                'message' => $this->say('Snapshot incident deleted.'),
378
                'action'  => ['redirect' => $uri]
379
            ];
380
        } else {
381
            return $this->response->redirect($uri);
382
        }
383
    }
384
}