NonceService   A
last analyzed

Complexity

Total Complexity 11

Size/Duplication

Total Lines 94
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 9

Test Coverage

Coverage 87.5%

Importance

Changes 0
Metric Value
wmc 11
lcom 1
cbo 9
dl 0
loc 94
ccs 28
cts 32
cp 0.875
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A createNonce() 0 28 3
B consume() 0 36 7
1
<?php
2
/**
3
 * Copyright (c) 2014 Roave, LLC.
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 *
10
 *   * Redistributions of source code must retain the above copyright
11
 *     notice, this list of conditions and the following disclaimer.
12
 *
13
 *   * Redistributions in binary form must reproduce the above copyright
14
 *     notice, this list of conditions and the following disclaimer in
15
 *     the documentation and/or other materials provided with the
16
 *     distribution.
17
 *
18
 *   * Neither the names of the copyright holders nor the names of the
19
 *     contributors may be used to endorse or promote products derived
20
 *     from this software without specific prior written permission.
21
 *
22
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
 * POSSIBILITY OF SUCH DAMAGE.
34
 *
35
 * @author Antoine Hedgecock
36
 *
37
 * @copyright 2014 Roave, LLC
38
 * @license http://www.opensource.org/licenses/bsd-license.php  BSD License
39
 */
40
namespace Roave\NonceUtility\Service;
41
42
use DateInterval;
43
use DateTime;
44
use Doctrine\Common\Persistence\ObjectManager;
45
use Roave\NonceUtility\Entity\NonceEntity;
46
use Roave\NonceUtility\Repository\NonceRepositoryInterface;
47
use Roave\NonceUtility\Stdlib\NonceOwnerInterface;
48
use Zend\Http\PhpEnvironment\RemoteAddress;
49
use Zend\Http\Request as HttpRequest;
50
use Zend\Math\Rand;
51
use Zend\Stdlib\RequestInterface;
52
53
/**
54
 * Class NonceService
55
 */
56
class NonceService implements NonceServiceInterface
57
{
58
    /**
59
     * @var NonceRepositoryInterface
60
     */
61
    private $repository;
62
63
    /**
64
     * @var ObjectManager
65
     */
66
    private $objectManager;
67
68
    /**
69
     * @param ObjectManager            $objectManager
70
     * @param NonceRepositoryInterface $repository
71
     */
72
    public function __construct(ObjectManager $objectManager, NonceRepositoryInterface $repository)
73
    {
74
        $this->repository    = $repository;
75
        $this->objectManager = $objectManager;
76
    }
77
78
    /**
79
     * {@Inheritdoc}
80
     */
81
    public function createNonce(
82
        NonceOwnerInterface $owner,
83
        $namespace = 'default',
84
        DateInterval $expiresIn = null,
85
        $length = 10
86
    ) {
87 6
        do {
88
            $nonce = strtr(Rand::getString($length), '+/', '-_');
89
        } while ($this->repository->has($owner, $nonce, $namespace));
90
91
        $entity = new NonceEntity();
92
        $entity->setOwner($owner);
93 6
        $entity->setNonce($nonce);
94 6
        $entity->setNamespace($namespace);
95 6
        $entity->setCreatedAt(new DateTime());
96 6
97 6
        if ($expiresIn !== null) {
98
            $expiresAt = new DateTime();
99 6
            $expiresAt->add($expiresIn);
100 2
101 2
            $entity->setExpiresAt($expiresAt);
102
        }
103 2
104 2
        $this->objectManager->persist($entity);
105
        $this->objectManager->flush();
106 6
107 6
        return $entity;
108
    }
109 6
110
    /**
111
     * {@inheritdoc}
112
     */
113
    public function consume(
114
        NonceOwnerInterface $owner,
115
        $nonce,
116
        $namespace = 'default',
117
        RequestInterface $request = null
118
    ) {
119
        $nonce = $this->repository->get($owner, $nonce, $namespace);
120 10
121
        if (! $nonce) {
122
            throw new Exception\NonceNotFoundException;
123
        }
124
125
        if ($nonce->getConsumedAt() !== null) {
126 10
            throw new Exception\NonceAlreadyConsumedException;
127 5
        }
128 5
129 5
        $now = new DateTime();
130
        if ($nonce->getExpiresAt() !== null && $nonce->getExpiresAt() < $now) {
131
            throw new Exception\NonceHasExpiredException;
132 10
        }
133 2
134
        $nonce->setConsumedAt($now);
135
136 8
        // Add additional information if a request object was passed
137 2
        if ($request instanceof HttpRequest) {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
138
139
            $httpUserAgentHeader = $request->getHeader('User-Agent');
140 6
            if ($httpUserAgentHeader) {
141 6
                $nonce->setHttpUserAgent($httpUserAgentHeader->getFieldValue());
0 ignored issues
show
Bug introduced by
The method getFieldValue does only exist in Zend\Http\Header\HeaderInterface, but not in ArrayIterator.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
142 2
            }
143
144
            $nonce->setIpAddress((new RemoteAddress())->getIpAddress());
145 4
        }
146
147
        $this->objectManager->flush();
148 4
    }
149
}
150