Search the Community
Showing results for tags 'module'.
-
Hello friends! I have another module for you, which will make your daily work as a Processwire developer easier. Introducing: AppApi This module helps you to create api-endpoints, to which an app or an external service can connect to. Features Simple routing definition Authentication - Three different authentication-mechanisms are ready to use. Access-management via UI Multiple different applications with unique access-rights and authentication-mechanisms can be defined The documentation has become quite extensive, so have a look at the Github repository for details: Installation Defining Applications Api-Keys PHP-Session (Recommended for on-site usage) Single JWT (Recommended for external server-calls) Double JWT (Recommended for apps) Creating Endpoints Output Formatting Error Handling Example: Listing Users Example: Universal Twack Api Routes Page Handlers File Handlers A special thanks goes to Thomas Aull , whose module RestApi was the starting point to this project. This module is not meant to replace this module because it does a great job. But if you want to connect and manage multiple apps or need other authentication methods, this module might help you. I am already very curious about your feedback and would be glad if the module helps you a little bit.
-
SnipWire - Snipcart integration for ProcessWire Snipcart is a powerful 3rd party, developer-first HTML/JavaScript shopping cart platform. SnipWire is the missing link between Snipcart and the content management framework ProcessWire. With SnipWire, you can quickly turn any ProcessWire site into a Snipcart online shop. The SnipWire plugin helps you to get your store up and running in no time. Detailed knowledge of the Snipcart system is not required. SnipWire is free and open source licensed under Mozilla Public License 2.0! A lot of work and effort has gone into development. It would be nice if you could donate an amount to support further development: Status update links (inside this thread) for SnipWire development 2020-07-03 -- SnipWire 0.8.7 (beta) released! Fixes some small bugs and adds an indicator for TEST mode 2020-04-06 -- SnipWire 0.8.6 (beta) released! Adds support for Snipcart subscriptions and also fixes some problems 2020-03-21 -- SnipWire 0.8.5 (beta) released! Improves SnipWires webhooks interface and provides some other fixes and additions 2020-03-03 -- SnipWire 0.8.4 (beta) released! Improves compatibility for Windows based Systems. 2020-03-01 -- SnipWire 0.8.3 (beta) released! The installation and uninstallation process has been heavily revised. 2020-02-08 -- SnipWire 0.8.2 (beta) released! Added a feature to change the cart and catalogue currency by GET, POST or SESSION param 2020-02-03 -- SnipWire 0.8.1 (beta) released! All custom classes moved into their own namespaces. 2020-02-01 -- SnipWire is now available via ProcessWire's module directory! 2020-01-30 -- SnipWire 0.8.0 (beta) first public release! (module just submitted to the PW modules directory) 2020-01-28 -- added Custom Order Fields feature (first SnipWire release version is near!) 2020-01-21 -- Snipcart v3 - when will the new cart system be implemented? 2020-01-19 -- integrated taxes provider finished (+ very flexible shipping taxes handling) 2020-01-14 -- new date range picker, discount editor, order notifiactions, order statuses, and more ... 2019-11-15 -- orders filter, order details, download + resend invoices, refunds 2019-10-18 -- list filters, REST API improvements, new docs platform, and more ... 2019-08-08 -- dashboard interface, currency selector, managing Orders, Customers and Products, Added a WireTabs, refinded caching behavior 2019-06-15 -- taxes provider, shop templates update, multiCURL implementation, and more ... 2019-06-02 -- FieldtypeSnipWireTaxSelector 2019-05-25 -- SnipWire will be free and open source Plugin Key Features Fast and simple store setup Full integration of the Snipcart dashboard into the ProcessWire backend (no need to leave the ProcessWire admin area) Browse and manage orders, customers, discounts, abandoned carts, and more Multi currency support Custom order and cart fields Process refunds and send customer notifications from within the ProcessWire backend Process Abandoned Carts + sending messages to customers from within the ProcessWire backend Complete Snipcart webhooks integration (all events are hookable via ProcessWire hooks) Integrated taxes provider (which is more flexible then Snipcart own provider) Useful Links SnipWire in PW modules directory SnipWire Docs (please note that the documentation is a work in progress) SnipWire @GitHub (feature requests and suggestions for improvement are welcome - I also accept pull requests) Snipcart Website ---- INITIAL POST FROM 2019-05-25 ----
- 231 replies
-
- 28
-
-
-
- shopping cart
- snipcart
-
(and 2 more)
Tagged with:
-
Following the advice of some PW-forum members @gebeer @dotnetic @bernhard @sebibu, I would like to share my first Processwire module with all members. QuickSave: My first attempt at developing a PW module to quickly save a page. What can the module QuickSave do: Quickly save a page edit in the admin and return to the last activity. Adds an extra save button AND shortcuts CMD+s and CTRL+s. QuickSave includes an additional plugin for TinyMCE. The plugin for TinyMCE must be assigned and activated specifically for these textarea fields. (Keyboard input shortcut does not yet work in an iFrame - RTE/iFrame, CKE, etc.) PW-QuickSave-1024-v16.mp4 Installation: To install the module, it simply needs to be copied into the Processwire module directory and then activated in the Processwire admin. Optional: Anyone who uses TinyMCE can activate the keyboard input shortcuts via the configuration as a plugin for TinyMCE. Afterwards it has to be activated for the field (e.g. body). This is the path for the configuration in TinyMCE: /site/modules/QuickSave/tinymce/quicksavetinymce.js QuickSave-TinyMCE-inst.mp4 I have been using the module only as a save button version for some time in a long Processwire page with a strong content and a four-fold nested repeater matrix and it works. The keyboard shortcuts were added because of a request. I was only able to test these on the Mac and hope they also work with Windows browsers. Due to another request, the short notification after saving was added. I hope you like the module and that it helps the moderators to keep a better eye on the areas they are currently working on. Especially with long pages and, for example, a table with many rows, it is very helpful for me not to lose the row when saving. (see the video) Note: The module does not intervene in the Processwire saving process, only the original saving button function is triggered. Please note that the keyborad shortcodes do not work in iframes or CKEditor. UPDATE: New version 0.1.7 added on April 13, 2024. A new combined version without jQuery has been created. Thanks to @dotnetic and all others 🤗. It is now more optimized and further optimizations are planned. Module 0.1.7 Download: QuickSave.zip Feedback on whether the keyboard shortcuts ctrl+s work under MS Windows would be great... 🤗 Thanks and Greetings Chris
- 16 replies
-
- 10
-
-
-
--- Module Directory: https://modules.processwire.com/modules/privacy-wire/ Github: https://github.com/blaueQuelle/privacywire/ Packagist:https://packagist.org/packages/blauequelle/privacywire Module Class Name: PrivacyWire Changelog: https://github.com/blaueQuelle/privacywire/blob/master/Changelog.md --- This module is (yet another) way for implementing a cookie management solution. Of course there are several other possibilities: - https://processwire.com/talk/topic/22920-klaro-cookie-consent-manager/ - https://github.com/webmanufaktur/CookieManagementBanner - https://github.com/johannesdachsel/cookiemonster - https://www.oiljs.org/ - ... and so on ... In this module you can configure which kind of cookie categories you want to manage: You can also enable the support for respecting the Do-Not-Track (DNT) header to don't annoy users, who already decided for all their browsing experience. Currently there are four possible cookie groups: - Necessary (always enabled) - Functional - Statistics - Marketing - External Media All groups can be renamed, so feel free to use other cookie group names. I just haven't found a way to implement a "repeater like" field as configurable module field ... When you want to load specific scripts ( like Google Analytics, Google Maps, ...) only after the user's content to this specific category of cookies, just use the following script syntax: <script type="text/plain" data-type="text/javascript" data-category="statistics" data-src="/path/to/your/statistic/script.js"></script> <script type="text/plain" data-type="text/javascript" data-category="marketing" data-src="/path/to/your/mareketing/script.js"></script> <script type="text/plain" data-type="text/javascript" data-category="external_media" data-src="/path/to/your/external-media/script.js"></script> <script type="text/plain" data-type="text/javascript" data-category="marketing">console.log("Inline scripts are also working!");</script> The data-attributes (data-type and data-category) are required to get recognized by PrivacyWire. the data-attributes are giving hints, how the script shall be loaded, if the data-category is within the cookie consents of the user. These scripts are loaded asynchronously after the user made the decision. If you want to give the users the possibility to change their consent, you can use the following Textformatter: [[privacywire-choose-cookies]] It's planned to add also other Textformatters to opt-out of specific cookie groups or delete the whole consent cookie. You can also add a custom link to output the banner again with a link / button with following class: <a href="#" class="privacywire-show-options">Show Cookie Options</a> <button class="privacywire-show-options">Show Cookie Options</button> I would love to hear your feedback ? CHANGELOG You can find the always up-to-date changelog file here.
- 209 replies
-
- 28
-
-
-
Hi all, Media Manager Next/013 Sorry I haven't posted here in a while. I am currently working on the next version of Media Manager. It will part be refactoring and part be some new (some requested) features. I have been having some very helpful conversations with a number of you. Below are the current plans for the next version. Any other thoughts and/or ideas I should consider? It is a bit of work so I might have to stretch this into several updates (versions). Thanks. New Features Upload from external sources (Amazon, Google, etc.). Point media to external resource (e.g. to a video in YT, Vimeo, etc.). Independently set media title on upload Improve/extend media filter/profiles to MM Inputfields (possibly pick and apply a profile from a list) (thanks @gebeer) PDF thumb preview (thanks @gebeer) Upload and replace media (for single media MM inputfields). API (thanks @MrSnoozles) Any other thoughts.....? Refactor Remove dependency on JqueryFileUpload Remove dependency on jQuery -> use htmx and alpine JS instead. Easier to maintain for me as well as more flexibility. Improved preview of media and their properties. Better preview of media before upload. Redesigned GUI - Intuitive (like GDrive(?)), do away with media menus (use filters instead), need oMedia is just media. Remove/reduce use of modals. Allow grouping of media (link an album) <- not yet confirmed if will be implemented Implement hookable methods to allow easier developer control for those who need advanced/custom control of their MM. A number of reported bug fixes as well. ETA? I cannot give a firm date about this, sorry.
-
Phone Number Fieldtype A new fieldtype to enter phone numbers with 4 integer values for country, area code, number and extension and format the output based on predefined or custom options. StyledOutput The most common usage option will be: echo $page->fieldname //eg. +1 (123) 456-7890 x123 This provides a fully formatted phone number, based on the output format chosen from module's configuration page, or with the format override option (if enabled), when entering a phone number on a page. This is a shortcut that produces the same output as: echo $page->fieldname->formattedNumber //eg. +1 (123) 456-7890 x123 Alternate styled options are: echo $page->fieldname->formattedNumberNoExt: //eg. +1 (123) 456-7890 echo $page->fieldname->formattedNumberNoCtry: //eg. (123) 456-7890 x123 echo $page->fieldname->formattedNumberNoCtryNoExt: //eg. (123) 456-7890 echo $page->fieldname->unformattedNumber: //eg. 11234567890123 echo $page->fieldname->unformattedNumberNoExt: //eg. 11234567890 echo $page->fieldname->unformattedNumberNoCtry: //eg. 1234567890123 echo $page->fieldname->unformattedNumberNoCtryNoExt: //eg. 1234567890 Of course the actual output is determined by the selected format output Raw Output You can output the values for the component parts of the phone number like this: echo $page->fieldname->country; echo $page->fieldname->area_code; echo $page->fieldname->number; echo $page->fieldname->extension; Output for mobile compatibility To get iOS and other mobile platforms to recognize numbers and be able to automatically dial them, use something like this: echo '<a href="tel:+'.$page->fieldname->unformattedNumberNoExt.'">'.$page->fieldname->formattedNumber.'</a>'; Selectors for searching The component parts can be used in selectors like this: $pages->find("phone.area_code=123"); Field Settings There is a field settings for the width of the inputs in pixels. There is a field settings for the width of the inputs in pixels. You can also choose whether to display the country and extension fields for input. Off by default. There is an additional checkbox that determines whether there is an option to override the default format option on a per entry basis, which will be useful when styling phone numbers from different countries on the one website. Off by default. Custom formatting options On the module's configuration page you can choose from predefined formats, or create custom formats using syntax like this: {+[phoneCountry] }{([phoneAreaCode]) }{[phoneNumber,0,3]-}{[phoneNumber,3,4]}{ x[phoneExtension]} which generates: +1 (123) 456-7890 x123 Each component is surrounded by { } The names of the component parts are surrounded by [ ] Two comma separated numbers after the component name are used to get certain parts of the number using php's substr function, allowing for complete flexibility. Anything outside the [ ] is used directly: +,-,(,),x, spaces, etc - whatever every you want to use. There are lots of complicated rules around numbers changing when dialed from different locations. A simple example is for Australia. When dialing from within Australia, area codes start with a 0, but when dialing from another country, the 0 must be omitted. You can write a simple format to handle this. The following truncates the first number from an Australian two digit area code: {+[phoneCountry] }{([phoneAreaCode,1,1]) }{[phoneNumber,0,4] }{ [phoneNumber,4,4]}{ x[phoneExtension]} which generates: +1 (7) 1234 5678 x123 even though the full "07" is stored in the area code field. Where to get Available from github: https://github.com/adrianbj/FieldtypePhone And the modules directory: http://modules.processwire.com/modules/fieldtype-phone/ To Do Need to increase the number of pre-defined formats. There seem to be so many options and no real standards, so I thought rather than create a huge list of options that no-one will use, I thought I'd wait and get you guys to contribute them as you need them. Either post your formats here, or send me a PR on github and I'll add them. How to install Download and place the module folder named "FieldtypePhone" in: /site/modules/ In the admin control panel, go to Modules. At the bottom of the screen, click the "Check for New Modules" button. Now scroll to the FieldtypePhone module and click "Install". The required InputfieldPhone will get installed automatically. Create a new Field with the new "Phone" Fieldtype. Choose a Phone Output Format from the details tab. Acknowledgments This module uses code from Soma's DimensionFieldtype and the core FieldtypeDatetime module - thanks guys for making it so easy.
- 134 replies
-
- 15
-
-
This module adds CSV import and export functionality to Profields Table fields on both the admin and front-end. http://modules.processwire.com/modules/table-csv-import-export/ https://github.com/adrianbj/TableCsvImportExport Access to the admin import/export for non-superusers is controlled by two automatically created permissions: table-csv-import and table-csv-export Another permission (table-csv-import-overwrite) allows you to control access to the overwrite option when importing. The overwrite option is also controlled at the field level. Go to the table field's Input tab and check the new "Allow overwrite option" if you want this enabled at all for the specific field. Please consider limiting import overwrite option to trusted roles as you could do a lot of damage very quickly with the overwrite option Front-end export of a table field to CSV can be achieved with the exportCsv() method: // export as CSV if csv_export=1 is in url if($input->get->csv_export==1){ $modules->get('ProcessTableCsvExport'); // load module // delimiter, enclosure, file extension, multiple fields separator, names in first row $page->fields->tablefield->exportCsv('tab', '"', 'tsv', '|', true); } // display content of template with link to same page with appended csv_export=1 else{ include("./head.inc"); echo $page->tablefield->render(); //render table - not necessary for export - just displaying the table echo "<a href='./?csv_export=1'>Export Table as CSV</a>"; //link to initiate export include("./foot.inc"); } Front-end import can be achieved with the importCsv() method: $modules->get('TableCsvImportExport'); // load module // data, delimiter, enclosure, convert decimals, ignore first row, multiple fields separator, append or overwrite $page->fields->tablefield->importCsv($csvData, ';', '"', true, false, '|', 'append'); Please let me know if you have any problems, or suggestions for improvements. Enjoy!
-
Hey there, born out of a personal need I've implement a lightweight version of @Robin S' Hanna Code Dialog module for TinyMCE. In a bout of creativity, I've named it HannaCodeDialogTiny This module is still in alpha state and needs some extensive testing. If you encounter any problems, please open an issue on GitHub. It has no select options, descriptions or cheat sheets (yet), and it doesn't cope well with nested Hanna Codes. What it does have is the Insert Hanna Code dropdown in the TinyMCE menu bar with dialog-based insertion, non-editable Hanna Codes in the editor, double click on existing codes for editing in a dialog. Hanna Codes are also highlighted, and you can drag and drop them around. The dropdown: Double click on any highlighted Hanna Code: Fill in your values: The Hanna Code has been changed: Have fun!
-
So I stumbled over the request to allow limiting templates to be used only once under every parent page in this thread and found that this would actually come in handy (also in a site I've built). The code can be found on github and soon also in the module repo. After installation, you'll find a new checkbox "Only once per parent" in the family tab when editing a template.
-
Just launched my first public Module 🎉 This module allows ProcessWire to send transactional emails via Brevo. Download the latest version: https://github.com/ttttim0709/WireMailBrevo Installation Copy the WireMailBrevo directory into your site/modules/ directory. In the ProcessWire admin, go to Modules > Refresh. Click "Install" next to the WireMailBrevo module. Usage Example usage: $email = $mail->new(); $email->to = 'recipient@somedomain.com'; $email->subject = 'Test #1'; $email->body = 'An example email'; $email->send(); Use of Versions: Check the Brevo dev section for more information about Message versions $email->versions([ [ 'to' => [ [ 'email' => 'bob@example.com', 'name' => 'Bob Anderson' ], [ 'email' => 'anne@example.com', 'name' => 'Anne Smith' ], ], 'subject' => 'This is my version subject line', ], [ 'to' => [ [ 'email' => 'jim@example.com', 'name' => 'Jim Stevens' ] ], 'htmlContent' => "<!DOCTYPE html><html><body><h1>Modified header!</h1><p>This is still a paragraph</p></body></html>", ], ]); Configuration After installing the module, you can configure it by going to the module settings page. You need to provide the following configuration options: Brevo API Key: Obtain this key from your Brevo account settings. Sender Email Address: The email address to be used as the sender. Sender Name: The name associated with the sender's email address.
-
Module: Auto Smush https://github.com/matjazpotocnik/AutoSmush Optimize/compress images. In Automatic mode images that are uploaded can be automatically optimized. Variations of images that are created on resize/crop and admin thumbnails can also be automatically optimized. In Manual mode "Optimize image" link/button will be present. This allows manual optimization of the individual image or variation. In Bulk mode all images, all variations or both can be optimized in one click. Will process images sitewide. Two optimization "engines" are avaialable. reShmush.it is a free (at the moment) tool that provides an online way to optimize images. This tool is based on several well-known algorithms such as pngquant, jpegoptim, optipng. Image is uploaded to the reSmush.it web server, then optimized image is downloaded. There is a 5 MB file upload limit and no limit on number of uploaded images. "Local tools" is set of executables on the server for optimizing images: optipng, pngquant, pngcrush, pngout, advpng, gifsicle, jpegoptim, jpegtran. Binaries for Windows are provided with this module in windows_binaries folder, copy them somewhere on the PATH environment variable eg. to C:\Windows. Similar modules: JpegOptimImage by Jonathan Dart: https://processwire.com/talk/topic/6667-jpegoptimimage/ TinyPNG Image Compression by Roope: https://github.com/BlowbackDesign/TinyPNG ProcessImageMinimize by conclurer: https://processwire.com/talk/topic/5404-processimageminimize-image-compression-service-commercial/ Forum discusion: https://processwire.com/talk/topic/12111-crowdfunded-tinypng-integration-module/ Module created by Roland Toth (@tpr).
-
Field Initial Value For most field types, allows the definition of an initial value that is automatically set when pages are created. The initial value can be set in template context if you want a different initial value in different templates. Example for a "Countries" Page Reference field using AsmSelect: Example with explanatory notes in a CKEditor field: Differences from "Default value" The core allows setting a "Default value" for certain field types. The "Initial value" setting added by this module is different from the "Default value" setting in the following ways: The "Default value" is a setting that applies only to the inputfield, meaning that the value is shown in the inputfield by default but is not stored until you save the page. By contrast, the "Initial value" is automatically saved to the page when the page is first created. Related to point 1, when a page is created via the API rather than in the ProcessWire admin the "Initial value" is saved to the page but the "Default value" is not. The "Default value" has no effect when a field is not "required", but the "Initial value" is set for both required and not required fields. Related to point 3, a user can empty a field that had an "Initial value" applied but a field with a "Default value" set cannot be emptied. The "Initial value" setting is available for more field types than "Default value". Supported field types The following field types are supported, along with any types that extend them: FieldtypeText (includes types that extend it such as Textarea, CKEditor, URL, etc.) FieldtypeDatetime FieldtypeInteger FieldtypeDecimal FieldtypeFloat FieldtypePage (with all core inputfield types) FieldtypeCheckbox FieldtypeOptions (with all core inputfield types) FieldtypeToggle FieldtypeSelector FieldtypeMultiplier (ProField) FieldtypeCombo (ProField, only supported when File and Image subfields are not used) FieldtypeStars (third-party module) If you want to try field types beyond this you can define additional types in the module config, but your mileage may vary. Unsupported field types It's not possible to set an initial value for these field types, along with any types that extend them: FieldtypeFile (and FieldtypeImage) FieldtypeRepeater (includes types that extend it such as Repeater Matrix and Fieldset Page) FieldtypePageTable FieldtypeTable (ProField) Notes Seeing as the initial value is defined in the field config it has no idea of the current page - for the purposes of rendering the initial value inputfield the home page is supplied as a dummy page. This probably isn't an issue in most cases but it might have an effect for some Page Reference fields if they use the current page to limit the selectable pages. https://github.com/Toutouwai/FieldInitialValue https://processwire.com/modules/field-initial-value/
-
Here's a small module I wrote a few years ago and was asked to share in the module repo. TextformatterImgDataUri This Textformatter checks all images in the field's markup for images under a certain size and converts those from links to data URLs, i.e. it embeds the image data itself. This can be handy when you cache whole pages and want to cut down on the number of requests. Original post with the module code:
-
Hi everyone, This is the new official thread for the module that was previewed some time ago here: https://processwire.com/talk/topic/14117-module-settings-import-export/ Big thanks to @Robin S for help testing and feature suggestions! http://modules.processwire.com/modules/module-settings-import-export/ https://github.com/adrianbj/ModuleSettingsImportExport Module features Ability to copy and paste settings from one PW install to another Optional automatic backup of module settings on uninstall and ability to restore settings if you reinstall the module Backup current settings at any time Restore backed up settings at any time Import option checks module name and version number and warns if importing settings from a different version As always, let me know if you find any problems or have any suggestions!
- 16 replies
-
- 20
-
-
This module adds a "SEO" tab to every page where you can define a special title, description, keywords, etc. Try it http://aluminum-j4f.lightningpw.com/processwire/ Name: demo Pass: demo123 How to use You can choose between include automatically or use the following methods: $config->seo // includes all the default values and configuration settings // e.g.: $config->seo->title $config->seo->keywords $page->seo // includes all the default values mixed with the page related seo data // e.g.: $page->seo->title $page->seo->keywords // for rendering: $page->seo->render . . Screenshot Download You can download it in the modules repository: http://modules.processwire.com/modules/markup-seo/
-
ProcessWire Dashboard Download You can find the latest release on Github. Documentation Check out the documentation to get started. This is where you'll find information about included panel types and configuration options. Custom Panels The goal was to make it simple to create custom panels. The easiest way to do that is to use the panel type template and have it render a file in your templates folder. This might be enough for 80% of all use cases. For anything more complex (FormBuilder submissions? Comments? Live chat?), you can add new panel types by creating modules that extend the DashboardPanel base class. Check out the documentation on custom panels or take a look at the HelloWorld panel to get started. I'm happy to merge any user-created modules into the main repo if they might be useful to more than a few people. Roadmap Panel types Google Analytics Draft At a glance / Page counter 404s Layout options Render multiple tabs per panel Chart panel load chart data from JS file (currently passed as PHP array)
-
This module facilitates quick batch creation (titles only or CSV import for other fields), editing, sorting, deletion, and CSV export of all children under a given page. You can even provide an alternate parent page which allows for editing of an external page tree. http://modules.processwire.com/modules/batch-child-editor/ https://github.com/adrianbj/BatchChildEditor The interface can be added to the Children Tab, or in a new dedicated tab, or placed inline with other fields in the Content tab. Various modes allow you to: Lister - Embeds a customized Lister interface. Installation of ListerPro will allow inline ajax editing of displayed fields. Edit - This allows you to rename existing child pages and add new child pages. It is non-destructive and so could be used on child pages that have their own children or other content fields (not just title). It includes the ability to quickly sort and delete pages and change page templates. Also allows full editing of each page via a modal dialog by clicking on the page name link. This is my preferred default setup - see how it replaces the default Children/Subpages with an easily addable/editable/sortable/renamable/deletable list. Note that the edit links open each child page in a modal for quick editing of all fields. Add - adds newly entered page titles as child pages to the list of existing siblings. You could create a list of pages in Word or whatever and just paste them in here and viola! This screenshot shows the editor in its own tab (name is configurable) and shows some of the CSV creation options. Update and Replace modes look fairly similar but show existing page titles. Update - Updates the titles (and any other fields if you enter CSV data) for the existing pages and adds any additionally entered pages. Replace - Works similarly to Add, but replaces all the existing children. There are checks that prevent this method working if there are any child pages with their own children or other content fields that are not empty. This check can be disabled in the module config settings, but please be very careful with this. Export to CSV - Generates a CSV file containing the fields for all child pages. Fields to be exported can to fixed or customizable by the user. Also includes an API export method. Populating fields on new pages In Add, Update, and Replace modes you can enter CSV formatted rows to populate all text/numeric fields, making for an extremely quick way of creating new pages and populating their content fields. Predefined Field Pairings Like the field connections setup from Ryan's CSV Importer, but defined ahead of time so the dev controls what columns from the CSV pair with which PW fields. This is especially powerful in Update mode giving editors the ability to periodically import a CSV file to update only certain fields on a entire set of child pages. These pairings also allow for importing fieldtypes with subfields - verified to work for Profields Textareas and MapMarker fields, but I think should work for most others as well - let me know if you find any that don't work. Access permission This module requires a new permission: "batch-child-editor". This permission is created automatically on install and is added to the superuser role, but it is up to the developer to add the permission to other roles as required. Config Settings This module is HIGHLY configurable down to setting up custom descriptions and notes for your editors. You define one config globally for the site and then optionally you can define completely custom configurations for each page tree parent on your site. There are too many settings to bother showing here - you really just need to look through all the options and play around with them!
- 498 replies
-
- 22
-
-
Hello all- FieldtypeFormSelect does what the post title says it does. Lets you create a field to select a form created by the FormBuilder pro module. This type of field (or some variation of it) has probably been done elsewhere but I put this together with a few extra considerations for flexibility and utility. When creating a form select field you can choose what forms will be present and how their names will be shown. Let's go to the pictures: A form select field: Creating fields to choose from specific forms? You have options. You can also create a field that will only include forms that begin, include, or end with a specific string. This allows you to create a field once, then use form names to help group them together and add/remove them from form select elements without editing the field. This is also a pretty simple way to allow end users to create forms that will be selectable without having to ever edit a field configuration. For example, this field will only allow you to choose forms having names enting with "request", so "customer-support-request" and "consultation-request" will be included, but "newsletter-signup" and "call-to-action" won't. You can also choose how the form names will be presented in the select element. They can be shown as they are originally named, as spaced words, or as capitalized/spaced words. So, how does this field work? Form select fields store the ID of the form you select, but it also has a nice trick for working with forms in your markup too. FieldtypeFormSelect makes use of ProcessWire's built-in field rendering to keep things simple. Let's go to the code. <?php $page->select_a_form; // => Outputs the form ID, or null if no form has been selected // You could do this to output your form markup echo $forms->render($page->select_a_form); // Or you can do it this way. If a form has been selected the markup will be output to the page, if no form is selected, the output will be null. echo $page->render('select_a_form'); The fields you create will always be up-to-date with the forms that have been created in FormBuilder. This module also keeps things tidy- if a form is deleted that has been selected in one or more fields, on one or more pages, the values for those fields will be set to null so you won't experience any reference errors to form IDs that no longer exist. My primary use is to have a form select field available for blocks created in the RockPageBuilder module by @bernhard. I wanted each section on the page to contain an option to include a call to action button that can be a link to a page, a link to another URL, or that can open a modal with a call to action form to capture leads and visitor contact information. It's a great way to easily add flexibility and give some extra power to the end user when considering what they want visitors to do when browsing their website. RockPageBuilder is not required, but makes for a useful example! Protip for website designers- in my experience and empirical study of conversion analytics for sites that I've built, buttons located within sections of content on the page captured more leads and outperformed a call-to-action button in the page header, the call-to-action form at the bottom of the page, and forms located on a "Contact Us" page- by far. The true purpose of this field is to get the right forms in the right places quickly and easily without any need to work around markup output strategies or short codes. Contributions on Github are welcome if there's some extra functionality anyone wants to add that makes sense. Please let me know if you run into any bugs as well, when there's some extra usage and testing I'll submit it to the modules directory. Hope you find it useful! https://github.com/SkyLundy/FieldtypeFormSelect
- 4 replies
-
- 17
-
-
-
- forms
- formbuilder
-
(and 2 more)
Tagged with:
-
This module is improved and extended successor to Version Control For Text Fields. It handles everything it's predecessor did -- providing basic version control features for page content -- and quite a bit more. Download or clone from GitHub: https://github.com/teppokoivula/VersionControl. This module requires ProcessWire 2.4.1 or later, mostly because of the file features, which require certain Pagefile and Pageimage methods to be hookable. There's no sensible way around this limitation; for those stuck with < 2.4.1, Version Control For Text Fields will remain a viable option. What does it do? While editing pages, fields with old revisions available show up with a new icon in their header bars. By hovering that icon you get a list of available revisions and by clicking any one of those the value of that particular field is reverted to that revision. No changes are made to page until you choose a revision and save the page, which means that you can keep switching between revisions to get an idea what's really changed without inadvertently causing any content to change. The module also adds a History tab to page edit. This tab opens a view to the history of current page in the form of "revisions" -- each of which is a group of changes to page fields processed during one page save (similar to revisions in various source control applications). There are three actions you can perform on these revisions: adding comments, live previewing what the page might've looked in that revision and restoring the page to specific revision. One specific feature that has been a big thing for me personally is support for file (and image) fields, as the original version control module felt rather incomplete without it. I'm hoping to take this a lot further performance, stability and feature wise, but as it stands right now, it's already included here and should be fully functional. Watch the video preview here I prepared a little screencast outlining most of this: http://youtu.be/AkEt3W7meic. Considering that it was my first screencast ever, I'd like to think that it wasn't that bad.. but I might give it another shot at some point, this time planning a bit before hitting "record" Upgrading from Version Control For Text Fields For those already using Version Control For Text Fields, I've added something extra. If you upgrade that module to it's latest version, you should see a new checkbox in it's settings screen saying "Don't drop tables during uninstall". If you check this, uninstall the module and then remove it's files (this is required in order to install Version Control), your old data should be automagically imported to Version Control. Import has only been tested with limited amounts of demo data. Proper tests are yet to come, so please be careful with this feature! Update, 21.6.2015: as of today, this module is no longer in beta. While all the regular warnings still apply (making changes, including installing any new modules, on a production site should always be considered risky) Version Control has gone through pretty extensive testing, and should be as stable as any other module out there.
- 163 replies
-
- 37
-
-
-
Hello community! I want to share a new module I've been working on that I think could be a big boost for multi-language ProcessWire sites. Fluency is available in the ProcessWire Modules Directory and on Github Some background: I was looking for a way for our company website to be efficiently translated as working with human translators was pretty laborious and a lack of updating content created a divergence between languages. I, and several other devs here, have talked about translation integrations and have recognized the power that DeepL has. DeepL is an AI deep learning powered service that delivers translation quality beyond any automated service available. After access to the API was opened up to the US, I built Fluency, a third-party translation service integration for ProcessWire. Fluency brings automated translation to every multi-language field in the admin, and also provides a translation tool allowing the user to translate their text to any language without it being inside a template's field. With Fluency you can: Translate any plain textarea or text input Translate any TinyMCE or CKEditor (inline, or regular) Translate page names/URLs Translate in-template translation function wrapped strings Translate modules, both core and add-ons Installation and usage is completely plug and play. Whether you're building a new multi-language site, need to update a site to multi-language, or simply want to stop manually translating a site and make any language a one-click deal, it could not be easier to do it. Fluency works by having you match the languages configured in ProcessWire to those offered by the third party translation service you choose. Currently Fluency works with DeepL and Google Cloud Translation. Let's break out the screenshots... When the default language tab is shown, a message is displayed to let users know that translation is available. Clicking on each tab shows a link that says "Translate from English". Clicking it shows an animated overlay with the word "Translating..." cycling through each language and a light gradient shift. Have a CKEditor field? All good. Fluency will translate it and use DeepL's ability to translate text within HTML tags. CKEditor fields can be translated as easily and accurately as text/textarea fields. Repeaters and AJAX created fields also have translation enabled thanks to a JavaScript MutationObserver that searches for multi-language fields and adds translation as they're inserted into the DOM. If there's a multi-language field on the page, it will have translation added. Same goes for image description fields. Multi-language SEO friendly images are good to go. Creating a new page from one of your templates? Translate your title, and also translate your page name for native language URLs. (Not available for Russian, Chinese, or Japanese languages due to URL limitations). These can be changed in the "Settings" tab for any page as well so whether you're translating new pages or existing pages, you control the URLs everywhere. Language configuration pages are no different. Translate the names of your languages and search for both Site Translation Files (including all of your modules) Translate all of the static text in your templates as well. Notice that the placeholders are retained. DeepL is pretty good at recognizing and keeping non-translatable strings like that. If it is changed, it's easy to fix manually. Fluency adds a "Translate" item to the CMS header. When clicked this opens up a modal with a full translation tool that lets the user translate any language to any language. No need to leave the admin if you need to translate content from a secondary language back to the default ProcessWire language. There is also a button to get the current API usage statistics. DeepL account owners can set billing limitations via character count to control costs. This may help larger sites or sites being retrofitted keep an eye on their usage. Fluency can be used by users having roles given the fluency-translate permission. It couldn't be easier to add Fluency to your new or existing website. Simply add your API key and you're shown what languages are currently available for translation from/to as provided by DeepL. This list and all configuration options are taken live from the API so when DeepL releases new languages you can add them to your site without any work. No module updates, just an easy configuration. Just match the language you configured in ProcessWire to the DeepL language you want it to be associated with and you're done. Fluency also allows you to create a list of words/phrases that will not be translated which can prevent items such as brands and company names from being translated when they shouldn't Please note that the browser plugin for Grammarly conflicts with Fluency (as it does with many web applications). To address this issue it is recommended that you disable Grammarly when using Fluency, or open the admin to edit pages in a private window where Grammarly may not be loaded. This is a long-standing issue in the larger web development community and creating a workaround may not be possible. If you have insight as to how this may be solved please visit the Github page and file a bugfix ticket. Enhancements Translate All Fields On A Page Compatibility with newest rewrite of module is in progress... An exciting companion module has been written by @robert which extends the functionality of Fluency to translate all fields on a page at once. The module has several useful features that can make Fluency even more useful and can come in handy for translating existing content more quickly. I recommend reading his comments for details on how it works and input on best practices later in this thread. Get the module at the Github repo: https://github.com/robertweiss/ProcessTranslatePage Requirements: ProcessWire 3.0+ UIKit Admin Theme That's Fluency in a nutshell. A core effort in this module is to create it so that there is nothing DeepL related hard-coded in that would require updating it when DeepL offers new languages. I would like this to be a future-friendly module that doesn't require developer work to keep it up-to-date. The Module Is Free This is my first real module and I want to give it back to the community as thanks. This is the best CMS I've worked with (thank you Ryan & contributors) and a great community (thank you dear reader). DeepL Developer Accounts In addition to paid Pro Developer accounts, DeepL now offers no-cost free accounts. Now all ProcessWire developers and users can use Fluency at no cost. Learn more about free and paid accounts by visiting the DeepL website. Sign up for a Developer account, get an API key, and start using Fluency. Download & Feedback Download the latest version here https://github.com/SkyLundy/Fluency-Translation/archive/main.zip Github repository: https://github.com/SkyLundy/Fluency-Translation File issues and feature requests here (your feedback and testing is greatly appreciated): https://github.com/SkyLundy/Fluency-Translation/issues Thank you! ¡Gracias! Ich danke Ihnen! Merci! Obrigado! Grazie! Dank u wel! Dziękuję! Спасибо! ありがとうございます! 谢谢你!
- 189 replies
-
- 41
-
-
-
- translation
- language
-
(and 1 more)
Tagged with:
-
NOTE: This thread originally started in the Pub section of the forum. Since we moved it into the Plugin/Modules section I edited this post to meet the guidelines but also left the original content so that the replies can make sense. ProcessGraphQL ProcessGraphQL seamlessly integrates to your ProcessWire web app and allows you to serve the GraphQL api of your existing content. You don't need to apply changes to your content or it's structure. Just choose what you want to serve via GraphQL and your API is ready. Warning: The module supports PHP version >= 5.5 and ProcessWire version >= 3. Links: Zip Download Github Repo ScreenCast PW modules Page Please refer to the Readme to learn more about how to use the module. Original post starts here... Hi Everyone! I became very interested in this GraphQL thing lately and decided to learn a bit about it. And what is the better way of learning a new thing than making a ProcessWire module out of it! For those who are wondering what GraphQL is, in short, it is an alternative to REST. I couldn't find the thread but I remember that Ryan was not very happy with the REST and did not see much value in it. He offered his own AJAX API instead, but it doesn't seem to be supported much by him, and was never published to official modules directory. While ProcessWire's API is already amazing and allows you to quickly serve your content in any format with less than ten lines of code, I think it might be convenient to install a module and have JSON access to all of your content instantly. Especially this could be useful for developers that use ProcessWire as a framework instead of CMS. GraphQL is much more flexible than REST. In fact you can build queries in GraphQL with the same patterns you do with ProcessWire API. Ok, Ok. Enough talk. Here is what the module does after just installing it into skyscrapers profile. It supports filtering via ProcessWire selectors and complex fields like FieldtypeImage or FieldtypePage. See more demo here The module is ready to be used, but there are lots of things could be added to it. Like supporting any type of fields via third party modules, authentication, permissions on field level, optimization and so on. I would love to continue to develop it further if I would only know that there is an interest in it. It would be great to hear some feedback from you. I did not open a thread in modules section of the forum because I wanted to be sure there is interest in it first. You can install and learn about it more from it's repository. It should work with PHP >=5.5 and ProcessWire 3.x.x. The support for 2.x.x version is not planned yet. Please open an issue if you find bugs or you want some features added in issue tracker. Or you can share your experience with the module here in this thread.
-
FieldtypeMatrix and InputfieldMatrix Modules Directory: http://modules.processwire.com/modules/fieldtype-matrix/ GitHub: https://github.com/kongondo/FieldtypeMatrix The module Matrix enables you to save data from a 2D-Matrix table. The rows and columns of the matrix table are made up of pages retrieved via a ProcessWire selector or via a page field selection of parent pages. The matrix values are made up of the data input in the matrix cells, i.e. the 'intersection of rows and columns'. Example Usage You have Products whose prices vary depending on colour, size, material, etc. Using the Fieldtype, you can create a table with rows made up of colours and columns made up of sizes the combination of each making up their respective values (in this case price). So rather than creating multiple text fields to do the following: Colour Size Price Red Small £10 Red Medium £20 Red Large £30 Red X-large £35 Green Small £9 Green Medium £15 Etc... You can instead have the following in one field: Small Medium Large X-Large Red £10 £20 £30 £35 Green £9 £15 Blue Etc... Yellow Purple If you set a selector in the Field's settings, to retrieve pages to build your matrix's rows and columns, it follows that all pages using the template the Fieldtype is attached to will have identical rows and columns. In some cases, this could be the intention. For instance, you might have 'Car' pages, e.g. Audi, Volvo, Ford, Citroen, Mazda, BWM, etc., each of which uses a 'Cars' template that has a single FiedltypeMatrix called 'car_attributes'. If you set a selector to build the Fieldtype's rows and columns, your users can easily compare the cars based on a combination of different values. The following matrix table best illustrates this: Type Engine Size Fuel Efficiency Carbon Emissions Warranty Road Tax Price 1994 Audi brand 1 values, etc. 2000 Audi brand 2 2006 Audi brand 3 2012 Audi brand 4 Each of your car pages would have similar matrices. This allows you to make easy but powerful queries. Such a setup allows you to compare within and across car brands. Say you wanted to find out which car(s) offered the best value for money given certain parameters such as warranty, emissions etc. You can easily make such comparisons (see code below). You can also compare within one car type, e.g. which brand of BMWs does best in what area...The possibilities are endless. In the database, Rows and column pages data are stored as their respective page->id. Matrix-values store any data (varchar(255)). If instead you wanted a template's pages to each have a matrix built of different rows and columns, you would have to name a Multiple Page Field (attached to the same template as the as your matrix field) in the matrix field's settings. When editing those pages, your matrix table's rows and columns will be built using the published children pages of the 2 pages you select in the Multiple page field.. The module allows the creation of matrix tables of any sizes (rows x columns). The rows and columns dynamically grow/shrink depending on the addition of row/column pages that match what you set in the matrix field's settings (see its 'Details Tab'). Please note that, if such pages are deleted/trashed/hidden/unpublished, their data (and presence) in the matrix are also deleted. Entering values in the matrix You have three choices: Manually entry Uploading a comma delimited (CSV) file. This can be delimited by other characters (tab, pipe, etc); not just commas Copy-pasting CSV values. (Tip: you can copy paste directly from an Excel spreadsheet. Such values will be 'tab-delimited'). In addition, if your server supports it, in the field's settings, you can enable the use of MySQL's fast LOAD DATA INFILE to read and save your submitted CSV values. Note that for large tables, you may have to increase your PHP's max_input_vars from the default 1000 otherwise PHP will timeout/return an error and your values will not be saved. I have successfully tested the module with up to ~3000+ values (10x350 table), the Fieldtype is not really optimised (nor was it intended) to handle mega large matrix tables. For such, you might want to consider other strategies. Install Install as any other module. API + Output A typical output case for this module would work like this: The matrix's rows, columns and values are subfields of your matrix's field. So, if you created a field called 'products' of the type FieldtypeMatrix, you can access as: product.row, product.column and product.value respectively foreach($page->matrix as $m) { echo " <p> Colour: $m->row<br /> Size: $m->column<br /> Price: $m->value </p> "; } Of if you want to output a matrix table in the frontend: //create array to build matrix $products = array(); foreach($page->matrix as $m) $products[$m->row][$m->column] = $m->value; $tbody ='';//matrix rows $thcols = '';//matrix table column headers $i = 0;//set counter not to output extraneous column label headers $c = true;//set odd/even rows class foreach ($products as $row => $cols) { //matrix table row headers (first column) $rowHeader = $pages->get($row)->title; $tbody .= "<tr" . (($c = !$c) ? " class='even' " : '') . "><td class='MatrixRowHeader'>" . $rowHeader . "</td>"; $count = count($cols);//help to stop output of extra/duplicate column headers foreach ($cols as $col => $value) { //matrix table column headers $columnHeader = $pages->get($col)->title; //avoid outputting extra duplicate columns if ($i < $count) $thcols .= "<th class='MatrixColumnHeader'>" . $columnHeader . "</th>"; //output matrix values $currency = $value > 0 ? '£' : ''; $tbody .= "<td>" . $currency . $value . "</td>"; $i++; } $tbody .= "</tr>"; } //final matrix table for output $tableOut = "<table class='Matrix'> <thead> <tr class=''> <th></th> $thcols </tr> </thead> <tbody> $tbody </tbody> </table>"; echo $tableOut; The module provides a default rendering capability as well, so that you can also do this (below) and get a similar result as the first example above (without the captions). echo $page->matrix; Or this foreach($page->matrix as $m) { echo $m; } Finding matrix items The fieldtype includes indexed row, column and value fields. This enables you to find matrix items by either row types (e.g. colours) or columns (e.g. sizes) or their values (e.g. price) or a combination of some/all of these. For instance: //find all pages that have a matrix value of less than 1000 $results = $pages->find("products.value<1000"); //find some results in the matrix (called products) of this page $results = $page->products->find("column=$country, value=Singapore");//or $page->products->find("column=$age, value>=25"); //$country and $age would be IDs of two of your column pages Other more complex queries are possible, e.g. find all products that are either red or purple in colour, come in x-large size and are priced less than $50. Credits @Ryan on whose Fieldtype/InptufieldEvents this is largely based @charger and @sakkoulas for their matrix ideas Screens Field Details Tab Inputfield Larger matrix table Example output
-
Hey folks! Took a couple of late nights, but managed to turn this old gist of mine into a proper module. The name is SearchEngine, and currently it provides support for indexing page contents (into a hidden textarea field created automatically), and also includes a helper feature ("Finder") for querying said contents. No fancy features like stemming here yet, but something along those lines might be added later if it seems useful (and if I find a decent implementation to integrate). Though the API and selector engine make it really easy to create site search pages, I pretty much always end up duplicating the same features from site to site. Also – since it takes a bit of extra time – it's tempting to skip over some accessibility related things, and leave features like text highlighting out. Overall I think it makes sense to bundle all that into a module, which can then be reused over and over again ? Note: markup generation is not yet built into the module, which is why the examples below use PageArray::render() method to produce a simple list of results. This will be added later on, as a part of the same module or a separate Markup module. There's also no fancy JS API or anything like that (yet). This is an early release, so be kind – I got the find feature working last night (or perhaps this morning), and some final tweaks and updates were made just an hour ago ? GitHub repository: https://github.com/teppokoivula/SearchEngine Modules directory: https://modules.processwire.com/modules/search-engine/ Demo: https://wireframe-framework.com/search/ Usage Install SearchEngine module. Note: the module will automatically create an index field install time, so be sure to define a custom field (via site config) before installation if you don't want it to be called "search_index". You can change the field name later as well, but you'll have to update the "index_field" option in site config or module settings (in Admin) after renaming it. Add the site search index field to templates you want to make searchable. Use selectors to query values in site search index. Note: you can use any operator for your selectors, you will likely find the '=' and '%=' operators most useful here. You can read more about selector operators from ProcessWire's documentation. Options By default the module will create a search index field called 'search_index' and store values from Page fields title, headline, summary, and body to said index field when a page is saved. You can modify this behaviour (field name and/or indexed page fields) either via the Module config screen in the PocessWire Admin, or by defining $config->SearchEngine array in your site config file or other applicable location: $config->SearchEngine = [ 'index_field' => 'search_index', 'indexed_fields' => [ 'title', 'headline', 'summary', 'body', ], 'prefixes' => [ 'link' => 'link:', ], 'find_args' => [ 'limit' => 25, 'sort' => 'sort', 'operator' => '%=', 'query_param' => null, 'selector_extra' => '', ], ]; You can access the search index field just like any other ProcessWire field with selectors: if ($q = $sanitizer->selectorValue($input->get->q)) { $results = $pages->find('search_index%=' . $query_string . ', limit=25'); echo $results->render(); echo $results->renderPager(); } Alternatively you can delegate the find operation to the SearchEngine module: $query = $modules->get('SearchEngine')->find($input->get->q); echo $query->resultsString; // alias for $query->results->render() echo $query->pager; // alias for $query->results->renderPager() Requirements ProcessWire >= 3.0.112 PHP >= 7.1.0 Note: later versions of the module may require Composer, or alternatively some additional features may require installing via Composer. This is still under consideration – so far there's nothing here that would really depend on it, but advanced features like stemming most likely would. Installing It's the usual thing: download or clone the SearchEngine directory into your /site/modules/ directory and install via Admin. Alternatively you can install SearchEngine with Composer by executing composer require teppokoivula/search-engine in your site directory.
- 273 replies
-
- 32
-
-
-
Menu Builder As of 29 December 2017 ProcessWire versions earlier than 3.x are not supported Modules Directory Project Page Read Me (How to install, use, etc..) For highly customisable menus, please see this post. If you want a navigation that mirrors your ProcessWire page tree, the system allows you to easily create recursive menus using either vanilla PHP or Soma's great MarkupSimpleNavigation. In some cases, however, you may wish to create menus that: 1. Do not mirror you site's page tree (hirarchies and ancestry); and 2. You can add custom links (external to your site) to. That is primarily where Menu Builder comes in. It is also helpful if you: 3. Prefer creating menus via drag and drop 4. Have a need for menus (or other listings) that will be changing regularly or that you want to allow your admin users to edit. The issue of custom menus is not new here in the forums. The difference is that this module allows you to easily create such menus via drag and drop in the Admin. Actually, you can even use it to just create some list if you wanted to. In the backend, the module uses the jQueryUI plugin nestedSortable by Manuele J Sarfatti for the drag and drop and is inspired in part by the WP Custom Menu feature. Please read the Read Me completely before using this module. For Complex or highly-customised menus, it is recommended to use the getMenuItems() method as detailed in this post. Features Ability to create menus that do not mirror your ProcessWire Page Tree hierarchy/structure Menus can contain both ProcessWire pages and custom links Create menu hierarchies and nesting via drag and drop Easily add CSS IDs and Classes to each menu item on creating the menu items (both custom and from ProcessWire pages) or post creation. Optionally set custom links to open in a new tab Change menu item titles built from ProcessWire pages (without affecting the original page). E.g. if you have a page titled 'About Us' but you want the menu item title to be 'About' Readily view the structure and settings for each menu item Menus stored as pages (note: just the menu, not the items!) Menu items stored as JSON in a field in the menu pages (empty values not stored) Add menu items from ProcessWire pages using page fields (option to choose between PageAutocomplete and AsmSelect [default]) or a Selector (e.g. template=basic-page, limit=20, sort=title). For page fields, you can specify a selector to return only those specified pages for selection in the page field (i.e. asm and autocomplete) For superusers, optionally allow markup in your menu titles, e.g. <span>About</span> Menu settings for nestedSortable - e.g. maxLevels (limit nesting levels) Advanced features (e.g. add pages via selector, menu settings) currently permissible to superadmins only (may change to be permission-based) Delete single or all menu items without deleting the menu itself Lock down menus for editing Highly configurable MarkupMenuBuilder - e.g. can pass menu id, title, name or array to render(); Passing an array means you can conditionally manipulate it before rendering, e.g. make certain menu branches visible only to certain users [the code is up to you!] Optionally grab menu items only (as a Menu object WireArray or a normal array) and use your own code to create custom highly complex menus to meet any need. More... In the backend, ProcessMenuBuilder does the menu creation. For the frontend, menus are displayed using MarkupMenuBuilder. Credits In this module's infancy (way back!), I wanted to know more about ProcessWire modules as well as improve my PHP skills. As they say, what better way to learn than to actually create something? So, I developed this module (instead of writing PW tutorials as promised, tsk, tsk, naughty, naughty!) in my own summer of code . Props to Wanze, Soma, Pete, Antti and Ryan whose modules I studied (read copied ) to help in my module development and to Teppo for his wonderful write-up on the "Anatomy of fields in ProcessWire" that vastly improved my knowledge and understanding of how PW works. Diogo and marcus for idea about using pages (rather than a custom db table), onjegolders for his helpful UI comments, Martijn Geerts, OrganizedFellow, dazzyweb and Mike Anthony for 'pushing me' to complete this module and netcarver for help with the code. Screens
-
This module won't suit everyone because... It requires what is currently the latest dev version of ProcessWire It requires your server environment have AVIF support Generating AVIF files is slow It offers fewer features than the core provides for WebP It is likely incompatible with the core WebP features so is an either/or prospect ...but it allows for the basic generation and serving of AVIF files until such time as the core provides AVIF features. Auto AVIF Automatically generates AVIF files when image variations are created. The AVIF image format usually provides better compression efficiency than JPG or WebP formats, in many cases producing image files that are significantly smaller in size while also having fewer visible compression artifacts. Requires ProcessWire v3.0.236 or newer. In order to generate AVIF files your environment must have a version of GD or Imagick that supports the AVIF format. If you are using ImageSizerEngineGD (the ProcessWire default) then this means you need PHP 8.1 or newer and an OS that has AVIF support. If you want to use Imagick to generate AVIF files then you must have the core ImageSizerEngineIMagick module installed. The module attempts to detect if your environment supports AVIF and warns you on the module config screen if it finds a problem. Delayed Image Variations Generating AVIF files can be very slow - much slower than creating an equivalent JPG or WebP file. If you want to use this module it's highly recommended that you also install the Delayed Image Variations module so that image variations are created one by one on request rather than all at once before a page renders. Otherwise it's likely that pages with more than a few images will timeout before the AVIF files can be generated. Configuration On the module configuration screen are settings for "Quality (1 – 100)" and "Speed (0 – 9)". These are parameters for the underlying GD and Imagick AVIF generation methods. There is also an option to create AVIF files for existing image variations instead of only new image variations. If you enable this option then all image variations on your site will be recreated the next time they are requested. As per the earlier note, the process of recreating the image variations and the AVIF files is likely to be slow. Usage Just install the module, choose the configuration settings you want, and make the additions to the .htaccess file in the site root described in the next section. How the AVIF files are served The module doesn't have all the features that the ProcessWire core provides for WebP files. It's much simpler and uses .htaccess to serve an AVIF file instead of the original variation file when the visitor's browser supports AVIF and an AVIF file named the same as the variation exists. This may not be compatible with the various approaches the core takes to serving WebP files so you'll want to choose to serve either AVIF files via this module or WebP files via the core but not both. Two additions to the .htaccess file in the site root are needed. 1. Immediately after the RewriteEngine On line: # AutoAvif RewriteCond %{HTTP_ACCEPT} image/avif RewriteCond %{QUERY_STRING} !original=1 RewriteCond %{DOCUMENT_ROOT}/$1.avif -f RewriteRule (.+)\.(jpe?g|png|gif)$ $1.avif [T=image/avif,E=REQUEST_image,L] 2. After the last line: # AutoAvif <IfModule mod_headers.c> Header append Vary Accept env=REQUEST_image </IfModule> <IfModule mod_mime.c> AddType image/avif .avif </IfModule> Opting out of AVIF generation for specific images If you want to prevent an AVIF file being generated and served for a particular image you can hook AutoAvif::allowAvif and set the event return to false. AutoAvif generates an AVIF file when an image variation is being created so the hookable method receives some arguments relating to the resizing of the requested variation. Example: $wire->addHookAfter('AutoAvif::allowAvif', function(HookEvent $event) { $pageimage = $event->arguments(0); // The Pageimage that is being resized $width = $event->arguments(1); // The requested width of the variation $height = $event->arguments(2); // The requested height of the variation $options = $event->arguments(3); // The array of ImageSizer options supplied // You can check things like $pageimage->field, $pageimage->page and $pageimage->ext here... // Don't create an AVIF file if the file extension is PNG if($pageimage->ext === 'png') $event->return = false; }); Deleting an AVIF file If you delete a variation via the "Variations > Delete Checked" option for an image in an Images field then any corresponding AVIF file is also deleted. And if you delete an image then any AVIF files for that image are also deleted. Deleting all AVIF files If needed you can execute this code snippet to delete all AVIF files sitewide. $iterator = new \DirectoryIterator($config->paths->files); foreach($iterator as $dir) { if($dir->isDot() || !$dir->isDir()) continue; $sub_iterator = new \DirectoryIterator($dir->getPathname()); foreach($sub_iterator as $file) { if($file->isDot() || !$file->isFile()) continue; if($file->getExtension() === 'avif') { unlink($file->getPathname()); echo 'Deleted: ' . $file->getFilename() . '<br>'; } } } Saving an original variation file Because requests to images are being rewritten to matching AVIF files where they exist, if you try to save example.500x500.jpg from your browser you will actually save example.500x500.avif. You can prevent the rewrite and load/save the original variation file by adding "original=1" to the query string in the image URL, e.g. example.500x500.jpg?original=1. https://github.com/Toutouwai/AutoAvif https://processwire.com/modules/auto-avif/