<?php
/**
- * @copyright Copyright (C) 2021, Friendica
+ * @copyright Copyright (C) 2010-2022, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
-namespace Friendica\Model\Log;
-use \Friendica\Util\ReversedFileReader;
-use \Friendica\Object\Log\ParsedLog;
+namespace Friendica\Model\Log;
+use Friendica\Util\ReversedFileReader;
+use Friendica\Object\Log\ParsedLogLine;
/**
- * An iterator which returns `\Friendica\Objec\Log\ParsedLog` instances
+ * An iterator which returns `\Friendica\Objec\Log\ParsedLogLine` instances
*
* Uses `\Friendica\Util\ReversedFileReader` to fetch log lines
- * from newest to oldest
+ * from newest to oldest.
*/
class ParsedLogIterator implements \Iterator
{
- public function __construct(string $filename, int $limit=0)
+ /** @var \Iterator */
+ private $reader;
+
+ /** @var ParsedLogLine current iterator value*/
+ private $value = null;
+
+ /** @var int max number of lines to read */
+ private $limit = 0;
+
+ /** @var array filters per column */
+ private $filters = [];
+
+ /** @var string search term */
+ private $search = "";
+
+
+ /**
+ * @param ReversedFileReader $reader
+ */
+ public function __construct(ReversedFileReader $reader)
{
- $this->reader = new ReversedFileReader($filename);
- $this->_value = null;
- $this->_limit = $limit;
+ $this->reader = $reader;
}
- public function next()
+ /**
+ * @param string $filename File to open
+ * @return $this
+ */
+ public function open(string $filename): ParsedLogIterator
+ {
+ $this->reader->open($filename);
+ return $this;
+ }
+
+ /**
+ * @param int $limit Max num of lines to read
+ * @return $this
+ */
+ public function withLimit(int $limit): ParsedLogIterator
+ {
+ $this->limit = $limit;
+ return $this;
+ }
+
+ /**
+ * @param array $filters filters per column
+ * @return $this
+ */
+ public function withFilters(array $filters): ParsedLogIterator
+ {
+ $this->filters = $filters;
+ return $this;
+ }
+
+ /**
+ * @param string $search string to search to filter lines
+ * @return $this
+ */
+ public function withSearch(string $search): ParsedLogIterator
+ {
+ $this->search = $search;
+ return $this;
+ }
+
+ /**
+ * Check if parsed log line match filters.
+ * Always match if no filters are set.
+ *
+ * @param ParsedLogLine $parsedlogline ParsedLogLine instance
+ * @return bool Wether the parse log line matches
+ */
+ private function filter(ParsedLogLine $parsedlogline): bool
+ {
+ $match = true;
+ foreach ($this->filters as $filter => $filtervalue) {
+ switch ($filter) {
+ case "level":
+ $match = $match && ($parsedlogline->level == strtoupper($filtervalue));
+ break;
+ case "context":
+ $match = $match && ($parsedlogline->context == $filtervalue);
+ break;
+ }
+ }
+ return $match;
+ }
+
+ /**
+ * Check if parsed log line match search.
+ * Always match if no search query is set.
+ *
+ * @param ParsedLogLine $parsedlogline
+ * @return bool
+ */
+ private function search(ParsedLogLine $parsedlogline): bool
+ {
+ if ($this->search != "") {
+ return strstr($parsedlogline->logline, $this->search) !== false;
+ }
+ return true;
+ }
+
+ /**
+ * Read a line from reader and parse.
+ * Returns null if limit is reached or the reader is invalid.
+ *
+ * @param ParsedLogLine $parsedlogline
+ * @return ?ParsedLogLine
+ */
+ private function read()
{
$this->reader->next();
- if ($this->_limit > 0 && $this->reader->key() > $this->_limit) {
- $this->_value = null;
- return;
+ if ($this->limit > 0 && $this->reader->key() > $this->limit || !$this->reader->valid()) {
+ return null;
}
- if ($this->reader->valid()) {
- $line = $this->reader->current();
- $this->_value = new ParsedLog($this->reader->key(), $line);
- } else {
- $this->_value = null;
+
+ $line = $this->reader->current();
+ return new ParsedLogLine($this->reader->key(), $line);
+ }
+
+
+ /**
+ * Fetch next parsed log line which match with filters or search and
+ * set it as current iterator value.
+ *
+ * @see Iterator::next()
+ * @return void
+ */
+ public function next()
+ {
+ $parsed = $this->read();
+
+ while (is_null($parsed) == false && !($this->filter($parsed) && $this->search($parsed))) {
+ $parsed = $this->read();
}
+ $this->value = $parsed;
}
+ /**
+ * Rewind the iterator to the first matching log line
+ *
+ * @see Iterator::rewind()
+ * @return void
+ */
public function rewind()
{
- $this->_value = null;
+ $this->value = null;
$this->reader->rewind();
$this->next();
}
+ /**
+ * Return current parsed log line number
+ *
+ * @see Iterator::key()
+ * @see ReversedFileReader::key()
+ * @return int
+ */
public function key()
{
return $this->reader->key();
}
+ /**
+ * Return current iterator value
+ *
+ * @see Iterator::current()
+ * @return ?ParsedLogLing
+ */
public function current()
{
- return $this->_value;
+ return $this->value;
}
+ /**
+ * Checks if current iterator value is valid, that is, not null
+ *
+ * @see Iterator::valid()
+ * @return bool
+ */
public function valid()
{
- return ! is_null($this->_value);
+ return ! is_null($this->value);
}
-
}
-