From 8b4c50c2bb6eb8e58f67dc4ea6c444cd57c91860 Mon Sep 17 00:00:00 2001 From: "Joseph.Rawlings" Date: Wed, 3 Dec 2025 15:35:08 -0500 Subject: [PATCH] feat: implement comprehensive deployment script for Laravel with progress indicators and rollback functionality, enhancing deployment reliability and user experience --- extensions/Others/CreditsPlus/CreditsPlus.php | 141 +++++++++++------- .../components/navigation/index.blade.php | 4 +- .../navigation/sidebar-links.blade.php | 78 ++-------- .../resources/views/navbar-credits.blade.php | 38 +++++ gitsync.sh | 118 ++++++++++++++- 5 files changed, 261 insertions(+), 118 deletions(-) create mode 100644 extensions/Others/CreditsPlus/resources/views/navbar-credits.blade.php diff --git a/extensions/Others/CreditsPlus/CreditsPlus.php b/extensions/Others/CreditsPlus/CreditsPlus.php index e2bb10c88..8c92812db 100644 --- a/extensions/Others/CreditsPlus/CreditsPlus.php +++ b/extensions/Others/CreditsPlus/CreditsPlus.php @@ -13,6 +13,9 @@ namespace Paymenter\Extensions\Others\CreditsPlus; use App\Classes\Extension\Extension; +use Illuminate\Support\Facades\View; +use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Storage; class CreditsPlus extends Extension { @@ -28,7 +31,7 @@ class CreditsPlus extends Extension public function getVersion(): string { - return '2.0.0'; + return '2.1.0'; } public function getAuthor(): string @@ -52,50 +55,79 @@ class CreditsPlus extends Extension private function registerCreditsNavigation(): void { try { - if (function_exists('app') && app()->bound('view')) { - // Register the view namespace for custom components - app('view')->addNamespace('creditsplus', __DIR__ . '/resources/views'); - - app('view')->composer('components.navigation.index', function ($view) { - try { - if (!function_exists('auth') || !auth()->check() || !auth()->user()) { - return; - } - - $user = auth()->user(); - $creditsDisplay = $this->calculateUserCreditsDisplay($user); - $creditsUrl = function_exists('route') ? route('account.credits') : '/account/credits'; - - $customPath = __DIR__ . '/resources/views/components/navigation/index.blade.php'; - if (file_exists($customPath)) { - $view->setPath($customPath); - } - - $view->with([ - 'userCreditsDisplay' => $creditsDisplay, - 'creditsUrl' => $creditsUrl, - ]); - } catch (\Exception $e) { + // Register the view namespace + View::addNamespace('creditsplus', __DIR__ . '/resources/views'); + + // Store reference to this instance for use in closure + $extension = $this; + $extensionPath = __DIR__; + + // Use view composer to add credits data to navigation + View::composer('components.navigation.index', function ($view) use ($extension, $extensionPath) { + try { + if (!Auth::check()) { + return; } - }); - } + + // Only show credits if the feature is enabled + if (!config('settings.credits_enabled', false)) { + return; + } + + $user = Auth::user(); + $creditsDisplay = $extension->calculateUserCreditsDisplay($user); + + // Determine logo path using storage_url helper if available + $logoHtml = ''; + if (config('settings.logo')) { + $logoUrl = function_exists('storage_url') + ? storage_url(config('settings.logo')) + : Storage::url(config('settings.logo')); + $logoHtml = '' . e(config('app.name')) . ''; + } + + // Inject credits data, logo HTML, and credits URL into the view + $creditsUrlPath = '#'; + try { + if (function_exists('route')) { + $creditsUrlPath = route('account.credits'); + } + } catch (\Exception $e) { + $creditsUrlPath = '/account/credits'; + } + + $view->with([ + 'userCreditsDisplay' => $creditsDisplay, + 'creditsLogoHtml' => $logoHtml, + 'creditsUrl' => $creditsUrlPath, + ]); + + // Replace the view path with our custom navigation + $customPath = $extensionPath . '/resources/views/components/navigation/index.blade.php'; + if (file_exists($customPath)) { + $view->setPath($customPath); + } + } catch (\Exception $e) { + // Silently fail + } + }); } catch (\Exception $e) { + // Silently fail } } - private function calculateUserCreditsDisplay($user): string + public function calculateUserCreditsDisplay($user): string { try { + // Check if the credits relationship exists + if (!method_exists($user, 'credits')) { + return $this->getDefaultCurrencyDisplay(); + } + $credits = $user->credits()->with('currency')->get(); if ($credits->isEmpty()) { - $currencyCode = session('currency', config('settings.default_currency', 'USD')); - $currency = \App\Models\Currency::where('code', $currencyCode)->first(); - if ($currency) { - return $currency->prefix . '0.00' . $currency->suffix; - } else { - return '0.00 ' . $currencyCode; - } + return $this->getDefaultCurrencyDisplay(); } $creditsByCurrency = $credits->groupBy('currency_code'); @@ -111,33 +143,42 @@ class CreditsPlus extends Extension if ($maxAmount === null || $totalAmount > $maxAmount) { $maxAmount = $totalAmount; $maxCurrencyCode = $currencyCode; - $maxCurrency = $userCredits->first()->currency; + $maxCurrency = $userCredits->first()->currency ?? null; } } if ($maxAmount === null) { - $currencyCode = session('currency', config('settings.default_currency', 'USD')); - $currency = \App\Models\Currency::where('code', $currencyCode)->first(); - if ($currency) { - return $currency->prefix . '0.00' . $currency->suffix; - } else { - return '0.00 ' . $currencyCode; - } + return $this->getDefaultCurrencyDisplay(); } - if ($maxCurrency) { + if ($maxCurrency && isset($maxCurrency->prefix) && isset($maxCurrency->suffix)) { return $maxCurrency->prefix . number_format($maxAmount, 2) . $maxCurrency->suffix; } else { - return number_format($maxAmount, 2) . ' ' . $maxCurrencyCode; + return number_format($maxAmount, 2) . ' ' . ($maxCurrencyCode ?? ''); } } catch (\Exception $e) { + return $this->getDefaultCurrencyDisplay(); + } + } + + /** + * Get default currency display (0.00 with currency symbol) + */ + private function getDefaultCurrencyDisplay(): string + { + try { $currencyCode = session('currency', config('settings.default_currency', 'USD')); - $currency = class_exists('\App\Models\Currency') ? \App\Models\Currency::where('code', $currencyCode)->first() : null; - if ($currency) { - return $currency->prefix . '0.00' . $currency->suffix; - } else { - return '0.00 ' . $currencyCode; + + if (class_exists('\App\Models\Currency')) { + $currency = \App\Models\Currency::where('code', $currencyCode)->first(); + if ($currency && isset($currency->prefix) && isset($currency->suffix)) { + return $currency->prefix . '0.00' . $currency->suffix; + } } + + return '0.00 ' . $currencyCode; + } catch (\Exception $e) { + return '0.00 USD'; } } } diff --git a/extensions/Others/CreditsPlus/resources/views/components/navigation/index.blade.php b/extensions/Others/CreditsPlus/resources/views/components/navigation/index.blade.php index ba4aff93b..2a3157817 100644 --- a/extensions/Others/CreditsPlus/resources/views/components/navigation/index.blade.php +++ b/extensions/Others/CreditsPlus/resources/views/components/navigation/index.blade.php @@ -43,9 +43,7 @@ Unauthorized copying, modification, or distribution is prohibited.
- @if (config('settings.logo')) - {{ config('app.name') }} - @endif + {!! $creditsLogoHtml ?? '' !!} {{ config('app.name') }} diff --git a/extensions/Others/CreditsPlus/resources/views/components/navigation/sidebar-links.blade.php b/extensions/Others/CreditsPlus/resources/views/components/navigation/sidebar-links.blade.php index 61aff5a16..8ed0aad39 100644 --- a/extensions/Others/CreditsPlus/resources/views/components/navigation/sidebar-links.blade.php +++ b/extensions/Others/CreditsPlus/resources/views/components/navigation/sidebar-links.blade.php @@ -11,16 +11,16 @@ Unauthorized copying, modification, or distribution is prohibited.
@foreach (\App\Classes\Navigation::getLinks() as $nav) @if (!empty($nav['children'])) -
@@ -47,10 +47,10 @@ Unauthorized copying, modification, or distribution is prohibited. + {{ ($nav['active'] ?? false) ? 'bg-primary/10 text-primary font-semibold' : 'hover:bg-primary/5 text-color-base' }}"> @isset($nav['icon']) + class="size-5 {{ ($nav['active'] ?? false) ? 'text-primary' : 'text-color-muted' }}" /> @endisset {{ $nav['name'] }} @@ -70,16 +70,16 @@ Unauthorized copying, modification, or distribution is prohibited.
@foreach (\App\Classes\Navigation::getDashboardLinks() as $nav) @if (!empty($nav['children'])) -
@@ -108,10 +108,10 @@ Unauthorized copying, modification, or distribution is prohibited. + {{ ($nav['active'] ?? false) ? 'bg-primary/10 text-primary font-semibold' : 'hover:bg-primary/5 text-color-base' }}"> @isset($nav['icon']) + class="size-5 {{ ($nav['active'] ?? false) ? 'text-primary' : 'text-color-muted' }}" /> @endisset {{ $nav['name'] }} @@ -152,57 +152,7 @@ Unauthorized copying, modification, or distribution is prohibited. @if(auth()->check())
{{-- Credits Display for Mobile --}} - @php - try { - $user = auth()->user(); - $credits = $user->credits()->with('currency')->get(); - - if ($credits->isEmpty()) { - $currencyCode = session('currency', config('settings.default_currency', 'USD')); - $currency = \App\Models\Currency::where('code', $currencyCode)->first(); - if ($currency) { - $creditsDisplay = $currency->prefix . '0.00' . $currency->suffix; - } else { - $creditsDisplay = '0.00 ' . $currencyCode; - } - } else { - $creditsByCurrency = $credits->groupBy('currency_code'); - $maxAmount = null; - $maxCurrencyCode = null; - $maxCurrency = null; - - foreach ($creditsByCurrency as $currencyCode => $userCredits) { - $totalAmount = $userCredits->sum('amount'); - if ($totalAmount <= 0) continue; - if ($maxAmount === null || $totalAmount > $maxAmount) { - $maxAmount = $totalAmount; - $maxCurrencyCode = $currencyCode; - $maxCurrency = $userCredits->first()->currency; - } - } - - if ($maxAmount === null) { - $currencyCode = session('currency', config('settings.default_currency', 'USD')); - $currency = \App\Models\Currency::where('code', $currencyCode)->first(); - if ($currency) { - $creditsDisplay = $currency->prefix . '0.00' . $currency->suffix; - } else { - $creditsDisplay = '0.00 ' . $currencyCode; - } - } else { - if ($maxCurrency) { - $creditsDisplay = $maxCurrency->prefix . number_format($maxAmount, 2) . $maxCurrency->suffix; - } else { - $creditsDisplay = number_format($maxAmount, 2) . ' ' . $maxCurrencyCode; - } - } - } - } catch (\Exception $e) { - $creditsDisplay = '0.00'; - } - @endphp - - @if(isset($creditsDisplay)) + @if(isset($userCreditsDisplay))
@@ -211,7 +161,7 @@ Unauthorized copying, modification, or distribution is prohibited.
Account Credits - {{ $creditsDisplay }} + {{ $userCreditsDisplay }}
diff --git a/extensions/Others/CreditsPlus/resources/views/navbar-credits.blade.php b/extensions/Others/CreditsPlus/resources/views/navbar-credits.blade.php new file mode 100644 index 000000000..37c016bd9 --- /dev/null +++ b/extensions/Others/CreditsPlus/resources/views/navbar-credits.blade.php @@ -0,0 +1,38 @@ +{{-- +Credits Plus Navigation Component + +Created by: Exp (Discord: exp_yt) +Company: ExpHost - https://www.exphost.net/ + +This code is the intellectual property of Exp and ExpHost. +Unauthorized copying, modification, or distribution is prohibited. +--}} + + + + Credits: {{ $creditsDisplay }} + + diff --git a/gitsync.sh b/gitsync.sh index ccb7c248a..c01a5ea8e 100755 --- a/gitsync.sh +++ b/gitsync.sh @@ -1 +1,117 @@ -git pull && systemctl restart php8.3-fpm.service && ./cache.sh +#!/usr/bin/env bash +set -euo pipefail + +BAR_WIDTH=50 +SLEEP_INTERVAL=0.05 +CLEAR_LINE="\033[K" +LOG_FILE="/var/log/laravel_deploy.log" + +GREEN="\033[32m" +RESET="\033[0m" + +STEPS=( + "Pull latest code" + "Maintenance mode" + "Restart PHP-FPM" + "Clear caches" + "Optimize app" + "Set permissions" + "Ensure queue running" + "Reset OPcache" + "Bring app online" + "Check php-fpm" + "Check paymenter" +) + +CMDS=( + "git pull --rebase --autostash --quiet" + "php artisan down --render='errors::503' --retry=60 --quiet || true" + "systemctl restart php8.3-fpm.service" + "php artisan optimize:clear --quiet" + "php artisan optimize --quiet" + "find storage bootstrap/cache -not -perm 775 -type d -exec chmod 775 {} + -o -not -perm 664 -type f -exec chmod 664 {} +; chown -R www-data:www-data storage bootstrap/cache" + "if ! pgrep -f 'artisan queue:work' >/dev/null; then nohup php artisan queue:work --daemon --quiet >> /dev/null 2>&1 & fi" + "php -r 'if(function_exists(\"opcache_reset\")) opcache_reset();' 2>/dev/null || true" + "php artisan up --quiet" + "systemctl is-active --quiet php8.3-fpm || systemctl restart php8.3-fpm" + "systemctl is-active --quiet paymenter.service || systemctl restart paymenter.service" +) + +rollback(){ + echo -e "\n\033[31m✘ Deployment failed. Rolling back...\033[0m" + git reset --hard HEAD@{1} >> "$LOG_FILE" 2>&1 + php artisan up || true + exit 1 +} +trap rollback ERR + +draw_bar() { + local percent=$1 + local width=$2 + local text="$3" + + # Strip color codes for length calculation + local clean_text=$(echo -ne "$text" | sed 's/\x1b\[[0-9;]*m//g') + + [ ${#clean_text} -gt $width ] && clean_text="${clean_text:0:$width}" + + local filled=$(( percent * width / 100 )) + [ $filled -gt $width ] && filled=$width + + local text_start=$(( (width - ${#clean_text}) / 2 )) + local text_end=$(( text_start + ${#clean_text} )) + + local bar="" + for ((i=0;i= text_start && i < text_end )); then + bar+="${clean_text:i-text_start:1}" + else + if (( i < filled )); then + bar+="#" + else + bar+="-" + fi + fi + done + + printf "[%s] %3d%%" "$bar" "$percent" +} + +run_deployment() { + local total_steps=${#STEPS[@]} + + for i in "${!STEPS[@]}"; do + step_name="${STEPS[$i]}" + cmd="${CMDS[$i]}" + step_percent_start=$(( i * 100 / total_steps )) + step_percent_end=$(( (i+1) * 100 / total_steps )) + + bash -c "$cmd" > >(tee -a "$LOG_FILE") 2> >(tee -a "$LOG_FILE" >&2) & + pid=$! + + percent=$step_percent_start + while kill -0 "$pid" 2>/dev/null; do + [ "$percent" -lt "$step_percent_end" ] && percent=$((percent+1)) + echo -ne "\r$(draw_bar $percent $BAR_WIDTH "$step_name")$CLEAR_LINE" + sleep "$SLEEP_INTERVAL" + done + wait "$pid" + + # Fill bar to end of step + echo -ne "\r$(draw_bar $step_percent_end $BAR_WIDTH "$step_name")$CLEAR_LINE" + done + + # Final green completion bar + final_text="Deployment Complete" + # Construct bar normally + bar=$(draw_bar 100 $BAR_WIDTH "$final_text") + # Replace the visible text in the middle with green text + clean_text_len=${#final_text} + start=$(( (BAR_WIDTH - clean_text_len) / 2 + 1 )) # +1 for the [ + end=$(( start + clean_text_len - 1 )) + colored_bar="${bar:0:start-1}${GREEN}${final_text}${RESET}${bar:end}" + echo -e "\r$colored_bar$CLEAR_LINE" +# echo "Log: $LOG_FILE" +} + +run_deployment