Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
68.55% covered (warning)
68.55%
170 / 248
31.82% covered (danger)
31.82%
7 / 22
CRAP
0.00% covered (danger)
0.00%
0 / 1
Faker
68.55% covered (warning)
68.55%
170 / 248
31.82% covered (danger)
31.82%
7 / 22
244.37
0.00% covered (danger)
0.00%
0 / 1
 request
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 file
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
20
 files
83.33% covered (warning)
83.33%
30 / 36
0.00% covered (danger)
0.00%
0 / 1
14.91
 generateContent
66.67% covered (warning)
66.67%
6 / 9
0.00% covered (danger)
0.00%
0 / 1
10.37
 generateTextContent
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
12
 generateJsonContent
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
6
 generateHtmlContent
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
2
 generateCsvContent
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
6
 generateBinaryContent
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 randomString
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 textFile
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 jsonFile
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 htmlFile
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 csvFile
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 binaryFile
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 generateJsContent
100.00% covered (success)
100.00%
38 / 38
100.00% covered (success)
100.00%
1 / 1
7
 generateCssContent
100.00% covered (success)
100.00%
43 / 43
100.00% covered (success)
100.00%
1 / 1
3
 randomColor
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 randomFontFamily
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
1
 getCssPropertyValue
96.43% covered (success)
96.43%
27 / 28
0.00% covered (danger)
0.00%
0 / 1
16
 jsFile
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 cssFile
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace Lucent\Facades;
4
5use Lucent\Faker\FakeRequest;
6use Lucent\Filesystem\File;
7use Lucent\Filesystem\Folder;
8
9class Faker
10{
11    /**
12     * Create a fake HTTP request
13     *
14     * @return FakeRequest
15     */
16    public static function request(): FakeRequest
17    {
18        return new FakeRequest();
19    }
20
21    /**
22     * Generate a random file
23     *
24     * @param string|Folder $directory Directory where the file should be created
25     * @param array $options Options for file generation
26     * @param bool $absolute Whether the directory path is absolute
27     * @return File The generated file
28     */
29    public static function file(string|Folder $directory, array $options = [], bool $absolute = false): File
30    {
31        // Handle directory
32        if ($directory instanceof Folder) {
33            $dir = $directory;
34        } else {
35            $dir = new Folder($directory, $absolute);
36            if (!$dir->exists()) {
37                $dir->create();
38            }
39        }
40
41        // Default options
42        $defaults = [
43            'name' => self::randomString(8),
44            'extension' => 'txt',
45            'size' => rand(1024, 10240), // 1KB to 10KB
46            'type' => 'text',
47            'content' => null,
48        ];
49
50        $options = array_merge($defaults, $options);
51
52        // Generate filename
53        $filename = $options['name'] . '.' . $options['extension'];
54
55        // Generate content based on type if not explicitly provided
56        if ($options['content'] === null) {
57            $content = self::generateContent($options['type'], $options['size']);
58        } else {
59            $content = $options['content'];
60        }
61
62        // Create and return the file
63        return new File($dir->path . DIRECTORY_SEPARATOR . $filename, $content, true);
64    }
65
66    /**
67     * Generate multiple random files at once
68     *
69     * @param string|Folder $directory Directory where files should be created
70     * @param int $count Number of files to generate
71     * @param array $options Options for file generation
72     * @param bool $absolute Whether the directory path is absolute
73     * @return array An array of File objects
74     */
75    public static function files(string|Folder $directory, int $count = 5, array $options = [], bool $absolute = false): array
76    {
77        $files = [];
78
79        // Ensure directory exists
80        if ($directory instanceof Folder) {
81            $dir = $directory;
82        } else {
83            $dir = new Folder($directory, $absolute);
84            if (!$dir->exists()) {
85                $dir->create();
86            }
87        }
88
89        // Generate each file
90        for ($i = 0; $i < $count; $i++) {
91            // Copy the options to avoid modifying the original
92            $fileOptions = $options;
93
94            // Generate unique name if not specified
95            if (!isset($fileOptions['name'])) {
96                $fileOptions['name'] = self::randomString(8);
97            }
98
99            // Select random extension if array provided
100            if (isset($fileOptions['extension']) && is_array($fileOptions['extension'])) {
101                // Get a random index
102                $randomIndex = array_rand($fileOptions['extension']);
103                // Use the extension at that random index
104                $fileOptions['extension'] = $fileOptions['extension'][$randomIndex];
105            }
106
107            // Create the file with appropriate content type based on extension
108            $extension = $fileOptions['extension'] ?? 'txt';
109
110            // Determine content type based on extension if not specified
111            if (!isset($fileOptions['type'])) {
112                switch ($extension) {
113                    case 'html':
114                        $fileOptions['type'] = 'html';
115                        break;
116                    case 'json':
117                        $fileOptions['type'] = 'json';
118                        break;
119                    case 'csv':
120                        $fileOptions['type'] = 'csv';
121                        break;
122                    case 'js':
123                        $fileOptions['type'] = 'js'; // JavaScript as text
124                        break;
125                    case 'css':
126                        $fileOptions['type'] = 'css'; // CSS as text
127                        break;
128                    default:
129                        $fileOptions['type'] = 'text';
130                }
131            }
132
133            // Create the file
134            $filename = $fileOptions['name'] . '.' . $extension;
135            $content = self::generateContent($fileOptions['type'], $fileOptions['size'] ?? rand(1024, 10240));
136            $file = new File($dir->path . DIRECTORY_SEPARATOR . $filename, $content, true);
137
138            $files[] = $file;
139        }
140
141        return $files;
142    }
143    /**
144     * Generate content based on specified type
145     *
146     * @param string $type Content type
147     * @param int $size Approximate content size in bytes
148     * @return string|mixed Generated content
149     */
150    private static function generateContent(string $type, int $size): mixed
151    {
152        return match ($type) {
153            'json' => self::generateJsonContent(),
154            'html' => self::generateHtmlContent(),
155            'csv' => self::generateCsvContent(),
156            'binary' => self::generateBinaryContent($size),
157            'css' => self::generateCssContent(),
158            'js' => self::generateJsContent(),
159            default => self::generateTextContent($size),
160        };
161    }
162
163    /**
164     * Generate random text content
165     *
166     * @param int $size Approximate size in bytes
167     * @return string Random text content
168     */
169    public static function generateTextContent(int $size): string
170    {
171        $content = '';
172        $remaining = $size;
173
174        while ($remaining > 0) {
175            $length = min($remaining, rand(3, 15));
176            $content .= self::randomString($length) . ' ';
177            $remaining -= $length + 1;
178
179            if (rand(0, 10) == 0) {
180                $content .= "\n";
181                $remaining--;
182            }
183        }
184
185        return $content;
186    }
187
188    /**
189     * Generate random JSON content
190     *
191     * @return string JSON content
192     */
193    public static function generateJsonContent(): string
194    {
195        $data = [];
196        $count = rand(5, 20);
197
198        for ($i = 0; $i < $count; $i++) {
199            $data[] = [
200                'id' => $i + 1,
201                'name' => self::randomString(rand(5, 10)),
202                'value' => self::randomString(rand(10, 30)),
203                'created' => date('Y-m-d H:i:s')
204            ];
205        }
206
207        return json_encode($data, JSON_PRETTY_PRINT);
208    }
209
210    /**
211     * Generate random HTML content
212     *
213     * @return string HTML content
214     */
215    public static function generateHtmlContent(): string
216    {
217        $content = "<!DOCTYPE html>\n<html>\n<head>\n";
218        $content .= "\t<title>" . self::randomString(10) . "</title>\n";
219        $content .= "</head>\n<body>\n";
220        $content .= "\t<h1>" . self::randomString(15) . "</h1>\n";
221
222        $paragraphs = rand(3, 10);
223        for ($i = 0; $i < $paragraphs; $i++) {
224            $content .= "\t<p>" . self::randomString(rand(50, 200)) . "</p>\n";
225        }
226
227        $content .= "</body>\n</html>";
228
229        return $content;
230    }
231
232    /**
233     * Generate random CSV content
234     *
235     * @return string CSV content
236     */
237    public static function generateCsvContent(): string
238    {
239        $content = "id,name,email,date\n";
240        $rows = rand(10, 50);
241
242        for ($i = 1; $i <= $rows; $i++) {
243            $content .= $i . ',';
244            $content .= self::randomString(rand(5, 10)) . ',';
245            $content .= strtolower(self::randomString(5)) . '@' . strtolower(self::randomString(5)) . '.com,';
246            $content .= date('Y-m-d', strtotime('-' . rand(1, 365) . ' days')) . "\n";
247        }
248
249        return $content;
250    }
251
252    /**
253     * Generate random binary content
254     *
255     * @param int $size Size in bytes
256     * @return string Binary content
257     */
258    public static function generateBinaryContent(int $size): string
259    {
260        return random_bytes($size);
261    }
262
263    /**
264     * Generate a random string of specified length
265     *
266     * @param int $length Length of the string
267     * @return string Random string
268     */
269    public static function randomString(int $length): string
270    {
271        $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
272        $string = '';
273
274        for ($i = 0; $i < $length; $i++) {
275            $string .= $characters[rand(0, strlen($characters) - 1)];
276        }
277
278        return $string;
279    }
280
281    /**
282     * Generate a text file with random content
283     *
284     * @param string|Folder $directory Directory where the file should be created
285     * @param array $options Additional options
286     * @param bool $absolute Whether the directory path is absolute
287     * @return File The generated file
288     */
289    public static function textFile(string|Folder $directory, array $options = [], bool $absolute = false): File
290    {
291        $options['type'] = 'text';
292        $options['extension'] = $options['extension'] ?? 'txt';
293        return self::file($directory, $options, $absolute);
294    }
295
296    /**
297     * Generate a JSON file with random content
298     *
299     * @param string|Folder $directory Directory where the file should be created
300     * @param array $options Additional options
301     * @param bool $absolute Whether the directory path is absolute
302     * @return File The generated file
303     */
304    public static function jsonFile(string|Folder $directory, array $options = [], bool $absolute = false): File
305    {
306        $options['type'] = 'json';
307        $options['extension'] = $options['extension'] ?? 'json';
308        return self::file($directory, $options, $absolute);
309    }
310
311    /**
312     * Generate an HTML file with random content
313     *
314     * @param string|Folder $directory Directory where the file should be created
315     * @param array $options Additional options
316     * @param bool $absolute Whether the directory path is absolute
317     * @return File The generated file
318     */
319    public static function htmlFile(string|Folder $directory, array $options = [], bool $absolute = false): File
320    {
321        $options['type'] = 'html';
322        $options['extension'] = $options['extension'] ?? 'html';
323        return self::file($directory, $options, $absolute);
324    }
325
326    /**
327     * Generate a CSV file with random content
328     *
329     * @param string|Folder $directory Directory where the file should be created
330     * @param array $options Additional options
331     * @param bool $absolute Whether the directory path is absolute
332     * @return File The generated file
333     */
334    public static function csvFile(string|Folder $directory, array $options = [], bool $absolute = false): File
335    {
336        $options['type'] = 'csv';
337        $options['extension'] = $options['extension'] ?? 'csv';
338        return self::file($directory, $options, $absolute);
339    }
340
341    /**
342     * Generate a binary file with random content
343     *
344     * @param string|Folder $directory Directory where the file should be created
345     * @param array $options Additional options
346     * @param bool $absolute Whether the directory path is absolute
347     * @return File The generated file
348     */
349    public static function binaryFile(string|Folder $directory, array $options = [], bool $absolute = false): File
350    {
351        $options['type'] = 'binary';
352        $options['extension'] = $options['extension'] ?? 'bin';
353        return self::file($directory, $options, $absolute);
354    }
355
356    /**
357     * Generate random JavaScript content
358     *
359     * @return string JavaScript content
360     */
361    public static function generateJsContent(): string
362    {
363        $content = "// Generated JavaScript file\n";
364        $content .= "// Created on: " . date('Y-m-d H:i:s') . "\n\n";
365
366        // Add some constants
367        $content .= "const APP_NAME = '" . self::randomString(8) . "';\n";
368        $content .= "const VERSION = '" . rand(1, 5) . "." . rand(0, 9) . "." . rand(0, 9) . "';\n";
369        $content .= "const DEBUG = " . (rand(0, 1) ? 'true' : 'false') . ";\n\n";
370
371        // Add a class/object
372        $className = self::randomString(6);
373        $content .= "class " . ucfirst($className) . " {\n";
374        $content .= "  constructor() {\n";
375        $content .= "    this.id = '" . self::randomString(8) . "';\n";
376        $content .= "    this.name = '" . self::randomString(10) . "';\n";
377        $content .= "    this.created = new Date();\n";
378        $content .= "    this.items = [];\n";
379        $content .= "  }\n\n";
380
381        // Add some methods
382        $methods = rand(2, 5);
383        for ($i = 0; $i < $methods; $i++) {
384            $methodName = lcfirst(self::randomString(rand(5, 10)));
385            $content .= "  " . $methodName . "(";
386
387            // Random parameters
388            $params = rand(0, 3);
389            $paramNames = [];
390            for ($j = 0; $j < $params; $j++) {
391                $paramNames[] = "param" . ($j + 1);
392            }
393            $content .= implode(", ", $paramNames) . ") {\n";
394
395            // Method body
396            $content .= "    console.log('Executing " . $methodName . "');\n";
397            if (rand(0, 1) && !empty($paramNames)) {
398                $content .= "    return " . $paramNames[array_rand($paramNames)] . ";\n";
399            } else {
400                $content .= "    return " . (rand(0, 1) ? 'true' : 'null') . ";\n";
401            }
402            $content .= "  }\n\n";
403        }
404
405        $content .= "}\n\n";
406
407        // Add an initialization
408        $content .= "// Initialize the application\n";
409        $content .= "const app = new " . ucfirst($className) . "();\n";
410        $content .= "console.log('Application initialized', app);\n";
411
412        // Add event listener
413        $events = ['click', 'load', 'change', 'submit'];
414        $event = $events[array_rand($events)];
415        $content .= "\n// Event listeners\n";
416        $content .= "document.addEventListener('" . $event . "', function() {\n";
417        $content .= "  console.log('Event triggered');\n";
418        $content .= "});\n";
419
420        return $content;
421    }
422
423    /**
424     * Generate random CSS content
425     *
426     * @return string CSS content
427     */
428    public static function generateCssContent(): string
429    {
430        $content = "/* Generated CSS file */\n";
431        $content .= "/* Created on: " . date('Y-m-d H:i:s') . " */\n\n";
432
433        // Root variables
434        $content .= ":root {\n";
435        $content .= "  --primary-color: " . self::randomColor() . ";\n";
436        $content .= "  --secondary-color: " . self::randomColor() . ";\n";
437        $content .= "  --text-color: " . self::randomColor() . ";\n";
438        $content .= "  --background-color: " . self::randomColor() . ";\n";
439        $content .= "  --font-size: " . rand(12, 18) . "px;\n";
440        $content .= "  --padding: " . rand(5, 20) . "px;\n";
441        $content .= "  --margin: " . rand(5, 20) . "px;\n";
442        $content .= "  --border-radius: " . rand(3, 12) . "px;\n";
443        $content .= "}\n\n";
444
445        // Body styles
446        $content .= "body {\n";
447        $content .= "  font-family: " . self::randomFontFamily() . ";\n";
448        $content .= "  color: var(--text-color);\n";
449        $content .= "  background-color: var(--background-color);\n";
450        $content .= "  margin: 0;\n";
451        $content .= "  padding: 0;\n";
452        $content .= "  box-sizing: border-box;\n";
453        $content .= "}\n\n";
454
455        // Container
456        $content .= ".container {\n";
457        $content .= "  max-width: " . rand(960, 1200) . "px;\n";
458        $content .= "  margin: 0 auto;\n";
459        $content .= "  padding: var(--padding);\n";
460        $content .= "}\n\n";
461
462        // Generate some random element styles
463        $elements = ['header', 'footer', 'main', 'section', 'article', 'aside', 'nav', 'div', 'p', 'h1', 'h2', 'h3', 'a', 'button', 'input'];
464        $selectedElements = array_rand(array_flip($elements), rand(5, 10));
465
466        foreach ($selectedElements as $element) {
467            $content .= $element . " {\n";
468            $properties = ['margin', 'padding', 'color', 'background-color', 'font-size', 'line-height', 'text-align', 'border', 'border-radius', 'display', 'flex-direction', 'justify-content', 'align-items'];
469            $selectedProperties = array_rand(array_flip($properties), rand(3, 6));
470
471            foreach ($selectedProperties as $property) {
472                $content .= "  " . $property . ": " . self::getCssPropertyValue($property) . ";\n";
473            }
474
475            $content .= "}\n\n";
476        }
477
478        // Media query
479        $content .= "@media (max-width: " . rand(600, 900) . "px) {\n";
480        $content .= "  body {\n";
481        $content .= "    font-size: " . rand(10, 16) . "px;\n";
482        $content .= "  }\n";
483        $content .= "  .container {\n";
484        $content .= "    padding: " . rand(5, 15) . "px;\n";
485        $content .= "  }\n";
486        $content .= "}\n";
487
488        return $content;
489    }
490
491    /**
492     * Generate a random color in hex format
493     *
494     * @return string Color in hex format
495     */
496    private static function randomColor(): string
497    {
498        return sprintf('#%06x', rand(0, 0xFFFFFF));
499    }
500
501    /**
502     * Get a random font family
503     *
504     * @return string Font family
505     */
506    private static function randomFontFamily(): string
507    {
508        $families = [
509            'Arial, sans-serif',
510            '"Helvetica Neue", Helvetica, sans-serif',
511            'Georgia, serif',
512            '"Times New Roman", Times, serif',
513            'Verdana, Geneva, sans-serif',
514            '"Courier New", Courier, monospace',
515            'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
516        ];
517
518        return $families[array_rand($families)];
519    }
520
521    /**
522     * Get a random CSS property value based on property name
523     *
524     * @param string $property CSS property name
525     * @return string Property value
526     */
527    private static function getCssPropertyValue(string $property): string
528    {
529        switch ($property) {
530            case 'margin':
531            case 'padding':
532                return rand(0, 30) . 'px';
533            case 'color':
534            case 'background-color':
535                return 'var(--' . (rand(0, 1) ? 'primary' : 'secondary') . '-color)';
536            case 'font-size':
537                return rand(10, 24) . 'px';
538            case 'line-height':
539                return (rand(12, 20) / 10) . '';
540            case 'text-align':
541                $alignments = ['left', 'right', 'center', 'justify'];
542                return $alignments[array_rand($alignments)];
543            case 'border':
544                return '1px solid ' . self::randomColor();
545            case 'border-radius':
546                return 'var(--border-radius)';
547            case 'display':
548                $displays = ['block', 'flex', 'inline-block', 'grid'];
549                return $displays[array_rand($displays)];
550            case 'flex-direction':
551                $directions = ['row', 'column', 'row-reverse', 'column-reverse'];
552                return $directions[array_rand($directions)];
553            case 'justify-content':
554            case 'align-items':
555                $alignments = ['flex-start', 'flex-end', 'center', 'space-between', 'space-around'];
556                return $alignments[array_rand($alignments)];
557            default:
558                return 'initial';
559        }
560    }
561
562    /**
563     * Generate a JavaScript file with random content
564     *
565     * @param string|Folder $directory Directory where the file should be created
566     * @param array $options Additional options
567     * @param bool $absolute Whether the directory path is absolute
568     * @return File The generated file
569     */
570    public static function jsFile(string|Folder $directory, array $options = [], bool $absolute = false): File
571    {
572        $options['content'] = $options['content'] ?? self::generateJsContent();
573        $options['extension'] = 'js';
574        return self::file($directory, $options, $absolute);
575    }
576
577    /**
578     * Generate a CSS file with random content
579     *
580     * @param string|Folder $directory Directory where the file should be created
581     * @param array $options Additional options
582     * @param bool $absolute Whether the directory path is absolute
583     * @return File The generated file
584     */
585    public static function cssFile(string|Folder $directory, array $options = [], bool $absolute = false): File
586    {
587        $options['content'] = $options['content'] ?? self::generateCssContent();
588        $options['extension'] = 'css';
589        return self::file($directory, $options, $absolute);
590    }
591}