Skip to content
This repository was archived by the owner on Dec 6, 2022. It is now read-only.

Commit e65ae5a

Browse files
TimeToogoElliot Levin
authored and
Elliot Levin
committed
Change identity hash to hash instances of \DateTimeInterface by class and timestamp hence treating it as a value type throughout the PINQ API
1 parent e528d48 commit e65ae5a

15 files changed

+279
-24
lines changed

CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ dev
44
- Fix bug when attempting to parse function with a magic scope parameter type hint (eg `function (self $param) { ... }`.
55
- Implement `Analysis\TolerantExpressionAnalyser` which will convert analysis exceptions into the *mixed* type.
66
- Add `Providers\DSL\Compilation\Parameters\ParameterCollection::contains` to check whether the collection contains a parameter.
7-
- Add `Providers\DSL\Compilation\Parameters\ParameterCollection::remove` to remove a previously added parameter.\
7+
- Add `Providers\DSL\Compilation\Parameters\ParameterCollection::remove` to remove a previously added parameter.
88
- Introduce `Analysis\INativeType::TYPE_NUMERIC` acting as a union type for `Analysis\INativeType::TYPE_INT` and `Analysis\INativeType::TYPE_DOUBLE`
9+
- Change identity hash to hash instances of `DateTimeInterface` by class and timestamp hence treating it as a value type throughout the PINQ API
910

1011
3.1.0 (29/3/15)
1112
===============

Source/Iterators/Common/Identity.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ public static function hash($value)
4545

4646
case 'o': //object
4747

48-
return 'o' . spl_object_hash($value);
48+
return $value instanceof \DateTimeInterface || $value instanceof \DateTime
49+
? 'dt:' . get_class($value) . ':' . $value->getTimestamp()
50+
: 'o' . spl_object_hash($value);
4951

5052
case 'a': //array
5153

Tests/Helpers/ExtendedDateTime.php

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
namespace Pinq\Tests\Helpers;
4+
5+
/**
6+
*
7+
* @author Elliot Levin <[email protected]>
8+
*/
9+
class ExtendedDateTime extends \DateTime
10+
{
11+
12+
}

Tests/Integration/Collection/GroupJoinApplyTest.php

+29
Original file line numberDiff line numberDiff line change
@@ -149,4 +149,33 @@ public function testThatApplyGroupJoinWithDefaultValueOperatedCorrectly(\Pinq\IC
149149
'10:1,3,5,7,9,11,13,15,17,19',
150150
]);
151151
}
152+
153+
/**
154+
* @dataProvider oneToTen
155+
*/
156+
public function testThatOnEqualityWillNotMatchNullsAndUseDefault(\Pinq\ICollection $collection, array $data)
157+
{
158+
$collection
159+
->groupJoin($collection)
160+
->onEquality(
161+
function ($i) { return $i % 2 === 0 ? $i : null; },
162+
function ($i) { return $i % 2 === 0 ? $i : null; })
163+
->withDefault('<DEFAULT>')
164+
->apply(function (&$outer, \Pinq\ITraversable $innerGroup) {
165+
$outer .= ':' . $innerGroup->implode('-');
166+
});
167+
168+
$this->assertMatches($collection, [
169+
'1:<DEFAULT>',
170+
'2:2',
171+
'3:<DEFAULT>',
172+
'4:4',
173+
'5:<DEFAULT>',
174+
'6:6',
175+
'7:<DEFAULT>',
176+
'8:8',
177+
'9:<DEFAULT>',
178+
'10:10'
179+
]);
180+
}
152181
}

Tests/Integration/Collection/JoinApplyTest.php

+14-20
Original file line numberDiff line numberDiff line change
@@ -206,31 +206,25 @@ function ($i) { return $i % 2 === 0 ? $i : null; })
206206
}
207207

