ProcessWire 3.0.244 new main/master version

ProcessWire 3.0.244 is our newest main/master/stable version. It’s been more than a year in the making and is packed with tons of new features, issue fixes, optimizations and more. This post covers all the details.

There have been at least 110 issue fixes in this version relative to the previous main/master version, making this perhaps our most stable version ever!

A big thanks to matjazpotocnik who helped a lot in the issues repo with organizing, confirming, testing, and in several cases even solving reported issues. Thanks also to all that have helped to identify and report issues.

ProcessWire's code base is pretty mature at this point, so there aren't any major issue fixes to write about in this post, except perhaps that our previous main/master version had some issues with PHP 8.4+ and the new version is fully compatible. Instead, this post will focus mostly on what's been added and upgraded in this version, essentially the highlights. If you want details on all the details and issue fixes, the full commit log has you covered.


ProcessWire 3.0.244: By the numbers

  • 306 commits
  • 110 issue fixes
  • 45 authors (10 in this version)
  • 15 dev branch versions
  • 14 months development
  • 9 added pull requests
  • 1 great new core version

Contributors/authors attributed in this version

Special thanks to authors that contributed to this version (A-Z):

  • Adrianbj
  • BernhardBaumrock
  • Erikmh
  • Matjazpotocnik
  • MPSN
  • Romaincazier
  • Ryan
  • Tobaco
  • Toutouwai

These are the names that appeared in our commits, but there are no doubt many other contributors too. Those that have reported issues (whether on Github or in the forums or email), those that have contributed ideas and suggestions, contributed in the community by providing support to other ProcessWire users, or that have supported ProcessWire in other ways, such as with purchasing Pro modules, developing/supporting modules, and building amazing sites with ProcessWire. ProcessWire is a community effort — a big thanks to the entire ProcessWire community!


What’s new in 3.0.244

Please note that the updates below are grouped where related, but they are not ordered by significance, importance, scope, etc.

Versions

The PagesVersions module was added to the core. This module provides a simple API for managing page versions, and it is also used by the PagesVersionsPro module (available to ProDevTools and ProDrafts users). A second version of PagesVersions also added support for partial save and restore, which provides the ability to save or restore some fields and not others. PagesVersions supports the majority of ProcessWire Fieldtypes, core, 3rd party and ProFields, even repeaters (nested too).

Files and Images

Updated the Pagefile, Pagefiles, Pageimage, Pageimages, FieldtypeFile and FieldtypeImage classes to support new getFiles() methods that return all files connected with the field, whether originals, variations (i.e. different sizes, crops) or extras (i.e. WebP).

InputfieldFile and InputfieldImage were updated to support contexts (named file_context) so that the same file/image field can appear more than once in the same editor. This was already supported with repeaters, but now can be supported by other cases (and is used by the new PageEditChildren module).

Added the ability to hide or disable image items in a multiple image field.

Added the ability to interactively delete WebP extra images independently of an image's JPG/PNG variations. This is done from the image variations popup/modal when editing an image field in the page editor.

Admin

The AdminThemeUikit module had its Uikit version updated to the latest (at the time of commit).

Added a checkSystemTimes() method to SystemUpdaterChecks module that compares the PHP time to the database time. This occurs once per superuser session and a warning notification is displayed when they differ. The notification also includes instructions on how to fix the issue of PHP time differing from database time.

The column width slider in the fields list of ProcessTemplate has been improved. Specifically the part where you click and hold the percent and then drag your mouse left/right or up/down to adjust the column width value. It's now using 5% increments (plus 33%, 34% and 66%), and [when or if needed] you can now double click the percent to open the dedicated range slider in a modal, which provides more specific column width numbers.

The ProcessPageEdit module (page editor) was updated to show what Page class is being used (Settings tab > Info fieldset).

The ProcessWire.alert('text') javascript function has been updated to support an expiration time after which the alert will automatically close. Example: ProcessWire.alert('text', false, 3000); would auto-close the alert box in 3 seconds. Note that the false in that argument list refers to whether markup is allowed in the text or not.

