From 8c638ab06892c02f9e106c816efc4fa4f20ed64a Mon Sep 17 00:00:00 2001 From: Sam Wilson Date: Fri, 1 May 2026 09:10:20 +0200 Subject: [PATCH 1/3] Switch to support only Wikimedia Commons --- .github/workflows/ci.yml | 30 +++++++ .scrutinizer.yml | 20 ----- README.md | 14 ++-- admin.php | 111 ++----------------------- admin.tpl | 91 -------------------- admin/commons.svg | 14 ++++ admin/oauth.php | 47 +++++++++++ admin/photo.php | 160 ++++++++++++++++++++++++++++++++++++ admin/photo.tpl | 64 +++++++++++++++ admin/settings.php | 42 ++++++++++ admin/settings.tpl | 49 +++++++++++ composer.json | 22 +++-- main.inc.php | 72 +++++++--------- src/CommonsFileUploader.php | 41 +++++++++ 14 files changed, 511 insertions(+), 266 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 .scrutinizer.yml delete mode 100644 admin.tpl create mode 100644 admin/commons.svg create mode 100644 admin/oauth.php create mode 100644 admin/photo.php create mode 100644 admin/photo.tpl create mode 100644 admin/settings.php create mode 100644 admin/settings.tpl create mode 100644 src/CommonsFileUploader.php diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..9e1765d --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,30 @@ +name: CI + +on: push + +jobs: + build: + + strategy: + matrix: + # All supported PHP versions https://www.php.net/supported-versions.php + php: [ '8.2', '8.3', '8.4', '8.5' ] + + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Set up PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{matrix.php}} + + - name: Install + run: | + composer install + + - name: Test + run: | + composer test diff --git a/.scrutinizer.yml b/.scrutinizer.yml deleted file mode 100644 index 4606fc8..0000000 --- a/.scrutinizer.yml +++ /dev/null @@ -1,20 +0,0 @@ -checks: - php: - code_rating: true - duplication: true -filter: - excluded_paths: - - 'vendor/*' -build: - project_setup: - before: - - composer self-update - tests: - override: - - - command: composer test - nodes: - analysis: - tests: - override: - - php-scrutinizer-run diff --git a/README.md b/README.md index cd9571a..290f70a 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ -Piwigo to MediaWiki -=================== +Piwigo to Wikimedia Commons +=========================== -* Code: https://github.com/samwilson/piwigo2mediawiki -* Bug reports: https://github.com/samwilson/piwigo2mediawiki/issues -* License: GPL 3.0 or later -* [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/samwilson/Piwigo2MediaWiki/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/samwilson/Piwigo2MediaWiki/?branch=master) +This is a Piwigo plugin for copying photos to Wikimedia Commons. + +* Code: https://github.com/samwilson/Piwigo-WikimediaCommons +* Bug reports: https://github.com/samwilson/Piwigo-WikimediaCommons/issues +* Licence: GPL 3.0 or later +* Commons logo: CC-BY-SA 3.0 https://commons.wikimedia.org/wiki/File:Media_Viewer_Icon_-_Commons_Gray.svg diff --git a/admin.php b/admin.php index d6fba3e..c874f05 100644 --- a/admin.php +++ b/admin.php @@ -1,108 +1,15 @@ assign(array( - 'admin_url' => PIWIGO2MEDIAWIKI_ADMIN, - 'piwigo2mediawiki_page' => PIWIGO2MEDIAWIKI_PAGE, - 'mediawiki_url' => $url, - 'p2m_conf' => $p2mConf, -)); - -// Delete if requested. -if (isset($_POST['action']) && $_POST['action']==='delete' - && isset($_POST['id']) && isset($p2mConf[$_POST['id']]) -) { - unset($p2mConf[$_POST['id']]); - conf_update_param(PIWIGO2MEDIAWIKI_ID, $p2mConf); - redirect(PIWIGO2MEDIAWIKI_ADMIN); -} - -// Load one wiki's data for editing if an ID is specified. -if (isset($_REQUEST['id']) && isset($p2mConf[$_REQUEST['id']])) { - $info = $p2mConf[$_REQUEST['id']]; - $info['id'] = $_REQUEST['id']; - $template->assign(array( - 'info' => $info, - )); -} - -// Save (create or edit) a single wiki's data. -if ($url && isset($_POST['action']) && $_POST['action'] === 'add' - && isset($_POST['username']) && $_POST['username'] - && isset($_POST['password']) && $_POST['password'] -) { - // Find the API URL or show an error. - $validUrl = true; - try { - $api = MediawikiApi::newFromPage($url); - $url = $api->getApiUrl(); - } catch (Exception $exception) { - $msg = l10n( - 'MediaWiki API discovery failed for: %s
Error: %s', - $url, - $exception->getMessage() - ); - $template->assign(array( - 'warnings' => $msg, - 'info' => $_POST, - )); - $validUrl = false; - } - // If we've got a valid API URL, find the site name and save all data. - if ($validUrl) { - - $username = $_POST['username']; - $password = $_POST['password']; - - $loggedIn = false; - try - { - $loggedIn = $api->login(new ApiUser($username, $password)); - } catch (UsageException $e) { - $msg = l10n('Authentication failed.
Error: %s', $e->getMessage()); - $template->assign(array( - 'warnings' => $msg, - 'info' => $_POST, - )); - } - - // If logging in worked, get some more information and save the config. - if ($loggedIn) - { - $siteInfo = $api->getRequest( - FluentRequest::factory() - ->setAction('query') - ->setParam('meta', 'siteinfo') - ); - $p2mConf[$info['id']] = array( - 'sitename' => $siteInfo['query']['general']['sitename'], - 'url' => $url, - 'username' => $username, - 'password' => $password, - 'wikitext' => isset($_POST['wikitext']) ? $_POST['wikitext'] : '', - ); - conf_update_param(PIWIGO2MEDIAWIKI_ID, $p2mConf); - redirect(PIWIGO2MEDIAWIKI_ADMIN); - } - } +defined('PHPWG_ROOT_PATH') or exit(1); +// Main navigation. +$tab = $_GET['tab'] ?? 'settings'; +if (in_array($tab, array('settings', 'oauth'))) { + $adminPage = __DIR__.'/admin/'.$tab.'.php'; +} else { + $adminPage = __DIR__.'/admin/photo.php'; } - -$template_handle = PIWIGO2MEDIAWIKI_ID.'admin'; -$template_file = PIWIGO2MEDIAWIKI_DIR.'admin.tpl'; -$template->set_filename($template_handle, $template_file); -$template->assign_var_from_handle('ADMIN_CONTENT', $template_handle); +require_once $adminPage; diff --git a/admin.tpl b/admin.tpl deleted file mode 100644 index 636871a..0000000 --- a/admin.tpl +++ /dev/null @@ -1,91 +0,0 @@ -

{'Piwigo to MediaWiki'|translate}

- -

{'Available MediaWiki sites'|translate}

-{if ! $p2m_conf } -

{'None found'|translate}

-{else} - - - - - - - - - - - - {foreach from=$p2m_conf key=id item=site} - - - - - - - - {/foreach} - -
{'Number'|translate}{'Site name'|translate}{'API URL'|translate}{'Username'|translate}{'Actions'|translate}
{$id}{$site.sitename}{$site.url}{$site.username} - {'Edit'|translate} -
- - - - -
-
-{/if} - -
- - -
- - {if $info.id} - {"Edit this wiki's details"|translate} - - {else} - {'Add a new wiki'|translate} - {/if} - - - - - - - - - - - - - - - - - - - - - - -
- {if $info.id} - - {'Cancel'|translate} - {else} - - {/if} -
-
-
- -{footer_script} - $('#mediawiki_url').on('change', function() { - - }); -{/footer_script} - -{html_style} - .piwigo2mediawiki-wikis form { display:inline } -{/html_style} diff --git a/admin/commons.svg b/admin/commons.svg new file mode 100644 index 0000000..e6b61d2 --- /dev/null +++ b/admin/commons.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/admin/oauth.php b/admin/oauth.php new file mode 100644 index 0000000..1be60ac --- /dev/null +++ b/admin/oauth.php @@ -0,0 +1,47 @@ +setConsumer(new Consumer($conf[WIKIMEDIACOMMONS_ID]['key'], $conf[WIKIMEDIACOMMONS_ID]['secret'])); +$oauthClientConf->setUserAgent(get_root_url()); +$client = new Client($oauthClientConf); + +if (isset($_GET['logout'])) { + userprefs_update_param(WIKIMEDIACOMMONS_ID, null); + $_SESSION['page_infos'][] = l10n('You have been logged out of Wikimedia Commons.'); + redirect(get_root_url().'admin.php'); +} + +if (!isset($_GET['oauth_verifier'])) { + // Send them off to Commons to authorise Piwigo. + list( $authUrl, $requestToken ) = $client->initiate(); + $_SESSION['request_secret'] = $requestToken->secret; + redirect($authUrl); + +} else { + // When they come back, reconstruct the token from the session, and fetch an access token to store. + $requestToken = new Token( $_GET['oauth_token'], $_SESSION['request_secret'] ); + $accessToken = $client->complete( $requestToken, $_GET['oauth_verifier'] ); + $ident = $client->identify( $accessToken ); + userprefs_update_param(WIKIMEDIACOMMONS_ID, [ + 'username' => $ident->username, + 'access_key' => $accessToken->key, + 'access_secret' => $accessToken->secret, + ]); + $_SESSION['page_infos'][] = l10n('You are now logged in to Wikimedia Commons.'); + redirect(get_root_url().'admin.php'); +} diff --git a/admin/photo.php b/admin/photo.php new file mode 100644 index 0000000..cd2a124 --- /dev/null +++ b/admin/photo.php @@ -0,0 +1,160 @@ +set_id('photo'); +$tabsheet->select(WIKIMEDIACOMMONS_ID); +$tabsheet->assign(); + +// OAuth consumer config. +if (!isset($conf[WIKIMEDIACOMMONS_ID])) { +// $conf[WIKIMEDIACOMMONS_ID] = safe_unserialize($conf[WIKIMEDIACOMMONS_ID]); +//} else { + if (is_autorize_status(ACCESS_WEBMASTER)) { + $page['warnings'] = l10n('Please set up the Wikimedia Commons OAuth consumer in the plugin settings.'); + } else { + $page['errors'] = l10n('Please tell your site administrator to set up the Wikimedia Commons OAuth consumer in the plugin settings.'); + } +} + +$userPrefs = userprefs_get_param(WIKIMEDIACOMMONS_ID); +$loginUrl = false; +if (!isset($userPrefs['access_key'])) { + $loginUrl = WIKIMEDIACOMMONS_ADMIN.'-oauth'; +} + +$query = 'SELECT * FROM '.IMAGES_TABLE.' WHERE id = '.$imageId.';'; +$row = pwg_db_fetch_assoc(pwg_query($query)); + +if (isset($_POST['commons_filename'])) { + try { + $uploaded = uploadToCommons($row, $_POST['commons_filename'], $_POST['wikitext'], $_POST['caption']); + } catch (Exception $e) { + $uploaded['warnings'] = [$e->getCode() => $e->getMessage()]; + } + if (isset($uploaded['warnings'])) { + foreach ($uploaded['warnings'] as $key => $val) { + $formattedVal = is_string($val) ? $val : var_export($val, true); + $page['warnings'][] = "Unable to upload to Commons. $key: $formattedVal"; + } + } else { + $page['infos'][] = "Uploaded: {$uploaded['url']}"; + } +} + +$template->assign([ + 'ADMIN_PAGE_TITLE' => l10n('Edit photo').' #'.$imageId.'', + 'commons_url' => 'https://'.parse_url($conf[WIKIMEDIACOMMONS_ID]['endpoint'])['host'], + 'image_url' => DerivativeImage::url(IMG_MEDIUM, $row), + 'username' => $userPrefs['username'] ?? false, + 'login_url' => $loginUrl, + 'logout_url' => get_root_url().'admin.php?page=plugin-wikimediacommons-oauth&logout', + 'commons_filename' => $row['name'].'.'.pathinfo($row['file'], PATHINFO_EXTENSION), + 'caption' => $row['comment'], + 'wikitext' => getWikitext($row), +]); +$template_handle = WIKIMEDIACOMMONS_ID.'admin_photo'; +$template->set_filename($template_handle, __DIR__ . '/photo.tpl'); +$template->assign_var_from_handle('ADMIN_CONTENT', $template_handle); + +function getWikitext($row): string +{ + $information = "{{Information\n" + . "| description = \n" + . "| date = {{taken on|" . $row['date_creation'] . "|locationn=}}\n" + . "| source = " . get_absolute_root_url().make_picture_url(['image_id' => $row['id']]) . "\n" + . "| author = " . $row['author'] . "\n" + . "| permission = \n" + . "}}\n"; + $location = ''; + if (isset($row['latitude'])) { + $location = "{{location|".$row['latitude']."|".$row['longitude']."}}\n"; + } + return "== {{int:filedesc}} ==\n" + . $information + . $location + . "\n" + . "== {{int:license-header}} ==\n" + // @todo Make the license customisable. + . "{{cc-by-sa-4.0}}"; +} + +/** + * @param array $row Row from the images table. + * @param string $title Filename to use on Commons, with file extension. + * @param string $text Full wikitext to use for the descripiton page. + * @param string $caption Structured data caption. + * @return mixed[] With possible keys: 'url', 'filename', 'warnings'. + * @throws Exception + */ +function uploadToCommons(array $row, string $title, string $text, string $caption): array +{ + global $conf; + + $fullPath = realpath($row['path']); + if (!$fullPath) { + throw new InvalidArgumentException('Unable to find image file at '.$row['path']); + } + + $userPrefs = userprefs_get_param(WIKIMEDIACOMMONS_ID); + $authMethod = new OAuthOwnerConsumer( + $conf[WIKIMEDIACOMMONS_ID]['key'], + $conf[WIKIMEDIACOMMONS_ID]['secret'], + $userPrefs['access_key'], + $userPrefs['access_secret'] + ); + $api = MediaWiki::newFromPage($conf[WIKIMEDIACOMMONS_ID]['endpoint'], $authMethod)->action(); + $uploader = new CommonsFileUploader($api); + $uploadResult = $uploader->uploadWithResult($title, $fullPath, $text); + if (isset($uploadResult['upload']['warnings'])) { + return $uploadResult['upload']; + } + + // The resulting wiki page name, with 'File:' prefix. + $filename = $uploadResult['upload']['imageinfo']['canonicaltitle']; + $wikiUrl = $uploadResult['upload']['imageinfo']['descriptionurl']; + + // Get info. + $info = $api->request(ActionRequest::simpleGet('query') + ->setParam('titles', $filename)); + if (!isset($info['query']['pages'])) { + throw new Exception('Unable to get info about ' . $wikiUrl); + } + $pageInfo = array_shift($info['query']['pages']); + + // Caption. + $mediaId = 'M' . $pageInfo['pageid']; + $params = [ + 'language' => 'en', + 'id' => $mediaId, + 'value' => $caption, + 'token' => $api->getToken(), + ]; + $api->request(ActionRequest::simplePost('wbsetlabel', $params)); + + return [ + 'filename' => $filename, + 'url' => $wikiUrl, + ]; +} diff --git a/admin/photo.tpl b/admin/photo.tpl new file mode 100644 index 0000000..c9618dd --- /dev/null +++ b/admin/photo.tpl @@ -0,0 +1,64 @@ + +

{'With this form you can upload a photo from here to Wikimedia Commons.'|translate:$commons_url}

+ +{if $login_url} +

+ {'Connect to Wikimedia Commons'|translate} +

+{else} +

+ {'You are logged in as %s.'|translate:$username} + {'Disconnect from Wikimedia Commons'|translate} +

+{/if} + +
+
+ +
+ +
+

+ + +

+

+ + +

+

+ + +

+

+ +

+
+
+ +{html_head}{literal} + +{/literal}{/html_head} diff --git a/admin/settings.php b/admin/settings.php new file mode 100644 index 0000000..c635093 --- /dev/null +++ b/admin/settings.php @@ -0,0 +1,42 @@ + 'https://commons.wikimedia.org/w/index.php?title=Special:OAuth', + 'key' => '', + 'secret' => '', + ]; +} + +// Save the new settings and redirect back to the settings page. +if (isset($_POST[WIKIMEDIACOMMONS_ID]['endpoint'])) { + $conf[WIKIMEDIACOMMONS_ID] = [ + 'endpoint' => trim($_POST[WIKIMEDIACOMMONS_ID]['endpoint']), + 'key' => trim($_POST[WIKIMEDIACOMMONS_ID]['key']), + 'secret' => trim($_POST[WIKIMEDIACOMMONS_ID]['secret']), + ]; + conf_update_param(WIKIMEDIACOMMONS_ID, $conf[WIKIMEDIACOMMONS_ID]); + $_SESSION['page_infos'][] = l10n('Settings saved.'); + redirect(WIKIMEDIACOMMONS_ADMIN.'-settings'); +} + +// Prepare the template. +$template->assign([ + 'admin_url' => WIKIMEDIACOMMONS_ADMIN, + 'wikimediacommons_page' => WIKIMEDIACOMMONS_PAGE, + 'wikimediacommons_conf' => $conf[WIKIMEDIACOMMONS_ID], + 'callback_url' => add_url_params(get_absolute_root_url().'admin.php', ['page' => 'plugin-wikimediacommons-callback']), +]); + +$template_handle = WIKIMEDIACOMMONS_ID.'-settings'; +$template->set_filename($template_handle, __DIR__ . '/settings.tpl'); +$template->assign_var_from_handle('ADMIN_CONTENT', $template_handle); diff --git a/admin/settings.tpl b/admin/settings.tpl new file mode 100644 index 0000000..632d993 --- /dev/null +++ b/admin/settings.tpl @@ -0,0 +1,49 @@ +

{'Wikimedia Commons'|translate}

+ +
+

{'In order to export photos to Wikimedia Commons you must first authorize Piwigo.'|translate}

+

+ {'To do this, first'|translate} + + {'go to Meta Wiki to set up a new OAuth consumer'|translate} + with the following permissions: +

+ +

{'Set the callback URL to:'|translate} {$callback_url}

+

{'Meta Wiki will give you a key and a secret; add these to the form below.'|translate}

+

{'Even though you register the OAuth consumer on Meta Wiki, you should use the Commons domain name in the Endpoint URL here, so that your users are directed there to authorise instead of to Meta Wiki.'|translate}

+ +
+ + +

+ + +

+

+ + +

+

+ + +

+

+ + {'Cancel'|translate} +

+
+
+ +{html_style} + .wikimediacommons-settings { max-width:60em; margin:auto; } + .wikimediacommons-settings p, + .wikimediacommons-settings form p { text-align:left; margin:0.5em 0; } + .wikimediacommons-settings label { display:block; } + .wikimediacommons-settings form { margin:0; } +{/html_style} diff --git a/composer.json b/composer.json index ddd43d4..8d27095 100644 --- a/composer.json +++ b/composer.json @@ -1,14 +1,24 @@ { - "name": "samwilson/piwigo2mediawiki", - "description": "A Piwigo plugin for exporting photos to MediaWiki wikis.", + "name": "samwilson/wikimediacommons", + "description": "A Piwigo plugin for exporting photos to Wikimedia Commons.", "license": "GPL-3.0-or-later", + "config": { + "platform": { + "php": "8.2" + } + }, + "autoload": { + "psr-4": { + "Piwigo\\Plugin\\WikimediaCommons\\": "src/" + } + }, "require": { - "addwiki/mediawiki-api": "^0.7" + "addwiki/mediawiki-api": "^3" }, "require-dev": { - "squizlabs/php_codesniffer": "^3.0", - "jakub-onderka/php-parallel-lint": "^0.9", - "mediawiki/minus-x": "^0.3" + "squizlabs/php_codesniffer": "^4", + "php-parallel-lint/php-parallel-lint": "^1", + "mediawiki/minus-x": "^2" }, "scripts": { "test": [ diff --git a/main.inc.php b/main.inc.php index 39502f7..a0e460a 100644 --- a/main.inc.php +++ b/main.inc.php @@ -1,75 +1,65 @@ l10n('Piwigo to MediaWiki'), - 'URL' => PIWIGO2MEDIAWIKI_ADMIN, - ); - return $menu; - }); - - // Add the send-to-MediaWiki global action. - add_event_handler('loc_end_element_set_global', - function () { - global $template, $conf; - $content = $template->assign( PIWIGO2MEDIAWIKI_DIR.'action.tpl' ); - $template->append('element_set_global_plugins_actions', - array( - 'ID' => PIWIGO2MEDIAWIKI_ID, - 'NAME' => l10n('Copy to MediaWiki'), 'CONTENT' => $content, - ) +// Add a tab to the picture page. +add_event_handler( + 'tabsheet_before_select', + function(array $sheets, ?string $id) { + if ($id == 'photo') + { + $logoUrl = WIKIMEDIACOMMONS_PATH.'/admin/commons.svg'; + $logo = ''; + $sheets[WIKIMEDIACOMMONS_ID] = array( + 'caption' => $logo.' '.l10n('Wikimedia Commons'), + 'url' => WIKIMEDIACOMMONS_ADMIN.'-'.$_GET['image_id'], ); } - ); - -} + return $sheets; + } +); diff --git a/src/CommonsFileUploader.php b/src/CommonsFileUploader.php new file mode 100644 index 0000000..577ff87 --- /dev/null +++ b/src/CommonsFileUploader.php @@ -0,0 +1,41 @@ +setChunkSize(90 * 1024 * 1024); + } + + /** + * @param string $targetName + * @param string $location + * @param string $text + * @param string $comment + * @return mixed + */ + public function uploadWithResult(string $targetName, string $location, string $text = '', string $comment = '') + { + $params = [ + 'filename' => $targetName, + 'token' => $this->api->getToken(), + 'text' => $text, + 'comment' => $comment, + 'filesize' => filesize($location), + 'file' => fopen($location, 'r'), + ]; + $params = $this->uploadByChunks($params); + return $this->api->request(ActionRequest::simplePost('upload', $params)); + } +} From 20c194c53b4e14d81ad557e0f3ab0692d0485d51 Mon Sep 17 00:00:00 2001 From: Sam Wilson Date: Fri, 1 May 2026 10:57:08 +0200 Subject: [PATCH 2/3] fix phpcs issues --- .phpcs.xml | 30 +------- admin.php | 6 +- admin/oauth.php | 37 ++++++---- admin/photo.php | 143 ++++++++++++++++++++---------------- admin/settings.php | 23 +++--- composer.json | 2 +- main.inc.php | 4 +- src/CommonsFileUploader.php | 21 ++++-- 8 files changed, 136 insertions(+), 130 deletions(-) diff --git a/.phpcs.xml b/.phpcs.xml index 465482a..da668a2 100644 --- a/.phpcs.xml +++ b/.phpcs.xml @@ -1,34 +1,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - + . - ./vendor - diff --git a/admin.php b/admin.php index c874f05..15c2169 100644 --- a/admin.php +++ b/admin.php @@ -8,8 +8,8 @@ // Main navigation. $tab = $_GET['tab'] ?? 'settings'; if (in_array($tab, array('settings', 'oauth'))) { - $adminPage = __DIR__.'/admin/'.$tab.'.php'; + $admin_page = __DIR__.'/admin/'.$tab.'.php'; } else { - $adminPage = __DIR__.'/admin/photo.php'; + $admin_page = __DIR__.'/admin/photo.php'; } -require_once $adminPage; +require_once $admin_page; diff --git a/admin/oauth.php b/admin/oauth.php index 1be60ac..ff5d154 100644 --- a/admin/oauth.php +++ b/admin/oauth.php @@ -15,33 +15,38 @@ $conf[WIKIMEDIACOMMONS_ID] = safe_unserialize($conf[WIKIMEDIACOMMONS_ID]); -$oauthClientConf = new ClientConfig($conf[WIKIMEDIACOMMONS_ID]['endpoint'], true); -$oauthClientConf->setConsumer(new Consumer($conf[WIKIMEDIACOMMONS_ID]['key'], $conf[WIKIMEDIACOMMONS_ID]['secret'])); -$oauthClientConf->setUserAgent(get_root_url()); -$client = new Client($oauthClientConf); +$oauth_client_conf = new ClientConfig($conf[WIKIMEDIACOMMONS_ID]['endpoint']); +$oauth_client_conf->setConsumer(new Consumer( + $conf[WIKIMEDIACOMMONS_ID]['key'], + $conf[WIKIMEDIACOMMONS_ID]['secret'] +)); +$oauth_client_conf->setUserAgent(get_root_url()); +$client = new Client($oauth_client_conf); if (isset($_GET['logout'])) { userprefs_update_param(WIKIMEDIACOMMONS_ID, null); - $_SESSION['page_infos'][] = l10n('You have been logged out of Wikimedia Commons.'); + $logged_out_msg = 'You have been logged out of Wikimedia Commons.'; + $_SESSION['page_infos'][] = l10n($logged_out_msg); redirect(get_root_url().'admin.php'); } if (!isset($_GET['oauth_verifier'])) { // Send them off to Commons to authorise Piwigo. - list( $authUrl, $requestToken ) = $client->initiate(); - $_SESSION['request_secret'] = $requestToken->secret; - redirect($authUrl); + list( $auth_url, $request_token ) = $client->initiate(); + $_SESSION['request_secret'] = $request_token->secret; + redirect($auth_url); } else { - // When they come back, reconstruct the token from the session, and fetch an access token to store. - $requestToken = new Token( $_GET['oauth_token'], $_SESSION['request_secret'] ); - $accessToken = $client->complete( $requestToken, $_GET['oauth_verifier'] ); - $ident = $client->identify( $accessToken ); - userprefs_update_param(WIKIMEDIACOMMONS_ID, [ + // When they come back, reconstruct the token from the session, + // and fetch an access token to store. + $request_token = new Token($_GET['oauth_token'], $_SESSION['request_secret']); + $access_token = $client->complete( $request_token, $_GET['oauth_verifier'] ); + $ident = $client->identify( $access_token ); + userprefs_update_param(WIKIMEDIACOMMONS_ID, array( 'username' => $ident->username, - 'access_key' => $accessToken->key, - 'access_secret' => $accessToken->secret, - ]); + 'access_key' => $access_token->key, + 'access_secret' => $access_token->secret, + )); $_SESSION['page_infos'][] = l10n('You are now logged in to Wikimedia Commons.'); redirect(get_root_url().'admin.php'); } diff --git a/admin/photo.php b/admin/photo.php index cd2a124..ab1a076 100644 --- a/admin/photo.php +++ b/admin/photo.php @@ -12,13 +12,11 @@ include_once(WIKIMEDIACOMMONS_PATH.'vendor/autoload.php'); $_GET['image_id'] = $_GET['tab']; -check_input_parameter('image_id', $_GET, false, PATTERN_ID); -$admin_photo_base_url = get_root_url().'admin.php?page=photo-'.$_GET['image_id']; - -// check_input_parameter('tab', $_GET, false, PATTERN_ID); -// $_GET['image_id'] = $imageId; - -$imageId = $_GET['tab']; +check_input_parameter( + 'image_id', $_GET, false, PATTERN_ID +); +$image_id = $_GET['tab']; +$admin_photo_base_url = get_root_url().'admin.php?page=photo-'.$image_id; $page['active_menu'] = get_active_menu('photo'); @@ -29,75 +27,89 @@ // OAuth consumer config. if (!isset($conf[WIKIMEDIACOMMONS_ID])) { -// $conf[WIKIMEDIACOMMONS_ID] = safe_unserialize($conf[WIKIMEDIACOMMONS_ID]); -//} else { if (is_autorize_status(ACCESS_WEBMASTER)) { - $page['warnings'] = l10n('Please set up the Wikimedia Commons OAuth consumer in the plugin settings.'); + $page['warnings'] = l10n('Please set up the Wikimedia Commons + OAuth consumer in the plugin settings.'); } else { - $page['errors'] = l10n('Please tell your site administrator to set up the Wikimedia Commons OAuth consumer in the plugin settings.'); + $page['errors'] = l10n('Please tell your site administrator to set up + the Wikimedia Commons OAuth consumer in the plugin settings.'); } } -$userPrefs = userprefs_get_param(WIKIMEDIACOMMONS_ID); -$loginUrl = false; -if (!isset($userPrefs['access_key'])) { - $loginUrl = WIKIMEDIACOMMONS_ADMIN.'-oauth'; +$user_prefs = userprefs_get_param(WIKIMEDIACOMMONS_ID); +$login_url = false; +if (!isset($user_prefs['access_key'])) { + $login_url = WIKIMEDIACOMMONS_ADMIN.'-oauth'; } -$query = 'SELECT * FROM '.IMAGES_TABLE.' WHERE id = '.$imageId.';'; +$query = 'SELECT * FROM '.IMAGES_TABLE.' WHERE id = '.$image_id.';'; $row = pwg_db_fetch_assoc(pwg_query($query)); if (isset($_POST['commons_filename'])) { try { - $uploaded = uploadToCommons($row, $_POST['commons_filename'], $_POST['wikitext'], $_POST['caption']); + $uploaded = uploadToCommons( + $row, + $_POST['commons_filename'], + $_POST['wikitext'], + $_POST['caption'] + ); } catch (Exception $e) { $uploaded['warnings'] = [$e->getCode() => $e->getMessage()]; } if (isset($uploaded['warnings'])) { foreach ($uploaded['warnings'] as $key => $val) { - $formattedVal = is_string($val) ? $val : var_export($val, true); - $page['warnings'][] = "Unable to upload to Commons. $key: $formattedVal"; + $formatted_val = is_string($val) ? $val : var_export($val, true); + $page['warnings'][] = "Unable to upload to Commons. $key: $formatted_val"; } } else { - $page['infos'][] = "Uploaded: {$uploaded['url']}"; + $page['infos'][] = l10n('Uploaded:')." {$uploaded['url']}"; } } -$template->assign([ - 'ADMIN_PAGE_TITLE' => l10n('Edit photo').' #'.$imageId.'', - 'commons_url' => 'https://'.parse_url($conf[WIKIMEDIACOMMONS_ID]['endpoint'])['host'], +$commons_url = parse_url($conf[WIKIMEDIACOMMONS_ID]['endpoint'])['host']; +$commons_title = $row['name'].'.'.pathinfo($row['file'], PATHINFO_EXTENSION); +$template->assign(array( + 'ADMIN_PAGE_TITLE' => l10n('Edit photo').' #'.$image_id.'', + 'commons_url' => 'https://'.$commons_url, 'image_url' => DerivativeImage::url(IMG_MEDIUM, $row), - 'username' => $userPrefs['username'] ?? false, - 'login_url' => $loginUrl, - 'logout_url' => get_root_url().'admin.php?page=plugin-wikimediacommons-oauth&logout', - 'commons_filename' => $row['name'].'.'.pathinfo($row['file'], PATHINFO_EXTENSION), + 'username' => $user_prefs['username'] ?? false, + 'login_url' => $login_url, + 'logout_url' => WIKIMEDIACOMMONS_ADMIN.'-oauth&logout', + 'commons_filename' => $commons_title, 'caption' => $row['comment'], 'wikitext' => getWikitext($row), -]); +)); $template_handle = WIKIMEDIACOMMONS_ID.'admin_photo'; -$template->set_filename($template_handle, __DIR__ . '/photo.tpl'); +$template->set_filename($template_handle, __DIR__.'/photo.tpl'); $template->assign_var_from_handle('ADMIN_CONTENT', $template_handle); function getWikitext($row): string { + $source = get_absolute_root_url().make_picture_url( + array('image_id' => $row['id']) + ); + // phpcs:disable Squiz.Strings.ConcatenationSpacing.PaddingFound $information = "{{Information\n" - . "| description = \n" - . "| date = {{taken on|" . $row['date_creation'] . "|locationn=}}\n" - . "| source = " . get_absolute_root_url().make_picture_url(['image_id' => $row['id']]) . "\n" - . "| author = " . $row['author'] . "\n" - . "| permission = \n" - . "}}\n"; + ."| description = \n" + ."| date = {{taken on|".$row['date_creation']."|locationn=}}\n" + ."| source = $source\n" + ."| author = ".$row['author']."\n" + ."| permission = \n" + ."}}\n"; + // phpcs:enable $location = ''; if (isset($row['latitude'])) { $location = "{{location|".$row['latitude']."|".$row['longitude']."}}\n"; } + // phpcs:disable Squiz.Strings.ConcatenationSpacing.PaddingFound return "== {{int:filedesc}} ==\n" - . $information - . $location - . "\n" - . "== {{int:license-header}} ==\n" + .$information + .$location + ."\n" + ."== {{int:license-header}} ==\n" // @todo Make the license customisable. - . "{{cc-by-sa-4.0}}"; + ."{{cc-by-sa-4.0}}"; + // phpcs:enable } /** @@ -112,49 +124,54 @@ function uploadToCommons(array $row, string $title, string $text, string $captio { global $conf; - $fullPath = realpath($row['path']); - if (!$fullPath) { - throw new InvalidArgumentException('Unable to find image file at '.$row['path']); + $full_path = realpath($row['path']); + if (!$full_path) { + throw new InvalidArgumentException( + 'Unable to find image file at '.$row['path'] + ); } - - $userPrefs = userprefs_get_param(WIKIMEDIACOMMONS_ID); - $authMethod = new OAuthOwnerConsumer( + + $user_prefs = userprefs_get_param(WIKIMEDIACOMMONS_ID); + $auth_method = new OAuthOwnerConsumer( $conf[WIKIMEDIACOMMONS_ID]['key'], $conf[WIKIMEDIACOMMONS_ID]['secret'], - $userPrefs['access_key'], - $userPrefs['access_secret'] + $user_prefs['access_key'], + $user_prefs['access_secret'] ); - $api = MediaWiki::newFromPage($conf[WIKIMEDIACOMMONS_ID]['endpoint'], $authMethod)->action(); + $api = MediaWiki::newFromPage( + $conf[WIKIMEDIACOMMONS_ID]['endpoint'], + $auth_method + )->action(); $uploader = new CommonsFileUploader($api); - $uploadResult = $uploader->uploadWithResult($title, $fullPath, $text); - if (isset($uploadResult['upload']['warnings'])) { - return $uploadResult['upload']; + $upload_result = $uploader->uploadWithResult($title, $full_path, $text); + if (isset($upload_result['upload']['warnings'])) { + return $upload_result['upload']; } // The resulting wiki page name, with 'File:' prefix. - $filename = $uploadResult['upload']['imageinfo']['canonicaltitle']; - $wikiUrl = $uploadResult['upload']['imageinfo']['descriptionurl']; + $filename = $upload_result['upload']['imageinfo']['canonicaltitle']; + $wiki_url = $upload_result['upload']['imageinfo']['descriptionurl']; // Get info. $info = $api->request(ActionRequest::simpleGet('query') ->setParam('titles', $filename)); if (!isset($info['query']['pages'])) { - throw new Exception('Unable to get info about ' . $wikiUrl); + throw new Exception('Unable to get info about '.$wiki_url); } - $pageInfo = array_shift($info['query']['pages']); + $page_info = array_shift($info['query']['pages']); // Caption. - $mediaId = 'M' . $pageInfo['pageid']; - $params = [ + $media_id = 'M'.$page_info['pageid']; + $params = array( 'language' => 'en', - 'id' => $mediaId, + 'id' => $media_id, 'value' => $caption, 'token' => $api->getToken(), - ]; + ); $api->request(ActionRequest::simplePost('wbsetlabel', $params)); - return [ + return array( 'filename' => $filename, - 'url' => $wikiUrl, - ]; + 'url' => $wiki_url, + ); } diff --git a/admin/settings.php b/admin/settings.php index c635093..060478d 100644 --- a/admin/settings.php +++ b/admin/settings.php @@ -10,33 +10,38 @@ if (isset($conf[WIKIMEDIACOMMONS_ID])) { $conf[WIKIMEDIACOMMONS_ID] = safe_unserialize($conf[WIKIMEDIACOMMONS_ID]); } else { - $conf[WIKIMEDIACOMMONS_ID] = [ - 'endpoint' => 'https://commons.wikimedia.org/w/index.php?title=Special:OAuth', + $endpoint = 'https://commons.wikimedia.org/w/index.php?title=Special:OAuth'; + $conf[WIKIMEDIACOMMONS_ID] = array( + 'endpoint' => $endpoint, 'key' => '', 'secret' => '', - ]; + ); } // Save the new settings and redirect back to the settings page. if (isset($_POST[WIKIMEDIACOMMONS_ID]['endpoint'])) { - $conf[WIKIMEDIACOMMONS_ID] = [ + $conf[WIKIMEDIACOMMONS_ID] = array( 'endpoint' => trim($_POST[WIKIMEDIACOMMONS_ID]['endpoint']), 'key' => trim($_POST[WIKIMEDIACOMMONS_ID]['key']), 'secret' => trim($_POST[WIKIMEDIACOMMONS_ID]['secret']), - ]; + ); conf_update_param(WIKIMEDIACOMMONS_ID, $conf[WIKIMEDIACOMMONS_ID]); $_SESSION['page_infos'][] = l10n('Settings saved.'); redirect(WIKIMEDIACOMMONS_ADMIN.'-settings'); } // Prepare the template. -$template->assign([ +$callback_url = add_url_params( + get_absolute_root_url().'admin.php', + array('page' => 'plugin-wikimediacommons-callback') +); +$template->assign(array( 'admin_url' => WIKIMEDIACOMMONS_ADMIN, 'wikimediacommons_page' => WIKIMEDIACOMMONS_PAGE, 'wikimediacommons_conf' => $conf[WIKIMEDIACOMMONS_ID], - 'callback_url' => add_url_params(get_absolute_root_url().'admin.php', ['page' => 'plugin-wikimediacommons-callback']), -]); + 'callback_url' => $callback_url, +)); $template_handle = WIKIMEDIACOMMONS_ID.'-settings'; -$template->set_filename($template_handle, __DIR__ . '/settings.tpl'); +$template->set_filename($template_handle, __DIR__.'/settings.tpl'); $template->assign_var_from_handle('ADMIN_CONTENT', $template_handle); diff --git a/composer.json b/composer.json index 8d27095..a0d99c4 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,7 @@ "addwiki/mediawiki-api": "^3" }, "require-dev": { - "squizlabs/php_codesniffer": "^4", + "samwilson/piwigo-coding-standards": "^0.1", "php-parallel-lint/php-parallel-lint": "^1", "mediawiki/minus-x": "^2" }, diff --git a/main.inc.php b/main.inc.php index a0e460a..a703c46 100644 --- a/main.inc.php +++ b/main.inc.php @@ -53,8 +53,8 @@ function(array $sheets, ?string $id) { if ($id == 'photo') { - $logoUrl = WIKIMEDIACOMMONS_PATH.'/admin/commons.svg'; - $logo = ''; + $logo_url = WIKIMEDIACOMMONS_PATH.'/admin/commons.svg'; + $logo = ''; $sheets[WIKIMEDIACOMMONS_ID] = array( 'caption' => $logo.' '.l10n('Wikimedia Commons'), 'url' => WIKIMEDIACOMMONS_ADMIN.'-'.$_GET['image_id'], diff --git a/src/CommonsFileUploader.php b/src/CommonsFileUploader.php index 577ff87..c5316b7 100644 --- a/src/CommonsFileUploader.php +++ b/src/CommonsFileUploader.php @@ -19,23 +19,30 @@ public function __construct(ActionApi $api) } /** - * @param string $targetName + * @param string $target_name * @param string $location * @param string $text * @param string $comment * @return mixed */ - public function uploadWithResult(string $targetName, string $location, string $text = '', string $comment = '') + public function uploadWithResult( + string $target_name, + string $location, + string $text = '', + string $comment = '' + ) { - $params = [ - 'filename' => $targetName, + $params = array( + 'filename' => $target_name, 'token' => $this->api->getToken(), 'text' => $text, 'comment' => $comment, 'filesize' => filesize($location), 'file' => fopen($location, 'r'), - ]; - $params = $this->uploadByChunks($params); - return $this->api->request(ActionRequest::simplePost('upload', $params)); + ); + return $this->api->request(ActionRequest::simplePost( + 'upload', + $this->uploadByChunks($params) + )); } } From 7e10b2540a6ebb44c2d513b621b5b3aabb7e1a12 Mon Sep 17 00:00:00 2001 From: Sam Wilson Date: Fri, 1 May 2026 14:17:49 +0200 Subject: [PATCH 3/3] Composer name --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index a0d99c4..0b41760 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,5 @@ { - "name": "samwilson/wikimediacommons", + "name": "samwilson/piwigo-wikimediacommons", "description": "A Piwigo plugin for exporting photos to Wikimedia Commons.", "license": "GPL-3.0-or-later", "config": {