Add .gitignore and .htaccess for security
🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
14
.gitignore
vendored
Normal file
14
.gitignore
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
# IDE
|
||||
.idea/
|
||||
.vscode/
|
||||
*.sublime-*
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Node (if any build tools)
|
||||
node_modules/
|
||||
|
||||
# Composer dev dependencies (if installed locally)
|
||||
vendor/
|
||||
10
.htaccess
Normal file
10
.htaccess
Normal file
@@ -0,0 +1,10 @@
|
||||
# Apache 2.2
|
||||
<IfModule !mod_authz_core.c>
|
||||
Order deny,allow
|
||||
Deny from all
|
||||
</IfModule>
|
||||
|
||||
# Apache 2.4
|
||||
<IfModule mod_authz_core.c>
|
||||
Require all denied
|
||||
</IfModule>
|
||||
20
composer.json
Normal file
20
composer.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "myprestarocks/prestashop-compatibility",
|
||||
"description": "Shared compatibility traits for PrestaShop modules - AJAX responses, templates, and core fixes",
|
||||
"type": "library",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "mypresta.rocks",
|
||||
"email": "info@mypresta.rocks"
|
||||
}
|
||||
],
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"MyPrestaRocks\\Compatibility\\": "src/"
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
}
|
||||
}
|
||||
147
src/AjaxResponseTrait.php
Normal file
147
src/AjaxResponseTrait.php
Normal file
@@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Ajax Response Trait - Standardized JSON responses for PrestaShop modules
|
||||
*
|
||||
* Provides consistent AJAX response methods with proper headers and hook integration.
|
||||
*
|
||||
* Usage:
|
||||
* use MyPrestaRocks\Compatibility\AjaxResponseTrait;
|
||||
*
|
||||
* class YourModule extends Module {
|
||||
* use AjaxResponseTrait;
|
||||
* }
|
||||
*
|
||||
* @author mypresta.rocks <info@mypresta.rocks>
|
||||
* @copyright Copyright (c) mypresta.rocks
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace MyPrestaRocks\Compatibility;
|
||||
|
||||
if (!defined('_PS_VERSION_')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
trait AjaxResponseTrait
|
||||
{
|
||||
/**
|
||||
* Send a JSON response and exit
|
||||
*
|
||||
* Primary method for AJAX responses. Parameters ordered by frequency of use:
|
||||
* - success: always needed
|
||||
* - data: usually needed
|
||||
* - message: optional, only when you need to show user feedback
|
||||
*
|
||||
* @param bool $success Whether the operation succeeded
|
||||
* @param array $data Additional data to return
|
||||
* @param string|null $message Optional message for user feedback
|
||||
* @return void (exits)
|
||||
*/
|
||||
public function ajaxResponse($success, $data = [], $message = null)
|
||||
{
|
||||
$response = [
|
||||
'success' => $success,
|
||||
];
|
||||
|
||||
if ($message !== null) {
|
||||
$response['message'] = $message;
|
||||
$response['confirmations'] = $message;
|
||||
}
|
||||
|
||||
if (!empty($data)) {
|
||||
$response = array_merge($response, $data);
|
||||
}
|
||||
|
||||
$this->outputJsonResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a success response
|
||||
*
|
||||
* @param array $data Data to return
|
||||
* @param string|null $message Optional success message
|
||||
* @return void (exits)
|
||||
*/
|
||||
public function ajaxSuccess($data = [], $message = null)
|
||||
{
|
||||
$this->ajaxResponse(true, $data, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an error response
|
||||
*
|
||||
* @param string|null $message Error message
|
||||
* @param array $data Additional error data
|
||||
* @return void (exits)
|
||||
*/
|
||||
public function ajaxError($message = null, $data = [])
|
||||
{
|
||||
$this->ajaxResponse(false, $data, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render standardized JSON response for AJAX calls
|
||||
*
|
||||
* @deprecated Use ajaxResponse(), ajaxSuccess(), or ajaxError() instead
|
||||
* Kept for backward compatibility with existing code
|
||||
*
|
||||
* @param string $message Message to display
|
||||
* @param bool $success Whether the operation succeeded
|
||||
* @param array $data Additional data to return
|
||||
* @return void (exits)
|
||||
*/
|
||||
public function renderMessage($message, $success = true, $data = [])
|
||||
{
|
||||
$this->ajaxResponse($success, $data, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Output JSON response with proper headers and hooks
|
||||
*
|
||||
* @param array $response Response array to encode
|
||||
* @return void (exits)
|
||||
*/
|
||||
protected function outputJsonResponse($response)
|
||||
{
|
||||
$jsonResponse = json_encode($response);
|
||||
|
||||
$controller = get_class($this);
|
||||
$method = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)[2]['function'] ?? 'unknown';
|
||||
|
||||
\Hook::exec('actionAjaxDieBefore', ['controller' => $controller, 'method' => $method, 'value' => $jsonResponse]);
|
||||
\Hook::exec('actionBeforeAjaxDie' . $controller . $method, ['value' => $jsonResponse]);
|
||||
\Hook::exec('actionAjaxDie' . $controller . $method . 'Before', ['value' => $jsonResponse]);
|
||||
|
||||
header('Content-Type: application/json');
|
||||
header('Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0');
|
||||
|
||||
echo $jsonResponse;
|
||||
exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send HTTP error response code
|
||||
*
|
||||
* @param int $code HTTP status code (default 404)
|
||||
* @return void
|
||||
*/
|
||||
public function respondInvalid($code = 404)
|
||||
{
|
||||
http_response_code($code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send HTTP error response with JSON body
|
||||
*
|
||||
* @param int $code HTTP status code
|
||||
* @param string|null $message Error message
|
||||
* @param array $data Additional data
|
||||
* @return void (exits)
|
||||
*/
|
||||
public function respondWithError($code, $message = null, $data = [])
|
||||
{
|
||||
http_response_code($code);
|
||||
$this->ajaxError($message, $data);
|
||||
}
|
||||
}
|
||||
31
src/ModuleCompatibilityTrait.php
Normal file
31
src/ModuleCompatibilityTrait.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Module Compatibility Trait - All-in-one compatibility trait for regular modules
|
||||
*
|
||||
* Combines AjaxResponseTrait and ModuleTemplateTrait for convenient single-use import.
|
||||
* For payment modules, use PaymentModuleCompatibilityTrait instead.
|
||||
*
|
||||
* Usage:
|
||||
* use MyPrestaRocks\Compatibility\ModuleCompatibilityTrait;
|
||||
*
|
||||
* class YourModule extends Module {
|
||||
* use ModuleCompatibilityTrait;
|
||||
* }
|
||||
*
|
||||
* @author mypresta.rocks <info@mypresta.rocks>
|
||||
* @copyright Copyright (c) mypresta.rocks
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace MyPrestaRocks\Compatibility;
|
||||
|
||||
if (!defined('_PS_VERSION_')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
trait ModuleCompatibilityTrait
|
||||
{
|
||||
use AjaxResponseTrait;
|
||||
use ModuleTemplateTrait;
|
||||
}
|
||||
110
src/ModuleTemplateTrait.php
Normal file
110
src/ModuleTemplateTrait.php
Normal file
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Module Template Trait - Simplified Smarty template rendering for PrestaShop modules
|
||||
*
|
||||
* Provides convenient methods for rendering Smarty templates within modules.
|
||||
*
|
||||
* Usage:
|
||||
* use MyPrestaRocks\Compatibility\ModuleTemplateTrait;
|
||||
*
|
||||
* class YourModule extends Module {
|
||||
* use ModuleTemplateTrait;
|
||||
* }
|
||||
*
|
||||
* @author mypresta.rocks <info@mypresta.rocks>
|
||||
* @copyright Copyright (c) mypresta.rocks
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace MyPrestaRocks\Compatibility;
|
||||
|
||||
if (!defined('_PS_VERSION_')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
trait ModuleTemplateTrait
|
||||
{
|
||||
/**
|
||||
* Render a Smarty template from the module's views/templates directory
|
||||
*
|
||||
* @param string $template Template filename without extension
|
||||
* @param string $subfolder Subfolder within views/templates/ (with trailing slash if not empty)
|
||||
* @param array $variables Variables to assign to template
|
||||
* @return string Rendered template HTML
|
||||
*/
|
||||
public function renderTemplate($template, $subfolder = '', $variables = [])
|
||||
{
|
||||
$templatePath = $this->getLocalPath() . 'views/templates/' . $subfolder . $template . '.tpl';
|
||||
|
||||
if (!file_exists($templatePath)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!empty($variables)) {
|
||||
$this->context->smarty->assign([$this->name => $variables]);
|
||||
}
|
||||
|
||||
return $this->context->smarty->fetch($templatePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a front office template
|
||||
*
|
||||
* @param string $template Template filename without extension
|
||||
* @param array $variables Variables to assign to template
|
||||
* @return string Rendered template HTML
|
||||
*/
|
||||
public function renderFrontTemplate($template, $variables = [])
|
||||
{
|
||||
return $this->renderTemplate($template, 'front/', $variables);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render an admin template
|
||||
*
|
||||
* @param string $template Template filename without extension
|
||||
* @param array $variables Variables to assign to template
|
||||
* @return string Rendered template HTML
|
||||
*/
|
||||
public function renderAdminTemplate($template, $variables = [])
|
||||
{
|
||||
return $this->renderTemplate($template, 'admin/', $variables);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a hook template (from hooks/ subfolder)
|
||||
*
|
||||
* @param string $template Template filename without extension
|
||||
* @param array $variables Variables to assign to template
|
||||
* @return string Rendered template HTML
|
||||
*/
|
||||
public function renderHookTemplate($template, $variables = [])
|
||||
{
|
||||
return $this->renderTemplate($template, 'hook/', $variables);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign variables to Smarty and return for chaining
|
||||
*
|
||||
* @param array $variables Variables to assign
|
||||
* @return $this
|
||||
*/
|
||||
public function assignTemplateVars($variables)
|
||||
{
|
||||
$this->context->smarty->assign($variables);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign module-namespaced variables to prevent conflicts
|
||||
*
|
||||
* @param array $variables Variables to assign under module namespace
|
||||
* @return $this
|
||||
*/
|
||||
public function assignModuleVars($variables)
|
||||
{
|
||||
$this->context->smarty->assign([$this->name => $variables]);
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
31
src/PaymentModuleCompatibilityTrait.php
Normal file
31
src/PaymentModuleCompatibilityTrait.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Payment Module Compatibility Trait - All-in-one compatibility trait for payment modules
|
||||
*
|
||||
* Combines all compatibility traits including the PaymentModule carrier fix.
|
||||
*
|
||||
* Usage:
|
||||
* use MyPrestaRocks\Compatibility\PaymentModuleCompatibilityTrait;
|
||||
*
|
||||
* class YourPaymentModule extends PaymentModule {
|
||||
* use PaymentModuleCompatibilityTrait;
|
||||
* }
|
||||
*
|
||||
* @author mypresta.rocks <info@mypresta.rocks>
|
||||
* @copyright Copyright (c) mypresta.rocks
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace MyPrestaRocks\Compatibility;
|
||||
|
||||
if (!defined('_PS_VERSION_')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
trait PaymentModuleCompatibilityTrait
|
||||
{
|
||||
use AjaxResponseTrait;
|
||||
use ModuleTemplateTrait;
|
||||
use PaymentModuleTrait;
|
||||
}
|
||||
75
src/PaymentModuleTrait.php
Normal file
75
src/PaymentModuleTrait.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Payment Module Trait - Fixes for PrestaShop PaymentModule bugs
|
||||
*
|
||||
* Fixes PrestaShop core bugs related to PaymentModule installation.
|
||||
*
|
||||
* Issue: When carriers are edited, PrestaShop creates new carrier records
|
||||
* with the same id_reference. The core addCheckboxCarrierRestrictionsForModule()
|
||||
* method doesn't deduplicate, causing duplicate key errors on payment module install.
|
||||
*
|
||||
* Usage:
|
||||
* use MyPrestaRocks\Compatibility\PaymentModuleTrait;
|
||||
*
|
||||
* class YourPaymentModule extends PaymentModule {
|
||||
* use PaymentModuleTrait;
|
||||
* }
|
||||
*
|
||||
* @author mypresta.rocks <info@mypresta.rocks>
|
||||
* @copyright Copyright (c) mypresta.rocks
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace MyPrestaRocks\Compatibility;
|
||||
|
||||
if (!defined('_PS_VERSION_')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
trait PaymentModuleTrait
|
||||
{
|
||||
/**
|
||||
* Override core method to fix duplicate carrier reference bug
|
||||
*
|
||||
* This method overrides the buggy core PaymentModule method that fails
|
||||
* when carriers with duplicate id_reference exist (which happens when
|
||||
* carriers are edited in the back office).
|
||||
*
|
||||
* @param array $shops Shop IDs to process (uses all shops if empty)
|
||||
* @return bool
|
||||
*/
|
||||
public function addCheckboxCarrierRestrictionsForModule(array $shops = [])
|
||||
{
|
||||
if (!$shops) {
|
||||
$shops = \Shop::getShops(true, null, true);
|
||||
}
|
||||
|
||||
$carriers = \Carrier::getCarriers(
|
||||
(int) \Context::getContext()->language->id,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
\Carrier::ALL_CARRIERS
|
||||
);
|
||||
|
||||
// Deduplicate by id_reference to avoid duplicate key errors
|
||||
$uniqueReferences = [];
|
||||
foreach ($carriers as $carrier) {
|
||||
$uniqueReferences[$carrier['id_reference']] = true;
|
||||
}
|
||||
|
||||
foreach ($shops as $idShop) {
|
||||
foreach (array_keys($uniqueReferences) as $idReference) {
|
||||
\Db::getInstance()->execute(
|
||||
'INSERT IGNORE INTO `' . _DB_PREFIX_ . 'module_carrier`
|
||||
(`id_module`, `id_shop`, `id_reference`)
|
||||
VALUES (' . (int) $this->id . ', ' . (int) $idShop . ', ' . (int) $idReference . ')'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user