Completed
Push — develop ( ddf7ca...4ba190 )
by John
02:49
created

ActiveRecordController::doPOST()   D

Complexity

Conditions 11
Paths 186

Size

Total Lines 82
Code Lines 54

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 82
rs 4.9629
cc 11
eloc 54
nc 186
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
namespace Alpha\Controller;
4
5
use Alpha\Controller\Front\FrontController;
6
use Alpha\Util\Logging\Logger;
7
use Alpha\Util\Config\ConfigProvider;
8
use Alpha\Util\Http\Request;
9
use Alpha\Util\Http\Response;
10
use Alpha\Util\Helper\Validator;
11
use Alpha\View\View;
12
use Alpha\View\ViewState;
13
use Alpha\Exception\IllegalArguementException;
14
use Alpha\Exception\ResourceNotFoundException;
15
use Alpha\Exception\ResourceNotAllowedException;
16
use Alpha\Exception\SecurityException;
17
use Alpha\Exception\AlphaException;
18
use Alpha\Exception\RecordNotFoundException;
19
use Alpha\Exception\ValidationException;
20
use Alpha\Model\ActiveRecord;
21
22
/**
23
 * The main active record CRUD controller for the framework.
24
 *
25
 * @since 2.0
26
 *
27
 * @author John Collins <[email protected]>
28
 * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
29
 * @copyright Copyright (c) 2017, John Collins (founder of Alpha Framework).
30
 * All rights reserved.
31
 *
32
 * <pre>
33
 * Redistribution and use in source and binary forms, with or
34
 * without modification, are permitted provided that the
35
 * following conditions are met:
36
 *
37
 * * Redistributions of source code must retain the above
38
 *   copyright notice, this list of conditions and the
39
 *   following disclaimer.
40
 * * Redistributions in binary form must reproduce the above
41
 *   copyright notice, this list of conditions and the
42
 *   following disclaimer in the documentation and/or other
43
 *   materials provided with the distribution.
44
 * * Neither the name of the Alpha Framework nor the names
45
 *   of its contributors may be used to endorse or promote
46
 *   products derived from this software without specific
47
 *   prior written permission.
48
 *
49
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
50
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
51
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
52
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
53
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
54
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
56
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
57
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
59
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
60
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
61
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62
 * </pre>
63
 */
