PHP 8.4 upgrades.
This commit is contained in:
parent
9344d438bf
commit
2640a755a0
22 changed files with 206 additions and 434 deletions
|
@ -26,7 +26,7 @@ if(file_exists(MKI_ROOT . '/.migrating')) {
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
$makai->getCSRFP()->setInfo(
|
$makai->csrfp->setInfo(
|
||||||
$cfg->getString('csrfp:secret', 'meow'),
|
$cfg->getString('csrfp:secret', 'meow'),
|
||||||
(string)filter_input(INPUT_SERVER, 'REMOTE_ADDR')
|
(string)filter_input(INPUT_SERVER, 'REMOTE_ADDR')
|
||||||
);
|
);
|
||||||
|
|
|
@ -12,6 +12,6 @@ class AssetsRoutes implements RouteHandler {
|
||||||
|
|
||||||
#[HttpGet('/header-bgs.json')]
|
#[HttpGet('/header-bgs.json')]
|
||||||
public function getHeaderImages(): array {
|
public function getHeaderImages(): array {
|
||||||
return $this->siteInfo->getHeaderImages();
|
return $this->siteInfo->headerImages;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,75 +5,43 @@ use Index\Colour\{Colour,ColourRgb};
|
||||||
use Index\Db\DbResult;
|
use Index\Db\DbResult;
|
||||||
|
|
||||||
class ContactInfo {
|
class ContactInfo {
|
||||||
private string $name;
|
public function __construct(
|
||||||
private bool $homePage;
|
public private(set) string $name,
|
||||||
private int $order;
|
public private(set) bool $homePage,
|
||||||
private string $title;
|
public private(set) int $order,
|
||||||
private string $icon;
|
public private(set) string $title,
|
||||||
private int $colour;
|
public private(set) string $icon,
|
||||||
private string $display;
|
public private(set) int $colourRaw,
|
||||||
private ?string $link;
|
public private(set) string $display,
|
||||||
|
public private(set) ?string $link,
|
||||||
|
) {}
|
||||||
|
|
||||||
public function __construct(DbResult $result) {
|
public static function fromResult(DbResult $result): ContactInfo {
|
||||||
$this->name = $result->getString(0);
|
return new ContactInfo(
|
||||||
$this->homePage = $result->getInteger(1) !== 0;
|
name: $result->getString(0),
|
||||||
$this->order = $result->getInteger(2);
|
homePage: $result->getBoolean(1),
|
||||||
$this->title = $result->getString(3);
|
order: $result->getInteger(2),
|
||||||
$this->icon = $result->getString(4);
|
title: $result->getString(3),
|
||||||
$this->colour = $result->getInteger(5);
|
icon: $result->getString(4),
|
||||||
$this->display = $result->getString(6);
|
colourRaw: $result->getInteger(5),
|
||||||
$this->link = $result->isNull(7) ? null : $result->getString(7);
|
display: $result->getString(6),
|
||||||
|
link: $result->getStringOrNull(7),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName(): string {
|
public bool $iconIsDomain {
|
||||||
return $this->name;
|
get => str_starts_with($this->icon, 'url:');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isHomePage(): bool {
|
public bool $iconIsImage {
|
||||||
return $this->homePage;
|
get => mb_strlen($this->icon) > 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getOrder(): int {
|
public string $iconDomain {
|
||||||
return $this->order;
|
get => substr($this->icon, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTitle(): string {
|
public Colour $colour {
|
||||||
return $this->title;
|
get => ColourRgb::fromRawRgb($this->colourRaw);
|
||||||
}
|
|
||||||
|
|
||||||
public function getIcon(): string {
|
|
||||||
return $this->icon;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function iconIsDomain(): bool {
|
|
||||||
return str_starts_with($this->icon, 'url:');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function iconIsImage(): bool {
|
|
||||||
return mb_strlen($this->icon) > 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getIconDomain(): string {
|
|
||||||
return substr($this->icon, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getColour(): Colour {
|
|
||||||
return ColourRgb::fromRawRgb($this->colour);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getColourRaw(): int {
|
|
||||||
return $this->colour;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getDisplay(): string {
|
|
||||||
return $this->display;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function hasLink(): bool {
|
|
||||||
return $this->link !== null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getLink(): ?string {
|
|
||||||
return $this->link;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ class Contacts {
|
||||||
public function getContacts(
|
public function getContacts(
|
||||||
bool $featuredOnly = false,
|
bool $featuredOnly = false,
|
||||||
?int $take = null
|
?int $take = null
|
||||||
): array {
|
): iterable {
|
||||||
$hasTake = $take !== null;
|
$hasTake = $take !== null;
|
||||||
|
|
||||||
$query = 'SELECT cont_name, cont_homepage, cont_order, cont_title, cont_icon, cont_colour, cont_display, cont_link FROM fm_contacts';
|
$query = 'SELECT cont_name, cont_homepage, cont_order, cont_title, cont_icon, cont_colour, cont_display, cont_link FROM fm_contacts';
|
||||||
|
@ -28,12 +28,6 @@ class Contacts {
|
||||||
$stmt->addParameter(1, $take);
|
$stmt->addParameter(1, $take);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
|
|
||||||
$result = $stmt->getResult();
|
return $stmt->getResult()->getIterator(ContactInfo::fromResult(...));
|
||||||
$contacts = [];
|
|
||||||
|
|
||||||
while($result->next())
|
|
||||||
$contacts[] = new ContactInfo($result);
|
|
||||||
|
|
||||||
return $contacts;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ class DeveloperRoutes implements RouteHandler {
|
||||||
foreach($projectInfos as $projectInfo)
|
foreach($projectInfos as $projectInfo)
|
||||||
$projects[] = [
|
$projects[] = [
|
||||||
'info' => $projectInfo,
|
'info' => $projectInfo,
|
||||||
'colour' => $projectInfo->hasColour() ? $projectInfo->getColour() : $this->projects->getProjectColour($projectInfo),
|
'colour' => $projectInfo->colourRaw !== null ? $projectInfo->colour : $this->projects->getProjectColour($projectInfo),
|
||||||
];
|
];
|
||||||
|
|
||||||
return $this->templating->render('dev/index', [
|
return $this->templating->render('dev/index', [
|
||||||
|
@ -43,7 +43,7 @@ class DeveloperRoutes implements RouteHandler {
|
||||||
$projects[] = [
|
$projects[] = [
|
||||||
'info' => $projectInfo,
|
'info' => $projectInfo,
|
||||||
'langs' => $this->projects->getLanguages(projectInfo: $projectInfo),
|
'langs' => $this->projects->getLanguages(projectInfo: $projectInfo),
|
||||||
'colour' => $projectInfo->hasColour() ? $projectInfo->getColour() : $this->projects->getProjectColour($projectInfo),
|
'colour' => $projectInfo->colourRaw !== null ? $projectInfo->colour : $this->projects->getProjectColour($projectInfo),
|
||||||
];
|
];
|
||||||
|
|
||||||
return $this->templating->render('dev/projects', [
|
return $this->templating->render('dev/projects', [
|
||||||
|
|
|
@ -6,18 +6,18 @@ use Index\Db\Migration\{DbMigrationRepo,DbMigrationManager,FsDbMigrationRepo};
|
||||||
use Index\Templating\TplEnvironment;
|
use Index\Templating\TplEnvironment;
|
||||||
|
|
||||||
final class MakaiContext {
|
final class MakaiContext {
|
||||||
private DbConnection $dbConn;
|
public private(set) TplEnvironment $templating;
|
||||||
private TplEnvironment $templating;
|
public private(set) CSRFPContainer $csrfp;
|
||||||
private CSRFPContainer $csrfp;
|
|
||||||
|
|
||||||
private SiteInfo $siteInfo;
|
public private(set) SiteInfo $siteInfo;
|
||||||
|
|
||||||
private Contacts\Contacts $contacts;
|
public private(set) Contacts\Contacts $contacts;
|
||||||
private Projects\Projects $projects;
|
public private(set) Projects\Projects $projects;
|
||||||
private SSHKeys\SSHKeys $sshKeys;
|
public private(set) SSHKeys\SSHKeys $sshKeys;
|
||||||
|
|
||||||
public function __construct(DbConnection $dbConn) {
|
public function __construct(
|
||||||
$this->dbConn = $dbConn;
|
public private(set) DbConnection $dbConn
|
||||||
|
) {
|
||||||
$this->siteInfo = new SiteInfo;
|
$this->siteInfo = new SiteInfo;
|
||||||
|
|
||||||
$this->csrfp = new CSRFPContainer;
|
$this->csrfp = new CSRFPContainer;
|
||||||
|
@ -28,26 +28,6 @@ final class MakaiContext {
|
||||||
$this->sshKeys = new SSHKeys\SSHKeys($dbConn);
|
$this->sshKeys = new SSHKeys\SSHKeys($dbConn);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSiteInfo(): SiteInfo {
|
|
||||||
return $this->siteInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getContacts(): Contacts\Contacts {
|
|
||||||
return $this->contacts;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getProjects(): Projects\Projects {
|
|
||||||
return $this->projects;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getSSHKeys(): SSHKeys\SSHKeys {
|
|
||||||
return $this->sshKeys;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getDbConn(): DbConnection {
|
|
||||||
return $this->dbConn;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getDbQueryCount(): int {
|
public function getDbQueryCount(): int {
|
||||||
$result = $this->dbConn->query('SHOW SESSION STATUS LIKE "Questions"');
|
$result = $this->dbConn->query('SHOW SESSION STATUS LIKE "Questions"');
|
||||||
return $result->next() ? $result->getInteger(1) : 0;
|
return $result->next() ? $result->getInteger(1) : 0;
|
||||||
|
@ -61,10 +41,6 @@ final class MakaiContext {
|
||||||
return new FsDbMigrationRepo(MKI_DIR_MIGRATIONS);
|
return new FsDbMigrationRepo(MKI_DIR_MIGRATIONS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTemplating(): TplEnvironment {
|
|
||||||
return $this->templating;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function startTemplating(): void {
|
public function startTemplating(): void {
|
||||||
$this->templating = new TplEnvironment(
|
$this->templating = new TplEnvironment(
|
||||||
MKI_DIR_TEMPLATES,
|
MKI_DIR_TEMPLATES,
|
||||||
|
@ -79,10 +55,6 @@ final class MakaiContext {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCSRFP(): CSRFPContainer {
|
|
||||||
return $this->csrfp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function createRouting(): RoutingContext {
|
public function createRouting(): RoutingContext {
|
||||||
$routingCtx = new RoutingContext;
|
$routingCtx = new RoutingContext;
|
||||||
|
|
||||||
|
|
|
@ -5,33 +5,21 @@ use Index\Colour\{Colour,ColourRgb};
|
||||||
use Index\Db\DbResult;
|
use Index\Db\DbResult;
|
||||||
|
|
||||||
class LanguageInfo {
|
class LanguageInfo {
|
||||||
private string $id;
|
public function __construct(
|
||||||
private string $name;
|
public private(set) string $id,
|
||||||
private ?int $colour;
|
public private(set) string $name,
|
||||||
|
public private(set) ?int $colourRaw,
|
||||||
|
) {}
|
||||||
|
|
||||||
public function __construct(DbResult $result) {
|
public static function fromResult(DbResult $result): LanguageInfo {
|
||||||
$this->id = $result->getString(0);
|
return new LanguageInfo(
|
||||||
$this->name = $result->getString(1);
|
id: $result->getString(0),
|
||||||
$this->colour = $result->isNull(2) ? null : $result->getInteger(2);
|
name: $result->getString(1),
|
||||||
|
colourRaw: $result->getIntegerOrNull(2),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getId(): string {
|
public Colour $colour {
|
||||||
return $this->id;
|
get => $this->colourRaw === null ? Colour::none() : ColourRgb::fromRawRGB($this->colourRaw);
|
||||||
}
|
|
||||||
|
|
||||||
public function getName(): string {
|
|
||||||
return $this->name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function hasColour(): bool {
|
|
||||||
return $this->colour !== null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getColour(): Colour {
|
|
||||||
return $this->colour === null ? Colour::none() : ColourRgb::fromRawRGB($this->colour);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getColourRaw(): ?int {
|
|
||||||
return $this->colour;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,149 +6,65 @@ use Index\Colour\{Colour,ColourRgb};
|
||||||
use Index\Db\DbResult;
|
use Index\Db\DbResult;
|
||||||
|
|
||||||
class ProjectInfo {
|
class ProjectInfo {
|
||||||
private string $id;
|
public function __construct(
|
||||||
private string $name;
|
public private(set) string $id,
|
||||||
private string $nameClean;
|
public private(set) string $name,
|
||||||
private ?string $summary;
|
public private(set) string $nameClean,
|
||||||
private ?string $description;
|
public private(set) ?string $summary,
|
||||||
private int $order;
|
public private(set) ?string $description,
|
||||||
private string $type;
|
public private(set) int $order,
|
||||||
private bool $featured;
|
public private(set) string $type,
|
||||||
private ?int $colour;
|
public private(set) bool $featured,
|
||||||
private ?string $homepage;
|
public private(set) ?int $colourRaw,
|
||||||
private ?string $source;
|
public private(set) ?string $homePageUrl,
|
||||||
private ?string $discussion;
|
public private(set) ?string $sourceUrl,
|
||||||
private int $createdAt;
|
public private(set) ?string $discussionUrl,
|
||||||
private ?int $archivedAt;
|
public private(set) int $createdTime,
|
||||||
private ?int $deletedAt;
|
public private(set) ?int $archivedTime,
|
||||||
|
public private(set) ?int $deletedTime,
|
||||||
|
) {}
|
||||||
|
|
||||||
public function __construct(DbResult $result) {
|
public static function fromResult(DbResult $result): ProjectInfo {
|
||||||
$this->id = $result->getString(0);
|
return new ProjectInfo(
|
||||||
$this->name = $result->getString(1);
|
id: $result->getString(0),
|
||||||
$this->nameClean = $result->getString(2);
|
name: $result->getString(1),
|
||||||
$this->summary = $result->isNull(3) ? null : $result->getString(3);
|
nameClean: $result->getString(2),
|
||||||
$this->description = $result->isNull(4) ? null : $result->getString(4);
|
summary: $result->getStringOrNull(3),
|
||||||
$this->order = $result->getInteger(5);
|
description: $result->getStringOrNull(4),
|
||||||
$this->type = $result->getString(6);
|
order: $result->getInteger(5),
|
||||||
$this->featured = $result->getInteger(7) !== 0;
|
type: $result->getString(6),
|
||||||
$this->colour = $result->isNull(8) ? null : $result->getInteger(8);
|
featured: $result->getBoolean(7),
|
||||||
$this->homepage = $result->isNull(9) ? null : $result->getString(9);
|
colourRaw: $result->getIntegerOrNull(8),
|
||||||
$this->source = $result->isNull(10) ? null : $result->getString(10);
|
homePageUrl: $result->getStringOrNull(9),
|
||||||
$this->discussion = $result->isNull(11) ? null : $result->getString(11);
|
sourceUrl: $result->getStringOrNull(10),
|
||||||
$this->createdAt = $result->getInteger(12);
|
discussionUrl: $result->getStringOrNull(11),
|
||||||
$this->archivedAt = $result->isNull(13) ? null : $result->getInteger(13);
|
createdTime: $result->getInteger(12),
|
||||||
$this->deletedAt = $result->isNull(14) ? null : $result->getInteger(14);
|
archivedTime: $result->getIntegerOrNull(13),
|
||||||
|
deletedTime: $result->getIntegerOrNull(14),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getId(): string {
|
public Colour $colour {
|
||||||
return $this->id;
|
get => $this->colourRaw === null ? Colour::none() : ColourRgb::fromRawRGB($this->colourRaw);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName(): string {
|
public CarbonImmutable $createdAt {
|
||||||
return $this->name;
|
get => CarbonImmutable::createFromTimestampUTC($this->createdTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCleanName(): string {
|
public ?CarbonImmutable $archivedAt {
|
||||||
return $this->nameClean;
|
get => $this->archivedTime === null ? null : CarbonImmutable::createFromTimestampUTC($this->archivedTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function hasSummary(): bool {
|
public bool $archived {
|
||||||
return $this->summary !== null;
|
get => $this->archivedTime !== null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSummary(): ?string {
|
public ?CarbonImmutable $deletedAt {
|
||||||
return $this->summary;
|
get => $this->deletedTime === null ? null : CarbonImmutable::createFromTimestampUTC($this->deletedTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function hasDescription(): bool {
|
public bool $deleted {
|
||||||
return $this->description !== null;
|
get => $this->deletedTime !== null;
|
||||||
}
|
|
||||||
|
|
||||||
public function getDescription(): ?string {
|
|
||||||
return $this->description;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isFeatured(): bool {
|
|
||||||
return $this->featured;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getOrder(): int {
|
|
||||||
return $this->order;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function hasColour(): bool {
|
|
||||||
return $this->colour !== null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getColour(): Colour {
|
|
||||||
return $this->colour === null ? Colour::none() : ColourRgb::fromRawRGB($this->colour);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getColourRaw(): ?int {
|
|
||||||
return $this->colour;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getProjectType(): string {
|
|
||||||
return $this->type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isTool(): bool {
|
|
||||||
return $this->getProjectType() === 'Tool';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function hasHomePageUrl(): bool {
|
|
||||||
return $this->homepage !== null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getHomePageUrl(): ?string {
|
|
||||||
return $this->homepage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function hasSourceUrl(): bool {
|
|
||||||
return $this->source !== null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getSourceUrl(): ?string {
|
|
||||||
return $this->source;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function hasDiscussionUrl(): bool {
|
|
||||||
return $this->discussion !== null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getDiscussionUrl(): ?string {
|
|
||||||
return $this->discussion;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getCreatedTime(): int {
|
|
||||||
return $this->createdAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getCreatedAt(): CarbonImmutable {
|
|
||||||
return CarbonImmutable::createFromTimestampUTC($this->createdAt);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getArchivedTime(): ?int {
|
|
||||||
return $this->archivedAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getArchivedAt(): ?CarbonImmutable {
|
|
||||||
return $this->archivedAt === null ? null : CarbonImmutable::createFromTimestampUTC($this->archivedAt);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isArchived(): bool {
|
|
||||||
return $this->archivedAt !== null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getDeletedTime(): ?int {
|
|
||||||
return $this->deletedAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getDeletedAt(): ?CarbonImmutable {
|
|
||||||
return $this->deletedAt === null ? null : CarbonImmutable::createFromTimestampUTC($this->deletedAt);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isDeleted(): bool {
|
|
||||||
return $this->deletedAt !== null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ class Projects {
|
||||||
?bool $deleted = null,
|
?bool $deleted = null,
|
||||||
?int $take = null,
|
?int $take = null,
|
||||||
bool $random = false
|
bool $random = false
|
||||||
): array {
|
): iterable {
|
||||||
$hasDeleted = $deleted !== null;
|
$hasDeleted = $deleted !== null;
|
||||||
$hasTake = $take !== null;
|
$hasTake = $take !== null;
|
||||||
|
|
||||||
|
@ -37,18 +37,12 @@ class Projects {
|
||||||
$stmt->addParameter(1, $take);
|
$stmt->addParameter(1, $take);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
|
|
||||||
$result = $stmt->getResult();
|
return $stmt->getResult()->getIterator(ProjectInfo::fromResult(...));
|
||||||
$projects = [];
|
|
||||||
|
|
||||||
while($result->next())
|
|
||||||
$projects[] = new ProjectInfo($result);
|
|
||||||
|
|
||||||
return $projects;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLanguages(
|
public function getLanguages(
|
||||||
ProjectInfo|string|null $projectInfo = null
|
ProjectInfo|string|null $projectInfo = null
|
||||||
): array {
|
): iterable {
|
||||||
$hasProjectInfo = $projectInfo !== null;
|
$hasProjectInfo = $projectInfo !== null;
|
||||||
|
|
||||||
$query = 'SELECT l.language_id, l.language_name, l.language_colour FROM fm_proglangs AS l';
|
$query = 'SELECT l.language_id, l.language_name, l.language_colour FROM fm_proglangs AS l';
|
||||||
|
@ -57,23 +51,17 @@ class Projects {
|
||||||
|
|
||||||
$stmt = $this->cache->get($query);
|
$stmt = $this->cache->get($query);
|
||||||
if($hasProjectInfo)
|
if($hasProjectInfo)
|
||||||
$stmt->addParameter(1, $projectInfo instanceof ProjectInfo ? $projectInfo->getId() : $projectInfo);
|
$stmt->addParameter(1, $projectInfo instanceof ProjectInfo ? $projectInfo->id : $projectInfo);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
|
|
||||||
$result = $stmt->getResult();
|
return $stmt->getResult()->getIterator(LanguageInfo::fromResult(...));
|
||||||
$langs = [];
|
|
||||||
|
|
||||||
while($result->next())
|
|
||||||
$langs[] = new LanguageInfo($result);
|
|
||||||
|
|
||||||
return $langs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getProjectColour(ProjectInfo|string $projectInfo): Colour {
|
public function getProjectColour(ProjectInfo|string $projectInfo): Colour {
|
||||||
$query = 'SELECT language_colour FROM fm_proglangs WHERE language_id = (SELECT language_id FROM fm_projects_proglangs WHERE project_id = ? ORDER BY priority ASC)';
|
$query = 'SELECT language_colour FROM fm_proglangs WHERE language_id = (SELECT language_id FROM fm_projects_proglangs WHERE project_id = ? ORDER BY priority ASC)';
|
||||||
|
|
||||||
$stmt = $this->cache->get($query);
|
$stmt = $this->cache->get($query);
|
||||||
$stmt->addParameter(1, $projectInfo instanceof ProjectInfo ? $projectInfo->getId() : $projectInfo);
|
$stmt->addParameter(1, $projectInfo instanceof ProjectInfo ? $projectInfo->id : $projectInfo);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
$result = $stmt->getResult();
|
$result = $stmt->getResult();
|
||||||
|
|
||||||
|
|
|
@ -4,17 +4,13 @@ namespace Makai;
|
||||||
use Index\Http\Routing\{HttpRouter,Router,RouteHandler};
|
use Index\Http\Routing\{HttpRouter,Router,RouteHandler};
|
||||||
|
|
||||||
class RoutingContext {
|
class RoutingContext {
|
||||||
private HttpRouter $router;
|
public private(set) HttpRouter $router;
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
$this->router = new HttpRouter(errorHandler: new RoutingErrorHandler);
|
$this->router = new HttpRouter(errorHandler: new RoutingErrorHandler);
|
||||||
$this->router->use('/', fn($resp) => $resp->setPoweredBy('Makai'));
|
$this->router->use('/', fn($resp) => $resp->setPoweredBy('Makai'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getRouter(): Router {
|
|
||||||
return $this->router;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function register(RouteHandler $handler): void {
|
public function register(RouteHandler $handler): void {
|
||||||
$this->router->register($handler);
|
$this->router->register($handler);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,72 +1,49 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Makai\SSHKeys;
|
namespace Makai\SSHKeys;
|
||||||
|
|
||||||
|
use Stringable;
|
||||||
use Carbon\CarbonImmutable;
|
use Carbon\CarbonImmutable;
|
||||||
use Index\Db\DbResult;
|
use Index\Db\DbResult;
|
||||||
|
|
||||||
class SSHKeyInfo {
|
class SSHKeyInfo implements Stringable {
|
||||||
private string $id;
|
public function __construct(
|
||||||
private int $level;
|
public private(set) string $id,
|
||||||
private string $algo;
|
public private(set) int $level,
|
||||||
private string $body;
|
public private(set) string $algo,
|
||||||
private string $comment;
|
public private(set) string $body,
|
||||||
private int $createdAt;
|
public private(set) string $comment,
|
||||||
private ?int $deprecatedAt;
|
public private(set) int $createdTime,
|
||||||
|
public private(set) ?int $deprecatedTime,
|
||||||
|
) {}
|
||||||
|
|
||||||
public function __construct(DbResult $result) {
|
public static function fromResult(DbResult $result): SSHKeyInfo {
|
||||||
$this->id = $result->getString(0);
|
return new SSHKeyInfo(
|
||||||
$this->level = $result->getInteger(1);
|
id: $result->getString(0),
|
||||||
$this->algo = $result->getString(2);
|
level: $result->getInteger(1),
|
||||||
$this->body = $result->getString(3);
|
algo: $result->getString(2),
|
||||||
$this->comment = $result->getString(4);
|
body: $result->getString(3),
|
||||||
$this->createdAt = $result->getInteger(5);
|
comment: $result->getString(4),
|
||||||
$this->deprecatedAt = $result->isNull(6) ? null : $result->getInteger(6);
|
createdTime: $result->getInteger(5),
|
||||||
|
deprecatedTime: $result->getIntegerOrNull(6),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getId(): string {
|
public CarbonImmutable $createdAt {
|
||||||
return $this->id;
|
get => CarbonImmutable::createFromTimestampUTC($this->createdTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLevel(): int {
|
public bool $deprecated {
|
||||||
return $this->level;
|
get => $this->deprecatedTime !== null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAlgorithm(): string {
|
public ?CarbonImmutable $deprecatedAt {
|
||||||
return $this->algo;
|
get => $this->deprecatedTime === null ? null : CarbonImmutable::createFromTimestampUTC($this->deprecatedTime);
|
||||||
}
|
|
||||||
|
|
||||||
public function getBody(): string {
|
|
||||||
return $this->body;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getComment(): string {
|
|
||||||
return $this->comment;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getCreatedTime(): int {
|
|
||||||
return $this->createdAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getCreatedAt(): CarbonImmutable {
|
|
||||||
return CarbonImmutable::createFromTimestampUTC($this->createdAt);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isDeprecated(): bool {
|
|
||||||
return $this->deprecatedAt !== null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getDeprecatedTime(): ?int {
|
|
||||||
return $this->deprecatedAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getDeprecatedAt(): ?CarbonImmutable {
|
|
||||||
return $this->deprecatedAt === null ? null : CarbonImmutable::createFromTimestampUTC($this->deprecatedAt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function toString(bool $includeComment): string {
|
public function toString(bool $includeComment): string {
|
||||||
$line = sprintf('ssh-%s %s', $this->getAlgorithm(), $this->getBody());
|
$line = sprintf('ssh-%s %s', $this->algo, $this->body);
|
||||||
if($includeComment)
|
if($includeComment)
|
||||||
$line .= sprintf(' %s (%s)', (string)$this->getComment(), $this->getCreatedAt()->format('M Y'));
|
$line .= sprintf(' %s (%s)', (string)$this->comment, $this->createdAt->format('M Y'));
|
||||||
return $line;
|
return $line;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ class SSHKeys {
|
||||||
public function getKeys(
|
public function getKeys(
|
||||||
?int $minLevel = null,
|
?int $minLevel = null,
|
||||||
?bool $deprecated = null,
|
?bool $deprecated = null,
|
||||||
): array {
|
): iterable {
|
||||||
$hasMinLevel = $minLevel !== null;
|
$hasMinLevel = $minLevel !== null;
|
||||||
$hasDeprecated = $deprecated !== null;
|
$hasDeprecated = $deprecated !== null;
|
||||||
|
|
||||||
|
@ -32,12 +32,6 @@ class SSHKeys {
|
||||||
$stmt->addParameter(1, $minLevel);
|
$stmt->addParameter(1, $minLevel);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
|
|
||||||
$result = $stmt->getResult();
|
return $stmt->getResult()->getIterator(SSHKeyInfo::fromResult(...));
|
||||||
$keys = [];
|
|
||||||
|
|
||||||
while($result->next())
|
|
||||||
$keys[] = new SSHKeyInfo($result);
|
|
||||||
|
|
||||||
return $keys;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,12 +24,12 @@ class SSHKeysRoutes implements RouteHandler {
|
||||||
|
|
||||||
foreach($keys as $key) {
|
foreach($keys as $key) {
|
||||||
$items[] = $item = new \stdClass;
|
$items[] = $item = new \stdClass;
|
||||||
$item->algo = $key->getAlgorithm();
|
$item->algo = $key->algo;
|
||||||
$item->key = $key->getBody();
|
$item->key = $key->body;
|
||||||
if($includeComment) {
|
if($includeComment) {
|
||||||
$item->comment = (string)$key->getComment();
|
$item->comment = (string)$key->comment;
|
||||||
$item->created = $key->getCreatedAt()->format(DateTimeInterface::ATOM);
|
$item->created = $key->createdAt->format(DateTimeInterface::ATOM);
|
||||||
$item->level = $key->getLevel();
|
$item->level = $key->level;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,15 +2,15 @@
|
||||||
namespace Makai;
|
namespace Makai;
|
||||||
|
|
||||||
class SiteInfo {
|
class SiteInfo {
|
||||||
public function getHeaderNavigation(): array {
|
public array $headerNavigation {
|
||||||
return [
|
get => [
|
||||||
['title' => 'Home', 'url' => '/'],
|
['title' => 'Home', 'url' => '/'],
|
||||||
['title' => 'Projects', 'url' => '/projects'],
|
['title' => 'Projects', 'url' => '/projects'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getToolsMenu(): array {
|
public array $toolsMenu {
|
||||||
return [
|
get => [
|
||||||
['icon' => '♪', 'title' => 'Now Listening', 'url' => '//now.flash.moe'],
|
['icon' => '♪', 'title' => 'Now Listening', 'url' => '//now.flash.moe'],
|
||||||
['icon' => 'A', 'title' => 'ASCII Table', 'url' => '/tools/ascii'],
|
['icon' => 'A', 'title' => 'ASCII Table', 'url' => '/tools/ascii'],
|
||||||
['icon' => '?', 'title' => 'WHOIS', 'url' => '/tools/whois'],
|
['icon' => '?', 'title' => 'WHOIS', 'url' => '/tools/whois'],
|
||||||
|
@ -18,8 +18,8 @@ class SiteInfo {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHeaderImages(): array {
|
public array $headerImages {
|
||||||
return [
|
get => [
|
||||||
'/images/krk-000.jpg', '/images/krk-001.jpg', '/images/krk-002.jpg',
|
'/images/krk-000.jpg', '/images/krk-001.jpg', '/images/krk-002.jpg',
|
||||||
'/images/krk-003.jpg', '/images/krk-004.jpg', '/images/krk-005.jpg',
|
'/images/krk-003.jpg', '/images/krk-004.jpg', '/images/krk-005.jpg',
|
||||||
'/images/krk-006.jpg', '/images/krk-007.jpg', '/images/krk-008.jpg',
|
'/images/krk-006.jpg', '/images/krk-007.jpg', '/images/krk-008.jpg',
|
||||||
|
|
|
@ -6,38 +6,38 @@ use JsonSerializable;
|
||||||
|
|
||||||
class AsciiCharacter implements JsonSerializable {
|
class AsciiCharacter implements JsonSerializable {
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private int $char
|
public private(set) int $char
|
||||||
) {
|
) {
|
||||||
if($char < 0 || $char > 0xFF)
|
if($char < 0 || $char > 0xFF)
|
||||||
throw new InvalidArgumentException('$char must be a single byte');
|
throw new InvalidArgumentException('$char must be a single byte');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDecimal(): string {
|
public string $decimal {
|
||||||
return (string)$this->char;
|
get => (string)$this->char;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getOctal(): string {
|
public string $octal {
|
||||||
return decoct($this->char);
|
get => decoct($this->char);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHex(): string {
|
public string $hex {
|
||||||
return dechex($this->char);
|
get => dechex($this->char);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isPrintable(): bool {
|
public bool $printable {
|
||||||
return $this->char > 31
|
get => $this->char > 31
|
||||||
&& $this->char < 127;
|
&& $this->char < 127;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function hasHtml(): bool {
|
public bool $hasHtml {
|
||||||
return $this->char === 34
|
get => $this->char === 34
|
||||||
|| $this->char === 38
|
|| $this->char === 38
|
||||||
|| $this->char === 60
|
|| $this->char === 60
|
||||||
|| $this->char === 62;
|
|| $this->char === 62;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHtml(): string {
|
public string $html {
|
||||||
return match($this->char) {
|
get => match($this->char) {
|
||||||
34 => 'quot',
|
34 => 'quot',
|
||||||
38 => 'amp',
|
38 => 'amp',
|
||||||
60 => 'lt',
|
60 => 'lt',
|
||||||
|
@ -46,8 +46,8 @@ class AsciiCharacter implements JsonSerializable {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getString(): string {
|
public string $string {
|
||||||
return match($this->char) {
|
get => match($this->char) {
|
||||||
0 => 'NUL', 1 => 'SOH', 2 => 'STX', 3 => 'ETX', 4 => 'EOT',
|
0 => 'NUL', 1 => 'SOH', 2 => 'STX', 3 => 'ETX', 4 => 'EOT',
|
||||||
5 => 'ENQ', 6 => 'ACK', 7 => 'BEL', 8 => 'BS', 9 => 'HT',
|
5 => 'ENQ', 6 => 'ACK', 7 => 'BEL', 8 => 'BS', 9 => 'HT',
|
||||||
10 => 'LF', 11 => 'VT', 12 => 'FF', 13 => 'CR', 14 => 'SO',
|
10 => 'LF', 11 => 'VT', 12 => 'FF', 13 => 'CR', 14 => 'SO',
|
||||||
|
@ -59,8 +59,8 @@ class AsciiCharacter implements JsonSerializable {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName(): string {
|
public string $name {
|
||||||
return match($this->char) {
|
get => match($this->char) {
|
||||||
0 => 'Null character',
|
0 => 'Null character',
|
||||||
1 => 'Start of heading',
|
1 => 'Start of heading',
|
||||||
2 => 'Start of text',
|
2 => 'Start of text',
|
||||||
|
@ -203,20 +203,20 @@ class AsciiCharacter implements JsonSerializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __toString(): string {
|
public function __toString(): string {
|
||||||
return $this->getString();
|
return $this->string;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function jsonSerialize(): mixed {
|
public function jsonSerialize(): mixed {
|
||||||
$info = [
|
$info = [
|
||||||
'dec' => $this->getDecimal(),
|
'dec' => $this->decimal,
|
||||||
'oct' => $this->getOctal(),
|
'oct' => $this->octal,
|
||||||
'hex' => $this->getHex(),
|
'hex' => $this->hex,
|
||||||
'string' => $this->getString(),
|
'string' => $this->string,
|
||||||
'name' => $this->getName(),
|
'name' => $this->name,
|
||||||
];
|
];
|
||||||
|
|
||||||
if($this->hasHtml())
|
if($this->hasHtml)
|
||||||
$info['html'] = $this->getHtml();
|
$info['html'] = $this->html;
|
||||||
|
|
||||||
return $info;
|
return $info;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,17 +5,13 @@ use Exception;
|
||||||
use ErrorException;
|
use ErrorException;
|
||||||
|
|
||||||
class WhoisClient {
|
class WhoisClient {
|
||||||
public const ROOT = 'whois.iana.org';
|
public const string ROOT = 'whois.iana.org';
|
||||||
public const PORT = 43;
|
public const int PORT = 43;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private string $server = self::ROOT
|
public private(set) string $server = self::ROOT
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public function getServer(): string {
|
|
||||||
return $this->server;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function query(string $target, int $timeout = 5): WhoisResponse {
|
public function query(string $target, int $timeout = 5): WhoisResponse {
|
||||||
$sock = @fsockopen($this->server, self::PORT, $errno, $errstr, $timeout);
|
$sock = @fsockopen($this->server, self::PORT, $errno, $errstr, $timeout);
|
||||||
if(!$sock) throw new \RuntimeException('WhoisClient: ' . $errstr);
|
if(!$sock) throw new \RuntimeException('WhoisClient: ' . $errstr);
|
||||||
|
|
|
@ -1,24 +1,18 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Makai\Tools\Whois;
|
namespace Makai\Tools\Whois;
|
||||||
|
|
||||||
class WhoisResponse implements \JsonSerializable {
|
use JsonSerializable;
|
||||||
private const WHOIS_SERVER_PREFIXES = ['refer', 'whois', 'registrar whois server'];
|
|
||||||
|
class WhoisResponse implements JsonSerializable {
|
||||||
|
private const array WHOIS_SERVER_PREFIXES = ['refer', 'whois', 'registrar whois server'];
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private string $server,
|
public private(set) string $server,
|
||||||
private array $lines
|
public private(set) array $lines
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public function getServer(): string {
|
public string $text {
|
||||||
return $this->server;
|
get => implode(PHP_EOL, $this->lines);
|
||||||
}
|
|
||||||
|
|
||||||
public function getLines(): array {
|
|
||||||
return $this->lines;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getText(): string {
|
|
||||||
return implode(PHP_EOL, $this->lines);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function findNextWhoisServer(): string {
|
public function findNextWhoisServer(): string {
|
||||||
|
|
|
@ -1,28 +1,18 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Makai\Tools\Whois;
|
namespace Makai\Tools\Whois;
|
||||||
|
|
||||||
class WhoisResult implements \JsonSerializable {
|
use JsonSerializable;
|
||||||
|
|
||||||
|
class WhoisResult implements JsonSerializable {
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private string $target,
|
public private(set) string $target,
|
||||||
private array $responses
|
public private(set) array $responses
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public function getTarget(): string {
|
|
||||||
return $this->target;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getResponses(): array {
|
|
||||||
return $this->responses;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getResponse(int $index): WhoisResponse {
|
public function getResponse(int $index): WhoisResponse {
|
||||||
return $this->responses[$index];
|
return $this->responses[$index];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getResponseCount(): int {
|
|
||||||
return count($this->responses);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function jsonSerialize(): mixed {
|
public function jsonSerialize(): mixed {
|
||||||
return [
|
return [
|
||||||
'target' => $this->target,
|
'target' => $this->target,
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<div class="sidelist-title">Elsewhere</div>
|
<div class="sidelist-title">Elsewhere</div>
|
||||||
<div class="sidelist-body">
|
<div class="sidelist-body">
|
||||||
{% for contact in side_contacts %}
|
{% for contact in side_contacts %}
|
||||||
<a class="{{ html_classes('sidelist-item', 'sidecontact', { 'sidelist-item-link': contact.hasLink }) }}" {% if contact.hasLink %} href="{{ contact.link }}" target="_blank" rel="me noopener"{% endif %}>
|
<a class="{{ html_classes('sidelist-item', 'sidecontact', { 'sidelist-item-link': contact.link is not null }) }}" {% if contact.link is not null %} href="{{ contact.link }}" target="_blank" rel="me noopener"{% endif %}>
|
||||||
<div class="sidelist-item-icon">
|
<div class="sidelist-item-icon">
|
||||||
{% if contact.iconIsDomain %}
|
{% if contact.iconIsDomain %}
|
||||||
<img width="16" height="16" src="//icons.duckduckgo.com/ip3/{{ contact.iconDomain }}.ico" alt="">
|
<img width="16" height="16" src="//icons.duckduckgo.com/ip3/{{ contact.iconDomain }}.ico" alt="">
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
<div class="sidelist-title">Featured Projects</div>
|
<div class="sidelist-title">Featured Projects</div>
|
||||||
<div class="sidelist-body">
|
<div class="sidelist-body">
|
||||||
{% for i, project in side_projects %}
|
{% for i, project in side_projects %}
|
||||||
<a class="sidelist-item sidelist-item-link" href="/projects#{{ project.info.cleanName }}">
|
<a class="sidelist-item sidelist-item-link" href="/projects#{{ project.info.nameClean }}">
|
||||||
<div class="sidelist-item-icon">{{ i % 2 ? '★' : '☆' }}</div>
|
<div class="sidelist-item-icon">{{ i % 2 ? '★' : '☆' }}</div>
|
||||||
<div class="sidelist-item-label">{{ project.info.name }}</div>
|
<div class="sidelist-item-label">{{ project.info.name }}</div>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -5,14 +5,14 @@
|
||||||
|
|
||||||
{% block column_centre %}
|
{% block column_centre %}
|
||||||
{% for project in projects %}
|
{% for project in projects %}
|
||||||
<div class="project" id="{{ project.info.cleanName }}" style="--project-colour: {{ project.colour }};">
|
<div class="project" id="{{ project.info.nameClean }}" style="--project-colour: {{ project.colour }};">
|
||||||
<h2>{{ project.info.name }}</h2>
|
<h2>{{ project.info.name }}</h2>
|
||||||
|
|
||||||
{% if project.info.hasSummary %}
|
{% if project.info.summary is not empty %}
|
||||||
<p>{{ project.info.summary }}</p>
|
<p>{{ project.info.summary }}</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if project.info.hasDescription %}
|
{% if project.info.description is not empty %}
|
||||||
{% set lines = project.info.description|split("\n") %}
|
{% set lines = project.info.description|split("\n") %}
|
||||||
{% for line in lines %}
|
{% for line in lines %}
|
||||||
<p>{{ line|trim }}</p>
|
<p>{{ line|trim }}</p>
|
||||||
|
@ -24,15 +24,15 @@
|
||||||
<span class="project-tag" style="--tag-colour: {{ lang.colour }};">{{ lang.name }}</span>
|
<span class="project-tag" style="--tag-colour: {{ lang.colour }};">{{ lang.name }}</span>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{% if project.info.hasHomePageUrl %}
|
{% if project.info.homePageUrl is not empty %}
|
||||||
<a class="project-tag project-tag-link" href="{{ project.info.homePageUrl }}" rel="noopener" target="_blank">Homepage</a>
|
<a class="project-tag project-tag-link" href="{{ project.info.homePageUrl }}" rel="noopener" target="_blank">Homepage</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if project.info.hasSourceUrl %}
|
{% if project.info.sourceUrl is not empty %}
|
||||||
<a class="project-tag project-tag-link" href="{{ project.info.sourceUrl }}" rel="noopener" target="_blank">Source</a>
|
<a class="project-tag project-tag-link" href="{{ project.info.sourceUrl }}" rel="noopener" target="_blank">Source</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if project.info.hasDiscussionUrl %}
|
{% if project.info.discussionUrl is not empty %}
|
||||||
<a class="project-tag project-tag-link" href="{{ project.info.discussionUrl }}" rel="noopener" target="_blank">Discussion</a>
|
<a class="project-tag project-tag-link" href="{{ project.info.discussionUrl }}" rel="noopener" target="_blank">Discussion</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -48,7 +48,7 @@
|
||||||
{% for info in chars %}
|
{% for info in chars %}
|
||||||
{% set print = info.string %}
|
{% set print = info.string %}
|
||||||
|
|
||||||
<div class="ascii-char {{ info.isPrintable ? 'ascii-char-printable' : 'ascii-char-control' }} js-ascii-char" data-key-code="{{ info.decimal }}" data-key-desc="{{ info.name }}" data-key-print="{{ info.string }}" data-copy="{{ info.string }}" {% if info.hasHtml %}data-key-html="{{ info.html }}"{% endif %}>
|
<div class="ascii-char {{ info.printable ? 'ascii-char-printable' : 'ascii-char-control' }} js-ascii-char" data-key-code="{{ info.decimal }}" data-key-desc="{{ info.name }}" data-key-print="{{ info.string }}" data-copy="{{ info.string }}" {% if info.hasHtml %}data-key-html="{{ info.html }}"{% endif %}>
|
||||||
<div class="ascii-char-main">
|
<div class="ascii-char-main">
|
||||||
<div class="ascii-char-print">{{ info.string }}</div>
|
<div class="ascii-char-print">{{ info.string }}</div>
|
||||||
<div class="ascii-char-desc">{{ info.name }}</div>
|
<div class="ascii-char-desc">{{ info.name }}</div>
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . '/../makai.php';
|
require_once __DIR__ . '/../makai.php';
|
||||||
|
|
||||||
$templating = $makai->getTemplating();
|
echo $makai->templating->render(
|
||||||
$path = implode(' ', array_slice($argv, 1));
|
implode(' ', array_slice($argv, 1))
|
||||||
|
);
|
||||||
echo $templating->render($path);
|
|
||||||
|
|
Loading…
Reference in a new issue