Completed
Push — master ( 89ec26...6a878a )
by adam
04:53 queued 02:13
created

MediawikiSession   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 153
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 89.29%

Importance

Changes 10
Bugs 0 Features 2
Metric Value
wmc 23
c 10
b 0
f 2
lcom 1
cbo 4
dl 0
loc 153
ccs 50
cts 56
cp 0.8929
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A setLogger() 0 3 1
A clearTokens() 0 4 1
A getToken() 0 17 3
A reallyGetPre125Token() 0 9 1
A reallyGetToken() 0 21 4
B getNewTokenType() 0 16 10
A getOldTokenType() 0 8 2
1
<?php
2
3
namespace Mediawiki\Api;
4
5
use Psr\Log\LoggerAwareInterface;
6
use Psr\Log\LoggerInterface;
7
use Psr\Log\LogLevel;
8
use Psr\Log\NullLogger;
9
10
/**
11
 * @since 0.1
12
 *
13
 * @author Addshore
14
 */
15
class MediawikiSession implements LoggerAwareInterface {
16
17
	/**
18
	 * @var array
19
	 */
20
	private $tokens = array();
21
22
	/**
23
	 * @var MediawikiApi
24
	 */
25
	private $api;
26
27
	/**
28
	 * @var bool if this session is running against mediawiki version pre 1.25
29
	 */
30
	private $usePre125TokensModule = false;
31
32
	/**
33
	 * @var LoggerInterface
34
	 */
35
	private $logger;
36
37
	/**
38
	 * @param MediawikiApi $api
39
	 */
40 5
	public function __construct( MediawikiApi $api ) {
41 5
		$this->api = $api;
42 5
		$this->logger = new NullLogger();
43 5
	}
44
45
	/**
46
	 * Sets a logger instance on the object
47
	 *
48
	 * @since 1.1
49
	 *
50
	 * @param LoggerInterface $logger
51
	 *
52
	 * @return null
53
	 */
54
	public function setLogger( LoggerInterface $logger ) {
55
		$this->logger = $logger;
56
	}
57
58
	/**
59
	 * Tries to get the specified token from the API
60
	 *
61
	 * @since 0.1
62
	 *
63
	 * @param string $type
64
	 *
65
	 * @return string
66
	 */
67 6
	public function getToken( $type = 'csrf' ) {
68
		// If we don't already have the token that we want
69 6
		if( !array_key_exists( $type, $this->tokens ) ) {
70
71 6
			$this->logger->log( LogLevel::DEBUG, 'Getting fresh token', array( 'type' => $type ) );
72
73
			// If we know that we don't have the new module mw<1.25
74 6
			if( $this->usePre125TokensModule ) {
75
				return $this->reallyGetPre125Token( $type );
76
			} else {
77 6
				return $this->reallyGetToken( $type );
78
			}
79
80
		}
81
82 4
		return $this->tokens[$type];
83
	}
84
85 2
	private function reallyGetPre125Token( $type ) {
86
		// Suppress deprecation warning
87 2
		$result = @$this->api->postRequest(
88 2
			new SimpleRequest( 'tokens', array( 'type' => $this->getOldTokenType( $type ) ) )
89 2
		);
90 2
		$this->tokens[$type] = array_pop( $result['tokens'] );
91
92 2
		return $this->tokens[$type];
93
	}
94
95 4
	private function reallyGetToken( $type ) {
96
		// We suppress errors on this call so the user doesn't get get a warning that isn't their fault.
97 4
		$result = @$this->api->postRequest(
98 4
			new SimpleRequest( 'query', array(
99 4
				'meta' => 'tokens',
100 4
				'type' => $this->getNewTokenType( $type ),
101 4
				'continue' => '',
102 4
			) )
103 4
		);
104
		// If mw<1.25 (no new module)
105 4
		if( array_key_exists( 'warnings', $result ) && array_key_exists( 'query', $result['warnings'] ) &&
106 4
			strstr( $result['warnings']['query']['*'], "Unrecognized value for parameter 'meta': tokens" ) ) {
107 2
			$this->usePre125TokensModule = true;
108 2
			$this->logger->log( LogLevel::DEBUG, 'Falling back to pre 1.25 token system' );
109 2
			$this->tokens[$type] = $this->reallyGetPre125Token( $type );
110 2
		} else {
111 2
			$this->tokens[$type] = array_pop( $result['query']['tokens'] );
112
		}
113
114 4
		return $this->tokens[$type];
115
	}
116
117
	/**
118
	 * Tries to guess a new token type from an old token type
119
	 *
120
	 * @param string $type
121
	 *
122
	 * @return string
123
	 */
124 4
	private function getNewTokenType( $type ) {
125
		switch ( $type ) {
126 4
			case 'edit':
127 4
			case 'delete':
128 4
			case 'protect':
129 4
			case 'move':
130 4
			case 'block':
131 4
			case 'unblock':
132 4
			case 'email':
133 4
			case 'import':
134 4
			case 'options':
135
				return 'csrf';
136
		}
137
		// Return the same type, don't know what to do with this..
138 4
		return $type;
139
	}
140
141
	/**
142
	 * Tries to guess an old token type from a new token type
143
	 *
144
	 * @param $type
145
	 *
146
	 * @return string
147
	 */
148 2
	private function getOldTokenType( $type ) {
149
		switch ( $type ) {
150
			// Guess that we want an edit token, this may not always work as we might be trying to use it for something else...
151 2
			case 'csrf':
152 2
				return 'edit';
153
		}
154
		return $type;
155
	}
156
157
	/**
158
	 * Clears all tokens stored by the api
159
	 *
160
	 * @since 0.2
161
	 */
162 2
	public function clearTokens() {
163 2
		$this->logger->log( LogLevel::DEBUG, 'Clearing session tokens', array( 'tokens' => $this->tokens ) );
164 2
		$this->tokens = array();
165 2
	}
166
167
}
168