Migrate remaining implementation
This commit is contained in:
@@ -34,4 +34,19 @@ class Document
|
||||
{
|
||||
Custom::nonQuery(Query::save($tableName), Parameters::json('@data', $document), $pdo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update (replace) an entire document by its ID
|
||||
*
|
||||
* @param string $tableName The table in which the document should be updated
|
||||
* @param mixed $docId The ID of the document to be updated
|
||||
* @param array|object $document The document to be updated
|
||||
* @param PDO|null $pdo The database connection to use (optional; will obtain one if not provided)
|
||||
* @throws DocumentException If any is encountered
|
||||
*/
|
||||
public static function update(string $tableName, mixed $docId, array|object $document, ?PDO $pdo = null): void
|
||||
{
|
||||
Custom::nonQuery(Query::update($tableName),
|
||||
array_merge(Parameters::id($docId), Parameters::json('@data', $document)), $pdo);
|
||||
}
|
||||
}
|
||||
|
||||
44
src/Exists.php
Normal file
44
src/Exists.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace BitBadger\PDODocument;
|
||||
|
||||
use BitBadger\PDODocument\Mapper\ExistsMapper;
|
||||
use PDO;
|
||||
|
||||
/**
|
||||
* Functions to determine if documents exist
|
||||
*/
|
||||
class Exists
|
||||
{
|
||||
/**
|
||||
* Determine if a document exists for the given ID
|
||||
*
|
||||
* @param string $tableName The name of the table in which document existence should be determined
|
||||
* @param mixed $docId The ID of the document whose existence should be determined
|
||||
* @param PDO|null $pdo The database connection to use (optional; will obtain one if not provided)
|
||||
* @return bool True if the document exists, false if not
|
||||
* @throws DocumentException If any is encountered
|
||||
*/
|
||||
public static function byId(string $tableName, mixed $docId, ?PDO $pdo = null): bool
|
||||
{
|
||||
return Custom::scalar(Query\Exists::byId($tableName), Parameters::id($docId), new ExistsMapper(), $pdo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a document exists using a comparison on JSON fields
|
||||
*
|
||||
* @param string $tableName The name of the table in which document existence should be determined
|
||||
* @param Field[] $fields The field comparison to match
|
||||
* @param PDO|null $pdo The database connection to use (optional; will obtain one if not provided)
|
||||
* @param string $conjunction How to handle multiple conditions (optional; defaults to `AND`)
|
||||
* @return bool True if any documents match the field comparison, false if not
|
||||
* @throws DocumentException If any is encountered
|
||||
*/
|
||||
public static function byFields(string $tableName, array $fields, ?PDO $pdo = null,
|
||||
string $conjunction = 'AND'): bool
|
||||
{
|
||||
$namedFields = Parameters::nameFields($fields);
|
||||
return Custom::scalar(Query\Exists::byFields($tableName, $namedFields, $conjunction),
|
||||
Parameters::addFields($namedFields, []), new ExistsMapper(), $pdo);
|
||||
}
|
||||
}
|
||||
78
src/Find.php
Normal file
78
src/Find.php
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace BitBadger\PDODocument;
|
||||
|
||||
use BitBadger\PDODocument\Mapper\DocumentMapper;
|
||||
|
||||
/**
|
||||
* Functions to find documents
|
||||
*/
|
||||
class Find
|
||||
{
|
||||
/**
|
||||
* Retrieve all documents in the given table
|
||||
*
|
||||
* @template TDoc The type of document to be retrieved
|
||||
* @param string $tableName The table from which documents should be retrieved
|
||||
* @param class-string<TDoc> $className The name of the class to be retrieved
|
||||
* @return DocumentList<TDoc> A list of all documents from the table
|
||||
* @throws DocumentException If any is encountered
|
||||
*/
|
||||
public static function all(string $tableName, string $className): DocumentList
|
||||
{
|
||||
return Custom::list(Query::selectFromTable($tableName), [], new DocumentMapper($className));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a document by its ID (returns false if not found)
|
||||
*
|
||||
* @template TDoc The type of document to be retrieved
|
||||
* @param string $tableName The table from which the document should be retrieved
|
||||
* @param mixed $docId The ID of the document to retrieve
|
||||
* @param class-string<TDoc> $className The name of the class to be retrieved
|
||||
* @return false|TDoc The document if it exists, false if not
|
||||
* @throws DocumentException If any is encountered
|
||||
*/
|
||||
public static function byId(string $tableName, mixed $docId, string $className): mixed
|
||||
{
|
||||
return Custom::single(Query\Find::byId($tableName), Parameters::id($docId), new DocumentMapper($className));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve documents via a comparison on JSON fields
|
||||
*
|
||||
* @template TDoc The type of document to be retrieved
|
||||
* @param string $tableName The table from which documents should be retrieved
|
||||
* @param array|Field[] $fields The field comparison to match
|
||||
* @param class-string<TDoc> $className The name of the class to be retrieved
|
||||
* @param string $conjunction How to handle multiple conditions (optional; defaults to `AND`)
|
||||
* @return DocumentList<TDoc> A list of documents matching the given field comparison
|
||||
* @throws DocumentException If any is encountered
|
||||
*/
|
||||
public static function byFields(string $tableName, array $fields, string $className,
|
||||
string $conjunction = 'AND'): DocumentList
|
||||
{
|
||||
$namedFields = Parameters::nameFields($fields);
|
||||
return Custom::list(Query\Find::byFields($tableName, $namedFields, $conjunction),
|
||||
Parameters::addFields($namedFields, []), new DocumentMapper($className));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve documents via a comparison on JSON fields, returning only the first result
|
||||
*
|
||||
* @template TDoc The type of document to be retrieved
|
||||
* @param string $tableName The table from which the document should be retrieved
|
||||
* @param array|Field[] $fields The field comparison to match
|
||||
* @param class-string<TDoc> $className The name of the class to be retrieved
|
||||
* @param string $conjunction How to handle multiple conditions (optional; defaults to `AND`)
|
||||
* @return false|TDoc The first document if any matches are found, false otherwise
|
||||
* @throws DocumentException If any is encountered
|
||||
*/
|
||||
public static function firstByFields(string $tableName, array $fields, string $className,
|
||||
string $conjunction = 'AND'): mixed
|
||||
{
|
||||
$namedFields = Parameters::nameFields($fields);
|
||||
return Custom::single(Query\Find::byFields($tableName, $namedFields, $conjunction),
|
||||
Parameters::addFields($namedFields, []), new DocumentMapper($className));
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace BitBadger\PDODocument\Mapper;
|
||||
|
||||
use BitBadger\PDODocument\DocumentException;
|
||||
use JsonMapper;
|
||||
use JsonMapper_Exception;
|
||||
|
||||
/**
|
||||
@@ -11,7 +12,7 @@ use JsonMapper_Exception;
|
||||
* @template TDoc The type of document returned by this mapper
|
||||
* @implements Mapper<TDoc> Provide a mapping from JSON
|
||||
*/
|
||||
class JsonMapper implements Mapper
|
||||
class DocumentMapper implements Mapper
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
@@ -35,7 +36,7 @@ class JsonMapper implements Mapper
|
||||
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);
|
||||
return (new JsonMapper())->map($json, $this->className);
|
||||
} catch (JsonMapper_Exception $ex) {
|
||||
throw new DocumentException("Could not map document for $this->className", previous: $ex);
|
||||
}
|
||||
44
src/Patch.php
Normal file
44
src/Patch.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace BitBadger\PDODocument;
|
||||
|
||||
use PDO;
|
||||
|
||||
/**
|
||||
* Functions to patch (partially update) documents
|
||||
*/
|
||||
class Patch
|
||||
{
|
||||
/**
|
||||
* Patch a document by its ID
|
||||
*
|
||||
* @param string $tableName The table in which the document should be patched
|
||||
* @param mixed $docId The ID of the document to be patched
|
||||
* @param array|object $patch The object with which the document should be patched (will be JSON-encoded)
|
||||
* @param PDO|null $pdo The database connection to use (optional; will obtain one if not provided)
|
||||
* @throws DocumentException If any is encountered (database mode must be set)
|
||||
*/
|
||||
public static function byId(string $tableName, mixed $docId, array|object $patch, ?PDO $pdo = null): void
|
||||
{
|
||||
Custom::nonQuery(Query\Patch::byId($tableName),
|
||||
array_merge(Parameters::id($docId), Parameters::json('@data', $patch)), $pdo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Patch documents using a comparison on JSON fields
|
||||
*
|
||||
* @param string $tableName The table in which documents should be patched
|
||||
* @param array|Field[] $fields The field comparison to match
|
||||
* @param array|object $patch The object with which the documents should be patched (will be JSON-encoded)
|
||||
* @param PDO|null $pdo The database connection to use (optional; will obtain one if not provided)
|
||||
* @param string $conjunction How to handle multiple conditions (optional; defaults to `AND`)
|
||||
* @throws DocumentException If any is encountered
|
||||
*/
|
||||
public static function byFields(string $tableName, array $fields, array|object $patch, ?PDO $pdo = null,
|
||||
string $conjunction = 'AND'): void
|
||||
{
|
||||
$namedFields = Parameters::nameFields($fields);
|
||||
Custom::nonQuery(Query\Patch::byFields($tableName, $namedFields, $conjunction),
|
||||
Parameters::addFields($namedFields, Parameters::json('@data', $patch)), $pdo);
|
||||
}
|
||||
}
|
||||
70
src/Query/RemoveFields.php
Normal file
70
src/Query/RemoveFields.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace BitBadger\PDODocument\Query;
|
||||
|
||||
use BitBadger\PDODocument\Configuration;
|
||||
use BitBadger\PDODocument\DocumentException;
|
||||
use BitBadger\PDODocument\Field;
|
||||
use BitBadger\PDODocument\Mode;
|
||||
use BitBadger\PDODocument\Query;
|
||||
|
||||
/**
|
||||
* Queries to remove fields from documents
|
||||
*
|
||||
* _NOTE: When using these queries to build custom functions, be aware that different databases use significantly
|
||||
* different syntax. The `$parameters` passed to these functions should be run through `Parameters::fieldNames`
|
||||
* function to generate them appropriately for the database currently being targeted._
|
||||
*/
|
||||
class RemoveFields
|
||||
{
|
||||
/**
|
||||
* Create an UPDATE statement to remove fields from a JSON document
|
||||
*
|
||||
* @param string $tableName The name of the table in which documents should be manipulated
|
||||
* @param array $parameters The parameter list for the query
|
||||
* @param string $whereClause The body of the WHERE clause for the update
|
||||
* @return string The UPDATE statement to remove fields from a JSON document
|
||||
* @throws DocumentException If the database mode has not been set
|
||||
*/
|
||||
public static function update(string $tableName, array $parameters, string $whereClause): string
|
||||
{
|
||||
switch (Configuration::$mode) {
|
||||
case Mode::PgSQL:
|
||||
return "UPDATE $tableName SET data = data - " . array_keys($parameters)[0] . " WHERE $whereClause";
|
||||
case Mode::SQLite:
|
||||
$paramNames = implode(', ', array_keys($parameters));
|
||||
return "UPDATE $tableName SET data = json_remove(data, $paramNames) WHERE $whereClause";
|
||||
default:
|
||||
throw new DocumentException('Database mode not set; cannot generate field removal query');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query to remove fields from a document by the document's ID
|
||||
*
|
||||
* @param string $tableName The name of the table in which the document should be manipulated
|
||||
* @param array $parameters The parameter list for the query
|
||||
* @return string The UPDATE statement to remove fields from a document by its ID
|
||||
* @throws DocumentException If the database mode has not been set
|
||||
*/
|
||||
public static function byId(string $tableName, array $parameters): string
|
||||
{
|
||||
return self::update($tableName, $parameters, Query::whereById());
|
||||
}
|
||||
|
||||
/**
|
||||
* Query to remove fields from documents via a comparison on JSON fields within the document
|
||||
*
|
||||
* @param string $tableName The name of the table in which documents should be manipulated
|
||||
* @param array|Field[] $fields The field comparison to match
|
||||
* @param array $parameters The parameter list for the query
|
||||
* @param string $conjunction How to handle multiple conditions (optional; defaults to `AND`)
|
||||
* @return string The UPDATE statement to remove fields from documents via field comparison
|
||||
* @throws DocumentException If the database mode has not been set
|
||||
*/
|
||||
public static function byFields(string $tableName, array $fields, array $parameters,
|
||||
string $conjunction = 'AND'): string
|
||||
{
|
||||
return self::update($tableName, $parameters, Query::whereByFields($fields, $conjunction));
|
||||
}
|
||||
}
|
||||
46
src/RemoveFields.php
Normal file
46
src/RemoveFields.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace BitBadger\PDODocument;
|
||||
|
||||
use PDO;
|
||||
|
||||
/**
|
||||
* Functions to remove fields from documents
|
||||
*/
|
||||
class RemoveFields
|
||||
{
|
||||
/**
|
||||
* Remove fields from a document by the document's ID
|
||||
*
|
||||
* @param string $tableName The table in which the document should have fields removed
|
||||
* @param mixed $docId The ID of the document from which fields should be removed
|
||||
* @param array|string[] $fieldNames The names of the fields to be removed
|
||||
* @param PDO|null $pdo The database connection to use (optional; will obtain one if not provided)
|
||||
* @throws DocumentException If any is encountered
|
||||
*/
|
||||
public static function byId(string $tableName, mixed $docId, array $fieldNames, ?PDO $pdo = null): void
|
||||
{
|
||||
$nameParams = Parameters::fieldNames('@name', $fieldNames);
|
||||
Custom::nonQuery(Query\RemoveFields::byId($tableName, $nameParams),
|
||||
array_merge(Parameters::id($docId), $nameParams), $pdo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove fields from documents via a comparison on a JSON field in the document
|
||||
*
|
||||
* @param string $tableName The table in which documents should have fields removed
|
||||
* @param array|Field[] $fields The field comparison to match
|
||||
* @param array|string[] $fieldNames The names of the fields to be removed
|
||||
* @param PDO|null $pdo The database connection to use (optional; will obtain one if not provided)
|
||||
* @param string $conjunction How to handle multiple conditions (optional; defaults to `AND`)
|
||||
* @throws DocumentException If any is encountered
|
||||
*/
|
||||
public static function byFields(string $tableName, array $fields, array $fieldNames, ?PDO $pdo = null,
|
||||
string $conjunction = 'AND'): void
|
||||
{
|
||||
$nameParams = Parameters::fieldNames('@name', $fieldNames);
|
||||
$namedFields = Parameters::nameFields($fields);
|
||||
Custom::nonQuery(Query\RemoveFields::byFields($tableName, $namedFields, $nameParams, $conjunction),
|
||||
Parameters::addFields($namedFields, $nameParams), $pdo);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user