Skip to content

Commit 3657e9a

Browse files
committed
feat: allow creating "named" temp files
1 parent 8b077e6 commit 3657e9a

File tree

3 files changed

+131
-2
lines changed

3 files changed

+131
-2
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ $file = TempFile::new();
2424
// create empty file with random filename, with extension (in /tmp)
2525
$file = TempFile::withExtension('txt');
2626

27+
// create file with specific filename (in /tmp)
28+
$file = TempFile::withName('my-file.txt'); // creates empty file
29+
$file = TempFile::withName('my-file.txt', 'some content'); // creates file with string content
30+
$file = TempFile::withName('my-file.txt', \fopen('some/file.txt', 'r')); // creates file with resource as content
31+
$file = TempFile::withName('my-file.txt', new \SplFileInfo('some/file.txt')); // creates file from existing file (existing file is copied)
32+
2733
// create for existing file
2834
$file = TempFile::new('some/file.txt'); // note: will be deleted at the end of the script
2935

@@ -40,6 +46,7 @@ $file = TempFile::for(new \SplFileInfo('some/file.txt'));
4046
$image = TempFile::image(); // temporary 10x10 image with 'jpg' as the extension
4147
$image = TempFile::image(100, 50); // customize the dimensions
4248
$image = TempFile::image(type: 'gif'); // customize the image type
49+
$image = TempFile::image(name: 'my-image.png'); // customize the file name
4350
```
4451

4552
### Using `TempFile`'s

src/TempFile.php

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,31 @@ public static function new(?string $filename = null): self
4242
return new self($filename);
4343
}
4444

45+
/**
46+
* @param string $name Name for the file (must contain no directory separators)
47+
* @param string|resource|\SplFileInfo|null $content
48+
*/
49+
public static function withName(string $name, mixed $content = null): self
50+
{
51+
if (\str_contains($name, '/')) {
52+
throw new \InvalidArgumentException('File name cannot contain directory separator.');
53+
}
54+
55+
$filename = \sprintf('%s/%s', \sys_get_temp_dir(), $name);
56+
57+
if ($content instanceof \SplFileInfo) {
58+
@\copy($content, $filename) ?: throw new \RuntimeException('Unable to copy file.');
59+
60+
return new self($filename);
61+
}
62+
63+
if (false === @\file_put_contents($filename, $content ?? '')) {
64+
throw new \RuntimeException('Unable to write to file.');
65+
}
66+
67+
return new self($filename);
68+
}
69+
4570
public static function withExtension(string $extension): self
4671
{
4772
$original = self::tempFile();
@@ -78,10 +103,14 @@ public static function for(mixed $what, ?string $extension = null): self
78103
*
79104
* @source https://github.com/laravel/framework/blob/183d38f18c0ea9fe13b6d10a6d8360be881d096c/src/Illuminate/Http/Testing/FileFactory.php#L68
80105
*/
81-
public static function image(int $width = 10, int $height = 10, string $type = 'jpg'): self
106+
public static function image(int $width = 10, int $height = 10, string $type = 'jpg', ?string $name = null): self
82107
{
108+
if ($name) {
109+
$type = \pathinfo($name, \PATHINFO_EXTENSION) ?: throw new \InvalidArgumentException('File name must include an extension.');
110+
}
111+
83112
$type = \mb_strtolower($type);
84-
$file = self::withExtension($type);
113+
$file = $name ? self::withName($name) : self::withExtension($type);
85114

86115
if (false === $image = @\imagecreatetruecolor($width, $height)) {
87116
throw new \RuntimeException('Error creating temporary image.');

tests/TempFileTest.php

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,41 @@ public function can_create_image_with_dimensions(): void
198198
$this->assertSame('png', $file->getExtension());
199199
}
200200

201+
/**
202+
* @test
203+
*/
204+
public function can_create_image_with_name(): void
205+
{
206+
$imageSize = \getimagesize($file = TempFile::image(5, 6, name: 'some-image.png'));
207+
208+
$this->assertFileExists($file);
209+
$this->assertSame(\sys_get_temp_dir().'/some-image.png', (string) $file);
210+
$this->assertSame(5, $imageSize[0]);
211+
$this->assertSame(6, $imageSize[1]);
212+
$this->assertSame('image/png', $imageSize['mime']);
213+
$this->assertSame('png', $file->getExtension());
214+
}
215+
216+
/**
217+
* @test
218+
*/
219+
public function image_name_requires_extension(): void
220+
{
221+
$this->expectException(\InvalidArgumentException::class);
222+
223+
TempFile::image(name: 'some-image');
224+
}
225+
226+
/**
227+
* @test
228+
*/
229+
public function image_name_cannot_contain_directory_separator(): void
230+
{
231+
$this->expectException(\InvalidArgumentException::class);
232+
233+
TempFile::image(name: 'some/dir/image.png');
234+
}
235+
201236
/**
202237
* @test
203238
*/
@@ -207,4 +242,62 @@ public function cannot_create_image_for_invalid_type(): void
207242

208243
TempFile::image(type: 'invalid');
209244
}
245+
246+
/**
247+
* @test
248+
*/
249+
public function can_create_named_temp_file(): void
250+
{
251+
$file = TempFile::withName('some-file.txt');
252+
253+
$this->assertFileExists($file);
254+
$this->assertSame(\sys_get_temp_dir().'/some-file.txt', (string) $file);
255+
$this->assertSame('', \file_get_contents($file));
256+
257+
TempFile::purge();
258+
259+
$this->assertFileDoesNotExist($file);
260+
}
261+
262+
/**
263+
* @test
264+
*/
265+
public function can_create_named_temp_file_with_string_content(): void
266+
{
267+
$file = TempFile::withName('some-file.txt', 'content');
268+
269+
$this->assertFileExists($file);
270+
$this->assertSame(\sys_get_temp_dir().'/some-file.txt', (string) $file);
271+
$this->assertSame('content', \file_get_contents($file));
272+
273+
TempFile::purge();
274+
275+
$this->assertFileDoesNotExist($file);
276+
}
277+
278+
/**
279+
* @test
280+
*/
281+
public function can_create_named_temp_file_with_spl_file(): void
282+
{
283+
$file = TempFile::withName('some-file.txt', new \SplFileInfo(__FILE__));
284+
285+
$this->assertFileExists($file);
286+
$this->assertSame(\sys_get_temp_dir().'/some-file.txt', (string) $file);
287+
$this->assertFileEquals($file, __FILE__);
288+
289+
TempFile::purge();
290+
291+
$this->assertFileDoesNotExist($file);
292+
}
293+
294+
/**
295+
* @test
296+
*/
297+
public function name_cannot_contain_directory_separator(): void
298+
{
299+
$this->expectException(\InvalidArgumentException::class);
300+
301+
TempFile::withName('some/dir/some-file.txt');
302+
}
210303
}

0 commit comments

Comments
 (0)