wiki.techinc.nl/includes/api/Validator/ApiParamValidatorCallbacks.php
C. Scott Ananian 1408b322b6 api: Add new 'raw' parameter type which avoids Unicode NFC normalization
The mandatory Unicode NFC normalization on API parameters was causing
spurious dirty diffs in VisualEditor/DiscussionTools when editors used
HTML entities to encode non-NFC codepoints, like  .  Although
wikitext is (ought to be!) in NFC form, the output HTML may not be,
due to explicit entities in the wikitext.

This type is used in VisualEditor change
I0d34c9a01f1132c2616ed3392ea40d8b73e15325 to prevent Parsoid HTML from
being corrupted when it is round-tripped.

Bug: T266140
Change-Id: I2e78e660ba1867744e34eda7d00ea527ec016b71
2020-12-23 18:24:34 +00:00

141 lines
3.6 KiB
PHP

<?php
namespace MediaWiki\Api\Validator;
use ApiMain;
use MediaWiki\Message\Converter as MessageConverter;
use Wikimedia\Message\DataMessageValue;
use Wikimedia\ParamValidator\Callbacks;
use Wikimedia\ParamValidator\Util\UploadedFile;
/**
* ParamValidator callbacks for the Action API
* @since 1.35
* @ingroup API
*/
class ApiParamValidatorCallbacks implements Callbacks {
/** @var ApiMain */
private $apiMain;
/** @var MessageConverter */
private $messageConverter;
/**
* @internal
* @param ApiMain $main
*/
public function __construct( ApiMain $main ) {
$this->apiMain = $main;
$this->messageConverter = new MessageConverter();
}
public function hasParam( $name, array $options ) {
return $this->apiMain->getCheck( $name );
}
public function getValue( $name, $default, array $options ) {
$value = $this->apiMain->getVal( $name, $default );
$request = $this->apiMain->getRequest();
$rawValue = $request->getRawVal( $name );
if ( $options['raw'] ?? false ) {
// Bypass NFC normalization
return $rawValue;
}
if ( is_string( $rawValue ) ) {
// Preserve U+001F for multi-values
if ( substr( $rawValue, 0, 1 ) === "\x1f" ) {
// This loses the potential checkTitleEncoding() transformation done by
// WebRequest for $_GET. Let's call that a feature.
$value = implode( "\x1f", $request->normalizeUnicode( explode( "\x1f", $rawValue ) ) );
}
// Check for NFC normalization, and warn
if ( $rawValue !== $value ) {
$options['module']->handleParamNormalization( $name, $value, $rawValue );
}
}
return $value;
}
public function hasUpload( $name, array $options ) {
return $this->getUploadedFile( $name, $options ) !== null;
}
public function getUploadedFile( $name, array $options ) {
$upload = $this->apiMain->getUpload( $name );
if ( !$upload->exists() ) {
return null;
}
return new UploadedFile( [
'error' => $upload->getError(),
'tmp_name' => $upload->getTempName(),
'size' => $upload->getSize(),
'name' => $upload->getName(),
'type' => $upload->getType(),
] );
}
public function recordCondition(
DataMessageValue $message, $name, $value, array $settings, array $options
) {
/** @var \ApiBase $module */
$module = $options['module'];
$code = $message->getCode();
switch ( $code ) {
case 'param-deprecated': // @codeCoverageIgnore
case 'deprecated-value': // @codeCoverageIgnore
if ( $code === 'param-deprecated' ) {
$feature = $name;
} else {
$feature = $name . '=' . $value;
$data = $message->getData() ?? [];
if ( isset( $data['💩'] ) ) {
// This is from an old-style Message. Strip out ParamValidator's added params.
unset( $data['💩'] );
$message = DataMessageValue::new(
$message->getKey(),
array_slice( $message->getParams(), 2 ),
$code,
$data
);
}
}
$m = $module;
while ( !$m->isMain() ) {
$p = $m->getParent();
$mName = $m->getModuleName();
$mParam = $p->encodeParamName( $p->getModuleManager()->getModuleGroup( $mName ) );
$feature = "{$mParam}={$mName}&{$feature}";
$m = $p;
}
$module->addDeprecation(
$this->messageConverter->convertMessageValue( $message ),
$feature,
$message->getData()
);
break;
case 'param-sensitive': // @codeCoverageIgnore
$module->getMain()->markParamsSensitive( $name );
break;
default:
$module->addWarning(
$this->messageConverter->convertMessageValue( $message ),
$message->getCode(),
$message->getData()
);
break;
}
}
public function useHighLimits( array $options ) {
return $this->apiMain->canApiHighLimits();
}
}