Completed
Push — master ( 4aee11...dd7177 )
by Kacper
04:24
created

Roster::removeItem()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 7
nc 2
nop 1
dl 0
loc 12
ccs 0
cts 8
cp 0
crap 6
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * Nucleus - XMPP Library for PHP
4
 *
5
 * Copyright (C) 2016, Some rights reserved.
6
 *
7
 * @author Kacper "Kadet" Donat <[email protected]>
8
 *
9
 * Contact with author:
10
 * Xmpp: [email protected]
11
 * E-mail: [email protected]
12
 *
13
 * From Kadet with love.
14
 */
15
16
namespace Kadet\Xmpp\Component;
17
18
19
use Kadet\Highlighter\Utils\Console;
20
use Kadet\Xmpp\Exception\ReadOnlyException;
21
use Kadet\Xmpp\Jid;
22
use Kadet\Xmpp\Stanza\Iq;
23
use Kadet\Xmpp\Utils\Accessors;
24
use Kadet\Xmpp\Utils\BetterEmitter;
25
use Kadet\Xmpp\Utils\filter as with;
26
use Kadet\Xmpp\XmppClient;
27
use Traversable;
28
use function Kadet\Xmpp\Utils\helper\format;
29
30
/**
31
 * Class Roster
32
 * @package Kadet\Xmpp\Component
33
 *
34
 * @property-read Iq\Query\Roster\Item[] $items Copy of all roster items
35
 */