208208
/**
209-
* @dataProvider oneToTen
209+
* @dataProvider emptyData
210210
*/
211-
public function testThatOnEqualityWillNotMatchNullsAndUseDefault(\Pinq\ICollection $collection, array $data)
211+
public function testThatOnEqualityWillPassForValueWiseIdenticalDateTimes(\Pinq\ICollection $collection, array $data)
212212
{
213+
$dateTime = new \DateTime('2-1-2001');
214+
$anotherDateTime = new \DateTime('2-1-2000');
215+
$collection[] = $dateTime;
216+
$collection[] = $anotherDateTime;
217+
213218
$collection
214-
->groupJoin($collection)
215-
->onEquality(
216-
function ($i) { return $i % 2 === 0 ? $i : null; },
217-
function ($i) { return $i % 2 === 0 ? $i : null; })
218-
->withDefault('<DEFAULT>')
219-
->apply(function (&$outer, \Pinq\ITraversable $innerGroup) {
220-
$outer .= ':' . $innerGroup->implode('-');
219+
->join([$dateTime])
220+
->onEquality(function ($outer) { return $outer; }, function ($inner) { return $inner; })
221+
->apply(function (&$outer) {
222+
$outer = '<MATCHED>';
221223
});
222224

223-
$this->assertMatches($collection, [
224-
'1:<DEFAULT>',
225-
'2:2',
226-
'3:<DEFAULT>',
227-
'4:4',
228-
'5:<DEFAULT>',
229-
'6:6',
230-
'7:<DEFAULT>',
231-
'8:8',
232-
'9:<DEFAULT>',
233-
'10:10'
225+
$this->assertMatchesValues($collection, [
226+
'<MATCHED>',
227+
$anotherDateTime
234228
]);
235229
}
236230
}

Tests/Integration/Collection/RemoveTest.php

+16
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,20 @@ public function testThatRemoveWillRemovesIdenticalValuesFromCollectionAndPreserv
3333

3434
$this->assertMatchesValues($collection, $data);
3535
}
36+
37+
/**
38+
* @dataProvider dateTimes
39+
*/
40+
public function testRemovesDateTimeClassesByValueRatherThenReference(
41+
\Pinq\ICollection $collection,
42+
array $data
43+
) {
44+
$originalCount = $collection->count();
45+
$dateTime = $collection[2];
46+
47+
$collection->remove($dateTime);
48+
49+
$this->assertCount($originalCount - 1, $collection);
50+
$this->assertNotContains($dateTime, $collection);
51+
}
3652
}

Tests/Integration/Collection/SetIndexTest.php

+18-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public function testThatSettingAnIndexWillOverrideTheElementInTheCollection(\Pin
2424
}
2525

2626
/**
27-
* @dataProvider everything
27+
* @dataProvider emptyData
2828
*/
2929
public function testThatSetIndexWithNoKeyAppendsTheValueWithTheNextLargestIntGreaterThanOrEqualToZeroLikeAnArray(\Pinq\ICollection $collection, array $data)
3030
{
@@ -53,4 +53,21 @@ public function testThatSetIndexWithNoKeyAppendsTheValueWithTheNextLargestIntGre
5353

5454
$this->assertSame('boo', $collection[1]);
5555
}
56+
57+
/**
58+
* @dataProvider emptyData
59+
*/
60+
public function testThatDateTimeIndexesAreComparedByValue(\Pinq\ICollection $collection, array $data)
61+
{
62+
$dateTime = new \DateTime('2-1-2001');
63+
$anotherDateTime = new \DateTime('2-1-2000');
64+
65+
$collection[$dateTime] = 1;
66+
$collection[$anotherDateTime] = 2;
67+
$collection[clone $anotherDateTime] = 3;
68+
69+
$this->assertSame(1, $collection[$dateTime]);
70+
$this->assertSame(3, $collection[$anotherDateTime]);
71+
$this->assertSame(3, $collection[clone $anotherDateTime]);
72+
}
5673
}

Tests/Integration/Collection/UnsetIndexTest.php

+18
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,22 @@ public function testThatUnsetingAnIndexWillRemoveTheElementFromTheCollection(\Pi
2020

2121
$this->assertMatches($collection, $data);
2222
}
23+
24+
/**
25+
* @dataProvider emptyData
26+
*/
27+
public function testThatDateTimeIndexesAreComparedByValue(\Pinq\ICollection $collection, array $data)
28+
{
29+
$dateTime = new \DateTime('2-1-2001');
30+
$anotherDateTime = new \DateTime('2-1-2000');
31+
32+
$collection[$dateTime] = 1;
33+
$collection[$anotherDateTime] = 2;
34+
unset($collection[new \DateTime('2-1-2000')]);
35+
36+
$this->assertTrue(isset($collection[$dateTime]));
37+
$this->assertFalse(isset($collection[$anotherDateTime]));
38+
$this->assertFalse(isset($collection[clone $anotherDateTime]));
39+
$this->assertFalse(isset($collection[new \DateTime('2-1-2000')]));
40+
}
2341
}

