summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYaco <franco@reevo.org>2021-10-19 20:42:50 -0300
committerYaco <franco@reevo.org>2021-10-19 20:42:50 -0300
commit1dc109c979d7788e8811b4eecfb8bfdf3b6ea6e2 (patch)
tree21d2a3bd6706af9eeb3e9d1def5a6ab8d8a67e93
parent8c201ace3699b4928daf41eb7b4cdcb4565c6f3b (diff)
adds reevotech scripts
-rwxr-xr-xbin/bkp/bkp_wiki.sh24
-rwxr-xr-xbin/reevotech/CompletaGeoPorDireccion.sh39
-rw-r--r--bin/reevotech/CreateSemanticObject.sh4
-rw-r--r--bin/reevotech/ListarPaginas.php66
-rw-r--r--bin/reevotech/PropiedadActualizar.php128
-rw-r--r--bin/reevotech/PropiedadObtener.php91
-rwxr-xr-xbin/reevotech/PullPages.sh34
-rwxr-xr-xbin/reevotech/PutPages.sh19
-rw-r--r--bin/reevotech/test.php44
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/.gitignore6
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/.phan/config.php40
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/.scrutinizer.yml13
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/.travis.yml61
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/LICENSE.md264
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/README.md16
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/RELEASENOTES.md95
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/build/travis/install-mediawiki.sh29
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/build/travis/run-webserver.sh25
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/composer.json52
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/docs/Makefile225
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/docs/conf.py80
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/docs/index.rst17
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/docs/make.bat281
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/docs/multipart.rst28
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/docs/overview.rst129
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/docs/quickstart.rst87
-rwxr-xr-xbin/reevotech/vendor/addwiki/mediawiki-api-base/phpcs.xml6
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/phpunit.xml.dist16
-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
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Integration/MediawikiApiTest.php103
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Integration/TestEnvironment.php92
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Integration/TokenHandlingTest.php28
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/ApiUserTest.php71
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/FluentRequestTest.php69
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/Guzzle/ClientFactoryTest.php91
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/Guzzle/MiddlewareFactoryTest.php214
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/MediawikiApiTest.php296
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/MediawikiSessionTest.php95
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/MultipartRequestTest.php44
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/SimpleRequestTest.php49
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/UsageExceptionTest.php39
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/.gitignore9
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/.scrutinizer.yml13
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/.travis.yml52
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/LICENSE.md264
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/README.md74
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/RELEASENOTES.md111
-rwxr-xr-xbin/reevotech/vendor/addwiki/mediawiki-api/bin/install-mediawiki.sh55
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/composer.json44
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/docs/Makefile225
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/docs/category_traverser.rst28
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/docs/conf.py80
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/docs/contributing.rst44
-rwxr-xr-xbin/reevotech/vendor/addwiki/mediawiki-api/docs/file_uploader.rst28
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/docs/index.rst25
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/docs/make.bat281
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/docs/namespace_getter.rst54
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/docs/page_list_getter.rst88
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/docs/page_purger.rst34
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/phpcs.xml11
-rwxr-xr-xbin/reevotech/vendor/addwiki/mediawiki-api/phpunit.xml.dist21
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/src/CategoryLoopException.php32
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/src/Generator/AnonymousGenerator.php41
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/src/Generator/ApiGenerator.php27
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/src/Generator/FluentGenerator.php68
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/src/MediawikiFactory.php240
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/CategoryTraverser.php161
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/FileUploader.php139
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/ImageRotator.php56
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/LogListGetter.php83
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/NamespaceGetter.php108
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/PageDeleter.php105
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/PageGetter.php246
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/PageListGetter.php147
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/PageMover.php68
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/PageProtector.php55
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/PagePurger.php116
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/PageRestorer.php76
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/PageWatcher.php37
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/Parser.php47
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/RevisionDeleter.php39
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/RevisionPatroller.php47
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/RevisionRestorer.php39
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/RevisionRollbacker.php73
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/RevisionSaver.php96
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/RevisionUndoer.php48
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/Service.php23
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/UserBlocker.php45
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/UserCreator.php83
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/UserGetter.php63
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/UserRightsChanger.php59
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/tests/fixtures/blue ℳ𝒲♥𝓊𝓃𝒾𝒸ℴ𝒹ℯ.pngbin0 -> 2807 bytes
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/tests/fixtures/namespaces.json241
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/tests/integration/CategoryTraverserTest.php203
-rwxr-xr-xbin/reevotech/vendor/addwiki/mediawiki-api/tests/integration/FileUploaderTest.php75
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/tests/integration/NamespaceGetterTest.php86
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/tests/integration/PageIntegrationTest.php66
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/tests/integration/PageListGetterTest.php99
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/tests/integration/TestEnvironment.php116
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/tests/integration/UserIntegrationTest.php35
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/tests/integration/phpunit.xml.dist18
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/tests/unit/Generator/AnonymousGeneratorTest.php26
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/tests/unit/Generator/FluentGeneratorTest.php55
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/tests/unit/MediawikiFactoryTest.php54
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/tests/unit/Service/PagePurgerTest.php187
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-api/tests/unit/phpunit.xml.dist13
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/.gitignore5
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/.scrutinizer.yml13
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/.travis.yml25
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/LICENSE.md264
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/README.md17
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/RELEASENOTES.md88
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/composer.json32
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/docs/Makefile225
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/docs/conf.py80
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/docs/index.rst22
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/docs/make.bat281
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/phpunit.xml.dist13
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/Content.php83
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/EditInfo.php79
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/File.php37
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/Log.php171
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/LogList.php138
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/NamespaceInfo.php131
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/Page.php63
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/PageIdentifier.php85
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/Pages.php99
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/Redirect.php53
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/Revision.php106
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/Revisions.php102
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/Title.php83
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/User.php140
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/ContentTest.php30
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/EditInfoTest.php51
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/FileTest.php44
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/LogListTest.php25
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/NamespaceInfoTest.php72
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/PageIdentifierTest.php54
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/PageTest.php48
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/PagesTest.php44
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/RedirectTest.php20
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/RevisionTest.php57
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/RevisionsTest.php41
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/TitleTest.php56
-rw-r--r--bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/UserTest.php59
-rw-r--r--bin/reevotech/vendor/autoload.php7
-rw-r--r--bin/reevotech/vendor/composer/ClassLoader.php445
-rw-r--r--bin/reevotech/vendor/composer/LICENSE21
-rw-r--r--bin/reevotech/vendor/composer/autoload_classmap.php9
-rw-r--r--bin/reevotech/vendor/composer/autoload_files.php13
-rw-r--r--bin/reevotech/vendor/composer/autoload_namespaces.php9
-rw-r--r--bin/reevotech/vendor/composer/autoload_psr4.php16
-rw-r--r--bin/reevotech/vendor/composer/autoload_real.php70
-rw-r--r--bin/reevotech/vendor/composer/autoload_static.php75
-rw-r--r--bin/reevotech/vendor/composer/installed.json489
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/CHANGELOG.md1287
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/LICENSE19
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/README.md91
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/UPGRADING.md1203
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/composer.json44
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/Client.php422
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/ClientInterface.php84
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php314
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php84
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php90
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php71
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php403
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.php27
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/Exception/ClientException.php7
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/Exception/ConnectException.php37
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.php13
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php217
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/Exception/SeekException.php27
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/Exception/ServerException.php7
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php4
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/Exception/TransferException.php4
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php565
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php27
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/Handler/CurlHandler.php45
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php199
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/Handler/EasyHandle.php92
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/Handler/MockHandler.php189
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/Handler/Proxy.php55
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php532
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/HandlerStack.php273
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/MessageFormatter.php180
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/Middleware.php255
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/Pool.php123
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php106
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/RedirectMiddleware.php237
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/RequestOptions.php255
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/RetryMiddleware.php112
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/TransferStats.php126
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/UriTemplate.php237
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/functions.php333
-rw-r--r--bin/reevotech/vendor/guzzlehttp/guzzle/src/functions_include.php6
-rw-r--r--bin/reevotech/vendor/guzzlehttp/promises/CHANGELOG.md65
-rw-r--r--bin/reevotech/vendor/guzzlehttp/promises/LICENSE19
-rw-r--r--bin/reevotech/vendor/guzzlehttp/promises/Makefile13
-rw-r--r--bin/reevotech/vendor/guzzlehttp/promises/README.md504
-rw-r--r--bin/reevotech/vendor/guzzlehttp/promises/composer.json34
-rw-r--r--bin/reevotech/vendor/guzzlehttp/promises/src/AggregateException.php16
-rw-r--r--bin/reevotech/vendor/guzzlehttp/promises/src/CancellationException.php9
-rw-r--r--bin/reevotech/vendor/guzzlehttp/promises/src/Coroutine.php151
-rw-r--r--bin/reevotech/vendor/guzzlehttp/promises/src/EachPromise.php229
-rw-r--r--bin/reevotech/vendor/guzzlehttp/promises/src/FulfilledPromise.php82
-rw-r--r--bin/reevotech/vendor/guzzlehttp/promises/src/Promise.php280
-rw-r--r--bin/reevotech/vendor/guzzlehttp/promises/src/PromiseInterface.php93
-rw-r--r--bin/reevotech/vendor/guzzlehttp/promises/src/PromisorInterface.php15
-rw-r--r--bin/reevotech/vendor/guzzlehttp/promises/src/RejectedPromise.php87
-rw-r--r--bin/reevotech/vendor/guzzlehttp/promises/src/RejectionException.php47
-rw-r--r--bin/reevotech/vendor/guzzlehttp/promises/src/TaskQueue.php66
-rw-r--r--bin/reevotech/vendor/guzzlehttp/promises/src/TaskQueueInterface.php25
-rw-r--r--bin/reevotech/vendor/guzzlehttp/promises/src/functions.php457
-rw-r--r--bin/reevotech/vendor/guzzlehttp/promises/src/functions_include.php6
-rw-r--r--bin/reevotech/vendor/guzzlehttp/psr7/.editorconfig9
-rw-r--r--bin/reevotech/vendor/guzzlehttp/psr7/CHANGELOG.md225
-rw-r--r--bin/reevotech/vendor/guzzlehttp/psr7/LICENSE19
-rw-r--r--bin/reevotech/vendor/guzzlehttp/psr7/README.md745
-rw-r--r--bin/reevotech/vendor/guzzlehttp/psr7/composer.json45
-rw-r--r--bin/reevotech/vendor/guzzlehttp/psr7/src/AppendStream.php241
-rw-r--r--bin/reevotech/vendor/guzzlehttp/psr7/src/BufferStream.php137
-rw-r--r--bin/reevotech/vendor/guzzlehttp/psr7/src/CachingStream.php138
-rw-r--r--bin/reevotech/vendor/guzzlehttp/psr7/src/DroppingStream.php42
-rw-r--r--bin/reevotech/vendor/guzzlehttp/psr7/src/FnStream.php158
-rw-r--r--bin/reevotech/vendor/guzzlehttp/psr7/src/InflateStream.php52
-rw-r--r--bin/reevotech/vendor/guzzlehttp/psr7/src/LazyOpenStream.php39
-rw-r--r--bin/reevotech/vendor/guzzlehttp/psr7/src/LimitStream.php155
-rw-r--r--bin/reevotech/vendor/guzzlehttp/psr7/src/MessageTrait.php183
-rw-r--r--bin/reevotech/vendor/guzzlehttp/psr7/src/MultipartStream.php153
-rw-r--r--bin/reevotech/vendor/guzzlehttp/psr7/src/NoSeekStream.php22
-rw-r--r--bin/reevotech/vendor/guzzlehttp/psr7/src/PumpStream.php165
-rw-r--r--bin/reevotech/vendor/guzzlehttp/psr7/src/Request.php142
-rw-r--r--bin/reevotech/vendor/guzzlehttp/psr7/src/Response.php136
-rw-r--r--bin/reevotech/vendor/guzzlehttp/psr7/src/Rfc7230.php18
-rw-r--r--bin/reevotech/vendor/guzzlehttp/psr7/src/ServerRequest.php376
-rw-r--r--bin/reevotech/vendor/guzzlehttp/psr7/src/Stream.php270
-rw-r--r--bin/reevotech/vendor/guzzlehttp/psr7/src/StreamDecoratorTrait.php149
-rw-r--r--bin/reevotech/vendor/guzzlehttp/psr7/src/StreamWrapper.php161
-rw-r--r--bin/reevotech/vendor/guzzlehttp/psr7/src/UploadedFile.php316
-rw-r--r--bin/reevotech/vendor/guzzlehttp/psr7/src/Uri.php738
-rw-r--r--bin/reevotech/vendor/guzzlehttp/psr7/src/UriNormalizer.php216
-rw-r--r--bin/reevotech/vendor/guzzlehttp/psr7/src/UriResolver.php219
-rw-r--r--bin/reevotech/vendor/guzzlehttp/psr7/src/functions.php898
-rw-r--r--bin/reevotech/vendor/guzzlehttp/psr7/src/functions_include.php6
-rw-r--r--bin/reevotech/vendor/psr/http-message/CHANGELOG.md36
-rw-r--r--bin/reevotech/vendor/psr/http-message/LICENSE19
-rw-r--r--bin/reevotech/vendor/psr/http-message/README.md13
-rw-r--r--bin/reevotech/vendor/psr/http-message/composer.json26
-rw-r--r--bin/reevotech/vendor/psr/http-message/src/MessageInterface.php187
-rw-r--r--bin/reevotech/vendor/psr/http-message/src/RequestInterface.php129
-rw-r--r--bin/reevotech/vendor/psr/http-message/src/ResponseInterface.php68
-rw-r--r--bin/reevotech/vendor/psr/http-message/src/ServerRequestInterface.php261
-rw-r--r--bin/reevotech/vendor/psr/http-message/src/StreamInterface.php158
-rw-r--r--bin/reevotech/vendor/psr/http-message/src/UploadedFileInterface.php123
-rw-r--r--bin/reevotech/vendor/psr/http-message/src/UriInterface.php323
-rw-r--r--bin/reevotech/vendor/psr/log/.gitignore1
-rw-r--r--bin/reevotech/vendor/psr/log/LICENSE19
-rw-r--r--bin/reevotech/vendor/psr/log/Psr/Log/AbstractLogger.php128
-rw-r--r--bin/reevotech/vendor/psr/log/Psr/Log/InvalidArgumentException.php7
-rw-r--r--bin/reevotech/vendor/psr/log/Psr/Log/LogLevel.php18
-rw-r--r--bin/reevotech/vendor/psr/log/Psr/Log/LoggerAwareInterface.php18
-rw-r--r--bin/reevotech/vendor/psr/log/Psr/Log/LoggerAwareTrait.php26
-rw-r--r--bin/reevotech/vendor/psr/log/Psr/Log/LoggerInterface.php123
-rw-r--r--bin/reevotech/vendor/psr/log/Psr/Log/LoggerTrait.php140
-rw-r--r--bin/reevotech/vendor/psr/log/Psr/Log/NullLogger.php28
-rw-r--r--bin/reevotech/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php144
-rw-r--r--bin/reevotech/vendor/psr/log/Psr/Log/Test/TestLogger.php146
-rw-r--r--bin/reevotech/vendor/psr/log/README.md52
-rw-r--r--bin/reevotech/vendor/psr/log/composer.json26
-rw-r--r--bin/reevotech/vendor/ralouphie/getallheaders/.gitignore5
-rw-r--r--bin/reevotech/vendor/ralouphie/getallheaders/.travis.yml18
-rw-r--r--bin/reevotech/vendor/ralouphie/getallheaders/LICENSE21
-rw-r--r--bin/reevotech/vendor/ralouphie/getallheaders/README.md19
-rw-r--r--bin/reevotech/vendor/ralouphie/getallheaders/composer.json21
-rw-r--r--bin/reevotech/vendor/ralouphie/getallheaders/phpunit.xml22
-rw-r--r--bin/reevotech/vendor/ralouphie/getallheaders/src/getallheaders.php46
-rw-r--r--bin/reevotech/vendor/ralouphie/getallheaders/tests/GetAllHeadersTest.php121
-rw-r--r--bin/wiki/PropiedadActualizar.php2
-rw-r--r--bin/wiki/PropiedadObtener.php3
-rw-r--r--bin/wiki/initReevoClass.php2
-rw-r--r--bin/wiki/reevoPages/int/Formulario:Audiovisual.mw90
-rw-r--r--bin/wiki/reevoPages/int/Formulario:Experiencia.mw182
-rw-r--r--bin/wiki/reevoPages/int/Formulario:Prensa.mw64
-rw-r--r--bin/wiki/reevoPages/int/MediaWiki:Sidebar.mw15
-rw-r--r--bin/wiki/reevoPages/int/Plantilla:Audiovisual.mw72
-rw-r--r--bin/wiki/reevoPages/int/Plantilla:Experiencia.mw131
-rw-r--r--bin/wiki/reevoPages/int/Plantilla:Prensa-Archivo.mw13
-rw-r--r--bin/wiki/reevoPages/int/Plantilla:Prensa-Vista.mw21
-rw-r--r--bin/wiki/reevoPages/int/Plantilla:Prensa.mw49
-rw-r--r--bin/wiki/reevoPages/int/Plantilla:Sistema-ImportarPerfil.mw8
-rw-r--r--bin/wiki/reevoPages/int/Plantilla:Sistema-ImportarPerfilMsg.mw3
-rw-r--r--bin/wiki/reevoPages/int/Plantilla:Usuario.mw25
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Audiovisual:autoria.mw1
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Audiovisual:duracion.mw1
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Audiovisual:estreno.mw1
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Audiovisual:genero.mw5
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Audiovisual:magnet.mw1
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Audiovisual:pais.mw258
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Audiovisual:poster.mw1
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Audiovisual:sub.mw6
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Audiovisual:titulo.mw1
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Audiovisual:url.mw1
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Audiovisual:urltrailer.mw1
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Audiovisual:web.mw1
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Experiencia:contacto-email.mw1
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Experiencia:contacto-telefono.mw1
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Experiencia:contacto-url.mw1
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Experiencia:descripcion.mw1
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Experiencia:imagen-destacada.mw1
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Experiencia:info-certificacion.mw5
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Experiencia:info-contextosocial.mw8
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Experiencia:info-corrientes.mw1
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Experiencia:info-final.mw1
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Experiencia:info-inicio.mw1
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Experiencia:info-lucro.mw5
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Experiencia:info-nivel.mw9
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Experiencia:info-niveleconomico.mw7
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Experiencia:info-participantes.mw1
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Experiencia:info-tipoeducacion.mw6
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Experiencia:info-virtual.mw6
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Experiencia:lugar-calle.mw1
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Experiencia:lugar-ciudad.mw1
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Experiencia:lugar-pais.mw259
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Experiencia:lugar-provincia.mw1
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Experiencia:lugar.mw1
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Prensa:descripcion.mw1
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Prensa:elggid.mw1
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Prensa:etiquetas.mw1
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Prensa:fecha.mw1
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Prensa:fuente.mw1
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Prensa:idioma.mw6
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Prensa:imagen.mw1
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Prensa:pageid.mw1
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Prensa:pais.mw258
-rw-r--r--bin/wiki/reevoPages/int/Propiedad:Prensa:url.mw1
-rw-r--r--bin/wiki/reevoPages/int/REEVO:Audiovisual.mw1
-rw-r--r--bin/wiki/reevoPages/int/REEVO:Experiencia.mw1
-rw-r--r--bin/wiki/reevoPages/int/REEVO:Prensa.mw1
-rw-r--r--bin/wiki/reevoPages/int/REEVO:Usuario.mw1
353 files changed, 33365 insertions, 1554 deletions
diff --git a/bin/bkp/bkp_wiki.sh b/bin/bkp/bkp_wiki.sh
index c9aef4a4..7591d212 100755
--- a/bin/bkp/bkp_wiki.sh
+++ b/bin/bkp/bkp_wiki.sh
@@ -6,14 +6,26 @@
# EN: This file is part of: reevo-web (http://git.reevo.org/reevo/reevo-web)
# ----
-cd /srv/reevo-2020/bin/bkp/
+cd /srv/reevotech
-RUTA=`cat ../../etc/global_config.php | grep '^$REEVO_PATH' | cut -d '"' -f 2`
-DOMINIO=`cat $RUTA/etc/global_config.php | grep '^$REEVO_URL' | cut -d '"' -f 2`
-USER=`cat $RUTA/etc/global_config.php | grep '^$REEVO_DB_USER' | cut -d '"' -f 2`
-PASSWORD=`cat $RUTA/etc/global_config.php | grep '^$REEVO_DB_PASS' | cut -d '"' -f 2`
+if [ -z $1 ];
+then
+ echo "You must specify the deployment codename"
+ exit
+fi
-DB=`cat $RUTA/etc/global_config.php | grep '^$REEVO_DB_WIKI' | cut -d '"' -f 2`
+DEPLOY=$1
+DEPLOYFILE=`ls ./etc | grep $DEPLOY`
+
+echo $DEPLOY
+read
+cd /srv/reevotech/bin/bkp/
+RUTA=`cat ../../etc/global_config-$DEPLOY.php | grep '^$REEVO_PATH' | cut -d '"' -f 2`
+DOMINIO=`cat $RUTA/etc/global_config-$DEPLOY.php | grep '^$REEVO_URL' | cut -d '"' -f 2`
+USER=`cat $RUTA/etc/global_config-$DEPLOY.php | grep '^$REEVO_DB_USER' | cut -d '"' -f 2`
+PASSWORD=`cat $RUTA/etc/global_config-$DEPLOY.php | grep '^$REEVO_DB_PASS' | cut -d '"' -f 2`
+
+DB=`cat $RUTA/etc/global_config-$DEPLOY.php | grep '^$REEVO_DB_WIKI' | cut -d '"' -f 2`
TIMESTAMP=`date +%Y-%m-%d-%H:%M:%S`
echo ""
diff --git a/bin/reevotech/CompletaGeoPorDireccion.sh b/bin/reevotech/CompletaGeoPorDireccion.sh
new file mode 100755
index 00000000..6950e2dc
--- /dev/null
+++ b/bin/reevotech/CompletaGeoPorDireccion.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+# Este script lo usamos para actualizar los datos de geolocalizcion ubicacion de experiencia a partir de los campos que contienen la dirección postal... Usamos OSM nominatim: `https://nominatim.org/release-docs/develop/api/Search/`
+#
+# Se puede usar como: IFS=$(echo -en "\n\b") && for i in `php ../ListarPaginas.php Plantilla:Experiencia`; do ./CompletaGeoPorDireccion.sh "$i"; done
+DEPLOY="$1"
+EXP="$2"
+DATA=`php PropiedadObtener.php -d="$DEPLOY" -t="$EXP" -p="ecoversity:place-street" -p="ecoversity:place-city" -p="ecoversity:place-state" -p="ecoversity:place-country" > /tmp/x && sed 's/ /+/g' /tmp/x | sed ':a;N;$!ba;s/\n/,/g'`
+echo "https://nominatim.openstreetmap.org/search.php?format=json&addressdetails=1&q=$DATA"
+
+if [ -z "$DATA" ]
+then
+ echo "\$DATA is empty, exiting...."
+ exit
+else
+ echo "\$DATA is NOT empty"
+fi
+
+
+
+curl -s "https://nominatim.openstreetmap.org/search.php?format=json&addressdetails=1&q=$DATA" > /tmp/json
+
+cat /tmp/json | jq '.[0]'
+
+LAT=`cat /tmp/json | jq '.[0] | .lat' | sed 's/"//g'`
+LON=`cat /tmp/json | jq '.[0] | .lon' | sed 's/"//g'`
+
+echo "Lat: $LAT"
+echo "Lon: $LON"
+
+if [ $LAT != "null" ]; then
+ php PropiedadActualizar.php -d="$DEPLOY" -t="$EXP" -f="true" -p="ecoversity:place|$LAT, $LON"
+ sed -i "/$EXP/d" todos.log
+ echo $EXP >> correctos.log
+else
+ echo "I was unable to get a coordinate, logging to revisar.log"
+ sed -i "/$EXP/d" todos.log
+ echo $EXP >> revisar.log
+fi
diff --git a/bin/reevotech/CreateSemanticObject.sh b/bin/reevotech/CreateSemanticObject.sh
new file mode 100644
index 00000000..87dc64a9
--- /dev/null
+++ b/bin/reevotech/CreateSemanticObject.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+echo "This script is used to create a Semantic Object defined in a specific Deployment"
+echo ""
diff --git a/bin/reevotech/ListarPaginas.php b/bin/reevotech/ListarPaginas.php
new file mode 100644
index 00000000..96a4d6ef
--- /dev/null
+++ b/bin/reevotech/ListarPaginas.php
@@ -0,0 +1,66 @@
+<?php
+# ----
+# Copyright (C) 2013-2020 - Reevo Project (http://reevo.org)
+# License: Affero GPL version 3 - http://www.gnu.org/licenses/agpl.html
+# ES: Este script recibe el nombre de una Plantilla o Categoría y lista todas las paginas que lo usan.
+# Se usa con: php ListarPaginas.php "Categoría:Experiencia"
+# ----
+
+
+// error_reporting(0);
+// Load all the stuff
+require_once( __DIR__ . '/vendor/autoload.php' );
+require_once( __DIR__ .'/../../etc/global_config.php' );
+
+// Log in to a wiki
+$api = new \Mediawiki\Api\MediawikiApi( $wgServer .'/api.php' );
+$api->login( new \Mediawiki\Api\ApiUser( $REEVO_WIKI_API_USER, $REEVO_WIKI_API_PASS ) );
+$services = new \Mediawiki\Api\MediawikiFactory( $api );
+
+// Obtengo el nombre del template como parámetro
+if ($argv[1]) {
+
+ $pageListGetter = $services->newPageListGetter();
+ $tipo = explode(':',$argv[1]);
+ switch ($tipo[0]) {
+ case 'Categoria':
+ $examplePages = $pageListGetter->getPageListFromCategoryName( $argv[1] );
+ break;
+ case 'Plantilla':
+ $examplePages = $pageListGetter->getPageListFromPageTransclusions( $argv[1] );
+ break;
+ default:
+ echo "No reconozco el tipo de objeto que estas intentando listar (debe ser Categoría o Plantilla)\n\n";
+ exit();
+ }
+ $array = accessProtected($examplePages,'pages');
+ foreach ( $array as $exPage ) {
+ $pagename = $exPage->getTitle()->getText();
+ echo "$pagename \n";
+ }
+} else {
+ echo "Hay que indicar una plantilla como parametro \n";
+}
+
+function accessProtected($obj, $prop) {
+ $reflection = new ReflectionClass($obj);
+ $property = $reflection->getProperty($prop);
+ $property->setAccessible(true);
+ return $property->getValue($obj);
+}
+
+
+
+
+
+// print_r($examplePages);
+
+// $myArray = json_decode(json_encode($examplePages), true);
+// print_r($examplePages->getPageList());
+
+
+
+
+
+
+?>
diff --git a/bin/reevotech/PropiedadActualizar.php b/bin/reevotech/PropiedadActualizar.php
new file mode 100644
index 00000000..6e0fb829
--- /dev/null
+++ b/bin/reevotech/PropiedadActualizar.php
@@ -0,0 +1,128 @@
+<?php
+# ----
+# Copyright (C) 2013-2020 - Reevo Project (http://reevo.org)
+# License: Affero GPL version 3 - http://www.gnu.org/licenses/agpl.html
+# ES: Este script recibe el nombre de una pagina e intenta agregar o actualizar las propiedades específicadas de las mismas con el valor dado.
+# Algo como: php PropiedadActualizar.php -t=Experiencia:Summerhill -f=true -p="experiencia:descripcion|Algo" -p="experiencia:lugar-pais|AR"
+# ----
+
+$opciones = getopt('d:t:p:f:');
+
+if ($opciones['d']) {
+ $deployment = $opciones['d'];
+} else {
+ echo "Es necesario que definas el nombre del deployment con -d='ecoversities'\n";
+ exit;
+}
+
+// error_reporting(0);
+// Load all the stuff
+require_once( __DIR__ . '/vendor/autoload.php' );
+require_once( __DIR__ .'/../../etc/global_config-'.$deployment.'.php' );
+
+// Log in to a wiki
+$api = new \Mediawiki\Api\MediawikiApi( $wgServer .'/api.php' );
+$api->login( new \Mediawiki\Api\ApiUser( $REEVO_WIKI_API_USER, $REEVO_WIKI_API_PASS ) );
+$services = new \Mediawiki\Api\MediawikiFactory( $api );
+echo "Deployment URL: $wgServer \n";
+
+
+if ($opciones['t']) {
+ if ($opciones['p']) {
+ $title = $opciones['t'];
+ if (is_string($opciones['p'])) {
+ $prop[] = $opciones['p'];
+ } else {
+ $prop = $opciones['p'];
+ }
+ foreach ($prop as $key => $value) {
+ $p = explode('|', $value);
+ $propiedades[$p[0]] = $p[1];
+ }
+ $result = ActualizarPropiedades($title, $propiedades, $opciones, $services);
+ echo "\nSe actualizó correctamente la página $result ($wgServer/$result)\n\n\n";
+ } else {
+ echo "Es necesario que definas al menos una propiedad para agregar o modificar con -p='propiedad|valor'\n";
+ }
+} else {
+ echo "Es necesario que definas el nombe de la pagina a editar con -t='Pagina'\n";
+}
+
+// Obtengo el nombre de la página como parámetro
+
+function ActualizarPropiedades($title, $propiedades, $opciones, $services) {
+
+ $page = $services->newPageGetter()->getFromTitle( $title );
+ $pagecontent = $page->getRevisions()->getLatest();
+ if (!$pagecontent) {
+ echo "\n**** ERROR: No existe una página con el nombre '$title'\n\n\n";
+ exit();
+ } else {
+ echo "\n**** PROCESANDO: '$title' ****\n";
+ }
+
+ $pagecontent = $page->getRevisions()->getLatest()->getContent()->getData();
+
+ $template = preg_grep('/^\{{(.*(?<!}}))$/', explode("\n", $pagecontent));
+ $template_pos = array_key_first($template);
+ $templatefin = preg_grep('/^\}}(.*)$/', explode("\n", $pagecontent));
+ $templatefin_pos = array_key_first($templatefin);
+
+
+ $extracto = preg_grep('/^\|/', explode("\n", $pagecontent));
+ foreach ($extracto as $key => $value) {
+ $data = str_replace('|','',$value);
+ $data_limpia = explode('=', $data, 2);
+ $propiedades_previas[$data_limpia[0]] = $data_limpia[1];
+ }
+
+
+ // Verifico que tengo que hacer
+ if ($opciones['f'] == 'true') {
+ echo "\nVoy a actulizar y/o agregar las siguientes propiedades: \n";
+ $propiedades_actualizables = array_intersect_key($propiedades,$propiedades_previas);
+ print_r($propiedades_actualizables);
+ $propiedades_final = array_replace($propiedades_previas, $propiedades);
+ } else {
+ echo "\nNo se van a reemplazar los valores de propiedades existentes. Agrega '-f=true' para hacerlo. Propiedadedes existentes con sus valores actuales: \n";
+ $propiedades_actualizables = array_intersect_key($propiedades, $propiedades_previas);
+ print_r($propiedades_actualizables);
+
+ echo "\nPropiedades antes no definidas que voy a agregar: \n";
+ $propiedades_nuevas = array_diff_key($propiedades,$propiedades_previas);
+ print_r($propiedades_nuevas);
+ $propiedades_final = array_replace($propiedades_previas, $propiedades_nuevas);
+ }
+
+ // Construyo un array con el formato del template original
+ $propiedades_final_array[] = $template[$template_pos];
+ foreach ($propiedades_final as $key => $value) {
+ $propiedades_final_array[] = '|'.$key.'='.$value;
+ }
+ $propiedades_final_array[] = $templatefin[$templatefin_pos];
+
+ // Hago un array con el contenido de toda la pagina y reemplazo el template viejo por el nuevo
+ $contenido_array = explode("\n", $pagecontent);
+ $templatefin_pos = $templatefin_pos + 1;
+ array_splice($contenido_array, $template_pos, $templatefin_pos,$propiedades_final_array);
+
+ $contenido_final = implode("\n", $contenido_array);
+
+ $newContent = new \Mediawiki\DataModel\Content( $contenido_final );
+ $pagetitle = new \Mediawiki\DataModel\Title( $title );
+ $identifier = new \Mediawiki\DataModel\PageIdentifier( $pagetitle );
+ $revision = new \Mediawiki\DataModel\Revision( $newContent, $identifier );
+ $services->newRevisionSaver()->save( $revision );
+
+ return $title;
+
+}
+
+function accessProtected($obj, $prop) {
+ $reflection = new ReflectionClass($obj);
+ $property = $reflection->getProperty($prop);
+ $property->setAccessible(true);
+ return $property->getValue($obj);
+}
+
+?>
diff --git a/bin/reevotech/PropiedadObtener.php b/bin/reevotech/PropiedadObtener.php
new file mode 100644
index 00000000..938c7d92
--- /dev/null
+++ b/bin/reevotech/PropiedadObtener.php
@@ -0,0 +1,91 @@
+<?php
+# ----
+# Copyright (C) 2013-2020 - Reevo Project (http://reevo.org)
+# License: Affero GPL version 3 - http://www.gnu.org/licenses/agpl.html
+# ES: Este script recibe el nombre de una pagina e intenta obtener el valor las propiedades específicas.
+# Algo como: php PropiedadObtener.php -d="Deployment" -t="Experiencia:Summerhill" -p="experiencia:lugar" -p="experiencia:lugar-pais"
+# ----
+
+$opciones = getopt('d:t:p:f:');
+
+if ($opciones['d']) {
+ $deployment = $opciones['d'];
+} else {
+ echo "Es necesario que definas el nombre del deployment con -d='ecoversities'\n";
+ exit;
+}
+
+// error_reporting(0);
+// Load all the stuff
+require_once( __DIR__ . '/vendor/autoload.php' );
+require_once( __DIR__ .'/../../etc/global_config-'.$deployment.'.php' );
+#echo "Deployment URL: $wgServer \n";
+
+// Log in to a wiki
+$api = new \Mediawiki\Api\MediawikiApi( $wgServer .'/api.php' );
+$api->login( new \Mediawiki\Api\ApiUser( $REEVO_WIKI_API_USER, $REEVO_WIKI_API_PASS ) );
+$services = new \Mediawiki\Api\MediawikiFactory( $api );
+
+
+
+if ($opciones['t']) {
+ if ($opciones['p']) {
+ $title = $opciones['t'];
+ if (is_string($opciones['p'])) {
+ $prop[] = $opciones['p'];
+ } else {
+ $prop = $opciones['p'];
+ }
+ foreach ($prop as $key => $value) {
+ // $p = explode('|', $value);
+ $propiedades[$value] = '';
+ }
+ $result = ObtenerPropiedades($title, $propiedades, $opciones, $services);
+ } else {
+ echo "Es necesario que definas al menos una propiedad para obtener con -p='propiedad|valor'\n";
+ exit;
+ }
+} else {
+ echo "Es necesario que definas el nombe de la pagina a revisar con -t='Pagina'\n";
+ exit;
+}
+
+// Obtengo el nombre de la página como parámetro
+
+function ObtenerPropiedades($title, $propiedades, $opciones, $services) {
+
+ $page = $services->newPageGetter()->getFromTitle( $title );
+ $pagecontent = $page->getRevisions()->getLatest();
+ if (!$pagecontent) {
+ echo "\n**** ERROR: No existe una página con el nombre '$title'\n\n\n";
+ exit();
+ } else {
+ // echo "\n**** PROCESANDO: '$title' ****\n";
+ }
+
+ $pagecontent = $page->getRevisions()->getLatest()->getContent()->getData();
+
+ // armo un array con las propiedades de SMW
+ $extracto = preg_grep('/^\|/', explode("\n", $pagecontent));
+ foreach ($extracto as $key => $value) {
+ $data = str_replace('|','',$value);
+ $data_limpia = explode('=', $data);
+ $propiedades_previas[$data_limpia[0]] = $data_limpia[1];
+ }
+
+ foreach ($propiedades as $key => $value) {
+ if (array_key_exists($key, $propiedades_previas)) {
+ echo "$propiedades_previas[$key]\n";
+ }
+ }
+
+}
+
+function accessProtected($obj, $prop) {
+ $reflection = new ReflectionClass($obj);
+ $property = $reflection->getProperty($prop);
+ $property->setAccessible(true);
+ return $property->getValue($obj);
+}
+
+?>
diff --git a/bin/reevotech/PullPages.sh b/bin/reevotech/PullPages.sh
new file mode 100755
index 00000000..e479e39e
--- /dev/null
+++ b/bin/reevotech/PullPages.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# Use: ./bin/reevotech/PullPages.sh ecoversities Help
+
+if [ $# -eq 0 ]
+ then
+ echo "Missing parameters. Use: ./bin/reevotech/PullPages.sh ecoversities Help"
+ exit
+fi
+
+cd /srv/reevotech
+
+DEPLOY=$1
+DEPLOYFILE=`ls ./etc | grep $DEPLOY`
+NS=$2
+DOMAIN=`cat ./etc/$DEPLOYFILE | grep 'REEVO_URL =' | cut -d'"' -f 2`
+
+# echo $DEPLOY
+# echo $DEPLOYFILE
+# echo $DOMAIN
+
+cd ./www/wiki/deployments/$DEPLOY
+
+if [[ -d pages_tmp/$NS ]]
+then
+ echo ""
+ cd pages_tmp/$NS
+ git pull
+ cd ../../
+else
+ git clone -c remote.origin.namespaces="$NS" mediawiki::http://$DOMAIN pages_tmp/$NS
+fi
+
+cp -rf pages_tmp/$NS pages
+rm -rf pages/$NS/.git
diff --git a/bin/reevotech/PutPages.sh b/bin/reevotech/PutPages.sh
new file mode 100755
index 00000000..831a8616
--- /dev/null
+++ b/bin/reevotech/PutPages.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+# Use: ./bin/reevotech/PutPages.sh ecoversities Property
+
+if [ $# -eq 0 ]
+ then
+ echo "Missing parameters. Use: ./bin/reevotech/PutPages.sh ecoversities Help"
+ exit
+fi
+
+
+cd /srv/reevotech
+
+DEPLOY=$1
+NS=$2
+
+cd /srv/reevotech/www/wiki/maintenance/
+
+
+php importTextFiles.php --conf ../LocalSettings-$DEPLOY.php -s "Updated using PutPages.sh" --overwrite "../deployments/$DEPLOY/pages/$NS/*"
diff --git a/bin/reevotech/test.php b/bin/reevotech/test.php
new file mode 100644
index 00000000..4bb78902
--- /dev/null
+++ b/bin/reevotech/test.php
@@ -0,0 +1,44 @@
+<?php
+
+// Load all the stuff
+require_once( __DIR__ . '/vendor/autoload.php' );
+
+// Log in to a wiki
+$api = new \Mediawiki\Api\MediawikiApi( 'http://source.ecoversities.test/api.php' );
+$api->login( new \Mediawiki\Api\ApiUser( 'Yaco', 'yaco2234' ) );
+$services = new \Mediawiki\Api\MediawikiFactory( $api );
+
+// Get a page
+$page = $services->newPageGetter()->getFromTitle( 'Portada' );
+
+print_r("$page", TRUE);
+//
+// // Edit a page
+// $content = new \Mediawiki\DataModel\Content( 'New Text' );
+// $revision = new \Mediawiki\DataModel\Revision( $content, $page->getPageIdentifier() );
+// $services->newRevisionSaver()->save( $revision );
+//
+// // Move a page
+// $services->newPageMover()->move(
+// $services->newPageGetter()->getFromTitle( 'FooBar' ),
+// new Title( 'FooBar' )
+// );
+//
+// // Delete a page
+// $services->newPageDeleter()->delete(
+// $services->newPageGetter()->getFromTitle( 'DeleteMe!' ),
+// array( 'reason' => 'Reason for Deletion' )
+// );
+//
+// // Create a new page
+// $newContent = new \Mediawiki\DataModel\Content( 'Hello World' );
+// $title = new \Mediawiki\DataModel\Title( 'New Page' );
+// $identifier = new \Mediawiki\DataModel\PageIdentifier( $title );
+// $revision = new \Mediawiki\DataModel\Revision( $newContent, $identifier );
+// $services->newRevisionSaver()->save( $revision );
+//
+// // List all pages in a category
+// $pages = $services->newPageListGetter()->getPageListFromCategoryName( 'Category:Cat name' );
+
+
+?>
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/.gitignore b/bin/reevotech/vendor/addwiki/mediawiki-api-base/.gitignore
new file mode 100644
index 00000000..9c16bff2
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/.gitignore
@@ -0,0 +1,6 @@
+.idea
+vendor
+composer.lock
+test.php
+docs/_build
+phpunit.xml
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/.phan/config.php b/bin/reevotech/vendor/addwiki/mediawiki-api-base/.phan/config.php
new file mode 100644
index 00000000..28c1f4ad
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/.phan/config.php
@@ -0,0 +1,40 @@
+<?php
+
+/**
+ * This configuration will be read and overlaid on top of the
+ * default configuration. Command line arguments will be applied
+ * after this file is read.
+ */
+return [
+
+ /**
+ * A list of directories that should be parsed for class and
+ * method information. After excluding the directories
+ * defined in exclude_analysis_directory_list, the remaining
+ * files will be statically analyzed for errors.
+ *
+ * Thus, both first-party and third-party code being used by
+ * your application should be included in this list.
+ */
+ 'directory_list' => [
+ 'src',
+ 'vendor',
+ ],
+
+ /**
+ * A directory list that defines files that will be excluded
+ * from static analysis, but whose class and method
+ * information should be included.
+ *
+ * Generally, you'll want to include the directories for
+ * third-party code (such as "vendor/") in this list.
+ *
+ * n.b.: If you'd like to parse but not analyze 3rd
+ * party code, directories containing that code
+ * should be added to the `directory_list` as
+ * to `exclude_analysis_directory_list`.
+ */
+ "exclude_analysis_directory_list" => [
+ 'vendor/'
+ ],
+];
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/.scrutinizer.yml b/bin/reevotech/vendor/addwiki/mediawiki-api-base/.scrutinizer.yml
new file mode 100644
index 00000000..ffc976e3
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/.scrutinizer.yml
@@ -0,0 +1,13 @@
+inherit: true
+
+tools:
+ php_code_sniffer: true
+ php_cpd: true
+ php_cs_fixer: true
+ php_loc: true
+ php_mess_detector: true
+ php_pdepend: true
+ php_analyzer: true
+ sensiolabs_security_checker: true
+ external_code_coverage:
+ timeout: 300 \ No newline at end of file
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/.travis.yml b/bin/reevotech/vendor/addwiki/mediawiki-api-base/.travis.yml
new file mode 100644
index 00000000..cb3e7641
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/.travis.yml
@@ -0,0 +1,61 @@
+language: php
+
+php:
+ - hhvm
+ - 5.5
+ - 5.6
+ - 7.0
+ - 7.1
+
+env:
+ - MW=master
+
+matrix:
+ include:
+ - php: 7.1
+ env: MW=REL1_28
+ - php: 7.1
+ env: MW=REL1_27
+ - php: 7.1
+ env: MW=REL1_26
+ - php: 7.1
+ env: MW=REL1_25
+ - php: 7.1
+ env: MW=REL1_24
+ allow_failures:
+ - env: MW=REL1_24
+
+addons:
+ mariadb: '10.0'
+
+before_install:
+ - bash ./build/travis/install-mediawiki.sh
+
+install:
+ - travis_retry composer install
+
+before_script:
+ - bash ./build/travis/run-webserver.sh
+ - export ADDWIKI_MW_API='http://localhost:8080/w/api.php'
+ - export ADDWIKI_MW_USER='CIUser'
+ - export ADDWIKI_MW_PASSWORD='CIPass'
+
+script:
+ - composer lint
+ - composer phpcs
+ - composer phpunit-coverage
+
+after_success:
+ - travis_retry wget https://scrutinizer-ci.com/ocular.phar
+ - php ocular.phar code-coverage:upload --format=php-clover coverage.clover
+
+cache:
+ directories:
+ - $HOME/.composer/cache
+
+notifications:
+ irc:
+ channels:
+ - "chat.freenode.net##add"
+ on_success: change
+ on_failure: always
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/LICENSE.md b/bin/reevotech/vendor/addwiki/mediawiki-api-base/LICENSE.md
new file mode 100644
index 00000000..0671f06a
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/LICENSE.md
@@ -0,0 +1,264 @@
+The GNU General Public License, Version 2, June 1991 (GPLv2)
+============================================================
+
+> Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+> 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+
+Everyone is permitted to copy and distribute verbatim copies of this license
+document, but changing it is not allowed.
+
+
+Preamble
+--------
+
+The licenses for most software are designed to take away your freedom to share
+and change it. By contrast, the GNU General Public License is intended to
+guarantee your freedom to share and change free software--to make sure the
+software is free for all its users. This General Public License applies to most
+of the Free Software Foundation's software and to any other program whose
+authors commit to using it. (Some other Free Software Foundation software is
+covered by the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+When we speak of free software, we are referring to freedom, not price. Our
+General Public Licenses are designed to make sure that you have the freedom to
+distribute copies of free software (and charge for this service if you wish),
+that you receive source code or can get it if you want it, that you can change
+the software or use pieces of it in new free programs; and that you know you can
+do these things.
+
+To protect your rights, we need to make restrictions that forbid anyone to deny
+you these rights or to ask you to surrender the rights. These restrictions
+translate to certain responsibilities for you if you distribute copies of the
+software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis or for a
+fee, you must give the recipients all the rights that you have. You must make
+sure that they, too, receive or can get the source code. And you must show them
+these terms so they know their rights.
+
+We protect your rights with two steps: (1) copyright the software, and (2) offer
+you this license which gives you legal permission to copy, distribute and/or
+modify the software.
+
+Also, for each author's protection and ours, we want to make certain that
+everyone understands that there is no warranty for this free software. If the
+software is modified by someone else and passed on, we want its recipients to
+know that what they have is not the original, so that any problems introduced by
+others will not reflect on the original authors' reputations.
+
+Finally, any free program is threatened constantly by software patents. We wish
+to avoid the danger that redistributors of a free program will individually
+obtain patent licenses, in effect making the program proprietary. To prevent
+this, we have made it clear that any patent must be licensed for everyone's free
+use or not licensed at all.
+
+The precise terms and conditions for copying, distribution and modification
+follow.
+
+
+Terms And Conditions For Copying, Distribution And Modification
+---------------------------------------------------------------
+
+**0.** This License applies to any program or other work which contains a notice
+placed by the copyright holder saying it may be distributed under the terms of
+this General Public License. The "Program", below, refers to any such program or
+work, and a "work based on the Program" means either the Program or any
+derivative work under copyright law: that is to say, a work containing the
+Program or a portion of it, either verbatim or with modifications and/or
+translated into another language. (Hereinafter, translation is included without
+limitation in the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not covered by
+this License; they are outside its scope. The act of running the Program is not
+restricted, and the output from the Program is covered only if its contents
+constitute a work based on the Program (independent of having been made by
+running the Program). Whether that is true depends on what the Program does.
+
+**1.** You may copy and distribute verbatim copies of the Program's source code
+as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this License
+and to the absence of any warranty; and give any other recipients of the Program
+a copy of this License along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and you may at
+your option offer warranty protection in exchange for a fee.
+
+**2.** You may modify your copy or copies of the Program or any portion of it,
+thus forming a work based on the Program, and copy and distribute such
+modifications or work under the terms of Section 1 above, provided that you also
+meet all of these conditions:
+
+* **a)** You must cause the modified files to carry prominent notices stating
+ that you changed the files and the date of any change.
+
+* **b)** You must cause any work that you distribute or publish, that in whole
+ or in part contains or is derived from the Program or any part thereof, to
+ be licensed as a whole at no charge to all third parties under the terms of
+ this License.
+
+* **c)** If the modified program normally reads commands interactively when
+ run, you must cause it, when started running for such interactive use in the
+ most ordinary way, to print or display an announcement including an
+ appropriate copyright notice and a notice that there is no warranty (or
+ else, saying that you provide a warranty) and that users may redistribute
+ the program under these conditions, and telling the user how to view a copy
+ of this License. (Exception: if the Program itself is interactive but does
+ not normally print such an announcement, your work based on the Program is
+ not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If identifiable
+sections of that work are not derived from the Program, and can be reasonably
+considered independent and separate works in themselves, then this License, and
+its terms, do not apply to those sections when you distribute them as separate
+works. But when you distribute the same sections as part of a whole which is a
+work based on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the entire whole,
+and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your
+rights to work written entirely by you; rather, the intent is to exercise the
+right to control the distribution of derivative or collective works based on the
+Program.
+
+In addition, mere aggregation of another work not based on the Program with the
+Program (or with a work based on the Program) on a volume of a storage or
+distribution medium does not bring the other work under the scope of this
+License.
+
+**3.** You may copy and distribute the Program (or a work based on it, under
+Section 2) in object code or executable form under the terms of Sections 1 and 2
+above provided that you also do one of the following:
+
+* **a)** Accompany it with the complete corresponding machine-readable source
+ code, which must be distributed under the terms of Sections 1 and 2 above on
+ a medium customarily used for software interchange; or,
+
+* **b)** Accompany it with a written offer, valid for at least three years, to
+ give any third party, for a charge no more than your cost of physically
+ performing source distribution, a complete machine-readable copy of the
+ corresponding source code, to be distributed under the terms of Sections 1
+ and 2 above on a medium customarily used for software interchange; or,
+
+* **c)** Accompany it with the information you received as to the offer to
+ distribute corresponding source code. (This alternative is allowed only for
+ noncommercial distribution and only if you received the program in object
+ code or executable form with such an offer, in accord with Subsection b
+ above.)
+
+The source code for a work means the preferred form of the work for making
+modifications to it. For an executable work, complete source code means all the
+source code for all modules it contains, plus any associated interface
+definition files, plus the scripts used to control compilation and installation
+of the executable. However, as a special exception, the source code distributed
+need not include anything that is normally distributed (in either source or
+binary form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component itself
+accompanies the executable.
+
+If distribution of executable or object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the source code
+from the same place counts as distribution of the source code, even though third
+parties are not compelled to copy the source along with the object code.
+
+**4.** You may not copy, modify, sublicense, or distribute the Program except as
+expressly provided under this License. Any attempt otherwise to copy, modify,
+sublicense or distribute the Program is void, and will automatically terminate
+your rights under this License. However, parties who have received copies, or
+rights, from you under this License will not have their licenses terminated so
+long as such parties remain in full compliance.
+
+**5.** You are not required to accept this License, since you have not signed
+it. However, nothing else grants you permission to modify or distribute the
+Program or its derivative works. These actions are prohibited by law if you do
+not accept this License. Therefore, by modifying or distributing the Program (or
+any work based on the Program), you indicate your acceptance of this License to
+do so, and all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+**6.** Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program subject to these terms and
+conditions. You may not impose any further restrictions on the recipients'
+exercise of the rights granted herein. You are not responsible for enforcing
+compliance by third parties to this License.
+
+**7.** If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues), conditions
+are imposed on you (whether by court order, agreement or otherwise) that
+contradict the conditions of this License, they do not excuse you from the
+conditions of this License. If you cannot distribute so as to satisfy
+simultaneously your obligations under this License and any other pertinent
+obligations, then as a consequence you may not distribute the Program at all.
+For example, if a patent license would not permit royalty-free redistribution of
+the Program by all those who receive copies directly or indirectly through you,
+then the only way you could satisfy both it and this License would be to refrain
+entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply and the
+section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or
+other property right claims or to contest validity of any such claims; this
+section has the sole purpose of protecting the integrity of the free software
+distribution system, which is implemented by public license practices. Many
+people have made generous contributions to the wide range of software
+distributed through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing to
+distribute software through any other system and a licensee cannot impose that
+choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+**8.** If the distribution and/or use of the Program is restricted in certain
+countries either by patents or by copyrighted interfaces, the original copyright
+holder who places the Program under this License may add an explicit
+geographical distribution limitation excluding those countries, so that
+distribution is permitted only in or among countries not thus excluded. In such
+case, this License incorporates the limitation as if written in the body of this
+License.
+
+**9.** The Free Software Foundation may publish revised and/or new versions of
+the General Public License from time to time. Such new versions will be similar
+in spirit to the present version, but may differ in detail to address new
+problems or concerns.
+
+Each version is given a distinguishing version number. If the Program specifies
+a version number of this License which applies to it and "any later version",
+you have the option of following the terms and conditions either of that version
+or of any later version published by the Free Software Foundation. If the
+Program does not specify a version number of this License, you may choose any
+version ever published by the Free Software Foundation.
+
+**10.** If you wish to incorporate parts of the Program into other free programs
+whose distribution conditions are different, write to the author to ask for
+permission. For software which is copyrighted by the Free Software Foundation,
+write to the Free Software Foundation; we sometimes make exceptions for this.
+Our decision will be guided by the two goals of preserving the free status of
+all derivatives of our free software and of promoting the sharing and reuse of
+software generally.
+
+
+No Warranty
+-----------
+
+**11.** BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
+THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
+STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM
+"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+**12.** IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
+INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
+BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER
+OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/README.md b/bin/reevotech/vendor/addwiki/mediawiki-api-base/README.md
new file mode 100644
index 00000000..ea2a7d4b
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/README.md
@@ -0,0 +1,16 @@
+# mediawiki-api-base
+
+[![Build Status](https://travis-ci.org/addwiki/mediawiki-api-base.svg?branch=master)](https://travis-ci.org/addwiki/mediawiki-api-base)
+[![Code Coverage](https://scrutinizer-ci.com/g/addwiki/mediawiki-api-base/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/addwiki/mediawiki-api-base/?branch=master)
+[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/addwiki/mediawiki-api-base/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/addwiki/mediawiki-api-base/?branch=master)
+[![Dependency Status](https://www.versioneye.com/php/addwiki:mediawiki-api-base/badge?style=flat-square)](https://www.versioneye.com/php/addwiki:mediawiki-api-base)
+
+[![Tested Against](http://php-eye.com/badge/addwiki/mediawiki-api-base/tested.svg)](https://php-eye.com/package/addwiki/mediawiki-api-base)
+
+[![Latest Stable Version](https://poser.pugx.org/addwiki/mediawiki-api-base/version.png)](https://packagist.org/packages/addwiki/mediawiki-api-base)
+[![Download count](https://poser.pugx.org/addwiki/mediawiki-api-base/d/total.png)](https://packagist.org/packages/addwiki/mediawiki-api-base)
+[![Reference Status](https://www.versioneye.com/php/addwiki:mediawiki-api-base/reference_badge.svg?style=flat-square)](https://www.versioneye.com/php/addwiki:mediawiki-api-base/references)
+
+Issue tracker: https://phabricator.wikimedia.org/project/profile/1490/
+
+Documentation: https://addwiki.readthedocs.io \ No newline at end of file
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/RELEASENOTES.md b/bin/reevotech/vendor/addwiki/mediawiki-api-base/RELEASENOTES.md
new file mode 100644
index 00000000..a84b19cc
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/RELEASENOTES.md
@@ -0,0 +1,95 @@
+These are the release notes for the [mediawiki-api-base](README.md) library.
+
+## Version 2.4.0 (2 November 2017)
+* New MultipartRequest class added. PR [#38](https://github.com/addwiki/mediawiki-api-base/pull/38).
+
+## Version 2.3.1 (3 May 2017)
+* Don't fail on libxml errors if the RSD URL can still be found. PR [#35](https://github.com/addwiki/mediawiki-api-base/pull/35), Fixes [T163527](https://phabricator.wikimedia.org/T163527).
+
+## Version 2.3.0 (27 April 2017)
+
+* All guzzle configuration settings can now be overridden in `ClientFactory`. [#27](https://github.com/addwiki/mediawiki-api-base/pull/27)
+* Requests that fail due to maxlag will be automatically retried. [#28](https://github.com/addwiki/mediawiki-api-base/pull/28). Fixes [T143193](https://phabricator.wikimedia.org/T143193).
+* Added `MediawikiApi::getApiUrl`. [#24](https://github.com/addwiki/mediawiki-api-base/pull/24)
+* Debugging infomation now logged when login fails. [#26](https://github.com/addwiki/mediawiki-api-base/pull/26)
+* UsageException messages now include the error code and result the API returned. [#31](https://github.com/addwiki/mediawiki-api-base/pull/31)
+* Both formatversion=2 and old style API results supported [#33](https://github.com/addwiki/mediawiki-api-base/pull/33)
+* Fix [MediawikiApi::newFromPage() fails on non-XML HTML](https://phabricator.wikimedia.org/T163527). [#34](https://github.com/addwiki/mediawiki-api-base/pull/34)
+* Various CI improvements.
+
+## Version 2.2.1 (3 August 2016)
+
+* Cast SimpleXMLElements attributes as string in `MediawikiApi::newFromPage()`
+
+## Version 2.2.0 (18 January 2016)
+
+* Added `MediawikiApiInterface`, now implemented by `MediawikiApi`
+* Added `ApiRequester`, now implemented by `MediawikiApi`
+* Added `AsyncApiRequester`, now implemented by `MediawikiApi`
+* The constructor of `MediawikiApi` was made package public
+
+## Version 2.1.0 (29 December 2015)
+
+* Retry throttled actions that return a failed-save code and anti-abuse message
+* Added delay between retried requests
+* Added and used `Guzzle/ClientFactory`
+
+## Version 2.0.0 (18 December 2015)
+
+* Added `MediawikiApi::newFromApiEndpoint` and `MediawikiApi::newFromPage`
+* MediawikiApi constructor access marked as private (please use static factory methods)
+* Added async methods to MediawikiApi `getRequestAsync` & `postRequestAsync`
+* Requires "guzzlehttp/guzzle": "~6.0" ( From "guzzle/guzzle": "~5.2" )
+* Requires "guzzlehttp/promises": "~1.0"
+
+## Version 1.1.1 (20 July 2016)
+
+* Issue with README fixed
+
+## Version 1.1.0 (5 September 2015)
+
+* Requests that encounter a connection exception are now retried
+* Requests that result in non blocking mediawiki api error codes are now retried (ratelimited, readonly, internal_api_error_DBQueryError)
+* MediawikiApi now implements PSR-3 LoggerAwareInterface
+* MediawikiSession now implements PSR-3 LoggerAwareInterface
+* MediawikiApi no longer raises PHP warnings, instead it logs warnings
+
+## Version 1.0.0 (23 August 2015)
+
+* Added `FluentRequest` object
+* Requires "guzzlehttp/retry-subscriber": "~2.0"
+
+## Version 0.3 (1 June 2015)
+
+* UsageExceptions can now contain the full api result array
+* No longer uses addwiki/guzzle-mediawiki-client
+* Now using "guzzlehttp/guzzle": "~5.0" ( From "guzzle/guzzle": "~3.2" )
+* Added getHeaders method to Request interface
+* ApiUser now accepts a domain
+
+## Version 0.2 (13 January 2015)
+
+### Compatibility changes
+
+* Session objects now use action=query&meta=tokens to get tokens when possible.
+NOTE: [Token names have changed between versions](//www.mediawiki.org/wiki/API:Tokens)
+
+### Deprecations
+
+* MediawikiApi getAction and postAction methods have been deprecated in favour of getRequest and postRequest
+
+### New features
+
+* If warnings are present in API results E_USER_WARNING errors are triggered
+* The Request interface and SimpleRequest class have been added
+* MediawikiApi now has a getRequest and postRequest method
+* MediawikiApi now has a getVersion method
+* Unsuccessful logins now throw a UsageException with extra details
+
+## Version 0.1.2 (25 May 2014)
+
+* Fix issue where API tokens were not returned
+
+## Version 0.1 (12 May 2014)
+
+* Initial release after split from mediawiki-api lib
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/build/travis/install-mediawiki.sh b/bin/reevotech/vendor/addwiki/mediawiki-api-base/build/travis/install-mediawiki.sh
new file mode 100644
index 00000000..59d29ba4
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/build/travis/install-mediawiki.sh
@@ -0,0 +1,29 @@
+#! /bin/bash
+
+set -x
+
+originalDirectory=$(pwd)
+
+if [[ $TRAVIS_PHP_VERSION == *"hhvm"* ]]
+then
+ PHPINI=/etc/hhvm/php.ini
+ echo "hhvm.enable_zend_compat = true" >> $PHPINI
+fi
+
+mkdir ./../web
+cd ./../web
+
+wget https://github.com/wikimedia/mediawiki/archive/$MW.tar.gz
+tar -zxf $MW.tar.gz
+mv mediawiki-$MW w
+ln -s ./w ./wiki
+
+cd w
+
+composer self-update
+composer install
+
+mysql -e 'CREATE DATABASE mediawiki;'
+php maintenance/install.php --dbtype mysql --dbuser root --dbname mediawiki --dbpath $(pwd) --pass CIPass TravisWiki CIUser
+
+cd $originalDirectory
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/build/travis/run-webserver.sh b/bin/reevotech/vendor/addwiki/mediawiki-api-base/build/travis/run-webserver.sh
new file mode 100644
index 00000000..2412031c
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/build/travis/run-webserver.sh
@@ -0,0 +1,25 @@
+#! /bin/bash
+
+set -x
+
+# HHVM doesn't have a built in web server
+# We can't guarantee any single PHP version is always installed on Travis hosts
+# So list the versions and try to pick the latest PHP version
+# Also the web server on 7.1 seems to have issues, so don't use that?
+if [[ $TRAVIS_PHP_VERSION == *"hhvm"* ]] || [[ $TRAVIS_PHP_VERSION == *"7.1"* ]]
+then
+ WEBSERVERPHPVERSION=`phpenv versions | grep -v system | grep -v hhvm | grep -v 7.1 | tail -n 1 | xargs`
+ phpenv global $WEBSERVERPHPVERSION
+ php --version
+fi
+
+# Run a web server for MediaWiki and wait until it is up
+nohup php -S 0.0.0.0:8080 -t ./../web > /dev/null 2>&1 &
+until curl -s localhost:8080; do true; done > /dev/null 2>&1
+
+# Switch back to the actual php version requested for this build if needed
+if [ -v $WEBSERVERPHPVERSION ]
+then
+ phpenv global $TRAVIS_PHP_VERSION
+ php --version
+fi
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/composer.json b/bin/reevotech/vendor/addwiki/mediawiki-api-base/composer.json
new file mode 100644
index 00000000..c83fca09
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/composer.json
@@ -0,0 +1,52 @@
+{
+ "name": "addwiki/mediawiki-api-base",
+ "type": "library",
+ "description": "A basic Mediawiki api base library",
+ "keywords": ["Mediawiki"],
+ "license": "GPL-2.0+",
+ "authors": [
+ { "name": "Addshore" }
+ ],
+ "require": {
+ "php": ">=5.5",
+ "guzzlehttp/guzzle": "~6.0",
+ "guzzlehttp/promises": "~1.0",
+ "psr/log": "~1.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.8.0|~5.3.0",
+ "jakub-onderka/php-parallel-lint": "0.9.2",
+ "mediawiki/mediawiki-codesniffer": "^13.0"
+ },
+ "suggest": {
+ "etsy/phan": "Allows running static analysis on the package (requires PHP 7+)"
+ },
+ "scripts": {
+ "lint": "parallel-lint . --exclude vendor",
+ "phpunit": "phpunit",
+ "phpunit-unit": "phpunit --testsuite unit",
+ "phpunit-integration": "phpunit --testsuite integration",
+ "phpunit-coverage": "phpunit --coverage-clover=coverage.clover",
+ "phpcs": "phpcs -ps",
+ "test": [
+ "@lint",
+ "@phpcs",
+ "@phpunit"
+ ]
+ },
+ "autoload": {
+ "psr-4": {
+ "Mediawiki\\Api\\": "src/"
+ }
+ },
+ "autoload-dev": {
+ "files": [
+ "tests/Integration/TestEnvironment.php"
+ ]
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.4.x-dev"
+ }
+ }
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/docs/Makefile b/bin/reevotech/vendor/addwiki/mediawiki-api-base/docs/Makefile
new file mode 100644
index 00000000..54002b3b
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/docs/Makefile
@@ -0,0 +1,225 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+BUILDDIR = _build
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help
+help:
+ @echo "Please use \`make <target>' where <target> is one of"
+ @echo " html to make standalone HTML files"
+ @echo " dirhtml to make HTML files named index.html in directories"
+ @echo " singlehtml to make a single large HTML file"
+ @echo " pickle to make pickle files"
+ @echo " json to make JSON files"
+ @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " qthelp to make HTML files and a qthelp project"
+ @echo " applehelp to make an Apple Help Book"
+ @echo " devhelp to make HTML files and a Devhelp project"
+ @echo " epub to make an epub"
+ @echo " epub3 to make an epub3"
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+ @echo " latexpdf to make LaTeX files and run them through pdflatex"
+ @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
+ @echo " text to make text files"
+ @echo " man to make manual pages"
+ @echo " texinfo to make Texinfo files"
+ @echo " info to make Texinfo files and run them through makeinfo"
+ @echo " gettext to make PO message catalogs"
+ @echo " changes to make an overview of all changed/added/deprecated items"
+ @echo " xml to make Docutils-native XML files"
+ @echo " pseudoxml to make pseudoxml-XML files for display purposes"
+ @echo " linkcheck to check all external links for integrity"
+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
+ @echo " coverage to run coverage check of the documentation (if enabled)"
+ @echo " dummy to check syntax errors of document sources"
+
+.PHONY: clean
+clean:
+ rm -rf $(BUILDDIR)/*
+
+.PHONY: html
+html:
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+.PHONY: dirhtml
+dirhtml:
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+.PHONY: singlehtml
+singlehtml:
+ $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+ @echo
+ @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+.PHONY: pickle
+pickle:
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+.PHONY: json
+json:
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+.PHONY: htmlhelp
+htmlhelp:
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+.PHONY: qthelp
+qthelp:
+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+ @echo
+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+ ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/mediawiki-api-base.qhcp"
+ @echo "To view the help file:"
+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/mediawiki-api-base.qhc"
+
+.PHONY: applehelp
+applehelp:
+ $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
+ @echo
+ @echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
+ @echo "N.B. You won't be able to view it unless you put it in" \
+ "~/Library/Documentation/Help or install it in your application" \
+ "bundle."
+
+.PHONY: devhelp
+devhelp:
+ $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+ @echo
+ @echo "Build finished."
+ @echo "To view the help file:"
+ @echo "# mkdir -p $$HOME/.local/share/devhelp/mediawiki-api-base"
+ @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/mediawiki-api-base"
+ @echo "# devhelp"
+
+.PHONY: epub
+epub:
+ $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+ @echo
+ @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+.PHONY: epub3
+epub3:
+ $(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3
+ @echo
+ @echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3."
+
+.PHONY: latex
+latex:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+ @echo "Run \`make' in that directory to run these through (pdf)latex" \
+ "(use \`make latexpdf' here to do that automatically)."
+
+.PHONY: latexpdf
+latexpdf:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through pdflatex..."
+ $(MAKE) -C $(BUILDDIR)/latex all-pdf
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+.PHONY: latexpdfja
+latexpdfja:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through platex and dvipdfmx..."
+ $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+.PHONY: text
+text:
+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+ @echo
+ @echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+.PHONY: man
+man:
+ $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+ @echo
+ @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+.PHONY: texinfo
+texinfo:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo
+ @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+ @echo "Run \`make' in that directory to run these through makeinfo" \
+ "(use \`make info' here to do that automatically)."
+
+.PHONY: info
+info:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo "Running Texinfo files through makeinfo..."
+ make -C $(BUILDDIR)/texinfo info
+ @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+.PHONY: gettext
+gettext:
+ $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+ @echo
+ @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+.PHONY: changes
+changes:
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+ @echo
+ @echo "The overview file is in $(BUILDDIR)/changes."
+
+.PHONY: linkcheck
+linkcheck:
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in $(BUILDDIR)/linkcheck/output.txt."
+
+.PHONY: doctest
+doctest:
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+ @echo "Testing of doctests in the sources finished, look at the " \
+ "results in $(BUILDDIR)/doctest/output.txt."
+
+.PHONY: coverage
+coverage:
+ $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
+ @echo "Testing of coverage in the sources finished, look at the " \
+ "results in $(BUILDDIR)/coverage/python.txt."
+
+.PHONY: xml
+xml:
+ $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
+ @echo
+ @echo "Build finished. The XML files are in $(BUILDDIR)/xml."
+
+.PHONY: pseudoxml
+pseudoxml:
+ $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
+ @echo
+ @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
+
+.PHONY: dummy
+dummy:
+ $(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy
+ @echo
+ @echo "Build finished. Dummy builder generates no files."
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/docs/conf.py b/bin/reevotech/vendor/addwiki/mediawiki-api-base/docs/conf.py
new file mode 100644
index 00000000..cb3ce592
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/docs/conf.py
@@ -0,0 +1,80 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#
+# import os
+# import sys
+# sys.path.insert(0, os.path.abspath('.'))
+
+import sys, os
+from sphinx.highlighting import lexers
+from pygments.lexers.web import PhpLexer
+
+lexers['php'] = PhpLexer(startinline=True, linenos=1)
+lexers['php-annotations'] = PhpLexer(startinline=True, linenos=1)
+primary_domain = 'php'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = []
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix(es) of source filenames.
+# You can specify multiple suffix as a list of string:
+#
+# source_suffix = ['.rst', '.md']
+source_suffix = '.rst'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = 'mediawiki-api-base'
+copyright = '2016, addwiki'
+author = 'addwiki'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '2.2'
+# The full version, including alpha/beta/rc tags.
+release = '2.2.1'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#
+# This is also used if you do content translation via gettext catalogs.
+# Usually you set "language" from the command line for these cases.
+language = None
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This patterns also effect to html_static_path and html_extra_path
+exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# If true, `todo` and `todoList` produce output, else they produce nothing.
+todo_include_todos = False
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+#
+html_theme = 'default'
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'mediawiki-api-basedoc'
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/docs/index.rst b/bin/reevotech/vendor/addwiki/mediawiki-api-base/docs/index.rst
new file mode 100644
index 00000000..ac4860ce
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/docs/index.rst
@@ -0,0 +1,17 @@
+Welcome to mediawiki-api-base's documentation!
+==============================================
+
+.. toctree::
+ :maxdepth: 3
+
+ overview
+ quickstart
+ multipart
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/docs/make.bat b/bin/reevotech/vendor/addwiki/mediawiki-api-base/docs/make.bat
new file mode 100644
index 00000000..7ce5e397
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/docs/make.bat
@@ -0,0 +1,281 @@
+@ECHO OFF
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set BUILDDIR=_build
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
+set I18NSPHINXOPTS=%SPHINXOPTS% .
+if NOT "%PAPER%" == "" (
+ set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
+ set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
+)
+
+if "%1" == "" goto help
+
+if "%1" == "help" (
+ :help
+ echo.Please use `make ^<target^>` where ^<target^> is one of
+ echo. html to make standalone HTML files
+ echo. dirhtml to make HTML files named index.html in directories
+ echo. singlehtml to make a single large HTML file
+ echo. pickle to make pickle files
+ echo. json to make JSON files
+ echo. htmlhelp to make HTML files and a HTML help project
+ echo. qthelp to make HTML files and a qthelp project
+ echo. devhelp to make HTML files and a Devhelp project
+ echo. epub to make an epub
+ echo. epub3 to make an epub3
+ echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
+ echo. text to make text files
+ echo. man to make manual pages
+ echo. texinfo to make Texinfo files
+ echo. gettext to make PO message catalogs
+ echo. changes to make an overview over all changed/added/deprecated items
+ echo. xml to make Docutils-native XML files
+ echo. pseudoxml to make pseudoxml-XML files for display purposes
+ echo. linkcheck to check all external links for integrity
+ echo. doctest to run all doctests embedded in the documentation if enabled
+ echo. coverage to run coverage check of the documentation if enabled
+ echo. dummy to check syntax errors of document sources
+ goto end
+)
+
+if "%1" == "clean" (
+ for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
+ del /q /s %BUILDDIR%\*
+ goto end
+)
+
+
+REM Check if sphinx-build is available and fallback to Python version if any
+%SPHINXBUILD% 1>NUL 2>NUL
+if errorlevel 9009 goto sphinx_python
+goto sphinx_ok
+
+:sphinx_python
+
+set SPHINXBUILD=python -m sphinx.__init__
+%SPHINXBUILD% 2> nul
+if errorlevel 9009 (
+ echo.
+ echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+ echo.installed, then set the SPHINXBUILD environment variable to point
+ echo.to the full path of the 'sphinx-build' executable. Alternatively you
+ echo.may add the Sphinx directory to PATH.
+ echo.
+ echo.If you don't have Sphinx installed, grab it from
+ echo.http://sphinx-doc.org/
+ exit /b 1
+)
+
+:sphinx_ok
+
+
+if "%1" == "html" (
+ %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/html.
+ goto end
+)
+
+if "%1" == "dirhtml" (
+ %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
+ goto end
+)
+
+if "%1" == "singlehtml" (
+ %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
+ goto end
+)
+
+if "%1" == "pickle" (
+ %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can process the pickle files.
+ goto end
+)
+
+if "%1" == "json" (
+ %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can process the JSON files.
+ goto end
+)
+
+if "%1" == "htmlhelp" (
+ %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in %BUILDDIR%/htmlhelp.
+ goto end
+)
+
+if "%1" == "qthelp" (
+ %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can run "qcollectiongenerator" with the ^
+.qhcp project file in %BUILDDIR%/qthelp, like this:
+ echo.^> qcollectiongenerator %BUILDDIR%\qthelp\mediawiki-api-base.qhcp
+ echo.To view the help file:
+ echo.^> assistant -collectionFile %BUILDDIR%\qthelp\mediawiki-api-base.ghc
+ goto end
+)
+
+if "%1" == "devhelp" (
+ %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished.
+ goto end
+)
+
+if "%1" == "epub" (
+ %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The epub file is in %BUILDDIR%/epub.
+ goto end
+)
+
+if "%1" == "epub3" (
+ %SPHINXBUILD% -b epub3 %ALLSPHINXOPTS% %BUILDDIR%/epub3
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The epub3 file is in %BUILDDIR%/epub3.
+ goto end
+)
+
+if "%1" == "latex" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "latexpdf" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ cd %BUILDDIR%/latex
+ make all-pdf
+ cd %~dp0
+ echo.
+ echo.Build finished; the PDF files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "latexpdfja" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ cd %BUILDDIR%/latex
+ make all-pdf-ja
+ cd %~dp0
+ echo.
+ echo.Build finished; the PDF files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "text" (
+ %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The text files are in %BUILDDIR%/text.
+ goto end
+)
+
+if "%1" == "man" (
+ %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The manual pages are in %BUILDDIR%/man.
+ goto end
+)
+
+if "%1" == "texinfo" (
+ %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
+ goto end
+)
+
+if "%1" == "gettext" (
+ %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
+ goto end
+)
+
+if "%1" == "changes" (
+ %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.The overview file is in %BUILDDIR%/changes.
+ goto end
+)
+
+if "%1" == "linkcheck" (
+ %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Link check complete; look for any errors in the above output ^
+or in %BUILDDIR%/linkcheck/output.txt.
+ goto end
+)
+
+if "%1" == "doctest" (
+ %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Testing of doctests in the sources finished, look at the ^
+results in %BUILDDIR%/doctest/output.txt.
+ goto end
+)
+
+if "%1" == "coverage" (
+ %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Testing of coverage in the sources finished, look at the ^
+results in %BUILDDIR%/coverage/python.txt.
+ goto end
+)
+
+if "%1" == "xml" (
+ %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The XML files are in %BUILDDIR%/xml.
+ goto end
+)
+
+if "%1" == "pseudoxml" (
+ %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
+ goto end
+)
+
+if "%1" == "dummy" (
+ %SPHINXBUILD% -b dummy %ALLSPHINXOPTS% %BUILDDIR%/dummy
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. Dummy builder generates no files.
+ goto end
+)
+
+:end
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/docs/multipart.rst b/bin/reevotech/vendor/addwiki/mediawiki-api-base/docs/multipart.rst
new file mode 100644
index 00000000..1b438c71
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/docs/multipart.rst
@@ -0,0 +1,28 @@
+==================
+Multipart requests
+==================
+
+The MultipartRequest class can be used if you need a FluentRequest that has more parameters to be set on individual parts of a multipart request.
+
+The name is a slight misnomer, because either of the other two Request classes (SimpleRequest and FluentRequest)
+will also end up being multipart requests if you pass any parameters of type Resource_.
+
+.. _Resource: http://php.net/manual/en/resource.php
+
+To use a MultipartRequest you must first set the main parameters, and then you can add additional "multipart parameters" to any of the parameters you've set.
+(You will get an Exception if you try to set a multipart parameter for a main parameter that doesn't exist yet.)
+
+For example, to add a ``Content-Disposition`` header to a parameter named ``param1``::
+
+ $contentDisposition = 'form-data; name="param1"; filename="a_filename.png"';
+ $request = MultipartRequest::factory()
+ ->setParams( [ 'param1' => 'Lorem ipsum' ] )
+ ->setAction( 'actionname' )
+ ->setMultipartParams( [
+ 'param1' => [
+ 'headers' => [ 'Content-Disposition' => $contentDisposition ],
+ ],
+ ] );
+ $response = $api->postRequest( $request );
+
+(For details of creating the ``$api`` object in this example, see :ref:`quickstart`.)
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/docs/overview.rst b/bin/reevotech/vendor/addwiki/mediawiki-api-base/docs/overview.rst
new file mode 100644
index 00000000..0e83549d
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/docs/overview.rst
@@ -0,0 +1,129 @@
+========
+Overview
+========
+
+addwiki/mediawiki-api-base is a PHP HTTP client wrapped around guzzle that makes it easy to interest with a mediawiki installation.
+
+#. Uses PSR-3 interfaces for logging
+#. Handles Mediawiki login, sessions, cookies and tokens
+#. Handles response errors by throwing catchable UsageExceptions
+#. Retries failed requests where possible
+#. Allows Async requests
+
+Requirements
+========================
+
+#. PHP 5.5.0
+#. Guzzle HTTP library ~6.0
+
+.. _installation:
+
+Installation
+========================
+
+The recommended way to install this library is with
+`Composer <http://getcomposer.org>`_. Composer is a dependency management tool
+for PHP that allows you to declare the dependencies your project needs and
+installs them into your project.
+
+.. code-block:: bash
+
+ # Install Composer
+ curl -sS https://getcomposer.org/installer | php
+
+You can add addwiki/mediawiki-api-base as a dependency using the composer.phar CLI:
+
+.. code-block:: bash
+
+ php composer.phar require addwiki/mediawiki-api-base:~2.0
+
+Alternatively, you can specify addwiki/mediawiki-api-base as a dependency in your project's
+existing composer.json file:
+
+.. code-block:: js
+
+ {
+ "require": {
+ "addwiki/mediawiki-api-base": "~2.0"
+ }
+ }
+
+After installing, you need to require Composer's autoloader:
+
+.. code-block:: php
+
+ require 'vendor/autoload.php';
+
+You can find out more on how to install Composer, configure autoloading, and
+other best-practices for defining dependencies at `getcomposer.org <http://getcomposer.org>`_.
+
+
+Bleeding edge
+--------------------------
+
+During your development, you can keep up with the latest changes on the master
+branch by setting the version requirement for addwiki/mediawiki-api-base to ``~2.0@dev``.
+
+.. code-block:: js
+
+ {
+ "require": {
+ "addwiki/mediawiki-api-base": "~2.0@dev"
+ }
+ }
+
+
+License
+===================
+
+Licensed using the `GPL-2.0+ <https://opensource.org/licenses/GPL-2.0>`_.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+
+Contributing
+========================
+
+Running the tests
+-----------------
+
+In order to contribute, you'll need to checkout the source from GitHub and
+install the dependencies using Composer:
+
+.. code-block:: bash
+
+ git clone https://github.com/addwiki/mediawiki-api-base.git
+ cd mediawiki-api-base
+ curl -s http://getcomposer.org/installer | php
+ ./composer.phar install --dev
+
+The library is tested with a combination of linters and phpunit. Run all of the tests as follows:
+
+.. code-block:: bash
+
+ ./composer.phar test
+
+You can choose to run each part of the whole test suite individually using the following commands:
+
+.. code-block:: bash
+
+ # Run the linting only
+ ./composer.phar lint
+ # Run phpunit only
+ ./composer.phar phpunit
+ # Run only the phpunit unit tests
+ ./composer.phar phpunit-unit
+ # Run only the phpunit integration tests
+ ./composer.phar phpunit-integration \ No newline at end of file
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/docs/quickstart.rst b/bin/reevotech/vendor/addwiki/mediawiki-api-base/docs/quickstart.rst
new file mode 100644
index 00000000..5db0601f
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/docs/quickstart.rst
@@ -0,0 +1,87 @@
+.. _quickstart:
+
+==========
+Quickstart
+==========
+
+This page provides a quick introduction to this library and introductory examples.
+If you have not already installed the library head over to the :ref:`installation`
+page.
+
+Getting an API object
+----------------------------------
+
+You can get an api object by simply passing the api endpoint:
+
+.. code-block:: php
+
+ use \Mediawiki\Api\MediawikiApi;
+
+ $api = MediawikiApi::newFromApiEndpoint( 'https://en.wikipedia.org/w/api.php' );
+
+You can even just pass a page:
+
+.. code-block:: php
+
+ use \Mediawiki\Api\MediawikiApi;
+
+ $api = MediawikiApi::newFromPage( 'https://en.wikipedia.org/wiki/Berlin' );
+
+Logging in and out
+----------------------------------
+
+.. code-block:: php
+
+ use \MediawikiApi\Api\ApiUser;
+
+ $api->login( new ApiUser( 'username', 'password' ) );
+ $api->logout();
+
+Making request objects
+----------------------------------
+
+The library provides two different way of constructing requests.
+
+.. code-block:: php
+
+ use Mediawiki\Api\SimpleRequest;
+ use Mediawiki\Api\FluentRequest;
+
+ $purgeRequest = new SimpleRequest( 'purge', array( 'titles' => 'Berlin' ) );
+ // or
+ $purgeRequest = FluentRequest::factory()->setAction( 'purge' )->setParam( 'titles', 'Berlin' ) );
+
+Sending requests
+----------------------------------
+
+.. code-block:: php
+
+ $api->postRequest( $purgeRequest );
+
+ $queryResponse = $api->getRequest( FluentRequest::factory()->setAction( 'query' )->setParam( 'meta', 'siteinfo' ) );
+
+ try{
+ $api->postRequest( new SimpleRequest( 'FooBarBaz' ) );
+ }
+ catch ( UsageException $e ) {
+ echo "The api returned an error!";
+ }
+
+
+Making async requests
+----------------------------------
+
+.. code-block:: php
+
+ // Initiate each request but do not block
+ $requestPromises = array(
+ 'Page1' => $api->postRequestAsync( FluentRequest::factory()->setAction( 'purge' )->setParam( 'titles', 'Page1' ) ),
+ 'Page2' => $api->postRequestAsync( FluentRequest::factory()->setAction( 'purge' )->setParam( 'titles', 'Page2' ) ),
+ 'Page3' => $api->postRequestAsync( FluentRequest::factory()->setAction( 'purge' )->setParam( 'titles', 'Page3' ) ),
+ );
+
+ // Wait on all of the requests to complete.
+ $results = GuzzleHttp\Promise\unwrap( $requestPromises );
+
+ // You can access each result using the key provided to the unwrap function.
+ print_r( $results['Page1'], $results['Page2'], $results['Page3'] )
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/phpcs.xml b/bin/reevotech/vendor/addwiki/mediawiki-api-base/phpcs.xml
new file mode 100755
index 00000000..c4ca4081
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/phpcs.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<ruleset name="MediaWiki">
+ <rule ref="vendor/mediawiki/mediawiki-codesniffer/MediaWiki"/>
+ <file>.</file>
+ <exclude-pattern>vendor/</exclude-pattern>
+</ruleset>
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/phpunit.xml.dist b/bin/reevotech/vendor/addwiki/mediawiki-api-base/phpunit.xml.dist
new file mode 100644
index 00000000..a5874032
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/phpunit.xml.dist
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit colors="true">
+ <testsuites>
+ <testsuite name="unit">
+ <directory suffix="Test.php">./tests/Unit</directory>
+ </testsuite>
+ <testsuite name="integration">
+ <directory suffix="Test.php">./tests/Integration</directory>
+ </testsuite>
+ </testsuites>
+ <filter>
+ <whitelist addUncoveredFilesFromWhitelist="true">
+ <directory suffix=".php">./src</directory>
+ </whitelist>
+ </filter>
+</phpunit> \ No newline at end of file
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;
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Integration/MediawikiApiTest.php b/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Integration/MediawikiApiTest.php
new file mode 100644
index 00000000..da6683e4
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Integration/MediawikiApiTest.php
@@ -0,0 +1,103 @@
+<?php
+
+namespace Mediawiki\Api\Test\Integration;
+
+use Mediawiki\Api\MediawikiApi;
+use Mediawiki\Api\SimpleRequest;
+
+/**
+ * @author Addshore
+ */
+class MediawikiApiTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @covers Mediawiki\Api\MediawikiApi::newFromPage
+ */
+ public function testNewFromPage() {
+ $api = MediawikiApi::newFromPage( TestEnvironment::newInstance()->getPageUrl() );
+ $this->assertInstanceOf( 'Mediawiki\Api\MediawikiApi', $api );
+ }
+
+ /**
+ * @covers Mediawiki\Api\MediawikiApi::newFromPage
+ * @expectedException Mediawiki\Api\RsdException
+ * @expectedExceptionMessageRegExp |Unable to find RSD URL in page.*|
+ */
+ public function testNewFromPageInvalidHtml() {
+ // This could be any URL that doesn't contain the RSD link, but the README URL
+ // is a test-accessible one that doesn't return 404.
+ $nonWikiPage = str_replace( 'api.php', 'README', TestEnvironment::newInstance()->getApiUrl() );
+ MediawikiApi::newFromPage( $nonWikiPage );
+ }
+
+ /**
+ * Duplicate element IDs break DOMDocument::loadHTML
+ * @see https://phabricator.wikimedia.org/T163527#3219833
+ * @covers Mediawiki\Api\MediawikiApi::newFromPage
+ */
+ public function testNewFromPageWithDuplicateId() {
+ $testPageName = __METHOD__;
+ $testEnv = TestEnvironment::newInstance();
+ $wikiPageUrl = str_replace( 'api.php', "index.php?title=$testPageName", $testEnv->getApiUrl() );
+
+ // Test with no duplicate IDs.
+ $testEnv->savePage( $testPageName, '<p id="unique-id"></p>' );
+ $api1 = MediawikiApi::newFromPage( $wikiPageUrl );
+ $this->assertInstanceOf( MediawikiApi::class, $api1 );
+
+ // Test with duplicate ID.
+ $wikiText = '<p id="duplicated-id"></p><div id="duplicated-id"></div>';
+ $testEnv->savePage( $testPageName, $wikiText );
+ $api2 = MediawikiApi::newFromPage( $wikiPageUrl );
+ $this->assertInstanceOf( MediawikiApi::class, $api2 );
+ }
+
+ /**
+ * @covers Mediawiki\Api\MediawikiApi::getRequest
+ * @covers Mediawiki\Api\MediawikiApi::getClientRequestOptions
+ * @covers Mediawiki\Api\MediawikiApi::decodeResponse
+ * @covers Mediawiki\Api\MediawikiApi::getClient
+ */
+ public function testQueryGetResponse() {
+ $api = TestEnvironment::newInstance()->getApi();
+ $response = $api->getRequest( new SimpleRequest( 'query' ) );
+ $this->assertInternalType( 'array', $response );
+ }
+
+ /**
+ * @covers Mediawiki\Api\MediawikiApi::getRequestAsync
+ * @covers Mediawiki\Api\MediawikiApi::getClientRequestOptions
+ * @covers Mediawiki\Api\MediawikiApi::decodeResponse
+ * @covers Mediawiki\Api\MediawikiApi::getClient
+ */
+ public function testQueryGetResponseAsync() {
+ $api = TestEnvironment::newInstance()->getApi();
+ $response = $api->getRequestAsync( new SimpleRequest( 'query' ) );
+ $this->assertInternalType( 'array', $response->wait() );
+ }
+
+ /**
+ * @covers Mediawiki\Api\MediawikiApi::postRequest
+ * @covers Mediawiki\Api\MediawikiApi::getClientRequestOptions
+ * @covers Mediawiki\Api\MediawikiApi::decodeResponse
+ * @covers Mediawiki\Api\MediawikiApi::getClient
+ */
+ public function testQueryPostResponse() {
+ $api = TestEnvironment::newInstance()->getApi();
+ $response = $api->postRequest( new SimpleRequest( 'query' ) );
+ $this->assertInternalType( 'array', $response );
+ }
+
+ /**
+ * @covers Mediawiki\Api\MediawikiApi::postRequestAsync
+ * @covers Mediawiki\Api\MediawikiApi::getClientRequestOptions
+ * @covers Mediawiki\Api\MediawikiApi::decodeResponse
+ * @covers Mediawiki\Api\MediawikiApi::getClient
+ */
+ public function testQueryPostResponseAsync() {
+ $api = TestEnvironment::newInstance()->getApi();
+ $response = $api->postRequestAsync( new SimpleRequest( 'query' ) );
+ $this->assertInternalType( 'array', $response->wait() );
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Integration/TestEnvironment.php b/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Integration/TestEnvironment.php
new file mode 100644
index 00000000..cb781508
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Integration/TestEnvironment.php
@@ -0,0 +1,92 @@
+<?php
+
+namespace Mediawiki\Api\Test\Integration;
+
+use Exception;
+use Mediawiki\Api\MediawikiApi;
+use Mediawiki\Api\SimpleRequest;
+
+/**
+ * @author Addshore
+ */
+class TestEnvironment {
+
+ /**
+ * Get a new TestEnvironment.
+ * This is identical to calling self::__construct() but is useful for fluent construction.
+ *
+ * @return TestEnvironment
+ */
+ public static function newInstance() {
+ return new self();
+ }
+
+ /** @var MediawikiApi */
+ private $api;
+
+ /** @var string */
+ private $apiUrl;
+
+ /** @var string */
+ private $pageUrl;
+
+ /**
+ * Set up the test environment by creating a new API object pointing to a
+ * MediaWiki installation on localhost (or elsewhere as specified by the
+ * ADDWIKI_MW_API environment variable).
+ *
+ * @throws Exception If the ADDWIKI_MW_API environment variable does not end in 'api.php'
+ */
+ public function __construct() {
+ $apiUrl = getenv( 'ADDWIKI_MW_API' );
+
+ if ( substr( $apiUrl, -7 ) !== 'api.php' ) {
+ $msg = "URL incorrect: $apiUrl"
+ ." (Set the ADDWIKI_MW_API environment variable correctly)";
+ throw new Exception( $msg );
+ }
+
+ $this->apiUrl = $apiUrl;
+ $this->pageUrl = str_replace( 'api.php', 'index.php?title=Special:SpecialPages', $apiUrl );
+ $this->api = MediawikiApi::newFromApiEndpoint( $this->apiUrl );
+ }
+
+ /**
+ * Get the url of the api to test against, based on the MEDIAWIKI_API_URL environment variable.
+ * @return string
+ */
+ public function getApiUrl() {
+ return $this->apiUrl;
+ }
+
+ /**
+ * Get the url of a page on the wiki to test against, based on the api url.
+ * @return string
+ */
+ public function getPageUrl() {
+ return $this->pageUrl;
+ }
+
+ /**
+ * Get the MediawikiApi to test against
+ * @return MediawikiApi
+ */
+ public function getApi() {
+ return $this->api;
+ }
+
+ /**
+ * Save a wiki page.
+ * @param string $title The title of the page.
+ * @param string $content The complete page text to save.
+ */
+ public function savePage( $title, $content ) {
+ $params = [
+ 'title' => $title,
+ 'text' => $content,
+ 'md5' => md5( $content ),
+ 'token' => $this->api->getToken(),
+ ];
+ $this->api->postRequest( new SimpleRequest( 'edit', $params ) );
+ }
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Integration/TokenHandlingTest.php b/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Integration/TokenHandlingTest.php
new file mode 100644
index 00000000..68ec52be
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Integration/TokenHandlingTest.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace Mediawiki\Api\Test\Integration;
+
+/**
+ * @author Addshore
+ */
+class TokenHandlingTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider provideTokenTypes
+ *
+ * @covers Mediawiki\Api\MediawikiApi::getToken
+ * @covers Mediawiki\Api\MediawikiSession::getToken
+ */
+ public function testGetAnonUserToken() {
+ $api = TestEnvironment::newInstance()->getApi();
+ $this->assertEquals( '+\\', $api->getToken() );
+ }
+
+ public function provideTokenTypes() {
+ return [
+ [ 'csrf' ],
+ [ 'edit' ],
+ ];
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/ApiUserTest.php b/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/ApiUserTest.php
new file mode 100644
index 00000000..7e0da7ca
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/ApiUserTest.php
@@ -0,0 +1,71 @@
+<?php
+
+namespace Mediawiki\Api\Test\Unit;
+
+use Mediawiki\Api\ApiUser;
+
+/**
+ * @author Addshore
+ *
+ * @covers Mediawiki\Api\ApiUser
+ */
+class ApiUserTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider provideValidConstruction
+ */
+ public function testValidConstruction( $user, $pass, $domain = null ) {
+ $apiUser = new ApiUser( $user, $pass, $domain );
+ $this->assertSame( $user, $apiUser->getUsername() );
+ $this->assertSame( $pass, $apiUser->getPassword() );
+ $this->assertSame( $domain, $apiUser->getDomain() );
+ }
+
+ public function provideValidConstruction() {
+ return [
+ [ 'user', 'pass' ],
+ [ 'user', 'pass', 'domain' ],
+ ];
+ }
+
+ /**
+ * @dataProvider provideInvalidConstruction
+ */
+ public function testInvalidConstruction( $user, $pass, $domain = null ) {
+ $this->setExpectedException( 'InvalidArgumentException' );
+ new ApiUser( $user, $pass, $domain );
+ }
+
+ public function provideInvalidConstruction() {
+ return [
+ [ 'user', '' ],
+ [ '', 'pass' ],
+ [ '', '' ],
+ [ 'user', [] ],
+ [ 'user', 455667 ],
+ [ 34567, 'pass' ],
+ [ [], 'pass' ],
+ [ 'user', 'pass', [] ],
+ ];
+ }
+
+ /**
+ * @dataProvider provideTestEquals
+ */
+ public function testEquals( ApiUser $user1, ApiUser $user2, $shouldEqual ) {
+ $this->assertSame( $shouldEqual, $user1->equals( $user2 ) );
+ $this->assertSame( $shouldEqual, $user2->equals( $user1 ) );
+ }
+
+ public function provideTestEquals() {
+ return [
+ [ new ApiUser( 'usera', 'passa' ), new ApiUser( 'usera', 'passa' ), true ],
+ [ new ApiUser( 'usera', 'passa', 'domain' ), new ApiUser( 'usera', 'passa', 'domain' ), true ],
+ [ new ApiUser( 'DIFF', 'passa' ), new ApiUser( 'usera', 'passa' ), false ],
+ [ new ApiUser( 'usera', 'DIFF' ), new ApiUser( 'usera', 'passa' ), false ],
+ [ new ApiUser( 'usera', 'passa' ), new ApiUser( 'DIFF', 'passa' ), false ],
+ [ new ApiUser( 'usera', 'passa' ), new ApiUser( 'usera', 'DIFF' ), false ],
+ ];
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/FluentRequestTest.php b/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/FluentRequestTest.php
new file mode 100644
index 00000000..93af921e
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/FluentRequestTest.php
@@ -0,0 +1,69 @@
+<?php
+
+namespace Mediawiki\Api\Test\Unit;
+
+use Mediawiki\Api\FluentRequest;
+use PHPUnit_Framework_TestCase;
+
+/**
+ * @author Addshore
+ *
+ * @covers Mediawiki\Api\FluentRequest
+ */
+class FluentRequestTest extends PHPUnit_Framework_TestCase {
+
+ public function testFactory() {
+ $this->assertInstanceOf( 'Mediawiki\Api\FluentRequest', FluentRequest::factory() );
+ }
+
+ public function testConstructionDefaults() {
+ $request = new FluentRequest();
+
+ $this->assertEquals( [], $request->getParams() );
+ $this->assertEquals( [], $request->getHeaders() );
+ }
+
+ public function testSetParams() {
+ $request = new FluentRequest();
+
+ $params = [ 'foo', 'bar' ];
+ $request->setParams( $params );
+
+ $this->assertEquals( $params, $request->getParams() );
+ }
+
+ public function testSetParam() {
+ $request = new FluentRequest();
+
+ $request->setParam( 'paramName', 'fooValue' );
+
+ $this->assertEquals( [ 'paramName' => 'fooValue' ], $request->getParams() );
+ }
+
+ public function testAddParams() {
+ $request = new FluentRequest();
+
+ $params = [ 'a' => 'foo', 'b' => 'bar' ];
+ $request->addParams( $params );
+
+ $this->assertEquals( $params, $request->getParams() );
+ }
+
+ public function testSetHeaders() {
+ $request = new FluentRequest();
+
+ $params = [ 'foo', 'bar' ];
+ $request->setHeaders( $params );
+
+ $this->assertEquals( $params, $request->getHeaders() );
+ }
+
+ public function testSetAction() {
+ $request = new FluentRequest();
+
+ $request->setAction( 'fooAction' );
+
+ $this->assertEquals( [ 'action' => 'fooAction' ], $request->getParams() );
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/Guzzle/ClientFactoryTest.php b/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/Guzzle/ClientFactoryTest.php
new file mode 100644
index 00000000..d84d0333
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/Guzzle/ClientFactoryTest.php
@@ -0,0 +1,91 @@
+<?php
+
+namespace Mediawiki\Api\Test\Unit\Guzzle;
+
+use GuzzleHttp\HandlerStack;
+use Mediawiki\Api\Guzzle\ClientFactory;
+use Psr\Http\Message\RequestInterface;
+
+/**
+ * @author Christian Schmidt
+ *
+ * @covers Mediawiki\Api\Guzzle\ClientFactory
+ */
+class ClientFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ public function testNoConfig() {
+ $clientFactory = new ClientFactory();
+
+ $client = $clientFactory->getClient();
+
+ $this->assertSame( $client, $clientFactory->getClient() );
+
+ $config = $client->getConfig();
+ $this->assertEquals( $config['headers']['User-Agent'], 'Addwiki - mediawiki-api-base' );
+
+ $this->assertFalse( empty( $config['cookies'] ) );
+ }
+
+ public function testUserAgent() {
+ $clientFactory = new ClientFactory( [ 'user-agent' => 'Foobar' ] );
+
+ $client = $clientFactory->getClient();
+
+ $this->assertNull( $client->getConfig( 'user-agent' ) );
+
+ $config = $client->getConfig();
+ $this->assertEquals( $config['headers']['User-Agent'], 'Foobar' );
+ }
+
+ public function testHeaders() {
+ $clientFactory = new ClientFactory( [
+ 'headers' => [
+ 'User-Agent' => 'Foobar',
+ 'X-Foo' => 'Bar',
+ ]
+ ] );
+
+ $client = $clientFactory->getClient();
+
+ $headers = $client->getConfig( 'headers' );
+ $this->assertCount( 2, $headers );
+ $this->assertEquals( $headers['User-Agent'], 'Foobar' );
+ $this->assertEquals( $headers['X-Foo'], 'Bar' );
+ }
+
+ public function testHandler() {
+ $handler = HandlerStack::create();
+
+ $clientFactory = new ClientFactory( [ 'handler' => $handler ] );
+
+ $client = $clientFactory->getClient();
+
+ $this->assertSame( $handler, $client->getConfig( 'handler' ) );
+ }
+
+ public function testMiddleware() {
+ $invoked = false;
+ $middleware = function () use ( &$invoked ) {
+ return function () use ( &$invoked ) {
+ $invoked = true;
+ };
+ };
+
+ $clientFactory = new ClientFactory( [ 'middleware' => [ $middleware ] ] );
+
+ $client = $clientFactory->getClient();
+
+ $this->assertNull( $client->getConfig( 'middleware' ) );
+
+ $request = $this->getMockBuilder( RequestInterface::class )->getMock();
+
+ $handler = $client->getConfig( 'handler' );
+ $handler->remove( 'http_errors' );
+ $handler->remove( 'allow_redirects' );
+ $handler->remove( 'cookies' );
+ $handler->remove( 'prepare_body' );
+ $handler( $request, [] );
+
+ $this->assertTrue( $invoked );
+ }
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/Guzzle/MiddlewareFactoryTest.php b/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/Guzzle/MiddlewareFactoryTest.php
new file mode 100644
index 00000000..1cf7270a
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/Guzzle/MiddlewareFactoryTest.php
@@ -0,0 +1,214 @@
+<?php
+
+namespace Mediawiki\Api\Test\Unit\Guzzle;
+
+use GuzzleHttp\Client;
+use GuzzleHttp\Exception\ConnectException;
+use GuzzleHttp\Handler\MockHandler;
+use GuzzleHttp\HandlerStack;
+use GuzzleHttp\Psr7\Request;
+use GuzzleHttp\Psr7\Response;
+use Mediawiki\Api\Guzzle\MiddlewareFactory;
+
+/**
+ * @author Addshore
+ *
+ * @todo test interaction with logger
+ *
+ * @covers Mediawiki\Api\Guzzle\MiddlewareFactory
+ */
+class MiddlewareFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ public function testRetriesConnectException() {
+ $queue = [
+ new ConnectException( 'Error 1', new Request( 'GET', 'test' ) ),
+ new Response( 200, [ 'X-Foo' => 'Bar' ] ),
+ ];
+
+ $client = $this->getClient( $queue, $delays );
+ $response = $client->request( 'GET', '/' );
+
+ $this->assertEquals( 200, $response->getStatusCode() );
+ $this->assertEquals( [ 1000 ], $delays );
+ }
+
+ public function testRetries500Errors() {
+ $queue = [
+ new Response( 500 ),
+ new Response( 200 ),
+ ];
+
+ $client = $this->getClient( $queue, $delays );
+ $response = $client->request( 'GET', '/' );
+
+ $this->assertEquals( 200, $response->getStatusCode() );
+ $this->assertEquals( [ 1000 ], $delays );
+ }
+
+ public function testRetriesSomeMediawikiApiErrorHeaders() {
+ $queue = [
+ new Response( 200, [ 'mediawiki-api-error' => 'ratelimited' ] ),
+ new Response( 200, [ 'mediawiki-api-error' => 'maxlag' ] ),
+ new Response( 200, [ 'mediawiki-api-error' => 'readonly' ] ),
+ new Response( 200, [ 'mediawiki-api-error' => 'internal_api_error_DBQueryError' ] ),
+ new Response( 200, [ 'mediawiki-api-error' => 'DoNotRetryThisHeader' ] ),
+ ];
+
+ $client = $this->getClient( $queue, $delays );
+ $response = $client->request( 'GET', '/' );
+
+ $this->assertEquals( 200, $response->getStatusCode() );
+ $this->assertEquals(
+ [ 'DoNotRetryThisHeader' ],
+ $response->getHeader( 'mediawiki-api-error' )
+ );
+ $this->assertEquals( [ 1000, 2000, 3000, 4000 ], $delays );
+ }
+
+ public function testRetryAntiAbuseMeasure() {
+ $antiAbusejson = json_encode(
+ [
+ 'error' => [
+ 'info' => 'anti-abuse measure'
+ ]
+ ]
+ );
+
+ $queue = [
+ new Response( 200, [ 'mediawiki-api-error' => 'failed-save' ], $antiAbusejson ),
+ new Response( 200, [ 'mediawiki-api-error' => 'DoNotRetryThisHeader' ] ),
+ ];
+
+ $client = $this->getClient( $queue, $delays );
+ $response = $client->request( 'GET', '/' );
+
+ $this->assertEquals( 200, $response->getStatusCode() );
+ $this->assertEquals( 'DoNotRetryThisHeader', $response->getHeaderLine( 'mediawiki-api-error' ) );
+ }
+
+ public function testRetryLimit() {
+ $queue = [
+ new ConnectException( 'Error 1', new Request( 'GET', 'test' ) ),
+ new ConnectException( 'Error 2', new Request( 'GET', 'test' ) ),
+ new ConnectException( 'Error 3', new Request( 'GET', 'test' ) ),
+ new ConnectException( 'Error 4', new Request( 'GET', 'test' ) ),
+ new ConnectException( 'Error 5', new Request( 'GET', 'test' ) ),
+ new ConnectException( 'Error 6', new Request( 'GET', 'test' ) ),
+ new Response( 200 ),
+ ];
+
+ $client = $this->getClient( $queue );
+
+ $this->setExpectedException(
+ 'GuzzleHttp\Exception\ConnectException',
+ 'Error 6'
+ );
+
+ $client->request( 'GET', '/' );
+ }
+
+ public function testConnectExceptionRetryDelay() {
+ $queue = [
+ new ConnectException( '+1 second delay', new Request( 'GET', 'test' ) ),
+ new ConnectException( '+2 second delay', new Request( 'GET', 'test' ) ),
+ new Response( 200 ),
+ ];
+
+ $client = $this->getClient( $queue, $delays );
+ $response = $client->request( 'GET', '/' );
+
+ $this->assertEquals( 200, $response->getStatusCode() );
+ $this->assertEquals( [ 1000, 2000 ], $delays );
+ }
+
+ public function testServerErrorRetryDelay() {
+ $queue = [
+ new Response( 500 ),
+ new Response( 503 ),
+ new Response( 200 ),
+ ];
+
+ $client = $this->getClient( $queue, $delays );
+ $response = $client->request( 'GET', '/' );
+
+ $this->assertEquals( 200, $response->getStatusCode() );
+ $this->assertEquals( [ 1000, 2000 ], $delays );
+ }
+
+ public function testRelativeRetryDelayHeaderRetryDelay() {
+ $queue = [
+ new Response( 200, [ 'mediawiki-api-error' => 'maxlag', 'retry-after' => 10 ] ),
+ new Response( 200 ),
+ ];
+
+ $this->getClient( $queue, $delays )->request( 'GET', '/' );
+
+ $this->assertEquals( [ 10000 ], $delays );
+ }
+
+ public function testAbsoluteRetryDelayHeaderRetryDelay() {
+ $queue = [
+ new Response(
+ 200,
+ [
+ 'mediawiki-api-error' => 'maxlag',
+ 'retry-after' => gmdate( DATE_RFC1123, time() + 600 ),
+ ]
+ ),
+ new Response( 200 ),
+ ];
+
+ $client = $this->getClient( $queue, $delays );
+ $response = $client->request( 'GET', '/' );
+
+ $this->assertEquals( 200, $response->getStatusCode() );
+ $this->assertCount( 1, $delays );
+ // Allow 5 second delay while running this test.
+ $this->assertGreaterThan( 600000 - 5000, $delays[0] );
+ }
+
+ public function testPastRetryDelayHeaderRetryDelay() {
+ $queue = [
+ new Response(
+ 200,
+ [
+ 'mediawiki-api-error' => 'maxlag',
+ 'retry-after' => 'Fri, 31 Dec 1999 23:59:59 GMT',
+ ]
+ ),
+ new Response( 200 ),
+ ];
+
+ $client = $this->getClient( $queue, $delays );
+ $response = $client->request( 'GET', '/' );
+
+ $this->assertEquals( 200, $response->getStatusCode() );
+ $this->assertEquals( [ 1000 ], $delays );
+ }
+
+ private function getClient( array $queue, &$delays = null ) {
+ $mock = new MockHandler( $queue );
+
+ $handler = HandlerStack::create( $mock );
+
+ $middlewareFactory = new MiddlewareFactory();
+ $handler->push( $middlewareFactory->retry() );
+
+ $delayMocker = $this->getDelayMocker( $delays );
+ $handler->push( $delayMocker );
+
+ return new Client( [ 'handler' => $handler ] );
+ }
+
+ private function getDelayMocker( &$delays ) {
+ return function ( callable $handler ) use ( &$delays ) {
+ return function ( $request, array $options ) use ( $handler, &$delays ) {
+ if ( isset( $options['delay'] ) ) {
+ $delays[] = $options['delay'];
+ unset( $options['delay'] );
+ }
+ return $handler( $request, $options );
+ };
+ };
+ }
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/MediawikiApiTest.php b/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/MediawikiApiTest.php
new file mode 100644
index 00000000..a55f6739
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/MediawikiApiTest.php
@@ -0,0 +1,296 @@
+<?php
+
+namespace Mediawiki\Api\Test\Unit;
+
+use Mediawiki\Api\ApiUser;
+use Mediawiki\Api\MediawikiApi;
+use Mediawiki\Api\SimpleRequest;
+use Mediawiki\Api\UsageException;
+use PHPUnit_Framework_TestCase;
+use stdClass;
+
+/**
+ * @author Addshore
+ *
+ * @covers Mediawiki\Api\MediawikiApi
+ */
+class MediawikiApiTest extends PHPUnit_Framework_TestCase {
+
+ public function provideValidConstruction() {
+ return [
+ [ 'localhost' ],
+ [ 'http://en.wikipedia.org/w/api.php' ],
+ [ '127.0.0.1/foo/bar/wwwwwwwww/api.php' ],
+ ];
+ }
+
+ /**
+ * @dataProvider provideValidConstruction
+ */
+ public function testValidConstruction( $apiLocation ) {
+ new MediawikiApi( $apiLocation );
+ $this->assertTrue( true );
+ }
+
+ public function provideInvalidConstruction() {
+ return [
+ [ null ],
+ [ 12345678 ],
+ [ [] ],
+ [ new stdClass() ],
+ ];
+ }
+
+ /**
+ * @dataProvider provideInvalidConstruction
+ */
+ public function testInvalidConstruction( $apiLocation ) {
+ $this->setExpectedException( 'InvalidArgumentException' );
+ new MediawikiApi( $apiLocation );
+ }
+
+ private function getMockClient() {
+ return $this->getMock( 'GuzzleHttp\ClientInterface' );
+ }
+
+ private function getMockResponse( $responseValue ) {
+ $mock = $this->getMock( 'Psr\Http\Message\ResponseInterface' );
+ $mock->expects( $this->any() )
+ ->method( 'getBody' )
+ ->will( $this->returnValue( json_encode( $responseValue ) ) );
+ return $mock;
+ }
+
+ private function getExpectedRequestOpts( $params, $paramsLocation ) {
+ return [
+ $paramsLocation => array_merge( $params, [ 'format' => 'json' ] ),
+ 'headers' => [ 'User-Agent' => 'addwiki-mediawiki-client' ],
+ ];
+ }
+
+ public function testGetRequestThrowsUsageExceptionOnError() {
+ $client = $this->getMockClient();
+ $client->expects( $this->once() )
+ ->method( 'request' )
+ ->will( $this->returnValue(
+ $this->getMockResponse( [ 'error' => [
+ 'code' => 'imacode',
+ 'info' => 'imamsg',
+ ] ] )
+ ) );
+ $api = new MediawikiApi( '', $client );
+
+ try{
+ $api->getRequest( new SimpleRequest( 'foo' ) );
+ $this->fail( 'No Usage Exception Thrown' );
+ }
+ catch ( UsageException $e ) {
+ $this->assertEquals( 'imacode', $e->getApiCode() );
+ $this->assertEquals( 'imamsg', $e->getRawMessage() );
+ }
+ }
+
+ public function testPostRequestThrowsUsageExceptionOnError() {
+ $client = $this->getMockClient();
+ $client->expects( $this->once() )
+ ->method( 'request' )
+ ->will( $this->returnValue(
+ $this->getMockResponse( [ 'error' => [
+ 'code' => 'imacode',
+ 'info' => 'imamsg',
+ ] ] )
+ ) );
+ $api = new MediawikiApi( '', $client );
+
+ try{
+ $api->postRequest( new SimpleRequest( 'foo' ) );
+ $this->fail( 'No Usage Exception Thrown' );
+ }
+ catch ( UsageException $e ) {
+ $this->assertSame( 'imacode', $e->getApiCode() );
+ $this->assertSame( 'imamsg', $e->getRawMessage() );
+ }
+ }
+
+ /**
+ * @dataProvider provideActionsParamsResults
+ */
+ public function testGetActionReturnsResult( $expectedResult, $action, $params = [] ) {
+ $client = $this->getMockClient();
+ $params = array_merge( [ 'action' => $action ], $params );
+ $client->expects( $this->once() )
+ ->method( 'request' )
+ ->with( 'GET', null, $this->getExpectedRequestOpts( $params, 'query' ) )
+ ->will( $this->returnValue( $this->getMockResponse( $expectedResult ) ) );
+ $api = new MediawikiApi( '', $client );
+
+ $result = $api->getRequest( new SimpleRequest( $action, $params ) );
+
+ $this->assertEquals( $expectedResult, $result );
+ }
+
+ /**
+ * @dataProvider provideActionsParamsResults
+ */
+ public function testPostActionReturnsResult( $expectedResult, $action, $params = [] ) {
+ $client = $this->getMockClient();
+ $params = array_merge( [ 'action' => $action ], $params );
+ $client->expects( $this->once() )
+ ->method( 'request' )
+ ->with( 'POST', null, $this->getExpectedRequestOpts( $params, 'form_params' ) )
+ ->will( $this->returnValue( $this->getMockResponse( $expectedResult ) ) );
+ $api = new MediawikiApi( '', $client );
+
+ $result = $api->postRequest( new SimpleRequest( $action, $params ) );
+
+ $this->assertEquals( $expectedResult, $result );
+ }
+
+ private function getNullFilePointer() {
+ if ( !file_exists( '/dev/null' ) ) {
+ // windows
+ return fopen( 'NUL', 'r' );
+ }
+ return fopen( '/dev/null', 'r' );
+ }
+
+ public function testPostActionWithFileReturnsResult() {
+ $dummyFile = $this->getNullFilePointer();
+ $params = [
+ 'filename' => 'foo.jpg',
+ 'file' => $dummyFile,
+ ];
+ $client = $this->getMockClient();
+ $client->expects( $this->once() )->method( 'request' )->with(
+ 'POST',
+ null,
+ [
+ 'multipart' => [
+ [ 'name' => 'action', 'contents' => 'upload' ],
+ [ 'name' => 'filename', 'contents' => 'foo.jpg' ],
+ [ 'name' => 'file', 'contents' => $dummyFile ],
+ [ 'name' => 'format', 'contents' => 'json' ],
+ ],
+ 'headers' => [ 'User-Agent' => 'addwiki-mediawiki-client' ],
+ ]
+ )->will( $this->returnValue( $this->getMockResponse( [ 'success ' => 1 ] ) ) );
+ $api = new MediawikiApi( '', $client );
+
+ $result = $api->postRequest( new SimpleRequest( 'upload', $params ) );
+
+ $this->assertEquals( [ 'success ' => 1 ], $result );
+ }
+
+ public function provideActionsParamsResults() {
+ return [
+ [ [ 'key' => 'value' ], 'logout' ],
+ [ [ 'key' => 'value' ], 'logout', [ 'param1' => 'v1' ] ],
+ [ [ 'key' => 'value', 'key2' => 1212, [] ], 'logout' ],
+ ];
+ }
+
+ public function testGoodLoginSequence() {
+ $client = $this->getMockClient();
+ $user = new ApiUser( 'U1', 'P1' );
+ $eq1 = [
+ 'action' => 'login',
+ 'lgname' => 'U1',
+ 'lgpassword' => 'P1',
+ ];
+ $client->expects( $this->at( 0 ) )
+ ->method( 'request' )
+ ->with( 'POST', null, $this->getExpectedRequestOpts( $eq1, 'form_params' ) )
+ ->will( $this->returnValue( $this->getMockResponse( [ 'login' => [
+ 'result' => 'NeedToken',
+ 'token' => 'IamLoginTK',
+ ] ] ) ) );
+ $params = array_merge( $eq1, [ 'lgtoken' => 'IamLoginTK' ] );
+ $response = $this->getMockResponse( [ 'login' => [ 'result' => 'Success' ] ] );
+ $client->expects( $this->at( 1 ) )
+ ->method( 'request' )
+ ->with( 'POST', null, $this->getExpectedRequestOpts( $params, 'form_params' ) )
+ ->will( $this->returnValue( $response ) );
+ $api = new MediawikiApi( '', $client );
+
+ $this->assertTrue( $api->login( $user ) );
+ $this->assertSame( 'U1', $api->isLoggedin() );
+ }
+
+ public function testBadLoginSequence() {
+ $client = $this->getMockClient();
+ $user = new ApiUser( 'U1', 'P1' );
+ $eq1 = [
+ 'action' => 'login',
+ 'lgname' => 'U1',
+ 'lgpassword' => 'P1',
+ ];
+ $client->expects( $this->at( 0 ) )
+ ->method( 'request' )
+ ->with( 'POST', null, $this->getExpectedRequestOpts( $eq1, 'form_params' ) )
+ ->will( $this->returnValue( $this->getMockResponse( [ 'login' => [
+ 'result' => 'NeedToken',
+ 'token' => 'IamLoginTK',
+ ] ] ) ) );
+ $params = array_merge( $eq1, [ 'lgtoken' => 'IamLoginTK' ] );
+ $response = $this->getMockResponse( [ 'login' => [ 'result' => 'BADTOKENorsmthin' ] ] );
+ $client->expects( $this->at( 1 ) )
+ ->method( 'request' )
+ ->with( 'POST', null, $this->getExpectedRequestOpts( $params, 'form_params' ) )
+ ->will( $this->returnValue( $response ) );
+ $api = new MediawikiApi( '', $client );
+
+ $this->setExpectedException( 'Mediawiki\Api\UsageException' );
+ $api->login( $user );
+ }
+
+ public function testLogout() {
+ $client = $this->getMockClient();
+ $client->expects( $this->at( 0 ) )
+ ->method( 'request' )
+ ->with( 'POST', null, $this->getExpectedRequestOpts( [ 'action' => 'logout' ], 'form_params' ) )
+ ->will( $this->returnValue( $this->getMockResponse( [] ) ) );
+ $api = new MediawikiApi( '', $client );
+
+ $this->assertTrue( $api->logout() );
+ }
+
+ public function testLogoutOnFailure() {
+ $client = $this->getMockClient();
+ $client->expects( $this->at( 0 ) )
+ ->method( 'request' )
+ ->with( 'POST', null, $this->getExpectedRequestOpts( [ 'action' => 'logout' ], 'form_params' ) )
+ ->will( $this->returnValue( $this->getMockResponse( null ) ) );
+ $api = new MediawikiApi( '', $client );
+
+ $this->assertFalse( $api->logout() );
+ }
+
+ /**
+ * @dataProvider provideVersions
+ */
+ public function testGetVersion( $apiValue, $expectedVersion ) {
+ $client = $this->getMockClient();
+ $params = [ 'action' => 'query', 'meta' => 'siteinfo', 'continue' => '' ];
+ $client->expects( $this->exactly( 1 ) )
+ ->method( 'request' )
+ ->with( 'GET', null, $this->getExpectedRequestOpts( $params, 'query' ) )
+ ->will( $this->returnValue( $this->getMockResponse( [
+ 'query' => [
+ 'general' => [
+ 'generator' => $apiValue,
+ ],
+ ],
+ ] ) ) );
+ $api = new MediawikiApi( '', $client );
+ $this->assertEquals( $expectedVersion, $api->getVersion() );
+ }
+
+ public function provideVersions() {
+ return [
+ [ 'MediaWiki 1.25wmf13', '1.25' ],
+ [ 'MediaWiki 1.24.1', '1.24.1' ],
+ [ 'MediaWiki 1.19', '1.19' ],
+ [ 'MediaWiki 1.0.0', '1.0.0' ],
+ ];
+ }
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/MediawikiSessionTest.php b/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/MediawikiSessionTest.php
new file mode 100644
index 00000000..667a526f
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/MediawikiSessionTest.php
@@ -0,0 +1,95 @@
+<?php
+
+namespace Mediawiki\Api\Test\Unit;
+
+use Mediawiki\Api\MediawikiApi;
+use Mediawiki\Api\MediawikiSession;
+use PHPUnit_Framework_MockObject_MockObject;
+use PHPUnit_Framework_TestCase;
+
+/**
+ * @author Addshore
+ *
+ * @covers Mediawiki\Api\MediawikiSession
+ */
+class MediawikiSessionTest extends PHPUnit_Framework_TestCase {
+
+ /**
+ * @return PHPUnit_Framework_MockObject_MockObject|MediawikiApi
+ */
+ private function getMockApi() {
+ return $this->getMockBuilder( '\Mediawiki\Api\MediawikiApi' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testConstruction() {
+ $session = new MediawikiSession( $this->getMockApi() );
+ $this->assertInstanceOf( '\Mediawiki\Api\MediawikiSession', $session );
+ }
+
+ /**
+ * @dataProvider provideTokenTypes
+ */
+ public function testGetToken( $tokenType ) {
+ $mockApi = $this->getMockApi();
+ $mockApi->expects( $this->exactly( 2 ) )
+ ->method( 'postRequest' )
+ ->with( $this->isInstanceOf( '\Mediawiki\Api\SimpleRequest' ) )
+ ->will( $this->returnValue( [
+ 'query' => [
+ 'tokens' => [
+ $tokenType => 'TKN-' . $tokenType,
+ ]
+ ]
+ ] ) );
+
+ $session = new MediawikiSession( $mockApi );
+
+ // Although we make 2 calls to the method we assert the tokens method about is only called once
+ $this->assertEquals( 'TKN-' . $tokenType, $session->getToken() );
+ $this->assertEquals( 'TKN-' . $tokenType, $session->getToken() );
+ // Then clearing the tokens and calling again should make a second call!
+ $session->clearTokens();
+ $this->assertEquals( 'TKN-' . $tokenType, $session->getToken() );
+ }
+
+ /**
+ * @dataProvider provideTokenTypes
+ */
+ public function testGetTokenPre125( $tokenType ) {
+ $mockApi = $this->getMockApi();
+ $mockApi->expects( $this->at( 0 ) )
+ ->method( 'postRequest' )
+ ->with( $this->isInstanceOf( '\Mediawiki\Api\SimpleRequest' ) )
+ ->will( $this->returnValue( [
+ 'warnings' => [
+ 'query' => [
+ '*' => "Unrecognized value for parameter 'meta': tokens",
+ ]
+ ]
+ ] ) );
+ $mockApi->expects( $this->at( 1 ) )
+ ->method( 'postRequest' )
+ ->with( $this->isInstanceOf( '\Mediawiki\Api\SimpleRequest' ) )
+ ->will( $this->returnValue( [
+ 'tokens' => [
+ $tokenType => 'TKN-' . $tokenType,
+ ]
+ ] ) );
+
+ $session = new MediawikiSession( $mockApi );
+
+ // Although we make 2 calls to the method we assert the tokens method about is only called once
+ $this->assertSame( 'TKN-' . $tokenType, $session->getToken() );
+ $this->assertSame( 'TKN-' . $tokenType, $session->getToken() );
+ }
+
+ public function provideTokenTypes() {
+ return [
+ [ 'csrf' ],
+ [ 'edit' ],
+ ];
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/MultipartRequestTest.php b/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/MultipartRequestTest.php
new file mode 100644
index 00000000..993c29e8
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/MultipartRequestTest.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace Mediawiki\Api\Test\Unit;
+
+use Exception;
+use Mediawiki\Api\MultipartRequest;
+use PHPUnit_Framework_TestCase;
+
+class MultipartRequestTest extends PHPUnit_Framework_TestCase {
+
+ public function testBasics() {
+ $request = new MultipartRequest();
+ $this->assertEquals( [], $request->getMultipartParams() );
+
+ // One parameter.
+ $request->setParam( 'testparam', 'value' );
+ $request->addMultipartParams( [ 'testparam' => [ 'lorem' => 'ipsum' ] ] );
+ $this->assertEquals(
+ [ 'testparam' => [ 'lorem' => 'ipsum' ] ],
+ $request->getMultipartParams()
+ );
+
+ // Another parameter.
+ $request->setParam( 'testparam2', 'value' );
+ $request->addMultipartParams( [ 'testparam2' => [ 'lorem2' => 'ipsum2' ] ] );
+ $this->assertEquals(
+ [
+ 'testparam' => [ 'lorem' => 'ipsum' ],
+ 'testparam2' => [ 'lorem2' => 'ipsum2' ],
+ ],
+ $request->getMultipartParams()
+ );
+ }
+
+ /**
+ * You are not allowed to set multipart parameters on a parameter that doesn't exist.
+ * @expectedException Exception
+ * @expectedExceptionMessage Parameter 'testparam' is not already set on this request.
+ */
+ public function testParamNotYetSet() {
+ $request = new MultipartRequest();
+ $request->addMultipartParams( [ 'testparam' => [] ] );
+ }
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/SimpleRequestTest.php b/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/SimpleRequestTest.php
new file mode 100644
index 00000000..df979992
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/SimpleRequestTest.php
@@ -0,0 +1,49 @@
+<?php
+
+namespace Mediawiki\Api\Test\Unit;
+
+use Mediawiki\Api\SimpleRequest;
+use PHPUnit_Framework_TestCase;
+
+/**
+ * @author Addshore
+ *
+ * @covers Mediawiki\Api\SimpleRequest
+ */
+class SimpleRequestTest extends PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider provideValidConstruction
+ */
+ public function testValidConstruction( $action, $params, $expected, $headers = [] ) {
+ $request = new SimpleRequest( $action, $params, $headers );
+ $this->assertEquals( $expected, $request->getParams() );
+ $this->assertEquals( $headers, $request->getHeaders() );
+ }
+
+ public function provideValidConstruction() {
+ return [
+ [ 'action', [], [ 'action' => 'action' ] ],
+ [ '1123', [], [ 'action' => '1123' ] ],
+ [ 'a', [ 'b' => 'c' ], [ 'action' => 'a', 'b' => 'c' ] ],
+ [ 'a', [ 'b' => 'c', 'd' => 'e' ], [ 'action' => 'a', 'b' => 'c', 'd' => 'e' ] ],
+ [ 'a', [ 'b' => 'c|d|e|f' ], [ 'action' => 'a', 'b' => 'c|d|e|f' ] ],
+ [ 'foo', [], [ 'action' => 'foo' ] ,[ 'foo' => 'bar' ] ],
+ ];
+ }
+
+ /**
+ * @dataProvider provideInvalidConstruction
+ */
+ public function testInvalidConstruction( $action, $params ) {
+ $this->setExpectedException( 'InvalidArgumentException' );
+ new SimpleRequest( $action, $params );
+ }
+
+ public function provideInvalidConstruction() {
+ return [
+ [ [], [] ],
+ ];
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/UsageExceptionTest.php b/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/UsageExceptionTest.php
new file mode 100644
index 00000000..2b7d6072
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api-base/tests/Unit/UsageExceptionTest.php
@@ -0,0 +1,39 @@
+<?php
+
+namespace Mediawiki\Api\Test\Unit;
+
+use Mediawiki\Api\UsageException;
+use PHPUnit_Framework_TestCase;
+
+/**
+ * @author Addshore
+ *
+ * @covers Mediawiki\Api\UsageException
+ */
+class UsageExceptionTest extends PHPUnit_Framework_TestCase {
+
+ public function testUsageExceptionWithNoParams() {
+ $e = new UsageException();
+ $this->assertSame(
+ 'Code: ' . PHP_EOL .
+ 'Message: ' . PHP_EOL .
+ 'Result: []',
+ $e->getMessage()
+ );
+ $this->assertSame( '', $e->getApiCode() );
+ $this->assertEquals( [], $e->getApiResult() );
+ }
+
+ public function testUsageExceptionWithParams() {
+ $e = new UsageException( 'imacode', 'imamsg', [ 'foo' => 'bar' ] );
+ $this->assertSame( 'imacode', $e->getApiCode() );
+ $this->assertSame(
+ 'Code: imacode' . PHP_EOL .
+ 'Message: imamsg' . PHP_EOL .
+ 'Result: {"foo":"bar"}',
+ $e->getMessage()
+ );
+ $this->assertEquals( [ 'foo' => 'bar' ], $e->getApiResult() );
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/.gitignore b/bin/reevotech/vendor/addwiki/mediawiki-api/.gitignore
new file mode 100644
index 00000000..2bd8a05e
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/.gitignore
@@ -0,0 +1,9 @@
+.idea
+vendor
+composer.lock
+test.php
+phpunit.xml
+nbproject
+docs/_build
+log
+
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/.scrutinizer.yml b/bin/reevotech/vendor/addwiki/mediawiki-api/.scrutinizer.yml
new file mode 100644
index 00000000..ffc976e3
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/.scrutinizer.yml
@@ -0,0 +1,13 @@
+inherit: true
+
+tools:
+ php_code_sniffer: true
+ php_cpd: true
+ php_cs_fixer: true
+ php_loc: true
+ php_mess_detector: true
+ php_pdepend: true
+ php_analyzer: true
+ sensiolabs_security_checker: true
+ external_code_coverage:
+ timeout: 300 \ No newline at end of file
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/.travis.yml b/bin/reevotech/vendor/addwiki/mediawiki-api/.travis.yml
new file mode 100644
index 00000000..26793151
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/.travis.yml
@@ -0,0 +1,52 @@
+language: php
+
+php:
+ - 5.5
+ - 5.6
+ - 7.0
+
+env:
+ matrix:
+ - TEST_SUITE=unit
+ # All the currently-supported versions from https://www.mediawiki.org/wiki/Version_lifecycle
+ - TEST_SUITE=integration MEDIAWIKI_VERSION=1.26.4
+ - TEST_SUITE=integration MEDIAWIKI_VERSION=1.27.3
+ - TEST_SUITE=integration MEDIAWIKI_VERSION=1.28.2
+ - TEST_SUITE=integration MEDIAWIKI_VERSION=1.29.1
+ global:
+ - MEDIAWIKI_API_URL='http://127.0.0.1:8081/api.php'
+
+matrix:
+ include:
+ - php: hhvm
+ env: TEST_SUITE=unit
+ before_install:
+ install:
+ - composer install
+ - php: 7.1
+ env: TEST_SUITE=unit
+ before_install:
+ install:
+ - composer install
+
+before_install:
+ - bin/install-mediawiki.sh
+
+install:
+ - php -S 127.0.0.1:8081 -t build/mediawiki >/dev/null 2>&1 &
+ - composer install
+
+script:
+ - $TRAVIS_BUILD_DIR/vendor/bin/phpunit --coverage-clover=$TRAVIS_BUILD_DIR/coverage.clover $TRAVIS_BUILD_DIR/tests/$TEST_SUITE
+ - $TRAVIS_BUILD_DIR/vendor/bin/phpcs
+
+after_script:
+ - wget https://scrutinizer-ci.com/ocular.phar
+ - php ocular.phar code-coverage:upload --format=php-clover $TRAVIS_BUILD_DIR/coverage.clover
+
+notifications:
+ irc:
+ channels:
+ - "chat.freenode.net##add"
+ on_success: change
+ on_failure: always
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/LICENSE.md b/bin/reevotech/vendor/addwiki/mediawiki-api/LICENSE.md
new file mode 100644
index 00000000..0671f06a
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/LICENSE.md
@@ -0,0 +1,264 @@
+The GNU General Public License, Version 2, June 1991 (GPLv2)
+============================================================
+
+> Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+> 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+
+Everyone is permitted to copy and distribute verbatim copies of this license
+document, but changing it is not allowed.
+
+
+Preamble
+--------
+
+The licenses for most software are designed to take away your freedom to share
+and change it. By contrast, the GNU General Public License is intended to
+guarantee your freedom to share and change free software--to make sure the
+software is free for all its users. This General Public License applies to most
+of the Free Software Foundation's software and to any other program whose
+authors commit to using it. (Some other Free Software Foundation software is
+covered by the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+When we speak of free software, we are referring to freedom, not price. Our
+General Public Licenses are designed to make sure that you have the freedom to
+distribute copies of free software (and charge for this service if you wish),
+that you receive source code or can get it if you want it, that you can change
+the software or use pieces of it in new free programs; and that you know you can
+do these things.
+
+To protect your rights, we need to make restrictions that forbid anyone to deny
+you these rights or to ask you to surrender the rights. These restrictions
+translate to certain responsibilities for you if you distribute copies of the
+software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis or for a
+fee, you must give the recipients all the rights that you have. You must make
+sure that they, too, receive or can get the source code. And you must show them
+these terms so they know their rights.
+
+We protect your rights with two steps: (1) copyright the software, and (2) offer
+you this license which gives you legal permission to copy, distribute and/or
+modify the software.
+
+Also, for each author's protection and ours, we want to make certain that
+everyone understands that there is no warranty for this free software. If the
+software is modified by someone else and passed on, we want its recipients to
+know that what they have is not the original, so that any problems introduced by
+others will not reflect on the original authors' reputations.
+
+Finally, any free program is threatened constantly by software patents. We wish
+to avoid the danger that redistributors of a free program will individually
+obtain patent licenses, in effect making the program proprietary. To prevent
+this, we have made it clear that any patent must be licensed for everyone's free
+use or not licensed at all.
+
+The precise terms and conditions for copying, distribution and modification
+follow.
+
+
+Terms And Conditions For Copying, Distribution And Modification
+---------------------------------------------------------------
+
+**0.** This License applies to any program or other work which contains a notice
+placed by the copyright holder saying it may be distributed under the terms of
+this General Public License. The "Program", below, refers to any such program or
+work, and a "work based on the Program" means either the Program or any
+derivative work under copyright law: that is to say, a work containing the
+Program or a portion of it, either verbatim or with modifications and/or
+translated into another language. (Hereinafter, translation is included without
+limitation in the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not covered by
+this License; they are outside its scope. The act of running the Program is not
+restricted, and the output from the Program is covered only if its contents
+constitute a work based on the Program (independent of having been made by
+running the Program). Whether that is true depends on what the Program does.
+
+**1.** You may copy and distribute verbatim copies of the Program's source code
+as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this License
+and to the absence of any warranty; and give any other recipients of the Program
+a copy of this License along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and you may at
+your option offer warranty protection in exchange for a fee.
+
+**2.** You may modify your copy or copies of the Program or any portion of it,
+thus forming a work based on the Program, and copy and distribute such
+modifications or work under the terms of Section 1 above, provided that you also
+meet all of these conditions:
+
+* **a)** You must cause the modified files to carry prominent notices stating
+ that you changed the files and the date of any change.
+
+* **b)** You must cause any work that you distribute or publish, that in whole
+ or in part contains or is derived from the Program or any part thereof, to
+ be licensed as a whole at no charge to all third parties under the terms of
+ this License.
+
+* **c)** If the modified program normally reads commands interactively when
+ run, you must cause it, when started running for such interactive use in the
+ most ordinary way, to print or display an announcement including an
+ appropriate copyright notice and a notice that there is no warranty (or
+ else, saying that you provide a warranty) and that users may redistribute
+ the program under these conditions, and telling the user how to view a copy
+ of this License. (Exception: if the Program itself is interactive but does
+ not normally print such an announcement, your work based on the Program is
+ not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If identifiable
+sections of that work are not derived from the Program, and can be reasonably
+considered independent and separate works in themselves, then this License, and
+its terms, do not apply to those sections when you distribute them as separate
+works. But when you distribute the same sections as part of a whole which is a
+work based on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the entire whole,
+and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your
+rights to work written entirely by you; rather, the intent is to exercise the
+right to control the distribution of derivative or collective works based on the
+Program.
+
+In addition, mere aggregation of another work not based on the Program with the
+Program (or with a work based on the Program) on a volume of a storage or
+distribution medium does not bring the other work under the scope of this
+License.
+
+**3.** You may copy and distribute the Program (or a work based on it, under
+Section 2) in object code or executable form under the terms of Sections 1 and 2
+above provided that you also do one of the following:
+
+* **a)** Accompany it with the complete corresponding machine-readable source
+ code, which must be distributed under the terms of Sections 1 and 2 above on
+ a medium customarily used for software interchange; or,
+
+* **b)** Accompany it with a written offer, valid for at least three years, to
+ give any third party, for a charge no more than your cost of physically
+ performing source distribution, a complete machine-readable copy of the
+ corresponding source code, to be distributed under the terms of Sections 1
+ and 2 above on a medium customarily used for software interchange; or,
+
+* **c)** Accompany it with the information you received as to the offer to
+ distribute corresponding source code. (This alternative is allowed only for
+ noncommercial distribution and only if you received the program in object
+ code or executable form with such an offer, in accord with Subsection b
+ above.)
+
+The source code for a work means the preferred form of the work for making
+modifications to it. For an executable work, complete source code means all the
+source code for all modules it contains, plus any associated interface
+definition files, plus the scripts used to control compilation and installation
+of the executable. However, as a special exception, the source code distributed
+need not include anything that is normally distributed (in either source or
+binary form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component itself
+accompanies the executable.
+
+If distribution of executable or object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the source code
+from the same place counts as distribution of the source code, even though third
+parties are not compelled to copy the source along with the object code.
+
+**4.** You may not copy, modify, sublicense, or distribute the Program except as
+expressly provided under this License. Any attempt otherwise to copy, modify,
+sublicense or distribute the Program is void, and will automatically terminate
+your rights under this License. However, parties who have received copies, or
+rights, from you under this License will not have their licenses terminated so
+long as such parties remain in full compliance.
+
+**5.** You are not required to accept this License, since you have not signed
+it. However, nothing else grants you permission to modify or distribute the
+Program or its derivative works. These actions are prohibited by law if you do
+not accept this License. Therefore, by modifying or distributing the Program (or
+any work based on the Program), you indicate your acceptance of this License to
+do so, and all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+**6.** Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program subject to these terms and
+conditions. You may not impose any further restrictions on the recipients'
+exercise of the rights granted herein. You are not responsible for enforcing
+compliance by third parties to this License.
+
+**7.** If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues), conditions
+are imposed on you (whether by court order, agreement or otherwise) that
+contradict the conditions of this License, they do not excuse you from the
+conditions of this License. If you cannot distribute so as to satisfy
+simultaneously your obligations under this License and any other pertinent
+obligations, then as a consequence you may not distribute the Program at all.
+For example, if a patent license would not permit royalty-free redistribution of
+the Program by all those who receive copies directly or indirectly through you,
+then the only way you could satisfy both it and this License would be to refrain
+entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply and the
+section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or
+other property right claims or to contest validity of any such claims; this
+section has the sole purpose of protecting the integrity of the free software
+distribution system, which is implemented by public license practices. Many
+people have made generous contributions to the wide range of software
+distributed through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing to
+distribute software through any other system and a licensee cannot impose that
+choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+**8.** If the distribution and/or use of the Program is restricted in certain
+countries either by patents or by copyrighted interfaces, the original copyright
+holder who places the Program under this License may add an explicit
+geographical distribution limitation excluding those countries, so that
+distribution is permitted only in or among countries not thus excluded. In such
+case, this License incorporates the limitation as if written in the body of this
+License.
+
+**9.** The Free Software Foundation may publish revised and/or new versions of
+the General Public License from time to time. Such new versions will be similar
+in spirit to the present version, but may differ in detail to address new
+problems or concerns.
+
+Each version is given a distinguishing version number. If the Program specifies
+a version number of this License which applies to it and "any later version",
+you have the option of following the terms and conditions either of that version
+or of any later version published by the Free Software Foundation. If the
+Program does not specify a version number of this License, you may choose any
+version ever published by the Free Software Foundation.
+
+**10.** If you wish to incorporate parts of the Program into other free programs
+whose distribution conditions are different, write to the author to ask for
+permission. For software which is copyrighted by the Free Software Foundation,
+write to the Free Software Foundation; we sometimes make exceptions for this.
+Our decision will be guided by the two goals of preserving the free status of
+all derivatives of our free software and of promoting the sharing and reuse of
+software generally.
+
+
+No Warranty
+-----------
+
+**11.** BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
+THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
+STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM
+"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+**12.** IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
+INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
+BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER
+OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/README.md b/bin/reevotech/vendor/addwiki/mediawiki-api/README.md
new file mode 100644
index 00000000..325958fc
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/README.md
@@ -0,0 +1,74 @@
+mediawiki-api
+==================
+[![Build Status](https://travis-ci.org/addwiki/mediawiki-api.png?branch=master)](https://travis-ci.org/addwiki/mediawiki-api)
+[![Code Coverage](https://scrutinizer-ci.com/g/addwiki/mediawiki-api/badges/coverage.png?s=5bce1c1f0939d278ac715c7846b679a61401b1de)](https://scrutinizer-ci.com/g/addwiki/mediawiki-api/)
+[![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/addwiki/mediawiki-api/badges/quality-score.png?s=4182ebaf18fb0b22af9bc3e7941fd4e3524c932e)](https://scrutinizer-ci.com/g/addwiki/mediawiki-api/)
+[![Dependency Status](https://www.versioneye.com/user/projects/54b92f798d55087422000030/badge.svg?style=flat)](https://www.versioneye.com/user/projects/54b92f798d55087422000030)
+
+On Packagist:
+[![Latest Stable Version](https://poser.pugx.org/addwiki/mediawiki-api/version.png)](https://packagist.org/packages/addwiki/mediawiki-api)
+[![Download count](https://poser.pugx.org/addwiki/mediawiki-api/d/total.png)](https://packagist.org/packages/addwiki/mediawiki-api)
+
+Issue tracker: https://phabricator.wikimedia.org/project/profile/1490/
+
+## Installation
+
+Use composer to install the library and all its dependencies:
+
+ composer require "addwiki/mediawiki-api:~0.7.0"
+
+## Example Usage
+
+```php
+// Load all the stuff
+require_once( __DIR__ . '/vendor/autoload.php' );
+
+// Log in to a wiki
+$api = new \Mediawiki\Api\MediawikiApi( 'http://localhost/w/api.php' );
+$api->login( new \Mediawiki\Api\ApiUser( 'username', 'password' ) );
+$services = new \Mediawiki\Api\MediawikiFactory( $api );
+
+// Get a page
+$page = $services->newPageGetter()->getFromTitle( 'Foo' );
+
+// Edit a page
+$content = new \Mediawiki\DataModel\Content( 'New Text' );
+$revision = new \Mediawiki\DataModel\Revision( $content, $page->getPageIdentifier() );
+$services->newRevisionSaver()->save( $revision );
+
+// Move a page
+$services->newPageMover()->move(
+ $services->newPageGetter()->getFromTitle( 'FooBar' ),
+ new Title( 'FooBar' )
+);
+
+// Delete a page
+$services->newPageDeleter()->delete(
+ $services->newPageGetter()->getFromTitle( 'DeleteMe!' ),
+ array( 'reason' => 'Reason for Deletion' )
+);
+
+// Create a new page
+$newContent = new \Mediawiki\DataModel\Content( 'Hello World' );
+$title = new \Mediawiki\DataModel\Title( 'New Page' );
+$identifier = new \Mediawiki\DataModel\PageIdentifier( $title );
+$revision = new \Mediawiki\DataModel\Revision( $newContent, $identifier );
+$services->newRevisionSaver()->save( $revision );
+
+// List all pages in a category
+$pages = $services->newPageListGetter()->getPageListFromCategoryName( 'Category:Cat name' );
+```
+
+## Running the integration tests
+
+To run the integration tests, you need to have a running MediaWiki instance. The tests will create pages and categories without using a user account so it's best if you use a test instance. Furthermore you need to turn off rate limiting by adding the line
+
+ $wgGroupPermissions['*']['noratelimit'] = true;
+
+to the `LocalSettings.php` of your MediaWiki.
+
+By default, the tests will use the URL `http://localhost/w/api.php` as the API endpoint. If you have a different URL (e.g. `http://localhost:8080/w/api.php`), you need to configure the URL as an environemnt variable before running the tests. Example:
+
+ export MEDIAWIKI_API_URL='http://localhost:8080/w/api.php'
+
+**Warning:** Running the integration tests can take a long time to complete.
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/RELEASENOTES.md b/bin/reevotech/vendor/addwiki/mediawiki-api/RELEASENOTES.md
new file mode 100644
index 00000000..8d8bb9a1
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/RELEASENOTES.md
@@ -0,0 +1,111 @@
+Release Notes
+=============
+
+These are the release notes for [mediawiki-api](http://addwiki.readthedocs.io/projects/mediawiki-api/).
+
+## Version 0.7.2 (20th November 2017)
+
+* New parent class for all API service classes,
+ with protected access on `Service::$api` to make it easier to subclass any services.
+* File uploading improved, with the option of [chunked uploading](https://www.mediawiki.org/wiki/API:Upload#Chunked_uploading).
+* Various fixes and improvements to the testing set-up and coding standards.
+
+## Version 0.7.1 (8th March 2017)
+
+* Fixed dependancy on addwiki/mediawiki-datamodel
+
+## Version 0.7 (March 2017)
+
+* Documentation! This package now has a
+ [dedicated documentation website](https://addwiki.readthedocs.io/projects/mediawiki-api/).
+* A new NamespaceGetter service with which you can get all namespaces,
+ or a single namespace by localised name, alias, or canonical name
+ ([#39](https://github.com/addwiki/mediawiki-api/pull/39), [#41](https://github.com/addwiki/mediawiki-api/pull/41)).
+* A new CategoryTraverser service for descending (all levels of) category trees
+ and either retrieving all pages or performing some action on each page.
+* A new method to PagePurger for purging multiple pages at once ([#36](https://github.com/addwiki/mediawiki-api/pull/36)).
+* All methods of the PageListGetter now continue their queries where the first request doesn't retrieve the whole result set
+ ([#31](https://github.com/addwiki/mediawiki-api/pull/31)).
+* Bug [#40](https://github.com/addwiki/mediawiki-api/pull/40) fixed with `RevisionSaver::save()` overwriting EditInfo if null.
+* Integration tests: more documentation about how to run integration tests locally,
+ and the tests are running on Travis CI.
+* Lots of fixes to coding-standards and in-code documentation.
+
+## Version 0.6 (3 August 2016)
+
+* Adds newParser method to factory
+* Use the new API continuation mode
+* Fix ignored bot assertion in EditInfo
+
+## Version 0.5.1 (7 September 2015)
+
+* Adds ApiGenerator interface
+* Adds AnonymousGenerator implementation of Generator
+* Adds FluentGenerator implementation of Generator
+
+## Version 0.5 (4 September 2015)
+
+####Breaks
+
+* LogListGetter now requires mediawiki verison 1.25 or above
+* PageListGetter now requires mediawiki verison 1.25 or above
+* Removed ALL Options objects
+
+####Additions
+
+* Introduces RevisionUndoer service
+* Introduces UserCreator service
+* Introduces FileUploader service
+* Introduces ImageRotator service
+
+####Libs
+
+* Using mediawiki-api-base 1.0
+* Using mediawiki-datamodel 0.6
+
+## Version 0.4 (13 January 2015)
+
+* Issue#8 PageListGetter methods now construct pages with a Title object rather than string
+* Page(Deleter|ListGetter|Mover|Protector|Restorer), User(Blocker|RightsChanger) service methods now require an *Options object rather than a selection of parameters.
+* Implemented PageListGetter::getRandom
+
+## Version 0.3 (2014-06-24)
+
+* Removes NewEditInfo and NewRevision
+* Moved basic api functionality to a separate base lib (mediawiki-api-base)
+* Repos renamed to Getters
+* PageGetter, RevisionSaver and UserGetter moved to the Service Namespace
+* Introduces MediawikiFactory
+* Introduces PageDeleter service
+* Introduces PageListGetter service
+* Introduces PageProtector service
+* Introduces PagePurger service
+* Introduces RevisionDeleter service
+* Introduces RevisionPatroller service
+* Introduces RevisionRollbacker service
+* Introduces UserBlocker service
+* Introduces UserRightsChanger service
+* Introduces PageRestorer service
+* Introduces RevisionRestorer service
+* Correctly handle non existent users in UserGetter
+
+
+## Version 0.2 (2014-02-23)
+
+* Altered everything for changed in mediawiki-datamodel
+* Removed Edit << action class
+* Introduces NewEditInfo and NewRevision
+
+
+## Version 0.1 (2014-02-23)
+
+Initial release with the following features:
+
+* MediawikiApi
+* ApiUser
+* MediawikiSession
+* UsageExceptions
+* PageRepo
+* UserRepo
+* EditSaver
+* Edit << action
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/bin/install-mediawiki.sh b/bin/reevotech/vendor/addwiki/mediawiki-api/bin/install-mediawiki.sh
new file mode 100755
index 00000000..030830ad
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/bin/install-mediawiki.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+##
+## This script installs MediaWiki to ./build/mediawiki (relative to the directory from which it's called).
+##
+
+## Check inputs.
+if [ -z $MEDIAWIKI_VERSION ]; then
+ echo "You must specify the MEDIAWIKI_VERSION environment variable"
+ exit 0
+fi
+
+## Set some paths.
+BUILDDIR=$(cd $(dirname "$0"); pwd -P)"/../build"
+if [ ! -d $BUILDDIR ]; then
+ mkdir "$BUILDDIR"
+fi
+INSTALLDIR="$BUILDDIR/mediawiki"
+if [ -d "$INSTALLDIR" ]; then
+ rm -r "$INSTALLDIR"
+fi
+echo "Installing MediaWiki $MEDIAWIKI_VERSION to $INSTALLDIR"
+
+## Get the required version, and unpack it to `./build/mediawiki`.
+if [ ! -s "$BUILDDIR/$MEDIAWIKI_VERSION.tar.gz" ]; then
+ wget --directory-prefix="$BUILDDIR" "https://github.com/wikimedia/mediawiki/archive/$MEDIAWIKI_VERSION.tar.gz"
+fi
+cd "$BUILDDIR"
+echo "Unpacking"
+tar -zxf "$MEDIAWIKI_VERSION.tar.gz"
+mv "mediawiki-$MEDIAWIKI_VERSION" $INSTALLDIR
+
+## Install MediaWiki.
+cd "$INSTALLDIR"
+WIKIDB="test_wiki1"
+echo "Creating database as MySQL root user"
+PASSARG=""
+if [ -n "$DBPASS" ]; then
+ PASSARG="-p$DBPASS"
+fi
+mysql "$PASSARG" -uroot -e "DROP DATABASE IF EXISTS $WIKIDB"
+mysql "$PASSARG" -uroot -e "CREATE DATABASE $WIKIDB"
+echo "Updating dependencies (Composer)"
+composer install
+echo "Installing TestWiki1 wiki"
+php maintenance/install.php --dbtype mysql --dbuser "root" --dbpass "$DBPASS" --dbname $WIKIDB --scriptpath "" --pass admin123 TestWiki1 admin
+
+# Add some extra configuration to LocalSettings.php
+cat << 'EOF' >> "$INSTALLDIR/LocalSettings.php"
+$wgEnableUploads = true;
+$wgShowExceptionDetails = true;
+$wgCacheDirectory = __DIR__."/images/tmp";
+$wgServer = "http://127.0.0.1:8081";
+$wgUsePathInfo = false;
+$wgJobRunRate = 200;
+EOF
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/composer.json b/bin/reevotech/vendor/addwiki/mediawiki-api/composer.json
new file mode 100644
index 00000000..f49a19ca
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/composer.json
@@ -0,0 +1,44 @@
+{
+ "name": "addwiki/mediawiki-api",
+ "type": "library",
+ "description": "A MediaWiki API library",
+ "keywords": ["Mediawiki"],
+ "license": "GPL-2.0+",
+ "authors": [
+ {
+ "name": "Addshore"
+ }
+ ],
+ "require": {
+ "addwiki/mediawiki-api-base": "~2.4",
+ "addwiki/mediawiki-datamodel": "~0.7.0"
+ },
+ "require-dev": {
+ "jakub-onderka/php-parallel-lint": "^0.9.2",
+ "mediawiki/mediawiki-codesniffer": "^13.0",
+ "phpunit/phpunit": "~4.8",
+ "monolog/monolog": "^1.23"
+ },
+ "autoload": {
+ "psr-4": {
+ "Mediawiki\\Api\\": "src/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Mediawiki\\Api\\Test\\": ["tests/integration", "tests/unit"]
+ }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "0.7.x-dev"
+ }
+ },
+ "scripts": {
+ "fix": "phpcbf",
+ "test": [
+ "parallel-lint . --exclude vendor",
+ "phpcs -ps"
+ ]
+ }
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/docs/Makefile b/bin/reevotech/vendor/addwiki/mediawiki-api/docs/Makefile
new file mode 100644
index 00000000..46208266
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/docs/Makefile
@@ -0,0 +1,225 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+BUILDDIR = _build
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help
+help:
+ @echo "Please use \`make <target>' where <target> is one of"
+ @echo " html to make standalone HTML files"
+ @echo " dirhtml to make HTML files named index.html in directories"
+ @echo " singlehtml to make a single large HTML file"
+ @echo " pickle to make pickle files"
+ @echo " json to make JSON files"
+ @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " qthelp to make HTML files and a qthelp project"
+ @echo " applehelp to make an Apple Help Book"
+ @echo " devhelp to make HTML files and a Devhelp project"
+ @echo " epub to make an epub"
+ @echo " epub3 to make an epub3"
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+ @echo " latexpdf to make LaTeX files and run them through pdflatex"
+ @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
+ @echo " text to make text files"
+ @echo " man to make manual pages"
+ @echo " texinfo to make Texinfo files"
+ @echo " info to make Texinfo files and run them through makeinfo"
+ @echo " gettext to make PO message catalogs"
+ @echo " changes to make an overview of all changed/added/deprecated items"
+ @echo " xml to make Docutils-native XML files"
+ @echo " pseudoxml to make pseudoxml-XML files for display purposes"
+ @echo " linkcheck to check all external links for integrity"
+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
+ @echo " coverage to run coverage check of the documentation (if enabled)"
+ @echo " dummy to check syntax errors of document sources"
+
+.PHONY: clean
+clean:
+ rm -rf $(BUILDDIR)/*
+
+.PHONY: html
+html:
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+.PHONY: dirhtml
+dirhtml:
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+.PHONY: singlehtml
+singlehtml:
+ $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+ @echo
+ @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+.PHONY: pickle
+pickle:
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+.PHONY: json
+json:
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+.PHONY: htmlhelp
+htmlhelp:
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+.PHONY: qthelp
+qthelp:
+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+ @echo
+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+ ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/mediawiki-api.qhcp"
+ @echo "To view the help file:"
+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/mediawiki-api.qhc"
+
+.PHONY: applehelp
+applehelp:
+ $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
+ @echo
+ @echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
+ @echo "N.B. You won't be able to view it unless you put it in" \
+ "~/Library/Documentation/Help or install it in your application" \
+ "bundle."
+
+.PHONY: devhelp
+devhelp:
+ $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+ @echo
+ @echo "Build finished."
+ @echo "To view the help file:"
+ @echo "# mkdir -p $$HOME/.local/share/devhelp/mediawiki-api"
+ @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/mediawiki-api"
+ @echo "# devhelp"
+
+.PHONY: epub
+epub:
+ $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+ @echo
+ @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+.PHONY: epub3
+epub3:
+ $(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3
+ @echo
+ @echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3."
+
+.PHONY: latex
+latex:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+ @echo "Run \`make' in that directory to run these through (pdf)latex" \
+ "(use \`make latexpdf' here to do that automatically)."
+
+.PHONY: latexpdf
+latexpdf:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through pdflatex..."
+ $(MAKE) -C $(BUILDDIR)/latex all-pdf
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+.PHONY: latexpdfja
+latexpdfja:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through platex and dvipdfmx..."
+ $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+.PHONY: text
+text:
+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+ @echo
+ @echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+.PHONY: man
+man:
+ $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+ @echo
+ @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+.PHONY: texinfo
+texinfo:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo
+ @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+ @echo "Run \`make' in that directory to run these through makeinfo" \
+ "(use \`make info' here to do that automatically)."
+
+.PHONY: info
+info:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo "Running Texinfo files through makeinfo..."
+ make -C $(BUILDDIR)/texinfo info
+ @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+.PHONY: gettext
+gettext:
+ $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+ @echo
+ @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+.PHONY: changes
+changes:
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+ @echo
+ @echo "The overview file is in $(BUILDDIR)/changes."
+
+.PHONY: linkcheck
+linkcheck:
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in $(BUILDDIR)/linkcheck/output.txt."
+
+.PHONY: doctest
+doctest:
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+ @echo "Testing of doctests in the sources finished, look at the " \
+ "results in $(BUILDDIR)/doctest/output.txt."
+
+.PHONY: coverage
+coverage:
+ $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
+ @echo "Testing of coverage in the sources finished, look at the " \
+ "results in $(BUILDDIR)/coverage/python.txt."
+
+.PHONY: xml
+xml:
+ $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
+ @echo
+ @echo "Build finished. The XML files are in $(BUILDDIR)/xml."
+
+.PHONY: pseudoxml
+pseudoxml:
+ $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
+ @echo
+ @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
+
+.PHONY: dummy
+dummy:
+ $(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy
+ @echo
+ @echo "Build finished. Dummy builder generates no files."
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/docs/category_traverser.rst b/bin/reevotech/vendor/addwiki/mediawiki-api/docs/category_traverser.rst
new file mode 100644
index 00000000..497398e8
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/docs/category_traverser.rst
@@ -0,0 +1,28 @@
+Category Traversal
+==================
+
+The CategoryTraverser class is used to start at one Category page in a wiki's category hierarchy
+and descend through that category's children, grandchildren, and so on.
+The basic output of this is a Pages object containing all the pages in the category tree.
+It is also possible to register callbacks that will be called
+for every subcategory or other page (i.e. anything not a category).
+
+Basic usage
+-----------
+
+To get all pages in a category or any of its subcategories.
+
+.. code-block:: php
+ :linenos:
+
+ // Construct the API.
+ $api = new \Mediawiki\Api\MediawikiApi( 'http://localhost/w/api.php' );
+ $services = new \Mediawiki\Api\MediawikiFactory( $api );
+ $categoryTraverser = $services->newCategoryTraverser();
+
+ // Get the root category.
+ $rootCatIdent = new PageIdentifier( new Title( 'Category:Categories' ) );
+ $rootCat = $this->factory->newPageGetter()->getFromPageIdentifier( $pageIdentifier );
+
+ // Get all pages.
+ $allPages = $categoryTraverser->descend( $rootCat );
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/docs/conf.py b/bin/reevotech/vendor/addwiki/mediawiki-api/docs/conf.py
new file mode 100644
index 00000000..3310f585
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/docs/conf.py
@@ -0,0 +1,80 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#
+# import os
+# import sys
+# sys.path.insert(0, os.path.abspath('.'))
+
+import sys, os
+from sphinx.highlighting import lexers
+from pygments.lexers.web import PhpLexer
+
+lexers['php'] = PhpLexer(startinline=True, linenos=1)
+lexers['php-annotations'] = PhpLexer(startinline=True, linenos=1)
+primary_domain = 'php'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = []
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix(es) of source filenames.
+# You can specify multiple suffix as a list of string:
+#
+# source_suffix = ['.rst', '.md']
+source_suffix = '.rst'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = 'mediawiki-api'
+copyright = '2016, addwiki'
+author = 'addwiki'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '0.6'
+# The full version, including alpha/beta/rc tags.
+release = '0.6'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#
+# This is also used if you do content translation via gettext catalogs.
+# Usually you set "language" from the command line for these cases.
+language = None
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This patterns also effect to html_static_path and html_extra_path
+exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# If true, `todo` and `todoList` produce output, else they produce nothing.
+todo_include_todos = False
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+#
+html_theme = 'default'
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'mediawiki-apidoc'
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/docs/contributing.rst b/bin/reevotech/vendor/addwiki/mediawiki-api/docs/contributing.rst
new file mode 100644
index 00000000..c2cd2813
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/docs/contributing.rst
@@ -0,0 +1,44 @@
+Contributing
+============
+
+We welcome all contributions, be they code, documentation, or even just ideas about how to make this package better!
+
+The best way to get started is to browse the `#addwiki board on Phabricator`_
+and either work on one of the tasks already there or create a new one with details of what you want to work on.
+
+.. _Addwiki board on Phabricator: https://phabricator.wikimedia.org/tag/addwiki/
+
+Get the code
+------------
+
+The code is `hosted on GitHub`_. Clone the repository with::
+
+ $ git clone https://github.com/addwiki/mediawiki-api.git
+
+.. _hosted on GitHub: https://github.com/addwiki/mediawiki-api
+
+Run the tests
+-------------
+
+After cloning the repository and updating the dependencies with Composer,
+you should be able to run all **unit** tests with::
+
+ ./vendor/bin/phpunit ./tests/unit
+
+To run the **integration** tests you need to set up a local MediaWiki installation
+(including with a ``admin`` administrator user with password ``admin123``)
+and tell ``phpunit`` where to find it.
+
+1. Copy ``./phpunit.xml.dist`` to ``./phpunit.xml`` and add the following section::
+
+ <php>
+ <env name="MEDIAWIKI_API_URL" value="http://localhost/path/to/your/wiki/api.php" />
+ </php>
+
+2. Create and promote a new user::
+
+ $ php mediawiki/maintenance/createAndPromote.php --sysop WikiSysop wiki123sysop
+
+Now all integration tests can be run with::
+
+ ./vendor/bin/phpunit ./tests/integration
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/docs/file_uploader.rst b/bin/reevotech/vendor/addwiki/mediawiki-api/docs/file_uploader.rst
new file mode 100755
index 00000000..9f8b534f
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/docs/file_uploader.rst
@@ -0,0 +1,28 @@
+Uploading files
+===============
+
+Basic usage
+-----------
+
+To upload a single, small-sized file:
+
+.. code-block:: php
+ :linenos:
+
+ // Construct the API.
+ $api = new \Mediawiki\Api\MediawikiApi( 'http://localhost/w/api.php' );
+ $services = new \Mediawiki\Api\MediawikiFactory( $api );
+ $fileUploader = $services->newFileUploader();
+
+ // Upload the file.
+ $fileUploader->upload( 'The_file.png', '/full/path/to/the_file.png' );
+
+If you need to work with larger files, you can switch to chunked uploading:
+
+.. code-block:: php
+ :linenos:
+
+ // Upload the file in 10 MB chunks.
+ $fileUploader = $services->newFileUploader();
+ $fileUploader->setChunkSize( 1024 * 1024 * 10 );
+ $fileUploader->upload( 'The_file.png', '/full/path/to/the_file.png' );
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/docs/index.rst b/bin/reevotech/vendor/addwiki/mediawiki-api/docs/index.rst
new file mode 100644
index 00000000..558107b3
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/docs/index.rst
@@ -0,0 +1,25 @@
+Documentation for addwiki/mediawiki-api
+=======================================
+
+Welcome to the documentation for the ``addwiki/mediawiki-api`` package!
+This is part of the Addwiki_ family of PHP packages.
+
+.. _Addwiki: http://addwiki.readthedocs.io/
+
+Quick links:
+
+* This documentation: http://addwiki.readthedocs.io/projects/mediawiki-api/
+* Source code: https://github.com/addwiki/mediawiki-api/
+* Issue tracker: https://phabricator.wikimedia.org/project/profile/1490/
+
+Contents
+--------
+
+.. toctree::
+ :maxdepth: 2
+
+ page_list_getter.rst
+ category_traverser.rst
+ namespace_getter.rst
+ file_uploader.rst
+ contributing.rst
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/docs/make.bat b/bin/reevotech/vendor/addwiki/mediawiki-api/docs/make.bat
new file mode 100644
index 00000000..a5507331
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/docs/make.bat
@@ -0,0 +1,281 @@
+@ECHO OFF
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set BUILDDIR=_build
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
+set I18NSPHINXOPTS=%SPHINXOPTS% .
+if NOT "%PAPER%" == "" (
+ set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
+ set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
+)
+
+if "%1" == "" goto help
+
+if "%1" == "help" (
+ :help
+ echo.Please use `make ^<target^>` where ^<target^> is one of
+ echo. html to make standalone HTML files
+ echo. dirhtml to make HTML files named index.html in directories
+ echo. singlehtml to make a single large HTML file
+ echo. pickle to make pickle files
+ echo. json to make JSON files
+ echo. htmlhelp to make HTML files and a HTML help project
+ echo. qthelp to make HTML files and a qthelp project
+ echo. devhelp to make HTML files and a Devhelp project
+ echo. epub to make an epub
+ echo. epub3 to make an epub3
+ echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
+ echo. text to make text files
+ echo. man to make manual pages
+ echo. texinfo to make Texinfo files
+ echo. gettext to make PO message catalogs
+ echo. changes to make an overview over all changed/added/deprecated items
+ echo. xml to make Docutils-native XML files
+ echo. pseudoxml to make pseudoxml-XML files for display purposes
+ echo. linkcheck to check all external links for integrity
+ echo. doctest to run all doctests embedded in the documentation if enabled
+ echo. coverage to run coverage check of the documentation if enabled
+ echo. dummy to check syntax errors of document sources
+ goto end
+)
+
+if "%1" == "clean" (
+ for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
+ del /q /s %BUILDDIR%\*
+ goto end
+)
+
+
+REM Check if sphinx-build is available and fallback to Python version if any
+%SPHINXBUILD% 1>NUL 2>NUL
+if errorlevel 9009 goto sphinx_python
+goto sphinx_ok
+
+:sphinx_python
+
+set SPHINXBUILD=python -m sphinx.__init__
+%SPHINXBUILD% 2> nul
+if errorlevel 9009 (
+ echo.
+ echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+ echo.installed, then set the SPHINXBUILD environment variable to point
+ echo.to the full path of the 'sphinx-build' executable. Alternatively you
+ echo.may add the Sphinx directory to PATH.
+ echo.
+ echo.If you don't have Sphinx installed, grab it from
+ echo.http://sphinx-doc.org/
+ exit /b 1
+)
+
+:sphinx_ok
+
+
+if "%1" == "html" (
+ %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/html.
+ goto end
+)
+
+if "%1" == "dirhtml" (
+ %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
+ goto end
+)
+
+if "%1" == "singlehtml" (
+ %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
+ goto end
+)
+
+if "%1" == "pickle" (
+ %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can process the pickle files.
+ goto end
+)
+
+if "%1" == "json" (
+ %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can process the JSON files.
+ goto end
+)
+
+if "%1" == "htmlhelp" (
+ %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in %BUILDDIR%/htmlhelp.
+ goto end
+)
+
+if "%1" == "qthelp" (
+ %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can run "qcollectiongenerator" with the ^
+.qhcp project file in %BUILDDIR%/qthelp, like this:
+ echo.^> qcollectiongenerator %BUILDDIR%\qthelp\mediawiki-api.qhcp
+ echo.To view the help file:
+ echo.^> assistant -collectionFile %BUILDDIR%\qthelp\mediawiki-api.ghc
+ goto end
+)
+
+if "%1" == "devhelp" (
+ %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished.
+ goto end
+)
+
+if "%1" == "epub" (
+ %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The epub file is in %BUILDDIR%/epub.
+ goto end
+)
+
+if "%1" == "epub3" (
+ %SPHINXBUILD% -b epub3 %ALLSPHINXOPTS% %BUILDDIR%/epub3
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The epub3 file is in %BUILDDIR%/epub3.
+ goto end
+)
+
+if "%1" == "latex" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "latexpdf" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ cd %BUILDDIR%/latex
+ make all-pdf
+ cd %~dp0
+ echo.
+ echo.Build finished; the PDF files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "latexpdfja" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ cd %BUILDDIR%/latex
+ make all-pdf-ja
+ cd %~dp0
+ echo.
+ echo.Build finished; the PDF files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "text" (
+ %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The text files are in %BUILDDIR%/text.
+ goto end
+)
+
+if "%1" == "man" (
+ %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The manual pages are in %BUILDDIR%/man.
+ goto end
+)
+
+if "%1" == "texinfo" (
+ %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
+ goto end
+)
+
+if "%1" == "gettext" (
+ %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
+ goto end
+)
+
+if "%1" == "changes" (
+ %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.The overview file is in %BUILDDIR%/changes.
+ goto end
+)
+
+if "%1" == "linkcheck" (
+ %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Link check complete; look for any errors in the above output ^
+or in %BUILDDIR%/linkcheck/output.txt.
+ goto end
+)
+
+if "%1" == "doctest" (
+ %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Testing of doctests in the sources finished, look at the ^
+results in %BUILDDIR%/doctest/output.txt.
+ goto end
+)
+
+if "%1" == "coverage" (
+ %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Testing of coverage in the sources finished, look at the ^
+results in %BUILDDIR%/coverage/python.txt.
+ goto end
+)
+
+if "%1" == "xml" (
+ %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The XML files are in %BUILDDIR%/xml.
+ goto end
+)
+
+if "%1" == "pseudoxml" (
+ %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
+ goto end
+)
+
+if "%1" == "dummy" (
+ %SPHINXBUILD% -b dummy %ALLSPHINXOPTS% %BUILDDIR%/dummy
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. Dummy builder generates no files.
+ goto end
+)
+
+:end
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/docs/namespace_getter.rst b/bin/reevotech/vendor/addwiki/mediawiki-api/docs/namespace_getter.rst
new file mode 100644
index 00000000..c362833f
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/docs/namespace_getter.rst
@@ -0,0 +1,54 @@
+Getting Namespaces
+==================
+
+The Name Space Getter allows you to search for namespaces and their aliases and to list all namespaces of a wiki.
+
+To use it, first get a new NamespaceGetter object from the factory:
+
+.. code-block:: php
+
+ $api = new \Mediawiki\Api\MediawikiApi( 'http://localhost/w/api.php' );
+ $services = new \Mediawiki\Api\MediawikiFactory( $api );
+ $namespaceGetter = $services->newNamespaceGetter();
+
+
+Looking for a namespace
+-----------------------
+
+If you've got a page name like ``File:awesome_cats.jpg`` and want to know its namespace ID and possible localized names
+and aliases, use the following code:
+
+.. code-block:: php
+
+ $fileNamespace = $namespaceGetter->getNamespaceByName( 'File' );
+ printf( "Name in local language: %s\n", $fileNamespace->getLocalName() );
+ printf( "Possible aliases: %s\n", implode( ', ', $fileNamespace->getAliases() ) );
+ // ... etc
+
+``getNamespaceByName`` accepts the canonical name, the local name and aliases. If you want to match only the canonical
+name, use ``getNamespaceByCanonicalName`` instead.
+
+
+Getting a namespaced page
+-------------------------
+
+If you have a page title that is not in the default namespace, you can't pass the page name string ``PageGetter`` but
+must construct a ``Title`` object instead:
+
+.. code-block:: php
+
+ $pageName = 'User:MalReynolds';
+ $nameParts = explode( ':', $pageName, 2 );
+ $namespace = $namespaceGetter->getNamespaceByName( $nameParts[0] );
+ $title = new \Mediawiki\DataModel\Title( $nameParts[1], $namespace->getId() );
+ $page = $services->newPageGetter()->getFromTitle( $title );
+
+
+Listing all namespaces
+----------------------
+
+.. code-block:: php
+
+ foreach( $namespaceGetter->getNamespaces() as $namespace ) {
+ echo $namespace->getLocalName() . "\n";
+ } \ No newline at end of file
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/docs/page_list_getter.rst b/bin/reevotech/vendor/addwiki/mediawiki-api/docs/page_list_getter.rst
new file mode 100644
index 00000000..aad9f8a8
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/docs/page_list_getter.rst
@@ -0,0 +1,88 @@
+Page Lists
+==========
+
+The Page List Getter allows you to retrieve lists of pages based on various criteria.
+It takes care of continuing queries where they span multiple requests,
+ensuring that you get all pages in your result set.
+This means that for some lists of pages a great many requests will be sent,
+and you should account for this possible performance problem when you request these lists
+(e.g. by running these as a background process and caching the results).
+
+To use it, first get a new PageListGetter object from the factory:
+
+.. code-block:: php
+
+ $api = new \Mediawiki\Api\MediawikiApi( 'http://localhost/w/api.php' );
+ $services = new \Mediawiki\Api\MediawikiFactory( $api );
+ $pageListGetter = $services->newPageListGetter();
+
+The examples below all use this ``$pageListGetter`` object.
+
+All methods of the PageListGetter return ``Page`` objects;
+this class is part of the `addwiki/mediawiki-datamodel`_ package,
+and is documented in `that page's documentation`_.
+
+.. _addwiki/mediawiki-datamodel: https://packagist.org/packages/addwiki/mediawiki-datamodel
+.. _that page's documentation: http://addwiki.readthedocs.io/projects/mediawiki-datamodel/
+
+All pages in a category
+-----------------------
+
+Note that the category name as provided should also include the 'Category' namespace prefix
+(in the language of the wiki, or in canonical English form).
+
+.. code-block:: php
+
+ $examplePages = $pageListGetter->getPageListFromCategoryName( 'Category:Example pages' );
+ foreach ( $examplePages->asArray() as $exPage ) {
+ echo $exPage->getTitle()->getText();
+ }
+
+Pages that transclude a template
+--------------------------------
+
+Although generally it is templates that are transcluded,
+any page may be and so any page title can be passed to this method.
+
+.. code-block:: php
+
+ $usingTestTemplate = $pageListGetter->getPageListFromPageTransclusions( 'Template:Test' );
+
+Pages that link to a given page
+-------------------------------
+
+Get the list of pages that link to a particular page.
+
+.. code-block:: php
+
+ $backLinks = $pageListGetter->getFromWhatLinksHere( 'Test page' );
+
+Pages with a given prefix
+-------------------------
+
+Find pages that have a particular prefix to their title.
+This can also be used to find subpages of any page.
+
+.. code-block:: php
+
+ $backLinks = $pageListGetter->getFromPrefix( 'A page/' );
+
+Random pages
+------------
+
+Get up to ten random pages at a time.
+This method takes the same arguments as the API `list=random`_ query.
+
+.. _list=random: https://www.mediawiki.org/wiki/API:Random
+
+* ``rnlimit`` How many pages to get. No more than 10 (20 for bots) allowed. Default: 1.
+* ``rnnamespace`` Pipe-separate list of namespace IDs.
+* ``rnfilterredir`` How to filter for redirects. Possible values: ``all``, ``redirects``, ``nonredirects``. Default: ``nonredirects``.
+
+.. code-block:: php
+
+ $backLinks = $pageListGetter->getRandom( [
+ 'rnlimit' => 7,
+ 'rnnamespace' => '3|5|6',
+ 'rnfilterredir' => 'all',
+ ] );
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/docs/page_purger.rst b/bin/reevotech/vendor/addwiki/mediawiki-api/docs/page_purger.rst
new file mode 100644
index 00000000..84cd7523
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/docs/page_purger.rst
@@ -0,0 +1,34 @@
+Page Purger
+===========
+
+``PagePurger`` allows you to purge a single ``Page`` or multiple ``Pages``.
+You can also check whether the ``Page`` or ``Pages`` have been purged successfully.
+
+To get started you need to create ``PagePurger`` object:
+
+.. code-block:: php
+
+$api = new \Mediawiki\Api\MediawikiApi( 'http://localhost/w/api.php' );
+$pagePurger = new \Mediawiki\Api\Service\PagePurger( $api );
+
+Purge
+-----
+
+Purge a single ``Page``. It will return a ``boolean`` that indicates if the purge operation was successful.
+
+Example:
+
+.. code-block:: php
+
+$page = new \Mediawiki\DataModel\Page(...);
+$pagePurger->purge( $page );
+
+PurgePages
+----------
+
+Purges every ``Page`` in the ``Pages`` object at once. It will return a new ``Pages`` object *with the purged ``Page``(s) only!*
+
+.. code-block:: php
+
+$pages = new \Mediawiki\DataModel\Pages(...);
+$pagePurger->purgePages( $pages );
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/phpcs.xml b/bin/reevotech/vendor/addwiki/mediawiki-api/phpcs.xml
new file mode 100644
index 00000000..1c5b15ce
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/phpcs.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<ruleset name="MediaWiki">
+ <rule ref="vendor/mediawiki/mediawiki-codesniffer/MediaWiki">
+ <exclude name="MediaWiki.Commenting.FunctionComment.MissingParamComment" />
+ </rule>
+ <file>.</file>
+ <arg name="extensions" value="php,php5,inc"/>
+ <arg name="encoding" value="utf8"/>
+ <exclude-pattern>build/</exclude-pattern>
+ <exclude-pattern>vendor/</exclude-pattern>
+</ruleset>
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/phpunit.xml.dist b/bin/reevotech/vendor/addwiki/mediawiki-api/phpunit.xml.dist
new file mode 100755
index 00000000..f674132b
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/phpunit.xml.dist
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- convertWarningsToExceptions is false as real API calls can return un expected warnings -->
+<phpunit
+ bootstrap="./vendor/autoload.php"
+ colors="true"
+ convertWarningsToExceptions="false"
+>
+ <testsuites>
+ <testsuite>
+ <directory suffix="Test.php">./tests/integration</directory>
+ </testsuite>
+ <testsuite>
+ <directory suffix="Test.php">./tests/unit</directory>
+ </testsuite>
+ </testsuites>
+ <filter>
+ <whitelist addUncoveredFilesFromWhitelist="true">
+ <directory suffix=".php">./src</directory>
+ </whitelist>
+ </filter>
+</phpunit>
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/src/CategoryLoopException.php b/bin/reevotech/vendor/addwiki/mediawiki-api/src/CategoryLoopException.php
new file mode 100644
index 00000000..9612f050
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/src/CategoryLoopException.php
@@ -0,0 +1,32 @@
+<?php
+
+namespace Mediawiki\Api;
+
+use Mediawiki\DataModel\Pages;
+
+/**
+ * Class CategoryLoopException
+ * @package Mediawiki\Api
+ */
+class CategoryLoopException extends \Exception {
+
+ /** @var Pages */
+ protected $categoryPath;
+
+ /**
+ * @param Pages $path
+ */
+ public function setCategoryPath( Pages $path ) {
+ $this->categoryPath = $path;
+ }
+
+ /**
+ * Get the path of Pages that comprise the category loop. The first item in this list is also a
+ * child page of the last item.
+ * @return Pages The set of category Pages that comprise the category loop.
+ */
+ public function getCategoryPath() {
+ return $this->categoryPath;
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/src/Generator/AnonymousGenerator.php b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Generator/AnonymousGenerator.php
new file mode 100644
index 00000000..715e3c02
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Generator/AnonymousGenerator.php
@@ -0,0 +1,41 @@
+<?php
+
+namespace Mediawiki\Api\Generator;
+
+/**
+ * @access public
+ *
+ * @author Addshore
+ *
+ * @since 0.5.1
+ */
+class AnonymousGenerator implements ApiGenerator {
+
+ /**
+ * @var string
+ */
+ private $name;
+
+ /**
+ * @var array
+ */
+ private $params;
+
+ /**
+ * @param string $name
+ * @param array $params including 'g' prefix keys
+ */
+ public function __construct( $name, array $params ) {
+ $this->name = $name;
+ $this->params = $params;
+ }
+
+ /**
+ * @return array
+ */
+ public function getParams() {
+ $params = $this->params;
+ $params['generator'] = $this->name;
+ return $params;
+ }
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/src/Generator/ApiGenerator.php b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Generator/ApiGenerator.php
new file mode 100644
index 00000000..923e98cd
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Generator/ApiGenerator.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace Mediawiki\Api\Generator;
+
+/**
+ * Interface relating to Mediawiki generators
+ * @see https://www.mediawiki.org/wiki/API:Query#Generators
+ *
+ * @access public
+ *
+ * @author Addshore
+ *
+ * @since 0.5.1
+ */
+interface ApiGenerator {
+
+ /**
+ * @since 0.5.1
+ *
+ * Associative array of parameters including the 'generator' parameter.
+ * All generator param keys must have their 'g' prefixes
+ *
+ * @return string[]
+ */
+ public function getParams();
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/src/Generator/FluentGenerator.php b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Generator/FluentGenerator.php
new file mode 100644
index 00000000..108f4999
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Generator/FluentGenerator.php
@@ -0,0 +1,68 @@
+<?php
+
+namespace Mediawiki\Api\Generator;
+
+/**
+ * @access public
+ *
+ * @author Addshore
+ *
+ * @since 0.5.1
+ */
+class FluentGenerator implements ApiGenerator {
+
+ private $name;
+ private $params;
+
+ /**
+ * @param string $name
+ */
+ public function __construct( $name ) {
+ $this->name = $name;
+ }
+
+ /**
+ * Convenience method for using this fluidly
+ *
+ * @param string $name
+ *
+ * @return FluentGenerator
+ */
+ public static function factory( $name ) {
+ return new self( $name );
+ }
+
+ /**
+ * @return string[]
+ */
+ public function getParams() {
+ $params = $this->params;
+ $params['generator'] = $this->name;
+ return $params;
+ }
+
+ /**
+ * @param string $key optionally with the 'g' prefix
+ * @param string $value
+ *
+ * @return $this
+ */
+ public function set( $key, $value ) {
+ $key = $this->addKeyprefixIfNeeded( $key );
+ $this->params[$key] = $value;
+ return $this;
+ }
+
+ /**
+ * @param string $key
+ *
+ * @return string
+ */
+ private function addKeyPrefixIfNeeded( $key ) {
+ if ( strtolower( substr( $key, 0, 1 ) ) === 'g' ) {
+ return $key;
+ }
+ return 'g' . $key;
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/src/MediawikiFactory.php b/bin/reevotech/vendor/addwiki/mediawiki-api/src/MediawikiFactory.php
new file mode 100644
index 00000000..fc773ce5
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/src/MediawikiFactory.php
@@ -0,0 +1,240 @@
+<?php
+
+namespace Mediawiki\Api;
+
+use Mediawiki\Api\Service\CategoryTraverser;
+use Mediawiki\Api\Service\FileUploader;
+use Mediawiki\Api\Service\ImageRotator;
+use Mediawiki\Api\Service\LogListGetter;
+use Mediawiki\Api\Service\NamespaceGetter;
+use Mediawiki\Api\Service\PageDeleter;
+use Mediawiki\Api\Service\PageListGetter;
+use Mediawiki\Api\Service\PageMover;
+use Mediawiki\Api\Service\PageProtector;
+use Mediawiki\Api\Service\PagePurger;
+use Mediawiki\Api\Service\PageGetter;
+use Mediawiki\Api\Service\PageRestorer;
+use Mediawiki\Api\Service\PageWatcher;
+use Mediawiki\Api\Service\Parser;
+use Mediawiki\Api\Service\RevisionDeleter;
+use Mediawiki\Api\Service\RevisionPatroller;
+use Mediawiki\Api\Service\RevisionRestorer;
+use Mediawiki\Api\Service\RevisionRollbacker;
+use Mediawiki\Api\Service\RevisionSaver;
+use Mediawiki\Api\Service\RevisionUndoer;
+use Mediawiki\Api\Service\UserBlocker;
+use Mediawiki\Api\Service\UserCreator;
+use Mediawiki\Api\Service\UserGetter;
+use Mediawiki\Api\Service\UserRightsChanger;
+
+/**
+ * @access public
+ *
+ * @author Addshore
+ */
+class MediawikiFactory {
+
+ /**
+ * @var MediawikiApi
+ */
+ private $api;
+
+ /**
+ * @param MediawikiApi $api
+ */
+ public function __construct( MediawikiApi $api ) {
+ $this->api = $api;
+ }
+
+ /**
+ * Get a new CategoryTraverser object for this API.
+ * @return \Mediawiki\Api\Service\CategoryTraverser
+ */
+ public function newCategoryTraverser() {
+ return new CategoryTraverser( $this->api );
+ }
+
+ /**
+ * @since 0.3
+ * @return RevisionSaver
+ */
+ public function newRevisionSaver() {
+ return new RevisionSaver( $this->api );
+ }
+
+ /**
+ * @since 0.5
+ * @return RevisionUndoer
+ */
+ public function newRevisionUndoer() {
+ return new RevisionUndoer( $this->api );
+ }
+
+ /**
+ * @since 0.3
+ * @return PageGetter
+ */
+ public function newPageGetter() {
+ return new PageGetter( $this->api );
+ }
+
+ /**
+ * @since 0.3
+ * @return UserGetter
+ */
+ public function newUserGetter() {
+ return new UserGetter( $this->api );
+ }
+
+ /**
+ * @since 0.3
+ * @return PageDeleter
+ */
+ public function newPageDeleter() {
+ return new PageDeleter( $this->api );
+ }
+
+ /**
+ * @since 0.3
+ * @return PageMover
+ */
+ public function newPageMover() {
+ return new PageMover( $this->api );
+ }
+
+ /**
+ * @since 0.3
+ * @return PageListGetter
+ */
+ public function newPageListGetter() {
+ return new PageListGetter( $this->api );
+ }
+
+ /**
+ * @since 0.3
+ * @return PageRestorer
+ */
+ public function newPageRestorer() {
+ return new PageRestorer( $this->api );
+ }
+
+ /**
+ * @since 0.3
+ * @return PagePurger
+ */
+ public function newPagePurger() {
+ return new PagePurger( $this->api );
+ }
+
+ /**
+ * @since 0.3
+ * @return RevisionRollbacker
+ */
+ public function newRevisionRollbacker() {
+ return new RevisionRollbacker( $this->api );
+ }
+
+ /**
+ * @since 0.3
+ * @return RevisionPatroller
+ */
+ public function newRevisionPatroller() {
+ return new RevisionPatroller( $this->api );
+ }
+
+ /**
+ * @since 0.3
+ * @return PageProtector
+ */
+ public function newPageProtector() {
+ return new PageProtector( $this->api );
+ }
+
+ /**
+ * @since 0.5
+ * @return PageWatcher
+ */
+ public function newPageWatcher() {
+ return new PageWatcher( $this->api );
+ }
+
+ /**
+ * @since 0.3
+ * @return RevisionDeleter
+ */
+ public function newRevisionDeleter() {
+ return new RevisionDeleter( $this->api );
+ }
+
+ /**
+ * @since 0.3
+ * @return RevisionRestorer
+ */
+ public function newRevisionRestorer() {
+ return new RevisionRestorer( $this->api );
+ }
+
+ /**
+ * @since 0.3
+ * @return UserBlocker
+ */
+ public function newUserBlocker() {
+ return new UserBlocker( $this->api );
+ }
+
+ /**
+ * @since 0.3
+ * @return UserRightsChanger
+ */
+ public function newUserRightsChanger() {
+ return new UserRightsChanger( $this->api );
+ }
+
+ /**
+ * @since 0.5
+ * @return UserCreator
+ */
+ public function newUserCreator() {
+ return new UserCreator( $this->api );
+ }
+
+ /**
+ * @since 0.4
+ * @return LogListGetter
+ */
+ public function newLogListGetter() {
+ return new LogListGetter( $this->api );
+ }
+
+ /**
+ * @since 0.5
+ * @return FileUploader
+ */
+ public function newFileUploader() {
+ return new FileUploader( $this->api );
+ }
+
+ /**
+ * @since 0.5
+ * @return ImageRotator
+ */
+ public function newImageRotator() {
+ return new ImageRotator( $this->api );
+ }
+
+ /**
+ * @since 0.6
+ * @return Parser
+ */
+ public function newParser() {
+ return new Parser( $this->api );
+ }
+
+ /**
+ * @since 0.7
+ * @return NamespaceGetter
+ */
+ public function newNamespaceGetter() {
+ return new NamespaceGetter( $this->api );
+ }
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/CategoryTraverser.php b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/CategoryTraverser.php
new file mode 100644
index 00000000..c82b5d69
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/CategoryTraverser.php
@@ -0,0 +1,161 @@
+<?php
+
+namespace Mediawiki\Api\Service;
+
+use Mediawiki\Api\CategoryLoopException;
+use Mediawiki\Api\MediawikiApi;
+use Mediawiki\Api\SimpleRequest;
+use Mediawiki\DataModel\Page;
+use Mediawiki\DataModel\Pages;
+
+/**
+ * Category traverser.
+ *
+ * Note on spelling 'descendant' (from Wiktionary):
+ * The adjective, "descending from a biological ancestor", may be spelt either
+ * with an 'a' or with an 'e' in the final syllable. However the noun descendant,
+ * "one who is the progeny of someone", may be spelt only with an 'a'.
+ */
+class CategoryTraverser extends Service {
+
+ const CALLBACK_CATEGORY = 10;
+ const CALLBACK_PAGE = 20;
+
+ /**
+ * @var string[]
+ */
+ protected $namespaces;
+
+ /**
+ * @var callable[]
+ */
+ protected $callbacks;
+
+ /**
+ * Used to remember the previously-visited categories when traversing.
+ * @var string[]
+ */
+ protected $alreadyVisited;
+
+ /**
+ * @param MediawikiApi $api The API to connect to.
+ */
+ public function __construct( MediawikiApi $api ) {
+ parent::__construct( $api );
+ $this->callbacks = [];
+ }
+
+ /**
+ * Query the remote site for the list of namespaces in use, so that later we can tell what's a
+ * category and what's not. This populates $this->namespaces, and will not re-request on
+ * repeated invocations.
+ * @return void
+ */
+ protected function retrieveNamespaces() {
+ if ( is_array( $this->namespaces ) ) {
+ return;
+ }
+ $params = [ 'meta' => 'siteinfo', 'siprop' => 'namespaces' ];
+ $namespaces = $this->api->getRequest( new SimpleRequest( 'query', $params ) );
+ if ( isset( $namespaces['query']['namespaces'] ) ) {
+ $this->namespaces = $namespaces['query']['namespaces'];
+ }
+ }
+
+ /**
+ * Register a callback that will be called for each page or category visited during the
+ * traversal.
+ * @param int $type One of the 'CALLBACK_' constants of this class.
+ * @param callable $callback A callable that takes two \Mediawiki\DataModel\Page parameters.
+ */
+ public function addCallback( $type, $callback ) {
+ if ( !isset( $this->callbacks[$type] ) ) {
+ $this->callbacks[$type] = [];
+ }
+ $this->callbacks[$type][] = $callback;
+ }
+
+ /**
+ * Visit every descendant page of $rootCategoryName (which will be a Category
+ * page, because there are no desecendants of any other pages).
+ * @param Page $rootCat The full name of the page to start at.
+ * @param Page[] $currentPath Used only when recursing into this method, to track each path
+ * through the category hierarchy in case of loops.
+ * @return Pages All descendants of the given category.
+ * @throws CategoryLoopException If a category loop is detected.
+ */
+ public function descend( Page $rootCat, $currentPath = null ) {
+ // Make sure we know the namespace IDs.
+ $this->retrieveNamespaces();
+
+ $rootCatName = $rootCat->getPageIdentifier()->getTitle()->getText();
+ if ( is_null( $currentPath ) ) {
+ $this->alreadyVisited = [];
+ $currentPath = new Pages();
+ }
+ $this->alreadyVisited[] = $rootCatName;
+ $currentPath->addPage( $rootCat );
+
+ // Start a list of child pages.
+ $descendants = new Pages();
+ do {
+ $pageListGetter = new PageListGetter( $this->api );
+ $members = $pageListGetter->getPageListFromCategoryName( $rootCatName );
+ foreach ( $members->toArray() as $member ) {
+ /** @var Title */
+ $memberTitle = $member->getPageIdentifier()->getTitle();
+
+ // See if this page is a Category page.
+ $isCat = false;
+ if ( isset( $this->namespaces[ $memberTitle->getNs() ] ) ) {
+ $ns = $this->namespaces[ $memberTitle->getNs() ];
+ $isCat = ( isset( $ns['canonical'] ) && $ns['canonical'] === 'Category' );
+ }
+ // If it's a category, descend into it.
+ if ( $isCat ) {
+ // If this member has already been visited on this branch of the traversal,
+ // throw an Exception with information about which categories form the loop.
+ if ( $currentPath->hasPage( $member ) ) {
+ $currentPath->addPage( $member );
+ $loop = new CategoryLoopException();
+ $loop->setCategoryPath( $currentPath );
+ throw $loop;
+ }
+ // Don't go any further if we've already visited this member
+ // (does not indicate a loop, however; we've already caught that above).
+ if ( in_array( $memberTitle->getText(), $this->alreadyVisited ) ) {
+ continue;
+ }
+ // Call any registered callbacked, and carry on to the next branch.
+ $this->call( self::CALLBACK_CATEGORY, [ $member, $rootCat ] );
+ $newDescendants = $this->descend( $member, $currentPath );
+ $descendants->addPages( $newDescendants );
+ // Re-set the path.
+ $currentPath = new Pages();
+ } else {
+ // If it's a page, add it to the list and carry on.
+ $descendants->addPage( $member );
+ $this->call( self::CALLBACK_PAGE, [ $member, $rootCat ] );
+ }
+ }
+ } while ( isset( $result['continue'] ) );
+ return $descendants;
+ }
+
+ /**
+ * Call all the registered callbacks of a particular type.
+ * @param int $type The callback type; should match one of the 'CALLBACK_' constants.
+ * @param mixed[] $params The parameters to pass to the callback function.
+ */
+ protected function call( $type, $params ) {
+ if ( !isset( $this->callbacks[$type] ) ) {
+ return;
+ }
+ foreach ( $this->callbacks[$type] as $callback ) {
+ if ( is_callable( $callback ) ) {
+ call_user_func_array( $callback, $params );
+ }
+ }
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/FileUploader.php b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/FileUploader.php
new file mode 100644
index 00000000..5ada5739
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/FileUploader.php
@@ -0,0 +1,139 @@
+<?php
+
+namespace Mediawiki\Api\Service;
+
+use Exception;
+use Mediawiki\Api\MultipartRequest;
+use Mediawiki\Api\SimpleRequest;
+
+/**
+ * @access private
+ *
+ * @author Addshore
+ */
+class FileUploader extends Service {
+
+ /** @var int */
+ protected $chunkSize;
+
+ /**
+ * Set the chunk size used for chunked uploading.
+ *
+ * Chunked uploading is available in MediaWiki 1.20 and above, although prior to version 1.25,
+ * SVGs could not be uploaded via chunked uploading.
+ *
+ * @link https://www.mediawiki.org/wiki/API:Upload#Chunked_uploading
+ *
+ * @param int $chunkSize In bytes.
+ */
+ public function setChunkSize( $chunkSize ) {
+ $this->chunkSize = $chunkSize;
+ }
+
+ /**
+ * Upload a file.
+ *
+ * @param string $targetName The name to give the file on the wiki (no 'File:' prefix required).
+ * @param string $location Can be local path or remote URL.
+ * @param string $text Initial page text for new files.
+ * @param string $comment Upload comment. Also used as the initial page text for new files if
+ * text parameter not provided.
+ * @param string $watchlist Unconditionally add or remove the page from your watchlist, use
+ * preferences or do not change watch. Possible values: 'watch', 'preferences', 'nochange'.
+ * @param bool $ignoreWarnings Ignore any warnings. This must be set to upload a new version of
+ * an existing image.
+ *
+ * @return bool
+ */
+ public function upload(
+ $targetName,
+ $location,
+ $text = '',
+ $comment = '',
+ $watchlist = 'preferences',
+ $ignoreWarnings = false
+ ) {
+ $params = [
+ 'filename' => $targetName,
+ 'token' => $this->api->getToken(),
+ ];
+ // Watchlist behaviour.
+ if ( in_array( $watchlist, [ 'watch', 'nochange' ] ) ) {
+ $params['watchlist'] = $watchlist;
+ }
+ // Ignore warnings?
+ if ( $ignoreWarnings ) {
+ $params['ignorewarnings'] = '1';
+ }
+ // Page text.
+ if ( !empty( $text ) ) {
+ $params['text'] = $text;
+ }
+ // Revision comment.
+ if ( !empty( $comment ) ) {
+ $params['comment'] = $comment;
+ }
+
+ if ( is_file( $location ) ) {
+ // Normal single-request upload.
+ $params['filesize'] = filesize( $location );
+ $params['file'] = fopen( $location, 'r' );
+ if ( is_int( $this->chunkSize ) && $this->chunkSize > 0 ) {
+ // Chunked upload.
+ $params = $this->uploadByChunks( $params );
+ }
+ } else {
+ // Upload from URL.
+ $params['url'] = $location;
+ }
+
+ $response = $this->api->postRequest( new SimpleRequest( 'upload', $params ) );
+ return ( $response['upload']['result'] === 'Success' );
+ }
+
+ /**
+ * Upload a file by chunks and get the parameters for the final upload call.
+ * @param mixed[] $params The request parameters.
+ * @return mixed[]
+ * @throws Exception
+ */
+ protected function uploadByChunks( $params ) {
+ // Get the file handle for looping, but don't keep it in the request parameters.
+ $fileHandle = $params['file'];
+ unset( $params['file'] );
+ // Track the chunks and offset.
+ $chunksDone = 0;
+ $params['offset'] = 0;
+ while ( true ) {
+
+ // 1. Make the request.
+ $params['chunk'] = fread( $fileHandle, $this->chunkSize );
+ $contentDisposition = 'form-data; name="chunk"; filename="' . $params['filename'] . '"';
+ $request = MultipartRequest::factory()
+ ->setParams( $params )
+ ->setAction( 'upload' )
+ ->setMultipartParams( [
+ 'chunk' => [ 'headers' => [ 'Content-Disposition' => $contentDisposition ] ],
+ ] );
+ $response = $this->api->postRequest( $request );
+
+ // 2. Deal with the response.
+ $chunksDone++;
+ $params['offset'] = ( $chunksDone * $this->chunkSize );
+ if ( !isset( $response['upload']['filekey'] ) ) {
+ // This should never happen. Even the last response still has the filekey.
+ throw new Exception( 'Unable to get filekey for chunked upload' );
+ }
+ $params['filekey'] = $response['upload']['filekey'];
+ if ( $response['upload']['result'] === 'Continue' ) {
+ // Amend parameters for next upload POST request.
+ $params['offset'] = $response['upload']['offset'];
+ } else {
+ // The final upload POST will be done in self::upload()
+ // to commit the upload out of the stash area.
+ unset( $params['chunk'], $params['offset'] );
+ return $params;
+ }
+ }
+ }
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/ImageRotator.php b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/ImageRotator.php
new file mode 100644
index 00000000..ba5624dc
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/ImageRotator.php
@@ -0,0 +1,56 @@
+<?php
+
+namespace Mediawiki\Api\Service;
+
+use Mediawiki\Api\SimpleRequest;
+use Mediawiki\Api\UsageException;
+use Mediawiki\DataModel\File;
+
+/**
+ * @access private
+ *
+ * @author Addshore
+ */
+class ImageRotator extends Service {
+
+ /**
+ * NOTE: This service has not been fully tested
+ *
+ * @param File $file
+ * @param int $rotation Degrees to rotate image clockwise, One value: 90, 180, 270
+ *
+ * @throws UsageException
+ * @return bool
+ */
+ public function rotate( File $file, $rotation ) {
+ $params = [
+ 'rotation' => $rotation,
+ 'token' => $this->api->getToken(),
+ ];
+
+ if ( !is_null( $file->getPageIdentifier()->getTitle() ) ) {
+ $params['titles'] = $file->getPageIdentifier()->getTitle()->getText();
+ } else {
+ $params['pageids'] = $file->getPageIdentifier()->getId();
+ }
+
+ $result = $this->api->postRequest( new SimpleRequest( 'imagerotate', $params ) );
+
+ // This module sometimes gives odd errors so deal with them..
+ if ( array_key_exists( 'imagerotate', $result ) ) {
+ $imageRotate = array_pop( $result['imagerotate'] );
+ if ( array_key_exists( 'result', $imageRotate ) &&
+ $imageRotate['result'] == 'Failure'
+ ) {
+ throw new UsageException(
+ 'imagerotate-Failure',
+ $imageRotate['errormessage'],
+ $result
+ );
+ }
+ }
+
+ return true;
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/LogListGetter.php b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/LogListGetter.php
new file mode 100644
index 00000000..d9394919
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/LogListGetter.php
@@ -0,0 +1,83 @@
+<?php
+
+namespace Mediawiki\Api\Service;
+
+use Mediawiki\Api\SimpleRequest;
+use Mediawiki\DataModel\Log;
+use Mediawiki\DataModel\LogList;
+use Mediawiki\DataModel\Page;
+use Mediawiki\DataModel\PageIdentifier;
+use Mediawiki\DataModel\Revisions;
+use Mediawiki\DataModel\Title;
+
+/**
+ * @access private
+ *
+ * @author Thomas Arrow
+ */
+class LogListGetter extends Service {
+
+ /**
+ * @param array $extraParams
+ *
+ * @return LogList
+ */
+ public function getLogList( array $extraParams = [] ) {
+ $logList = new LogList();
+
+ while ( true ) {
+ $params = [
+ 'list' => 'logevents',
+ 'leprop' => 'title|ids|type|user|timestamp|comment|details'
+ ];
+
+ $newParams = array_merge( $extraParams, $params );
+ $result = $this->api->getRequest( new SimpleRequest( 'query', $newParams ) );
+
+ foreach ( $result[ 'query' ]['logevents'] as $logevent ) {
+ $logList->addLog(
+ new Log(
+ $logevent['logid'],
+ $logevent['type'],
+ $logevent['action'],
+ $logevent['timestamp'],
+ $logevent['user'],
+ new Page(
+ new PageIdentifier(
+ new Title( $logevent['title'], $logevent['ns'] ),
+ $logevent['pageid']
+ ),
+ new Revisions()
+ ),
+ $logevent['comment'],
+ $this->getLogDetailsFromEvent( $logevent )
+ )
+ );
+ }
+
+ return $logList;
+ }
+ }
+
+ /**
+ * @param array $event
+ *
+ * @return array
+ */
+ private function getLogDetailsFromEvent( $event ) {
+ $ignoreKeys = array_flip( [
+ 'logid',
+ 'ns',
+ 'title',
+ 'pageid',
+ 'logpage',
+ 'type',
+ 'action',
+ 'user',
+ 'type',
+ 'timestamp',
+ 'comment' ] );
+ return array_diff_key( $event, $ignoreKeys );
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/NamespaceGetter.php b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/NamespaceGetter.php
new file mode 100644
index 00000000..c3f00030
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/NamespaceGetter.php
@@ -0,0 +1,108 @@
+<?php
+
+namespace Mediawiki\Api\Service;
+
+use Mediawiki\Api\SimpleRequest;
+use Mediawiki\DataModel\NamespaceInfo;
+
+/**
+ * @access private
+ *
+ * @author gbirke
+ */
+class NamespaceGetter extends Service {
+
+ /**
+ * Find a namespace by its canonical name
+ *
+ * @param string $canonicalName
+ * @return NamespaceInfo|null
+ */
+ public function getNamespaceByCanonicalName( $canonicalName ) {
+ $result = $this->getNamespaceResult()['query'];
+ foreach ( $result['namespaces'] as $nsInfo ) {
+ if ( !empty( $nsInfo['canonical'] ) && $nsInfo['canonical'] === $canonicalName ) {
+ return $this->createNamespaceFromQuery( $nsInfo, $result['namespacealiases'] );
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Find a namespace by its canonical name, local name or namespace alias
+ *
+ * @param string $name
+ * @return NamespaceInfo|null
+ */
+ public function getNamespaceByName( $name ) {
+ $result = $this->getNamespaceResult()['query'];
+ foreach ( $result['namespaces'] as $nsInfo ) {
+ if ( ( !empty( $nsInfo['canonical'] ) && $nsInfo['canonical'] === $name ) ||
+ $nsInfo['*'] === $name ) {
+ return $this->createNamespaceFromQuery( $nsInfo, $result['namespacealiases'] );
+ }
+ }
+ foreach ( $result['namespacealiases'] as $alias ) {
+ if ( $alias['*'] === $name && !empty( $result['namespaces'][$alias['id']] ) ) {
+ return $this->createNamespaceFromQuery(
+ $result['namespaces'][$alias['id']],
+ $result['namespacealiases']
+ );
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @return NamespaceInfo[]
+ */
+ public function getNamespaces() {
+ $namespaces = [];
+ $result = $this->getNamespaceResult()['query'];
+ foreach ( $result['namespaces'] as $nsInfo ) {
+ $namespaces[$nsInfo['id']] = $this->createNamespaceFromQuery(
+ $nsInfo, $result['namespacealiases']
+ );
+ }
+ return $namespaces;
+ }
+
+ private function createNamespaceFromQuery( $nsInfo, $namespaceAliases ) {
+ return new NamespaceInfo(
+ $nsInfo['id'],
+ empty( $nsInfo['canonical'] ) ? '' : $nsInfo['canonical'],
+ $nsInfo['*'],
+ $nsInfo['case'],
+ empty( $nsInfo['defaultcontentmodel'] ) ? null : $nsInfo['defaultcontentmodel'],
+ $this->getAliases( $nsInfo['id'], $namespaceAliases )
+ );
+ }
+
+ /**
+ * @param int $id
+ * @param array $namespaceAliases Alias list, as returned by the API
+ * @return string[]
+ */
+ private function getAliases( $id, $namespaceAliases ) {
+ $aliases = [];
+ foreach ( $namespaceAliases as $alias ) {
+ if ( $alias['id'] === $id ) {
+ $aliases[] = $alias['*'];
+ }
+ }
+ return $aliases;
+ }
+
+ /**
+ * @return array
+ */
+ private function getNamespaceResult() {
+ return $this->api->getRequest( new SimpleRequest(
+ 'query', [
+ 'meta' => 'siteinfo',
+ 'siprop' => 'namespaces|namespacealiases'
+ ]
+ ) );
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/PageDeleter.php b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/PageDeleter.php
new file mode 100644
index 00000000..60c43e30
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/PageDeleter.php
@@ -0,0 +1,105 @@
+<?php
+
+namespace Mediawiki\Api\Service;
+
+use Mediawiki\Api\SimpleRequest;
+use Mediawiki\DataModel\Page;
+use Mediawiki\DataModel\PageIdentifier;
+use Mediawiki\DataModel\Revision;
+use Mediawiki\DataModel\Title;
+
+/**
+ * @access private
+ *
+ * @author Addshore
+ */
+class PageDeleter extends Service {
+
+ /**
+ * @since 0.2
+ *
+ * @param Page $page
+ * @param array $extraParams
+ *
+ * @return bool
+ */
+ public function delete( Page $page, array $extraParams = [] ) {
+ $this->api->postRequest( new SimpleRequest(
+ 'delete',
+ $this->getDeleteParams( $page->getPageIdentifier(), $extraParams )
+ ) );
+ return true;
+ }
+
+ /**
+ * @since 0.2
+ *
+ * @param Revision $revision
+ * @param array $extraParams
+ *
+ * @return bool
+ */
+ public function deleteFromRevision( Revision $revision, array $extraParams = [] ) {
+ $this->api->postRequest( new SimpleRequest(
+ 'delete',
+ $this->getDeleteParams( $revision->getPageIdentifier(), $extraParams )
+ ) );
+ return true;
+ }
+
+ /**
+ * @since 0.2
+ *
+ * @param int $pageid
+ * @param array $extraParams
+ *
+ * @return bool
+ */
+ public function deleteFromPageId( $pageid, array $extraParams = [] ) {
+ $this->api->postRequest( new SimpleRequest(
+ 'delete',
+ $this->getDeleteParams( new PageIdentifier( null, $pageid ), $extraParams )
+ ) );
+ return true;
+ }
+
+ /**
+ * @since 0.5
+ *
+ * @param Title|string $title
+ * @param array $extraParams
+ *
+ * @return bool
+ */
+ public function deleteFromPageTitle( $title, array $extraParams = [] ) {
+ if ( is_string( $title ) ) {
+ $title = new Title( $title );
+ }
+ $this->api->postRequest( new SimpleRequest(
+ 'delete',
+ $this->getDeleteParams( new PageIdentifier( $title ), $extraParams )
+ ) );
+ return true;
+ }
+
+ /**
+ * @param PageIdentifier $identifier
+ * @param array $extraParams
+ *
+ * @return array
+ */
+ private function getDeleteParams( PageIdentifier $identifier, $extraParams ) {
+ $params = [];
+
+ if ( !is_null( $identifier->getId() ) ) {
+ $params['pageid'] = $identifier->getId();
+ } else {
+ $params['title'] = $identifier->getTitle()->getTitle();
+ }
+
+ $params['token'] = $this->api->getToken( 'delete' );
+
+ return array_merge( $extraParams, $params );
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/PageGetter.php b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/PageGetter.php
new file mode 100644
index 00000000..6c5c54cf
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/PageGetter.php
@@ -0,0 +1,246 @@
+<?php
+
+namespace Mediawiki\Api\Service;
+
+use Mediawiki\Api\SimpleRequest;
+use Mediawiki\DataModel\Content;
+use Mediawiki\DataModel\EditInfo;
+use Mediawiki\DataModel\Page;
+use Mediawiki\DataModel\PageIdentifier;
+use Mediawiki\DataModel\Revision;
+use Mediawiki\DataModel\Revisions;
+use Mediawiki\DataModel\Title;
+use RuntimeException;
+
+/**
+ * @access private
+ *
+ * @author Addshore
+ */
+class PageGetter extends Service {
+
+ /**
+ * @since 0.2
+ *
+ * @param int $id
+ * @param array $extraParams
+ *
+ * @return Page
+ */
+ public function getFromRevisionId( $id, array $extraParams = [] ) {
+ $result =
+ $this->api->getRequest(
+ new SimpleRequest(
+ 'query',
+ $this->getQuery( [ 'revids' => $id ], $extraParams )
+ )
+ );
+
+ return $this->newPageFromResult( array_shift( $result['query']['pages'] ) );
+ }
+
+ /**
+ * @since 0.2
+ *
+ * @param string|Title $title
+ * @param array $extraParams
+ *
+ * @return Page
+ */
+ public function getFromTitle( $title, array $extraParams = [] ) {
+ if ( $title instanceof Title ) {
+ $title = $title->getTitle();
+ }
+ $result =
+ $this->api->getRequest(
+ new SimpleRequest(
+ 'query',
+ $this->getQuery( [ 'titles' => $title ], $extraParams )
+ )
+ );
+
+ return $this->newPageFromResult( array_shift( $result['query']['pages'] ) );
+ }
+
+ /**
+ * @since 0.2
+ *
+ * @param int $id
+ * @param array $extraParams
+ *
+ * @return Page
+ */
+ public function getFromPageId( $id, array $extraParams = [] ) {
+ $result =
+ $this->api->getRequest(
+ new SimpleRequest(
+ 'query',
+ $this->getQuery( [ 'pageids' => $id ], $extraParams )
+ )
+ );
+
+ return $this->newPageFromResult( array_shift( $result['query']['pages'] ) );
+ }
+
+ /**
+ * @since 0.4
+ *
+ * @param PageIdentifier $pageIdentifier
+ * @param array $extraParams
+ *
+ * @throws RuntimeException
+ * @return Page
+ */
+ public function getFromPageIdentifier(
+ PageIdentifier $pageIdentifier,
+ array $extraParams = []
+ ) {
+ if ( !$pageIdentifier->identifiesPage() ) {
+ throw new RuntimeException( '$pageIdentifier does not identify a page' );
+ }
+ if ( !is_null( $pageIdentifier->getId() ) ) {
+ return $this->getFromPageId( $pageIdentifier->getId(), $extraParams );
+ } else {
+ return $this->getFromTitle( $pageIdentifier->getTitle(), $extraParams );
+ }
+ }
+
+ /**
+ * @since 0.2
+ *
+ * @param Page $page
+ * @param array $extraParams
+ *
+ * @return Page
+ */
+ public function getFromPage( Page $page, array $extraParams = [] ) {
+ $result =
+ $this->api->getRequest(
+ new SimpleRequest(
+ 'query',
+ $this->getQuery( [ 'pageids' => $page->getId() ], $extraParams )
+ )
+ );
+ $revisions = $this->getRevisionsFromResult( array_shift( $result['query']['pages'] ) );
+ $revisions->addRevisions( $page->getRevisions() );
+
+ return new Page(
+ $page->getPageIdentifier(),
+ $revisions
+ );
+ }
+
+ /**
+ * @since 0.2
+ *
+ * @param Revision $revision
+ * @param array $extraParams
+ *
+ * @return Page
+ */
+ public function getFromRevision( Revision $revision, array $extraParams = [] ) {
+ $result =
+ $this->api->getRequest(
+ new SimpleRequest(
+ 'query',
+ $this->getQuery( [ 'revids' => $revision->getId() ], $extraParams )
+ )
+ );
+ $revisions = $this->getRevisionsFromResult( array_shift( $result['query']['pages'] ) );
+ $revisions->addRevision( $revision );
+
+ return new Page(
+ new PageIdentifier(
+ new Title(
+ $result['title'],
+ $result['ns']
+ ),
+ $result['pageid']
+ ),
+ $revisions
+ );
+ }
+
+ /**
+ * @param array $additionalParams
+ *
+ * @param array $extraParams
+ *
+ * @return array
+ */
+ private function getQuery( $additionalParams, array $extraParams = [] ) {
+ $base = [
+ 'prop' => 'revisions|info|pageprops',
+ 'rvprop' => 'ids|flags|timestamp|user|size|sha1|comment|content|tags',
+ 'inprop' => 'protection',
+ ];
+
+ return array_merge( $extraParams, $base, $additionalParams );
+ }
+
+ /**
+ * @param array $array
+ *
+ * @return Revisions
+ */
+ private function getRevisionsFromResult( $array ) {
+ $revisions = new Revisions();
+ $pageid = $array['pageid'];
+ foreach ( $array['revisions'] as $revision ) {
+ $revisions->addRevision(
+ new Revision(
+ $this->getContent( $array['contentmodel'], $revision['*'] ),
+ new PageIdentifier( new Title( $array['title'], $array['ns'] ), $pageid ),
+ $revision['revid'],
+ new EditInfo(
+ $revision['comment'],
+ array_key_exists( 'minor', $revision ),
+ array_key_exists( 'bot', $revision )
+ ),
+ $revision['user'],
+ $revision['timestamp']
+ )
+ );
+ }
+
+ return $revisions;
+ }
+
+ /**
+ * @param string $model
+ * @param string $content returned from the API
+ *
+ * @throws RuntimeException
+ * @return Content
+ */
+ private function getContent( $model, $content ) {
+ return new Content( $content, $model );
+ }
+
+ /**
+ * @param array $array
+ *
+ * @return Page
+ */
+ private function newPageFromResult( $array ) {
+ if ( array_key_exists( 'pageid', $array ) ) {
+ $pageid = $array['pageid'];
+ $revisions = $this->getRevisionsFromResult( $array );
+ } else {
+ $pageid = 0;
+ $revisions = new Revisions();
+ }
+
+ return new Page(
+ new PageIdentifier(
+ new Title(
+ $array['title'],
+ $array['ns']
+ ),
+ $pageid
+ ),
+ $revisions
+ );
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/PageListGetter.php b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/PageListGetter.php
new file mode 100644
index 00000000..6b6d0007
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/PageListGetter.php
@@ -0,0 +1,147 @@
+<?php
+
+namespace Mediawiki\Api\Service;
+
+use Mediawiki\Api\SimpleRequest;
+use Mediawiki\DataModel\Page;
+use Mediawiki\DataModel\PageIdentifier;
+use Mediawiki\DataModel\Pages;
+use Mediawiki\DataModel\Title;
+
+/**
+ * @access private
+ *
+ * @author Addshore
+ */
+class PageListGetter extends Service {
+
+ /**
+ * Get the set of pages in a given category. Extra parameters can include:
+ * cmtype: default 'page|subcat|file'
+ * cmlimit: default 10, maximum 500 (5000 for bots)
+ *
+ * @link https://www.mediawiki.org/wiki/API:Categorymembers
+ * @since 0.3
+ *
+ * @param string $name
+ * @param array $extraParams
+ *
+ * @return Pages
+ */
+ public function getPageListFromCategoryName( $name, array $extraParams = [] ) {
+ $params = array_merge( $extraParams, [
+ 'list' => 'categorymembers',
+ 'cmtitle' => $name,
+ ] );
+ return $this->runQuery( $params, 'cmcontinue', 'categorymembers' );
+ }
+
+ /**
+ * List pages that transclude a certain page.
+ *
+ * @link https://www.mediawiki.org/wiki/API:Embeddedin
+ * @since 0.5
+ *
+ * @param string $pageName
+ * @param array $extraParams
+ *
+ * @return Pages
+ */
+ public function getPageListFromPageTransclusions( $pageName, array $extraParams = [] ) {
+ $params = array_merge( $extraParams, [
+ 'list' => 'embeddedin',
+ 'eititle' => $pageName,
+ ] );
+ return $this->runQuery( $params, 'eicontinue', 'embeddedin' );
+ }
+
+ /**
+ * Get all pages that link to the given page.
+ *
+ * @link https://www.mediawiki.org/wiki/API:Linkshere
+ * @since 0.5
+ * @uses PageListGetter::runQuery()
+ *
+ * @param string $pageName The page name
+ * @param string[] Any extra parameters to use: lhprop, lhnamespace, lhshow, lhlimit
+ *
+ * @return Pages
+ */
+ public function getFromWhatLinksHere( $pageName, $extraParams = [] ) {
+ $params = array_merge( $extraParams, [
+ 'prop' => 'info',
+ 'generator' => 'linkshere',
+ 'titles' => $pageName,
+ ] );
+ return $this->runQuery( $params, 'glhcontinue', 'pages' );
+ }
+
+ /**
+ * Get all pages that have the given prefix.
+ *
+ * @link https://www.mediawiki.org/wiki/API:Allpages
+ *
+ * @param string $prefix The page title prefix.
+ *
+ * @return Pages
+ */
+ public function getFromPrefix( $prefix ) {
+ $params = [
+ 'list' => 'allpages',
+ 'apprefix' => $prefix,
+ ];
+ return $this->runQuery( $params, 'apcontinue', 'allpages' );
+ }
+
+ /**
+ * Get up to 10 random pages.
+ *
+ * @link https://www.mediawiki.org/wiki/API:Random
+ * @uses PageListGetter::runQuery()
+ *
+ * @param array $extraParams
+ *
+ * @return Pages
+ */
+ public function getRandom( array $extraParams = [] ) {
+ $params = array_merge( $extraParams, [ 'list' => 'random' ] );
+ return $this->runQuery( $params, null, 'random', 'id', false );
+ }
+
+ /**
+ * Run a query to completion.
+ *
+ * @param string[] $params Query parameters
+ * @param string $contName Result subelement name for continue details
+ * @param string $resName Result element name for main results array
+ * @param string $pageIdName Result element name for page ID
+ * @param bool $cont Whether to continue the query, using multiple requests
+ * @return Pages
+ */
+ protected function runQuery( $params, $contName, $resName, $pageIdName = 'pageid', $cont = true ) {
+ $pages = new Pages();
+
+ do {
+ // Set up continue parameter if it's been set already.
+ if ( isset( $result['continue'][$contName] ) ) {
+ $params[$contName] = $result['continue'][$contName];
+ }
+
+ // Run the actual query.
+ $result = $this->api->getRequest( new SimpleRequest( 'query', $params ) );
+ if ( !array_key_exists( 'query', $result ) ) {
+ return $pages;
+ }
+
+ // Add the results to the output page list.
+ foreach ( $result['query'][$resName] as $member ) {
+ $pageTitle = new Title( $member['title'], $member['ns'] );
+ $page = new Page( new PageIdentifier( $pageTitle, $member[$pageIdName] ) );
+ $pages->addPage( $page );
+ }
+
+ } while ( $cont && isset( $result['continue'] ) );
+
+ return $pages;
+ }
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/PageMover.php b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/PageMover.php
new file mode 100644
index 00000000..f7eba2af
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/PageMover.php
@@ -0,0 +1,68 @@
+<?php
+
+namespace Mediawiki\Api\Service;
+
+use Mediawiki\Api\SimpleRequest;
+use Mediawiki\DataModel\Page;
+use Mediawiki\DataModel\Title;
+
+/**
+ * @access private
+ *
+ * @author Addshore
+ */
+class PageMover extends Service {
+
+ /**
+ * @since 0.2
+ *
+ * @param Page $page
+ * @param Title $target
+ * @param array $extraParams
+ *
+ * @return bool
+ */
+ public function move( Page $page, Title $target, array $extraParams = [] ) {
+ $this->api->postRequest(
+ new SimpleRequest(
+ 'move', $this->getMoveParams( $page->getId(), $target, $extraParams )
+ )
+ );
+
+ return true;
+ }
+
+ /**
+ * @since 0.2
+ *
+ * @param int $pageid
+ * @param Title $target
+ * @param array $extraParams
+ *
+ * @return bool
+ */
+ public function moveFromPageId( $pageid, Title $target, array $extraParams = [] ) {
+ $this->api->postRequest(
+ new SimpleRequest( 'move', $this->getMoveParams( $pageid, $target, $extraParams ) )
+ );
+
+ return true;
+ }
+
+ /**
+ * @param int $pageid
+ * @param Title $target
+ * @param array $extraParams
+ *
+ * @return array
+ */
+ private function getMoveParams( $pageid, $target, $extraParams ) {
+ $params = [];
+ $params['fromid'] = $pageid;
+ $params['to'] = $target->getTitle();
+ $params['token'] = $this->api->getToken( 'move' );
+
+ return array_merge( $extraParams, $params );
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/PageProtector.php b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/PageProtector.php
new file mode 100644
index 00000000..e3988e84
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/PageProtector.php
@@ -0,0 +1,55 @@
+<?php
+
+namespace Mediawiki\Api\Service;
+
+use InvalidArgumentException;
+use Mediawiki\Api\SimpleRequest;
+use Mediawiki\DataModel\Page;
+
+/**
+ * @access private
+ *
+ * @author Addshore
+ */
+class PageProtector extends Service {
+
+ /**
+ * @since 0.3
+ *
+ * @param Page $page
+ * @param string[] $protections where the 'key' is the action and the 'value' is the group
+ * @param array $extraParams
+ *
+ * @return bool
+ * @throws InvalidArgumentException
+ */
+ public function protect( Page $page, $protections, array $extraParams = [] ) {
+ if ( !is_array( $protections ) || empty( $protections ) ) {
+ throw new InvalidArgumentException(
+ '$protections must be an array with keys and values'
+ );
+ }
+
+ $params = [
+ 'pageid' => $page->getId(),
+ 'token' => $this->api->getToken( 'protect' ),
+ ];
+ $protectionsString = '';
+ foreach ( $protections as $action => $value ) {
+ if ( !is_string( $action ) || !is_string( $value ) ) {
+ throw new InvalidArgumentException(
+ 'All keys and elements of $protections must be strings'
+ );
+ }
+ $protectionsString = $action . '=' . $value . '|';
+ }
+ $params['protections'] = rtrim( $protectionsString, '|' );
+
+ $this->api->postRequest(
+ new SimpleRequest( 'protect', array_merge( $extraParams, $params ) )
+ );
+
+ return true;
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/PagePurger.php b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/PagePurger.php
new file mode 100644
index 00000000..6f9057f1
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/PagePurger.php
@@ -0,0 +1,116 @@
+<?php
+
+namespace Mediawiki\Api\Service;
+
+use Mediawiki\Api\Generator\ApiGenerator;
+use Mediawiki\Api\SimpleRequest;
+use Mediawiki\DataModel\Pages;
+use Mediawiki\DataModel\Page;
+
+/**
+ * @access private
+ *
+ * @author Addshore
+ * @author Thomas Arrow
+ */
+class PagePurger extends Service {
+
+ /**
+ * @since 0.3
+ *
+ * @brief Purge a single page
+ *
+ * Purges a single page by submitting a
+ * 'purge' action to the mediawiki api
+ * with the parameter 'pageids' set to
+ * the singe page id
+ *
+ * @param Page $page the page that is going to be purged
+ *
+ * @return bool return true if the purge was successful
+ */
+ public function purge( Page $page ) {
+ $responseArray = $this->api->postRequest(
+ new SimpleRequest( 'purge', [ 'pageids' => $page->getId() ] )
+ );
+
+ // the purge response for the page
+ $purgeResponse = $responseArray['purge'][0];
+
+ return array_key_exists( 'purged', $purgeResponse );
+ }
+
+ /**
+ * @since 0.7
+ *
+ * @brief Purge multiple pages
+ *
+ * Purges all the pages of the Pages object
+ * by submitting a 'purge' action to the mediawiki
+ * api with the parameter 'pageids' set to be the
+ * pages ids in multiple-value seperation.
+ *
+ * @param Pages $pages the pages that are going to be purged
+ *
+ * @return Pages the pages that have been purged successfully
+ */
+ public function purgePages( Pages $pages ) {
+ $pagesArray = $pages->toArray();
+ $pagesIds = [];
+
+ foreach ( $pagesArray as $page ) {
+ array_push( $pagesIds, $page->getId() );
+ }
+
+ // convert an array to multiple-value format
+ // because the mediawiki api require multiple
+ // values to be seperated like the example
+ // ex: [111, 222, 333] => "111|222|333"
+ $pageIdsMultiple = implode( '|', $pagesIds );
+
+ $responseArray = $this->api->postRequest(
+ new SimpleRequest( 'purge', [ 'pageids' => $pageIdsMultiple ] )
+ );
+
+ // array that will hold the successfully purged pages
+ $purgedPages = new Pages();
+
+ // for every purge result
+ foreach ( $responseArray['purge'] as $purgeResponse ) {
+ // if the purge for the page was successful
+ if ( array_key_exists( 'purged', $purgeResponse ) ) {
+ // we iterate all the input pages
+ foreach ( $pagesArray as $page ) {
+ // and if the page from the input was successfully purged
+ if ( $purgeResponse['title'] === $page->getTitle()->getText() ) {
+ // add it in the purgedPages object
+ $purgedPages->addPage( $page );
+
+ break;
+ }
+
+ }
+
+ }
+
+ }
+
+ return $purgedPages;
+ }
+
+ /**
+ * @since 0.6
+ *
+ * @param ApiGenerator $generator
+ *
+ * @return bool
+ */
+ public function purgeGenerator( ApiGenerator $generator ) {
+ $this->api->postRequest(
+ new SimpleRequest( 'purge', $generator->getParams() )
+ );
+
+ return true;
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/PageRestorer.php b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/PageRestorer.php
new file mode 100644
index 00000000..a422bd97
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/PageRestorer.php
@@ -0,0 +1,76 @@
+<?php
+
+namespace Mediawiki\Api\Service;
+
+use Mediawiki\Api\SimpleRequest;
+use Mediawiki\DataModel\Page;
+use Mediawiki\DataModel\Title;
+use OutOfBoundsException;
+
+/**
+ * @access private
+ *
+ * @author Addshore
+ */
+class PageRestorer extends Service {
+
+ /**
+ * @since 0.3
+ *
+ * @param Page $page
+ * @param array $extraParams
+ *
+ * @return bool
+ */
+ public function restore( Page $page, array $extraParams = [] ) {
+ $this->api->postRequest(
+ new SimpleRequest(
+ 'undelete',
+ $this->getUndeleteParams( $page->getTitle(), $extraParams )
+ )
+ );
+
+ return true;
+ }
+
+ /**
+ * @param Title $title
+ * @param array $extraParams
+ *
+ * @return array
+ */
+ private function getUndeleteParams( Title $title, $extraParams ) {
+ $params = [];
+
+ $params['title'] = $title->getTitle();
+ $params['token'] = $this->getUndeleteToken( $title );
+
+ return array_merge( $extraParams, $params );
+ }
+
+ /**
+ * @param Title $title
+ *
+ * @throws OutOfBoundsException
+ * @returns string
+ */
+ private function getUndeleteToken( Title $title ) {
+ $response = $this->api->postRequest(
+ new SimpleRequest(
+ 'query', [
+ 'list' => 'deletedrevs',
+ 'titles' => $title->getTitle(),
+ 'drprop' => 'token',
+ ]
+ )
+ );
+ if ( array_key_exists( 'token', $response['query']['deletedrevs'][0] ) ) {
+ return $response['query']['deletedrevs'][0]['token'];
+ } else {
+ throw new OutOfBoundsException(
+ 'Could not get page undelete token from list=deletedrevs query'
+ );
+ }
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/PageWatcher.php b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/PageWatcher.php
new file mode 100644
index 00000000..e7afab17
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/PageWatcher.php
@@ -0,0 +1,37 @@
+<?php
+
+namespace Mediawiki\Api\Service;
+
+use Mediawiki\Api\SimpleRequest;
+use Mediawiki\DataModel\Page;
+
+/**
+ * @access private
+ *
+ * @author Addshore
+ */
+class PageWatcher extends Service {
+
+ /**
+ * @param Page $page
+ *
+ * @return bool
+ */
+ public function watch( Page $page ) {
+ $params = [
+ 'token' => $this->api->getToken( 'watch' ),
+ ];
+ if ( !is_null( $page->getPageIdentifier()->getId() ) ) {
+ $params['pageids'] = $page->getPageIdentifier()->getId();
+ } elseif ( !is_null( $page->getPageIdentifier()->getTitle() ) ) {
+ $params['titles'] = $page->getPageIdentifier()->getTitle()->getTitle();
+ } elseif ( !is_null( $page->getRevisions()->getLatest() ) ) {
+ $params['revids'] = $page->getRevisions()->getLatest()->getId();
+ }
+
+ $this->api->postRequest( new SimpleRequest( 'watch', $params ) );
+
+ return true;
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/Parser.php b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/Parser.php
new file mode 100644
index 00000000..da83e39e
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/Parser.php
@@ -0,0 +1,47 @@
+<?php
+
+namespace Mediawiki\Api\Service;
+
+use GuzzleHttp\Promise\PromiseInterface;
+use Mediawiki\Api\SimpleRequest;
+use Mediawiki\DataModel\PageIdentifier;
+
+/**
+ * @access private
+ *
+ * @author Addshore
+ */
+class Parser extends Service {
+
+ /**
+ * @param PageIdentifier $pageIdentifier
+ *
+ * @return array the parse result (raw from the api)
+ */
+ public function parsePage( PageIdentifier $pageIdentifier ) {
+ return $this->parsePageAsync( $pageIdentifier )->wait();
+ }
+
+ /**
+ * @param PageIdentifier $pageIdentifier
+ *
+ * @return PromiseInterface of array the parse result (raw from the api)
+ */
+ public function parsePageAsync( PageIdentifier $pageIdentifier ) {
+ $params = [];
+ if ( $pageIdentifier->getId() !== null ) {
+ $params['pageid'] = $pageIdentifier->getId();
+ } elseif ( $pageIdentifier->getTitle() !== null ) {
+ $params['page'] = $pageIdentifier->getTitle()->getText();
+ } else {
+ throw new \RuntimeException( 'No way to identify page' );
+ }
+
+ $promise = $this->api->getRequestAsync( new SimpleRequest( 'parse', $params ) );
+
+ return $promise->then( function ( $result ) {
+ return $result['parse'];
+ } );
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/RevisionDeleter.php b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/RevisionDeleter.php
new file mode 100644
index 00000000..b12a7278
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/RevisionDeleter.php
@@ -0,0 +1,39 @@
+<?php
+
+namespace Mediawiki\Api\Service;
+
+use Mediawiki\Api\SimpleRequest;
+use Mediawiki\DataModel\Revision;
+
+/**
+ * @access private
+ *
+ * @author Addshore
+ */
+class RevisionDeleter extends Service {
+
+ /**
+ * @since 0.5
+ *
+ * @param Revision $revision
+ *
+ * @return bool
+ */
+ public function delete( Revision $revision ) {
+ $params = [
+ 'type' => 'revision',
+ 'hide' => 'content',
+ // Note: pre 1.24 this is a delete token, post it is csrf
+ 'token' => $this->api->getToken( 'delete' ),
+ 'ids' => $revision->getId(),
+ ];
+
+ $this->api->postRequest( new SimpleRequest(
+ 'revisiondelete',
+ $params
+ ) );
+
+ return true;
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/RevisionPatroller.php b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/RevisionPatroller.php
new file mode 100644
index 00000000..e642fd96
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/RevisionPatroller.php
@@ -0,0 +1,47 @@
+<?php
+
+namespace Mediawiki\Api\Service;
+
+use Mediawiki\Api\SimpleRequest;
+use Mediawiki\DataModel\Revision;
+
+/**
+ * @access private
+ *
+ * @author Addshore
+ */
+class RevisionPatroller extends Service {
+
+ /**
+ * @since 0.3
+ *
+ * @param Revision $revision
+ *
+ * @return bool success
+ */
+ public function patrol( Revision $revision ) {
+ $this->api->postRequest( new SimpleRequest(
+ 'patrol', [
+ 'revid' => $revision->getId(),
+ 'token' => $this->getTokenForRevision( $revision ),
+ ] ) );
+ return true;
+ }
+
+ /**
+ * @param Revision $revision
+ *
+ * @returns string
+ */
+ private function getTokenForRevision( Revision $revision ) {
+ $result = $this->api->postRequest( new SimpleRequest( 'query', [
+ 'list' => 'recentchanges',
+ 'rcstart' => $revision->getTimestamp(),
+ 'rcend' => $revision->getTimestamp(),
+ 'rctoken' => 'patrol',
+ ] ) );
+ $result = array_shift( $result['query']['recentchanges'] );
+ return $result['patroltoken'];
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/RevisionRestorer.php b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/RevisionRestorer.php
new file mode 100644
index 00000000..fb82c252
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/RevisionRestorer.php
@@ -0,0 +1,39 @@
+<?php
+
+namespace Mediawiki\Api\Service;
+
+use Mediawiki\Api\SimpleRequest;
+use Mediawiki\DataModel\Revision;
+
+/**
+ * @access private
+ *
+ * @author Addshore
+ */
+class RevisionRestorer extends Service {
+
+ /**
+ * @since 0.5
+ *
+ * @param Revision $revision
+ *
+ * @return bool
+ */
+ public function restore( Revision $revision ) {
+ $params = [
+ 'type' => 'revision',
+ 'show' => 'content',
+ // Note: pre 1.24 this is a delete token, post it is csrf
+ 'token' => $this->api->getToken( 'delete' ),
+ 'ids' => $revision->getId(),
+ ];
+
+ $this->api->postRequest( new SimpleRequest(
+ 'revisiondelete',
+ $params
+ ) );
+
+ return true;
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/RevisionRollbacker.php b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/RevisionRollbacker.php
new file mode 100644
index 00000000..76a2f5c7
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/RevisionRollbacker.php
@@ -0,0 +1,73 @@
+<?php
+
+namespace Mediawiki\Api\Service;
+
+use Mediawiki\Api\SimpleRequest;
+use Mediawiki\DataModel\Revision;
+use Mediawiki\DataModel\Title;
+
+/**
+ * @access private
+ *
+ * @author Addshore
+ */
+class RevisionRollbacker extends Service {
+
+ /**
+ * @since 0.3
+ *
+ * @param Revision $revision
+ * @param Title $title if using MW 1.24 of lower (https://gerrit.wikimedia.org/r/#/c/133063/)
+ *
+ * @return bool
+ */
+ public function rollback( Revision $revision, Title $title = null ) {
+ $this->api->postRequest(
+ new SimpleRequest( 'rollback', $this->getRollbackParams( $revision, $title ) )
+ );
+
+ return true;
+ }
+
+ /**
+ * @param Revision $revision
+ * @param Title|null $title
+ *
+ * @return array
+ */
+ private function getRollbackParams( Revision $revision, $title ) {
+ $params = [];
+ if ( !is_null( $title ) ) {
+ // This is needed prior to https://gerrit.wikimedia.org/r/#/c/133063/
+ $params['title'] = $title->getTitle();
+ } else {
+ // This will work after https://gerrit.wikimedia.org/r/#/c/133063/
+ $params['pageid'] = $revision->getPageId();
+ }
+ $params['user'] = $revision->getUser();
+ $params['token'] = $this->getTokenForRevision( $revision );
+
+ return $params;
+ }
+
+ /**
+ * @param Revision $revision
+ *
+ * @returns string
+ */
+ private function getTokenForRevision( Revision $revision ) {
+ $result = $this->api->postRequest(
+ new SimpleRequest(
+ 'query', [
+ 'prop' => 'revisions',
+ 'revids' => $revision->getId(),
+ 'rvtoken' => 'rollback',
+ ]
+ )
+ );
+ $result = array_shift( $result['query']['pages'] );
+
+ return $result['revisions'][0]['rollbacktoken'];
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/RevisionSaver.php b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/RevisionSaver.php
new file mode 100644
index 00000000..00b91ee6
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/RevisionSaver.php
@@ -0,0 +1,96 @@
+<?php
+
+namespace Mediawiki\Api\Service;
+
+use Mediawiki\Api\SimpleRequest;
+use Mediawiki\DataModel\EditInfo;
+use Mediawiki\DataModel\Revision;
+use RuntimeException;
+
+/**
+ * @access private
+ *
+ * @author Addshore
+ * @author DFelten (EditInfo fix)
+ */
+class RevisionSaver extends Service {
+
+ /**
+ * @since 0.2
+ *
+ * @param Revision $revision
+ * @param EditInfo $editInfo
+ *
+ * @return bool success
+ */
+ public function save( Revision $revision, EditInfo $editInfo = null ) {
+ $editInfo = $editInfo ? $editInfo : $revision->getEditInfo();
+
+ $result = $this->api->postRequest(
+ new SimpleRequest( 'edit', $this->getEditParams( $revision, $editInfo ) )
+ );
+ return ( $result['edit']['result'] == 'Success' );
+ }
+
+ /**
+ * @param Revision $revision
+ * @param EditInfo $editInfo
+ *
+ * @throws RuntimeException
+ * @returns array
+ */
+ private function getEditParams( Revision $revision, EditInfo $editInfo = null ) {
+ if ( !$revision->getPageIdentifier()->identifiesPage() ) {
+ throw new RuntimeException( '$revision PageIdentifier does not identify a page' );
+ }
+
+ $params = [];
+
+ $content = $revision->getContent();
+ $data = $content->getData();
+ if ( !is_string( $data ) ) {
+ throw new RuntimeException( 'Dont know how to save content of this model.' );
+ }
+ $params['text'] = $content->getData();
+ $params['md5'] = md5( $content->getData() );
+
+ $timestamp = $revision->getTimestamp();
+ if ( !is_null( $timestamp ) ) {
+ $params['basetimestamp'] = $timestamp;
+ }
+
+ if ( !is_null( $revision->getPageIdentifier()->getId() ) ) {
+ $params['pageid'] = $revision->getPageIdentifier()->getId();
+ } else {
+ $params['title'] = $revision->getPageIdentifier()->getTitle()->getTitle();
+ }
+
+ $params['token'] = $this->api->getToken();
+
+ if ( $this->api->isLoggedin() ) {
+ $params['assert'] = 'user';
+ }
+
+ $this->addEditInfoParams( $editInfo, $params );
+
+ return $params;
+ }
+
+ /**
+ * @param null|EditInfo $editInfo
+ * @param array &$params
+ */
+ private function addEditInfoParams( $editInfo, &$params ) {
+ if ( !is_null( $editInfo ) ) {
+ $params['summary'] = $editInfo->getSummary();
+ if ( $editInfo->getMinor() ) {
+ $params['minor'] = true;
+ }
+ if ( $editInfo->getBot() ) {
+ $params['bot'] = true;
+ $params['assert'] = 'bot';
+ }
+ }
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/RevisionUndoer.php b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/RevisionUndoer.php
new file mode 100644
index 00000000..e411030e
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/RevisionUndoer.php
@@ -0,0 +1,48 @@
+<?php
+
+namespace Mediawiki\Api\Service;
+
+use Mediawiki\Api\SimpleRequest;
+use Mediawiki\DataModel\Revision;
+
+/**
+ * @access private
+ *
+ * @author Addshore
+ */
+class RevisionUndoer extends Service {
+
+ /**
+ * @param Revision $revision
+ *
+ * @return bool
+ */
+ public function undo( Revision $revision ) {
+ $this->api->postRequest( new SimpleRequest(
+ 'edit',
+ $this->getParamsFromRevision( $revision )
+ ) );
+ return true;
+ }
+
+ /**
+ * @param Revision $revision
+ *
+ * @return array
+ */
+ private function getParamsFromRevision( Revision $revision ) {
+ $params = [
+ 'undo' => $revision->getId(),
+ 'token' => $this->api->getToken(),
+ ];
+
+ if ( !is_null( $revision->getPageIdentifier()->getId() ) ) {
+ $params['pageid'] = $revision->getPageIdentifier()->getId();
+ } else {
+ $params['title'] = $revision->getPageIdentifier()->getTitle()->getTitle();
+ }
+
+ return $params;
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/Service.php b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/Service.php
new file mode 100644
index 00000000..4a4b466b
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/Service.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace MediaWiki\Api\Service;
+
+use Mediawiki\Api\MediawikiApi;
+
+/**
+ * The base service functions that all services inherit.
+ * @since 0.7.2
+ */
+abstract class Service {
+
+ /** @var MediawikiApi */
+ protected $api;
+
+ /**
+ * @param MediawikiApi $api The API to in for this service.
+ */
+ public function __construct( MediawikiApi $api ) {
+ $this->api = $api;
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/UserBlocker.php b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/UserBlocker.php
new file mode 100644
index 00000000..9cf9f421
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/UserBlocker.php
@@ -0,0 +1,45 @@
+<?php
+
+namespace Mediawiki\Api\Service;
+
+use InvalidArgumentException;
+use Mediawiki\Api\SimpleRequest;
+use Mediawiki\DataModel\User;
+
+/**
+ * @access private
+ *
+ * @author Addshore
+ */
+class UserBlocker extends Service {
+
+ /**
+ * @since 0.3
+ *
+ * @param User|string $user
+ * @param array $extraParams
+ *
+ * @throws InvalidArgumentException
+ * @return bool
+ */
+ public function block( $user, array $extraParams = [] ) {
+ if ( !$user instanceof User && !is_string( $user ) ) {
+ throw new InvalidArgumentException( '$user must be either a string or User object' );
+ }
+
+ if ( $user instanceof User ) {
+ $user = $user->getName();
+ }
+
+ $params = [
+ 'user' => $user,
+ 'token' => $this->api->getToken( 'block' ),
+ ];
+
+ $params = array_merge( $extraParams, $params );
+
+ $this->api->postRequest( new SimpleRequest( 'block', $params ) );
+ return true;
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/UserCreator.php b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/UserCreator.php
new file mode 100644
index 00000000..8d74b107
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/UserCreator.php
@@ -0,0 +1,83 @@
+<?php
+
+namespace Mediawiki\Api\Service;
+
+use InvalidArgumentException;
+use Mediawiki\Api\SimpleRequest;
+use Mediawiki\Api\UsageException;
+
+/**
+ * @access private
+ *
+ * @author Addshore
+ */
+class UserCreator extends Service {
+
+ /**
+ * @param string $username
+ * @param string $password
+ * @param string|null $email
+ *
+ * @return bool
+ */
+ public function create( $username, $password, $email = null ) {
+ if ( !is_string( $username ) ) {
+ throw new InvalidArgumentException( '$username should be a string' );
+ }
+ if ( !is_string( $password ) ) {
+ throw new InvalidArgumentException( '$password should be a string' );
+ }
+ if ( !is_string( $email ) && !is_null( $email ) ) {
+ throw new InvalidArgumentException( '$email should be a string or null' );
+ }
+
+ $params = [
+ 'createreturnurl' => $this->api->getApiUrl(),
+ 'createtoken' => $this->api->getToken( 'createaccount' ),
+ 'username' => $username,
+ 'password' => $password,
+ 'retype' => $password,
+ ];
+
+ if ( !is_null( $email ) ) {
+ $params['email'] = $email;
+ }
+
+ try {
+ $result = $this->api->postRequest( new SimpleRequest( 'createaccount', $params ) );
+ return $result['createaccount']['status'] === 'PASS';
+ } catch ( UsageException $exception ) {
+ // If the above request failed, try again in the old way.
+ if ( $exception->getApiCode() === 'noname' ) {
+ return $this->createPreOneTwentySeven( $params );
+ }
+ throw $exception;
+ }
+ }
+
+ /**
+ * Create a user in the pre 1.27 manner.
+ * @link https://www.mediawiki.org/wiki/API:Account_creation/pre-1.27
+ * @return bool
+ */
+ protected function createPreOneTwentySeven( $params ) {
+ $newParams = [
+ 'name' => $params['username'],
+ 'password' => $params['password'],
+ ];
+ if ( array_key_exists( 'email', $params ) ) {
+ $newParams['email'] = $params['email'];
+ }
+ // First get the token.
+ $tokenRequest = new SimpleRequest( 'createaccount', $newParams );
+ $result = $this->api->postRequest( $tokenRequest );
+ if ( $result['createaccount']['result'] == 'NeedToken' ) {
+ // Then send the token to create the account.
+ $newParams['token'] = $result['createaccount']['token'];
+ $request = new SimpleRequest( 'createaccount', $newParams );
+ $result = $this->api->postRequest( $request );
+ }
+ return ( $result['createaccount']['result'] === 'Success' );
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/UserGetter.php b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/UserGetter.php
new file mode 100644
index 00000000..d3bfbd5b
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/UserGetter.php
@@ -0,0 +1,63 @@
+<?php
+
+namespace Mediawiki\Api\Service;
+
+use Mediawiki\Api\SimpleRequest;
+use Mediawiki\DataModel\User;
+
+/**
+ * @access private
+ *
+ * @author Addshore
+ */
+class UserGetter extends Service {
+
+ /**
+ * @param string $username
+ *
+ * @return User
+ */
+ public function getFromUsername( $username ) {
+ $result = $this->api->getRequest(
+ new SimpleRequest(
+ 'query', [
+ 'list' => 'users',
+ 'ususers' => $username,
+ 'usprop' => 'gender|emailable|registration|editcount|rights|implicitgroups|groups|blockinfo',
+ ]
+ )
+ );
+
+ return $this->newUserFromListUsersResult( array_shift( $result['query']['users'] ) );
+ }
+
+ /**
+ * @param array $array
+ *
+ * @return User
+ */
+ private function newUserFromListUsersResult( $array ) {
+ if ( array_key_exists( 'userid', $array ) ) {
+ return new User(
+ $array['name'],
+ $array['userid'],
+ $array['editcount'],
+ $array['registration'],
+ [ 'groups' => $array['groups'], 'implicitgroups' => $array['implicitgroups'] ],
+ $array['rights'],
+ $array['gender']
+ );
+ } else {
+ return new User(
+ $array['name'],
+ 0,
+ 0,
+ '',
+ [ 'groups' => [], 'implicitgroups' => [] ],
+ [],
+ ''
+ );
+ }
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/UserRightsChanger.php b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/UserRightsChanger.php
new file mode 100644
index 00000000..4fbea9c1
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/src/Service/UserRightsChanger.php
@@ -0,0 +1,59 @@
+<?php
+
+namespace Mediawiki\Api\Service;
+
+use Mediawiki\Api\SimpleRequest;
+use Mediawiki\DataModel\User;
+
+/**
+ * @access private
+ *
+ * @author Addshore
+ */
+class UserRightsChanger extends Service {
+
+ /**
+ * @since 0.3
+ *
+ * @param User $user
+ * @param string[] $add
+ * @param string[] $remove
+ * @param array $extraParams
+ *
+ * @return bool
+ */
+ public function change(
+ User $user,
+ $add = [],
+ $remove = [],
+ array $extraParams = []
+ ) {
+ $result = $this->api->postRequest(
+ new SimpleRequest(
+ 'query', [
+ 'list' => 'users',
+ 'ustoken' => 'userrights',
+ 'ususers' => $user->getName(),
+ ]
+ )
+ );
+
+ $params = [
+ 'user' => $user->getName(),
+ 'token' => $result['query']['users'][0]['userrightstoken'],
+ ];
+ if ( !empty( $add ) ) {
+ $params['add'] = implode( '|', $add );
+ }
+ if ( !empty( $remove ) ) {
+ $params['remove'] = implode( '|', $remove );
+ }
+
+ $this->api->postRequest(
+ new SimpleRequest( 'userrights', array_merge( $extraParams, $params ) )
+ );
+
+ return true;
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/tests/fixtures/blue ℳ𝒲♥𝓊𝓃𝒾𝒸ℴ𝒹ℯ.png b/bin/reevotech/vendor/addwiki/mediawiki-api/tests/fixtures/blue ℳ𝒲♥𝓊𝓃𝒾𝒸ℴ𝒹ℯ.png
new file mode 100644
index 00000000..9f8efbc8
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/tests/fixtures/blue ℳ𝒲♥𝓊𝓃𝒾𝒸ℴ𝒹ℯ.png
Binary files differ
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/tests/fixtures/namespaces.json b/bin/reevotech/vendor/addwiki/mediawiki-api/tests/fixtures/namespaces.json
new file mode 100644
index 00000000..2933692a
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/tests/fixtures/namespaces.json
@@ -0,0 +1,241 @@
+{
+ "batchcomplete": "",
+ "query": {
+ "namespaces": {
+ "-2": {
+ "id": -2,
+ "case": "first-letter",
+ "canonical": "Media",
+ "*": "Medium"
+ },
+ "-1": {
+ "id": -1,
+ "case": "first-letter",
+ "canonical": "Special",
+ "*": "Spezial"
+ },
+ "0": {
+ "id": 0,
+ "case": "first-letter",
+ "content": "",
+ "*": ""
+ },
+ "1": {
+ "id": 1,
+ "case": "first-letter",
+ "subpages": "",
+ "canonical": "Talk",
+ "*": "Diskussion"
+ },
+ "2": {
+ "id": 2,
+ "case": "first-letter",
+ "subpages": "",
+ "canonical": "User",
+ "*": "Benutzer"
+ },
+ "3": {
+ "id": 3,
+ "case": "first-letter",
+ "subpages": "",
+ "canonical": "User talk",
+ "*": "Benutzer Diskussion"
+ },
+ "4": {
+ "id": 4,
+ "case": "first-letter",
+ "subpages": "",
+ "canonical": "Project",
+ "*": "Wikipedia"
+ },
+ "5": {
+ "id": 5,
+ "case": "first-letter",
+ "subpages": "",
+ "canonical": "Project talk",
+ "*": "Wikipedia Diskussion"
+ },
+ "6": {
+ "id": 6,
+ "case": "first-letter",
+ "canonical": "File",
+ "*": "Datei"
+ },
+ "7": {
+ "id": 7,
+ "case": "first-letter",
+ "subpages": "",
+ "canonical": "File talk",
+ "*": "Datei Diskussion"
+ },
+ "8": {
+ "id": 8,
+ "case": "first-letter",
+ "canonical": "MediaWiki",
+ "*": "MediaWiki"
+ },
+ "9": {
+ "id": 9,
+ "case": "first-letter",
+ "subpages": "",
+ "canonical": "MediaWiki talk",
+ "*": "MediaWiki Diskussion"
+ },
+ "10": {
+ "id": 10,
+ "case": "first-letter",
+ "canonical": "Template",
+ "*": "Vorlage"
+ },
+ "11": {
+ "id": 11,
+ "case": "first-letter",
+ "subpages": "",
+ "canonical": "Template talk",
+ "*": "Vorlage Diskussion"
+ },
+ "12": {
+ "id": 12,
+ "case": "first-letter",
+ "subpages": "",
+ "canonical": "Help",
+ "*": "Hilfe"
+ },
+ "13": {
+ "id": 13,
+ "case": "first-letter",
+ "subpages": "",
+ "canonical": "Help talk",
+ "*": "Hilfe Diskussion"
+ },
+ "14": {
+ "id": 14,
+ "case": "first-letter",
+ "subpages": "",
+ "canonical": "Category",
+ "*": "Kategorie"
+ },
+ "15": {
+ "id": 15,
+ "case": "first-letter",
+ "subpages": "",
+ "canonical": "Category talk",
+ "*": "Kategorie Diskussion"
+ },
+ "100": {
+ "id": 100,
+ "case": "first-letter",
+ "subpages": "",
+ "canonical": "Portal",
+ "*": "Portal"
+ },
+ "101": {
+ "id": 101,
+ "case": "first-letter",
+ "subpages": "",
+ "canonical": "Portal Diskussion",
+ "*": "Portal Diskussion"
+ },
+ "828": {
+ "id": 828,
+ "case": "first-letter",
+ "subpages": "",
+ "canonical": "Module",
+ "*": "Modul"
+ },
+ "829": {
+ "id": 829,
+ "case": "first-letter",
+ "subpages": "",
+ "canonical": "Module talk",
+ "*": "Modul Diskussion"
+ },
+ "2300": {
+ "id": 2300,
+ "case": "first-letter",
+ "canonical": "Gadget",
+ "*": "Gadget"
+ },
+ "2301": {
+ "id": 2301,
+ "case": "first-letter",
+ "canonical": "Gadget talk",
+ "*": "Gadget Diskussion"
+ },
+ "2302": {
+ "id": 2302,
+ "case": "case-sensitive",
+ "canonical": "Gadget definition",
+ "defaultcontentmodel": "GadgetDefinition",
+ "*": "Gadget-Definition"
+ },
+ "2303": {
+ "id": 2303,
+ "case": "case-sensitive",
+ "canonical": "Gadget definition talk",
+ "*": "Gadget-Definition Diskussion"
+ },
+ "2600": {
+ "id": 2600,
+ "case": "first-letter",
+ "canonical": "Topic",
+ "defaultcontentmodel": "flow-board",
+ "*": "Thema"
+ }
+ },
+ "namespacealiases": [
+ {
+ "id": 2,
+ "*": "Benutzerin"
+ },
+ {
+ "id": 3,
+ "*": "BD"
+ },
+ {
+ "id": 3,
+ "*": "Benutzerin Diskussion"
+ },
+ {
+ "id": 4,
+ "*": "WP"
+ },
+ {
+ "id": 5,
+ "*": "WD"
+ },
+ {
+ "id": 6,
+ "*": "Bild"
+ },
+ {
+ "id": 6,
+ "*": "Image"
+ },
+ {
+ "id": 7,
+ "*": "Bild Diskussion"
+ },
+ {
+ "id": 7,
+ "*": "Image talk"
+ },
+ {
+ "id": 12,
+ "*": "H"
+ },
+ {
+ "id": 13,
+ "*": "HD"
+ },
+ {
+ "id": 100,
+ "*": "P"
+ },
+ {
+ "id": 101,
+ "*": "PD"
+ }
+ ]
+ }
+} \ No newline at end of file
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/tests/integration/CategoryTraverserTest.php b/bin/reevotech/vendor/addwiki/mediawiki-api/tests/integration/CategoryTraverserTest.php
new file mode 100644
index 00000000..7161447d
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/tests/integration/CategoryTraverserTest.php
@@ -0,0 +1,203 @@
+<?php
+
+namespace Mediawiki\Api\Test;
+
+use Mediawiki\Api\CategoryLoopException;
+use Mediawiki\Api\Service\CategoryTraverser;
+use Mediawiki\DataModel\Page;
+use Mediawiki\DataModel\PageIdentifier;
+use Mediawiki\DataModel\Title;
+use Mediawiki\DataModel\Revision;
+use Mediawiki\DataModel\Content;
+
+class CategoryTraverserTest extends \PHPUnit_Framework_TestCase {
+
+ /** @var TestEnvironment */
+ protected $testEnvironment;
+
+ /** @var \Mediawiki\Api\MediawikiFactory */
+ protected $factory;
+
+ /** @var \Mediawiki\Api\Service\CategoryTraverser */
+ protected $traverser;
+
+ public function setUp() {
+ parent::setUp();
+ $this->testEnvironment = TestEnvironment::newDefault();
+ $this->factory = $this->testEnvironment->getFactory();
+ $this->traverser = $this->factory->newCategoryTraverser();
+ }
+
+ /**
+ * A convenience wrapper around a PageDeleter.
+ * @param string[] $titles The titles to delete.
+ */
+ public function deletePages( $titles ) {
+ $deleter = $this->factory->newPageDeleter();
+ foreach ( $titles as $t ) {
+ // @todo Properly delete?
+ // $deleter->deleteFromPageTitle( new Title( $t ) );
+ $this->savePage( $t, '' );
+ }
+ }
+
+ /**
+ * A convenience wrapper to a RevisionSaver.
+ * @param string $title The title of the new page.
+ * @param string $content The wikitext to save to the page.
+ * @return Page The saved Page.
+ */
+ protected function savePage( $title, $content ) {
+ $pageIdentifier = new PageIdentifier( new Title( $title ) );
+ $revision = new Revision( new Content( $content ), $pageIdentifier );
+ $this->factory->newRevisionSaver()->save( $revision );
+ return $this->factory->newPageGetter()->getFromPageIdentifier( $pageIdentifier );
+ }
+
+ /**
+ * Get a list of all pages in a category or any of its descendants.
+ */
+ public function testDescendants() {
+ $rootCat = $this->savePage( 'Category:Root category', '' );
+ $this->savePage( 'Category:Sub category B', '[[Category:Root category]]' );
+ $this->savePage( 'Category:Sub category C', '[[Category:Root category]]' );
+ $this->savePage( 'Test page A1', 'Testing. [[Category:Root category]]' );
+ $this->savePage( 'Test page B1', 'Testing. [[Category:Sub category B]]' );
+ $this->savePage( 'Test page B2', 'Testing. [[Category:Sub category B]]' );
+ $this->savePage( 'Test page C1', 'Testing. [[Category:Sub category C]]' );
+ $this->testEnvironment->runJobs();
+
+ $callback = function ( Page $pageInfo, Page $parentCat ) {
+ $parentCatName = $parentCat->getPageIdentifier()->getTitle()->getText();
+ $thisPageName = $pageInfo->getPageIdentifier()->getTitle()->getText();
+ if ( $parentCatName === 'Category:Root category' ) {
+ $this->assertEquals( 'Test page A1', $thisPageName );
+ }
+ if ( $parentCatName === 'Category:Sub category C' ) {
+ $this->assertEquals( 'Test page C1', $thisPageName );
+ }
+ };
+ $this->traverser->addCallback( CategoryTraverser::CALLBACK_PAGE, $callback );
+ $decendants = $this->traverser->descend( $rootCat );
+ $this->assertCount( 4, $decendants->toArray() );
+ $this->deletePages( [
+ 'Category:Root category',
+ 'Category:Sub category B',
+ 'Category:Sub category C',
+ 'Test page A1',
+ 'Test page B1',
+ 'Test page B2',
+ 'Test page C1',
+ ] );
+ }
+
+ /**
+ * Make sure there aren't duplicate results when there are multiple paths to
+ * the same page.
+ */
+ public function testDescendantsWithMultiplePaths() {
+ $grandparent = $this->savePage( 'Category:Grandparent', '' );
+ $this->savePage( 'Category:Parent 1', '[[Category:Grandparent]]' );
+ $this->savePage( 'Category:Parent 2', '[[Category:Grandparent]]' );
+ $this->savePage( 'Parent 1', '[[Category:Grandparent]]' );
+ $this->savePage( 'Child 1', '[[Category:Parent 1]]' );
+ $this->savePage( 'Child 2', '[[Category:Parent 1]]' );
+ $this->savePage( 'Child 3', '[[Category:Parent 2]]' );
+ $this->testEnvironment->runJobs();
+ $decendants = $this->traverser->descend( $grandparent );
+ $this->assertCount( 4, $decendants->toArray() );
+ $this->deletePages( [
+ 'Category:Grandparent',
+ 'Category:Parent 1',
+ 'Category:Parent 2',
+ 'Child 1',
+ 'Child 2',
+ 'Child 3',
+ ] );
+ }
+
+ /**
+ * Categories should only be traversed once. For example, in the following graph, 'C' can be
+ * reached as a child of 'A' or of 'B', but only the first arrival will proceed to 'D':
+ *
+ * A
+ * | \
+ * | B
+ * | /
+ * C
+ * |
+ * D
+ *
+ */
+ public function testDescendantsOnlyVisitCatsOnce() {
+ global $wgVisitedCats;
+ $wgVisitedCats = [];
+ $catA = $this->savePage( 'Category:A cat', '' );
+ $this->savePage( 'Category:B cat', 'Testing. [[Category:A cat]]' );
+ $this->savePage( 'Category:C cat', 'Testing. [[Category:A cat]][[Category:B cat]]' );
+ $this->savePage( 'Category:D cat', 'Testing. [[Category:C cat]]' );
+ $this->testEnvironment->runJobs();
+ $callback = function ( Page $pageInfo, Page $parentCat ) {
+ global $wgVisitedCats;
+ $wgVisitedCats[] = $parentCat->getPageIdentifier()->getTitle()->getText();
+ };
+ $this->traverser->addCallback( CategoryTraverser::CALLBACK_CATEGORY, $callback );
+ $descendants = $this->traverser->descend( $catA );
+ $this->assertCount( 0, $descendants->toArray() );
+ $this->assertCount( 3, $wgVisitedCats );
+ $this->deletePages( [
+ 'Category:A cat',
+ 'Category:B cat',
+ 'Category:C cat',
+ 'Category:D cat',
+ ] );
+ }
+
+ /**
+ * Category loops are caught on descent.
+ *
+ * E
+ * / \
+ * F G
+ * / \
+ * H I
+ * |
+ * E <-- throw an Exception when we get to this repetition
+ *
+ */
+ public function testDescendIntoLoop() {
+ $catA = $this->savePage( 'Category:E cat', '[[Category:H cat]]' );
+ $catB = $this->savePage( 'Category:F cat', '[[Category:E cat]]' );
+ $catC = $this->savePage( 'Category:G cat', '[[Category:E cat]]' );
+ $catD = $this->savePage( 'Category:H cat', '[[Category:F cat]]' );
+ $catE = $this->savePage( 'Category:I cat', '[[Category:F cat]]' );
+ $this->testEnvironment->runJobs();
+ $haveCaught = false;
+ try {
+ $this->traverser->descend( $catA );
+ } catch ( CategoryLoopException $ex ) {
+ $haveCaught = true;
+ $expectedCatLoop = [
+ 'Category:E cat',
+ 'Category:F cat',
+ 'Category:H cat',
+ ];
+ // Build a simplified representation of the thrown loop pages, to get around different
+ // revision IDs.
+ $actualCatLoop = [];
+ foreach ( $ex->getCategoryPath()->toArray() as $p ) {
+ $actualCatLoop[] = $p->getPageIdentifier()->getTitle()->getText();
+ }
+ $this->assertEquals( $expectedCatLoop, $actualCatLoop );
+ }
+ $this->assertTrue( $haveCaught );
+ $this->deletePages( [
+ 'Category:E cat',
+ 'Category:F cat',
+ 'Category:G cat',
+ 'Category:H cat',
+ 'Category:I cat',
+ ] );
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/tests/integration/FileUploaderTest.php b/bin/reevotech/vendor/addwiki/mediawiki-api/tests/integration/FileUploaderTest.php
new file mode 100755
index 00000000..e805ee1d
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/tests/integration/FileUploaderTest.php
@@ -0,0 +1,75 @@
+<?php
+
+namespace Mediawiki\Api\Test;
+
+use Mediawiki\Api\ApiUser;
+use Mediawiki\Api\MediawikiApi;
+use Mediawiki\Api\MediawikiFactory;
+use Mediawiki\Api\Service\FileUploader;
+use Mediawiki\Api\SimpleRequest;
+use Mediawiki\DataModel\Page;
+use Mediawiki\DataModel\PageIdentifier;
+use Mediawiki\DataModel\Title;
+use PHPUnit_Framework_TestCase;
+
+/**
+ * Test the \Mediawiki\Api\Service\FileUploader class.
+ */
+class FileUploaderTest extends PHPUnit_Framework_TestCase {
+
+ /** @var MediawikiFactory */
+ protected $factory;
+
+ /** @var FileUploader */
+ protected $fileUploader;
+
+ /**
+ * Create a FileUploader to use in all these tests.
+ */
+ public function setup() {
+ parent::setup();
+ $testEnvironment = TestEnvironment::newDefault();
+ $this->factory = $testEnvironment->getFactory();
+ $this->fileUploader = $this->factory->newFileUploader();
+
+ // Log in as the sysop user. These credentials are referenced in docs/contributing.rst.
+ $localApiUser = new ApiUser( 'admin', 'admin123' );
+ $api = $testEnvironment->getApi();
+ $api->login( $localApiUser );
+ }
+
+ public function testUpload() {
+ $testPagename = uniqid( 'file-uploader-test-' ) . '.png';
+ $testTitle = new Title( 'File:'.$testPagename );
+
+ // Check that the file doesn't exist yet.
+ $testFile = $this->factory->newPageGetter()->getFromTitle( $testTitle );
+ $this->assertEquals( 0, $testFile->getPageIdentifier()->getId() );
+
+ // Upload a file.
+ $testFilename = dirname( __DIR__ ) . '/fixtures/blue ℳ𝒲♥𝓊𝓃𝒾𝒸ℴ𝒹ℯ.png';
+ $uploaded = $this->fileUploader->upload( $testPagename, $testFilename, 'Testing',
+ null, null, true );
+ $this->assertTrue( $uploaded );
+
+ // Get the file again, and check that it exists this time.
+ $testFile2 = $this->factory->newPageGetter()->getFromTitle( $testTitle );
+ $this->assertGreaterThan( 0, $testFile2->getPageIdentifier()->getId() );
+ }
+
+ public function testUploadByChunks() {
+ $testPagename = uniqid( 'file-uploader-test-' ) . '.png';
+ $testTitle = new Title( 'File:'.$testPagename );
+
+ // Upload a 83725 byte file in 10k chunks.
+ $testFilename = dirname( __DIR__ ) . '/fixtures/blue ℳ𝒲♥𝓊𝓃𝒾𝒸ℴ𝒹ℯ.png';
+ $this->fileUploader->setChunkSize( 1024 * 10 );
+ $uploaded = $this->fileUploader->upload( $testPagename, $testFilename, 'Testing',
+ null, null, true );
+ $this->assertTrue( $uploaded );
+
+ // Get the file again, and check that it exists this time.
+ $testFile2 = $this->factory->newPageGetter()->getFromTitle( $testTitle );
+ $this->assertGreaterThan( 0, $testFile2->getPageIdentifier()->getId() );
+ }
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/tests/integration/NamespaceGetterTest.php b/bin/reevotech/vendor/addwiki/mediawiki-api/tests/integration/NamespaceGetterTest.php
new file mode 100644
index 00000000..eea55f9f
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/tests/integration/NamespaceGetterTest.php
@@ -0,0 +1,86 @@
+<?php
+
+namespace Mediawiki\Api\Test;
+
+use Mediawiki\Api\MediawikiApi;
+use Mediawiki\Api\Service\NamespaceGetter;
+use Mediawiki\Api\SimpleRequest;
+use Mediawiki\DataModel\NamespaceInfo;
+
+class NamespaceGetterTest extends \PHPUnit_Framework_TestCase {
+ public function testGetNamespaceByCanonicalNameReturnsNullIfNamespaceWasNotFound() {
+ $nsGetter = new NamespaceGetter( $this->getApi() );
+ $this->assertNull( $nsGetter->getNamespaceByCanonicalName( 'Dummy' ) );
+ }
+
+ public function testGetNamespaceByCanonicalNameReturnsNamespaceIfNamespaceWasFound() {
+ $nsGetter = new NamespaceGetter( $this->getApi() );
+ $expectedNamespace = new NamespaceInfo( 1, 'Talk', 'Diskussion', 'first-letter' );
+ $this->assertEquals( $expectedNamespace, $nsGetter->getNamespaceByCanonicalName( 'Talk' ) );
+ }
+
+ public function testGetNamespaceByNameTriesAllNames() {
+ $nsGetter = new NamespaceGetter( $this->getApi() );
+ $expectedNamespace = new NamespaceInfo( 1, 'Talk', 'Diskussion', 'first-letter' );
+ $this->assertEquals( $expectedNamespace, $nsGetter->getNamespaceByName( 'Talk' ) );
+ $this->assertEquals( $expectedNamespace, $nsGetter->getNamespaceByName( 'Diskussion' ) );
+ }
+
+ public function testGetNamespaceByNameTriesAliases() {
+ $nsGetter = new NamespaceGetter( $this->getApi() );
+ $expectedNamespace = new NamespaceInfo(
+ 3,
+ 'User talk',
+ 'Benutzer Diskussion',
+ 'first-letter',
+ null,
+ [ 'BD', 'Benutzerin Diskussion' ]
+ );
+ $this->assertEquals( $expectedNamespace, $nsGetter->getNamespaceByName(
+ 'Benutzerin Diskussion'
+ ) );
+ $this->assertEquals( $expectedNamespace, $nsGetter->getNamespaceByName( 'BD' ) );
+ }
+
+ public function testGetNamespacesReturnsAllNamespaces() {
+ $nsGetter = new NamespaceGetter( $this->getApi() );
+ $talkNamespace = new NamespaceInfo( 1, 'Talk', 'Diskussion', 'first-letter' );
+ $gadgetNamespace = new NamespaceInfo(
+ 2302,
+ 'Gadget definition',
+ 'Gadget-Definition',
+ 'case-sensitive',
+ 'GadgetDefinition'
+ );
+ $namespaces = $nsGetter->getNamespaces();
+ $this->assertCount( 27, $namespaces );
+ $this->assertArrayHasKey( 1, $namespaces );
+ $this->assertEquals( $talkNamespace, $namespaces[1] );
+ $this->assertArrayHasKey( 2302, $namespaces );
+ $this->assertEquals( $gadgetNamespace, $namespaces[2302] );
+ }
+
+ /**
+ * @return \PHPUnit_Framework_MockObject_MockObject|MediawikiApi
+ */
+ private function getApi() {
+ $api = $this->getMockBuilder( MediawikiApi::class )->disableOriginalConstructor()->getMock();
+ $api->expects( $this->any() )
+ ->method( 'getRequest' )
+ ->with( $this->getRequest() )
+ ->willReturn( $this->getNamespaceFixture() );
+ return $api;
+ }
+
+ private function getRequest() {
+ return new SimpleRequest(
+ 'query', [
+ 'meta' => 'siteinfo',
+ 'siprop' => 'namespaces|namespacealiases'
+ ] );
+ }
+
+ private function getNamespaceFixture() {
+ return json_decode( file_get_contents( __DIR__ . '/../fixtures/namespaces.json' ), true );
+ }
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/tests/integration/PageIntegrationTest.php b/bin/reevotech/vendor/addwiki/mediawiki-api/tests/integration/PageIntegrationTest.php
new file mode 100644
index 00000000..673eac8f
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/tests/integration/PageIntegrationTest.php
@@ -0,0 +1,66 @@
+<?php
+
+namespace Mediawiki\Api\Test;
+
+use Mediawiki\DataModel\Content;
+use Mediawiki\DataModel\PageIdentifier;
+use Mediawiki\DataModel\Revision;
+use Mediawiki\DataModel\Title;
+use PHPUnit_Framework_TestCase;
+
+/**
+ * @author Addshore
+ */
+class PageIntegrationTest extends PHPUnit_Framework_TestCase {
+
+ /**
+ * @var PageIdentifier
+ */
+ private static $localPageIdentifier;
+
+ public static function setUpBeforeClass() {
+ parent::setUpBeforeClass();
+ $title = new Title( 'TestPage - ' . strval( time() ) );
+ self::$localPageIdentifier = new PageIdentifier( $title );
+ }
+
+ public function testCreatePage() {
+ $factory = TestEnvironment::newDefault()->getFactory();
+ $this->assertTrue(
+ $factory->newRevisionSaver()->save(
+ new Revision(
+ new Content( 'testCreatePage_content' ),
+ self::$localPageIdentifier
+ )
+ ),
+ 'Failed to Create Page ' . self::$localPageIdentifier->getTitle()->getText()
+ );
+ }
+
+ /**
+ * This is testGetPageUsingTitle as currently we only know the title
+ * @depends testCreatePage
+ */
+ public function testGetPageUsingTitle() {
+ $factory = TestEnvironment::newDefault()->getFactory();
+ $page = $factory->newPageGetter()->getFromPageIdentifier( self::$localPageIdentifier );
+ $this->assertTrue( is_int( $page->getPageIdentifier()->getId() ) );
+ $title = $page->getPageIdentifier()->getTitle();
+ $this->assertEquals( self::$localPageIdentifier->getTitle(), $title );
+ $content = $page->getRevisions()->getLatest()->getContent()->getData();
+ $this->assertEquals( 'testCreatePage_content', $content );
+ self::$localPageIdentifier = $page->getPageIdentifier();
+ }
+
+ /**
+ * @depends testGetPageUsingTitle
+ */
+ public function testGetPageUsingId() {
+ $factory = TestEnvironment::newDefault()->getFactory();
+ $page = $factory->newPageGetter()->getFromPageId( self::$localPageIdentifier->getId() );
+ $this->assertEquals( self::$localPageIdentifier->getId(), $page->getPageIdentifier()->getId() );
+ $title = $page->getPageIdentifier()->getTitle();
+ $this->assertEquals( self::$localPageIdentifier->getTitle(), $title );
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/tests/integration/PageListGetterTest.php b/bin/reevotech/vendor/addwiki/mediawiki-api/tests/integration/PageListGetterTest.php
new file mode 100644
index 00000000..39a973a4
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/tests/integration/PageListGetterTest.php
@@ -0,0 +1,99 @@
+<?php
+
+namespace Mediawiki\Api\Test;
+
+use Mediawiki\DataModel\Content;
+use Mediawiki\DataModel\PageIdentifier;
+use Mediawiki\DataModel\Revision;
+use Mediawiki\DataModel\Title;
+use PHPUnit_Framework_TestCase;
+
+/**
+ * Test the \Mediawiki\Api\Service\PageListGetter class.
+ */
+class PageListGetterTest extends PHPUnit_Framework_TestCase {
+
+ /** @var string */
+ private $emptyCatName = 'Category:Empty category';
+
+ /** @var string */
+ private $nonemptyCatName = 'Category:Test category';
+
+ /** @var \Mediawiki\Api\Service\PageListGetter */
+ private $pageListGetter;
+
+ /**
+ * Set up some test categories and pages.
+ */
+ public function setUp() {
+ $testEnvironment = TestEnvironment::newDefault();
+ $factory = $testEnvironment->getFactory();
+
+ // An empty category.
+ $emptyCat = new PageIdentifier( new Title( $this->emptyCatName ) );
+ $factory->newRevisionSaver()->save( new Revision( new Content( '' ), $emptyCat ) );
+
+ // A non-empty category.
+ $testCat = new PageIdentifier( new Title( $this->nonemptyCatName ) );
+ $factory->newRevisionSaver()->save( new Revision( new Content( '' ), $testCat ) );
+
+ // Some pages in the latter.
+ // (Count must exceed the default categorymember result set size of 10.)
+ $revisionSaver = $factory->newRevisionSaver();
+ for ( $i = 1; $i <= 35; $i++ ) {
+ $testCat = new PageIdentifier( new Title( "Test page $i" ) );
+ // Even pages link to Main Page, odd pages transclude {{test}}.
+ $mainPageLink = ( ( $i % 2 ) == 0 ) ? 'Go to [[Main Page]].' : 'This is a {{test}}.';
+ $content = new Content( "$mainPageLink\n\n[[$this->nonemptyCatName]]" );
+ $revisionSaver->save( new Revision( $content, $testCat ) );
+ }
+
+ // Run all jobs, to make sure everything is up to date.
+ $testEnvironment->runJobs();
+
+ $this->pageListGetter = $factory->newPageListGetter();
+ }
+
+ public function testGetPageListFromCategoryName() {
+ // The empty category.
+ $emptyCategory = $this->pageListGetter->getPageListFromCategoryName( $this->emptyCatName );
+ $this->assertCount( 0, $emptyCategory->toArray() );
+
+ // The nonempty category.
+ $testCategory = $this->pageListGetter->getPageListFromCategoryName( $this->nonemptyCatName );
+ $this->assertCount( 35, $testCategory->toArray() );
+ }
+
+ public function testGetPageListFromPageTransclusions() {
+ $linksHere = $this->pageListGetter->getPageListFromPageTransclusions( 'Template:Test' );
+ // Only odd-numbered test pages link to the 'Test' template.
+ $this->assertCount( 18, $linksHere->toArray() );
+ }
+
+ public function testGetFromWhatLinksHere() {
+ // Every even-numbered test page links to Main Page.
+ $mainPageLinks = $this->pageListGetter->getFromWhatLinksHere( 'Main Page' );
+ $this->assertCount( 17, $mainPageLinks->toArray() );
+
+ // Nothing links to 'Test page 4'.
+ $testPageLinks = $this->pageListGetter->getFromWhatLinksHere( 'Test page 4' );
+ $this->assertCount( 0, $testPageLinks->toArray() );
+ }
+
+ public function testGetFromPrefix() {
+ // Pages with this prefix should be test pages 1, & 10-15; i.e. 7 of them.
+ $testPages = $this->pageListGetter->getFromPrefix( 'Test page 1' );
+ $this->assertCount( 11, $testPages->toArray() );
+ }
+
+ public function testGetRandom() {
+ // Default is 1.
+ $randomPages1 = $this->pageListGetter->getRandom();
+ $this->assertCount( 1, $randomPages1->toArray() );
+
+ // 8 random pages.
+ $randomPages2 = $this->pageListGetter->getRandom( [ 'rnlimit' => 8 ] );
+ $this->assertCount( 8, $randomPages2->toArray() );
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/tests/integration/TestEnvironment.php b/bin/reevotech/vendor/addwiki/mediawiki-api/tests/integration/TestEnvironment.php
new file mode 100644
index 00000000..f40c0cd9
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/tests/integration/TestEnvironment.php
@@ -0,0 +1,116 @@
+<?php
+
+namespace Mediawiki\Api\Test;
+
+use Mediawiki\Api\Guzzle\ClientFactory;
+use Mediawiki\Api\MediawikiApi;
+use Mediawiki\Api\MediawikiFactory;
+use Mediawiki\Api\SimpleRequest;
+use Monolog\Handler\StreamHandler;
+use Monolog\Logger;
+
+/**
+ * @author Addshore
+ */
+class TestEnvironment {
+
+ /** @var \Mediawiki\Api\MediawikiFactory */
+ private $factory;
+
+ /** @var MediawikiApi */
+ protected $api;
+
+ /**
+ * Get a new default test environment.
+ * @return TestEnvironment
+ */
+ public static function newDefault() {
+ return new self();
+ }
+
+ /**
+ * Set up the test environment by creating a new API object pointing to a
+ * MediaWiki installation on localhost (or elsewhere as specified by the
+ * MEDIAWIKI_API_URL environment variable).
+ */
+ public function __construct() {
+ $this->factory = new MediawikiFactory( $this->getApi() );
+ }
+
+ /**
+ * Get the MediawikiApi to test against, based on the MEDIAWIKI_API_URL environment variable.
+ * @return MediawikiApi
+ * @throws \Exception If the MEDIAWIKI_API_URL environment variable does not end in 'api.php'
+ */
+ public function getApi() {
+ if ( $this->api instanceof MediawikiApi ) {
+ return $this->api;
+ }
+ $apiUrl = getenv( 'MEDIAWIKI_API_URL' );
+ if ( empty( $apiUrl ) ) {
+ $apiUrl = 'http://localhost/w/api.php';
+ } elseif ( substr( $apiUrl, -7 ) !== 'api.php' ) {
+ $msg = "URL incorrect: $apiUrl"
+ . " (the MEDIAWIKI_API_URL environment variable should end in 'api.php')";
+ throw new \Exception( $msg );
+ }
+
+ // Log to a local file.
+ $logger = new Logger( 'mediawiki-api' );
+ $logFile = __DIR__ . '/../../log/mediawiki-api.log';
+ $logger->pushHandler( new StreamHandler( $logFile, Logger::DEBUG ) );
+
+ // Create and return the API object.
+ $this->api = new MediawikiApi( $apiUrl );
+ $this->api->setLogger( $logger );
+ return $this->api;
+ }
+
+ /**
+ * Get the MediaWiki factory.
+ *
+ * @return \Mediawiki\Api\MediawikiFactory The factory instance.
+ */
+ public function getFactory() {
+ return $this->factory;
+ }
+
+ /**
+ * Run all jobs in the queue. This only works if the MediaWiki installation has $wgJobRunRate
+ * set to greater than zero (for test-running, you should set it to something higher than 50).
+ * @todo This and TestEnvironment::getJobQueueLength() should probably not live here.
+ * @return void
+ */
+ public function runJobs() {
+ $reqestProps = [ 'meta' => 'siteinfo', 'siprop' => 'general' ];
+ $siteInfoRequest = new SimpleRequest( 'query', $reqestProps );
+ $out = $this->getApi()->getRequest( $siteInfoRequest );
+ $mainPageUrl = $out['query']['general']['base'];
+ $i = 0;
+ while ( $this->getJobQueueLength( $this->getApi() ) > 0 ) {
+ $i++;
+ $cf = new ClientFactory();
+ $cf->getClient()->get( $mainPageUrl );
+ if ($i == 10) {
+ // Give up if we've been looping too much. This is very arbitrary.
+ break;
+ }
+ }
+ }
+
+ /**
+ * Get the number of jobs currently in the queue.
+ * @todo This and TestEnvironment::runJobs() should probably not live here.
+ * @param MediawikiApi $api
+ * @return int
+ */
+ public function getJobQueueLength( MediawikiApi $api ) {
+ $req = new SimpleRequest( 'query', [
+ 'meta' => 'siteinfo',
+ 'siprop' => 'statistics',
+ ]
+ );
+ $out = $api->getRequest( $req );
+ return (int)$out['query']['statistics']['jobs'];
+ }
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/tests/integration/UserIntegrationTest.php b/bin/reevotech/vendor/addwiki/mediawiki-api/tests/integration/UserIntegrationTest.php
new file mode 100644
index 00000000..29221edb
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/tests/integration/UserIntegrationTest.php
@@ -0,0 +1,35 @@
+<?php
+
+namespace Mediawiki\Api\Test;
+
+use Mediawiki\Api\ApiUser;
+use PHPUnit_Framework_TestCase;
+
+/**
+ * @author Addshore
+ */
+class UserIntegrationTest extends PHPUnit_Framework_TestCase {
+
+ /**
+ * @var ApiUser
+ */
+ private static $localApiUser;
+
+ public static function setUpBeforeClass() {
+ parent::setUpBeforeClass();
+ $strTime = strval( time() );
+ self::$localApiUser = new ApiUser( 'TestUser - ' . strval( time() ), $strTime . '-pass' );
+ }
+
+ public function testCreateUser() {
+ $factory = TestEnvironment::newDefault()->getFactory();
+ $createResult = $factory->newUserCreator()->create(
+ self::$localApiUser->getUsername(),
+
+
+ self::$localApiUser->getPassword()
+ );
+ $this->assertTrue( $createResult );
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/tests/integration/phpunit.xml.dist b/bin/reevotech/vendor/addwiki/mediawiki-api/tests/integration/phpunit.xml.dist
new file mode 100644
index 00000000..4a0040c3
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/tests/integration/phpunit.xml.dist
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- convertWarningsToExceptions is false as real API calls can return un expected warnings -->
+<phpunit
+ bootstrap="../../vendor/autoload.php"
+ colors="true"
+ convertWarningsToExceptions="false"
+ >
+ <testsuites>
+ <testsuite name="addwiki/mediawiki-api/integration">
+ <directory suffix="Test.php">.</directory>
+ </testsuite>
+ </testsuites>
+ <filter>
+ <whitelist addUncoveredFilesFromWhitelist="true">
+ <directory suffix=".php">./../../src</directory>
+ </whitelist>
+ </filter>
+</phpunit> \ No newline at end of file
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/tests/unit/Generator/AnonymousGeneratorTest.php b/bin/reevotech/vendor/addwiki/mediawiki-api/tests/unit/Generator/AnonymousGeneratorTest.php
new file mode 100644
index 00000000..67d6e450
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/tests/unit/Generator/AnonymousGeneratorTest.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace Mediawiki\Api\Test\Generator;
+
+use Mediawiki\Api\Generator\AnonymousGenerator;
+
+/**
+ * @author Addshore
+ *
+ * @covers \Mediawiki\Api\Generator\AnonymousGenerator
+ */
+class AnonymousGeneratorTest extends \PHPUnit_Framework_TestCase {
+
+ public function testConstruction() {
+ $generator = new AnonymousGenerator( 'name', [ 'gfoo' => 'bar' ] );
+
+ $this->assertEquals(
+ [
+ 'generator' => 'name',
+ 'gfoo' => 'bar',
+ ],
+ $generator->getParams()
+ );
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/tests/unit/Generator/FluentGeneratorTest.php b/bin/reevotech/vendor/addwiki/mediawiki-api/tests/unit/Generator/FluentGeneratorTest.php
new file mode 100644
index 00000000..bd7cb0bf
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/tests/unit/Generator/FluentGeneratorTest.php
@@ -0,0 +1,55 @@
+<?php
+
+namespace Mediawiki\Api\Test\Generator;
+
+use Mediawiki\Api\Generator\FluentGenerator;
+
+/**
+ * @author Addshore
+ *
+ * @covers \Mediawiki\Api\Generator\FluentGenerator
+ */
+class FluentGeneratorTest extends \PHPUnit_Framework_TestCase {
+
+ public function testConstructionWithNoGPrefix() {
+ $generator = new FluentGenerator( 'name' );
+ $generator->set( 'foo', 'bar' );
+
+ $this->assertEquals(
+ [
+ 'generator' => 'name',
+ 'gfoo' => 'bar',
+ ],
+ $generator->getParams()
+ );
+ }
+
+ public function testConstructionWithGPrefix() {
+ $generator = new FluentGenerator( 'name' );
+ $generator->set( 'gfoo', 'bar' );
+
+ $this->assertEquals(
+ [
+ 'generator' => 'name',
+ 'gfoo' => 'bar',
+ ],
+ $generator->getParams()
+ );
+ }
+
+ public function testFluidity() {
+ $generator = FluentGenerator::factory( 'name' )
+ ->set( 'foo', 'bar' )
+ ->set( 'gcat', 'meow' );
+
+ $this->assertEquals(
+ [
+ 'generator' => 'name',
+ 'gfoo' => 'bar',
+ 'gcat' => 'meow',
+ ],
+ $generator->getParams()
+ );
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/tests/unit/MediawikiFactoryTest.php b/bin/reevotech/vendor/addwiki/mediawiki-api/tests/unit/MediawikiFactoryTest.php
new file mode 100644
index 00000000..c4ce958f
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/tests/unit/MediawikiFactoryTest.php
@@ -0,0 +1,54 @@
+<?php
+
+namespace Mediawiki\Api\Test;
+
+use Mediawiki\Api\MediawikiFactory;
+
+/**
+ * @covers Mediawiki\Api\MediawikiFactory
+ *
+ * @author Addshore
+ */
+class MediawikiFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ public function getMockMediawikiApi() {
+ return $this->getMockBuilder( 'Mediawiki\Api\MediawikiApi' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function provideFactoryMethodsTest() {
+ return [
+ [ 'Mediawiki\Api\Service\RevisionSaver', 'newRevisionSaver' ],
+ [ 'Mediawiki\Api\Service\RevisionUndoer', 'newRevisionUndoer' ],
+ [ 'Mediawiki\Api\Service\PageGetter', 'newPageGetter' ],
+ [ 'Mediawiki\Api\Service\UserGetter', 'newUserGetter' ],
+ [ 'Mediawiki\Api\Service\PageDeleter', 'newPageDeleter' ],
+ [ 'Mediawiki\Api\Service\PageMover', 'newPageMover' ],
+ [ 'Mediawiki\Api\Service\PageListGetter', 'newPageListGetter' ],
+ [ 'Mediawiki\Api\Service\PageRestorer', 'newPageRestorer' ],
+ [ 'Mediawiki\Api\Service\PagePurger', 'newPagePurger' ],
+ [ 'Mediawiki\Api\Service\RevisionRollbacker', 'newRevisionRollbacker' ],
+ [ 'Mediawiki\Api\Service\RevisionPatroller', 'newRevisionPatroller' ],
+ [ 'Mediawiki\Api\Service\PageProtector', 'newPageProtector' ],
+ [ 'Mediawiki\Api\Service\PageWatcher', 'newPageWatcher' ],
+ [ 'Mediawiki\Api\Service\RevisionDeleter', 'newRevisionDeleter' ],
+ [ 'Mediawiki\Api\Service\RevisionRestorer', 'newRevisionRestorer' ],
+ [ 'Mediawiki\Api\Service\UserBlocker', 'newUserBlocker' ],
+ [ 'Mediawiki\Api\Service\UserRightsChanger', 'newUserRightsChanger' ],
+ [ 'Mediawiki\Api\Service\UserCreator', 'newUserCreator' ],
+ [ 'Mediawiki\Api\Service\LogListGetter', 'newLogListGetter' ],
+ [ 'Mediawiki\Api\Service\FileUploader', 'newFileUploader' ],
+ [ 'Mediawiki\Api\Service\ImageRotator', 'newImageRotator' ],
+ ];
+ }
+
+ /**
+ * @dataProvider provideFactoryMethodsTest
+ */
+ public function testFactoryMethod( $class, $method ) {
+ $factory = new MediawikiFactory( $this->getMockMediawikiApi() );
+ $this->assertInstanceOf( $class, $factory->$method() );
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/tests/unit/Service/PagePurgerTest.php b/bin/reevotech/vendor/addwiki/mediawiki-api/tests/unit/Service/PagePurgerTest.php
new file mode 100644
index 00000000..38199c26
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/tests/unit/Service/PagePurgerTest.php
@@ -0,0 +1,187 @@
+<?php
+
+namespace Mediawiki\Api\Test\Service;
+
+use Mediawiki\Api\MediawikiApi;
+use Mediawiki\Api\Service\PagePurger;
+use Mediawiki\DataModel\Page;
+use Mediawiki\DataModel\Pages;
+use Mediawiki\DataModel\PageIdentifier;
+use Mediawiki\DataModel\Title;
+use PHPUnit_Framework_MockObject_MockObject;
+
+/**
+ * @author Addshore
+ * @covers Mediawiki\Api\Service\PagePurger
+ */
+class PagePurgerTest extends \PHPUnit_Framework_TestCase {
+
+ private function getMockApi() {
+ /** @var MediawikiApi|PHPUnit_Framework_MockObject_MockObject $mock */
+ $mock = $this->getMockBuilder( '\Mediawiki\Api\MediawikiApi' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ return $mock;
+ }
+
+ public function testValidConstruction() {
+ new PagePurger( $this->getMockApi() );
+ $this->assertTrue( true );
+ }
+
+ public function testPurgePage() {
+ $api = $this->getMockApi();
+ $api->expects( $this->once() )
+ ->method( 'postRequest' )
+ ->with(
+ $this->isInstanceOf( '\Mediawiki\Api\SimpleRequest' )
+ )
+ ->will( $this->returnValue(
+ [
+ "batchcomplete" => "",
+ "purge" => [ [ "ns" => 0, "title" => "Foo", "purged" => "" ] ]
+ ] ) );
+
+ $service = new PagePurger( $api );
+
+ $page = new Page(
+ new PageIdentifier(
+ new Title( 'Foo', 0 ),
+ 123
+ )
+ );
+
+ $this->assertTrue( $service->purge( $page ) );
+ }
+
+ function testIncorrectPurgePage() {
+ $api = $this->getMockApi();
+ $api->expects( $this->once() )
+ ->method( 'postRequest' )
+ ->with(
+ $this->isInstanceOf( '\Mediawiki\Api\SimpleRequest' )
+ )
+ ->will( $this->returnValue( [
+ "batchcomplete" => "",
+ "purge" =>
+ [ [
+ "ns" => 0,
+ "title" => "This page really does not exist",
+ "missing" => ""
+ ] ]
+ ] ) );
+
+ $service = new PagePurger( $api );
+
+ $page = new Page(
+ new PageIdentifier(
+ new Title( 'Foo', 0 ),
+ 123
+ )
+ );
+
+ $this->assertFalse( $service->purge( $page ) );
+ }
+
+ public function testPurgePages() {
+ $api = $this->getMockApi();
+ $api->expects( $this->once() )
+ ->method( 'postRequest' )
+ ->with(
+ $this->isInstanceOf( '\Mediawiki\Api\SimpleRequest' )
+ )
+ ->will( $this->returnValue(
+ [
+ "batchcomplete" => "",
+ "purge" => [
+ [
+ "ns" => 0,
+ "title" => "Foo",
+ "purged" => ""
+ ],
+ [
+ "ns" => 0,
+ "title" => "Bar",
+ "purged" => ""
+ ],
+ ]
+ ]
+ ) );
+
+ $service = new PagePurger( $api );
+
+ $pages = new Pages( [
+ new Page(
+ new PageIdentifier(
+ new Title( 'Foo', 0 ),
+ 100
+ )
+ ), new Page(
+ new PageIdentifier(
+ new Title( 'Bar', 1 ),
+ 101
+ )
+ ) ] );
+
+ $this->assertEquals( $service->purgePages( $pages ), $pages );
+ }
+
+ function testIncorrectPurgePages() {
+ $api = $this->getMockApi();
+ $api->expects( $this->once() )
+ ->method( 'postRequest' )
+ ->with(
+ $this->isInstanceOf( '\Mediawiki\Api\SimpleRequest' )
+ )
+ ->will( $this->returnValue(
+ [
+ "batchcomplete" => "",
+ "purge" => [
+ [
+ "ns" => 0,
+ "title" => "Foo",
+ "purged" => ""
+ ],
+ [
+ "ns" => 0,
+ "title" => "Bar",
+ "purged" => ""
+ ],
+ [
+ "ns" => 0,
+ "title" => "This page really does not exist",
+ "missing" => ""
+ ],
+ ]
+ ]
+ ) );
+
+ $service = new PagePurger( $api );
+
+ $pages = new Pages( [
+ new Page(
+ new PageIdentifier(
+ new Title( 'Foo', 0 ),
+ 100
+ )
+ ), new Page(
+ new PageIdentifier(
+ new Title( 'Bar', 1 ),
+ 101
+ )
+ ), new Page(
+ new PageIdentifier(
+ new Title( 'MissingPage', 1 ),
+ 103
+ )
+ ) ] );
+
+ // MissingPage is not in the pages that are returned by purgePages
+ $pagesArray = $pages->toArray();
+ array_pop( $pagesArray );
+ $result = new Pages( $pagesArray );
+
+ $this->assertEquals( $service->purgePages( $pages ), $result );
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-api/tests/unit/phpunit.xml.dist b/bin/reevotech/vendor/addwiki/mediawiki-api/tests/unit/phpunit.xml.dist
new file mode 100644
index 00000000..8f4cecef
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-api/tests/unit/phpunit.xml.dist
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit bootstrap="../../vendor/autoload.php" colors="true">
+ <testsuites>
+ <testsuite name="addwiki/mediawiki-api/unit">
+ <directory suffix="Test.php">.</directory>
+ </testsuite>
+ </testsuites>
+ <filter>
+ <whitelist addUncoveredFilesFromWhitelist="true">
+ <directory suffix=".php">./../../src</directory>
+ </whitelist>
+ </filter>
+</phpunit> \ No newline at end of file
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/.gitignore b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/.gitignore
new file mode 100644
index 00000000..014936d3
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/.gitignore
@@ -0,0 +1,5 @@
+.idea
+vendor
+composer.lock
+test.php
+docs/_build
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/.scrutinizer.yml b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/.scrutinizer.yml
new file mode 100644
index 00000000..ffc976e3
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/.scrutinizer.yml
@@ -0,0 +1,13 @@
+inherit: true
+
+tools:
+ php_code_sniffer: true
+ php_cpd: true
+ php_cs_fixer: true
+ php_loc: true
+ php_mess_detector: true
+ php_pdepend: true
+ php_analyzer: true
+ sensiolabs_security_checker: true
+ external_code_coverage:
+ timeout: 300 \ No newline at end of file
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/.travis.yml b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/.travis.yml
new file mode 100644
index 00000000..a58745e1
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/.travis.yml
@@ -0,0 +1,25 @@
+language: php
+
+php:
+ - hhvm
+ - 5.5
+ - 5.6
+ - 7.0
+ - 7.1
+
+before_script:
+ - composer install
+
+script:
+ - ./vendor/bin/phpunit --coverage-clover=coverage.clover
+
+after_script:
+ - wget https://scrutinizer-ci.com/ocular.phar
+ - php ocular.phar code-coverage:upload --format=php-clover coverage.clover
+
+notifications:
+ irc:
+ channels:
+ - "chat.freenode.net##add"
+ on_success: change
+ on_failure: always
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/LICENSE.md b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/LICENSE.md
new file mode 100644
index 00000000..0671f06a
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/LICENSE.md
@@ -0,0 +1,264 @@
+The GNU General Public License, Version 2, June 1991 (GPLv2)
+============================================================
+
+> Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+> 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+
+Everyone is permitted to copy and distribute verbatim copies of this license
+document, but changing it is not allowed.
+
+
+Preamble
+--------
+
+The licenses for most software are designed to take away your freedom to share
+and change it. By contrast, the GNU General Public License is intended to
+guarantee your freedom to share and change free software--to make sure the
+software is free for all its users. This General Public License applies to most
+of the Free Software Foundation's software and to any other program whose
+authors commit to using it. (Some other Free Software Foundation software is
+covered by the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+When we speak of free software, we are referring to freedom, not price. Our
+General Public Licenses are designed to make sure that you have the freedom to
+distribute copies of free software (and charge for this service if you wish),
+that you receive source code or can get it if you want it, that you can change
+the software or use pieces of it in new free programs; and that you know you can
+do these things.
+
+To protect your rights, we need to make restrictions that forbid anyone to deny
+you these rights or to ask you to surrender the rights. These restrictions
+translate to certain responsibilities for you if you distribute copies of the
+software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis or for a
+fee, you must give the recipients all the rights that you have. You must make
+sure that they, too, receive or can get the source code. And you must show them
+these terms so they know their rights.
+
+We protect your rights with two steps: (1) copyright the software, and (2) offer
+you this license which gives you legal permission to copy, distribute and/or
+modify the software.
+
+Also, for each author's protection and ours, we want to make certain that
+everyone understands that there is no warranty for this free software. If the
+software is modified by someone else and passed on, we want its recipients to
+know that what they have is not the original, so that any problems introduced by
+others will not reflect on the original authors' reputations.
+
+Finally, any free program is threatened constantly by software patents. We wish
+to avoid the danger that redistributors of a free program will individually
+obtain patent licenses, in effect making the program proprietary. To prevent
+this, we have made it clear that any patent must be licensed for everyone's free
+use or not licensed at all.
+
+The precise terms and conditions for copying, distribution and modification
+follow.
+
+
+Terms And Conditions For Copying, Distribution And Modification
+---------------------------------------------------------------
+
+**0.** This License applies to any program or other work which contains a notice
+placed by the copyright holder saying it may be distributed under the terms of
+this General Public License. The "Program", below, refers to any such program or
+work, and a "work based on the Program" means either the Program or any
+derivative work under copyright law: that is to say, a work containing the
+Program or a portion of it, either verbatim or with modifications and/or
+translated into another language. (Hereinafter, translation is included without
+limitation in the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not covered by
+this License; they are outside its scope. The act of running the Program is not
+restricted, and the output from the Program is covered only if its contents
+constitute a work based on the Program (independent of having been made by
+running the Program). Whether that is true depends on what the Program does.
+
+**1.** You may copy and distribute verbatim copies of the Program's source code
+as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this License
+and to the absence of any warranty; and give any other recipients of the Program
+a copy of this License along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and you may at
+your option offer warranty protection in exchange for a fee.
+
+**2.** You may modify your copy or copies of the Program or any portion of it,
+thus forming a work based on the Program, and copy and distribute such
+modifications or work under the terms of Section 1 above, provided that you also
+meet all of these conditions:
+
+* **a)** You must cause the modified files to carry prominent notices stating
+ that you changed the files and the date of any change.
+
+* **b)** You must cause any work that you distribute or publish, that in whole
+ or in part contains or is derived from the Program or any part thereof, to
+ be licensed as a whole at no charge to all third parties under the terms of
+ this License.
+
+* **c)** If the modified program normally reads commands interactively when
+ run, you must cause it, when started running for such interactive use in the
+ most ordinary way, to print or display an announcement including an
+ appropriate copyright notice and a notice that there is no warranty (or
+ else, saying that you provide a warranty) and that users may redistribute
+ the program under these conditions, and telling the user how to view a copy
+ of this License. (Exception: if the Program itself is interactive but does
+ not normally print such an announcement, your work based on the Program is
+ not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If identifiable
+sections of that work are not derived from the Program, and can be reasonably
+considered independent and separate works in themselves, then this License, and
+its terms, do not apply to those sections when you distribute them as separate
+works. But when you distribute the same sections as part of a whole which is a
+work based on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the entire whole,
+and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your
+rights to work written entirely by you; rather, the intent is to exercise the
+right to control the distribution of derivative or collective works based on the
+Program.
+
+In addition, mere aggregation of another work not based on the Program with the
+Program (or with a work based on the Program) on a volume of a storage or
+distribution medium does not bring the other work under the scope of this
+License.
+
+**3.** You may copy and distribute the Program (or a work based on it, under
+Section 2) in object code or executable form under the terms of Sections 1 and 2
+above provided that you also do one of the following:
+
+* **a)** Accompany it with the complete corresponding machine-readable source
+ code, which must be distributed under the terms of Sections 1 and 2 above on
+ a medium customarily used for software interchange; or,
+
+* **b)** Accompany it with a written offer, valid for at least three years, to
+ give any third party, for a charge no more than your cost of physically
+ performing source distribution, a complete machine-readable copy of the
+ corresponding source code, to be distributed under the terms of Sections 1
+ and 2 above on a medium customarily used for software interchange; or,
+
+* **c)** Accompany it with the information you received as to the offer to
+ distribute corresponding source code. (This alternative is allowed only for
+ noncommercial distribution and only if you received the program in object
+ code or executable form with such an offer, in accord with Subsection b
+ above.)
+
+The source code for a work means the preferred form of the work for making
+modifications to it. For an executable work, complete source code means all the
+source code for all modules it contains, plus any associated interface
+definition files, plus the scripts used to control compilation and installation
+of the executable. However, as a special exception, the source code distributed
+need not include anything that is normally distributed (in either source or
+binary form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component itself
+accompanies the executable.
+
+If distribution of executable or object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the source code
+from the same place counts as distribution of the source code, even though third
+parties are not compelled to copy the source along with the object code.
+
+**4.** You may not copy, modify, sublicense, or distribute the Program except as
+expressly provided under this License. Any attempt otherwise to copy, modify,
+sublicense or distribute the Program is void, and will automatically terminate
+your rights under this License. However, parties who have received copies, or
+rights, from you under this License will not have their licenses terminated so
+long as such parties remain in full compliance.
+
+**5.** You are not required to accept this License, since you have not signed
+it. However, nothing else grants you permission to modify or distribute the
+Program or its derivative works. These actions are prohibited by law if you do
+not accept this License. Therefore, by modifying or distributing the Program (or
+any work based on the Program), you indicate your acceptance of this License to
+do so, and all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+**6.** Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program subject to these terms and
+conditions. You may not impose any further restrictions on the recipients'
+exercise of the rights granted herein. You are not responsible for enforcing
+compliance by third parties to this License.
+
+**7.** If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues), conditions
+are imposed on you (whether by court order, agreement or otherwise) that
+contradict the conditions of this License, they do not excuse you from the
+conditions of this License. If you cannot distribute so as to satisfy
+simultaneously your obligations under this License and any other pertinent
+obligations, then as a consequence you may not distribute the Program at all.
+For example, if a patent license would not permit royalty-free redistribution of
+the Program by all those who receive copies directly or indirectly through you,
+then the only way you could satisfy both it and this License would be to refrain
+entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply and the
+section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or
+other property right claims or to contest validity of any such claims; this
+section has the sole purpose of protecting the integrity of the free software
+distribution system, which is implemented by public license practices. Many
+people have made generous contributions to the wide range of software
+distributed through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing to
+distribute software through any other system and a licensee cannot impose that
+choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+**8.** If the distribution and/or use of the Program is restricted in certain
+countries either by patents or by copyrighted interfaces, the original copyright
+holder who places the Program under this License may add an explicit
+geographical distribution limitation excluding those countries, so that
+distribution is permitted only in or among countries not thus excluded. In such
+case, this License incorporates the limitation as if written in the body of this
+License.
+
+**9.** The Free Software Foundation may publish revised and/or new versions of
+the General Public License from time to time. Such new versions will be similar
+in spirit to the present version, but may differ in detail to address new
+problems or concerns.
+
+Each version is given a distinguishing version number. If the Program specifies
+a version number of this License which applies to it and "any later version",
+you have the option of following the terms and conditions either of that version
+or of any later version published by the Free Software Foundation. If the
+Program does not specify a version number of this License, you may choose any
+version ever published by the Free Software Foundation.
+
+**10.** If you wish to incorporate parts of the Program into other free programs
+whose distribution conditions are different, write to the author to ask for
+permission. For software which is copyrighted by the Free Software Foundation,
+write to the Free Software Foundation; we sometimes make exceptions for this.
+Our decision will be guided by the two goals of preserving the free status of
+all derivatives of our free software and of promoting the sharing and reuse of
+software generally.
+
+
+No Warranty
+-----------
+
+**11.** BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
+THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
+STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM
+"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+**12.** IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
+INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
+BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER
+OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/README.md b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/README.md
new file mode 100644
index 00000000..f0fdf1b1
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/README.md
@@ -0,0 +1,17 @@
+mediawiki-datamodel
+==================
+[![Build Status](https://travis-ci.org/addwiki/mediawiki-datamodel.png?branch=master)](https://travis-ci.org/addwiki/mediawiki-datamodel)
+[![Code Coverage](https://scrutinizer-ci.com/g/addwiki/mediawiki-datamodel/badges/coverage.png?s=ce4091cc4471ee9feff0c5fd963101c93bf54080)](https://scrutinizer-ci.com/g/addwiki/mediawiki-datamodel/)
+[![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/addwiki/mediawiki-datamodel/badges/quality-score.png?s=9383c67ac0068ac3052243cd636e05eafd505b80)](https://scrutinizer-ci.com/g/addwiki/mediawiki-datamodel/)
+
+On Packagist:
+[![Latest Stable Version](https://poser.pugx.org/addwiki/mediawiki-datamodel/version.png)](https://packagist.org/packages/addwiki/mediawiki-datamodel)
+[![Download count](https://poser.pugx.org/addwiki/mediawiki-datamodel/d/total.png)](https://packagist.org/packages/addwiki/mediawiki-datamodel)
+
+Issue tracker: https://phabricator.wikimedia.org/project/profile/1490/
+
+## Installation
+
+Use composer to install the library and all its dependencies:
+
+ composer require "addwiki/mediawiki-datamodel:~0.7.0"
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/RELEASENOTES.md b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/RELEASENOTES.md
new file mode 100644
index 00000000..08df4aab
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/RELEASENOTES.md
@@ -0,0 +1,88 @@
+These are the release notes for the [mediawiki-datamodel](README.md).
+
+## Version 0.7.1 (10th January 2017)
+
+* [T184567](https://phabricator.wikimedia.org/T184567) `User` objects can now be created with a `null` `$registration`.
+
+## Version 0.7 (8th March 2017)
+
+#### New features
+
+* Add NamespaceInfo class
+
+## Version 0.6 (2015-09-04)
+
+#### Compatibility changes
+
+* Log object now takes a PageIdentifier object instead of a Page object
+
+#### Deprecations
+
+* Title::getTitle is deprecated
+
+#### New features
+
+* Implemented File class
+* Implemented Redirect class
+* Title::getText introduced to replace getTitle
+* Log now implements JsonSerializable
+* LogList now implements JsonSerializable
+* Title now implements JsonSerializable
+* PageIdentifier now implements JsonSerializable
+
+## Version 0.5 (2015-01-13)
+
+#### Compatibility changes
+
+* Revision objects now require a PageIdentifier object instead of a $pageId int
+* Page objects now require a PageIdentifier objects instead of a $title and $pageId
+* Content getNativeData renamed to getData
+* Content constructor changed, now takes data and optional model
+* Content has new method getModel in places of random constants
+* Removed WikitextContent class. Content is no longer abstract.
+
+#### New features
+
+* Implemented Log class
+* Implemented LogList class
+* Introduce PageIdentifier class
+* Page objects can be constructed without a Revisions object
+
+## Version 0.4 (2014-07-08)
+
+* Page objects now ONLY accept a Title object for $title in their constructor.
+* InvalidArgumentExceptions are now thrown when objects are constructed with the wrong types.
+* User objects now split up implicitgroups and regular groups, thus $groups is now array[]
+
+
+## Version 0.3 (2014-06-24)
+
+#### Compatibility changes
+
+* Revision objects now take a Content object as $content
+
+#### Additions
+
+* Content class
+* WikitextContent class
+* Pages class
+
+
+## Version 0.2 (2014-02-23)
+
+#### Compatibility changes
+
+* Revision enhanced to allow more flexibility, Constructor and public functions have changed
+* contentmodel has been removed from the Page class
+
+
+## Version 0.1 (2014-02-23)
+
+Initial release with the following features:
+
+* EditInfo
+* Page
+* Revision
+* Revisions
+* Title
+* User
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/composer.json b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/composer.json
new file mode 100644
index 00000000..9ac4e519
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/composer.json
@@ -0,0 +1,32 @@
+{
+ "name": "addwiki/mediawiki-datamodel",
+ "type": "library",
+ "description": "A Mediawiki datamodel",
+ "keywords": ["Mediawiki"],
+ "license": "GPL-2.0+",
+ "authors": [
+ {
+ "name": "Addshore"
+ }
+ ],
+ "autoload": {
+ "psr-4": {
+ "Mediawiki\\DataModel\\": "src/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Mediawiki\\DataModel\\Test\\": "tests/"
+ }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "0.7.x-dev"
+ }
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.8.0|~5.3.0",
+ "jakub-onderka/php-parallel-lint": "0.9.2",
+ "mediawiki/mediawiki-codesniffer": "^13.0"
+ }
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/docs/Makefile b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/docs/Makefile
new file mode 100644
index 00000000..af9b9d0b
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/docs/Makefile
@@ -0,0 +1,225 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+BUILDDIR = _build
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help
+help:
+ @echo "Please use \`make <target>' where <target> is one of"
+ @echo " html to make standalone HTML files"
+ @echo " dirhtml to make HTML files named index.html in directories"
+ @echo " singlehtml to make a single large HTML file"
+ @echo " pickle to make pickle files"
+ @echo " json to make JSON files"
+ @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " qthelp to make HTML files and a qthelp project"
+ @echo " applehelp to make an Apple Help Book"
+ @echo " devhelp to make HTML files and a Devhelp project"
+ @echo " epub to make an epub"
+ @echo " epub3 to make an epub3"
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+ @echo " latexpdf to make LaTeX files and run them through pdflatex"
+ @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
+ @echo " text to make text files"
+ @echo " man to make manual pages"
+ @echo " texinfo to make Texinfo files"
+ @echo " info to make Texinfo files and run them through makeinfo"
+ @echo " gettext to make PO message catalogs"
+ @echo " changes to make an overview of all changed/added/deprecated items"
+ @echo " xml to make Docutils-native XML files"
+ @echo " pseudoxml to make pseudoxml-XML files for display purposes"
+ @echo " linkcheck to check all external links for integrity"
+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
+ @echo " coverage to run coverage check of the documentation (if enabled)"
+ @echo " dummy to check syntax errors of document sources"
+
+.PHONY: clean
+clean:
+ rm -rf $(BUILDDIR)/*
+
+.PHONY: html
+html:
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+.PHONY: dirhtml
+dirhtml:
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+.PHONY: singlehtml
+singlehtml:
+ $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+ @echo
+ @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+.PHONY: pickle
+pickle:
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+.PHONY: json
+json:
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+.PHONY: htmlhelp
+htmlhelp:
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+.PHONY: qthelp
+qthelp:
+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+ @echo
+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+ ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/mediawiki-datamodel.qhcp"
+ @echo "To view the help file:"
+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/mediawiki-datamodel.qhc"
+
+.PHONY: applehelp
+applehelp:
+ $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
+ @echo
+ @echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
+ @echo "N.B. You won't be able to view it unless you put it in" \
+ "~/Library/Documentation/Help or install it in your application" \
+ "bundle."
+
+.PHONY: devhelp
+devhelp:
+ $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+ @echo
+ @echo "Build finished."
+ @echo "To view the help file:"
+ @echo "# mkdir -p $$HOME/.local/share/devhelp/mediawiki-datamodel"
+ @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/mediawiki-datamodel"
+ @echo "# devhelp"
+
+.PHONY: epub
+epub:
+ $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+ @echo
+ @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+.PHONY: epub3
+epub3:
+ $(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3
+ @echo
+ @echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3."
+
+.PHONY: latex
+latex:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+ @echo "Run \`make' in that directory to run these through (pdf)latex" \
+ "(use \`make latexpdf' here to do that automatically)."
+
+.PHONY: latexpdf
+latexpdf:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through pdflatex..."
+ $(MAKE) -C $(BUILDDIR)/latex all-pdf
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+.PHONY: latexpdfja
+latexpdfja:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through platex and dvipdfmx..."
+ $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+.PHONY: text
+text:
+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+ @echo
+ @echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+.PHONY: man
+man:
+ $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+ @echo
+ @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+.PHONY: texinfo
+texinfo:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo
+ @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+ @echo "Run \`make' in that directory to run these through makeinfo" \
+ "(use \`make info' here to do that automatically)."
+
+.PHONY: info
+info:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo "Running Texinfo files through makeinfo..."
+ make -C $(BUILDDIR)/texinfo info
+ @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+.PHONY: gettext
+gettext:
+ $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+ @echo
+ @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+.PHONY: changes
+changes:
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+ @echo
+ @echo "The overview file is in $(BUILDDIR)/changes."
+
+.PHONY: linkcheck
+linkcheck:
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in $(BUILDDIR)/linkcheck/output.txt."
+
+.PHONY: doctest
+doctest:
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+ @echo "Testing of doctests in the sources finished, look at the " \
+ "results in $(BUILDDIR)/doctest/output.txt."
+
+.PHONY: coverage
+coverage:
+ $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
+ @echo "Testing of coverage in the sources finished, look at the " \
+ "results in $(BUILDDIR)/coverage/python.txt."
+
+.PHONY: xml
+xml:
+ $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
+ @echo
+ @echo "Build finished. The XML files are in $(BUILDDIR)/xml."
+
+.PHONY: pseudoxml
+pseudoxml:
+ $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
+ @echo
+ @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
+
+.PHONY: dummy
+dummy:
+ $(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy
+ @echo
+ @echo "Build finished. Dummy builder generates no files."
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/docs/conf.py b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/docs/conf.py
new file mode 100644
index 00000000..1f465d00
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/docs/conf.py
@@ -0,0 +1,80 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#
+# import os
+# import sys
+# sys.path.insert(0, os.path.abspath('.'))
+
+import sys, os
+from sphinx.highlighting import lexers
+from pygments.lexers.web import PhpLexer
+
+lexers['php'] = PhpLexer(startinline=True, linenos=1)
+lexers['php-annotations'] = PhpLexer(startinline=True, linenos=1)
+primary_domain = 'php'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = []
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix(es) of source filenames.
+# You can specify multiple suffix as a list of string:
+#
+# source_suffix = ['.rst', '.md']
+source_suffix = '.rst'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = 'mediawiki-datamodel'
+copyright = '2016, addwiki'
+author = 'addwiki'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '0.6'
+# The full version, including alpha/beta/rc tags.
+release = '0.6'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#
+# This is also used if you do content translation via gettext catalogs.
+# Usually you set "language" from the command line for these cases.
+language = None
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This patterns also effect to html_static_path and html_extra_path
+exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# If true, `todo` and `todoList` produce output, else they produce nothing.
+todo_include_todos = False
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+#
+html_theme = 'default'
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'mediawiki-datamodeldoc'
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/docs/index.rst b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/docs/index.rst
new file mode 100644
index 00000000..c862502f
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/docs/index.rst
@@ -0,0 +1,22 @@
+.. mediawiki-datamodel documentation master file, created by
+ sphinx-quickstart on Sat Oct 1 18:15:20 2016.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+Welcome to mediawiki-datamodel's documentation!
+===============================================
+
+Contents:
+
+.. toctree::
+ :maxdepth: 2
+
+
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/docs/make.bat b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/docs/make.bat
new file mode 100644
index 00000000..6ff153c5
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/docs/make.bat
@@ -0,0 +1,281 @@
+@ECHO OFF
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set BUILDDIR=_build
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
+set I18NSPHINXOPTS=%SPHINXOPTS% .
+if NOT "%PAPER%" == "" (
+ set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
+ set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
+)
+
+if "%1" == "" goto help
+
+if "%1" == "help" (
+ :help
+ echo.Please use `make ^<target^>` where ^<target^> is one of
+ echo. html to make standalone HTML files
+ echo. dirhtml to make HTML files named index.html in directories
+ echo. singlehtml to make a single large HTML file
+ echo. pickle to make pickle files
+ echo. json to make JSON files
+ echo. htmlhelp to make HTML files and a HTML help project
+ echo. qthelp to make HTML files and a qthelp project
+ echo. devhelp to make HTML files and a Devhelp project
+ echo. epub to make an epub
+ echo. epub3 to make an epub3
+ echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
+ echo. text to make text files
+ echo. man to make manual pages
+ echo. texinfo to make Texinfo files
+ echo. gettext to make PO message catalogs
+ echo. changes to make an overview over all changed/added/deprecated items
+ echo. xml to make Docutils-native XML files
+ echo. pseudoxml to make pseudoxml-XML files for display purposes
+ echo. linkcheck to check all external links for integrity
+ echo. doctest to run all doctests embedded in the documentation if enabled
+ echo. coverage to run coverage check of the documentation if enabled
+ echo. dummy to check syntax errors of document sources
+ goto end
+)
+
+if "%1" == "clean" (
+ for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
+ del /q /s %BUILDDIR%\*
+ goto end
+)
+
+
+REM Check if sphinx-build is available and fallback to Python version if any
+%SPHINXBUILD% 1>NUL 2>NUL
+if errorlevel 9009 goto sphinx_python
+goto sphinx_ok
+
+:sphinx_python
+
+set SPHINXBUILD=python -m sphinx.__init__
+%SPHINXBUILD% 2> nul
+if errorlevel 9009 (
+ echo.
+ echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+ echo.installed, then set the SPHINXBUILD environment variable to point
+ echo.to the full path of the 'sphinx-build' executable. Alternatively you
+ echo.may add the Sphinx directory to PATH.
+ echo.
+ echo.If you don't have Sphinx installed, grab it from
+ echo.http://sphinx-doc.org/
+ exit /b 1
+)
+
+:sphinx_ok
+
+
+if "%1" == "html" (
+ %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/html.
+ goto end
+)
+
+if "%1" == "dirhtml" (
+ %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
+ goto end
+)
+
+if "%1" == "singlehtml" (
+ %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
+ goto end
+)
+
+if "%1" == "pickle" (
+ %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can process the pickle files.
+ goto end
+)
+
+if "%1" == "json" (
+ %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can process the JSON files.
+ goto end
+)
+
+if "%1" == "htmlhelp" (
+ %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in %BUILDDIR%/htmlhelp.
+ goto end
+)
+
+if "%1" == "qthelp" (
+ %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can run "qcollectiongenerator" with the ^
+.qhcp project file in %BUILDDIR%/qthelp, like this:
+ echo.^> qcollectiongenerator %BUILDDIR%\qthelp\mediawiki-datamodel.qhcp
+ echo.To view the help file:
+ echo.^> assistant -collectionFile %BUILDDIR%\qthelp\mediawiki-datamodel.ghc
+ goto end
+)
+
+if "%1" == "devhelp" (
+ %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished.
+ goto end
+)
+
+if "%1" == "epub" (
+ %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The epub file is in %BUILDDIR%/epub.
+ goto end
+)
+
+if "%1" == "epub3" (
+ %SPHINXBUILD% -b epub3 %ALLSPHINXOPTS% %BUILDDIR%/epub3
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The epub3 file is in %BUILDDIR%/epub3.
+ goto end
+)
+
+if "%1" == "latex" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "latexpdf" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ cd %BUILDDIR%/latex
+ make all-pdf
+ cd %~dp0
+ echo.
+ echo.Build finished; the PDF files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "latexpdfja" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ cd %BUILDDIR%/latex
+ make all-pdf-ja
+ cd %~dp0
+ echo.
+ echo.Build finished; the PDF files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "text" (
+ %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The text files are in %BUILDDIR%/text.
+ goto end
+)
+
+if "%1" == "man" (
+ %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The manual pages are in %BUILDDIR%/man.
+ goto end
+)
+
+if "%1" == "texinfo" (
+ %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
+ goto end
+)
+
+if "%1" == "gettext" (
+ %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
+ goto end
+)
+
+if "%1" == "changes" (
+ %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.The overview file is in %BUILDDIR%/changes.
+ goto end
+)
+
+if "%1" == "linkcheck" (
+ %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Link check complete; look for any errors in the above output ^
+or in %BUILDDIR%/linkcheck/output.txt.
+ goto end
+)
+
+if "%1" == "doctest" (
+ %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Testing of doctests in the sources finished, look at the ^
+results in %BUILDDIR%/doctest/output.txt.
+ goto end
+)
+
+if "%1" == "coverage" (
+ %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Testing of coverage in the sources finished, look at the ^
+results in %BUILDDIR%/coverage/python.txt.
+ goto end
+)
+
+if "%1" == "xml" (
+ %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The XML files are in %BUILDDIR%/xml.
+ goto end
+)
+
+if "%1" == "pseudoxml" (
+ %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
+ goto end
+)
+
+if "%1" == "dummy" (
+ %SPHINXBUILD% -b dummy %ALLSPHINXOPTS% %BUILDDIR%/dummy
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. Dummy builder generates no files.
+ goto end
+)
+
+:end
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/phpunit.xml.dist b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/phpunit.xml.dist
new file mode 100644
index 00000000..d8bbce08
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/phpunit.xml.dist
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit bootstrap="./vendor/autoload.php" colors="true">
+ <testsuites>
+ <testsuite name="addwiki/mediawiki-datamodel">
+ <directory suffix="Test.php">./tests</directory>
+ </testsuite>
+ </testsuites>
+ <filter>
+ <whitelist addUncoveredFilesFromWhitelist="true">
+ <directory suffix=".php">src</directory>
+ </whitelist>
+ </filter>
+</phpunit> \ No newline at end of file
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/Content.php b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/Content.php
new file mode 100644
index 00000000..c1372d46
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/Content.php
@@ -0,0 +1,83 @@
+<?php
+
+namespace Mediawiki\DataModel;
+
+use LogicException;
+
+/**
+ * Class Representing the content of a revision
+ * @author Addshore
+ */
+class Content {
+
+ /**
+ * @var string sha1 hash of the object content upon creation
+ */
+ private $initialHash;
+
+ /**
+ * @var mixed
+ */
+ private $data;
+
+ /**
+ * @var string|null
+ */
+ private $model;
+
+ /**
+ * Should always be called AFTER overriding constructors so a hash can be created
+ *
+ * @param mixed $data
+ * @param string|null $model
+ */
+ public function __construct( $data, $model = null ) {
+ $this->data = $data;
+ $this->model = $model;
+ $this->initialHash = $this->getHash();
+ }
+
+ /**
+ * @return string
+ */
+ public function getModel() {
+ return $this->model;
+ }
+
+ /**
+ * Returns a sha1 hash of the content
+ *
+ * @throws LogicException
+ * @return string
+ */
+ public function getHash() {
+ $data = $this->getData();
+ if( is_object( $data ) ) {
+ if( method_exists( $data, 'getHash' ) ) {
+ return $data->getHash();
+ } else {
+ return sha1( serialize( $data ) );
+ }
+ }
+ if( is_string( $data ) ) {
+ return sha1( $data );
+ }
+ throw new LogicException( "Cant get hash for data of type: " . gettype( $data ) );
+ }
+
+ /**
+ * Has the content been changed since object construction (this shouldn't happen!)
+ * @return bool
+ */
+ public function hasChanged() {
+ return $this->initialHash !== $this->getHash();
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getData() {
+ return $this->data;
+ }
+
+} \ No newline at end of file
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/EditInfo.php b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/EditInfo.php
new file mode 100644
index 00000000..b6ba7845
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/EditInfo.php
@@ -0,0 +1,79 @@
+<?php
+
+namespace Mediawiki\DataModel;
+
+use InvalidArgumentException;
+
+/**
+ * Represents flags that can be used when edits are made
+ * @author Addshore
+ */
+class EditInfo {
+
+ //minor flags
+ const MINOR = true;
+ const NOTMINOR = false;
+ //bot flags
+ const BOT = true;
+ const NOTBOT = false;
+
+ /**
+ * @var EditInfo::MINOR|self::NOTMINOR
+ */
+ protected $minor = false;
+
+ /**
+ * @var EditInfo::BOT|self::NOTBOT
+ */
+ protected $bot = false;
+
+ /**
+ * @var string
+ */
+ protected $summary = null;
+
+ /**
+ * @param string $summary
+ * @param bool $minor
+ * @param bool $bot
+ *
+ * @throws InvalidArgumentException
+ */
+ public function __construct( $summary = '', $minor = self::NOTMINOR, $bot = self::NOTBOT ) {
+ if( !is_string( $summary ) ) {
+ throw new InvalidArgumentException( '$summary must be a string' );
+ }
+ if( !is_bool( $minor ) ) {
+ throw new InvalidArgumentException( '$minor must be a bool' );
+ }
+ if( !is_bool( $bot ) ) {
+ throw new InvalidArgumentException( '$bot must be a bool' );
+ }
+
+ $this->summary = $summary;
+ $this->bot = $bot;
+ $this->minor = $minor;
+ }
+
+ /**
+ * @return EditInfo::BOT|self::NOTBOT
+ */
+ public function getBot() {
+ return $this->bot;
+ }
+
+ /**
+ * @return EditInfo::MINOR|self::NOTMINOR
+ */
+ public function getMinor() {
+ return $this->minor;
+ }
+
+ /**
+ * @return string
+ */
+ public function getSummary() {
+ return $this->summary;
+ }
+
+} \ No newline at end of file
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/File.php b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/File.php
new file mode 100644
index 00000000..7851b3b8
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/File.php
@@ -0,0 +1,37 @@
+<?php
+
+namespace Mediawiki\DataModel;
+
+use InvalidArgumentException;
+
+/**
+ * @author Addshore
+ */
+class File extends Page {
+
+ /**
+ * @var string
+ */
+ private $url;
+
+ /**
+ * @param string $url
+ * @param PageIdentifier $pageIdentifier
+ * @param Revisions $revisions
+ */
+ public function __construct( $url, PageIdentifier $pageIdentifier = null, Revisions $revisions = null ) {
+ parent::__construct( $pageIdentifier, $revisions );
+ if( !is_string( $url ) ) {
+ throw new InvalidArgumentException( '$url must be a string' );
+ }
+ $this->url = $url;
+ }
+
+ /**
+ * @return string
+ */
+ public function getUrl() {
+ return $this->url;
+ }
+
+} \ No newline at end of file
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/Log.php b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/Log.php
new file mode 100644
index 00000000..d3e48637
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/Log.php
@@ -0,0 +1,171 @@
+<?php
+
+namespace Mediawiki\DataModel;
+
+use JsonSerializable;
+
+/**
+ * @since 0.5
+ */
+class Log implements JsonSerializable {
+
+ /**
+ * @var int
+ */
+ private $id;
+
+ /**
+ * @var string
+ */
+ private $type;
+
+ /**
+ * @var string
+ */
+ private $action;
+
+ /**
+ * @var string
+ */
+ private $timestamp;
+
+ /**
+ * @var string
+ */
+ private $user;
+
+ /**
+ * @var string
+ */
+ private $comment;
+
+ /**
+ * @var PageIdentifier
+ */
+ private $pageIdentifier;
+
+ /**
+ * @var array
+ */
+ private $details;
+
+ /**
+ * @param int $id
+ * @param string $type
+ * @param string $action
+ * @param string $timestamp
+ * @param string $user
+ * @param PageIdentifier $pageIdentifier
+ * @param string $comment
+ * @param array $details
+ */
+ public function __construct( $id, $type, $action, $timestamp, $user, $pageIdentifier, $comment, $details ) {
+ $this->id = $id;
+ $this->type = $type;
+ $this->action = $action;
+ $this->timestamp = $timestamp;
+ $this->user = $user;
+ $this->pageIdentifier = $pageIdentifier;
+ $this->comment = $comment;
+ $this->details = $details;
+ }
+
+ /**
+ * @since 0.5
+ * @return string
+ */
+ public function getUser() {
+ return $this->user;
+ }
+
+ /**
+ * @since 0.5
+ * @return string
+ */
+ public function getAction() {
+ return $this->action;
+ }
+
+ /**
+ * @since 0.5
+ * @return string
+ */
+ public function getComment() {
+ return $this->comment;
+ }
+
+ /**
+ * @since 0.5
+ * @return int
+ */
+ public function getId() {
+ return $this->id;
+ }
+
+ /**
+ * @since 0.6
+ * @return PageIdentifier
+ */
+ public function getPageIdentifier() {
+ return $this->pageIdentifier;
+ }
+
+ /**
+ * @since 0.5
+ * @return string
+ */
+ public function getTimestamp() {
+ return $this->timestamp;
+ }
+
+ /**
+ * @since 0.5
+ * @return string
+ */
+ public function getType() {
+ return $this->type;
+ }
+
+ /**
+ * @since 0.5
+ * @return array
+ */
+ public function getDetails() {
+ return $this->details;
+ }
+
+ /**
+ * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
+ */
+ public function jsonSerialize() {
+ return array(
+ 'id' => $this->id,
+ 'type' => $this->type,
+ 'action' => $this->action,
+ 'timestamp' => $this->timestamp,
+ 'user' => $this->user,
+ 'pageidentifier' => $this->pageIdentifier,
+ 'comment' => $this->comment,
+ 'details' => $this->details,
+ );
+ }
+
+ /**
+ * @param array $json
+ *
+ * @return self
+ */
+ public static function jsonDeserialize( $json ) {
+ return new self(
+ $json['id'],
+ $json['type'],
+ $json['action'],
+ $json['timestamp'],
+ $json['user'],
+ PageIdentifier::jsonDeserialize( $json['pageidentifier'] ),
+ $json['comment'],
+ $json['details']
+ );
+ }
+
+} \ No newline at end of file
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/LogList.php b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/LogList.php
new file mode 100644
index 00000000..9ce30263
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/LogList.php
@@ -0,0 +1,138 @@
+<?php
+
+namespace Mediawiki\DataModel;
+
+use InvalidArgumentException;
+use JsonSerializable;
+use RuntimeException;
+
+/**
+ * Represents a collection of Log classes
+ * @author Addshore
+ */
+class LogList implements JsonSerializable {
+
+ /**
+ * @var Log[]
+ */
+ private $logs;
+
+ /**
+ * @param Log[] $logs
+ */
+ public function __construct( $logs = array() ) {
+ $this->logs = array();
+ $this->addLogs( $logs );
+ }
+
+ /**
+ * @param Log[]|LogList $logs
+ *
+ * @throws InvalidArgumentException
+ */
+ public function addLogs( $logs ) {
+ if( !is_array( $logs ) && !$logs instanceof LogList ) {
+ throw new InvalidArgumentException( '$logs needs to either be an array or a LogList object' );
+ }
+ if( $logs instanceof LogList ) {
+ $logs = $logs->toArray();
+ }
+ foreach( $logs as $log ) {
+ $this->addLog( $log );
+ }
+ }
+
+ /**
+ * @param Log $log
+ */
+ public function addLog( Log $log ) {
+ $this->logs[$log->getId()] = $log;
+ }
+
+ /**
+ * @param int $id
+ *
+ * @return bool
+ */
+ public function hasLogWithId( $id ){
+ return array_key_exists( $id, $this->logs );
+ }
+
+ /**
+ * @param Log $log
+ *
+ * @return bool
+ */
+ public function hasLog( Log $log ){
+ return array_key_exists( $log->getId(), $this->logs );
+ }
+
+ /**
+ * @return Log|null Log or null if there is no log
+ */
+ public function getLatest() {
+ if( empty( $this->logs ) ) {
+ return null;
+ }
+ return $this->logs[ max( array_keys( $this->logs ) ) ];
+ }
+
+ /**
+ * @since 0.6
+ * @return Log|null Log or null if there is no log
+ */
+ public function getOldest() {
+ if( empty( $this->logs ) ) {
+ return null;
+ }
+ return $this->logs[ min( array_keys( $this->logs ) ) ];
+ }
+
+ /**
+ * @since 0.6
+ * @return bool
+ */
+ public function isEmpty() {
+ return empty( $this->logs );
+ }
+
+ /**
+ * @param int $id
+ *
+ * @throws RuntimeException
+ * @return Log
+ */
+ public function get( $id ){
+ if( $this->hasLogWithId( $id ) ){
+ return $this->logs[$id];
+ }
+ throw new RuntimeException( 'No such Log loaded in LogList object' );
+ }
+
+ /**
+ * @return Log[]
+ */
+ public function toArray() {
+ return $this->logs;
+ }
+
+ /**
+ * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
+ */
+ public function jsonSerialize() {
+ return $this->toArray();
+ }
+
+ /**
+ * @param array $json
+ *
+ * @return self
+ */
+ public static function jsonDeserialize( $json ) {
+ $self = new LogList();
+ foreach ( $json as $logJson ) {
+ $self->addLog( Log::jsonDeserialize( $logJson ) );
+ }
+ return $self;
+ }
+} \ No newline at end of file
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/NamespaceInfo.php b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/NamespaceInfo.php
new file mode 100644
index 00000000..451ec972
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/NamespaceInfo.php
@@ -0,0 +1,131 @@
+<?php
+
+namespace Mediawiki\DataModel;
+
+/**
+ * Class representing metadata about a MediaWiki namespace
+ *
+ * @author gbirke
+ */
+class NamespaceInfo
+{
+ /**
+ * @var int
+ */
+ private $id;
+
+ /**
+ * @var string
+ */
+ private $canonicalName;
+
+ /**
+ * @var string
+ */
+ private $localName;
+
+ /**
+ * @var string
+ */
+ private $caseHandling;
+
+ /**
+ * @var string
+ */
+ private $defaultContentModel;
+
+ /**
+ * @var array
+ */
+ private $aliases;
+
+ /**
+ * NamespaceInfo constructor.
+ * @param int $id
+ * @param string $canonicalName
+ * @param string $localName
+ * @param string $caseHandling
+ * @param string $defaultContentModel
+ * @param array $aliases
+ *
+ * @throws InvalidArgumentException
+ */
+ public function __construct( $id, $canonicalName, $localName, $caseHandling, $defaultContentModel = null, $aliases = [] )
+ {
+ if( !is_int( $id ) ) {
+ throw new \InvalidArgumentException( '$id must be an integer' );
+ }
+ if ( !is_string( $canonicalName ) ) {
+ throw new \InvalidArgumentException( '$canonicalName must be a string' );
+ }
+ if ( !is_string( $localName ) ) {
+ throw new \InvalidArgumentException( '$localName must be a string' );
+ }
+ if ( !is_string( $caseHandling ) ) {
+ throw new \InvalidArgumentException( '$caseHandling must be a string' );
+ }
+ if ( !is_null( $defaultContentModel) && !is_string( $defaultContentModel ) ) {
+ throw new \InvalidArgumentException( '$canonicalName must be a string' );
+ }
+
+ if ( !is_array( $aliases ) ) {
+ throw new \InvalidArgumentException( '$aliases must be an array' );
+ }
+
+ $this->id = $id;
+ $this->canonicalName = $canonicalName;
+ $this->localName = $localName;
+ $this->caseHandling = $caseHandling;
+ $this->defaultContentModel = $defaultContentModel;
+ $this->aliases = $aliases;
+ }
+
+ /**
+ * @return int
+ */
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ /**
+ * @return string
+ */
+ public function getCanonicalName()
+ {
+ return $this->canonicalName;
+ }
+
+ /**
+ * @return string
+ */
+ public function getLocalName()
+ {
+ return $this->localName;
+ }
+
+ /**
+ * @return string
+ */
+ public function getCaseHandling()
+ {
+ return $this->caseHandling;
+ }
+
+ /**
+ * @return string
+ */
+ public function getDefaultContentModel()
+ {
+ return $this->defaultContentModel;
+ }
+
+ /**
+ * @return array
+ */
+ public function getAliases()
+ {
+ return $this->aliases;
+ }
+
+} \ No newline at end of file
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/Page.php b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/Page.php
new file mode 100644
index 00000000..c3951e85
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/Page.php
@@ -0,0 +1,63 @@
+<?php
+
+namespace Mediawiki\DataModel;
+
+use InvalidArgumentException;
+
+class Page {
+
+ /**
+ * @var Revisions
+ */
+ private $revisions;
+
+ /**
+ * @var PageIdentifier
+ */
+ private $pageIdentifier;
+
+ /**
+ * @param PageIdentifier $pageIdentifier
+ * @param Revisions|null $revisions
+ *
+ * @throws InvalidArgumentException
+ */
+ public function __construct( PageIdentifier $pageIdentifier = null , Revisions $revisions = null ) {
+ if( is_null( $revisions ) ) {
+ $revisions = new Revisions();
+ }
+ $this->revisions = $revisions;
+ $this->pageIdentifier = $pageIdentifier;
+ }
+
+ /**
+ * @deprecated since 0.5
+ * @return int
+ */
+ public function getId() {
+ return $this->pageIdentifier->getId();
+ }
+
+ /**
+ * @return Revisions
+ */
+ public function getRevisions() {
+ return $this->revisions;
+ }
+
+ /**
+ * @deprecated since 0.5
+ * @return Title
+ */
+ public function getTitle() {
+ return $this->pageIdentifier->getTitle();
+ }
+
+ /**
+ * @return PageIdentifier
+ */
+ public function getPageIdentifier() {
+ return $this->pageIdentifier;
+ }
+
+} \ No newline at end of file
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/PageIdentifier.php b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/PageIdentifier.php
new file mode 100644
index 00000000..528e3c88
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/PageIdentifier.php
@@ -0,0 +1,85 @@
+<?php
+
+namespace Mediawiki\DataModel;
+
+use InvalidArgumentException;
+use JsonSerializable;
+
+class PageIdentifier implements JsonSerializable {
+
+ /**
+ * @var int|null
+ */
+ private $id;
+
+ /**
+ * @var Title|null
+ */
+ private $title;
+
+ /**
+ * @param Title|null $title
+ * @param int|null $id
+ * @throws InvalidArgumentException
+ */
+ public function __construct( Title $title = null, $id = null ) {
+ if( !is_int( $id ) && !is_null( $id ) ) {
+ throw new InvalidArgumentException( '$id must be an int' );
+ }
+ $this->title = $title;
+ $this->id = $id;
+ }
+
+ /**
+ * @return int|null
+ */
+ public function getId() {
+ return $this->id;
+ }
+
+ /**
+ * @return Title|null
+ */
+ public function getTitle() {
+ return $this->title;
+ }
+
+ /**
+ * Does this object identify a page
+ * @return bool
+ */
+ public function identifiesPage() {
+ if( is_null( $this->title ) && is_null( $this->id ) ) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
+ */
+ public function jsonSerialize() {
+ $array = array();
+ if ( $this->id !== null ) {
+ $array['id'] = $this->id;
+ }
+ if ( $this->title !== null ) {
+ $array['title'] = $this->title->jsonSerialize();
+ }
+ return $array;
+ }
+
+ /**
+ * @param array $array
+ *
+ * @returns self
+ */
+ public static function jsonDeserialize( $array ) {
+ return new self(
+ isset( $array['title'] ) ? Title::jsonDeserialize( $array['title'] ) : null,
+ isset( $array['id'] ) ? $array['id'] : null
+
+ );
+ }
+}
+ \ No newline at end of file
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/Pages.php b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/Pages.php
new file mode 100644
index 00000000..b8c5614c
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/Pages.php
@@ -0,0 +1,99 @@
+<?php
+
+namespace Mediawiki\DataModel;
+
+use InvalidArgumentException;
+use RuntimeException;
+
+/**
+ * Represents a collection or Page classes
+ * @author Addshore
+ */
+class Pages {
+
+ /**
+ * @var Page[]
+ */
+ private $pages;
+
+ /**
+ * @param Page[] $pages
+ */
+ public function __construct( $pages = array() ) {
+ $this->pages = array();
+ $this->addPages( $pages );
+ }
+
+ /**
+ * @param Page[]|Pages $pages
+ *
+ * @throws InvalidArgumentException
+ */
+ public function addPages( $pages ) {
+ if( !is_array( $pages ) && !$pages instanceof Pages ) {
+ throw new InvalidArgumentException( '$pages needs to either be an array or a Pages object' );
+ }
+ if( $pages instanceof Pages ) {
+ $pages = $pages->toArray();
+ }
+ foreach( $pages as $page ) {
+ $this->addPage( $page );
+ }
+ }
+
+ /**
+ * @param Page $page
+ */
+ public function addPage( Page $page ) {
+ $this->pages[$page->getId()] = $page;
+ }
+
+ /**
+ * @param int $id
+ *
+ * @return bool
+ */
+ public function hasPageWithId( $id ){
+ return array_key_exists( $id, $this->pages );
+ }
+
+ /**
+ * @param Page $page
+ *
+ * @return bool
+ */
+ public function hasPage( Page $page ){
+ return array_key_exists( $page->getId(), $this->pages );
+ }
+
+ /**
+ * @return Page|null Page or null if there is no page
+ */
+ public function getLatest() {
+ if( empty( $this->pages ) ) {
+ return null;
+ }
+ return $this->pages[ max( array_keys( $this->pages ) ) ];
+ }
+
+
+ /**
+ * @param int $pageid
+ *
+ * @throws RuntimeException
+ * @return Page
+ */
+ public function get( $pageid ){
+ if( $this->hasPageWithId( $pageid ) ){
+ return $this->pages[$pageid];
+ }
+ throw new RuntimeException( 'No such page loaded in Pages object' );
+ }
+
+ /**
+ * @return Page[]
+ */
+ public function toArray() {
+ return $this->pages;
+ }
+} \ No newline at end of file
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/Redirect.php b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/Redirect.php
new file mode 100644
index 00000000..55b8b607
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/Redirect.php
@@ -0,0 +1,53 @@
+<?php
+
+namespace Mediawiki\DataModel;
+
+use JsonSerializable;
+
+class Redirect implements JsonSerializable {
+
+ private $from;
+ private $to;
+
+ public function __construct( Title $from, Title $to ) {
+ $this->from = $from;
+ $this->to = $to;
+ }
+
+ /**
+ * @return Title
+ */
+ public function getFrom() {
+ return $this->from;
+ }
+
+ /**
+ * @return Title
+ */
+ public function getTo() {
+ return $this->to;
+ }
+
+ /**
+ * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
+ */
+ public function jsonSerialize() {
+ return array(
+ 'from' => $this->from->jsonSerialize(),
+ 'to' => $this->to->jsonSerialize(),
+ );
+ }
+
+ /**
+ * @param array $json
+ *
+ * @return self
+ */
+ public static function jsonDeserialize( $json ) {
+ return new self(
+ Title::jsonDeserialize( $json['from'] ),
+ Title::jsonDeserialize( $json['to'] )
+ );
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/Revision.php b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/Revision.php
new file mode 100644
index 00000000..09afe63f
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/Revision.php
@@ -0,0 +1,106 @@
+<?php
+
+namespace Mediawiki\DataModel;
+
+/**
+ * Representation of a version of content
+ * @author Addshore
+ */
+class Revision {
+
+ /**
+ * @var int Id of the revision
+ */
+ private $id;
+
+ /**
+ * @var PageIdentifier of the page for the revision
+ */
+ private $pageIdentifier;
+
+ /**
+ * @var Content
+ */
+ private $content;
+
+ /**
+ * @var EditInfo
+ */
+ private $editInfo;
+
+ /**
+ * @var null|string
+ */
+ private $user;
+
+ /**
+ * @var null|string
+ */
+ private $timestamp;
+
+ /**
+ * @param Content $content
+ * @param PageIdentifier|null $pageIdentifier
+ * @param int|null $revId
+ * @param EditInfo|null $editInfo
+ * @param string|null $user
+ * @param string|null $timestamp
+ */
+ public function __construct( Content $content, PageIdentifier $pageIdentifier = null, $revId = null, EditInfo $editInfo = null, $user = null, $timestamp = null ) {
+ if( is_null( $editInfo ) ) {
+ $editInfo = new EditInfo();
+ }
+ if( is_null( $pageIdentifier ) ) {
+ $pageIdentifier = new PageIdentifier();
+ }
+ $this->content = $content;
+ $this->pageIdentifier = $pageIdentifier;
+ $this->id = $revId;
+ $this->editInfo = $editInfo;
+ $this->user = $user;
+ $this->timestamp = $timestamp;
+ }
+
+ /**
+ * @return Content
+ */
+ public function getContent() {
+ return $this->content;
+ }
+
+ /**
+ * @return EditInfo
+ */
+ public function getEditInfo() {
+ return $this->editInfo;
+ }
+
+ /**
+ * @return int|null
+ */
+ public function getId() {
+ return $this->id;
+ }
+
+ /**
+ * @return PageIdentifier|null
+ */
+ public function getPageIdentifier() {
+ return $this->pageIdentifier;
+ }
+
+ /**
+ * @return null|string
+ */
+ public function getUser() {
+ return $this->user;
+ }
+
+ /**
+ * @return null|string
+ */
+ public function getTimestamp() {
+ return $this->timestamp;
+ }
+
+} \ No newline at end of file
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/Revisions.php b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/Revisions.php
new file mode 100644
index 00000000..c6d2f436
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/Revisions.php
@@ -0,0 +1,102 @@
+<?php
+
+namespace Mediawiki\DataModel;
+
+use InvalidArgumentException;
+use RuntimeException;
+
+/**
+ * Represents a collection or revisions
+ * @author Addshore
+ */
+class Revisions {
+
+ /**
+ * @var Revision[]
+ */
+ private $revisions;
+
+ /**
+ * @param Revisions[] $revisions
+ */
+ public function __construct( $revisions = array() ) {
+ $this->revisions = array();
+ $this->addRevisions( $revisions );
+ }
+
+ /**
+ * @param Revision[]|Revisions $revisions
+ *
+ * @throws InvalidArgumentException
+ */
+ public function addRevisions( $revisions ) {
+ if( !is_array( $revisions ) && !$revisions instanceof Revisions ) {
+ throw new InvalidArgumentException( '$revisions needs to either be an array or a Revisions object' );
+ }
+ if( $revisions instanceof Revisions ) {
+ $revisions = $revisions->toArray();
+ }
+ foreach( $revisions as $revision ) {
+ $this->addRevision( $revision );
+ }
+ }
+
+ /**
+ * @param Revision $revision
+ */
+ public function addRevision( Revision $revision ) {
+ $this->revisions[$revision->getId()] = $revision;
+ }
+
+ /**
+ * @param int $id
+ *
+ * @return bool
+ */
+ public function hasRevisionWithId( $id ){
+ return array_key_exists( $id, $this->revisions );
+ }
+
+ /**
+ * @param Revision $revision
+ *
+ * @return bool
+ */
+ public function hasRevision( Revision $revision ){
+ return array_key_exists( $revision->getId(), $this->revisions );
+ }
+
+ /**
+ * @return Revision|null Revision or null if there is no revision
+ */
+ public function getLatest() {
+ if( empty( $this->revisions ) ) {
+ return null;
+ }
+ return $this->revisions[ max( array_keys( $this->revisions ) ) ];
+ }
+
+ /**
+ * @param int $revid
+ *
+ * @throws RuntimeException
+ * @throws InvalidArgumentException
+ * @return Revision
+ */
+ public function get( $revid ){
+ if( !is_int( $revid ) ) {
+ throw new InvalidArgumentException( '$revid needs to be an int' );
+ }
+ if( $this->hasRevisionWithId( $revid ) ){
+ return $this->revisions[$revid];
+ }
+ throw new RuntimeException( 'No such revision loaded in Revisions object' );
+ }
+
+ /**
+ * @return Revision[]
+ */
+ public function toArray() {
+ return $this->revisions;
+ }
+} \ No newline at end of file
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/Title.php b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/Title.php
new file mode 100644
index 00000000..1fb15138
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/Title.php
@@ -0,0 +1,83 @@
+<?php
+
+namespace Mediawiki\DataModel;
+
+use InvalidArgumentException;
+use JsonSerializable;
+
+/**
+ * @author Addshore
+ */
+class Title implements JsonSerializable {
+
+ /**
+ * @var string
+ */
+ private $title;
+
+ /**
+ * @var int
+ */
+ private $ns;
+
+ /**
+ * @param string $title
+ * @param int $ns
+ *
+ * @throws InvalidArgumentException
+ */
+ public function __construct( $title, $ns = 0 ) {
+ if( !is_string( $title ) ) {
+ throw new InvalidArgumentException( '$title must be a string' );
+ }
+ if( !is_int( $ns ) ) {
+ throw new InvalidArgumentException( '$ns must be an int' );
+ }
+ $this->title = $title;
+ $this->ns = $ns;
+ }
+
+ /**
+ * @return int
+ * @since 0.1
+ */
+ public function getNs() {
+ return $this->ns;
+ }
+
+ /**
+ * @return string
+ * @since 0.6
+ */
+ public function getText() {
+ return $this->title;
+ }
+
+ /**
+ * @return string
+ * @deprecated in 0.6 use getText (makes things look cleaner)
+ */
+ public function getTitle() {
+ return $this->getText();
+ }
+
+ /**
+ * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
+ */
+ public function jsonSerialize() {
+ return array(
+ 'title' => $this->title,
+ 'ns' => $this->ns,
+ );
+ }
+
+ /**
+ * @param array $json
+ *
+ * @return self
+ */
+ public static function jsonDeserialize( $json ) {
+ return new self( $json['title'], $json['ns'] );
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/User.php b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/User.php
new file mode 100644
index 00000000..fca5ddf3
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/src/User.php
@@ -0,0 +1,140 @@
+<?php
+
+namespace Mediawiki\DataModel;
+
+use InvalidArgumentException;
+
+/**
+ * Represents a mediawiki user
+ * @author Addshore
+ */
+class User {
+
+ /**
+ * @var string
+ */
+ private $name;
+
+ /**
+ * @var int
+ */
+ private $id;
+
+ /**
+ * @var int
+ */
+ private $editcount;
+
+ /**
+ * @var string
+ */
+ private $registration;
+
+ /**
+ * @var array
+ */
+ private $groups;
+
+ /**
+ * @var array
+ */
+ private $rights;
+
+ /**
+ * @var string
+ */
+ private $gender;
+
+ /**
+ * @param string $name
+ * @param int $id
+ * @param int $editcount
+ * @param string $registration
+ * @param array[] $groups groups grouped by type.
+ * Keys to use are 'groups' and 'implicitgroups' as returned by the api.
+ * @param array $rights
+ * @param string $gender
+ *
+ * @throws InvalidArgumentException
+ */
+ public function __construct( $name, $id, $editcount, $registration, $groups, $rights, $gender ) {
+ if( !is_string( $name ) || empty( $name ) ) {
+ throw new InvalidArgumentException( '$name must be a string and can not be empty' );
+ }
+ if( !is_int( $id ) ) {
+ throw new InvalidArgumentException( '$id must be an int' );
+ }
+ if( !is_int( $editcount ) ) {
+ throw new InvalidArgumentException( '$editcount must be an int' );
+ }
+ if( !is_array( $groups ) || !array_key_exists( 'groups', $groups ) || !array_key_exists( 'implicitgroups', $groups ) ) {
+ throw new InvalidArgumentException( '$groups must be an array or arrays with keys "groups" and "implicitgroups"' );
+ }
+ if( !is_array( $rights ) ) {
+ throw new InvalidArgumentException( '$rights must be an array' );
+ }
+ if( !is_string( $gender ) ) {
+ throw new InvalidArgumentException( '$gender must be a string' );
+ }
+
+ $this->editcount = $editcount;
+ $this->gender = $gender;
+ $this->groups = $groups;
+ $this->id = $id;
+ $this->name = $name;
+ $this->registration = $registration;
+ $this->rights = $rights;
+ }
+
+ /**
+ * @return int
+ */
+ public function getEditcount() {
+ return $this->editcount;
+ }
+
+ /**
+ * @return string
+ */
+ public function getGender() {
+ return $this->gender;
+ }
+
+ /**
+ * @param string $type 'groups' or 'implicitgroups'
+ *
+ * @return array
+ */
+ public function getGroups( $type = 'groups' ) {
+ return $this->groups[$type];
+ }
+
+ /**
+ * @return int
+ */
+ public function getId() {
+ return $this->id;
+ }
+
+ /**
+ * @return string
+ */
+ public function getName() {
+ return $this->name;
+ }
+
+ /**
+ * @return string
+ */
+ public function getRegistration() {
+ return $this->registration;
+ }
+
+ /**
+ * @return array
+ */
+ public function getRights() {
+ return $this->rights;
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/ContentTest.php b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/ContentTest.php
new file mode 100644
index 00000000..e412749a
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/ContentTest.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Mediawiki\DataModel\Test;
+
+use Mediawiki\DataModel\Content;
+use PHPUnit_Framework_TestCase;
+
+class ContentTest extends PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider provideValidConstruction
+ */
+ public function testValidConstruction( $data, $model ) {
+ $content = new Content( $data, $model );
+ $this->assertEquals( $data, $content->getData() );
+ $this->assertEquals( $model, $content->getModel() );
+ $this->assertTrue( is_string( $content->getHash() ) );
+ $this->assertFalse( $content->hasChanged() );
+ }
+
+ public function provideValidConstruction() {
+ return array(
+ array( '', null ),
+ array( 'foo', null ),
+ array( new \stdClass(), null ),
+ );
+ }
+
+}
+ \ No newline at end of file
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/EditInfoTest.php b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/EditInfoTest.php
new file mode 100644
index 00000000..c3128bca
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/EditInfoTest.php
@@ -0,0 +1,51 @@
+<?php
+
+namespace Mediawiki\DataModel\Test;
+
+use Mediawiki\DataModel\EditInfo;
+use PHPUnit_Framework_TestCase;
+
+/**
+ * @covers \Mediawiki\DataModel\EditInfo
+ * @author Addshore
+ */
+class EditInfoTest extends PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider provideValidConstruction
+ */
+ public function testValidConstruction( $sum, $minor, $bot ) {
+ $flags = new EditInfo( $sum, $minor, $bot );
+ $this->assertEquals( $sum, $flags->getSummary() );
+ $this->assertEquals( $minor, $flags->getMinor() );
+ $this->assertEquals( $bot, $flags->getBot() );
+ }
+
+ public function provideValidConstruction() {
+ return array(
+ array( '', EditInfo::MINOR, EditInfo::BOT ),
+ array( '', EditInfo::MINOR, EditInfo::NOTBOT ),
+ array( '', EditInfo::NOTMINOR, EditInfo::BOT ),
+ array( '', EditInfo::NOTMINOR, EditInfo::NOTBOT ),
+ array( 'FOO', EditInfo::NOTMINOR, EditInfo::NOTBOT ),
+ );
+ }
+
+ /**
+ * @dataProvider provideInvalidConstruction
+ */
+ public function testInvalidConstruction( $sum, $minor, $bot ) {
+ $this->setExpectedException( 'InvalidArgumentException' );
+ new EditInfo( $sum, $minor, $bot );
+ }
+
+ public function provideInvalidConstruction() {
+ return array(
+ array( 1, 2, 3 ),
+ array( "foo", false, 3 ),
+ array( "foo", 3, false ),
+ array( array(), true, false ),
+ );
+ }
+
+} \ No newline at end of file
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/FileTest.php b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/FileTest.php
new file mode 100644
index 00000000..0da77bd1
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/FileTest.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace Mediawiki\DataModel\Test;
+
+use Mediawiki\DataModel\File;
+use Mediawiki\DataModel\PageIdentifier;
+
+/**
+ * @covers \Mediawiki\DataModel\File
+ * @author Addshore
+ */
+class FileTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider provideValidConstruction
+ */
+ public function testValidConstruction( $url ) {
+ $file = new File(
+ $url,
+ new PageIdentifier( $this->newMockTitle(), 1 ),
+ $this->newMockRevisions()
+ );
+ $this->assertEquals( $url, $file->getUrl() );
+ }
+
+ public function provideValidConstruction() {
+ return array(
+ array( 'http://upload.wikimedia.org/wikipedia/en/3/39/Journal_of_Geek_Studies_-_logo.jpg' ),
+ );
+ }
+
+ private function newMockTitle() {
+ return $this->getMockBuilder( '\Mediawiki\DataModel\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ private function newMockRevisions() {
+ return $this->getMockBuilder( '\Mediawiki\DataModel\Revisions' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+} \ No newline at end of file
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/LogListTest.php b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/LogListTest.php
new file mode 100644
index 00000000..1098a8a6
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/LogListTest.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace Mediawiki\DataModel\Test;
+
+use Mediawiki\DataModel\Log;
+use Mediawiki\DataModel\LogList;
+use Mediawiki\DataModel\PageIdentifier;
+
+/**
+ * @covers \Mediawiki\DataModel\LogList
+ * @author Addshore
+ */
+class LogListTest extends \PHPUnit_Framework_TestCase {
+
+ public function testJsonRoundTrip() {
+ $logList = new LogList( array(
+ new Log( 1, 'ty', 'ac', '2014', 'Addshore', new PageIdentifier( null, 22 ), 'comment', array() ),
+ new Log( 2, 'ty2', 'ac2', '2015', 'Addbot', new PageIdentifier( null, 33 ), 'comment2', array() ),
+ ) );
+ $json = $logList->jsonSerialize();
+ $json = json_decode( json_encode( $json ), true );
+ $this->assertEquals( $logList, LogList::jsonDeserialize( $json ) );
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/NamespaceInfoTest.php b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/NamespaceInfoTest.php
new file mode 100644
index 00000000..4587a8a0
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/NamespaceInfoTest.php
@@ -0,0 +1,72 @@
+<?php
+
+namespace Mediawiki\DataModel\Test;
+
+use Mediawiki\DataModel\NamespaceInfo;
+
+/**
+ * @covers \Mediawiki\DataModel\NamespaceInfo
+ * @author gbirke
+ */
+class NamespaceInfoTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @dataProvider provideValidConstruction
+ * @param int $id
+ * @param string $canonicalName
+ * @param string $localName
+ * @param string $caseHandling
+ * @param null $defaultContentModel
+ * @param array $aliases
+ */
+ public function testValidConstruction($id, $canonicalName, $localName, $caseHandling, $defaultContentModel = null,
+ $aliases = [] ) {
+ $namespace = new NamespaceInfo( $id, $canonicalName, $localName, $caseHandling, $defaultContentModel, $aliases );
+ $this->assertSame( $id, $namespace->getId() );
+ $this->assertSame( $canonicalName, $namespace->getCanonicalName() );
+ $this->assertSame( $localName, $namespace->getLocalName() );
+ $this->assertSame( $caseHandling, $namespace->getCaseHandling() );
+ $this->assertSame( $defaultContentModel, $namespace->getDefaultContentModel() );
+ $this->assertSame( $aliases, $namespace->getAliases() );
+ }
+
+ public function provideValidConstruction() {
+ return array(
+ array( -2, 'Media', 'Media', 'first-letter' ),
+ array( 0, '', '', 'first-letter' ),
+ array( 4, 'Project', 'Wikipedia', 'first-letter' ),
+ array( 2302, 'Gadget definition', 'Gadget definition', 'case-sensitive', 'GadgetDefinition' ),
+ array( 2302, 'Gadget definition', 'Gadget definition', 'case-sensitive', 'GadgetDefinition', [ 'GD' ] ),
+ );
+ }
+
+ /**
+ * @param $id
+ * @param $canonicalName
+ * @param $localName
+ * @param $caseHandling
+ * @param null $defaultContentModel
+ * @param array $aliases
+ *
+ * @dataProvider provideInvalidConstruction
+ */
+ public function testInvalidConstruction($id, $canonicalName, $localName, $caseHandling, $defaultContentModel = null,
+ $aliases = [] ) {
+ $this->setExpectedException( 'InvalidArgumentException' );
+ new NamespaceInfo( $id, $canonicalName, $localName, $caseHandling, $defaultContentModel, $aliases );
+ }
+
+ public function provideInvalidConstruction() {
+ return array(
+ array( .5, 'Media', 'Media', 'first-letter' ),
+ array( '0', '', '', 'first-letter' ),
+ array( -2, null, 'Media', 'first-letter' ),
+ array( -2, 'Media', null, 'first-letter' ),
+ array( 4, 'Project', 'Wikipedia', 'first-letter', 5 ),
+ array( 2302, null, 'Gadget definition', 'case-sensitive', 'GadgetDefinition' ),
+ array( 4, 'Project', 'Wikipedia', 'first-letter', 5 ),
+ array( 4, 'Project', 'Wikipedia', 'first-letter', 'GadgetDefinition', 'notanalias' ),
+ );
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/PageIdentifierTest.php b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/PageIdentifierTest.php
new file mode 100644
index 00000000..42aa8412
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/PageIdentifierTest.php
@@ -0,0 +1,54 @@
+<?php
+
+namespace Mediawiki\DataModel\Test;
+
+use Mediawiki\DataModel\PageIdentifier;
+use Mediawiki\DataModel\Title;
+
+/**
+ * @covers Mediawiki\DataModel\PageIdentifier
+ */
+class PageIdentifierTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider provideValidConstruction
+ */
+ public function testValidConstruction( $title, $pageid, $identifiesPage ) {
+ $pageIdentifier = new PageIdentifier( $title, $pageid );
+ if( is_string( $title ) ) {
+ $this->assertEquals( new Title( $title ), $pageIdentifier->getTitle() );
+ } else {
+ $this->assertEquals( $title, $pageIdentifier->getTitle() );
+ }
+ $this->assertEquals( $pageid, $pageIdentifier->getId() );
+ $this->assertEquals( $identifiesPage, $pageIdentifier->identifiesPage() );
+ }
+
+ public function provideValidConstruction() {
+ return array(
+ array( null, null, false ),
+ array( new Title( 'Foo' ), null, true ),
+ array( new Title( 'Foo', 2 ), null, true ),
+ array( null, 3, true ),
+ );
+ }
+
+ public function provideRoundTripObjects() {
+ return array(
+ array( new PageIdentifier( null, null ) ),
+ array( new PageIdentifier( null, 44 ) ),
+ array( new PageIdentifier( new Title( 'someTitle', 12 ), null ) ),
+ array( new PageIdentifier( new Title( 'someTitle', 55 ), 99 ) ),
+ );
+ }
+
+ /**
+ * @dataProvider provideRoundTripObjects
+ */
+ public function testJsonRoundTrip( PageIdentifier $identifierObject ) {
+ $json = $identifierObject->jsonSerialize();
+ $this->assertEquals( $identifierObject, PageIdentifier::jsonDeserialize( $json ) );
+ }
+
+}
+ \ No newline at end of file
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/PageTest.php b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/PageTest.php
new file mode 100644
index 00000000..cbc31c8c
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/PageTest.php
@@ -0,0 +1,48 @@
+<?php
+
+namespace Mediawiki\DataModel\Test;
+
+use Mediawiki\DataModel\Page;
+use Mediawiki\DataModel\PageIdentifier;
+
+/**
+ * @covers \Mediawiki\DataModel\Page
+ * @author Addshore
+ */
+class PageTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider provideValidConstruction
+ */
+ public function testValidConstruction( $pageIdentifier, $revisions ) {
+ $page = new Page( $pageIdentifier, $revisions );
+ $this->assertEquals( $pageIdentifier, $page->getPageIdentifier() );
+ if( is_null( $revisions ) ) {
+ $this->assertInstanceOf( 'Mediawiki\DataModel\Revisions', $page->getRevisions() );
+ } else {
+ $this->assertEquals( $revisions, $page->getRevisions() );
+ }
+ }
+
+ public function provideValidConstruction() {
+ return array(
+ array( null, null ),
+ array( null, $this->newMockRevisions() ),
+ array( new PageIdentifier( $this->newMockTitle(), 1 ), $this->newMockRevisions() ),
+ array( new PageIdentifier( $this->newMockTitle(), 123 ), null ),
+ );
+ }
+
+ private function newMockTitle() {
+ return $this->getMockBuilder( '\Mediawiki\DataModel\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ private function newMockRevisions() {
+ return $this->getMockBuilder( '\Mediawiki\DataModel\Revisions' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+} \ No newline at end of file
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/PagesTest.php b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/PagesTest.php
new file mode 100644
index 00000000..0055ecc7
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/PagesTest.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace Mediawiki\DataModel\Test;
+
+use Mediawiki\DataModel\Page;
+use Mediawiki\DataModel\PageIdentifier;
+use Mediawiki\DataModel\Pages;
+
+/**
+ * @covers \Mediawiki\DataModel\Pages
+ * @author Addshore
+ */
+class PagesTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider provideValidConstruction
+ */
+ public function testValidConstruction( $input, $expected ) {
+ $pages = new Pages( $input );
+ $this->assertEquals( $expected, $pages->toArray() );
+ }
+
+ public function provideValidConstruction() {
+ $mockTitle = $this->getMockBuilder( 'Mediawiki\DataModel\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ $mockRevisions = $this->getMockBuilder( 'Mediawiki\DataModel\Revisions' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ //todo mock these
+ $page1 = new Page( new PageIdentifier( $mockTitle, 1 ), $mockRevisions );
+ $page2 = new Page( new PageIdentifier( $mockTitle, 2 ), $mockRevisions );
+ $page4 = new Page( new PageIdentifier( $mockTitle, 4 ), $mockRevisions );
+
+ return array(
+ array( array( $page1 ), array( 1 => $page1 ) ),
+ array( array( $page2, $page1 ), array( 1 => $page1, 2 => $page2 ) ),
+ array( array( $page4, $page1 ), array( 1 => $page1, 4 => $page4 ) ),
+ array( new Pages( array( $page4, $page1 ) ), array( 1 => $page1, 4 => $page4 ) ),
+ );
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/RedirectTest.php b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/RedirectTest.php
new file mode 100644
index 00000000..0f561e92
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/RedirectTest.php
@@ -0,0 +1,20 @@
+<?php
+
+namespace Mediawiki\DataModel\Test;
+
+use Mediawiki\DataModel\Redirect;
+use Mediawiki\DataModel\Title;
+
+/**
+ * @covers \Mediawiki\DataModel\Redirect
+ * @author Addshore
+ */
+class RedirectTest extends \PHPUnit_Framework_TestCase {
+
+ public function testJsonRoundTrip() {
+ $title = new Redirect( new Title( 'Foo', 12 ), new Title( 'bar', 13 ) );
+ $json = $title->jsonSerialize();
+ $this->assertEquals( $title, Redirect::jsonDeserialize( $json ) );
+ }
+
+}
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/RevisionTest.php b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/RevisionTest.php
new file mode 100644
index 00000000..e6260acb
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/RevisionTest.php
@@ -0,0 +1,57 @@
+<?php
+
+namespace Mediawiki\DataModel\Test;
+
+use Mediawiki\DataModel\PageIdentifier;
+use Mediawiki\DataModel\Revision;
+
+/**
+ * @covers \Mediawiki\DataModel\Revision
+ * @author Addshore
+ */
+class RevisionTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider provideValidConstruction
+ */
+ public function testValidConstruction( $content, $pageIdentifier, $id, $editInfo, $user, $timestamp ) {
+ $rev = new Revision( $content, $pageIdentifier, $id, $editInfo, $user, $timestamp );
+ $this->assertEquals( $content, $rev->getContent() );
+ if( !is_null( $pageIdentifier ) ) {
+ $this->assertEquals( $pageIdentifier, $rev->getPageIdentifier() );
+ } else {
+ $this->assertInstanceOf( '\Mediawiki\DataModel\PageIdentifier', $rev->getPageIdentifier() );
+ }
+
+ $this->assertEquals( $id, $rev->getId() );
+ if( !is_null( $editInfo ) ) {
+ $this->assertEquals( $editInfo, $rev->getEditInfo() );
+ } else {
+ $this->assertInstanceOf( '\Mediawiki\DataModel\EditInfo', $rev->getEditInfo() );
+ }
+ $this->assertEquals( $user, $rev->getUser() );
+ $this->assertEquals( $timestamp, $rev->getTimestamp() );
+ }
+
+ public function provideValidConstruction() {
+ $mockContent = $this->getMockBuilder( 'Mediawiki\DataModel\Content' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ $mockEditInfo = $this->getMockBuilder( '\Mediawiki\DataModel\EditInfo' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ $mockTitle = $this->getMockBuilder( 'Mediawiki\DataModel\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ return array(
+ array( $mockContent, null, null, null, null, null ),
+ array( $mockContent, new PageIdentifier( null, 1 ), null , null, null,null ),
+ array( $mockContent, new PageIdentifier( null, 1 ), 1 , null, null, null ),
+ array( $mockContent, new PageIdentifier( null, 2 ), 1 , $mockEditInfo, null, null ),
+ array( $mockContent, new PageIdentifier( $mockTitle ), 1 , $mockEditInfo, 'foo', null ),
+ array( $mockContent, new PageIdentifier( $mockTitle, 3 ), 1 , $mockEditInfo, 'foo', '20141212121212' ),
+ );
+ }
+
+} \ No newline at end of file
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/RevisionsTest.php b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/RevisionsTest.php
new file mode 100644
index 00000000..6b7afbed
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/RevisionsTest.php
@@ -0,0 +1,41 @@
+<?php
+
+namespace Mediawiki\DataModel\Test;
+
+use Mediawiki\DataModel\PageIdentifier;
+use Mediawiki\DataModel\Revision;
+use Mediawiki\DataModel\Revisions;
+
+/**
+ * @covers \Mediawiki\DataModel\Revisions
+ * @author Addshore
+ */
+class RevisionsTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider provideValidConstruction
+ */
+ public function testValidConstruction( $input, $expected ) {
+ $revisions = new Revisions( $input );
+ $this->assertEquals( $expected, $revisions->toArray() );
+ }
+
+ public function provideValidConstruction() {
+ $mockContent = $this->getMockBuilder( 'Mediawiki\DataModel\Content' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ //todo mock these
+ $rev1 = new Revision( $mockContent, new PageIdentifier( null, 1 ), 1 );
+ $rev2 = new Revision( $mockContent, new PageIdentifier( null, 1 ), 2 );
+ $rev4 = new Revision( $mockContent, new PageIdentifier( null, 1 ), 4 );
+
+ return array(
+ array( array( $rev1 ), array( 1 => $rev1 ) ),
+ array( array( $rev2, $rev1 ), array( 1 => $rev1, 2 => $rev2 ) ),
+ array( array( $rev4, $rev1 ), array( 1 => $rev1, 4 => $rev4 ) ),
+ array( new Revisions( array( $rev4, $rev1 ) ), array( 1 => $rev1, 4 => $rev4 ) ),
+ );
+ }
+
+} \ No newline at end of file
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/TitleTest.php b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/TitleTest.php
new file mode 100644
index 00000000..2c4d73da
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/TitleTest.php
@@ -0,0 +1,56 @@
+<?php
+
+namespace Mediawiki\DataModel\Test;
+
+use Mediawiki\DataModel\Title;
+
+/**
+ * @covers \Mediawiki\DataModel\Title
+ * @author Addshore
+ */
+class TitleTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider provideValidConstruction
+ */
+ public function testValidConstruction( $title, $ns ) {
+ $titleObj = new Title( $title, $ns );
+ $this->assertEquals( $title, $titleObj->getText() );
+ $this->assertEquals( $title, $titleObj->getTitle() );
+ $this->assertEquals( $ns, $titleObj->getNs() );
+ }
+
+ public function provideValidConstruction() {
+ return array(
+ array( 'fooo', 0 ),
+ array( 'Foo:Bar', 15 ),
+ array( 'FooBar:Bar', 9999 ),
+ );
+ }
+
+ /**
+ * @dataProvider provideInvalidConstruction
+ */
+ public function testInvalidConstruction( $title, $ns ) {
+ $this->setExpectedException( 'InvalidArgumentException' );
+ new Title( $title, $ns );
+ }
+
+ public function provideInvalidConstruction() {
+ return array(
+ array( array(), array() ),
+ array( 'foo', array() ),
+ array( array(), 1 ),
+ array( null, 1 ),
+ array( null, null ),
+ array( 'foo', null ),
+ );
+ }
+
+ public function testJsonRoundTrip() {
+ $title = new Title( 'Foo', 19 );
+ $json = $title->jsonSerialize();
+ $this->assertEquals( $title, Title::jsonDeserialize( $json ) );
+ }
+
+} \ No newline at end of file
diff --git a/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/UserTest.php b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/UserTest.php
new file mode 100644
index 00000000..fcf89994
--- /dev/null
+++ b/bin/reevotech/vendor/addwiki/mediawiki-datamodel/tests/UserTest.php
@@ -0,0 +1,59 @@
+<?php
+
+namespace Mediawiki\DataModel\Test;
+
+use Mediawiki\DataModel\User;
+
+/**
+ * @covers \Mediawiki\DataModel\User
+ * @author Addshore
+ */
+class UserTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider provideValidConstruction
+ */
+ public function testValidConstruction( $name, $id, $editcount, $registration, $groups, $rights, $gender ) {
+ $user = new User( $name, $id, $editcount, $registration, $groups, $rights, $gender );
+ $this->assertEquals( $name, $user->getName() );
+ $this->assertEquals( $id, $user->getId() );
+ $this->assertEquals( $editcount, $user->getEditcount() );
+ $this->assertEquals( $registration, $user->getRegistration() );
+ $this->assertEquals( $groups['groups'], $user->getGroups() );
+ $this->assertEquals( $groups['implicitgroups'], $user->getGroups( 'implicitgroups' ) );
+ $this->assertEquals( $rights, $user->getRights() );
+ $this->assertEquals( $gender, $user->getGender() );
+ }
+
+ public function provideValidConstruction() {
+ return array(
+ array( 'Username', 1, 1, 'TIMESTAMP', array( 'groups' => array(), 'implicitgroups' => array() ), array(), 'male' ),
+ array( 'Username', 1, 1, 'TIMESTAMP', array( 'groups' => array(), 'implicitgroups' => array() ), array(), 'female' ),
+ array( 'Username', 99999999, 99999997, 'TIMESTAMP', array( 'groups' => array(), 'implicitgroups' => array() ), array(), 'male' ),
+ array( 'Username', 1, 1, null, array( 'groups' => array(), 'implicitgroups' => array() ), array(), 'female' ),
+ );
+ }
+
+ /**
+ * @dataProvider provideInvalidConstruction
+ */
+ public function testInvalidConstruction( $name, $id, $editcount, $registration, $groups, $rights, $gender ) {
+ $this->setExpectedException( 'InvalidArgumentException' );
+ new User( $name, $id, $editcount, $registration, $groups, $rights, $gender );
+ }
+
+ public function provideInvalidConstruction() {
+ return array(
+ array( 'Username', 1, 1, 'TIMESTAMP', 'bad', array(), 'male' ),
+ array( 'Username', 1, 1, 'TIMESTAMP', array( 'groups' => array(), 'implicitgroups' => array() ), 'bad', 'male' ),
+ array( 'Username', 1, 1, 'TIMESTAMP', array( 'groups' => array(), 'implicitgroups' => array() ), array(), 1 ),
+ array( 'Username', 1, 'bad', 'TIMESTAMP', array( 'groups' => array(), 'implicitgroups' => array() ), array(), 'male' ),
+ array( 'Username', 'bad', 1, 'TIMESTAMP', array( 'groups' => array(), 'implicitgroups' => array() ), array(), 'male' ),
+ array( 14287941, 1, 1, 'TIMESTAMP', array( 'groups' => array(), 'implicitgroups' => array() ), array(), 'male' ),
+ array( 'Username', 1, 1, 'TIMESTAMP', array( 'groups' => array(), 'foo' => array() ), array(), 'male' ),
+ array( 'Username', 1, 1, 'TIMESTAMP', array( 'groups' => array() ), array(), 'male' ),
+ array( 'Username', 1, 1, 'TIMESTAMP', array(), array(), 'male' ),
+ );
+ }
+
+}
diff --git a/bin/reevotech/vendor/autoload.php b/bin/reevotech/vendor/autoload.php
new file mode 100644
index 00000000..99420711
--- /dev/null
+++ b/bin/reevotech/vendor/autoload.php
@@ -0,0 +1,7 @@
+<?php
+
+// autoload.php @generated by Composer
+
+require_once __DIR__ . '/composer/autoload_real.php';
+
+return ComposerAutoloaderInit1597705ddb4a19e7b99e0b2375ab438e::getLoader();
diff --git a/bin/reevotech/vendor/composer/ClassLoader.php b/bin/reevotech/vendor/composer/ClassLoader.php
new file mode 100644
index 00000000..2c72175e
--- /dev/null
+++ b/bin/reevotech/vendor/composer/ClassLoader.php
@@ -0,0 +1,445 @@
+<?php
+
+/*
+ * This file is part of Composer.
+ *
+ * (c) Nils Adermann <naderman@naderman.de>
+ * Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Composer\Autoload;
+
+/**
+ * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
+ *
+ * $loader = new \Composer\Autoload\ClassLoader();
+ *
+ * // register classes with namespaces
+ * $loader->add('Symfony\Component', __DIR__.'/component');
+ * $loader->add('Symfony', __DIR__.'/framework');
+ *
+ * // activate the autoloader
+ * $loader->register();
+ *
+ * // to enable searching the include path (eg. for PEAR packages)
+ * $loader->setUseIncludePath(true);
+ *
+ * In this example, if you try to use a class in the Symfony\Component
+ * namespace or one of its children (Symfony\Component\Console for instance),
+ * the autoloader will first look for the class under the component/
+ * directory, and it will then fallback to the framework/ directory if not
+ * found before giving up.
+ *
+ * This class is loosely based on the Symfony UniversalClassLoader.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Jordi Boggiano <j.boggiano@seld.be>
+ * @see http://www.php-fig.org/psr/psr-0/
+ * @see http://www.php-fig.org/psr/psr-4/
+ */
+class ClassLoader
+{
+ // PSR-4
+ private $prefixLengthsPsr4 = array();
+ private $prefixDirsPsr4 = array();
+ private $fallbackDirsPsr4 = array();
+
+ // PSR-0
+ private $prefixesPsr0 = array();
+ private $fallbackDirsPsr0 = array();
+
+ private $useIncludePath = false;
+ private $classMap = array();
+ private $classMapAuthoritative = false;
+ private $missingClasses = array();
+ private $apcuPrefix;
+
+ public function getPrefixes()
+ {
+ if (!empty($this->prefixesPsr0)) {
+ return call_user_func_array('array_merge', $this->prefixesPsr0);
+ }
+
+ return array();
+ }
+
+ public function getPrefixesPsr4()
+ {
+ return $this->prefixDirsPsr4;
+ }
+
+ public function getFallbackDirs()
+ {
+ return $this->fallbackDirsPsr0;
+ }
+
+ public function getFallbackDirsPsr4()
+ {
+ return $this->fallbackDirsPsr4;
+ }
+
+ public function getClassMap()
+ {
+ return $this->classMap;
+ }
+
+ /**
+ * @param array $classMap Class to filename map
+ */
+ public function addClassMap(array $classMap)
+ {
+ if ($this->classMap) {
+ $this->classMap = array_merge($this->classMap, $classMap);
+ } else {
+ $this->classMap = $classMap;
+ }
+ }
+
+ /**
+ * Registers a set of PSR-0 directories for a given prefix, either
+ * appending or prepending to the ones previously set for this prefix.
+ *
+ * @param string $prefix The prefix
+ * @param array|string $paths The PSR-0 root directories
+ * @param bool $prepend Whether to prepend the directories
+ */
+ public function add($prefix, $paths, $prepend = false)
+ {
+ if (!$prefix) {
+ if ($prepend) {
+ $this->fallbackDirsPsr0 = array_merge(
+ (array) $paths,
+ $this->fallbackDirsPsr0
+ );
+ } else {
+ $this->fallbackDirsPsr0 = array_merge(
+ $this->fallbackDirsPsr0,
+ (array) $paths
+ );
+ }
+
+ return;
+ }
+
+ $first = $prefix[0];
+ if (!isset($this->prefixesPsr0[$first][$prefix])) {
+ $this->prefixesPsr0[$first][$prefix] = (array) $paths;
+
+ return;
+ }
+ if ($prepend) {
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
+ (array) $paths,
+ $this->prefixesPsr0[$first][$prefix]
+ );
+ } else {
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
+ $this->prefixesPsr0[$first][$prefix],
+ (array) $paths
+ );
+ }
+ }
+
+ /**
+ * Registers a set of PSR-4 directories for a given namespace, either
+ * appending or prepending to the ones previously set for this namespace.
+ *
+ * @param string $prefix The prefix/namespace, with trailing '\\'
+ * @param array|string $paths The PSR-4 base directories
+ * @param bool $prepend Whether to prepend the directories
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function addPsr4($prefix, $paths, $prepend = false)
+ {
+ if (!$prefix) {
+ // Register directories for the root namespace.
+ if ($prepend) {
+ $this->fallbackDirsPsr4 = array_merge(
+ (array) $paths,
+ $this->fallbackDirsPsr4
+ );
+ } else {
+ $this->fallbackDirsPsr4 = array_merge(
+ $this->fallbackDirsPsr4,
+ (array) $paths
+ );
+ }
+ } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
+ // Register directories for a new namespace.
+ $length = strlen($prefix);
+ if ('\\' !== $prefix[$length - 1]) {
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+ }
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
+ } elseif ($prepend) {
+ // Prepend directories for an already registered namespace.
+ $this->prefixDirsPsr4[$prefix] = array_merge(
+ (array) $paths,
+ $this->prefixDirsPsr4[$prefix]
+ );
+ } else {
+ // Append directories for an already registered namespace.
+ $this->prefixDirsPsr4[$prefix] = array_merge(
+ $this->prefixDirsPsr4[$prefix],
+ (array) $paths
+ );
+ }
+ }
+
+ /**
+ * Registers a set of PSR-0 directories for a given prefix,
+ * replacing any others previously set for this prefix.
+ *
+ * @param string $prefix The prefix
+ * @param array|string $paths The PSR-0 base directories
+ */
+ public function set($prefix, $paths)
+ {
+ if (!$prefix) {
+ $this->fallbackDirsPsr0 = (array) $paths;
+ } else {
+ $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
+ }
+ }
+
+ /**
+ * Registers a set of PSR-4 directories for a given namespace,
+ * replacing any others previously set for this namespace.
+ *
+ * @param string $prefix The prefix/namespace, with trailing '\\'
+ * @param array|string $paths The PSR-4 base directories
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function setPsr4($prefix, $paths)
+ {
+ if (!$prefix) {
+ $this->fallbackDirsPsr4 = (array) $paths;
+ } else {
+ $length = strlen($prefix);
+ if ('\\' !== $prefix[$length - 1]) {
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+ }
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
+ }
+ }
+
+ /**
+ * Turns on searching the include path for class files.
+ *
+ * @param bool $useIncludePath
+ */
+ public function setUseIncludePath($useIncludePath)
+ {
+ $this->useIncludePath = $useIncludePath;
+ }
+
+ /**
+ * Can be used to check if the autoloader uses the include path to check
+ * for classes.
+ *
+ * @return bool
+ */
+ public function getUseIncludePath()
+ {
+ return $this->useIncludePath;
+ }
+
+ /**
+ * Turns off searching the prefix and fallback directories for classes
+ * that have not been registered with the class map.
+ *
+ * @param bool $classMapAuthoritative
+ */
+ public function setClassMapAuthoritative($classMapAuthoritative)
+ {
+ $this->classMapAuthoritative = $classMapAuthoritative;
+ }
+
+ /**
+ * Should class lookup fail if not found in the current class map?
+ *
+ * @return bool
+ */
+ public function isClassMapAuthoritative()
+ {
+ return $this->classMapAuthoritative;
+ }
+
+ /**
+ * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
+ *
+ * @param string|null $apcuPrefix
+ */
+ public function setApcuPrefix($apcuPrefix)
+ {
+ $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
+ }
+
+ /**
+ * The APCu prefix in use, or null if APCu caching is not enabled.
+ *
+ * @return string|null
+ */
+ public function getApcuPrefix()
+ {
+ return $this->apcuPrefix;
+ }
+
+ /**
+ * Registers this instance as an autoloader.
+ *
+ * @param bool $prepend Whether to prepend the autoloader or not
+ */
+ public function register($prepend = false)
+ {
+ spl_autoload_register(array($this, 'loadClass'), true, $prepend);
+ }
+
+ /**
+ * Unregisters this instance as an autoloader.
+ */
+ public function unregister()
+ {
+ spl_autoload_unregister(array($this, 'loadClass'));
+ }
+
+ /**
+ * Loads the given class or interface.
+ *
+ * @param string $class The name of the class
+ * @return bool|null True if loaded, null otherwise
+ */
+ public function loadClass($class)
+ {
+ if ($file = $this->findFile($class)) {
+ includeFile($file);
+
+ return true;
+ }
+ }
+
+ /**
+ * Finds the path to the file where the class is defined.
+ *
+ * @param string $class The name of the class
+ *
+ * @return string|false The path if found, false otherwise
+ */
+ public function findFile($class)
+ {
+ // class map lookup
+ if (isset($this->classMap[$class])) {
+ return $this->classMap[$class];
+ }
+ if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
+ return false;
+ }
+ if (null !== $this->apcuPrefix) {
+ $file = apcu_fetch($this->apcuPrefix.$class, $hit);
+ if ($hit) {
+ return $file;
+ }
+ }
+
+ $file = $this->findFileWithExtension($class, '.php');
+
+ // Search for Hack files if we are running on HHVM
+ if (false === $file && defined('HHVM_VERSION')) {
+ $file = $this->findFileWithExtension($class, '.hh');
+ }
+
+ if (null !== $this->apcuPrefix) {
+ apcu_add($this->apcuPrefix.$class, $file);
+ }
+
+ if (false === $file) {
+ // Remember that this class does not exist.
+ $this->missingClasses[$class] = true;
+ }
+
+ return $file;
+ }
+
+ private function findFileWithExtension($class, $ext)
+ {
+ // PSR-4 lookup
+ $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
+
+ $first = $class[0];
+ if (isset($this->prefixLengthsPsr4[$first])) {
+ $subPath = $class;
+ while (false !== $lastPos = strrpos($subPath, '\\')) {
+ $subPath = substr($subPath, 0, $lastPos);
+ $search = $subPath.'\\';
+ if (isset($this->prefixDirsPsr4[$search])) {
+ foreach ($this->prefixDirsPsr4[$search] as $dir) {
+ $length = $this->prefixLengthsPsr4[$first][$search];
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
+ return $file;
+ }
+ }
+ }
+ }
+ }
+
+ // PSR-4 fallback dirs
+ foreach ($this->fallbackDirsPsr4 as $dir) {
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
+ return $file;
+ }
+ }
+
+ // PSR-0 lookup
+ if (false !== $pos = strrpos($class, '\\')) {
+ // namespaced class name
+ $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
+ . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
+ } else {
+ // PEAR-like class name
+ $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
+ }
+
+ if (isset($this->prefixesPsr0[$first])) {
+ foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
+ if (0 === strpos($class, $prefix)) {
+ foreach ($dirs as $dir) {
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
+ return $file;
+ }
+ }
+ }
+ }
+ }
+
+ // PSR-0 fallback dirs
+ foreach ($this->fallbackDirsPsr0 as $dir) {
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
+ return $file;
+ }
+ }
+
+ // PSR-0 include paths.
+ if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
+ return $file;
+ }
+
+ return false;
+ }
+}
+
+/**
+ * Scope isolated include.
+ *
+ * Prevents access to $this/self from included files.
+ */
+function includeFile($file)
+{
+ include $file;
+}
diff --git a/bin/reevotech/vendor/composer/LICENSE b/bin/reevotech/vendor/composer/LICENSE
new file mode 100644
index 00000000..f27399a0
--- /dev/null
+++ b/bin/reevotech/vendor/composer/LICENSE
@@ -0,0 +1,21 @@
+
+Copyright (c) Nils Adermann, Jordi Boggiano
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
diff --git a/bin/reevotech/vendor/composer/autoload_classmap.php b/bin/reevotech/vendor/composer/autoload_classmap.php
new file mode 100644
index 00000000..7a91153b
--- /dev/null
+++ b/bin/reevotech/vendor/composer/autoload_classmap.php
@@ -0,0 +1,9 @@
+<?php
+
+// autoload_classmap.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = dirname($vendorDir);
+
+return array(
+);
diff --git a/bin/reevotech/vendor/composer/autoload_files.php b/bin/reevotech/vendor/composer/autoload_files.php
new file mode 100644
index 00000000..03507c9c
--- /dev/null
+++ b/bin/reevotech/vendor/composer/autoload_files.php
@@ -0,0 +1,13 @@
+<?php
+
+// autoload_files.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = dirname($vendorDir);
+
+return array(
+ 'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
+ '7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
+ 'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php',
+ '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
+);
diff --git a/bin/reevotech/vendor/composer/autoload_namespaces.php b/bin/reevotech/vendor/composer/autoload_namespaces.php
new file mode 100644
index 00000000..b7fc0125
--- /dev/null
+++ b/bin/reevotech/vendor/composer/autoload_namespaces.php
@@ -0,0 +1,9 @@
+<?php
+
+// autoload_namespaces.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = dirname($vendorDir);
+
+return array(
+);
diff --git a/bin/reevotech/vendor/composer/autoload_psr4.php b/bin/reevotech/vendor/composer/autoload_psr4.php
new file mode 100644
index 00000000..bc85a820
--- /dev/null
+++ b/bin/reevotech/vendor/composer/autoload_psr4.php
@@ -0,0 +1,16 @@
+<?php
+
+// autoload_psr4.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = dirname($vendorDir);
+
+return array(
+ 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
+ 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'),
+ 'Mediawiki\\DataModel\\' => array($vendorDir . '/addwiki/mediawiki-datamodel/src'),
+ 'Mediawiki\\Api\\' => array($vendorDir . '/addwiki/mediawiki-api-base/src', $vendorDir . '/addwiki/mediawiki-api/src'),
+ 'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
+ 'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'),
+ 'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
+);
diff --git a/bin/reevotech/vendor/composer/autoload_real.php b/bin/reevotech/vendor/composer/autoload_real.php
new file mode 100644
index 00000000..10b15c45
--- /dev/null
+++ b/bin/reevotech/vendor/composer/autoload_real.php
@@ -0,0 +1,70 @@
+<?php
+
+// autoload_real.php @generated by Composer
+
+class ComposerAutoloaderInit1597705ddb4a19e7b99e0b2375ab438e
+{
+ private static $loader;
+
+ public static function loadClassLoader($class)
+ {
+ if ('Composer\Autoload\ClassLoader' === $class) {
+ require __DIR__ . '/ClassLoader.php';
+ }
+ }
+
+ public static function getLoader()
+ {
+ if (null !== self::$loader) {
+ return self::$loader;
+ }
+
+ spl_autoload_register(array('ComposerAutoloaderInit1597705ddb4a19e7b99e0b2375ab438e', 'loadClassLoader'), true, true);
+ self::$loader = $loader = new \Composer\Autoload\ClassLoader();
+ spl_autoload_unregister(array('ComposerAutoloaderInit1597705ddb4a19e7b99e0b2375ab438e', 'loadClassLoader'));
+
+ $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
+ if ($useStaticLoader) {
+ require_once __DIR__ . '/autoload_static.php';
+
+ call_user_func(\Composer\Autoload\ComposerStaticInit1597705ddb4a19e7b99e0b2375ab438e::getInitializer($loader));
+ } else {
+ $map = require __DIR__ . '/autoload_namespaces.php';
+ foreach ($map as $namespace => $path) {
+ $loader->set($namespace, $path);
+ }
+
+ $map = require __DIR__ . '/autoload_psr4.php';
+ foreach ($map as $namespace => $path) {
+ $loader->setPsr4($namespace, $path);
+ }
+
+ $classMap = require __DIR__ . '/autoload_classmap.php';
+ if ($classMap) {
+ $loader->addClassMap($classMap);
+ }
+ }
+
+ $loader->register(true);
+
+ if ($useStaticLoader) {
+ $includeFiles = Composer\Autoload\ComposerStaticInit1597705ddb4a19e7b99e0b2375ab438e::$files;
+ } else {
+ $includeFiles = require __DIR__ . '/autoload_files.php';
+ }
+ foreach ($includeFiles as $fileIdentifier => $file) {
+ composerRequire1597705ddb4a19e7b99e0b2375ab438e($fileIdentifier, $file);
+ }
+
+ return $loader;
+ }
+}
+
+function composerRequire1597705ddb4a19e7b99e0b2375ab438e($fileIdentifier, $file)
+{
+ if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
+ require $file;
+
+ $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
+ }
+}
diff --git a/bin/reevotech/vendor/composer/autoload_static.php b/bin/reevotech/vendor/composer/autoload_static.php
new file mode 100644
index 00000000..71b15755
--- /dev/null
+++ b/bin/reevotech/vendor/composer/autoload_static.php
@@ -0,0 +1,75 @@
+<?php
+
+// autoload_static.php @generated by Composer
+
+namespace Composer\Autoload;
+
+class ComposerStaticInit1597705ddb4a19e7b99e0b2375ab438e
+{
+ public static $files = array (
+ 'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',
+ '7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
+ 'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php',
+ '37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
+ );
+
+ public static $prefixLengthsPsr4 = array (
+ 'P' =>
+ array (
+ 'Psr\\Log\\' => 8,
+ 'Psr\\Http\\Message\\' => 17,
+ ),
+ 'M' =>
+ array (
+ 'Mediawiki\\DataModel\\' => 20,
+ 'Mediawiki\\Api\\' => 14,
+ ),
+ 'G' =>
+ array (
+ 'GuzzleHttp\\Psr7\\' => 16,
+ 'GuzzleHttp\\Promise\\' => 19,
+ 'GuzzleHttp\\' => 11,
+ ),
+ );
+
+ public static $prefixDirsPsr4 = array (
+ 'Psr\\Log\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
+ ),
+ 'Psr\\Http\\Message\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/psr/http-message/src',
+ ),
+ 'Mediawiki\\DataModel\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/addwiki/mediawiki-datamodel/src',
+ ),
+ 'Mediawiki\\Api\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/addwiki/mediawiki-api-base/src',
+ 1 => __DIR__ . '/..' . '/addwiki/mediawiki-api/src',
+ ),
+ 'GuzzleHttp\\Psr7\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/guzzlehttp/psr7/src',
+ ),
+ 'GuzzleHttp\\Promise\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/guzzlehttp/promises/src',
+ ),
+ 'GuzzleHttp\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/guzzlehttp/guzzle/src',
+ ),
+ );
+
+ public static function getInitializer(ClassLoader $loader)
+ {
+ return \Closure::bind(function () use ($loader) {
+ $loader->prefixLengthsPsr4 = ComposerStaticInit1597705ddb4a19e7b99e0b2375ab438e::$prefixLengthsPsr4;
+ $loader->prefixDirsPsr4 = ComposerStaticInit1597705ddb4a19e7b99e0b2375ab438e::$prefixDirsPsr4;
+
+ }, null, ClassLoader::class);
+ }
+}
diff --git a/bin/reevotech/vendor/composer/installed.json b/bin/reevotech/vendor/composer/installed.json
new file mode 100644
index 00000000..b7b07b4f
--- /dev/null
+++ b/bin/reevotech/vendor/composer/installed.json
@@ -0,0 +1,489 @@
+[
+ {
+ "name": "addwiki/mediawiki-datamodel",
+ "version": "0.7.1",
+ "version_normalized": "0.7.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/addwiki/mediawiki-datamodel.git",
+ "reference": "05dd783715a92ec5449bab4091c0482cf3fcface"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/addwiki/mediawiki-datamodel/zipball/05dd783715a92ec5449bab4091c0482cf3fcface",
+ "reference": "05dd783715a92ec5449bab4091c0482cf3fcface",
+ "shasum": ""
+ },
+ "require-dev": {
+ "jakub-onderka/php-parallel-lint": "0.9.2",
+ "mediawiki/mediawiki-codesniffer": "^13.0",
+ "phpunit/phpunit": "~4.8.0|~5.3.0"
+ },
+ "time": "2018-01-10T19:14:13+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "0.7.x-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Mediawiki\\DataModel\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "GPL-2.0+"
+ ],
+ "authors": [
+ {
+ "name": "Addshore"
+ }
+ ],
+ "description": "A Mediawiki datamodel",
+ "keywords": [
+ "mediawiki"
+ ]
+ },
+ {
+ "name": "psr/log",
+ "version": "1.1.0",
+ "version_normalized": "1.1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/log.git",
+ "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd",
+ "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "time": "2018-11-20T15:27:04+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Psr\\Log\\": "Psr/Log/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for logging libraries",
+ "homepage": "https://github.com/php-fig/log",
+ "keywords": [
+ "log",
+ "psr",
+ "psr-3"
+ ]
+ },
+ {
+ "name": "guzzlehttp/promises",
+ "version": "v1.3.1",
+ "version_normalized": "1.3.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/promises.git",
+ "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646",
+ "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.5.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.0"
+ },
+ "time": "2016-12-20T10:07:11+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.4-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Promise\\": "src/"
+ },
+ "files": [
+ "src/functions_include.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "description": "Guzzle promises library",
+ "keywords": [
+ "promise"
+ ]
+ },
+ {
+ "name": "ralouphie/getallheaders",
+ "version": "2.0.5",
+ "version_normalized": "2.0.5.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ralouphie/getallheaders.git",
+ "reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/5601c8a83fbba7ef674a7369456d12f1e0d0eafa",
+ "reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~3.7.0",
+ "satooshi/php-coveralls": ">=1.0"
+ },
+ "time": "2016-02-11T07:05:27+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "files": [
+ "src/getallheaders.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ralph Khattar",
+ "email": "ralph.khattar@gmail.com"
+ }
+ ],
+ "description": "A polyfill for getallheaders."
+ },
+ {
+ "name": "psr/http-message",
+ "version": "1.0.1",
+ "version_normalized": "1.0.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-message.git",
+ "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
+ "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "time": "2016-08-06T14:39:51+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Message\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for HTTP messages",
+ "homepage": "https://github.com/php-fig/http-message",
+ "keywords": [
+ "http",
+ "http-message",
+ "psr",
+ "psr-7",
+ "request",
+ "response"
+ ]
+ },
+ {
+ "name": "guzzlehttp/psr7",
+ "version": "1.5.2",
+ "version_normalized": "1.5.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/psr7.git",
+ "reference": "9f83dded91781a01c63574e387eaa769be769115"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/psr7/zipball/9f83dded91781a01c63574e387eaa769be769115",
+ "reference": "9f83dded91781a01c63574e387eaa769be769115",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.4.0",
+ "psr/http-message": "~1.0",
+ "ralouphie/getallheaders": "^2.0.5"
+ },
+ "provide": {
+ "psr/http-message-implementation": "1.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8"
+ },
+ "time": "2018-12-04T20:46:45+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.5-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Psr7\\": "src/"
+ },
+ "files": [
+ "src/functions_include.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "Tobias Schultze",
+ "homepage": "https://github.com/Tobion"
+ }
+ ],
+ "description": "PSR-7 message implementation that also provides common utility methods",
+ "keywords": [
+ "http",
+ "message",
+ "psr-7",
+ "request",
+ "response",
+ "stream",
+ "uri",
+ "url"
+ ]
+ },
+ {
+ "name": "guzzlehttp/guzzle",
+ "version": "6.3.3",
+ "version_normalized": "6.3.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/guzzle.git",
+ "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba",
+ "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba",
+ "shasum": ""
+ },
+ "require": {
+ "guzzlehttp/promises": "^1.0",
+ "guzzlehttp/psr7": "^1.4",
+ "php": ">=5.5"
+ },
+ "require-dev": {
+ "ext-curl": "*",
+ "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0",
+ "psr/log": "^1.0"
+ },
+ "suggest": {
+ "psr/log": "Required for using the Log middleware"
+ },
+ "time": "2018-04-22T15:46:56+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "6.3-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "files": [
+ "src/functions_include.php"
+ ],
+ "psr-4": {
+ "GuzzleHttp\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "description": "Guzzle is a PHP HTTP client library",
+ "homepage": "http://guzzlephp.org/",
+ "keywords": [
+ "client",
+ "curl",
+ "framework",
+ "http",
+ "http client",
+ "rest",
+ "web service"
+ ]
+ },
+ {
+ "name": "addwiki/mediawiki-api-base",
+ "version": "2.4.0",
+ "version_normalized": "2.4.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/addwiki/mediawiki-api-base.git",
+ "reference": "33c147e91d05a48e953839fb3ad9e6386cfd85c1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/addwiki/mediawiki-api-base/zipball/33c147e91d05a48e953839fb3ad9e6386cfd85c1",
+ "reference": "33c147e91d05a48e953839fb3ad9e6386cfd85c1",
+ "shasum": ""
+ },
+ "require": {
+ "guzzlehttp/guzzle": "~6.0",
+ "guzzlehttp/promises": "~1.0",
+ "php": ">=5.5",
+ "psr/log": "~1.0"
+ },
+ "require-dev": {
+ "jakub-onderka/php-parallel-lint": "0.9.2",
+ "mediawiki/mediawiki-codesniffer": "^13.0",
+ "phpunit/phpunit": "~4.8.0|~5.3.0"
+ },
+ "suggest": {
+ "etsy/phan": "Allows running static analysis on the package (requires PHP 7+)"
+ },
+ "time": "2017-11-02T10:53:36+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.4.x-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Mediawiki\\Api\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "GPL-2.0+"
+ ],
+ "authors": [
+ {
+ "name": "Addshore"
+ }
+ ],
+ "description": "A basic Mediawiki api base library",
+ "keywords": [
+ "mediawiki"
+ ]
+ },
+ {
+ "name": "addwiki/mediawiki-api",
+ "version": "0.7.2",
+ "version_normalized": "0.7.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/addwiki/mediawiki-api.git",
+ "reference": "f52fc3760d82774512d344e41c45c878a2c6659e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/addwiki/mediawiki-api/zipball/f52fc3760d82774512d344e41c45c878a2c6659e",
+ "reference": "f52fc3760d82774512d344e41c45c878a2c6659e",
+ "shasum": ""
+ },
+ "require": {
+ "addwiki/mediawiki-api-base": "~2.4",
+ "addwiki/mediawiki-datamodel": "~0.7.0"
+ },
+ "require-dev": {
+ "jakub-onderka/php-parallel-lint": "^0.9.2",
+ "mediawiki/mediawiki-codesniffer": "^13.0",
+ "monolog/monolog": "^1.23",
+ "phpunit/phpunit": "~4.8"
+ },
+ "time": "2017-11-20T03:08:06+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "0.7.x-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Mediawiki\\Api\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "GPL-2.0+"
+ ],
+ "authors": [
+ {
+ "name": "Addshore"
+ }
+ ],
+ "description": "A MediaWiki API library",
+ "keywords": [
+ "mediawiki"
+ ]
+ }
+]
diff --git a/bin/reevotech/vendor/guzzlehttp/guzzle/CHANGELOG.md b/bin/reevotech/vendor/guzzlehttp/guzzle/CHANGELOG.md
new file mode 100644
index 00000000..17badd75
--- /dev/null
+++ b/bin/reevotech/vendor/guzzlehttp/guzzle/CHANGELOG.md
@@ -0,0 +1,1287 @@
+# Change Log
+
+## 6.3.3 - 2018-04-22
+
+* Fix: Default headers when decode_content is specified
+
+
+## 6.3.2 - 2018-03-26
+
+* Fix: Release process
+
+
+## 6.3.1 - 2018-03-26
+
+* Bug fix: Parsing 0 epoch expiry times in cookies [#2014](https://github.com/guzzle/guzzle/pull/2014)
+* Improvement: Better ConnectException detection [#2012](https://github.com/guzzle/guzzle/pull/2012)
+* Bug fix: Malformed domain that contains a "/" [#1999](https://github.com/guzzle/guzzle/pull/1999)
+* Bug fix: Undefined offset when a cookie has no first key-value pair [#1998](https://github.com/guzzle/guzzle/pull/1998)
+* Improvement: Support PHPUnit 6 [#1953](https://github.com/guzzle/guzzle/pull/1953)
+* Bug fix: Support empty headers [#1915](https://github.com/guzzle/guzzle/pull/1915)
+* Bug fix: Ignore case during header modifications [#1916](https://github.com/guzzle/guzzle/pull/1916)
+
++ Minor code cleanups, documentation fixes and clarifications.
+
+
+## 6.3.0 - 2017-06-22
+
+* Feature: force IP resolution (ipv4 or ipv6) [#1608](https://github.com/guzzle/guzzle/pull/1608), [#1659](https://github.com/guzzle/guzzle/pull/1659)
+* Improvement: Don't include summary in exception message when body is empty [#1621](https://github.com/guzzle/guzzle/pull/1621)
+* Improvement: Handle `on_headers` option in MockHandler [#1580](https://github.com/guzzle/guzzle/pull/1580)
+* Improvement: Added SUSE Linux CA path [#1609](https://github.com/guzzle/guzzle/issues/1609)
+* Improvement: Use class reference for getting the name of the class instead of using hardcoded strings [#1641](https://github.com/guzzle/guzzle/pull/1641)
+* Feature: Added `read_timeout` option [#1611](https://github.com/guzzle/guzzle/pull/1611)
+* Bug fix: PHP 7.x fixes [#1685](https://github.com/guzzle/guzzle/pull/1685), [#1686](https://github.com/guzzle/guzzle/pull/1686), [#1811](https://github.com/guzzle/guzzle/pull/1811)
+* Deprecation: BadResponseException instantiation without a response [#1642](https://github.com/guzzle/guzzle/pull/1642)
+* Feature: Added NTLM auth [#1569](https://github.com/guzzle/guzzle/pull/1569)
+* Feature: Track redirect HTTP status codes [#1711](https://github.com/guzzle/guzzle/pull/1711)
+* Improvement: Check handler type during construction [#1745](https://github.com/guzzle/guzzle/pull/1745)
+* Improvement: Always include the Content-Length if there's a body [#1721](https://github.com/guzzle/guzzle/pull/1721)
+* Feature: Added convenience method to access a cookie by name [#1318](https://github.com/guzzle/guzzle/pull/1318)
+* Bug fix: Fill `CURLOPT_CAPATH` and `CURLOPT_CAINFO` properly [#1684](https://github.com/guzzle/guzzle/pull/1684)
+* Improvement: Use `\GuzzleHttp\Promise\rejection_for` function instead of object init [#1827](https://github.com/guzzle/guzzle/pull/1827)
+
+
++ Minor code cleanups, documentation fixes and clarifications.
+
+## 6.2.3 - 2017-02-28
+
+* Fix deprecations with guzzle/psr7 version 1.4
+
+## 6.2.2 - 2016-10-08
+
+* Allow to pass nullable Response to delay callable
+* Only add scheme when host is present
+* Fix drain case where content-length is the literal string zero
+* Obfuscate in-URL credentials in exceptions
+
+## 6.2.1 - 2016-07-18
+
+* Address HTTP_PROXY security vulnerability, CVE-2016-5385:
+ https://httpoxy.org/
+* Fixing timeout bug with StreamHandler:
+ https://github.com/guzzle/guzzle/pull/1488
+* Only read up to `Content-Length` in PHP StreamHandler to avoid timeouts when
+ a server does not honor `Connection: close`.
+* Ignore URI fragment when sending requests.
+
+## 6.2.0 - 2016-03-21
+
+* Feature: added `GuzzleHttp\json_encode` and `GuzzleHttp\json_decode`.
+ https://github.com/guzzle/guzzle/pull/1389
+* Bug fix: Fix sleep calculation when waiting for delayed requests.
+ https://github.com/guzzle/guzzle/pull/1324
+* Feature: More flexible history containers.
+ https://github.com/guzzle/guzzle/pull/1373
+* Bug fix: defer sink stream opening in StreamHandler.
+ https://github.com/guzzle/guzzle/pull/1377
+* Bug fix: do not attempt to escape cookie values.
+ https://github.com/guzzle/guzzle/pull/1406
+* Feature: report original content encoding and length on decoded responses.
+ https://github.com/guzzle/guzzle/pull/1409
+* Bug fix: rewind seekable request bodies before dispatching to cURL.
+ https://github.com/guzzle/guzzle/pull/1422
+* Bug fix: provide an empty string to `http_build_query` for HHVM workaround.
+ https://github.com/guzzle/guzzle/pull/1367
+
+## 6.1.1 - 2015-11-22
+
+* Bug fix: Proxy::wrapSync() now correctly proxies to the appropriate handler
+ https://github.com/guzzle/guzzle/commit/911bcbc8b434adce64e223a6d1d14e9a8f63e4e4
+* Feature: HandlerStack is now more generic.
+ https://github.com/guzzle/guzzle/commit/f2102941331cda544745eedd97fc8fd46e1ee33e
+* Bug fix: setting verify to false in the StreamHandler now disables peer
+ verification. https://github.com/guzzle/guzzle/issues/1256
+* Feature: Middleware now uses an exception factory, including more error
+ context. https://github.com/guzzle/guzzle/pull/1282
+* Feature: better support for disabled functions.
+ https://github.com/guzzle/guzzle/pull/1287
+* Bug fix: fixed regression where MockHandler was not using `sink`.
+ https://github.com/guzzle/guzzle/pull/1292
+
+## 6.1.0 - 2015-09-08
+
+* Feature: Added the `on_stats` request option to provide access to transfer
+ statistics for requests. https://github.com/guzzle/guzzle/pull/1202
+* Feature: Added the ability to persist session cookies in CookieJars.
+ https://github.com/guzzle/guzzle/pull/1195
+* Feature: Some compatibility updates for Google APP Engine
+ https://github.com/guzzle/guzzle/pull/1216
+* Feature: Added support for NO_PROXY to prevent the use of a proxy based on
+ a simple set of rules. https://github.com/guzzle/guzzle/pull/1197
+* Feature: Cookies can now contain square brackets.
+ https://github.com/guzzle/guzzle/pull/1237
+* Bug fix: Now correctly parsing `=` inside of quotes in Cookies.
+ https://github.com/guzzle/guzzle/pull/1232
+* Bug fix: Cusotm cURL options now correctly override curl options of the
+ same name. https://github.com/guzzle/guzzle/pull/1221
+* Bug fix: Content-Type header is now added when using an explicitly provided
+ multipart body. https://github.com/guzzle/guzzle/pull/1218
+* Bug fix: Now ignoring Set-Cookie headers that have no name.
+* Bug fix: Reason phrase is no longer cast to an int in some cases in the
+ cURL handler. https://github.com/guzzle/guzzle/pull/1187
+* Bug fix: Remove the Authorization header when redirecting if the Host
+ header changes. https://github.com/guzzle/guzzle/pull/1207
+* Bug fix: Cookie path matching fixes
+ https://github.com/guzzle/guzzle/issues/1129
+* Bug fix: Fixing the cURL `body_as_string` setting
+ https://github.com/guzzle/guzzle/pull/1201
+* Bug fix: quotes are no longer stripped when parsing cookies.
+ https://github.com/guzzle/guzzle/issues/1172
+* Bug fix: `form_params` and `query` now always uses the `&` separator.
+ https://github.com/guzzle/guzzle/pull/1163
+* Bug fix: Adding a Content-Length to PHP stream wrapper requests if not set.
+ https://github.com/guzzle/guzzle/pull/1189
+
+## 6.0.2 - 2015-07-04
+
+* Fixed a memory leak in the curl handlers in which references to callbacks
+ were not being removed by `curl_reset`.
+* Cookies are now extracted properly before redirects.
+* Cookies now allow more character ranges.
+* Decoded Content-Encoding responses are now modified to correctly reflect
+ their state if the encoding was automatically removed by a handler. This
+ means that the `Content-Encoding` header may be removed an the
+ `Content-Length` modified to reflect the message size after removing the
+ encoding.
+* Added a more explicit error message when trying to use `form_params` and
+ `multipart` in the same request.
+* Several fixes for HHVM support.
+* Functions are now conditionally required using an additional level of
+ indirection to help with global Composer installations.
+
+## 6.0.1 - 2015-05-27
+
+* Fixed a bug with serializing the `query` request option where the `&`
+ separator was missing.
+* Added a better error message for when `body` is provided as an array. Please
+ use `form_params` or `multipart` instead.
+* Various doc fixes.
+
+## 6.0.0 - 2015-05-26
+
+* See the UPGRADING.md document for more information.
+* Added `multipart` and `form_params` request options.
+* Added `synchronous` request option.
+* Added the `on_headers` request option.
+* Fixed `expect` handling.
+* No longer adding default middlewares in the client ctor. These need to be
+ present on the provided handler in order to work.
+* Requests are no longer initiated when sending async requests with the
+ CurlMultiHandler. This prevents unexpected recursion from requests completing
+ while ticking the cURL loop.
+* Removed the semantics of setting `default` to `true`. This is no longer
+ required now that the cURL loop is not ticked for async requests.
+* Added request and response logging middleware.
+* No longer allowing self signed certificates when using the StreamHandler.
+* Ensuring that `sink` is valid if saving to a file.
+* Request exceptions now include a "handler context" which provides handler
+ specific contextual information.
+* Added `GuzzleHttp\RequestOptions` to allow request options to be applied
+ using constants.
+* `$maxHandles` has been removed from CurlMultiHandler.
+* `MultipartPostBody` is now part of the `guzzlehttp/psr7` package.
+
+## 5.3.0 - 2015-05-19
+
+* Mock now supports `save_to`
+* Marked `AbstractRequestEvent::getTransaction()` as public.
+* Fixed a bug in which multiple headers using different casing would overwrite
+ previous headers in the associative array.
+* Added `Utils::getDefaultHandler()`
+* Marked `GuzzleHttp\Client::getDefaultUserAgent` as deprecated.
+* URL scheme is now always lowercased.
+
+## 6.0.0-beta.1
+
+* Requires PHP >= 5.5
+* Updated to use PSR-7
+ * Requires immutable messages, which basically means an event based system
+ owned by a request instance is no longer possible.
+ * Utilizing the [Guzzle PSR-7 package](https://github.com/guzzle/psr7).
+ * Removed the dependency on `guzzlehttp/streams`. These stream abstractions
+ are available in the `guzzlehttp/psr7` package under the `GuzzleHttp\Psr7`
+ namespace.
+* Added middleware and handler system
+ * Replaced the Guzzle event and subscriber system with a middleware system.
+ * No longer depends on RingPHP, but rather places the HTTP handlers directly
+ in Guzzle, operating on PSR-7 messages.
+ * Retry logic is now encapsulated in `GuzzleHttp\Middleware::retry`, which
+ means the `guzzlehttp/retry-subscriber` is now obsolete.
+ * Mocking responses is now handled using `GuzzleHttp\Handler\MockHandler`.
+* Asynchronous responses
+ * No longer supports the `future` request option to send an async request.
+ Instead, use one of the `*Async` methods of a client (e.g., `requestAsync`,
+ `getAsync`, etc.).
+ * Utilizing `GuzzleHttp\Promise` instead of React's promise library to avoid
+ recursion required by chaining and forwarding react promises. See
+ https://github.com/guzzle/promises
+ * Added `requestAsync` and `sendAsync` to send request asynchronously.
+ * Added magic methods for `getAsync()`, `postAsync()`, etc. to send requests
+ asynchronously.
+* Request options
+ * POST and form updates
+ * Added the `form_fields` and `form_files` request options.
+ * Removed the `GuzzleHttp\Post` namespace.
+ * The `body` request option no longer accepts an array for POST requests.
+ * The `exceptions` request option has been deprecated in favor of the
+ `http_errors` request options.
+ * The `save_to` request option has been deprecated in favor of `sink` request
+ option.
+* Clients no longer accept an array of URI template string and variables for
+ URI variables. You will need to expand URI templates before passing them
+ into a client constructor or request method.
+* Client methods `get()`, `post()`, `put()`, `patch()`, `options()`, etc. are
+ now magic methods that will send synchronous requests.
+* Replaced `Utils.php` with plain functions in `functions.php`.
+* Removed `GuzzleHttp\Collection`.
+* Removed `GuzzleHttp\BatchResults`. Batched pool results are now returned as
+ an array.
+* Removed `GuzzleHttp\Query`. Query string handling is now handled using an
+ associative array passed into the `query` request option. The query string
+ is serialized using PHP's `http_build_query`. If you need more control, you
+ can pass the query string in as a string.
+* `GuzzleHttp\QueryParser` has been replaced with the
+ `GuzzleHttp\Psr7\parse_query`.
+
+## 5.2.0 - 2015-01-27
+
+* Added `AppliesHeadersInterface` to make applying headers to a request based
+ on the body more generic and not specific to `PostBodyInterface`.
+* Reduced the number of stack frames needed to send requests.
+* Nested futures are now resolved in the client rather than the RequestFsm
+* Finishing state transitions is now handled in the RequestFsm rather than the
+ RingBridge.
+* Added a guard in the Pool class to not use recursion for request retries.
+
+## 5.1.0 - 2014-12-19
+
+* Pool class no longer uses recursion when a request is intercepted.
+* The size of a Pool can now be dynamically adjusted using a callback.
+ See https://github.com/guzzle/guzzle/pull/943.
+* Setting a request option to `null` when creating a request with a client will
+ ensure that the option is not set. This allows you to overwrite default
+ request options on a per-request basis.
+ See https://github.com/guzzle/guzzle/pull/937.
+* Added the ability to limit which protocols are allowed for redirects by
+ specifying a `protocols` array in the `allow_redirects` request option.
+* Nested futures due to retries are now resolved when waiting for synchronous
+ responses. See https://github.com/guzzle/guzzle/pull/947.
+* `"0"` is now an allowed URI path. See
+ https://github.com/guzzle/guzzle/pull/935.
+* `Query` no longer typehints on the `$query` argument in the constructor,
+ allowing for strings and arrays.
+* Exceptions thrown in the `end` event are now correctly wrapped with Guzzle
+ specific exceptions if necessary.
+
+## 5.0.3 - 2014-11-03
+
+This change updates query strings so that they are treated as un-encoded values
+by default where the value represents an un-encoded value to send over the
+wire. A Query object then encodes the value before sending over the wire. This
+means that even value query string values (e.g., ":") are url encoded. This
+makes the Query class match PHP's http_build_query function. However, if you
+want to send requests over the wire using valid query string characters that do
+not need to be encoded, then you can provide a string to Url::setQuery() and
+pass true as the second argument to specify that the query string is a raw
+string that should not be parsed or encoded (unless a call to getQuery() is
+subsequently made, forcing the query-string to be converted into a Query
+object).
+
+## 5.0.2 - 2014-10-30
+
+* Added a trailing `\r\n` to multipart/form-data payloads. See
+ https://github.com/guzzle/guzzle/pull/871
+* Added a `GuzzleHttp\Pool::send()` convenience method to match the docs.
+* Status codes are now returned as integers. See
+ https://github.com/guzzle/guzzle/issues/881
+* No longer overwriting an existing `application/x-www-form-urlencoded` header
+ when sending POST requests, allowing for customized headers. See
+ https://github.com/guzzle/guzzle/issues/877
+* Improved path URL serialization.
+
+ * No longer double percent-encoding characters in the path or query string if
+ they are already encoded.
+ * Now properly encoding the supplied path to a URL object, instead of only
+ encoding ' ' and '?'.
+ * Note: This has been changed in 5.0.3 to now encode query string values by
+ default unless the `rawString` argument is provided when setting the query
+ string on a URL: Now allowing many more characters to be present in the
+ query string without being percent encoded. See http://tools.ietf.org/html/rfc3986#appendix-A
+
+## 5.0.1 - 2014-10-16
+
+Bugfix release.
+
+* Fixed an issue where connection errors still returned response object in
+ error and end events event though the response is unusable. This has been
+ corrected so that a response is not returned in the `getResponse` method of
+ these events if the response did not complete. https://github.com/guzzle/guzzle/issues/867
+* Fixed an issue where transfer statistics were not being populated in the
+ RingBridge. https://github.com/guzzle/guzzle/issues/866
+
+## 5.0.0 - 2014-10-12
+
+Adding support for non-blocking responses and some minor API cleanup.
+
+### New Features
+
+* Added support for non-blocking responses based on `guzzlehttp/guzzle-ring`.
+* Added a public API for creating a default HTTP adapter.
+* Updated the redirect plugin to be non-blocking so that redirects are sent
+ concurrently. Other plugins like this can now be updated to be non-blocking.
+* Added a "progress" event so that you can get upload and download progress
+ events.
+* Added `GuzzleHttp\Pool` which implements FutureInterface and transfers
+ requests concurrently using a capped pool size as efficiently as possible.
+* Added `hasListeners()` to EmitterInterface.
+* Removed `GuzzleHttp\ClientInterface::sendAll` and marked
+ `GuzzleHttp\Client::sendAll` as deprecated (it's still there, just not the
+ recommended way).
+
+### Breaking changes
+
+The breaking changes in this release are relatively minor. The biggest thing to
+look out for is that request and response objects no longer implement fluent
+interfaces.
+
+* Removed the fluent interfaces (i.e., `return $this`) from requests,
+ responses, `GuzzleHttp\Collection`, `GuzzleHttp\Url`,
+ `GuzzleHttp\Query`, `GuzzleHttp\Post\PostBody`, and
+ `GuzzleHttp\Cookie\SetCookie`. This blog post provides a good outline of
+ why I did this: http://ocramius.github.io/blog/fluent-interfaces-are-evil/.
+ This also makes the Guzzle message interfaces compatible with the current
+ PSR-7 message proposal.
+* Removed "functions.php", so that Guzzle is truly PSR-4 compliant. Except
+ for the HTTP request functions from function.php, these functions are now
+ implemented in `GuzzleHttp\Utils` using camelCase. `GuzzleHttp\json_decode`
+ moved to `GuzzleHttp\Utils::jsonDecode`. `GuzzleHttp\get_path` moved to
+ `GuzzleHttp\Utils::getPath`. `GuzzleHttp\set_path` moved to
+ `GuzzleHttp\Utils::setPath`. `GuzzleHttp\batch` should now be
+ `GuzzleHttp\Pool::batch`, which returns an `objectStorage`. Using functions.php
+ caused problems for many users: they aren't PSR-4 compliant, require an
+ explicit include, and needed an if-guard to ensure that the functions are not
+ declared multiple times.
+* Rewrote adapter layer.
+ * Removing all classes from `GuzzleHttp\Adapter`, these are now
+ implemented as callables that are stored in `GuzzleHttp\Ring\Client`.
+ * Removed the concept of "parallel adapters". Sending requests serially or
+ concurrently is now handled using a single adapter.
+ * Moved `GuzzleHttp\Adapter\Transaction` to `GuzzleHttp\Transaction`. The
+ Transaction object now exposes the request, response, and client as public
+ properties. The getters and setters have been removed.
+* Removed the "headers" event. This event was only useful for changing the
+ body a response once the headers of the response were known. You can implement
+ a similar behavior in a number of ways. One example might be to use a
+ FnStream that has access to the transaction being sent. For example, when the
+ first byte is written, you could check if the response headers match your
+ expectations, and if so, change the actual stream body that is being
+ written to.
+* Removed the `asArray` parameter from
+ `GuzzleHttp\Message\MessageInterface::getHeader`. If you want to get a header
+ value as an array, then use the newly added `getHeaderAsArray()` method of
+ `MessageInterface`. This change makes the Guzzle interfaces compatible with
+ the PSR-7 interfaces.
+* `GuzzleHttp\Message\MessageFactory` no longer allows subclasses to add
+ custom request options using double-dispatch (this was an implementation
+ detail). Instead, you should now provide an associative array to the
+ constructor which is a mapping of the request option name mapping to a
+ function that applies the option value to a request.
+* Removed the concept of "throwImmediately" from exceptions and error events.
+ This control mechanism was used to stop a transfer of concurrent requests
+ from completing. This can now be handled by throwing the exception or by
+ cancelling a pool of requests or each outstanding future request individually.
+* Updated to "GuzzleHttp\Streams" 3.0.
+ * `GuzzleHttp\Stream\StreamInterface::getContents()` no longer accepts a
+ `maxLen` parameter. This update makes the Guzzle streams project
+ compatible with the current PSR-7 proposal.
+ * `GuzzleHttp\Stream\Stream::__construct`,
+ `GuzzleHttp\Stream\Stream::factory`, and
+ `GuzzleHttp\Stream\Utils::create` no longer accept a size in the second
+ argument. They now accept an associative array of options, including the
+ "size" key and "metadata" key which can be used to provide custom metadata.
+
+## 4.2.2 - 2014-09-08
+
+* Fixed a memory leak in the CurlAdapter when reusing cURL handles.
+* No longer using `request_fulluri` in stream adapter proxies.
+* Relative redirects are now based on the last response, not the first response.
+
+## 4.2.1 - 2014-08-19
+
+* Ensuring that the StreamAdapter does not always add a Content-Type header
+* Adding automated github releases with a phar and zip
+
+## 4.2.0 - 2014-08-17
+
+* Now merging in default options using a case-insensitive comparison.
+ Closes https://github.com/guzzle/guzzle/issues/767
+* Added the ability to automatically decode `Content-Encoding` response bodies
+ using the `decode_content` request option. This is set to `true` by default
+ to decode the response body if it comes over the wire with a
+ `Content-Encoding`. Set this value to `false` to disable decoding the
+ response content, and pass a string to provide a request `Accept-Encoding`
+ header and turn on automatic response decoding. This feature now allows you
+ to pass an `Accept-Encoding` header in the headers of a request but still
+ disable automatic response decoding.
+ Closes https://github.com/guzzle/guzzle/issues/764
+* Added the ability to throw an exception immediately when transferring
+ requests in parallel. Closes https://github.com/guzzle/guzzle/issues/760
+* Updating guzzlehttp/streams dependency to ~2.1
+* No longer utilizing the now deprecated namespaced methods from the stream
+ package.
+
+## 4.1.8 - 2014-08-14
+
+* Fixed an issue in the CurlFactory that caused setting the `stream=false`
+ request option to throw an exception.
+ See: https://github.com/guzzle/guzzle/issues/769
+* TransactionIterator now calls rewind on the inner iterator.
+ See: https://github.com/guzzle/guzzle/pull/765
+* You can now set the `Content-Type` header to `multipart/form-data`
+ when creating POST requests to force multipart bodies.
+ See https://github.com/guzzle/guzzle/issues/768
+
+## 4.1.7 - 2014-08-07
+
+* Fixed an error in the HistoryPlugin that caused the same request and response
+ to be logged multiple times when an HTTP protocol error occurs.
+* Ensuring that cURL does not add a default Content-Type when no Content-Type
+ has been supplied by the user. This prevents the adapter layer from modifying
+ the request that is sent over the wire after any listeners may have already
+ put the request in a desired state (e.g., signed the request).
+* Throwing an exception when you attempt to send requests that have the
+ "stream" set to true in parallel using the MultiAdapter.
+* Only calling curl_multi_select when there are active cURL handles. This was
+ previously changed and caused performance problems on some systems due to PHP
+ always selecting until the maximum select timeout.
+* Fixed a bug where multipart/form-data POST fields were not correctly
+ aggregated (e.g., values with "&").
+
+## 4.1.6 - 2014-08-03
+
+* Added helper methods to make it easier to represent messages as strings,
+ including getting the start line and getting headers as a string.
+
+## 4.1.5 - 2014-08-02
+
+* Automatically retrying cURL "Connection died, retrying a fresh connect"
+ errors when possible.
+* cURL implementation cleanup
+* Allowing multiple event subscriber listeners to be registered per event by
+ passing an array of arrays of listener configuration.
+
+## 4.1.4 - 2014-07-22
+
+* Fixed a bug that caused multi-part POST requests with more than one field to
+ serialize incorrectly.
+* Paths can now be set to "0"
+* `ResponseInterface::xml` now accepts a `libxml_options` option and added a
+ missing default argument that was required when parsing XML response bodies.
+* A `save_to` stream is now created lazily, which means that files are not
+ created on disk unless a request succeeds.
+
+## 4.1.3 - 2014-07-15
+
+* Various fixes to multipart/form-data POST uploads
+* Wrapping function.php in an if-statement to ensure Guzzle can be used
+ globally and in a Composer install
+* Fixed an issue with generating and merging in events to an event array
+* POST headers are only applied before sending a request to allow you to change
+ the query aggregator used before uploading
+* Added much more robust query string parsing
+* Fixed various parsing and normalization issues with URLs
+* Fixing an issue where multi-valued headers were not being utilized correctly
+ in the StreamAdapter
+
+## 4.1.2 - 2014-06-18
+
+* Added support for sending payloads with GET requests
+
+## 4.1.1 - 2014-06-08
+
+* Fixed an issue related to using custom message factory options in subclasses
+* Fixed an issue with nested form fields in a multi-part POST
+* Fixed an issue with using the `json` request option for POST requests
+* Added `ToArrayInterface` to `GuzzleHttp\Cookie\CookieJar`
+
+## 4.1.0 - 2014-05-27
+
+* Added a `json` request option to easily serialize JSON payloads.
+* Added a `GuzzleHttp\json_decode()` wrapper to safely parse JSON.
+* Added `setPort()` and `getPort()` to `GuzzleHttp\Message\RequestInterface`.
+* Added the ability to provide an emitter to a client in the client constructor.
+* Added the ability to persist a cookie session using $_SESSION.
+* Added a trait that can be used to add event listeners to an iterator.
+* Removed request method constants from RequestInterface.
+* Fixed warning when invalid request start-lines are received.
+* Updated MessageFactory to work with custom request option methods.
+* Updated cacert bundle to latest build.
+
+4.0.2 (2014-04-16)
+------------------
+
+* Proxy requests using the StreamAdapter now properly use request_fulluri (#632)
+* Added the ability to set scalars as POST fields (#628)
+
+## 4.0.1 - 2014-04-04
+
+* The HTTP status code of a response is now set as the exception code of
+ RequestException objects.
+* 303 redirects will now correctly switch from POST to GET requests.
+* The default parallel adapter of a client now correctly uses the MultiAdapter.
+* HasDataTrait now initializes the internal data array as an empty array so
+ that the toArray() method always returns an array.
+
+## 4.0.0 - 2014-03-29
+
+* For more information on the 4.0 transition, see:
+ http://mtdowling.com/blog/2014/03/15/guzzle-4-rc/
+* For information on changes and upgrading, see:
+ https://github.com/guzzle/guzzle/blob/master/UPGRADING.md#3x-to-40
+* Added `GuzzleHttp\batch()` as a convenience function for sending requests in
+ parallel without needing to write asynchronous code.
+* Restructured how events are added to `GuzzleHttp\ClientInterface::sendAll()`.
+ You can now pass a callable or an array of associative arrays where each
+ associative array contains the "fn", "priority", and "once" keys.
+
+## 4.0.0.rc-2 - 2014-03-25
+
+* Removed `getConfig()` and `setConfig()` from clients to avoid confusion
+ around whether things like base_url, message_factory, etc. should be able to
+ be retrieved or modified.
+* Added `getDefaultOption()` and `setDefaultOption()` to ClientInterface
+* functions.php functions were renamed using snake_case to match PHP idioms
+* Added support for `HTTP_PROXY`, `HTTPS_PROXY`, and
+ `GUZZLE_CURL_SELECT_TIMEOUT` environment variables
+* Added the ability to specify custom `sendAll()` event priorities
+* Added the ability to specify custom stream context options to the stream
+ adapter.
+* Added a functions.php function for `get_path()` and `set_path()`
+* CurlAdapter and MultiAdapter now use a callable to generate curl resources
+* MockAdapter now properly reads a body and emits a `headers` event
+* Updated Url class to check if a scheme and host are set before adding ":"
+ and "//". This allows empty Url (e.g., "") to be serialized as "".
+* Parsing invalid XML no longer emits warnings
+* Curl classes now properly throw AdapterExceptions
+* Various performance optimizations
+* Streams are created with the faster `Stream\create()` function
+* Marked deprecation_proxy() as internal
+* Test server is now a collection of static methods on a class
+
+## 4.0.0-rc.1 - 2014-03-15
+
+* See https://github.com/guzzle/guzzle/blob/master/UPGRADING.md#3x-to-40
+
+## 3.8.1 - 2014-01-28
+
+* Bug: Always using GET requests when redirecting from a 303 response
+* Bug: CURLOPT_SSL_VERIFYHOST is now correctly set to false when setting `$certificateAuthority` to false in
+ `Guzzle\Http\ClientInterface::setSslVerification()`
+* Bug: RedirectPlugin now uses strict RFC 3986 compliance when combining a base URL with a relative URL
+* Bug: The body of a request can now be set to `"0"`
+* Sending PHP stream requests no longer forces `HTTP/1.0`
+* Adding more information to ExceptionCollection exceptions so that users have more context, including a stack trace of
+ each sub-exception
+* Updated the `$ref` attribute in service descriptions to merge over any existing parameters of a schema (rather than
+ clobbering everything).
+* Merging URLs will now use the query string object from the relative URL (thus allowing custom query aggregators)
+* Query strings are now parsed in a way that they do no convert empty keys with no value to have a dangling `=`.
+ For example `foo&bar=baz` is now correctly parsed and recognized as `foo&bar=baz` rather than `foo=&bar=baz`.
+* Now properly escaping the regular expression delimiter when matching Cookie domains.
+* Network access is now disabled when loading XML documents
+
+## 3.8.0 - 2013-12-05
+
+* Added the ability to define a POST name for a file
+* JSON response parsing now properly walks additionalProperties
+* cURL error code 18 is now retried automatically in the BackoffPlugin
+* Fixed a cURL error when URLs contain fragments
+* Fixed an issue in the BackoffPlugin retry event where it was trying to access all exceptions as if they were
+ CurlExceptions
+* CURLOPT_PROGRESS function fix for PHP 5.5 (69fcc1e)
+* Added the ability for Guzzle to work with older versions of cURL that do not support `CURLOPT_TIMEOUT_MS`
+* Fixed a bug that was encountered when parsing empty header parameters
+* UriTemplate now has a `setRegex()` method to match the docs
+* The `debug` request parameter now checks if it is truthy rather than if it exists
+* Setting the `debug` request parameter to true shows verbose cURL output instead of using the LogPlugin
+* Added the ability to combine URLs using strict RFC 3986 compliance
+* Command objects can now return the validation errors encountered by the command
+* Various fixes to cache revalidation (#437 and 29797e5)
+* Various fixes to the AsyncPlugin
+* Cleaned up build scripts
+
+## 3.7.4 - 2013-10-02
+
+* Bug fix: 0 is now an allowed value in a description parameter that has a default value (#430)
+* Bug fix: SchemaFormatter now returns an integer when formatting to a Unix timestamp
+ (see https://github.com/aws/aws-sdk-php/issues/147)
+* Bug fix: Cleaned up and fixed URL dot segment removal to properly resolve internal dots
+* Minimum PHP version is now properly specified as 5.3.3 (up from 5.3.2) (#420)
+* Updated the bundled cacert.pem (#419)
+* OauthPlugin now supports adding authentication to headers or query string (#425)
+
+## 3.7.3 - 2013-09-08
+
+* Added the ability to get the exception associated with a request/command when using `MultiTransferException` and
+ `CommandTransferException`.
+* Setting `additionalParameters` of a response to false is now honored when parsing responses with a service description
+* Schemas are only injected into response models when explicitly configured.
+* No longer guessing Content-Type based on the path of a request. Content-Type is now only guessed based on the path of
+ an EntityBody.
+* Bug fix: ChunkedIterator can now properly chunk a \Traversable as well as an \Iterator.
+* Bug fix: FilterIterator now relies on `\Iterator` instead of `\Traversable`.
+* Bug fix: Gracefully handling malformed responses in RequestMediator::writeResponseBody()
+* Bug fix: Replaced call to canCache with canCacheRequest in the CallbackCanCacheStrategy of the CachePlugin
+* Bug fix: Visiting XML attributes first before visiting XML children when serializing requests
+* Bug fix: Properly parsing headers that contain commas contained in quotes
+* Bug fix: mimetype guessing based on a filename is now case-insensitive
+
+## 3.7.2 - 2013-08-02
+
+* Bug fix: Properly URL encoding paths when using the PHP-only version of the UriTemplate expander
+ See https://github.com/guzzle/guzzle/issues/371
+* Bug fix: Cookie domains are now matched correctly according to RFC 6265
+ See https://github.com/guzzle/guzzle/issues/377
+* Bug fix: GET parameters are now used when calculating an OAuth signature
+* Bug fix: Fixed an issue with cache revalidation where the If-None-Match header was being double quoted
+* `Guzzle\Common\AbstractHasDispatcher::dispatch()` now returns the event that was dispatched
+* `Guzzle\Http\QueryString::factory()` now guesses the most appropriate query aggregator to used based on the input.
+ See https://github.com/guzzle/guzzle/issues/379
+* Added a way to add custom domain objects to service description parsing using the `operation.parse_class` event. See
+ https://github.com/guzzle/guzzle/pull/380
+* cURL multi cleanup and optimizations
+
+## 3.7.1 - 2013-07-05
+
+* Bug fix: Setting default options on a client now works
+* Bug fix: Setting options on HEAD requests now works. See #352
+* Bug fix: Moving stream factory before send event to before building the stream. See #353
+* Bug fix: Cookies no longer match on IP addresses per RFC 6265
+* Bug fix: Correctly parsing header parameters that are in `<>` and quotes
+* Added `cert` and `ssl_key` as request options
+* `Host` header can now diverge from the host part of a URL if the header is set manually
+* `Guzzle\Service\Command\LocationVisitor\Request\XmlVisitor` was rewritten to change from using SimpleXML to XMLWriter
+* OAuth parameters are only added via the plugin if they aren't already set
+* Exceptions are now thrown when a URL cannot be parsed
+* Returning `false` if `Guzzle\Http\EntityBody::getContentMd5()` fails
+* Not setting a `Content-MD5` on a command if calculating the Content-MD5 fails via the CommandContentMd5Plugin
+
+## 3.7.0 - 2013-06-10
+
+* See UPGRADING.md for more information on how to upgrade.
+* Requests now support the ability to specify an array of $options when creating a request to more easily modify a
+ request. You can pass a 'request.options' configuration setting to a client to apply default request options to
+ every request created by a client (e.g. default query string variables, headers, curl options, etc.).
+* Added a static facade class that allows you to use Guzzle with static methods and mount the class to `\Guzzle`.
+ See `Guzzle\Http\StaticClient::mount`.
+* Added `command.request_options` to `Guzzle\Service\Command\AbstractCommand` to pass request options to requests
+ created by a command (e.g. custom headers, query string variables, timeout settings, etc.).
+* Stream size in `Guzzle\Stream\PhpStreamRequestFactory` will now be set if Content-Length is returned in the
+ headers of a response
+* Added `Guzzle\Common\Collection::setPath($path, $value)` to set a value into an array using a nested key
+ (e.g. `$collection->setPath('foo/baz/bar', 'test'); echo $collection['foo']['bar']['bar'];`)
+* ServiceBuilders now support storing and retrieving arbitrary data
+* CachePlugin can now purge all resources for a given URI
+* CachePlugin can automatically purge matching cached items when a non-idempotent request is sent to a resource
+* CachePlugin now uses the Vary header to determine if a resource is a cache hit
+* `Guzzle\Http\Message\Response` now implements `\Serializable`
+* Added `Guzzle\Cache\CacheAdapterFactory::fromCache()` to more easily create cache adapters
+* `Guzzle\Service\ClientInterface::execute()` now accepts an array, single command, or Traversable
+* Fixed a bug in `Guzzle\Http\Message\Header\Link::addLink()`
+* Better handling of calculating the size of a stream in `Guzzle\Stream\Stream` using fstat() and caching the size
+* `Guzzle\Common\Exception\ExceptionCollection` now creates a more readable exception message
+* Fixing BC break: Added back the MonologLogAdapter implementation rather than extending from PsrLog so that older
+ Symfony users can still use the old version of Monolog.
+* Fixing BC break: Added the implementation back in for `Guzzle\Http\Message\AbstractMessage::getTokenizedHeader()`.
+ Now triggering an E_USER_DEPRECATED warning when used. Use `$message->getHeader()->parseParams()`.
+* Several performance improvements to `Guzzle\Common\Collection`
+* Added an `$options` argument to the end of the following methods of `Guzzle\Http\ClientInterface`:
+ createRequest, head, delete, put, patch, post, options, prepareRequest
+* Added an `$options` argument to the end of `Guzzle\Http\Message\Request\RequestFactoryInterface::createRequest()`
+* Added an `applyOptions()` method to `Guzzle\Http\Message\Request\RequestFactoryInterface`
+* Changed `Guzzle\Http\ClientInterface::get($uri = null, $headers = null, $body = null)` to
+ `Guzzle\Http\ClientInterface::get($uri = null, $headers = null, $options = array())`. You can still pass in a
+ resource, string, or EntityBody into the $options parameter to specify the download location of the response.
+* Changed `Guzzle\Common\Collection::__construct($data)` to no longer accepts a null value for `$data` but a
+ default `array()`
+* Added `Guzzle\Stream\StreamInterface::isRepeatable`
+* Removed `Guzzle\Http\ClientInterface::setDefaultHeaders(). Use
+ $client->getConfig()->setPath('request.options/headers/{header_name}', 'value')`. or
+ $client->getConfig()->setPath('request.options/headers', array('header_name' => 'value'))`.
+* Removed `Guzzle\Http\ClientInterface::getDefaultHeaders(). Use $client->getConfig()->getPath('request.options/headers')`.
+* Removed `Guzzle\Http\ClientInterface::expandTemplate()`
+* Removed `Guzzle\Http\ClientInterface::setReque