36
class Roster extends Component implements \IteratorAggregate
37
{
38
    use BetterEmitter, Accessors;
39
40
    private $_items = [];
41
42 3
    public function setClient(XmppClient $client)
43
    {
44 3
        parent::setClient($client);
45
        $this->_client->on('init', function(\SplQueue $queue) {
46 1
            $queue->enqueue($this->_client->send(new Iq('get', ['query' => new Iq\Query\Roster()])));
47 3
        });
48
49 3
        $this->_client->on('iq', function(Iq $iq) {
50
            /** @var Roster $iq->query */
51 2
            switch ($iq->type) {
52 2
                case "result":
53 2
                    $this->handleResult($iq->query);
0 ignored issues
show
Documentation introduced by
$iq->query is of type object<Kadet\Xmpp\Component\Roster>, but the function expects a object<Kadet\Xmpp\Stanza\Iq\Query\Roster>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
54 2
                    break;
55
                case "set":
56
                    $this->handleSet($iq->query);
0 ignored issues
show
Documentation introduced by
$iq->query is of type object<Kadet\Xmpp\Component\Roster>, but the function expects a object<Kadet\Xmpp\Stanza\Iq\Query\Roster>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
57
                    break;
58
            }
59 3
        }, with\iq\query(Iq\Query\Roster::class));
60 3
    }
61
62 2
    private function handleSet(Iq\Query\Roster $query)
63
    {
64 2
        foreach ($query->items as $item) {
65 2
            if($item->subscription == 'remove') {
66
                $this->removeItem($item->jid);
67
            } else {
68 2
                $this->setItem($item);
69
            }
70
        }
71
72 2
        $this->emit('update');
73 2
    }
74
75 2
    private function handleResult(Iq\Query\Roster $query)
76
    {
77 2
        $this->_client->getLogger()->debug(format('Received roster (version: {version}) update with {no} roster items.', [
78 2
            'no' => count($query->items),
79 2
            'version' => $query->version
80
        ]));
81 2
        $this->_items = [];
82 2
        $this->handleSet($query);
83 2
    }
84
85
    /**
86
     * Whether a offset exists
87
     * @link  http://php.net/manual/en/arrayaccess.offsetexists.php
88
     * @param mixed $offset <p>
89
     *                      An offset to check for.
90
     *                      </p>
91
     * @return boolean true on success or false on failure.
92
     *                      </p>
93
     *                      <p>
94
     *                      The return value will be casted to boolean if non-boolean was returned.
95
     * @since 5.0.0
96
     */
97
    public function offsetExists($offset)
98
    {
99
        return array_key_exists($offset, $this->_items);
100
    }
101
102
    /**
103
     * Offset to retrieve
104
     * @link  http://php.net/manual/en/arrayaccess.offsetget.php
105
     * @param mixed $offset <p>
106
     *                      The offset to retrieve.
107
     *                      </p>
108
     * @return mixed Can return all value types.
109
     * @since 5.0.0
110
     */
111
    public function offsetGet($offset)
112
    {
113
        return clone ($this->_items[(string)$offset] ?? null);
114
    }
115
116
    /**
117
     * Offset to set
118
     * @link  http://php.net/manual/en/arrayaccess.offsetset.php
119
     * @param mixed $offset <p>
120
     *                      The offset to assign the value to.
121
     *                      </p>
122
     * @param mixed $value  <p>
123
     *                      The value to set.
124
     *                      </p>
125
     * @return void
126
     * @since 5.0.0
127
     */
128
    public function offsetSet($offset, $value)
0 ignored issues
show
Unused Code introduced by
The parameter $offset 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...
Unused Code introduced by
The parameter $value 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...
129
    {
130
        throw new ReadOnlyException('You should not modify roster directly, use update() method.');
131
    }
132
133
    /**
134
     * Offset to unset
135
     * @link  http://php.net/manual/en/arrayaccess.offsetunset.php
136
     * @param mixed $offset <p>
137
     *                      The offset to unset.
138
     *                      </p>
139
     * @return void
140
     * @since 5.0.0
141
     */
142
    public function offsetUnset($offset)
0 ignored issues
show
Unused Code introduced by
The parameter $offset 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...
143
    {
144
        throw new ReadOnlyException('You should not modify roster directly, use remove() method.');
145
    }
146
147 1
    public function remove($what)
148
    {
149 1
        $predicate = $what instanceof \Closure ? $what : with\property('jid', with\equals($what));
150 1
        $remove    = array_filter($this->_items, $predicate);
151
152 1
        $iq = new Iq('remove', ['query' => new Iq\Query\Roster()]);
153
        /** @var Iq\Query\Roster\Item $item */
154 1
        foreach($remove as $item) {
155 1
            $iq->query->append(new Iq\Query\Roster\Item($item->jid, ['subscription' => 'remove']));
156
        }
157
158 1
        $this->_client->send($iq);
159 1
    }
160
161
    /**
162
     * Retrieve an external iterator
163
     * @link  http://php.net/manual/en/iteratoraggregate.getiterator.php
164
     * @return Traversable An instance of an object implementing <b>Iterator</b> or
165
     * <b>Traversable</b>
166
     * @since 5.0.0
167
     */
168
    public function getIterator(): Traversable
169
    {
170
        return new \ArrayIterator($this->_items);
171
    }
172
173
    /**
174
     * @return Iq\Query\Roster\Item[]
175
     */
176 1
    public function getItems()
177
    {
178 1
        return \Kadet\Xmpp\Utils\helper\copy($this->_items);
179
    }
180
181
    public static function group($name)
182
    {
183
        return with\property('groups', with\contains($name));
184
    }
185
186
    /**
187
     * @param callable(Item $item) $mapper
0 ignored issues
show
Documentation introduced by
The doc-type callable(Item could not be parsed: Expected "|" or "end of type", but got "(" at position 8. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
Bug introduced by
There is no parameter named $item). Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
188
     * @return array
189
     */
190
    public function map(callable $mapper)
191
    {
192
        return array_map($mapper, $this->items);
193
    }
194
195
    /**
196
     * @param callable $predicate
197
     * @return Iq\Query\Roster\Item[]
198
     */
199
    public function filter(callable $predicate)
200
    {
201
        return array_filter($this->items, $predicate);
202
    }
203
204
    public function asArray() : array
205
    {
206
        return $this->items;
207
    }
208
209
    public static function fromArray(array $array)
0 ignored issues
show
Unused Code introduced by
The parameter $array 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...
210
    {
211
        // TODO: Implement fromArray() method.
212
    }
213
214
    /**
215
     * Count elements of an object
216
     * @link  http://php.net/manual/en/countable.count.php
217
     * @return int The custom count as an integer.
218
     * </p>
219
     * <p>
220
     * The return value is cast to an integer.
221
     * @since 5.1.0
222
     */
223
    public function count()
224
    {
225
        return count($this->items);
226
    }
227
228
229 2
    private function setItem(Iq\Query\Roster\Item $item)
230
    {
231 2
        $this->emit('item', [ $item ]);
232 2
        $this->_items[(string)$item->jid] = $item;
233 2
    }
234
235
    private function removeItem(Jid $jid)
236
    {
237
        if (!isset($this->_items[(string)$jid])) {
238
            $this->_client->getLogger()->warning(format('Trying to remove non-existing roster item {jid}', [
239
                'item' => Console::styled(['color' => 'green'], (string)$jid)
240
            ]));
241
            return;
242
        }
243
244
        $this->emit('remove', [ $this->_items[(string)$jid] ]);
245
        unset($this->_items[(string)$jid]);
246
    }
247
}
248