mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-11-23 14:06:52 +00:00
Introduce VisualEditorApiVisualEditorPostSaveHook
What: Add hook that runs after a save attempt is made in ApiVisualEditorEdit. The hook receives the same data available in ApiVisualEditorEdit, and implementations of the hook can modify the API response. Also introduce templated parameters (https://www.mediawiki.org/wiki/API:Templated_parameters) in the API parameters; this allows plugins to pass arbitrary data along with their request using e.g. plugins=linkrecommendation&data-linkrecommendation=foo Add ServiceWiring files, a PHP namespace, and a HookRunner class to support the above changes. Why: VE plugins may wish to send additional data when saving an edit and take action based on that data on the server-side. See for example the AddLink plugin in I7a052f8e which sends annotation data, and then uses the new hook to perform a database operation. Change-Id: I392691475fbdcec766acbd832600e82efcb5bfe8
This commit is contained in:
parent
1486e5f038
commit
f035ce51f1
|
@ -27,6 +27,9 @@
|
|||
"MediaWiki": ">= 1.36.0"
|
||||
},
|
||||
"callback": "VisualEditorHooks::onRegistration",
|
||||
"ServiceWiringFiles": [
|
||||
"includes/ServiceWiring.php"
|
||||
],
|
||||
"config": {
|
||||
"VisualEditorAllowExternalLinkPaste": {
|
||||
"value": false
|
||||
|
@ -187,7 +190,12 @@
|
|||
"UserNameUtils"
|
||||
]
|
||||
},
|
||||
"visualeditoredit": "ApiVisualEditorEdit"
|
||||
"visualeditoredit": {
|
||||
"class": "ApiVisualEditorEdit",
|
||||
"services": [
|
||||
"VisualEditorHookRunner"
|
||||
]
|
||||
}
|
||||
},
|
||||
"MessagesDirs": {
|
||||
"VisualEditor": [
|
||||
|
@ -2827,6 +2835,9 @@
|
|||
"SpecialPages": {
|
||||
"CollabPad": "SpecialCollabPad"
|
||||
},
|
||||
"AutoloadNamespaces": {
|
||||
"MediaWiki\\Extension\\VisualEditor\\": "includes/"
|
||||
},
|
||||
"AutoloadClasses": {
|
||||
"ApiParsoidTrait": "includes/ApiParsoidTrait.php",
|
||||
"ApiVisualEditor": "includes/ApiVisualEditor.php",
|
||||
|
|
|
@ -52,6 +52,8 @@
|
|||
"apihelp-visualeditoredit-param-cachekey": "Use the result of a previous serializeforcache request with this key. Overrides $1html.",
|
||||
"apihelp-visualeditoredit-param-captchaid": "Captcha ID (when saving with a captcha response).",
|
||||
"apihelp-visualeditoredit-param-captchaword": "Answer to the captcha (when saving with a captcha response).",
|
||||
"apihelp-visualeditoredit-param-plugins": "Plugins associated with the API request.",
|
||||
"apihelp-visualeditoredit-param-data-{plugin}": "Arbitrary data sent by a plugin with the API request.",
|
||||
"apihelp-visualeditoredit-param-etag": "ETag to send.",
|
||||
"apihelp-visualeditoredit-param-html": "HTML to send to Parsoid in exchange for wikitext.",
|
||||
"apihelp-visualeditoredit-param-minor": "Flag for minor edit.",
|
||||
|
|
|
@ -61,6 +61,8 @@
|
|||
"apihelp-visualeditoredit-param-cachekey": "{{doc-apihelp-param|visualeditoredit|cachekey}}",
|
||||
"apihelp-visualeditoredit-param-captchaid": "{{doc-apihelp-param|visualeditoredit|captchaid}}",
|
||||
"apihelp-visualeditoredit-param-captchaword": "{{doc-apihelp-param|visualeditoredit|captchaword}}",
|
||||
"apihelp-visualeditoredit-param-plugins": "{{doc-apihelp-param|visualeditoredit|plugins}}",
|
||||
"apihelp-visualeditoredit-param-data-{plugin}": "{{doc-apihelp-param|visualeditoredit|data-{plugin} }}",
|
||||
"apihelp-visualeditoredit-param-etag": "{{doc-apihelp-param|visualeditoredit|etag}}",
|
||||
"apihelp-visualeditoredit-param-html": "{{doc-apihelp-param|visualeditoredit|html}}",
|
||||
"apihelp-visualeditoredit-param-minor": "{{doc-apihelp-param|visualeditoredit|minor}}",
|
||||
|
|
|
@ -4,12 +4,14 @@
|
|||
*
|
||||
* @file
|
||||
* @ingroup Extensions
|
||||
* @copyright 2011-2020 VisualEditor Team and others; see AUTHORS.txt
|
||||
* @copyright 2011-2021 VisualEditor Team and others; see AUTHORS.txt
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
use MediaWiki\Extension\VisualEditor\VisualEditorHookRunner;
|
||||
use MediaWiki\Logger\LoggerFactory;
|
||||
use MediaWiki\MediaWikiServices;
|
||||
use MediaWiki\Page\PageIdentityValue;
|
||||
use MediaWiki\User\UserIdentity;
|
||||
use Wikimedia\ParamValidator\ParamValidator;
|
||||
|
||||
|
@ -19,12 +21,18 @@ class ApiVisualEditorEdit extends ApiBase {
|
|||
private const MAX_CACHE_RECENT = 2;
|
||||
private const MAX_CACHE_TTL = 900;
|
||||
|
||||
/** @var VisualEditorHookRunner */
|
||||
private $hookRunner;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @param ApiMain $main
|
||||
* @param string $name Name of this module
|
||||
* @param VisualEditorHookRunner $hookRunner
|
||||
*/
|
||||
public function __construct( ApiMain $main, $name ) {
|
||||
public function __construct( ApiMain $main, string $name, VisualEditorHookRunner $hookRunner ) {
|
||||
parent::__construct( $main, $name );
|
||||
$this->setLogger( LoggerFactory::getInstance( 'VisualEditor' ) );
|
||||
$this->hookRunner = $hookRunner;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -446,8 +454,26 @@ class ApiVisualEditorEdit extends ApiBase {
|
|||
$result['watchlistexpiry'] = $saveresult['edit']['watchlistexpiry'] ?? null;
|
||||
$result['result'] = 'success';
|
||||
}
|
||||
$plugins = explode( '|', $this->getRequest()->getVal( 'plugins', '' ) );
|
||||
$pluginData = [];
|
||||
foreach ( $plugins as $plugin ) {
|
||||
$pluginData[$plugin] = $this->getRequest()->getVal( 'data-' . $plugin );
|
||||
}
|
||||
$this->hookRunner->onVisualEditorApiVisualEditorEditPostSave(
|
||||
new PageIdentityValue(
|
||||
$title->getId(),
|
||||
$title->getNamespace(),
|
||||
$title->getDBkey(),
|
||||
PageIdentityValue::LOCAL
|
||||
),
|
||||
$user,
|
||||
$wikitext,
|
||||
$params,
|
||||
$pluginData,
|
||||
$saveresult,
|
||||
$result
|
||||
);
|
||||
}
|
||||
|
||||
// @phan-suppress-next-line PhanPossiblyUndeclaredVariable False positive
|
||||
$this->getResult()->addValue( null, $this->getModuleName(), $result );
|
||||
}
|
||||
|
@ -502,6 +528,16 @@ class ApiVisualEditorEdit extends ApiBase {
|
|||
'tags' => [
|
||||
ParamValidator::PARAM_ISMULTI => true,
|
||||
],
|
||||
'plugins' => [
|
||||
ParamValidator::PARAM_ISMULTI => true,
|
||||
ParamValidator::PARAM_TYPE => 'string',
|
||||
],
|
||||
// Additional data sent by the client. Not used directly in the ApiVisualEditorEdit workflows, but
|
||||
// is passed alongside the other parameters to implementations of onApiVisualEditorEditPostSave
|
||||
'data-{plugin}' => [
|
||||
ParamValidator::PARAM_ISMULTI => true,
|
||||
ApiBase::PARAM_TEMPLATE_VARS => [ 'plugin' => 'plugins' ]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
|
|
20
includes/ServiceWiring.php
Normal file
20
includes/ServiceWiring.php
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* ServiceWiring files for VisualEditor.
|
||||
*
|
||||
* @file
|
||||
* @ingroup Extensions
|
||||
* @copyright 2011-2021 VisualEditor Team and others; see AUTHORS.txt
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace MediaWiki\Extension\VisualEditor;
|
||||
|
||||
use MediaWiki\MediaWikiServices;
|
||||
|
||||
return [
|
||||
VisualEditorHookRunner::SERVICE_NAME => static function ( MediaWikiServices $services ): VisualEditorHookRunner {
|
||||
return new VisualEditorHookRunner( $services->getHookContainer() );
|
||||
},
|
||||
];
|
47
includes/VisualEditorApiVisualEditorEditPostSaveHook.php
Normal file
47
includes/VisualEditorApiVisualEditorEditPostSaveHook.php
Normal file
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
namespace MediaWiki\Extension\VisualEditor;
|
||||
|
||||
use MediaWiki\Page\ProperPageIdentity;
|
||||
use MediaWiki\User\UserIdentity;
|
||||
|
||||
/**
|
||||
* VisualEditorApiVisualEditorEditPostSaveHook
|
||||
*
|
||||
* @file
|
||||
* @ingroup Extensions
|
||||
* @copyright 2011-2021 VisualEditor Team and others; see AUTHORS.txt
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
interface VisualEditorApiVisualEditorEditPostSaveHook {
|
||||
|
||||
/**
|
||||
* This hook is executed in the ApiVisualEditorEdit after a action=save attempt.
|
||||
*
|
||||
* ApiVisualEditorEdit will wait for implementations of this hook to complete before returning a response, so
|
||||
* if the implementation needs to do something time-consuming that does not need to be sent back with the response,
|
||||
* consider using a DeferredUpdate or Job.
|
||||
*
|
||||
* @param ProperPageIdentity $page The page identity of the title used in the save attempt.
|
||||
* @param UserIdentity $user User associated with the save attempt.
|
||||
* @param string $wikitext The wikitext used in the save attempt.
|
||||
* @param array $params The params passed by the client in the API request. See
|
||||
* ApiVisualEditorEdit::getAllowedParams()
|
||||
* @param array $pluginData Associative array containing additional data specified by plugins, where the keys of
|
||||
* the array are plugin names and the value are arbitrary data.
|
||||
* @param array $saveResult The result from ApiVisualEditorEdit::saveWikitext()
|
||||
* @param array &$apiResponse The modifiable API response that VisualEditor will return to the client.
|
||||
* @return void
|
||||
*/
|
||||
public function onVisualEditorApiVisualEditorEditPostSave(
|
||||
ProperPageIdentity $page,
|
||||
UserIdentity $user,
|
||||
string $wikitext,
|
||||
array $params,
|
||||
array $pluginData,
|
||||
array $saveResult,
|
||||
array &$apiResponse
|
||||
): void;
|
||||
|
||||
}
|
52
includes/VisualEditorHookRunner.php
Normal file
52
includes/VisualEditorHookRunner.php
Normal file
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
|
||||
namespace MediaWiki\Extension\VisualEditor;
|
||||
|
||||
/**
|
||||
* VisualEditorHookRunner
|
||||
*
|
||||
* @file
|
||||
* @ingroup Extensions
|
||||
* @copyright 2011-2021 VisualEditor Team and others; see AUTHORS.txt
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
use MediaWiki\HookContainer\HookContainer;
|
||||
use MediaWiki\Page\ProperPageIdentity;
|
||||
use MediaWiki\User\UserIdentity;
|
||||
|
||||
class VisualEditorHookRunner implements VisualEditorApiVisualEditorEditPostSaveHook {
|
||||
|
||||
public const SERVICE_NAME = 'VisualEditorHookRunner';
|
||||
|
||||
/** @var HookContainer */
|
||||
private $hookContainer;
|
||||
|
||||
/**
|
||||
* @param HookContainer $hookContainer
|
||||
*/
|
||||
public function __construct( HookContainer $hookContainer ) {
|
||||
$this->hookContainer = $hookContainer;
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public function onVisualEditorApiVisualEditorEditPostSave(
|
||||
ProperPageIdentity $page,
|
||||
UserIdentity $user,
|
||||
string $wikitext,
|
||||
array $params,
|
||||
array $pluginData,
|
||||
array $saveResult,
|
||||
array &$apiResponse
|
||||
): void {
|
||||
$this->hookContainer->run( 'VisualEditorApiVisualEditorEditPostSave', [
|
||||
$page,
|
||||
$user,
|
||||
$wikitext,
|
||||
$params,
|
||||
$pluginData,
|
||||
$saveResult,
|
||||
&$apiResponse
|
||||
], [ 'abortable' => false ] );
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue