Skip to content

Commit fe8f195

Browse files
committed
feat: faker support
1 parent c02ee7a commit fe8f195

24 files changed

Lines changed: 1107 additions & 150 deletions

src/Core/Fake/Faker.php

Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Constructo\Core\Fake;
6+
7+
use Constructo\Contract\Formatter;
8+
use Constructo\Contract\Testing\Faker as Contract;
9+
use Constructo\Core\Fake\Resolver\FromCollection;
10+
use Constructo\Core\Fake\Resolver\FromDefaultValue;
11+
use Constructo\Core\Fake\Resolver\FromDependency;
12+
use Constructo\Core\Fake\Resolver\FromEnum;
13+
use Constructo\Core\Fake\Resolver\FromPreset;
14+
use Constructo\Core\Fake\Resolver\FromTypeAttributes;
15+
use Constructo\Core\Fake\Resolver\FromTypeBuiltin;
16+
use Constructo\Core\Fake\Resolver\FromTypeDate;
17+
use Constructo\Support\Reflective\Engine;
18+
use Constructo\Support\Reflective\Factory\Target;
19+
use Constructo\Support\Reflective\Notation;
20+
use Constructo\Support\Set;
21+
use DateTime;
22+
use Faker\Factory;
23+
use Faker\Generator;
24+
use ReflectionException;
25+
use ReflectionParameter;
26+
27+
use function Constructo\Cast\stringify;
28+
use function getenv;
29+
30+
/**
31+
* @method string citySuffix()
32+
* @method string streetSuffix()
33+
* @method string buildingNumber()
34+
* @method string city()
35+
* @method string streetName()
36+
* @method string streetAddress()
37+
* @method string postcode()
38+
* @method string address()
39+
* @method string country()
40+
* @method float latitude($min = -90, $max = 90)
41+
* @method float longitude($min = -180, $max = 180)
42+
* @method float[] localCoordinates()
43+
* @method int randomDigitNotNull()
44+
* @method mixed passthrough($value)
45+
* @method string randomLetter()
46+
* @method string randomAscii()
47+
* @method array randomElements($array = ['a', 'b', 'c'], $count = 1, $allowDuplicates = false)
48+
* @method mixed randomElement($array = ['a', 'b', 'c'])
49+
* @method int|string|null randomKey($array = [])
50+
* @method array|string shuffle($arg = '')
51+
* @method array shuffleArray($array = [])
52+
* @method string shuffleString($string = '', $encoding = 'UTF-8')
53+
* @method string numerify($string = '###')
54+
* @method string lexify($string = '????')
55+
* @method string bothify($string = '## ??')
56+
* @method string asciify($string = '****')
57+
* @method string regexify($regex = '')
58+
* @method string toLower($string = '')
59+
* @method string toUpper($string = '')
60+
* @method int biasedNumberBetween($min = 0, $max = 100, $function = 'sqrt')
61+
* @method string hexColor()
62+
* @method string safeHexColor()
63+
* @method array rgbColorAsArray()
64+
* @method string rgbColor()
65+
* @method string rgbCssColor()
66+
* @method string rgbaCssColor()
67+
* @method string safeColorName()
68+
* @method string colorName()
69+
* @method string hslColor()
70+
* @method array hslColorAsArray()
71+
* @method string company()
72+
* @method string companySuffix()
73+
* @method string jobTitle()
74+
* @method int unixTime($max = 'now')
75+
* @method DateTime dateTime($max = 'now', $timezone = null)
76+
* @method DateTime dateTimeAD($max = 'now', $timezone = null)
77+
* @method string iso8601($max = 'now')
78+
* @method string date($format = 'Y-m-d', $max = 'now')
79+
* @method string time($format = 'H:i:s', $max = 'now')
80+
* @method DateTime dateTimeBetween($startDate = '-30 years', $endDate = 'now', $timezone = null)
81+
* @method DateTime dateTimeInInterval($date = '-30 years', $interval = '+5 days', $timezone = null)
82+
* @method DateTime dateTimeThisCentury($max = 'now', $timezone = null)
83+
* @method DateTime dateTimeThisDecade($max = 'now', $timezone = null)
84+
* @method DateTime dateTimeThisYear($max = 'now', $timezone = null)
85+
* @method DateTime dateTimeThisMonth($max = 'now', $timezone = null)
86+
* @method string amPm($max = 'now')
87+
* @method string dayOfMonth($max = 'now')
88+
* @method string dayOfWeek($max = 'now')
89+
* @method string month($max = 'now')
90+
* @method string monthName($max = 'now')
91+
* @method string year($max = 'now')
92+
* @method string century()
93+
* @method string timezone($countryCode = null)
94+
* @method void setDefaultTimezone($timezone = null)
95+
* @method string getDefaultTimezone()
96+
* @method string file($sourceDirectory = '/tmp', $targetDirectory = '/tmp', $fullPath = true)
97+
* @method string randomHtml($maxDepth = 4, $maxWidth = 4)
98+
* @method string imageUrl($width = 640, $height = 480, $category = null, $randomize = true, $word = null, $gray = false, string $format = 'png')
99+
* @method string image($dir = null, $width = 640, $height = 480, $category = null, $fullPath = true, $randomize = true, $word = null, $gray = false, string $format = 'png')
100+
* @method string email()
101+
* @method string safeEmail()
102+
* @method string freeEmail()
103+
* @method string companyEmail()
104+
* @method string freeEmailDomain()
105+
* @method string safeEmailDomain()
106+
* @method string userName()
107+
* @method string password($minLength = 6, $maxLength = 20)
108+
* @method string domainName()
109+
* @method string domainWord()
110+
* @method string tld()
111+
* @method string url()
112+
* @method string slug($nbWords = 6, $variableNbWords = true)
113+
* @method string ipv4()
114+
* @method string ipv6()
115+
* @method string localIpv4()
116+
* @method string macAddress()
117+
* @method string word()
118+
* @method array|string words($nb = 3, $asText = false)
119+
* @method string sentence($nbWords = 6, $variableNbWords = true)
120+
* @method array|string sentences($nb = 3, $asText = false)
121+
* @method string paragraph($nbSentences = 3, $variableNbSentences = true)
122+
* @method array|string paragraphs($nb = 3, $asText = false)
123+
* @method string text($maxNbChars = 200)
124+
* @method bool boolean($chanceOfGettingTrue = 50)
125+
* @method string md5()
126+
* @method string sha1()
127+
* @method string sha256()
128+
* @method string countryCode()
129+
* @method string countryISOAlpha3()
130+
* @method string languageCode()
131+
* @method string currencyCode()
132+
* @method string emoji()
133+
* @method string creditCardType()
134+
* @method string creditCardNumber($type = null, $formatted = false, $separator = '-')
135+
* @method DateTime creditCardExpirationDate($valid = true)
136+
* @method string creditCardExpirationDateString($valid = true, $expirationDateFormat = null)
137+
* @method array creditCardDetails($valid = true)
138+
* @method string iban($countryCode = null, $prefix = '', $length = null)
139+
* @method string swiftBicNumber()
140+
* @method string name($gender = null)
141+
* @method string firstName($gender = null)
142+
* @method string firstNameMale()
143+
* @method string firstNameFemale()
144+
* @method string lastName($gender = null)
145+
* @method string title($gender = null)
146+
* @method string titleMale()
147+
* @method string titleFemale()
148+
* @method string phoneNumber()
149+
* @method string e164PhoneNumber()
150+
* @method int imei()
151+
* @method string realText($maxNbChars = 200, $indexSize = 2)
152+
* @method string realTextBetween($minNbChars = 160, $maxNbChars = 200, $indexSize = 2)
153+
* @method string macProcessor()
154+
* @method string linuxProcessor()
155+
* @method string userAgent()
156+
* @method string chrome()
157+
* @method string msedge()
158+
* @method string firefox()
159+
* @method string safari()
160+
* @method string opera()
161+
* @method string internetExplorer()
162+
* @method string windowsPlatformToken()
163+
* @method string macPlatformToken()
164+
* @method string iosMobileToken()
165+
* @method string linuxPlatformToken()
166+
* @method string uuid()
167+
* @method string mimeType()
168+
* @method string fileExtension()
169+
* @method string filePath()
170+
* @method string bloodType()
171+
* @method string bloodRh()
172+
* @method string bloodGroup()
173+
* @method string ean13()
174+
* @method string ean8()
175+
* @method string isbn10()
176+
* @method string isbn13()
177+
* @method int numberBetween($int1 = 0, $int2 = 2147483647)
178+
* @method int randomDigit()
179+
* @method int randomDigitNot($except)
180+
* @method int randomDigitNotZero()
181+
* @method float randomFloat($nbMaxDecimals = null, $min = 0, $max = null)
182+
* @method int randomNumber($nbDigits = null, $strict = false)
183+
* @method string semver(bool $preRelease = false, bool $build = false)
184+
* @method string vat($spacedNationalPrefix = true)
185+
*/
186+
class Faker extends Engine implements Contract
187+
{
188+
protected readonly Generator $generator;
189+
190+
/**
191+
* @param array<callable|Formatter> $formatters
192+
* @SuppressWarnings(StaticAccess)
193+
*/
194+
public function __construct(
195+
Notation $case = Notation::SNAKE,
196+
array $formatters = [],
197+
?string $locale = null,
198+
) {
199+
parent::__construct($case, $formatters);
200+
201+
$this->generator = Factory::create($this->locale($locale));
202+
}
203+
204+
public function __call(string $name, array $arguments): mixed
205+
{
206+
return $this->generate($name, $arguments);
207+
}
208+
209+
/**
210+
* @template U of object
211+
* @param class-string<U> $class
212+
* @throws ReflectionException
213+
*/
214+
public function fake(string $class, array $presets = []): Set
215+
{
216+
$target = Target::createFrom($class);
217+
$parameters = $target->getReflectionParameters();
218+
if (empty($parameters)) {
219+
return Set::createFrom([]);
220+
}
221+
222+
return $this->resolveParameters($parameters, new Set($presets));
223+
}
224+
225+
public function generate(string $name, array $arguments = []): mixed
226+
{
227+
return $this->generator->__call($name, $arguments);
228+
}
229+
230+
public function generator(): Generator
231+
{
232+
return $this->generator;
233+
}
234+
235+
/**
236+
* @param array<ReflectionParameter> $parameters
237+
*/
238+
private function resolveParameters(array $parameters, Set $presets): Set
239+
{
240+
$values = [];
241+
foreach ($parameters as $parameter) {
242+
$field = $this->casedField($parameter);
243+
$generated = (new FromDependency($this->notation, $this->formatters))
244+
->then(new FromTypeDate($this->notation, $this->formatters))
245+
->then(new FromCollection($this->notation, $this->formatters))
246+
->then(new FromTypeBuiltin($this->notation, $this->formatters))
247+
->then(new FromTypeAttributes($this->notation, $this->formatters))
248+
->then(new FromEnum($this->notation, $this->formatters))
249+
->then(new FromDefaultValue($this->notation, $this->formatters))
250+
->then(new FromPreset($this->notation, $this->formatters))
251+
->resolve($parameter, $presets);
252+
253+
if ($generated === null) {
254+
continue;
255+
}
256+
$values[$field] = $generated->content;
257+
}
258+
return Set::createFrom($values);
259+
}
260+
261+
private function locale(?string $locale): string
262+
{
263+
$fallback = static function (string $default = 'en_US'): string {
264+
$locale = stringify(getenv('FAKER_LOCALE'), $default);
265+
return empty($locale) ? $default : $locale;
266+
};
267+
return $locale ?? $fallback();
268+
}
269+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
declare(strict_types=1);
44

5-
namespace Constructo\Testing\Faker;
5+
namespace Constructo\Core\Fake;
66

77
use Constructo\Support\Set;
88
use Constructo\Support\Value;

src/Testing/Faker/Resolver/FromCollection.php renamed to src/Core/Fake/Resolver/FromCollection.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,17 @@
22

33
declare(strict_types=1);
44

5-
namespace Constructo\Testing\Faker\Resolver;
5+
namespace Constructo\Core\Fake\Resolver;
66

7+
use Constructo\Core\Fake\Resolver;
78
use Constructo\Support\Set;
89
use Constructo\Support\Value;
10+
use Constructo\Testing\MakeExtension;
11+
use Constructo\Testing\ManagedExtension;
912
use Constructo\Type\Collection;
1013
use ReflectionClass;
1114
use ReflectionException;
1215
use ReflectionParameter;
13-
use Constructo\Testing\Faker\Resolver;
1416

1517
final class FromCollection extends Resolver
1618
{

src/Testing/Faker/Resolver/FromDefaultValue.php renamed to src/Core/Fake/Resolver/FromDefaultValue.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
declare(strict_types=1);
44

5-
namespace Constructo\Testing\Faker\Resolver;
5+
namespace Constructo\Core\Fake\Resolver;
66

7+
use Constructo\Core\Fake\Resolver;
78
use Constructo\Support\Set;
89
use Constructo\Support\Value;
910
use ReflectionException;
1011
use ReflectionParameter;
11-
use Constructo\Testing\Faker\Resolver;
1212

1313
final class FromDefaultValue extends Resolver
1414
{

src/Testing/Faker/Resolver/FromDependency.php renamed to src/Core/Fake/Resolver/FromDependency.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22

33
declare(strict_types=1);
44

5-
namespace Constructo\Testing\Faker\Resolver;
5+
namespace Constructo\Core\Fake\Resolver;
66

7+
use Constructo\Core\Fake\Resolver;
78
use Constructo\Support\Set;
89
use Constructo\Support\Value;
910
use ReflectionException;
@@ -12,7 +13,6 @@
1213
use ReflectionParameter;
1314
use ReflectionType;
1415
use ReflectionUnionType;
15-
use Constructo\Testing\Faker\Resolver;
1616

1717
final class FromDependency extends Resolver
1818
{
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22

33
declare(strict_types=1);
44

5-
namespace Constructo\Testing\Faker\Resolver;
5+
namespace Constructo\Core\Fake\Resolver;
66

77
use BackedEnum;
8+
use Constructo\Core\Fake\Resolver;
89
use Constructo\Support\Set;
910
use Constructo\Support\Value;
1011
use Random\RandomException;
1112
use ReflectionNamedType;
1213
use ReflectionParameter;
13-
use Constructo\Testing\Faker\Resolver;
1414

1515
final class FromEnum extends Resolver
1616
{
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22

33
declare(strict_types=1);
44

5-
namespace Constructo\Testing\Faker\Resolver;
5+
namespace Constructo\Core\Fake\Resolver;
66

7+
use Constructo\Core\Fake\Resolver;
78
use Constructo\Support\Set;
89
use Constructo\Support\Value;
910
use ReflectionParameter;
10-
use Constructo\Testing\Faker\Resolver;
1111

1212
final class FromPreset extends Resolver
1313
{

0 commit comments

Comments
 (0)