Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
37.50% |
15 / 40 |
|
20.00% |
1 / 5 |
CRAP | |
0.00% |
0 / 1 |
UserTuple | |
37.50% |
15 / 40 |
|
20.00% |
1 / 5 |
191.04 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
15 / 15 |
|
100.00% |
1 / 1 |
12 | |||
newFromUser | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
6 | |||
newFromArray | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
56 | |||
toArray | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
2 | |||
createUser | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
20 |
1 | <?php |
2 | |
3 | namespace Flow\Model; |
4 | |
5 | use Flow\Exception\CrossWikiException; |
6 | use Flow\Exception\FlowException; |
7 | use Flow\Exception\InvalidDataException; |
8 | use MediaWiki\User\User; |
9 | use MediaWiki\WikiMap\WikiMap; |
10 | |
11 | /** |
12 | * Small value object holds the values necessary to uniquely identify |
13 | * a user across multiple wiki's. |
14 | */ |
15 | class UserTuple { |
16 | /** |
17 | * @var string The wiki the user belongs to |
18 | */ |
19 | public $wiki; |
20 | |
21 | /** |
22 | * @var int The id of the user, or 0 for anonymous |
23 | */ |
24 | public $id; |
25 | |
26 | /** |
27 | * @var string|null The ip of the user, null if logged in. |
28 | */ |
29 | public $ip; |
30 | |
31 | /** |
32 | * @param string $wiki The wiki the user belongs to |
33 | * @param int|string $id The id of the user, or 0 for anonymous |
34 | * @param string|null $ip The ip of the user, blank string for no ip. |
35 | * null special case pass-through to be removed. |
36 | * @throws InvalidDataException |
37 | */ |
38 | public function __construct( $wiki, $id, $ip ) { |
39 | if ( !is_int( $id ) ) { |
40 | if ( ctype_digit( (string)$id ) ) { |
41 | $id = (int)$id; |
42 | } else { |
43 | throw new InvalidDataException( 'User id must be an integer' ); |
44 | } |
45 | } |
46 | if ( $id < 0 ) { |
47 | throw new InvalidDataException( 'User id must be >= 0' ); |
48 | } |
49 | if ( !$wiki ) { |
50 | throw new InvalidDataException( 'No wiki provided' ); |
51 | } |
52 | if ( $id === 0 && ( $ip === null || strlen( $ip ) === 0 ) ) { |
53 | throw new InvalidDataException( 'User has no id and no ip' ); |
54 | } |
55 | if ( $id !== 0 && $ip && strlen( $ip ) !== 0 ) { |
56 | throw new InvalidDataException( 'User has both id and ip' ); |
57 | } |
58 | // @todo assert ip is ipv4 or ipv6, but do we really want |
59 | // that on every anon user we load from storage? |
60 | |
61 | $this->wiki = $wiki; |
62 | $this->id = $id; |
63 | $this->ip = (string)$ip ?: null; |
64 | } |
65 | |
66 | public static function newFromUser( User $user ) { |
67 | return new self( |
68 | WikiMap::getCurrentWikiId(), |
69 | $user->getId(), |
70 | $user->isRegistered() ? null : $user->getName() |
71 | ); |
72 | } |
73 | |
74 | public static function newFromArray( array $user, $prefix = '' ) { |
75 | $wiki = "{$prefix}wiki"; |
76 | $id = "{$prefix}id"; |
77 | $ip = "{$prefix}ip"; |
78 | |
79 | if ( |
80 | isset( $user[$wiki] ) |
81 | && array_key_exists( $id, $user ) && array_key_exists( $ip, $user ) |
82 | // $user[$id] === 0 is special case when when IRC formatter mocks up objects |
83 | && ( $user[$id] || $user[$ip] || $user[$id] === 0 ) |
84 | ) { |
85 | return new self( $user["{$prefix}wiki"], $user["{$prefix}id"], $user["{$prefix}ip"] ); |
86 | } else { |
87 | return null; |
88 | } |
89 | } |
90 | |
91 | public function toArray( $prefix = '' ) { |
92 | return [ |
93 | "{$prefix}wiki" => $this->wiki, |
94 | "{$prefix}id" => $this->id, |
95 | "{$prefix}ip" => $this->ip |
96 | ]; |
97 | } |
98 | |
99 | public function createUser() { |
100 | if ( $this->wiki !== WikiMap::getCurrentWikiId() ) { |
101 | throw new CrossWikiException( 'Can only retrieve same-wiki users' ); |
102 | } |
103 | if ( $this->id ) { |
104 | return User::newFromId( $this->id ); |
105 | } elseif ( !$this->ip ) { |
106 | throw new FlowException( 'Either $userId or $userIp must be set.' ); |
107 | } else { |
108 | return User::newFromName( $this->ip, /* $validate = */ false ); |
109 | } |
110 | } |
111 | } |