Tests/Integration/DataTest.php

+13-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ public function everything()
2828
'oneToTenTwice',
2929
'assocOneToTen',
3030
'tenRandomStrings',
31-
'assocMixedValues'
31+
'assocMixedValues',
32+
'dateTimes'
3233
];
3334

3435
foreach ($dataProviders as $provider) {
@@ -106,6 +107,17 @@ public function assocTenRandomStrings()
106107
return $this->getImplementations(array_combine($this->randomStrings(10), $this->randomStrings(10)));
107108
}
108109

110+
public function dateTimes()
111+
{
112+
return $this->getImplementations(iterator_to_array(
113+
new \DatePeriod(
114+
new \DateTime('1-1-2000'),
115+
new \DateInterval('P4M'),
116+
new \DateTime('2-3-2004')
117+
)
118+
));
119+
}
120+
109121
private function randomStrings($amount)
110122
{
111123
$letters = 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890-!@#$%^&*()_';

Tests/Integration/Traversable/GetIndexTest.php

+22
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,26 @@ public function testThatIndexesSupportArrayKeys(\Pinq\ITraversable $traversable,
6161
'Should be using strict equality for arrays (order matters)');
6262
}
6363
}
64+
65+
/**
66+
* @dataProvider emptyData
67+
*/
68+
public function testThatDateTimeIndexesAreComparedByValueAndClass(\Pinq\ITraversable $traversable, array $data)
69+
{
70+
$dateTime = new \DateTime('2-1-2001');
71+
$anotherDateTime = new \DateTime('2-1-2000');
72+
73+
$traversable = $traversable
74+
->append([$dateTime, $anotherDateTime])
75+
->indexBy(function ($value) { return $value; })
76+
->select(function (\DateTime $dateTime) { return $dateTime->format('j-n-Y'); });
77+
78+
$this->assertSame('2-1-2001', $traversable[$dateTime]);
79+
$this->assertSame('2-1-2001', $traversable[clone $dateTime]);
80+
$this->assertSame('2-1-2001', $traversable[new \DateTime('2-1-2001')]);
81+
82+
if(class_exists('DateTimeImmutable', false)) {
83+
$this->assertNull($traversable[new \DateTimeImmutable('2-1-2001')]);
84+
}
85+
}
6486
}

Tests/Integration/Traversable/GroupByTest.php

+21
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
namespace Pinq\Tests\Integration\Traversable;
44

5+
use Pinq\ITraversable;
6+
57
class GroupByTest extends TraversableTest
68
{
79
protected function _testReturnsNewInstanceOfSameTypeWithSameScheme(\Pinq\ITraversable $traversable)
@@ -137,4 +139,23 @@ public function testThatGroupByMaintainsArrayReferences(\Pinq\ITraversable $trav
137139

138140
$this->assertSame($data, [[1], [2], [1, 2, 'foo' => 1], [3, 5, 'foo' => 3], [4, 2, 'foo' => 4]]);
139141
}
142+
143+
/**
144+
* @dataProvider emptyData
145+
*/
146+
public function testThatDateTimeAreGroupedByValue(\Pinq\ITraversable $traversable, array $data)
147+
{
148+
$traversable = $traversable
149+
->append([2000, 2000, 2001, 2000, 2002, 2000, 2001, 2000, 2002])
150+
->groupBy(function ($year) { return new \DateTime('1-1-' . $year); })
151+
->select(function (ITraversable $years, \DateTime $dateTime) {
152+
return [$dateTime->format('Y'), $years->count()];
153+
});
154+
155+
$this->assertMatchesValues($traversable, [
156+
['2000', 5],
157+
['2001', 2],
158+
['2002', 2],
159+
]);
160+
}
140161
}

Tests/Integration/Traversable/IssetIndexTest.php

+20
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
namespace Pinq\Tests\Integration\Traversable;
44

