Merge pull request #1977 from Azhar-Webkul/gli-3320

Fixed: Google hotel connector issues.
This commit is contained in:
Rohit Jain
2026-10-27 20:36:36 +05:30
committed by GitHub
7 changed files with 238 additions and 40 deletions

View File

@@ -95,4 +95,24 @@ class QghcApiLog extends ObjectModel
return false;
}
}
public static function cleanupApiLogs()
{
$cutoff = date('Y-m-d H:i:s', strtotime('-2 months'));
if (!Db::getInstance()->delete('qghc_api_log', '`date_add` < \'' . pSQL($cutoff) . '\'')) {
return false;
}
// Daily file logs follow the same retention window as the DB rows.
$logDir = _PS_MODULE_DIR_ . 'qlogooglehotelconnector/logs/';
if (is_dir($logDir)) {
foreach (glob($logDir . '*.log') as $file) {
$fileDate = basename($file, '.log');
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $fileDate) && strtotime($fileDate) < strtotime($cutoff)) {
@unlink($file);
}
}
}
return true;
}
}

View File

@@ -35,6 +35,7 @@ class AdminGoogleHotelConfigController extends ModuleAdminController
const CONF_DISCONNECTED = 102;
/** _conf[] code: webservice key regenerated successfully. */
const CONF_KEY_REGENERATED = 103;
const CONF_CRON_UPDATED = 104;
public function __construct()
{
@@ -50,6 +51,7 @@ class AdminGoogleHotelConfigController extends ModuleAdminController
$this->_conf[self::CONF_CONNECTED] = $this->l('Connection created successfully.');
$this->_conf[self::CONF_DISCONNECTED] = $this->l('Connection disconnected successfully.');
$this->_conf[self::CONF_KEY_REGENERATED] = $this->l('Webservice key regenerated successfully.');
$this->_conf[self::CONF_CRON_UPDATED] = $this->l('Cron job set up successfully.');
}
/**
@@ -72,6 +74,27 @@ class AdminGoogleHotelConfigController extends ModuleAdminController
$this->processRegenerateKey();
return;
}
if (Tools::isSubmit('submitGhcCron')) {
$this->processSaveCron();
return;
}
}
public function processSaveCron()
{
if (!$this->tabAccess['edit']) {
$this->errors[] = Tools::displayError('You do not have permission to edit this.');
return;
}
$result = $this->module->setupCronTask();
if ($result !== true) {
$this->errors[] = $result;
return;
}
Tools::redirectAdmin($this->context->link->getAdminLink('AdminGoogleHotelConfig') . '&conf=' . self::CONF_CRON_UPDATED);
}
/** True when the current admin request came over HTTPS (directly or via a TLS-terminating proxy). */
@@ -122,7 +145,7 @@ class AdminGoogleHotelConfigController extends ModuleAdminController
$rows = QghcProperty::getEnrolledProperties($idLang);
$configs = array();
$hotelEditBase = $this->context->link->getAdminLink('AdminAddHotel');
if ($rows) {
foreach ($rows as $row) {
$badge = isset($statusBadges[(int)$row['google_status']]) ? $statusBadges[(int)$row['google_status']] : $pendingBadge;
@@ -138,7 +161,6 @@ class AdminGoogleHotelConfigController extends ModuleAdminController
}
}
// Token must match the check in ghclogcron.php
$cronUrl = Tools::getShopDomainSsl(true, true) . __PS_BASE_URI__ . 'modules/qlogooglehotelconnector/ghclogcron.php?token=' . Tools::encrypt('qlogooglehotelconnector');
$this->context->smarty->assign(array(
@@ -149,6 +171,8 @@ class AdminGoogleHotelConfigController extends ModuleAdminController
'ssl_settings_url' => $this->context->link->getAdminLink('AdminPreferences'),
'action_url' => $this->context->link->getAdminLink('AdminGoogleHotelConfig'),
'cron_url' => $cronUrl,
'cron_task' => $this->module->getCronTaskSchedule(),
'cron_manager_enabled' => Module::isEnabled('qlocrontaskmanager'),
'hotel_list_url' => $hotelEditBase,
));
}

View File

