Extension:Diff
|
Diff Release status: stable |
|
|---|---|
| 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].
See also[edit]
External links[edit]
| This extension is being used on one or more Wikimedia projects. This probably means that the extension is stable and works well enough to be used by such high-traffic websites. Look for this extension's name in Wikimedia's CommonSettings.php and InitialiseSettings.php configuration files to see where it's installed. A full list of the extensions installed on a particular wiki can be seen on the wiki's Special:Version page. |
