Completed
Pull Request — master (#331)
by thomas
34:30
created

Stack::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace BitWasp\Bitcoin\Script\Interpreter;
4
5
use BitWasp\Buffertools\BufferInterface;
6
7
class Stack extends \SplDoublyLinkedList implements StackInterface
8
{
9 3729
    public function __construct()
10
    {
11 3729
        $this->setIteratorMode(\SplDoublyLinkedList::IT_MODE_FIFO | \SplDoublyLinkedList::IT_MODE_KEEP);
12 3729
    }
13
14 135
    public function bottom()
15
    {
16 135
        return parent::offsetGet(count($this) - 1);
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (offsetGet() instead of bottom()). Are you sure this is correct? If so, you might want to change this to $this->offsetGet().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
17
    }
18
19
    /**
20
     * @param BufferInterface $value
21
     * @throws \InvalidArgumentException
22
     */
23 75
    private function typeCheck($value)
24
    {
25 75
        if (!$value instanceof BufferInterface) {
26
            throw new \InvalidArgumentException('Value was not of type Buffer');
27
        }
28 75
    }
29
30
    /**
31
     * @see \ArrayAccess::offsetGet()
32
     * @param int $offset
33
     * @return \BitWasp\Buffertools\BufferInterface
34
     */
35 2784
    public function offsetGet($offset)
36
    {
37 2784
        $offset = count($this) + $offset;
38 2784
        return parent::offsetGet($offset);
39
    }
40
41
    /**
42
     * @see \ArrayAccess::offsetSet()
43
     * @param int $offset
44
     * @param BufferInterface $value
45
     * @throws \InvalidArgumentException
46
     */
47 63
    public function offsetSet($offset, $value)
48
    {
49 63
        $this->typeCheck($value);
50 63
        $offset = count($this) + $offset;
51 63
        parent::offsetSet($offset, $value);
52 63
    }
53
54
    /**
55
     * @see \ArrayAccess::offsetExists()
56
     * @param int $offset
57
     * @return bool
58
     */
59 3
    public function offsetExists($offset)
60
    {
61 3
        $offset = count($this) + $offset;
62 3
        return parent::offsetExists($offset);
63
    }
64
65
    /**
66
     * @see \ArrayAccess::offsetUnset()
67
     * @param int $offset
68
     */
69 81
    public function offsetUnset($offset)
70
    {
71 81
        $offset = count($this) + $offset;
72 81
        parent::offsetUnset($offset);
73 78
    }
74
75
    /**
76
     * @param int $first
77
     * @param int $second
78
     */
79 63
    public function swap($first, $second)
80
    {
81 63
        $val1 = $this->offsetGet($first);
82 63
        $val2 = $this->offsetGet($second);
83 63
        $this->offsetSet($second, $val1);
84 63
        $this->offsetSet($first, $val2);
85 63
    }
86
87
    /**
88
     * @param int $index
89
     * @param BufferInterface $value
90
     */
91
    public function add2($index, $value)
92
    {
93
        $this->typeCheck($value);
94
95
        if (getenv('HHVM_VERSION') || version_compare(phpversion(), '5.5.0', 'lt')) {
96
            if ($index == $this->count()) {
97
                $this->push($value);
98
            } else {
99
                $size = count($this);
100
                $temp = [];
101
                for ($i = $size; $i > $index; $i--) {
102
                    array_unshift($temp, $this->pop());
103
                }
104
105
                $this->push($value);
106
                foreach ($temp as $value) {
107
                    $this->push($value);
108
                }
109
            }
110
        } else {
111
            parent::add($index, $value);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class SplDoublyLinkedList as the method add() does only exist in the following sub-classes of SplDoublyLinkedList: BitWasp\Bitcoin\Script\Interpreter\Stack. 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...
Comprehensibility Bug introduced by
It seems like you call parent on a different method (add() instead of add2()). Are you sure this is correct? If so, you might want to change this to $this->add().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
112
        }
113
    }
114
115
116
    /**
117
     * @param int $index
118
     * @param BufferInterface $value
119
     */
120 18
    public function add($index, $value)
121
    {
122 18
        $this->typeCheck($value);
123
124 18
        if (getenv('HHVM_VERSION') || version_compare(phpversion(), '5.5.0', 'lt')) {
125
            if ($index == $this->count()) {
126
                $this->push($value);
127
            } else {
128
                $temp = [];
129
                for ($i = count($this); $i >= $index; $i--) {
130
                    array_unshift($temp, $this->pop());
131
                }
132
133
                $this->push($value);
134
                foreach ($temp as $value) {
135
                    $this->push($value);
136
                }
137
            }
138
        } else {
139 18
            parent::add($index, $value);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class SplDoublyLinkedList as the method add() does only exist in the following sub-classes of SplDoublyLinkedList: BitWasp\Bitcoin\Script\Interpreter\Stack. 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...
140
        }
141 18
    }
142
143
    /**
144
     * @return int
145
     */
146
    public function end()
147
    {
148
        $count = count($this);
149
        if ($count === 0) {
150
            return 0;
151
        }
152
153
        return $count - 1;
154
    }
155
156
    /**
157
     * @param int $length
158
     * @return $this
159
     */
160 39
    public function resize($length)
161
    {
162 39
        if ($length > count($this)) {
163
            throw new \RuntimeException('Invalid start or length');
164
        }
165
166 39
        while (count($this) > $length) {
167 39
            $this->pop();
168 26
        }
169
170 39
        return $this;
171
    }
172
}
173