Admin: Modules

A README Markdown viewer was added to to the Modules administration (ProcessModule). Now if you have a ModuleName.README.md file, it will display automatically above the module config settings.

This update also makes any relative <a href=/url/> or <img src=file.jpg> (or Markdown equivalents) in the README automatically point to the module's /site/modules/ location. This means that an <img src="file.jpg"> automatically updates to refer to the file.jpg in the module's /site/modules/ModuleName/ directory.

Links to README.md or CHANGELOG.md are updated to use the built in-viewer. Other links are converted to target=_blank links, so that they don't take over the iframe used by the modal. You can use the placeholders {MODULE_INFO.NAME}, {MODULE_INFO.TITLE}, or {MODULE_INFO.WHATEVER}, to refer to and replace the named module info property. It will convert automatically to the appropriate value.

This update also adds support for text-only files like README.txt, CHANGELOG.txt, LICENSE.txt.

Admin: Search

You can now type id=1234 (where 1234 is page ID) to find a page by ID in the admin live search.

We have added support for custom live search results in the admin search. A hookable method in the ProcessPageSearchLive class enables overriding what gets searched in the admin search box at runtime. This is also useful if you want to search fields on pages that the interactive module configuration may not let you configure, such as some_field.some_property. More details on how to use and configure here.

Admin: Pages Clone

Added the configurable option to always use the full clone form (see ProcessPageClone module settings in the admin). Prior to this, the quick clone option was always used when cloning a page in the page list that didn't have children.

We have updated the page clone process to show a count of how many pages would be cloned when doing a recursive clone (such as when cloning children).

Dropdown options were added to the clone submit button so that you can optionally edit a page after cloning.

Added an option to choose whether children/granchidren/etc. are unpublished on cloned pages.

The ProcessPageClone getSuggestedNameAndTitle() method is now hookable. This enables you to control what name/title are suggested for cloned pages.

Installer

The installer has been updated so that it works if site the profile is already present in /site/ rather than /site-name/.

The installer now excludes some $config settings when already supplied by site profile's config.php. This ensures no settings duplication when writing /site/config.php.

The installer now uses utf8mb4 and InnoDB as the default settings for MySQL (rather than the former utf8 and MyISAM).

Database socket support has been added to the installer's DB configuration screen.

Selectors

OR-groups support has been added to the Selectors class so that it can also be used with non-page matching.

We have upgraded in-memory page matching selectors by adding support for OR-groups, sub-selectors, and same (1) item group matches.

$database

The $database API has been updated with a new reset() method. This $database->reset() method closes then restarts the DB connection.

The $database->execute($query) method now uses the above mentioned reset() method to retry a failed query due to loss of connection.

$pages Hooks

New $pages->moveReady(), restoreReady(), and renameReady() hooks. These hooks are called immediately before each action named in the hook.

Added a new pages.save callback hook:
$pages->save($page, [ 'callback' => function($page) { … }) ]);
This callback function is called after save of a page. While this is something you can already do with hooks, this callback is useful in specific cases where it need only apply to a specific page and/or the callback implementation might not be known at the time the save() call is written in code.

$pages Methods

Added a new $pages->saveFields([ 'field1', 'field2', 'etc.' ]); method that enables you to save multiple fields on a page. Previously you could only save the entire page, or 1 field at a time.

Added a new $pages->cacher()->hasCache($id) method that returns true or false as to whether or not a given page ID has already been cached in memory.

Added a new $pages->request()->getPageInfo() method. This returns a verbose associative array (just like this one) about the page that was matched for the request URL, including all the details of how it was matched and what additional features are used in the URL.

$page (or any Page object)

Added a new $page->preload([ 'field1', 'field2', 'etc.' ]); method that preloads multiple fields in a single query. This is kind of like Autojoin except that it can be called on an already-loaded page.

Added support for a $page->sortPrevious property (integer), which is populated with the old value when a page's sort value is changed at runtime.

