Skip to content

Commit da9c7ea

Browse files
committed
Add library
1 parent cd2b7d0 commit da9c7ea

File tree

10 files changed

+293
-2
lines changed

10 files changed

+293
-2
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.idea/
2+
/vendor/
3+
/composer.lock

.travis-ci.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
language: php
2+
3+
matrix:
4+
include:
5+
- php: 5.6
6+
- php: hhvm
7+
- php: 7.0
8+
- php: 7.1
9+
- php: nightly
10+
allow_failures:
11+
- php: nightly
12+
fast_finish: true
13+
14+
before_install:
15+
16+
install:
17+
- composer install
18+
19+
script:
20+
- vendor/bin/phpunit tests

README.md

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,20 @@
1-
# php-sorting
2-
A sorting library for PHP
1+
Sorting Module
2+
==============
3+
4+
Implementation of a generic sorting system with an interface definition compatible
5+
to the [Comparable RFC](https://wiki.php.net/rfc/comparable).
6+
7+
## Usage
8+
9+
You have two possible options. Depending on your use case you can implement the
10+
`Sorting\Comparable` interface or use a comparator.
11+
12+
```php
13+
<?php
14+
15+
// with a comparable
16+
$orderedList = $sortManager->sortComparable($unorderedListOfComparable);
17+
18+
// or with a comparator
19+
$orderedList = $sortManager->sortWithComparator($comparator, $unorderedList);
20+
```

composer.json

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"name": "1blankz7/php-sorting",
3+
"description": "A sorting library for PHP",
4+
"keywords": ["array", "sorting"],
5+
"homepage": "https://github.com/1blankz7/php-sorting",
6+
"type": "library",
7+
"license": "MIT",
8+
"authors": [
9+
{
10+
"name": "Christian Blank",
11+
"email": "1blankz7@googlemail.com"
12+
}
13+
],
14+
"require-dev": {
15+
"phpunit/phpunit": "^5.7"
16+
},
17+
"autoload": {
18+
"psr-4": {
19+
"Sorting\\": [
20+
"src"
21+
],
22+
"Sorting\\Test\\": [
23+
"tests"
24+
]
25+
}
26+
}
27+
}

src/Comparable.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
namespace Sorting;
4+
5+
use Sorting\Exception\InvalidComparisonException;
6+
7+
/**
8+
* Interface for the natural ordering of objects.
9+
*
10+
* @package Sorting
11+
*/
12+
interface Comparable {
13+
14+
/**
15+
* Compares the current object to the passed $other.
16+
*
17+
* Returns 0 if they are semantically equal, 1 if the other object
18+
* is less than the current one, or -1 if its more than the current one.
19+
*
20+
* @param mixed $other
21+
*
22+
* @return int
23+
* @throws InvalidComparisonException
24+
*/
25+
public function compareTo($other);
26+
}

src/ComparatorInterface.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace Sorting;
4+
5+
/**
6+
* Interface ComparatorInterface
7+
*
8+
* @package Sorting
9+
*/
10+
interface ComparatorInterface
11+
{
12+
/**
13+
* @param mixed $a
14+
* @param mixed $b
15+
*
16+
* @return int
17+
*/
18+
public function compare($a, $b);
19+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace Sorting\Exception;
4+
5+
use \Exception;
6+
7+
/**
8+
* Exception should be thrown if a given value or object cannot be compared to
9+
* another value or object.
10+
*
11+
* @package Sorting\Exception
12+
*/
13+
class InvalidComparisonException extends Exception
14+
{
15+
16+
}

src/SortManager.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
namespace Sorting;
4+
5+
/**
6+
* Class SortManager
7+
*
8+
* @package Sorting
9+
*/
10+
class SortManager implements SortManagerInterface
11+
{
12+
/**
13+
* @inheritdoc
14+
*/
15+
public function sortWithComparator(ComparatorInterface $comparator, array $list)
16+
{
17+
usort($list, [$comparator, 'compare']);
18+
19+
return $list;
20+
}
21+
22+
/**
23+
* @inheritdoc
24+
*/
25+
public function sortComparable(array $list)
26+
{
27+
usort(
28+
$list,
29+
function(Comparable $a, Comparable $b) {
30+
return $a->compareTo($b);
31+
}
32+
);
33+
34+
return $list;
35+
}
36+
}

src/SortManagerInterface.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
namespace Sorting;
4+
5+
/**
6+
* A sort manager handles user defined sorting of objects or value types. Make sure
7+
* that the objects or the values you want to sort have a total ordering, otherwise
8+
* the result of the methods is not specified.
9+
*
10+
* @package Sorting
11+
*/
12+
interface SortManagerInterface
13+
{
14+
/**
15+
* Sort a list of values or objects by a given comparator.
16+
*
17+
* @param ComparatorInterface $comparator
18+
* @param array $list a possible unsorted list
19+
*
20+
* @return array the sorted list
21+
*/
22+
public function sortWithComparator(ComparatorInterface $comparator, array $list);
23+
24+
25+
/**
26+
* Sort the list of objects by their natural order.
27+
*
28+
* @param Comparable[] $list
29+
*
30+
* @return array the sorted list
31+
*/
32+
public function sortComparable(array $list);
33+
}

tests/Unit/SortManagerTest.php

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?php
2+
3+
namespace Sorting\Test\Unit;
4+
5+
use Prophecy\Argument;
6+
use Prophecy\Prophecy\ObjectProphecy;
7+
use Sorting\Comparable;
8+
use Sorting\ComparatorInterface;
9+
use Sorting\SortManager;
10+
use Sorting\SortManagerInterface;
11+
12+
/**
13+
* Class SortManagerTest
14+
*
15+
* @package Sorting
16+
*/
17+
class SortManagerTest extends \PHPUnit_Framework_TestCase
18+
{
19+
/**
20+
* @var SortManagerInterface
21+
*/
22+
private $sortManager;
23+
24+
/**
25+
*
26+
*/
27+
protected function setUp()
28+
{
29+
parent::setUp();
30+
$this->sortManager = new SortManager();
31+
}
32+
33+
/**
34+
* @test
35+
*/
36+
public function itShouldReturnAnEmptyListIfAnEmptyListAndAComparatorIsGiven()
37+
{
38+
$comparator = $this->getComparator();
39+
40+
$actual = $this->sortManager->sortWithComparator($comparator->reveal(), []);
41+
42+
$this->assertSame([], $actual);
43+
}
44+
45+
/**
46+
* @test
47+
*/
48+
public function itShouldCallTheCompareMethodOnTheComparatorWithTwoValues()
49+
{
50+
$comparator = $this->getComparator();
51+
$comparator->compare(Argument::any(), Argument::any())->willReturn(-1)->shouldBeCalled();
52+
53+
$this->sortManager->sortWithComparator($comparator->reveal(), [1, 2]);
54+
}
55+
56+
/**
57+
* @test
58+
*/
59+
public function itShouldReturnAnEmptyListIfAnEmptyListOfComparablesIsGiven()
60+
{
61+
$actual = $this->sortManager->sortComparable([]);
62+
63+
$this->assertSame([], $actual);
64+
}
65+
66+
/**
67+
* @test
68+
*/
69+
public function itShouldCallCompareToOnOneComparable()
70+
{
71+
$comparable1 = $this->getComparable();
72+
$comparable2 = $this->getComparable();
73+
$comparable1->compareTo($comparable2->reveal())->willReturn(1)->shouldBeCalled();
74+
75+
$this->sortManager->sortComparable([$comparable1->reveal(), $comparable2->reveal()]);
76+
}
77+
78+
/**
79+
* @return ObjectProphecy
80+
*/
81+
private function getComparator()
82+
{
83+
return $this->prophesize(ComparatorInterface::class);
84+
}
85+
86+
/**
87+
* @return ObjectProphecy
88+
*/
89+
private function getComparable()
90+
{
91+
return $this->prophesize(Comparable::class);
92+
}
93+
}

0 commit comments

Comments
 (0)