Extension:Diff
Diff Release status: stable |
|
---|---|
![]() |
|
Description | Structured data diff library |
Author(s) | Jeroen De Dauw |
Last version | 0.3 (2012-11-21) |
MediaWiki | 1.16.0 or higher |
PHP | 5.3 or above |
Database changes | no |
License | GNU GPL v2+ |
Download |
readme release notes |
Bugs: list open list all report |
Diff is a small diff library for structured data. It can be used as stand alone in any PHP application or as MediaWiki extension that can then be used by other extensions.
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 |
[edit] Requirements
Diff requires:
- PHP 5.3 or above
- (If used as MediaWiki extension: MediaWiki 1.16 or later)
[edit] Download
You can download the extension directly from the MediaWiki source code repository (browse code). You can get:
- One of the extensions tags (click the tag number and then "snapshot"). Tags tend to be stable.
- A snapshot of the latest code. This might be unstable.
- 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
The last change to the extension was:
- Localisation updates from http://translatewiki.net.
- Localisation updates from http://translatewiki.net.
- — Fri, 11 Jan 2013 20:32:36 +0000
[edit] Installation
[edit] As MediaWiki extension
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" );
[edit] As standalone library
Include Diff/Diff.standalone.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.
[edit] Usage
Note: This section describes version 0.4 and later. Version 0.3 and earlier do not contain differs or patchers.
The Diff library can be subdevided into 3 components.
[edit] DiffOp
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.
[edit] Differ
Often you need to construct a diff between to 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
.
[edit] Patcher
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
[edit] Examples
- 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 );
[edit] Version
This is a copy of the release notes file on Git, which might be more up to date than this page.
[edit] Version 0.4
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
[edit] Version 0.3
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
[edit] Version 0.2
2012-11-01
- Fixed tests to work with PHP 5.4 and above
- Added translations
- Added some profiling calls
[edit] Version 0.1
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
[edit] Internationalization
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.
[edit] Authors
Diff has been written by Jeroen De Dauw as Wikimedia Germany employee for the Wikidata project.
[edit] Test coverage
Diff has better unit test coverage then any other MediaWiki extension [citation needed].