diff --git a/src/Composer/Json/JsonManipulator.php b/src/Composer/Json/JsonManipulator.php index 7099b7ffd..901d40cc0 100644 --- a/src/Composer/Json/JsonManipulator.php +++ b/src/Composer/Json/JsonManipulator.php @@ -92,8 +92,7 @@ class JsonManipulator if (true === $sortPackages) { $requirements = json_decode($links, true); - - ksort($requirements); + $this->sortPackages($requirements); $links = $this->format($requirements); } @@ -102,6 +101,40 @@ class JsonManipulator return true; } + /** + * Sorts packages by importance (platform packages first, then PHP dependencies) and alphabetically. + * + * @link https://getcomposer.org/doc/02-libraries.md#platform-packages + * + * @param array $packages + */ + private function sortPackages(array &$packages = array()) + { + $prefix = function ($requirement) { + return preg_replace( + array( + '/^php$/', + '/^hhvm$/', + '/^ext-\w+$/', + '/^lib-\w+$/', + '/^.+$/', + ), + array( + '0-$0', + '1-$0', + '2-$0', + '3-$0', + '4-$0', + ), + $requirement + ); + }; + + uksort($packages, function ($a, $b) use ($prefix) { + return strcmp($prefix($a), $prefix($b)); + }); + } + public function addRepository($name, $config) { return $this->addSubNode('repositories', $name, $config); diff --git a/tests/Composer/Test/Json/JsonManipulatorTest.php b/tests/Composer/Test/Json/JsonManipulatorTest.php index a2054e719..b56f4bc0d 100644 --- a/tests/Composer/Test/Json/JsonManipulatorTest.php +++ b/tests/Composer/Test/Json/JsonManipulatorTest.php @@ -332,6 +332,34 @@ class JsonManipulatorTest extends \PHPUnit_Framework_TestCase } ' ), + array( + '{ + "require": { + "foo": "baz", + "ext-mcrypt": "*", + "ext-gd": "*", + "lib-foo": "*", + "hhvm": "*", + "php": ">=5.5" + } +}', + 'require', + 'igorw/retry', + '*', + true, + '{ + "require": { + "php": ">=5.5", + "hhvm": "*", + "ext-gd": "*", + "ext-mcrypt": "*", + "lib-foo": "*", + "foo": "baz", + "igorw/retry": "*" + } +} +', + ), ); }