• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

orchestral / sidekick / 20704986116

05 Jan 2026 04:20AM UTC coverage: 91.549% (-0.4%) from 91.943%
20704986116

push

github

web-flow
[1.2.x] Move `is_symlink()` and `join_paths()` to `Orchestra\Sidekick\Filesystem` namespace (#60)

* [1.2.x] Move `is_symlink()` and `join_paths()` to
`Orchestra\Sidekick\Filesystem` namespace

Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com>

* wip

Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com>

---------

Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com>

9 of 12 new or added lines in 2 files covered. (75.0%)

195 of 213 relevant lines covered (91.55%)

6.48 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.57
/src/functions.php
1
<?php
2

3
namespace Orchestra\Sidekick;
4

5
use BackedEnum;
6
use Closure;
7
use Composer\InstalledVersions;
8
use Composer\Semver\VersionParser;
9
use Illuminate\Contracts\Foundation\Application as ApplicationContract;
10
use Illuminate\Foundation\Application;
11
use Illuminate\Support\Arr;
12
use OutOfBoundsException;
13
use PHPUnit\Runner\Version;
14
use RuntimeException;
15
use UnitEnum;
16

17
if (! \function_exists('Orchestra\Sidekick\enum_name')) {
18
    /**
19
     * Get the proper name from enum.
20
     *
21
     * @api
22
     *
23
     * @throws \RuntimeException
24
     */
25
    function enum_name(BackedEnum|UnitEnum $enum): string
26
    {
27
        return mb_convert_case(str_replace('_', ' ', $enum->name), MB_CASE_TITLE, 'UTF-8');
5✔
28
    }
29
}
30

31
if (! \function_exists('Orchestra\Sidekick\enum_value')) {
32
    /**
33
     * Get the proper name from enum.
34
     *
35
     * @api
36
     *
37
     * @template TValue
38
     * @template TDefault
39
     *
40
     * @param  TValue  $value
41
     * @param  TDefault|callable(TValue): TDefault  $default
42
     * @return ($value is empty ? TDefault : mixed)
43
     *
44
     * @throws \RuntimeException
45
     */
46
    function enum_value(mixed $value, mixed $default = null): mixed
47
    {
48
        return match (true) {
49
            $value instanceof BackedEnum => $value->value,
20✔
50
            $value instanceof UnitEnum => $value->name,
16✔
51

52
            default => $value ?? value($default),
20✔
53
        };
54
    }
55
}
56

57
if (! \function_exists('Orchestra\Sidekick\after_resolving')) {
58
    /**
59
     * Register after resolving callback.
60
     *
61
     * @api
62
     *
63
     * @template TLaravel of \Illuminate\Contracts\Foundation\Application
64
     *
65
     * @param  TLaravel  $app
66
     * @param  class-string|string  $name
67
     * @param  (\Closure(object, TLaravel):(mixed))|null  $callback
68
     */
69
    function after_resolving(ApplicationContract $app, string $name, ?Closure $callback = null): void
70
    {
71
        $app->afterResolving($name, $callback);
2✔
72

73
        if ($app->resolved($name)) {
2✔
74
            value($callback, $app->make($name), $app);
1✔
75
        }
76
    }
77
}
78

79
if (! \function_exists('Orchestra\Sidekick\join_paths')) {
80

81
    /**
82
     * Join the given paths together.
83
     *
84
     * @api
85
     *
86
     * @deprecated
87
     */
88
    function join_paths(?string $basePath, string ...$paths): string
89
    {
90
        return Filesystem\join_paths($basePath, ...$paths);
20✔
91
    }
92
}
93

94
if (! \function_exists('Orchestra\Sidekick\once')) {
95
    /**
96
     * Run callback only once.
97
     *
98
     * @api
99
     *
100
     * @param  mixed  $callback
101
     * @return \Closure():mixed
102
     */
103
    function once($callback): Closure
104
    {
105
        $response = new UndefinedValue;
24✔
106

107
        return function () use ($callback, &$response) {
24✔
108
            if ($response instanceof UndefinedValue) {
24✔
109
                $response = value($callback) ?? null;
24✔
110
            }
111

112
            return $response;
24✔
113
        };
24✔
114
    }
115
}
116

117
if (! \function_exists('Orchestra\Sidekick\is_safe_callable')) {
118
    /**
119
     * Determine if the value is a callable and not a string matching an available function name.
120
     *
121
     * @api
122
     */
123
    function is_safe_callable(mixed $value): bool
124
    {
125
        if ($value instanceof Closure) {
6✔
126
            return true;
1✔
127
        }
128

129
        if (! \is_callable($value)) {
5✔
130
            return false;
2✔
131
        }
132

133
        if (\is_array($value)) {
3✔
134
            return \count($value) === 2 && array_is_list($value) && method_exists(...$value);
1✔
135
        }
136

137
        return ! \is_string($value);
2✔
138
    }
139
}
140

141
if (! \function_exists('Orchestra\Sidekick\is_symlink')) {
142
    /**
143
     * Determine if the path is a symlink for both Unix and Windows environments.
144
     *
145
     * @api
146
     *
147
     * @deprecated
148
     */
149
    function is_symlink(string $path): bool
150
    {
NEW
151
        return Filesystem\is_symlink($path);
×
152
    }
153
}
154

155
if (! \function_exists('Orchestra\Sidekick\is_testbench_cli')) {
156
    /**
157
     * Determine if command executed via Testbench CLI.
158
     *
159
     * @api
160
     */
161
    function is_testbench_cli(?bool $dusk = null): bool
162
    {
163
        $usingTestbench = \defined('TESTBENCH_CORE');
1✔
164
        $usingTestbenchDusk = \defined('TESTBENCH_DUSK');
1✔
165

166
        return match ($dusk) {
1✔
167
            false => $usingTestbench === true && $usingTestbenchDusk === false,
×
168
            true => $usingTestbench === true && $usingTestbenchDusk === true,
1✔
169
            default => $usingTestbench === true,
1✔
170
        };
1✔
171
    }
172
}
173

174
if (! \function_exists('Orchestra\Sidekick\transform_relative_path')) {
175
    /**
176
     * Transform relative path.
177
     *
178
     * @api
179
     */
180
    function transform_relative_path(string $path, string $workingPath): string
181
    {
182
        return str_starts_with($path, './')
1✔
183
            ? rtrim($workingPath, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.mb_substr($path, 2)
1✔
184
            : $path;
1✔
185
    }
186
}
187

188
if (! \function_exists('Orchestra\Sidekick\working_path')) {
189
    /**
190
     * Get the working path.
191
     *
192
     * @api
193
     *
194
     * @no-named-arguments
195
     *
196
     * @param  array<int, string|null>|string  ...$path
197
     */
198
    function working_path(array|string $path = ''): string
199
    {
200
        return is_testbench_cli() && \function_exists('Orchestra\Testbench\package_path')
1✔
201
            ? \Orchestra\Testbench\package_path($path)
×
202
            : base_path(join_paths(...Arr::wrap(\func_num_args() > 1 ? \func_get_args() : $path)));
1✔
203
    }
204
}
205

206
if (! \function_exists('Orchestra\Sidekick\laravel_normalize_version')) {
207
    /**
208
     * Laravel normalize version.
209
     *
210
     * @api
211
     *
212
     * @throws \OutOfBoundsException
213
     */
214
    function laravel_normalize_version(): string
215
    {
216
        if (! class_exists(Application::class)) {
20✔
217
            throw new OutOfBoundsException('Unable to verify "laravel/framework" version');
×
218
        }
219

220
        /** @var string $version */
221
        $version = transform(
20✔
222
            Application::VERSION,
20✔
223
            fn (string $version) => match ($version) {
20✔
224
                '13.x-dev' => '13.0.0',
20✔
225
                default => $version,
20✔
226
            }
227
        );
20✔
228

229
        return (new VersionParser)->normalize($version);
20✔
230
    }
231
}
232

233
if (! \function_exists('Orchestra\Sidekick\phpunit_normalize_version')) {
234
    /**
235
     * PHPUnit normalize version.
236
     *
237
     * @api
238
     *
239
     * @throws \OutOfBoundsException
240
     */
241
    function phpunit_normalize_version(): string
242
    {
243
        if (! class_exists(Version::class)) {
1✔
244
            throw new OutOfBoundsException('Unable to verify "phpunit/phpunit" version');
×
245
        }
246

247
        /** @var string $version */
248
        $version = transform(
1✔
249
            Version::id(),
1✔
250
            fn (string $version) => match (true) {
1✔
251
                str_starts_with($version, '13.0-') => '13.0.0',
1✔
252
                default => $version,
1✔
253
            }
254
        );
1✔
255

256
        return (new VersionParser)->normalize($version);
1✔
257
    }
258
}
259

260
if (! \function_exists('Orchestra\Sidekick\laravel_version_compare')) {
261
    /**
262
     * Laravel version compare.
263
     *
264
     * @api
265
     *
266
     * @template TOperator of string|null
267
     *
268
     * @param  TOperator  $operator
269
     * @return (TOperator is null ? int : bool)
270
     *
271
     * @throws \RuntimeException
272
     *
273
     * @codeCoverageIgnore
274
     */
275
    function laravel_version_compare(string $version, ?string $operator = null): int|bool
276
    {
277
        if (! class_exists(Application::class)) {
278
            return package_version_compare('laravel/framework', $version, $operator);
279
        }
280

281
        $laravel = laravel_normalize_version();
282
        $version = (new VersionParser)->normalize($version);
283

284
        if (\is_null($operator)) {
285
            return version_compare($laravel, $version);
286
        }
287

288
        return version_compare($laravel, $version, $operator);
289
    }
290
}
291

292
if (! \function_exists('Orchestra\Sidekick\package_version_compare')) {
293
    /**
294
     * Package version compare.
295
     *
296
     * @api
297
     *
298
     * @template TOperator of string|null
299
     *
300
     * @phpstan-param  TOperator  $operator
301
     *
302
     * @phpstan-return (TOperator is null ? int : bool)
303
     *
304
     * @throws \OutOfBoundsException
305
     * @throws \RuntimeException
306
     *
307
     * @codeCoverageIgnore
308
     */
309
    function package_version_compare(string $package, string $version, ?string $operator = null): int|bool
310
    {
311
        $prettyVersion = InstalledVersions::getPrettyVersion($package);
312

313
        if (\is_null($prettyVersion)) {
314
            throw new RuntimeException(\sprintf('Unable to compare "%s" version', $package));
315
        }
316

317
        $versionParser = new VersionParser;
318

319
        $package = $versionParser->normalize($prettyVersion);
320
        $version = $versionParser->normalize($version);
321

322
        if (\is_null($operator)) {
323
            return version_compare($package, $version);
324
        }
325

326
        return version_compare($package, $version, $operator);
327
    }
328
}
329

330
if (! \function_exists('Orchestra\Sidekick\phpunit_version_compare')) {
331
    /**
332
     * PHPUnit version compare.
333
     *
334
     * @api
335
     *
336
     * @template TOperator of string|null
337
     *
338
     * @param  TOperator  $operator
339
     * @return (TOperator is null ? int : bool)
340
     *
341
     * @throws \OutOfBoundsException
342
     * @throws \RuntimeException
343
     *
344
     * @codeCoverageIgnore
345
     */
346
    function phpunit_version_compare(string $version, ?string $operator = null): int|bool
347
    {
348
        if (! class_exists(Version::class)) {
349
            return package_version_compare('phpunit/phpunit', $version, $operator);
350
        }
351

352
        $phpunit = phpunit_normalize_version();
353
        $version = (new VersionParser)->normalize($version);
354

355
        if (\is_null($operator)) {
356
            return version_compare($phpunit, $version);
357
        }
358

359
        return version_compare($phpunit, $version, $operator);
360
    }
361
}
362

363
if (! \function_exists('Orchestra\Sidekick\php_binary')) {
364
    /**
365
     * Determine the PHP Binary.
366
     *
367
     * @api
368
     *
369
     * @codeCoverageIgnore
370
     */
371
    function php_binary(): string
372
    {
373
        return (new PhpExecutableFinder)->find(false) ?: 'php';
374
    }
375
}
376

377
if (! \function_exists('Orchestra\Sidekick\windows_os')) {
378
    /**
379
     * Determine whether the current environment is Windows-based.
380
     *
381
     * @api
382
     *
383
     * @codeCoverageIgnore
384
     */
385
    function windows_os(): bool
386
    {
387
        return PHP_OS_FAMILY === 'Windows';
388
    }
389
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc