* @file
* @ingroup DifferenceEngine
*/
+use Wikimedia\Assert\Assert;
/**
* Renders a diff for a single slot (that is, a diff between two content objects).
return [];
}
+ /**
+ * Helper method to normalize the input of getDiff().
+ * Verifies that at least one of $oldContent and $newContent is not null, verifies that
+ * they are instances of one of the allowed classes (if provided), and replaces null with
+ * empty content.
+ * @param Content|null &$oldContent
+ * @param Content|null &$newContent
+ * @param string|array|null $allowedClasses
+ */
+ protected function normalizeContents(
+ Content &$oldContent = null, Content &$newContent = null, $allowedClasses = null
+ ) {
+ if ( !$oldContent && !$newContent ) {
+ throw new InvalidArgumentException( '$oldContent and $newContent cannot both be null' );
+ }
+
+ if ( $allowedClasses ) {
+ if ( is_array( $allowedClasses ) ) {
+ $allowedClasses = implode( '|', $allowedClasses );
+ }
+ Assert::parameterType( $allowedClasses . '|null', $oldContent, '$oldContent' );
+ Assert::parameterType( $allowedClasses . '|null', $newContent, '$newContent' );
+ }
+
+ if ( !$oldContent ) {
+ $oldContent = $newContent->getContentHandler()->makeEmptyContent();
+ } elseif ( !$newContent ) {
+ $newContent = $oldContent->getContentHandler()->makeEmptyContent();
+ }
+ }
+
}
/** @inheritDoc */
public function getDiff( Content $oldContent = null, Content $newContent = null ) {
- if ( !$oldContent && !$newContent ) {
- throw new InvalidArgumentException( '$oldContent and $newContent cannot both be null' );
- } elseif ( $oldContent && !( $oldContent instanceof TextContent ) ) {
- throw new InvalidArgumentException( __CLASS__ . ' does not handle ' . get_class( $oldContent ) );
- } elseif ( $newContent && !( $newContent instanceof TextContent ) ) {
- throw new InvalidArgumentException( __CLASS__ . ' does not handle ' . get_class( $newContent ) );
- }
-
- if ( !$oldContent ) {
- $oldContent = $newContent->getContentHandler()->makeEmptyContent();
- } elseif ( !$newContent ) {
- $newContent = $oldContent->getContentHandler()->makeEmptyContent();
- }
+ $this->normalizeContents( $oldContent, $newContent, TextContent::class );
$oldText = $oldContent->serialize();
$newText = $newContent->serialize();
--- /dev/null
+<?php
+use Wikimedia\Assert\ParameterTypeException;
+use Wikimedia\TestingAccessWrapper;
+
+/**
+ * @covers SlotDiffRenderer
+ */
+class SlotDiffRendererTest extends \PHPUnit\Framework\TestCase {
+
+ /**
+ * @dataProvider provideNormalizeContents
+ */
+ public function testNormalizeContents(
+ $oldContent, $newContent, $allowedClasses,
+ $expectedOldContent, $expectedNewContent, $expectedExceptionClass
+ ) {
+ $slotDiffRenderer = $this->getMockBuilder( SlotDiffRenderer::class )
+ ->getMock();
+ try {
+ // __call needs help deciding which parameter to take by reference
+ call_user_func_array( [ TestingAccessWrapper::newFromObject( $slotDiffRenderer ),
+ 'normalizeContents' ], [ &$oldContent, &$newContent, $allowedClasses ] );
+ $this->assertEquals( $expectedOldContent, $oldContent );
+ $this->assertEquals( $expectedNewContent, $newContent );
+ } catch ( Exception $e ) {
+ if ( !$expectedExceptionClass ) {
+ throw $e;
+ }
+ $this->assertInstanceOf( $expectedExceptionClass, $e );
+ }
+ }
+
+ public function provideNormalizeContents() {
+ return [
+ 'both null' => [ null, null, null, null, null, InvalidArgumentException::class ],
+ 'left null' => [
+ null, new WikitextContent( 'abc' ), null,
+ new WikitextContent( '' ), new WikitextContent( 'abc' ), null,
+ ],
+ 'right null' => [
+ new WikitextContent( 'def' ), null, null,
+ new WikitextContent( 'def' ), new WikitextContent( '' ), null,
+ ],
+ 'type filter' => [
+ new WikitextContent( 'abc' ), new WikitextContent( 'def' ), WikitextContent::class,
+ new WikitextContent( 'abc' ), new WikitextContent( 'def' ), null,
+ ],
+ 'type filter (subclass)' => [
+ new WikitextContent( 'abc' ), new WikitextContent( 'def' ), TextContent::class,
+ new WikitextContent( 'abc' ), new WikitextContent( 'def' ), null,
+ ],
+ 'type filter (null)' => [
+ new WikitextContent( 'abc' ), null, TextContent::class,
+ new WikitextContent( 'abc' ), new WikitextContent( '' ), null,
+ ],
+ 'type filter failure (left)' => [
+ new TextContent( 'abc' ), new WikitextContent( 'def' ), WikitextContent::class,
+ null, null, ParameterTypeException::class,
+ ],
+ 'type filter failure (right)' => [
+ new WikitextContent( 'abc' ), new TextContent( 'def' ), WikitextContent::class,
+ null, null, ParameterTypeException::class,
+ ],
+ 'type filter (array syntax)' => [
+ new WikitextContent( 'abc' ), new JsonContent( 'def' ),
+ [ JsonContent::class, WikitextContent::class ],
+ new WikitextContent( 'abc' ), new JsonContent( 'def' ), null,
+ ],
+ 'type filter failure (array syntax)' => [
+ new WikitextContent( 'abc' ), new CssContent( 'def' ),
+ [ JsonContent::class, WikitextContent::class ],
+ null, null, ParameterTypeException::class,
+ ],
+ ];
+ }
+
+}
<?php
+use Wikimedia\Assert\ParameterTypeException;
+
/**
* @covers TextSlotDiffRenderer
*/
'non-text left content' => [
$this->makeContent( '', 'testing-nontext' ),
$this->makeContent( "aaa\nbbb\nccc" ),
- new InvalidArgumentException( 'TextSlotDiffRenderer does not handle DummyNonTextContent' ),
+ new ParameterTypeException( '$oldContent', 'TextContent|null' ),
],
'non-text right content' => [
$this->makeContent( "aaa\nbbb\nccc" ),
$this->makeContent( '', 'testing-nontext' ),
- new InvalidArgumentException( 'TextSlotDiffRenderer does not handle DummyNonTextContent' ),
+ new ParameterTypeException( '$newContent', 'TextContent|null' ),
],
];
}