Skip to content

Commit

Permalink
Merge pull request #197 from michalananapps/copy-DatePeriod
Browse files Browse the repository at this point in the history
bug: #196 Introduce a custom DatePeriodFilter that safely copies DatePeriod objects without modifying their readonly properties.
  • Loading branch information
mnapoli authored Nov 8, 2024
2 parents 3a6b9a4 + bed190b commit 123267b
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/DeepCopy/DeepCopy.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use ArrayObject;
use DateInterval;
use DatePeriod;
use DateTimeInterface;
use DateTimeZone;
use DeepCopy\Exception\CloneException;
Expand All @@ -12,6 +13,7 @@
use DeepCopy\Matcher\Matcher;
use DeepCopy\Reflection\ReflectionHelper;
use DeepCopy\TypeFilter\Date\DateIntervalFilter;
use DeepCopy\TypeFilter\Date\DatePeriodFilter;
use DeepCopy\TypeFilter\Spl\ArrayObjectFilter;
use DeepCopy\TypeFilter\Spl\SplDoublyLinkedListFilter;
use DeepCopy\TypeFilter\TypeFilter;
Expand Down Expand Up @@ -64,6 +66,7 @@ public function __construct($useCloneMethod = false)

$this->addTypeFilter(new ArrayObjectFilter($this), new TypeMatcher(ArrayObject::class));
$this->addTypeFilter(new DateIntervalFilter(), new TypeMatcher(DateInterval::class));
$this->addTypeFilter(new DatePeriodFilter(), new TypeMatcher(DatePeriod::class));
$this->addTypeFilter(new SplDoublyLinkedListFilter($this), new TypeMatcher(SplDoublyLinkedList::class));
}

Expand Down
42 changes: 42 additions & 0 deletions src/DeepCopy/TypeFilter/Date/DatePeriodFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace DeepCopy\TypeFilter\Date;

use DatePeriod;
use DeepCopy\TypeFilter\TypeFilter;

/**
* @final
*/
class DatePeriodFilter implements TypeFilter
{
/**
* {@inheritdoc}
*
* @param DatePeriod $element
*
* @see http://news.php.net/php.bugs/205076
*/
public function apply($element)
{
$options = 0;
if (PHP_VERSION_ID >= 80200 && $element->include_end_date) {
$options |= DatePeriod::INCLUDE_END_DATE;
}
if (!$element->include_start_date) {
$options |= DatePeriod::EXCLUDE_START_DATE;
}

if ($element->getEndDate()) {
return new DatePeriod($element->getStartDate(), $element->getDateInterval(), $element->getEndDate(), $options);
}

if (PHP_VERSION_ID >= 70217) {
$recurrences = $element->getRecurrences();
} else {
$recurrences = $element->recurrences - $element->include_start_date;
}

return new DatePeriod($element->getStartDate(), $element->getDateInterval(), $recurrences, $options);
}
}
3 changes: 3 additions & 0 deletions tests/DeepCopyTest/DeepCopyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use ArrayObject;
use DateInterval;
use DatePeriod;
use DateTime;
use DateTimeImmutable;
use DateTimeZone;
Expand Down Expand Up @@ -158,13 +159,15 @@ public function test_it_can_copy_an_object_with_a_date_object_property()
$object->d2 = new DateTimeImmutable();
$object->dtz = new DateTimeZone('UTC');
$object->di = new DateInterval('P2D');
$object->dp = new DatePeriod(new DateTime(), new DateInterval('P2D'), 3);

$copy = deep_copy($object);

$this->assertEqualButNotSame($object->d1, $copy->d1);
$this->assertEqualButNotSame($object->d2, $copy->d2);
$this->assertEqualButNotSame($object->dtz, $copy->dtz);
$this->assertEqualButNotSame($object->di, $copy->di);
$this->assertEqualButNotSame($object->dp, $copy->dp);
}

/**
Expand Down
67 changes: 67 additions & 0 deletions tests/DeepCopyTest/TypeFilter/Date/DatePeriodFilterTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php declare(strict_types=1);

namespace DeepCopyTest\TypeFilter\Date;

use DateInterval;
use DatePeriod;
use DateTime;
use DeepCopy\TypeFilter\Date\DateIntervalFilter;
use DeepCopy\TypeFilter\Date\DatePeriodFilter;
use PHPUnit\Framework\TestCase;

/**
* @covers \DeepCopy\TypeFilter\Date\DatePeriodFilter
*/
class DatePeriodFilterTest extends TestCase
{
public function test_it_deep_copies_a_DatePeriod()
{
$object = new DatePeriod(new DateTime(), new DateInterval('P2D'), 3);

$filter = new DatePeriodFilter();

$copy = $filter->apply($object);

$this->assertEquals($object, $copy);
$this->assertNotSame($object, $copy);
}

public function test_it_deep_copies_a_DatePeriod_with_exclude_start_date()
{
$object = new DatePeriod(new DateTime(), new DateInterval('P2D'), 3, DatePeriod::EXCLUDE_START_DATE);

$filter = new DatePeriodFilter();

$copy = $filter->apply($object);

$this->assertEquals($object, $copy);
$this->assertNotSame($object, $copy);
}

/**
* @requires PHP 8.2
*/
public function test_it_deep_copies_a_DatePeriod_with_include_end_date()
{
$object = new DatePeriod(new DateTime(), new DateInterval('P2D'), 3, DatePeriod::INCLUDE_END_DATE);

$filter = new DatePeriodFilter();

$copy = $filter->apply($object);

$this->assertEquals($object, $copy);
$this->assertNotSame($object, $copy);
}

public function test_it_deep_copies_a_DatePeriod_with_end_date()
{
$object = new DatePeriod(new DateTime(), new DateInterval('P2D'), new DateTime('+2 days'));

$filter = new DatePeriodFilter();

$copy = $filter->apply($object);

$this->assertEquals($object, $copy);
$this->assertNotSame($object, $copy);
}
}

0 comments on commit 123267b

Please sign in to comment.