mediawiki-extensions-Gadgets/includes/Content/GadgetDefinitionContent.php

106 lines
2.9 KiB
PHP
Raw Normal View History

<?php
/**
* 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\Extension\Gadgets\Content;
use FormatJson;
use JsonContent;
use MediaWiki\Status\Status;
class GadgetDefinitionContent extends JsonContent {
/** @var Status|null Cached validation result */
private $validation;
/**
* @param string $text
*/
public function __construct( $text ) {
parent::__construct( $text, 'GadgetDefinition' );
}
public function isValid() {
// parent::isValid() is called in validate()
return $this->validate()->isOK();
}
/**
* Pretty-print JSON.
*
* If called before validation, it may return JSON "null".
*
* @return string
*/
public function beautifyJSON() {
// @todo we should normalize entries in module.pages
return FormatJson::encode( $this->getAssocArray(), "\t", FormatJson::UTF8_OK );
}
/**
Replace EditFilterMergedContent hook with ContentHandler override The reason for this hook is not the validation itself, because that is already done by `GadgetDefinitionContent->isValid` which is part of the core Content interface, already enforced by ContentHandler. Instead, the hook was here to provide the custom interface message GadgetDefinitionValidator, because the core Content interface is limited to boolean isValid(), which provides a very generic error message. However, nowadays ContentHandler exposes this mechanism directly such that we can directly attach a custom message to it without needing to wait for the stack to reach the EditPage and then override it after the fact from a global hook. Also: * Simplify validation logic towards "is" checks with only an expected description. * Move schema.json file to top-level file. It has been unused for as long as it has been in the repo, despite appearing (due to its placement) to be used as part of the source. It was added, I believe, with the intent to be used by the validator, but it isn't. It also isn't validated or checked for correctness by anything right now. For now, keep it as informal schema in the top-level location for easy discovery where perhaps others can find a use for it. SD0001 mentions gadget developers may want to start using it for Git-maintained gadgets to help with validation in their IDE, after Gadgets 2.0 is launched. Test Plan: * Set `$wgGadgetsRepo = 'json+definition';` * Create `MediaWiki:Gadgets/example.json` * Attempt to save "x" in settings.namespaces item. * Attempt to save "x.zip" in module.pages item. * Fails with this patch, similar as on master. Bug: T31272 Change-Id: I61bc3e40348a0aeb3bd3fa9ca86ccb7b93304095
2024-03-26 21:06:26 +00:00
* Helper for isValid
*
* This placed into a separate method so that the detailed error can be communicated
* to editors via GadgetDefinitionContentHandler::validateSave, instead of the generic
* 'invalid-content-data' message from ContentHandler::validateSave based on isValid.
*
* @return Status
*/
public function validate() {
// Cache the validation result to avoid re-computations
if ( !$this->validation ) {
if ( !parent::isValid() ) {
Replace EditFilterMergedContent hook with ContentHandler override The reason for this hook is not the validation itself, because that is already done by `GadgetDefinitionContent->isValid` which is part of the core Content interface, already enforced by ContentHandler. Instead, the hook was here to provide the custom interface message GadgetDefinitionValidator, because the core Content interface is limited to boolean isValid(), which provides a very generic error message. However, nowadays ContentHandler exposes this mechanism directly such that we can directly attach a custom message to it without needing to wait for the stack to reach the EditPage and then override it after the fact from a global hook. Also: * Simplify validation logic towards "is" checks with only an expected description. * Move schema.json file to top-level file. It has been unused for as long as it has been in the repo, despite appearing (due to its placement) to be used as part of the source. It was added, I believe, with the intent to be used by the validator, but it isn't. It also isn't validated or checked for correctness by anything right now. For now, keep it as informal schema in the top-level location for easy discovery where perhaps others can find a use for it. SD0001 mentions gadget developers may want to start using it for Git-maintained gadgets to help with validation in their IDE, after Gadgets 2.0 is launched. Test Plan: * Set `$wgGadgetsRepo = 'json+definition';` * Create `MediaWiki:Gadgets/example.json` * Attempt to save "x" in settings.namespaces item. * Attempt to save "x.zip" in module.pages item. * Fails with this patch, similar as on master. Bug: T31272 Change-Id: I61bc3e40348a0aeb3bd3fa9ca86ccb7b93304095
2024-03-26 21:06:26 +00:00
// Invalid JSON, use the detailed Status from JsonContent::getData for syntax errors.
$this->validation = $this->getData();
} else {
$validator = new GadgetDefinitionValidator();
$this->validation = $validator->validate( $this->getAssocArray(), true );
}
}
return $this->validation;
}
/**
* Get the JSON content as an associative array with
* all fields filled out, populating defaults as necessary.
*
* @return array
* @suppress PhanUndeclaredMethod
*/
public function getAssocArray() {
$info = wfObjectToArray( $this->getData()->getValue() );
/** @var GadgetDefinitionContentHandler $handler */
$handler = $this->getContentHandler();
$info = wfArrayPlus2d( $info, $handler->getEmptyDefinition() );
return $info;
}
/**
* @inheritDoc
*/
protected function objectTable( $val ) {
if ( $val instanceof GadgetDefinitionContentArmor ) {
return (string)$val;
}
return parent::objectTable( $val );
}
}