Completed
Push — master ( 5208af...9fdf1f )
by Christian
47:25 queued 37:29
created

FormatNegotiator::getBest()   D

Complexity

Conditions 19
Paths 80

Size

Total Lines 59

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 33
CRAP Score 19.2086

Importance

Changes 0
Metric Value
dl 0
loc 59
ccs 33
cts 36
cp 0.9167
rs 4.5166
c 0
b 0
f 0
cc 19
nc 80
nop 2
crap 19.2086

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
/*
4
 * This file is part of the FOSRestBundle package.
5
 *
6
 * (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace FOS\RestBundle\Negotiation;
13
14
use FOS\RestBundle\Util\StopFormatListenerException;
15
use Negotiation\Accept;
16
use Negotiation\Negotiator as BaseNegotiator;
17
use Symfony\Component\HttpFoundation\Request;
18
use Symfony\Component\HttpFoundation\RequestMatcherInterface;
19
use Symfony\Component\HttpFoundation\RequestStack;
20
21
/**
22
 * @author Ener-Getick <[email protected]>
23
 */
24
class FormatNegotiator extends BaseNegotiator
25
{
26
    private $map = [];
27
    private $requestStack;
28
    private $mimeTypes;
29 21
30
    public function __construct(RequestStack $requestStack, array $mimeTypes = array())
31 21
    {
32 21
        $this->requestStack = $requestStack;
33 21
        $this->mimeTypes = $mimeTypes;
34
    }
35
36
    /**
37
     * @param RequestMatcherInterface $requestMatcher
38
     * @param array                   $options
39 20
     */
40
    public function add(RequestMatcherInterface $requestMatcher, array $options = [])
41 20
    {
42 20
        $this->map[] = [$requestMatcher, $options];
43
    }
44
45
    /**
46
     * {@inheritdoc}
47
     * The best format is also determined in function of the bundle configuration.
48
     *
49
     * @throws StopFormatListenerException
50 18
     */
51
    public function getBest($header, array $priorities = [])
52 18
    {
53 18
        $request = $this->getRequest();
54
        $header = $header ?: $request->headers->get('Accept');
55 18
56
        foreach ($this->map as $elements) {
57 17
            // Check if the current RequestMatcherInterface matches the current request
58 1
            if (!$elements[0]->matches($request)) {
59
                continue;
60 17
            }
61
            $options = &$elements[1]; // Do not reallow memory for this variable
62 17
63 1
            if (!empty($options['stop'])) {
64
                throw new StopFormatListenerException('Stopped format listener');
65 16
            }
66 2
            if (empty($options['priorities']) && empty($priorities)) {
67 2
                if (!empty($options['fallback_format'])) {
68
                    return new Accept($request->getMimeType($options['fallback_format']));
69 1
                }
70
71
                continue;
72 14
            }
73 9
74
            if (isset($options['prefer_extension']) && $options['prefer_extension'] && !isset($extensionHeader)) {
75 9
                $extension = pathinfo($request->getPathInfo(), PATHINFO_EXTENSION);
76
77 1
                if (!empty($extension)) {
78 1
                    // $extensionHeader will now be either a non empty string or an empty string
79
                    $extensionHeader = $request->getMimeType($extension);
80
81 1
                    if ($extensionHeader) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $extensionHeader of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
82 1
                        $header = $extensionHeader.'; q='.$options['prefer_extension'].($header ? ','.$header : '');
83 9
                    }
84
                }
85 14
            }
86 13
87 13
            if ($header) {
88 13
                $mimeTypes = $this->normalizePriorities($request,
89
                    empty($priorities) ? $options['priorities'] : $priorities
90 13
                );
91
92 13
                $mimeType = parent::getBest($header, $mimeTypes);
93 12
94
                if (null !== $mimeType) {
95 1
                    return $mimeType;
96
                }
97 2
            }
98
99 2
            if (isset($options['fallback_format'])) {
100
                // if false === fallback_format then we fail here instead of considering more rules
101
                if (false === $options['fallback_format']) {
102
                    return;
103
                }
104 2
105
                // stop looking at rules since we have a fallback defined
106 3
                return new Accept($request->getMimeType($options['fallback_format']));
107 3
            }
108
        }
109
    }
110
111
    /**
112
     * @param array $values
113
     *
114
     * @return array
115
     */
116 13
    private function sanitize(array $values)
117 13
    {
118 13
        return array_map(function ($value) {
119
            return preg_replace('/\s+/', '', strtolower($value));
120
        }, $values);
121
    }
122
123
    /**
124
     * Transform the format (json, html, ...) to their mimeType form (application/json, text/html, ...).
125
     *
126
     * @param Request  $request
127
     * @param string[] $priorities
128
     *
129 13
     * @return string[] formatted priorities
130
     */
131 13
    private function normalizePriorities(Request $request, array $priorities)
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...
132
    {
133 13
        $priorities = $this->sanitize($priorities);
134 13
135 13
        $mimeTypes = array();
136 2
        foreach ($priorities as $priority) {
137 2
            if (strpos($priority, '/')) {
138
                $mimeTypes[] = $priority;
139
140 12
                continue;
141 12
            }
142 12
143
            $mimeTypes = array_merge($mimeTypes, Request::getMimeTypes($priority));
144
145
            if (isset($this->mimeTypes[$priority])) {
146
                foreach ($this->mimeTypes[$priority] as $mimeType) {
147
                    $mimeTypes[] = $mimeType;
148 12
                }
149 3
            }
150 3
        }
151 3
152 3
        return $mimeTypes;
153 13
    }
154
155 13
    /**
156
     * @throws \RuntimeException
157
     *
158
     * @return Request
159
     */
160 View Code Duplication
    private function getRequest()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
161
    {
162
        $request = $this->requestStack->getCurrentRequest();
163 18
        if (null === $request) {
164
            throw new \RuntimeException('There is no current request.');
165 18
        }
166 18
167
        return $request;
168
    }
169
}
170