Extension:Diff

From MediaWiki.org
Jump to: navigation, search
MediaWiki extensions manual - list
Crystal Clear action run.png
Diff

Release status: stable

Diff extension.png
Description Structured data diff library
Author(s) Jeroen De Dauw
Last version 0.6 (2013-05-08)
MediaWiki Not required
PHP 5.3 or above
Database changes no
License GNU GPL v2+
Download
readme
release notes
Check usage and version matrix; stats
Bugs: list open list all report

Diff is a small library for creating and representing diffs between data structures. It is a standalone PHP library that can be used by PHP applications (such as MediaWiki extensions). It does thus not expose functionality to the user on its own.

Diff provides classes to represent diffs and the operations they consist of, as well as service objects to compute such diffs or apply them as a patch.

Contents

Requirements[edit]

Diff requires:

  • PHP 5.3 or above
  • (For running the PHPUnit tests: PHPUnit 3.7 or later)
  • (If used as MediaWiki extension: MediaWiki 1.16 or later)

Download[edit]

You can download the extension directly from the MediaWiki source code repository (browse code). You can get:

One of the extensions tags

Not all extensions have tags. Some extensions have tags for each release, in which case those tags have the same stability as the release. To download a tag

  • Go to the tags list
  • Click the name of the tag you want to download
  • Click "snapshot"
The latest version of one of the extensions branches

Each extension has a master branch containing the latest code (might be unstable). Extensions can have further branches as well.

  • Go to the branches list
  • Click the branch name
  • Click "snapshot"
A snapshot made during the release of a MediaWiki version.

This might be unstable and is not guaranteed to work with the associated MediaWiki version.

After you've got the code, save it into the extensions/Diff directory of your wiki.

If you are familiar with git and have shell access to your server, you can obtain the extension, with all its tags and branches, as follows:

cd extensions
git clone https://gerrit.wikimedia.org/r/p/mediawiki/extensions/Diff.git

Installation[edit]

As MediaWiki extension[edit]

Once you have downloaded the code, place the Diff directory within your MediaWiki 'extensions' directory. Then add the following code to your LocalSettings.php file:

# Diff
require_once( "$IP/extensions/Diff/Diff.php" );

As standalone library[edit]

Include Diff/Diff.php. This file includes an autoloader allowing you to directly reference the diff classes without first including their files. If you want to use your own autoloader, you can find the list of diff classes in Diff/Diff.classes.php.

Usage[edit]

The Diff library can be subdevided into 3 components.

DiffOp[edit]

First and formost are the objects to represent diffs. Diffs are represented by the Diff class, which is an aggregate for diff operations, think "add" and "remove", that all extend from DiffOp. Diff itself is a DiffOp, since the library supports recursion, and thus has the need to be able to represent nested diffs.

The available DiffOps are:

  • DiffOpAdd - addition of a value (newValue)
  • DiffOpChange - modification of a value (oldValue, newValue)
  • DiffOpRemove - removal of a value (oldValue)
  • Diff - a collection of diff operations

These can all be found in includes/diffop.

The Diff class can be set to be either associative or non-assocative. In case of the later, only DiffOpAdd and DiffOpRemove are allowed in it.

Differ[edit]

Often you need to construct a diff between two arrays, rather then creating it manually. To do this, the Diff library includes a few classes implementing the Differ interface, which contains one very simple method.

/**
 * Takes two arrays, computes the diff, and returns this diff as an array of DiffOp.
 *
 * @since 0.1
 *
 * @param array $oldValues The first array
 * @param array $newValues The second array
 *
 * @throws Exception
 * @return DiffOp[]
 */
public function doDiff( array $oldValues, array $newValues );

The Differs that come with the library are:

  • ListDiffer: Differ that only looks at the values of the arrays (and thus ignores key differences).
  • MapDiffer: Differ that does an associative diff between two arrays, with the option to do this recursively.

Both Differ objects come with a few options that can be used to change their behaviour.

