diff --git a/src/MediaWiki/SchemaEditAction.php b/src/MediaWiki/SchemaEditAction.php index c216e5e..83473bc 100644 --- a/src/MediaWiki/SchemaEditAction.php +++ b/src/MediaWiki/SchemaEditAction.php @@ -3,12 +3,21 @@ namespace Wikibase\Schema\MediaWiki; use CommentStoreComment; +use Content; use Deserializers\Exceptions\DeserializationException; use FormAction; +use Revision; use RuntimeException; use Status; +use Wikibase\DataModel\Term\AliasGroup; +use Wikibase\DataModel\Term\AliasGroupList; +use Wikibase\DataModel\Term\Fingerprint; +use Wikibase\DataModel\Term\Term; +use Wikibase\DataModel\Term\TermList; use Wikibase\Schema\DataModel\Schema; use Wikibase\Schema\Deserializers\DeserializerFactory; +use Wikibase\Schema\Diff\SchemaDiffer; +use Wikibase\Schema\Diff\SchemaPatcher; use Wikibase\Schema\MediaWiki\Content\WikibaseSchemaContent; /** @@ -53,48 +62,26 @@ class SchemaEditAction extends FormAction { } protected function getFormFields() { - /** @var WikibaseSchemaContent $content */ - $content = $this->getContext()->getWikiPage()->getContent(); - if ( !$content ) { - throw new RuntimeException( $this->msg( 'wikibaseschema-error-schemadeleted' ) ); - } + $undo = $this->getRequest()->getInt( 'undo' ); + $undoafter = $this->getRequest()->getInt( 'undoafter' ); + if ( $undo > 0 && $undoafter > 0 ) { + $olderContent = Revision::newFromId( $undo )->getContent(); + $newerContent = Revision::newFromId( $undoafter )->getContent(); + $latestContent = $this->getContext()->getWikiPage()->getContent(); - $deserializer = DeserializerFactory::newSchemaDeserializer(); - $serializedContent = json_decode( $content->getText(), true ); - try { - $schema = $deserializer->deserialize( $serializedContent ); - } catch ( DeserializationException $e ) { - // FIXME remove this try catch by 2019-02-11 ! - return [ - 'warning' => [ - 'type' => 'info', - 'default' => 'FIXME: Please remove this workaround in SchemaEditAction::getFormFields!', - 'cssclass' => 'warning' - ], - 'label' => [ - 'type' => 'text', - 'default' => $serializedContent[ 'labels' ][ 'en' ], - 'label-message' => 'wikibaseschema-editpage-label-inputlabel', - 'placeholder-message' => 'wikibaseschema-label-edit-placeholder', - ], - 'description' => [ - 'type' => 'text', - 'default' => $serializedContent[ 'descriptions' ][ 'en' ], - 'label-message' => 'wikibaseschema-editpage-description-inputlabel', - 'placeholder-message' => 'wikibaseschema-description-edit-placeholder', - ], - 'aliases' => [ - 'type' => 'text', - 'default' => implode( ' | ', $serializedContent[ 'aliases' ][ 'en' ] ), - 'label-message' => 'wikibaseschema-editpage-aliases-inputlabel', - 'placeholder-message' => 'wikibaseschema-aliases-edit-placeholder', - ], - 'schema' => [ - 'type' => 'textarea', - 'default' => $serializedContent[ 'schema' ], - 'label-message' => 'wikibaseschema-editpage-schema-inputlabel', - ], - ]; + $diff = ( new SchemaDiffer() )->diffSchemas( + $this->contentToSchema( $olderContent ), + $this->contentToSchema( $newerContent ) + ); + + $schema = $this->contentToSchema( $latestContent ); + ( new SchemaPatcher() )->patchSchema( + $schema, + $diff + ); + } else { + $content = $this->getContext()->getWikiPage()->getContent(); + $schema = $this->contentToSchema( $content ); } return [ @@ -124,6 +111,36 @@ class SchemaEditAction extends FormAction { ]; } + private function contentToSchema( Content $content = null ) { + if ( !$content ) { + throw new RuntimeException( $this->msg( 'wikibaseschema-error-schemadeleted' ) ); + } + if ( !( $content instanceof WikibaseSchemaContent ) ) { + throw new RuntimeException( 'internal error, unexpected content type' ); + } + + $deserializer = DeserializerFactory::newSchemaDeserializer(); + $serializedContent = json_decode( $content->getText(), true ); + try { + return $deserializer->deserialize( $serializedContent ); + } catch ( DeserializationException $e ) { + return new Schema( + $serializedContent['schema'], + new Fingerprint( + new TermList( [ + new Term( 'en', $serializedContent[ 'labels' ][ 'en' ] ) + ] ), + new TermList( [ + new Term( 'en', $serializedContent[ 'descriptions' ][ 'en' ] ) + ] ), + new AliasGroupList( [ + new AliasGroup( 'en', $serializedContent[ 'aliases' ][ 'en' ] ) + ] ) + ) + ); + } + } + protected function usesOOUI() { return true; }