Jump to content


Popular Content

Showing content with the highest reputation since 08/15/2019 in all areas

  1. 16 points
    ProcessWire added WebP image support this year and many have been adopting it enthusiastically in existing projects. In this post we’ll look at a process used for migrating an existing website to use WebP images. We’ll cover everything from preliminary considerations to implementation and testing, with lots of tips and tricks along the way— https://processwire.com/blog/posts/webp-images-on-an-existing-site/
  2. 8 points
    Hello everyone, Recently I spent some time researching how I can update my workflow. I really enjoy working with TailwindCSS however, when it comes to Javascript, I often find myself having to search around to find a good package. Often I find myself having a package for lazy loading, a package for sliders, a package for animation, a package for parallax and a package for ajax. Before you know it, you are worrying about dependicies, conflicts and vunrabilities for many different packages. Since the push is to get rid of jQuery and use native javascript, often each will have their own utility classes, some of which do the same thing. This adds a lot of bulk to the website. This is what I love about UIKit, it provides plenty of functionality for a small ~130KB unminified. Not many know this, but the UIKit helper classes are exposed via the API too. So it means you will not have to worry about your javascript working cross-browser (https://github.com/uikit/uikit-site/blob/feature/js-utils/docs/pages/javascript-utilities.md). The perfect thing would be to combine UIKit and TailwindCSS, but the best way to achieve this is up for grabs. I personally use TailwindCSS base and implement components from UIKit. I then use PurgeCSS on the CSS file to make sure anything unused by either UIKit or Tailwind isn't making it to production. I do this using Parcel JS. I have used Webpack and Gulp previously, but I find Parcel is a simple and easy way to get a project started (and it's fast!). The next thing I've found is UIKit is not always the answer. There are now more than ever better ways of achieving things in browser. Such as CSS Grid, `position: sticky`, and `object-fit` try to use these CSS alternatives where possible. Purge will always make sure that you get the smallest possible file size, so avoid using the uk-grid element where possible and use CSS Grid. I have setup a github starter template (https://github.com/TomS-/UIKit-TailwindCSS/tree/master) if you want to have a look at it. CSS Grid will introduce intrinsic design (https://www.youtube.com/watch?v=lZ2JX_6SGNI - Great series) Next will be to use WebP, there is plenty going around on the blogs now about this, but this will make a massive improvement to your Google Page Insight rating (https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2Fwww.tikari.co.uk%2F&tab=desktop). I would love to hear your web manifesto - and ask me anything about mine 🙂
  3. 6 points
    This module will log information about all mails that are sent wie WireMail to the PW logs https://github.com/BernhardBaumrock/RockMailLogger https://modules.processwire.com/modules/rock-mail-logger/
  4. 6 points
    Fixed! Not completely sure why, but switching: $mail = new WireMail(); to this: $mail = $this->wire('mail')->new(); in the LoginRegister module did the trick — line 684. Now Gmail's sending my registration emails too 🙂 Gotta say, I am hugely grateful for Processwire. Ryan, and all you fantastic moderators and commenters—this is such a great place to learn, and goddamn if the sky doesn't seem to be the limit.
  5. 6 points
  6. 5 points
    The newest version of RockGrid now supports RockFinder2 as data source 😎 $finder = new RockFinder2(); $finder->find('template=basic-page'); $finder->addColumns([ 'title', 'body' ]); $this->setData($finder); Data is available on the JS side via the RockFinder2 property in the GridItem object:
  7. 5 points
    Hey folks – a quick update: Wireframe 0.5.0 was released couple of days ago. Compared to 0.4.x this version mainly fixes bugs and improves performance – nothing particularly major, but if you're using Wireframe, it's a recommended update. On a loosely related note, Tracy Debugger has been really helpful in figuring things out, identifying bottlenecks, etc. Brilliant module 🙂
  8. 4 points
    /* * Example of how to clone a locked page, remove the lock on the copy, and clear the value of a field in the copy. * Reset stockCode Field when copying a page using a specific template, also remove locked status. * This code is included in the /site/ready.php file. */ $wire->addHookAfter('Pages::cloned', function($event) { /* * Important: The event arguments include both the copied page and the newly created page. * Don't use $event->arguments('page') as this returns the page that is being cloned rather than the cloned copy. * Instead use $event->arguments(1) which correctly refers to the new copy. */ $currentPage = $event->arguments(1); if ($currentPage->template == 'bom') { $currentPage->stockCode = ''; $currentPage->status = $currentPage->status & ~Page::statusLocked; //probably better to use removeStatus(Page::statusLocked) $currentPage->save(array('quiet' => true)); } }); Here's my documented example of how I got this to work.
  9. 3 points
    Hello folks! Recently we published a new website for Brightline, a Project Management Institute (PMI) initiative together with leading global organizations dedicated to helping executives bridge the expensive and unproductive gap between strategy design and delivery. The previous website was made in Hugo as in the beginning it was a very simple website, but as the business needs changed, I decided to build this version in ProcessWire. Nothing fancy occurs behind the curtains, the need was more on getting some data in a way that makes it easier to create reports and to give access to PW's great admin to another team member. For the other website, that you can see here, I didn't implement a CMS on top of Hugo because for me it was quicker to edit the files and push to the repository. Some content is still being copied but 98% is done. A quick list of modules used: - ProCache, FormBuilder, ProFields, SeoMaestro, PageHits, TracyDebugger, MenuBuilder, AutoSmush, and other custom ones. I'm biased, but there a lot of good and useful content created by us and also by partners and all is free to download. :)
  10. 3 points
    The notes on the Settings tab of Page Edit are a good summary of what the statuses mean: Hidden and unpublished pages are both excluded from selectors (unless you override this) - the difference is that a hidden page is viewable if the URL is known, whereas an unpublished page cannot be viewed unless the user is logged in and has edit access for the page.
  11. 3 points
    No problem! When I have some time here I'm planning to build a site profile using Tailwind CSS so more people can see how it can be integrated with PW. Using both the CDN version, which gzipped is around 60kb and using brotli compression goes down to less than 20kb and the webpack installation I mentioned. :)
  12. 3 points
  13. 3 points
    Hi @Soma, Could you please add this very useful module to the PW modules directory? Thanks!
  14. 3 points
    The map still seems broken. It would be really sweet if Ryan could put the website code on Github so other people can contribute as well through PR's.
  15. 3 points
    I wrote an api-module a few years ago, where the module generated a custom template (e.g. "api-page"), which could be used to create one or more endpoint-pages. To handle calls to these pages I used ProcessPageView::pageNotFound like @bernhard did: $this->addHookBefore('ProcessPageView::pageNotFound', $this, 'handleApiRequest'); public function handleApiRequest(HookEvent $e) { $page = $e->arguments[0]; if ($page->template === 'api-page') { // handle request here... $otherEvent = $e->arguments(0); // grab event provided to PageRender::renderPage $e->replace = true; // prevent PageRender::renderPage from being called } } It worked nice for me, but I cannot say if caching or multi-language works better in this hook. pageNotFound should be called later than execute, so there is a chance that it helps 🤷‍♂️
  16. 3 points
    For a front-end search form? One strategy I often use is concatenating the selector one input field at a time. Just make sure your add your validation. Something like this: $selector = ''; if($place = sanitizer()->selectorValue($input->post->place)) { $input->whitelist('place', $place); $selector .= ", place%=$place"; } if($input->post->doctor) { $input->whitelist('doctor', $input->post->doctor); if($input->post->doctor == '1') { $selector .= ", name=jim"; } elseif($input->post->doctor == '2') { $selector .= ", name=jon"; } elseif($input->post->doctor == '3') { $selector .= ", name=jake"; } } $limit = 12; $template = doctor; $parent = doctors; $selector .= ", sort=sort, limit=$limit"; $selector = "template=$template, parent=$parent" . $selector; $results = pages()->find->($selector);
  17. 3 points
    Using the brand new "multiple methods" hook feature in PW 3.0.137 you could save the average stars value to a decimal (or float) field every time a comment is approved/disapproved/updated/deleted. Then you can find or sort pages by the field more efficiently. The hook below assumes a comments field named "comments" and a decimal field named "decimal": $wire->addHookAfter('FieldtypeComments::commentApproved, FieldtypeComments::commentUnapproved, FieldtypeComments::commentDeleted, FieldtypeComments::updateComment', function(HookEvent $event) { /* @var Page $page */ $page = $event->arguments(0); /* @var Field $field */ $field = $event->arguments(1); if($field->name !== 'comments') return; if($page->template->hasField('decimal')) { // Save the average star rating for comments with approved or featured status $page->setAndSave('decimal', $page->comments->find("status=1|2")->stars(true)); } }); P.S. You'd do a one-off API operation to save the average stars value for all your existing comments to get things set up initially.
  18. 3 points
    Offtopic, but have you (@zeka) had a look at RockFinder and RockGrid? And the upcoming RockFinder2 and RockTabulator? 😉
  19. 2 points
    Hi, I agree it is a bit hidden, but it is here -> https://processwire.com/api/ref/page/#pwapi-methods-constants.
  20. 2 points
    Status update links (inside this thread) for SnipWire development will be always posted here: 2019-08-08 2019-06-15 2019-06-02 2019-05-25 If you are interested, you can test the current state of development: https://github.com/gadgetto/SnipWire Please note that the software is not yet intended for use in a production system (alpha version). If you like, you can also submit feature requests and suggestions for improvement. I also accept pull requests. ---- INITIAL POST FROM 2019-05-25 ---- I wanted to let you know that I am currently working on a new ProcessWire module that fully integrates the Snipcart Shopping Cart System into ProcessWire. (this is a customer project, so I had to postpone the development of my other module GroupMailer). The new module SnipWire offers full integration of the Snipcart Shopping Cart System into ProcessWire. Here are some highlights: simple setup with (optional) pre-installed templates, product fields, sample products (quasi a complete shop system to get started immediately) store dashboard with all data from the snipcart system (no change to the snipcart dashboard itself required) Integrated REST API for controlling and querying snipcart data webhooks to trigger events from Snipcart (new order, new customer, etc.) multi currency support self-defined/configurable tax rates etc. Development is already well advanced and I plan to release the module in the next 2-3 months. I'm not sure yet if this will be a "Pro" module or if it will be made available for free. I would be grateful for suggestions and hints! (please have a look at the screenshots to get an idea what I'm talking about)
  21. 2 points
  22. 2 points
  23. 2 points
    You can use the Connect Page Fields module by @Robin S. This makes it easy to connect both page fields.
  24. 2 points
    That feeling is simply awesome! Welcome to the community :)
  25. 2 points
    The easiest way I've found is to use Laravel Mix with two plugins, Laravel Mix Tailwind and Laravel Mix PurgeCSS to reduce file size by going through all php templates. But note, the website is not running the purged version yet, as I'm working on some configs on javascript generated classes and classes set by the user via admin (using RepeaterMatrix). But I also reduced manually Tailwinds output by using just a few colors and removing other pieces. Take a look on my webpack.mix.js file: And here goes Tailwind Config file. Note: I'm using Tailwind earlier version (prior to 1.0). Will upgrade it when possible, but it works just fine.
  26. 2 points
    It's all in the facebook docs: https://developers.facebook.com/docs/plugins/comments/
  27. 2 points
    @Gadgetto My bad. I misled you a bit. I can't find it now, but @teppo made an excellent post about the executeWhatever() aspect of Process modules. In Process Modules, unlike URL segments in the frontend, ProcessWire will 'jealously guard' the first URL Segment, i.e. the Whatever part of execute....(). In other words, if your Process module has a first URL segment, it will look for a method in your Process module named executeYourFirstURLSegment(). If it doesn't find that, rather than render what is in execute(), it returns the error, Processwire: Unrecognized Path and the content The process returned no content. However, this only applies to the first URL Segment. After that, i.e. 2nd, 3rd, etc URL segments will resolve to whatever you decide based on the code you have in the method of the first URL Segment. For instance, in the case /admin/mymodule/firsturlsegment/whatever/, ProcessWire will not complain if there is no 'whatever' as long as firsturlsegment has content. Please find an example Process module below and the demo of it. The example is a bit rudimentary but you get the idea. Normally, I don't include the content of what I want the 2nd, etc URL segments to resolve to within the executeWhatever() method itself. I usually throw those in their own methods or even class. Example In this example, executeColours() is our gateway to anything we want the 2nd URL segment to resolve to. The 'red', 'green', etc segments do not exist independently (i.e. no corresponding executeXXX() methods for them). ProcessWire does not complain since the first segment /colours/ exists as executeColours(). Demo
  28. 2 points
  29. 2 points
    Nothing in that regard yet. Let's just try to meet over a drink and learn from that point on whether to set up any form of "infrastructure" at all 🙂
  30. 2 points
    @iipa Pasting stuff from Word should be no problem ... I think most of our clients likely do this. So you definitely shouldn't get an internal server error from PW at least. Though you might try setting $config->debug=true; in your /site/config.php file (temporarily) and trying again, just in case — that will make it produce a verbose error message. But it's more likely that it is coming from mod_security or some other Apache or PHP module on the server that is monitoring input and halting the request when it comes across something it doesn't like. I don't blame it, as MS word can produce some pretty sketchy looking markup. But between CKEditor and htmlpurifier, PW should be able to clean it up just fine once the server lets it through. But if it's an Apache/PHP module doing this (which seems likely) then nothing you adjust in PW can fix it since the module examines the request before PW even boots, so you'd instead have to disable or configure the Apache module (mod_security, suhosin, or whatever it might be).
  31. 2 points
    Affinity used it in a clever way. I like(d) their software.
  32. 2 points
    From the docs https://code.google.com/archive/p/jquery-asmselect/ addItemTarget: Where to place new selected items that are added to the list. Allowed values: 'top' or 'bottom' Default: 'bottom'
  33. 2 points
    When I installed Processwire for the first time, I noticed that Admin sessions were not lasting for a long time and it was very common to be logged out. Reading this forum I found useful information, but I could not solve this issue. I tried to modify site/config.php adding $config->sessionExpireSeconds with different values, but without success (for your awareness sessionExpireSeconds default value is 86400 seconds, ie 1 day .. so quite enough!). OK, I had no time to go deeper, so I kept doing what I had to do ... being happily logged out … time to time. Few weeks later while studying Session.php in wire/core/ I got the hint (please read the commented text) which helped me to understand how to solve it: if(ini_get('session.save_handler') == 'files') { if(ini_get('session.gc_probability') == 0) { // Some debian distros replace PHP's gc without fully implementing it, // which results in broken garbage collection if the save_path is set. // As a result, we avoid setting the save_path when this is detected. } else { ini_set("session.save_path", rtrim($this->config->paths->sessions, '/')); } } Uh! Yes, my VPS uses Debian 9 ! So I quickly did a test: echo ini_get('session.gc_probability'); echo ini_get('session.gc_divisor'); echo ini_get('session.gc_maxlifetime'); The session.gc_maxlifetime was rightly set to 86400, but session.gc_probability was 0 ! As you can easily get from Session.php routine, if probability is 0 bye bye PHP's session garbage collection and of course PW will not set the save_path. But why probability is set to 0 ?? This is due to the fact Debian/Ubuntu Linux overrides standard PHP’s session garbage collection by setting session.gc_probability to 0. As a consequence PHP’s standard session garbage collection will never run. Instead Debian/Ubuntu sets a specific Cron job for garbage collection with a duration of 1440 seconds, ie 24 minutes. This determines the max session duration. If you try to change session.gc_maxlifetime through $config->sessionExpireSeconds=86400 or ini_set('session.gc_maxlifetime', 86400) it will have no effect and sessions will be deleted at intervals of 24 minutes (or within 54 minutes). The Cron job garbage collection duration is defined at php.ini level, and runtime changes to session.gc_maxlifetime will not affect the Cron job timeout. Uh! Of course the simplest solution would be to change session.gc_maxlifetime in php.ini. However sometimes this is not possible (shared hosting). Another point to consider is that this change may affect multiple applications running on your server. Instead of modifying php.ini, personally I preferred to enable PHP's session garbage collection locally for Processwire only. Majority of the code is already written in PW Session.php, we have just to take benefit of it. Let's go step by step. Let's open site/config.php and do the following modifications (I choose to implement 14400 seconds session time, ie 4 hours): /** * Reduce inactivity timeout (original 86400 = 1 day) * How many seconds of inactivity before session expires */ $config->sessionExpireSeconds = 14400; /** * Enable Session Garbage Collection * Garbage Collection is disabled in Debian as default (probability set to zero) * Enable session garbage collection with a 1% chance of running on each session_start(); * Chance calculated as gc_probability/gc_divisor * Session path is defined inside wire/core/Session.php and points to site/assets/sessions * Thanks to this modification session now takes into account gc_maxlifetime set in config */ ini_set('session.gc_probability', 1); ini_set('session.gc_divisor', 100); Do not forget to lock site/config.php after modifying it. Here it is! We are done! After we have set gc_maxlifetime (through sessionExpireSeconds), enabled the garbage collection (gc_probability=1), and set its intervention probability (gc_divisor=100 ie 1% chance), we can rely on Session.php where the a session path (session_save_path()) is defined, and session is started (session_start()). In the development session of our browser let's look for our session cookie: if you go to site/assets/sessions you will find your corresponding session: Please note that during development phase, likely having little traffic, the number of sessions may grow and they will not be deleted. This depends from the 1% chance of deletion. If you want to test garbage collection is properly working or just to make sure sessions files are regularly cleaned during development, you can decrease gc_divisor to a lower rate(10=>10% ... 2=>50%). Do not forget to reestablish gc_divisor = 100 when moving to production. I hope some can find that tutorial useful in the future ... and may save several log outs!
  34. 2 points
    Definitely, I would recommend PW. In my case, the client didn't like the tree structure of pages, so I had to create separate Process modules for managing news, tags, banners, categories. I have found that it's much easier to control permissions and workflow via custom modules.
  35. 2 points
    Well, I use personally use UIkit 3 + TailwindCSS. Tailwind you are going to hear a whole lot more about in the upcoming months. I know you are talking about file size and this is exactly why UIkit + Tailwind is great! I don't really use UIkit's CSS at all. I just use the JavaScript because the amount of utilities they have manage to pack into 130kb (less than most images) is amazing. I'm talking Parallax, Sliders, Lazy Loading Images, Srcset utilities, placeholder generators, scrollspy, sticky. Most of which can be and usually is utilised in any project. I challenge you to get all of that under 130kb. Also it doesn't have any dependencies. Tailwind you can get down to about 3KB per website using Purge and Gulp/Webpack. It truly is amazing and Utility first CSS is such a refreshing way to work with CSS. I know all the arguments, and I'm a minimalist. I don't like all the classes too. But Tailwind's benifits out weigh the cost. 1. You don't have to struggle with inherited styles, or coming up with class names to define each section, some of which may look the same but be very different in content. 2. Consistency, it puts pressure on you to keep things consistent. So you hardly stray to loads of different type sizes and colours. 3. With Purge, you can have an entire website styles in ~3kb. I believe Ryan chose UIkit 3 because he has learnt the classes and is confident with the framework, and is impressed with the JavaScript utilities. And because you can build website much quicker using it. I see it as a hybrid between utility and a standard framework. It offers many utility classes. You could also Purge UIkit's CSS and get it around 160KB. I don't believe that this isn't a good fit for ProcessWire as you have previously mentioned. Many who use ProcessWire love UIkit. It follows the same philosophy: A powerful framework, that is easy to understand and learn to get things done quicker. Just like ProcessWire gives developers confidence in that they can do challenging bits of functionality easily with the power of ProcessWire's amazing API (like seriously, I built a real estate system using ProcessWire, something I wouldn't have dreamed of doing on any other platform). Well UIkit also gives that confidence to the front-end. But if I was to choose for myself, I much prefer pairing Tailwind for the CSS and UIkit for the JavaScript. That ~140KB (Tailwind + UIkit) covers me for most websites I build.
  36. 1 point
    One of the ways you can show support for ProcessWire is to help get the word out by including a small "Powered by ProcessWire CMS" tagline (ideally linking to processwire.com) in the footer of sites that you develop. This is a big help to the ProcessWire project. But I know there are many cases where it just doesn't work to do that because the client thinks of it as gratuitous. I think it's important to communicate to your client that it's not gratuitous at all. It is doing the right thing by showing appreciation and support for a software that is running their site at no cost. Even so, it's not always as simple as that, and I completely understand. We have no requirement or expectation that sites developed in ProcessWire do this. We just encourage and appreciate it when you can. Let your client decide One thing I've been doing lately is to put the control into my clients hands. They really appreciate that I've given them control over it… more so than if I'd left out mention of ProcessWire completely. It also makes them feel good as they are the one showing support, not just their site developer. Here's how to do it in 1 minute: 1. Create a new "checkbox" field in Setup > Fields called "toggle_powered" (or whatever you want to call it), and enter the following for label and description: 2. Add the "toggle_powered" field to your homepage template. 3. Edit the homepage and check the box (if possible in your situation). 4. Edit the template file or include file that contains the site footer and paste in the following: <?php if($pages->get('/')->toggle_powered): ?> <p> <a id='processwire' target='_blank' href='http://processwire.com'>Powered by ProcessWire Open Source CMS/CMF</a> </p> <?php endif; ?> The code above is an example, so adjust the markup, size, wording and placement to suit the site.
  37. 1 point
    another website : http://jeevanism.com/
  38. 1 point
    I want to be able to allow users with page clone rights the ability to clone locked pages with specified templates to a new unlocked copy, but without letting them edit the locked page. It looks as though I have the right permissions set to allow them to copy a page, but I need to add a hook in the /site/ready.php to unlock a page after it's copied. What method should I hook into? Edit: Figured it out. AddHookAfter Pages::Cloned. I had to be careful to pick the right argument though so that I was modifying the cloned copy and not the page that the copy was made from.
  39. 1 point
    Hello, Will you please share a code snippet for future reference so that others can clearly see what to watch out for?
  40. 1 point
    Hi iipa Does the user use the "Paste from Word"-button?
  41. 1 point
    Hey @opalepatrick – just a heads-up that I'm moving this thread to the Module/Plugin Development area. The main "Modules" area is only intended for support threads of existing modules.
  42. 1 point
    Anyone new to this module, please be aware of this unfixed issue: https://github.com/ryancramerdesign/ServiceCurrencyConversion/issues/1
  43. 1 point
    Thanks – this should now be fixed in the latest version (2.2.2).
  44. 1 point
    It doesn't diminish your request, but Interestingly I have an issue where AOS actually causes a horizontal scrollbar to appear on desktop on some pages - as soon as I disable AOS it goes away. I haven't narrowed down the cause, but something worth thinking about in all this.
  45. 1 point
    @dragan Indeed nice catch. @bernhard Thanks for the RockSkinUikit module. Will use it in an upcoming project.
  46. 1 point
    Just in case, I use those alias to install or upgrade my installs : # ProcessWire Wireshell bash alias # grab and install the latest ProcessWire development version from the latest commit alias pwnew='wireshell new --sha=`git ls-remote https://github.com/processwire/processwire refs/heads/dev | cut -f1`' # upgrade to the latest ProcessWire development version from the latest commit alias pwup='wireshell upgrade --sha=`git ls-remote https://github.com/processwire/processwire refs/heads/dev | cut -f1`' https://gist.github.com/flydev-fr/addcf54fa8348de20115d3c1314ddb3d
  47. 1 point
    Hey there @Samk80, Max from Snipcart here. Don't hesitate to ping us at geeks@snipcart.com should you decide to give our product a try! We'd be glad to help. And a huge thanks to @evan & @flydev for mentioning Snipcart. Goes a long way!
  48. 1 point
    Check out advanced mode in config.php and you'll have this for each template: Maybe doesn't take care of everything you need, but remember that the status can also be changed from the Page List view via the extended (after the arrow) action buttons.
  49. 1 point
    I was being nice - the man behind the counter even said he thought I was very nice as he dialed the police.
  50. 1 point
    Ryan, thank you for your input. This looks promising I've responded to specifics below: My thought was to put the data into the Processwire database but in its own table so that any updates to PW don't interfere with the custom data. Is this what you mean? I like the idea of "piece of cake" Can you explain this a bit more? I'm not quite familiar with bootstrapping PW yet Thanks again, I will play with this code and see what I get So far I've only built really simple sites with PW so I'm pretty excited about doing some more indepth stuff and getting my hands dirty with some PHP and the API Thanks for the welcome Glad you found the tuts useful. I'm already sold on PW I've built a few simple sites with it and understand the basics, but I'm looking to delve deeper now, play with the API and do some more complex stuff.
  • Create New...