<?php
//
// +----------------------------------------------------------------------+
// | PHP version 4.0                                                      |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997, 1998, 1999, 2000 The PHP Group                   |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.0 of the PHP license,       |
// | that is bundled with this package in the file LICENSE, and is        |
// | available at through the world-wide-web at                           |
// | http://www.php.net/license/2_02.txt.                                 |
// | If you did not receive a copy of the PHP license and are unable to   |
// | obtain it through the world-wide-web, please send a note to          |
// | license@php.net so we can mail you a copy immediately.               |
// +----------------------------------------------------------------------+
// | Authors: Sterling Hughes <sterling@php.net>                          |
// |          Stig Bakken <ssb@fast.no>                                   |
// +----------------------------------------------------------------------+
//
// $Id: PEAR.php.in,v 1.9 2000/10/15 09:02:54 ssb Exp $
//

define('PEAR_ERROR_RETURN', 1);
define('PEAR_ERROR_PRINT', 2);
define('PEAR_ERROR_TRIGGER', 4);
define('PEAR_ERROR_DIE', 8);
define('PEAR_ERROR_CALLBACK', 16);

define('PHP_BINDIR', '/boot/phpinst/bin');
define('PEAR_INSTALL_DIR', '/boot/phpinst/lib/php');
define('PEAR_EXTENSION_DIR', '/boot/phpinst/lib/php/extensions/no-debug-non-zts-20001214');

$_PEAR_destructor_object_list = array();

//
// Tests needed: - PEAR inheritance
//               - destructors
//

/**
 * Base class for other PEAR classes.  Provides rudimentary
 * emulation of destructors.
 *
 * If you want a destructor in your class, inherit PEAR and make a
 * destructor method called _yourclassname (same name as the
 * constructor, but with a "_" prefix).  Also, in your constructor you
 * have to call the PEAR constructor: <code>$this->PEAR();</code>.
 * The destructor method will be called without parameters.  Note that
 * at in some SAPI implementations (such as Apache), any output during
 * the request shutdown (in which destructors are called) seems to be
 * discarded.  If you need to get any debug information from your
 * destructor, use <code>error_log()</code>, <code>syslog()</code> or
 * something like that instead.
 *
 * @since PHP 4.0.2
 * @author Stig Bakken <ssb@fast.no>
 */
class PEAR
{
	// {{{ properties

	var $_debug = false;

	// }}}

    // {{{ constructor

    /**
     * Constructor.  Registers this object in
     * $_PEAR_destructor_object_list for destructor emulation.
     */
	function PEAR() {
		global $_PEAR_destructor_object_list;
		$_PEAR_destructor_object_list[] = &$this;
		if ($this->_debug) {
			printf("PEAR constructor called, class=%s\n",
				   get_class($this));
		}
	}

    // }}}
    // {{{ destructor

    /**
     * Destructor (the emulated type of...).  Does nothing right now,
	 * but is included for forward compatibility, so subclass
	 * destructors should always call it.
     * 
     * See the note in the class desciption about output from
     * destructors.
	 *
	 * @access public
     */
    function _PEAR() {
		if ($this->_debug) {
			printf("PEAR destructor called, class=%s\n",
				   get_class($this));
		}
    }

    // }}}
    // {{{ isError()

    /**
     * Tell whether a value is a PEAR error.
     *
     * @param	$data	the value to test
     * @access	public
     * @return	bool	true if $data is an error
     */
	function isError(&$data) {
		return (bool)(is_object($data) &&
					  (get_class($data) == "pear_error" ||
					   is_subclass_of($data, "pear_error")));
	}

    // }}}
}

// {{{ _PEAR_call_destructors()

function _PEAR_call_destructors() {
    global $_PEAR_destructor_object_list;
    if (is_array($_PEAR_destructor_object_list) && sizeof($_PEAR_destructor_object_list)) {
	reset($_PEAR_destructor_object_list);
	while (list($k, $objref) = each($_PEAR_destructor_object_list)) {
	    $destructor = "_".get_class($objref);
	    if (method_exists($objref, $destructor)) {
		$objref->$destructor();
	    }
	}
	// Empty the object list to ensure that destructors are
	// not called more than once.
	$_PEAR_destructor_object_list = array();
    }
}

// }}}

class PEAR_Error
{
    // {{{ properties

	var $error_message_prefix = '';
	var $error_prepend        = '';
	var $error_append         = '';
	var $mode                 = PEAR_ERROR_RETURN;
	var $level                = E_USER_NOTICE;
	var $code                 = -1;
	var $message              = '';
	var $debuginfo            = '';

	// Wait until we have a stack-groping function in PHP.
	//var $file    = '';
	//var $line    = 0;
	

    // }}}
    // {{{ constructor

