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