Test Failed
Push — main ( b30d66...68ae2b )
by Peter
15:45 queued 12:41
created

FakeCar::isSupported()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 2
eloc 4
c 1
b 1
f 0
nc 2
nop 1
dl 0
loc 9
ccs 4
cts 4
cp 1
crap 2
rs 10
1
<?php
2
3
namespace Faker\Provider;
4
5
use Exception;
6
use Faker\Generator;
7
8
class FakeCar extends \Faker\Provider\Base
9
{
10
    protected const EBCDIC = '0123456789.ABCDEFGH..JKLMN.P.R..STUVWXYZ';
11
12
    protected const MODEL_YEAR = 'ABCDEFGHJKLMNPRSTVWXY123456789';
13
14
    protected FakeCarDataProviderInterface $dataProvider;
15
16
    public function __construct(Generator $generator)
17
    {
18 19
        parent::__construct($generator);
19
        $this->setDataProvider(new FakeCarDataProvider);
20 19
    }
21 19
22
    public function setDataProvider(FakeCarDataProviderInterface $dataProvider): void
23
    {
24 19
        $this->dataProvider = $dataProvider;
25
    }
26 19
27
    /**
28
     * Get vehicle string with brand and model
29
     */
30
    public function vehicle(): string
31
    {
32
        $vehicleBrand = $this->vehicleBrand();
33
34 2
        return $vehicleBrand.' '.$this->vehicleModel($vehicleBrand);
35
    }
36 2
37
    /**
38 2
     * Get vehicle with brand and model as an array
39
     *
40
     * @return array{brand: string, model: string}
41
     */
42
    public function vehicleArray(): array
43
    {
44
        $vehicleBrand = $this->vehicleBrand();
45
46 3
        return [
47
            'brand' => $vehicleBrand,
48 3
            'model' => $this->vehicleModel($vehicleBrand),
49
        ];
50 3
    }
51 3
52 3
    /**
53 3
     * Get random vehicle brand
54
     */
55
    public function vehicleBrand(): string
56
    {
57
        return (string) $this->dataProvider->getVehicleBrand();
58
    }
59
60
    /**
61 6
     * Get random vehicle model
62
     *
63 6
     * @param  ?string  $brand  Get a random model from specific brand (optional)
64
     */
65
    public function vehicleModel(?string $brand = null): string
66
    {
67
        return $this->dataProvider->getVehicleModel($brand);
68
    }
69
70
    /**
71
     * Generate VIN
72
     *
73 5
     * @link https://en.wikipedia.org/wiki/Vehicle_identification_number
74
     */
75 5
    public function vin(int $year = 1980): string
76
    {
77
        $modelYear = self::encodeModelYear($year);
78
        $regex     = "([a-hj-npr-z0-9]{8})_{$modelYear}([a-hj-npr-z0-9]{7})";
79
        $vin       = static::regexify($regex);
80
81
        return str_replace('_', self::checkDigit($vin), $vin);
82
    }
83
84
    /**
85
     * Get vehicle registration number
86 1
     */
87
    public function vehicleRegistration(string $regex = '[A-Z]{3}-[0-9]{3}'): string
88 1
    {
89 1
        //TODO: Set format based on locale
90 1
        return static::regexify($regex);
91 1
    }
92
93
    /**
94
     * Get a vehicle type
95
     *
96
     * @throws Exception
97
     */
98
    public function vehicleType(): string
99
    {
100
        return (string) $this->dataProvider->getVehicleType();
101 1
    }
102
103
    /**
104 1
     * Get vehicle fuel type(s)
105
     *
106
     * @return string|array<string>
107
     */
108
    public function vehicleFuelType(int $count = 1): string|array
109
    {
110
        return $this->dataProvider->getVehicleFuelType($count);
111
    }
112
113 3
    /**
114
     * Get vehicle door count
115 3
     *
116
     * @throws Exception
117
     */
118
    public function vehicleDoorCount(): int
119
    {
120
        return $this->dataProvider->getVehicleDoorCount();
121
    }
122
123
    /**
124
     * Get vehicle door count
125 2
     *
126
     * @throws Exception
127 2
     */
128
    public function vehicleSeatCount(): int
129
    {
130
        return $this->dataProvider->getVehicleSeatCount();
131
    }
132
133
    /**
134
     * Get an array of random vehicle properties
135
     *
136 2
     * @return array<string>
137
     *
138 2
     * @throws Exception
139
     */
140
    public function vehicleProperties(int $count = 0): array
141
    {
142
        return $this->dataProvider->getVehicleProperties($count);
143
    }
144
145
    /**
146
     * Get random vehicle gearbox type
147 2
     *
148
     * @throws Exception
149 2
     */
150
    public function vehicleGearBoxType(): string
151
    {
152
        return $this->dataProvider->getVehicleGearBoxType();
153
    }
154
155
    /**
156
     * Get a random vehicle gearbox type without a unit
157
     *
158
     * @throws Exception
159
     */
160 2
    public function vehicleGearBoxTypeValue(): string
161
    {
162 2
        return $this->dataProvider->getVehicleGearBoxType();
163
    }
164
165
    /**
166
     * Get engine torque
167
     *
168
     * @throws Exception
169
     */
170
    public function vehicleEngineTorque(): string
171 1
    {
172
        //TODO: Remove check and add to data provider interface in next major version
173 1
        $this->isSupported(__FUNCTION__);
174
175
        /** @phpstan-ignore method.notFound */
176
        return $this->dataProvider->getVehicleEngineTorque();
0 ignored issues
show
Bug introduced by
The method getVehicleEngineTorque() does not exist on Faker\Provider\FakeCarDataProviderInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Faker\Provider\FakeCarDataProviderInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

176
        return $this->dataProvider->/** @scrutinizer ignore-call */ getVehicleEngineTorque();
Loading history...
177
    }
178
179
    /**
180
     * Get engine torque without a unit
181
     *
182
     * @throws Exception
183 1
     */
184
    public function vehicleEngineTorqueValue(): string
185 1
    {
186
        //TODO: Remove check and add to data provider interface in next major version
187
        $this->isSupported(__FUNCTION__);
188
189
        /** @phpstan-ignore method.notFound */
190
        return $this->dataProvider->getVehicleEngineTorqueValue();
0 ignored issues
show
Bug introduced by
The method getVehicleEngineTorqueValue() does not exist on Faker\Provider\FakeCarDataProviderInterface. It seems like you code against a sub-type of Faker\Provider\FakeCarDataProviderInterface such as Faker\Provider\FakeCarDataProvider. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

190
        return $this->dataProvider->/** @scrutinizer ignore-call */ getVehicleEngineTorqueValue();
Loading history...
191
    }
192
193
    /**
194 1
     * Get engine power (horsepower or kilowatts)
195
     *
196 1
     * @throws Exception
197
     */
198
    public function vehicleEnginePower(): string
199
    {
200
        //TODO: Remove check and add to data provider interface in next major version
201
        $this->isSupported(__FUNCTION__);
202
203
        /** @phpstan-ignore method.notFound */
204
        return $this->dataProvider->getVehicleEnginePower();
0 ignored issues
show
Bug introduced by
The method getVehicleEnginePower() does not exist on Faker\Provider\FakeCarDataProviderInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Faker\Provider\FakeCarDataProviderInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

204
        return $this->dataProvider->/** @scrutinizer ignore-call */ getVehicleEnginePower();
Loading history...
205 2
    }
206
207 2
    /**
208
     * Get engine power without a unit
209
     *
210
     * @throws Exception
211
     */
212
    public function vehicleEnginePowerValue(): string
213
    {
214
        //TODO: Remove check and add to data provider interface in next major version
215 3
        $this->isSupported(__FUNCTION__);
216
217 3
        /** @phpstan-ignore method.notFound */
218
        return $this->dataProvider->getVehicleEnginePowerValue();
0 ignored issues
show
Bug introduced by
The method getVehicleEnginePowerValue() does not exist on Faker\Provider\FakeCarDataProviderInterface. It seems like you code against a sub-type of Faker\Provider\FakeCarDataProviderInterface such as Faker\Provider\FakeCarDataProvider. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

218
        return $this->dataProvider->/** @scrutinizer ignore-call */ getVehicleEnginePowerValue();
Loading history...
219
    }
220
221
    public function isSupported(string $method): bool
222
    {
223
        $method = 'get'.ucfirst($method);
224
225 2
        if (method_exists($this->dataProvider, $method)) {
226
            return true;
227 2
        }
228 2
229 2
        throw new \RuntimeException('Method not supported be data provider. Please implement '.$method.'() in your data provider.');
230 2
    }
231 2
232 2
    /**
233
     * Model year encoding for VIN generation.
234 2
     *
235
     * @link: https://en.wikipedia.org/wiki/Vehicle_identification_number#Model_year_encoding
236
     */
237
    private static function encodeModelYear(int $modelYear = 1980): string
238
    {
239
        return substr(self::MODEL_YEAR, ($modelYear - 1980) % 30, 1);
240
    }
241
242 2
    /**php
243
     * @link: https://en.wikipedia.org/wiki/Vehicle_identification_number#Check-digit_calculation
244 2
     */
245 1
    private static function checkDigit(string $vin): string
246
    {
247
        $map     = '0123456789X';
248 2
        $weights = '8765432X098765432';
249
        $sum     = 0;
250
        for ($i = 0; $i < 17; $i++) {
251
            $sum += self::transliterate($vin[$i] ?? '')
252
                    * stripos($map, $weights[$i]);
253
        }
254
255
        return $map[$sum % 11];
256
    }
257
258
    private static function transliterate(string $character): int
259
    {
260
        return stripos(self::EBCDIC, $character) % 10;
261
    }
262
263
    public static function validateVin(string $vin): bool
264
    {
265
        if (strlen($vin) !== 17) {
266
            return false;
267
        }
268
269
        return self::checkDigit($vin) === $vin[8];
270
    }
271
}
272