Repository: cakephp/chronos (php)

Issue:
2.4.x: b/c break in Cake\Chronos\Date::create()
Updating Chronos to version 2.4.x introduces following b/c break:

Calling `Cake\Chronos\Date::create()` without any arguments results in an `ArgumentCountError`.

`ArgumentCountError: Too few arguments to function Cake\Chronos\ChronosDate::create(), 0 passed in [...] and exactly 3 expected in /var/www/html/vendor/cakephp/chronos/src/ChronosDate.php:154`

Before version 2.4.0 `Date::create()` was inherited from the `FactoryTrait` with all arguments optional. Now the trait's function is overridden by `ChronosDate`'s own implementation where parameters differ.

Pull request:
Restore Date::create() compatibility with no params
Restore the historical behavior of create() that uses the current day by default.

Fixes #434

Patch:
diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
index 509adb3..71d6787 100644
--- a/phpstan-baseline.neon
+++ b/phpstan-baseline.neon
@@ -21,22 +21,7 @@ parameters:
 			path: src/Chronos.php
 
 		-
-			message: "#^Parameter \\#1 \\$year of static method Cake\\\\Chronos\\\\ChronosDate\\:\\:create\\(\\) expects int, null given\\.$#"
-			count: 1
-			path: src/ChronosDate.php
-
-		-
-			message: "#^Parameter \\#2 \\$month of static method Cake\\\\Chronos\\\\ChronosDate\\:\\:create\\(\\) expects int, null given\\.$#"
-			count: 1
-			path: src/ChronosDate.php
-
-		-
-			message: "#^Parameter \\#3 \\$day of static method Cake\\\\Chronos\\\\ChronosDate\\:\\:create\\(\\) expects int, null given\\.$#"
-			count: 1
-			path: src/ChronosDate.php
-
-		-
-			message: "#^Static method Cake\\\\Chronos\\\\ChronosDate\\:\\:create\\(\\) invoked with 8 parameters, 3 required\\.$#"
+			message: "#^Static method Cake\\\\Chronos\\\\ChronosDate\\:\\:create\\(\\) invoked with 8 parameters, 0-3 required\\.$#"
 			count: 2
 			path: src/ChronosDate.php
 
diff --git a/src/ChronosDate.php b/src/ChronosDate.php
index f22474d..41d168b 100644
--- a/src/ChronosDate.php
+++ b/src/ChronosDate.php
@@ -146,13 +146,18 @@ class ChronosDate extends DateTimeImmutable implements ChronosInterface
     /**
      * Create an instance from a specific date.
      *
-     * @param int $year The year to create an instance with.
-     * @param int $month The month to create an instance with.
-     * @param int $day The day to create an instance with.
+     * @param ?int $year The year to create an instance with.
+     * @param ?int $month The month to create an instance with.
+     * @param ?int $day The day to create an instance with.
      * @return static
      */
-    public static function create(int $year, int $month, int $day)
+    public static function create(?int $year = null, ?int $month = null, ?int $day = null)
     {
+        $now = static::today();
+        $year = $year ?? (int)$now->format('Y');
+        $month = $month ?? $now->format('m');
+        $day = $day ?? $now->format('d');
+
         $instance = static::createFromFormat(
             'Y-m-d',
             sprintf('%s-%s-%s', 0, $month, $day)


Test patch:
diff --git a/tests/TestCase/Date/ConstructTest.php b/tests/TestCase/Date/ConstructTest.php
index 042b5b2..fb817eb 100644
--- a/tests/TestCase/Date/ConstructTest.php
+++ b/tests/TestCase/Date/ConstructTest.php
@@ -294,6 +294,26 @@ class ConstructTest extends TestCase
         $class::setTestNow(null);
     }
 
+    /**
+     * @dataProvider dateClassProvider
+     */
+    public function testCreateWithTestNowNoParams($class)
+    {
+        $class::setTestNow($class::create(2001, 1, 1));
+        $date = $class::create();
+        $this->assertDate($date, 2001, 1, 1);
+    }
+
+    /**
+     * @dataProvider dateClassProvider
+     */
+    public function testCreateWithSomeParams($class)
+    {
+        $now = $class::today();
+        $date = $class::create(2022, 1);
+        $this->assertDate($date, 2022, 1, (int)$now->format('d'));
+    }
+
     /**
      * @dataProvider dateClassProvider
      */