Leaderboard
Popular Content
Showing content with the highest reputation on 08/13/2024 in all areas
-
Just a thought for future in case performance really becomes an issue for someone: it's possible to add a generated + stored column to a MySQL table that feeds itself from a dedicated value in a JSON column, and this column can of course have a fulltext index. A hook on PageFinder::getQueryUnknownField could then "redirect" the query to the generated column. Would only work on single valued fields, of course. For anybody interested in creating such a generated field from a JSON field, here's a blog entry that explains it better than I could.5 points
-
The main benefit of this thread is that I finally have a space to post in PW forums. I have this internal desire of being super active here, but as a forever-noob developer I can't participate in others people's topics. So, this post suits me hahaha. I have a secret: The infinite site hosting scheme. The only word in marketing that's more 'scheme' than 'scheme' is infinite. And when they combine infinite and secret, you can know you've officially landed in the Promised Land.3 points
-
Padloper 010 Padloper 010 (aka Padloper 2 version 010) is ready for download. Requirements PHP>= 8.2.0 ProcessWire>=3.0.200 Maintenance Padloper 010 is mainly a maintenance release: Fixes money rounding bugs found in Padloper 009 (and earlier). Adds the Money for PHP Library to handle monetary values in an easy and powerful way. Fixes money math issues when prices include tax. For the sake of internal maintenance, reorganises files and directory structure. Money Matters Specifically regarding 'prices include tax', and I will be adding this to the docs, it is important that you display your prices in the frontend in a way that doesn't confuse consumers. This is not unique to Padloper but a general e-commerce issue. This means making careful decisions around displaying unit vs total prices as well as whether to include notes about potential rounding pence/cents issues in your shop's policy documents. Due to rounding issues (pence, cents, etc) when it comes to money, especially if quantity is more than 1, the math might look off. I.e., (item * quantity) + tax IS NOT NECESSARILY EQUAL TO (item + tax) * quantity. See this article for a thorough discussion. Breaking Changes There are a few unavoidable breaking changes due to code rationalisation. API Some API had to be changed for maintenance and usage simplicity reasons. This affects checkout, cart and discounts. For instance: <?php namespace ProcessWire; # OLD API $checkout = $padloper->checkout; $response = $checkout->render($options); # NEW API // $response = $padloper->render($options);// this will be deprecated in a future release $response = $padloper->renderCheckout($options); ########## # OLD API $cartRender = $padloper->cartRender; $content = $cartRender->editCart(); # NEW API $content = $padloper->editCart(); ########## # OLD API $cartRender = $padloper->cartRender; $content = $cartRender->viewCart(); # NEW API $content = $padloper->viewCart(); HOOKS Backend hooks rename: // OLD NAMING FORMAT PadloperProcessRenderXXX e.g. PadloperProcessRenderOrders // NEW NAMING FORMAT PadloperAdminRenderXXX e.g. PadloperAdminRenderOrders Other hooks rename: // OLD NAMING FORMAT PadloperXXX::methodName e.g. PadloperUtilities::getProductWeight, PadloperCart::getProductPrice // NEW NAMING FORMAT Padloper::methodName e.g. Padloper::getProductWeight, Padloper::getProductPrice Upgrading Replace all files (not overwrite!). This is because some files have been deprecated, renamed or moved. Safest way to upgrade is to get rid of all existing Padloper files and folders under /site/modules/Padloper/ and then copy over the new 010 files and folders then do a module refresh. New Features The two new features are: $padloper->money(); More information will be added to docs. Bank Name as a property (bankAccountName) in the return value of $padloper->getShopBankDetails();. See request in this topic. Next Steps As mentioned in Padloper 009 topic, the focus now will be the documentation. Any questions or issues, please let me know. Thanks.1 point
-
@bernhard Can pw:install be completely unattended if I execute it with all the required options on the command line (which I'm guessing is not possible for database info) or does it require "stepping" through given that it's built with BrowserKit? Note: I'm not using ddev if that matters.1 point
-
I've created a custom alias: So all I have to do is type "ddc" and hit enter1 point
-
Possible solutions as discussed in this thread... Add a <datalist> to a text field: Text Input Awesomplete: https://processwire.com/modules/text-input-awesomplete/1 point
-
To answer my own question, part of it has to do with the order of operation stuff we discussed here: https://github.com/baumrock/RockMigrations/issues/231 point
-
@bernhard I took a quick look and understand what you mean. Thanks!1 point
-
Using RockFrontend in a real project for the first time since yesterday – I'm totally blown away! Currently I am only using Latte templates and LiveReload, but these two features alone are such game changers. @bernhard Thank you so much (again!) for donating such a genius module to the community! I don't know if anybody already asked/answered this, so I'll leave this info here: If you want to add additional folders to be watched by LiveReload, you can define them this way: /site/config.php: $config->livereload = [ 'interval' => 1, 'include' => [ $config->paths->root . '/some/folder', $config->paths->root . '/another/folder', ], ];1 point
-
The concept of this module is indeed based on that in Drupal. If you have any suggestions or functionality requests, please feel free to let me know.1 point
-
If I understand correctly that the clicked checkboxes are already marked as checked after submitting the form, you could solve it as follows: $selectedCategories = (isset($input->get->category)) ? $input->get->category : []; <?php foreach ($pages->get(1104)->children() as $category) : ?> <div class="flex items-center"> <input id="<?= $category->id; ?>" name="category[]" value="<?= $category->id; ?>" type="checkbox" class="text-gold-600 h-4 w-4 rounded border-brown-300 focus:ring-gold-500"<?php echo in_array($category->id, $selectedCategories) ? ' checked' : '' ?>/> <label for="<?= $category->id; ?>" class="ml-3 text-brown-800"><?= $category->title; ?></label> </div> <?php endforeach; ?> I hope this helps you!1 point
-
@bernhard Good questions and I'll answer according to the design of the core. These considerations are rigid when it comes to what the core does with these Page classes, but flexible outside of that. You are using Page classes in a way that gives them multiple roles. Whether that's good or not depends on your architectural point of view. But it sounds like you are happy with how it's working, and you've got a well defined strategy, and this is valuable. So none of this may useful for your case, so keep that in mind. That sounds okay to me. Why does it load an extra 10-20 pages? Or does that just depend on what pages are used in the request? As long as that magic page interface isn't increasing resource usage each individual Page object significantly, then it should scale just fine. It shouldn't be related to either. It should be independent of environment. A page is a type that aggregates content for a location in the tree. The problem with having front-end-only or admin-only stuff in a Page object is that it's code in the page that steps outside of its role and applies for one environment and not another. It can be seen as a type of bloat, turning a Page object into a jack of multiple trades. If you've got significant code that's just for one environment or another then the idea is that it's better to keep it separate from the Page. Perhaps delegated to a different class like my earlier example (or even a function outside of a class). But if it's just for a one-off case or something then I wouldn't bother. Take that getPageListLabel() method, that's something to represent the Page in the admin only, which is why it makes me uneasy. It's a tradeoff. It's a one-off case, so I think it's okay as long as we don't add more like it. Potentially the method might have front-end value in some cases too, so maybe that's another reason it's an okay compromise. But if we found ourselves starting to put a lot of admin-specific methods in Page classes then those would be better in a separate supporting class or function, or better yet, decouple it from the class entirely. That way it doesn't add code to the page class for something that goes outside its responsibility. Another point is that often code added for one environment or another will be the same between different page classes. To avoid repeating yourself, you'd have to repeat the same methods in multiple classes, or more likely add complexity with more levels of inheritance or traits to share that code. Moving that code to a dedicated class makes it more contextual, maintainable and extendable across multiple classes. There's that word "things" which seems like it might mean "everything" in this context. Here we're treating the Page like it's a Swiss Army knife for the type, rather than the type itself. It's like being the car and the carwash, the lawnmower and the grass, or not just the ball but the bat and glove too. That editForm() method looks like it's got the Page class now involved in manipulating forms in the admin. In that case Page is not just a type representing an aggregate of content, but also a form editor, adding application logic, giving the Page class multiple unrelated responsibilities. Some responsibilities which apply to all instances of the page and others which might only apply to one instance on occasion. If the Page must be the gatekeeper for multiple responsibilities, the idea is that it would be preferable that it delegates those responsibilities rather than implements them itself. That would enable it to provide that interface without expanding the internal role of the class. If you find benefits in using them differently then I'm not suggesting you change anything. Since you asked I have to give you an accurate answer of what Page classes are originally designed for and what I consider best practices around them. These are how the core considers them and doing likewise ensures things stay simple, efficient and scalable in the long term. But in PW flexibility is more important than rules and this is also true of Page classes. There's more than one way to do things well, I like your creativity and if you've found something that works well for your projects over time and scale then stick with it.1 point
-
Again, regarding a more modern administration: I like how the Silverstripe backend works, both how the page tree is presented, as well how the page edit screen looks. I also like that expanding the tree works in a (imo) more standard way (meaning a click will edit the page, to expand it there's an arrow). I think we could get some inspiration from there. You can try the demo here, no need to sign up: https://demo.silverstripe.org/admin/1 point
-
With regards to SEO related features, I think that being natively built in to ProcessWire is not the best choice as it goes against the unopinionated nature of ProcessWire. If one were to develop a webapp where SEO is not necessary, those fields would cause bloat. But if this were to be an official Profield, it would be wonderful. Personally, I use the FieldsetGroup Pro field (I gave SEOMaestro a try but it didn't work the way I liked), but since that's now legacy, I will have to switch my approach at some point in the future. It looks like this (note: it used to have XML sitemap fields as well, however when WireSitemapXML came out, I removed them and let that module handle it): If there were to be an new SEO module similar to my screenshot (meaning it supports fields for X, Facebook and other social networks), I would hope it's not officially called "FieldtypeSEO" but rather something like "FieldtypePresence" (ChatGPT helped me with that one) since it's more fitting (it helps improve your site's "presence" via search engines and social media networks). Personally I dislike the word SEO as it represents a lot of what's wrong with the internet and the snake-oil behind it.1 point
-
My main wish for ProcessWire 4 would be a generally more modern admin theme (e.g. with Ajax-Save unpoly/htmx style) and that at least fields that are also used in the frontend (FormBuilder) no longer have a jQuery dependency. On the subject of jQuery, it would also be great if the updates announced last year could also be activated for live pages in the next major release.1 point
-
@ryan I like the idea. This could speed up the initial setup and if done well would also work for non technical users (They never heard of composer). It could be like a modules manager/installer/picker that lists all modules with short description. Like a more compact list/grid of modules (maybe an expandable accordion with checkboxes for each module). Anything that makes it easier to find and install modules from the backend/installer would be a good addition in my opinion. I have to say doing commercial modules in PW is hard. The target group is small and the marketing of the module is the sole responsibility of the developer (eg. building a website/shop to promote and get the module). It would be nice if there was a platform integrated into the PW site to list/promote and maybe even buy commercial modules (Not only Ryans pro modules but also commercial modules build by the community). What was asked here shows the interest in page/block builders, and I think both RockPageBuilder and PAGEGRID are already very promising and have the potential to attract more users to PW (Which in return would make it easier for other developers to sell modules). I could envision a light/free version of PAGEGRID, but I need to justify the time to maintain and develop it further, so I think there needs to be a commercial aspect to drive the project forward.1 point
-
I am probably the least capable person in the community. I was able to build a very nice delivery app two years ago with Processwire. I was proud of it although it needed more polish. Because of being a relative newbie and designer by trade, I built a front-end that was meant to replicate a backend. Why? Because I wasn’t versed enough on creating custom admin pages in PW plus I didn't want it to look like the PW backend. That left me open to security holes, no doubt. But the end result was decently slick. But guess what really bothered me about the PW backend? I didn’t want my client seeing the word “Pages” throughout the UI they’d be working on. PW is powerful and I didn’t want them thinking this app was a glorified website. “Pages” stuck out like a sore thumb. Other CMSs forgo that which makes building something on top of them seem more custom and crafted to the specific use case. For instance, Craft CMS (see attachments) has a modern backend UI that would feel at home to me and yet there is no mention of “Pages.” I think that extends the use of their product beyond just a website. I know some of you may think I’m crazy but it’s been touched upon throughout this thread in one way or another. PW is the perfect ground floor. Being so opinionated on Pages just seems to pigeon-hole it and especially if the backend UI improved to feel more modern, then we’d have a tool that would allow relative beginners (to custom app development) to build some powerful stuff. Thanks for listening.1 point
-
1 point
-
Thank you for all the feedback, I'm enjoying reading it and it's opening up a lot of good ideas, so please keep it coming. I also have some ideas to add. With regard to big/major features, I'd ideally like to focus on things that absolutely must be in the core, and not on things that can be built and supported by others as modules. My wishlist would be that ProcessWire focuses more on its roots, being the best it can be as a framework and CMS for running modules. If I can focus on that part of the core, and let others develop major new features with modules, then not only would the core be that much better, but I think I'd have the bandwidth to do things like develop a more formal testing framework, make the docs that much better, have more time for issues and requests, etc. Things like media/asset managers and web/block builders/editors (as examples) are best built by those that use them. When you are both the user and developer, you can develop and support something better than if you hired someone to develop it. @bernhard is a great example, he has stepped up and built answers to several things that people ask for, and he's both developer and user of those things. I understand some of these external modules cost money. But when something doesn't cost money to you, it has still cost money and time resources from someone else, the developer, or whoever sponsored the developer. So it's a question of who pays for it and how they are doing so. My strategy here has been to focus on developing things that I can use in my projects and very often the clients help cover the cost. That's how much of ProcessWire has been built. Other features that I use but could not afford to develop and support for free have been developed into Pro modules. This helps fund the core too. I don't make enough to survive on that alone, so I do a lot of client work as well, and I like the diversity of work. When I say that one particular feature is not likely to be developed in PW's core in the next version, I'm not saying that it's a bad idea at all, nor am I rejecting it, but more likely that I don't have the ability to fund that feature at the moment. (But maybe will later). Or in many other cases, it may be that a particular feature might only be useful in some installations rather than most, and thus belongs as an external module. If something like RockPageBuilder or PageGRID or others could suit your needs on a particular project, support the developer and get it. The more we can do this, the more that developer can do, the more decentralized the responsibility for ProcessWire can be, and the more I think it benefits not just that module and developer, but the entire ProcessWire project. Maybe the developers of these modules would be open to having a free version with less features so people could get to know them better and upgrade when they need it. Kind of like how there is Lister and ListerPro. One idea I'd like feedback on. What if ProcessWire 4.x would be just the core and only the modules essential for the "blank" profile? And that's all the core would be. Then, on the download page (or maybe the installer), you could select all the modules you want to be part of your installation. For instance, you know you'll need repeaters, so you check the box for the Repeater Fieldtype. You know you want Tracy, so you check the box for that. At this stage you could select both 1st party and 3rd party modules to basically configure your own ideal version. From here we could also highlight other options like the Page Builders mentioned. There would have to be some predefined options, like a "well appointed" installation that is the same as the core as it is now. It would be a whole different way of building ProcessWire, but much more back to the roots of PW, becoming even more of a community project, sharing the responsibility a little further and getting more people involved, growing the family.1 point
-
This is not really a question or a tutorial, but merely an observation in case it helps anyone else. I have a site which I built before the custom page classes became available in the core, using a similar approach to this: https://processwire.com/docs/tutorials/using-custom-page-types-in-processwire/ To achieve this, I set the pageClass property of the relevant templates to be the same as the template name. I have now refactored the site to use the core custom page class functionality. I didn't change the pageClass property. Until then, I hadn't realised that $template->pageClass and $template->getPageClass() would yield different results, but they do. For instance, if the template name is 'Collection' and the pageClass property is set on the system tab to be 'Collection': $template->pageClass is 'Collection' $template->getPageClass() is: 'Collection' if that class exists (this was the case in my initial implementation - hence why I didn't realise the difference between pageClass and getPageClass() ) 'Page' if the Collection class does not exist and $config->usePageClasses is not set 'CollectionPage' if that class exists, the Collection class does not exist and $config->usePageClasses = true 'Page' if the Collection and CollectionPage classes do not exist and $config->usePageClasses = true In the last two cases, getPageClass() will output a warning "Template '$template' page class '$pageClass' is not available" Removing the pageClass property from the template results in: $template->pageClass is '' $template->getPageClass() is: 'Page' if $config->usePageClasses is not set 'CollectionPage' if that class exists and $config->usePageClasses = true 'Page' if the CollectionPage class does not exist and $config->usePageClasses = true In this case, no warnings are output. Bottom line: if you are migrating from the 'old' approach to the use of core custom page classes, beware of any instances of $template->pageClass as you may need to change them to $template->getPageClass().1 point
-
@maetmar When rendering templates using Latte, I've found the built-in field rendering a bit cumbersome to set up since you'll need an intermediary PHP file to render the Latte view from. The straight-forward version would be using a loop and including a file based on the matrix type. This will look for a view partial at site/templates/views/partials/blocks/image.latte, when rendering a matrix page of the type "image" in a matrix field named "blocks": {foreach $page->blocks as $block} <div class="block" data-block="{$block->type}"> {include 'partials.blocks.' . $block->type, block => $block} </div> {/foreach}1 point
-
You have to first get the "itinerary" array as a variable distinct from the $session->itinerary overloaded property, modify it as needed, and then set it back to $session->itinerary. if(isset($_GET[$key])){ $itinerary = $session->itinerary; if(is_array($itinerary)) { // destroy a single element of an array unset($itinerary[$key]); $session->itinerary = $itinerary; $session->redirect($page->url); } }1 point
-
How are you doing your markup? You should have something like this: <input type="checkbox" name="color[]" value="red"> <input type="checkbox" name="color[]" value="blue"> Now color is an array: $selector = ""; $colorOptions = $sanitizer->array($input->get->color,'text'); if(count($colorOptions){ $colorOptions = implode('|',$colorOptions); $selector = ",color=$colorOptions"; }1 point
-
That isn't valid syntax for whitelist(). See the docs: https://processwire.com/api/ref/wire-input/whitelist/ The syntax is valid here, but you'll be overwriting the same whitelist key in each iteration of your loop. I think you want to set an array to the whitelist key, e.g. $san_array = array(); foreach($input->get->st as $st) { $san = $sanitizer->selectorValue($st); $san_array[] = $san; $selector .= "projectStatus=$san, "; } $input->whitelist('st', $san_array); // later, call renderPager() with arrayToCSV set false // or do as Ryan suggests: https://processwire.com/talk/topic/1883-how-to-use-input-whitelist-with-checkboxes-or-any-array/?do=findComment&comment=17706 echo $works->renderPager(array('arrayToCSV' => false)); For the other issue regarding setting the selected attribute of the checkbox you'll want to use in_array.1 point