RichController::action()   D
last analyzed

Complexity

Conditions 9
Paths 18

Size

Total Lines 41
Code Lines 22

Duplication

Lines 7
Ratio 17.07 %

Importance

Changes 0
Metric Value
dl 7
loc 41
c 0
b 0
f 0
rs 4.909
cc 9
eloc 22
nc 18
nop 1
1
<?php /** MicroRichController */
2
3
namespace Micro\Mvc\Controllers;
4
5
use Micro\Base\Exception;
6
use Micro\Web\RequestInjector;
7
use Psr\Http\Message\ServerRequestInterface;
8
9
10
/**
11
 * Class RichController
12
 *
13
 * @author Oleg Lunegov <[email protected]>
14
 * @link https://github.com/linpax/microphp-framework
15
 * @copyright Copyright (c) 2013 Oleg Lunegov
16
 * @license https://github.com/linpax/microphp-framework/blob/master/LICENSE
17
 * @package Micro
18
 * @subpackage Mvc\Controllers
19
 * @version 1.0
20
 * @since 1.0
21
 * @abstract
22
 */
23
abstract class RichController extends Controller
24
{
25
    /** @var string $format Format for response */
26
    public $format = 'application/json';
27
28
    /** @var string $methodType */
29
    protected $methodType = 'get';
30
31
32
    /**
33
     * Construct RICH controller
34
     *
35
     * @access public
36
     *
37
     * @param string $modules
38
     *
39
     * @result void
40
     * @throws Exception
41
     */
42
    public function __construct($modules = '')
43
    {
44
        parent::__construct($modules);
45
46
        /** @var ServerRequestInterface $request */
47
        $request = (new RequestInjector)->build();
48
49
        $this->methodType = $request->getMethod() ?: 'GET';
50
    }
51
52
    /**
53
     * @inheritdoc
54
     * @throws \InvalidArgumentException
55
     */
56
    public function action($name = 'index')
57
    {
58
        $actionClass = false;
59
60
        // check action exists
61
        if (!method_exists($this, 'action'.ucfirst($name)) && !$actionClass = $this->getActionClassByName($name)) {
62
            return $this->response->withStatus(500, 'Action `'.$name.'` not found into '.get_class($this));
63
        }
64
65
        $types = $this->actionsTypes();
66
67
        if (!empty($types[$name]) && $this->methodType !== $types[$name]) {
68
            return $this->response->withStatus(500,
69
                'Action `'.$name.'` not run with method `'.$this->methodType.'` into '.get_class($this)
70
            );
71
        }
72
73
        $filters = method_exists($this, 'filters') ? $this->filters() : [];
0 ignored issues
show
Bug introduced by
The method filters() does not exist on Micro\Mvc\Controllers\RichController. Did you maybe mean applyFilters()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
74
75
        $this->applyFilters($name, true, $filters, null);
76
77 View Code Duplication
        if ($actionClass) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
78
            /** @var \Micro\Mvc\Action $cl */
79
            $cl = new $actionClass();
80
            $view = $cl->run();
81
        } else {
82
            $view = $this->{'action'.ucfirst($name)}();
83
        }
84
85
        $this->response = $this->response->withHeader('Content-Type', $this->format);
86
87
        $contentType = $this->response->getHeader('Content-Type') ?: 'text/html';
88
        if ($contentType !== $this->format) {
89
            $this->response = $this->response->withHeader('Content-Type', $this->format);
90
        }
91
92
        $stream = $this->response->getBody();
93
        $stream->write($this->switchContentType($this->applyFilters($name, false, $filters, $view)));
0 ignored issues
show
Bug introduced by
It seems like $this->applyFilters($nam...false, $filters, $view) targeting Micro\Mvc\Controllers\Controller::applyFilters() can also be of type object<Psr\Http\Message\ResponseInterface>; however, Micro\Mvc\Controllers\Ri...er::switchContentType() does only seem to accept null|string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
94
95
        return $this->response->withBody($stream);
96
    }
97
98
    /**
99
     * Define types for actions
100
     *
101
     * <code>
102
     *  // DELETE, GET, HEAD, OPTIONS, POST, PUT
103
     * public function actionsTypes() {
104
     *  return [
105
     *     'create' => 'POST',
106
     *     'read'   => 'GET',
107
     *     'update' => 'UPDATE'
108
     *     'delete' => 'DELETE'
109
     *  ];
110
     * }
111
     * </code>
112
     *
113
     * @access public
114
     *
115
     * @return array
116
     * @abstract
117
     */
118
    abstract public function actionsTypes();
119
120
    /**
121
     * Switch content type
122
     *
123
     * @access protected
124
     *
125
     * @param null|string $data Any content
126
     *
127
     * @return string
128
     */
129
    protected function switchContentType($data)
130
    {
131
        switch ($this->format) {
132
            case 'application/json':
133
                $data = json_encode(is_object($data) ? (array)$data : $data);
134
                break;
135
136
            case 'application/xml':
137
                $data = is_object($data) ? (string)$data : $data;
138
                break;
139
140
            default:
141
                $data = (string)$data;
142
        }
143
144
        return $data;
145
    }
146
}
147