* @link https://TheTempusProject.com/Core * @license https://opensource.org/licenses/MIT [MIT LICENSE] */ namespace TheTempusProject\Canary\Bin; use TheTempusProject\Canary\Classes\TempusDebugger; use TheTempusProject\Canary\Classes\Logger; use Exception; class Canary { private static $lastCall = ''; private static $group = 0; private static $tempusDebugger; private static $tempusLogger; private static $debugLog = ''; /** * @param {object} [$exception] */ public static function handle_exception( $exception ) { echo '
'; echo '

Exception Handler:

'; echo 'Class: ' . get_class( $exception ) . '
'; // echo "Message: { $exception->message }" . '
'; // echo "File: { $exception->getFile() }" . '
'; // echo "Line: { $exception->getLine() }" . '
'; echo 'Exception:
' . print_r( $exception, true ) . '


'; echo '
'; } /** * @param {object} [$exception] */ public static function handle_error( $error_code, $error_description, $file = null, $error_line_number = null ) { $displayErrors = ini_get( 'display_errors' ); $displayErrors = strtolower( $displayErrors ); echo '
'; if ( 0 === $error_code || 0 === error_reporting() || $displayErrors === 'on' ) { echo '

fail

'; return false; } // wtf? remove this or find an alternative // if ( isset( $GLOBALS['error_fatal'] ) ) { // if ( $GLOBALS['error_fatal'] && $error_code ) { // die('fatal'); // } // } $errstr = htmlspecialchars( $error_description ); switch( $error_code ) { case E_ERROR: $errorType = 'E_ERROR'; $errorReadable = 'Fatal Error'; // throw new ErrorException($error_description, 0, $error_code, $file, $err_line); // $log = LOG_ERR; break; case E_WARNING: $errorType = 'E_WARNING'; $errorReadable = 'Warning'; // throw new WarningException($error_description, 0, $error_code, $file, $err_line); // $log = LOG_WARNING; break; case E_PARSE: $errorType = 'E_PARSE'; $errorReadable = 'Parse Error'; // throw new ParseException($error_description, 0, $error_code, $file, $err_line); // $log = LOG_ERR; break; case E_NOTICE: $errorType = 'E_NOTICE'; $errorReadable = 'Notice'; // throw new NoticeException($error_description, 0, $error_code, $file, $err_line); // $log = LOG_NOTICE; break; case E_CORE_ERROR: $errorType = 'E_CORE_ERROR'; $errorReadable = 'Core Error'; // throw new CoreErrorException($error_description, 0, $error_code, $file, $err_line); // $log = LOG_ERR; break; case E_CORE_WARNING: $errorType = 'E_CORE_WARNING'; $errorReadable = 'Core Warning'; // throw new CoreWarningException($error_description, 0, $error_code, $file, $err_line); // $log = LOG_WARNING; break; case E_COMPILE_ERROR: $errorType = 'E_COMPILE_ERROR'; $errorReadable = 'Compile Error'; // throw new CompileErrorException($error_description, 0, $error_code, $file, $err_line); // $log = LOG_ERR; break; case E_COMPILE_WARNING: $errorType = 'E_COMPILE_WARNING'; $errorReadable = 'Compile Warning'; // throw new CoreWarningException($error_description, 0, $error_code, $file, $err_line); // $log = LOG_WARNING; break; case E_USER_ERROR: $errorType = 'E_USER_ERROR'; $errorReadable = 'User Error'; // handling an sql error if ( $error_description == '(SQL)' ) { echo 'SQL Query: ' . SQLQUERY . '
'; echo 'SQL Line: ' . SQLERRORLINE . '
'; echo 'SQL File: ' . SQLERRORFILE . '
'; } // throw new UserErrorException($error_description, 0, $error_code, $file, $err_line); // $log = LOG_ERR; break; case E_USER_NOTICE: $errorType = 'E_USER_NOTICE'; $errorReadable = 'User Notice'; // $log = LOG_NOTICE; break; case E_STRICT: $errorType = 'E_STRICT'; $errorReadable = 'Strict'; // $log = LOG_NOTICE; break; case E_RECOVERABLE_ERROR: $errorType = 'E_RECOVERABLE_ERROR'; $errorReadable = 'Recoverable Error'; // $log = LOG_WARNING; break; case E_USER_WARNING: $errorType = 'E_USER_WARNING'; $errorReadable = 'User Warning'; // $log = LOG_WARNING; break; case E_DEPRECATED: $errorType = 'E_DEPRECATED'; $errorReadable = 'Deprecated'; // $log = LOG_NOTICE; // no break case E_USER_DEPRECATED: $errorType = 'E_USER_DEPRECATED'; $errorReadable = 'User Deprecated'; // $log = LOG_NOTICE; break; default: $errorType = 'UNKNOWN'; $errorReadable = 'Unknown Error'; break; } echo '

