summaryrefslogtreecommitdiff
path: root/bin/reevotech/vendor/addwiki/mediawiki-api-base/src
diff options
context:
space:
mode:
Diffstat (limited to 'bin/reevotech/vendor/addwiki/mediawiki-api-base/src')
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/src/ApiRequester.php31
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/src/ApiUser.php90
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/src/AsyncApiRequester.php37
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/src/FluentRequest.php118
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/src/Guzzle/ClientFactory.php96
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/src/Guzzle/MiddlewareFactory.php158
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/src/MediawikiApi.php507
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/src/MediawikiApiInterface.php60
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/src/MediawikiSession.php168
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/src/MultipartRequest.php77
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/src/Request.php30
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/src/RsdException.php12
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/src/SimpleRequest.php61
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/src/UsageException.php75
14 files changed, 1520 insertions, 0 deletions
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/ApiRequester.php b/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/ApiRequester.php
new file mode 100644
index 00000000..cc3c8bcf
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/ApiRequester.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Mediawiki\Api;
+
+/**
+ * @since 2.2
+ * @licence GNU GPL v2+
+ * @author Addshore
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+interface ApiRequester {
+
+ /**
+ * @since 2.2
+ *
+ * @param Request $request The GET request to send.
+ *
+ * @return mixed Normally an array
+ */
+ public function getRequest( Request $request );
+
+ /**
+ * @since 2.2
+ *
+ * @param Request $request The POST request to send.
+ *
+ * @return mixed Normally an array
+ */
+ public function postRequest( Request $request );
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/ApiUser.php b/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/ApiUser.php
new file mode 100644
index 00000000..b2f59153
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/ApiUser.php
@@ -0,0 +1,90 @@
+<?php
+
+namespace Mediawiki\Api;
+
+use InvalidArgumentException;
+
+/**
+ * @since 0.1
+ *
+ * @author Addshore
+ * @author RobinR1
+ * @author Bene
+ *
+ * Represents a user that can log in to the api
+ */
+class ApiUser {
+
+ /**
+ * @var string
+ */
+ private $password;
+
+ /**
+ * @var string
+ */
+ private $username;
+
+ /**
+ * @var string
+ */
+ private $domain;
+
+ /**
+ * @param string $username The username.
+ * @param string $password The user's password.
+ * @param string|null $domain The domain (for authentication systems that support domains).
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function __construct( $username, $password, $domain = null ) {
+ $domainIsStringOrNull = ( is_string( $domain ) || is_null( $domain ) );
+ if ( !is_string( $username ) || !is_string( $password ) || !$domainIsStringOrNull ) {
+ throw new InvalidArgumentException( 'Username, Password and Domain must all be strings' );
+ }
+ if ( empty( $username ) || empty( $password ) ) {
+ throw new InvalidArgumentException( 'Username and Password are not allowed to be empty' );
+ }
+ $this->username = $username;
+ $this->password = $password;
+ $this->domain = $domain;
+ }
+
+ /**
+ * @since 0.1
+ * @return string
+ */
+ public function getUsername() {
+ return $this->username;
+ }
+
+ /**
+ * @since 0.1
+ * @return string
+ */
+ public function getPassword() {
+ return $this->password;
+ }
+
+ /**
+ * @since 0.1
+ * @return string
+ */
+ public function getDomain() {
+ return $this->domain;
+ }
+
+ /**
+ * @since 0.1
+ * @param mixed $other Another ApiUser object to compare with.
+ *
+ * @return bool
+ */
+ public function equals( $other ) {
+ return $other instanceof self
+ && $this->username == $other->getUsername()
+ && $this->password == $other->getPassword()
+ && $this->domain == $other->getDomain();
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/AsyncApiRequester.php b/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/AsyncApiRequester.php
new file mode 100644
index 00000000..6190ac7e
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/AsyncApiRequester.php
@@ -0,0 +1,37 @@
+<?php
+
+namespace Mediawiki\Api;
+
+use GuzzleHttp\Promise\PromiseInterface;
+
+/**
+ * @since 2.2
+ * @licence GNU GPL v2+
+ * @author Addshore
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+interface AsyncApiRequester {
+
+ /**
+ * @since 2.2
+ *
+ * @param Request $request The GET request to send.
+ *
+ * @return PromiseInterface
+ * Normally promising an array, though can be mixed (json_decode result)
+ * Can throw UsageExceptions or RejectionExceptions
+ */
+ public function getRequestAsync( Request $request );
+
+ /**
+ * @since 2.2
+ *
+ * @param Request $request The POST request to send.
+ *
+ * @return PromiseInterface
+ * Normally promising an array, though can be mixed (json_decode result)
+ * Can throw UsageExceptions or RejectionExceptions
+ */
+ public function postRequestAsync( Request $request );
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/FluentRequest.php b/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/FluentRequest.php
new file mode 100644
index 00000000..0d10553b
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/FluentRequest.php
@@ -0,0 +1,118 @@
+<?php
+
+namespace Mediawiki\Api;
+
+/**
+ * @since 1.0
+ *
+ * @author Addshore
+ */
+class FluentRequest implements Request {
+
+ /**
+ * @var array
+ */
+ private $params = [];
+
+ /**
+ * @var array
+ */
+ private $headers = [];
+
+ /**
+ * @since 1.0
+ *
+ * @return array
+ */
+ public function getParams() {
+ return $this->params;
+ }
+
+ /**
+ * @since 1.0
+ *
+ * @return array
+ */
+ public function getHeaders() {
+ return $this->headers;
+ }
+
+ /**
+ * @since 1.0
+ *
+ * @return static
+ */
+ public static function factory() {
+ return new static();
+ }
+
+ /**
+ * @since 1.0
+ *
+ * @param string $action The action name.
+ *
+ * @return $this
+ */
+ public function setAction( $action ) {
+ $this->setParam( 'action', $action );
+ return $this;
+ }
+
+ /**
+ * Totally overwrite any previously set params
+ *
+ * @since 1.0
+ *
+ * @param array $params New parameters.
+ *
+ * @return $this
+ */
+ public function setParams( array $params ) {
+ $this->params = $params;
+ return $this;
+ }
+
+ /**
+ * Totally overwrite any previously set params
+ *
+ * @since 1.0
+ *
+ * @param array $params Additional parameters.
+ *
+ * @return $this
+ */
+ public function addParams( array $params ) {
+ $this->params = array_merge( $this->params, $params );
+ return $this;
+ }
+
+ /**
+ * Set a single parameter.
+ *
+ * @since 1.0
+ *
+ * @param string $param The parameter name.
+ * @param string $value The parameter value.
+ *
+ * @return $this
+ */
+ public function setParam( $param, $value ) {
+ $this->params[$param] = $value;
+ return $this;
+ }
+
+ /**
+ * Totally overwrite any previously set HTTP headers.
+ *
+ * @since 1.0
+ *
+ * @param array $headers New headers.
+ *
+ * @return $this
+ */
+ public function setHeaders( $headers ) {
+ $this->headers = $headers;
+ return $this;
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/Guzzle/ClientFactory.php b/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/Guzzle/ClientFactory.php
new file mode 100644
index 00000000..704a1660
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/Guzzle/ClientFactory.php
@@ -0,0 +1,96 @@
+<?php
+
+namespace Mediawiki\Api\Guzzle;
+
+use GuzzleHttp\Client;
+use GuzzleHttp\Handler\CurlHandler;
+use GuzzleHttp\HandlerStack;
+use Psr\Log\LoggerAwareInterface;
+use Psr\Log\LoggerInterface;
+use Psr\Log\NullLogger;
+
+/**
+ * @since 2.1
+ *
+ * @author Addshore
+ */
+class ClientFactory implements LoggerAwareInterface {
+
+ private $client;
+ private $logger;
+ private $config;
+
+ /**
+ * @since 2.1
+ *
+ * @param array $config All configuration settings supported by Guzzle, and these:
+ * middleware => array of extra middleware to pass to guzzle
+ * user-agent => string default user agent to use for requests
+ */
+ public function __construct( array $config = [] ) {
+ $this->logger = new NullLogger();
+ $this->config = $config;
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return Client
+ */
+ public function getClient() {
+ if ( $this->client === null ) {
+ $this->client = $this->newClient();
+ }
+ return $this->client;
+ }
+
+ /**
+ * @return Client
+ */
+ private function newClient() {
+ $this->config += [
+ 'cookies' => true,
+ 'headers' => [],
+ 'middleware' => [],
+ ];
+
+ if ( !array_key_exists( 'User-Agent', $this->config['headers'] ) ) {
+ if ( array_key_exists( 'user-agent', $this->config ) ) {
+ $this->config['headers']['User-Agent'] = $this->config['user-agent'];
+ } else {
+ $this->config['headers']['User-Agent'] = 'Addwiki - mediawiki-api-base';
+ }
+ }
+ unset( $this->config['user-agent'] );
+
+ if ( !array_key_exists( 'handler', $this->config ) ) {
+ $this->config['handler'] = HandlerStack::create( new CurlHandler() );
+ }
+
+ $middlewareFactory = new MiddlewareFactory();
+ $middlewareFactory->setLogger( $this->logger );
+
+ $this->config['middleware'][] = $middlewareFactory->retry();
+
+ foreach ( $this->config['middleware'] as $name => $middleware ) {
+ $this->config['handler']->push( $middleware );
+ }
+ unset( $this->config['middleware'] );
+
+ return new Client( $this->config );
+ }
+
+ /**
+ * Sets a logger instance on the object
+ *
+ * @since 2.1
+ *
+ * @param LoggerInterface $logger The new Logger object.
+ *
+ * @return null
+ */
+ public function setLogger( LoggerInterface $logger ) {
+ $this->logger = $logger;
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/Guzzle/MiddlewareFactory.php b/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/Guzzle/MiddlewareFactory.php
new file mode 100644
index 00000000..9e03c02f
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/Guzzle/MiddlewareFactory.php
@@ -0,0 +1,158 @@
+<?php
+
+namespace Mediawiki\Api\Guzzle;
+
+use GuzzleHttp\Exception\ConnectException;
+use GuzzleHttp\Exception\RequestException;
+use GuzzleHttp\Middleware;
+use GuzzleHttp\Psr7\Request;
+use GuzzleHttp\Psr7\Response;
+use Psr\Log\LoggerAwareInterface;
+use Psr\Log\LoggerInterface;
+use Psr\Log\NullLogger;
+
+/**
+ * @access private
+ *
+ * @author Addshore
+ */
+class MiddlewareFactory implements LoggerAwareInterface {
+
+ /**
+ * @var LoggerInterface
+ */
+ private $logger;
+
+ public function __construct() {
+ $this->logger = new NullLogger();
+ }
+
+ /**
+ * @param LoggerInterface $logger The new Logger object.
+ */
+ public function setLogger( LoggerInterface $logger ) {
+ $this->logger = $logger;
+ }
+
+ /**
+ * @access private
+ *
+ * @param bool $delay default to true, can be false to speed up tests
+ *
+ * @return callable
+ */
+ public function retry( $delay = true ) {
+ if ( $delay ) {
+ return Middleware::retry( $this->newRetryDecider(), $this->getRetryDelay() );
+ } else {
+ return Middleware::retry( $this->newRetryDecider() );
+ }
+ }
+
+ /**
+ * Returns a method that takes the number of retries and returns the number of miliseconds
+ * to wait
+ *
+ * @return callable
+ */
+ private function getRetryDelay() {
+ return function ( $numberOfRetries, Response $response = null ) {
+ // The $response argument is only passed as of Guzzle 6.2.2.
+ if ( $response !== null ) {
+ // Retry-After may be a number of seconds or an absolute date (RFC 7231,
+ // section 7.1.3).
+ $retryAfter = $response->getHeaderLine( 'Retry-After' );
+
+ if ( is_numeric( $retryAfter ) ) {
+ return 1000 * $retryAfter;
+ }
+
+ if ( $retryAfter ) {
+ $seconds = strtotime( $retryAfter ) - time();
+ return 1000 * max( 1, $seconds );
+ }
+ }
+
+ return 1000 * $numberOfRetries;
+ };
+ }
+
+ /**
+ * @return callable
+ */
+ private function newRetryDecider() {
+ return function (
+ $retries,
+ Request $request,
+ Response $response = null,
+ RequestException $exception = null
+ ) {
+ // Don't retry if we have run out of retries
+ if ( $retries >= 5 ) {
+ return false;
+ }
+
+ $shouldRetry = false;
+
+ // Retry connection exceptions
+ if ( $exception instanceof ConnectException ) {
+ $shouldRetry = true;
+ }
+
+ if ( $response ) {
+ $data = json_decode( $response->getBody(), true );
+
+ // Retry on server errors
+ if ( $response->getStatusCode() >= 500 ) {
+ $shouldRetry = true;
+ }
+
+ foreach ( $response->getHeader( 'Mediawiki-Api-Error' ) as $mediawikiApiErrorHeader ) {
+ if (
+ // Retry if the API explicitly tells us to:
+ // https://www.mediawiki.org/wiki/Manual:Maxlag_parameter
+ $response->getHeaderLine( 'Retry-After' )
+ ||
+ // Retry if we have a response with an API error worth retrying
+ in_array(
+ $mediawikiApiErrorHeader,
+ [
+ 'ratelimited',
+ 'maxlag',
+ 'readonly',
+ 'internal_api_error_DBQueryError',
+ ]
+ )
+ ||
+ // Or if we have been stopped from saving as an 'anti-abuse measure'
+ // Note: this tries to match "actionthrottledtext" i18n messagae for mediawiki
+ (
+ $mediawikiApiErrorHeader == 'failed-save' &&
+ strstr( $data['error']['info'], 'anti-abuse measure' )
+ )
+ ) {
+ $shouldRetry = true;
+ }
+
+ }
+ }
+
+ // Log if we are retrying
+ if ( $shouldRetry ) {
+ $this->logger->warning(
+ sprintf(
+ 'Retrying %s %s %s/5, %s',
+ $request->getMethod(),
+ $request->getUri(),
+ $retries + 1,
+ $response ? 'status code: ' . $response->getStatusCode() :
+ $exception->getMessage()
+ )
+ );
+ }
+
+ return $shouldRetry;
+ };
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/MediawikiApi.php b/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/MediawikiApi.php
new file mode 100644
index 00000000..0c6c4fe3
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/MediawikiApi.php
@@ -0,0 +1,507 @@
+<?php
+
+namespace Mediawiki\Api;
+
+use DOMDocument;
+use DOMXPath;
+use GuzzleHttp\Client;
+use GuzzleHttp\ClientInterface;
+use GuzzleHttp\Exception\RequestException;
+use GuzzleHttp\Promise\PromiseInterface;
+use InvalidArgumentException;
+use Mediawiki\Api\Guzzle\ClientFactory;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Log\LoggerAwareInterface;
+use Psr\Log\LoggerInterface;
+use Psr\Log\LogLevel;
+use Psr\Log\NullLogger;
+use SimpleXMLElement;
+
+/**
+ * Main class for this library
+ *
+ * @since 0.1
+ *
+ * @author Addshore
+ */
+class MediawikiApi implements MediawikiApiInterface, LoggerAwareInterface {
+
+ /**
+ * @var ClientInterface|null Should be accessed through getClient
+ */
+ private $client = null;
+
+ /**
+ * @var bool|string
+ */
+ private $isLoggedIn;
+
+ /**
+ * @var MediawikiSession
+ */
+ private $session;
+
+ /**
+ * @var string
+ */
+ private $version;
+
+ /**
+ * @var LoggerInterface
+ */
+ private $logger;
+
+ /**
+ * @var string
+ */
+ private $apiUrl;
+
+ /**
+ * @since 2.0
+ *
+ * @param string $apiEndpoint e.g. https://en.wikipedia.org/w/api.php
+ *
+ * @return self returns a MediawikiApi instance using $apiEndpoint
+ */
+ public static function newFromApiEndpoint( $apiEndpoint ) {
+ return new self( $apiEndpoint );
+ }
+
+ /**
+ * Create a new MediawikiApi object from a URL to any page in a MediaWiki website.
+ *
+ * @since 2.0
+ * @see https://en.wikipedia.org/wiki/Really_Simple_Discovery
+ *
+ * @param string $url e.g. https://en.wikipedia.org OR https://de.wikipedia.org/wiki/Berlin
+ * @return self returns a MediawikiApi instance using the apiEndpoint provided by the RSD
+ * file accessible on all Mediawiki pages
+ * @throws RsdException If the RSD URL could not be found in the page's HTML.
+ */
+ public static function newFromPage( $url ) {
+ // Set up HTTP client and HTML document.
+ $tempClient = new Client( [ 'headers' => [ 'User-Agent' => 'addwiki-mediawiki-client' ] ] );
+ $pageHtml = $tempClient->get( $url )->getBody();
+ $pageDoc = new DOMDocument();
+
+ // Try to load the HTML (turn off errors temporarily; most don't matter, and if they do get
+ // in the way of finding the API URL, will be reported in the RsdException below).
+ $internalErrors = libxml_use_internal_errors( true );
+ $pageDoc->loadHTML( $pageHtml );
+ $libXmlErrors = libxml_get_errors();
+ libxml_use_internal_errors( $internalErrors );
+
+ // Extract the RSD link.
+ $xpath = 'head/link[@type="application/rsd+xml"][@href]';
+ $link = ( new DOMXpath( $pageDoc ) )->query( $xpath );
+ if ( $link->length === 0 ) {
+ // Format libxml errors for display.
+ $libXmlErrorStr = array_reduce( $libXmlErrors, function ( $prevErr, $err ) {
+ return $prevErr . ', ' . $err->message . ' (line '.$err->line . ')';
+ } );
+ if ( $libXmlErrorStr ) {
+ $libXmlErrorStr = "In addition, libxml had the following errors: $libXmlErrorStr";
+ }
+ throw new RsdException( "Unable to find RSD URL in page: $url $libXmlErrorStr" );
+ }
+ $rsdUrl = $link->item( 0 )->attributes->getnamedItem( 'href' )->nodeValue;
+
+ // Then get the RSD XML, and return the API link.
+ $rsdXml = new SimpleXMLElement( $tempClient->get( $rsdUrl )->getBody() );
+ return self::newFromApiEndpoint( (string)$rsdXml->service->apis->api->attributes()->apiLink );
+ }
+
+ /**
+ * @param string $apiUrl The API Url
+ * @param ClientInterface|null $client Guzzle Client
+ * @param MediawikiSession|null $session Inject a custom session here
+ */
+ public function __construct( $apiUrl, ClientInterface $client = null,
+ MediawikiSession $session = null ) {
+ if ( !is_string( $apiUrl ) ) {
+ throw new InvalidArgumentException( '$apiUrl must be a string' );
+ }
+ if ( $session === null ) {
+ $session = new MediawikiSession( $this );
+ }
+
+ $this->apiUrl = $apiUrl;
+ $this->client = $client;
+ $this->session = $session;
+
+ $this->logger = new NullLogger();
+ }
+
+ /**
+ * Get the API URL (the URL to which API requests are sent, usually ending in api.php).
+ * This is useful if you've created this object via MediawikiApi::newFromPage().
+ *
+ * @since 2.3
+ *
+ * @return string The API URL.
+ */
+ public function getApiUrl() {
+ return $this->apiUrl;
+ }
+
+ /**
+ * @return ClientInterface
+ */
+ private function getClient() {
+ if ( $this->client === null ) {
+ $clientFactory = new ClientFactory();
+ $clientFactory->setLogger( $this->logger );
+ $this->client = $clientFactory->getClient();
+ }
+ return $this->client;
+ }
+
+ /**
+ * Sets a logger instance on the object
+ *
+ * @since 1.1
+ *
+ * @param LoggerInterface $logger The new Logger object.
+ *
+ * @return null
+ */
+ public function setLogger( LoggerInterface $logger ) {
+ $this->logger = $logger;
+ $this->session->setLogger( $logger );
+ }
+
+ /**
+ * @since 2.0
+ *
+ * @param Request $request The GET request to send.
+ *
+ * @return PromiseInterface
+ * Normally promising an array, though can be mixed (json_decode result)
+ * Can throw UsageExceptions or RejectionExceptions
+ */
+ public function getRequestAsync( Request $request ) {
+ $promise = $this->getClient()->requestAsync(
+ 'GET',
+ $this->apiUrl,
+ $this->getClientRequestOptions( $request, 'query' )
+ );
+
+ return $promise->then( function ( ResponseInterface $response ) {
+ return call_user_func( [ $this, 'decodeResponse' ], $response );
+ } );
+ }
+
+ /**
+ * @since 2.0
+ *
+ * @param Request $request The POST request to send.
+ *
+ * @return PromiseInterface
+ * Normally promising an array, though can be mixed (json_decode result)
+ * Can throw UsageExceptions or RejectionExceptions
+ */
+ public function postRequestAsync( Request $request ) {
+ $promise = $this->getClient()->requestAsync(
+ 'POST',
+ $this->apiUrl,
+ $this->getClientRequestOptions( $request, $this->getPostRequestEncoding( $request ) )
+ );
+
+ return $promise->then( function ( ResponseInterface $response ) {
+ return call_user_func( [ $this, 'decodeResponse' ], $response );
+ } );
+ }
+
+ /**
+ * @since 0.2
+ *
+ * @param Request $request The GET request to send.
+ *
+ * @return mixed Normally an array
+ */
+ public function getRequest( Request $request ) {
+ $response = $this->getClient()->request(
+ 'GET',
+ $this->apiUrl,
+ $this->getClientRequestOptions( $request, 'query' )
+ );
+
+ return $this->decodeResponse( $response );
+ }
+
+ /**
+ * @since 0.2
+ *
+ * @param Request $request The POST request to send.
+ *
+ * @return mixed Normally an array
+ */
+ public function postRequest( Request $request ) {
+ $response = $this->getClient()->request(
+ 'POST',
+ $this->apiUrl,
+ $this->getClientRequestOptions( $request, $this->getPostRequestEncoding( $request ) )
+ );
+
+ return $this->decodeResponse( $response );
+ }
+
+ /**
+ * @param ResponseInterface $response
+ *
+ * @return mixed
+ * @throws UsageException
+ */
+ private function decodeResponse( ResponseInterface $response ) {
+ $resultArray = json_decode( $response->getBody(), true );
+
+ $this->logWarnings( $resultArray );
+ $this->throwUsageExceptions( $resultArray );
+
+ return $resultArray;
+ }
+
+ /**
+ * @param Request $request
+ *
+ * @return string
+ */
+ private function getPostRequestEncoding( Request $request ) {
+ if ( $request instanceof MultipartRequest ) {
+ return 'multipart';
+ }
+ foreach ( $request->getParams() as $value ) {
+ if ( is_resource( $value ) ) {
+ return 'multipart';
+ }
+ }
+ return 'form_params';
+ }
+
+ /**
+ * @param Request $request
+ * @param string $paramsKey either 'query' or 'multipart'
+ *
+ * @throws RequestException
+ *
+ * @return array as needed by ClientInterface::get and ClientInterface::post
+ */
+ private function getClientRequestOptions( Request $request, $paramsKey ) {
+ $params = array_merge( $request->getParams(), [ 'format' => 'json' ] );
+ if ( $paramsKey === 'multipart' ) {
+ $params = $this->encodeMultipartParams( $request, $params );
+ }
+
+ return [
+ $paramsKey => $params,
+ 'headers' => array_merge( $this->getDefaultHeaders(), $request->getHeaders() ),
+ ];
+ }
+
+ /**
+ * Turn the normal key-value array of request parameters into a multipart array where each
+ * parameter is a new array with a 'name' and 'contents' elements (and optionally more, if the
+ * request is a MultipartRequest).
+ *
+ * @param Request $request The request to which the parameters belong.
+ * @param string[] $params The existing parameters. Not the same as $request->getParams().
+ *
+ * @return array
+ */
+ private function encodeMultipartParams( Request $request, $params ) {
+ // See if there are any multipart parameters in this request.
+ $multipartParams = ( $request instanceof MultipartRequest )
+ ? $request->getMultipartParams()
+ : [];
+ return array_map(
+ function ( $name, $value ) use ( $multipartParams ) {
+ $partParams = [
+ 'name' => $name,
+ 'contents' => $value,
+ ];
+ if ( isset( $multipartParams[ $name ] ) ) {
+ // If extra parameters have been set for this part, use them.
+ $partParams = array_merge( $multipartParams[ $name ], $partParams );
+ }
+ return $partParams;
+ },
+ array_keys( $params ),
+ $params
+ );
+ }
+
+ /**
+ * @return array
+ */
+ private function getDefaultHeaders() {
+ return [
+ 'User-Agent' => $this->getUserAgent(),
+ ];
+ }
+
+ private function getUserAgent() {
+ $loggedIn = $this->isLoggedin();
+ if ( $loggedIn ) {
+ return 'addwiki-mediawiki-client/' . $loggedIn;
+ }
+ return 'addwiki-mediawiki-client';
+ }
+
+ /**
+ * @param $result
+ */
+ private function logWarnings( $result ) {
+ if ( is_array( $result ) && array_key_exists( 'warnings', $result ) ) {
+ foreach ( $result['warnings'] as $module => $warningData ) {
+ // Accomodate both formatversion=2 and old-style API results
+ $logPrefix = $module . ': ';
+ if ( isset( $warningData['*'] ) ) {
+ $this->logger->warning( $logPrefix . $warningData['*'], [ 'data' => $warningData ] );
+ } else {
+ $this->logger->warning( $logPrefix . $warningData['warnings'], [ 'data' => $warningData ] );
+ }
+ }
+ }
+ }
+
+ /**
+ * @param array $result
+ *
+ * @throws UsageException
+ */
+ private function throwUsageExceptions( $result ) {
+ if ( is_array( $result ) && array_key_exists( 'error', $result ) ) {
+ throw new UsageException(
+ $result['error']['code'],
+ $result['error']['info'],
+ $result
+ );
+ }
+ }
+
+ /**
+ * @since 0.1
+ *
+ * @return bool|string false or the name of the current user
+ */
+ public function isLoggedin() {
+ return $this->isLoggedIn;
+ }
+
+ /**
+ * @since 0.1
+ *
+ * @param ApiUser $apiUser The ApiUser to log in as.
+ *
+ * @throws UsageException
+ * @return bool success
+ */
+ public function login( ApiUser $apiUser ) {
+ $this->logger->log( LogLevel::DEBUG, 'Logging in' );
+ $credentials = $this->getLoginParams( $apiUser );
+ $result = $this->postRequest( new SimpleRequest( 'login', $credentials ) );
+ if ( $result['login']['result'] == "NeedToken" ) {
+ $params = array_merge( [ 'lgtoken' => $result['login']['token'] ], $credentials );
+ $result = $this->postRequest( new SimpleRequest( 'login', $params ) );
+ }
+ if ( $result['login']['result'] == "Success" ) {
+ $this->isLoggedIn = $apiUser->getUsername();
+ return true;
+ }
+
+ $this->isLoggedIn = false;
+ $this->logger->log( LogLevel::DEBUG, 'Login failed.', $result );
+ $this->throwLoginUsageException( $result );
+ return false;
+ }
+
+ /**
+ * @param ApiUser $apiUser
+ *
+ * @return string[]
+ */
+ private function getLoginParams( ApiUser $apiUser ) {
+ $params = [
+ 'lgname' => $apiUser->getUsername(),
+ 'lgpassword' => $apiUser->getPassword(),
+ ];
+
+ if ( !is_null( $apiUser->getDomain() ) ) {
+ $params['lgdomain'] = $apiUser->getDomain();
+ }
+ return $params;
+ }
+
+ /**
+ * @param array $result
+ *
+ * @throws UsageException
+ */
+ private function throwLoginUsageException( $result ) {
+ $loginResult = $result['login']['result'];
+
+ throw new UsageException(
+ 'login-' . $loginResult,
+ array_key_exists( 'reason', $result['login'] )
+ ? $result['login']['reason']
+ : 'No Reason given',
+ $result
+ );
+ }
+
+ /**
+ * @since 0.1
+ *
+ * @return bool success
+ */
+ public function logout() {
+ $this->logger->log( LogLevel::DEBUG, 'Logging out' );
+ $result = $this->postRequest( new SimpleRequest( 'logout' ) );
+ if ( $result === [] ) {
+ $this->isLoggedIn = false;
+ $this->clearTokens();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * @since 0.1
+ *
+ * @param string $type The token type to get.
+ *
+ * @return string
+ */
+ public function getToken( $type = 'csrf' ) {
+ return $this->session->getToken( $type );
+ }
+
+ /**
+ * Clear all tokens stored by the API.
+ *
+ * @since 0.1
+ */
+ public function clearTokens() {
+ $this->session->clearTokens();
+ }
+
+ /**
+ * @return string
+ */
+ public function getVersion() {
+ if ( !isset( $this->version ) ) {
+ $result = $this->getRequest( new SimpleRequest( 'query', [
+ 'meta' => 'siteinfo',
+ 'continue' => '',
+ ] ) );
+ preg_match(
+ '/\d+(?:\.\d+)+/',
+ $result['query']['general']['generator'],
+ $versionParts
+ );
+ $this->version = $versionParts[0];
+ }
+ return $this->version;
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/MediawikiApiInterface.php b/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/MediawikiApiInterface.php
new file mode 100644
index 00000000..83580676
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/MediawikiApiInterface.php
@@ -0,0 +1,60 @@
+<?php
+
+namespace Mediawiki\Api;
+
+/**
+ * @since 2.2
+ * @licence GNU GPL v2+
+ * @author Addshore
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+interface MediawikiApiInterface extends ApiRequester, AsyncApiRequester {
+
+ /**
+ * @since 2.2
+ *
+ * @return bool|string false or the name of the current user
+ */
+ public function isLoggedin();
+
+ /**
+ * @since 2.2
+ *
+ * @param ApiUser $apiUser The ApiUser to log in as.
+ *
+ * @throws UsageException
+ * @return bool success
+ */
+ public function login( ApiUser $apiUser );
+
+ /**
+ * @since 2.2
+ *
+ * @return bool success
+ */
+ public function logout();
+
+ /**
+ * @since 2.2
+ *
+ * @param string $type The type of token to get.
+ *
+ * @return string
+ */
+ public function getToken( $type = 'csrf' );
+
+ /**
+ * @since 2.2
+ *
+ * Clears all tokens stored by the api
+ */
+ public function clearTokens();
+
+ /**
+ * @since 2.2
+ *
+ * @return string
+ */
+ public function getVersion();
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/MediawikiSession.php b/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/MediawikiSession.php
new file mode 100644
index 00000000..c430695c
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/MediawikiSession.php
@@ -0,0 +1,168 @@
+<?php
+
+namespace Mediawiki\Api;
+
+use Psr\Log\LoggerAwareInterface;
+use Psr\Log\LoggerInterface;
+use Psr\Log\LogLevel;
+use Psr\Log\NullLogger;
+
+/**
+ * @since 0.1
+ *
+ * @author Addshore
+ */
+class MediawikiSession implements LoggerAwareInterface {
+
+ /**
+ * @var array
+ */
+ private $tokens = [];
+
+ /**
+ * @var MediawikiApi
+ */
+ private $api;
+
+ /**
+ * @var bool if this session is running against mediawiki version pre 1.25
+ */
+ private $usePre125TokensModule = false;
+
+ /**
+ * @var LoggerInterface
+ */
+ private $logger;
+
+ /**
+ * @param MediawikiApi $api The API object to use for this session.
+ */
+ public function __construct( MediawikiApi $api ) {
+ $this->api = $api;
+ $this->logger = new NullLogger();
+ }
+
+ /**
+ * Sets a logger instance on the object
+ *
+ * @since 1.1
+ *
+ * @param LoggerInterface $logger The new Logger object.
+ *
+ * @return null
+ */
+ public function setLogger( LoggerInterface $logger ) {
+ $this->logger = $logger;
+ }
+
+ /**
+ * Tries to get the specified token from the API
+ *
+ * @since 0.1
+ *
+ * @param string $type The type of token to get.
+ *
+ * @return string
+ */
+ public function getToken( $type = 'csrf' ) {
+ // If we don't already have the token that we want
+ if ( !array_key_exists( $type, $this->tokens ) ) {
+ $this->logger->log( LogLevel::DEBUG, 'Getting fresh token', [ 'type' => $type ] );
+
+ // If we know that we don't have the new module mw<1.25
+ if ( $this->usePre125TokensModule ) {
+ return $this->reallyGetPre125Token( $type );
+ } else {
+ return $this->reallyGetToken( $type );
+ }
+
+ }
+
+ return $this->tokens[$type];
+ }
+
+ private function reallyGetPre125Token( $type ) {
+ // Suppress deprecation warning
+ $result = @$this->api->postRequest( // @codingStandardsIgnoreLine
+ new SimpleRequest( 'tokens', [ 'type' => $this->getOldTokenType( $type ) ] )
+ );
+ $this->tokens[$type] = array_pop( $result['tokens'] );
+
+ return $this->tokens[$type];
+ }
+
+ private function reallyGetToken( $type ) {
+ // We suppress errors on this call so the user doesn't get get a warning that isn't their fault.
+ $result = @$this->api->postRequest( // @codingStandardsIgnoreLine
+ new SimpleRequest( 'query', [
+ 'meta' => 'tokens',
+ 'type' => $this->getNewTokenType( $type ),
+ 'continue' => '',
+ ] )
+ );
+ // If mw<1.25 (no new module)
+ $metaWarning = "Unrecognized value for parameter 'meta': tokens";
+ if ( isset( $result['warnings']['query']['*'] )
+ && false !== strpos( $result['warnings']['query']['*'], $metaWarning ) ) {
+ $this->usePre125TokensModule = true;
+ $this->logger->log( LogLevel::DEBUG, 'Falling back to pre 1.25 token system' );
+ $this->tokens[$type] = $this->reallyGetPre125Token( $type );
+ } else {
+ $this->tokens[$type] = array_pop( $result['query']['tokens'] );
+ }
+
+ return $this->tokens[$type];
+ }
+
+ /**
+ * Tries to guess a new token type from an old token type
+ *
+ * @param string $type
+ *
+ * @return string
+ */
+ private function getNewTokenType( $type ) {
+ switch ( $type ) {
+ case 'edit':
+ case 'delete':
+ case 'protect':
+ case 'move':
+ case 'block':
+ case 'unblock':
+ case 'email':
+ case 'import':
+ case 'options':
+ return 'csrf';
+ }
+ // Return the same type, don't know what to do with this..
+ return $type;
+ }
+
+ /**
+ * Tries to guess an old token type from a new token type
+ *
+ * @param $type
+ *
+ * @return string
+ */
+ private function getOldTokenType( $type ) {
+ switch ( $type ) {
+ // Guess that we want an edit token, this may not always work as we might be trying to
+ // use it for something else...
+ case 'csrf':
+ return 'edit';
+ }
+ return $type;
+ }
+
+ /**
+ * Clears all tokens stored by the api
+ *
+ * @since 0.2
+ */
+ public function clearTokens() {
+ $this->logger->log( LogLevel::DEBUG, 'Clearing session tokens', [ 'tokens' => $this->tokens ] );
+ $this->tokens = [];
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/MultipartRequest.php b/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/MultipartRequest.php
new file mode 100644
index 00000000..8d3fbdf4
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/MultipartRequest.php
@@ -0,0 +1,77 @@
+<?php
+
+namespace Mediawiki\Api;
+
+use Exception;
+
+/**
+ * A MultipartRequest is the same as a FluentRequest with additional support for setting request
+ * parameters (both normal parameters and headers) on multipart requests.
+ *
+ * @link http://docs.guzzlephp.org/en/stable/request-options.html#multipart
+ *
+ * @since 2.4.0
+ */
+class MultipartRequest extends FluentRequest {
+
+ /** @var mixed[] */
+ protected $multipartParams = [];
+
+ /**
+ * Check the structure of a multipart parameter array.
+ *
+ * @param mixed[] $params The multipart parameters to check.
+ *
+ * @throws Exception
+ */
+ protected function checkMultipartParams( $params ) {
+ foreach ( $params as $key => $val ) {
+ if ( !is_array( $val ) ) {
+ throw new Exception( "Parameter '$key' must be an array." );
+ }
+ if ( !in_array( $key, array_keys( $this->getParams() ) ) ) {
+ throw new Exception( "Parameter '$key' is not already set on this request." );
+ }
+ }
+ }
+
+ /**
+ * Set all multipart parameters, replacing all existing ones.
+ *
+ * Each key of the array passed in here must be the name of a parameter already set on this
+ * request object.
+ *
+ * @param mixed[] $params The multipart parameters to use.
+ * @return $this
+ */
+ public function setMultipartParams( $params ) {
+ $this->checkMultipartParams( $params );
+ $this->multipartParams = $params;
+ return $this;
+ }
+
+ /**
+ * Add extra multipart parameters.
+ *
+ * Each key of the array passed in here must be the name of a parameter already set on this
+ * request object.
+ *
+ * @param mixed[] $params The multipart parameters to add to any already present.
+ *
+ * @return $this
+ */
+ public function addMultipartParams( $params ) {
+ $this->checkMultipartParams( $params );
+ $this->multipartParams = array_merge( $this->multipartParams, $params );
+ return $this;
+ }
+
+ /**
+ * Get all multipart request parameters.
+ *
+ * @return mixed[]
+ */
+ public function getMultipartParams() {
+ return $this->multipartParams;
+ }
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/Request.php b/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/Request.php
new file mode 100644
index 00000000..0daace2a
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/Request.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Mediawiki\Api;
+
+/**
+ * @since 0.2
+ *
+ * @author Addshore
+ */
+interface Request {
+
+ /**
+ * @since 0.2
+ *
+ * @return array
+ */
+ public function getParams();
+
+ /**
+ * Associative array of headers to add to the request.
+ * Each key is the name of a header, and each value is a string or array of strings representing
+ * the header field values.
+ *
+ * @since 0.3
+ *
+ * @return array
+ */
+ public function getHeaders();
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/RsdException.php b/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/RsdException.php
new file mode 100644
index 00000000..b304f574
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/RsdException.php
@@ -0,0 +1,12 @@
+<?php
+
+namespace Mediawiki\Api;
+
+use Exception;
+
+/**
+ * An exception raised when an issue is encountered with Really Simple Discovery.
+ * @see https://en.wikipedia.org/wiki/Really_Simple_Discovery
+ */
+class RsdException extends Exception {
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/SimpleRequest.php b/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/SimpleRequest.php
new file mode 100644
index 00000000..1e33348d
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/SimpleRequest.php
@@ -0,0 +1,61 @@
+<?php
+
+namespace Mediawiki\Api;
+
+use InvalidArgumentException;
+
+/**
+ * Please consider using a FluentRequest object
+ *
+ * @since 0.2
+ *
+ * @author Addshore
+ */
+class SimpleRequest implements Request {
+
+ /**
+ * @var string
+ */
+ private $action;
+
+ /**
+ * @var array
+ */
+ private $params;
+
+ /**
+ * @var array
+ */
+ private $headers;
+
+ /**
+ * @param string $action The API action.
+ * @param array $params The parameters for the action.
+ * @param array $headers Any extra HTTP headers to send.
+ *
+ * @throws InvalidArgumentException
+ */
+ public function __construct( $action, array $params = [], array $headers = [] ) {
+ if ( !is_string( $action ) ) {
+ throw new InvalidArgumentException( '$action must be string' );
+ }
+ $this->action = $action;
+ $this->params = $params;
+ $this->headers = $headers;
+ }
+
+ /**
+ * @return string[]
+ */
+ public function getParams() {
+ return array_merge( [ 'action' => $this->action ], $this->params );
+ }
+
+ /**
+ * @return string[]
+ */
+ public function getHeaders() {
+ return $this->headers;
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/UsageException.php b/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/UsageException.php
new file mode 100644
index 00000000..77148f1b
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/src/UsageException.php
@@ -0,0 +1,75 @@
+<?php
+
+namespace Mediawiki\Api;
+
+use Exception;
+
+/**
+ * Class representing a Mediawiki Api UsageException
+ *
+ * @since 0.1
+ *
+ * @author Addshore
+ */
+class UsageException extends Exception {
+
+ /**
+ * @var string
+ */
+ private $apiCode;
+
+ /**
+ * @var array
+ */
+ private $result;
+
+ /**
+ * @var string
+ */
+ private $rawMessage;
+
+ /**
+ * @since 0.1
+ *
+ * @param string $apiCode The API error code.
+ * @param string $message The API error message.
+ * @param array $result the result the exception was generated from
+ */
+ public function __construct( $apiCode = '', $message = '', $result = [] ) {
+ $this->apiCode = $apiCode;
+ $this->result = $result;
+ $this->rawMessage = $message;
+ $message = 'Code: ' . $apiCode . PHP_EOL .
+ 'Message: ' . $message . PHP_EOL .
+ 'Result: ' . json_encode( $result );
+ parent::__construct( $message, 0, null );
+ }
+
+ /**
+ * @since 0.1
+ *
+ * @return string
+ */
+ public function getApiCode() {
+ return $this->apiCode;
+ }
+
+ /**
+ * @since 0.3
+ *
+ * @return array
+ */
+ public function getApiResult() {
+ return $this->result;
+ }
+
+ /**
+ * @since 2.3.0
+ *
+ * @return string
+ */
+ public function getRawMessage() {
+ return $this->rawMessage;
+ }
+
+}