<?php
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Logs messages as HTTP headers using the FirePHP Insight API.
 * 
 * This appender requires the FirePHP server library version 1.0 or later.
 * 
 * ## Configurable parameters: ##
 * 
 * - **target** - (string) The target to which messages will be sent. Possible options are 
 *            'page' (default), 'request', 'package' and 'controller'. For more details,
 *            see FirePHP documentation.
 * 
 * This class was originally contributed by Bruce Ingalls (Bruce.Ingalls-at-gmail-dot-com).
 * 
 * @link https://github.com/firephp/firephp FirePHP homepage.
 * @link http://sourcemint.com/github.com/firephp/firephp/1:1.0.0b1rc6/-docs/Welcome FirePHP documentation.
 * @link http://sourcemint.com/github.com/firephp/firephp/1:1.0.0b1rc6/-docs/Configuration/Constants FirePHP constants documentation.
 * @link http://logging.apache.org/log4php/docs/appenders/firephp.html Appender documentation
 * 
 * @version $Revision$
 * @package log4php
 * @subpackage appenders
 * @since 2.3
 */
class LoggerAppenderFirePHP extends LoggerAppender {
	
	/**
	 * Instance of the Insight console class.
	 * @var Insight_Plugin_Console
	 */
	protected $console;
	
	/**
	 * The target for log messages. Possible values are: 'page' (default), 
	 * 'request', 'package' and 'controller'.
	 */
	protected $target = 'page';

	public function activateOptions() {
		if (method_exists('FirePHP', 'to')) {
			$this->console = FirePHP::to($this->target)->console();
			$this->closed = false;
		} else {
			$this->warn('FirePHP is not installed correctly. Closing appender.');
		}
	}
	
	public function append(LoggerLoggingEvent $event) {
		$msg = $event->getMessage();
		
		// Skip formatting for objects and arrays which are handled by FirePHP.
		if (!is_array($msg) && !is_object($msg)) {
			$msg = $this->getLayout()->format($event);
		}
		
		switch ($event->getLevel()->toInt()) {
			case LoggerLevel::TRACE:
			case LoggerLevel::DEBUG:
				$this->console->log($msg);
				break;
			case LoggerLevel::INFO:
				$this->console->info($msg);
				break;
			case LoggerLevel::WARN:
				$this->console->warn($msg);
				break;
			case LoggerLevel::ERROR:
			case LoggerLevel::FATAL:
				$this->console->error($msg);
				break;
		}
	}
	
	/** Returns the target. */
	public function getTarget() {
		return $this->target;
	}

	/** Sets the target. */
	public function setTarget($target) {
		$this->setString('target', $target);
	}
}