Files
pdo-document/src/Mapper/DocumentMapper.php

54 lines
1.7 KiB
PHP

<?php
/**
* @author Daniel J. Summers <daniel@bitbadger.solutions>
* @license MIT
*/
declare(strict_types=1);
namespace BitBadger\PDODocument\Mapper;
use BitBadger\PDODocument\DocumentException;
use Exception;
use JsonMapper;
/**
* Map domain class instances from JSON documents
*
* @template TDoc The type of document returned by this mapper
* @implements Mapper<TDoc> Provide a mapping from JSON
*/
class DocumentMapper implements Mapper
{
/**
* Constructor
*
* @param class-string<TDoc> $className The type of class to be returned by this mapping
* @param string $fieldName The name of the field (optional; defaults to `data`)
*/
public function __construct(public string $className, public string $fieldName = 'data') {}
/**
* Map a result to a domain class instance
*
* @param array $result An associative array representing a single database result
* @return TDoc The document, deserialized from its JSON representation
* @throws DocumentException If the JSON cannot be deserialized
*/
public function map(array $result): mixed
{
try {
if (method_exists($this->className, 'fromJsonString')) {
return $this->className::fromJsonString($result[$this->fieldName]);
}
$json = json_decode($result[$this->fieldName]);
if (is_null($json)) {
throw new DocumentException("Could not map document for $this->className: " . json_last_error_msg());
}
return (new JsonMapper())->map($json, $this->className);
} catch (Exception $ex) {
throw new DocumentException("Could not map document for $this->className", previous: $ex);
}
}
}