strata-mvc/strata

View on GitHub
src/Logger/LoggerBase.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php

namespace Strata\Logger;

use Strata\Strata;
use Strata\Core\StrataConfigurableTrait;
use Strata\Core\StrataObjectTrait;

/**
 * Log messages to the application's log file.
 */
class LoggerBase
{
    use StrataConfigurableTrait;
    use StrataObjectTrait;

    const PLAIN = 1;
    const COLOR = 2;

    public $colors = array(
        'black' => 30,
        'red' => 91,
        'green' => 32,
        'yellow' => 33,
        'blue' => 34,
        'magenta' => 35,
        'cyan' => 36,
        'white' => 37
    );

    public $styles = array(
        'emergency' => ['text' => 'red'],
        'alert' => ['text' => 'red'],
        'critical' => ['text' => 'red'],
        'error' => ['text' => 'red'],
        'warning' => ['text' => 'yellow'],
        'info' => ['text' => 'cyan'],
        'debug' => ['text' => 'yellow'],
        'success' => ['text' => 'green'],
        'comment' => ['text' => 'blue'],
        'question' => ['text' => 'magenta'],
        'notice' => ['text' => 'cyan']
    );

    /**
     * The stack context helps carrying visual context
     * to the log by indenting the lines.
     * @var array
     */
    protected $stackContext = array();

    /**
     * Returns the default class name suffix for this object.
     * @return string
     */
    public static function getClassNameSuffix()
    {
        return "Logger";
    }

    public static function getNamespaceStringInStrata()
    {
        return "Logger";
    }

    public static function getFactoryScopes($name)
    {
        return array(
            self::generateClassPath($name),
            self::generateClassPath($name, false)
        );
    }

    public function initialize()
    {
        if ((DIRECTORY_SEPARATOR === '\\' && !(bool)getenv('ANSICON') && getenv('ConEmuANSI') !== 'ON') ||
            (function_exists('posix_isatty') && !posix_isatty($this->getConfig('output')))
        ) {
            $this->setConfig("outputAs", LoggerBase::PLAIN);
        } else {
            $this->setConfig("outputAs", LoggerBase::COLOR);
        }
    }

    /**
     * Sends a message of type log
     * @param  string $message
     * @param  string $context (optional) Flag to separate message types
     */
    public function log($message, $context = "Strata:Log")
    {
        $this->write($context, $this->indent($message));
    }

    /**
     * Sends a message of type debug
     * @param  string $message
     * @param  string $context (optional) Flag to separate message types
     */
    public function debug($message, $context = "Strata:Debug")
    {
        $this->write("<question>" . $context . "</question>", $message);
    }

    /**
     * Sends a message of type debug
     * @param  string $message
     * @param  string $context (optional) Flag to separate message types
     */
    public function error($message, $context = "Strata:Error")
    {
        $this->write('<critical>' . $context . '</critical>', '<critical>' . $message . '</critical>');
    }

    public function nl()
    {
        $this->writeNl();
    }

    public function logNewContext($message, $context =  "Strata:Log", $style = "black")
    {
        $this->write($context, $this->indent("/ ") . $message);
        $this->stackContext[] = $style;
    }

    public function logContextEnd($message, $context =  "Strata:Log", $style = "black")
    {
        array_pop($this->stackContext);
        $this->write($context, $this->indent("\ ") . $message);
    }

    public function write($message, $context)
    {
        return false;
    }

    public function writeNl()
    {
        return false;
    }

    protected function format($message)
    {
        $length = strlen(preg_replace('#</?.+?>#', '', $message));

        // Largest internal known message is Template
        $minLength = 13;
        if (preg_match('#(</.+?>)#', $message, $matches)) {
            $minLength += (strlen($matches[1]) * 2) + 1;

        }

        return $this->formatColor($this->formatType(str_pad($message, $minLength)));
    }

    private function formatColor($text)
    {
        if ($this->getConfig("outputAs") === LoggerBase::PLAIN) {
            return preg_replace('#</?.+?>#', '', $text);
        }

        $tags = array_keys($this->styles) + array_keys($this->colors);
        return preg_replace_callback(
            '/<(?P<tag>[a-z0-9-_]+)>(?P<text>.*?)<\/(\1)>/ims',
            [$this, 'replaceTags'],
            $text
        );
    }

    protected function replaceTags($matches)
    {
        if (array_key_exists($matches['tag'], $this->colors)) {
            $frontColor = $this->colors[$matches['tag']];
            return "\033[" . $frontColor . 'm' . $matches['text'] . "\033[0m";
        }

        if (array_key_exists($matches['tag'], $this->styles)) {
            $styles = $this->styles[$matches['tag']];
            if (array_key_exists($styles['text'], $this->colors)) {
                $frontColor = $this->colors[$styles['text']];
                return "\033[" . $frontColor . 'm' . $matches['text'] . "\033[0m";
            }
        }

        return '<' . $matches['tag'] . '>' . $matches['text'] . '</' . $matches['tag'] . '>';
    }

    private function formatType($data)
    {
        if (is_string($data)) {
            return $data;
        }

        $object = is_object($data);
        if ($object && method_exists($data, '__toString')) {
            return (string)$data;
        }

        if ($object && $data instanceof JsonSerializable) {
            return json_encode($data);
        }

        return print_r($data, true);
    }

    private function indent($text)
    {
        if ($this->getConfig("outputAs") === LoggerBase::PLAIN) {
            return str_repeat("  ", count($this->stackContext)) . $text;
        }

        $str = "";
        foreach ($this->stackContext as $context) {
            $str .= "│ ";
        }

        return $str . $text;
    }
}