1: <?php
2: 3: 4: 5: 6: 7: 8: 9:
10:
11: namespace Kotchasan\Log;
12:
13: use Kotchasan\File;
14: use Kotchasan\Language;
15: use Psr\Log\LoggerInterface;
16: use Psr\Log\LogLevel;
17:
18: 19: 20: 21: 22: 23: 24:
25: class Logger extends AbstractLogger implements LoggerInterface
26: {
27: 28: 29:
30: protected static $instance = null;
31: 32: 33: 34: 35:
36: protected $logLevels = array(
37: LogLevel::EMERGENCY => 0,
38: LogLevel::ALERT => 1,
39: LogLevel::CRITICAL => 2,
40: LogLevel::ERROR => 3,
41: LogLevel::WARNING => 4,
42: LogLevel::NOTICE => 5,
43: LogLevel::INFO => 6,
44: LogLevel::DEBUG => 7,
45: );
46: 47: 48: 49: 50:
51: protected $options = array(
52: 'dateFormat' => 'Y-m-d H:i:s',
53: 'logFormat' => '[{datetime}] {level}: {message} {context}',
54: 'logFilePath' => 'logs/',
55: 'extension' => 'php',
56: );
57:
58: 59: 60: 61: 62: 63: 64:
65: public static function create(array $options = array())
66: {
67: if (null === self::$instance) {
68: self::$instance = new static($options);
69: }
70:
71: return self::$instance;
72: }
73:
74: 75: 76: 77: 78: 79: 80:
81: public function log($level, $message, array $context = array())
82: {
83: $patt = array(
84: 'datetime' => date($this->options['dateFormat'], time()),
85: 'level' => isset($this->logLevels[$level]) ? strtoupper($level) : 'UNKNOW',
86: 'message' => $message,
87: 'context' => empty($context) ? '' : json_encode($context),
88: );
89: $message = $this->options['logFormat'];
90: foreach ($patt as $key => $value) {
91: $message = str_replace('{'.$key.'}', $value, $message);
92: }
93: $message = "\n".preg_replace('/[\s\n\t\r]+/', ' ', $message);
94: if (File::makeDirectory($this->options['logFilePath'])) {
95:
96: switch ($level) {
97: case LogLevel::DEBUG:
98: case LogLevel::INFO:
99: case LogLevel::ALERT:
100: $file = $this->options['logFilePath'].date('Y-m-d').'.'.$this->options['extension'];
101: break;
102: default:
103: $file = $this->options['logFilePath'].'error_log.'.$this->options['extension'];
104: break;
105: }
106:
107: if (file_exists($file)) {
108: $f = @fopen($file, 'a');
109: } else {
110: $f = @fopen($file, 'w');
111: if ($f && $this->options['extension'] == 'php') {
112: fwrite($f, '<'.'?php exit() ?'.'>');
113: }
114: }
115: if ($f) {
116: fwrite($f, $message);
117: fclose($f);
118: } else {
119: printf(Language::get('File %s cannot be created or is read-only.'), 'log');
120: }
121: } else {
122: printf(Language::get('Directory %s cannot be created or is read-only.'), 'logs/');
123: echo $message;
124: }
125: }
126:
127: 128: 129: 130: 131:
132: private function __construct($options)
133: {
134: $this->options['logFilePath'] = ROOT_PATH.'datas/logs/';
135: foreach ($options as $key => $value) {
136: $this->options[$key] = $value;
137: }
138: }
139: }
140: