Compare commits

..

16 Commits

Author SHA1 Message Date
Remo Zaros
0ba7c07287 rewrite API call 2026-06-10 09:11:28 +02:00
Remo Zaros
558ea24cec style postcode form 2026-06-01 12:03:17 +02:00
Remo Zaros
f0b7c405fa add extra error messages 2026-06-01 12:02:59 +02:00
Remo Zaros
a9c7f7c70f increase version 2026-06-01 12:01:38 +02:00
Remo Zaros
5345b86a25 Increase version number 2026-05-28 09:46:24 +02:00
Remo Zaros
f458be3293 Change shipping fields to billing fields. Change error message to error code in switcht statement. 2026-05-28 09:44:33 +02:00
Remo Zaros
a08d0527b4 remove session_start() that magically reappeared 2026-05-20 09:14:48 +02:00
Remo Zaros
458c216fea Replace | with a - in postcode ranges 2026-05-20 09:06:39 +02:00
Remo Zaros
5828269a70 include admin page, bump version number 2026-05-19 16:57:24 +02:00
Remo Zaros
d4be70eb78 Change postcode_in_range() to work with admin page 2026-05-19 16:56:03 +02:00
Remo Zaros
f1d0414f58 Add page wp admin 2026-05-19 16:54:21 +02:00
Remo Zaros
41f44b1200 Add more postcode ranges 2026-05-18 18:42:26 +02:00
Remo Zaros
7f32a4bb1b Add new styles 2026-05-18 18:41:52 +02:00
Remo Zaros
492289deb1 session changed, css, postcode range 2026-05-18 10:17:45 +02:00
Remo Zaros
318eb8f0c5 Change postcode modal. 2026-05-17 16:44:57 +02:00
Remo Zaros
6fd3f4a13c Add dropdown filter. Add label rename variable products admin 2026-05-14 15:04:55 +02:00
4 changed files with 570 additions and 173 deletions

167
admin.php Normal file
View File

@@ -0,0 +1,167 @@
<?php
function init_postode_admin()
{
add_action("admin_menu", "local_postcodes_admin_menu", 99);
add_action("admin_head", "local_postcodes_admin_css");
add_action("admin_init", "local_postcodes_register_settings"); // Correct
}
function local_postcodes_admin_menu()
{
add_submenu_page(
"woocommerce", // Parent menu slug
"Lokale Postcodes", // Page title
"Lokale Postcodes", // Menu title
"manage_options", // Capability
"local-postcodes", // Menu slug
"generate_admin_page", // Callback function
"dashicons-buddicons-pm", // Optional icon URL or dashicon
);
}
function local_postcodes_register_settings()
{
register_setting(
"my_plugin_options",
"local_postcodes_values",
"local_postcodes_input_validate",
);
}
function generate_admin_page()
{
?>
<div class="wrap">
<h1><span class="dashicons dashicons-admin-home"></span> Lokale Postcodereeksen</h1>
<?php settings_errors("local_postcodes_error_messages"); ?>
<div class="info">
<p class="info">Vul hier de lokale postcodereeksen in.</p>
<ul>
<li>Het formaat voor een reeks is #### - #### (voorbeeld: 5000 - 5199).</li>
<li>Plaats één reeks op één regel.</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>
</ul>
</div>
<form id="postcodes_form" method="post" action="options.php">
<?php
settings_fields("my_plugin_options");
do_settings_sections("my_plugin_options");
?>
<textarea id="local_postcodes_values" name="local_postcodes_values"><?php echo esc_textarea(
get_option("local_postcodes_values"),
); ?></textarea>
<?php submit_button(); ?>
</form>
</div>
<?php
}
function local_postcodes_admin_css()
{
?>
<style>
h1 .dashicons{
font-size: 25px;
}
.info {
font-size: 1.1rem;
max-width: 60ch;
ul {
list-style: square inside;
}
}
#postcodes_form {
display: flex;
flex-direction: column;
max-width: 60ch;
align-items: flex-end;
font-size: 1.1rem;
#local_postcodes_values{
width: 100% !important;
height: 50vh !important;
font-size: 1.1rem;
font-family: "Consolas", "Monaco", "Courier New", monospace;
}
.submit{
margin-top: .2rem;
}
}
</style>';
<?php
}
function local_postcodes_input_validate($input)
{
$valid_input = "";
$lines = preg_split("/\R/", $input, -1, PREG_SPLIT_NO_EMPTY);
$pattern = '/^\d{4}\s*\-\s*\d{4}$/';
$pc_arr = [];
foreach ($lines as $line) {
$line = trim($line);
if (preg_match($pattern, $line)) {
$parts = explode("-", $line);
$first = (int) $parts[0];
$second = (int) $parts[1];
if ($first <= $second) {
$pc_arr[] = [$first, $second];
} else {
$pc_arr[] = [$second, $first];
}
} else {
add_settings_error(
"local_postcodes_error_messages",
"invalid_postcode_" . md5($line),
'❌️ Ongeldige regel: "' .
esc_html($line) .
'". Gebruik het formaat #### - ####.(bijvoorbeeld: 5000 - 5199)',
"error",
);
}
}
usort($pc_arr, function ($a, $b) {
return $a[0] <=> $b[0];
});
$old_pc_arr_len = count($pc_arr);
$pc_arr = array_map(
"unserialize",
array_unique(array_map("serialize", $pc_arr)),
);
$new_pc_arr_len = count($pc_arr);
if ($new_pc_arr_len < $old_pc_arr_len) {
add_settings_error(
"local_postcodes_error_messages",
"Duplicaten",
// @formatter:off
"⚠️ " .
$old_pc_arr_len -
$new_pc_arr_len .
" " .
($old_pc_arr_len - $new_pc_arr_len > 1
? "duplicaten"
: "duplicaat") .
" verwijderd.",
// @formatter:on
"warning",
);
}
foreach ($pc_arr as $range) {
$valid_input .= $range[0] . " - " . $range[1] . "\n";
}
return $valid_input;
}

