Files
ik-codex/src/Parser/PatternParser.php
indifferentketchup 66a2fcc5f3 Rename namespace Aternos\Codex to IndifferentKetchup\Codex
Bulk substitution across all PHP files in src/ and test/. Covers
namespace declarations, use statements, fully-qualified class
references, and @package PHPDoc tags. No logic changes.
2026-04-30 15:13:52 +00:00

183 lines
5.0 KiB
PHP

<?php
namespace IndifferentKetchup\Codex\Parser;
use IndifferentKetchup\Codex\Log\Entry;
use IndifferentKetchup\Codex\Log\EntryInterface;
use IndifferentKetchup\Codex\Log\Level;
use IndifferentKetchup\Codex\Log\LevelInterface;
use IndifferentKetchup\Codex\Log\Line;
use DateTime;
use DateTimeZone;
use InvalidArgumentException;
/**
* Class PatternParser
*
* @package IndifferentKetchup\Codex\Parser
*/
class PatternParser extends Parser
{
/**
* Match constants, see setMatches()
*/
public const string TIME = "time";
public const string LEVEL = "level";
public const string PREFIX = "prefix";
/**
* @var class-string<EntryInterface>
*/
protected string $entryClass = Entry::class;
/**
* @noinspection PhpDocFieldTypeMismatchInspection
* @var class-string<LevelInterface>|LevelInterface
*/
protected string $levelClass = Level::class;
protected ?string $pattern = null;
protected array $matches = [];
protected ?string $timeFormat = null;
protected ?DateTimeZone $timeZone = null;
/**
* Set the entry pattern
*
* Every line matching this pattern is defined as
* new entry, all other lines are added to the
* previous entry
*
* @param string $pattern
* @return $this
*/
public function setPattern(string $pattern): static
{
$this->pattern = $pattern;
return $this;
}
/**
* Get the entry pattern
*
* @return string
*/
public function getPattern(): string
{
return $this->pattern;
}
/**
* Set the array of match constants
*
* The position/key in the array defines
* the position of the matching capturing
* group in the $pattern
*
* @param array $matches
* @return $this
*/
public function setMatches(array $matches): static
{
$this->matches = $matches;
return $this;
}
/**
* Set the time format
*
* Time is parsed with the DateTime::createFromFormat() function,
* see this for format information:
*
* http://php.net/manual/en/datetime.createfromformat.php
*
* @param string $timeFormat
* @return $this
*/
public function setTimeFormat(string $timeFormat): static
{
$this->timeFormat = $timeFormat;
return $this;
}
/**
* Set the time zone
*
* Optional, uses OS timezone otherwise
*
* @param DateTimeZone $timeZone
* @return $this
*/
public function setTimezone(DateTimeZone $timeZone): static
{
$this->timeZone = $timeZone;
return $this;
}
/**
* Parse a log from resource to Log object
*/
public function parse(): void
{
foreach ($this->getLogContentAsArray() as $number => $lineString) {
$line = new Line($number + 1, $lineString);
$result = preg_match($this->pattern, $lineString, $matches);
if ($result !== 1) {
if (!isset($entry)) {
/** @var Entry $entry */
$entry = new $this->entryClass();
$this->log->addEntry($entry);
}
$entry->addLine($line);
continue;
}
/** @var Entry $entry */
$entry = new $this->entryClass();
$this->log->addEntry($entry);
foreach ($matches as $key => $match) {
if ($key === 0) {
continue;
}
$matchKey = $key - 1;
if (!isset($this->matches[$matchKey])) {
throw new InvalidArgumentException("More matches found in string than defined in PatternParser::setMatches().");
}
$this->parseEntryMatch($entry, $this->matches[$matchKey], $match);
}
$entry->addLine($line);
}
}
/**
* Parse an entry match
*
* Overwrite this function to add more different
* match types and call the parent function (this function)
* if you don't know the match type (default in a switch)
*
* @param Entry $entry
* @param string $matchType One of the match constants
* @param string $matchString
*/
protected function parseEntryMatch(Entry $entry, string $matchType, string $matchString): void
{
switch ($matchType) {
case static::TIME:
$date = DateTime::createFromFormat($this->timeFormat, $matchString, $this->timeZone);
if ($date) {
$entry->setTime($date->getTimestamp());
}
break;
case static::LEVEL:
$entry->setLevel($this->levelClass::fromString($matchString));
break;
case static::PREFIX:
$entry->setPrefix($matchString);
break;
default:
throw new InvalidArgumentException("Match type '" . $matchType . "' is not defined.");
}
}
}