Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions app/Views/Components/navbar.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{# SproutPHP Component: navbar.twig #}
<div class="component navbar">
<nav>
<ul>
<li>
<strong class="">
<img src="{{ assets('img/logo.png') }}" width="22px"/>
SproutPHP
</strong>
</li>
</ul>
<ul>
<li><a href="#">About</a></li>
<li><a href="#">Docs</a></li>
<li><a href="#"><img src="https://img.shields.io/github/stars/sproutphp/framework?style=social&link=https%3A%2F%2Fgithub.com%2FSproutPHP%2Fframework"/></a></li>
</ul>
</nav>
</div>
32 changes: 17 additions & 15 deletions app/Views/layouts/base.twig
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,22 @@
<script src="{{ assets('js/sprout.min.js') }}"></script>
</head>
<body>
<main class="container"> {% block content %}{% endblock %}
</main>
<main class="container">
{% include 'components/navbar.twig' %}
{% block content %}{% endblock %}
</main>

{% if env('APP_ENV') == 'local' %}
<div style="position:fixed;top:10px;right:10px;background:#eef;border:1px solid #ccd;padding:0.5rem;font-family:monospace;font-size:0.8rem;border-radius:4px;">
⚡ HTMX Active
<br/>
📃
<a href="https://htmx.org/docs/" target="_blank">HTMX Docs ↗</a>
</div>
{% endif %}
{% if env('APP_ENV') == 'local' %}
<div style="z-index:9999;position:fixed;bottom:75px;right:10px;background:#eef;border:1px solid #ccd;padding:0.5rem;font-family:monospace;font-size:0.8rem;border-radius:4px;">
⚡ HTMX Active
<br/>
📃
<a href="https://htmx.org/docs/" target="_blank">HTMX Docs ↗</a>
</div>
{% endif %}

{% if app_debug %}
{{ debugbar|raw }}
{% endif %}
</body>
</html>
{% if app_debug %}
{{ debugbar|raw }}
{% endif %}
</body>
</html>
4 changes: 2 additions & 2 deletions core/Console/Commands/MakeComponent.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class MakeComponent
public static function handle($name)
{
$name = strtolower(trim($name));
$dir = __DIR__ . '/../../../app/Views/Components/';
$dir = __DIR__ . '/../../../app/Views/components/';
$file = "{$dir}/{$name}.twig";

if (!is_dir($dir)) {
Expand All @@ -32,6 +32,6 @@ public static function handle($name)
TWIG;

file_put_contents($file, $template);
echo "✅ Component created: app/Components/{$name}.twig\n";
echo "✅ Component created: app/Views/components/{$name}.twig\n";
}
}
8 changes: 4 additions & 4 deletions core/Console/Commands/MakeView.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public static function handle($name, $flags = [])
{% extends 'layouts/base.twig' %}

{% block content %}
<h2>HTMX Demo Page</h2>
<h2>HTMX Demo Page for $name</h2>

<button hx-get="/" hx-target="#demo" hx-swap="innerHTML">
Load Partial via HTMX
Expand All @@ -38,11 +38,11 @@ public static function handle($name, $flags = [])
TWIG
: <<<TWIG
{% extends "layouts/base.twig" %}
{% block title %}{{ title }}{% endblock %}
{% block title %}$name{% endblock %}

{% block content %}
<h1>{{ title }}</h1>
<p>This is the <strong>{{ title }}</strong> page.</p>
<h1>$name</h1>
<p>This is the <strong>$name</strong> page.</p>
<blockquote style="margin-top:2rem; font-style:italic; color:#888;">
{$quote}
</blockquote>
Expand Down
5 changes: 5 additions & 0 deletions core/Database/DB.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ public static function getQueries()
return self::$queries;
}

public static function resetQueryLog()
{
self::$queries = [];
}

public static function logQuery($sql, $params, $start, $end)
{
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5);
Expand Down
31 changes: 30 additions & 1 deletion core/Support/Debugbar.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,41 @@

class Debugbar
{
/**
* Check if current request is AJAX or HTMX
*/
public static function isAjaxRequest(): bool
{
return (
isset($_SERVER['HTTP_X_REQUESTED_WITH']) &&
strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest'
) || (
isset($_SERVER['HTTP_HX_REQUEST']) &&
$_SERVER['HTTP_HX_REQUEST'] === 'true'
);
}

/**
* Reset debugbar for new request
*/
public static function resetForRequest()
{
// Reset query log for this specific request
DB::resetQueryLog();

// Set new start time for this request
if (!defined('REQUEST_START')) {
define('REQUEST_START', microtime(true));
}
}

public static function render()
{
if (env('APP_DEBUG') !== 'true') return;

$endTime = microtime(true);
$executionTime = round(($endTime - SPROUT_START) * 1000, 2); // ms
$startTime = defined('REQUEST_START') ? REQUEST_START : SPROUT_START;
$executionTime = round(($endTime - $startTime) * 1000, 2); // ms
$memoryUsage = round(memory_get_usage(true) / 1024 / 1024, 2); // MB
$queries = DB::getQueries();
$totalQueryTime = round(array_sum(array_column($queries, 'duration')), 2);
Expand Down
16 changes: 16 additions & 0 deletions core/Support/helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,19 @@ function getLatestRelease()
return 'unknown';
}
}

/**
* Check if current request is AJAX or HTMX
*/
if (!function_exists('is_ajax_request')) {
function is_ajax_request(): bool
{
return (
isset($_SERVER['HTTP_X_REQUESTED_WITH']) &&
strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest'
) || (
isset($_SERVER['HTTP_HX_REQUEST']) &&
$_SERVER['HTTP_HX_REQUEST'] === 'true'
);
}
}
53 changes: 41 additions & 12 deletions core/View/View.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,28 +19,57 @@ public static function init()
'debug' => true,
]);

// Register global functions like assets() debug() if it exists as Twig doesn’t have direct access to PHP global functions by default
if (function_exists('assets')) {
self::$twig->addFunction(new TwigFunction('assets', 'assets'));
}
// Register global helper functions like assets() debug() if it exists as Twig doesn't have direct access to PHP global functions by default
self::registerAllHelpers();
}

/**
* Get All PHP Helpers that are currently defined
*/
private static function discoverHelpers() {
$functions = get_defined_functions();
return $functions['user'];
}

/**
* Register all helpers found in $helperFunctions
*/
private static function registerAllHelpers(){
$helperFunctions = self::discoverHelpers();

if (function_exists('debug') || function_exists('dd') || function_exists('env')) {
self::$twig->addFunction(new \Twig\TwigFunction('debug', 'debug'));
self::$twig->addFunction(new \Twig\TwigFunction('dd', 'dd'));
self::$twig->addFunction(new \Twig\TwigFunction('env', fn($key) => env($key)));
foreach($helperFunctions as $functionName) {
if(function_exists($functionName)) {
self::$twig->addFunction(new TwigFunction($functionName, $functionName));
}
}
}

public static function render($template, $data = [])
{
if (!self::$twig) {
self::init();
}

// Check if this is an AJAX/HTMX request
if (Debugbar::isAjaxRequest() && env('APP_DEBUG') === 'true') {
// Reset debugbar for this request
Debugbar::resetForRequest();

// Render the template first
$content = self::$twig->render($template . '.twig', $data);

// Append debugbar to the response
$debugbar = Debugbar::render();

echo $content . $debugbar;
return;
}

// Regular request handling
if (env('APP_DEBUG') === 'true') {
$data['debugbar'] = Debugbar::render();
$data['app_debug'] = true;
}

if (!self::$twig) {
self::init();
}

echo self::$twig->render($template . '.twig', $data);
}
Expand Down
Binary file added public/assets/img/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion routes/web.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,4 @@
});
Route::get('/test500', function () {
throw new Exception("Manual 500 test triggered.");
});
});