@@ -36,28 +36,11 @@ if ($token !== Tools::encrypt('qlogooglehotelconnector')) {
die('Invalid token.');
}
// Delete qghc_api_log rows older than 2 months
$cutoff = date('Y-m-d H:i:s', strtotime('-2 months'));
$deleted = Db::getInstance()->execute(
'DELETE FROM `' . _DB_PREFIX_ . 'qghc_api_log`
WHERE `date_add` < \'' . pSQL($cutoff) . '\''
);
if ($deleted) {
$count = Db::getInstance()->Affected_Rows();
echo 'OK — ' . (int)$count . ' log(s) deleted (older than ' . $cutoff . ').';
// Delete qghc_api_log rows and daily file logs older than 2 months
Module::getInstanceByName('qlogooglehotelconnector'); // loads the module classes
if (QghcApiLog::cleanupApiLogs()) {
echo 'OK — logs older than 2 months deleted.';
} else {
header('HTTP/1.1 500 Internal Server Error');
echo 'ERROR — failed to delete old logs.';
}
// Delete daily file logs older than the same retention window used for the DB rows above.
$logDir = _PS_MODULE_DIR_ . 'qlogooglehotelconnector/logs/';
if (is_dir($logDir)) {
foreach (glob($logDir . '*.log') as $file) {
$fileDate = basename($file, '.log');
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $fileDate) && strtotime($fileDate) < strtotime($cutoff)) {
@unlink($file);
}
}
}

View File

@@ -0,0 +1,32 @@
<?php
/**
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License version 3.0
* that is bundled with this package in the file LICENSE.md
* It is also available through the world-wide-web at this URL:
* https://opensource.org/license/osl-3-0-php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to support@qloapps.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade this module to a newer
* versions in the future. If you wish to customize this module for your needs
* please refer to https://store.webkul.com/customisation-guidelines for more information.
*
* @author Webkul IN
* @copyright Since 2010 Webkul
* @license https://opensource.org/license/osl-3-0-php Open Software License version 3.0
*/
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../../');
exit;

View File

@@ -34,9 +34,15 @@ class QloGoogleHotelConnector extends Module
/** PS Configuration key that stores the module connection status (0 = off, 1 = connected). */
const CONFIG_STATUS = 'QGHC_STATUS';
/** Cron task name registered in the Cron Task Manager module. */
const CRON_TASK_CLEANUP_LOGS = 'cleanup_api_logs';
public $debugging = false;
public $logger;
/** Default schedule of the API log cleanup task (daily at midnight), as a cron expression. */
protected $cronExpression = '0 0 * * *';
/** Sets up module properties (name, version, author) and initialises the file logger. */
public function __construct()
{
@@ -192,9 +198,102 @@ class QloGoogleHotelConnector extends Module
'actionObjectHotelOrderRestrictDateUpdateBefore',
// Front-end structured data markup
'displayFooterBefore',
// Cron Task Manager
'registerCronTasks',
));
}
/** Tells the Cron Task Manager module which tasks this module provides. */
public function hookRegisterCronTasks()
{
return array(
array(
'name' => self::CRON_TASK_CLEANUP_LOGS,
'description' => $this->l('Delete Google Hotel API logs older than 2 months'),
'cron' => $this->cronExpression,
'callback' => 'cronCleanupApiLogs',
),
);
}
/** Cron Task Manager callback for the API log cleanup. */
public function cronCleanupApiLogs()
{
if (QghcApiLog::cleanupApiLogs() === false) {
throw new Exception('Unable to delete the old API logs.');
}
}
/**
* Creates the API log cleanup task in the Cron Task Manager when it does not exist.
*
* @return string|bool Error message, true on success.
*/
public function setupCronTask()
{
if (!Module::isEnabled('qlocrontaskmanager')) {
return $this->l('The Cron Task Manager module is not enabled.');
}
if ($this->getCronTask()) {
return true;
}
(new QctmCronTask())->registerTasksForModule((int) $this->id, $this->hookRegisterCronTasks());
if (!$this->getCronTask()) {
return $this->l('Unable to create the cleanup cron task in the Cron Task Manager.');
}
return true;
}
/** Returns the log cleanup task of the Cron Task Manager, false when it does not exist. */
protected function getCronTask()
{
if (!Module::isEnabled('qlocrontaskmanager')) {
return false;
}
require_once _PS_MODULE_DIR_ . 'qlocrontaskmanager/classes/QctmRequiredClasses.php';
$idTask = QctmCronTask::getByModuleAndName((int) $this->id, self::CRON_TASK_CLEANUP_LOGS);
if (!$idTask) {
return false;
}
$cronTask = new QctmCronTask((int) $idTask);
return Validate::isLoadedObject($cronTask) ? $cronTask : false;
}
/** Returns the cleanup task state for display, false when the Cron Task Manager is not enabled. */
public function getCronTaskSchedule()
{
if (!Module::isEnabled('qlocrontaskmanager')) {
return false;
}
$cronTask = $this->getCronTask();
if (!$cronTask) {
return array(
'exists' => false,
'active' => false,
'readable' => '',
);
}
$readable = $cronTask->cron_expression;
if (\Cron\CronExpression::isValidExpression($cronTask->cron_expression)) {
$readable = (new QctmCronExpressionTranslator())->getCronExpressionTranslation($cronTask->cron_expression);
}
return array(
'exists' => true,
'active' => (bool) $cronTask->active,
'readable' => $readable,
);
}
/** Adds the Google Hotel Connector menu group with Configuration and API Logs sub-tabs to the admin sidebar. */
public function callInstallTab()
{

View File

@@ -37,6 +37,12 @@
text-align: left;
}
#ghc-dashboard-notification h3 {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* ── Prevent scrollbar jitter on GHC admin pages ─────────────────
Scoped to exactly the controllers this stylesheet is loaded on
(see hookActionAdminControllerSetMedia) via QloApps admin's own

View File

@@ -164,26 +164,60 @@
{/if}
{* ── Cron job setting ─────────────────────────────────────────────────── *}
<div class="panel">
<form method="post" action="{$action_url|escape:'html':'UTF-8'}" class="form-horizontal">
<div class="panel">
<div class="panel-heading">
<i class="icon-clock-o"></i>
{l s='Cron job setting' mod='qlogooglehotelconnector'}
</div>
<div class="panel-body">
<div class="alert alert-info qlo-ghc-no-margin">
<strong>
{l s='For automatic cleanup of API logs older than 2 months, set the following cron job to run once every 24 hours:' mod='qlogooglehotelconnector'}
</strong>
<br><br>
<strong>
<code>0 0 * * * curl {$cron_url|escape:'html':'UTF-8'}</code>
</strong>
<div class="panel-heading">
<i class="icon-clock-o"></i>
{l s='Cron job setting' mod='qlogooglehotelconnector'}
</div>
</div>
</div>
{if $cron_manager_enabled}
{if $cron_task.exists}
<div class="alert alert-info">
<p><strong>{l s='Automatic API log cleanup' mod='qlogooglehotelconnector'}</strong></p>
<ul>
{if $cron_task.active}
<li>{l s='API logs older than 2 months are deleted automatically. Current schedule:' mod='qlogooglehotelconnector'} <strong>{$cron_task.readable|escape:'html':'UTF-8'}</strong>.</li>
{else}
<li>{l s='Automatic API log cleanup is turned off.' mod='qlogooglehotelconnector'}</li>
{/if}
</ul>
</div>
<div class="alert alert-warning">
{l s='If you have set up a cron job for the API log cleanup manually on your server, we recommend removing that cron job and using the Cron Task Manager from now on.' mod='qlogooglehotelconnector'}
</div>
{else}
<div class="alert alert-info">
<p>{l s='The API log cleanup task is not present in the Cron Task Manager.' mod='qlogooglehotelconnector'}</p>
<button type="submit" name="submitGhcCron" class="btn btn-default">
<i class="icon-plus-sign"></i> {l s='Set up cron job' mod='qlogooglehotelconnector'}
</button>
</div>
<div class="alert alert-info">
<strong>
{l s='Or, for automatic cleanup of API logs older than 2 months, set the following cron job to run once every 24 hours:' mod='qlogooglehotelconnector'}
</strong>
<br><br>
<strong>
<code>0 0 * * * curl {$cron_url|escape:'html':'UTF-8'}</code>
</strong>
</div>
{/if}
{else}
<div class="alert alert-info">
<strong>
{l s='For automatic cleanup of API logs older than 2 months, set the following cron job to run once every 24 hours:' mod='qlogooglehotelconnector'}
</strong>
<br><br>
<strong>
<code>0 0 * * * curl {$cron_url|escape:'html':'UTF-8'}</code>
</strong>
</div>
{/if}
</div>
</form>
{* ── Connected Properties ───────────────────────────────────────────────── *}
<div class="panel">