Test Failed
Push — feature/add-more-data-types ( c872db...5c357c )
by Peter
02:58
created

FakeCar::validateVin()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 3
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 7
ccs 2
cts 2
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 26
        parent::__construct($generator);
19
        $this->setDataProvider(new FakeCarDataProvider);
20 26
    }
21 26
22
    public function setDataProvider(FakeCarDataProviderInterface $dataProvider): void
23
    {
24 26
        $this->dataProvider = $dataProvider;
25
    }
26 26
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 2
     */
87
    public function vehicleRegistration(string $regex = '[A-Z]{3}-[0-9]{3}'): string
88 2
    {
89 2
        //TODO: Set format based on locale
90 2
        return static::regexify($regex);
91 2
    }
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
        /** @phpstan-ignore method.notFound */
175
        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

175
        return $this->dataProvider->/** @scrutinizer ignore-call */ getVehicleEngineTorque();
Loading history...
176
    }
177
178
    /**
179
     * Get engine torque without a unit
180
     *
181
     * @throws Exception
182
     */
183
    public function vehicleEngineTorqueValue(): string
184
    {
185
        //TODO: Remove check and add to data provider interface in next major version
186
        $this->isSupported(__FUNCTION__);
187
        /** @phpstan-ignore method.notFound */
188
        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

188
        return $this->dataProvider->/** @scrutinizer ignore-call */ getVehicleEngineTorqueValue();
Loading history...
189
    }
190
191
    /**
192
     * Get engine power (horsepower or kilowatts)
193
     *
194 2
     * @throws Exception
195
     */
196 2
    public function vehicleEnginePower(): string
197
    {
198
        //TODO: Remove check and add to data provider interface in next major version
199
        $this->isSupported(__FUNCTION__);
200
        /** @phpstan-ignore method.notFound */
201
        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

201
        return $this->dataProvider->/** @scrutinizer ignore-call */ getVehicleEnginePower();
Loading history...
202
    }
203
204
    /**
205
     * Get engine power without a unit
206
     *
207
     * @throws Exception
208
     */
209
    public function vehicleEnginePowerValue(): string
210
    {
211
        //TODO: Remove check and add to data provider interface in next major version
212
        $this->isSupported(__FUNCTION__);
213
        /** @phpstan-ignore method.notFound */
214
        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

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