64
class ActiveRecordController extends Controller implements ControllerInterface
65
{
66
    /**
67
     * The start number for list pageination.
68
     *
69
     * @var int
70
     *
71
     * @since 2.0
72
     */
73
    protected $start = 0;
74
75
    /**
76
     * The amount of records to return during pageination.
77
     *
78
     * @var int
79
     *
80
     * @since 2.0
81
     */
82
    protected $limit;
83
84
    /**
85
     * The count of the records of this type in the database (used during pagination).
86
     *
87
     * @var int
88
     *
89
     * @since 2.0
90
     */
91
    protected $recordCount = 0;
92
93
    /**
94
     * The field name to sort the list by (optional, default is ID).
95
     *
96
     * @var string
97
     *
98
     * @since 2.0
99
     */
100
    protected $sort;
101
102
    /**
103
     * The order to sort the list by (optional, should be ASC or DESC, default is ASC).
104
     *
105
     * @var string
106
     *
107
     * @since 2.0
108
     */
109
    protected $order;
110
111
    /**
112
     * The name of the Record field to filter the list by (optional).
113
     *
114
     * @var string
115
     *
116
     * @since 2.0
117
     */
118
    protected $filterField;
119
120
    /**
121
     * The value of the filterField to filter by (optional).
122
     *
123
     * @var string
124
     *
125
     * @since 2.0
126
     */
127
    protected $filterValue;
128
129
    /**
130
     * Trace logger.
131
     *
132
     * @var \Alpha\Util\Logging\Logger
133
     *
134
     * @since 2.0
135
     */
136
    private static $logger = null;
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
137
138
    /**
139
     * Constructor to set up the object.
140
     *
141
     * @param string $visibility The name of the rights group that can access this controller.
142
     *
143
     * @since 1.0
144
     */
145
    public function __construct($visibility = 'Admin')
146
    {
147
        self::$logger = new Logger('ActiveRecordController');
148
        self::$logger->debug('>>__construct()');
149
150
        // ensure that the super class constructor is called, indicating the rights group
151
        parent::__construct($visibility);
152
153
        self::$logger->debug('<<__construct');
154
    }
155
156
    /**
157
     * Handle GET requests.
158
     *
159
     * @param \Alpha\Util\Http\Request $request
160
     *
161
     * @throws \Alpha\Exception\ResourceNotFoundException
162
     * @throws \Alpha\Exception\IllegalArguementException
163
     *
164
     * @return \Alpha\Util\Http\Response
165
     *
166
     * @since 2.0
167
     */
168
    public function doGET($request)
169
    {
170
        self::$logger->debug('>>doGET(request=['.var_export($request, true).'])');
171
172
        $params = $request->getParams();
173
        $accept = $request->getAccept();
174
175
        $body = '';
176
177
        try {
178
            // get a single record
179
            if (isset($params['ActiveRecordType']) && isset($params['ActiveRecordID'])) {
180
                if (!Validator::isInteger($params['ActiveRecordID'])) {
181
                    throw new IllegalArguementException('Invalid oid ['.$params['ActiveRecordID'].'] provided on the request!');
182
                }
183
184
                $ActiveRecordType = urldecode($params['ActiveRecordType']);
185
186
                if (class_exists($ActiveRecordType)) {
187
                    $record = new $ActiveRecordType();
188
                } else {
189
                    throw new IllegalArguementException('No ActiveRecord available to view!');
190
                }
191
192
                // set up the title and meta details
193
                if (isset($params['view']) && $params['view'] == 'edit') {
194
                    if (!isset($this->title)) {
195
                        $this->setTitle('Editing a '.$record->getFriendlyClassName());
196
                    }
197
                    if (!isset($this->description)) {
198
                        $this->setDescription('Page to edit a '.$record->getFriendlyClassName().'.');
199
                    }
200
                    if (!isset($this->keywords)) {
201
                        $this->setKeywords('edit,'.$record->getFriendlyClassName());
202
                    }
203
                } else {
204
                    if (!isset($this->title)) {
205
                        $this->setTitle('Viewing a '.$record->getFriendlyClassName());
206
                    }
207
                    if (!isset($this->description)) {
208
                        $this->setDescription('Page to view a '.$record->getFriendlyClassName().'.');
209
                    }
210
                    if (!isset($this->keywords)) {
211
                        $this->setKeywords('view,'.$record->getFriendlyClassName());
212
                    }
213
                }
214
215
                $record->load($params['ActiveRecordID']);
216
                ActiveRecord::disconnect();
217
218
                $view = View::getInstance($record, false, $accept);
219
220
                $body .= View::displayPageHead($this);
221
222
                $message = $this->getStatusMessage();
223
                if (!empty($message)) {
224
                    $body .= $message;
225
                }
226
227
                $body .= View::renderDeleteForm($request->getURI());
228
229
                if (isset($params['view']) && $params['view'] == 'edit') {
230
                    $fields = array('formAction' => $this->request->getURI());
231
                    $body .= $view->editView($fields);
232
                } else {
233
                    $body .= $view->detailedView();
234
                }
235
            } elseif (isset($params['ActiveRecordType']) && isset($params['start'])) {
236
                // list all records of this type
237
                $ActiveRecordType = urldecode($params['ActiveRecordType']);
238
239
                if (class_exists($ActiveRecordType)) {
240
                    $record = new $ActiveRecordType();
241
                } else {
242
                    throw new IllegalArguementException('No ActiveRecord available to view!');
243
                }
244
245
                // set up the title and meta details
246
                if (!isset($this->title)) {
247
                    $this->setTitle('Listing all '.$record->getFriendlyClassName());
248
                }
249
                if (!isset($this->description)) {
250
                    $this->setDescription('Listing all '.$record->getFriendlyClassName());
251
                }
252
                if (!isset($this->keywords)) {
253
                    $this->setKeywords('list,all,'.$record->getFriendlyClassName());
254
                }
255
256
                if (isset($this->filterField) && isset($this->filterValue)) {
257
                    if (isset($this->sort) && isset($this->order)) {
258
                        $records = $record->loadAllByAttribute($this->filterField, $this->filterValue, $params['start'], $params['limit'],
259
                            $this->sort, $this->order);
260
                    } else {
261
                        $records = $record->loadAllByAttribute($this->filterField, $this->filterValue, $params['start'], $params['limit']);
262
                    }
263
264
                    $this->recordCount = $record->getCount(array($this->filterField), array($this->filterValue));
265
                } else {
266
                    if (isset($this->sort) && isset($this->order)) {
267
                        $records = $record->loadAll($params['start'], $params['limit'], $this->sort, $this->order);
268
                    } else {
269
                        $records = $record->loadAll($params['start'], $params['limit']);
270
                    }
271
272
                    $this->recordCount = $record->getCount();
273
                }
274
275
                ActiveRecord::disconnect();
276
277
                $view = View::getInstance($record, false, $accept);
278
279
                $body .= View::displayPageHead($this);
280
281
                $message = $this->getStatusMessage();
282
                if (!empty($message)) {
283
                    $body .= $message;
284
                }
285
286
                $body .= View::renderDeleteForm($this->request->getURI());
287
288
                foreach ($records as $record) {
289
                    $view = View::getInstance($record, false, $accept);
290
                    $fields = array('formAction' => $this->request->getURI());
291
                    $body .= $view->listView($fields);
292
                }
293
294
                if ($accept == 'application/json') {
295
                    $body = rtrim($body, ',');
296
                }
297
            } elseif (isset($params['ActiveRecordType'])) {
298
                // create a new record of this type
299
                $ActiveRecordType = urldecode($params['ActiveRecordType']);
300
301
                if (class_exists($ActiveRecordType)) {
302
                    $record = new $ActiveRecordType();
303
                } else {
304
                    throw new IllegalArguementException('No ActiveRecord available to create!');
305
                }
306
307
                // set up the title and meta details
308
                if (!isset($this->title)) {
309
                    $this->setTitle('Create a new '.$record->getFriendlyClassName());
310
                }
311
                if (!isset($this->description)) {
312
                    $this->setDescription('Create a new '.$record->getFriendlyClassName().'.');
313
                }
314
                if (!isset($this->keywords)) {
315
                    $this->setKeywords('create,new,'.$record->getFriendlyClassName());
316
                }
317
318
                $view = View::getInstance($record, false, $accept);
319
320
                $body .= View::displayPageHead($this);
321
                $fields = array('formAction' => $this->request->getURI());
322
                $body .= $view->createView($fields);
323
            } else {
324
                throw new IllegalArguementException('No ActiveRecord available to display!');
325
            }
326
        } catch (IllegalArguementException $e) {
327
            self::$logger->warn($e->getMessage());
328
            throw new ResourceNotFoundException('The record that you have requested cannot be found!');
329
        } catch (RecordNotFoundException $e) {
330
            self::$logger->warn($e->getMessage());
331
            throw new ResourceNotFoundException('The record that you have requested cannot be found!');
332
        }
333
334
        $body .= View::displayPageFoot($this);
335
336
        self::$logger->debug('<<doGET');
337
338
        return new Response(200, $body, array('Content-Type' => ($accept == 'application/json' ? 'application/json' : 'text/html')));
339
    }
340
341
    /**
342
     * Method to handle POST requests.
343
     *
344
     * @param \Alpha\Util\Http\Request $request
345
     *
346
     * @throws \Alpha\Exception\IllegalArguementException
347
     * @throws \Alpha\Exception\SecurityException
348
     *
349
     * @return \Alpha\Util\Http\Response
350
     *
351
     * @since 2.0
352
     */
353
    public function doPOST($request)
354
    {
355
        self::$logger->debug('>>doDPOST(request=['.var_export($request, true).'])');
356
357
        $config = ConfigProvider::getInstance();
358
359
        $params = $request->getParams();
360
        $accept = $request->getAccept();
361
362
        try {
363
            if (isset($params['ActiveRecordType'])) {
364
                $ActiveRecordType = urldecode($params['ActiveRecordType']);
365
            } else {
366
                throw new IllegalArguementException('No ActiveRecord available to create!');
367
            }
368
369
            if (class_exists($ActiveRecordType)) {
370
                $record = new $ActiveRecordType();
371
            } else {
372
                throw new IllegalArguementException('No ActiveRecord ['.$ActiveRecordType.'] available to create!');
373
            }
374
375
            // check the hidden security fields before accepting the form POST data
376
            if (!$this->checkSecurityFields()) {
377
                throw new SecurityException('This page cannot accept post data from remote servers!');
378
            }
379
380
            $record->populateFromArray($params);
381
382
            try {
383
                $record->save();
384
            } catch (ValidationException $e) {
385
                self::$logger->warn($e->getMessage());
386
                $this->setStatusMessage(View::displayErrorMessage($e->getMessage()));
387
            }
388
389
            self::$logger->action('Created new '.$ActiveRecordType.' instance with ID '.$record->getID());
390
391
            if (isset($params['statusMessage'])) {
392
                $this->setStatusMessage(View::displayUpdateMessage($params['statusMessage']));
393
            } else {
394
                $this->setStatusMessage(View::displayUpdateMessage('Created'));
395
            }
396
397
            ActiveRecord::disconnect();
398
399
            if ($accept == 'application/json') {
400
                $view = View::getInstance($record, false, $accept);
401
                $body = $view->detailedView();
402
                $response = new Response(201);
403
                $response->setHeader('Content-Type', 'application/json');
404
                $response->setHeader('Location', $config->get('app.url').'/record/'.$params['ActiveRecordType'].'/'.$record->getID());
405
                $response->setBody($body);
406
407
                self::$logger->debug('<<doPOST');
408
409
                return $response;
410
            } else {
411
                $response = new Response(301);
412
413
                if ($this->getNextJob() != '') {
414
                    $response->redirect($this->getNextJob());
415
                } else {
416
                    if ($this->request->isSecureURI()) {
417
                        $response->redirect(FrontController::generateSecureURL('act=Alpha\\Controller\\ActiveRecordController&ActiveRecordType='.$ActiveRecordType.'&ActiveRecordID='.$record->getID()));
418
                    } else {
419
                        $response->redirect($config->get('app.url').'/record/'.$params['ActiveRecordType'].'/'.$record->getID());
420
                    }
421
                }
422
423
                self::$logger->debug('<<doPOST');
424
425
                return $response;
426
            }
427
        } catch (SecurityException $e) {
428
            self::$logger->warn($e->getMessage());
429
            throw new ResourceNotAllowedException($e->getMessage());
430
        } catch (IllegalArguementException $e) {
431
            self::$logger->warn($e->getMessage());
432
            throw new ResourceNotFoundException('The record that you have requested cannot be found!');
433
        }
434
    }
435
436
    /**
437
     * Method to handle PUT requests.
438
     *
439
     * @param \Alpha\Util\Http\Request $request
440
     *
441
     * @throws \Alpha\Exception\IllegalArguementException
442
     * @throws \Alpha\Exception\SecurityException
443
     *
444
     * @return \Alpha\Util\Http\Response
445
     *
446
     * @since 2.0
447
     */
448
    public function doPUT($request)
449
    {
450
        self::$logger->debug('>>doPUT(request=['.var_export($request, true).'])');
451
452
        $config = ConfigProvider::getInstance();
453
454
        $params = $request->getParams();
455
        $accept = $request->getAccept();
456
457
        try {
458
            if (isset($params['ActiveRecordType'])) {
459
                $ActiveRecordType = urldecode($params['ActiveRecordType']);
460
            } else {
461
                throw new IllegalArguementException('No ActiveRecord available to edit!');
462
            }
463
464
            if (class_exists($ActiveRecordType)) {
465
                $record = new $ActiveRecordType();
466
            } else {
467
                throw new IllegalArguementException('No ActiveRecord ['.$ActiveRecordType.'] available to edit!');
468
            }
469
470
            // check the hidden security fields before accepting the form POST data
471
            if (!$this->checkSecurityFields()) {
472
                throw new SecurityException('This page cannot accept post data from remote servers!');
473
            }
474
475
            $record->load($params['ActiveRecordID']);
476
            $record->populateFromArray($params);
477
            $record->save();
478
479
            self::$logger->action('Saved '.$ActiveRecordType.' instance with ID '.$record->getID());
480
481
            if (isset($params['statusMessage'])) {
482
                $this->setStatusMessage(View::displayUpdateMessage($params['statusMessage']));
483
            } else {
484
                $this->setStatusMessage(View::displayUpdateMessage('Saved'));
485
            }
486
487
            ActiveRecord::disconnect();
488
        } catch (SecurityException $e) {
489
            self::$logger->warn($e->getMessage());
490
            throw new ResourceNotAllowedException($e->getMessage());
491
        } catch (IllegalArguementException $e) {
492
            self::$logger->warn($e->getMessage());
493
            throw new ResourceNotFoundException('The record that you have requested cannot be found!');
494
        } catch (RecordNotFoundException $e) {
495
            self::$logger->warn($e->getMessage());
496
            throw new ResourceNotFoundException('The record that you have requested cannot be found!');
497
        } catch (ValidationException $e) {
498
            self::$logger->warn($e->getMessage());
499
            $this->setStatusMessage(View::displayErrorMessage($e->getMessage()));
500
        }
501
502
        if ($accept == 'application/json') {
503
            $view = View::getInstance($record, false, $accept);
0 ignored issues
show
Bug introduced by
The variable $record does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
504
            $body = $view->detailedView();
505
            $response = new Response(200);
506
            $response->setHeader('Content-Type', 'application/json');
507
            $response->setHeader('Location', $config->get('app.url').'/record/'.$params['ActiveRecordType'].'/'.$record->getID());
508
            $response->setBody($body);
509
        } else {
510
            $response = new Response(301);
511
512
            if ($this->getNextJob() != '') {
513
                $response->redirect($this->getNextJob());
514
            } else {
515
                if ($this->request->isSecureURI()) {
516
                    $response->redirect(FrontController::generateSecureURL('act=Alpha\\Controller\\ActiveRecordController&ActiveRecordType='.urldecode($params['ActiveRecordType']).'&ActiveRecordID='.$record->getID().'&view=edit'));
517
                } else {
518
                    $response->redirect($config->get('app.url').'/record/'.$params['ActiveRecordType'].'/'.$record->getID().'/edit');
519
                }
520
            }
521
        }
522
523
        self::$logger->debug('<<doPUT');
524
525
        return $response;
526
    }
527
528
    /**
529
     * Method to handle DELETE requests.
530
     *
531
     * @param \Alpha\Util\Http\Request $request
532
     *
533
     * @throws \Alpha\Exception\IllegalArguementException
534
     * @throws \Alpha\Exception\SecurityException
535
     * @throws \Alpha\Exception\ResourceNotAllowedException
536
     *
537
     * @return \Alpha\Util\Http\Response
538
     *
539
     * @since 2.0
540
     */
541
    public function doDELETE($request)
542
    {
543
        self::$logger->debug('>>doDELETE(request=['.var_export($request, true).'])');
544
545
        $config = ConfigProvider::getInstance();
546
547
        $params = $request->getParams();
548
        $accept = $request->getAccept();
549
550
        try {
551
            // check the hidden security fields before accepting the form data
552
            if (!$this->checkSecurityFields()) {
553
                throw new SecurityException('This page cannot accept data from remote servers!');
554
            }
555
556
            if (isset($params['ActiveRecordType'])) {
557
                $ActiveRecordType = urldecode($params['ActiveRecordType']);
558
            } else {
559
                throw new IllegalArguementException('No ActiveRecord available to edit!');
560
            }
561
562
            if (class_exists($ActiveRecordType)) {
563
                $record = new $ActiveRecordType();
564
            } else {
565
                throw new IllegalArguementException('No ActiveRecord ['.$ActiveRecordType.'] available to edit!');
566
            }
567
568
            // check the hidden security fields before accepting the form POST data
569
            if (!$this->checkSecurityFields()) {
570
                throw new SecurityException('This page cannot accept post data from remote servers!');
571
            }
572
573
            $record->load($params['ActiveRecordID']);
574
575
            ActiveRecord::begin();
576
            $record->delete();
577
            ActiveRecord::commit();
578
            ActiveRecord::disconnect();
579
580
            self::$logger->action('Deleted '.$ActiveRecordType.' instance with ID '.$params['ActiveRecordID']);
581
582
            if ($accept == 'application/json') {
583
                $response = new Response(200);
584
                $response->setHeader('Content-Type', 'application/json');
585
                $response->setBody(json_encode(array('message' => 'deleted')));
586
            } else {
587
                $response = new Response(301);
588
589
                if (isset($params['statusMessage'])) {
590
                    $this->setStatusMessage(View::displayUpdateMessage($params['statusMessage']));
591
                } else {
592
                    $this->setStatusMessage(View::displayUpdateMessage('Deleted'));
593
                }
594
595
                if ($this->getNextJob() != '') {
596
                    $response->redirect($this->getNextJob());
597
                } else {
598
                    if ($this->request->isSecureURI()) {
599
                        $response->redirect(FrontController::generateSecureURL('act=Alpha\\Controller\\ActiveRecordController&ActiveRecordType='.$ActiveRecordType.'&start=0&limit='.$config->get('app.list.page.amount')));
600
                    } else {
601
                        $response->redirect($config->get('app.url').'/records/'.$params['ActiveRecordType']);
602
                    }
603
                }
604
            }
605
606
            self::$logger->debug('<<doDELETE');
607
608
            return $response;
609
        } catch (SecurityException $e) {
610
            self::$logger->warn($e->getMessage());
611
            throw new ResourceNotAllowedException($e->getMessage());
612
        } catch (RecordNotFoundException $e) {
613
            self::$logger->warn($e->getMessage());
614
            throw new ResourceNotFoundException('The item that you have requested cannot be found!');
615
        } catch (AlphaException $e) {
616
            self::$logger->error($e->getMessage());
617
            ActiveRecord::rollback();
618
            throw new ResourceNotAllowedException($e->getMessage());
619
        }
620
    }
621
622
    /**
623
     * Sets up the pagination start point and limit.
624
     *
625
     * @since 2.0
626
     */
627
    public function after_displayPageHead_callback()
628
    {
629
        $body = parent::after_displayPageHead_callback();
630
631
        // set the start point for the list pagination
632
        if ($this->request->getParam('start') != null) {
633
            $this->start = $this->request->getParam('start');
0 ignored issues
show
Documentation Bug introduced by
The property $start was declared of type integer, but $this->request->getParam('start') is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
634
635
            $viewState = ViewState::getInstance();
636
            $viewState->set('selectedStart', $this->start);
637
638
            if ($this->request->getParam('limit') != null) {
639
                $this->limit = $this->request->getParam('limit');
0 ignored issues
show
Documentation Bug introduced by
The property $limit was declared of type integer, but $this->request->getParam('limit') is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
640
            } else {
641
                $config = ConfigProvider::getInstance();
642
                $this->limit = $config->get('app.list.page.amount');
0 ignored issues
show
Documentation Bug introduced by
The property $limit was declared of type integer, but $config->get('app.list.page.amount') is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
643
            }
644
645
            $accept = $this->request->getAccept();
646
647
            if ($accept == 'application/json') {
648
                $body .= '[';
649
            }
650
        }
651
652
        return $body;
653
    }
654
655
    /**
656
     * Method to display the page footer with pageination links.
657
     *
658
     * @return string
659
     *
660
     * @since 2.0
661
     */
662
    public function before_displayPageFoot_callback()
663
    {
664
        $body = '';
665
666
        if ($this->request->getParam('start') != null) {
667
            $accept = $this->request->getAccept();
668
669
            if ($accept == 'application/json') {
670
                $body .= ']';
671
            } else {
672
                $body .= $this->renderPageLinks();
673
                $body .= '<br>';
674
            }
675
        }
676
677
        return $body;
678
    }
679
680
    /**
681
     * Method for rendering the pagination links.
682
     *
683
     * @return string
684
     *
685
     * @since 2.0
686
     */
687
    protected function renderPageLinks()
688
    {
689
        $config = ConfigProvider::getInstance();
690
691
        $body = '';
692
693
        // the index of the last record displayed on this page
694
        $last = $this->start+$config->get('app.list.page.amount');
695
696
        // ensure that the last index never overruns the total record count
697
        if ($last > $this->recordCount) {
698
            $last = $this->recordCount;
699
        }
700
701
        // render a message for an empty list
702
        if ($this->recordCount > 0) {
703
            $body .= '<ul class="pagination">';
704
        } else {
705
            $body .= '<p align="center">The list is empty.&nbsp;&nbsp;</p>';
706
707
            return $body;
708
        }
709
710
        // render "Previous" link
711
        if ($this->start > 0) {
712
            // handle secure URLs
713
            if ($this->request->getParam('token', null) != null) {
714
                $body .= '<li><a href="'.FrontController::generateSecureURL('act=Alpha\Controller\ActiveRecordController&ActiveRecordType='.$this->request->getParam('ActiveRecordType').'&start='.($this->start-$this->limit).'&limit='.$this->limit).'">&lt;&lt;-Previous</a></li>';
715
            } else {
716
                $body .= '<li><a href="/records/'.urlencode($this->request->getParam('ActiveRecordType')).'/'.($this->start-$this->limit).'/'.$this->limit.'">&lt;&lt;-Previous</a></li>';
717
            }
718
        } elseif ($this->recordCount > $this->limit) {
719
            $body .= '<li class="disabled"><a href="#">&lt;&lt;-Previous</a></li>';
720
        }
721
722
        // render the page index links
723
        if ($this->recordCount > $this->limit) {
724
            $page = 1;
725
726
            for ($i = 0; $i < $this->recordCount; $i += $this->limit) {
727
                if ($i != $this->start) {
728
                    // handle secure URLs
729
                    if ($this->request->getParam('token', null) != null) {
730
                        $body .= '<li><a href="'.FrontController::generateSecureURL('act=Alpha\Controller\ActiveRecordController&ActiveRecordType='.$this->request->getParam('ActiveRecordType').'&start='.$i.'&limit='.$this->limit).'">'.$page.'</a></li>';
731
                    } else {
732
                        $body .= '<li><a href="/records/'.urlencode($this->request->getParam('ActiveRecordType')).'/'.$i.'/'.$this->limit.'">'.$page.'</a></li>';
733
                    }
734
                } elseif ($this->recordCount > $this->limit) { // render an anchor for the current page
735
                    $body .= '<li class="active"><a href="#">'.$page.'</a></li>';
736
                }
737
738
                ++$page;
739
            }
740
        }
741
742
        // render "Next" link
743
        if ($this->recordCount > $last) {
744
            // handle secure URLs
745
            if ($this->request->getParam('token', null) != null) {
746
                $body .= '<li><a href="'.FrontController::generateSecureURL('act=Alpha\Controller\ActiveRecordController&ActiveRecordType='.$this->request->getParam('ActiveRecordType').'&start='.($this->start+$this->limit).'&limit='.$this->limit).'">Next-&gt;&gt;</a></li>';
747
            } else {
748
                $body .= '<li><a href="/records/'.urlencode($this->request->getParam('ActiveRecordType')).'/'.($this->start+$this->limit.'/'.$this->limit).
749
                    '">Next-&gt;&gt;</a></li>';
750
            }
751
        } elseif ($this->recordCount > $this->limit) {
752
            $body .= '<li class="disabled"><a href="#">Next-&gt;&gt;</a></li>';
753
        }
754
755
        $body .= '</ul>';
756
757
        return $body;
758
    }
759
}
760