Compare commits
15 Commits
d805477f4e
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ef3abb9514 | ||
|
|
03f7e9857d | ||
|
|
bdeae51bdb | ||
|
|
2df645be97 | ||
|
|
4173e32489 | ||
|
|
a43d6213b5 | ||
|
|
76ca74e1a6 | ||
|
|
4f8de2e1f4 | ||
|
|
159f96c9c2 | ||
|
|
72bfb88bfb | ||
|
|
0b467752fb | ||
|
|
ab97611783 | ||
|
|
8d42eee2c1 | ||
|
|
29109c47d1 | ||
|
|
297ba93508 |
@@ -40,7 +40,7 @@ function generate_admin_page()
|
|||||||
<ul>
|
<ul>
|
||||||
<li>Het formaat voor een reeks is #### - #### (voorbeeld: 5000 - 5199).</li>
|
<li>Het formaat voor een reeks is #### - #### (voorbeeld: 5000 - 5199).</li>
|
||||||
<li>Plaats één reeks op één regel.</li>
|
<li>Plaats één reeks op één regel.</li>
|
||||||
<li>Een reeks van 1 is geldig. (voorbeeld: 5000 - 5000)</li>
|
<li>Een reeks van 1 is geldig. (voorbeeld: 5000 - 5000).</li>
|
||||||
<li>Om een reeks te verwijderen. Wis de reeks en sla vervolgens de wijzigen op.</li>
|
<li>Om een reeks te verwijderen. Wis de reeks en sla vervolgens de wijzigen op.</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -40,11 +40,14 @@ function set_pppr_cookie($is_local, $street_name, $house_number, $postcode, $cit
|
|||||||
$signature = hash_hmac('sha256', $data_string, WP_PPPR_SALT);
|
$signature = hash_hmac('sha256', $data_string, WP_PPPR_SALT);
|
||||||
$cookie_value = $data_string . "|" . $signature;
|
$cookie_value = $data_string . "|" . $signature;
|
||||||
|
|
||||||
|
$cookie_domain = $_SERVER['SERVER_NAME'];
|
||||||
|
$is_secure = is_ssl();
|
||||||
|
|
||||||
setcookie("PPPR", $cookie_value, [
|
setcookie("PPPR", $cookie_value, [
|
||||||
'expires' => time() + 7200,
|
'expires' => time() + 7200,
|
||||||
'path' => '/',
|
'path' => '/',
|
||||||
'domain' => $_SERVER['SERVER_NAME'],
|
'domain' => $cookie_domain,
|
||||||
'secure' => true, // Only send over HTTPS
|
'secure' => $is_secure,
|
||||||
'httponly' => true, // Prevent JavaScript access
|
'httponly' => true, // Prevent JavaScript access
|
||||||
'samesite' => 'Lax' // Protect against CSRF
|
'samesite' => 'Lax' // Protect against CSRF
|
||||||
]);
|
]);
|
||||||
@@ -53,11 +56,38 @@ function set_pppr_cookie($is_local, $street_name, $house_number, $postcode, $cit
|
|||||||
function unset_pppr_cookie( $path = '/') {
|
function unset_pppr_cookie( $path = '/') {
|
||||||
unset($_COOKIE["PPPR"]);
|
unset($_COOKIE["PPPR"]);
|
||||||
|
|
||||||
if (empty($domain)) {
|
$domain = $_SERVER['SERVER_NAME'];
|
||||||
setcookie("PPPR", '', time() - 3600, '/');
|
$is_secure = is_ssl();
|
||||||
} else {
|
|
||||||
setcookie("PPPR", '', time() - 3600, '/' , $_SERVER['SERVER_NAME']);
|
// 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() {
|
function verify_pppr_cookie_string() {
|
||||||
@@ -132,6 +162,14 @@ function get_PPPR_data() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function pppr_is_local() {
|
function pppr_is_local() {
|
||||||
$first_char = $_COOKIE['PPPR'][0];
|
// Check if the cookie exists and is not empty
|
||||||
return $first_char === '1';
|
if (isset($_COOKIE['PPPR']) && !empty($_COOKIE['PPPR'])) {
|
||||||
|
// Ensure it's treated as a string before accessing the first character
|
||||||
|
$cookie_value = (string) $_COOKIE['PPPR'];
|
||||||
|
$first_char = $cookie_value[0] ?? '';
|
||||||
|
return $first_char === '1';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return false if cookie is missing or empty
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Plugin Name: Prijzen per poscodeereeks.
|
* Plugin Name: Prijs per poscodeereeks.
|
||||||
* Description: Producten worden gefiltered aan de hand van opgegegeven postcodereksen.Klanten met een postcode Die in de opgegegeven postcode reeks vallen zullen een lokale prijs zien. Waar iedereen die niet in de reeks vallen de overige regios prijs te zien krijgt.
|
* 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
|
* Author: Remo Zaros
|
||||||
* Version: 0.9.6
|
* Version: 0.9.090
|
||||||
* Text Domeain: prijs-per-postcode
|
* Text Domeain: prijs-per-postcode
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -12,79 +12,59 @@ require_once plugin_dir_path(__FILE__) . "session_dialog.php";
|
|||||||
require_once plugin_dir_path(__FILE__) . "admin.php";
|
require_once plugin_dir_path(__FILE__) . "admin.php";
|
||||||
require_once plugin_dir_path(__FILE__) . "pppr_cookie.php";
|
require_once plugin_dir_path(__FILE__) . "pppr_cookie.php";
|
||||||
|
|
||||||
|
|
||||||
if (!defined("ABSPATH")) {
|
if (!defined("ABSPATH")) {
|
||||||
echo "big bag of potatoes";
|
echo "big bag of potatoes";
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create salt
|
||||||
|
*/
|
||||||
register_activation_hook( __FILE__, 'create_pppr_salt' );
|
register_activation_hook( __FILE__, 'create_pppr_salt' );
|
||||||
if ( ! defined( 'WP_PPPR_SALT' ) ) {
|
if ( ! defined( 'WP_PPPR_SALT' ) ) {
|
||||||
$salt_file = ABSPATH . 'wp-pppr-salt.php';
|
$salt_file = __DIR__ . '/wp-pppr-salt.php';
|
||||||
if ( file_exists( $salt_file ) ) {
|
if ( file_exists( $salt_file ) ) {
|
||||||
require_once $salt_file;
|
require_once $salt_file;
|
||||||
|
}else {
|
||||||
|
define("WP_PPPR_SALT", wp_salt( 'auth' ));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PrijsPerPostcode
|
|
||||||
{
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
add_action("init", [$this, "init"], 1);
|
|
||||||
add_action("rest_api_init", "register_modal_api");
|
|
||||||
}
|
|
||||||
|
|
||||||
public function init()
|
add_filter("woocommerce_sale_flash", "__return_null");
|
||||||
{
|
add_filter('woocommerce_show_variation_price', '__return_true');
|
||||||
|
|
||||||
$uri = $_SERVER["REQUEST_URI"];
|
|
||||||
init_postcode_handlers($uri);
|
|
||||||
init_postode_admin();
|
|
||||||
|
|
||||||
add_filter("woocommerce_sale_flash", "__return_null");
|
/*
|
||||||
add_filter('woocommerce_show_variation_price', '__return_true');
|
* Init the plugin
|
||||||
add_action(
|
*/
|
||||||
"woocommerce_variation_options_pricing",
|
add_action("init", function() {
|
||||||
[$this, "add_local_price_field"],
|
$uri = $_SERVER["REQUEST_URI"];
|
||||||
10,
|
init_postcode_handlers($uri);
|
||||||
3,
|
// set the admin page
|
||||||
);
|
init_postode_admin();
|
||||||
add_action(
|
}, 1
|
||||||
"woocommerce_save_product_variation",
|
);
|
||||||
[$this, "save_local_price_field"],
|
|
||||||
10,
|
|
||||||
2,
|
|
||||||
);
|
|
||||||
add_action("woocommerce_before_calculate_totals", [
|
|
||||||
$this,
|
|
||||||
"use_local_price_if_local_postcode",
|
|
||||||
]);
|
|
||||||
|
|
||||||
add_filter(
|
|
||||||
"woocommerce_get_price_html",
|
|
||||||
[$this, "display_local_price_on_product"],
|
|
||||||
10,
|
|
||||||
2,
|
|
||||||
);
|
|
||||||
add_action("template_redirect", [
|
|
||||||
$this,
|
|
||||||
"check_postcode_on_every_woocommerce_page",
|
|
||||||
]);
|
|
||||||
add_filter(
|
|
||||||
"woocommerce_variation_is_visible",
|
|
||||||
[$this, "filter_variation_by_local_price"],
|
|
||||||
10,
|
|
||||||
4,
|
|
||||||
);
|
|
||||||
add_filter(
|
|
||||||
"gettext",
|
|
||||||
[$this, "change_variation_regular_price_label"],
|
|
||||||
99,
|
|
||||||
3,
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
/*
|
||||||
|
* Set endpoint (postcode-modal/v1/submit) for the modal form.
|
||||||
|
*/
|
||||||
|
add_action("rest_api_init", function () {
|
||||||
|
register_rest_route( 'postcode-modal/v1', '/submit', array(
|
||||||
|
'methods' => 'POST',
|
||||||
|
'callback' => 'handle_postcode_modal',
|
||||||
|
'permission_callback' => '__return_true',
|
||||||
|
) );
|
||||||
|
});
|
||||||
|
|
||||||
public function add_local_price_field($loop, $variation_data, $variation)
|
|
||||||
|
/*
|
||||||
|
* Add local orice field to variation product.
|
||||||
|
*/
|
||||||
|
add_action("woocommerce_variation_options_pricing",
|
||||||
|
function($loop, $variation_data, $variation)
|
||||||
{
|
{
|
||||||
woocommerce_wp_text_input([
|
woocommerce_wp_text_input([
|
||||||
"id" => "_local_price[" . $loop . "]",
|
"id" => "_local_price[" . $loop . "]",
|
||||||
@@ -97,9 +77,15 @@ class PrijsPerPostcode
|
|||||||
"data_type" => "price",
|
"data_type" => "price",
|
||||||
"wrapper_class" => "form-row form-row-first", // Left half
|
"wrapper_class" => "form-row form-row-first", // Left half
|
||||||
]);
|
]);
|
||||||
}
|
}, 10, 3,
|
||||||
|
);
|
||||||
|
|
||||||
public function save_local_price_field($variation_id, $i)
|
|
||||||
|
/*
|
||||||
|
* Save the local price on product save in the admin
|
||||||
|
*/
|
||||||
|
add_action("woocommerce_save_product_variation",
|
||||||
|
function ($variation_id, $i)
|
||||||
{
|
{
|
||||||
$local_price = $_POST["_local_price"][$i];
|
$local_price = $_POST["_local_price"][$i];
|
||||||
if (isset($local_price)) {
|
if (isset($local_price)) {
|
||||||
@@ -109,79 +95,36 @@ class PrijsPerPostcode
|
|||||||
wc_clean($local_price),
|
wc_clean($local_price),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}, 10, 2,
|
||||||
|
);
|
||||||
|
|
||||||
public function use_local_price_if_local_postcode($cart)
|
|
||||||
{
|
|
||||||
if (is_admin() && !defined("DOING_AJAX")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($cart->get_cart() as $cart_item) {
|
|
||||||
$product = $cart_item["data"];
|
|
||||||
$variation_id = $product->is_type("variation")
|
|
||||||
? $product->get_id()
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
if (
|
|
||||||
$variation_id &&
|
|
||||||
isset($_COOKIE["PPPR"]) &&
|
|
||||||
pppr_is_local()
|
|
||||||
) {
|
|
||||||
$local_price = get_post_meta(
|
|
||||||
$variation_id,
|
|
||||||
"_local_price",
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
if ($local_price) {
|
|
||||||
$product->set_price($local_price);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function check_postcode_on_every_woocommerce_page()
|
|
||||||
{
|
|
||||||
if (is_admin() || defined("DOING_AJAX")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Replace "Reguliere prijs" with "Prijs overige regios"
|
||||||
|
* in variation prodict admin
|
||||||
|
*/
|
||||||
|
add_filter( "gettext", function( $translated_text, $text, $domain,) {
|
||||||
if (
|
if (
|
||||||
(is_product() ||
|
"woocommerce" === $domain &&
|
||||||
is_product_category() ||
|
is_admin() &&
|
||||||
is_product_tag() ||
|
isset($_REQUEST["action"]) &&
|
||||||
is_cart() ||
|
"woocommerce_load_variations" === $_REQUEST["action"]
|
||||||
is_checkout() ||
|
|
||||||
is_account_page()) &&
|
|
||||||
!is_shop()
|
|
||||||
) {
|
) {
|
||||||
if (!verify_pppr_cookie_string()) {
|
if ($translated_text === "Reguliere prijs (%s)") {
|
||||||
wp_redirect(home_url("/winkel/"));
|
$translated_text = "Prijs overige regios (%s)";
|
||||||
exit();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return $translated_text;
|
||||||
|
}, 99, 3,
|
||||||
|
);
|
||||||
|
|
||||||
public function display_local_price_on_product($price_html, $product)
|
|
||||||
{
|
|
||||||
if (
|
|
||||||
$product->is_type("variation") &&
|
|
||||||
isset($_COOKIE["PPPR"]) &&
|
|
||||||
pppr_is_local()
|
|
||||||
) {
|
|
||||||
$local_price = get_post_meta(
|
|
||||||
$product->get_id(),
|
|
||||||
"_local_price",
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
if ($local_price !== "") {
|
|
||||||
return wc_price($local_price);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $price_html;
|
|
||||||
}
|
|
||||||
|
|
||||||
function filter_variation_by_local_price(
|
/*
|
||||||
|
* Filter out variations whwre the price is
|
||||||
|
* either 0 or '' in the dropdown menu product page
|
||||||
|
*/
|
||||||
|
add_filter("woocommerce_variation_is_visible",
|
||||||
|
function (
|
||||||
$visible,
|
$visible,
|
||||||
$variation_id,
|
$variation_id,
|
||||||
$parent_id,
|
$parent_id,
|
||||||
@@ -205,25 +148,145 @@ class PrijsPerPostcode
|
|||||||
}
|
}
|
||||||
|
|
||||||
return $visible;
|
return $visible;
|
||||||
}
|
}, 10, 4,
|
||||||
|
);
|
||||||
|
|
||||||
public function change_variation_regular_price_label(
|
|
||||||
$translated_text,
|
/*
|
||||||
$text,
|
* Dynamically recalculates the cart total by overriding the standard price
|
||||||
$domain,
|
* with a region-specific _local_price for variations when
|
||||||
) {
|
* the user's location matches the PPPR cookie criteria
|
||||||
if (
|
*/
|
||||||
"woocommerce" === $domain &&
|
add_action("woocommerce_before_calculate_totals", function($cart)
|
||||||
is_admin() &&
|
{
|
||||||
isset($_REQUEST["action"]) &&
|
if (is_admin() && !defined("DOING_AJAX")) {
|
||||||
"woocommerce_load_variations" === $_REQUEST["action"]
|
return;
|
||||||
) {
|
}
|
||||||
if ($translated_text === "Reguliere prijs (%s)") {
|
|
||||||
$translated_text = "Prijs overige regios (%s)";
|
foreach ($cart->get_cart() as $cart_item)
|
||||||
|
{
|
||||||
|
$product = $cart_item["data"];
|
||||||
|
$variation_id = $product->is_type("variation")
|
||||||
|
? $product->get_id()
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
if ( $variation_id && isset($_COOKIE["PPPR"]) && pppr_is_local() )
|
||||||
|
{
|
||||||
|
$local_price = get_post_meta(
|
||||||
|
$variation_id,
|
||||||
|
"_local_price",
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($local_price)
|
||||||
|
{
|
||||||
|
$product->set_price($local_price);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $translated_text;
|
|
||||||
}
|
}
|
||||||
}
|
);
|
||||||
|
|
||||||
new PrijsPerPostcode();
|
|
||||||
|
/*
|
||||||
|
* Filter to display the regular or local price on teh product page.
|
||||||
|
*/
|
||||||
|
add_filter( "woocommerce_get_price_html",
|
||||||
|
function($price_html, $product)
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
$product->is_type("variation") &&
|
||||||
|
isset($_COOKIE["PPPR"]) &&
|
||||||
|
pppr_is_local()
|
||||||
|
) {
|
||||||
|
$local_price = get_post_meta(
|
||||||
|
$product->get_id(),
|
||||||
|
"_local_price",
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
if ($local_price !== "") {
|
||||||
|
return wc_price($local_price);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $price_html;
|
||||||
|
}, 10, 2,
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enforces region-locking by clearing the cart and redirecting users to
|
||||||
|
* the shop page if their location cookie is invalid or expired when
|
||||||
|
* accessing key WooCommerce pages.
|
||||||
|
*/
|
||||||
|
add_action("template_redirect",
|
||||||
|
function ()
|
||||||
|
{
|
||||||
|
if (is_admin() || defined("DOING_AJAX")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
(is_product() ||
|
||||||
|
is_product_category() ||
|
||||||
|
is_product_tag() ||
|
||||||
|
is_cart() ||
|
||||||
|
is_checkout() ||
|
||||||
|
is_account_page()) &&
|
||||||
|
!is_shop()
|
||||||
|
) {
|
||||||
|
if (!verify_pppr_cookie_string()) {
|
||||||
|
if (!WC()->cart->is_empty()) {
|
||||||
|
WC()->cart->empty_cart();
|
||||||
|
}
|
||||||
|
wp_safe_redirect(get_shop_url());
|
||||||
|
exit();
|
||||||
|
}else{
|
||||||
|
update_expire_pppr_cookie();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chack or postcode is still valid when pressing the buy button
|
||||||
|
*/
|
||||||
|
add_action( 'woocommerce_after_checkout_validation', function( $data, $errors ) {
|
||||||
|
// 1. Controleer of de cookie bestaat en geldig is
|
||||||
|
if ( ! isset( $_COOKIE['PPPR'] ) || ! verify_pppr_cookie_string() ) {
|
||||||
|
$errors->add(
|
||||||
|
'pppr_cookie_invalid',
|
||||||
|
__( '<strong>Fout:</strong> Sessie verlopen. Vernieuw de pagina en vul je postcode opnieuw in.', 'woocommerce' )
|
||||||
|
);
|
||||||
|
return; // Stop hier, geen zin om verder te checken
|
||||||
|
}
|
||||||
|
|
||||||
|
$pppr_data = get_PPPR_data();
|
||||||
|
|
||||||
|
if ( ! $pppr_data || empty( $pppr_data['postcode'] ) ) {
|
||||||
|
$errors->add(
|
||||||
|
'pppr_data_missing',
|
||||||
|
__( '<strong>Fout:</strong> Kon postcode niet laden.', 'woocommerce' )
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Normalizeer postcodes (gebruik de juiste variabelen!)
|
||||||
|
$cookie_pc = strtoupper( str_replace( ' ', '', $pppr_data['postcode'] ) );
|
||||||
|
$shipping_pc = strtoupper( str_replace( ' ', '', $data['shipping_postcode'] ) );
|
||||||
|
|
||||||
|
// 4. Vergelijk
|
||||||
|
if ( $cookie_pc !== $shipping_pc ) {
|
||||||
|
wc_add_notice(
|
||||||
|
__( '<strong>Fout:</strong> Afleverpostcode komt niet overeen met de eerder ingevulde postcode.', 'woocommerce' ),
|
||||||
|
'error'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, 10, 2 );
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
|
|
||||||
function init_postcode_handlers($uri)
|
function init_postcode_handlers($uri)
|
||||||
{
|
{
|
||||||
if (strpos($uri, "/winkel/") !== false) {
|
if (strpos($uri, "/winkel/") !== false) {
|
||||||
add_action("wp_enqueue_scripts", "modal_styles");
|
add_action("wp_enqueue_scripts", "modal_styles");
|
||||||
add_action("wp_footer", "send_postcode_data");
|
add_action("wp_footer", "send_postcode_data");
|
||||||
if (!verify_pppr_cookie_string()) {
|
if (!verify_pppr_cookie_string()) {
|
||||||
if (!is_admin()) {
|
if (!is_admin()) {
|
||||||
WC()->cart->empty_cart();
|
WC()->cart->empty_cart();
|
||||||
}
|
}
|
||||||
add_action("wp_footer", "show_modal");
|
add_action("wp_footer", "show_modal");
|
||||||
render_dialog_html();
|
render_dialog_html();
|
||||||
@@ -21,30 +21,30 @@ function init_postcode_handlers($uri)
|
|||||||
|
|
||||||
function modal_styles()
|
function modal_styles()
|
||||||
{
|
{
|
||||||
wp_enqueue_style(
|
wp_enqueue_style(
|
||||||
"prijs-per-postcode",
|
"prijs-per-postcode",
|
||||||
plugins_url("/assets/postcode_modal.css", __FILE__),
|
plugins_url("/assets/postcode_modal.css", __FILE__),
|
||||||
[], // Voeg een lege dependencies array toe (verplicht)
|
[], // Voeg een lege dependencies array toe (verplicht)
|
||||||
filemtime(plugin_dir_path(__FILE__) . "assets/postcode_modal.css"), // Voeg versie toe
|
filemtime(plugin_dir_path(__FILE__) . "assets/postcode_modal.css"), // Voeg versie toe
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function show_modal()
|
function show_modal()
|
||||||
{
|
{
|
||||||
echo <<<'HTML'
|
echo <<<'HTML'
|
||||||
<script id="postcode_modal_open">
|
<script id="postcode_modal_open">
|
||||||
const postcodeModal = document.querySelector("#postcode_modal");
|
const postcodeModal = document.querySelector("#postcode_modal");
|
||||||
postcodeModal.showModal();
|
postcodeModal.showModal();
|
||||||
</script>
|
</script>
|
||||||
HTML;
|
HTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
function send_postcode_data()
|
function send_postcode_data()
|
||||||
{
|
{
|
||||||
$URL = get_rest_url(null, "postcode-modal/v1/submit");
|
$URL = get_rest_url(null, "postcode-modal/v1/submit");
|
||||||
$nonce = wp_create_nonce("wp_rest");
|
$nonce = wp_create_nonce("wp_rest");
|
||||||
|
|
||||||
echo <<<HTML
|
echo <<<HTML
|
||||||
<script type="module">
|
<script type="module">
|
||||||
const postcodeModal = document.querySelector("#postcode_modal");
|
const postcodeModal = document.querySelector("#postcode_modal");
|
||||||
const modalForm = document.querySelector("#postcode_modal_form");
|
const modalForm = document.querySelector("#postcode_modal_form");
|
||||||
@@ -88,10 +88,8 @@ function send_postcode_data()
|
|||||||
body: JSON.stringify(payload)
|
body: JSON.stringify(payload)
|
||||||
});
|
});
|
||||||
|
|
||||||
// Parse altijd eerst de JSON, zelfs bij HTTP fouten
|
|
||||||
const data = await resp.json();
|
const data = await resp.json();
|
||||||
|
|
||||||
// UI: Reset knop
|
|
||||||
sndBtn.disabled = false;
|
sndBtn.disabled = false;
|
||||||
sndBtnLdr.style.opacity = "0";
|
sndBtnLdr.style.opacity = "0";
|
||||||
sndBtnTxt.style.opacity = "1";
|
sndBtnTxt.style.opacity = "1";
|
||||||
@@ -135,12 +133,12 @@ function send_postcode_data()
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
HTML;
|
HTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
function render_dialog_html()
|
function render_dialog_html()
|
||||||
{
|
{
|
||||||
echo <<<'HTML'
|
echo <<<'HTML'
|
||||||
<dialog id="postcode_modal" class="postcode_modal" closedby="none">
|
<dialog id="postcode_modal" class="postcode_modal" closedby="none">
|
||||||
<h2>Vul je postcode en huisnummer in.</h2>
|
<h2>Vul je postcode en huisnummer in.</h2>
|
||||||
<p>Onze prijzen zijn afhankelijk van de regio. Vul daarom de postcode en het huisnummer in om de exacte prijzen te bekijken.</p>
|
<p>Onze prijzen zijn afhankelijk van de regio. Vul daarom de postcode en het huisnummer in om de exacte prijzen te bekijken.</p>
|
||||||
@@ -259,36 +257,26 @@ function handle_postcode_modal($data)
|
|||||||
|
|
||||||
// 5. Response sturen
|
// 5. Response sturen
|
||||||
if ($hasError) {
|
if ($hasError) {
|
||||||
echo json_encode([
|
return new WP_REST_Response([
|
||||||
"status" => "error",
|
"status" => "error",
|
||||||
"code" => $errorCode,
|
"code" => $errorCode,
|
||||||
"message" => $errorMessage,
|
"message" => $errorMessage,
|
||||||
"suggestions" => $result["error"]["details"]["suggestions"] ?? [],
|
"suggestions" => $result["error"]["details"]["suggestions"] ?? [],
|
||||||
"apirequest" => "openpostcode.nl",
|
"apirequest" => "openpostcode.nl",
|
||||||
]);
|
], 400);
|
||||||
exit();
|
|
||||||
}
|
}
|
||||||
set_pppr_cookie(
|
set_pppr_cookie(
|
||||||
postcode_in_range($params["postcode"]),
|
postcode_in_range($params["postcode"]),
|
||||||
$straatnaam,
|
trim($straatnaam),
|
||||||
$params["huisnummer"],
|
trim($params["huisnummer"]),
|
||||||
$params["postcode"],
|
trim($params["postcode"]),
|
||||||
$woonplaats
|
trim($woonplaats)
|
||||||
);
|
);
|
||||||
|
|
||||||
echo json_encode([
|
return new WP_REST_Response([
|
||||||
"status" => "success",
|
"status" => "success",
|
||||||
"message" => "all good",
|
"message" => "all good",
|
||||||
]);
|
], 200);
|
||||||
exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
function register_modal_api()
|
|
||||||
{
|
|
||||||
register_rest_route("postcode-modal/v1", "submit", [
|
|
||||||
"methods" => "POST",
|
|
||||||
"callback" => "handle_postcode_modal",
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function verify_postcode($postcode)
|
function verify_postcode($postcode)
|
||||||
@@ -346,7 +334,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;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,108 +365,192 @@ function postcode_in_range($postcode)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function modify_checkout_with_js()
|
function modify_checkout_with_js() {
|
||||||
{
|
if ( ! is_checkout() || ( is_wc_endpoint_url() && ! is_wc_endpoint_url( 'order-received' ) ) ) {
|
||||||
if (
|
|
||||||
!is_checkout() ||
|
|
||||||
(is_wc_endpoint_url() && !is_wc_endpoint_url("order-received"))
|
|
||||||
) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$data = get_PPPR_data();
|
|
||||||
|
|
||||||
$city = $data["city"];
|
$data = get_PPPR_data();
|
||||||
$postcode = $formatted_postcode = preg_replace(
|
if ( empty( $data ) ) {
|
||||||
"/(\d+)([A-Z]+)/",
|
return;
|
||||||
'$1 $2',
|
}
|
||||||
strtoupper($data["postcode"]),
|
|
||||||
);
|
$city = esc_js( $data['city'] );
|
||||||
$address =
|
$postcode = esc_js( preg_replace( '/(\d+)([A-Z]+)/', '$1 $2', strtoupper( $data['postcode'])));
|
||||||
$data["street"] . " " . strtoupper($data["house_number"]);
|
$address = 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
|
echo <<<HTML
|
||||||
<script type="text/javascript" id="fill_address_fields">
|
<script type="text/javascript" id="set_pppr_fields">
|
||||||
jQuery(document).ready(function(\$) {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
fillCheckoutFields();
|
|
||||||
\$(document.body).on('updated_checkout', fillCheckoutFields);
|
|
||||||
});
|
|
||||||
|
|
||||||
function fillCheckoutFields() {
|
// Safari Fix: Handle back/forward cache (bfcache)
|
||||||
if (typeof wp !== 'undefined' && wp.data && wp.data.dispatch) {
|
window.addEventListener('pageshow', function(event) {
|
||||||
const store = 'wc/store/cart';
|
if (event.persisted || (typeof wp !== 'undefined' && wp.data)) {
|
||||||
|
initPPPRFields();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
wp.data.dispatch(store).setShippingAddress({
|
function initPPPRFields() {
|
||||||
first_name: '',
|
// Wait for React/WC Blocks to mount
|
||||||
last_name: '',
|
setTimeout(() => {
|
||||||
address_1: '{$address}',
|
const addressVal = '{$address}';
|
||||||
address_2: '',
|
const cityVal = '{$city}';
|
||||||
city: '{$city}',
|
const postcodeVal = '{$postcode}';
|
||||||
state: '',
|
|
||||||
postcode: '{$postcode}',
|
|
||||||
country: 'NL',
|
|
||||||
phone: '',
|
|
||||||
email: ''
|
|
||||||
});
|
|
||||||
|
|
||||||
//make fields READONLY and ppstcode reset.
|
// Map WC Blocks field selectors
|
||||||
setTimeout(() => {
|
const fields = [
|
||||||
// make prefilled fiields readonly.
|
{ id: 'shipping-address_1', val: addressVal },
|
||||||
\$('#shipping-postcode, #shipping-city, #shipping-address_1')
|
{ id: 'shipping-city', val: cityVal },
|
||||||
.prop('readonly', true)
|
{ id: 'shipping-postcode', val: postcodeVal }
|
||||||
.css('background', '#f9f9f9');
|
];
|
||||||
|
|
||||||
// create postcode reset button
|
fields.forEach(field => {
|
||||||
const div = document.createElement("div");
|
// 1. Try Redux Dispatch (Standard)
|
||||||
div.setAttribute("class", "postcode-reset")
|
if (typeof wp !== 'undefined' && wp.data && wp.data.dispatch) {
|
||||||
div.innerHTML = `
|
try {
|
||||||
<a href="#" class="reset-postcode-show-comfirm" >Reset postcode.</a>
|
wp.data.dispatch('wc/store/cart').setShippingAddress({ [field.id.replace('shipping-', '')]: field.val });
|
||||||
<span class="bevestiging"> Deze handeling leegt ook de winkelwagen. Weet je het zeker?
|
} catch(e) { console.warn('Redux update skipped', e); }
|
||||||
<a href="#" class="accept"> JA </a>/<a href="#" class="decline"> nee </a>
|
}
|
||||||
</span> `;
|
|
||||||
div.style.width = "100%";
|
|
||||||
document.querySelector(".wc-block-components-address-form__city").after(div);
|
|
||||||
}, 500);
|
|
||||||
|
|
||||||
jQuery(document.body).trigger('update_checkout');
|
// 2. Force DOM Update (Safari Fallback)
|
||||||
} else {
|
// Select both legacy and Blocks inputs
|
||||||
console.error('WooCommerce Blocks API is niet beschikbaar');
|
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;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 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; 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);
|
||||||
|
|
||||||
|
// Event Listeners (using delegation for safety)
|
||||||
|
div.addEventListener('click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
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',
|
||||||
|
},
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}, 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>
|
</script>
|
||||||
HTML;
|
HTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
function load_assets_reset_postcode_on_checkout()
|
function load_assets_reset_postcode_on_checkout()
|
||||||
{
|
{
|
||||||
if (is_checkout() && !is_wc_endpoint_url()) {
|
if (is_checkout() && !is_wc_endpoint_url()) {
|
||||||
wp_enqueue_style(
|
wp_enqueue_style(
|
||||||
"reset-postcode-style",
|
"reset-postcode-style",
|
||||||
plugin_dir_url(__FILE__) . "assets/reset-postcode.css",
|
plugin_dir_url(__FILE__) . "assets/reset-postcode.css",
|
||||||
[],
|
[],
|
||||||
"1.0.0",
|
"1.0.0",
|
||||||
);
|
);
|
||||||
|
|
||||||
wp_enqueue_script(
|
wp_enqueue_script(
|
||||||
"reset-postcode-script",
|
"reset-postcode-script",
|
||||||
plugin_dir_url(__FILE__) . "assets/reset-postcode.js",
|
plugin_dir_url(__FILE__) . "assets/reset-postcode.js",
|
||||||
[],
|
[],
|
||||||
"1.0.0",
|
"1.0.0",
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Pass PHP variables to JavaScript
|
// Pass PHP variables to JavaScript
|
||||||
wp_localize_script("reset-postcode-script", "ajax_object", [
|
wp_localize_script("reset-postcode-script", "ajax_object", [
|
||||||
"ajax_url" => admin_url("admin-ajax.php"),
|
"ajax_url" => admin_url("admin-ajax.php"),
|
||||||
"nonce" => wp_create_nonce("reset_postcode_nonce"), // Creates a secure token
|
"nonce" => wp_create_nonce("reset_postcode_nonce"), // Creates a secure token
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function handle_unset_session_fetch()
|
function handle_unset_session_fetch()
|
||||||
{
|
{
|
||||||
// Verify the nonce for security
|
// Verify the nonce for security
|
||||||
if (!wp_verify_nonce($_POST["nonce"], "reset_postcode_nonce")) {
|
if (!wp_verify_nonce($_POST["nonce"], "reset_postcode_nonce")) {
|
||||||
wp_die("Security check failed.");
|
wp_die("Security check failed.");
|
||||||
}
|
}
|
||||||
unset_pppr_cookie();
|
unset_pppr_cookie();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user