Completed
Push — v2 ( 001a0f...329c52 )
by Faouzi
01:44
created

JSONServiceProvider   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 84
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 14
Bugs 3 Features 0
Metric Value
wmc 14
c 14
b 3
f 0
lcom 1
cbo 3
dl 0
loc 84
rs 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A register() 0 7 1
A jsonInputHandler() 0 15 3
A errorHandler() 0 17 4
B sanitizeExceptionCode() 0 16 6
1
<?php
2
3
namespace ETNA\Silex\Provider\JSON;
4
5
use Silex\Application;
6
use Pimple\ServiceProviderInterface;
7
use Pimple\Container;
8
use Symfony\Component\HttpFoundation\Request;
9
10
/**
11
 *
12
 */
13
class JSONServiceProvider implements ServiceProviderInterface
14
{
15
    private $app;
16
17
    public function register(Container $app)
18
    {
19
        $this->app = $app;
20
21
        $app->before([$this, "jsonInputHandler"]);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Pimple\Container as the method before() does only exist in the following sub-classes of Pimple\Container: Silex\Application, Silex\Tests\Application\FormApplication, Silex\Tests\Application\MonologApplication, Silex\Tests\Application\SecurityApplication, Silex\Tests\Application\SwiftmailerApplication, Silex\Tests\Application\TranslationApplication, Silex\Tests\Application\TwigApplication, Silex\Tests\Application\UrlGeneratorApplication. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
22
        $app->error([$this, "errorHandler"]);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Pimple\Container as the method error() does only exist in the following sub-classes of Pimple\Container: Silex\Application, Silex\Tests\Application\FormApplication, Silex\Tests\Application\MonologApplication, Silex\Tests\Application\SecurityApplication, Silex\Tests\Application\SwiftmailerApplication, Silex\Tests\Application\TranslationApplication, Silex\Tests\Application\TwigApplication, Silex\Tests\Application\UrlGeneratorApplication. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
23
    }
24
25
    /**
26
     * Gère le JSON dans le body d'une requête
27
     *
28
     * @param Request $request
29
     */
30
    public function jsonInputHandler(Request $request)
31
    {
32
        // on ne s'interese qu'aux requêtes de type "application/json"
33
        if (0 !== strpos($request->headers->get('Content-Type'), 'application/json')) {
34
            return;
35
        }
36
37
        $params = json_decode($request->getContent(), true);
38
        if (false === is_array($params)) {
39
            $this->app->abort(400, "Invalid JSON data");
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Pimple\Container as the method abort() does only exist in the following sub-classes of Pimple\Container: Silex\Application, Silex\Tests\Application\FormApplication, Silex\Tests\Application\MonologApplication, Silex\Tests\Application\SecurityApplication, Silex\Tests\Application\SwiftmailerApplication, Silex\Tests\Application\TranslationApplication, Silex\Tests\Application\TwigApplication, Silex\Tests\Application\UrlGeneratorApplication. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
40
        }
41
42
        // OUF, on peut enfin faire ce qu'on a à faire...
43
        $request->request->replace($params);
44
    }
45
46
    /**
47
     * Gère les erreurs et retourne un truc standardisé
48
     *
49
     * Le code d'erreur HTTP est gardé, mais pas forcément le message, et sera encapsuler dans une réponse JSON
50
     * Le message de l'exception n'est retourné que si ce n'est pas une erreur 500
51
     * ou que le `debug` est activé
52
     *
53
     * @param \Exception $exception
54
     * @param integer $code HTTP status code (100 <= $code <= 50x)
55
     * @return \Symfony\Component\HttpFoundation\JsonResponse
56
     */
57
    public function errorHandler(\Exception $exception, $code)
58
    {
59
        $code = $this->sanitizeExceptionCode($code, $exception);
60
61
        switch (true) {
62
            case 100 <= $code && $code < 500:
63
            case $this->app["debug"] === true:
64
                $message = $exception->getMessage();
65
                break;
66
67
            default:
68
                $message = null;
69
                break;
70
        }
71
72
        return $this->app->json($message, $code);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Pimple\Container as the method json() does only exist in the following sub-classes of Pimple\Container: Silex\Application, Silex\Tests\Application\FormApplication, Silex\Tests\Application\MonologApplication, Silex\Tests\Application\SecurityApplication, Silex\Tests\Application\SwiftmailerApplication, Silex\Tests\Application\TranslationApplication, Silex\Tests\Application\TwigApplication, Silex\Tests\Application\UrlGeneratorApplication. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
73
    }
74
75
    /**
76
     * @param integer $code
77
     * @param null|\Exception $exception
78
     * @return integer
79
     */
80
    private function sanitizeExceptionCode($code, \Exception $exception = null)
81
    {
82
        switch (true) {
83
            case $exception instanceof \InvalidArgumentException:
84
                return 400;
85
86
            case null !== $exception && !$exception instanceof \Symfony\Component\HttpKernel\Exception\HttpException:
87
                return $this->sanitizeExceptionCode($exception->getCode());
88
89
            case 100 <= $code && $code < 600:
90
                return $code;
91
92
            default:
93
                return 500;
94
        }
95
    }
96
}
97