View File

@@ -1,70 +1,127 @@
.postcode_modal { .postcode_modal {
border-radius: 20px; border-radius: 3px;
box-shadow(10px);
border: none; border: none;
max-width: 80ch; max-width: 65ch;
box-shadow: 0 0 20pc black;
padding: 2rem; padding: 2rem;
padding-bottom: 1rem;
opacity: 0; opacity: 0;
transition: opacity 0.3s ease, display 0.3s allow-discrete; transition:
opacity 0.3s ease,
display 0.3s allow-discrete;
&[open] { &[open] {
opacity: 1; opacity: 1;
transition-behavior: allow-discrete; transition-behavior: allow-discrete;
transition: opacity 0.3s ease, display 0.3s allow-discrete; transition:
} opacity 0.3s ease,
display 0.3s allow-discrete;
&:not([open]) { @starting-style {
display: none; opacity: 0;
}
} }
h2 { h2 {
font-size: 1.5rem; font-size: 1.1rem;
margin: .6rem; font-weight: 700;
}
p {
font-size: 1rem;
}
&:not([open]) {
display: none;
}
form {
margin-top: 1rem;
} }
input[type="text"] { input[type="text"] {
padding: .3rem; padding: 0.3rem;
font-size: 1.4rem; font-size: 1.2rem;
caret-color: hsl(344 98 40); caret-color: var(--wp--preset--color--vivid-red);
background: hsl(0 1 80);
border: none;
text-transform: uppercase;
&:focus,
&:valid,
&:invalid,
&:autofill,
&:autofill:focus {
background: hsl(0 1 80) !important;
}
} }
button { #postcode_modal_submit {
border: none; display: grid;
font-size: 1.4rem; grid-template-columns: 1fr;
grid-template-rows: 1fr;
place-items: center;
font-size: 1.2rem;
font-weight: 700;
color: hsl(233 100 100); color: hsl(233 100 100);
padding: .4rem 1rem; padding: 0.4rem 1rem;
border-radius: 5px; background: var(--wp--preset--color--vivid-red);
background: hsl(344 98 40); border: 1px var(--wp--preset--color--vivid-red) solid;
border: 1px hsl(344 98 40) solid; transition: 0.2s all linear;
margin: 0 0 0 .3rem; padding: 0.2em 2.5em;
transition: .2s all linear; &:hover {
color: var(--wp--preset--color--vivid-red);
&:hover{
color: hsl(344 98 40 );
background: hsl(344 98 100); background: hsl(344 98 100);
cursor: pointer; cursor: pointer;
} }
}
&:hover > .btn_loader > svg > circle {
fill: var(--wp--preset--color--vivid-red);
}
.btn_loader,
.btn_text {
transition: 0.2s opacity linear;
grid-row: 1 / -1;
grid-column: 1 / -1;
}
}
.form_fields { .form_fields {
display: flex; display: flex;
justify-content: space-between; justify-content: center;
align-items: center; align-items: center;
gap: 0.5rem;
&>{
display: flex;
}
} }
&::backdrop { &::backdrop {
backdrop-filter: blur(1px); backdrop-filter: blur(2px);
background-color: hsl(40deg 100 0 /0.4); background: hsl(0 1 65 / 0.6);
background: radial-gradient(circle,rgba(33, 33, 33, 0.68) 0%, rgba(15, 15, 15, 0.8) 23%, rgba(0, 0, 0, 0.87) 100%);
} }
.error_message_modal_postcode { .error_message_modal_postcode {
min-height: 1lh; min-height: 1lh;
color: hsl(344 98 40 ); color: var(--wp--preset--color--vivid-red);
}/* HTML: <div class="loader"></div> */ } /* HTML: <div class="loader"></div> */
}
/* HTML: <div class="loader"></div> */
.btn_loader {
opacity: 0;
svg {
height: 0.4rem;
}
circle {
fill: white;
transition: 0.2s fill linear;
animation: loader-pulse 1.5s ease-in-out infinite;
animation-delay: calc((var(--i, 0)) * 0.2s);
}
}
@keyframes loader-pulse {
0%,
100% {
opacity: 0.3; /* Dim state */
}
50% {
opacity: 1; /* Bright state */
}
} }

