Code

< 40 %
40-60 %
> 60 %
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
declare (strict_types = 1);
17
/**
18
 * XMPP Library
19
 *
20
 * Copyright (C) 2016, Some right reserved.
21
 *
22
 * @author Kacper "Kadet" Donat <[email protected]>
23
 *
24
 * Contact with author:
25
 * Xmpp: [email protected]
26
 * E-mail: [email protected]
27
 *
28
 * From Kadet with love.
29
 */
30
31
namespace Kadet\Xmpp;
32
33
use Kadet\Xmpp\Exception\InvalidArgumentException;
34
use Kadet\Xmpp\Utils\Accessors;
35
use Kadet\Xmpp\Utils\Immutable;
36
37
/**
38
 * Class Jid
39
 * @package Kadet\Xmpp
40
 *
41
 * @property-read string $domain
42
 * @property-read string $local
43
 * @property-read string $resource
44
 */
45
class Jid implements Immutable
46
{
47
    use Accessors;
48
49
    private $_local;
50
51
    /**
52
     * @var string
53
     */
54
    private $_domain;
55
56
    /**
57
     * @var string|null
58
     */
59
    private $_resource;
60
61 24
    public function __construct(string $address, string $local = null, string $resource = null)
62
    {
63 24 View Code Duplication
        if ($local === null && $resource === null) {
64 20
            list($address, $local, $resource) = self::_split($address);
65
        }
66
67 24
        self::validate($address, $local, $resource);
68
69 20
        $this->_domain   = $address;
70 20
        $this->_local    = $local;
71 20
        $this->_resource = $resource;
72 20
    }
73
74 29
    private static function _split(string $address)
75
    {
76 29
        preg_match('#^(?:(?P<local>[^@]+)@)?(?P<host>.*?)(?:/(?P<resource>.+?))?$#i', $address, $result);
77
78 29
        return [$result['host'], $result['local'] ?: null, $result['resource'] ?? null];
79
    }
80
81
    /**
82
     * Validates address and throws InvalidArgumentException in case of failure.
83
     *
84
     * @param string      $address
85
     * @param string      $local
86
     * @param string|null $resource
87
     * @return bool
88
     */
89 43
    public static function validate(string $address, string $local = null, string $resource = null)
90
    {
91 43 View Code Duplication
        if ($local === null && $resource === null) {
92 15
            list($address, $local, $resource) = self::_split($address);
93
        }
94
95 43
        if (empty($address)) {
96 9
            throw new InvalidArgumentException("Domain-part of JID is REQUIRED");
97
        }
98
99 34
        if (preg_match('#[<>:&"\'/@]#i', $address, $match) !== 0) {
100 3
            throw new InvalidArgumentException("Domain-part of JID contains not allowed character '{$match[0]}'");
101
        }
102
103 31
        if ($local !== null && preg_match('#[<>:&"\'/@]#i', $local, $match) !== 0) {
104 2
            throw new InvalidArgumentException("Local-part of JID contains not allowed character '{$match[0]}'");
105
        }
106
107 29
        if ($resource !== null && preg_match('#[<>:&"\'/]#i', $resource, $match) !== 0) {
108 3
            throw new InvalidArgumentException("Resource-part of JID contains not allowed character '{$match[0]}'");
109
        }
110
111 26
        return true;
112
    }
113
114
    /**
115
     * Returns if address is valid or not.
116
     *
117
     * @param string      $address
118
     * @param string      $local
119
     * @param string|null $resource
120
     * @return bool
121
     */
122 17
    public static function isValid(string $address, string $local = null, string $resource = null) : bool
123
    {
124
        try {
125 17
            return self::validate($address, $local, $resource);
126 11
        } catch (InvalidArgumentException $exception) {
127 11
            return false;
128
        }
129
    }
130
131 5
    public function __toString() : string
132
    {
133
        return
134 5
            ($this->_local ? "{$this->_local}@" : null)
135 5
            . $this->_domain
136 5
            . ($this->_resource ? "/{$this->_resource}" : null);
137
    }
138
139
    /**
140
     * Returns the domain part of address.
141
     *
142
     * @return string
143
     */
144 11
    public function getDomain() : string
145
    {
146 11
        return $this->_domain;
147
    }
148
149
    /**
150
     * Returns the local part of JID.
151
     *
152
     * @return string
153
     */
154 8
    public function getLocal() : string
155
    {
156 8
        return $this->_local;
157
    }
158
159
    /**
160
     * Returns resource part of address or null if resource is not set
161
     *
162
     * @return null|string
163
     */
164 6
    public function getResource()
165
    {
166 6
        return $this->_resource;
167
    }
168
169 4
    public function bare()
170
    {
171 4
        return new static($this->domain, $this->local, null);
172
    }
173
174 1
    public function isBare() : bool
175
    {
176 1
        return $this->_resource === null;
177
    }
178
179 1
    public function isFull() : bool
180
    {
181 1
        return $this->_resource !== null && $this->_local !== null;
182
    }
183
}
184