Skip to content

Commit 7cb255b

Browse files
authored
Merge pull request #71 from veewee/create-while-write-to-file
Attempt to create file and directory when starting a writer for a file
2 parents 6fae11b + 0dffb8d commit 7cb255b

File tree

4 files changed

+41
-6
lines changed

4 files changed

+41
-6
lines changed

docs/writer.md

+2
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,8 @@ $doc = Writer::inMemory(...$configurators)
534534
#### xml_file_opener
535535

536536
Loads an XML document from a file.
537+
When the file or folder does not exists, the code will attempt to create it.
538+
If it is not possible to create a target to write to, a `RuntimException` will be thrown.
537539

538540
```php
539541
use VeeWee\Xml\Writer\Writer;

src/Xml/Writer/Opener/xml_file_opener.php

+8-2
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,22 @@
55
namespace VeeWee\Xml\Writer\Opener;
66

77
use Closure;
8-
use Webmozart\Assert\Assert;
8+
use Psl\File\WriteMode;
99
use XMLWriter;
10+
use function Psl\File\write;
1011

1112
/**
13+
* @param non-empty-string $file
14+
*
1215
* @return Closure(XMLWriter): bool XMLWriter
1316
*/
1417
function xml_file_opener(string $file): Closure
1518
{
1619
return static function (XMLWriter $writer) use ($file) : bool {
17-
Assert::writable($file);
20+
// Try to create the file first.
21+
// If the file exists, it will truncated. (Default behaviour of XMLWriter as well)
22+
// If it cannot be created, it will throw exceptions.
23+
write($file, '', WriteMode::TRUNCATE);
1824

1925
return $writer->openUri($file);
2026
};

src/Xml/Writer/Writer.php

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public static function fromUnsafeWriter(XMLWriter $writer, callable ... $configu
4040
}
4141

4242
/**
43+
* @param non-empty-string $file
4344
* @param list<(callable(XMLWriter): XMLWriter)> $configurators
4445
*/
4546
public static function forFile(string $file, callable ... $configurators): self

tests/Xml/Writer/Opener/XmlFileOpenerTest.php

+30-4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
namespace VeeWee\Tests\Xml\Writer\Opener;
66

77
use PHPUnit\Framework\TestCase;
8+
use Psl\File;
9+
use Psl\Filesystem;
10+
use Psl\OS;
811
use VeeWee\Tests\Xml\Helper\TmpFileTrait;
912
use VeeWee\Xml\Exception\RuntimeException;
1013
use VeeWee\Xml\Writer\Writer;
@@ -14,23 +17,46 @@ final class XmlFileOpenerTest extends TestCase
1417
{
1518
use TmpFileTrait;
1619

17-
1820
public function test_it_can_open_a_file(): void
1921
{
2022
$this->createTmpFile(static function (string $path): void {
23+
File\write($path, 'will be truncated', File\WriteMode::TRUNCATE);
24+
2125
$writer = Writer::forFile($path);
2226
$writer->write(element('root'));
2327

2428
self::assertXmlStringEqualsXmlFile($path, '<root />');
2529
});
2630
}
2731

28-
32+
public function test_it_can_write_to_a_new_file(): void
33+
{
34+
$temporaryFile = Filesystem\create_temporary_file();
35+
Filesystem\delete_file($temporaryFile);
36+
37+
$writer = Writer::forFile($temporaryFile);
38+
$writer->write(element('root'));
39+
static::assertXmlStringEqualsXmlFile($temporaryFile, '<root />');
40+
41+
unlink($temporaryFile);
42+
}
43+
2944
public function test_it_errors_if_file_is_not_writable(): void
3045
{
46+
if (OS\is_windows()) {
47+
static::markTestSkipped('Permissions are not reliable on windows.');
48+
}
49+
50+
$temporary_file = Filesystem\create_temporary_file();
51+
Filesystem\delete_file($temporary_file);
52+
Filesystem\create_directory($temporary_file);
53+
Filesystem\change_permissions($temporary_file, 0555);
54+
55+
$file = $temporary_file . Filesystem\SEPARATOR . 'foo';
56+
3157
$this->expectException(RuntimeException::class);
32-
$this->expectExceptionMessage('The path "doesnotexist" is not writable.');
58+
$this->expectExceptionMessage('File "' . $file . '" is not writable.');
3359

34-
Writer::forFile('doesnotexist');
60+
Writer::forFile($file);
3561
}
3662
}

0 commit comments

Comments
 (0)