Completed
Push — master ( ce3f18...1319dc )
by Christian
05:54
created

FormatNegotiator   A

Complexity

Total Complexity 30

Size/Duplication

Total Lines 144
Duplicated Lines 6.25 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 88.24%

Importance

Changes 8
Bugs 2 Features 2
Metric Value
wmc 30
c 8
b 2
f 2
lcom 1
cbo 6
dl 9
loc 144
ccs 60
cts 68
cp 0.8824
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A add() 0 4 1
A __construct() 0 5 1
C getBest() 0 58 19
A sanitize() 0 6 1
B normalizePriorities() 0 22 6
A getRequest() 9 9 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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
30 20
    public function __construct(RequestStack $requestStack, array $mimeTypes = array())
31
    {
32 20
        $this->requestStack = $requestStack;
33 20
        $this->mimeTypes = $mimeTypes;
34 20
    }
35
36
    /**
37
     * @param RequestMatcherInterface $requestMatcher
38
     * @param array                   $options
39
     */
40 15
    public function add(RequestMatcherInterface $requestMatcher, array $options = [])
41
    {
42 15
        $this->map[] = [$requestMatcher, $options];
43 15
    }
44
45
    /**
46
     * {@inheritdoc}
47
     * The best format is also determined in function of the bundle configuration.
48
     *
49
     * @throws StopFormatListenerException
50
     */
51 18
    public function getBest($header, array $priorities = [])
52
    {
53 18
        $request = $this->getRequest();
54 18
        $header = $header ?: $request->headers->get('Accept');
55
56 18
        foreach ($this->map as $elements) {
57
            // Check if the current RequestMatcherInterface matches the current request
58 13
            if (!$elements[0]->matches($request)) {
59 1
                continue;
60
            }
61 13
            $options = &$elements[1]; // Do not reallow memory for this variable
62
63 13
            if (!empty($options['stop'])) {
64 1
                throw new StopFormatListenerException('Stopped format listener');
65
            }
66 12
            if (empty($options['priorities']) && empty($priorities)) {
67 1
                if (!empty($options['fallback_format'])) {
68 1
                    return new Accept($request->getMimeType($options['fallback_format']));
69
                }
70 1
                continue;
71
            }
72
73 11
            if (isset($options['prefer_extension']) && $options['prefer_extension'] && !isset($extensionHeader)) {
74 6
                $extension = pathinfo($request->getPathInfo(), PATHINFO_EXTENSION);
75
76 6
                if (!empty($extension)) {
77
                    // $extensionHeader will now be either a non empty string or an empty string
78
                    $extensionHeader = $request->getMimeType($extension);
79
                    if ($header && $extensionHeader) {
80
                        $header .= ',';
81
                    }
82
                    $header .= $extensionHeader.'; q='.$options['prefer_extension'];
83
                }
84 6
            }
85
86 11
            if ($header) {
87 10
                $mimeTypes = $this->normalizePriorities($request,
88 10
                    empty($priorities) ? $options['priorities'] : $priorities
89 10
                );
90
91 10
                $mimeType = parent::getBest($header, $mimeTypes);
92
93 10
                if ($mimeType !== null) {
94 9
                    return $mimeType;
95
                }
96 1
            }
97
98 2
            if (isset($options['fallback_format'])) {
99
                // if false === fallback_format then we fail here instead of considering more rules
100 2
                if (false === $options['fallback_format']) {
101
                    return;
102
                }
103
104
                // stop looking at rules since we have a fallback defined
105 2
                return new Accept($request->getMimeType($options['fallback_format']));
106
            }
107 7
        }
108 7
    }
109
110
    /**
111
     * @param array $values
112
     *
113
     * @return array
114
     */
115
    private function sanitize(array $values)
116
    {
117 10
        return array_map(function ($value) {
118 10
            return preg_replace('/\s+/', '', strtolower($value));
119 10
        }, $values);
120
    }
121
122
    /**
123
     * Transform the format (json, html, ...) to their mimeType form (application/json, text/html, ...).
124
     *
125
     * @param Request  $request
126
     * @param string[] $priorities
127
     *
128
     * @return string[] formatted priorities
129
     */
130 10
    private function normalizePriorities(Request $request, array $priorities)
131
    {
132 10
        $priorities = $this->sanitize($priorities);
133
134 10
        $mimeTypes = array();
135 10
        foreach ($priorities as $priority) {
136 10
            if (strpos($priority, '/')) {
137 2
                $mimeTypes[] = $priority;
138 2
                continue;
139
            }
140
141 9
            if (isset($this->mimeTypes[$priority])) {
142 7
                foreach ($this->mimeTypes[$priority] as $mimeType) {
143 7
                    $mimeTypes[] = $mimeType;
144 7
                }
145 9
            } elseif (($mimeType = $request->getMimeType($priority)) !== null) {
146 2
                $mimeTypes[] = $mimeType;
147 2
            }
148 10
        }
149
150 10
        return $mimeTypes;
151
    }
152
153
    /**
154
     * @throws \RuntimeException
155
     *
156
     * @return Request
157
     */
158 18 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...
159
    {
160 18
        $request = $this->requestStack->getCurrentRequest();
161 18
        if ($request === null) {
162
            throw new \RuntimeException('There is no current request.');
163
        }
164
165 18
        return $request;
166
    }
167
}
168