Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?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
 */
11
 
12
namespace Carbon\Traits;
13
 
14
use Carbon\CarbonInterface;
15
use Carbon\CarbonTimeZone;
16
use Closure;
17
use DateTimeImmutable;
18
use DateTimeInterface;
19
use InvalidArgumentException;
20
use Throwable;
21
 
22
trait Test
23
{
24
    ///////////////////////////////////////////////////////////////////
25
    ///////////////////////// TESTING AIDS ////////////////////////////
26
    ///////////////////////////////////////////////////////////////////
27
 
28
    /**
29
     * A test Carbon instance to be returned when now instances are created.
30
     *
31
     * @var Closure|static|null
32
     */
33
    protected static $testNow;
34
 
35
    /**
36
     * The timezone to resto to when clearing the time mock.
37
     *
38
     * @var string|null
39
     */
40
    protected static $testDefaultTimezone;
41
 
42
    /**
43
     * Set a Carbon instance (real or mock) to be returned when a "now"
44
     * instance is created.  The provided instance will be returned
45
     * specifically under the following conditions:
46
     *   - A call to the static now() method, ex. Carbon::now()
47
     *   - When a null (or blank string) is passed to the constructor or parse(), ex. new Carbon(null)
48
     *   - When the string "now" is passed to the constructor or parse(), ex. new Carbon('now')
49
     *   - When a string containing the desired time is passed to Carbon::parse().
50
     *
51
     * Note the timezone parameter was left out of the examples above and
52
     * has no affect as the mock value will be returned regardless of its value.
53
     *
54
     * Only the moment is mocked with setTestNow(), the timezone will still be the one passed
55
     * as parameter of date_default_timezone_get() as a fallback (see setTestNowAndTimezone()).
56
     *
57
     * To clear the test instance call this method using the default
58
     * parameter of null.
59
     *
60
     * /!\ Use this method for unit tests only.
61
     *
62
     * @param DateTimeInterface|Closure|static|string|false|null $testNow real or mock Carbon instance
63
     */
64
    public static function setTestNow($testNow = null)
65
    {
66
        static::$testNow = $testNow instanceof self || $testNow instanceof Closure
67
            ? $testNow
68
            : static::make($testNow);
69
    }
70
 
71
    /**
72
     * Set a Carbon instance (real or mock) to be returned when a "now"
73
     * instance is created.  The provided instance will be returned
74
     * specifically under the following conditions:
75
     *   - A call to the static now() method, ex. Carbon::now()
76
     *   - When a null (or blank string) is passed to the constructor or parse(), ex. new Carbon(null)
77
     *   - When the string "now" is passed to the constructor or parse(), ex. new Carbon('now')
78
     *   - When a string containing the desired time is passed to Carbon::parse().
79
     *
80
     * It will also align default timezone (e.g. call date_default_timezone_set()) with
81
     * the second argument or if null, with the timezone of the given date object.
82
     *
83
     * To clear the test instance call this method using the default
84
     * parameter of null.
85
     *
86
     * /!\ Use this method for unit tests only.
87
     *
88
     * @param DateTimeInterface|Closure|static|string|false|null $testNow real or mock Carbon instance
89
     */
90
    public static function setTestNowAndTimezone($testNow = null, $tz = null)
91
    {
92
        if ($testNow) {
93
            self::$testDefaultTimezone = self::$testDefaultTimezone ?? date_default_timezone_get();
94
        }
95
 
96
        $useDateInstanceTimezone = $testNow instanceof DateTimeInterface;
97
 
98
        if ($useDateInstanceTimezone) {
99
            self::setDefaultTimezone($testNow->getTimezone()->getName(), $testNow);
100
        }
101
 
102
        static::setTestNow($testNow);
103
 
104
        if (!$useDateInstanceTimezone) {
105
            $now = static::getMockedTestNow(\func_num_args() === 1 ? null : $tz);
106
            $tzName = $now ? $now->tzName : null;
107
            self::setDefaultTimezone($tzName ?? self::$testDefaultTimezone ?? 'UTC', $now);
108
        }
109
 
110
        if (!$testNow) {
111
            self::$testDefaultTimezone = null;
112
        }
113
    }
114
 
115
    /**
116
     * Temporarily sets a static date to be used within the callback.
117
     * Using setTestNow to set the date, executing the callback, then
118
     * clearing the test instance.
119
     *
120
     * /!\ Use this method for unit tests only.
121
     *
122
     * @param DateTimeInterface|Closure|static|string|false|null $testNow  real or mock Carbon instance
123
     * @param Closure|null                                       $callback
124
     *
125
     * @return mixed
126
     */
127
    public static function withTestNow($testNow = null, $callback = null)
128
    {
129
        static::setTestNow($testNow);
130
 
131
        try {
132
            $result = $callback();
133
        } finally {
134
            static::setTestNow();
135
        }
136
 
137
        return $result;
138
    }
139
 
140
    /**
141
     * Get the Carbon instance (real or mock) to be returned when a "now"
142
     * instance is created.
143
     *
144
     * @return Closure|static the current instance used for testing
145
     */
146
    public static function getTestNow()
147
    {
148
        return static::$testNow;
149
    }
150
 
151
    /**
152
     * Determine if there is a valid test instance set. A valid test instance
153
     * is anything that is not null.
154
     *
155
     * @return bool true if there is a test instance, otherwise false
156
     */
157
    public static function hasTestNow()
158
    {
159
        return static::getTestNow() !== null;
160
    }
161
 
162
    /**
163
     * Get the mocked date passed in setTestNow() and if it's a Closure, execute it.
164
     *
165
     * @param string|\DateTimeZone $tz
166
     *
167
     * @return \Carbon\CarbonImmutable|\Carbon\Carbon|null
168
     */
169
    protected static function getMockedTestNow($tz)
170
    {
171
        $testNow = static::getTestNow();
172
 
173
        if ($testNow instanceof Closure) {
174
            $realNow = new DateTimeImmutable('now');
175
            $testNow = $testNow(static::parse(
176
                $realNow->format('Y-m-d H:i:s.u'),
177
                $tz ?: $realNow->getTimezone()
178
            ));
179
        }
180
        /* @var \Carbon\CarbonImmutable|\Carbon\Carbon|null $testNow */
181
 
182
        return $testNow instanceof CarbonInterface
183
            ? $testNow->avoidMutation()->tz($tz)
184
            : $testNow;
185
    }
186
 
187
    protected static function mockConstructorParameters(&$time, $tz)
188
    {
189
        /** @var \Carbon\CarbonImmutable|\Carbon\Carbon $testInstance */
190
        $testInstance = clone static::getMockedTestNow($tz);
191
 
192
        if (static::hasRelativeKeywords($time)) {
193
            $testInstance = $testInstance->modify($time);
194
        }
195
 
196
        $time = $testInstance instanceof self
197
            ? $testInstance->rawFormat(static::MOCK_DATETIME_FORMAT)
198
            : $testInstance->format(static::MOCK_DATETIME_FORMAT);
199
    }
200
 
201
    private static function setDefaultTimezone($timezone, DateTimeInterface $date = null)
202
    {
203
        $previous = null;
204
        $success = false;
205
 
206
        try {
207
            $success = date_default_timezone_set($timezone);
208
        } catch (Throwable $exception) {
209
            $previous = $exception;
210
        }
211
 
212
        if (!$success) {
213
            $suggestion = @CarbonTimeZone::create($timezone)->toRegionName($date);
214
 
215
            throw new InvalidArgumentException(
216
                "Timezone ID '$timezone' is invalid".
217
                ($suggestion && $suggestion !== $timezone ? ", did you mean '$suggestion'?" : '.')."\n".
218
                "It must be one of the IDs from DateTimeZone::listIdentifiers(),\n".
219
                'For the record, hours/minutes offset are relevant only for a particular moment, '.
220
                'but not as a default timezone.',
221
                0,
222
                $previous
223
            );
224
        }
225
    }
226
}