View File

@@ -1,12 +1,12 @@
<?php <?php
session_start(); require_once plugin_dir_path(__FILE__) . "session_dialog.php";
require_once "session_dialog.php"; require_once plugin_dir_path(__FILE__) . "admin.php";
/* /*
* Plugin Name: prijzen per poscode range * Plugin Name: Prijzen per poscodeereeks.
* Description: posctcodes in de 5000-5800 range krijgen een lokaal tarief aangeboden. * 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.
* Author: Remo Zaros * Author: Remo Zaros
* Version: 0.9.1 * Version: 0.9.6
* Text Domeain: prijs-per-postcode * Text Domeain: prijs-per-postcode
*/ */
@@ -19,15 +19,21 @@ class PrijsPerPostcode
{ {
public function __construct() public function __construct()
{ {
add_action("init", [$this, "init"]); add_action("init", [$this, "init"], 1);
add_action("rest_api_init", "register_modal_api"); add_action("rest_api_init", "register_modal_api");
} }
public function init() public function init()
{ {
if (session_status() == PHP_SESSION_NONE) {
ob_start();
@session_start();
}
$uri = $_SERVER["REQUEST_URI"]; $uri = $_SERVER["REQUEST_URI"];
add_filter("woocommerce_sale_flash", "__return_null");
init_postcode_handlers($uri); init_postcode_handlers($uri);
init_postode_admin();
add_filter("woocommerce_sale_flash", "__return_null");
//add_action("template_redirect", [$this, "redirect_if_missing_tag"]); //add_action("template_redirect", [$this, "redirect_if_missing_tag"]);
add_action( add_action(
@@ -57,6 +63,18 @@ class PrijsPerPostcode
$this, $this,
"controleer_postcode_op_woocommerce_paginas", "controleer_postcode_op_woocommerce_paginas",
]); ]);
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,
);
} }
public function add_local_price_field($loop, $variation_data, $variation) public function add_local_price_field($loop, $variation_data, $variation)
@@ -155,6 +173,53 @@ class PrijsPerPostcode
} }
return $price_html; return $price_html;
} }
function filter_variation_by_local_price(
$visible,
$variation_id,
$parent_id,
$variation,
) {
// Ensure $variation is a valid object
if (!$variation instanceof WC_Product_Variation) {
$variation = wc_get_product($variation_id);
}
if (!$variation) {
return false;
}
$is_local = isset($_SESSION["postcode_is_local"])
? $_SESSION["postcode_is_local"]
: false;
$price = $is_local
? $variation->get_meta("_local_price", true)
: $variation->get_regular_price();
if (empty($price) || floatval($price) == 0) {
return false;
}
return $visible;
}
public function change_variation_regular_price_label(
$translated_text,
$text,
$domain,
) {
if (
"woocommerce" === $domain &&
is_admin() &&
isset($_REQUEST["action"]) &&
"woocommerce_load_variations" === $_REQUEST["action"]
) {
if ($translated_text === "Reguliere prijs (%s)") {
$translated_text = "Prijs overige regios (%s)";
}
}
return $translated_text;
}
} }
new PrijsPerPostcode(); new PrijsPerPostcode();

