Page MenuHomePhabricator

Understand how to create a new MediaWiki API (in core?) for oEmbed protocol management
Closed, ResolvedPublic7 Estimated Story Points

Event Timeline

valerio.bozzolan triaged this task as High priority.

Looking at all available APIs - https://www.mediawiki.org/w/api.php - to understand where somebody should propose something like this.

Considerations:

  • 🔶 action=query probably nonsense to expand its children calls, since
  • 💚 action=oembed may make sense at least for this prototype

P.S. since it does not make sense to try, I tried to use https://duck.ai using LLAMA 90B parameters with the prompt:

How should be named the new MediaWiki API that manages oembed protocol, under /w/api.php`

First answers (links deactivated, but look at action=something):

  • https:// example.com/w/api.php?action=oembed&url=https:// example.com/wiki/File:Example.jpg
  • https:// example.com/w/api.php?action=embed&url=https:// example.com/wiki/File:Example.jpg
  • https:// example.com/w/api.php?action=mediaembed&url=https:// example.com/wiki/File:Example.jpg
  • https:// example.com/w/api.php?action=oembedprovider&url=https:// example.com/wiki/File:Example.jpg

So I guess I will continue documenting myself about creating action=oembed since it makes some sense

valerio.bozzolan changed the point value for this task from 1 to 7.

Dear Diary,

Registering a new MediaWiki API was true fun. Here the friends I've met in this travel:

  1. I needed a fresh MediaWiki copy from latest main master branch from MediaWiki core
    1. uhm interestingly in WMIT and WMCH I've invested hours in migrating the git branches from "master" to "main" after reading this Wikimedia discussion T254646, aaand wow I notice for the first time that MediaWiki core is still on "master". It makes sense for legacy reasons but I really never noticed that. Maybe knowing this would have helped me ignore it in other projects, or reduce this priority. lol
      1. the branch topic of mw core is covered here if you are interested, after a bit of digging: T377562: Rename mainline Git branch of MediaWiki core, extensions and skins from "master" to "main"
  2. interestingly if you need to "run MediaWiki in Docker" you risk to land here: https://www.mediawiki.org/wiki/Docker/Hub
  3. Assuming that creating a core API was a good idea for this basic task, I've explored the codebase and found this nice home for APIs https://phabricator.wikimedia.org/source/mediawiki/browse/master/includes/api/
  4. Instead of writing something from scratch I've examined what would be a "similar" API to start from, using these mental criteria:
    1. API that may have a small amount of arguments
    2. ... may have non-complicated output (not with generators)
    3. ... may have small business logic
    4. ... may receive/validate a page title
    5. ... and with a non-esoteric / non-weird name/workflow lol
  5. at this point the website was still working but the API was not listed
    • 🔶 I guessed that Phabricator had an autoloader file with all the classes hardcoded in it (that may sounds obvious - but in other projects there is some PHP reflection in place to do this automagically - not in MediaWiki I guess)
    • So I've found autoload.php and I tried to understand how to generate it
    • So I've triggered it with: docker compose exec mediawiki php maintenance/run.php generateLocalAutoload
      • it worked 🎉
    • 🔶 Well, I hope that an automatic local thing somewhere would have helped me find this problem if I had been a novice. I'd be curious to know how people are supposed to discover this in general. For example in Phorge there is a lint error for this - maybe also in MediaWiki but really I don't know how to test this thing - if you know how to run this class lint (?) please share thanks
  6. uhm API still not listed here http://localhost:9000/w/api.php
  7. manually added - it works lol

Very shortly, you need:

diff --git a/autoload.php b/autoload.php
index 31e2fdba1bd..9beee60b5c7 100644
--- a/autoload.php
+++ b/autoload.php
@@ -837,6 +837,7 @@ $wgAutoloadLocalClasses = [
        'MediaWiki\\Api\\ApiMessageTrait' => __DIR__ . '/includes/api/ApiMessageTrait.php',
        'MediaWiki\\Api\\ApiModuleManager' => __DIR__ . '/includes/api/ApiModuleManager.php',
        'MediaWiki\\Api\\ApiMove' => __DIR__ . '/includes/api/ApiMove.php',
+       'MediaWiki\\Api\\ApiOembed' => __DIR__ . '/includes/api/ApiOembed.php',
        'MediaWiki\\Api\\ApiOpenSearch' => __DIR__ . '/includes/api/ApiOpenSearch.php',
        'MediaWiki\\Api\\ApiOpenSearchFormatJson' => __DIR__ . '/includes/api/ApiOpenSearchFormatJson.php',
        'MediaWiki\\Api\\ApiOptions' => __DIR__ . '/includes/api/ApiOptions.php',
diff --git a/includes/api/ApiMain.php b/includes/api/ApiMain.php
index 956c901b3df..4154b2c369e 100644
--- a/includes/api/ApiMain.php
+++ b/includes/api/ApiMain.php
@@ -486,6 +486,9 @@ class ApiMain extends ApiBase {
                                'TempUserCreator',
                        ]
                ],
+               'oembed' => [
+                       'class' => ApiOEmbed::class,
+               ],
        ];
 
        /**
diff --git a/includes/api/ApiOEmbed.php b/includes/api/ApiOEmbed.php
new file mode 100644
index 00000000000..69031543e19
--- /dev/null
+++ b/includes/api/ApiOEmbed.php
@@ -0,0 +1,81 @@
+<?php
+/**
+ * Copyright © 2025 Valerio Bozzolan <nsa+mediawiki@succhia.cz>
+ *
+ * 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.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+namespace MediaWiki\Api;
+
+use LogicException;
+use MediaWiki\MainConfigNames;
+use MediaWiki\Page\MovePageFactory;
+use MediaWiki\Status\Status;
+use MediaWiki\Title\Title;
+use MediaWiki\User\Options\UserOptionsLookup;
+use MediaWiki\Watchlist\WatchlistManager;
+use RepoGroup;
+use Wikimedia\ParamValidator\ParamValidator;
+
+/**
+ * API Module to move pages
+ * @ingroup API
+ */
+class ApiOEmbed extends ApiBase {
+
+	public function __construct(
+		ApiMain $mainModule,
+		string $moduleName
+	) {
+		parent::__construct( $mainModule, $moduleName );
+	}
+
+	public function execute() {
+    $params = $this->extractRequestParams();
+		$this->requireOnlyOneParameter( $params, 'title' );
+		$title = Title::newFromText( $params['title'] );
+		if ( !$title || $title->isExternal() ) {
+			$this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $params['title'] ) ] );
+		}
+
+		$result = $this->getResult();
+		$result->addValue( null, "asd", $params['title'] );
+	}
+
+	public function getAllowedParams() {
+		return [
+			'title' => [
+				ParamValidator::PARAM_TYPE => 'string',
+				ParamValidator::PARAM_REQUIRED => true
+			],
+		];
+	}
+
+	protected function getExamplesMessages() {
+    $title = Title::newMainPage()->getPrefixedText();
+    $mp = rawurlencode( $title );
+		return [
+			'action=oembed&title={$title}'
+			  => 'apihelp-query+oembed-example-simple',
+		];
+	}
+
+	public function getHelpUrls() {
+		return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Oembed';
+	}
+}

\o/

Screenshot MediaWiki API result asd equals lol.png (291×855 px, 66 KB)

http://localhost:9000/w/api.php?action=oembed&title=lol


\o/

Lol. Putting 7 story points but probably more. I've really enjoyed the friends met in this small travel. asd

Now I can concentrate in the oEmbed business logic.

Let's continue in T364479: Allow media embedding from Wikimedia Commons using oEmbed