Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
25 / 25
94.44% covered (success)
94.44%
34 / 36
72.73% covered (warning)
72.73%
16 / 22
66.67% covered (warning)
66.67%
4 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
Integer
100.00% covered (success)
100.00%
25 / 25
94.44% covered (success)
94.44%
34 / 36
72.73% covered (warning)
72.73%
16 / 22
100.00% covered (success)
100.00%
6 / 6
22.86
100.00% covered (success)
100.00%
1 / 1
 coerce
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
7 / 7
80.00% covered (warning)
80.00%
4 / 5
100.00% covered (success)
100.00%
1 / 1
4.13
 coerceStrict
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 toInteger
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
5 / 5
75.00% covered (warning)
75.00%
3 / 4
100.00% covered (success)
100.00%
1 / 1
3.14
 invalid
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 parseInteger
100.00% covered (success)
100.00%
4 / 4
88.89% covered (warning)
88.89%
8 / 9
60.00% covered (warning)
60.00%
3 / 5
100.00% covered (success)
100.00%
1 / 1
3.58
 isEmpty
100.00% covered (success)
100.00%
1 / 1
87.50% covered (warning)
87.50%
7 / 8
50.00% covered (danger)
50.00%
2 / 4
100.00% covered (success)
100.00%
1 / 1
4.12
1<?php
2
3declare(strict_types=1);
4
5namespace Celemas\Sire\Coercer;
6
7use Celemas\Sire\Coercion;
8use Celemas\Sire\CoercionMode;
9use Celemas\Sire\Contract;
10use Celemas\Sire\Failure;
11use Override;
12
13/** @api */
14final class Integer implements Contract\Coercer
15{
16    public string $message {
17        get => '{label} must be a whole number';
18    }
19
20    #[Override]
21    public function coerce(mixed $pristine, CoercionMode $mode): Contract\Coercion
22    {
23        if ($mode === CoercionMode::Strict) {
24            return self::coerceStrict($pristine);
25        }
26
27        $value = self::toInteger($pristine);
28
29        if ($value === null && $pristine !== null) {
30            return self::invalid($pristine);
31        }
32
33        return new Coercion($value, $pristine, empty: $value === null);
34    }
35
36    private static function coerceStrict(mixed $pristine): Coercion
37    {
38        if ($pristine === null) {
39            return new Coercion(null, null, empty: true);
40        }
41
42        return is_int($pristine)
43            ? new Coercion($pristine, $pristine)
44            : self::invalid($pristine);
45    }
46
47    private static function toInteger(mixed $value): ?int
48    {
49        if ($value === null || is_int($value)) {
50            return $value;
51        }
52
53        return self::parseInteger($value);
54    }
55
56    private static function invalid(mixed $pristine): Coercion
57    {
58        return new Coercion(
59            $pristine,
60            $pristine,
61            Failure::invalid(),
62            empty: self::isEmpty($pristine),
63        );
64    }
65
66    private static function parseInteger(mixed $value): ?int
67    {
68        if (!is_string($value)) {
69            return null;
70        }
71
72        $parsed = filter_var(trim($value), FILTER_VALIDATE_INT);
73
74        return $parsed === false ? null : $parsed;
75    }
76
77    private static function isEmpty(mixed $value): bool
78    {
79        return $value === null || is_string($value) && trim($value) === '';
80    }
81}