Skip to content

Commit

Permalink
Introduce convertAndSave method
Browse files Browse the repository at this point in the history
- Introduce the `convertAndSave` method to save in a php file
the result of xml conversion.
- Refactor `FileConverter` following decorator  pattern instead
of class extension.
  • Loading branch information
cristianoc72 committed Sep 11, 2024
1 parent 3d991f6 commit c07198d
Show file tree
Hide file tree
Showing 4 changed files with 273 additions and 15 deletions.
39 changes: 35 additions & 4 deletions src/Converter.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,19 @@
/**
* Class to convert an xml string to array
*/
class Converter
final class Converter
{
private array $options;

/**
* Static constructor.
*/
public static function create(array $options = []): static
public static function create(array $options = []): self
{
return new static($options);
return new self($options);
}

final public function __construct(array $options = [])
public function __construct(array $options = [])
{
$resolver = new OptionsResolver();
$this->configureOptions($resolver);
Expand Down Expand Up @@ -66,6 +66,37 @@ public function convert(string $xmlToParse): array
return $array;
}

/**
* Convert an XML string to array and save it to file.
*
* @param string $xmlToParse The XML to parse
* @param string $filename The file name where to save the parsed array
*
* @throw \RuntimeException If the file is not writeable or the directory doesn't exist
*/
public function convertAndSave(string $xmlToParse, string $filename): void
{
$dirName = dirname($filename);
if (!file_exists($dirName)) {
throw new \RuntimeException("The directory `$dirName` does not exist: you should create it before writing a file.");
}

if (!is_writable($dirName)) {
throw new \RuntimeException("It's impossible to write into `$dirName` directory: do you have the correct permissions?");
}

$array = $this->convert($xmlToParse);

$content = "<?php declare(strict_types=1);
/*
* This file is auto-generated by susina/xml-to-array library.
*/
return " . var_export($array, true) . ";
";
file_put_contents($filename, $content);
}

private function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
Expand Down
55 changes: 48 additions & 7 deletions src/FileConverter.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,64 @@

namespace Susina\XmlToArray;

class FileConverter extends Converter
class FileConverter
{
private Converter $converter;

/**
* Static constructor.
*/
public static function create(array $options = []): self
{
return new self($options);
}

/**
* @see Susina\XmlToArray\Converter::__construct()
*/
public function __construct(array $options = [])
{
$this->converter = new Converter($options);
}

/**
* Create a PHP array from an XML file.
*
* @param string $filename The XML file to parse.
* @param string $xmlFile The XML file to parse.
*
* @return array
*
* @throws \RuntimeException If the file does not exist or it's not readable.
*
* @psalm-suppress ParamNameMismatch It's a desired behavior, since in this method the parameter
* is a filename while in the parent methods it's the xml to convert.
*/
public function convert(string $filename): array
public function convert(string $xmlFile): array
{
$this->assertValidFile($xmlFile);

return $this->converter->convert(file_get_contents($xmlFile));
}

/**
* Convert an XML file to array and save it to file.
*
* @param string $xmlFile The XML file to parse.
* @param string $saveFile The file where to save the parsed array.
*
* @throw \RuntimeException If the file is not writeable or the directory doesn't exist.
*/
public function convertAndSave(string $xmlFile, string $saveFile): void
{
$this->assertValidFile($xmlFile);

$this->converter->convertAndSave(file_get_contents($xmlFile), $saveFile);
}

/**
* Check if a file exists and is readable
*
* @throws \RuntimeException If the file is not writeable or the directory doesn't exist.
*/
private function assertValidFile(string $filename): void
{
if (!file_exists($filename)) {
throw new \RuntimeException("The file `$filename` does not exist.");
Expand All @@ -38,7 +81,5 @@ public function convert(string $filename): array
if (!is_readable($filename)) {
throw new \RuntimeException("The file `$filename` is not readable: do you have the correct permissions?");
}

return parent::convert(file_get_contents($filename));
}
}
65 changes: 65 additions & 0 deletions tests/Unit/ConverterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,68 @@
$actual = Converter::create(['preserveFirstTag' => true])->convert($xml);
expect($actual)->toBe($expected);
});

it('converts an xml string and save to a file', function (string $xml, array $expected, string $content) {
$file = vfsStream::newFile('saved_file.php')->at($this->getRoot());

$this->converter->convertAndSave($xml, $file->url());

$actual = include($file->url());

expect($actual)->toBe($expected)
->and($content)->toBe($file->getContent());
})->with([
["<?xml version='1.0' standalone='yes'?>
<movies>
<movie>
<title>Star Wars</title>
<starred>True</starred>
<percentage>32.5</percentage>
</movie>
<movie>
<title>The Lord Of The Rings</title>
<starred>false</starred>
</movie>
</movies>
",
[
'movie' => [
0 => ['title' => 'Star Wars', 'starred' => true, 'percentage' => 32.5],
1 => ['title' => 'The Lord Of The Rings', 'starred' => false]
]
],
"<?php declare(strict_types=1);
/*
* This file is auto-generated by susina/xml-to-array library.
*/
return array (
'movie' =>
array (
0 =>
array (
'title' => 'Star Wars',
'starred' => true,
'percentage' => 32.5,
),
1 =>
array (
'title' => 'The Lord Of The Rings',
'starred' => false,
),
),
);
"
]
]);

