Skip to content

Commit

Permalink
Merge pull request #7 from Hi-Folks/feat/6-yaml
Browse files Browse the repository at this point in the history
Handling YAML
  • Loading branch information
roberto-butti authored Jun 22, 2024
2 parents b6cc826 + cd0a305 commit c86355a
Show file tree
Hide file tree
Showing 10 changed files with 202 additions and 110 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog

## 0.2.0 - 2024-06-22
- Add Yaml capabilities (loading from Yaml and exporting to Yaml)

## 0.1.1 - 2024-06-22
- Add toJson() method for exporting JSON string

Expand Down
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,16 @@ $data = Block::make($fruitsArray);
$jsonString = $data->toJson(); // JSON string with "pretty print"
```

### Exporting to YAML string with `toYaml()`
In the case you need to generate a valid YAML string with the content of the Block object, you can use the `toYaml()` method.

This is helpful when you are manipulating data with the Block class and at a certain point need to send the data in YAML string format to your own function or a function from a third-party package that expects to receive a YAML string as a parameter.

```php
$data = Block::make($fruitsArray);
$yamlString = $data->toYaml(); // YAML string
```

## Loading Data

### Loading Data from JSON file
Expand All @@ -274,6 +284,17 @@ echo $composerContent->get("name"); // for example: "hi-folks/data-block"
echo $composerContent->get("authors.0.name"); // for example: "Roberto B."
```

### Loading Data from YAML file

```php
$file = "./.github/workflows/run-tests.yml";
$workflow = Block::fromYamlFile($file);
echo $workflow->get("name"); // Name of the GitHub Action Workflow
echo $workflow->get("jobs.test.runs-on");
echo $workflow->get("on.0"); // push , the first event
```


## Querying, sorting data

### The `where()` method
Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
}
],
"require": {
"php": "^8.1|^8.2|^8.3"
"php": "^8.1|^8.2|^8.3",
"symfony/yaml": "^6.4|^7.1"
},
"require-dev": {
"laravel/pint": "^1.2",
Expand Down
106 changes: 4 additions & 102 deletions src/Block.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
use HiFolks\DataType\Traits\EditableBlock;
use HiFolks\DataType\Traits\QueryableBlock;
use HiFolks\DataType\Traits\ExportableBlock;
use HiFolks\DataType\Traits\IteratableBlock;
use HiFolks\DataType\Traits\LoadableBlock;
use Iterator;

/**
Expand All @@ -23,6 +25,8 @@ final class Block implements Iterator, ArrayAccess, Countable
use QueryableBlock;
use EditableBlock;
use ExportableBlock;
use LoadableBlock;
use IteratableBlock;

/** @var array<int|string, mixed> */
private array $data;
Expand All @@ -43,68 +47,7 @@ public function iterateBlock(bool $returnsBlock = true): self
}


public function current(): mixed
{
if ($this->iteratorReturnsBlock) {
$current = current($this->data);
if (is_array($current)) {
return self::make($current);
}
return $current;
}
return current($this->data);
}

public function next(): void
{
next($this->data);
}

/**
* Return the key of the current element
*
* @link https://php.net/manual/en/iterator.key.php
*
* @return string|int|null scalar on success, or null on failure.
*/
public function key(): string|int|null
{
return key($this->data);
}

public function valid(): bool
{
return !is_null($this->key());
}

public function rewind(): void
{
reset($this->data);
}

public function offsetExists(mixed $offset): bool
{
return array_key_exists($offset, $this->data);
}

public function offsetGet(mixed $offset): mixed
{
return $this->get($offset);
}

public function offsetSet(mixed $offset, mixed $value): void
{
if (is_null($offset)) {
$this->data[] = $value;
} else {
$this->data[$offset] = $value;
}
}

public function offsetUnset(mixed $offset): void
{
unset($this->data[$offset]);
}

/** @param array<int|string, mixed> $data */
public static function make(array $data = [], bool $iteratorReturnsBlock = true): self
Expand All @@ -119,35 +62,6 @@ public function count(): int
return count($this->data);
}

/**
* Get the array
* @return array<int|string, mixed>
*/
public function array(): array
{
return $this->data;
}

public static function fromJsonString(string $jsonString = "[]"): self
{
/** @var array<int|string, mixed> $json */
$json = json_decode($jsonString, associative: true);
return self::make($json);
}

public static function fromJsonFile(string $jsonFile): self
{
if (file_exists($jsonFile)) {
$content = file_get_contents($jsonFile);
if ($content === false) {
return self::make([]);
}
return self::fromJsonString($content);
}
return self::make([]);
}



/** @param array<int|string, mixed> $encodedJson */
public static function fromEncodedJson(mixed $encodedJson): self
Expand Down Expand Up @@ -180,19 +94,7 @@ public function get(mixed $key, mixed $defaultValue = null, string $charNestedKe
return $this->data[$key] ?? $defaultValue;
}

public function json(): string|bool
{
return json_encode($this->data);
}
public function jsonObject(): mixed
{
$jsonString = json_encode($this->data);
if ($jsonString === false) {
return false;
}

return json_decode($jsonString, associative:false);
}


/**
Expand Down
20 changes: 20 additions & 0 deletions src/Traits/ExportableBlock.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace HiFolks\DataType\Traits;

use Symfony\Component\Yaml\Yaml;

trait ExportableBlock
{
/**
Expand All @@ -22,4 +24,22 @@ public function toJson(): string|false
{
return json_encode($this->data, JSON_PRETTY_PRINT);
}

public function toJsonObject(): mixed
{
$jsonString = json_encode($this->data);
if ($jsonString === false) {
return false;
}
return json_decode($jsonString, associative: false);
}


/**
* Returns the YAML String
*/
public function toYaml(): string
{
return Yaml::dump($this->data, 3, 2);
}
}
69 changes: 69 additions & 0 deletions src/Traits/IteratableBlock.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

namespace HiFolks\DataType\Traits;

trait IteratableBlock
{
public function current(): mixed
{
if ($this->iteratorReturnsBlock) {
$current = current($this->data);
if (is_array($current)) {
return self::make($current);
}
return $current;
}
return current($this->data);
}

public function next(): void
{
next($this->data);
}

/**
* Return the key of the current element
*
* @link https://php.net/manual/en/iterator.key.php
*
* @return string|int|null scalar on success, or null on failure.
*/
public function key(): string|int|null
{
return key($this->data);
}

public function valid(): bool
{
return !is_null($this->key());
}

public function rewind(): void
{
reset($this->data);
}

public function offsetExists(mixed $offset): bool
{
return array_key_exists($offset, $this->data);
}

public function offsetGet(mixed $offset): mixed
{
return $this->get($offset);
}

public function offsetSet(mixed $offset, mixed $value): void
{
if (is_null($offset)) {
$this->data[] = $value;
} else {
$this->data[$offset] = $value;
}
}

public function offsetUnset(mixed $offset): void
{
unset($this->data[$offset]);
}
}
46 changes: 46 additions & 0 deletions src/Traits/LoadableBlock.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

namespace HiFolks\DataType\Traits;

use Symfony\Component\Yaml\Yaml;

trait LoadableBlock
{
public static function fromJsonString(string $jsonString = "[]"): self
{
/** @var array<int|string, mixed> $json */
$json = json_decode($jsonString, associative: true);
return self::make($json);
}

public static function fromJsonFile(string $jsonFile): self
{
if (file_exists($jsonFile)) {
$content = file_get_contents($jsonFile);
if ($content === false) {
return self::make([]);
}
return self::fromJsonString($content);
}
return self::make([]);
}

public static function fromYamlFile(string $yamlFile): self
{
if (file_exists($yamlFile)) {
$content = file_get_contents($yamlFile);
if ($content === false) {
return self::make([]);
}
return self::fromYamlString($content);
}
return self::make([]);
}

public static function fromYamlString(string $yamlString = ""): self
{
/** @var array<int|string, mixed> $yaml */
$yaml = Yaml::parse($yamlString);
return self::make($yaml);
}
}
5 changes: 5 additions & 0 deletions tests/Architecture/BasicTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php

arch('globals')
->expect(['dd', 'dump'])
->not->toBeUsed();
25 changes: 25 additions & 0 deletions tests/Feature/BlockTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,28 @@
expect($array["authors"][0]["name"])->toBe("Roberto B.");

});


it('load YAML object', function (): void {
$file = "./.github/workflows/run-tests.yml";
$workflow = Block::fromYamlFile($file);
expect($workflow->get("on"))->toBeArray();
expect($workflow->get("on"))->toHaveCount(2);
expect($workflow->get("on.0"))->toBe("push");
expect($workflow->get("on.1"))->toBe("pull_request");
expect($workflow->get("jobs.test.runs-on"))->toBe('${{ matrix.os }}');


});

it('Convert Json to Yaml', function (): void {
$file = "./composer.json";
$composer1 = Block::fromJsonFile($file);
$yaml = $composer1->toYaml();
$composer2 = Block::fromYamlString($yaml);
expect($composer2->get("name"))->toBe("hi-folks/data-block");
expect($composer2->get("authors.0.name"))->toBe("Roberto B.");
echo $yaml;


});
Loading

0 comments on commit c86355a

Please sign in to comment.