<?php

   // Poziomy logowania. Im wyszy poziom, tym mniejsza waga wiadomoci.
   // Luki w numeracji pozwalaj na doczanie nowych poziomw.
   define('LOGGER_DEBUG', 100);
   define('LOGGER_INFO', 75);
   define('LOGGER_NOTICE', 50);
   define('LOGGER_WARNING', 25);
   define('LOGGER_ERROR', 10);
   define('LOGGER_CRITICAL', 5);

   class Logger {

      private $hLogFile;
      private $logLevel;

      // Uwaga: prywatny konstruktor. Klasa opiera si na wzorcu singleton.
      private function __construct() {
         global $cfg;  // globalna tablica z konfiguracj

         $this->logLevel = $cfg['LOGGER_LEVEL'];
         $logFilePath = $cfg['LOGGER_FILE'];

         if(!strlen($logFilePath)) {
            throw new Exception('W konfiguracji nie podano ' .
                                'nazwy pliku dziennika.');
         }

         // Otwiera plik dziennika. Tymczasowo wycza komunikaty o bdach.
         // Z bdami poradzimy sobie samodzielnie, zgaszajc wyjtek.
         $this->hLogFile = @fopen($logFilePath, 'a+');
         if(!is_resource($this->hLogFile)) {
            throw new Exception("Plik dziennika $logFilePath " .
                                'nie moe zosta otwarty ani utworzony.' .
                                'Sprawd uprawnienia.');
         }
      }

      public function __destruct() {
         if(is_resource($this->hLogFile)) {
            fclose($this->hLogFile);
         }
      }

      public static function getInstance() {
         static $objLog;

         if(!isset($objLog)) {
            $objLog = new Logger();
         }

         return $objLog;
      }

      public function logMessage($msg, $logLevel = LOGGER_INFO, $module = null) {
         if($logLevel <= $this->logLevel) {
            $time = strftime('%x %X', time());
            $msg = str_replace("\t", '    ', $msg);
            $msg = str_replace("\n", ' ', $msg);

            $strLogLevel = $this->levelToString($logLevel);

            if(isset($module)) {
               $module = str_replace("\t", '    ', $module);
               $module = str_replace("\n", ' ', $module);
            }

            // Zapisuje: data/czas poziom komunikat modu
            // oddzielony tabulacjami, zakoczony znakiem nowej linii.
            $logLine = "$time\t$strLogLevel\t$msg\t$module\n";
            fwrite($this->hLogFile, $logLine);
         }
      }

      public static function levelToString($logLevel) {
         switch ($logLevel) {
            case LOGGER_DEBUG:
               return 'LOGGER_DEBUG';
               break;
            case LOGGER_INFO:
               return 'LOGGER_INFO';
               break;
            case LOGGER_NOTICE:
               return 'LOGGER_NOTICE';
               break;
            case LOGGER_WARNING:
               return 'LOGGER_WARNING';
               break;
            case LOGGER_ERROR:
               return 'LOGGER_ERROR';
               break;
            case LOGGER_CRITICAL:
               return 'LOGGER_CRITICAL';
            default:
               return '[nieznany]';
         }
      }
   }

?>