All differ functionality can be found in includes/differ.

Patcher[edit]

The third component that comes with the Diff library is a set of classes implementing the Patcher interface. This interface contains a single simple method:

/**
 * Applies the applicable operations from the provided diff to
 * the provided base value.
 *
 * @since 0.1
 *
 * @param array $base
 * @param Diff $diffOps
 *
 * @return array
 */
public function patch( array $base, Diff $diffOps );

Diff comes with two clases implementing the Patcher interface:

  • ListPatcher: Applies non-associative diffs to a base. With default options does the reverse of ListDiffer
  • MapPatcher: Applies diff to a base, recursivly if needed. With default options does the reverse of MapDiffer

All classes part of the patcher component can be found in includes/patcher

Comparer[edit]

Added in 0.6

TODO

Merger[edit]

Added in 0.7

TODO

Examples[edit]

DiffOp
// Constructing an empty diff
$diff = new Diff();
 
// Adding a single add-operation to the diff
$diff[] = new DiffOpAdd( 'added value' );
 
// Adding a single change-operation to the diff for key "awesomeness"
$diff['awesomeness'] = new DiffOpChange( 9000, 9001 );
 
// Getting an array with the change operations from the Diff
$changeOps = $diff->getChanges();
 
// Creating a new diff with a set op DiffOps, and specifying that it is an associative diff
$diff = new Diff( $changeOps, true );
 
// Looping over the diff operations that make up the diff
foreach ( $diff as $diffOp ) {}
 
// Removing the "awesomeness" operation from the diff
unset( $diff['awesomeness'] );
 
// Adding a non-associative diff with one add operation to the diff for the "recursion" key
$diff['recursion'] = new Diff( array( DiffOpAdd( 42 ) ), false );
 
// Counting the number of diff operations that make up the diff
count( $diff );
Differ
$oldValues = array( 0, 1, 2, 42, 9001, 'foobar' );
$newValues = array( 0, 0, 23, 'foobar', 1, 2 );
 
$differ = new ListDiffer();
 
$diffOps = $differ->doDiff( $oldValues, $newValues );
 
// This is the result
$diffOps = array(
    DiffOpRemove( 42 ),
    DiffOpRemove( 9001 )
    DiffOpAdd( 0 ),
    DiffOpAdd( 23 )
);
$oldValues = array( 'a' => 0, 'b' => array( 'c' => 0, 'd' => 1 ) );
$newValues = array( 'a' => 1, 'b' => array( 'c' => 10, 'd' => 1 ), 'e' => 42 );
 
$differ = new MapDiffer();
 
$diffOps = $differ->doDiff( $oldValues, $newValues );
 
// This is the result
$diffOps = array(
    'a' => DiffOpChange( 0, 1 ),
    'b' => Diff( array( 'c' => new DiffOpChange( 0, 10 ) ) ),
    'e' => DiffOpAdd( 42 )
);
Patcher
$oldValues = array( 0, 1, 2, 42, 9001, 'foobar' );
$diff = new Diff( array(
    'a' => DiffOpChange( 0, 1 ),
    'b' => Diff( array( 'c' => new DiffOpChange( 0, 10 ) ) ),
    'e' => DiffOpAdd( 42 )
) );
 
$patcher = new ListPatcher();
 
$newValues = $patcher->patch( $oldValues, $diff );
 
// This is the result
$diffOps = array( 0, 0, 23, 'foobar', 1, 2 );
$oldValues = array( 'a' => 0, 'b' => array( 'c' => 0, 'd' => 1 ) );
$diff = new Diff( array(
    'a' => DiffOpChange( 0, 1 ),
    'b' => Diff( array( 'c' => new DiffOpChange( 0, 10 ) ) ),
    'e' => DiffOpAdd( 42 )
) );
 
$differ = new MapPatcher();
 
$newValues = $patcher->patch( $oldValues, $diff );
 
// This is the result
$newValues = array( 'a' => 1, 'b' => array( 'c' => 10, 'd' => 1 ), 'e' => 42 );

Version[edit]

This is a copy of the release notes file on Git, which might be more up to date than this page.

Version 0.6[edit]

2013-05-08

Compatibility changes
  • The tests can now run independently of MediaWiki
  • The tests now require PHPUnit 3.7 or later
Additions
  • Added phpunit.php runner in the tests directory
  • Added Diff\Comparer\ValueComparer interface with CallbackComparer and StrictComparer implementations
  • Added MapPatcher::setValueComparer to facilitate patching maps containing objects
  • Added PHPUnit configuration file using the new tests/bootstrap.php
Removals
  • GenericArrayObject has been removed from this package. Diff derives from ArrayObject rather than GenericArrayObject. Its interface has not changed expect for the points below.
  • The getObjectType method in Diff (previously defined in GenericArrayObject) is now private rather than public.
  • Adding a non-DiffOp element to a Diff will now result in an InvalidArgumentException rather than a MWException.
  • Removed Diff\Exception

Version 0.5[edit]

2013-02-26

Additions
  • Added DiffOpFactory
  • Added DiffOp::toArray
  • Added CallbackListDiffer
  • Added MapDiffer::setComparisonCallback
Deprecations
  • Hard deprecated ListDiff, MapDiff and IDiff
Removals
  • Removed Diff::getApplicableDiff

Version 0.4[edit]

2013-01-08

Additions
  • Split off diffing code from MapDiff and ListDiff to dedicated Differ classes
  • Added dedicated Patcher classes, which are used for the getApplicableDiff functionality
Deprecations
  • Deprecated ListDiff:newFromArrays and MapDiff::newFromArrays
  • Deprecated ListDiff::newEmpty and MapDiff::newEmpty
  • Deprecated Diff::getApplicableDiff
  • Soft deprecated DiffOp interface in favour of DiffOp
  • Soft deprecated IDiff interface in favour of Diff
  • Soft deprecated MapDiff and ListDiff in favour of Diff
Removals
  • Removed parentKey functionality from Diff
  • Removed constructor from Diff interface
  • Removed Diff::newEmpty

Version 0.3[edit]

2012-11-21

  • Improved entry point and setup code. Diff.php is now the main entry point for both MW extension and standalone library
  • ListDiffs with only add operations can now be applied on top of bases that do not have their key
  • Added IDiff::removeEmptyOperations
  • Improved type hinting
  • Improved test coverage
    • Added constructor tests for MapDiff and ListDiff
    • Added extra tests for Diff and MapDiff
    • Test coverage is now 100%
  • Removed static method from IDiff interface since this is not allowed in strict mode

Version 0.2[edit]

2012-11-01

  • Fixed tests to work with PHP 5.4 and above
  • Added translations
  • Added some profiling calls

Version 0.1[edit]

2012-9-25

Initial release with these features:

  • Classes to represent diffs or collections of diff operations: Diff, MapDiff, ListDiff
  • Classes to represent diff operations: Diff, MapDiff, ListDiff, DiffOpAdd, DiffOpChange, DiffOpRemove
  • Methods to compute list and maps diffs
  • Support for recursive diffs of arbitrary depth
  • Works as MediaWiki extension or as standalone library

Internationalization[edit]

Diff is fully internationalized. Translation of Diff messages is done through translatewiki.net. The translation for this extension can be found here. To add language values or change existing ones, you should create an account on translatewiki.net, then request permission from the administrators to translate a certain language or languages on this page (this is a very simple process). Once you have permission for a given language, you can log in and add or edit whatever messages you want to in that language.

Authors[edit]

Diff has been written by Jeroen De Dauw as Wikimedia Germany employee for the Wikidata project.

Test coverage[edit]

Diff has better unit test coverage then any other MediaWiki extension [citation needed].

Diffcoverage.png

See also[edit]

External links[edit]