View File

@@ -1,6 +1,5 @@
<?php <?php
session_start();
function init_postcode_handlers($uri) function init_postcode_handlers($uri)
{ {
if (strpos($uri, "/winkel/") !== false) { if (strpos($uri, "/winkel/") !== false) {
@@ -25,6 +24,8 @@ 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)
filemtime(plugin_dir_path(__FILE__) . "assets/postcode_modal.css"), // Voeg versie toe
); );
} }
@@ -44,57 +45,97 @@ function send_postcode_data()
<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");
const sndBtn = document.querySelector("#postcode_modal_submit");
const sndBtnLdr = sndBtn.querySelector(".btn_loader");
const sndBtnTxt = sndBtn.querySelector(".btn_text");
const errorMsg = document.querySelector("#error_message_modal_postcode");
// 1. Validatie bij blur (client-side checks)
modalForm.querySelectorAll("input").forEach(input => {
input.addEventListener("blur", ev => {
errorMsg.innerHTML = "";
if (!ev.target.validity.valid && ev.target.value !== "") {
errorMsg.innerHTML = ev.target.title;
}
});
});
// 2. Submit Handler
modalForm.addEventListener('submit', async (e) => { modalForm.addEventListener('submit', async (e) => {
e.preventDefault(); e.preventDefault();
errorMsg.innerHTML = "";
// UI: Laadstatus
sndBtn.disabled = true;
sndBtnLdr.style.opacity = "1";
sndBtnTxt.style.opacity = "0";
const formData = new FormData(e.target); const formData = new FormData(e.target);
const data = Object.fromEntries(formData.entries()); const payload = Object.fromEntries(formData.entries());
const json = JSON.stringify(data);
try { try {
const resp = await fetch('<?php echo get_rest_url( const resp = await fetch('<?php echo get_rest_url(
null, null,
"postcode-modal/v1/submit", "postcode-modal/v1/submit",
); ?>', { ); ?>', {
method: 'POST', method: 'POST',
credentials: 'same-origin', credentials: 'same-origin',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'X-WP-Nonce': '<?php echo wp_create_nonce("wp_rest"); ?>' 'X-WP-Nonce': '<?php echo wp_create_nonce(
}, "wp_rest",
body: json ); ?>'
}); },
body: JSON.stringify(payload)
});
if(!resp.ok){ // Parse altijd eerst de JSON, zelfs bij HTTP fouten
throw new Error(`HTTP Error! status: ${resp.status}` ); const data = await resp.json();
}
const data = await resp.json();
console.log("Data returnd", data);
if (data.status === "error"){ // UI: Reset knop
const err = data.message; sndBtn.disabled = false;
let errmsg sndBtnLdr.style.opacity = "0";
sndBtnTxt.style.opacity = "1";
switch (err) { if (data.status === "error") {
case "Huisnummer not found": const errorCode = data.code; // Komt nu correct door vanuit PHP
errmsg = "Adres niet gevonden."; const apiMessage = data.message;
break;
case "Multiple addresses match this huisnummer; add huisletter and/or huisnummertoevoeging":
errmsg = "Huisnummertovoeging mist.";
break;
default:
errmsg = "Gegevens niet correct.";
}
document.querySelector("#error_message_modal_postcode").innerHTML = errmsg;
}
if (data.status === "success"){ let userErrorMessage = "Gegevens zijn niet correct.";
postcodeModal.close();
//location.reload(); // Specifieke foutafhandeling
} if (errorCode === "HUISNUMMER_NOT_FOUND" || apiMessage.includes("not found")) {
}catch(err){ userErrorMessage = "Adres is niet gevonden.";
console.error("Fetch Failed:", err); }
throw err; else if (errorCode === "HUISNUMMER_AMBIGUOUS") {
// Deze komt ALLEEN nog hier als PHP géén 'platte' match kon vinden.
// Dat betekent dat de gebruiker verplicht een toevoeging moet geven (bijv. alleen 15A bestaat).
const suggestions = data.suggestions || [];
if (suggestions.length > 0) {
userErrorMessage = `Meerdere opties: ${suggestions.join(", ")}. Voeg een toevoeging toe.`;
} else {
userErrorMessage = "Huisnummertoevoeging is verplicht.";
}
}
else if (errorCode === "CURL_ERROR" || errorCode === "JSON_ERROR") {
userErrorMessage = "Serverfout. Probeer het later opnieuw.";
}
errorMsg.innerHTML = userErrorMessage;
}
if (data.status === "success") {
// Succes: Modal sluiten en eventueel reload of update
postcodeModal.close();
// Optioneel: location.reload(); of update de pagina content
}
} catch (err) {
console.error("Fetch Failed:", err);
sndBtn.disabled = false;
sndBtnLdr.style.opacity = "0";
sndBtnTxt.style.opacity = "1";
errorMsg.innerHTML = "Er ging iets mis bij het verbinden.";
} }
}); });
</script> </script>
@@ -106,30 +147,44 @@ function render_dialog_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>
<form id="postcode_modal_form" method="post" action="" novalidation> <p>Onze prijzen zijn afhankelijk van de regio. Vul daarom de postcode en het huisnummer in om de exacte prijzen te bekijken.</p>
<form id="postcode_modal_form" method="post" action="" novalidate>
<div class="form_fields"> <div class="form_fields">
<div> <!-- Dutch Postcode Field -->
<input type="text" name="postcode" <input
title="Voer een geldige Nederlandse postcode in (bijv. 1234AB of 1234 AB)." type="text"
name="postcode"
title="Voer een geldige postcode in (bijv. 1234AB of 1234 AB)."
pattern="[1-9][0-9]{3} ?(?!sa|sd|ss)[a-zA-Z]{2}" pattern="[1-9][0-9]{3} ?(?!sa|sd|ss)[a-zA-Z]{2}"
placeholder= "1010 AA" placeholder="5010 AA"
size="10" size="8"
required required
autocomplete="off"
/> />
<input type="text" name="huisnummer" <!-- House Number Field -->
pattern="/\d+([-\\s]?[a-zA-Z]+)?/" <input
title="Voer een geldig huisnummer in (bijv. 1, 1A, 1-A, 1a)." type="text"
placeholder= "12A" name="huisnummer"
size="5" title="Voer een geldig huisnummer in (bijv. 1, 1A, 1-A)."
pattern="\d+([\- ]?[a-zA-Z]+)?"
placeholder="10"
size="3"
required required
autocomplete="off"
/> />
<button id="postcode_modal_submit" type="submit"><span class="btn_text">OK</span>
<div class="btn_loader">
<svg viewBox="0 0 128 30" xmlns="http://www.w3.org/2000/svg">
<circle style="--i:0" cx="14" cy="15" r="14" />
<circle style="--i:1" cx="64" cy="15" r="14" />
<circle style="--i:2" cx="114" cy="15" r="14" />
</svg>
</div>
</button>
</div> </div>
<button id="postcode_modal_submit" type="submit">verzend</button>
</div>
</form> </form>
<div class="error_message_modal_postcode" id="error_message_modal_postcode" aria-live="polite"></div> <div class="error_message_modal_postcode" id="error_message_modal_postcode" aria-live="polite"></div>
<div class="loader_modal"></div>
</dialog> </dialog>
<?php <?php
} }
@@ -147,64 +202,99 @@ function handle_postcode_modal($data)
$params = $data->get_params(); $params = $data->get_params();
$nonce = $data->get_header("X-WP-Nonce"); $nonce = $data->get_header("X-WP-Nonce");
if (wp_verify_nonce($nonce, "wp_rest")) { // 1. Security
if (!verify_postcode($params["postcode"])) { if (!wp_verify_nonce($nonce, "wp_rest")) {
$resp = [ echo json_encode(["status" => "error", "message" => "nononce"]);
"status" => "error", exit();
"message" => "postcode",
];
echo json_encode($resp);
exit();
}
if (!verify_huisnummer($params["huisnummer"])) {
$resp = [
"status" => "error",
"message" => "huisnummer",
];
echo json_encode($resp);
exit();
}
$result = getStraatnaam($params["postcode"], $params["huisnummer"]);
if (isset($result["error"])) {
$resp = [
"status" => "error",
"message" => $result["error"],
"apirequest" => "openpostcode.nl",
];
echo json_encode($resp);
exit();
}
$_SESSION["postcode"] = $params["postcode"];
$_SESSION["huisnummer"] = $params["huisnummer"];
$_SESSION["straatnaam"] = $result["straatnaam"];
$_SESSION["woonplaats"] = $result["woonplaats"];
$_SESSION["postcode_is_local"] = postcode_in_range(
$params["postcode"],
5000,
5800,
);
$resp = [
"status" => "success",
"message" => "all good",
"straatnaam" => $result["straatnaam"],
"lokaal_trarief" => postcode_in_range(
$params["postcode"],
5000,
5800,
),
];
} else {
$resp = [
"status" => "error",
"message" => "nononce",
];
} }
echo json_encode($resp);
// 2. Basis Validatie
if (!verify_postcode($params["postcode"])) {
echo json_encode(["status" => "error", "message" => "postcode"]);
exit();
}
if (!verify_huisnummer($params["huisnummer"])) {
echo json_encode(["status" => "error", "message" => "huisnummer"]);
exit();
}
// 3. API Call (Ruwe data)
$result = getStraatnaam($params["postcode"], $params["huisnummer"]);
// 4. Validatie & Logic
$hasError = isset($result["error"]);
$errorCode = null;
$errorMessage = null;
$candidates = [];
$straatnaam = null;
$woonplaats = null;
if ($hasError) {
$errorCode = $result["error"]["code"] ?? "UNKNOWN_ERROR";
$errorMessage = $result["error"]["message"] ?? "Onbekende fout";
$candidates = $result["error"]["details"]["candidates"] ?? [];
// SPECIAL CASE: HUISNUMMER_AMBIGUOUS
if ($errorCode === "HUISNUMMER_AMBIGUOUS" && !empty($candidates)) {
$plainMatch = null;
// Zoek naar candidate ZONDER toevoeging
foreach ($candidates as $candidate) {
if (
empty($candidate["huisletter"]) &&
empty($candidate["huisnummertoevoeging"])
) {
$plainMatch = $candidate;
break;
}
}
// Als we een 'platte' match hebben (bijv. 15), dan is het SUCCES
if ($plainMatch) {
$hasError = false; // Negeer de error
$straatnaam = $plainMatch["straat"];
$woonplaats = $plainMatch["woonplaats"];
}
}
} else {
// Normaal succes (geen error in response)
if (!empty($result["results"])) {
$straatnaam = $result["results"][0]["straat"];
$woonplaats = $result["results"][0]["woonplaats"];
} else {
// Edge case: geen error veld, maar ook geen results
$hasError = true;
$errorCode = "NO_RESULTS";
$errorMessage = "Adres niet gevonden";
}
}
// 5. Response sturen
if ($hasError) {
echo json_encode([
"status" => "error",
"code" => $errorCode,
"message" => $errorMessage,
"suggestions" => $result["error"]["details"]["suggestions"] ?? [],
"apirequest" => "openpostcode.nl",
]);
exit();
}
// 6. Succes: Sessie opslaan & response
$_SESSION["postcode"] = $params["postcode"];
$_SESSION["huisnummer"] = $params["huisnummer"];
$_SESSION["straatnaam"] = $straatnaam;
$_SESSION["woonplaats"] = $woonplaats;
$_SESSION["postcode_is_local"] = postcode_in_range($params["postcode"]);
echo json_encode([
"status" => "success",
"message" => "all good",
"straatnaam" => $straatnaam,
"woonplaats" => $woonplaats,
"lokaal_tarief" => postcode_in_range($params["postcode"]),
]);
exit(); exit();
} }
@@ -247,31 +337,45 @@ function getStraatnaam($postcode, $huisnummer)
curl_setopt($ch, CURLOPT_USERAGENT, "PHP/OpenPostcodeClient"); curl_setopt($ch, CURLOPT_USERAGENT, "PHP/OpenPostcodeClient");
$response = curl_exec($ch); $response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_error($ch)) { if (curl_error($ch)) {
curl_close($ch); curl_close($ch);
return ["error" => "cURL error: " . curl_error($ch)]; return [
"error" => ["code" => "CURL_ERROR", "message" => curl_error($ch)],
];
} }
curl_close($ch); curl_close($ch);
// Decodeer als associatieve array (true)
$data = json_decode($response, true); $data = json_decode($response, true);
if (isset($data["error"])) { // Als JSON decode faalt
if (json_last_error() !== JSON_ERROR_NONE) {
return [ return [
"error" => $data["error"]["message"], "error" => [
"code" => $data["error"]["code"], "code" => "JSON_ERROR",
"message" => "Invalid JSON response",
],
]; ];
} }
return [ // Geef de RUWE response terug (inclusief meta, error, results, etc.)
"straatnaam" => $data["results"][0]["straat"], return $data;
"woonplaats" => $data["results"][0]["woonplaats"],
];
} }
function postcode_in_range($postcode, $start, $end) function postcode_in_range($postcode)
{ {
$vals = get_option("local_postcodes_values", "");
$rows = preg_split("/\R/", $vals, -1, PREG_SPLIT_NO_EMPTY);
$pc_arr = [];
foreach ($rows as $row) {
$row = trim($row);
$postcode_range = explode("-", $row);
$pc_arr[] = [(int) $postcode_range[0], (int) $postcode_range[1]];
}
$cleanPostcode = strtoupper(preg_replace("/\s+/", "", $postcode)); $cleanPostcode = strtoupper(preg_replace("/\s+/", "", $postcode));
if (!preg_match('/^\d{4}[A-Z]{2}$/', $cleanPostcode)) { if (!preg_match('/^\d{4}[A-Z]{2}$/', $cleanPostcode)) {
@@ -280,7 +384,12 @@ function postcode_in_range($postcode, $start, $end)
$numberPart = (int) substr($cleanPostcode, 0, 4); $numberPart = (int) substr($cleanPostcode, 0, 4);
return $numberPart >= $start && $numberPart <= $end; foreach ($pc_arr as $pc_to_check) {
if ($numberPart >= $pc_to_check[0] && $numberPart <= $pc_to_check[1]) {
return true;
}
}
return false;
} }
function modify_checkout_with_js() function modify_checkout_with_js()
@@ -338,9 +447,8 @@ function modify_checkout_with_js()
div.setAttribute("class", "postcode-reset") div.setAttribute("class", "postcode-reset")
div.innerHTML = ` div.innerHTML = `
<a href="#" class="reset-postcode-show-comfirm" >Reset postcode.</a> <a href="#" class="reset-postcode-show-comfirm" >Reset postcode.</a>
<span class="bevestiging"> Weet je het zeker? <span class="bevestiging"> Deze handeling leegt ook de winkelwagen. Weet je het zeker?
<a href="#" class="accept">ja</a>/<a href="#" class="decline">nee</a> <a href="#" class="accept">&nbsp;&nbsp;JA&nbsp;</a>/<a href="#" class="decline">&nbsp;nee&nbsp;&nbsp;</a>
(Deze handeling leegt de winkelwagen.)
</span> `; </span> `;
div.style.width = "100%"; div.style.width = "100%";
document.querySelector(".wc-block-components-address-form__city").after(div); document.querySelector(".wc-block-components-address-form__city").after(div);