Completed
Push — master ( 88adbd...3ca75f )
by Adeola
05:41
created

EmojiController::getUsername()   A

Complexity

Conditions 3
Paths 7

Size

Total Lines 18
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 18
rs 9.4285
cc 3
eloc 12
nc 7
nop 2
1
<?php
2
3
/**
4
 * @author: Raimi Ademola <[email protected]>
5
 * @copyright: 2016 Andela
6
 */
7
namespace Demo;
8
9
10
use Exception;
11
use Carbon\Carbon;
12
use Firebase\JWT\JWT;
13
use Illuminate\Database\Capsule\Manager as Capsule;
14
use Psr\Http\Message\ResponseInterface as Response;
15
16
class EmojiController
17
{
18
    public $authController;
19
20
    /**
21
     * This is a constructor; a default method  that will be called automatically during class instantiation.
22
     */
23
    public function __construct()
24
    {
25
        $this->authController = new AuthController();
26
    }
27
28
    /**
29
     * Get all emojis.
30
     *
31
     * @param Slim\Http\Request  $request
32
     * @param Slim\Http\Response $response
33
     * @param array              $args
0 ignored issues
show
Bug introduced by
There is no parameter named $args. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
34
     *
35
     * @return Slim\Http\Response
36
     */
37
    public function getAllEmojis($request, $response)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
38
    {
39
        $emojis = Emoji::all();
40
        
41
        if (!count($emojis) > 0) {
42
            return $response->withJson(['message' => 'Oops, No Emoji to display'], 404);
43
        }
44
45
        $emojiArray = [];
46
47
        foreach($emojis as $emoji) {
48
            $emojiProperty = [
49
                'id'         => $emoji->id,
50
                'name'       => $emoji->name, 
51
                'chars'      => $emoji->chars, 
52
                'category'   => $emoji->category,
53
                'created_by' => $emoji->created_by
54
            ];
55
56
            $keywords = [];
57
58
            foreach($emoji->keywords as $keyword) {
59
                array_push($keywords, $keyword->name);
60
            }
61
            
62
            $emojiProperty['keywords'] = $keywords;
63
            $emojiArray[] = $emojiProperty;
64
        }
65
66
        return $response->withJson($emojiArray);
67
    }
68
69
    /**
70
     * Get a single emoji.
71
     *
72
     * @param Slim\Http\Request  $request
73
     * @param Slim\Http\Response $response
74
     * @param array              $args
75
     *
76
     * @return Slim\Http\Response
77
     */
78
    public function getSingleEmoji($request, $response, $args)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
79
    {
80
        if (!is_numeric($args['id'])) {
81
            return $response->withJson(['message' => 'The argument supplied must be an integer.'], 401);
82
        }
83
84
        $emoji = Emoji::find($args['id']);
85
86
        if (count($emoji) < 1) {
87
            return $response->withJson(['message' => 'The requested Emoji is not found.'], 404);
88
        }
89
90
        $keywords = [];
91
92
        foreach ($emoji->keywords as $keyword) {
93
            array_push($keywords, $keyword->name);
94
        }
95
96
        $emoji = ['id'=> $emoji->id, 'name' => $emoji->name, 'chars' => $emoji->chars, 'category' => $emoji->category, 'created_by' => $emoji->created_by, 'keywords' => $keywords];
97
98
        return $response->withJson($emoji);
99
    }
100
101
    /**
102
     * This method creates emoji and keywords associated with it.
103
     *
104
     * @param $request
105
     * @param $response
106
     * @param $requestParams
107
     *
108
     * @return json response
109
     */
110
    public function CreateEmoji($request, $response, $requestParams)
0 ignored issues
show
Unused Code introduced by
The parameter $requestParams is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
111
    {
112
        //dd('I love this');
113
        $requestParams    = $request->getParsedBody();
114
        $validateUserData = $this->authController->validateUserData(['name', 'chars', 'category', 'keywords'], $requestParams);
115
116
        if (is_array($validateUserData)) {
117
            return $response->withJson($validateUserData, 400);
118
        }
119
        
120
        $validateEmptyInput = $this->checkEmptyInput($requestParams['name'], $requestParams['chars'], $requestParams['category'], $requestParams['keywords']);
121
122
        if (is_array($validateEmptyInput)) {
123
            return $response->withJson($validateEmptyInput, 401);
124
        }
125
126
        $validateEmojiDuplicate = $this->checkDuplicateEmoji($requestParams['name'], $requestParams['chars']);
127
128
        if (is_array($validateEmojiDuplicate)) {
129
            return $response->withJson($validateEmojiDuplicate, 400);
130
        }
131
    
132
        $emoji = Emoji::create([
133
            'name'       => strtolower($requestParams['name']),
134
            'chars'      => $requestParams['chars'],
135
            'category'   => $requestParams['category'],
136
            'created_at' => Carbon::now()->toDateTimeString(),
137
            'updated_at' => Carbon::now()->toDateTimeString(),
138
            'created_by' => $this->getUsername($request, $response),
139
        ]);
140
141
        $this->createEmojiKeywords($emoji->id, $requestParams['keywords']);
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<Demo\Emoji>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
142
    
143
        return $response->withJson(['message' => 'Emoji has been created successfully'], 201);
144
    }
145
146
    /**
147
     * This method updates an emoji by using Patch.
148
     *
149
     * @param $request
150
     * @param $response
151
     * @param $args
152
     *
153
     * @return json $response
154
     */
155
    public function updateEmojiByPatch($request, $response, $args)
156
    {
157
        $updateParams     = $request->getParsedBody();
158
        $validateUserData = $this->authController->validateUserData(['name'], $updateParams);
159
       
160
        if (is_array($validateUserData)) {
161
            return $response->withJson($validateUserData, 400);
162
        }
163
164
        $validateArgs = $this->validateArgs($request, $response, $args);
165
166
        if (is_array($validateArgs)) {
167
            return $response->withJson($validateArgs, 401);
168
        }
169
170
        Emoji::where('id', '=', $args['id'])
171
            ->update(['name' => strtolower($updateParams['name']), 'updated_at' => Carbon::now()->toDateTimeString()]);
172
173
        return $response->withJson(['message' => 'Emoji has been updated successfully'], 200);
174
    }
175
176
    /**
177
     * This method updates an emoji by using put.
178
     *
179
     * @param $request
180
     * @param $response
181
     * @param $args
182
     *
183
     * @return json $response
184
     */
185
    public function updateEmojiByPut($request, $response, $args)
186
    {
187
        $updateParams = $request->getParsedBody();
188
        $validateUserData = $this->authController->validateUserData(['name', 'chars', 'category'], $updateParams);
189
       
190
        if (is_array($validateUserData)) {
191
            return $response->withJson($validateUserData, 400);
192
        }
193
194
        $validateArgs = $this->validateArgs($request, $response, $args);
195
196
        if (is_array($validateArgs)) {
197
            return $response->withJson($validateArgs, 401);
198
        }
199
200
        Emoji::where('id', '=', $args['id'])
201
            ->update(['name' => strtolower($updateParams['name']), 'chars' => $updateParams['chars'], 'category' => $updateParams['category'], 'updated_at' => Carbon::now()->toDateTimeString()]);
202
203
        return $response->withJson(['message' => 'Emoji has been updated successfully'], 200);
204
    }
205
206
    /**
207
     * This method deletes an emoji.
208
     *
209
     * @param Slim\Http\Request  $request
210
     * @param Slim\Http\Response $response
211
     * @param array              $args
212
     *
213
     * @return json response
214
     */
215
    public function deleteEmoji($request, $response, $args)
216
    {
217
        $validateArgs = $this->validateArgs($request, $response, $args);
218
        if (is_array($validateArgs)) {
219
            return $response->withJson($validateArgs, 401);
220
        }
221
222
        Emoji::where('id', '=', $args['id'])->delete();
223
224
        return $response->withJson(['message' => 'Emoji successfully deleted.'], 200);
225
    }
226
227
    /**
228
     * This method authenticate and returns user id.
229
     *
230
     * @param $response
231
     * @param $request
232
     *
233
     * @return user id
234
     */
235
    private function getUsername($request, $response)
236
    {
237
        $jwtoken = $request->getHeader('HTTP_AUTHORIZATION');
238
239
        try {
240
            if (isset($jwtoken)) {
241
                $secretKey    = getenv('APP_SECRET');
242
                $jwt          = $jwtoken[0];
243
                $decodedToken = JWT::decode($jwt, $secretKey, ['HS512']);
244
                $tokenInfo    = (array) $decodedToken;
245
                $userInfo     = (array) $tokenInfo['data'];
246
                //dd($userInfo['username']);
0 ignored issues
show
Unused Code Comprehensibility introduced by
88% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
247
                return $userInfo['username'];
248
            }
249
        } catch (Exception $e) {
250
            return $response->withJson(['status: fail, msg: Unauthorized']);
251
        }
252
    }
253
254
    /**
255
     * This method solves for rightful owner of a record.
256
     *
257
     * @param $response
258
     * @param $request
259
     * @param $args
260
     *
261
     * @return user id
262
     */
263
    private function getTheOwner($request, $response, $args)
264
    {
265
        return Capsule::table('emojis')
266
            ->where('id', '=', $args['id'])
267
            ->where('created_by', '=', $this->getUsername($request, $response));
268
    }
269
270
    /**
271
     * This method creates emoji keywords.
272
     *
273
     * @param $emoji_id
274
     * @param $keywords
275
     *
276
     * @return keyword id
277
     */
278
    public function createEmojiKeywords($emoji_id, $keywords)
279
    {
280
        if (isset($keywords)) {
281
            $splittedKeywords = explode(',', $keywords);
282
            $created_at       = Carbon::now()->toDateTimeString();
283
            $updated_at       = Carbon::now()->toDateTimeString();
284
285
            foreach ($splittedKeywords as $keyword) {
286
                $emojiKeyword = Keyword::create([
287
                    'emoji_id'     => $emoji_id,
288
                    'name'         => $keyword,
289
                    'created_at'   => $created_at,
290
                    'updated_at'   => $updated_at,
291
                ]);
292
            }
293
294
            return $emojiKeyword->name;
0 ignored issues
show
Bug introduced by
The variable $emojiKeyword 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...
Documentation introduced by
The property name does not exist on object<Demo\Keyword>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
295
        }
296
297
        return true;
298
    }
299
300
    /**
301
     * This method checks for empty input from user.
302
     *
303
     * @param $inputName
304
     * @param $inputChars
305
     * @param $inputCategory
306
     * @param $inputKeywords
307
     *
308
     * @return bool
309
     */
310
    public function checkEmptyInput($inputName, $inputChars, $inputCategory, $inputKeywords)
311
    {
312
        if (empty($inputName) || empty($inputChars) || empty($inputCategory) || empty($inputKeywords)) {
313
            return ['message' => 'All fields must be provided.'];
314
        }
315
316
        return true;
317
    }
318
319
    /**
320
     * This method checks for duplicate emoji.
321
     *
322
     * @param $inputName
323
     * @param $inputChars
324
     *
325
     * @return bool
326
     */
327
    public function checkDuplicateEmoji($inputName, $inputChars)
328
    {
329
        $nameCheck = Capsule::table('emojis')->where('name', '=', strtolower($inputName))->get();
330
        $charsCheck = Capsule::table('emojis')->where('chars', '=', $inputChars)->get();
331
       
332
        if ($nameCheck || $charsCheck) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $nameCheck of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
Bug Best Practice introduced by
The expression $charsCheck of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
333
334
            return ['message' => 'The emoji already exist in the database.'];
335
        }
336
337
        return true;
338
    }
339
340
    /**
341
     * This method checks for empty input from user.
342
     *
343
     * @param $request
344
     * @param $response
345
     * @param $args
346
     *
347
     * @return bool
348
     */
349
    public function validateArgs($request, $response, $args)
350
    {
351
        if (!is_numeric($args['id'])) {
352
            return ['message' => 'The argument supplied must be an integer.'];
353
        }
354
355
        $emoji = Emoji::find($args['id']);
356
        
357
        if (count($emoji) < 1) {
358
            return ['message' => 'Action cannot be performed because the id supplied is invalid'];
359
        }
360
361
        if (is_null($this->getTheOwner($request, $response, $args)->first())) {
0 ignored issues
show
Documentation Bug introduced by
The method first does not exist on object<Demo\User>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
362
            return ['message' => 'Action cannot be performed because you are not the creator'];
363
        }
364
365
        return true;
366
    }
367
}
368