Skip to content

Commit

Permalink
Merge pull request #71 from veewee/create-while-write-to-file
Browse files Browse the repository at this point in the history
Attempt to create file and directory when starting a writer for a file
  • Loading branch information
veewee committed Jan 29, 2024
2 parents 6fae11b + 0dffb8d commit 7cb255b
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 6 deletions.
2 changes: 2 additions & 0 deletions docs/writer.md
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,8 @@ $doc = Writer::inMemory(...$configurators)
#### xml_file_opener

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

```php
use VeeWee\Xml\Writer\Writer;
Expand Down
10 changes: 8 additions & 2 deletions src/Xml/Writer/Opener/xml_file_opener.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,22 @@
namespace VeeWee\Xml\Writer\Opener;

use Closure;
use Webmozart\Assert\Assert;
use Psl\File\WriteMode;
use XMLWriter;
use function Psl\File\write;

/**
* @param non-empty-string $file
*
* @return Closure(XMLWriter): bool XMLWriter
*/
function xml_file_opener(string $file): Closure
{
return static function (XMLWriter $writer) use ($file) : bool {
Assert::writable($file);
// Try to create the file first.
// If the file exists, it will truncated. (Default behaviour of XMLWriter as well)
// If it cannot be created, it will throw exceptions.
write($file, '', WriteMode::TRUNCATE);

return $writer->openUri($file);
};
Expand Down
1 change: 1 addition & 0 deletions src/Xml/Writer/Writer.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public static function fromUnsafeWriter(XMLWriter $writer, callable ... $configu
}

/**
* @param non-empty-string $file
* @param list<(callable(XMLWriter): XMLWriter)> $configurators
*/
public static function forFile(string $file, callable ... $configurators): self
Expand Down
34 changes: 30 additions & 4 deletions tests/Xml/Writer/Opener/XmlFileOpenerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
namespace VeeWee\Tests\Xml\Writer\Opener;

use PHPUnit\Framework\TestCase;
use Psl\File;
use Psl\Filesystem;
use Psl\OS;
use VeeWee\Tests\Xml\Helper\TmpFileTrait;
use VeeWee\Xml\Exception\RuntimeException;
use VeeWee\Xml\Writer\Writer;
Expand All @@ -14,23 +17,46 @@ final class XmlFileOpenerTest extends TestCase
{
use TmpFileTrait;


public function test_it_can_open_a_file(): void
{
$this->createTmpFile(static function (string $path): void {
File\write($path, 'will be truncated', File\WriteMode::TRUNCATE);

$writer = Writer::forFile($path);
$writer->write(element('root'));

self::assertXmlStringEqualsXmlFile($path, '<root />');
});
}


public function test_it_can_write_to_a_new_file(): void
{
$temporaryFile = Filesystem\create_temporary_file();
Filesystem\delete_file($temporaryFile);

$writer = Writer::forFile($temporaryFile);
$writer->write(element('root'));
static::assertXmlStringEqualsXmlFile($temporaryFile, '<root />');

unlink($temporaryFile);
}

public function test_it_errors_if_file_is_not_writable(): void
{
if (OS\is_windows()) {
static::markTestSkipped('Permissions are not reliable on windows.');
}

$temporary_file = Filesystem\create_temporary_file();
Filesystem\delete_file($temporary_file);
Filesystem\create_directory($temporary_file);
Filesystem\change_permissions($temporary_file, 0555);

$file = $temporary_file . Filesystem\SEPARATOR . 'foo';

$this->expectException(RuntimeException::class);
$this->expectExceptionMessage('The path "doesnotexist" is not writable.');
$this->expectExceptionMessage('File "' . $file . '" is not writable.');

Writer::forFile('doesnotexist');
Writer::forFile($file);
}
}

0 comments on commit 7cb255b

Please sign in to comment.