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