Completed
Push — 8.x-1.x ( dece3c...0d95ba )
by
unknown
28:39
created

ParamConverterManager   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 122
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 18
c 0
b 0
f 0
lcom 1
cbo 2
dl 0
loc 122
ccs 42
cts 42
cp 1
rs 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
D applyConverter() 0 41 9
A add() 0 14 4
A all() 0 11 2
A apply() 0 10 3
1
<?php
2
3
namespace Drupal\controller_annotations\Request\ParamConverter;
4
5
use Drupal\controller_annotations\Configuration\ConfigurationInterface;
6
use Symfony\Component\HttpFoundation\Request;
7
8
/**
9
 * Managers converters.
10
 *
11
 * @author Fabien Potencier <[email protected]>
12
 * @author Henrik Bjornskov <[email protected]>
13
 */
14
class ParamConverterManager
15
{
16
    /**
17
     * @var array
18
     */
19
    protected $converters = [];
20
21
    /**
22
     * @var array
23
     */
24
    protected $namedConverters = [];
25
26
    /**
27
     * Applies all converters to the passed configurations and stops when a
28
     * converter is applied it will move on to the next configuration and so on.
29
     *
30
     * @param Request      $request
31
     * @param array|object $configurations
32
     */
33 12
    public function apply(Request $request, $configurations)
34
    {
35 12
        if (is_object($configurations)) {
36 1
            $configurations = [$configurations];
37
        }
38
39 12
        foreach ($configurations as $configuration) {
40 6
            $this->applyConverter($request, $configuration);
41
        }
42 10
    }
43
44
    /**
45
     * Apply converter on request based on the given configuration.
46
     *
47
     * @param Request                $request
48
     * @param ConfigurationInterface $configuration
49
     */
50 6
    protected function applyConverter(Request $request, ConfigurationInterface $configuration)
51
    {
52 6
        $value = $request->attributes->get($configuration->getName());
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Drupal\controller_annota...\ConfigurationInterface as the method getName() does only exist in the following implementations of said interface: Drupal\controller_annota...guration\ParamConverter.

Let’s take a look at an example:

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

class MyUser implements 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 implementation 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 interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
53 6
        $className = $configuration->getClass();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Drupal\controller_annota...\ConfigurationInterface as the method getClass() does only exist in the following implementations of said interface: Drupal\controller_annota...guration\ParamConverter.

Let’s take a look at an example:

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

class MyUser implements 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 implementation 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 interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
54
55
        // If the value is already an instance of the class we are trying to convert it into
56
        // we should continue as no conversion is required
57 6
        if (is_object($value) && $value instanceof $className) {
58 1
            return;
59
        }
60
61 5
        if ($converterName = $configuration->getConverter()) {
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Drupal\controller_annota...\ConfigurationInterface as the method getConverter() does only exist in the following implementations of said interface: Drupal\controller_annota...guration\ParamConverter.

Let’s take a look at an example:

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

class MyUser implements 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 implementation 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 interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
62 3
            if (!isset($this->namedConverters[$converterName])) {
63 1
                throw new \RuntimeException(sprintf(
64 1
                    "No converter named '%s' found for conversion of parameter '%s'.",
65 1
                    $converterName, $configuration->getName()
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Drupal\controller_annota...\ConfigurationInterface as the method getName() does only exist in the following implementations of said interface: Drupal\controller_annota...guration\ParamConverter.

Let’s take a look at an example:

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

class MyUser implements 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 implementation 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 interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
66
                ));
67
            }
68
69 2
            $converter = $this->namedConverters[$converterName];
70
71 2
            if (!$converter->supports($configuration)) {
72 1
                throw new \RuntimeException(sprintf(
73 1
                    "Converter '%s' does not support conversion of parameter '%s'.",
74 1
                    $converterName, $configuration->getName()
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Drupal\controller_annota...\ConfigurationInterface as the method getName() does only exist in the following implementations of said interface: Drupal\controller_annota...guration\ParamConverter.

Let’s take a look at an example:

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

class MyUser implements 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 implementation 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 interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
75
                ));
76
            }
77
78 1
            $converter->apply($request, $configuration);
79
80 1
            return;
81
        }
82
83 2
        foreach ($this->all() as $converter) {
84 2
            if ($converter->supports($configuration)) {
85 1
                if ($converter->apply($request, $configuration)) {
86 2
                    return;
87
                }
88
            }
89
        }
90 2
    }
91
92
    /**
93
     * Adds a parameter converter.
94
     *
95
     * Converters match either explicitly via $name or by iteration over all
96
     * converters with a $priority. If you pass a $priority = null then the
97
     * added converter will not be part of the iteration chain and can only
98
     * be invoked explicitly.
99
     *
100
     * @param ParamConverterInterface $converter A ParamConverterInterface instance
101
     * @param int                     $priority  The priority (between -10 and 10).
102
     * @param string                  $name      Name of the converter.
103
     */
104 12
    public function add(ParamConverterInterface $converter, $priority = 0, $name = null)
105
    {
106 12
        if ($priority !== null) {
107 12
            if (!isset($this->converters[$priority])) {
108 12
                $this->converters[$priority] = [];
109
            }
110
111 12
            $this->converters[$priority][] = $converter;
112
        }
113
114 12
        if (null !== $name) {
115 2
            $this->namedConverters[$name] = $converter;
116
        }
117 12
    }
118
119
   /**
120
    * Returns all registered param converters.
121
    *
122
    * @return array An array of param converters
123
    */
124 3
   public function all()
125
   {
126 3
       krsort($this->converters);
127
128 3
       $converters = array();
129 3
       foreach ($this->converters as $all) {
130 3
           $converters = array_merge($converters, $all);
131
       }
132
133 3
       return $converters;
134
   }
135
}
136