Skip to content

Commit 47aebd6

Browse files
bug: #196 Introduce a custom DatePeriodFilter that safely copies DatePeriod objects without modifying their readonly properties.
1 parent 3a6b9a4 commit 47aebd6

File tree

4 files changed

+109
-0
lines changed

4 files changed

+109
-0
lines changed

Diff for: src/DeepCopy/DeepCopy.php

+3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use ArrayObject;
66
use DateInterval;
7+
use DatePeriod;
78
use DateTimeInterface;
89
use DateTimeZone;
910
use DeepCopy\Exception\CloneException;
@@ -12,6 +13,7 @@
1213
use DeepCopy\Matcher\Matcher;
1314
use DeepCopy\Reflection\ReflectionHelper;
1415
use DeepCopy\TypeFilter\Date\DateIntervalFilter;
16+
use DeepCopy\TypeFilter\Date\DatePeriodFilter;
1517
use DeepCopy\TypeFilter\Spl\ArrayObjectFilter;
1618
use DeepCopy\TypeFilter\Spl\SplDoublyLinkedListFilter;
1719
use DeepCopy\TypeFilter\TypeFilter;
@@ -64,6 +66,7 @@ public function __construct($useCloneMethod = false)
6466

6567
$this->addTypeFilter(new ArrayObjectFilter($this), new TypeMatcher(ArrayObject::class));
6668
$this->addTypeFilter(new DateIntervalFilter(), new TypeMatcher(DateInterval::class));
69+
$this->addTypeFilter(new DatePeriodFilter(), new TypeMatcher(DatePeriod::class));
6770
$this->addTypeFilter(new SplDoublyLinkedListFilter($this), new TypeMatcher(SplDoublyLinkedList::class));
6871
}
6972

Diff for: src/DeepCopy/TypeFilter/Date/DatePeriodFilter.php

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
namespace DeepCopy\TypeFilter\Date;
4+
5+
use DatePeriod;
6+
use DeepCopy\TypeFilter\TypeFilter;
7+
8+
/**
9+
* @final
10+
*/
11+
class DatePeriodFilter implements TypeFilter
12+
{
13+
/**
14+
* {@inheritdoc}
15+
*
16+
* @param DatePeriod $element
17+
*
18+
* @see http://news.php.net/php.bugs/205076
19+
*/
20+
public function apply($element)
21+
{
22+
$options = 0;
23+
if (PHP_VERSION_ID >= 80200 && $element->include_end_date) {
24+
$options |= DatePeriod::INCLUDE_END_DATE;
25+
}
26+
if (!$element->include_start_date) {
27+
$options |= DatePeriod::EXCLUDE_START_DATE;
28+
}
29+
30+
if ($element->getEndDate()) {
31+
return new DatePeriod($element->getStartDate(), $element->getDateInterval(), $element->getEndDate(), $options);
32+
}
33+
34+
return new DatePeriod($element->getStartDate(), $element->getDateInterval(), $element->getRecurrences(), $options);
35+
}
36+
}

Diff for: tests/DeepCopyTest/DeepCopyTest.php

+3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use ArrayObject;
66
use DateInterval;
7+
use DatePeriod;
78
use DateTime;
89
use DateTimeImmutable;
910
use DateTimeZone;
@@ -158,13 +159,15 @@ public function test_it_can_copy_an_object_with_a_date_object_property()
158159
$object->d2 = new DateTimeImmutable();
159160
$object->dtz = new DateTimeZone('UTC');
160161
$object->di = new DateInterval('P2D');
162+
$object->dp = new DatePeriod(new DateTime(), new DateInterval('P2D'), 3);
161163

162164
$copy = deep_copy($object);
163165

164166
$this->assertEqualButNotSame($object->d1, $copy->d1);
165167
$this->assertEqualButNotSame($object->d2, $copy->d2);
166168
$this->assertEqualButNotSame($object->dtz, $copy->dtz);
167169
$this->assertEqualButNotSame($object->di, $copy->di);
170+
$this->assertEqualButNotSame($object->dp, $copy->dp);
168171
}
169172

170173
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace DeepCopyTest\TypeFilter\Date;
4+
5+
use DateInterval;
6+
use DatePeriod;
7+
use DateTime;
8+
use DeepCopy\TypeFilter\Date\DateIntervalFilter;
9+
use DeepCopy\TypeFilter\Date\DatePeriodFilter;
10+
use PHPUnit\Framework\TestCase;
11+
12+
/**
13+
* @covers \DeepCopy\TypeFilter\Date\DatePeriodFilter
14+
*/
15+
class DatePeriodFilterTest extends TestCase
16+
{
17+
public function test_it_deep_copies_a_DatePeriod()
18+
{
19+
$object = new DatePeriod(new DateTime(), new DateInterval('P2D'), 3);
20+
21+
$filter = new DatePeriodFilter();
22+
23+
$copy = $filter->apply($object);
24+
25+
$this->assertEquals($object, $copy);
26+
$this->assertNotSame($object, $copy);
27+
}
28+
29+
public function test_it_deep_copies_a_DatePeriod_with_exclude_start_date()
30+
{
31+
$object = new DatePeriod(new DateTime(), new DateInterval('P2D'), 3, DatePeriod::EXCLUDE_START_DATE);
32+
33+
$filter = new DatePeriodFilter();
34+
35+
$copy = $filter->apply($object);
36+
37+
$this->assertEquals($object, $copy);
38+
$this->assertNotSame($object, $copy);
39+
}
40+
41+
/**
42+
* @requires PHP 8.2
43+
*/
44+
public function test_it_deep_copies_a_DatePeriod_with_include_end_date()
45+
{
46+
$object = new DatePeriod(new DateTime(), new DateInterval('P2D'), 3, DatePeriod::INCLUDE_END_DATE);
47+
48+
$filter = new DatePeriodFilter();
49+
50+
$copy = $filter->apply($object);
51+
52+
$this->assertEquals($object, $copy);
53+
$this->assertNotSame($object, $copy);
54+
}
55+
56+
public function test_it_deep_copies_a_DatePeriod_with_end_date()
57+
{
58+
$object = new DatePeriod(new DateTime(), new DateInterval('P2D'), new DateTime('+2 days'));
59+
60+
$filter = new DatePeriodFilter();
61+
62+
$copy = $filter->apply($object);
63+
64+
$this->assertEquals($object, $copy);
65+
$this->assertNotSame($object, $copy);
66+
}
67+
}

0 commit comments

Comments
 (0)