PHP 8.4 upgrades.

This commit is contained in:
Pachira 2024-12-16 19:15:50 +00:00
parent 9344d438bf
commit 2640a755a0
22 changed files with 206 additions and 434 deletions

View file

@ -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')
); );

View file

@ -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;
} }
} }

View file

@ -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;
} }
} }

View file

@ -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;
} }
} }

View file

@ -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', [

View file

@ -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;

View file

@ -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;
} }
} }

View file

@ -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;
} }
} }

View file

@ -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();

View file

@ -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);
} }

View file

@ -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;
} }

View file

@ -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;
} }
} }

View file

@ -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;
} }
} }

View file

@ -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',

View file

@ -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;
} }

View file

@ -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);

View file

@ -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 {

View file

@ -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,

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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);