Completed
Pull Request — master (#76)
by Luke
02:26
created

LList::drop()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 0
dl 0
loc 6
ccs 0
cts 0
cp 0
crap 2
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * Nozavroni/Collections
4
 * Just another collections library for PHP5.6+.
5
 * @version   {version}
6
 * @copyright Copyright (c) 2017 Luke Visinoni <[email protected]>
7
 * @author    Luke Visinoni <[email protected]>
8
 * @license   https://github.com/deni-zen/csvelte/blob/master/LICENSE The MIT License (MIT)
9
 */
10
namespace Noz\Immutable;
11
12
use InvalidArgumentException;
13
14
use Countable;
15
use Traversable;
16
use Serializable;
17
use SplDoublyLinkedList;
18
19
use Noz\Contracts\Structure\Listable;
20
use Noz\Contracts\Immutable;
21
use Noz\Contracts\Arrayable;
22
use Noz\Contracts\Invokable;
23
24
use Noz\Traits\IsArrayable;
25
use Noz\Traits\IsImmutable;
26
use Noz\Traits\IsContainer;
27
28
use function
29
    Noz\is_traversable;
30
31
class LList implements
32
    Listable,
33
    Immutable,
34
    Countable,
35
    Arrayable,
36
    Invokable,
37
    Serializable
38
{
39
    use IsImmutable,
40
        IsArrayable,
41
        IsContainer;
42
    /**
43
     * @var SplDoublyLinkedList
44
     */
45
    private $data;
46
47
    /**
48
     * LList constructor.
49
     *
50
     * @param array|Traversable $data The list constructor
0 ignored issues
show
Documentation introduced by
Should the type for parameter $data not be array|Traversable|null? Also, consider making the array more specific, something like array<String>, or String[].

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive. In addition it looks for parameters that have the generic type array and suggests a stricter type like array<String>.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
51
     */
52
    public function __construct($data = null)
53
    {
54
        if (is_null($data)) {
55
            $data = [];
56
        }
57
        $this->setData($data);
58
    }
59
60
    /**
61
     * Set internal data array.
62
     *
63
     * @param array|Traversable $data The list constructor
64
     */
65
    private function setData($data)
66
    {
67
        if (!is_traversable($data)) {
68
            throw new InvalidArgumentException(
69
                '%s expects traversable data.',
70
                __CLASS__
71
            );
72
        }
73
        if ($data instanceof SplDoublyLinkedList) {
74
            $dll = $data;
75
        } else {
76
            $dll = new SplDoublyLinkedList($data);
0 ignored issues
show
Unused Code introduced by
The call to SplDoublyLinkedList::__construct() has too many arguments starting with $data.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
77
            $dll->setIteratorMode(SplDoublyLinkedList::IT_MODE_KEEP);
78
            foreach($data as $key => $val) {
79
                $dll->push($val);
80
            }
81
        }
82
        $this->data = $dll;
83
    }
84
85
    /**
86
     * Get internal data array.
87
     *
88
     * @return SplDoublyLinkedList
89
     */
90
    protected function getData()
91
    {
92
        return clone $this->data;
93
    }
94
95
    /**
96
     * Invoke LList.
97
     *
98
     * This method is called when a LList object is invoked (called as if it were a function).
99
     *
100
     * @return mixed
101
     */
102
    public function __invoke()
103
    {
104
105
    }
106
107
    /**
108
     * Count elements of an object
109
     * @link  http://php.net/manual/en/countable.count.php
110
     * @return int The custom count as an integer.
111
     * </p>
112
     * <p>
113
     * The return value is cast to an integer.
114
     * @since 5.1.0
115
     */
116
    public function count()
117
    {
118
        return $this->data->count();
119
    }
120
121
    /**
122
     * Return new sequence with the first item "bumped" off.
123
     *
124
     * @return Listable
125
     */
126
    public function bump()
127
    {
128
        $data = $this->getData();
129
        $data->shift();
130
        return new static($data);
131
    }
132
133
    /**
134
     * Return new sequence with the last item "dropped" off.
135
     *
136
     * @return Listable
137
     */
138
    public function drop()
139
    {
140
        $data = $this->getData();
141
        $data->pop();
142
        return new static($data);
143
    }
144
145
    /**
146
     * Get the top item of the list.
147
     *
148
     * @return mixed
149
     */
150
    public function top()
151
    {
152
        return $this->data->top();
153
    }
154
155
    /**
156
     * Get the bottom item of the list.
157
     *
158
     * @return mixed
159
     */
160
    public function bottom()
161
    {
162
        return $this->data->bottom();
163
    }
164
165
    /**
166
     * Is collection empty?
167
     * You may optionally pass in a callback which will determine if each of the items within the collection are empty.
168
     * If all items in the collection are empty according to this callback, this method will return true.
169
     *
170
     * @param callable $predicate The callback
0 ignored issues
show
Documentation introduced by
Should the type for parameter $predicate not be null|callable? Also, consider making the array more specific, something like array<String>, or String[].

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive. In addition it looks for parameters that have the generic type array and suggests a stricter type like array<String>.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
171
     *
172
     * @return bool
173
     */
174
    public function isEmpty(callable $predicate = null)
175
    {
176
        if (!is_null($predicate)) {
177
            foreach ($this->data as $val) {
178
                if (!$predicate($val)) {
179
                    return false;
180
                }
181
            }
182
        }
183
        return $this->data->isEmpty();
184
    }
185
186
    /**
187
     * Pipe collection through callback.
188
     *
189
     * Passes entire collection to provided callback and returns the result.
190
     *
191
     * @param callable $through Function to pipe collection through
192
     *
193
     * @return mixed
194
     */
195
    public function pipe(callable $through)
196
    {
197
        return $through($this);
198
    }
199
200
    /**
201
     * Does every item return true?
202
     *
203
     * If callback is provided, this method will return true if all items in collection cause callback to return true.
204
     * Otherwise, it will return true if all items in the collection have a truthy value.
205
     *
206
     * @param callable|null $funk The callback
207
     *
208
     * @return bool
0 ignored issues
show
Documentation introduced by
Should the return type not be boolean|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
209
     */
210
    public function every(callable $funk = null)
211
    {
212
        return $this->fold(function($carry, $val, $key, $iter) use ($funk) {
213
            if (!$funk($val, $key, $iter)) {
214
                return false;
215
            }
216
            return $carry && true;
217
        }, true);
218
    }
219
220
    /**
221
     * Does every item return false?
222
     *
223
     * This method is the exact opposite of "all".
224
     *
225
     * @param callable|null $callback The callback
226
     *
227
     * @return bool
0 ignored issues
show
Documentation introduced by
Should the return type not be boolean|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
228
     */
229
    public function none(callable $callback = null)
230
    {
231
        return $this->fold(function($carry, $val, $key, $iter) use ($funk) {
0 ignored issues
show
Bug introduced by
The variable $funk does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
232
            if ($funk($val, $key, $iter)) {
233
                return false;
234
            }
235
            return $carry && true;
236
        }, true);
237
    }
238
239
    /**
240
     * Prepend item to collection.
241
     *
242
     * Return a new list with this item prepended to the collection.
243
     *
244
     * @param mixed $item Item to prepend to collection
245
     *
246
     * @return Listable
247
     */
248
    public function prepend($item)
249
    {
250
        $data = $this->getData();
251
        $data->unshift($item);
252
        return new static($data);
253
    }
254
255
    /**
256
     * Append item to collection.
257
     *
258
     * Return a new list with this item appended to the collection.
259
     *
260
     * @param mixed $item Item to append to collection
261
     *
262
     * @return Listable
263
     */
264
    public function append($item)
265
    {
266
        $data = $this->getData();
267
        $data->push($item);
268
        return new static($data);
269
    }
270
271
    public function serialize()
272
    {
273
        return $this->getData()->serialize();
274
    }
275
276
    public function unserialize($serialized)
277
    {
278
        $data = new SplDoublyLinkedList;
279
        $data->unserialize($serialized);
280
        $this->data = $data;
281
    }
282
283
    /**
284
     * @param callable|null $folder
285
     * @param null          $initial
286
     *
287
     * @return null
288
     */
289
    public function fold(callable $folder = null, $initial = null)
290
    {
291
        $iter = 0;
292
        $carry = $initial;
293
        foreach ($this->getData() as $key => $val) {
294
            $carry = $folder($carry, $val, $key, $iter++);
295
        }
296
        return $carry;
297
    }
298
299
}
300