<?php

/*
 * Configuration :
 * // Log file
 * $log_file='/path/to/app.log';
 *
 * // Log level (DEBUG / INFO / WARNING / ERROR / FATAL)
 * $log_level='INFO';
 */


// Log file descriptor (Do not change !!!)
$_log_file_fd=null;

// Log Levels
$_log_levels=array(
  'TRACE' => 0,
  'DEBUG' => 1,
  'INFO' => 2,
  'WARNING' => 3,
  'ERROR' => 4,
  'FATAL' => 5,
);

function logging($level, $message) {
  global $log_file, $_log_file_fd, $_log_levels, $log_level, $argv, $auth_user;

  if (!array_key_exists($level, $_log_levels)) $level = 'INFO';
  $level_id = $_log_levels[$level];

  if (!array_key_exists($log_level, $_log_levels)) $log_level = 'INFO';
  $log_level_id = $_log_levels[$log_level];

  if ($level_id < $log_level_id) return true;
  if(is_null($_log_file_fd)) {
    $_log_file_fd = fopen($log_file, 'a');
  }

  // If more than 2 arguments passed, format message using sprintf
  if (func_num_args() > 2) {
    $message = call_user_func_array(
      'sprintf',
      array_merge(array($message), array_slice(func_get_args(), 2))
    );
  }

  if (php_sapi_name() == "cli") {
    $msg = implode(' - ', array(
      date('Y/m/d H:i:s'),
      basename($argv[0]),
      $level,
      $message
    ))."\n";
  }
  else {
    $msg = array(
      date('Y/m/d H:i:s'),
      $_SERVER['REQUEST_URI'],
      $_SERVER['REMOTE_ADDR'],
    );
    if (isset($auth_user))
      $msg[] = ($auth_user?$auth_user:'anonymous');
    $msg[] = $level;
    $msg[] = $message;
    $msg = implode(' - ', $msg)."\n";
  }

  fwrite($_log_file_fd , $msg);

  if ($level == 'FATAL')
    if (function_exists('fatal_error'))
      fatal_error($message);
    else
      die("\n$message\n\n");
  elseif (php_sapi_name() == "cli")
    echo $msg;

  return true;
}

function change_log_file($file) {
  global $log_file, $_log_file_fd;
  if ($file == $log_file) return True;
  if ($_log_file_fd) {
    fclose($_log_file_fd);
    $_log_file_fd = false;
  }
  $log_file = $file;
  return True;
}

// Handle exception logging
function get_debug_backtrace_context($ignore_last=0) {
  $traces = debug_backtrace();

  // Also ignore this function it self
  $ignore_last++;

  if (!is_array($traces) || count($traces) <= $ignore_last)
    return "";

  $msg = array();
  for ($i=$ignore_last; $i < count($traces); $i++) {
    $trace = array("#$i");
    if (isset($traces[$i]['file']))
      $trace[] = $traces[$i]['file'].(isset($traces[$i]['line'])?":".$traces[$i]['line']:"");
    if (isset($traces[$i]['class']) && isset($traces[$i]['function']))
      $trace[] = implode(" ", array(
        $traces[$i]['class'],
        $traces[$i]['type'],
        $traces[$i]['function']. "()"));
    elseif (isset($traces[$i]['function']))
      $trace[] = $traces[$i]['function']. "()";
    $msg[] = implode(" - ", $trace);
  }

  return implode("\n", $msg);
}

function log_exception($exception, $prefix=null) {
  // If more than 2 arguments passed, format prefix message using sprintf
  if ($prefix && func_num_args() > 2) {
    $prefix = call_user_func_array(
      'sprintf',
      array_merge(array($prefix), array_slice(func_get_args(), 2))
    );
  }
  logging(
    "ERROR", "%s:\n%s\n## %s:%d : %s",
    ($prefix?$prefix:"An exception occured"),
    get_debug_backtrace_context(1),
    $exception->getFile(), $exception->getLine(),
    $exception->getMessage());
}
set_exception_handler('log_exception');

// Handle PHP error logging
function log_php_eror($errno, $errstr, $errfile, $errline) {
  logging("ERROR", "A PHP error occured : [%d] %s\nFile : %s (line : %d)",
    $errno, $errstr, $errfile, $errline);
  return False;
}
if ($log_level == 'DEBUG')
  set_error_handler('log_php_eror', E_ALL & ~E_STRICT);
else
  set_error_handler('log_php_eror', E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED);
