rodrigorm/audit

View on GitHub
src/Audit/Reader.php

Summary

Maintainability
A
1 hr
Test Coverage
<?php

namespace RodrigoRM\Audit;

use RodrigoRM\Audit\Builder;
use RodrigoRM\Audit\Record\Entry;
use RodrigoRM\Audit\Record\Leave;
use RodrigoRM\Audit\Record\End;
use RodrigoRM\Audit\InvalidRecordException;

class Reader
{
    const DATETIME_FORMAT = 'Y-m-d G:i:s';

    const RECORD_DELIMITER = "\t";

    const RECORD_FIELD_LEVEL = 0;
    const RECORD_FIELD_STACK = 1;
    const RECORD_FIELD_TYPE = 2;
    const RECORD_FIELD_TIME = 3;
    const RECORD_FIELD_MEMORY = 4;
    const RECORD_FIELD_FUNCTION = 5;
    const RECORD_FIELD_USER_DEFINED = 6;
    const RECORD_FIELD_INCLUDE = 7;
    const RECORD_FIELD_FILENAME = 8;
    const RECORD_FIELD_LINE = 9;

    const RECORD_TYPE_ENTRY = '0';
    const RECORD_TYPE_EXIT  = '1';
    const RECORD_TYPE_END  = '';

    private $builder;

    public function __construct(Builder $builder)
    {
        $this->builder = $builder;
    }

    public function read($filename)
    {
        $file = fopen($filename, 'r');
        $this->parse($file);
    }

    private function parse($file)
    {
        $line = 1;
        while (!feof($file)) {
            $this->parseRow(trim(fgets($file), "\n"), $line++);
        }
    }

    private function parseRow($row, $line)
    {
        if (preg_match('@^Version: (.*)@', $row, $matches)) {
            $this->builder->setVersion($matches[1]);
        } elseif (preg_match('@^File format: (.*)@', $row, $matches)) {
            $this->builder->setFileFormat($matches[1]);
        } elseif (preg_match('@^TRACE\s+(START|END)\s+\[(.*)\]@', $row, $matches)) {
            $date = \DateTime::createFromFormat(self::DATETIME_FORMAT, $matches[2]);
            if ($matches[1] == 'START') {
                $this->builder->traceStart($date);
            } else {
                $this->builder->traceEnd($date);
            }
        } elseif (trim($row) != '') {
            $this->parseRecord($row, $line);
        }
    }

    private function parseRecord($row, $line)
    {
        $values = explode(self::RECORD_DELIMITER, $row);
        $type = $values[self::RECORD_FIELD_TYPE];

        if ($type == self::RECORD_TYPE_ENTRY) {
            return $this->builder->addEntryRecord(new Entry(
                $values[self::RECORD_FIELD_LEVEL],
                $values[self::RECORD_FIELD_STACK],
                $values[self::RECORD_FIELD_TIME],
                $values[self::RECORD_FIELD_MEMORY],
                $values[self::RECORD_FIELD_FUNCTION],
                $values[self::RECORD_FIELD_USER_DEFINED],
                $values[self::RECORD_FIELD_INCLUDE],
                $values[self::RECORD_FIELD_FILENAME],
                $values[self::RECORD_FIELD_LINE]
            ));
        } elseif ($type == self::RECORD_TYPE_EXIT) {
            return $this->builder->addLeaveRecord(new Leave(
                $values[self::RECORD_FIELD_LEVEL],
                $values[self::RECORD_FIELD_STACK],
                $values[self::RECORD_FIELD_TIME],
                $values[self::RECORD_FIELD_MEMORY]
            ));
        } elseif ($type == self::RECORD_TYPE_END) {
            return $this->builder->addEndRecord(new End(
                $values[self::RECORD_FIELD_TIME],
                $values[self::RECORD_FIELD_MEMORY]
            ));
        }

        throw new InvalidRecordException(sprintf('Invalid record found at line %s', $line));
    }
}