' . $errorReadable . ':

'; echo "Error Description: {$error_description}" . '
'; echo "File: {$file}" . '
'; echo "Line Number: {$error_line_number}" . '
'; echo "Error Case: {$errorType}" . '
'; echo "Error Code: {$error_code}" . '
'; echo "Error Description (fancy): {$errstr}" . '
'; echo 'PHP Version: ' . PHP_VERSION . '
'; echo 'PHP OS: ' . PHP_OS . '
'; // $data = [ // // 'level' => $log, // 'code' => $error_line_number, // // 'error' => $error, // 'description' => $error_description, // 'file' => $file, // 'line' => $error_line_number, // 'path' => $file, // 'message' => $error . ' (' . $error_line_number . '): ' . $error_description . ' in [' . $file . ', line ' . $error_line_number . ']' // ]; echo ''; } /** * Acts as a constructor. */ private static function startDebug() { if ( self::status( 'file' ) ) { self::$tempusLogger = new Logger; } if ( self::status( 'console' ) ) { ob_start(); self::$tempusDebugger = TempusDebugger::getInstance( true ); self::$tempusDebugger->setOption( 'includeLineNumbers', CANARY_SHOW_LINES ); // self::$tempusDebugger->setHash( CANARY_SECURE_HASH ); } } /** * Returns the current Debug Status. * * @return bool */ public static function status( $flag = null ) { switch ( $flag ) { case 'console': return CANARY_DEBUG_TO_CONSOLE; case 'file': return CANARY_DEBUG_TO_FILE; case 'trace': return CANARY_TRACE_ENABLED; case 'render': return RENDERING_ENABLED; case 'debug': default: return CANARY_ENABLED; } } /** * This is the interface that writes to our log file/console depending on input type. * * @param string $type - Debugging type. * @param string $data - Debugging data. * * @todo make a case statement */ private static function put( $type, $data = null, $params = null ) { if ( ! CANARY_ENABLED ) { return; } if ( strlen( self::$debugLog ) > 50000 ) { self::$tempusDebugger->log( 'Error log too large, possible loop.' ); return; } if ( is_object( $data ) ) { $data = 'cannot save objects'; } if ( !is_string( $data ) ) { $data = var_export( $data, true ); } if ( !empty( self::$lastCall ) ) { $highlight = ''; $trimmed_class = trim(self::$lastCall, '\\'); $trimmed_class = trim($trimmed_class, '"'); $trimmed_class = trim($trimmed_class, "'"); $exploded_classname = explode( '\\\\', $trimmed_class ); $exploded_classname[1] = ''.$exploded_classname[1].''; $bolded_line = implode( ' \\ ', $exploded_classname ); $shortened_name = str_ireplace( 'TheTempusProject', 'TTP', $bolded_line ); if ( in_array( $type, ['error','info','warn'])) { $highlight = 'debug-log-' . $type; } $full_line = "<{$shortened_name}>:{$data}
"; self::$debugLog .= $full_line; self::$lastCall = ''; } if ( self::status( 'file' ) ) { if ( ! self::$tempusLogger ) { self::startDebug(); } switch ( $type ) { case 'error': case 'warn': case 'info': case 'log': case 'debug': self::$tempusLogger->addLog( $type, $data ); break; default: break; } } if ( ! self::status( 'console' ) ) { return; } if ( ! self::$tempusDebugger ) { self::startDebug(); } switch ( $type ) { case 'variable': self::$tempusDebugger->info( $data, $params ); break; case 'groupEnd': self::$tempusDebugger->groupEnd(); break; case 'trace': self::$tempusDebugger->trace( $data ); break; case 'group': if ( $params ) { self::$tempusDebugger->group( $data, $params ); } else { self::$tempusDebugger->group( $data ); } break; case 'info': self::$tempusDebugger->$type( 'color: #1452ff', '%c' . $data ); break; default: self::$tempusDebugger->$type( $data ); break; } } /** * Ends a group. */ public static function gend() { if ( self::$group > 0 ) { self::$group--; self::put( 'groupEnd' ); } } /** * Creates a group divider into the console output. * * @param string $data name of the group * @param wild $collapsed if anything is present the group will be collapsed by default */ public static function closeAllGroups() { list($childClass, $caller) = debug_backtrace(false, 2); self::$lastCall = var_export($caller['class'],true); if ( self::$group > 0 ) { while ( self::$group > 0 ) { self::$group--; self::put( 'groupEnd' ); } // self::put('log', 'closed all groups.'); } } /** * Creates a group divider into the console output. * * @param string $data name of the group * @param wild $collapsed if anything is present the group will be collapsed by default */ public static function group( $data, $collapsed = null ) { list($childClass, $caller) = debug_backtrace(false, 2); self::$lastCall = var_export($caller['class'],true); if ( !empty( $collapsed ) ) { $params = ['Collapsed' => true]; self::put( 'group', $data, $params ); } else { self::put( 'group', $data ); } self::$group++; } /** * Allows you to print the contents of any variable into the console. * * @param WILD $var - The variable you wish to read. * @param string $data - Optional name for the variable output. */ public static function v( $var, $data = null ) { list($childClass, $caller) = debug_backtrace(false, 2); self::$lastCall = var_export($caller['class'],true); if ( !isset( $data ) ) { $data = 'Default Variable label'; } self::put( 'variable', $var, $data ); } /** * Socket function for a basic debugging log. * * @param string $data - The debug data. */ public static function log( $data, $params = null ) { list($childClass, $caller) = debug_backtrace(false, 2); self::$lastCall = var_export($caller['class'],true); self::put( 'log', $data ); if ( !empty( $params ) ) { self::gend(); } } /** * Provides a stack trace from the current calling spot. * * @param string $data the name of the trace */ public static function trace( $data = 'Default Trace' ) { list( $childClass, $caller ) = debug_backtrace(false, 2); self::$lastCall = var_export( $caller['class'], true ); self::group( 'Debug Trace', 1 ); self::put( 'trace' ); self::gend(); } /** * Socket function for debugging info. * * @param string $data - The debug data. */ public static function info( $data, $params = null ) { list($childClass, $caller) = debug_backtrace(false, 2); self::$lastCall = var_export($caller['class'],true); self::put( 'info', $data ); if ( !empty( $params ) ) { self::gend(); } } /** * Socket function for a debugging warning. * * @param string $data - The debug data. */ public static function warn( $data, $params = null ) { list($childClass, $caller) = debug_backtrace(false, 2); self::$lastCall = var_export($caller['class'],true); self::put( 'warn', $data ); if ( !empty( $params ) ) { self::gend(); } } public static function debug( $data, $params = null ) { list($childClass, $caller) = debug_backtrace(false, 2); self::$lastCall = var_export($caller['class'],true); self::put( 'debug', $data ); if ( !empty( $params ) ) { self::gend(); } } /** * Socket function for a debugging error. * * @param string $data - The debug data. */ public static function error( $data, $params = null ) { list($childClass, $caller) = debug_backtrace(false, 2); self::$lastCall = var_export($caller['class'],true); self::put( 'error', $data ); if ( CANARY_TRACE_ENABLED ) { self::trace(); } if ( !empty( $params ) ) { self::gend(); } } /** * This returns the contents of the debug log. */ public static function dump() { return self::$debugLog; } }