it('try to save in a not existent directory', function () {
$xml = "<movies><movie><title>The Lord Of The Rings</title><starred>false</starred></movie></movies>";
$this->converter->convertAndSave($xml, $this->getRoot()->url() . '/my_dir/my_array.php');
})->throws(\RuntimeException::class, "The directory `vfs://root/my_dir` does not exist: you should create it before writing a file.");

it('try to save in a not writeable directory', function () {
$dir = vfsStream::newDirectory('xml_dir', 000)->at($this->getRoot());
$xml = "<movies><movie><title>The Lord Of The Rings</title><starred>false</starred></movie></movies>";
$this->converter->convertAndSave($xml, $dir->url() . '/my_array.php');
})->throws(\RuntimeException::class, "It's impossible to write into `vfs://root/xml_dir` directory: do you have the correct permissions?");
129 changes: 125 additions & 4 deletions tests/Unit/FileConverterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@
use org\bovigo\vfs\vfsStream;
use Susina\XmlToArray\FileConverter;

it('instantiate the correct object via static method', function () {
expect(FileConverter::create())->toBeInstanceOf(FileConverter::class);
});

it('converts an XML file to an array', function (string $xml, array $expected) {
$file = vfsStream::newFile("test_file.xml")->at($this->getRoot())->setContent($xml);
$actual = FileConverter::create()->convert($file->url());
Expand All @@ -36,3 +32,128 @@
$file = vfsStream::newFile('notreadable.xml', 200)->at($this->getRoot())->setContent("<root></root>");
FileConverter::create()->convert($file->url());
})->throws(\RuntimeException::class, 'The file `vfs://root/notreadable.xml` is not readable: do you have the correct permissions?');

it('converts an xml file into an array and save to a file', function (string $xml, array $expected, string $content) {
$xmlFile = vfsStream::newFile('xml_file.xml')->at($this->getRoot())->setContent($xml);
$saveFile = vfsStream::newFile('saved_file.php')->at($this->getRoot());

FileConverter::create()->convertAndSave($xmlFile->url(), $saveFile->url());

$actual = include($saveFile->url());

expect($actual)->toBe($expected)
->and($content)->toBe($saveFile->getContent());
})->with([
["<?xml version='1.0' standalone='yes'?>
<movies>
<movie>
<title>Star Wars</title>
<starred>True</starred>
<percentage>32.5</percentage>
</movie>
<movie>
<title>The Lord Of The Rings</title>
<starred>false</starred>
</movie>
</movies>
",
[
'movie' => [
0 => ['title' => 'Star Wars', 'starred' => true, 'percentage' => 32.5],
1 => ['title' => 'The Lord Of The Rings', 'starred' => false]
]
],
"<?php declare(strict_types=1);
/*
* This file is auto-generated by susina/xml-to-array library.
*/
return array (
'movie' =>
array (
0 =>
array (
'title' => 'Star Wars',
'starred' => true,
'percentage' => 32.5,
),
1 =>
array (
'title' => 'The Lord Of The Rings',
'starred' => false,
),
),
);
"
]
]);

it('converts an xml string and save to a file, creating it', function (string $xml, array $expected, string $content) {
$xmlFile = vfsStream::newFile('xml_file.xml')->at($this->getRoot())->setContent($xml);
FileConverter::create()->convertAndSave($xmlFile->url(), $this->getRoot()->url() . '/save_file.php');
expect('vfs://root/save_file.php')->toBeFile();

$actual = include('vfs://root/save_file.php');

expect($actual)->toBe($expected)
->and($content)->toBe(file_get_contents('vfs://root/save_file.php'));
})->with([
["<?xml version='1.0' standalone='yes'?>
<movies>
<movie>
<title>Star Wars</title>
<starred>True</starred>
<percentage>32.5</percentage>
</movie>
<movie>
<title>The Lord Of The Rings</title>
<starred>false</starred>
</movie>
</movies>
",
[
'movie' => [
0 => ['title' => 'Star Wars', 'starred' => true, 'percentage' => 32.5],
1 => ['title' => 'The Lord Of The Rings', 'starred' => false]
]
],
"<?php declare(strict_types=1);
/*
* This file is auto-generated by susina/xml-to-array library.
*/
return array (
'movie' =>
array (
0 =>
array (
'title' => 'Star Wars',
'starred' => true,
'percentage' => 32.5,
),
1 =>
array (
'title' => 'The Lord Of The Rings',
'starred' => false,
),
),
);
"
]
]);

it('try to save in a not existent directory', function () {
$xmlFile = vfsStream::newFile('xml_file.xml')
->at($this->getRoot())
->setContent("<movies><movie><title>The Lord Of The Rings</title><starred>false</starred></movie></movies>");
$converter = new FileConverter();
$converter->convertAndSave($xmlFile->url(), $this->getRoot()->url() . '/my_dir/my_array.php');
})->throws(\RuntimeException::class, "The directory `vfs://root/my_dir` does not exist: you should create it before writing a file.");

it('try to save in a not writeable directory', function () {
$dir = vfsStream::newDirectory('xml_dir', 000)->at($this->getRoot());
$xmlFile = vfsStream::newFile('xml_file.xml')
->at($this->getRoot())
->setContent("<movies><movie><title>The Lord Of The Rings</title><starred>false</starred></movie></movies>");
FileConverter::create()->convertAndSave($xmlFile->url(), $dir->url() . '/my_array.php');
})->throws(\RuntimeException::class, "It's impossible to write into `vfs://root/xml_dir` directory: do you have the correct permissions?");

0 comments on commit c07198d

Please sign in to comment.