-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9520b24
commit 20d873c
Showing
13 changed files
with
782 additions
and
353 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Focus\Data\KeyedData; | ||
|
||
use ArrayAccess; | ||
use InvalidArgumentException; | ||
|
||
use function gettype; | ||
use function is_array; | ||
use function is_object; | ||
use function vsprintf; | ||
|
||
final readonly class KeyedDataFactory | ||
{ | ||
public static function from(mixed $value): KeyedDataArray|KeyedDataObject | ||
{ | ||
if (is_array($value) || $value instanceof ArrayAccess) { | ||
return new KeyedDataArray($value); | ||
} | ||
|
||
if (is_object($value)) { | ||
return new KeyedDataObject($value); | ||
} | ||
|
||
throw new InvalidArgumentException( | ||
message: vsprintf(format: 'Cannot create KeyedDataObject or KeyedDataArray from %s', values: [ | ||
gettype($value), | ||
]), | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Focus\Data\KeyedData; | ||
|
||
use Focus\Data\Data; | ||
use JmesPath\Env as JmesPath; | ||
use RuntimeException; | ||
use stdClass; | ||
|
||
use function explode; | ||
use function gettype; | ||
use function is_object; | ||
use function preg_match; | ||
use function property_exists; | ||
use function trim; | ||
use function vsprintf; | ||
|
||
final readonly class KeyedDataObject implements Data | ||
{ | ||
public static function from(object $value): self | ||
{ | ||
return new self($value); | ||
} | ||
|
||
public static function tryFrom(mixed $value): KeyedDataObject | ||
{ | ||
if ($value === null) { | ||
return new self(); | ||
} | ||
|
||
return KeyedDataFactory::from($value); | ||
} | ||
|
||
public function __construct( | ||
private object $value = new stdClass(), | ||
) { | ||
} | ||
|
||
public function jsonSerialize(): object | ||
{ | ||
return $this->value; | ||
} | ||
|
||
public function has(string $path): bool | ||
{ | ||
$data = $this->value; | ||
|
||
foreach ($this->expand($path) as $key) { | ||
if (is_object($data)) { | ||
if (! property_exists($data, $key)) { | ||
return false; | ||
} | ||
|
||
$data = $data->$key; | ||
} else { | ||
return false; | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
|
||
public function get(string $path): mixed | ||
{ | ||
$data = $this->value; | ||
|
||
foreach ($this->expand($path) as $key) { | ||
if (is_object($data)) { | ||
$data = $data->$key ?? null; | ||
} else { | ||
throw new RuntimeException( | ||
message: vsprintf(format: 'Cannot follow path %s into type %s', values: [ | ||
$path, | ||
gettype($data), | ||
]), | ||
); | ||
} | ||
} | ||
|
||
return $data; | ||
} | ||
|
||
public function search(string $path): mixed | ||
{ | ||
if (preg_match(pattern: '/^[a-zA-Z0-9_.-]+$/', subject: $path)) { | ||
return $this->get($path); | ||
} | ||
|
||
return JmesPath::search($path, $this->value); | ||
} | ||
|
||
private function expand(string $path): array | ||
{ | ||
// The path SHOULD be written as keys separated by periods. | ||
return explode(separator: '.', string: trim($path, characters: '.')); | ||
} | ||
} |
Oops, something went wrong.