Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@ zip:
rsync -a $(RSYNC_EXCLUDES) ./ $(STAGE_DIR)/
cp composer.json $(STAGE_DIR)/
@if [ -f composer.lock ]; then cp composer.lock $(STAGE_DIR)/; fi
cd $(STAGE_DIR) && composer install --no-dev --optimize-autoloader --no-interaction 2>/dev/null; rm -f $(STAGE_DIR)/composer.json $(STAGE_DIR)/composer.lock
(cd $(STAGE_DIR) && composer install --no-dev --optimize-autoloader --no-interaction 2>/dev/null)
rm -f $(STAGE_DIR)/composer.lock $(STAGE_DIR)/vendor/bin/.phpunit.result.cache
@if [ "$(KIRIOF_ENV)" != "prd" ] && [ -f .env ]; then \
API_URL=$$(grep '^$(ENV_VAR_NAME)=' .env | head -1 | cut -d= -f2- | xargs); \
if [ -n "$$API_URL" ]; then \
Expand Down
5 changes: 2 additions & 3 deletions inc/Controllers/CheckoutController.php
Original file line number Diff line number Diff line change
Expand Up @@ -635,14 +635,13 @@ function add_custom_select_options_field_and_script_shipping()
}

private function kiriof_get_posted_text_field( string $key ): string {
// phpcs:disable WordPress.Security.NonceVerification.Missing -- Read-only checkout POST normalization; WooCommerce verifies checkout/update-order-review requests.
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Read-only checkout POST normalization; WooCommerce verifies checkout/update-order-review requests.
if ( ! isset( $_POST[ $key ] ) || is_array( $_POST[ $key ] ) ) {
// phpcs:enable WordPress.Security.NonceVerification.Missing
return '';
}

// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Read-only checkout POST normalization; WooCommerce verifies checkout/update-order-review requests.
$value = sanitize_text_field( wp_unslash( $_POST[ $key ] ) );
// phpcs:enable WordPress.Security.NonceVerification.Missing

return $value;
}
Expand Down
3 changes: 0 additions & 3 deletions inc/Controllers/SettingController.php
Original file line number Diff line number Diff line change
Expand Up @@ -364,9 +364,6 @@ function storeCourierWhitelist() {
'origin_whitelist_expedition_name'=> $whitelist_names,
));

// Bust the couriers API cache so the updated whitelist is reflected immediately.
( new \KiriminAjaOfficial\Services\KiriminajaApiService() )->invalidateCouriersCache();

wp_send_json_success(['status' => 200, 'message' => 'Saved']);
}catch (Throwable $e){
wp_send_json_error(['status'=>400,'message'=>$e->getMessage()]);
Expand Down
6 changes: 3 additions & 3 deletions inc/Controllers/ShippingDiscountCouponController.php
Original file line number Diff line number Diff line change
Expand Up @@ -947,11 +947,11 @@ public function flushCouriersCache() {
}

$service = new KiriminajaApiService();
$service->invalidateCouriersCache();
$service->invalidateCouriersCache( false );
$fresh = $service->get_couriers();

if ( 200 !== $fresh->status ) {
wp_send_json_error( array( 'message' => __( 'Flushed, but could not re-fetch from API. Will retry on next page load.', 'kiriminaja-official' ) ) );
if ( 200 !== $fresh->status || 'courier_cache_fallback' === $fresh->customCode ) {
wp_send_json_error( array( 'message' => __( 'Could not refresh couriers from the API. The last successful courier list remains available.', 'kiriminaja-official' ) ) );
}

$count = is_array( $fresh->data ) ? count( $fresh->data ) : 0;
Expand Down
1 change: 1 addition & 0 deletions inc/Controllers/ShippingProcessController.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ private function markTransactionsPrinted( array $orderIds )
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared -- Placeholder list is generated from sanitized order IDs above.
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Print status is updated immediately after successful label fetch.
$wpdb->query(
// phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber -- Dynamic IN placeholders match the sanitized order IDs in $query_args.
$wpdb->prepare(
"UPDATE {$wpdb->prefix}kiriminaja_transactions
SET is_printed = %d, printed_at = %s
Expand Down
20 changes: 18 additions & 2 deletions inc/Services/KiriminajaApiService.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public function getTracking($order_id)
return self::success($repo['data']);
}
private const KIRIOF_COURIERS_CACHE_KEY = 'kiriof_couriers_list_v2';
private const KIRIOF_COURIERS_LAST_SUCCESS_CACHE_KEY = 'kiriof_couriers_last_success_cache';
private const KIRIOF_COURIERS_CACHE_TTL = DAY_IN_SECONDS;

public function get_couriers(){
Expand All @@ -52,6 +53,17 @@ public function get_couriers(){

$repo = (new \KiriminAjaOfficial\Repositories\KiriminajaApiRepository())->get_couriers();
if ( empty( $repo['status'] ) || ! is_object( $repo['data'] ?? null ) || empty( $repo['data']->status ) ) {
$last_success = get_transient( self::KIRIOF_COURIERS_LAST_SUCCESS_CACHE_KEY );
if ( false !== $last_success ) {
kiriof_log(
'warning',
'Courier lookup used the cached fallback because the live API request failed.',
array( 'source' => 'kiriminaja_api' )
);
set_transient( self::KIRIOF_COURIERS_CACHE_KEY, $last_success, self::KIRIOF_COURIERS_CACHE_TTL );
return self::success( $last_success, 'Using cached courier data.', 'courier_cache_fallback' );
}

return self::error( array(), $this->extractErrorMessage( $repo, 'Something is wrong' ) );
}

Expand All @@ -66,11 +78,15 @@ function ( $courier ) use ( $excluded_types ) {
)
);
set_transient( self::KIRIOF_COURIERS_CACHE_KEY, $data, self::KIRIOF_COURIERS_CACHE_TTL );
set_transient( self::KIRIOF_COURIERS_LAST_SUCCESS_CACHE_KEY, $data, WEEK_IN_SECONDS );
return self::success( $data );
}

public function invalidateCouriersCache(): void {
public function invalidateCouriersCache( bool $include_last_success = true ): void {
delete_transient( self::KIRIOF_COURIERS_CACHE_KEY );
if ( $include_last_success ) {
delete_transient( self::KIRIOF_COURIERS_LAST_SUCCESS_CACHE_KEY );
}
}

public function invalidateProfileCache(): void {
Expand Down Expand Up @@ -216,4 +232,4 @@ private function extractErrorMessage($repo, string $fallback): string {

return $fallback;
}
}
}
2 changes: 2 additions & 0 deletions inc/Services/SettingService.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public function processingSetupKey($setupKey)
/** Storing result to DB*/
$arrayRepoDataData = (array) $arrayRepoData['result'];
(new \KiriminAjaOfficial\Services\KiriminajaApiService())->invalidateProfileCache();
(new \KiriminAjaOfficial\Services\KiriminajaApiService())->invalidateCouriersCache();
(new \KiriminAjaOfficial\Repositories\SettingRepository())->storeIntegrationData([
'api_key' => sanitize_text_field($arrayRepoDataData['api_key']),
'oid_prefix' => sanitize_text_field($arrayRepoDataData['oid_prefix']),
Expand Down Expand Up @@ -82,6 +83,7 @@ public function disconnectIntegration()
{
try {
(new \KiriminAjaOfficial\Services\KiriminajaApiService())->invalidateProfileCache();
(new \KiriminAjaOfficial\Services\KiriminajaApiService())->invalidateCouriersCache();
$repo = (new \KiriminAjaOfficial\Repositories\SettingRepository())->disconnectIntegration();
kiriof_log(
'notice',
Expand Down
16 changes: 16 additions & 0 deletions lang/kiriminaja-official-id_ID.po
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,22 @@ msgstr ""
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Domain: kiriminaja-official\n"

#: templates/setting/setuped/section-couriers.php
msgid "Could not load couriers. Reload this page and try again."
msgstr "Tidak dapat memuat kurir. Muat ulang halaman ini dan coba lagi."

#: inc/Controllers/ShippingDiscountCouponController.php
msgid "Could not refresh couriers from the API. The last successful courier list remains available."
msgstr "Tidak dapat memperbarui kurir dari API. Daftar kurir terakhir yang berhasil masih tersedia."

#: templates/setting/setuped/section-couriers.php
msgid "Could not save courier settings."
msgstr "Tidak dapat menyimpan pengaturan kurir."

#: templates/setting/setuped/section-couriers.php
msgid "No couriers are available for this account."
msgstr "Tidak ada kurir yang tersedia untuk akun ini."

#. translators: %s: total number of items
#: templates/transaction-process/view/index.php:86
#: templates/transaction-process/view/index.php:283
Expand Down
47 changes: 25 additions & 22 deletions templates/request-pickup/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@ private function pageQuery(){
$items_per_page = 20;

// phpcs:ignore WordPress.Security.NonceVerification.Recommended
$page = isset($_GET['cpage']) ? absint($_GET['cpage']) : 1;
$offset = ( $page * $items_per_page ) - $items_per_page;
$page = isset($_GET['cpage']) ? max( 1, absint($_GET['cpage']) ) : 1;

$whereConditions = [];

Expand All @@ -72,18 +71,36 @@ private function pageQuery(){
$whereConditions[] = $wpdb->prepare("kiriminaja_payments.created_at LIKE %s", '%' . $wpdb->esc_like($month) . '%');
}
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
if (!empty(sanitize_text_field(wp_unslash($_GET['status'] ?? '')))) {
$status = sanitize_text_field(wp_unslash($_GET['status'])); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$status = sanitize_text_field(wp_unslash($_GET['status'] ?? '')); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( in_array( $status, array( 'unpaid', 'paid' ), true ) ) {
$whereConditions[] = $wpdb->prepare("kiriminaja_payments.status = %s", $status);
}

// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Each condition is individually prepared above
$whereCondition = !empty($whereConditions) ? 'WHERE ' . implode(' AND ', $whereConditions) : '';

/** Pagination Query*/
$count_sql = "SELECT
kiriminaja_payments.id, kiriminaja_payments.pickup_number
FROM {$wpdb->prefix}kiriminaja_payments as kiriminaja_payments
INNER JOIN {$wpdb->prefix}kiriminaja_transactions as kiriminaja_transactions
ON kiriminaja_payments.pickup_number = kiriminaja_transactions.pickup_number
" . $whereCondition . "
GROUP BY kiriminaja_payments.pickup_number";

// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Query safe: whereCondition contains pre-prepared statements, no additional params needed
$totalQuery = $wpdb->get_results($count_sql);
$total = count($totalQuery);
$total_pages = (int) ceil($total/$items_per_page);
if ( $page > $total_pages && $total_pages > 0 ) {
$page = $total_pages;
}
$offset = ( $page - 1 ) * $items_per_page;

/** Main Query*/
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Table names use prefix, whereCondition pre-prepared above
$baseQuery = "SELECT
kiriminaja_payments.*,
$baseQuery = "SELECT
kiriminaja_payments.*,
SUM(CASE WHEN kiriminaja_transactions.cod_fee = 0 THEN kiriminaja_transactions.shipping_cost - COALESCE(kiriminaja_transactions.discount_amount, 0) + kiriminaja_transactions.insurance_cost ELSE 0 END) AS cost
FROM {$wpdb->prefix}kiriminaja_payments as kiriminaja_payments
INNER JOIN {$wpdb->prefix}kiriminaja_transactions as kiriminaja_transactions
Expand All @@ -94,28 +111,14 @@ private function pageQuery(){
LIMIT %d, %d";

// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
$results = $wpdb->get_results(
$results = $wpdb->get_results(
$wpdb->prepare($baseQuery, $offset, $items_per_page) // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
);

if (strlen(@$wpdb->last_error ?? '') > 0){
(new \KiriminAjaOfficial\Base\BaseInit())->logThis('last_error',@$wpdb->last_error);
}

/** Pagination Query*/
$count_sql = "SELECT
kiriminaja_payments.id, kiriminaja_payments.pickup_number
FROM {$wpdb->prefix}kiriminaja_payments as kiriminaja_payments
INNER JOIN {$wpdb->prefix}kiriminaja_transactions as kiriminaja_transactions
ON kiriminaja_payments.pickup_number = kiriminaja_transactions.pickup_number
" . $whereCondition . "
GROUP BY kiriminaja_payments.pickup_number";

// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Query safe: whereCondition contains pre-prepared statements, no additional params needed
$totalQuery = $wpdb->get_results($count_sql);
$total = count($totalQuery);
$total_pages = ceil($total/$items_per_page);

/** Paginate*/
$next_page_link = admin_url( 'admin.php?' );
$prev_page_link = admin_url( 'admin.php?' );
Expand Down
Loading
Loading