SaveAction::run()   C
last analyzed

Complexity

Conditions 12
Paths 268

Size

Total Lines 99
Code Lines 62

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 62
nc 268
nop 2
dl 0
loc 99
rs 5.0557
c 0
b 0
f 0

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 Charcoal\Admin\Action\Object;
4
5
use Exception;
6
use PDOException;
7
8
// From PSR-7
9
use Psr\Http\Message\RequestInterface;
10
use Psr\Http\Message\ResponseInterface;
11
12
// From 'charcoal-core'
13
use Charcoal\Model\ModelValidator;
14
15
// From 'charcoal-object'
16
use Charcoal\Object\ContentInterface;
17
18
/**
19
 * Action: Create an object and insert into storage.
20
 *
21
 * ## Required Parameters
22
 *
23
 * - `obj_type` (_string_) — The object type, as an identifier for a {@see \Charcoal\Model\ModelInterface}.
24
 *
25
 * ## Response
26
 *
27
 * - `success` (_boolean_) — TRUE if the object was properly saved, FALSE in case of any error.
28
 * - `obj_id` (_mixed_) — The created object ID, if any.
29
 * - `obj` (_array_) — The created object data.
30
 *
31
 * ## HTTP Status Codes
32
 *
33
 * - `200` — Successful; Object has been created
34
 * - `400` — Client error; Invalid request data
35
 * - `500` — Server error; Object could not be created
36
 */
