Initial import from aternosorg/codex-minecraft
Some checks failed
Tests / Run tests on PHP v8.4 (push) Failing after 32s
Tests / Run tests on PHP v8.5 (push) Failing after 2s

This commit is contained in:
2026-04-30 09:56:57 -05:00
commit 7c7fe5ca80
94 changed files with 7003 additions and 0 deletions

50
src/Log/AnalysableLog.php Normal file
View File

@@ -0,0 +1,50 @@
<?php
namespace Aternos\Codex\Log;
use Aternos\Codex\Analyser\AnalyserInterface;
use Aternos\Codex\Analysis\AnalysisInterface;
/**
* Class AnalysableLog
*
* @package Aternos\Codex\Log
*/
abstract class AnalysableLog extends Log implements AnalysableLogInterface
{
protected ?AnalysisInterface $analysis = null;
/**
* Analyse a log file with an analyser
*
* Every log type should have a default analyser,
* but the $analyser argument can be used to override
* the default analyser
*
* @param AnalyserInterface|null $analyser
* @return AnalysisInterface
*/
public function analyse(?AnalyserInterface $analyser = null): AnalysisInterface
{
if ($this->analysis !== null) {
return $this->analysis;
}
if ($analyser === null) {
$analyser = static::getDefaultAnalyser();
}
$analyser->setLog($this);
return $this->analysis = $analyser->analyse();
}
/**
* @return array
*/
public function jsonSerialize(): array
{
return array_merge(parent::jsonSerialize(), [
'analysis' => $this->analyse()
]);
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace Aternos\Codex\Log;
use Aternos\Codex\Analyser\AnalyserInterface;
use Aternos\Codex\Analysis\AnalysisInterface;
/**
* Interface AnalysableLogInterface
*
* @package Aternos\Codex\Log
*/
interface AnalysableLogInterface
{
/**
* Get the default analyser
*
* @return AnalyserInterface
*/
public static function getDefaultAnalyser(): AnalyserInterface;
/**
* Analyse a log file with an analyser
*
* Every log type should have a default analyser,
* but the $analyser argument can be used to override
* the default analyser
*
* @param AnalyserInterface|null $analyser
* @return AnalysisInterface
*/
public function analyse(?AnalyserInterface $analyser = null): AnalysisInterface;
}

View File

@@ -0,0 +1,20 @@
<?php
namespace Aternos\Codex\Log;
use Aternos\Codex\Detective\DetectorInterface;
/**
* Interface DetectableLogInterface
*
* @package Aternos\Codex\Log
*/
interface DetectableLogInterface extends LogInterface
{
/**
* Get an array of detectors matching DetectorInterface
*
* @return DetectorInterface[]
*/
public static function getDetectors(): array;
}

244
src/Log/Entry.php Normal file
View File

@@ -0,0 +1,244 @@
<?php
namespace Aternos\Codex\Log;
/**
* Class Entry
*
* @package Aternos\Codex\Log
*/
class Entry implements EntryInterface
{
/**
* @var LineInterface[]
*/
protected array $lines = [];
protected ?LevelInterface $level = null;
protected ?int $time = null;
protected ?string $prefix = null;
protected int $iterator = 0;
/**
* Set all lines at once in an array replacing the current lines
*
* @param LineInterface[] $lines
* @return $this
*/
public function setLines(array $lines = []): static
{
$this->lines = $lines;
return $this;
}
/**
* Add a line
*
* @param LineInterface $line
* @return $this
*/
public function addLine(LineInterface $line): static
{
$this->lines[] = $line;
return $this;
}
/**
* Get all lines
*
* @return array
*/
public function getLines(): array
{
return $this->lines;
}
/**
* Set the log level of the entry
*
* @param LevelInterface $level
* @return $this
*/
public function setLevel(LevelInterface $level): static
{
$this->level = $level;
return $this;
}
/**
* Get the log level of the entry
*
* @return LevelInterface
*/
public function getLevel(): LevelInterface
{
return $this->level ?? Level::INFO;
}
/**
* Set the timestamp of the entry
*
* @param int $time
* @return $this
*/
public function setTime(int $time): static
{
$this->time = $time;
return $this;
}
/**
* Get the timestamp of the entry
*
* @return int|null
*/
public function getTime(): ?int
{
return $this->time;
}
/**
* Set the prefix
*
* @param string $prefix
* @return $this
*/
public function setPrefix(string $prefix): static
{
$this->prefix = $prefix;
return $this;
}
/**
* Get the prefix
*
* @return string|null
*/
public function getPrefix(): ?string
{
return $this->prefix;
}
/**
* Return the current element
*
* @return Line
*/
public function current(): Line
{
return $this->lines[$this->iterator];
}
/**
* Move forward to next element
*
* @return void
*/
public function next(): void
{
$this->iterator++;
}
/**
* Return the key of the current element
*
* @return int
*/
public function key(): int
{
return $this->iterator;
}
/**
* Checks if current position is valid
*
* @return boolean
*/
public function valid(): bool
{
return array_key_exists($this->iterator, $this->lines);
}
/**
* Rewind the Iterator to the first element
*
* @return void
*/
public function rewind(): void
{
$this->iterator = 0;
}
/**
* Count elements of an object
*
* @return int
*/
public function count(): int
{
return count($this->lines);
}
/**
* Whether an offset exists
*
* @param mixed $offset
* @return bool
*/
public function offsetExists(mixed $offset): bool
{
return isset($this->lines[$offset]);
}
/**
* Offset to retrieve
*
* @param mixed $offset
* @return LineInterface
*/
public function offsetGet(mixed $offset): LineInterface
{
return $this->lines[$offset];
}
/**
* Offset to set
*
* @param mixed $offset
* @param LineInterface $value
*/
public function offsetSet(mixed $offset, mixed $value): void
{
$this->lines[$offset] = $value;
}
/**
* Offset to unset
*
* @param mixed $offset
*/
public function offsetUnset(mixed $offset): void
{
unset($this->lines[$offset]);
}
/**
* @return string
*/
public function __toString(): string
{
return implode("\n", $this->getLines());
}
/**
* @return array
*/
public function jsonSerialize(): array
{
return [
'level' => $this->getLevel(),
'time' => $this->getTime(),
'prefix' => $this->getPrefix(),
'lines' => $this->getLines()
];
}
}

View File

@@ -0,0 +1,67 @@
<?php
namespace Aternos\Codex\Log;
use ArrayAccess;
use Countable;
use Iterator;
use JsonSerializable;
/**
* Interface EntryInterface
*
* @package Aternos\Codex\Log
*/
interface EntryInterface extends Iterator, Countable, ArrayAccess, JsonSerializable
{
/**
* Set all lines at once in an array replacing the current lines
*
* @param LineInterface[] $lines
* @return $this
*/
public function setLines(array $lines = []): static;
/**
* Add a line
*
* @param LineInterface $line
* @return $this
*/
public function addLine(LineInterface $line): static;
/**
* Get all lines
*
* @return LineInterface[]
*/
public function getLines(): array;
/**
* @return string
*/
public function __toString(): string;
/**
* Return the current element
*
* @return LineInterface
*/
public function current(): LineInterface;
/**
* Offset to set
*
* @param mixed $offset
* @param LineInterface $value
*/
public function offsetSet(mixed $offset, mixed $value): void;
/**
* Offset to retrieve
*
* @param mixed $offset
* @return LineInterface
*/
public function offsetGet(mixed $offset): LineInterface;
}

23
src/Log/File/LogFile.php Normal file
View File

@@ -0,0 +1,23 @@
<?php
namespace Aternos\Codex\Log\File;
/**
* Class LogFile
*
* @package Aternos\Codex\Log\File
*/
abstract class LogFile implements LogFileInterface
{
protected ?string $content = null;
/**
* Get the log file content
*
* @return string
*/
public function getContent(): string
{
return $this->content;
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace Aternos\Codex\Log\File;
/**
* Interface LogFileInterface
*
* @package Aternos\Codex\Log\File
*/
interface LogFileInterface
{
/**
* Get the log file content
*
* @return string
*/
public function getContent(): string;
}

View File

@@ -0,0 +1,27 @@
<?php
namespace Aternos\Codex\Log\File;
use InvalidArgumentException;
/**
* Class PathLogFile
*
* @package Aternos\Codex\Log\File
*/
class PathLogFile extends LogFile
{
/**
* PathLogFile constructor.
*
* @param string $path
*/
public function __construct(string $path)
{
if (!file_exists($path)) {
throw new InvalidArgumentException("File '" . $path . "' not found.");
}
$this->content = file_get_contents($path);
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace Aternos\Codex\Log\File;
use InvalidArgumentException;
/**
* Class StreamLogFile
*
* @package Aternos\Codex\Log\File
*/
class StreamLogFile extends LogFile
{
/**
* StreamLogFile constructor.
*
* @param resource $streamResource
*/
public function __construct($streamResource)
{
if (!is_resource($streamResource)) {
throw new InvalidArgumentException("Stream argument is not a resource");
}
$this->content = '';
while (!feof($streamResource)) {
$this->content .= fread($streamResource, 8192);
}
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace Aternos\Codex\Log\File;
/**
* Class StringLogFile
*
* @package Aternos\Codex\Log\File
*/
class StringLogFile extends LogFile
{
/**
* StringLogFile constructor.
*
* @param string $string
*/
public function __construct(string $string)
{
$this->content = $string;
}
}

66
src/Log/Level.php Normal file
View File

@@ -0,0 +1,66 @@
<?php
namespace Aternos\Codex\Log;
enum Level: int implements LevelInterface
{
case EMERGENCY = 0;
case ALERT = 1;
case CRITICAL = 2;
case ERROR = 3;
case WARNING = 4;
case NOTICE = 5;
case INFO = 6;
case DEBUG = 7;
/**
* @param string $level
* @return Level
*/
public static function fromString(string $level): Level
{
return match (strtolower($level)) {
"emergency" => Level::EMERGENCY,
"alert" => Level::ALERT,
"critical", "severe", "fatal" => Level::CRITICAL,
"error", "stderr" => Level::ERROR,
"warning", "warn" => Level::WARNING,
"notice", "fine" => Level::NOTICE,
"debug", "finer", "finest" => Level::DEBUG,
default => Level::INFO
};
}
/**
* @return string
*/
public function asString(): string
{
return match ($this) {
Level::EMERGENCY => "emergency",
Level::ALERT => "alert",
Level::CRITICAL => "critical",
Level::ERROR => "error",
Level::WARNING => "warning",
Level::NOTICE => "notice",
Level::INFO => "info",
Level::DEBUG => "debug"
};
}
/**
* @return int
*/
public function asInt(): int
{
return $this->value;
}
/**
* @return int
*/
public function jsonSerialize(): int
{
return $this->value;
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace Aternos\Codex\Log;
use JsonSerializable;
interface LevelInterface extends JsonSerializable
{
/**
* @param string $level
* @return LevelInterface
*/
public static function fromString(string $level): LevelInterface;
/**
* @return string
*/
public function asString(): string;
/**
* @return int
*/
public function asInt(): int;
}

84
src/Log/Line.php Normal file
View File

@@ -0,0 +1,84 @@
<?php
namespace Aternos\Codex\Log;
/**
* Class Line
*
* @package Aternos\Codex\Log
*/
class Line implements LineInterface
{
/**
* @param int $number
* @param string $text
*/
public function __construct(
protected int $number,
protected string $text)
{
}
/**
* Set the text of the line
*
* @param string $text
* @return $this
*/
public function setText(string $text): static
{
$this->text = $text;
return $this;
}
/**
* Get the text of the line
*
* @return string
*/
public function getText(): string
{
return $this->text;
}
/**
* Set the line number
*
* @param int $number
* @return $this
*/
public function setNumber(int $number): static
{
$this->number = $number;
return $this;
}
/**
* Get the line number
*
* @return int
*/
public function getNumber(): int
{
return $this->number;
}
/**
* @return string
*/
public function __toString(): string
{
return $this->getText();
}
/**
* @return array
*/
public function jsonSerialize(): array
{
return [
'number' => $this->getNumber(),
'content' => $this->getText()
];
}
}

48
src/Log/LineInterface.php Normal file
View File

@@ -0,0 +1,48 @@
<?php
namespace Aternos\Codex\Log;
use JsonSerializable;
/**
* Interface LineInterface
*
* @package Aternos\Codex\Log
*/
interface LineInterface extends JsonSerializable
{
/**
* Set the text of the line
*
* @param string $text
* @return $this
*/
public function setText(string $text): static;
/**
* Get the text of the line
*
* @return string
*/
public function getText(): string;
/**
* Set the line number
*
* @param int $number
* @return $this
*/
public function setNumber(int $number): static;
/**
* Get the line number
*
* @return int
*/
public function getNumber(): int;
/**
* @return string
*/
public function __toString(): string;
}

253
src/Log/Log.php Normal file
View File

@@ -0,0 +1,253 @@
<?php
namespace Aternos\Codex\Log;
use Aternos\Codex\Log\File\LogFileInterface;
use Aternos\Codex\Parser\DefaultParser;
use Aternos\Codex\Parser\ParserInterface;
/**
* Class Log
*
* @package Aternos\Codex\Log
*/
class Log implements LogInterface
{
/**
* @var EntryInterface[]
*/
protected array $entries = [];
protected int $iterator = 0;
protected ?LogFileInterface $logFile = null;
protected bool $includeEntries = true;
/**
* Get the default parser
*
* @return ParserInterface
*/
public static function getDefaultParser(): ParserInterface
{
return new DefaultParser();
}
/**
* Set the log file
*
* @param LogFileInterface $logFile
* @return $this
*/
public function setLogFile(LogFileInterface $logFile): static
{
$this->logFile = $logFile;
return $this;
}
/**
* Get the log file
*
* @return LogFileInterface
*/
public function getLogfile(): LogFileInterface
{
return $this->logFile;
}
/**
* Parse a log file with a parser
*
* Every log type should have a default parser,
* but the $parser argument can be used to override
* the default parser
*
* @param ParserInterface|null $parser
* @return $this
*/
public function parse(?ParserInterface $parser = null): static
{
if ($parser === null) {
$parser = static::getDefaultParser();
}
$parser->setLog($this)->parse();
return $this;
}
/**
* Set all entries of the log at once replacing the current entries
*
* @param EntryInterface[] $entries
* @return $this
*/
public function setEntries(array $entries = []): static
{
$this->entries = $entries;
return $this;
}
/**
* Add an entry to the log
*
* @param EntryInterface $entry
* @return $this
*/
public function addEntry(EntryInterface $entry): static
{
$this->entries[] = $entry;
return $this;
}
/**
* Get all entries of the log
*
* @return EntryInterface[]
*/
public function getEntries(): array
{
return $this->entries;
}
/**
* Return the current element
*
* @return EntryInterface
*/
public function current(): EntryInterface
{
return $this->entries[$this->iterator];
}
/**
* Move forward to next element
*
* @return void
*/
public function next(): void
{
$this->iterator++;
}
/**
* Return the key of the current element
*
* @return int
*/
public function key(): int
{
return $this->iterator;
}
/**
* Checks if current position is valid
*
* @return boolean
*/
public function valid(): bool
{
return array_key_exists($this->iterator, $this->entries);
}
/**
* Rewind the Iterator to the first element
*
* @return void
*/
public function rewind(): void
{
$this->iterator = 0;
}
/**
* Count elements of an object
*
* @return int
*/
public function count(): int
{
return count($this->entries);
}
/**
* Whether an offset exists
*
* @param mixed $offset
* @return bool
*/
public function offsetExists(mixed $offset): bool
{
return isset($this->entries[$offset]);
}
/**
* Offset to retrieve
*
* @param mixed $offset
* @return EntryInterface
*/
public function offsetGet(mixed $offset): EntryInterface
{
return $this->entries[$offset];
}
/**
* Offset to set
*
* @param mixed $offset
* @param EntryInterface $value
*/
public function offsetSet(mixed $offset, mixed $value): void
{
$this->entries[$offset] = $value;
}
/**
* Offset to unset
*
* @param mixed $offset
*/
public function offsetUnset(mixed $offset): void
{
unset($this->entries[$offset]);
}
/**
* @return string
*/
public function __toString(): string
{
return implode("\n", $this->getEntries());
}
/**
* @param bool $includeEntries
* @return $this
*/
public function setIncludeEntries(bool $includeEntries): static
{
$this->includeEntries = $includeEntries;
return $this;
}
/**
* @return array
*/
public function jsonSerialize(): array
{
if (!$this->includeEntries) {
return [];
}
return [
"entries" => $this->getEntries()
];
}
/**
* @inheritDoc
*/
public function getTitle(): string
{
return "Log";
}
}

110
src/Log/LogInterface.php Normal file
View File

@@ -0,0 +1,110 @@
<?php
namespace Aternos\Codex\Log;
use ArrayAccess;
use Aternos\Codex\Log\File\LogFileInterface;
use Aternos\Codex\Parser\ParserInterface;
use Countable;
use Iterator;
use JsonSerializable;
/**
* Interface LogInterface
*
* @package Aternos\Codex\Log
*/
interface LogInterface extends Iterator, Countable, ArrayAccess, JsonSerializable
{
/**
* Get the default parser
*
* @return ParserInterface
*/
public static function getDefaultParser(): ParserInterface;
/**
* Set the log file
*
* @param LogFileInterface $logFile
* @return $this
*/
public function setLogFile(LogFileInterface $logFile): static;
/**
* Get the log file
*
* @return LogFileInterface
*/
public function getLogFile(): LogFileInterface;
/**
* Get a human-readable title for the log
*
* @return string
*/
public function getTitle(): string;
/**
* Parse a log file with a parser
*
* Every log type should have a default parser,
* but the $parser argument can be used to override
* the default parser
*
* @param ParserInterface|null $parser
* @return $this
*/
public function parse(?ParserInterface $parser = null): static;
/**
* Set all entries of the log at once replacing the current entries
*
* @param EntryInterface[] $entries
* @return $this
*/
public function setEntries(array $entries = []): static;
/**
* Add an entry to the log
*
* @param EntryInterface $entry
* @return $this
*/
public function addEntry(EntryInterface $entry): static;
/**
* Get all entries of the log
*
* @return EntryInterface[]
*/
public function getEntries(): array;
/**
* @return string
*/
public function __toString(): string;
/**
* Return the current element
*
* @return EntryInterface
*/
public function current(): EntryInterface;
/**
* Offset to set
*
* @param mixed $offset
* @param EntryInterface $value
*/
public function offsetSet(mixed $offset, mixed $value): void;
/**
* Offset to retrieve
*
* @param mixed $offset
* @return EntryInterface
*/
public function offsetGet(mixed $offset): EntryInterface;
}