Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation since 10/08/2025 in all areas

  1. Today there’s a new version of ProCache (4.0.7) available for download in the ProCache support/upgrades board. Here’s what’s new in this version of ProCache: ProCache has been updated throughout for PHP 8.4 support. Upgraded the SCSS compiler to the latest Leafo SCSSPHP 2.0.1. This version requires PHP 8.2, so ProCache also lets you choose from two older versions if you prefer. Upgraded the LESS compiler to the latest Wikimedia LESS 5.4.1. Past versions can also be selected, including Wikimedia 3.0.0 and Leafo LESS 0.5.0. Upgraded the CSS/JS minifier to the latest available version (1.3.75 latest). Because we had customized the CSS/JS minification quite a bit, the older version (1.0 stable) also remains selectable, just in case there’s anything the older version handles that the new one doesn’t yet. LESS, SCSS and Minifier versions can be selected and changed in the ProCache configuration: Setup > ProCache > JS/CSS. Likewise the ProcessProCache module has a new JS/CSS tab for configuring the settings mentioned above. ProCache now logs LESS/SCSS and Minify status and errors to the JS console (when in debug mode or for a logged-in superuser). ProCache now has a proper API reference page available here: https://processwire.com/api/ref/pro-cache/ Because this is a brand new version with several upgraded libraries, it should be considered beta until it's been out a couple of weeks. Thanks for reading and have a great weekend!
    14 points
  2. 🎉 Now with Subscriptions & Webhooks! (v 1.0.8) In the past months, several frameless clients asked for an easy way to sell their content as subscriptions — without manually managing access. Think of a coach publishing daily audio files and offering a weekly subscription for them. That’s exactly what this update makes possible. 💡 🆕 What’s new in 1.0.8 Stripe Webhook support The module now listens at /stripepaymentlinks/api/stripe-webhook and reacts in real-time to subscription events — cancel, pause, resume, renew, or failed payment. → Access updates instantly. No cron jobs, no manual actions. Subscription handling Each purchase now stores a period_end_map, so the module knows exactly when access should expire. Pause or cancel a subscription → access is blocked immediately. Resume or renew → access restored automatically. Smarter access logic hasActiveAccess() now distinguishes between: recurring products (time-limited access) one-time purchases (lifetime access) Config update Added a field for the Webhook Signing Secret in module settings. ⚙️ Setup (2 min) In Stripe → Developers → Webhooks → Add endpoint https://yourdomain.com/stripepaymentlinks/api/stripe-webhook Choose either “All events” or only the relevant ones: customer.subscription.updated customer.subscription.deleted customer.subscription.paused customer.subscription.resumed invoice.payment_succeeded invoice.payment_failed Copy your Signing Secret into the module config. Done ✅ — test by pausing, resuming or cancelling a subscription and watch access update live. Short, clean, and 100 % ProcessWire-native. Perfect for creators, coaches, and anyone who wants to sell recurring access without maintaining users manually. Cheers, Mike
    5 points
  3. Hi welcome back to paradise 😄 In my case, let's keep it simple. - blank profile for all sites - and generally speaking, no CSS framework. sorry, I realize that's a bit brief... let me elaborate a little, i used bootstrap a lot which once was a good selling point for agencies: “the website will be responsive with bootstrap” boom, sold... i still use it sometimes, but more for tools made up of forms and tables. In that case, i use purge.js and end up with a bootstrap of about 30 kb. today, the trendy selling point would be tailwind, for me, no way!!! 😄 i love css too much (scss for me) and clean HTML without 20 utility classes per tag. In the semantic vs. utility class debate, let's say I'm 90-95% semantic and 5-10% utility (my own little scss "framework" easy to modify and override without !important everywhere). well, I'm not sure if any of this is very useful 🙂 but the idea is simple: processwire offers so much freedom in coding, the least i can do is taking full advantage of it so, starting point... bare pw 🙂 have a nice day
    3 points
  4. With anything new that gets designed (a website, operating system, interface), there's always that initial cringe feeling because it's no longer familiar and comfortable, but after a couple weeks, that goes away. I'm developing a new site and using the new Konkat admin theme, which at first felt totally wrong, but now it feels just right (with 1-2 CSS tweaks, like to make repeaters jump out more). My brain is very picky about adjusting to new fonts... Inter in this case. I like the font a lot, but I just need to adjust to it, get used to the curves. Same thing with new versions of Windows when they change the default font. It's kind of like when Facebook went through a few major design changes at during the 5-10 mark and everyone would complain, then everyone got used to it. Anyway, great work. It's grown on me.
    2 points
  5. [Update] Notify existing buyers and update purchases when products gain gated content (v1.0.10) Hi everyone, we’ve extended StripePaymentLinks based on a customer request. Some products evolve over time and later receive gated content (downloads, course pages, etc.). We now handle that case automatically. What it does: When an existing product is later marked as gated and has a stripe product id the module will: Notify existing users via an access email that new gated content is available for something they already own. Update all relevant purchase entries for those users so the meta object and the purchase_lines reflect the actual delivery page (page ID scope), keeping historical purchases consistent with the current site structure and enabling access control. No manual migration needed; it all happens in the background once the product is flagged as requiring access and the corresponding stripe product id is pasted. Available from now on in v1.0.10. Thanks for the request and feedback that led to this improvement! Cheers, Mike
    2 points
  6. PAGEGRID makes no assumptions about CSS or markup. This means that all CSS frameworks also work with PAGEGRID. I don't work with CSS frameworks myself, so I can't really recommend any (I prefer to use modern vanilla CSS like variables, grid, etc.). But I think it's totally fine to use them. I don't think it will have big impact on performance (depending on how large the CSS file for the framework is), just make sure to load your CSS fraemwork files inside the <head> tag so it's not blocking the rendering of your page. There are basically two approaches to working with PAGEGRID, but these can also be combined: No-code approach: You can create entire websites with PAGEGRID without writing any code yourself. To do this, you can use the “Ready-Made Blocks” and create CSS classes and styles with the Style Panel. This works similarly to Webflow or Figma and is particularly interesting for people who want to customize their website visually (which can be faster then doing it in code). Code only: If you prefer to work in code, you can disable the Style Panel in the PAGEGRID settings (Setup > PAGEGRID). You can then use any CSS framework with PAGEGRID. If you want to use your own CSS code or a framework, you can load it into your page template (take a look at the pagegrid-page.php template as an example). If you want to create your own blocks, you can copy the ready-made blocks from “site/modules/PageGridBlocks/blocks” to your “site/templates/blocks” folder and customize the markup there (e.g., add classes and markup for your CSS framework), or create your blocks from scratch. Learn more here: How do I create my own blocks? or here: how styles work in PAGEGRID. Here is an example of an accordion block using the UIkit framework as an example: <?php namespace ProcessWire; ?> <!-- UIkit accordion block using PAGEGRID's children option --> <ul uk-accordion pg-children="true" pg-children-label="Accordion Items" pg-children-tab="append" pg-autotitle="false" pg-wrapper> <?php foreach ($page->children() as $item) : ?> <li> <a class="uk-accordion-title" href><?= $item->title ?></a> <div class="uk-accordion-content"><?= $pagegrid->renderItem($item) ?></div> </li> <?php endforeach ?> </ul> In this example we use PAGEGRID's children option to render the accordion items (as child pages). Users can then add child items using the backend editor. You could also use repeaters to render the child items for PAGEGRID. The point here is that you can easily add whatever markup is neede for your CSS framework by creating your own custom blocks.
    2 points
  7. Unfortunately, only my PageGridBlocks are available so far. But it would be nice if the community created and shared their own blocks as well. My PageGridBlocks module makes it easy to install and uninstall block templates. It could be a good starting point for others. Another good option would be Bernhard's RockMigrations module to create the block templates. I think it would be best if those blocks would be installable as modules. It would be cool, for example, if someone created blocks for a specific CSS framework. Since I don't work with frameworks myself, this isn't particularly useful for me. However, there seem to be many people in the PW community who work with frameworks. If someone were willing to create and share their own block library, I would be happy to grant that person free access to PAGEGRID.
    2 points
  8. I assume that almost everyone who develops a new website in Processwire works with the Blank profile 🙂 The other existing profiles are more suitable for familiarizing yourself with the system 🙂
    2 points
  9. Strange I know, but you will want to remove the space after -f for this to work
    2 points
  10. Ah, I've found the answer to my question already. See phpMailAdditionalParameters on here: https://processwire.com/api/ref/config/ I assume this will do it in config.php: $config->phpMailAdditionalParameters = '-f bounce@example.com';
    2 points
  11. Tip: In Symfony Console, if you run code and an Exception or WireException occurs, ProcessWire will not be able to log it (and also send an adminEmail). There were cases where I was calling an undefined method on a page object and not knowing about it erroring. I used AI to work through this and ultimately it said I have to basically manage this myself because Symfony Console will catch things if I don't and never hit ProcessWire. Therefore, you may want to do something like this in your handle method: public function handle() { try { nonExistentFunction(); // purposely cause an error } catch (\Throwable $e) { // log the error $this->wire()->log->save('errors', $e->getMessage()); // consider adding additional code here to send an email notification using WireMail // ... // Re-throw so it still displays in console throw $e; } return self::SUCCESS; } I wonder if there's a more efficient way to do this? It took me too long to figure out what was happening in the first place so I haven't spent time optimizing the approach (if it's even possible).
    2 points
  12. Last week I was on a boat, far from any computer, so that’s why there weren’t any updates. This week I’m back in the office and back to work on the core. The focus has been primarily on optimizations and issue fixes (see dev branch commit log). There were also a couple commits related to PHP 8.4 support. Issue fixes and optimizations will likely continue to get more focus as we get closer to our next main/master version.There are also some Pro module updates in the works as well. Have a great weekend!
    2 points
  13. [Update] More flexible access mails (v 1.0.11) Just pushed a small update to the module — a few quality-of-life improvements for access mails. What’s new Custom intro text for access mails – There’s a new field called Access Mail Intro Text (optional) access_mail_addon_txt added to your product templates. Whatever you put in there gets prepended to the access mail’s lead text — great for short intros, personal notes, or product-specific instructions. Hookable mail variables – PLMailService adds the hookable method ___alterAccessMailVars($vars, $mod, $user, $links) You can now easily tweak mail content in your ready.php, for example "first purchase vs. repeat purchase": wire()->addHookAfter('PLMailService::alterAccessMailVars', function(\ProcessWire\HookEvent $event) { $vars = (array) $event->arguments(0); $user = $event->arguments(2); // check if this is the user's first purchase $purchaseCount = ($user->hasField('spl_purchases') && $user->spl_purchases) ? $user->spl_purchases->count() : 0; $isFirstPurchase = ($purchaseCount <= 1); if ($isFirstPurchase) { $vars['preheader'] = 'Welcome! Your new access is ready.'; } else { $vars['preheader'] = 'New access added to your account.'; } // Hand back the modified variables $event->return = $vars; }); As always, feedback, ideas, and real-world use cases are more than welcome — especially if you’ve built custom hooks for your own onboarding or mail flows. Cheers, Mike
    1 point
  14. For anyone trying to use this module in PHP 8, after changing the 2x lines mentioned previously in the main module file I was getting the following error at line 314 of /lib/JSMin-2.1.7.php : ord(): Passing null to parameter #1 ($character) of type string is deprecated The line in the file is: if (ord($c) >= self::ORD_SPACE || $c === "\n" || $c === null) { return $c; } Changing it to his solves the issue: if ($c === null || ord($c) >= self::ORD_SPACE || $c === "\n") {return $c;} @David Karich This is a super module and including the three line changes outlined in this thread would be a really nice thing if possible!
    1 point
  15. Wow, that was quick. Thanks. Will wait until it goes into main and then update through module interface.
    1 point
  16. Hey @gebeer thx for that report! I have pushed your suggested fix on the dev branch of RockFrontend 🙂
    1 point
  17. Only 4 years later I found the cause for this. It’s an Apache behaviour: Some Apache configurations are just fine with spaces in URL paths. Some force a 404 status code, no matter what you try to do in your PHP. Might have something to do with ModSecurity module, but I’m not sure. Better be safe: If you can avoid spaces or %20 in URLs, do it!
    1 point
  18. There are quite a few topics with this issue but maybe this specific answer from @Robin S could help? Also, since it seems to be an issue with AJAX, are you seeing any difference if you toggle on (or off) this option?
    1 point
  19. Many thanks @jploch that really helps to start and to find some more orientation how and with what in Page Grid. I have to to dive in...
    1 point
  20. I just switched to UiKit version 3.24.1 (thanks to RockFrontend to make this easy), and I can reproduce this with the latest version of the Less module... The same errors
    1 point
  21. Thanks @jploch for your further explanation.
    1 point
  22. When learning or testing PW, I would recommend to start with a non blank profile to get an idea and play around with stuff. https://github.com/processwire/site-invoices https://processwire.com/blog/posts/invoices-site-profile https://github.com/processwire/site-default When developing a new project, I start over with the blank profile.
    1 point
  23. Hey folks! We’ve had a bunch of questions about how purchases show up in the backend, so here are the details: By default, every purchase gets its own repeater item on the user’s profile, and every product bought is pulled straight from the checkout session and listed as a line item. The PRODUCT_ID is the mapped page id, and in case the product does not have a product page it shows the Stripe product id prefixed with "0#": The full session always sits in the purchases.meta object. That means you can totally use the ProcessDataTables module to show whatever data you want in a nice table. For example, you could have an customer table with a column that totals up all purchases and pops up a full list of purchases in a table when you click on it: If you're looking to do just that, here’s the column template to make it happen: sales.column.php
    1 point
  24. Many thanks @BrendonKoz for your thoughts and thanks for sharing. For me it is interesting that you also take the blank profile and start from there. I've already placed a PageGrid specific question in the PageGrid subforum.
    1 point
  25. I found it hard to answer your question because I've always started with a blank profile. It gives the most freedom without any constraints, to build a custom site as needed for the project right from the start. No more, no less. I'm not sure which framework might work best with PageGrid, that would likely be a question for the PageGrid-specific forum. The last few sites I've built, I have taken advantage of Bootstrap with the assumption that if anyone were to need to maintain or edit after me, using something that is more ubiquitous would be useful. Beyond that reasoning, we can choose what we would like. Tailwind might be a better (or prettier?) option now, depending on certain factors. If it's a lightweight enough website in terms of elements/components to be used, vanilla CSS without a framework would be awesome.
    1 point
  26. Not sure if it was body text, or quote, or code, so trying all three. Sync report == StripePaymentLinks: Sync (TEST RUN) == Mode: DRY RUN (no writes) Update existing: yes Create missing users: yes From: 2025-10-08 To: - 2025-10-08 13:53 cs_test_a12s... [LINKED] XXXXXXXXXXX => action: UPDATE purchase #1961 2025-10-08 13:02 cs_test_a1DI... [LINKED] XXXXXXXXXXX => action: UPDATE purchase #1964 2025-10-08 09:19 cs_test_a1U9... [LINKED] XXXXXXXXXXX => action: UPDATE purchase #1965 2025-10-08 09:10 cs_test_a1iB... [LINKED] XXXXXXXXXXX => action: UPDATE purchase #1966 Sync report == StripePaymentLinks: Sync (TEST RUN) == Mode: DRY RUN (no writes) Update existing: yes Create missing users: yes From: 2025-10-08 To: - 2025-10-08 13:53 cs_test_a12s... [LINKED] XXXXXXXXXXX => action: UPDATE purchase #1961 2025-10-08 13:02 cs_test_a1DI... [LINKED] XXXXXXXXXXX => action: UPDATE purchase #1964 2025-10-08 09:19 cs_test_a1U9... [LINKED] XXXXXXXXXXX => action: UPDATE purchase #1965 2025-10-08 09:10 cs_test_a1iB... [LINKED] XXXXXXXXXXX => action: UPDATE purchase #1966 I did not get blocked. I'm wondering if it's forum category/subforum specific?
    1 point
  27. Hi @adrian, I found an open issue on github https://github.com/processwire/processwire-issues/issues/2077 realted to the same issue and this was the reply from @ryan at the time: - https://github.com/processwire/processwire-issues/issues/2077#issuecomment-3024317669 I will add a comment to it as soon as possible and thank you for your feedback. Kind regards
    1 point
  28. Hello Jan, I did not find any infos about the possibility of creating multi-step forms inside the form builder docs, but maybe I have overlooked it too.😉 I will take your request as an idea about a new feature for the future and maybe I will integrate the possibility of creating a multi-step form out of the box in an easy way. I have some ideas but I guess this will take a lot of time, so it cannot be realized in the next days.
    1 point
  29. @dab thank you so much for sharing! That actually solved my problem! Because $config->httpHosts = array('domain.com'); didn't work, but $config->httpHosts = array('domain.com', 'www.domain.com'); did!
    1 point
  30. @BigRed I experienced this & in my case I pinned it down to the $config->httpHosts = array('xxxxxxxxxxx'); in config.php not matching the sub-domain I has hosting the new site on. Sorry if I've stated the obvious & e.g. adding www. when it wasn't required.
    1 point
  31. @BFD Calendar Btw, I did try to access your site, and am getting an HTTPS error. So I think whatever your webhost restored might have broken the HTTPS setup. Chances are your webhost can fix that by checking a box somewhere, or if you have cPanel or something you might be able to do it from there. Once I proceeded without HTTPS, then I got ProcessWire's "internal server error" message, which means that ProcessWire found and logged an error to /site/assets/logs/errors.txt. So the source of the issue is likely identified in that log file.
    1 point
  32. Good luck to the Craft team, but to me it looks like they need to reinvent the wheel every now and then. Luckily, we have our own genius, Ryan, who figured that reinventing the wheel is not for everyone. At least not for us ;)
    1 point
  33. I'm no longer maintaining any of my modules. If someone wants to take them over, let me know. It's been a long time since I first asked, but nobody has reached out.
    1 point
  34. Hi, everyone! We recently built a small add-on module for our StripePaymentLinks setup and thought it might be useful to share here. We’ve been working with StripePaymentLinks quite a lot lately, and one thing the clients always wanted was a simple way to get purchases synced into Mailchimp without relying on external paid add-ons. So we built a small ProcessWire module to handle exactly that. The idea is simple: every time a customer makes a purchase via StripePaymentLinks, their details (name, email) plus the purchased products (as tags) get synced directly into Mailchimp. That means you can instantly segment, automate, and follow up with buyers without any manual exports. We built this because we didn’t want to rely on a separate paid Stripe → Mailchimp connector. With this add-on, it’s all handled natively inside ProcessWire — lightweight, minimal, and no extra subscription fees. What it does right now: Hooks into the creation of purchase repeater items (repeater_spl_purchases) Pulls customer name + email from the User created by StripePaymentLinks Extracts product names either from the expanded Stripe session line_items or as fallback from the purchase_lines field Pushes everything to Mailchimp, creating the subscriber if you allow it in the config Assigns the product titles as Mailchimp tags Config is super simple: just drop in your Mailchimp API key, Audience ID, and decide if you want to auto-create subscribers or only update existing ones. We’re keeping this intentionally minimal — one module, no extra steps, no fuss. Install, configure, and you’re done. We’ve been running it in production for some clients and it’s working reliably. If you’re already using StripePaymentLinks, this could save you the cost of external integrations while keeping everything in one place. Get it here: ProcessWire: https://processwire.com/modules/stripe-pl-mailchimp-sync/ Github: https://github.com/frameless-at/StripePlMailchimpSync Happy to hear your feedback or ideas for tweaks. Cheers, Mike from frameless Media
    1 point
  35. AdminQuickTree This module is great for productivity when editing many pages within the admin, as it gives you direct access to the page tree navigation without having to hover the tree icon first. Download from Github Donwload fom Module Directory For non-superusers the page dropdown currently looks like this (if no bookmarks are defined): With this module it looks like this: For super-users or users with all permissions set it looks like this: These changes are achieved width a small js file that triggers the ajax tree navigation after the dom has been loaded. While I have tested it already a bit, I release this for now as a beta version. I hope others find it useful as well.
    1 point
  36. If you have the core ProcessPageClone module installed you can copy a page via Page List: But sometimes I don't want to hunt around through Page List to find the page I want to copy, and instead I have found the page via the admin search and have it open in Page Edit. So I used this hook in /site/ready.php to add a "Clone this page" button to the bottom of the Settings tab. // Add a clone button to the Settings tab of Page Edit if this page is allowed to be cloned $wire->addHookAfter('ProcessPageEdit::buildFormSettings', function(HookEvent $event) { $wrapper = $event->return; $modules = $event->wire()->modules; $page = $event->process->getPage(); /** @var ProcessPageClone $ppc */ $ppc = $modules->get('ProcessPageClone'); if($page && $ppc->hasPermission($page)) { /** @var InputfieldButton $f */ $f = $modules->get('InputfieldButton'); $f->value = 'Clone this page'; $f->href = $event->wire()->config->urls->admin . 'page/clone/?id=' . $page->id; $wrapper->add($f); } }); Maybe somebody else has this need and finds this useful.
    1 point
  37. @Jonathan Lahijani - not sure if this is what you are looking for, but all Tracy's settings can be overridden in config.php like: $config->tracy = [ 'outputMode' => 'development', 'guestForceDevelopmentLocal' => true, 'forceIsLocal' => true, ]; Not sure if those are the exact options you want, but hopefully that approach works for you.
    1 point
  38. This one's been a long time coming, but this week we launched a site for the UK charity INQUEST who provide support for families involved in state related deaths. This was part of their 40th Anniversary and the site showcases significant milestones and events from their archive over the last 40 years. There's an interactive timeline, case studies and oral histories. Even given the difficult subject matter we're really pleased with the result: Behind the scenes, the modules we used were mostly the usual suspects, Tracy Debugger, ProCache etc. Also RockFrontend specifically for the ajax routing (would love that as a separate module @bernhard ) which we used with HMTX in various places. Not sure we really needed to use HTMX on this one but hey, it is very handy. One module we made use of which we hadn't used before was @Richard Jedlička's PDF fieldtype so that we could generate thumbnails of PDF documents. There are a lot of historical documents on the site and having the thumbnails generated automatically was really handy. The site seems to have gone down really well. And we actually had a launch party - it's been years since that happened... https://history.inquest.org.uk/ Oh, and it does very nicely in Lighthouse and gets A+ in Observatory as well 🙂
    1 point
  39. View website: ID Studio Web Agency We have been working on the ID Studio website for quiet some time using ProcessWire extensively for ourseleves and 90% of all our clients. This post will highlight some features we have implmented and also show off some of the hidden functionality. A quick overview is as follows: Custom web design of course 🙂 Front-end uses Canvas and Three.JS The core objective for us is to get users engaged, reviewing the showcase and services, then getting in touch The showcase and blog have alot of content We hide the ID Lab and About section in the footer but there if folks want to dive in and have the time Development features include: We use the form builder system with some custom modifications 3D tools and management Linking 3D elements to HTML elements Repeater matrix for content panels and lots more, best way is to see it on the video overview below ID-Overview.mp4
    1 point
  40. Deprecation warnings say, that it potentially may not be ready for 8.4.2 or 8.4.3 or any other further version. But in my understanding, it is ready for PHP 8.4.0 and 8.4.1. 🙂 If the deprecation warnings bother you, you can disable showing only those messages with a call of PHPs set_error_handler(): /** OWN ERROR HANDLER FOR DEPRECATION NOTES ************************************/ function myLocalDevDeprecationErrorHandler($errno, $errstr, $errfile, $errline) { return true; // true | false = suppress further processing } // preceed the callback function name with the PW namespace, // and define the error types that should passed to the function set_error_handler('ProcessWire\myLocalDevDeprecationErrorHandler', E_DEPRECATED); /** OWN ERROR HANDLER FOR DEPRECATION NOTES ************************************/ I often use this directly in site/config-dev.php, when I want to collect them, but only show them collected at the end of pages in dev local. /** OWN ERROR HANDLER FOR DEPRECATION NOTES ************************************/ function myLocalDevDeprecationErrorHandler($errno, $errstr, $errfile, $errline) { // CHECK / CREATE COLLECTION CONTAINER if (!isset($GLOBALS['DEPRECATION_WARNINGS_BAG'])) { $GLOBALS['DEPRECATION_WARNINGS_BAG'] = []; } if (!is_array($GLOBALS['DEPRECATION_WARNINGS_BAG'])) { $GLOBALS['DEPRECATION_WARNINGS_BAG'] = []; } // DO NOT SHOW THIS KNOWN THIRD PARTY ONES : $hideThisOnes = [ //'FileCompiler', 'Duplicator', 'ProcessCustomUploadNames', ]; foreach($hideThisOnes as $item) { if (preg_match("/{$item}/", $errfile)) return true; } // ADD IT TO THE COLLECTION $GLOBALS['DEPRECATION_WARNINGS_BAG'][] = [$errfile, $errline, $errstr]; return true; // true | false = suppress further processing } // preceed the callback function name with the PW namespace, // and define the error types that should passed to the function set_error_handler('ProcessWire\myLocalDevDeprecationErrorHandler', E_DEPRECATED); /** OWN ERROR HANDLER FOR DEPRECATION NOTES ************************************/
    1 point
  41. THANK YOU! Disabling mutagen did the trick! ddev mutagen reset && ddev config global --performance-mode=none && ddev config --performance-mode=none Now newly uploaded images have the correct permissions: 644. UPDATE: This is the typical mutagen behaviour: https://github.com/mutagen-io/mutagen/issues/23#issuecomment-345277107 But there is a also a way to have mutagen enabled and still get the correct file permissions: Add this line to your DDEV config.yaml: upload_dirs: - site/assets/files
    1 point
  42. I have to implement Google Consent v2 together with PrivacyWire for the first time. I tried to summarize the most imporant things and make a quick example. Hope that helps. Improvements welcome. Basically Google wants you to send the user preferences. This way Google can process at least anonymized data if the user denies permissions (and promises to respect privacy). Luckily PrivacyWire gives us the possibility to define a custom js function in the module configuration, which is executed whenever user preferences change. PrivacyWire stores user preferences in localStorage. From there we can fetch this information when needed. So we have to: 1. Integrate Google Tag Manger without modifying the script tag. 2. Set Consent v2 defaults (by default deny every permission): <!-- GOOGLE CONSENT V2 --> <script async src="https://www.googletagmanager.com/gtag/js?id=GTM-ID-HERE"></script> <script> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('consent', 'default', { 'ad_storage': 'denied', 'analytics_storage': 'denied', 'ad_user_data': 'denied', 'ad_personalization': 'denied' }); gtag('js', new Date()); gtag('config', 'GTM-ID-HERE'); </script> <!-- End GOOGLE CONSENT V2 --> 3. Use a function called by PrivacyWire, when user changes preferences. Fetch user preferences from localStorage and send them to Google: function updateConsentFromPrivacyWire() { console.log('update consent from privacy wire...'); const privacyWireData = localStorage.getItem('privacywire'); if (privacyWireData) { try { const consentData = JSON.parse(privacyWireData); const consentPreferences = { // Set Google params based on user preferences 'ad_storage': consentData.cookieGroups.marketing ? 'granted' : 'denied', 'analytics_storage': consentData.cookieGroups.statistics ? 'granted' : 'denied', 'ad_user_data': consentData.cookieGroups.marketing ? 'granted' : 'denied', 'ad_personalization': consentData.cookieGroups.marketing ? 'granted' : 'denied' }; // Update google consent gtag('consent', 'update', consentPreferences); console.log(consentPreferences); } catch (e) { console.error('Error parsing PrivacyWire-Data:', e); } } else { console.warn('No PrivacyWire-Data found in localStorage'); } } // Update consent at pageload document.addEventListener('DOMContentLoaded', updateConsentFromPrivacyWire); 5. This is what the parameters control: ad_storage: Controls whether ad-related cookies and identifiers are stored (e.g., for remarketing). analytics_storage: Controls whether analytics-related cookies are stored (e.g., for Google Analytics tracking). ad_user_data: Controls the collection and use of user data for advertising purposes. ad_personalization: Controls the use of data to personalize ads based on user behavior and preferences. 4. Configure the function name (here updateConsentFromPrivacyWire) in PrivacyWire module settings.
    1 point
  43. Do not use global unless you really know what you are doing. Read this: https://stackoverflow.com/questions/16959576/reference-what-is-variable-scope-which-variables-are-accessible-from-where-and $this->wire() is another option to assign global vars, especially for more complex stuff ... like class instances. /** * Get an API variable, create an API variable, or inject dependencies. * * * @param string|object $name Name of API variable to retrieve, set, or omit to retrieve the master ProcessWire object. * @param null|mixed $value Value to set if using this as a setter, otherwise omit. * @param bool $lock When using as a setter, specify true if you want to lock the value from future changes (default=false). * @return object|string|mixed * @throws WireException * * */ public function wire($name = '', $value = null, $lock = false) {}
    1 point
  44. Hay Ryan.. I can confirm that it is a issue with PHP 5.3/4 and 5.2 Keep it up.. Im still in love...
    1 point
×
×
  • Create New...