5+
use Pinq\Tests\Helpers\ExtendedDateTime;
6+
57
class IssetIndexTest extends TraversableTest
68
{
79
/**
@@ -27,4 +29,22 @@ public function testThatIssetOnInvalidIndexesReturnFalse(\Pinq\ITraversable $tra
2729

2830
$this->assertFalse(isset($traversable[$notAnIndex]));
2931
}
32+
33+
/**
34+
* @dataProvider emptyData
35+
*/
36+
public function testThatDateTimeIndexesAreComparedByValueAndClass(\Pinq\ITraversable $traversable, array $data)
37+
{
38+
$dateTime = new \DateTime('2-1-2001');
39+
$anotherDateTime = new \DateTime('2-1-2000');
40+
41+
$traversable = $traversable
42+
->append([$dateTime, $anotherDateTime])
43+
->indexBy(function ($value) { return $value; });
44+
45+
$this->assertTrue(isset($traversable[$dateTime]));
46+
$this->assertTrue(isset($traversable[clone $dateTime]));
47+
$this->assertTrue(isset($traversable[new \DateTime('2-1-2001')]));
48+
$this->assertFalse(isset($traversable[new ExtendedDateTime('2-1-2001')]));
49+
}
3050
}

Tests/Integration/Traversable/JoinTest.php

+21
Original file line numberDiff line numberDiff line change
@@ -346,4 +346,25 @@ function ($i) { return $i % 2 === 0 ? $i : null; })
346346
'10:10'
347347
]);
348348
}
349+
350+
/**
351+
* @dataProvider emptyData
352+
*/
353+
public function testThatOnEqualityWillPassForValueWiseIdenticalDateTimes(\Pinq\ITraversable $traversable, array $data)
354+
{
355+
$dateTime = new \DateTime('2-1-2001');
356+
$anotherDateTime = new \DateTime('2-1-2000');
357+
358+
$traversable = $traversable
359+
->append([$dateTime, $anotherDateTime])
360+
->join([$dateTime])
361+
->onEquality(function ($outer) { return $outer; }, function ($inner) { return $inner; })
362+
->to(function (\DateTime $outer) {
363+
return $outer->format('d-m-Y');
364+
});
365+
366+
$this->assertMatchesValues($traversable, [
367+
'02-01-2001',
368+
]);
369+
}
349370
}

Tests/Integration/Traversable/UnionTest.php

+38
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
namespace Pinq\Tests\Integration\Traversable;
44

5+
use Pinq\Tests\Helpers\ExtendedDateTime;
6+
57
class UnionTest extends TraversableTest
68
{
79
protected function _testReturnsNewInstanceOfSameTypeWithSameScheme(\Pinq\ITraversable $traversable)
@@ -63,4 +65,40 @@ public function testThatUnionMaintainsReferences(\Pinq\ITraversable $traversable
6365

6466
$this->assertSame('a-b-c-d-e-f-', implode('', $data));
6567
}
68+
69+
/**
70+
* @dataProvider emptyData
71+
*/
72+
public function testThatUnionWillMatchDateTimeByTimestampAndClass(\Pinq\ITraversable $traversable, array $data)
73+
{
74+
$traversable = $traversable
75+
->append([
76+
new \DateTime('2-1-2001'),
77+
new \DateTime('2-1-2001'),
78+
new \DateTime('2-1-2001 00:00:01'),
79+
new \DateTime('1-1-2001'),
80+
new \DateTime('1-1-2001'),
81+
new \DateTime('3-1-2001'),
82+
new ExtendedDateTime('1-1-2001'),
83+
])
84+
->union([
85+
new \DateTime('4-1-2001'),
86+
new \DateTime('2-1-2001'),
87+
new ExtendedDateTime('1-1-2001'),
88+
new ExtendedDateTime('2-1-2001'),
89+
])
90+
->select(function (\DateTime $outer) {
91+
return get_class($outer) . ':' . $outer->format('d-m-Y H:i:s');
92+
});
93+
94+
$this->assertMatchesValues($traversable, [
95+
'DateTime:02-01-2001 00:00:00',
96+
'DateTime:02-01-2001 00:00:01',
97+
'DateTime:01-01-2001 00:00:00',
98+
'DateTime:03-01-2001 00:00:00',
99+
'Pinq\Tests\Helpers\ExtendedDateTime:01-01-2001 00:00:00',
100+
'DateTime:04-01-2001 00:00:00',
101+
'Pinq\Tests\Helpers\ExtendedDateTime:02-01-2001 00:00:00',
102+
]);
103+
}
66104
}

0 commit comments

Comments
 (0)