Phriction Welcome in gitpull.it, a Phabricator instance! First steps with boz-mw MediaWiki API framework History Version 31 vs 32
Version 31 vs 32
Version 31 vs 32
Edits
Edits
- Edit by valerio.bozzolan, Version 32
- Mar 10 2023 09:03
- Edit by valerio.bozzolan, Version 31
- Mar 10 2023 09:00
« Previous Change | Next Change » |
Edit Older Version 31... | Edit Older Version 32... |
Content Changes
Content Changes
This is `boz-mw`, //another MediaWiki API handler in PHP// with batteries included! It has a tons of features that will make your head spin!
This is a library to interact with MediaWiki and Wikibase APIs. There are also some [[ first_steps_with_boz-mw/tools/ | boz-mw command line tools ]].
## Features
You may ask what we can offer to you:
* read/write support for Wikidata
* read/write support for Wikimedia Commons' **Structured Data**
* **file upload** support for Wikimedia Commons
* support for some other known wiki(s)
* support for your custom wiki
* lightweight project, well designed using [[ https://en.wikipedia.org/wiki/Object-oriented_programming | OOP ]]
* it does not require Composer, but it's on Composer
* it supports all versions from PHP 5.5 to PHP 8.2
Actually, this framework is useful for:
* developers, to create bots
* command line users for our [[ #Command line tools ]]
## Download
```
git clone https://gitpull.it/source/boz-mw.git
```
## Install
```
apt install php-cli php-curl
```
## Command line tools
See [[ first_steps_with_boz-mw/tools/ | command line tools ]].
### Command line script `replace.php`
The [replace.php](https://gitpull.it/source/boz-mw/browse/master/tools/#replace-script-tt-class-remarkup) allows you to do some sobstitutions in a wiki.
### Command line script `mega-export.php`
The [mega-export.php](https://gitpull.it/source/boz-mw/browse/master/tools/#mega-export-tt-class-remarkup) allows you to export the _full_ page history of whatever page.
## API framework showcase
Here some usage examples.
### Start: select your wiki
First of all you should init a wiki:
```
<?php
require 'boz-mw/autoload-with-laser-cannon.php';
// load Wikidata
$wikidata = wikidata();
// load Wikidata (this is the same)
// $wikidata = wiki( 'wikidatawiki' );
// load Wikidata (this is the same)
// $wikidata = \wm\Wikidata::instance();
// load Wikipedia in Italian (this is the same)
$itwiki = itwiki();
// load Wikipedia in Italian (this is the same)
// $itwiki = wiki( 'itwiki' );
// load Wikimedia Commons
$commons = commons();
// load Wikimedia Commons (this is the same)
// $commons = wiki( 'commonswiki' );
// load Wikimedia Commons (this is the same)
// $commons = \wm\Commons::instance();
// load Meta-Wiki
$meta = meta();
// load Meta-wiki (this is the same)
// $meta = wiki( 'metawiki' );
// load Meta-wiki this is the same
// $meta = \wm\MetaWiki::instance();
```
### Basic MediaWiki API read query
To obtain a simple information from the server (no continuation support):
```
<?php
require 'boz-mw/autoload-with-laser-cannon.php';
// load it.wiki
$wiki = itwiki();
$response =
$wiki->fetch( [
'action' => 'query',
'prop' => 'info',
'titles' => 'Pagina principale',
] );
// dramatically take the very first page since you requested just one page
$page = array_pop( $response->query->pages );
// show interesting information
print_r( $page->title );
print_r( $page->pageid );
```
Note: See [[ https://meta.wikimedia.org/w/api.php?action=help&modules=query | MediaWiki API action=query documentation ]].
### API query with continuation
To obtain a long result set from the server (with continuation support):
```
<?php
require 'boz-mw/autoload-with-laser-cannon.php';
$wiki = itwiki();
$request =
$wiki->createQuery( [
'action' => 'query',
'list' => 'categorymembers',
'cmtitle' => 'Categoria:Software con licenza GNU GPL',
] );
// automatic query continuation
foreach( $request as $response ) {
// loop each category member
$pages = $response->query->categorymembers ?? [];
foreach( $pages as $page ) {
// do something
var_dump( $page->pageid );
var_dump( $page->ns );
var_dump( $page->title );
print_r( $page );
}
}
```
NOTE: See [[ https://meta.wikimedia.org/w/api.php?action=help&modules=query%2Bcategorymembers | MediaWiki API action=query list=categorymembers documentation ]].
### Login and Edit API query
```
<?php
require 'boz-mw/autoload-with-laser-cannon.php';
// insert here your bot username and password from your wiki
// https://meta.wikimedia.org/wiki/Special:BotPasswords
$bot_user = '';
$bot_password = '';
// pick a wiki
$wiki = itwiki();
// login
$wiki->login( $bot_user, $bot_password );
// save a page
// if something bad happen here, it will quit your program (throwing a detailed exception)
$response = $wiki->edit( [
'title' => 'Wikipedia:Pagina delle prove',
'text' => 'My test wikitext with boz-mw (sorry for this test)',
'summary' => 'My test edit summary with boz-mw (sorry for this test)',
] );
// do something here
// a number
var_dump( $response->edit->pageid );
// a number
var_dump( $response->edit->oldrevid );
// a number
var_dump( $response->edit->newrevid );
```
This example works. If you run this example this page will be edited:
* https://it.wikipedia.org/wiki/Wikipedia:Pagina_delle_prove
Please do not abuse!
NOTE: See [[ https://mediawiki.org/w/api.php?action=help&modules=edit | MediaWiki action=edit documentation ]]. Yes, the `token` parameter is automatically handled for you automagically.
### Quick start bot wizard and serious-business error management
Do you need to configure your bot with its username and password? We have a wizard for that!
```
<?php
require 'boz-mw/autoload-with-laser-cannon.php';
/*
* Check your configuration
*
* A nice wizard will help you if it does not exist <3
*/
config_wizard( 'config.php' );
/*
* Login in your wiki
*
* It uses your bot username and password from your config.
*/
$wiki = itwiki()->login();
/*
* Set the page you want to edit
*
* This is an not-writable example to try what happens! <3
*/
$page_title = 'Special:Nothing';
/**
* Try to save the page
*
* The "try" block is useful to "catch" errors instead of dying.
*
*/
try {
// try to save a page
$response = $wiki->edit( [
'title' => $page_title,
'text' => 'My test wikitext with boz-mw (sorry for this test)',
'summary' => 'My test edit summary with boz-mw (sorry for this test)',
] );
// if you are here everything was OK
// do something here
// a number
var_dump( $response->edit->pageid );
// a number
var_dump( $response->edit->oldrevid );
// a number
var_dump( $response->edit->newrevid );
/**
* The catch block can be used to detect a specific exception
*
* Some of them:
* MaxLagException
* PageCannotExistException
* EditConflictException
* ProtectedPageException
* ReadApiDeniedException
* ReadOnlyException
* PermissionDeniedException
* PageCannotExistException
*
* and more!
*
* In this case we will detect the 'page cannot exist' exception.
*/
} catch( API\PageCannotExistException $e ) {
echo "Sorry but you are editing a page that cannot exist. \n";
// generic error handler
} catch( Exception $e ) {
// other exceptions
echo "Something unexpected happened: ";
echo $e->getMessage();
echo "\n";
}
// do something in any case
echo "End. \n";
```
This example works. If you run this example this page will be edited:
* https://it.wikipedia.org/wiki/Wikipedia:Pagina_delle_prove
Please do not abuse!
NOTE: The wizard will just create a configuration file with these constants inside:
```
\mw\API::$DEFAULT_USERNAME = '':
\mw\API::$DEFAULT_PASSWORD = '';
```
### Wikidata SPARQL query
What if you want to list all the [cats from Wikidata](https://query.wikidata.org/#%23Cats%0ASELECT%20%3Fitem%20%3FitemLabel%20%0AWHERE%20%0A%7B%0A%20%20%3Fitem%20wdt%3AP31%20wd%3AQ146.%0A%20%20SERVICE%20wikibase%3Alabel%20%7B%20bd%3AserviceParam%20wikibase%3Alanguage%20%22%5BAUTO_LANGUAGE%5D%2Cen%22.%20%7D%0A%7D)?
```
<?php
require 'boz-mw/autoload-with-laser-cannon.php';
$wikidata = wikidata();
// you should know how to build a SPARQL query
$query = 'SELECT ?item ?itemLabel WHERE {';
$query .= ' ?item wdt:P31 wd:Q146 ';
$query .= ' SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } ';
$query .= '}';
// query Wikidata and decode the response
$rows = $wikidata::querySPARQL( $query );
// for each cat
foreach( $rows as $row ) {
// example: 'http://www.wikidata.org/entity/Q5317221'
$url = $row->item->value;
// example: 'Q5317221'
$id = basename( $url );
// example: 'Dusty the Klepto Kitty'
$itemLabel = $row->itemLabel->value;
echo "Found cat ID: $id. Name: $itemLabel \n";
}
```
### Wikidata read API
Reading a Wikidata entity is really simple.
Under the hood it uses this API entry point:
https://www.wikidata.org/w/api.php?action=help&modules=wbgetentities
But the wrapper is really simplified.
```
<?php
require 'boz-mw/autoload-with-laser-cannon.php';
$wikidata = wiki( 'wikidatawiki' );
// query the Wikidata Sandbox
$data = $wikidata->fetchSingleEntity( 'Q4115189', [
'props' => [
'descriptions',
'labels',
'claims',
],
] );
// get descriptions and labels
$italian_description = $data->getDescriptionValue( 'it' );
$italian_label = $data->getLabelValue( 'it' );
// look all the Claims
var_dump( $data->getClaimsGrouped() );
```
### Wikidata edit API
Editing a Wikidata item, honestly, it's stuff for advanced people, but our wrapper simplifies lot of things. Trust me.
Under the hood it uses this API entry point:
https://www.wikidata.org/w/api.php?action=help&modules=wbeditentity
In this example you:
* overwrite a Wikidata label
* overwrite a Wikidata description
* add a Commons Category (← this is called a "Claim" in Wikidata)
To do all these changes, here a full example:
```
<?php
require 'boz-mw/autoload-with-laser-cannon.php';
// load a dedicated configuration - it will create that if missing
config_wizard( 'config.php' );
$wikidata = wiki( 'wikidatawiki' );
// this object registers your proposed changes
$newdata = $wikidata->createDataModel();
// prepare a new Wikimedia Commons category
$statement = new \wb\StatementCommonsCategory( 'P373', 'Test category name' );
$newdata->addClaim( $statement );
$newdata->setLabelValue( 'en', "New label" );
$newdata->setDescriptionValue( 'en', "New Description" );
$wikidata->login();
// this tries to save all your proposed changes in the Wikidata Sandbox
$newdata->editEntity( [
'id' => 'Q4115189',
] );
```
### Upload API query
Uploading a file requires to respect the [RFC1341](https://tools.ietf.org/html/rfc1341) about an HTTP multipart request.
Well, we made it easy:
```
<?php
require 'boz-mw/autoload.php';
// this can be an URL or a local pathname
$photo_url = 'http://.../libre-image.jpg';
$wiki->upload( [
'comment' => 'upload file about...',
'text' => 'bla bla [[bla]]',
'filename' => 'Libre image.jpg',
\network\ContentDisposition::createFromNameURLType( 'file', $photo_url, 'image/jpg' ),
] );
```
NOTE: See [[ https://www.mediawiki.org/wiki/Special:ApiHelp/upload | MediaWiki API action=upload documentation ]].
Eventually see the [[ https://gitpull.it/source/boz-mw/browse/master/include/network/ContentDisposition.php | ContentDisposition ]] class for some other constructors.
### Where to test
Please use your own wiki to test this framework or at least use the Wikimedia Wikis' Sandboxes!
Some known pages you can destroy:
* https://www.wikidata.org/wiki/Q4115189
* https://it.wikipedia.org/wiki/Wikipedia:Pagina_delle_prove_di_Wikidata
* https://en.wikipedia.org/wiki/Wikipedia:Wikidata/Wikidata_Sandbox
* etc.
### How to add another Wiki
Thank you for adding another wiki!
To create another wiki, create a file similar to this one:
https://gitpull.it/source/boz-mw/browse/master/include/web/LandscapeforWiki.php
Then, mention it in the list called `MediaWikis::allClasses()`. Example:
https://gitpull.it/source/boz-mw/browse/master/include/web/MediaWikis.php
Feel free to commit your wiki in the core and send upstream! So other can contribute.
### How to contribute? How to pull request?
Thank you for your code contributions! Follow the instructions in the Download and Install sections. Then:
Please start creating a Task here first:
* #boz-mw_mediawiki_api_client
Describe your problem / goal. Then we can help you in sharing your patch with upstream.
After you created the Task, the best method is, run this command from your local repository:
```
arc diff
```
And follow the wizard.
https://we.phorge.it/book/phorge/article/arcanist_quick_start/
If you have no time for all this mess, feel free to just do a pull request on the proprietary GitHub platform:
https://github.com/valerio-bozzolan/boz-mw/
Bonus point: after your pull request, please create an account in gitpull.it:
https://gitpull.it/auth/start/
If you do a pull request in GitHub, it's OK: I will do my best to merge your patch with my weird workflow Phabricator-based, for you. You're welcome!
### Other examples?
Feel free to fork and improve this documentation! Or just look inside the `/include` directory where there is some inline documentation for you!
## Troubleshooting
You can enable debug mode with `bozmw_debug()`. Example:
```
<?php
require 'boz-mw/autoload-with-laser-cannon.php';
bozmw_debug();
// other code
```
## Testing Unit Files
To run the Unit tests, just execute this in the main directory:
```
phpunit --bootstrap=phpunit/load.php --testdox phpunit
```
## Known usages
* [MediaWikiOrphanizerBot](https://github.com/valerio-bozzolan/MediaWikiOrphanizerBot)
* [ItalianWikipediaDeletionBot](https://github.com/valerio-bozzolan/ItalianWikipediaDeletionBot)
* [ItalianWikipediaListAdmins](https://github.com/valerio-bozzolan/ItalianWikipediaListAdmins)
* [Wikimedia Commons volleyball players uploader bot](https://gitpull.it/source/Wikimedia-Valerio-Bozzolan-bot-tasks/browse/master/2019-05-commons-volleyball-players-upload/)
* [2018 MiBACT Wikidata fixed](https://github.com/valerio-bozzolan/Wikimedia-Valerio-Bozzolan-bot-tasks/tree/master/2018-09-mibact-fixer)
* [2018 Wiki loves monuments CH](https://github.com/valerio-bozzolan/Wikimedia-Valerio-Bozzolan-bot-tasks/tree/master/2018-08-wiki-loves-monuments-switzerland)
* [wiki-users-leaflet](https://github.com/valerio-bozzolan/wiki-users-leaflet/) hosted at [WMF Labs](https://tools.wmflabs.org/it-wiki-users-leaflet/)
This is `boz-mw`, //another MediaWiki API handler in PHP// with batteries included! It has a tons of features that will make your head spin!
This is a library to interact with MediaWiki and Wikibase APIs. There are also some [[ first_steps_with_boz-mw/tools/ | boz-mw command line tools ]].
## Features
You may ask what we can offer to you:
* read/write support for Wikidata
* read/write support for Wikimedia Commons' **Structured Data**
* **file upload** support for Wikimedia Commons
* support for some other known wiki(s)
* support for your custom wiki
* lightweight project, well designed using [[ https://en.wikipedia.org/wiki/Object-oriented_programming | OOP ]]
* it does not require Composer, but it's on Composer
* it supports all versions from PHP 5.5 to PHP 8.2
Actually, this framework is useful for:
* developers, to create bots
* command line users for our [[ #Command line tools ]]
## Download
```
git clone https://gitpull.it/source/boz-mw.git
```
## Install
```
apt install php-cli php-curl
```
## Command line tools
See [[ first_steps_with_boz-mw/tools/ | command line tools ]].
### Command line script `replace.php`
The [replace.php](https://gitpull.it/source/boz-mw/browse/master/tools/#replace-script-tt-class-remarkup) allows you to do some sobstitutions in a wiki.
### Command line script `mega-export.php`
The [mega-export.php](https://gitpull.it/source/boz-mw/browse/master/tools/#mega-export-tt-class-remarkup) allows you to export the _full_ page history of whatever page.
## API framework showcase
Here some usage examples.
### Start: select your wiki
First of all you should init a wiki:
```
<?php
require 'boz-mw/autoload-with-laser-cannon.php';
// load Wikidata
$wikidata = wikidata();
// load Wikidata (this is the same)
// $wikidata = wiki( 'wikidatawiki' );
// load Wikidata (this is the same)
// $wikidata = \wm\Wikidata::instance();
// load Wikipedia in Italian (this is the same)
$itwiki = itwiki();
// load Wikipedia in Italian (this is the same)
// $itwiki = wiki( 'itwiki' );
// load Wikimedia Commons
$commons = commons();
// load Wikimedia Commons (this is the same)
// $commons = wiki( 'commonswiki' );
// load Wikimedia Commons (this is the same)
// $commons = \wm\Commons::instance();
// load Meta-Wiki
$meta = meta();
// load Meta-wiki (this is the same)
// $meta = wiki( 'metawiki' );
// load Meta-wiki this is the same
// $meta = \wm\MetaWiki::instance();
```
### Basic MediaWiki API read query
This is a very basic example to read from a very generic MediaWiki API.
This example is over-simplified, with the assumption that you get just one result. Spoiler: this never happens in real life, but it's just an idea.
To obtain a simple information from the server (this example has no support to "query continuation" for multiple results):
```
<?php
require 'boz-mw/autoload-with-laser-cannon.php';
// load it.wiki
$wiki = itwiki();
$response =
$wiki->fetch( [
'action' => 'query',
'prop' => 'info',
'titles' => 'Pagina principale',
] );
// dramatically take the very first page since you requested just one page
$page = array_pop( $response->query->pages );
// show interesting information
print_r( $page->title );
print_r( $page->pageid );
```
Note: See [[ https://meta.wikimedia.org/w/api.php?action=help&modules=query | MediaWiki API action=query documentation ]].
### API query with continuation
To obtain a long result set from the server (with continuation support):
```
<?php
require 'boz-mw/autoload-with-laser-cannon.php';
$wiki = itwiki();
$request =
$wiki->createQuery( [
'action' => 'query',
'list' => 'categorymembers',
'cmtitle' => 'Categoria:Software con licenza GNU GPL',
] );
// automatic query continuation
foreach( $request as $response ) {
// loop each category member
$pages = $response->query->categorymembers ?? [];
foreach( $pages as $page ) {
// do something
var_dump( $page->pageid );
var_dump( $page->ns );
var_dump( $page->title );
print_r( $page );
}
}
```
NOTE: See [[ https://meta.wikimedia.org/w/api.php?action=help&modules=query%2Bcategorymembers | MediaWiki API action=query list=categorymembers documentation ]].
### Login and Edit API query
```
<?php
require 'boz-mw/autoload-with-laser-cannon.php';
// insert here your bot username and password from your wiki
// https://meta.wikimedia.org/wiki/Special:BotPasswords
$bot_user = '';
$bot_password = '';
// pick a wiki
$wiki = itwiki();
// login
$wiki->login( $bot_user, $bot_password );
// save a page
// if something bad happen here, it will quit your program (throwing a detailed exception)
$response = $wiki->edit( [
'title' => 'Wikipedia:Pagina delle prove',
'text' => 'My test wikitext with boz-mw (sorry for this test)',
'summary' => 'My test edit summary with boz-mw (sorry for this test)',
] );
// do something here
// a number
var_dump( $response->edit->pageid );
// a number
var_dump( $response->edit->oldrevid );
// a number
var_dump( $response->edit->newrevid );
```
This example works. If you run this example this page will be edited:
* https://it.wikipedia.org/wiki/Wikipedia:Pagina_delle_prove
Please do not abuse!
NOTE: See [[ https://mediawiki.org/w/api.php?action=help&modules=edit | MediaWiki action=edit documentation ]]. Yes, the `token` parameter is automatically handled for you automagically.
### Quick start bot wizard and serious-business error management
Do you need to configure your bot with its username and password? We have a wizard for that!
```
<?php
require 'boz-mw/autoload-with-laser-cannon.php';
/*
* Check your configuration
*
* A nice wizard will help you if it does not exist <3
*/
config_wizard( 'config.php' );
/*
* Login in your wiki
*
* It uses your bot username and password from your config.
*/
$wiki = itwiki()->login();
/*
* Set the page you want to edit
*
* This is an not-writable example to try what happens! <3
*/
$page_title = 'Special:Nothing';
/**
* Try to save the page
*
* The "try" block is useful to "catch" errors instead of dying.
*
*/
try {
// try to save a page
$response = $wiki->edit( [
'title' => $page_title,
'text' => 'My test wikitext with boz-mw (sorry for this test)',
'summary' => 'My test edit summary with boz-mw (sorry for this test)',
] );
// if you are here everything was OK
// do something here
// a number
var_dump( $response->edit->pageid );
// a number
var_dump( $response->edit->oldrevid );
// a number
var_dump( $response->edit->newrevid );
/**
* The catch block can be used to detect a specific exception
*
* Some of them:
* MaxLagException
* PageCannotExistException
* EditConflictException
* ProtectedPageException
* ReadApiDeniedException
* ReadOnlyException
* PermissionDeniedException
* PageCannotExistException
*
* and more!
*
* In this case we will detect the 'page cannot exist' exception.
*/
} catch( API\PageCannotExistException $e ) {
echo "Sorry but you are editing a page that cannot exist. \n";
// generic error handler
} catch( Exception $e ) {
// other exceptions
echo "Something unexpected happened: ";
echo $e->getMessage();
echo "\n";
}
// do something in any case
echo "End. \n";
```
This example works. If you run this example this page will be edited:
* https://it.wikipedia.org/wiki/Wikipedia:Pagina_delle_prove
Please do not abuse!
NOTE: The wizard will just create a configuration file with these constants inside:
```
\mw\API::$DEFAULT_USERNAME = '':
\mw\API::$DEFAULT_PASSWORD = '';
```
### Wikidata SPARQL query
What if you want to list all the [cats from Wikidata](https://query.wikidata.org/#%23Cats%0ASELECT%20%3Fitem%20%3FitemLabel%20%0AWHERE%20%0A%7B%0A%20%20%3Fitem%20wdt%3AP31%20wd%3AQ146.%0A%20%20SERVICE%20wikibase%3Alabel%20%7B%20bd%3AserviceParam%20wikibase%3Alanguage%20%22%5BAUTO_LANGUAGE%5D%2Cen%22.%20%7D%0A%7D)?
```
<?php
require 'boz-mw/autoload-with-laser-cannon.php';
$wikidata = wikidata();
// you should know how to build a SPARQL query
$query = 'SELECT ?item ?itemLabel WHERE {';
$query .= ' ?item wdt:P31 wd:Q146 ';
$query .= ' SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } ';
$query .= '}';
// query Wikidata and decode the response
$rows = $wikidata::querySPARQL( $query );
// for each cat
foreach( $rows as $row ) {
// example: 'http://www.wikidata.org/entity/Q5317221'
$url = $row->item->value;
// example: 'Q5317221'
$id = basename( $url );
// example: 'Dusty the Klepto Kitty'
$itemLabel = $row->itemLabel->value;
echo "Found cat ID: $id. Name: $itemLabel \n";
}
```
### Wikidata read API
Reading a Wikidata entity is really simple.
Under the hood it uses this API entry point:
https://www.wikidata.org/w/api.php?action=help&modules=wbgetentities
But the wrapper is really simplified.
```
<?php
require 'boz-mw/autoload-with-laser-cannon.php';
$wikidata = wiki( 'wikidatawiki' );
// query the Wikidata Sandbox
$data = $wikidata->fetchSingleEntity( 'Q4115189', [
'props' => [
'descriptions',
'labels',
'claims',
],
] );
// get descriptions and labels
$italian_description = $data->getDescriptionValue( 'it' );
$italian_label = $data->getLabelValue( 'it' );
// look all the Claims
var_dump( $data->getClaimsGrouped() );
```
### Wikidata edit API
Editing a Wikidata item, honestly, it's stuff for advanced people, but our wrapper simplifies lot of things. Trust me.
Under the hood it uses this API entry point:
https://www.wikidata.org/w/api.php?action=help&modules=wbeditentity
In this example you:
* overwrite a Wikidata label
* overwrite a Wikidata description
* add a Commons Category (← this is called a "Claim" in Wikidata)
To do all these changes, here a full example:
```
<?php
require 'boz-mw/autoload-with-laser-cannon.php';
// load a dedicated configuration - it will create that if missing
config_wizard( 'config.php' );
$wikidata = wiki( 'wikidatawiki' );
// this object registers your proposed changes
$newdata = $wikidata->createDataModel();
// prepare a new Wikimedia Commons category
$statement = new \wb\StatementCommonsCategory( 'P373', 'Test category name' );
$newdata->addClaim( $statement );
$newdata->setLabelValue( 'en', "New label" );
$newdata->setDescriptionValue( 'en', "New Description" );
$wikidata->login();
// this tries to save all your proposed changes in the Wikidata Sandbox
$newdata->editEntity( [
'id' => 'Q4115189',
] );
```
### Upload API query
Uploading a file requires to respect the [RFC1341](https://tools.ietf.org/html/rfc1341) about an HTTP multipart request.
Well, we made it easy:
```
<?php
require 'boz-mw/autoload.php';
// this can be an URL or a local pathname
$photo_url = 'http://.../libre-image.jpg';
$wiki->upload( [
'comment' => 'upload file about...',
'text' => 'bla bla [[bla]]',
'filename' => 'Libre image.jpg',
\network\ContentDisposition::createFromNameURLType( 'file', $photo_url, 'image/jpg' ),
] );
```
NOTE: See [[ https://www.mediawiki.org/wiki/Special:ApiHelp/upload | MediaWiki API action=upload documentation ]].
Eventually see the [[ https://gitpull.it/source/boz-mw/browse/master/include/network/ContentDisposition.php | ContentDisposition ]] class for some other constructors.
### Where to test
Please use your own wiki to test this framework or at least use the Wikimedia Wikis' Sandboxes!
Some known pages you can destroy:
* https://www.wikidata.org/wiki/Q4115189
* https://it.wikipedia.org/wiki/Wikipedia:Pagina_delle_prove_di_Wikidata
* https://en.wikipedia.org/wiki/Wikipedia:Wikidata/Wikidata_Sandbox
* etc.
### How to add another Wiki
Thank you for adding another wiki!
To create another wiki, create a file similar to this one:
https://gitpull.it/source/boz-mw/browse/master/include/web/LandscapeforWiki.php
Then, mention it in the list called `MediaWikis::allClasses()`. Example:
https://gitpull.it/source/boz-mw/browse/master/include/web/MediaWikis.php
Feel free to commit your wiki in the core and send upstream! So other can contribute.
### How to contribute? How to pull request?
Thank you for your code contributions! Follow the instructions in the Download and Install sections. Then:
Please start creating a Task here first:
* #boz-mw_mediawiki_api_client
Describe your problem / goal. Then we can help you in sharing your patch with upstream.
After you created the Task, the best method is, run this command from your local repository:
```
arc diff
```
And follow the wizard.
https://we.phorge.it/book/phorge/article/arcanist_quick_start/
If you have no time for all this mess, feel free to just do a pull request on the proprietary GitHub platform:
https://github.com/valerio-bozzolan/boz-mw/
Bonus point: after your pull request, please create an account in gitpull.it:
https://gitpull.it/auth/start/
If you do a pull request in GitHub, it's OK: I will do my best to merge your patch with my weird workflow Phabricator-based, for you. You're welcome!
### Other examples?
Feel free to fork and improve this documentation! Or just look inside the `/include` directory where there is some inline documentation for you!
## Troubleshooting
You can enable debug mode with `bozmw_debug()`. Example:
```
<?php
require 'boz-mw/autoload-with-laser-cannon.php';
bozmw_debug();
// other code
```
## Testing Unit Files
To run the Unit tests, just execute this in the main directory:
```
phpunit --bootstrap=phpunit/load.php --testdox phpunit
```
## Known usages
* [MediaWikiOrphanizerBot](https://github.com/valerio-bozzolan/MediaWikiOrphanizerBot)
* [ItalianWikipediaDeletionBot](https://github.com/valerio-bozzolan/ItalianWikipediaDeletionBot)
* [ItalianWikipediaListAdmins](https://github.com/valerio-bozzolan/ItalianWikipediaListAdmins)
* [Wikimedia Commons volleyball players uploader bot](https://gitpull.it/source/Wikimedia-Valerio-Bozzolan-bot-tasks/browse/master/2019-05-commons-volleyball-players-upload/)
* [2018 MiBACT Wikidata fixed](https://github.com/valerio-bozzolan/Wikimedia-Valerio-Bozzolan-bot-tasks/tree/master/2018-09-mibact-fixer)
* [2018 Wiki loves monuments CH](https://github.com/valerio-bozzolan/Wikimedia-Valerio-Bozzolan-bot-tasks/tree/master/2018-08-wiki-loves-monuments-switzerland)
* [wiki-users-leaflet](https://github.com/valerio-bozzolan/wiki-users-leaflet/) hosted at [WMF Labs](https://tools.wmflabs.org/it-wiki-users-leaflet/)
This is `boz-mw`, //another MediaWiki API handler in PHP// with batteries included! It has a tons of features that will make your head spin!
This is a library to interact with MediaWiki and Wikibase APIs. There are also some [[ first_steps_with_boz-mw/tools/ | boz-mw command line tools ]].
## Features
You may ask what we can offer to you:
* read/write support for Wikidata
* read/write support for Wikimedia Commons' **Structured Data**
* **file upload** support for Wikimedia Commons
* support for some other known wiki(s)
* support for your custom wiki
* lightweight project, well designed using [[ https://en.wikipedia.org/wiki/Object-oriented_programming | OOP ]]
* it does not require Composer, but it's on Composer
* it supports all versions from PHP 5.5 to PHP 8.2
Actually, this framework is useful for:
* developers, to create bots
* command line users for our [[ #Command line tools ]]
## Download
```
git clone https://gitpull.it/source/boz-mw.git
```
## Install
```
apt install php-cli php-curl
```
## Command line tools
See [[ first_steps_with_boz-mw/tools/ | command line tools ]].
### Command line script `replace.php`
The [replace.php](https://gitpull.it/source/boz-mw/browse/master/tools/#replace-script-tt-class-remarkup) allows you to do some sobstitutions in a wiki.
### Command line script `mega-export.php`
The [mega-export.php](https://gitpull.it/source/boz-mw/browse/master/tools/#mega-export-tt-class-remarkup) allows you to export the _full_ page history of whatever page.
## API framework showcase
Here some usage examples.
### Start: select your wiki
First of all you should init a wiki:
```
<?php
require 'boz-mw/autoload-with-laser-cannon.php';
// load Wikidata
$wikidata = wikidata();
// load Wikidata (this is the same)
// $wikidata = wiki( 'wikidatawiki' );
// load Wikidata (this is the same)
// $wikidata = \wm\Wikidata::instance();
// load Wikipedia in Italian (this is the same)
$itwiki = itwiki();
// load Wikipedia in Italian (this is the same)
// $itwiki = wiki( 'itwiki' );
// load Wikimedia Commons
$commons = commons();
// load Wikimedia Commons (this is the same)
// $commons = wiki( 'commonswiki' );
// load Wikimedia Commons (this is the same)
// $commons = \wm\Commons::instance();
// load Meta-Wiki
$meta = meta();
// load Meta-wiki (this is the same)
// $meta = wiki( 'metawiki' );
// load Meta-wiki this is the same
// $meta = \wm\MetaWiki::instance();
```
### Basic MediaWiki API read query
This is a very basic example to read from a very generic MediaWiki API.
This example is over-simplified, with the assumption that you get just one result. Spoiler: this never happens in real life, but it's just an idea.
To obtain a simple information from the server (nothis example has no support to "query continuation support):" for multiple results):
```
<?php
require 'boz-mw/autoload-with-laser-cannon.php';
// load it.wiki
$wiki = itwiki();
$response =
$wiki->fetch( [
'action' => 'query',
'prop' => 'info',
'titles' => 'Pagina principale',
] );
// dramatically take the very first page since you requested just one page
$page = array_pop( $response->query->pages );
// show interesting information
print_r( $page->title );
print_r( $page->pageid );
```
Note: See [[ https://meta.wikimedia.org/w/api.php?action=help&modules=query | MediaWiki API action=query documentation ]].
### API query with continuation
To obtain a long result set from the server (with continuation support):
```
<?php
require 'boz-mw/autoload-with-laser-cannon.php';
$wiki = itwiki();
$request =
$wiki->createQuery( [
'action' => 'query',
'list' => 'categorymembers',
'cmtitle' => 'Categoria:Software con licenza GNU GPL',
] );
// automatic query continuation
foreach( $request as $response ) {
// loop each category member
$pages = $response->query->categorymembers ?? [];
foreach( $pages as $page ) {
// do something
var_dump( $page->pageid );
var_dump( $page->ns );
var_dump( $page->title );
print_r( $page );
}
}
```
NOTE: See [[ https://meta.wikimedia.org/w/api.php?action=help&modules=query%2Bcategorymembers | MediaWiki API action=query list=categorymembers documentation ]].
### Login and Edit API query
```
<?php
require 'boz-mw/autoload-with-laser-cannon.php';
// insert here your bot username and password from your wiki
// https://meta.wikimedia.org/wiki/Special:BotPasswords
$bot_user = '';
$bot_password = '';
// pick a wiki
$wiki = itwiki();
// login
$wiki->login( $bot_user, $bot_password );
// save a page
// if something bad happen here, it will quit your program (throwing a detailed exception)
$response = $wiki->edit( [
'title' => 'Wikipedia:Pagina delle prove',
'text' => 'My test wikitext with boz-mw (sorry for this test)',
'summary' => 'My test edit summary with boz-mw (sorry for this test)',
] );
// do something here
// a number
var_dump( $response->edit->pageid );
// a number
var_dump( $response->edit->oldrevid );
// a number
var_dump( $response->edit->newrevid );
```
This example works. If you run this example this page will be edited:
* https://it.wikipedia.org/wiki/Wikipedia:Pagina_delle_prove
Please do not abuse!
NOTE: See [[ https://mediawiki.org/w/api.php?action=help&modules=edit | MediaWiki action=edit documentation ]]. Yes, the `token` parameter is automatically handled for you automagically.
### Quick start bot wizard and serious-business error management
Do you need to configure your bot with its username and password? We have a wizard for that!
```
<?php
require 'boz-mw/autoload-with-laser-cannon.php';
/*
* Check your configuration
*
* A nice wizard will help you if it does not exist <3
*/
config_wizard( 'config.php' );
/*
* Login in your wiki
*
* It uses your bot username and password from your config.
*/
$wiki = itwiki()->login();
/*
* Set the page you want to edit
*
* This is an not-writable example to try what happens! <3
*/
$page_title = 'Special:Nothing';
/**
* Try to save the page
*
* The "try" block is useful to "catch" errors instead of dying.
*
*/
try {
// try to save a page
$response = $wiki->edit( [
'title' => $page_title,
'text' => 'My test wikitext with boz-mw (sorry for this test)',
'summary' => 'My test edit summary with boz-mw (sorry for this test)',
] );
// if you are here everything was OK
// do something here
// a number
var_dump( $response->edit->pageid );
// a number
var_dump( $response->edit->oldrevid );
// a number
var_dump( $response->edit->newrevid );
/**
* The catch block can be used to detect a specific exception
*
* Some of them:
* MaxLagException
* PageCannotExistException
* EditConflictException
* ProtectedPageException
* ReadApiDeniedException
* ReadOnlyException
* PermissionDeniedException
* PageCannotExistException
*
* and more!
*
* In this case we will detect the 'page cannot exist' exception.
*/
} catch( API\PageCannotExistException $e ) {
echo "Sorry but you are editing a page that cannot exist. \n";
// generic error handler
} catch( Exception $e ) {
// other exceptions
echo "Something unexpected happened: ";
echo $e->getMessage();
echo "\n";
}
// do something in any case
echo "End. \n";
```
This example works. If you run this example this page will be edited:
* https://it.wikipedia.org/wiki/Wikipedia:Pagina_delle_prove
Please do not abuse!
NOTE: The wizard will just create a configuration file with these constants inside:
```
\mw\API::$DEFAULT_USERNAME = '':
\mw\API::$DEFAULT_PASSWORD = '';
```
### Wikidata SPARQL query
What if you want to list all the [cats from Wikidata](https://query.wikidata.org/#%23Cats%0ASELECT%20%3Fitem%20%3FitemLabel%20%0AWHERE%20%0A%7B%0A%20%20%3Fitem%20wdt%3AP31%20wd%3AQ146.%0A%20%20SERVICE%20wikibase%3Alabel%20%7B%20bd%3AserviceParam%20wikibase%3Alanguage%20%22%5BAUTO_LANGUAGE%5D%2Cen%22.%20%7D%0A%7D)?
```
<?php
require 'boz-mw/autoload-with-laser-cannon.php';
$wikidata = wikidata();
// you should know how to build a SPARQL query
$query = 'SELECT ?item ?itemLabel WHERE {';
$query .= ' ?item wdt:P31 wd:Q146 ';
$query .= ' SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } ';
$query .= '}';
// query Wikidata and decode the response
$rows = $wikidata::querySPARQL( $query );
// for each cat
foreach( $rows as $row ) {
// example: 'http://www.wikidata.org/entity/Q5317221'
$url = $row->item->value;
// example: 'Q5317221'
$id = basename( $url );
// example: 'Dusty the Klepto Kitty'
$itemLabel = $row->itemLabel->value;
echo "Found cat ID: $id. Name: $itemLabel \n";
}
```
### Wikidata read API
Reading a Wikidata entity is really simple.
Under the hood it uses this API entry point:
https://www.wikidata.org/w/api.php?action=help&modules=wbgetentities
But the wrapper is really simplified.
```
<?php
require 'boz-mw/autoload-with-laser-cannon.php';
$wikidata = wiki( 'wikidatawiki' );
// query the Wikidata Sandbox
$data = $wikidata->fetchSingleEntity( 'Q4115189', [
'props' => [
'descriptions',
'labels',
'claims',
],
] );
// get descriptions and labels
$italian_description = $data->getDescriptionValue( 'it' );
$italian_label = $data->getLabelValue( 'it' );
// look all the Claims
var_dump( $data->getClaimsGrouped() );
```
### Wikidata edit API
Editing a Wikidata item, honestly, it's stuff for advanced people, but our wrapper simplifies lot of things. Trust me.
Under the hood it uses this API entry point:
https://www.wikidata.org/w/api.php?action=help&modules=wbeditentity
In this example you:
* overwrite a Wikidata label
* overwrite a Wikidata description
* add a Commons Category (← this is called a "Claim" in Wikidata)
To do all these changes, here a full example:
```
<?php
require 'boz-mw/autoload-with-laser-cannon.php';
// load a dedicated configuration - it will create that if missing
config_wizard( 'config.php' );
$wikidata = wiki( 'wikidatawiki' );
// this object registers your proposed changes
$newdata = $wikidata->createDataModel();
// prepare a new Wikimedia Commons category
$statement = new \wb\StatementCommonsCategory( 'P373', 'Test category name' );
$newdata->addClaim( $statement );
$newdata->setLabelValue( 'en', "New label" );
$newdata->setDescriptionValue( 'en', "New Description" );
$wikidata->login();
// this tries to save all your proposed changes in the Wikidata Sandbox
$newdata->editEntity( [
'id' => 'Q4115189',
] );
```
### Upload API query
Uploading a file requires to respect the [RFC1341](https://tools.ietf.org/html/rfc1341) about an HTTP multipart request.
Well, we made it easy:
```
<?php
require 'boz-mw/autoload.php';
// this can be an URL or a local pathname
$photo_url = 'http://.../libre-image.jpg';
$wiki->upload( [
'comment' => 'upload file about...',
'text' => 'bla bla [[bla]]',
'filename' => 'Libre image.jpg',
\network\ContentDisposition::createFromNameURLType( 'file', $photo_url, 'image/jpg' ),
] );
```
NOTE: See [[ https://www.mediawiki.org/wiki/Special:ApiHelp/upload | MediaWiki API action=upload documentation ]].
Eventually see the [[ https://gitpull.it/source/boz-mw/browse/master/include/network/ContentDisposition.php | ContentDisposition ]] class for some other constructors.
### Where to test
Please use your own wiki to test this framework or at least use the Wikimedia Wikis' Sandboxes!
Some known pages you can destroy:
* https://www.wikidata.org/wiki/Q4115189
* https://it.wikipedia.org/wiki/Wikipedia:Pagina_delle_prove_di_Wikidata
* https://en.wikipedia.org/wiki/Wikipedia:Wikidata/Wikidata_Sandbox
* etc.
### How to add another Wiki
Thank you for adding another wiki!
To create another wiki, create a file similar to this one:
https://gitpull.it/source/boz-mw/browse/master/include/web/LandscapeforWiki.php
Then, mention it in the list called `MediaWikis::allClasses()`. Example:
https://gitpull.it/source/boz-mw/browse/master/include/web/MediaWikis.php
Feel free to commit your wiki in the core and send upstream! So other can contribute.
### How to contribute? How to pull request?
Thank you for your code contributions! Follow the instructions in the Download and Install sections. Then:
Please start creating a Task here first:
* #boz-mw_mediawiki_api_client
Describe your problem / goal. Then we can help you in sharing your patch with upstream.
After you created the Task, the best method is, run this command from your local repository:
```
arc diff
```
And follow the wizard.
https://we.phorge.it/book/phorge/article/arcanist_quick_start/
If you have no time for all this mess, feel free to just do a pull request on the proprietary GitHub platform:
https://github.com/valerio-bozzolan/boz-mw/
Bonus point: after your pull request, please create an account in gitpull.it:
https://gitpull.it/auth/start/
If you do a pull request in GitHub, it's OK: I will do my best to merge your patch with my weird workflow Phabricator-based, for you. You're welcome!
### Other examples?
Feel free to fork and improve this documentation! Or just look inside the `/include` directory where there is some inline documentation for you!
## Troubleshooting
You can enable debug mode with `bozmw_debug()`. Example:
```
<?php
require 'boz-mw/autoload-with-laser-cannon.php';
bozmw_debug();
// other code
```
## Testing Unit Files
To run the Unit tests, just execute this in the main directory:
```
phpunit --bootstrap=phpunit/load.php --testdox phpunit
```
## Known usages
* [MediaWikiOrphanizerBot](https://github.com/valerio-bozzolan/MediaWikiOrphanizerBot)
* [ItalianWikipediaDeletionBot](https://github.com/valerio-bozzolan/ItalianWikipediaDeletionBot)
* [ItalianWikipediaListAdmins](https://github.com/valerio-bozzolan/ItalianWikipediaListAdmins)
* [Wikimedia Commons volleyball players uploader bot](https://gitpull.it/source/Wikimedia-Valerio-Bozzolan-bot-tasks/browse/master/2019-05-commons-volleyball-players-upload/)
* [2018 MiBACT Wikidata fixed](https://github.com/valerio-bozzolan/Wikimedia-Valerio-Bozzolan-bot-tasks/tree/master/2018-09-mibact-fixer)
* [2018 Wiki loves monuments CH](https://github.com/valerio-bozzolan/Wikimedia-Valerio-Bozzolan-bot-tasks/tree/master/2018-08-wiki-loves-monuments-switzerland)
* [wiki-users-leaflet](https://github.com/valerio-bozzolan/wiki-users-leaflet/) hosted at [WMF Labs](https://tools.wmflabs.org/it-wiki-users-leaflet/)
Public contents are in Creative Commons Attribution-ShareAlike 4.0 (CC-BY-SA) or GNU Free Documentation License (at your option) unless otherwise noted. · Contact / Register