Leaderboard
Popular Content
Showing content with the highest reputation on 07/21/2022 in all areas
-
Following recent discussion about the Latte templating language, I figured I'd give it a try too and put together a Latte renderer for Wireframe: GitHub repository at https://github.com/wireframe-framework/WireframeRendererLatte Composer installation: composer require wireframe-framework/wireframe-renderer-latte In case anyone wants to try this, it would be interesting to hear your thoughts. I'm honestly not sure if I'll be using it much myself, and I built the module without any real Latte experience under my belt, so it's possible that it does things in surprising ways. Let me know if you run into any issues ? Syntax wise, Latte doesn't differ much from regular PHP templates — you just write your PHP code within {curly brackets}, and it gets automatically escaped (with what they call context-aware escaping). They have this thing called n:attributes though, which is actually quite nice shortcut, especially if you happen to dislike if..else and foreach: <ul n:if="$page->numChildren(true)" class="menu"> <li n:foreach="$page->children as $child"> <a n:tag-if="!$child->hide_from_menu" href="{$child->url}"> {$item->title} </a> </li> </ul> You can read more about Latte from https://latte.nette.org/en/. For more details about Wireframe renderers and how they are enabled and used, check out https://wireframe-framework.com/docs/view/renderers/.4 points
-
Cross-posting in case any Wireframe user wants to give Latte a try: there's a renderer for it now. Somewhat experimental, since I have a rather miniscule understanding of Latte myself ? Slightly annoying marketing shenanigans aside (I didn't know how to do a single thing in Latte without reading the docs, "Latte is the only system with an effective defense, thanks to context-sensitive escaping" is a silly thing to claim, etc.) Latte does look quite nice. I dig the n:attributes in particular, they remind me a lot of the AngularJS (v1) syntax. Apart from that, Latte seems largely the same as other engines/languages I've used (e.g. Twig, Blade, and Dust). Admittedly I've just scratched the surface, so there's likely a lot more there ? I'm not sure yet whether it's a good thing or not that Latte syntax is so close to plain PHP, just with auto-escaping enabled and <?php ?> replaced with curly brackets. Among other things a) the PHP syntax isn't necessarily the easiest to grasp or nicest to look at, especially for non-developers (though this is admittedly highly opinionated), and b) there's a slight fear in the back of my head that this actually makes it extra tempting for developers to put unnecessarily complex code within their views. So far among the templating languages I've used Blade has been my personal favourite. It's easy to grasp, familiar to PHP users but also for everyone who's ever used another templating language (like Twig), has some very handy shortcuts available (particularly when it comes to loops), the syntax looks nice and clean (in my opinion), and components in particular are just brilliant in terms of both implementation and use. But enough advertising ?3 points
-
I just wanted to mention that I hope that our new editor will still be a rich text editor and not a page builder (like the mentioned "article" editor) - imho we should not mix those two! I've done a lot of work and research in that regard over the last two years or so and I'm now very happy with my repeater based content builder. When I started I also looked at editor.js as the interface looked neat. But I couldn't even manage to build a single custom content element with it. It's an editor for JS artisans and not for PHP devs like me (us?). A repeater based content builder has the huge benefit that we can simply use all the existing fields that PW provides. If at some point someone created a new field that would most likely just work within a repeater. Having a new editor interface with a totally new storage concept would mean we'd need to build all those block's for the editor and we could not use them outside of it. What about Multi-Language? The example above shows a nice page builder, but I wonder how multi-language would work with such a field? In a repeater-based setup we can just install LanguageSupport and make those fields translatable. PS: Using a matrix based approach makes CKEditor fields usually super simple! Like this one where only bold text and links are allowed:3 points
-
There is a lot going on here. You mentioned that visitors (guests or logged-in users?) will be able to subscribe to multiple events at once, but you will likely only want to verify the email once. AFAIK the only way to verify emails is to actually send a secret to the address and have the recipient send it back. So I would do a poor man’s solution somewhat like this: Create one page per recipient that stores the address and a secret token (ProcessWire can generate one for you like this: (new Password())->randomBase64String()) When the user has entered their address and you have created the page, send them a link like https://example.com/verify?mail=myemail@example.com&mytoken=xyIu6yehxXfTelYpqcOdv8 When that link requested, find the recipient and consider them verified if the token matches (i.e. set a checkbox or just delete the token and consider everyone without one verified) Store event subscriptions as multiple page references either on the recipient or on the event, whatever As long as these transactional mails don’t go overboard you should be fine. If you don’t need any personalisation, you might actually send the event reminders as a single email per event, just dumping everyone into BCC. If you’re thinking of growing the business, you will want to go with a dedicated solution such as https://de.sendinblue.com/preise/ (a German company formerly known as Newsletter2Go, should be fine GDPR-wise). Mass mailing is serious business. You don’t want to get blocked by Gmail or something, so above some threshold it’ll be worth shelling out for a service whose business is making sure emails go through. You mentioned you’re on shared hosting. Do you have cron jobs at all? Some shared hosting providers offer something like “cron jobs lite”, where you get a configuration form and the only action you can perform is an HTTP request. In that case you just expose some URL from your site that will send emails upon request.2 points
-
2 points
-
The Twig renderer for Wireframe has been around a while already, it just didn't have a support forum thread of its own, so here we go. This optional add-on module lets one author layouts, views, partials, and component views using Twig instead of PHP. By design you can have view files that are either Twig or PHP — with this module enabled Wireframe will initially look for a .twig file, but if that doesn't exist, it'll fall back to a regular .php file instead. GitHub repository: https://github.com/wireframe-framework/WireframeRendererTwig Composer installation: composer require wireframe-framework/wireframe-twig-renderer Here's a small sample of what Twig looks like: {% if page.numChildren(true) %} <ul class="menu"> {% for child in page.children %} <li> <a href="{{ child.url }}"> {{ child.title }} </a> </li> {% endfor %} </ul> {% endif %} You can read more about Twig from https://twig.symfony.com/doc/. Twig syntax in specific is covered in Twig for Template Designers. For more details about Wireframe renderers and how they are enabled and used, check out https://wireframe-framework.com/docs/view/renderers/.2 points
-
I updated the module to 1.0.4 and added an option to specify the Return-Path in the email header. This option is blank by default.2 points
-
Just a little rant: Please don't turn our textarea/RTF-fields into something like Gutenberg or similar. As a module, ok. But please... not as the default option. I'm not that deep into all the details about those RTF-Editor tools/scripts but what's so bad about staying with CKEditor 4.x for a while as it's stable and mature enough. Never had any issues with it.2 points
-
Article looks great, but their licensing model is indeed problematic. Folks at Bolt likely got a custom license (or perhaps paid OEM license) to use it, but on what terms is hard to say — I couldn't find specifics about their licensing terms. Only thing they do say is that it's available for use "in Bolt itself", which is a bit vague. It's up to Ryan whether he finds this interesting enough to contact Imperavi and query about license ? Either way, I wouldn't count CKEditor 5 out of the race quite yet. To me personally it looks UI/UX wise like a solid upgrade over CKEditor 4. I do remember that it seemed potentially "too different", and there were some relatively basic features (which I can't for the life of me remember anymore) from v4 that the devs originally said would be very difficult or nearly impossible to implement in v5, but that was a long time ago so perhaps things have changed. First of all, CKEditor 4 being EOL'd in 2023 is a huge reason to move on. There's no guarantee of updates after the EOL date, which includes potential security updates. ProcessWire is relatively safe since most of the time CKEditor is used by trusted users, but there are cases where that isn't necessarily true. And even if it was, there could still be vulnerabilities that third parties can abuse. In my opinion it's painfully obvious that we must drop CKEditor 4 support from the core at some point in the future. If some prefer to keep using EOL'd software (which I would personally recommend against), there's always the possibility of stripping it from the core and converting into a separate, possibly community-supported module. For me personally CKEditor 5 seems like a logical next step, but admittedly I've not used it enough to know if it's really going to be feasible, let alone how much work it will require. It's a good idea to check out what else there is, but CKEditor has quite a few things going for it as well: plenty of features, solid UI/UX, longevity of the project, active community, being open source with no costs or limiting licensing rules, etc. As for ease of use, I absolutely agree that this is vital. And in this regard CKEditor 5 feels like a big step up — if anything it feels less confusing and more streamlined than earlier versions. I would not expect my/our clients to have any trouble with it. Give it a try and see for yourself, and do keep in mind that CKEditor 5 is configurable: features you don't need can be disabled ? Just my two cents. 100%.2 points
-
1 point
-
Yes. Good ideas, thanks. This is not future proof. Similar to things like products and products titles, rates can get deleted, renamed, etc. Hence, for orders we want to 'freeze' the state of things when the order was made.1 point
-
I forgot to ask: How many mails will be sent? Tens? Hundreds? Thousands? Sure a cronjob would be the way to go. LazyCron can be an alternative on a shared host, but might not be the best solution ?1 point
-
Why do you think that? This is just using PW selectors and maybe comparing dates ? Also sending mails is not complicated (using WireMail for example as you already mentioned). The complicated parts are IMHO: subscription management (what happens if ... and what if ... and so on ...) mail deliverability (not too hard but you need to be careful) mail layouts (responsive, different mail clients etc) ProMailer can help for subscription management I guess and for deliverability the easiest solution is to use some transactional mail provider. For layout you can have a look at something like MJML...1 point
-
<div class="..."> <a n:foreach="$languages as $lang" href="{$page->localUrl($lang)}" class="..." > {$lang->title} </a> </div> Useful example and good jump start for me to try latte thanks for posting1 point
-
Probably with a SOAP call to the EU VAT Information Exchange System (VIES). That would already make sense. Thanks a lot!1 point
-
@bernhard That looks super cool. I'm now working for a studio that uses Craft CMS and although PW still feels way better in most aspects, in this one Craft has a very good solution. More or less like an automatic RockMigrations. As you create fields, sections (templates) and whatnot, Craft generates and updates a bunch of yaml files that contain all configurations. If these files are updated, i.e. you pull someone else's changes from the repo, run a command and it applies all the changes for you. Awesome solution.1 point
-
Need a language switcher? <div class="..."> <a n:foreach="$languages as $lang" href="{$page->localUrl($lang)}" class="..." > {$lang->title} </a> </div>1 point
-
@kongondo Thanks ! Maybe saving the name of the shipping method and the delay (the between xx and xx days), or just an id that can help retrieving those infos. On the same topic, I hooked the getOrderCustomerSummary function to display the shipping address on the order page and not just the email and country. I made a biig kind of triple shop completely from scratch spanning a looots of years (you don't want to look at the code, I don't want to look at the code XD), but one thing I learned is : save everything and add description fields everywheeeere to add explanations for the clients for about anything in the shop. ?1 point
-
You know what they say about opinions ? Seriously though, I get your point, and I'm a big fan of keeping code (or rather unnecessarily complex logic) out of the view layer myself. That being said, I don't mind a few foreach and if/else blocks here and there, as long as it doesn't get out of hand. Looking at my example above, that first "if" seems to be pointless; for a simple use case like this, here's all we really need: <?php foreach ($footer_scripts as $script): ?> <script src="<?= $buster->url($config->urls->resources . $script) ?>"></script> <?php endforeach; ?> That's three lines. There's also no cache busting required here, since we're using $buster (and there are also non-commercial alternatives, like Pete's Minify module or AIOM) ? This is absolutely true. FilenameArray is a rather limited/limiting tool, best suited for relatively simple use cases. In the example above I used that because it was enough for that particular use case. And, to be honest, it's been enough for most use cases for me — but if something more nuanced is needed, then another data type (or another approach altogether) is likely going to be a better choice. From my point of view the first one here is not a big issue (I don't usually have that many scripts, so this can be handled with a couple of if-else blocks at tops, or a variation of the technique mentioned above, or Wireframe's placeholders) while other two I prefer to handle via build tools. This is not to say that these are not real concerns, mind you — just that they are (mostly) non-issues for me in my workflow ?♂️? Anywho, it'll be interesting to check out RockFrontend once it's available. It sounds like an interesting tool ?1 point
-
I guess you are adding the hook in init(). If you add it at ready() it will work. Init() is too early for the system to know anything about the user or the language... I think my explanation above is wrong - it works because of the way my language switcher for tracy works! I've updated the code which works for me: $wire->addHookAfter("/foo", function($event) { // first we get a fresh copy of the current user $user = $this->wire->pages->getFresh($this->wire->user->id); $lang = $user->language; // then we set the correct language to retrieve values $this->wire->user->language = $lang; // output to check results $title = $this->wire->pages->get(1)->title; return "user name = $user->name, language = $lang, homepate title = $title"; }); So you are right, the hook does not seem to have the correct language of the user by default. Which it should I guess. Maybe open an issue on github?1 point
-
This is a great catch @Sonia Margollé! Currently we don't save this anywhere which is a design flaw on my part. I'll have a think but it looks like I'll have to add a field in the order table. I'll get back to you tomorrow, or latest Friday. Thanks.1 point
-
Hi @Robin S, I had an issue and just found a solution, but I can't explain why it's behaving this way: Given the setup mentionned in my previous post, when saving after selecting images it worked fine. But then if I saved the page without changes it cleared my selection. Trying to debug I checked if it was an issue with my image, my loops, had a look at your code but in the end what mattered was the artwork's id used as the option's value. Apparently if the option's key resolved to an int it got cleared ("1" was working though and "0" as well but then no image was shown in the selected part, weird). My solution was to add a prefix (e.g. "id1024") and then it worked as expected. I have to point out this is only happening with the SelectImages inputfield type, if I use AsmSelect, then it works as expected. Do you have an idea why it's behaving this way ? Thanks !1 point
-
In case anybody else comes upon a similar problem (calling wiremail in every other instance worked just fine) removing this from the module file (line 62) actually did the trick: $mailer->param('-f '.$data['notification_email']);1 point
-
1 point
-
Is it really necessary to have CKEditor 5 in Processwire ? Is CKEditor 4.x not more than safe and powerful enough already ? CKEditor 5 will not make more productive neither make a website client more happy. It will only make things more bloated. At least leave the option with the user and client to choose CKEditor 4.x or another simple Editor for the client. Most clients are non-tech people occupied with business for whom something like CKEditor 4.x is already complicated. They will never use all its options anyway. All they need is to change some prices, text and pictures. So please leave the option for the client to choose a simple Editor. What made Processwire stand out from the crowd was its focus on a versatile and powerful api with a core free from bloat. How much of that is still true ?1 point
-
Just a searchable note here in case s.o. else runs into the same problem ? You suddenly cannot log in any more with TFA/2FA (Two Factor Authentification)? After the step two (inserting the 2FA code) the server responds with an ERROR 500? There is no corresponding entry in the server logs? Check this: Open your site files with FTP, go to /site/assets/logs/ and look into the file exceptions.txt If you find an entry there, like so: ... Invalid base32 string (in /site/modules/TfaTotp/TwoFactorAuth/lib/TwoFactorAuth.php line 190) This indicates that the 2FA code got messed up. Two ways to fix this: Via FTP, move TfaTotp out of /modules/ Login and go to User/Profile While the login session is active, via FTP, move TfaTotp back to /modules/ Disable TfaTotp - and then save your profile page Re-enable TfaTotp - and then save your profile page again. …or (tip from @adrianj): Create a new superuser via the API and login via that and then disable and re-enable 2FA for the affected user via Access > Users. --- More in depth info from @ryan at Github: 2FA login error 500.1 point
-
It's not a bug as Ryan just explained in the issue:1 point
-
I'm wondering if it's time we considered other editors? Maybe this though is premature...1 point
-
Some introduction... This module is experimental and there are probably bugs - so treat it as alpha and don't use it on production websites. I started on this module because there have been quite a few requests for "fake" or "invisible" parent functionality and I was curious about what is possible given that the idea sort of goes against the PW page structure philosophy. I'm not sure that I will use this module myself, just because I don't really see a long list of pages under Home (or anywhere else) as untidy or cluttered. I would tend to use Lister Pro when I want to see some set of pages as a self-contained group. But maybe others will find it useful. At the moment this module does not manipulate the breadcrumb menu in admin. So when you are editing or adding a virtual child the real location of the page is revealed in the breadcrumb menu. That's because I don't see the point in trying to comprehensively fool users about the real location of pages - I think it's better that they have some understanding of where the pages really are. But I'm open to feedback on this and it is possible to alter the breadcrumbs if there's a consensus that it would be better that way. Virtual Parents Allows pages in Page List to be grouped under a virtual parent. This module manipulates the page list and the flyout tree menu to make it appear that one or more pages are children of another page when in fact they are siblings of that page. Why would you do that instead of actually putting the child pages inside the parent? Mainly if you want to avoid adding the parent name as part of the URL. For example, suppose you have some pages that you want to be accessed at URLs directly off the site root: yourdomain.com/some-page/. But in the page list you want them to be appear under a parent for the sake of visual grouping or to declutter the page list under Home. Example of how the page structure actually is Example of how the page structure appears with Virtual Parents activated How it works This module identifies the virtual parents and virtual children by way of template. You define a single template as the virtual parent template and one or more templates as the virtual child templates. Anytime pages using the child template(s) are siblings of a page using the parent template, those child pages will appear as children of the virtual parent in the page list and tree menu. You will want to create dedicated templates for identifying virtual parents and virtual children and reserve them just for use with this module. Features Adjusts both page list and tree flyout menu to show the virtual parent/child structure, including the count of child pages. Works everywhere page list is used: Page List Select / Page List Select Multiple (and therefore CKEditor link dialog). Intercepts the "Add page" process in admin, so that when an attempt is made to add a child to a virtual parent, the child is added where it belongs (the next level up) and the template selection is limited to virtual child templates. Intercepts moving and sorting pages in the page list, to ensure only virtual children may be moved/sorted under the virtual parent. Superusers have a toggle switch at the bottom of the page list to easily disable/enable Virtual Parents in order to get a view of what the real page structure is. Usage Install the Virtual Parents module. In the module config, enter pairs of parent/child template names in the form virtual_parent_template=virtual_child_template. If needed you can specify multiple pipe-separated child templates: virtual_parent_template=child_template_1|child_template_2. One pair of template names per line. There is a checkbox in the module config to toggle Virtual Pages on and off, but it's more convenient to use this from the page list. Notes It's important to keep in mind the real location of the virtual child pages. This module is only concerned with adjusting the appearance of page list and tree menu for the sake of visual grouping and tidiness. In all other respects the virtual children are not children of the virtual parent at all. It's recommended to select an icon for the virtual parent template (Advanced tab) so virtual parents are marked out in the page list as being different from normal parent pages. Do not place real children under a virtual parent. There is some protection against this when moving pages in the page list, but when it comes to changing a page's parent via the Settings tab the only protection is common sense. https://github.com/Toutouwai/VirtualParents1 point
-
You have to perform the check for the template name inside your hook function. $this->page or wire('page') returns whatever page in which the module code is executed (admin page editor, custom page with the code...). Pages::save on the other hand is called with the page object being saved, which is what you're looking for. public function init() { $this->pages->addHookAfter('Pages::save', $this, 'syncMobileDE'); } protected function syncMobileDE(HookEvent $event) { $page = $event->arguments(0); if($page->template->name == 'TemplateName') { // Run your code } }1 point
-
EDIT: This project has been put on ice - I don't work with ProcessWire in my day job anymore, so this project is looking for a new maintainer. Knowing that, you can decide whether it's worthwhile reading through 7 pages of posts EDIT: The source code has been dumped on GitHub - feel free to fork and have at it. There's one thing about ProcessWire that pains me, and I've brought this up before - it's the same problem I have with e.g. Drupal... Because the meta-data (Configuration, Fields and Templates) is stored inside the database, once you have a live site and a development site, moving changes from the development site to the live site is, well, not really possible. Repeating all the changes by hand on the live site is simply not an option I'm willing to consider. Telling the client to back off the site and give me a day or two to make the changes, and then moving the whole database after making and testing the changes on a development site, is really a pretty poor solution, too. I had heard some talk about a module in development, which would make it possible to import/export Fields and Templates? It sounds like that would mostly solve the problem. Ideally though, I'd really like a solution that records changes to Fields and Templates, and allows me to continuously integrate changes from one server to another. So I started hacking out a module, but I'm not sure if it's going to work at all, if it's even a good idea, or if it's worth the effort. I'm looking for feedback on the idea as such, more than the code I wrote, which isn't real pretty right now. Anyway, have a look: https://gist.github.com/b7269bb7bd814ecf54fb If you install this, create a "data" folder under the module's folder - migration files will be written there. Basic overview of the idea and code: The module hooks into Fields::load() and takes a "snapshot" of the current Field properties and settings on start-up. It also hooks into ProcessField::fieldSave() and when a field is saved, it compares it's properties and settings to the snapshot it took at startup - if changes were made, it writes the previous name and updated properties into a file. The same thing is not implemented for Templates yet, but would be. The migration-files are named like "YYYY-mm-dd-HH-mm-ss.json", so that they can be sorted and applied in order. Each file contains a JSON representation of a method-call - currently only updateField() which would repeat a previous set of changes and apply them to another installation of a site. (not implemented) So basically, the module would record changes to Fields and Templates, and would be able to repeat them. How those files get from one system to another is less of a concern - would be cool if servers could exchange migrations semi-automatically, using some kind of private key system, but initially, simply copying the files by hand would suffice. I'm more concerned about the whole idea of capturing changes and repeating them this way. Any thoughts? Is this approach wrong for some reason? Would this even work?1 point