Version 5.0.0 beta 1
This commit is contained in:
1 parent
25ddeb65d6
commit
15c7beabc5
6736 files changed
+627902
-497943
No files matched your search
+177
-31
@@ -11,48 +11,61 @@
|
||||
namespace IPS\Output;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use IPS\Dispatcher;
|
||||
use IPS\Http\Url;
|
||||
use IPS\Output;
|
||||
use IPS\Theme;
|
||||
use function defined;
|
||||
use function strstr;
|
||||
use function uniqid;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output Class
|
||||
*/
|
||||
class _System extends \IPS\Output
|
||||
class System extends Output
|
||||
{
|
||||
/**
|
||||
* Display Error Screen
|
||||
*
|
||||
* @param string $message language key for error message
|
||||
* @param mixed $code Error code
|
||||
* @param int $httpStatusCode HTTP Status Code
|
||||
* @param string $adminMessage language key for error message to show to admins
|
||||
* @param array $httpHeaders Additional HTTP Headers
|
||||
* @param string $extra Additional information (such as API error)
|
||||
* @return void
|
||||
* @param string $message language key for error message
|
||||
* @param mixed $code Error code
|
||||
* @param int $httpStatusCode HTTP Status Code
|
||||
* @param string|null $adminMessage language key for error message to show to admins
|
||||
* @param array $httpHeaders Additional HTTP Headers
|
||||
* @param string|null $extra Additional information (such as API error)
|
||||
* @param int|string|null $faultyAppOrHookId
|
||||
* @return void
|
||||
*/
|
||||
public function error( $message, $code, $httpStatusCode=500, $adminMessage=NULL, $httpHeaders=array(), $extra=NULL )
|
||||
public function error( string $message, mixed $code, int $httpStatusCode=500, string $adminMessage=NULL, array $httpHeaders=array(), string $extra=NULL, int|string $faultyAppOrHookId=NULL ) : void
|
||||
{
|
||||
/* Send output */
|
||||
$this->sendOutput( \IPS\Theme\System\Theme::i()->getTemplate('global', 'core', 'global')->error( $message ), $httpStatusCode, 'text/html', $httpHeaders );
|
||||
$this->sendOutput( Theme::i()->getTemplate('global', 'core', 'global')->error( $message ), $httpStatusCode, 'text/html', $httpHeaders );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send output
|
||||
*
|
||||
* @param string $output Content to output
|
||||
* @param int $httpStatusCode HTTP Status Code
|
||||
* @param string $contentType HTTP Content-type
|
||||
* @param array $httpHeaders Additional HTTP Headers
|
||||
* @param bool $cache Allows the page to be cached - set to FALSE when sending a cached page
|
||||
* @return void
|
||||
* @param string $output Content to output
|
||||
* @param int $httpStatusCode HTTP Status Code
|
||||
* @param string $contentType HTTP Content-type
|
||||
* @param array $httpHeaders Additional HTTP Headers
|
||||
* @param bool $cacheThisPage
|
||||
* @param bool $pageIsCached
|
||||
* @param bool $parseFileObjects
|
||||
* @param bool $parseEmoji
|
||||
* @return void
|
||||
*/
|
||||
public function sendOutput( $output='', $httpStatusCode=200, $contentType='text/html', $httpHeaders=array(), $cache=TRUE )
|
||||
public function sendOutput(string $output='', int $httpStatusCode=200, string $contentType='text/html', array $httpHeaders=array(), bool $cacheThisPage=TRUE, bool $pageIsCached=FALSE, bool $parseFileObjects=TRUE, bool $parseEmoji=TRUE ) : void
|
||||
{
|
||||
/* Set HTTP status */
|
||||
if( isset( $_SERVER['SERVER_PROTOCOL'] ) and \strstr( $_SERVER['SERVER_PROTOCOL'], '/1.0' ) !== false )
|
||||
if( isset( $_SERVER['SERVER_PROTOCOL'] ) and strstr( $_SERVER['SERVER_PROTOCOL'], '/1.0' ) !== false )
|
||||
{
|
||||
header( "HTTP/1.0 {$httpStatusCode} " . static::$httpStatuses[ $httpStatusCode ] );
|
||||
}
|
||||
@@ -64,7 +77,7 @@ class _System extends \IPS\Output
|
||||
/* Buffer output */
|
||||
if ( $output )
|
||||
{
|
||||
if( isset( $_SERVER['HTTP_ACCEPT_ENCODING'] ) and \strstr( $_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip' ) !== false and (bool) ini_get('zlib.output_compression') === false )
|
||||
if( isset( $_SERVER['HTTP_ACCEPT_ENCODING'] ) and strstr( $_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip' ) !== false and (bool) ini_get('zlib.output_compression') === false )
|
||||
{
|
||||
ob_start('ob_gzhandler');
|
||||
}
|
||||
@@ -73,7 +86,7 @@ class _System extends \IPS\Output
|
||||
ob_start();
|
||||
}
|
||||
|
||||
print \IPS\Theme\System\Theme::i()->getTemplate('global', 'core', 'global')->globalTemplate( $output, static::i()->title, array( 'app' => \IPS\Dispatcher::i()->application->directory, 'module' => \IPS\Dispatcher::i()->module->key, 'controller' => \IPS\Dispatcher::i()->controller ) );
|
||||
print Theme::i()->getTemplate('global', 'core', 'global')->globalTemplate( $output, static::i()->title, array( 'app' => Dispatcher::i()->application->directory, 'module' => Dispatcher::i()->module->key, 'controller' => Dispatcher::i()->controller ) );
|
||||
}
|
||||
|
||||
/* Send headers */
|
||||
@@ -91,23 +104,156 @@ class _System extends \IPS\Output
|
||||
flush();
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Redirect
|
||||
*
|
||||
* @param \IPS\Http\Url $url URL to redirect to
|
||||
* @param string $message Optional message to display
|
||||
* @param int $httpStatusCode HTTP Status Code
|
||||
* @param bool $forceScreen If TRUE, an intermeditate screen will be shown
|
||||
* @return void
|
||||
* @param Url|string $url URL to redirect to
|
||||
* @param string|null $message Optional message to display
|
||||
* @param int $httpStatusCode HTTP Status Code
|
||||
* @param bool $forceScreen If TRUE, an intermeditate screen will be shown
|
||||
* @return void
|
||||
*/
|
||||
public function redirect( $url, $message='', $httpStatusCode=303, $forceScreen=FALSE )
|
||||
public function redirect( Url|string $url, ?string $message='', int $httpStatusCode=301, bool $forceScreen=FALSE ) : void
|
||||
{
|
||||
if ( $forceScreen === TRUE )
|
||||
{
|
||||
$this->sendOutput( \IPS\Theme\System\Theme::i()->getTemplate( 'global', 'core', 'global' )->redirect( $url, $message ), $httpStatusCode );
|
||||
$this->sendOutput( Theme::i()->getTemplate( 'global', 'core', 'global' )->redirect( $url, $message ), $httpStatusCode );
|
||||
}
|
||||
|
||||
$this->sendOutput( '', $httpStatusCode, '', array( "Location: {$url}" ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a HTML file of the MySQL debug backtrace
|
||||
*
|
||||
* @param array $debug
|
||||
* @return string
|
||||
*/
|
||||
public static function generateDbLogHtml( array $debug ): string
|
||||
{
|
||||
$queryCount = count( $debug ) - 1; # The first query is the connection
|
||||
$html = <<<HTML
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>MySQL Debug Log</title>
|
||||
<style>
|
||||
* {
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
table {
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
th, td {
|
||||
padding: 10px;
|
||||
border: 1px solid #ddd;
|
||||
text-align: left;
|
||||
}
|
||||
td.query {
|
||||
font-family: monospace;
|
||||
word-wrap: break-word;
|
||||
font-size: 14px;
|
||||
text-wrap: wrap;
|
||||
}
|
||||
|
||||
td.details {
|
||||
width: 10%;
|
||||
}
|
||||
|
||||
tr.collapsible-content {
|
||||
display: none;
|
||||
background-color: #e5e5e5;
|
||||
}
|
||||
|
||||
.toggle-button {
|
||||
cursor: pointer;
|
||||
color: blue;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
function toggleRow(id) {
|
||||
const rows = document.querySelectorAll(`[data-row="content-\${id}"]`);
|
||||
// Loop through each row and toggle visibility
|
||||
rows.forEach(row => {
|
||||
if (row.style.display === "none") {
|
||||
document.querySelector(`td[data-query="\${id}"]`).style.backgroundColor = "lightblue";
|
||||
// If the row is hidden, show it
|
||||
row.style.display = "table-row";
|
||||
} else {
|
||||
// If the row is visible, hide it
|
||||
document.querySelector(`td[data-query="\${id}"]`).style.backgroundColor = "transparent";
|
||||
row.style.display = "none";
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>{$queryCount} Queries</h1>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Function</th>
|
||||
<th>File</th>
|
||||
<th>Line</th>
|
||||
<th style="width:150px">Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
HTML;
|
||||
|
||||
foreach ($debug as $index => $data)
|
||||
{
|
||||
$unique = md5( $data['query'] . uniqid() );
|
||||
$html .= <<<HTML
|
||||
<tr>
|
||||
<td data-query="{$unique}" colspan="3" class="query">{$data['query']}</td>
|
||||
<td class="details"><span class="toggle-button" onclick="toggleRow('{$unique}')">Expand/Collapse</span></td>
|
||||
</tr>
|
||||
HTML;
|
||||
|
||||
foreach( $data['backtrace'] as $id => $trace )
|
||||
{
|
||||
$trace['file'] = isset( $trace['file'] ) ? str_replace( \IPS\ROOT_PATH, '', $trace['file'] ) : '';
|
||||
$trace['line'] = $trace['line'] ?? '';
|
||||
$html .= <<<HTML
|
||||
<tr data-row="content-{$unique}" style="display: none" class="collapsible-content">
|
||||
<td>
|
||||
{$trace['function']}
|
||||
</td>
|
||||
<td>
|
||||
{$trace['file']}
|
||||
</td>
|
||||
<td>
|
||||
{$trace['line']}
|
||||
</td>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
HTML;
|
||||
}
|
||||
}
|
||||
|
||||
$html .= <<<HTML
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
HTML;
|
||||
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user