Skip to content

Instantly share code, notes, and snippets.

@xwero
Created November 23, 2025 17:52
Show Gist options
  • Select an option

  • Save xwero/8963539599b493972ddcc1307aab41a4 to your computer and use it in GitHub Desktop.

Select an option

Save xwero/8963539599b493972ddcc1307aab41a4 to your computer and use it in GitHub Desktop.
<?php
declare(strict_types=1);
namespace App\Pages\Frontend;
use App\NotFound;
use App\Pages\Database\FieldBooleanValues;
use App\Pages\Database\FieldFloatValues;
use App\Pages\Database\FieldIntegerValues;
use App\Pages\Database\FieldLongTextValues;
use App\Pages\Database\FieldShortTextValues;
use App\Pages\Database\Pages;
use App\PostgresSettings;
use Xwero\IdableQueriesCore\AliasCollection;
use Xwero\IdableQueriesCore\Error;
use Xwero\IdableQueriesCore\IdableParameterCollection;
use Xwero\IdableQueriesCore\MapCollection;
use function Xwero\IdableQueriesCore\buildAliasesMapCollection;
use function Xwero\IdableQueriesCore\createMapFromFirstLevelResults;
use function Xwero\IdableQueriesRelational\buildStatement;
use function Xwero\IdableQueriesRelational\getRow;
use function Xwero\IdableQueriesRelational\getRows;
use function Xwero\IdableQueriesRelational\getSecondLevelMapCollection;
class PostgresPageRepository implements PageRepository
{
private string $getFieldValuesByPageId = "
SELECT fbv.~FieldBooleanValues:Value boolean, null as float, null as integer, null as long_text, null as short_text, pffbv.~PageFieldBooleanValues:Weight as weight
FROM ~PageFieldBooleanValues:PageFieldBooleanValues pffbv
LEFT JOIN ~FieldBooleanValues:FieldBooleanValues fbv on fbv.~FieldBooleanValues:Id = pffbv.~PageFieldBooleanValues:FieldId
WHERE pffbv.~PageFieldBooleanValues:PageId = :Pages:Id
UNION ALL
SELECT null as boolean, ffv.~FieldFloatValues:Value::text float, null as integer, null as long_text, null as short_text, pfffv.~PageFieldFloatValues:Weight as weight
FROM ~PageFieldFloatValues:PageFieldFloatValues pfffv
LEFT JOIN ~FieldFloatValues:FieldFloatValues ffv on ffv.~FieldFloatValues:Id = pfffv.~PageFieldFloatValues:FieldId
WHERE pfffv.~PageFieldFloatValues:PageId = :Pages:Id
UNION ALL
SELECT null as boolean, null as float, fiv.~FieldIntegerValues:Value::text integer, null as long_text, null as short_text, pffiv.~PageFieldIntegerValues:Weight as weight
FROM ~PageFieldIntegerValues:PageFieldIntegerValues pffiv
LEFT JOIN ~FieldIntegerValues:FieldIntegerValues fiv on fiv.~FieldIntegerValues:Id = pffiv.~PageFieldIntegerValues:FieldId
WHERE pffiv.~PageFieldIntegerValues:PageId = :Pages:Id
UNION ALL
SELECT null as boolean, null as float, null as integer, fltv.~FieldLongTextValues:Value long_text, null as short_text, pffltv.~PageFieldLongTextValues:Weight as weight
FROM ~PageFieldLongTextValues:PageFieldLongTextValues pffltv
LEFT JOIN ~FieldLongTextValues:FieldLongTextValues fltv on fltv.~FieldLongTextValues:Id = pffltv.~PageFieldLongTextValues:FieldId
WHERE pffltv.~PageFieldLongTextValues:PageId = :Pages:Id
UNION ALL
SELECT null as boolean, null as float, null as integer, null as long_text, fstv.~FieldShortTextValues:Value short_text, pffstv.~PageFieldShortTextValues:Weight as weight
FROM ~PageFieldShortTextValues:PageFieldShortTextValues pffstv
LEFT JOIN ~FieldShortTextValues:FieldShortTextValues fstv on fstv.~FieldShortTextValues:Id = pffstv.~PageFieldShortTextValues:FieldId
WHERE pffstv.~PageFieldShortTextValues:PageId = :Pages:Id
;
";
public function __construct(private PostgresSettings $settings)
{}
public function getPageByUrl(string $url): Error|NotFound|Page
{
$query = "SELECT ~Pages:Id, ~Pages:Name, ~Pages:Url FROM ~Pages:Pages WHERE ~Pages:Url = :Pages:Url";
$page = $this->getPage(
$query,
new IdableParameterCollection()->add(Pages::Url, $url),
);
if($page instanceof Error) {
return $page;
}
if(count($page) === 0) {
return new NotFound(Pages::Pages, $url);
}
$pageMap = createMapFromFirstLevelResults($page, $query, namespaces: $this->settings->namespaces);
$mapCollection = $this->getFieldValueMapCollectionByPageId((int) $pageMap[Pages::Id]);
if($mapCollection instanceof Error) {
return $mapCollection;
}
return new Page($pageMap[Pages::Id], $pageMap[Pages::Name], $pageMap[Pages::Url], $mapCollection);
}
public function getPageById(int $id): Error|NotFound|Page
{
$query = "SELECT ~Pages:Name, ~Pages:Url FROM ~Pages:Pages WHERE ~Pages:Id = :Pages:Id";
$page = $this->getPage(
$query,
new IdableParameterCollection()->add(Pages::Id, $id),
);
if($page instanceof Error) {
return $page;
}
if(count($page) === 0) {
return new NotFound(Pages::Pages, (string) $id);
}
$pageMap = createMapFromFirstLevelResults($page, $query, namespaces: $this->settings->namespaces);
$mapCollection = $this->getFieldValueMapCollectionByPageId((int) $id);
if($mapCollection instanceof Error) {
return $mapCollection;
}
return new Page($id, $pageMap[Pages::Name], $pageMap[Pages::Url], $mapCollection);
}
public function getPages(): MapCollection|Error
{
$query = "SELECT ~Pages:Id, ~Pages:Name, ~Pages:Url FROM ~Pages:Pages";
return getSecondLevelMapCollection(
buildStatement(
$this->settings->connection,
$query,
namespaces: $this->settings->namespaces,
),
$query,
);
}
private function getPage(string $query, IdableParameterCollection $parameters): Error|array
{
return getRow(
buildStatement(
$this->settings->connection,
$query,
$parameters,
$this->settings->namespaces
),
);
}
private function getFieldValueMapCollectionByPageId(int $pageId): Error|MapCollection
{
$data = getRows(
buildStatement(
$this->settings->connection,
$this->getFieldValuesByPageId,
new IdableParameterCollection()->add(Pages::Id, $pageId),
$this->settings->namespaces
)
);
if($data instanceof Error) {
return $data;
}
usort($data, fn($a, $b) => $a['weight'] <=> $b['weight']);
$aliasValueFilter = fn($i): bool => is_string($i);
$aliases = AliasCollection::createWithAlias('boolean', FieldBooleanValues::Value, fn($i): bool => Is_bool($i))
->add('float', FieldFloatValues::Value, $aliasValueFilter)
->add('integer', FieldIntegerValues::Value, $aliasValueFilter)
->add('long_text', FieldLongTextValues::Value, $aliasValueFilter)
->add('short_text', FieldShortTextValues::Value, $aliasValueFilter)
;
return buildAliasesMapCollection($data, $aliases);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment