Merge branch 'latest' of forge.dmz.skyfritt.net:stopplidelsen/innhold into latest
This commit is contained in:
commit
6ee86d01d9
13 changed files with 145 additions and 30 deletions
|
|
@ -0,0 +1,55 @@
|
||||||
|
# Dette skjedde i desember og januar
|
||||||
|
|
||||||
|
## Media
|
||||||
|
|
||||||
|
I løpet av disse månedene har vi ferdigstilt en kronikk og et debattinnlegg.
|
||||||
|
|
||||||
|
Kronikken [«Hvorfor sier Norge nei til medisinsk cannabis»](https://www.dagensmedisin.no/legemidler-smertebehandling/hvorfor-sier-norge-nei-til-medisinsk-cannabis/731257) var på trykk i Dagens Medisin 6. februar 2026. Som medforfattere var representanter fra flere pasientforeninger, sammen med forskningsleder for medisinsk cannabis ved Imperial College; Mikael Södergren. Kronikken har blitt delt mye i sosiale medier, og bidrar til å øke oppmerksomheten om behovet for en prøveordning i Norge.
|
||||||
|
|
||||||
|
Vi har også ferdigstilt et debattinnlegg rundt førerkortreglementet. Denne har foreløpig blitt avslått av de store avisene i Norge, men vi fortsetter å henvende oss til mediehus, helt til vi får et «ja».
|
||||||
|
|
||||||
|
Vi har tipset flere mediehus om aktuelle saker å skrive om, men dette har til nå ikke ført frem. Vi fortsetter dette arbeidet kontinuerlig.
|
||||||
|
|
||||||
|
## Spørreundersøkelse - flertallet i Norge er for medisinsk cannabis
|
||||||
|
|
||||||
|
Sammen med Sapphire Nordics AB, gjennomførte Stopp lidelsen den 5 januar 2026, en landsrepresentativ InFact-spørreundersøkelse blant Norges befolkning. Resultatene vil bli distribuert som pressemelding til mediehus i Norge innen kort tid, så følg med!
|
||||||
|
|
||||||
|
## Underskriftskampanje
|
||||||
|
|
||||||
|
Den 22. januar lanserte Stopp lidelsen en ny underskriftkampanje. Mange av våre følgere har skrevet under på flere kampanjer tidligere, og kan kjenne på følelsen av at det nytter ikke likevel. Men det gjør det. Underskriftskampanjer er en god måte å synliggjøre et behov på, samtidig som det sprer informasjon om initiativet til et stadig større publikum. Tidligere kampanjer har blant annet bidrat til økt oppmerksomhet for saken og har åpnet dører inn hos politikere. Målet med denne kampanjen er å få gjennomført en minikonferanse om medisinsk cannabis og prøveordningen for sentrale Stortingspolitikere.
|
||||||
|
|
||||||
|
Har du ikke signert enda? [Gjør det nå!](https://stopplidelsen.no/underskriftskampanje/medisinsk-cannabis-pa-resept/) Man kan også signere anonymt.
|
||||||
|
|
||||||
|
## Politikere
|
||||||
|
|
||||||
|
Vi har nå snart flertall på Stortinget! FrP, Venstre, Rødt og MDG har alle medisinsk cannabis i sine partiprogrammer. Det betyr at når Ap eller Høyre velger å støtte initiativet, så har vi flertall. Kjenner du noen i disse partiene, enten lokalt eller nasjonalt, vil vi oppfordre deg til å kontakte dem og fortelle dem hvorfor dette er viktig for deg.
|
||||||
|
|
||||||
|
De fleste partier har nå byttet ut mannskapet i helse- og omsorgskomiteen. Vi jobber derfor med å få til møter med de nye representantene. Både i partier som støtter saken og i partier som ikke gjør det enda.
|
||||||
|
|
||||||
|
## Førerkort-saken
|
||||||
|
|
||||||
|
Stopp lidelsen har i ett år nå, forsøkt å komme til bunns i regelverket knyttet til medisinsk cannabis og førerkort. Det viser seg at regelverket *ikke* bygger på faglige vurderinger, men juridiske definisjoner. Sativex og Epidyolex er definert som «legemidler». Derfor kan man kjøre når man bruker disse. De resterende cannabinoid-medikamentene er definert som «narkotika», selv om de i praksis er like produktene som defineres som «legemidler». Bruker man disse produktene blir man automatisk fratatt førerkortet, helt uten faglige vurdering rundt om kjøreevne faktisk er påvirket. De som sitter med ansvaret for dette regelverket hos Helsedirektoratet har ingen planer om å endre dette, til tross for at det er opplagt urimelig.
|
||||||
|
|
||||||
|
Vi har derfor kontaktet Helse- og Omsorgsdepartementet, Sivilombudsmannen, Statsforvalteren, Klageorgan for helsetjenester, Justis- og Beredskapsdepartementet, Samferdselsdepartementet, Pasient- og brukerombudet og Helsetilsynet for å be dem etterse at Helsedirektoratet forholder seg til faglige vurderinger, og ikke bryter lover om diskriminering eller utredningsinstruksen. Alle fraskriver seg ansvaret for dette, og peker på at det er politikerne som må på banen. Derfor er det viktig at en gjennomgang av førerkortreglementet blir en del av prøveordningen i Norge.
|
||||||
|
|
||||||
|
## Pasientforeninger
|
||||||
|
|
||||||
|
Fibromyalgi-forbundet i Norge trykket i desember en artikkel i sitt medlemsblad som omhandlet medisinsk cannabis og prøveordningen Stopp lidelsen jobber med å få på plass. Dette bidrar til å spre informasjon og øke bevissthet blant pasientforeningene.
|
||||||
|
|
||||||
|
De siste månedene har vi ikke klart å komme i dialog med noen flere pasientforeninger enn dem som allerede støtter oss. Vi har kontaktet Kreftforeningen, som sier de ikke har kapasitet til å prioritere dette nå. MS-forbundet har ikke svar på våre henvendelser. Heller ikke Revmatikerforbundet. Er du medlem i noen av disse foreningene, og ønsker muligheten til å teste ut medisinsk cannabis mot dine symptomer, kontakt dem og fortelle dem hvorfor dette er viktig for deg. Når henvendelsene kommer innenfra, er de vanskeligere å ignorere.
|
||||||
|
|
||||||
|
## Fagmiljø
|
||||||
|
|
||||||
|
Stopp lidelsen samarbeider nå direkte med Imperial College London, som er et av de mest prestisjetunge universitetene i verden. De har et eget forskningsteam på medisinsk cannabis, ledet av svenske Mikael Södergren. De ønsker å bistå Norge med å innføre registerstudien, som vil bli bærebjelken i prøveordningen. Som tidligere informert er flere norske forskere interessert i å bidra til dette. Fagforankringen til initiativet er dermed sikret.
|
||||||
|
|
||||||
|
Vi har avholdt møte med leder for pasient- og brukerombudet i Norge. Hun bekrefter at de har fått flere henvendelser knyttet til dette medikamentet. Blant annet historier om pasienter som har gått fra å være i jobb til å bli uføre, da de helt uten faglige begrunnelser plutselig ble fratatt resept på medisinsk cannabis. Nedgangen i utskrevne resepter har vært på nær 30 % siden 2022, da en regelendring gjorde det klart at sykehusene fra da av måtte betale for medisinen.
|
||||||
|
|
||||||
|
Vi har kontaktet Helse- og Omsorgsdepartementet og Helsedirektoratet for å be om møter med dem. Vi venter på tilbakemeldinger og tidspunkt for dette.
|
||||||
|
|
||||||
|
## Sosiale medier (og nyhetsbrev!)
|
||||||
|
|
||||||
|
I denne perioden har vi vært plaget med feil og problemer knyttet til Meta og Facebook. I midten av januar fikk vi en ubegrunnet og feilaktig begrensning i rekkevidden på innleggene våre. Til tross for at vi har brukt flere arbeidsdager på å kontakte Meta og be dem ordne opp, skjer det ikke noe. De sier selv at det ikke er noen feil på siden vår, men at det nå er opp til «systemet» å gjenopprette opprinnelig rekkevidde. De kan ikke gjøre noe mer manuelt, så vi må bare vente på at dette skjer av seg selv. Vi er derfor mer avhengig enn noen gang, av at alle våre følgere hjelper oss med å dele innlegg, og invitere venner og kjente som dere vet sympatisere med saken, til å følge oss.
|
||||||
|
|
||||||
|
Vi har nå 3.350 følgere på Facebook-siden vår, men veksten har vært betraktelig lavere etter at begrensningene ble innført. Vi har innsett at det er for sårbart å kun bruke Meta sine plattformer for å nå ut til alle som interesserer seg for saken, så vi har nå startet et godt gammeldags nyhetsbrev!
|
||||||
|
|
||||||
|
Her vil vi sende ut semi-månedlige oppdateringer og vi håper nyhetsbrevet kan bli en god backup hvis problemene fortsetter hos Meta. Det er uhyggelig at kommunikasjonen med våre følgere kan forsvinne over natten uten god grunn og tilsynelatende uten ankemulighet. Så meld dere på nyhetsbrevet!
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
<?= newsletter_signup('Hold deg oppdatert, også uten Facebook!', 'small') ?>
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
## Tusen, tusen takk!
|
||||||
|
|
||||||
|
Til slutt vil vi takke dere alle for deres bidrag til å få dette til. Takk til dere som deler historien dere, takk til dere som engasjerer dere og sprer brosjyrer, takk til dere som liker og deler informasjon. Sammen kan vi få til endring!
|
||||||
BIN
content/nyheter/2026-02-06-hva-skjedde-i-des-jan/cover.jpg
Normal file
BIN
content/nyheter/2026-02-06-hva-skjedde-i-des-jan/cover.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 163 KiB |
|
|
@ -0,0 +1,7 @@
|
||||||
|
tags = "nyhetsbrev, oppsummering"
|
||||||
|
categories = "Nyhetsbrev"
|
||||||
|
plugins = "newsletter-signup"
|
||||||
|
|
||||||
|
[en]
|
||||||
|
tags = "newsletter, summary"
|
||||||
|
categories = "Newsletters"
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
menu = true
|
menu = true
|
||||||
menu_order = 1
|
menu_order = 1
|
||||||
|
feed = true
|
||||||
|
|
||||||
[en]
|
[en]
|
||||||
title = "News"
|
title = "News"
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ date = "2026-01-15"
|
||||||
plugins = "petition-form"
|
plugins = "petition-form"
|
||||||
thank_you_page = "takk"
|
thank_you_page = "takk"
|
||||||
hide_list = true
|
hide_list = true
|
||||||
|
newsletter_list_uuids = "dfcf73f4-c86a-43a1-9ddb-31309f7392a9,c4849164-d5e7-4aca-9721-423282773fa1"
|
||||||
title = "Underskriftskampanje: Ja til medisinsk cannabis på resept!"
|
title = "Underskriftskampanje: Ja til medisinsk cannabis på resept!"
|
||||||
|
|
||||||
[en]
|
[en]
|
||||||
|
|
|
||||||
|
|
@ -106,4 +106,5 @@ email_placeholder = "Your email address"
|
||||||
notice = "We send about 12 emails per year. You can unsubscribe whenever you want."
|
notice = "We send about 12 emails per year. You can unsubscribe whenever you want."
|
||||||
submit_button = "Subscribe"
|
submit_button = "Subscribe"
|
||||||
success_message = "Check your inbox!"
|
success_message = "Check your inbox!"
|
||||||
|
success_confirm = "Thank you! We've sent you an email. Open the link in the email and confirm to complete your subscription."
|
||||||
error_message = "Something went wrong!"
|
error_message = "Something went wrong!"
|
||||||
|
|
|
||||||
|
|
@ -110,4 +110,5 @@ email_placeholder = "Din e-postadresse"
|
||||||
notice = "Vi sender omtrent 12 e-poster i året. Du kan melde deg av når som helst."
|
notice = "Vi sender omtrent 12 e-poster i året. Du kan melde deg av når som helst."
|
||||||
submit_button = "Meld deg på"
|
submit_button = "Meld deg på"
|
||||||
success_message = "Sjekk innboksen din!"
|
success_message = "Sjekk innboksen din!"
|
||||||
|
success_confirm = "Takk! Vi har sendt en e-post til deg. Åpne lenken i e-posten og bekreft for å fullføre påmeldingen."
|
||||||
error_message = "Noe gikk galt!"
|
error_message = "Noe gikk galt!"
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
return [
|
return [
|
||||||
'enabled' => true,
|
'enabled' => true,
|
||||||
'url' => 'https://newsletter.example.com', // Your Listmonk URL (no trailing slash)
|
'url' => 'https://newsletter.example.com', // Your Listmonk URL (no trailing slash)
|
||||||
'list_uuids' => [
|
'list_uuids' => [ // Default lists (used when no per-form UUIDs are specified)
|
||||||
'UUID1',
|
'UUID1',
|
||||||
'UUID2'
|
'UUID2'
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
* Then in your PHP content file, call the function with your custom text and theme:
|
* Then in your PHP content file, call the function with your custom text and theme:
|
||||||
* <?= newsletter_signup('Your custom intro text here', 'hero') ?>
|
* <?= newsletter_signup('Your custom intro text here', 'hero') ?>
|
||||||
* <?= newsletter_signup('Short text here', 'small') ?>
|
* <?= newsletter_signup('Short text here', 'small') ?>
|
||||||
|
* <?= newsletter_signup('Text', 'small', ['list-uuid-here']) ?>
|
||||||
*
|
*
|
||||||
* Available themes:
|
* Available themes:
|
||||||
* - 'hero': Full-width gradient background section (like CTA sections)
|
* - 'hero': Full-width gradient background section (like CTA sections)
|
||||||
|
|
@ -43,6 +44,7 @@ function newsletterT(string $key): string {
|
||||||
'notice' => 'Vi sender ca. 12 e-poster i året.',
|
'notice' => 'Vi sender ca. 12 e-poster i året.',
|
||||||
'submit_button' => 'Meld deg på',
|
'submit_button' => 'Meld deg på',
|
||||||
'success_message' => 'Sjekk innboksen din!',
|
'success_message' => 'Sjekk innboksen din!',
|
||||||
|
'success_confirm' => 'Takk! Vi har sendt en e-post til deg. Åpne lenken i e-posten og bekreft for å fullføre påmeldingen.',
|
||||||
'error_message' => 'Noe gikk galt!'
|
'error_message' => 'Noe gikk galt!'
|
||||||
];
|
];
|
||||||
return $fallbacks[$key] ?? $key;
|
return $fallbacks[$key] ?? $key;
|
||||||
|
|
@ -56,7 +58,7 @@ function newsletterT(string $key): string {
|
||||||
/**
|
/**
|
||||||
* Subscribe to newsletter via Listmonk public API
|
* Subscribe to newsletter via Listmonk public API
|
||||||
*/
|
*/
|
||||||
function newsletterSubscribe(string $email, string $name): array {
|
function newsletterSubscribe(string $email, string $name, array $listUuids = []): array {
|
||||||
$configPath = dirname(__DIR__, 2) . '/listmonk-config.php';
|
$configPath = dirname(__DIR__, 2) . '/listmonk-config.php';
|
||||||
if (!file_exists($configPath)) {
|
if (!file_exists($configPath)) {
|
||||||
return ['success' => false, 'error' => 'config_missing'];
|
return ['success' => false, 'error' => 'config_missing'];
|
||||||
|
|
@ -70,7 +72,7 @@ function newsletterSubscribe(string $email, string $name): array {
|
||||||
$payload = json_encode([
|
$payload = json_encode([
|
||||||
'email' => $email,
|
'email' => $email,
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
'list_uuids' => $config['list_uuids']
|
'list_uuids' => !empty($listUuids) ? $listUuids : $config['list_uuids']
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$url = $config['url'] . '/api/public/subscription';
|
$url = $config['url'] . '/api/public/subscription';
|
||||||
|
|
@ -121,6 +123,7 @@ function newsletterGetTranslations(): array {
|
||||||
'notice' => htmlspecialchars(newsletterT('notice'), ENT_QUOTES, 'UTF-8'),
|
'notice' => htmlspecialchars(newsletterT('notice'), ENT_QUOTES, 'UTF-8'),
|
||||||
'submitButton' => htmlspecialchars(newsletterT('submit_button'), ENT_QUOTES, 'UTF-8'),
|
'submitButton' => htmlspecialchars(newsletterT('submit_button'), ENT_QUOTES, 'UTF-8'),
|
||||||
'successMessage' => htmlspecialchars(newsletterT('success_message'), ENT_QUOTES, 'UTF-8'),
|
'successMessage' => htmlspecialchars(newsletterT('success_message'), ENT_QUOTES, 'UTF-8'),
|
||||||
|
'successConfirm' => htmlspecialchars(newsletterT('success_confirm'), ENT_QUOTES, 'UTF-8'),
|
||||||
'errorMessage' => htmlspecialchars(newsletterT('error_message'), ENT_QUOTES, 'UTF-8'),
|
'errorMessage' => htmlspecialchars(newsletterT('error_message'), ENT_QUOTES, 'UTF-8'),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
@ -160,14 +163,22 @@ function newsletterGetScript(): string {
|
||||||
.then(function(data) {
|
.then(function(data) {
|
||||||
btn.classList.remove('is-loading');
|
btn.classList.remove('is-loading');
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
btn.classList.add('is-success');
|
var confirmMsg = form.getAttribute('data-success-confirm');
|
||||||
var successTextEl = btn.querySelector('.btn-success-text');
|
if (confirmMsg) {
|
||||||
var successMsg = form.getAttribute('data-success-message');
|
var notice = document.createElement('p');
|
||||||
if (successTextEl && successMsg) successTextEl.textContent = successMsg;
|
notice.className = 'newsletter-confirm';
|
||||||
setTimeout(function() {
|
notice.textContent = confirmMsg;
|
||||||
btn.classList.remove('is-success');
|
form.replaceWith(notice);
|
||||||
btn.disabled = false;
|
} else {
|
||||||
}, 5000);
|
btn.classList.add('is-success');
|
||||||
|
var successTextEl = btn.querySelector('.btn-success-text');
|
||||||
|
var successMsg = form.getAttribute('data-success-message');
|
||||||
|
if (successTextEl && successMsg) successTextEl.textContent = successMsg;
|
||||||
|
setTimeout(function() {
|
||||||
|
btn.classList.remove('is-success');
|
||||||
|
btn.disabled = false;
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
btn.classList.add('is-error');
|
btn.classList.add('is-error');
|
||||||
var errorTextEl = btn.querySelector('.btn-error-text');
|
var errorTextEl = btn.querySelector('.btn-error-text');
|
||||||
|
|
@ -200,12 +211,15 @@ SCRIPT;
|
||||||
/**
|
/**
|
||||||
* Render the "hero" theme - full-width gradient background section
|
* Render the "hero" theme - full-width gradient background section
|
||||||
*/
|
*/
|
||||||
function newsletterRenderHero(string $introText, string $formId): string {
|
function newsletterRenderHero(string $introText, string $formId, array $listUuids = []): string {
|
||||||
$csrfToken = $_SESSION['newsletter_csrf_token'];
|
$csrfToken = $_SESSION['newsletter_csrf_token'];
|
||||||
$nonce = bin2hex(random_bytes(8));
|
$nonce = bin2hex(random_bytes(8));
|
||||||
$escapedIntro = htmlspecialchars($introText, ENT_QUOTES, 'UTF-8');
|
$escapedIntro = htmlspecialchars($introText, ENT_QUOTES, 'UTF-8');
|
||||||
$escapedFormId = htmlspecialchars($formId, ENT_QUOTES, 'UTF-8');
|
$escapedFormId = htmlspecialchars($formId, ENT_QUOTES, 'UTF-8');
|
||||||
$t = newsletterGetTranslations();
|
$t = newsletterGetTranslations();
|
||||||
|
$listUuidsField = !empty($listUuids)
|
||||||
|
? "\n" . ' <input type="hidden" name="newsletter_list_uuids" value="' . htmlspecialchars(implode(',', $listUuids), ENT_QUOTES, 'UTF-8') . '">'
|
||||||
|
: '';
|
||||||
|
|
||||||
$html = <<<HTML
|
$html = <<<HTML
|
||||||
<section class="newsletter-section newsletter-hero escape" id="{$escapedFormId}">
|
<section class="newsletter-section newsletter-hero escape" id="{$escapedFormId}">
|
||||||
|
|
@ -213,7 +227,7 @@ function newsletterRenderHero(string $introText, string $formId): string {
|
||||||
<p class="newsletter-intro">{$escapedIntro}</p>
|
<p class="newsletter-intro">{$escapedIntro}</p>
|
||||||
<form class="newsletter-form" method="post" data-newsletter-form data-success-message="{$t['successMessage']}" data-error-message="{$t['errorMessage']}">
|
<form class="newsletter-form" method="post" data-newsletter-form data-success-message="{$t['successMessage']}" data-error-message="{$t['errorMessage']}">
|
||||||
<input type="hidden" name="newsletter_csrf" value="{$csrfToken}">
|
<input type="hidden" name="newsletter_csrf" value="{$csrfToken}">
|
||||||
<input type="hidden" name="newsletter_form_id" value="{$escapedFormId}">
|
<input type="hidden" name="newsletter_form_id" value="{$escapedFormId}">{$listUuidsField}
|
||||||
<div class="newsletter-fields">
|
<div class="newsletter-fields">
|
||||||
<div class="newsletter-field">
|
<div class="newsletter-field">
|
||||||
<label for="newsletter_name_{$nonce}" class="visually-hidden">{$t['nameLabel']}</label>
|
<label for="newsletter_name_{$nonce}" class="visually-hidden">{$t['nameLabel']}</label>
|
||||||
|
|
@ -242,28 +256,31 @@ HTML;
|
||||||
/**
|
/**
|
||||||
* Render the "small" theme - compact inline notice with border
|
* Render the "small" theme - compact inline notice with border
|
||||||
*/
|
*/
|
||||||
function newsletterRenderSmall(string $introText, string $formId): string {
|
function newsletterRenderSmall(string $introText, string $formId, array $listUuids = []): string {
|
||||||
$csrfToken = $_SESSION['newsletter_csrf_token'];
|
$csrfToken = $_SESSION['newsletter_csrf_token'];
|
||||||
$nonce = bin2hex(random_bytes(8));
|
$nonce = bin2hex(random_bytes(8));
|
||||||
$escapedIntro = htmlspecialchars($introText, ENT_QUOTES, 'UTF-8');
|
$escapedIntro = htmlspecialchars($introText, ENT_QUOTES, 'UTF-8');
|
||||||
$escapedFormId = htmlspecialchars($formId, ENT_QUOTES, 'UTF-8');
|
$escapedFormId = htmlspecialchars($formId, ENT_QUOTES, 'UTF-8');
|
||||||
$t = newsletterGetTranslations();
|
$t = newsletterGetTranslations();
|
||||||
|
$listUuidsField = !empty($listUuids)
|
||||||
|
? "\n" . ' <input type="hidden" name="newsletter_list_uuids" value="' . htmlspecialchars(implode(',', $listUuids), ENT_QUOTES, 'UTF-8') . '">'
|
||||||
|
: '';
|
||||||
|
|
||||||
$html = <<<HTML
|
$html = <<<HTML
|
||||||
<aside class="newsletter-section newsletter-small" id="{$escapedFormId}">
|
<aside class="newsletter-section newsletter-small" id="{$escapedFormId}">
|
||||||
<p class="newsletter-intro">{$escapedIntro}</p>
|
<p class="newsletter-intro">{$escapedIntro}</p>
|
||||||
<form class="newsletter-form" method="post" data-newsletter-form data-success-message="{$t['successMessage']}" data-error-message="{$t['errorMessage']}">
|
<form class="newsletter-form" method="post" data-newsletter-form data-success-message="{$t['successMessage']}" data-success-confirm="{$t['successConfirm']}" data-error-message="{$t['errorMessage']}">
|
||||||
<input type="hidden" name="newsletter_csrf" value="{$csrfToken}">
|
<input type="hidden" name="newsletter_csrf" value="{$csrfToken}">
|
||||||
<input type="hidden" name="newsletter_form_id" value="{$escapedFormId}">
|
<input type="hidden" name="newsletter_form_id" value="{$escapedFormId}">{$listUuidsField}
|
||||||
<div class="newsletter-fields">
|
<div class="newsletter-fields">
|
||||||
<div class="newsletter-field">
|
|
||||||
<label for="newsletter_name_{$nonce}" class="visually-hidden">{$t['nameLabel']}</label>
|
|
||||||
<input type="text" id="newsletter_name_{$nonce}" name="newsletter_name" placeholder="{$t['namePlaceholder']}" required maxlength="100">
|
|
||||||
</div>
|
|
||||||
<div class="newsletter-field">
|
<div class="newsletter-field">
|
||||||
<label for="newsletter_email_{$nonce}" class="visually-hidden">{$t['emailLabel']}</label>
|
<label for="newsletter_email_{$nonce}" class="visually-hidden">{$t['emailLabel']}</label>
|
||||||
<input type="email" id="newsletter_email_{$nonce}" name="newsletter_email" placeholder="{$t['emailPlaceholder']}" required maxlength="100">
|
<input type="email" id="newsletter_email_{$nonce}" name="newsletter_email" placeholder="{$t['emailPlaceholder']}" required maxlength="100">
|
||||||
</div>
|
</div>
|
||||||
|
<div class="newsletter-field">
|
||||||
|
<label for="newsletter_name_{$nonce}" class="visually-hidden">{$t['nameLabel']}</label>
|
||||||
|
<input type="text" id="newsletter_name_{$nonce}" name="newsletter_name" placeholder="{$t['namePlaceholder']}" required maxlength="100">
|
||||||
|
</div>
|
||||||
<button type="submit" name="newsletter_submit" class="button">
|
<button type="submit" name="newsletter_submit" class="button">
|
||||||
<span class="btn-text">{$t['submitButton']}</span>
|
<span class="btn-text">{$t['submitButton']}</span>
|
||||||
<span class="btn-spinner" aria-hidden="true"></span>
|
<span class="btn-spinner" aria-hidden="true"></span>
|
||||||
|
|
@ -436,6 +453,12 @@ function newsletterGetStyles(): string {
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
margin-top:0;
|
margin-top:0;
|
||||||
}
|
}
|
||||||
|
.newsletter-small .newsletter-confirm {
|
||||||
|
margin: 0.3rem 0 0;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
color: var(--color-green);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
.newsletter-small .button.is-success { background-color: var(--color-green); color: white; }
|
.newsletter-small .button.is-success { background-color: var(--color-green); color: white; }
|
||||||
.newsletter-small .button.is-error { background-color: oklch(0.55 0.2 25); color: white; outline: none; }
|
.newsletter-small .button.is-error { background-color: oklch(0.55 0.2 25); color: white; outline: none; }
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -448,19 +471,20 @@ STYLES;
|
||||||
*
|
*
|
||||||
* @param string $introText Custom intro text to display above the form
|
* @param string $introText Custom intro text to display above the form
|
||||||
* @param string $theme Theme to use: 'hero' (default) or 'small'
|
* @param string $theme Theme to use: 'hero' (default) or 'small'
|
||||||
|
* @param array $listUuids Optional Listmonk list UUIDs for this form (default: uses global config)
|
||||||
* @param string $formId Optional form ID for the section (default: 'newsletter')
|
* @param string $formId Optional form ID for the section (default: 'newsletter')
|
||||||
* @return string The complete HTML for the newsletter signup section
|
* @return string The complete HTML for the newsletter signup section
|
||||||
*/
|
*/
|
||||||
function newsletter_signup(string $introText, string $theme = 'hero', string $formId = 'newsletter'): string {
|
function newsletter_signup(string $introText, string $theme = 'hero', array $listUuids = [], string $formId = 'newsletter'): string {
|
||||||
$html = newsletterGetStyles();
|
$html = newsletterGetStyles();
|
||||||
|
|
||||||
switch ($theme) {
|
switch ($theme) {
|
||||||
case 'small':
|
case 'small':
|
||||||
$html .= newsletterRenderSmall($introText, $formId);
|
$html .= newsletterRenderSmall($introText, $formId, $listUuids);
|
||||||
break;
|
break;
|
||||||
case 'hero':
|
case 'hero':
|
||||||
default:
|
default:
|
||||||
$html .= newsletterRenderHero($introText, $formId);
|
$html .= newsletterRenderHero($introText, $formId, $listUuids);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -506,8 +530,20 @@ function newsletterHandleSubmission(): void {
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse per-form list UUIDs (if provided)
|
||||||
|
$listUuids = [];
|
||||||
|
if (!empty($_POST['newsletter_list_uuids'])) {
|
||||||
|
$raw = explode(',', $_POST['newsletter_list_uuids']);
|
||||||
|
foreach ($raw as $uuid) {
|
||||||
|
$uuid = trim($uuid);
|
||||||
|
if (preg_match('/^[0-9a-f\-]{36}$/i', $uuid)) {
|
||||||
|
$listUuids[] = $uuid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Subscribe
|
// Subscribe
|
||||||
$result = newsletterSubscribe($email, $name);
|
$result = newsletterSubscribe($email, $name, $listUuids);
|
||||||
|
|
||||||
if ($result['success']) {
|
if ($result['success']) {
|
||||||
$_SESSION['newsletter_last_submit'] = time();
|
$_SESSION['newsletter_last_submit'] = time();
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ function petitionSanitizeCSV(string $value): string {
|
||||||
* Subscribe email to Listmonk newsletter lists via public API
|
* Subscribe email to Listmonk newsletter lists via public API
|
||||||
* Listmonk handles double opt-in (sends its own confirmation email)
|
* Listmonk handles double opt-in (sends its own confirmation email)
|
||||||
*/
|
*/
|
||||||
function petitionSubscribeToNewsletter(string $email, string $name): bool {
|
function petitionSubscribeToNewsletter(string $email, string $name, array $listUuids = []): bool {
|
||||||
$configPath = dirname(__DIR__, 2) . '/listmonk-config.php';
|
$configPath = dirname(__DIR__, 2) . '/listmonk-config.php';
|
||||||
if (!file_exists($configPath)) {
|
if (!file_exists($configPath)) {
|
||||||
error_log("Listmonk config not found: {$configPath}");
|
error_log("Listmonk config not found: {$configPath}");
|
||||||
|
|
@ -59,13 +59,15 @@ function petitionSubscribeToNewsletter(string $email, string $name): bool {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$uuids = !empty($listUuids) ? $listUuids : $config['list_uuids'];
|
||||||
|
|
||||||
// Log the UUIDs being used
|
// Log the UUIDs being used
|
||||||
error_log("Listmonk attempting subscription with UUIDs: " . implode(', ', $config['list_uuids']));
|
error_log("Listmonk attempting subscription with UUIDs: " . implode(', ', $uuids));
|
||||||
|
|
||||||
$payload = json_encode([
|
$payload = json_encode([
|
||||||
'email' => $email,
|
'email' => $email,
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
'list_uuids' => $config['list_uuids']
|
'list_uuids' => $uuids
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$url = $config['url'] . '/api/public/subscription';
|
$url = $config['url'] . '/api/public/subscription';
|
||||||
|
|
@ -1238,6 +1240,9 @@ function petitionGetPageData(?Context $ctx): ?array {
|
||||||
// Use petition_title if set (for subpages), otherwise fall back to page title
|
// Use petition_title if set (for subpages), otherwise fall back to page title
|
||||||
$petitionTitle = $metadata['petition_title'] ?? $metadata['title'] ?? $petitionId;
|
$petitionTitle = $metadata['petition_title'] ?? $metadata['title'] ?? $petitionId;
|
||||||
$thankYouPage = $metadata['thank_you_page'] ?? 'takk';
|
$thankYouPage = $metadata['thank_you_page'] ?? 'takk';
|
||||||
|
$newsletterListUuids = !empty($metadata['newsletter_list_uuids'])
|
||||||
|
? array_map('trim', explode(',', $metadata['newsletter_list_uuids']))
|
||||||
|
: [];
|
||||||
|
|
||||||
$formErrors = [];
|
$formErrors = [];
|
||||||
$formData = ['firstname' => '', 'surname' => '', 'email' => '', 'region' => '', 'display' => 'semi'];
|
$formData = ['firstname' => '', 'surname' => '', 'email' => '', 'region' => '', 'display' => 'semi'];
|
||||||
|
|
@ -1472,7 +1477,7 @@ function petitionGetPageData(?Context $ctx): ?array {
|
||||||
error_log("Newsletter checkbox: " . ($newsletterOptIn ? 'checked' : 'not checked'));
|
error_log("Newsletter checkbox: " . ($newsletterOptIn ? 'checked' : 'not checked'));
|
||||||
if ($newsletterOptIn) {
|
if ($newsletterOptIn) {
|
||||||
$fullName = $formData['firstname'] . ' ' . $formData['surname'];
|
$fullName = $formData['firstname'] . ' ' . $formData['surname'];
|
||||||
petitionSubscribeToNewsletter($formData['email'], $fullName);
|
petitionSubscribeToNewsletter($formData['email'], $fullName, $newsletterListUuids);
|
||||||
}
|
}
|
||||||
|
|
||||||
$_SESSION['last_petition_submit'] = time();
|
$_SESSION['last_petition_submit'] = time();
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ Then call from PHP content files:
|
||||||
```php
|
```php
|
||||||
<?= newsletter_signup('Your custom intro text here', 'hero') ?>
|
<?= newsletter_signup('Your custom intro text here', 'hero') ?>
|
||||||
<?= newsletter_signup('Short text here', 'small') ?>
|
<?= newsletter_signup('Short text here', 'small') ?>
|
||||||
|
<?= newsletter_signup('Text', 'small', ['list-uuid-1', 'list-uuid-2']) ?>
|
||||||
```
|
```
|
||||||
|
|
||||||
## Themes
|
## Themes
|
||||||
|
|
@ -29,11 +30,12 @@ Then call from PHP content files:
|
||||||
## Function Signature
|
## Function Signature
|
||||||
|
|
||||||
```php
|
```php
|
||||||
newsletter_signup(string $introText, string $theme = 'hero', string $formId = 'newsletter'): string
|
newsletter_signup(string $introText, string $theme = 'hero', array $listUuids = [], string $formId = 'newsletter'): string
|
||||||
```
|
```
|
||||||
|
|
||||||
- `$introText` - Displayed above the form
|
- `$introText` - Displayed above the form
|
||||||
- `$theme` - `'hero'` or `'small'`
|
- `$theme` - `'hero'` or `'small'`
|
||||||
|
- `$listUuids` - Listmonk list UUIDs for this form (empty = use global config)
|
||||||
- `$formId` - HTML id for the section (for anchor links)
|
- `$formId` - HTML id for the section (for anchor links)
|
||||||
|
|
||||||
## How It Works
|
## How It Works
|
||||||
|
|
@ -58,6 +60,8 @@ return [
|
||||||
|
|
||||||
Uses Listmonk's **public** subscription API (`/api/public/subscription`). No authentication needed. Listmonk handles its own double opt-in flow.
|
Uses Listmonk's **public** subscription API (`/api/public/subscription`). No authentication needed. Listmonk handles its own double opt-in flow.
|
||||||
|
|
||||||
|
Per-form list UUIDs can be passed via `$listUuids` parameter. When empty, falls back to the global config's `list_uuids`.
|
||||||
|
|
||||||
## Anti-Spam
|
## Anti-Spam
|
||||||
|
|
||||||
1. **CSRF token** - Separate from petition (`newsletter_csrf_token`)
|
1. **CSRF token** - Separate from petition (`newsletter_csrf_token`)
|
||||||
|
|
@ -71,7 +75,7 @@ All use `newsletter.*` prefix in language files:
|
||||||
- `newsletter.email_label`, `newsletter.email_placeholder`
|
- `newsletter.email_label`, `newsletter.email_placeholder`
|
||||||
- `newsletter.notice` (e.g., "We send about 12 emails per year")
|
- `newsletter.notice` (e.g., "We send about 12 emails per year")
|
||||||
- `newsletter.submit_button`
|
- `newsletter.submit_button`
|
||||||
- `newsletter.success_message`, `newsletter.error_message`
|
- `newsletter.success_message`, `newsletter.success_confirm`, `newsletter.error_message`
|
||||||
|
|
||||||
## Static Resources
|
## Static Resources
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue