1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
18:
19: App::uses('BaseLog', 'Log/Engine');
20: App::uses('Hash', 'Utility');
21: App::uses('CakeNumber', 'Utility');
22:
23: 24: 25: 26: 27: 28:
29: class FileLog extends BaseLog {
30:
31: 32: 33: 34: 35: 36:
37: protected $_defaults = array(
38: 'path' => LOGS,
39: 'file' => null,
40: 'types' => null,
41: 'scopes' => array(),
42: 'rotate' => 10,
43: 'size' => 10485760,
44: 'mask' => null,
45: );
46:
47: 48: 49: 50: 51:
52: protected $_path = null;
53:
54: 55: 56: 57: 58:
59: protected $_file = null;
60:
61: 62: 63: 64: 65:
66: protected $_size = null;
67:
68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87:
88: public function __construct($config = array()) {
89: $config = Hash::merge($this->_defaults, $config);
90: parent::__construct($config);
91: }
92:
93: 94: 95: 96: 97: 98:
99: public function config($config = array()) {
100: parent::config($config);
101:
102: if (!empty($config['path'])) {
103: $this->_path = $config['path'];
104: }
105: if (Configure::read('debug') && !is_dir($this->_path)) {
106: mkdir($this->_path, 0775, true);
107: }
108:
109: if (!empty($config['file'])) {
110: $this->_file = $config['file'];
111: if (substr($this->_file, -4) !== '.log') {
112: $this->_file .= '.log';
113: }
114: }
115: if (!empty($config['size'])) {
116: if (is_numeric($config['size'])) {
117: $this->_size = (int)$config['size'];
118: } else {
119: $this->_size = CakeNumber::fromReadableSize($config['size']);
120: }
121: }
122:
123: return $this->_config;
124: }
125:
126: 127: 128: 129: 130: 131: 132:
133: public function write($type, $message) {
134: $output = date('Y-m-d H:i:s') . ' ' . ucfirst($type) . ': ' . $message . "\n";
135: $filename = $this->_getFilename($type);
136: if (!empty($this->_size)) {
137: $this->_rotateFile($filename);
138: }
139:
140: $pathname = $this->_path . $filename;
141: if (empty($this->_config['mask'])) {
142: return file_put_contents($pathname, $output, FILE_APPEND);
143: }
144:
145: $exists = file_exists($pathname);
146: $result = file_put_contents($pathname, $output, FILE_APPEND);
147: static $selfError = false;
148: if (!$selfError && !$exists && !chmod($pathname, (int)$this->_config['mask'])) {
149: $selfError = true;
150: trigger_error(__d(
151: 'cake_dev', 'Could not apply permission mask "%s" on log file "%s"',
152: array($this->_config['mask'], $pathname)), E_USER_WARNING);
153: $selfError = false;
154: }
155: return $result;
156: }
157:
158: 159: 160: 161: 162: 163:
164: protected function _getFilename($type) {
165: $debugTypes = array('notice', 'info', 'debug');
166:
167: if (!empty($this->_file)) {
168: $filename = $this->_file;
169: } elseif ($type === 'error' || $type === 'warning') {
170: $filename = 'error.log';
171: } elseif (in_array($type, $debugTypes)) {
172: $filename = 'debug.log';
173: } else {
174: $filename = $type . '.log';
175: }
176:
177: return $filename;
178: }
179:
180: 181: 182: 183: 184: 185: 186: 187:
188: protected function _rotateFile($filename) {
189: $filepath = $this->_path . $filename;
190: if (version_compare(PHP_VERSION, '5.3.0') >= 0) {
191: clearstatcache(true, $filepath);
192: } else {
193: clearstatcache();
194: }
195:
196: if (!file_exists($filepath) ||
197: filesize($filepath) < $this->_size
198: ) {
199: return;
200: }
201:
202: if ($this->_config['rotate'] === 0) {
203: $result = unlink($filepath);
204: } else {
205: $result = rename($filepath, $filepath . '.' . time());
206: }
207:
208: $files = glob($filepath . '.*');
209: if ($files) {
210: $filesToDelete = count($files) - $this->_config['rotate'];
211: while ($filesToDelete > 0) {
212: unlink(array_shift($files));
213: $filesToDelete--;
214: }
215: }
216:
217: return $result;
218: }
219:
220: }
221: