Files
root b6df4dbb92 Snapshot: MLS sync fixes, image refresh, plugin/theme updates
MLS plugin fixes from this session:
- Fix silent insert failures: location column NOT NULL was rejecting wpdb->insert calls,
  causing ~18k new properties since Dec 2025 to be lost. Inserts now build raw SQL
  with ST_PointFromText so the spatial column is populated atomically.
- Auto-refresh expired media URLs in MLS_Media_Handler::fetch_and_cache(), guarded by
  a property-level GET_LOCK so concurrent fetches share one API refresh.
- Normalize WP_Error to null in mls_get_property_image() so callers can rely on the
  documented string|null contract.
- Support comma-separated property_type filters in MLS_Query and MLS_Cluster so the
  homepage "View All Commercial" link (?property_type=Commercial+Sale,Land,Farm)
  actually filters correctly.
- Incremental sync now looks back 10 minutes past the latest modification timestamp
  as a safety margin against missed records.
- Smart sync exits silently (info-level, not warning) when a full sync is in progress.

Operational:
- New cron: weekly full sync Sundays at 3 AM (/usr/local/bin/mls-full-sync).
- New cron: hourly 2GB cap on mls-thumbnails/ and cache/transformed-images/
  (/usr/local/bin/mls-image-cache-cap).
- Logrotate config for wp-content/debug.log (2-day retention, daily rotation,
  delaycompress).

Repo policy:
- CLAUDE.md updated with explicit "commit everything except build artifacts" policy.
- .gitignore: untrack runtime image caches and debug.log rotations.

Other modifications in this snapshot are pre-existing in-flight theme/plugin/db_content_updates work.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 15:32:23 +00:00

230 lines
4.9 KiB
JavaScript
Executable File

/* global wpforms_admin, wpforms_admin_payments_single */
/**
* WPForms Single Payment View page.
*
* @since 1.8.2
*/
const WPFormsPaymentsSingle = window.WPFormsPaymentsSingle || ( function( document, window, $ ) {
/**
* Public functions and properties.
*
* @since 1.8.2
*
* @type {Object}
*/
const app = {
/**
* Start the engine.
*
* @since 1.8.2
*/
init() {
$( app.ready );
},
/**
* Document ready.
*
* @since 1.8.2
*/
ready() {
app.initTooltips();
app.paymentDeletionAlert();
app.actionButtons();
},
/**
* Initialize WPForms admin area tooltips.
*
* @since 1.8.2
*/
initTooltips() {
if ( typeof jQuery.fn.tooltipster === 'undefined' ) {
return;
}
jQuery( '.wpforms-single-payment-tooltip' ).tooltipster( {
contentCloning: true,
theme: 'borderless',
contentAsHTML: true,
position: 'top',
maxWidth: 500,
multiple: true,
interactive: true,
debug: false,
} );
},
/**
* Alert user before deleting payment.
*
* @since 1.8.2
*/
paymentDeletionAlert() {
$( document ).on( 'click', '.wpforms-payment-actions .button-delete', function( event ) {
event.preventDefault();
const url = $( this ).attr( 'href' );
// Trigger alert modal to confirm.
$.confirm( {
title: wpforms_admin.heads_up,
content: wpforms_admin_payments_single.payment_delete_confirm,
icon: 'fa fa-exclamation-circle',
type: 'orange',
buttons: {
confirm: {
text: wpforms_admin.ok,
btnClass: 'btn-confirm',
keys: [ 'enter' ],
action() {
window.location = url;
},
},
cancel: {
text: wpforms_admin.cancel,
keys: [ 'esc' ],
},
},
} );
} );
},
/**
* Handle payment actions.
*
* @since 1.8.4
*/
actionButtons() {
$( document ).on( 'click', '.wpforms-payments-single-action', ( event ) => {
const gateway = $( event.currentTarget ).data( 'gateway' ),
registeredHandlers = wpforms_admin.single_payment_button_handlers;
if ( ! registeredHandlers || ! registeredHandlers.includes( gateway ) ) {
return;
}
event.preventDefault();
const paymentId = $( event.currentTarget ).data( 'action-id' ),
actionType = $( event.currentTarget ).data( 'action-type' );
$.confirm( {
title: wpforms_admin.heads_up,
content: app.strings[ actionType ].confirm,
icon: 'fa fa-exclamation-circle',
type: 'orange',
buttons: {
confirm: {
text: wpforms_admin.ok,
btnClass: 'btn-confirm',
keys: [ 'enter' ],
action: () => {
app.sendActionRequest( paymentId, gateway, actionType );
},
},
cancel: {
text: wpforms_admin.cancel,
keys: [ 'esc' ],
},
},
} );
} );
},
/**
* Send action request to server.
*
* @since 1.8.4
*
* @param {number} paymentId Payment ID.
* @param {string} gateway Payment gateway.
* @param {string} actionType Action type.
*/
sendActionRequest( paymentId, gateway, actionType ) {
$.ajax( {
url: wpforms_admin.ajax_url,
type: 'POST',
data: {
action: 'wpforms_' + gateway + '_payments_' + actionType,
payment_id: paymentId, // eslint-disable-line camelcase
nonce: wpforms_admin.nonce,
},
dataType: 'json',
success: ( response ) => {
if ( response.success ) {
$.alert( {
title: wpforms_admin.success,
content: app.strings[ actionType ].success,
icon: 'fa fa-check-circle',
type: 'green',
buttons: {
confirm: {
text: wpforms_admin.close_refresh,
btnClass: 'btn-confirm',
keys: [ 'enter' ],
action: () => {
window.location.reload();
},
},
},
} );
} else {
app.failedResponseAlert( response?.data?.modal_msg || '' );
}
},
error: () => {
app.failedResponseAlert();
},
} );
},
/**
* Strings.
*
* @since 1.8.4
*/
strings : {
refund: {
confirm: wpforms_admin_payments_single.payment_refund_confirm,
success: wpforms_admin_payments_single.payment_refund_success,
},
cancel: {
confirm: wpforms_admin_payments_single.payment_cancel_confirm,
success: wpforms_admin_payments_single.payment_cancel_success,
},
},
/**
* Alert user when refunding payment failed.
*
* @since 1.8.4
*
* @param {string} message Modal message.
*/
failedResponseAlert( message = '' ) {
$.alert( {
title: wpforms_admin.heads_up,
content: message === '' ? wpforms_admin.try_again : message,
icon: 'fa fa-exclamation-circle',
type: 'red',
buttons: {
confirm: {
text: wpforms_admin.ok,
btnClass: 'btn-confirm',
keys: [ 'enter' ],
},
},
} );
},
};
return app;
}( document, window, jQuery ) );
// Initialize.
WPFormsPaymentsSingle.init();