	/**
	 * PEAR_Error constructor
	 *
	 * @param $message error message
	 *
	 * @param $code (optional) error code
	 *
	 * @param $mode (optional) error mode, one of: PEAR_ERROR_RETURN,
	 * PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER or
	 * PEAR_ERROR_CALLBACK
	 *
	 * @param $level (optional) error level, _OR_ in the case of
	 * PEAR_ERROR_CALLBACK, the callback function or object/method
	 * tuple.
	 *
	 * @access public
	 *
	 */
	function PEAR_Error($message = 'unknown error',
						$code = 0,
						$mode = null,
						$options = null,
						$debuginfo = null)
	{
		if ($mode === null) {
			$mode = PEAR_ERROR_RETURN;
		}
		$this->message   = $message;
		$this->code      = $code;
		$this->mode      = $mode;
		$this->debuginfo = $debuginfo;
		if ($mode & PEAR_ERROR_CALLBACK) {
			$this->level = E_USER_NOTICE;
			$this->callback = $options;
		} else {
			if ($options === null) {
				$options = E_USER_NOTICE;
			}
			$this->level = $options;
			$this->callback = null;
		}
		if ($this->mode & PEAR_ERROR_PRINT) {
			print $this->getMessage();
		}
		if ($this->mode & PEAR_ERROR_TRIGGER) {
			trigger_error($this->getMessage(), $this->level);
		}
		if ($this->mode & PEAR_ERROR_DIE) {
			die($this->getMessage());
		}
		if ($this->mode & PEAR_ERROR_CALLBACK) {
			if (is_string($this->callback) && strlen($this->callback)) {
				call_user_func($this->callback, $this);
			} elseif (is_array($this->callback) &&
					  sizeof($this->callback) == 2 &&
					  is_object($this->callback[0]) &&
					  is_string($this->callback[1]) &&
					  strlen($this->callback[1])) {
				call_user_method($this->callback[1], $this->callback[0],
								 $this);
			}
		}
	}

    // }}}
    // {{{ getMode()

	/**
	 * Get the error mode from an error object.
	 *
	 * @return int error mode
	 * @access public
	 */
	function getMode() {
		return $this->mode;
	}

    // }}}
    // {{{ getCallback()

	/**
	 * Get the callback function/method from an error object.
	 *
	 * @return mixed callback function or object/method array
	 * @access public
	 */
	function getCallback() {
		return $this->callback;
	}

    // }}}
    // {{{ getMessage()

	
	/**
	 * Get the error message from an error object.
	 *
	 * @return	string	full error message
	 * @access public
	 */
	function getMessage ()
	{
		return ($this->error_prepend . $this->error_message_prefix .
		        $this->message       . $this->error_append);
	}
	

    // }}}
    // {{{ getCode()
    
	/**
	 * Get error code from an error object
	 *
	 * @return int error code
	 * @access public
	 */
	 function getCode()
	 {
	 	return $this->code;
	 }

    // }}}
    // {{{ getType()

	/**
	 * Get the name of this error/exception.
	 *
	 * @return string error/exception name (type)
	 * @access public
	 */
	function getType ()
	{
		return get_class($this);
	}

    // }}}
    // {{{ getDebugInfo()

	/**
	 * Get additional debug information supplied by the application.
	 *
	 * @return string debug information
	 * @access public
	 */
	function getDebugInfo ()
	{
		return $this->debuginfo;
	}

    // }}}
    // {{{ toString()

	/**
	 * Make a string representation of this object.
	 *
	 * @return string a string with an object summary
	 * @access public
	 */
	function toString() {
		$modes = array();
		$levels = array(E_USER_NOTICE => "notice",
						E_USER_WARNING => "warning",
						E_USER_ERROR => "error");
		if ($this->mode & PEAR_ERROR_CALLBACK) {
			if (is_array($this->callback)) {
				$callback = get_class($this->callback[0]) . "::" .
					$this->callback[1];
			} else {
				$callback = $this->callback;
			}
			return sprintf('[%s: message="%s" code=%d mode=callback '.
						   'callback=%s prefix="%s" prepend="%s" append="%s" '.
						   'debug="%s"]',
						   get_class($this), $this->message, $this->code,
						   $callback, $this->error_message_prefix,
						   $this->error_prepend, $this->error_append,
						   $this->debuginfo);
		}
		if ($this->mode & PEAR_ERROR_CALLBACK) {
			$modes[] = "callback";
		}
		if ($this->mode & PEAR_ERROR_PRINT) {
			$modes[] = "print";
		}
		if ($this->mode & PEAR_ERROR_TRIGGER) {
			$modes[] = "trigger";
		}
		if ($this->mode & PEAR_ERROR_DIE) {
			$modes[] = "die";
		}
		if ($this->mode & PEAR_ERROR_RETURN) {
			$modes[] = "return";
		}
		return sprintf('[%s: message="%s" code=%d mode=%s level=%s prefix="%s" '.
					   'prepend="%s" append="%s" debug="%s"]',
					   get_class($this), $this->message, $this->code,
					   implode("|", $modes), $levels[$this->level],
					   $this->error_message_prefix,
					   $this->error_prepend, $this->error_append,
					   $this->debuginfo);
	}

    // }}}
}

register_shutdown_function("_PEAR_call_destructors");

/*
 * Local Variables:
 * mode: c++
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 */
?>
