1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
20:
21: 22: 23: 24: 25: 26: 27: 28: 29: 30:
31: class LoggerConfiguratorDefault implements LoggerConfigurator
32: {
33:
34: const FORMAT_XML = 'xml';
35:
36:
37: const FORMAT_PHP = 'php';
38:
39:
40: const FORMAT_INI = 'ini';
41:
42:
43: private $adapters = array(
44: self::FORMAT_XML => 'LoggerConfigurationAdapterXML',
45: self::FORMAT_INI => 'LoggerConfigurationAdapterINI',
46: self::FORMAT_PHP => 'LoggerConfigurationAdapterPHP',
47: );
48:
49:
50: private static $defaultConfiguration = array(
51: 'threshold' => 'ALL',
52: 'rootLogger' => array(
53: 'level' => 'DEBUG',
54: 'appenders' => array('default'),
55: ),
56: 'appenders' => array(
57: 'default' => array(
58: 'class' => 'LoggerAppenderEcho'
59: ),
60: ),
61: );
62:
63:
64: private $appenders = array();
65:
66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81:
82: public function configure(LoggerHierarchy $hierarchy, $input = null) {
83: $config = $this->parse($input);
84: $this->doConfigure($hierarchy, $config);
85: }
86:
87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99:
100: public function parse($input) {
101:
102: if (!isset($input)) {
103: $config = self::$defaultConfiguration;
104: }
105:
106:
107: else if (is_array($input)) {
108: $config = $input;
109: }
110:
111:
112: else if (is_string($input)) {
113: try {
114: $config = $this->parseFile($input);
115: } catch (LoggerException $e) {
116: $this->warn("Configuration failed. " . $e->getMessage() . " Using default configuration.");
117: $config = self::$defaultConfiguration;
118: }
119: }
120:
121:
122: else {
123: $this->warn("Invalid configuration param given. Reverting to default configuration.");
124: $config = self::$defaultConfiguration;
125: }
126:
127: return $config;
128: }
129:
130: 131: 132: 133:
134: public static function getDefaultConfiguration() {
135: return self::$defaultConfiguration;
136: }
137:
138: 139: 140: 141: 142: 143: 144: 145: 146: 147:
148: private function parseFile($url) {
149:
150: if (!file_exists($url)) {
151: throw new LoggerException("File not found at [$url].");
152: }
153:
154: $type = $this->getConfigType($url);
155: $adapterClass = $this->adapters[$type];
156:
157: $adapter = new $adapterClass();
158: return $adapter->convert($url);
159: }
160:
161:
162: private function getConfigType($url) {
163: $info = pathinfo($url);
164: $ext = strtolower($info['extension']);
165:
166: switch($ext) {
167: case 'xml':
168: return self::FORMAT_XML;
169:
170: case 'ini':
171: case 'properties':
172: return self::FORMAT_INI;
173:
174: case 'php':
175: return self::FORMAT_PHP;
176:
177: default:
178: throw new LoggerException("Unsupported configuration file extension: $ext");
179: }
180: }
181:
182: 183: 184: 185: 186: 187:
188: private function doConfigure(LoggerHierarchy $hierarchy, $config) {
189: if (isset($config['threshold'])) {
190: $threshold = LoggerLevel::toLevel($config['threshold']);
191: if (isset($threshold)) {
192: $hierarchy->setThreshold($threshold);
193: } else {
194: $this->warn("Invalid threshold value [{$config['threshold']}] specified. Ignoring threshold definition.");
195: }
196: }
197:
198:
199: if (isset($config['appenders']) && is_array($config['appenders'])) {
200: foreach($config['appenders'] as $name => $appenderConfig) {
201: $this->configureAppender($name, $appenderConfig);
202: }
203: }
204:
205:
206: if (isset($config['rootLogger'])) {
207: $this->configureRootLogger($hierarchy, $config['rootLogger']);
208: }
209:
210:
211: if (isset($config['loggers']) && is_array($config['loggers'])) {
212: foreach($config['loggers'] as $loggerName => $loggerConfig) {
213: $this->configureOtherLogger($hierarchy, $loggerName, $loggerConfig);
214: }
215: }
216:
217:
218: if (isset($config['renderers']) && is_array($config['renderers'])) {
219: foreach($config['renderers'] as $rendererConfig) {
220: $this->configureRenderer($hierarchy, $rendererConfig);
221: }
222: }
223:
224: if (isset($config['defaultRenderer'])) {
225: $this->configureDefaultRenderer($hierarchy, $config['defaultRenderer']);
226: }
227: }
228:
229: private function configureRenderer(LoggerHierarchy $hierarchy, $config) {
230: if (empty($config['renderingClass'])) {
231: $this->warn("Rendering class not specified. Skipping renderer definition.");
232: return;
233: }
234:
235: if (empty($config['renderedClass'])) {
236: $this->warn("Rendered class not specified. Skipping renderer definition.");
237: return;
238: }
239:
240:
241: $hierarchy->getRendererMap()->addRenderer($config['renderedClass'], $config['renderingClass']);
242: }
243:
244: private function configureDefaultRenderer(LoggerHierarchy $hierarchy, $class) {
245: if (empty($class)) {
246: $this->warn("Rendering class not specified. Skipping default renderer definition.");
247: return;
248: }
249:
250:
251: $hierarchy->getRendererMap()->setDefaultRenderer($class);
252: }
253:
254: 255: 256: 257: 258: 259:
260: private function configureAppender($name, $config) {
261:
262:
263: if (!is_array($config)) {
264: $type = gettype($config);
265: $this->warn("Invalid configuration provided for appender [$name]. Expected an array, found <$type>. Skipping appender definition.");
266: return;
267: }
268:
269:
270: $class = $config['class'];
271: if (empty($class)) {
272: $this->warn("No class given for appender [$name]. Skipping appender definition.");
273: return;
274: }
275: if (!class_exists($class)) {
276: $this->warn("Invalid class [$class] given for appender [$name]. Class does not exist. Skipping appender definition.");
277: return;
278: }
279:
280:
281: $appender = new $class($name);
282: if (!($appender instanceof LoggerAppender)) {
283: $this->warn("Invalid class [$class] given for appender [$name]. Not a valid LoggerAppender class. Skipping appender definition.");
284: return;
285: }
286:
287:
288: if (isset($config['threshold'])) {
289: $threshold = LoggerLevel::toLevel($config['threshold']);
290: if ($threshold instanceof LoggerLevel) {
291: $appender->setThreshold($threshold);
292: } else {
293: $this->warn("Invalid threshold value [{$config['threshold']}] specified for appender [$name]. Ignoring threshold definition.");
294: }
295: }
296:
297:
298: if ($appender->requiresLayout() && isset($config['layout'])) {
299: $this->createAppenderLayout($appender, $config['layout']);
300: }
301:
302:
303: if (isset($config['filters']) && is_array($config['filters'])) {
304: foreach($config['filters'] as $filterConfig) {
305: $this->createAppenderFilter($appender, $filterConfig);
306: }
307: }
308:
309:
310: if (isset($config['params'])) {
311: $this->setOptions($appender, $config['params']);
312: }
313:
314:
315: $appender->activateOptions();
316: $this->appenders[$name] = $appender;
317: }
318:
319: 320: 321: 322: 323:
324: private function createAppenderLayout(LoggerAppender $appender, $config) {
325: $name = $appender->getName();
326: $class = $config['class'];
327: if (empty($class)) {
328: $this->warn("Layout class not specified for appender [$name]. Reverting to default layout.");
329: return;
330: }
331: if (!class_exists($class)) {
332: $this->warn("Nonexistant layout class [$class] specified for appender [$name]. Reverting to default layout.");
333: return;
334: }
335:
336: $layout = new $class();
337: if (!($layout instanceof LoggerLayout)) {
338: $this->warn("Invalid layout class [$class] sepcified for appender [$name]. Reverting to default layout.");
339: return;
340: }
341:
342: if (isset($config['params'])) {
343: $this->setOptions($layout, $config['params']);
344: }
345:
346: $layout->activateOptions();
347: $appender->setLayout($layout);
348: }
349:
350: 351: 352: 353: 354: 355:
356: private function createAppenderFilter(LoggerAppender $appender, $config) {
357: $name = $appender->getName();
358: $class = $config['class'];
359: if (!class_exists($class)) {
360: $this->warn("Nonexistant filter class [$class] specified on appender [$name]. Skipping filter definition.");
361: return;
362: }
363:
364: $filter = new $class();
365: if (!($filter instanceof LoggerFilter)) {
366: $this->warn("Invalid filter class [$class] sepcified on appender [$name]. Skipping filter definition.");
367: return;
368: }
369:
370: if (isset($config['params'])) {
371: $this->setOptions($filter, $config['params']);
372: }
373:
374: $filter->activateOptions();
375: $appender->addFilter($filter);
376: }
377:
378: 379: 380: 381:
382: private function configureRootLogger(LoggerHierarchy $hierarchy, $config) {
383: $logger = $hierarchy->getRootLogger();
384: $this->configureLogger($logger, $config);
385: }
386:
387: 388: 389: 390:
391: private function configureOtherLogger(LoggerHierarchy $hierarchy, $name, $config) {
392:
393: $logger = $hierarchy->getLogger($name);
394: $this->configureLogger($logger, $config);
395: }
396:
397: 398: 399: 400: 401: 402:
403: private function configureLogger(Logger $logger, $config) {
404: $loggerName = $logger->getName();
405:
406:
407: if (isset($config['level'])) {
408: $level = LoggerLevel::toLevel($config['level']);
409: if (isset($level)) {
410: $logger->setLevel($level);
411: } else {
412: $this->warn("Invalid level value [{$config['level']}] specified for logger [$loggerName]. Ignoring level definition.");
413: }
414: }
415:
416:
417: if (isset($config['appenders'])) {
418: foreach($config['appenders'] as $appenderName) {
419: if (isset($this->appenders[$appenderName])) {
420: $logger->addAppender($this->appenders[$appenderName]);
421: } else {
422: $this->warn("Nonexistnant appender [$appenderName] linked to logger [$loggerName].");
423: }
424: }
425: }
426:
427:
428: if (isset($config['additivity'])) {
429: try {
430: $additivity = LoggerOptionConverter::toBooleanEx($config['additivity'], null);
431: $logger->setAdditivity($additivity);
432: } catch (Exception $ex) {
433: $this->warn("Invalid additivity value [{$config['additivity']}] specified for logger [$loggerName]. Ignoring additivity setting.");
434: }
435: }
436: }
437:
438: 439: 440: 441: 442: 443: 444: 445: 446: 447: 448: 449: 450: 451: 452: 453: 454: 455: 456: 457: 458: 459: 460:
461: private function setOptions($object, $options) {
462: foreach($options as $name => $value) {
463: $setter = "set$name";
464: if (method_exists($object, $setter)) {
465: $object->$setter($value);
466: } else {
467: $class = get_class($object);
468: $this->warn("Nonexistant option [$name] specified on [$class]. Skipping.");
469: }
470: }
471: }
472:
473:
474: private function warn($message) {
475: trigger_error("log4php: $message", E_USER_WARNING);
476: }
477: }
478: