HEX
Server: nginx/1.24.0
System: Linux rtfmfm 6.8.0-71-generic #71-Ubuntu SMP PREEMPT_DYNAMIC Tue Jul 22 16:52:38 UTC 2025 x86_64
User: neo (1001)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: /var/www/kpopbg.com/deploy_currency_conversion.php
<?php
/**
 * PrestaShop BGN to EUR Email Currency Conversion - PHP Deployment Script
 *
 * This PHP script applies all necessary changes to add EUR price equivalents
 * to email templates in a PrestaShop installation.
 *
 * Usage: php deploy_currency_conversion.php [prestashop_root_path]
 * Example: php deploy_currency_conversion.php /var/www/html/prestashop
 *
 * Author: GitHub Copilot
 * Date: July 26, 2025
 * Exchange Rate: 1 BGN = 1.95583 EUR (1 BGN = 0.5110789 EUR)
 */

// Set error reporting
error_reporting(E_ALL);
ini_set('display_errors', 1);

class CurrencyConversionDeployer
{
    private $psRoot;
    private $backupSuffix;

    public function __construct($psRoot = null)
    {
        $this->backupSuffix = '.backup.' . date('Ymd_His');

        if ($psRoot) {
            $this->psRoot = rtrim($psRoot, '/');
        } else {
            $this->psRoot = $this->getPrestaShopRoot();
        }

        $this->validatePrestaShopDirectory();
    }

    private function getPrestaShopRoot()
    {
        echo "Enter PrestaShop root directory path: ";
        $handle = fopen("php://stdin", "r");
        $path = trim(fgets($handle));
        fclose($handle);

        return rtrim($path, '/');
    }

    private function validatePrestaShopDirectory()
    {
        if (!is_dir($this->psRoot)) {
            throw new Exception("Directory does not exist: {$this->psRoot}");
        }

        if (!file_exists($this->psRoot . '/config/config.inc.php') || !is_dir($this->psRoot . '/classes')) {
            throw new Exception("Invalid PrestaShop directory: {$this->psRoot}");
        }

        $this->log("āœ“ Valid PrestaShop directory: {$this->psRoot}");
    }

    private function log($message)
    {
        echo $message . "\n";
    }

    private function backupFile($file)
    {
        if (file_exists($file)) {
            $backupFile = $file . $this->backupSuffix;
            copy($file, $backupFile);
            $this->log("āœ“ Backed up: " . basename($file));
            return true;
        }
        return false;
    }

    private function createCurrencyConverterHelper()
    {
        $this->log("\nšŸ“ Creating CurrencyConverterHelper class...");

        $helperContent = '<?php
/**
 * CurrencyConverter Helper
 *
 * This class provides functionality to convert BGN prices to EUR
 * for email templates display purposes.
 */

class CurrencyConverterHelper
{
    // Exchange rate: 1 BGN = 0.5110789 EUR (1 / 1.95583)
    const BGN_TO_EUR_RATE = 0.5110789;

    /**
     * Convert BGN amount to EUR
     *
     * @param float $bgn_amount Amount in BGN
     * @return float Amount in EUR
     */
    public static function convertBgnToEur($bgn_amount)
    {
        return (float) $bgn_amount * self::BGN_TO_EUR_RATE;
    }

    /**
     * Format BGN amount with EUR equivalent
     *
     * @param float $bgn_amount Amount in BGN
     * @param string $bgn_symbol BGN currency symbol (default: \'лв.\')
     * @param string $eur_symbol EUR currency symbol (default: \'€\')
     * @return string Formatted string with both currencies
     */
    public static function formatBgnWithEur($bgn_amount, $bgn_symbol = \'лв.\', $eur_symbol = \'€\')
    {
        $eur_amount = self::convertBgnToEur($bgn_amount);

        // Format the amounts with proper decimals
        $bgn_formatted = number_format($bgn_amount, 2, \'.\', \'\');
        $eur_formatted = number_format($eur_amount, 2, \'.\', \'\');

        return $bgn_formatted . \' \' . $bgn_symbol . \' (\' . $eur_formatted . \' \' . $eur_symbol . \')\';
    }

    /**
     * Format price using PrestaShop\'s locale formatter and add EUR equivalent
     *
     * @param float $bgn_amount Amount in BGN
     * @param Context $context PrestaShop context
     * @return string Formatted string with both currencies
     */
    public static function formatPriceWithEur($bgn_amount, $context = null)
    {
        if (!$context) {
            $context = Context::getContext();
        }

        $eur_amount = self::convertBgnToEur($bgn_amount);

        // Format BGN using PrestaShop\'s formatter
        $bgn_formatted = Tools::getContextLocale($context)->formatPrice($bgn_amount, $context->currency->iso_code);

        // Format EUR amount
        $eur_formatted = number_format($eur_amount, 2, \'.\', \'\') . \' €\';

        return $bgn_formatted . \' (\' . $eur_formatted . \')\';
    }
}';

        $helperFile = $this->psRoot . '/classes/CurrencyConverterHelper.php';
        file_put_contents($helperFile, $helperContent);

        $this->log("āœ“ Created: classes/CurrencyConverterHelper.php");
    }

    private function updatePaymentModule()
    {
        $this->log("\nšŸ”§ Updating PaymentModule...");

        $paymentModule = $this->psRoot . '/classes/PaymentModule.php';
        if (file_exists($paymentModule)) {
            $this->backupFile($paymentModule);

            $content = file_get_contents($paymentModule);

            // Update all the formatPrice calls to use CurrencyConverterHelper
            $replacements = [
                'Tools::getContextLocale($this->context)->formatPrice($order->total_paid, $this->context->currency->iso_code)' =>
                'CurrencyConverterHelper::formatPriceWithEur($order->total_paid, $this->context)',

                'Tools::getContextLocale($this->context)->formatPrice(Product::getTaxCalculationMethod() == PS_TAX_EXC ? $order->total_products : $order->total_products_wt, $this->context->currency->iso_code)' =>
                'CurrencyConverterHelper::formatPriceWithEur(Product::getTaxCalculationMethod() == PS_TAX_EXC ? $order->total_products : $order->total_products_wt, $this->context)',

                'Tools::getContextLocale($this->context)->formatPrice($order->total_discounts, $this->context->currency->iso_code)' =>
                'CurrencyConverterHelper::formatPriceWithEur($order->total_discounts, $this->context)',

                'Tools::getContextLocale($this->context)->formatPrice($order->total_shipping, $this->context->currency->iso_code)' =>
                'CurrencyConverterHelper::formatPriceWithEur($order->total_shipping, $this->context)',

                'Tools::getContextLocale($this->context)->formatPrice($order->total_shipping_tax_excl, $this->context->currency->iso_code)' =>
                'CurrencyConverterHelper::formatPriceWithEur($order->total_shipping_tax_excl, $this->context)',

                'Tools::getContextLocale($this->context)->formatPrice($order->total_shipping_tax_incl, $this->context->currency->iso_code)' =>
                'CurrencyConverterHelper::formatPriceWithEur($order->total_shipping_tax_incl, $this->context)',

                'Tools::getContextLocale($this->context)->formatPrice($order->total_wrapping, $this->context->currency->iso_code)' =>
                'CurrencyConverterHelper::formatPriceWithEur($order->total_wrapping, $this->context)',

                'Tools::getContextLocale($this->context)->formatPrice(($order->total_paid_tax_incl - $order->total_paid_tax_excl), $this->context->currency->iso_code)' =>
                'CurrencyConverterHelper::formatPriceWithEur(($order->total_paid_tax_incl - $order->total_paid_tax_excl), $this->context)'
            ];

            foreach ($replacements as $search => $replace) {
                $content = str_replace($search, $replace, $content);
            }

            file_put_contents($paymentModule, $content);
            $this->log("āœ“ Updated: classes/PaymentModule.php");
        } else {
            $this->log("⚠ PaymentModule not found, skipping...");
        }
    }

    private function updateEmailAlertsModule()
    {
        $this->log("\nšŸ“§ Updating ps_emailalerts module...");

        $emailAlerts = $this->psRoot . '/modules/ps_emailalerts/ps_emailalerts.php';
        if (file_exists($emailAlerts)) {
            $this->backupFile($emailAlerts);

            $content = file_get_contents($emailAlerts);

            // Update email alerts with EUR conversions
            $replacements = [
                "'{total_paid}' => \$contextLocale->formatPrice(\$order->total_paid, \$currency->iso_code)" =>
                "'{total_paid}' => class_exists('CurrencyConverterHelper') ? CurrencyConverterHelper::formatPriceWithEur(\$order->total_paid, Context::getContext()) : \$contextLocale->formatPrice(\$order->total_paid, \$currency->iso_code)",

                "'{total_products}' => \$contextLocale->formatPrice(\$total_products, \$currency->iso_code)" =>
                "'{total_products}' => class_exists('CurrencyConverterHelper') ? CurrencyConverterHelper::formatPriceWithEur(\$total_products, Context::getContext()) : \$contextLocale->formatPrice(\$total_products, \$currency->iso_code)",

                "'{total_discounts}' => \$contextLocale->formatPrice(\$order->total_discounts, \$currency->iso_code)" =>
                "'{total_discounts}' => class_exists('CurrencyConverterHelper') ? CurrencyConverterHelper::formatPriceWithEur(\$order->total_discounts, Context::getContext()) : \$contextLocale->formatPrice(\$order->total_discounts, \$currency->iso_code)",

                "'{total_shipping}' => \$contextLocale->formatPrice(\$order->total_shipping, \$currency->iso_code)" =>
                "'{total_shipping}' => class_exists('CurrencyConverterHelper') ? CurrencyConverterHelper::formatPriceWithEur(\$order->total_shipping, Context::getContext()) : \$contextLocale->formatPrice(\$order->total_shipping, \$currency->iso_code)",

                "'{total_shipping_tax_excl}' => \$contextLocale->formatPrice(\$order->total_shipping_tax_excl, \$currency->iso_code)" =>
                "'{total_shipping_tax_excl}' => class_exists('CurrencyConverterHelper') ? CurrencyConverterHelper::formatPriceWithEur(\$order->total_shipping_tax_excl, Context::getContext()) : \$contextLocale->formatPrice(\$order->total_shipping_tax_excl, \$currency->iso_code)"
            ];

            foreach ($replacements as $search => $replace) {
                $content = str_replace($search, $replace, $content);
            }

            file_put_contents($emailAlerts, $content);
            $this->log("āœ“ Updated: modules/ps_emailalerts/ps_emailalerts.php");
        } else {
            $this->log("⚠ ps_emailalerts module not found, skipping...");
        }
    }

    private function updateEmailPartialTemplates()
    {
        $this->log("\nšŸ“§ Updating email partial templates...");

        // Update product list template (HTML)
        $productListTpl = $this->psRoot . '/mails/_partials/order_conf_product_list.tpl';
        if (file_exists($productListTpl)) {
            $this->backupFile($productListTpl);

            $content = file_get_contents($productListTpl);

            // Add EUR conversion for unit prices and total prices
            $content = str_replace(
                '						{$product[\'unit_price\']}',
                '						{if class_exists(\'CurrencyConverterHelper\')}
							{assign var="bgn_price" value=$product[\'unit_price\']|regex_replace:\'/[^0-9.,]/\' :\'\'}
							{$product[\'unit_price\']} ({($bgn_price * 0.5110789)|string_format:"%.2f"} €)
						{else}
							{$product[\'unit_price\']}
						{/if}',
                $content
            );

            $content = str_replace(
                '						{$product[\'price\']}',
                '						{if class_exists(\'CurrencyConverterHelper\')}
							{assign var="bgn_price" value=$product[\'price\']|regex_replace:\'/[^0-9.,]/\' :\'\'}
							{$product[\'price\']} ({($bgn_price * 0.5110789)|string_format:"%.2f"} €)
						{else}
							{$product[\'price\']}
						{/if}',
                $content
            );

            file_put_contents($productListTpl, $content);
            $this->log("āœ“ Updated: mails/_partials/order_conf_product_list.tpl");
        }

        // Update product list template (Text)
        $productListTxt = $this->psRoot . '/mails/_partials/order_conf_product_list.txt';
        if (file_exists($productListTxt)) {
            $this->backupFile($productListTxt);

            $txtContent = '{foreach $list as $product}
						{$product[\'reference\']}

						{$product[\'name\']}

						{assign var="bgn_price" value=$product[\'price\']|regex_replace:\'/[^0-9.,]/\' :\'\'}
						{$product[\'price\']}{if $bgn_price > 0} ({($bgn_price * 0.5110789)|string_format:"%.2f"} €){/if}
						{capture "productPriceBlock"}{hook h=\'displayProductPriceBlock\' product=$product type="unit_price"}{/capture}{$smarty.capture.productPriceBlock|strip_tags|trim}

						{$product[\'quantity\']}

						{assign var="bgn_total_price" value=$product[\'price\']|regex_replace:\'/[^0-9.,]/\' :\'\'}
						{$product[\'price\']}{if $bgn_total_price > 0} ({($bgn_total_price * 0.5110789)|string_format:"%.2f"} €){/if}

	{foreach $product[\'customization\'] as $customization}
							{$customization[\'customization_text\']}

							{if count($product[\'customization\']) > 1}
								{$customization[\'customization_quantity\']}
							{/if}
	{/foreach}
{/foreach}';

            file_put_contents($productListTxt, $txtContent);
            $this->log("āœ“ Updated: mails/_partials/order_conf_product_list.txt");
        }

        // Update cart rules template (HTML)
        $cartRulesTpl = $this->psRoot . '/mails/_partials/order_conf_cart_rules.tpl';
        if (file_exists($cartRulesTpl)) {
            $this->backupFile($cartRulesTpl);

            $content = file_get_contents($cartRulesTpl);
            $content = str_replace(
                '							{$cart_rule[\'voucher_reduction\']}',
                '							{assign var="bgn_reduction" value=$cart_rule[\'voucher_reduction\']|regex_replace:\'/[^0-9.,]/\' :\'\'}
							{$cart_rule[\'voucher_reduction\']}{if $bgn_reduction > 0} ({($bgn_reduction * 0.5110789)|string_format:"%.2f"} €){/if}',
                $content
            );

            file_put_contents($cartRulesTpl, $content);
            $this->log("āœ“ Updated: mails/_partials/order_conf_cart_rules.tpl");
        }

        // Update cart rules template (Text)
        $cartRulesTxt = $this->psRoot . '/mails/_partials/order_conf_cart_rules.txt';
        if (file_exists($cartRulesTxt)) {
            $this->backupFile($cartRulesTxt);

            $txtContent = '{foreach $list as $cart_rule}
	{assign var="bgn_reduction" value=$cart_rule[\'voucher_reduction\']|regex_replace:\'/[^0-9.,]/\' :\'\'}
	{$cart_rule[\'voucher_name\']}  {$cart_rule[\'voucher_reduction\']}{if $bgn_reduction > 0} ({($bgn_reduction * 0.5110789)|string_format:"%.2f"} €){/if}
{/foreach}';

            file_put_contents($cartRulesTxt, $txtContent);
            $this->log("āœ“ Updated: mails/_partials/order_conf_cart_rules.txt");
        }
    }

    private function createTestScript()
    {
        $this->log("\n🧪 Creating test script...");

        $testContent = '<?php
/**
 * Simple Currency Converter Test
 * Tests the CurrencyConverterHelper class without requiring full PrestaShop initialization
 */

// Include the helper class directly
require_once(dirname(__FILE__) . \'/classes/CurrencyConverterHelper.php\');

echo "Testing CurrencyConverterHelper class...\\n\\n";

try {
    // Test basic conversion
    $testAmount = 195.58;
    $eurAmount = CurrencyConverterHelper::convertBgnToEur($testAmount);
    echo "āœ“ Basic conversion test:\\n";
    echo "  {$testAmount} BGN = {$eurAmount} EUR\\n\\n";

    // Test formatting
    $formatted = CurrencyConverterHelper::formatBgnWithEur($testAmount);
    echo "āœ“ Formatting test:\\n";
    echo "  Input: {$testAmount} BGN\\n";
    echo "  Output: {$formatted}\\n\\n";

    // Test various amounts
    $testAmounts = [100.00, 50.25, 1000.99, 0.01];
    echo "āœ“ Multiple amount tests:\\n";
    foreach ($testAmounts as $amount) {
        $eur = CurrencyConverterHelper::convertBgnToEur($amount);
        $formatted = CurrencyConverterHelper::formatBgnWithEur($amount);
        echo "  {$amount} BGN → {$formatted}\\n";
    }

    echo "\\nāœ“ All tests passed! The CurrencyConverterHelper is working correctly.\\n";
    echo "\\nExchange rate used: 1 BGN = " . CurrencyConverterHelper::BGN_TO_EUR_RATE . " EUR\\n";
    echo "(Based on: 1 BGN = 1 / 1.95583 EUR)\\n";

} catch (Exception $e) {
    echo "āœ— Error: " . $e->getMessage() . "\\n";
}';

        $testFile = $this->psRoot . '/test_currency_converter.php';
        file_put_contents($testFile, $testContent);

        $this->log("āœ“ Created: test_currency_converter.php");
    }

    private function runTest()
    {
        $this->log("\n🧪 Testing currency converter...");

        $testFile = $this->psRoot . '/test_currency_converter.php';
        $output = shell_exec("cd {$this->psRoot} && php test_currency_converter.php 2>&1");

        if (strpos($output, 'āœ“ All tests passed!') !== false) {
            $this->log("āœ… Currency converter test passed!");
        } else {
            $this->log("⚠ Currency converter test failed - output:");
            $this->log($output);
        }
    }

    private function clearCache()
    {
        $this->log("\n🧹 Attempting to clear PrestaShop cache...");

        $cacheDirs = [
            $this->psRoot . '/var/cache',
            $this->psRoot . '/cache'
        ];

        foreach ($cacheDirs as $cacheDir) {
            if (is_dir($cacheDir)) {
                $this->clearDirectory($cacheDir);
                $this->log("āœ“ Cleared: " . basename($cacheDir) . " directory");
            }
        }
    }

    private function clearDirectory($dir)
    {
        $files = array_diff(scandir($dir), array('.', '..'));
        foreach ($files as $file) {
            $path = $dir . '/' . $file;
            if (is_dir($path)) {
                $this->clearDirectory($path);
                rmdir($path);
            } else {
                unlink($path);
            }
        }
    }

    public function deploy()
    {
        echo "==========================================\n";
        echo "PrestaShop BGN to EUR Currency Converter\n";
        echo "Email Template Deployment Script (PHP)\n";
        echo "==========================================\n\n";

        echo "This script will:\n";
        echo "  1. Create backups of all modified files\n";
        echo "  2. Add CurrencyConverterHelper class\n";
        echo "  3. Update PaymentModule to include EUR prices\n";
        echo "  4. Update ps_emailalerts module\n";
        echo "  5. Update email partial templates\n";
        echo "  6. Test the implementation\n\n";

        echo "Continue? (y/N): ";
        $handle = fopen("php://stdin", "r");
        $confirm = trim(fgets($handle));
        fclose($handle);

        if (strtolower($confirm) !== 'y' && strtolower($confirm) !== 'yes') {
            $this->log("Deployment cancelled.");
            return;
        }

        try {
            $this->createCurrencyConverterHelper();
            $this->updatePaymentModule();
            $this->updateEmailAlertsModule();
            $this->updateEmailPartialTemplates();
            $this->createTestScript();
            $this->runTest();
            $this->clearCache();

            echo "\n==========================================\n";
            echo "āœ… DEPLOYMENT COMPLETED SUCCESSFULLY!\n";
            echo "==========================================\n\n";
            echo "Summary of changes:\n";
            echo "  āœ“ Created CurrencyConverterHelper class\n";
            echo "  āœ“ Updated PaymentModule for EUR conversions\n";
            echo "  āœ“ Updated ps_emailalerts module\n";
            echo "  āœ“ Updated email partial templates\n";
            echo "  āœ“ Created test script\n";
            echo "  āœ“ Cleared PrestaShop cache\n\n";
            echo "Exchange rate applied: 1 BGN = 1.95583 EUR\n\n";
            echo "All email templates will now show:\n";
            echo "  • Order totals: 195.58 лв. (99.96 €)\n";
            echo "  • Product prices: 25.00 лв. (12.78 €)\n";
            echo "  • Discounts: -5.00 лв. (-2.56 €)\n\n";
            echo "Test the implementation:\n";
            echo "  cd {$this->psRoot} && php test_currency_converter.php\n\n";
            echo "Backup files created with timestamp suffix{$this->backupSuffix}\n\n";
            $this->log("āœ… Deployment completed successfully!");

        } catch (Exception $e) {
            $this->log("āŒ Error during deployment: " . $e->getMessage());
            exit(1);
        }
    }
}

// Main execution
try {
    $psRoot = isset($argv[1]) ? $argv[1] : null;
    $deployer = new CurrencyConversionDeployer($psRoot);
    $deployer->deploy();
} catch (Exception $e) {
    echo "āŒ Fatal error: " . $e->getMessage() . "\n";
    exit(1);
}