Added a new $page->cloneable() method that returns true if the current user is allowed to clone the page. Or use $page->cloneable(true) to check if the user is allowed to clone the page and its children together.

Added new $page->saveFields([ 'field1, 'field2', 'etc.' ]) method as a front-end to the new $pages->saveFields($page, [ … ]) method. This method enables you to save multiple fields on a page. Previously you could only save the entire page, or 1 field at a time.

The Page::getInputfields() method is now hookable, enabling you manipulate what is shown in the page editor.

The $page->editUrl() method now supports a 'vars' (array) option that contains additional query string variables that it should bundle in to returned URL. For example: $page->editUrl([ vars' => [' foo' => bar' ] ]);

Repeaters

Added support for custom page classes on Repeater page items. For more details see the new getCustomPageClass() and setCustomPageClass() methods in FieldtypeRepeater.

Updated inputfields.js to add support for repeater 'forpage' selectors in showIf dependencies.

We now support open/close for family groups of repeater items together. When using repeater item depths, and you open (or close) a repeater item, items that are visually children of it also open (or close). To enable, see the field "Details" tab setting in: Repeater depths/indents > Open/close items as a family.

Added a Repeater field configuration setting that enables you to disable the automatic scrolling to newly added repeater items.

We have improved support for fields in repeaters (or other embedded types) so that dependencies (showIf/requiredIf) can reference fields outside the repeater. This is done by using the forpage.field_name=... syntax in the dependency configuration string. For instance, if you want a field in a repeater to only appear if editing a page using template ID 123 then you could use showIf dependency forpage.template=123.

Multi-language

Updated the Page API for getting/setting multi-language values. The methods $page->setLanguageValues() and $page->getLanguageValues() were added for setting and getting values from multiple languages at once.

The methods $page->setLanguageStatus() and $page->getLanguageStatus() were added for setting/getting the active status of a language or multiple languages at once. This replaces more cryptic calls like $page->status1234 = true (where 1234 is language ID).

The methods $page->setLanguageName() and $page->getLanguageName() were added for setting/getting the name of a page in a particular language or languages. This replaces more cryptic calls like $page->name1234 = 'page-name-in-spanish';

Added new setLanguageValue($language, $value) and getLanguageValue($language) methods to the Inputfield class when LanguageSupport is installed. This provides a nicer API for getting/setting multi-language values with Inputfields. Previously you could only get/set by dealing with value1234 type settings (where 1234 is language ID).

Several new methods have been added to the LanguageTranslator class:
Note: $t = $user->language->translator();

Inputfields

New support for Inputfield header actions have been added to the Inputfield APIs both in Javascript and PHP, see implementation details.

Related to the above, support has been added for Inputfield header dropdown menu actions. These expand upon the existing Inputfield header actions and enable you to have dropdown menus contain more actions within them.

Added a new hookable InputfieldPage::renderPageLabel method.

Added a loading="lazy" option for <img> tags in Textarea fields (TinyMCE, CKEditor) that is inserted at runtime when output formatting is enabled. To turn this on, edit your Textarea field and on the Details tab, see the HTML options.

It was news to me that you can use an <hr> in a <select>, but indeed you can! So we have added support for <hr> elements in InputfieldSelect, InputfieldSelectMultiple, and descending modules that use <select>.

In TinyMCE we have added support for a new "remove all style attributes" option to the Markup Toggle settings.

Our native PasteFilter addition to TinyMCE has been significantly improved, especially when pasting from MS Word.

Added support for custom jQuery UI datepicker settings in InputfieldDatetime. This makes several new options interactively configurable in the field settings (Input tab > Datepicker settings fieldset).

Added new getByField() method to the InputfieldWrapper class. This method enables you to recursively find an Inputfield within the wrapper by specifying the Field (object, name, ID) that it represents. This is useful in cases where the Inputfield name may differ from the Field name that it represents, and you only know the field name.

Added new getByProperty method to the InputfieldWrapper class. This method enables you to recursively find an Inputfield by any configuration property that it provides.

Lots of updates were made to the Inputfield Javascript API (inputfields.js) with several new method additions. A new icon() method can get or set the Inputfield icon. A new header() method returns the InputfieldHeader element for an Inputfield. A new content() method returns the InputfieldContent element, and a new addHeaderAction() method lets you add custom icon actions to any Inputfield.

Added support for matching data attributes in show-if conditions. This is currently supported for Options fields. For example colors.data-if-value=blue.

The Inputfield class has been updated so that dependencies can be supported on many ajax-loaded Inputfields before they are loaded.

Our custom TinyMCE JS (InputfieldTinyMCE.js) has been updated to support "saved" and "saveReady" JS events. This ensures that TinyMCE content gets populated to the original input/textarea elements.

The InputfieldTextTags module has been upgraded to support page selection for pages having digit-only titles (such as "2025").

InputfieldTextTags has also been upgraded to support single-page selection mode. Previously it only supported multi-page selection.

InputfieldSelector (most commonly seen as the Filters in Lister/ListerPro) has been upgraded to support a "children…" selection that works similarly to the "parent…" selection.

Fieldtypes

Several new methods were added to the SelectableOptionArray class, which represents FieldtypeOptions field values (checkboxes, radios, selects, etc.). Now it is much simpler to get, add, and remove options from the selection by referring to the option ID, value or title. The added methods include:

FieldtypeFloat has been updated to support a configurable column type of either 'float' or 'double'. Previously it only supported 'float' unless you manually changed the DB to use double.

And more…

Numerous updates for PHP 8.4 support. The changes required that we also adjust our minimum required PHP version from 7.0 up to 7.1, but with PHP 8.x still recommended.

New HTTP methods for OPTIONS, CONNECT and TRACE have been added to WireHttp.

New LazyCron methods have been added:

Added a new $datetime->strtodate() function which works like strtotime($str, $format) but returns a formatted date string rather than a timestamp.

Updated the $datetime->strtotime() function to accept an inputFormat option which lets you specify the format the given date string is in, for cases when it may not be recognized by PHP based purely on format. Plus a new outputFormat option which lets you specify the format it should return in rather than a timestamp (delegating to the new strtodate method).

We have added support for an experimental $config->userOutputFormatting setting and updated ProcessProfile module to support it.

WireCacheDatabase (the default handler for $cache) has been updated to improve the efficiency of cache maintenance. This also corrects the issue of past caches with an 0000-00-00 expiration date that would [incorrectly] never expire.

The TemplateFile halt() method has been updated to optionally accept string argument to output before halt of template file rendering. For instance: return $this->halt('<h1>Later dude!</h1>'); from a template file.


I know that's a lot to absorb, but we're thrilled to bring this new version to you, and we look forward to the next one too (hopefully it won't take another year!). For more about new versions please visit the ProcessWire Weekly every week, follow the News & Announcements board where new dev branch updates and/or versions are covered just about every week, and subscribe to the Weekly email if you haven't already. Thanks for reading and we hope that you enjoy this new ProcessWire version!

Post a comment

 

PrevPage List Custom Children module

This simple module gives you the ability to customize the parent/child relationship as it appears in the admin page list, enabling child pages to appear under more than one parent. More 

PrevCustom Fields Module

This week we look at a new ProFields module named Custom Fields. This module provides a way to rapidly build out ProcessWire fields that contain any number of subfields/properties within them. More 

Latest news

  • ProcessWire Weekly #557
    In the 557th issue of ProcessWire Weekly we're going to share the latest core development news, introduce a new third party module, and more. Read on!
    Weekly.pw / 12 January 2025
  • ProcessWire 3.0.244 new main/master version
    ProcessWire 3.0.244 is our newest main/master/stable version. It's been more than a year in the making and is packed with tons of new features, issue fixes, optimizations and more. This post covers all the details.
    Blog / 18 January 2025
  • Subscribe to weekly ProcessWire news

“The end client and designer love the ease at which they can update the website. Training beyond how to log in wasn’t even necessary since ProcessWire’s default interface is straightforward.” —Jonathan Lahijani