blob: d9989749800e8e48ae7961e72046db7a8aa4ea93 [file] [log] [blame]
Matthias Andreas Benkard7b2a3a12021-08-16 10:57:25 +02001<?php
2
3/**
4 * This file is part of the Carbon package.
5 *
6 * (c) Brian Nesbitt <brian@nesbot.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11namespace Carbon\Traits;
12
13use Closure;
14use DateTimeImmutable;
15
16trait Test
17{
18 ///////////////////////////////////////////////////////////////////
19 ///////////////////////// TESTING AIDS ////////////////////////////
20 ///////////////////////////////////////////////////////////////////
21
22 /**
23 * A test Carbon instance to be returned when now instances are created.
24 *
25 * @var static
26 */
27 protected static $testNow;
28
29 /**
30 * Set a Carbon instance (real or mock) to be returned when a "now"
31 * instance is created. The provided instance will be returned
32 * specifically under the following conditions:
33 * - A call to the static now() method, ex. Carbon::now()
34 * - When a null (or blank string) is passed to the constructor or parse(), ex. new Carbon(null)
35 * - When the string "now" is passed to the constructor or parse(), ex. new Carbon('now')
36 * - When a string containing the desired time is passed to Carbon::parse().
37 *
38 * Note the timezone parameter was left out of the examples above and
39 * has no affect as the mock value will be returned regardless of its value.
40 *
41 * To clear the test instance call this method using the default
42 * parameter of null.
43 *
44 * /!\ Use this method for unit tests only.
45 *
46 * @param Closure|static|string|false|null $testNow real or mock Carbon instance
47 */
48 public static function setTestNow($testNow = null)
49 {
50 if ($testNow === false) {
51 $testNow = null;
52 }
53
54 static::$testNow = \is_string($testNow) ? static::parse($testNow) : $testNow;
55 }
56
57 /**
58 * Temporarily sets a static date to be used within the callback.
59 * Using setTestNow to set the date, executing the callback, then
60 * clearing the test instance.
61 *
62 * /!\ Use this method for unit tests only.
63 *
64 * @param Closure|static|string|false|null $testNow real or mock Carbon instance
65 * @param Closure|null $callback
66 *
67 * @return mixed
68 */
69 public static function withTestNow($testNow = null, $callback = null)
70 {
71 static::setTestNow($testNow);
72 $result = $callback();
73 static::setTestNow();
74
75 return $result;
76 }
77
78 /**
79 * Get the Carbon instance (real or mock) to be returned when a "now"
80 * instance is created.
81 *
82 * @return Closure|static the current instance used for testing
83 */
84 public static function getTestNow()
85 {
86 return static::$testNow;
87 }
88
89 /**
90 * Determine if there is a valid test instance set. A valid test instance
91 * is anything that is not null.
92 *
93 * @return bool true if there is a test instance, otherwise false
94 */
95 public static function hasTestNow()
96 {
97 return static::getTestNow() !== null;
98 }
99
100 /**
101 * Return the given timezone and set it to the test instance if not null.
102 * If null, get the timezone from the test instance and return it.
103 *
104 * @param string|\DateTimeZone $tz
105 * @param \Carbon\CarbonInterface $testInstance
106 *
107 * @return string|\DateTimeZone
108 */
109 protected static function handleMockTimezone($tz, &$testInstance)
110 {
111 //shift the time according to the given time zone
112 if ($tz !== null && $tz !== static::getMockedTestNow($tz)->getTimezone()) {
113 $testInstance = $testInstance->setTimezone($tz);
114
115 return $tz;
116 }
117
118 return $testInstance->getTimezone();
119 }
120
121 /**
122 * Get the mocked date passed in setTestNow() and if it's a Closure, execute it.
123 *
124 * @param string|\DateTimeZone $tz
125 *
126 * @return \Carbon\CarbonImmutable|\Carbon\Carbon|null
127 */
128 protected static function getMockedTestNow($tz)
129 {
130 $testNow = static::getTestNow();
131
132 if ($testNow instanceof Closure) {
133 $realNow = new DateTimeImmutable('now');
134 $testNow = $testNow(static::parse(
135 $realNow->format('Y-m-d H:i:s.u'),
136 $tz ?: $realNow->getTimezone()
137 ));
138 }
139 /* @var \Carbon\CarbonImmutable|\Carbon\Carbon|null $testNow */
140
141 return $testNow;
142 }
143
144 protected static function mockConstructorParameters(&$time, &$tz)
145 {
146 /** @var \Carbon\CarbonImmutable|\Carbon\Carbon $testInstance */
147 $testInstance = clone static::getMockedTestNow($tz);
148
149 $tz = static::handleMockTimezone($tz, $testInstance);
150
151 if (static::hasRelativeKeywords($time)) {
152 $testInstance = $testInstance->modify($time);
153 }
154
155 $time = $testInstance instanceof self ? $testInstance->rawFormat(static::MOCK_DATETIME_FORMAT) : $testInstance->format(static::MOCK_DATETIME_FORMAT);
156 }
157}