Compare commits
6 Commits
8d42eee2c1
...
76ca74e1a6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
76ca74e1a6 | ||
|
|
4f8de2e1f4 | ||
|
|
159f96c9c2 | ||
|
|
72bfb88bfb | ||
|
|
0b467752fb | ||
|
|
ab97611783 |
@@ -40,13 +40,14 @@ function set_pppr_cookie($is_local, $street_name, $house_number, $postcode, $cit
|
||||
$signature = hash_hmac('sha256', $data_string, WP_PPPR_SALT);
|
||||
$cookie_value = $data_string . "|" . $signature;
|
||||
|
||||
$is_secure = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off');
|
||||
$cookie_domain = $_SERVER['SERVER_NAME'];
|
||||
$is_secure = is_ssl();
|
||||
|
||||
setcookie("PPPR", $cookie_value, [
|
||||
'expires' => time() + 7200,
|
||||
'path' => '/',
|
||||
'domain' => $_SERVER['SERVER_NAME'],
|
||||
'secure' => $is_secure, // Only send over HTTPS
|
||||
'domain' => $cookie_domain,
|
||||
'secure' => $is_secure,
|
||||
'httponly' => true, // Prevent JavaScript access
|
||||
'samesite' => 'Lax' // Protect against CSRF
|
||||
]);
|
||||
@@ -55,11 +56,38 @@ function set_pppr_cookie($is_local, $street_name, $house_number, $postcode, $cit
|
||||
function unset_pppr_cookie( $path = '/') {
|
||||
unset($_COOKIE["PPPR"]);
|
||||
|
||||
if (empty($domain)) {
|
||||
setcookie("PPPR", '', time() - 3600, '/');
|
||||
} else {
|
||||
setcookie("PPPR", '', time() - 3600, '/' , $_SERVER['SERVER_NAME']);
|
||||
$domain = $_SERVER['SERVER_NAME'];
|
||||
$is_secure = is_ssl();
|
||||
|
||||
// 3. Send the delete command with ALL matching parameters
|
||||
setcookie(
|
||||
"PPPR",
|
||||
'',
|
||||
time() - 3600,
|
||||
'/',
|
||||
$domain,
|
||||
$is_secure, // Critical: Must match the 'secure' flag used when setting
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
function update_expire_pppr_cookie() {
|
||||
if (!isset($_COOKIE['PPPR'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$cookie_value = $_COOKIE['PPPR'];
|
||||
$cookie_domain = $_SERVER['SERVER_NAME'];
|
||||
$is_secure = is_ssl();
|
||||
|
||||
setcookie("PPPR", $cookie_value, [
|
||||
'expires' => time() + 7200,
|
||||
'path' => '/',
|
||||
'domain' => $cookie_domain,
|
||||
'secure' => $is_secure,
|
||||
'httponly' => true, // Prevent JavaScript access
|
||||
'samesite' => 'Lax' // Protect against CSRF
|
||||
]);
|
||||
}
|
||||
|
||||
function verify_pppr_cookie_string() {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* Plugin Name: Prijzen per poscodeereeks.
|
||||
* Description: Producten worden gefiltered aan de hand van opgegegeven postcodereeksen.Gebruikers met een postcode die in een opgegegeven postcodereeks valt zal een lokale prijs zien. Waar elke gebruiker met een postcode die buiten eem opgegeven reeks valt zal de reguliere prijs te zien krijgen.
|
||||
* Author: Remo Zaros
|
||||
* Version: 0.9.8
|
||||
* Version: 0.9.82
|
||||
* Text Domeain: prijs-per-postcode
|
||||
*/
|
||||
|
||||
@@ -159,8 +159,13 @@ class PrijsPerPostcode
|
||||
!is_shop()
|
||||
) {
|
||||
if (!verify_pppr_cookie_string()) {
|
||||
wp_redirect(home_url("/winkel/"));
|
||||
if (!WC()->cart->is_empty()) {
|
||||
WC()->cart->empty_cart();
|
||||
}
|
||||
wp_safe_redirect($this->get_shop_url());
|
||||
exit();
|
||||
}else{
|
||||
update_expire_pppr_cookie();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -227,6 +232,12 @@ class PrijsPerPostcode
|
||||
}
|
||||
return $translated_text;
|
||||
}
|
||||
|
||||
public function get_shop_url () {
|
||||
return (function_exists('wcml_get_store_url'))
|
||||
? wcml_get_store_url() // WPML WooCommerce Multilingual
|
||||
: get_permalink(wc_get_page_id('shop')); // Fallback
|
||||
}
|
||||
}
|
||||
|
||||
new PrijsPerPostcode();
|
||||
|
||||
@@ -88,10 +88,8 @@ function send_postcode_data()
|
||||
body: JSON.stringify(payload)
|
||||
});
|
||||
|
||||
// Parse altijd eerst de JSON, zelfs bij HTTP fouten
|
||||
const data = await resp.json();
|
||||
|
||||
// UI: Reset knop
|
||||
sndBtn.disabled = false;
|
||||
sndBtnLdr.style.opacity = "0";
|
||||
sndBtnTxt.style.opacity = "1";
|
||||
@@ -269,10 +267,10 @@ function handle_postcode_modal($data)
|
||||
}
|
||||
set_pppr_cookie(
|
||||
postcode_in_range($params["postcode"]),
|
||||
$straatnaam,
|
||||
$params["huisnummer"],
|
||||
$params["postcode"],
|
||||
$woonplaats
|
||||
trim($straatnaam),
|
||||
trim($params["huisnummer"]),
|
||||
trim($params["postcode"]),
|
||||
trim($woonplaats)
|
||||
);
|
||||
|
||||
return new WP_REST_Response([
|
||||
@@ -345,7 +343,7 @@ function getStraatnaam($postcode, $huisnummer)
|
||||
];
|
||||
}
|
||||
|
||||
// Geef de RUWE response terug (inclusief meta, error, results, etc.)
|
||||
// Give me back RUWE data (inclusive meta, error, results, etc.)
|
||||
return $data;
|
||||
}
|
||||
|
||||
@@ -376,126 +374,154 @@ function postcode_in_range($postcode)
|
||||
return false;
|
||||
}
|
||||
|
||||
function modify_checkout_with_js()
|
||||
{
|
||||
if (
|
||||
!is_checkout() ||
|
||||
(is_wc_endpoint_url() && !is_wc_endpoint_url("order-received"))
|
||||
) {
|
||||
function modify_checkout_with_js() {
|
||||
if ( ! is_checkout() || ( is_wc_endpoint_url() && ! is_wc_endpoint_url( 'order-received' ) ) ) {
|
||||
return;
|
||||
}
|
||||
$data = get_PPPR_data();
|
||||
|
||||
$city = $data["city"];
|
||||
$postcode = $formatted_postcode = preg_replace(
|
||||
"/(\d+)([A-Z]+)/",
|
||||
'$1 $2',
|
||||
strtoupper($data["postcode"]),
|
||||
);
|
||||
$address =
|
||||
$data["street"] . " " . strtoupper($data["house_number"]);
|
||||
$data = get_PPPR_data();
|
||||
if ( empty( $data ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$city = trim(esc_js( $data['city'] ));
|
||||
$postcode = trim(esc_js( preg_replace( '/(\d+)([A-Z]+)/', '$1 $2', strtoupper( $data['postcode']))));
|
||||
$address = trim(esc_js( $data['street'] . ' ' . strtoupper( $data['house_number'])));
|
||||
|
||||
// Enqueue script properly to handle dependencies and nonces
|
||||
wp_enqueue_script( 'jquery' );
|
||||
wp_localize_script( 'jquery', 'ajax_object', array(
|
||||
'ajax_url' => admin_url( 'admin-ajax.php' ),
|
||||
'nonce' => wp_create_nonce( 'unset_my_session_nonce' )
|
||||
) );
|
||||
|
||||
echo <<<HTML
|
||||
<script type="text/javascript" id="set_pppr_fields">
|
||||
jQuery(document).ready(function($) {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
function lockCheckoutFields() {
|
||||
if (typeof wp !== 'undefined' && wp.data && wp.data.dispatch) {
|
||||
const store = 'wc/store/cart';
|
||||
|
||||
wp.data.dispatch(store).setShippingAddress({
|
||||
first_name: '',
|
||||
last_name: '',
|
||||
address_1: 'Tjeuke Timmermansstraat 43',
|
||||
address_2: '',
|
||||
city: 'Tilburg',
|
||||
state: '',
|
||||
postcode: '5041 EK',
|
||||
country: 'NL',
|
||||
phone: '',
|
||||
email: ''
|
||||
// Safari Fix: Handle back/forward cache (bfcache)
|
||||
window.addEventListener('pageshow', function(event) {
|
||||
if (event.persisted || (typeof wp !== 'undefined' && wp.data)) {
|
||||
initPPPRFields();
|
||||
}
|
||||
});
|
||||
|
||||
function initPPPRFields() {
|
||||
// Wait for React/WC Blocks to mount
|
||||
setTimeout(() => {
|
||||
const targets = '#shipping-postcode, #shipping-city, #shipping-address_1';
|
||||
const addressVal = '{$address}';
|
||||
const cityVal = '{$city}';
|
||||
const postcodeVal = '{$postcode}';
|
||||
|
||||
$(targets).each(function() {
|
||||
// Voeg readonly attribuut toe (voor toegankelijkheid)
|
||||
$(this).prop('readonly', true);
|
||||
// Map WC Blocks field selectors
|
||||
const fields = [
|
||||
{ id: 'shipping-address_1', val: addressVal },
|
||||
{ id: 'shipping-city', val: cityVal },
|
||||
{ id: 'shipping-postcode', val: postcodeVal }
|
||||
];
|
||||
|
||||
$(this).css({
|
||||
'background-color': '#f9f9f9',
|
||||
'cursor': 'not-allowed',
|
||||
'pointer-events': 'none' // Blokkeert alle muisklikken in het veld
|
||||
fields.forEach(field => {
|
||||
// 1. Try Redux Dispatch (Standard)
|
||||
if (typeof wp !== 'undefined' && wp.data && wp.data.dispatch) {
|
||||
try {
|
||||
wp.data.dispatch('wc/store/cart').setShippingAddress({ [field.id.replace('shipping-', '')]: field.val });
|
||||
} catch(e) { console.warn('Redux update skipped', e); }
|
||||
}
|
||||
|
||||
// 2. Force DOM Update (Safari Fallback)
|
||||
// Select both legacy and Blocks inputs
|
||||
const inputs = document.querySelectorAll('#' + field.id + ', input[name="' + field.id.replace('shipping-', '') + '"]');
|
||||
|
||||
inputs.forEach(input => {
|
||||
if (input.value !== field.val) {
|
||||
input.value = field.val;
|
||||
|
||||
// CRITICAL FOR SAFARI: Manually trigger events so React notices
|
||||
['input', 'change'].forEach(evtType => {
|
||||
input.dispatchEvent(new Event(evtType, { bubbles: true, cancelable: true }));
|
||||
});
|
||||
}
|
||||
|
||||
// 3. Apply Visual Lock
|
||||
input.setAttribute('data-pppr-locked', 'true');
|
||||
input.readOnly = true;
|
||||
});
|
||||
});
|
||||
|
||||
if ($('.postcode-reset').length === 0) {
|
||||
const div = document.createElement("div");
|
||||
div.setAttribute("class", "postcode-reset");
|
||||
// Inject Reset Button once
|
||||
if (!document.querySelector('.postcode-reset')) {
|
||||
const cityContainer = document.querySelector('.wc-block-components-address-form__city');
|
||||
if (cityContainer) {
|
||||
const div = document.createElement('div');
|
||||
div.className = 'postcode-reset';
|
||||
div.style.display = 'block';
|
||||
div.style.width = '100%';
|
||||
div.style.marginTop = '10px';
|
||||
|
||||
div.innerHTML = `
|
||||
<a href="#" class="reset-postcode-show-comfirm" style="font-size:12px; text-decoration:underline;">Reset postcode.</a>
|
||||
<span class="bevestiging" style="display:none; font-size:12px;">
|
||||
<a href="#" class="reset-postcode-show-comfirm" style="font-size:12px; text-decoration:underline; display:block; margin-top:5px;">Reset postcode.</a>
|
||||
<span class="bevestiging" style="display:none; font-size:12px; margin-top:5px;">
|
||||
Deze handeling leegt ook de winkelwagen. Weet je het zeker?
|
||||
<a href="#" class="accept" style="color:red; font-weight:bold;"> JA </a>/
|
||||
<a href="#" class="decline"> nee </a>
|
||||
</span>`;
|
||||
cityContainer.parentNode.insertBefore(div, cityContainer.nextSibling);
|
||||
|
||||
div.style.width = "100%";
|
||||
document.querySelector(".wc-block-components-address-form__city")?.after(div);
|
||||
|
||||
$('.reset-postcode-show-comfirm').on('click', function(e) {
|
||||
// Event Listeners (using delegation for safety)
|
||||
div.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
$(this).hide();
|
||||
$(this).next('.bevestiging').show();
|
||||
});
|
||||
$('.decline').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
$(this).closest('.bevestiging').hide();
|
||||
$('.reset-postcode-show-comfirm').show();
|
||||
});
|
||||
|
||||
|
||||
$('.accept').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
$.ajax({
|
||||
url: ajax_object.ajax_url,
|
||||
type: 'POST',
|
||||
data: {
|
||||
action: 'unset_my_session', // Matches wp_ajax_ hook
|
||||
nonce: ajax_object.nonce // Matches wp_create_nonce action
|
||||
if (e.target.classList.contains('reset-postcode-show-comfirm')) {
|
||||
e.target.style.display = 'none';
|
||||
div.querySelector('.bevestiging').style.display = 'block';
|
||||
} else if (e.target.classList.contains('decline')) {
|
||||
div.querySelector('.bevestiging').style.display = 'none';
|
||||
div.querySelector('.reset-postcode-show-comfirm').style.display = 'block';
|
||||
} else if (e.target.classList.contains('accept')) {
|
||||
fetch(ajax_object.ajax_url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
location.reload();
|
||||
} else {
|
||||
console.error('Server returned error:', response.data);
|
||||
alert('Failed to reset session: ' + (response.data || 'Unknown error'));
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('AJAX request failed:', status, error);
|
||||
console.log('Response Text:', xhr.responseText); // Check for PHP fatal errors
|
||||
body: new URLSearchParams({
|
||||
action: 'unset_my_session',
|
||||
nonce: ajax_object.nonce
|
||||
})
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(res => {
|
||||
if (res.success) location.reload();
|
||||
else alert('Failed to reset: ' + (res.data || 'Unknown error'));
|
||||
})
|
||||
.catch(err => console.error('AJAX error:', err));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
jQuery(document.body).trigger('update_checkout');
|
||||
|
||||
}, 800); // Iets langere delay voor React rendering
|
||||
} else {
|
||||
console.error('WooCommerce Blocks API is niet beschikbaar');
|
||||
}
|
||||
}
|
||||
|
||||
lockCheckoutFields();
|
||||
// Add CSS for locked state dynamically
|
||||
if (!document.getElementById('pppr-styles')) {
|
||||
const style = document.createElement('style');
|
||||
style.id = 'pppr-styles';
|
||||
style.textContent = `
|
||||
input[data-pppr-locked="true"] {
|
||||
background-color: #f9f9f9 !important;
|
||||
cursor: not-allowed !important;
|
||||
pointer-events: none !important;
|
||||
opacity: 0.7;
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
|
||||
let updateTimeout;
|
||||
$(document.body).on('updated_checkout', function() {
|
||||
clearTimeout(updateTimeout);
|
||||
updateTimeout = setTimeout(lockCheckoutFields, 500);
|
||||
}, 600); // Delay for WC Blocks hydration
|
||||
}
|
||||
|
||||
// Initialize on load
|
||||
initPPPRFields();
|
||||
|
||||
// Re-apply if checkout updates (e.g. shipping method change)
|
||||
document.body.addEventListener('updated_checkout', function() {
|
||||
setTimeout(initPPPRFields, 400);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user