37
class SaveAction extends AbstractSaveAction
38
{
39
    /**
40
     * Data for the target model.
41
     *
42
     * @var array
43
     */
44
    protected $saveData = [];
45
46
    /**
47
     * Sets the action data from a PSR Request object.
48
     *
49
     * Extract relevant model data from $data, excluding _object type_.
50
     * This {@see self::$saveData subset} is merged onto the target model.
51
     *
52
     * @param  RequestInterface $request A PSR-7 compatible Request instance.
53
     * @return self
54
     */
55
    protected function setDataFromRequest(RequestInterface $request)
56
    {
57
        parent::setDataFromRequest($request);
58
59
        $data = $request->getParams();
0 ignored issues
show
Bug introduced by
The method getParams() does not exist on Psr\Http\Message\RequestInterface. It seems like you code against a sub-type of Psr\Http\Message\RequestInterface such as Slim\Http\Request. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

59
        /** @scrutinizer ignore-call */ 
60
        $data = $request->getParams();
Loading history...
60
        unset($data['obj_type'], $data['objType']);
61
62
        $this->setSaveData($data);
63
64
        return $this;
65
    }
66
67
    /**
68
     * Retrieve the list of parameters to extract from the HTTP request.
69
     *
70
     * @return string[]
71
     */
72
    protected function validDataFromRequest()
73
    {
74
        return array_merge([
75
            'obj_type'
76
        ], parent::validDataFromRequest());
77
    }
78
79
    /**
80
     * Set the dataset used to create the target model.
81
     *
82
     * @param  array $saveData The save data.
83
     * @return SaveAction Chainable
84
     */
85
    public function setSaveData(array $saveData)
86
    {
87
        $this->saveData = $saveData;
88
89
        return $this;
90
    }
91
92
    /**
93
     * Retrieve the dataset used to create the target model.
94
     *
95
     * @return array
96
     */
97
    public function saveData()
98
    {
99
        return $this->saveData;
100
    }
101
102
    /**
103
     * @param  RequestInterface  $request  A PSR-7 compatible Request instance.
104
     * @param  ResponseInterface $response A PSR-7 compatible Response instance.
105
     * @return ResponseInterface
106
     */
107
    public function run(RequestInterface $request, ResponseInterface $response)
108
    {
109
        try {
110
            $failMessage = $this->translator()->translation('Failed to create object');
111
            $errorThrown = strtr($this->translator()->translation('{{ errorMessage }}: {{ errorThrown }}'), [
0 ignored issues
show
Bug introduced by
It seems like $this->translator()->tra...}}: {{ errorThrown }}') can also be of type null; however, parameter $str of strtr() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

111
            $errorThrown = strtr(/** @scrutinizer ignore-type */ $this->translator()->translation('{{ errorMessage }}: {{ errorThrown }}'), [
Loading history...
112
                '{{ errorMessage }}' => $failMessage
113
            ]);
114
            $reqMessage  = $this->translator()->translation(
115
                '{{ parameter }} required, must be a {{ expectedType }}, received {{ actualType }}'
116
            );
117
118
            $objType = $request->getParam('obj_type');
0 ignored issues
show
Bug introduced by
The method getParam() does not exist on Psr\Http\Message\RequestInterface. It seems like you code against a sub-type of Psr\Http\Message\RequestInterface such as Slim\Http\Request. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

118
            /** @scrutinizer ignore-call */ 
119
            $objType = $request->getParam('obj_type');
Loading history...
119
            if (!$objType) {
120
                $actualType = is_object($objType) ? get_class($objType) : gettype($objType);
121
                $this->addFeedback('error', strtr($reqMessage, [
122
                    '{{ parameter }}'    => '"obj_type"',
123
                    '{{ expectedType }}' => 'string',
124
                    '{{ actualType }}'   => $actualType,
125
                ]));
126
                $this->setSuccess(false);
127
128
                return $response->withStatus(400);
129
            }
130
131
            // Create or load object (From `ObjectContainerTrait`)
132
            $obj = $this->obj();
133
            $obj->setFlatData($this->saveData());
134
135
            $valid = $obj->validate();
0 ignored issues
show
Bug introduced by
The method validate() does not exist on Charcoal\Model\ModelInterface. It seems like you code against a sub-type of said class. However, the method does not exist in Charcoal\Queue\QueueItemInterface or Charcoal\Object\ContentInterface or Charcoal\Object\UserDataInterface or Charcoal\User\UserInterface. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

135
            /** @scrutinizer ignore-call */ 
136
            $valid = $obj->validate();
Loading history...
136
            if (!$valid) {
137
                if (!$this->hasFeedbacks()) {
138
                    $this->addFeedback('error', strtr($errorThrown, [
139
                        '{{ errorThrown }}' => $this->translator()->translation('Invalid Data')
140
                    ]));
141
                }
142
143
                $this->addFeedbackFromValidation($obj);
144
                $this->setSuccess(false);
145
146
                return $response->withStatus(400);
147
            }
148
149
            if ($obj instanceof ContentInterface) {
150
                $authorIdent = $this->authorIdent();
151
                if (!$obj->lastModifiedBy()) {
0 ignored issues
show
Bug introduced by
The method lastModifiedBy() does not exist on Charcoal\Object\ContentInterface. It seems like you code against a sub-type of said class. However, the method does not exist in Charcoal\User\UserInterface. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

151
                if (!$obj->/** @scrutinizer ignore-call */ lastModifiedBy()) {
Loading history...
152
                    $obj->setLastModifiedBy($authorIdent);
0 ignored issues
show
Bug introduced by
The method setLastModifiedBy() does not exist on Charcoal\Object\ContentInterface. It seems like you code against a sub-type of said class. However, the method does not exist in Charcoal\User\UserInterface. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

152
                    $obj->/** @scrutinizer ignore-call */ 
153
                          setLastModifiedBy($authorIdent);
Loading history...
153
                }
154
155
                if (!$obj->createdBy()) {
0 ignored issues
show
Bug introduced by
The method createdBy() does not exist on Charcoal\Object\ContentInterface. It seems like you code against a sub-type of said class. However, the method does not exist in Charcoal\User\UserInterface. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

155
                if (!$obj->/** @scrutinizer ignore-call */ createdBy()) {
Loading history...
156
                    $obj->setCreatedBy($authorIdent);
0 ignored issues
show
Bug introduced by
The method setCreatedBy() does not exist on Charcoal\Object\ContentInterface. It seems like you code against a sub-type of said class. However, the method does not exist in Charcoal\User\UserInterface. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

156
                    $obj->/** @scrutinizer ignore-call */ 
157
                          setCreatedBy($authorIdent);
Loading history...
157
                }
158
            }
159
160
            $result = $obj->save();
161
162
            if ($result) {
163
                $this->setObj($obj);
164
165
                $this->addFeedback('success', $this->translator()->translate('Object has been successfully created.'));
166
                $this->addFeedback('success', strtr($this->translator()->translate('Created Object: {{ objId }}'), [
167
                    '{{ objId }}' => $obj->id()
168
                ]));
169
                $this->addFeedbackFromValidation($obj, [ ModelValidator::NOTICE, ModelValidator::WARNING ]);
170
                $this->setSuccess(true);
171
172
                return $response;
173
            } else {
174
                $this->setObj(null);
175
176
                $this->addFeedback('error', $failMessage);
177
                $this->addFeedbackFromValidation($obj);
178
                $this->setSuccess(false);
179
180
                return $response->withStatus(500);
181
            }
182
        } catch (PDOException $e) {
183
            $this->setObj(null);
184
185
            if (isset($e->errorInfo[2])) {
186
                $message = $e->errorInfo[2];
187
            } else {
188
                $message = $e->getMessage();
189
            }
190
191
            $this->addFeedback('error', strtr($errorThrown, [
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $errorThrown does not seem to be defined for all execution paths leading up to this point.
Loading history...
192
                '{{ errorThrown }}' => $message
193
            ]));
194
            $this->setSuccess(false);
195
196
            return $response->withStatus(500);
197
        } catch (Exception $e) {
198
            $this->setObj(null);
199
200
            $this->addFeedback('error', strtr($errorThrown, [
201
                '{{ errorThrown }}' => $e->getMessage()
202
            ]));
203
            $this->setSuccess(false);
204
205
            return $response->withStatus(500);
206
        }
207
    }
208
}
209