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;
}
$makai->getCSRFP()->setInfo(
$makai->csrfp->setInfo(
$cfg->getString('csrfp:secret', 'meow'),
(string)filter_input(INPUT_SERVER, 'REMOTE_ADDR')
);

View file

@ -12,6 +12,6 @@ class AssetsRoutes implements RouteHandler {
#[HttpGet('/header-bgs.json')]
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;
class ContactInfo {
private string $name;
private bool $homePage;
private int $order;
private string $title;
private string $icon;
private int $colour;
private string $display;
private ?string $link;
public function __construct(
public private(set) string $name,
public private(set) bool $homePage,
public private(set) int $order,
public private(set) string $title,
public private(set) string $icon,
public private(set) int $colourRaw,
public private(set) string $display,
public private(set) ?string $link,
) {}
public function __construct(DbResult $result) {
$this->name = $result->getString(0);
$this->homePage = $result->getInteger(1) !== 0;
$this->order = $result->getInteger(2);
$this->title = $result->getString(3);
$this->icon = $result->getString(4);
$this->colour = $result->getInteger(5);
$this->display = $result->getString(6);
$this->link = $result->isNull(7) ? null : $result->getString(7);
public static function fromResult(DbResult $result): ContactInfo {
return new ContactInfo(
name: $result->getString(0),
homePage: $result->getBoolean(1),
order: $result->getInteger(2),
title: $result->getString(3),
icon: $result->getString(4),
colourRaw: $result->getInteger(5),
display: $result->getString(6),
link: $result->getStringOrNull(7),
);
}
public function getName(): string {
return $this->name;
public bool $iconIsDomain {
get => str_starts_with($this->icon, 'url:');
}
public function isHomePage(): bool {
return $this->homePage;
public bool $iconIsImage {
get => mb_strlen($this->icon) > 1;
}
public function getOrder(): int {
return $this->order;
public string $iconDomain {
get => substr($this->icon, 4);
}
public function getTitle(): string {
return $this->title;
}
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;
public Colour $colour {
get => ColourRgb::fromRawRgb($this->colourRaw);
}
}

View file

@ -13,7 +13,7 @@ class Contacts {
public function getContacts(
bool $featuredOnly = false,
?int $take = null
): array {
): iterable {
$hasTake = $take !== null;
$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->execute();
$result = $stmt->getResult();
$contacts = [];
while($result->next())
$contacts[] = new ContactInfo($result);
return $contacts;
return $stmt->getResult()->getIterator(ContactInfo::fromResult(...));
}
}

View file

@ -26,7 +26,7 @@ class DeveloperRoutes implements RouteHandler {
foreach($projectInfos as $projectInfo)
$projects[] = [
'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', [
@ -43,7 +43,7 @@ class DeveloperRoutes implements RouteHandler {
$projects[] = [
'info' => $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', [

View file

@ -6,18 +6,18 @@ use Index\Db\Migration\{DbMigrationRepo,DbMigrationManager,FsDbMigrationRepo};
use Index\Templating\TplEnvironment;
final class MakaiContext {
private DbConnection $dbConn;
private TplEnvironment $templating;
private CSRFPContainer $csrfp;
public private(set) TplEnvironment $templating;
public private(set) CSRFPContainer $csrfp;
private SiteInfo $siteInfo;
public private(set) SiteInfo $siteInfo;
private Contacts\Contacts $contacts;
private Projects\Projects $projects;
private SSHKeys\SSHKeys $sshKeys;
public private(set) Contacts\Contacts $contacts;
public private(set) Projects\Projects $projects;
public private(set) SSHKeys\SSHKeys $sshKeys;
public function __construct(DbConnection $dbConn) {
$this->dbConn = $dbConn;
public function __construct(
public private(set) DbConnection $dbConn
) {
$this->siteInfo = new SiteInfo;
$this->csrfp = new CSRFPContainer;
@ -28,26 +28,6 @@ final class MakaiContext {
$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 {
$result = $this->dbConn->query('SHOW SESSION STATUS LIKE "Questions"');
return $result->next() ? $result->getInteger(1) : 0;
@ -61,10 +41,6 @@ final class MakaiContext {
return new FsDbMigrationRepo(MKI_DIR_MIGRATIONS);
}
public function getTemplating(): TplEnvironment {
return $this->templating;
}
public function startTemplating(): void {
$this->templating = new TplEnvironment(
MKI_DIR_TEMPLATES,
@ -79,10 +55,6 @@ final class MakaiContext {
]);
}
public function getCSRFP(): CSRFPContainer {
return $this->csrfp;
}
public function createRouting(): RoutingContext {
$routingCtx = new RoutingContext;

View file

@ -5,33 +5,21 @@ use Index\Colour\{Colour,ColourRgb};
use Index\Db\DbResult;
class LanguageInfo {
private string $id;
private string $name;
private ?int $colour;
public function __construct(
public private(set) string $id,
public private(set) string $name,
public private(set) ?int $colourRaw,
) {}
public function __construct(DbResult $result) {
$this->id = $result->getString(0);
$this->name = $result->getString(1);
$this->colour = $result->isNull(2) ? null : $result->getInteger(2);
public static function fromResult(DbResult $result): LanguageInfo {
return new LanguageInfo(
id: $result->getString(0),
name: $result->getString(1),
colourRaw: $result->getIntegerOrNull(2),
);
}
public function getId(): string {
return $this->id;
}
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;
public Colour $colour {
get => $this->colourRaw === null ? Colour::none() : ColourRgb::fromRawRGB($this->colourRaw);
}
}

View file

@ -6,149 +6,65 @@ use Index\Colour\{Colour,ColourRgb};
use Index\Db\DbResult;
class ProjectInfo {
private string $id;
private string $name;
private string $nameClean;
private ?string $summary;
private ?string $description;
private int $order;
private string $type;
private bool $featured;
private ?int $colour;
private ?string $homepage;
private ?string $source;
private ?string $discussion;
private int $createdAt;
private ?int $archivedAt;
private ?int $deletedAt;
public function __construct(
public private(set) string $id,
public private(set) string $name,
public private(set) string $nameClean,
public private(set) ?string $summary,
public private(set) ?string $description,
public private(set) int $order,
public private(set) string $type,
public private(set) bool $featured,
public private(set) ?int $colourRaw,
public private(set) ?string $homePageUrl,
public private(set) ?string $sourceUrl,
public private(set) ?string $discussionUrl,
public private(set) int $createdTime,
public private(set) ?int $archivedTime,
public private(set) ?int $deletedTime,
) {}
public function __construct(DbResult $result) {
$this->id = $result->getString(0);
$this->name = $result->getString(1);
$this->nameClean = $result->getString(2);
$this->summary = $result->isNull(3) ? null : $result->getString(3);
$this->description = $result->isNull(4) ? null : $result->getString(4);
$this->order = $result->getInteger(5);
$this->type = $result->getString(6);
$this->featured = $result->getInteger(7) !== 0;
$this->colour = $result->isNull(8) ? null : $result->getInteger(8);
$this->homepage = $result->isNull(9) ? null : $result->getString(9);
$this->source = $result->isNull(10) ? null : $result->getString(10);
$this->discussion = $result->isNull(11) ? null : $result->getString(11);
$this->createdAt = $result->getInteger(12);
$this->archivedAt = $result->isNull(13) ? null : $result->getInteger(13);
$this->deletedAt = $result->isNull(14) ? null : $result->getInteger(14);
public static function fromResult(DbResult $result): ProjectInfo {
return new ProjectInfo(
id: $result->getString(0),
name: $result->getString(1),
nameClean: $result->getString(2),
summary: $result->getStringOrNull(3),
description: $result->getStringOrNull(4),
order: $result->getInteger(5),
type: $result->getString(6),
featured: $result->getBoolean(7),
colourRaw: $result->getIntegerOrNull(8),
homePageUrl: $result->getStringOrNull(9),
sourceUrl: $result->getStringOrNull(10),
discussionUrl: $result->getStringOrNull(11),
createdTime: $result->getInteger(12),
archivedTime: $result->getIntegerOrNull(13),
deletedTime: $result->getIntegerOrNull(14),
);
}
public function getId(): string {
return $this->id;
public Colour $colour {
get => $this->colourRaw === null ? Colour::none() : ColourRgb::fromRawRGB($this->colourRaw);
}
public function getName(): string {
return $this->name;
public CarbonImmutable $createdAt {
get => CarbonImmutable::createFromTimestampUTC($this->createdTime);
}
public function getCleanName(): string {
return $this->nameClean;
public ?CarbonImmutable $archivedAt {
get => $this->archivedTime === null ? null : CarbonImmutable::createFromTimestampUTC($this->archivedTime);
}
public function hasSummary(): bool {
return $this->summary !== null;
public bool $archived {
get => $this->archivedTime !== null;
}
public function getSummary(): ?string {
return $this->summary;
public ?CarbonImmutable $deletedAt {
get => $this->deletedTime === null ? null : CarbonImmutable::createFromTimestampUTC($this->deletedTime);
}
public function hasDescription(): bool {
return $this->description !== 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;
public bool $deleted {
get => $this->deletedTime !== null;
}
}

View file

@ -16,7 +16,7 @@ class Projects {
?bool $deleted = null,
?int $take = null,
bool $random = false
): array {
): iterable {
$hasDeleted = $deleted !== null;
$hasTake = $take !== null;
@ -37,18 +37,12 @@ class Projects {
$stmt->addParameter(1, $take);
$stmt->execute();
$result = $stmt->getResult();
$projects = [];
while($result->next())
$projects[] = new ProjectInfo($result);
return $projects;
return $stmt->getResult()->getIterator(ProjectInfo::fromResult(...));
}
public function getLanguages(
ProjectInfo|string|null $projectInfo = null
): array {
): iterable {
$hasProjectInfo = $projectInfo !== null;
$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);
if($hasProjectInfo)
$stmt->addParameter(1, $projectInfo instanceof ProjectInfo ? $projectInfo->getId() : $projectInfo);
$stmt->addParameter(1, $projectInfo instanceof ProjectInfo ? $projectInfo->id : $projectInfo);
$stmt->execute();
$result = $stmt->getResult();
$langs = [];
while($result->next())
$langs[] = new LanguageInfo($result);
return $langs;
return $stmt->getResult()->getIterator(LanguageInfo::fromResult(...));
}
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)';
$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();
$result = $stmt->getResult();

View file

@ -4,17 +4,13 @@ namespace Makai;
use Index\Http\Routing\{HttpRouter,Router,RouteHandler};
class RoutingContext {
private HttpRouter $router;
public private(set) HttpRouter $router;
public function __construct() {
$this->router = new HttpRouter(errorHandler: new RoutingErrorHandler);
$this->router->use('/', fn($resp) => $resp->setPoweredBy('Makai'));
}
public function getRouter(): Router {
return $this->router;
}
public function register(RouteHandler $handler): void {
$this->router->register($handler);
}

View file

@ -1,72 +1,49 @@
<?php
namespace Makai\SSHKeys;
use Stringable;
use Carbon\CarbonImmutable;
use Index\Db\DbResult;
class SSHKeyInfo {
private string $id;
private int $level;
private string $algo;
private string $body;
private string $comment;
private int $createdAt;
private ?int $deprecatedAt;
class SSHKeyInfo implements Stringable {
public function __construct(
public private(set) string $id,
public private(set) int $level,
public private(set) string $algo,
public private(set) string $body,
public private(set) string $comment,
public private(set) int $createdTime,
public private(set) ?int $deprecatedTime,
) {}
public function __construct(DbResult $result) {
$this->id = $result->getString(0);
$this->level = $result->getInteger(1);
$this->algo = $result->getString(2);
$this->body = $result->getString(3);
$this->comment = $result->getString(4);
$this->createdAt = $result->getInteger(5);
$this->deprecatedAt = $result->isNull(6) ? null : $result->getInteger(6);
public static function fromResult(DbResult $result): SSHKeyInfo {
return new SSHKeyInfo(
id: $result->getString(0),
level: $result->getInteger(1),
algo: $result->getString(2),
body: $result->getString(3),
comment: $result->getString(4),
createdTime: $result->getInteger(5),
deprecatedTime: $result->getIntegerOrNull(6),
);
}
public function getId(): string {
return $this->id;
public CarbonImmutable $createdAt {
get => CarbonImmutable::createFromTimestampUTC($this->createdTime);
}
public function getLevel(): int {
return $this->level;
public bool $deprecated {
get => $this->deprecatedTime !== null;
}
public function getAlgorithm(): string {
return $this->algo;
}
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 ?CarbonImmutable $deprecatedAt {
get => $this->deprecatedTime === null ? null : CarbonImmutable::createFromTimestampUTC($this->deprecatedTime);
}
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)
$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;
}

View file

@ -13,7 +13,7 @@ class SSHKeys {
public function getKeys(
?int $minLevel = null,
?bool $deprecated = null,
): array {
): iterable {
$hasMinLevel = $minLevel !== null;
$hasDeprecated = $deprecated !== null;
@ -32,12 +32,6 @@ class SSHKeys {
$stmt->addParameter(1, $minLevel);
$stmt->execute();
$result = $stmt->getResult();
$keys = [];
while($result->next())
$keys[] = new SSHKeyInfo($result);
return $keys;
return $stmt->getResult()->getIterator(SSHKeyInfo::fromResult(...));
}
}

View file

@ -24,12 +24,12 @@ class SSHKeysRoutes implements RouteHandler {
foreach($keys as $key) {
$items[] = $item = new \stdClass;
$item->algo = $key->getAlgorithm();
$item->key = $key->getBody();
$item->algo = $key->algo;
$item->key = $key->body;
if($includeComment) {
$item->comment = (string)$key->getComment();
$item->created = $key->getCreatedAt()->format(DateTimeInterface::ATOM);
$item->level = $key->getLevel();
$item->comment = (string)$key->comment;
$item->created = $key->createdAt->format(DateTimeInterface::ATOM);
$item->level = $key->level;
}
}

View file

@ -2,15 +2,15 @@
namespace Makai;
class SiteInfo {
public function getHeaderNavigation(): array {
return [
public array $headerNavigation {
get => [
['title' => 'Home', 'url' => '/'],
['title' => 'Projects', 'url' => '/projects'],
];
}
public function getToolsMenu(): array {
return [
public array $toolsMenu {
get => [
['icon' => '♪', 'title' => 'Now Listening', 'url' => '//now.flash.moe'],
['icon' => 'A', 'title' => 'ASCII Table', 'url' => '/tools/ascii'],
['icon' => '?', 'title' => 'WHOIS', 'url' => '/tools/whois'],
@ -18,8 +18,8 @@ class SiteInfo {
];
}
public function getHeaderImages(): array {
return [
public array $headerImages {
get => [
'/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-006.jpg', '/images/krk-007.jpg', '/images/krk-008.jpg',

View file

@ -6,38 +6,38 @@ use JsonSerializable;
class AsciiCharacter implements JsonSerializable {
public function __construct(
private int $char
public private(set) int $char
) {
if($char < 0 || $char > 0xFF)
throw new InvalidArgumentException('$char must be a single byte');
}
public function getDecimal(): string {
return (string)$this->char;
public string $decimal {
get => (string)$this->char;
}
public function getOctal(): string {
return decoct($this->char);
public string $octal {
get => decoct($this->char);
}
public function getHex(): string {
return dechex($this->char);
public string $hex {
get => dechex($this->char);
}
public function isPrintable(): bool {
return $this->char > 31
public bool $printable {
get => $this->char > 31
&& $this->char < 127;
}
public function hasHtml(): bool {
return $this->char === 34
public bool $hasHtml {
get => $this->char === 34
|| $this->char === 38
|| $this->char === 60
|| $this->char === 62;
}
public function getHtml(): string {
return match($this->char) {
public string $html {
get => match($this->char) {
34 => 'quot',
38 => 'amp',
60 => 'lt',
@ -46,8 +46,8 @@ class AsciiCharacter implements JsonSerializable {
};
}
public function getString(): string {
return match($this->char) {
public string $string {
get => match($this->char) {
0 => 'NUL', 1 => 'SOH', 2 => 'STX', 3 => 'ETX', 4 => 'EOT',
5 => 'ENQ', 6 => 'ACK', 7 => 'BEL', 8 => 'BS', 9 => 'HT',
10 => 'LF', 11 => 'VT', 12 => 'FF', 13 => 'CR', 14 => 'SO',
@ -59,8 +59,8 @@ class AsciiCharacter implements JsonSerializable {
};
}
public function getName(): string {
return match($this->char) {
public string $name {
get => match($this->char) {
0 => 'Null character',
1 => 'Start of heading',
2 => 'Start of text',
@ -203,20 +203,20 @@ class AsciiCharacter implements JsonSerializable {
}
public function __toString(): string {
return $this->getString();
return $this->string;
}
public function jsonSerialize(): mixed {
$info = [
'dec' => $this->getDecimal(),
'oct' => $this->getOctal(),
'hex' => $this->getHex(),
'string' => $this->getString(),
'name' => $this->getName(),
'dec' => $this->decimal,
'oct' => $this->octal,
'hex' => $this->hex,
'string' => $this->string,
'name' => $this->name,
];
if($this->hasHtml())
$info['html'] = $this->getHtml();
if($this->hasHtml)
$info['html'] = $this->html;
return $info;
}

View file

@ -5,17 +5,13 @@ use Exception;
use ErrorException;
class WhoisClient {
public const ROOT = 'whois.iana.org';
public const PORT = 43;
public const string ROOT = 'whois.iana.org';
public const int PORT = 43;
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 {
$sock = @fsockopen($this->server, self::PORT, $errno, $errstr, $timeout);
if(!$sock) throw new \RuntimeException('WhoisClient: ' . $errstr);

View file

@ -1,24 +1,18 @@
<?php
namespace Makai\Tools\Whois;
class WhoisResponse implements \JsonSerializable {
private const WHOIS_SERVER_PREFIXES = ['refer', 'whois', 'registrar whois server'];
use JsonSerializable;
class WhoisResponse implements JsonSerializable {
private const array WHOIS_SERVER_PREFIXES = ['refer', 'whois', 'registrar whois server'];
public function __construct(
private string $server,
private array $lines
public private(set) string $server,
public private(set) array $lines
) {}
public function getServer(): string {
return $this->server;
}
public function getLines(): array {
return $this->lines;
}
public function getText(): string {
return implode(PHP_EOL, $this->lines);
public string $text {
get => implode(PHP_EOL, $this->lines);
}
public function findNextWhoisServer(): string {

View file

@ -1,28 +1,18 @@
<?php
namespace Makai\Tools\Whois;
class WhoisResult implements \JsonSerializable {
use JsonSerializable;
class WhoisResult implements JsonSerializable {
public function __construct(
private string $target,
private array $responses
public private(set) string $target,
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 {
return $this->responses[$index];
}
public function getResponseCount(): int {
return count($this->responses);
}
public function jsonSerialize(): mixed {
return [
'target' => $this->target,

View file

@ -6,7 +6,7 @@
<div class="sidelist-title">Elsewhere</div>
<div class="sidelist-body">
{% 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">
{% if contact.iconIsDomain %}
<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-body">
{% 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-label">{{ project.info.name }}</div>
</a>

View file

@ -5,14 +5,14 @@
{% block column_centre %}
{% 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>
{% if project.info.hasSummary %}
{% if project.info.summary is not empty %}
<p>{{ project.info.summary }}</p>
{% endif %}
{% if project.info.hasDescription %}
{% if project.info.description is not empty %}
{% set lines = project.info.description|split("\n") %}
{% for line in lines %}
<p>{{ line|trim }}</p>
@ -24,15 +24,15 @@
<span class="project-tag" style="--tag-colour: {{ lang.colour }};">{{ lang.name }}</span>
{% 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>
{% 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>
{% 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>
{% endif %}
</div>

View file

@ -48,7 +48,7 @@
{% for info in chars %}
{% 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-print">{{ info.string }}</div>
<div class="ascii-char-desc">{{ info.name }}</div>

View file

@ -2,7 +2,6 @@
<?php
require_once __DIR__ . '/../makai.php';
$templating = $makai->getTemplating();
$path = implode(' ', array_slice($argv, 1));
echo $templating->render($path);
echo $makai->templating->render(
implode(' ', array_slice($argv, 1))
);