iranianpep/botonomous

View on GitHub
src/Botonomous/utility/LoggerUtility.php

Summary

Maintainability
A
0 mins
Test Coverage
A
94%
<?php

namespace Botonomous\utility;

use Botonomous\BotonomousException;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
use Psr\Log\LoggerInterface;

/**
 * Class LoggerUtility.
 */
class LoggerUtility extends AbstractUtility
{
    const DATE_FORMAT = 'Y-m-d H:i:s';
    const TEMP_FOLDER = 'tmp';

    const DEBUG = 'debug';
    const INFO = 'info';
    const NOTICE = 'notice';
    const WARNING = 'warning';
    const ERROR = 'error';
    const CRITICAL = 'critical';
    const ALERT = 'alert';
    const EMERGENCY = 'emergency';

    const HANDLERS_KEY = 'handlers';

    public static $levels = [
        self::DEBUG,
        self::INFO,
        self::NOTICE,
        self::WARNING,
        self::ERROR,
        self::CRITICAL,
        self::ALERT,
        self::EMERGENCY,
    ];

    private $logger;

    /**
     * LoggerUtility constructor.
     *
     * @param null $config
     *
     * @throws \Exception
     */
    public function __construct($config = null)
    {
        parent::__construct($config);

        try {
            $this->initLogger();
        } catch (\Exception $e) {
            throw $e;
        }
    }

    /**
     * Init the logger.
     *
     * @throws \Exception
     */
    private function initLogger()
    {
        $monologConfig = $this->getMonologConfig();

        if (empty($monologConfig)) {
            throw new BotonomousException('Monolog config is missing');
        }

        $logger = new Logger($monologConfig['channel']);

        foreach (array_keys($monologConfig[self::HANDLERS_KEY]) as $value) {
            $logger = $this->pushMonologHandler($logger, $value);
        }

        $this->setLogger($logger);
    }

    /**
     * @throws \Exception
     *
     * @return mixed
     */
    private function getMonologConfig()
    {
        $loggerConfig = $this->getConfig()->get('logger');

        return !empty($loggerConfig['monolog']) ? $loggerConfig['monolog'] : false;
    }

    /**
     * @param Logger $logger
     * @param string $handlerKey
     *
     * @throws \Exception
     *
     * @return Logger
     */
    private function pushMonologHandler(Logger $logger, string $handlerKey): Logger
    {
        $activeHandlers = [];

        // if there are more $handlerKey, use switch
        if ($handlerKey === 'file') {
            $activeHandlers[] = new StreamHandler($this->getLogFilePath());
        }

        if (!empty($activeHandlers)) {
            foreach ($activeHandlers as $activeHandler) {
                $logger->pushHandler($activeHandler);
            }
        }

        return $logger;
    }

    /**
     * @throws \Exception
     *
     * @return false|string
     */
    public function getLogFilePath()
    {
        $monologConfigFile = $this->getMonologConfigFileName();
        if (empty($monologConfigFile)) {
            return false;
        }

        return $this->getTempDir().DIRECTORY_SEPARATOR.$monologConfigFile;
    }

    /**
     * @throws \Exception
     *
     * @return mixed
     */
    private function getMonologConfigFileName()
    {
        $monologConfig = $this->getMonologConfig();

        if (isset($monologConfig[self::HANDLERS_KEY]['file']['fileName'])) {
            return $monologConfig[self::HANDLERS_KEY]['file']['fileName'];
        }
    }

    /**
     * @return LoggerInterface
     */
    private function getLogger(): LoggerInterface
    {
        return $this->logger;
    }

    /**
     * @param LoggerInterface $logger
     */
    private function setLogger(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }

    /**
     * @param string $function
     * @param string $message
     * @param string $channel
     *
     * @throws \Exception
     *
     * @return bool
     */
    public function logChat(string $function, string $message = '', string $channel = ''): bool
    {
        try {
            return $this->logInfo('Log Chat', [
                'function' => $function,
                'message'  => $message,
                'channel'  => $channel,
            ]);
        } catch (\Exception $e) {
            throw new BotonomousException($e->getMessage());
        }
    }

    /**
     * @throws \Exception
     *
     * @return bool
     */
    private function canLog(): bool
    {
        $loggerConfig = $this->getConfig()->get('logger');

        return empty($loggerConfig['enabled']) ? false : true;
    }

    /**
     * @throws \Exception
     *
     * @return string
     */
    public function getTempDir(): string
    {
        return dirname(__DIR__).DIRECTORY_SEPARATOR.self::TEMP_FOLDER;
    }

    /**
     * @param $function
     * @param string $message
     * @param $channel
     *
     * @return string
     */
    public function getLogContent(string $function, string $message, string $channel): string
    {
        return "{$function}|{$message}|{$channel}";
    }

    /**
     * @param string $message
     * @param array  $context
     *
     * @throws \Exception
     *
     * @return bool
     */
    public function logDebug(string $message, array $context = []): bool
    {
        return $this->log(self::DEBUG, $message, $context);
    }

    /**
     * @param string $message
     * @param array  $context
     *
     * @throws \Exception
     *
     * @return bool
     */
    public function logInfo(string $message, array $context = []): bool
    {
        return $this->log(self::INFO, $message, $context);
    }

    /**
     * @param string $message
     * @param array  $context
     *
     * @throws \Exception
     *
     * @return bool
     */
    public function logNotice(string $message, array $context = []): bool
    {
        return $this->log(self::NOTICE, $message, $context);
    }

    /**
     * @param string $message
     * @param array  $context
     *
     * @throws \Exception
     *
     * @return bool
     */
    public function logWarning(string $message, array $context = []): bool
    {
        return $this->log(self::WARNING, $message, $context);
    }

    /**
     * @param string $message
     * @param array  $context
     *
     * @throws \Exception
     *
     * @return bool
     */
    public function logError(string $message, array $context = []): bool
    {
        return $this->log(self::ERROR, $message, $context);
    }

    /**
     * @param string $message
     * @param array  $context
     *
     * @throws \Exception
     *
     * @return bool
     */
    public function logCritical(string $message, array $context = []): bool
    {
        return $this->log(self::CRITICAL, $message, $context);
    }

    /**
     * @param string $message
     * @param array  $context
     *
     * @throws \Exception
     *
     * @return bool
     */
    public function logAlert(string $message, array $context = []): bool
    {
        return $this->log(self::ALERT, $message, $context);
    }

    /**
     * @param string $message
     * @param array  $context
     *
     * @throws \Exception
     *
     * @return bool
     */
    public function logEmergency(string $message, array $context = []): bool
    {
        return $this->log(self::EMERGENCY, $message, $context);
    }

    /**
     * @param string $level
     * @param $message
     * @param array $context
     *
     * @throws \Exception
     *
     * @return bool
     */
    public function log(string $level, string $message, array $context = []): bool
    {
        if ($this->canLog() !== true) {
            return false;
        }

        $logger = $this->getLogger();

        if (!in_array($level, self::$levels)) {
            throw new BotonomousException("'{$level}' is an invalid log level");
        }

        $logger->$level($message, $context);

        return true;
    }
}