Add simple_withdrawalbutton PrestaShop module
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
<?php
|
||||
|
||||
if (!defined('_PS_VERSION_')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
class AdminSimpleWithdrawalController extends ModuleAdminController
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->bootstrap = true;
|
||||
$this->table = 'simple_withdrawal_request';
|
||||
$this->identifier = 'id_withdrawal_request';
|
||||
$this->lang = false;
|
||||
$this->explicitSelect = true;
|
||||
$this->_select = 'a.*';
|
||||
$this->_defaultOrderBy = 'created_at';
|
||||
$this->_defaultOrderWay = 'DESC';
|
||||
$this->allow_export = true;
|
||||
$this->list_no_link = false;
|
||||
$this->actions = ['view'];
|
||||
|
||||
$this->fields_list = [
|
||||
'id_withdrawal_request' => [
|
||||
'title' => $this->l('ID'),
|
||||
'align' => 'center',
|
||||
'class' => 'fixed-width-xs',
|
||||
],
|
||||
'created_at' => [
|
||||
'title' => $this->l('Received'),
|
||||
'type' => 'datetime',
|
||||
'filter_key' => 'a!created_at',
|
||||
],
|
||||
'order_reference' => [
|
||||
'title' => $this->l('Order reference'),
|
||||
'filter_key' => 'a!order_reference',
|
||||
],
|
||||
'customer_name' => [
|
||||
'title' => $this->l('Name'),
|
||||
'filter_key' => 'a!customer_name',
|
||||
],
|
||||
'customer_email' => [
|
||||
'title' => $this->l('Email'),
|
||||
'filter_key' => 'a!customer_email',
|
||||
],
|
||||
'withdrawal_scope' => [
|
||||
'title' => $this->l('Scope'),
|
||||
'callback' => 'renderScopeLabel',
|
||||
'callback_object' => $this,
|
||||
'filter_key' => 'a!withdrawal_scope',
|
||||
],
|
||||
'status' => [
|
||||
'title' => $this->l('Status'),
|
||||
'callback' => 'renderStatusLabel',
|
||||
'callback_object' => $this,
|
||||
'filter_key' => 'a!status',
|
||||
],
|
||||
];
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function renderScopeLabel($value, $row)
|
||||
{
|
||||
if ($value === 'partial') {
|
||||
return '<span class="label label-info">' . $this->l('Partial') . '</span>';
|
||||
}
|
||||
|
||||
return '<span class="label label-default">' . $this->l('Full order') . '</span>';
|
||||
}
|
||||
|
||||
public function renderStatusLabel($value, $row)
|
||||
{
|
||||
$labels = [
|
||||
'new' => ['class' => 'label-warning', 'text' => $this->l('New')],
|
||||
'processing' => ['class' => 'label-info', 'text' => $this->l('Processing')],
|
||||
'closed' => ['class' => 'label-success', 'text' => $this->l('Closed')],
|
||||
];
|
||||
|
||||
$label = isset($labels[$value]) ? $labels[$value] : ['class' => 'label-default', 'text' => $value];
|
||||
return '<span class="label ' . $label['class'] . '">' . Tools::safeOutput($label['text']) . '</span>';
|
||||
}
|
||||
|
||||
public function postProcess()
|
||||
{
|
||||
if (Tools::isSubmit('submitSimpleWithdrawalStatus')) {
|
||||
$this->processStatusUpdate();
|
||||
return;
|
||||
}
|
||||
|
||||
parent::postProcess();
|
||||
}
|
||||
|
||||
private function processStatusUpdate()
|
||||
{
|
||||
$id = (int) Tools::getValue($this->identifier);
|
||||
$status = (string) Tools::getValue('status');
|
||||
$allowedStatuses = ['new', 'processing', 'closed'];
|
||||
|
||||
if ($id <= 0 || !in_array($status, $allowedStatuses, true)) {
|
||||
$this->errors[] = $this->l('Invalid status update.');
|
||||
return;
|
||||
}
|
||||
|
||||
$ok = Db::getInstance()->update(
|
||||
'simple_withdrawal_request',
|
||||
['status' => $status],
|
||||
'`id_withdrawal_request` = ' . (int) $id
|
||||
);
|
||||
|
||||
if ($ok) {
|
||||
Tools::redirectAdmin(self::$currentIndex . '&token=' . $this->token . '&conf=4&view' . $this->table . '=1&' . $this->identifier . '=' . (int) $id);
|
||||
}
|
||||
|
||||
$this->errors[] = $this->l('The status could not be updated.');
|
||||
}
|
||||
|
||||
public function renderView()
|
||||
{
|
||||
$id = (int) Tools::getValue($this->identifier);
|
||||
$row = Db::getInstance()->getRow(
|
||||
'SELECT * FROM `' . _DB_PREFIX_ . pSQL('simple_withdrawal_request') . '`
|
||||
WHERE `id_withdrawal_request` = ' . (int) $id
|
||||
);
|
||||
|
||||
if (!$row) {
|
||||
$this->errors[] = $this->l('Withdrawal request not found.');
|
||||
return parent::renderList();
|
||||
}
|
||||
|
||||
$orderLink = '';
|
||||
if (!empty($row['id_order'])) {
|
||||
$orderLink = $this->context->link->getAdminLink('AdminOrders', true, [], [
|
||||
'id_order' => (int) $row['id_order'],
|
||||
'vieworder' => 1,
|
||||
]);
|
||||
}
|
||||
|
||||
$this->context->smarty->assign([
|
||||
'request' => $row,
|
||||
'order_link' => $orderLink,
|
||||
'current_index' => self::$currentIndex,
|
||||
'token' => $this->token,
|
||||
'identifier' => $this->identifier,
|
||||
'back_link' => self::$currentIndex . '&token=' . $this->token,
|
||||
]);
|
||||
|
||||
return $this->module->display(
|
||||
_PS_MODULE_DIR_ . $this->module->name . '/' . $this->module->name . '.php',
|
||||
'views/templates/admin/view.tpl'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
/** Silence is golden. */
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
/** Silence is golden. */
|
||||
@@ -0,0 +1,223 @@
|
||||
<?php
|
||||
|
||||
if (!defined('_PS_VERSION_')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
class Simple_withdrawalbuttonWithdrawModuleFrontController extends ModuleFrontController
|
||||
{
|
||||
public $ssl = true;
|
||||
public $auth = false;
|
||||
public $guestAllowed = true;
|
||||
|
||||
/** @var string */
|
||||
private $currentView = 'form';
|
||||
|
||||
/** @var array */
|
||||
private $formData = [];
|
||||
|
||||
/** @var array */
|
||||
private $errorsList = [];
|
||||
|
||||
/** @var array */
|
||||
private $successData = [];
|
||||
|
||||
public function initContent()
|
||||
{
|
||||
parent::initContent();
|
||||
|
||||
$this->context->smarty->assign([
|
||||
'errors_list' => $this->errorsList,
|
||||
'form_data' => $this->formData,
|
||||
'csrf_token' => $this->module->getFrontToken(),
|
||||
'action_url' => $this->context->link->getModuleLink($this->module->name, 'withdraw', [], true),
|
||||
'success_data' => $this->successData,
|
||||
'privacy_url' => (string) Configuration::get(Simple_withdrawalbutton::CONF_PRIVACY_URL),
|
||||
'revocation_url' => (string) Configuration::get(Simple_withdrawalbutton::CONF_REVOCATION_URL),
|
||||
]);
|
||||
|
||||
if ($this->currentView === 'confirm') {
|
||||
$this->setTemplate('module:' . $this->module->name . '/views/templates/front/confirm.tpl');
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->currentView === 'success') {
|
||||
$this->setTemplate('module:' . $this->module->name . '/views/templates/front/success.tpl');
|
||||
return;
|
||||
}
|
||||
|
||||
$this->setTemplate('module:' . $this->module->name . '/views/templates/front/form.tpl');
|
||||
}
|
||||
|
||||
public function postProcess()
|
||||
{
|
||||
if (Tools::isSubmit('submit_withdrawal_prepare')) {
|
||||
$this->handlePrepare();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Tools::isSubmit('submit_withdrawal_confirm')) {
|
||||
$this->handleConfirm();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Tools::isSubmit('submit_withdrawal_back')) {
|
||||
$this->formData = $this->collectInput();
|
||||
$this->currentView = 'form';
|
||||
return;
|
||||
}
|
||||
|
||||
$this->formData = $this->getEmptyFormData();
|
||||
}
|
||||
|
||||
private function handlePrepare()
|
||||
{
|
||||
$data = $this->collectInput();
|
||||
$this->formData = $data;
|
||||
|
||||
if (!$this->module->isValidFrontToken(Tools::getValue('csrf_token'))) {
|
||||
$this->errorsList[] = $this->module->l('The form could not be validated. Please reload the page and try again.', 'withdraw');
|
||||
}
|
||||
|
||||
if ($this->isHoneypotFilled()) {
|
||||
$this->errorsList[] = $this->module->l('The form could not be validated. Please reload the page and try again.', 'withdraw');
|
||||
}
|
||||
|
||||
$this->errorsList = array_merge($this->errorsList, $this->validateData($data));
|
||||
|
||||
if (!empty($this->errorsList)) {
|
||||
$this->currentView = 'form';
|
||||
return;
|
||||
}
|
||||
|
||||
$this->currentView = 'confirm';
|
||||
}
|
||||
|
||||
private function handleConfirm()
|
||||
{
|
||||
$data = $this->collectInput();
|
||||
$this->formData = $data;
|
||||
|
||||
if (!$this->module->isValidFrontToken(Tools::getValue('csrf_token'))) {
|
||||
$this->errorsList[] = $this->module->l('The form could not be validated. Please reload the page and try again.', 'withdraw');
|
||||
}
|
||||
|
||||
if ($this->isHoneypotFilled()) {
|
||||
// Do not save obvious bot submissions. Show a generic success page to avoid feedback loops.
|
||||
$this->currentView = 'success';
|
||||
$this->successData = [
|
||||
'mail_ok' => true,
|
||||
'fake' => true,
|
||||
];
|
||||
return;
|
||||
}
|
||||
|
||||
$this->errorsList = array_merge($this->errorsList, $this->validateData($data));
|
||||
|
||||
$ipHash = $this->module->hashForPrivacy($this->module->getClientIp());
|
||||
if (empty($this->errorsList) && $this->module->isRateLimited($data['customer_email'], $ipHash)) {
|
||||
$this->errorsList[] = $this->module->l('Too many withdrawal declarations were submitted in a short period. Please try again later or contact us by email.', 'withdraw');
|
||||
}
|
||||
|
||||
if (!empty($this->errorsList)) {
|
||||
$this->currentView = 'form';
|
||||
return;
|
||||
}
|
||||
|
||||
$saved = $this->module->saveWithdrawal($data);
|
||||
if (!$saved) {
|
||||
$this->errorsList[] = $this->module->l('Your withdrawal declaration could not be saved. Please try again or contact us by email.', 'withdraw');
|
||||
$this->currentView = 'form';
|
||||
return;
|
||||
}
|
||||
|
||||
$customerMailOk = $this->module->sendCustomerConfirmation($data, $saved['created_at']);
|
||||
$shopMailOk = $this->module->sendShopNotification($data, $saved['created_at'], (int) $saved['id_withdrawal_request']);
|
||||
|
||||
if ($customerMailOk) {
|
||||
$this->module->markConfirmationSent((int) $saved['id_withdrawal_request']);
|
||||
}
|
||||
|
||||
$this->currentView = 'success';
|
||||
$this->successData = [
|
||||
'id_withdrawal_request' => (int) $saved['id_withdrawal_request'],
|
||||
'created_at' => $this->module->formatDateTimeForMail($saved['created_at']),
|
||||
'mail_ok' => (bool) $customerMailOk,
|
||||
'shop_mail_ok' => (bool) $shopMailOk,
|
||||
'customer_email' => $data['customer_email'],
|
||||
'order_reference' => $data['order_reference'],
|
||||
'withdrawal_scope' => $data['withdrawal_scope'],
|
||||
'withdrawal_items_text' => $data['withdrawal_items_text'],
|
||||
'message' => $data['message'],
|
||||
];
|
||||
}
|
||||
|
||||
private function collectInput()
|
||||
{
|
||||
$scope = (string) Tools::getValue('withdrawal_scope');
|
||||
if (!in_array($scope, ['full', 'partial'], true)) {
|
||||
$scope = 'full';
|
||||
}
|
||||
|
||||
return [
|
||||
'customer_name' => $this->module->cleanText(Tools::getValue('customer_name'), 255),
|
||||
'customer_email' => strtolower($this->module->cleanText(Tools::getValue('customer_email'), 255)),
|
||||
'order_reference' => $this->module->cleanText(Tools::getValue('order_reference'), 64),
|
||||
'withdrawal_scope' => $scope,
|
||||
'withdrawal_items_text' => $this->module->cleanText(Tools::getValue('withdrawal_items_text'), 5000),
|
||||
'message' => $this->module->cleanText(Tools::getValue('message'), 5000),
|
||||
];
|
||||
}
|
||||
|
||||
private function getEmptyFormData()
|
||||
{
|
||||
$customerName = '';
|
||||
$customerEmail = '';
|
||||
|
||||
if (Validate::isLoadedObject($this->context->customer)) {
|
||||
$customerName = trim((string) $this->context->customer->firstname . ' ' . (string) $this->context->customer->lastname);
|
||||
$customerEmail = (string) $this->context->customer->email;
|
||||
}
|
||||
|
||||
return [
|
||||
'customer_name' => $customerName,
|
||||
'customer_email' => $customerEmail,
|
||||
'order_reference' => '',
|
||||
'withdrawal_scope' => 'full',
|
||||
'withdrawal_items_text' => '',
|
||||
'message' => '',
|
||||
];
|
||||
}
|
||||
|
||||
private function validateData(array $data)
|
||||
{
|
||||
$errors = [];
|
||||
|
||||
if ($data['customer_name'] === '' || Tools::strlen($data['customer_name']) < 2) {
|
||||
$errors[] = $this->module->l('Please enter your name.', 'withdraw');
|
||||
}
|
||||
|
||||
if (!Validate::isEmail($data['customer_email'])) {
|
||||
$errors[] = $this->module->l('Please enter a valid email address for the confirmation.', 'withdraw');
|
||||
}
|
||||
|
||||
if ($data['order_reference'] === '') {
|
||||
$errors[] = $this->module->l('Please enter the order number or order reference.', 'withdraw');
|
||||
}
|
||||
|
||||
if (!in_array($data['withdrawal_scope'], ['full', 'partial'], true)) {
|
||||
$errors[] = $this->module->l('Please select whether you want to withdraw the full order or part of it.', 'withdraw');
|
||||
}
|
||||
|
||||
if ($data['withdrawal_scope'] === 'partial' && $data['withdrawal_items_text'] === '') {
|
||||
$errors[] = $this->module->l('For a partial withdrawal, please enter the affected items and quantities.', 'withdraw');
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
private function isHoneypotFilled()
|
||||
{
|
||||
return trim((string) Tools::getValue('cyp_hp_v1')) !== '';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
/** Silence is golden. */
|
||||
Reference in New Issue
Block a user