Jump to content

Search the Community

Showing results for tags 'Module'.

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Forums

  • Welcome to ProcessWire
    • News & Announcements
    • Showcase
    • Wishlist & Roadmap
  • Community Support
    • Getting Started
    • Tutorials
    • FAQs
    • General Support
    • API & Templates
    • Modules/Plugins
    • Themes and Profiles
    • Multi-Language Support
    • Security
    • Jobs
  • Off Topic
    • Pub
    • Dev Talk

Product Groups

  • Form Builder
  • ProFields
  • ProCache
  • ProMailer
  • Login Register Pro
  • ProDrafts
  • ListerPro
  • ProDevTools
  • Likes
  • Custom Development

Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


AIM


MSN


Website URL


ICQ


Yahoo


Jabber


Skype


Location


Interests

  1. 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.
  2. PDF Fieldtype/Inputfield Module for ProcessWire allowing you to easily generate thumbnails of the PDF files embedded to the site. Current version: 1.1.2 (Changelog) Module page: http://modules.processwire.com/modules/fieldtype-pdf Github: https://github.com/uiii/ProcessWire-FieldtypePDF For detailed instructions see: https://github.com/uiii/ProcessWire-FieldtypePDF/blob/master/README.md
  3. Add Image URLs A module for ProcessWire CMS/CMF. Allows images/files to be added to Image/File fields by pasting URLs or using the API. Installation Install the Add Image URLs module. Configuration You can add MIME type > file extension mappings in the module config. These mappings are used when validating URLs to files that do not have file extensions. Usage A "Paste URLs" button will be added to all Image and File fields. Use the button to show a textarea where URLs may be pasted, one per line. Images/files are added when the page is saved. A Pagefiles::addFromUrl method is also added to the API to achieve the same result. The argument of this method is expected to be either: a URL: "https://domain.com/image.jpg" an array of URLs: ["https://domain.com/image1.jpg", "https://domain.com/image2.jpg"] Example: // Get unformatted value of File/Image field to be sure that it's an instance of Pagefiles $page->getUnformatted('file_field')->addFromUrl("https://domain.com/path-to-file.ext"); // No need to call $page->save() as it's already done in the method Should you have an issue using the method, please have a look at the "errors" log to check if something was wrong with your URL(s). WebP conversion The core InputfieldImage does not support images in WebP format. But if you have the WebP To Jpg module installed (v0.2.0 or newer) then any WebP images you add via Add Image URLs will be automatically converted to JPG format. https://github.com/Toutouwai/AddImageUrls https://modules.processwire.com/modules/add-image-urls/
  4. I'm really in love with FormBuilder, but the one thing missing to match all my end users' expectations were repeatable field groups. Think repeaters, in ProcessWire terms. Our primary application of PW is our corporate intranet, so "lines" of fields are quite common in the forms I build. We have all kinds of request forms where the information for a varying number of colleagues needs to be entered (from meal order to flight booking request) and where it is simply impractical to send a form for each, and I don't want to clutter my forms with multiple instances of fields that may only get used ten percent of the time. That's why I started to build FormBuilderMultiplier (link to GitHub). What it does: Adds an option to make a regular Fieldgroup repeatable Lets you limit the number of instances of a Fieldgroup on the form Adds an "Add row" button the form that adds another instance of the Fieldgroup's fields Adds a counter suffix at the end of every affected field's label Stores the entered values just like regular fields Makes the entered values available in preview and email notifications Supports most text based fields, textareas and selects (really, I haven't had enough time to test all the available choices yet) What it doesn't do (yet): Support saving to ProcessWire pages (i.e. real Repeaters) I haven't tested all the validation stuff, Date/Time inputs etc. yet, but since I'm utterly swamped with other stuff at work, I didn't want to wait until I have it polished. Any feedback is welcome. There might also be some issues with different output frameworks that I haven't encountered yet. The forms I work with mostly use UIKit. Status: Still alpha, so test well before using it in the field. Known issues: When rows are added, the form's iframe needs to be resized, which isn't completely clean yet. How it works: The Fieldgroup settings are added through regular hooks, as is the logic that adds the necessary field copies for processing the form and displaying previews. "Multiplied" field instances are suffixed with _NUM, where NUM is an incremental integer starting from 1. So if you have add two fields named "surname" and "givenname" to a fieldgroup and check the "multiply" checkbox, the form will initially have "surname_1" and "givenname_1" field (I'm still considering changing that to make the risk to shoot oneself into the foot by having a regular "surname_1" field somewhere else in the form less likely). When a "row" is added, the first row is cloned through JS and the counter in the fields' IDs, names and "for" attributes as well as the counter in the label are incremented before appending the copies to the Fieldset container in the form. To keep backend and frontend in sync, a hidden field named [name of the fieldset]__multiplier_rows is added to the form. Both the backend and the frontend script use this to store and retrieve the number of "rows". ToDo: Naturally, add the option to store the data in real repeaters when saving to pages. Do a lot of testing (and likely fixing). Make a few things (like the "Add row" button label etc.) configurable in field(set) context. Add a smooth API to retrieve the multiplied values as WireArrays. The mandatory moving screenshot:
  5. Inputfield Dependency Helper Adds "Insert field name" and "Insert value" dropdown menus to help with constructing show-if/required-if conditions, aka inputfield dependencies. The "Insert field name" menu helps you remember the field names that exist in your site (or exist in the current template) and avoids typos. The "Insert value" menu lets you select values for Page Reference or Select Options fields via the human-friendly label whereas the show-if/required-if conditions require those values to be inserted as numerical IDs. Insert field name When you click the button a dropdown menu appears listing field names, with the field labels in parentheses. When editing a field in template context only the fields that exist in the template are listed, and the field labels are in template context. When editing a field outside of template context all the non-system fields are listed. When you click an item in the list the field name is inserted into the settings field. Insert value When using a Page Reference or Select Options field value in a show-if/required-if condition you have to enter the numerical ID of the page/option, and this is not so user-friendly – often you have to switch to another tab and go and look up the relevant ID. The "Insert value" button is intended to make this process easier. When you click the button a dropdown menu appears listing any Page Reference and Select Options fields that exist in the current template (when editing in template context) or in the site. When you click one of the fields the selectable options for the field are AJAX-loaded into a flyout menu. Clicking one of the selectable options will insert the numerical ID of the option into the settings field. Configuration In the module config you can set a limit to the number of selectable options shown in the menu, so the menu doesn't get excessively long. https://github.com/Toutouwai/InputfieldDependencyHelper https://processwire.com/modules/inputfield-dependency-helper/
  6. Introducing our newest [commercial] module: Recurme Processwire Recurring Dates Field & Custom Calendar Module. http://www.99lime.com/modules/recurme/ One Field to Recur them ALL… A Recurring Dates InputField for your Processwire templates. The InputField you’ve been waiting for. Complex RRule date repeating in a simple and fast user interface. Use the super simple, & powerful API to output them into your templates. example: <? // easy to get recurring events $events = $recurme->find(); // events for this day $events = $recurme->day(); // events for this week $events = $recurme->week(); // events for this month $events = $recurme->month(); ?> <? // Loop through your events foreach($events as $event){ echo $event->title; echo $event->start_date; echo $event->rrule; echo $event->original->url; ... } ?> Unlimited Custom Calendars. Imagine you could create any calendar you wanted on your website. Use recurring events with the Recurme field, or use your own Processwire pages and date fields to render calendars… it’s up to you. Fully customizable. Make as many calendars as you like. Get events from anywhere. Recurme does all the hard date work for you. Unlimited Custom Admin Calendars too. Hope you like it , Joshua & Eduardo from 99Lime. ## [1.0.1] - 2017-05-29 ### changed - Fixed $options[weekStartDay] offset in Calendar - Fixed ->renderCalendar() Blank Days - Fixed missing ->renderList() [renderMonth][xAfter] - Removed ->renderCalendar() <table> attributes border, border-spacing - Fixed ->renderCalendar() excluded dates - Fixed rrule-giu.js exclude dates - Fixed ->renderList missing space in attr ID (shout out to @Juergen for multiple suggestions & feedback).
  7. 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!
  8. Logs JSON Viewer Formats JSON data in ProcessLogger for improved readability. Because log files can only contain strings, it's a common practice to use json_encode() to convert an array to a string when you want to save the data to a log file. But the resulting JSON is not as readable as it could be when viewing the log in ProcessLogger. The Logs JSON Viewer module uses the json-viewer library to improve the readability of JSON data in ProcessLogger and add some useful features. Before: After: Configuration You can set the config options for json-viewer in a textarea field. See the json-viewer readme for information about the options. There is also an option to set the width of the column that contains the JSON data. This setting exists because otherwise the column jumps around in an inconsistent and distracting way when changing from log to log or between paginations. Features You can switch the view of the JSON data between formatted and unformatted using the toggle button at the bottom of the data. The viewer has a number of useful features such as: Progressively expand or collapse levels in the data. View the count of child items and the data type of each item. Search for a string within the data. Copy all or part of the data to the clipboard (requires the HTTPS protocol). https://github.com/Toutouwai/LogsJsonViewer https://processwire.com/modules/logs-json-viewer/
  9. Verify Links Periodically verifies that external links are working and not leading to an error page. Requires the following core modules to be installed: PagePaths LazyCron How it works The module identifies links on a page when the page is saved and stores the URLs in a database table. For the purposes of this module a "link" is an external URL in any of the following... FieldtypeURL fields, and fields whose Fieldtype extends it (e.g. ProFields Verified URL) URL columns in a ProFields Table field URL subfields in a ProFields Combo field URL subfields in a ProFields Multiplier field ...and external href attributes from <a> tags in any of the following... Textarea fields where the "Content Type" is "Markup/HTML" (e.g. CKEditor and TinyMCE fields) CKEditor and TinyMCE columns in a ProFields Table field CKEditor and TinyMCE subfields in a ProFields Combo field The link URLs stored in the database table are then checked in batches via LazyCron and the response code for each URL is recorded. Configuration On the main module config screen you can define settings that determine the link verification rate. You can choose the frequency that the LazyCron task will execute and the number of links that are verified with each LazyCron execution. The description line in this section informs you approximately how often all links in the site will be verified based on the number of links currently detected and the settings you have chosen. The module verifies links using curl_multi_exec which is pretty fast in most cases so if your site has a lot of links you can experiment with increasing the number of links to verify during each LazyCron execution. You can also set the timeout for each link verification and customise the list of user agents if needed. In the Process module config there's a field allowing you to exclude URLs that start with a given string. This only applies to the "Error responses only" listing, and can be useful to avoid seeing false-positive error statuses for domains that you know provide inaccurate responses (more about this below). Usage Visit Setup > Verify Links to view a paginated table showing the status of the links that have been identified in your site. The table rows are colour-coded according to the response code: Potentially problematic response = red background Redirect response = orange background OK response = green background Link has not yet been checked = white background Where you see a 403 response code it's recommended to manually verify the link by clicking the URL to see if the page loads or not before treating it as a broken link. That's because some servers have anti-scraping firewalls that issue a 403 Forbidden response to requests from IP ranges that correspond to datacentres rather than to individual ISP customers and this will cause a "false positive" as a broken link. For each link the "Page" column contains a link to edit the page and the "View" column contains a link to view the page on the front-end. You can use the "Column visibility" dropdown to include a "Redirect" column in the table, which shows the redirect URL where this is available. You can use the "Custom Search Builder" to filter the table by particular column values, e.g. for a particular response code. To see only links that have an error response code (400 or higher, or 0), use the flyout menu to visit Setup > Verify Links > Error responses only. For those who can't wait The module identifies links as pages are saved and verifies links on a LazyCron schedule. If you've installed the module on an existing site and you don't want to wait for this process to happen organically you can use the ProcessWire API to save pages and verify links en masse. // Save all non-admin, non-trashed pages in the site // If your site has a very large number of pages you may need to split this into batches $items = $pages->find("has_parent!=2|7, template!=admin, include=all"); foreach($items as $item) { $item->of(false); $item->save(); } // Verify the given number of links from those that VerifyLinks has identified // Execute this repeatedly until there are no more white rows in the Verify Links table // You can try increasing $number_of_links if you like $vl = $modules->get('VerifyLinks'); $number_of_links = 20; $vl->verifyLinks($number_of_links); Advanced There are hookable methods but most users won't need to bother with these: VerifyLinks::allowForField($field, $page) - Allow link URLs to be extracted from this field on this page? VerifyLinks::isValidLink($url) - Is this a valid link URL to be saved by this module? VerifyLinks::extractHtmlLinks($html) - Extract an array of external link URLs from the supplied HTML string https://github.com/Toutouwai/VerifyLinks https://processwire.com/modules/verify-links/
  10. Season's Greetings ProcessWirers! I hope you enjoy the gift of this module, but use with care... TLDR: This module captures changes made in the development environment so that they can be easily migrated to the live environment without needing to specify the changes or write any code. The demo below gives a brief overview. Want to read? Read on. One of the (few) problems with ProcessWire, in my opinion, is the lack of any native way of handling migrations. Given that PW is such a powerful tool capable of sophisticated and complex web-based applications, this is less than ideal. There is a solution, however, in RockMigrations which accomplishes a lot in a controllable way, provided you are happy to specify your database set-up in code rather than via the UI (albeit that the latest versions allow you to grab much of the required code from the UI). If that suits your need, great. Around the same time as the first versions of RockMigrations, I started developing my own UI-based migrations module, which I have been using with reasonable success for some time. I halted development of the module for a while as RockMigrations developed and I considered switching to that route. However, I decided that my module suited me better and that a real improvement could be made if it was effectively automated so that I no longer needed to specify a migration. So that is exactly what it does: after configuring the module, you add a new migration page with ‘log changes’ enabled (which includes determining what types of objects are relevant for the migration) and work on your development system. Once you have made the desired changes (and tested them!) in the development environment, you go back to the migration page where it has magically captured the objects which have changed and listed them in dependency order. You then ‘export’ the changes, which creates json files to be uploaded to the live environment (via Git or FTP etc.), where they are then ‘installed’ to re-create the changes in the live system. The demo below illustrates this briefly. This first demo shows the creation of a migration. The installation demo will be in the next post, because of size constraints. See post 4 for HD video. Video-source small.mp4 There is a very extensive manual which covers all the features of the module, not just this ‘automatic’ method. Available on github at https://github.com/MetaTunes/ProcessDbMigrate and in the modules library here. PLEASE NOTE that this is still in 'alpha'. Do not use in production without fully testing and backing up at every stage. It is quite complex so, although I have tried hard to eliminate bugs, there will inevitably be some left!
  11. Wire Mail SMTP An extension to the (new) WireMail base class that uses SMTP-transport This module integrates EmailMessage, SMTP and SASL php-libraries from Manuel Lemos into ProcessWire. I use this continously evolved libraries for about 10 years now and there was never a reason or occasion not to do so. I use it nearly every day in my office for automated composing and sending personalized messages with attachments, requests for Disposition Notifications, etc. Also I have used it for sending personalized Bulkmails many times. The WireMailSmtp module extends the new email-related WireMail base class introduced in ProcessWire 2.4.1 (while this writing, the dev-branch only). Here are Ryans announcement. Current Version 0.6.0 Changelog: https://github.com/horst-n/WireMailSmtp/blob/master/CHANGELOG.md get it from the Modules Directory Install and Configure Download the module into your site/modules/ directory and install it. In the config page you fill in settings for the SMTP server and optionaly the (default) sender, like email address, name and signature. You can test the smtp settings directly there. If it says "SUCCESS! SMTP settings appear to work correctly." you are ready to start using it in templates, modules or bootstrap scripts. Usage Examples The simplest way to use it: $numSent = wireMail($to, $from, $subject, $textBody); $numSent = wireMail($to, '', $subject, $textBody); // or with a default sender emailaddress on config page This will send a plain text message to each recipient. You may also use the object oriented style: $mail = wireMail(); // calling an empty wireMail() returns a wireMail object $mail->to($toEmail, $toName); $mail->from = $yourEmailaddress; // if you don't have set a default sender in config // or if you want to override that $mail->subject($subject); $mail->body($textBody); $numSent = $mail->send(); Or chained, like everywhere in ProcessWire: $mail = wireMail(); $numSent = $mail->to($toEmail)->subject($subject)->body($textBody)->send(); Additionaly to the basics there are more options available with WireMailSmtp. The main difference compared to the WireMail BaseClass is the sendSingle option. With it you can set only one To-Recipient but additional CC-Recipients. $mail = wireMail(); $mail->sendSingle(true)->to($toEmail, $toName)->cc(array('person1@example.com', 'person2@example.com', 'person3@example.com')); $numSent = $mail->subject($subject)->body($textBody)->send(); The same as function call with options array: $options = array( 'sendSingle' => true, 'cc' => array('person1@example.com', 'person2@example.com', 'person3@example.com') ); $numSent = wireMail($to, '', $subject, $textBody, $options); There are methods to your disposal to check if you have the right WireMail-Class and if the SMTP-settings are working: $mail = wireMail(); if($mail->className != 'WireMailSmtp') { // Uups, wrong WireMail-Class: do something to inform the user and quit echo "<p>Couldn't get the right WireMail-Module (WireMailSmtp). found: {$mail->className}</p>"; return; } if(!$mail->testConnection()) { // Connection not working: echo "<p>Couldn't connect to the SMTP server. Please check the {$mail->className} modules config settings!</p>"; return; } A MORE ADVANCED DEBUG METHOD! You can add some debug code into a template file and call a page with it: $to = array('me@example.com'); $subject = 'Wiremail-SMTP Test ' . date('H:i:s') . ' äöü ÄÖÜ ß'; $mail = wireMail(); if($mail->className != 'WireMailSmtp') { echo "<p>Couldn't get the right WireMail-Module (WireMailSmtp). found: {$mail->className}</p>"; } else { $mail->from = '--INSERT YOUR SENDER ADDRESS HERE --'; // <--- !!!! $mail->to($to); $mail->subject($subject); $mail->sendSingle(true); $mail->body("Titel\n\ntext text TEXT text text\n"); $mail->bodyHTML("<h1>Titel</h1><p>text text <strong>TEXT</strong> text text</p>"); $dump = $mail->debugSend(1); } So, in short, instead of using $mail->send(), use $mail->debugSend(1) to get output on a frontend testpage. The output is PRE formatted and contains the areas: SETTINGS, RESULT, ERRORS and a complete debuglog of the server connection, like this one: Following are a ... List of all options and features testConnection () - returns true on success, false on failures sendSingle ( true | false ) - default is false sendBulk ( true | false ) - default is false, Set this to true if you have lots of recipients (50+) to ($recipients) - one emailaddress or array with multiple emailaddresses cc ($recipients) - only available with mode sendSingle, one emailaddress or array with multiple emailaddresses bcc ($recipients) - one emailaddress or array with multiple emailaddresses from = 'person@example.com' - emailaddress, can be set in module config (called Sender Emailaddress) but it can be overwritten here fromName = 'Name Surname' - optional, can be set in module config (called Sender Name) but it can be overwritten here priority (3) - 1 = Highest | 2 = High | 3 = Normal | 4 = Low | 5 = Lowest dispositionNotification () or notification () - request a Disposition Notification subject ($subject) - subject of the message body ($textBody) - use this one alone to create and send plainText emailmessages bodyHTML ($htmlBody) - use this to create a Multipart Alternative Emailmessage (containing a HTML-Part and a Plaintext-Part as fallback) addSignature ( true | false ) - the default-behave is selectable in config screen, this can be overridden here (only available if a signature is defined in the config screen) attachment ($filename, $alternativeBasename = "") - add attachment file, optionally alternative basename send () - send the message(s) and return number of successful sent messages debugSend(1) - returns and / or outputs a (pre formatted) dump that contains the areas: SETTINGS, RESULT, ERRORS and a complete debuglog of the server connection. (See above the example code under ADVANCED DEBUG METHOD for further instructions!) getResult () - returns a dump (array) with all recipients (to, cc, bcc) and settings you have selected with the message, the message subject and body, and lists of successfull addresses and failed addresses, logActivity ($logmessage) - you may log success if you want logError ($logmessage) - you may log warnings, too. - Errors are logged automaticaly useSentLog (true | false) - intended for usage with e.g. third party newsletter modules - tells the send() method to make usage of the sentLog-methods - the following three sentLog methods are hookable, e.g. if you don't want log into files you may provide your own storage, or add additional functionality here sentLogReset () - starts a new LogSession - Best usage would be interactively once when setting up a new Newsletter sentLogGet () - is called automaticly within the send() method - returns an array containing all previously used emailaddresses sentLogAdd ($emailaddress) - is called automaticly within the send() method Changelog: https://github.com/horst-n/WireMailSmtp/blob/master/CHANGELOG.md
  12. Generate image placeholders for smoother lazyloading. Currently supports ThumbHash, BlurHash, and average color placeholders. I've been using the wonderful ImageBlurhash module for this in the past, but unfortunately it's no longer in active development. This new module adds ThumbHash and Average Color placeholder algorithms, improves performance by caching generated placeholders, fixes an issue when replacing images, and allows regenerating and clearing placeholders via the admin interface. Try it out using the installation instructions below or check out the GitHub repo for details. Why use image placeholders? Low-Quality Image Placeholders (LQIP) are used to improve the perceived performance of sites by displaying a small, low-quality version of an image while the high-quality version is being loaded. The LQIP technique is often used in combination with progressive lazyloading. How it works This module will automatically generate a small blurry image placeholder for each image that is uploaded to fields configured to use them. In your frontend templates, you can access the image placeholder as a data URI string to display while the high-quality image is loading. See below for markup examples. Placeholder types The module supports generating various types of image placeholders. The recommended type is ThumbHash which encodes most detail and supports transparent images. ThumbHash is a newer image placeholder algorithm with improved color rendering and support for transparency. BlurHash is the original placeholder algorithm, developed at Wolt. It currently has no support for alpha channels and will render transparency in black. Average color calculates the average color of the image. Installation Install the module using composer from the root of your ProcessWire installation. composer require daun/processwire-image-placeholders Open the admin panel of your site and navigate to Modules → Site → ImagePlaceholders to finish installation. Configuration You'll need to configure your image fields to generate image placeholders. Setup → Fields → [images] → Details → Image placeholders There, you can choose the type of placeholder to generate. If you're installing the module on an existing site, you can also choose to batch-generate placeholders for any existing images. Usage Accessing an image's lqip property will return a data URI string of its placeholder. $page->image->lqip; // data:image/png;base64,R0lGODlhEAAQAMQAA Accessing it as a method allows setting a custom width and/or height of the placeholder. $page->image->lqip(300, 200); // 300x200px Markup Using a lazyloading library like lazysizes or vanilla-lazyload, you can show a placeholder image by using its data URI as src of the image. <!-- Using the placeholder as src while lazyloading the image --> <img src="<?= $page->image->lqip ?>" data-src="<?= $page->image->url ?>" data-lazyload /> Another technique is rendering the placeholder and the original image as separate images on top of each other. This allows smoother animations between the blurry unloaded and the final loaded state. <!-- Display placeholder and image on top of each other --> <div class="ratio-box"> <img src="<?= $page->image->lqip ?>" aria-hidden="true"> <img data-src="<?= $page->image->url ?>" data-lazyload> </div>
  13. MarkupSocialShareButtons This module outputs a list of share links for the following services by default * E-Mail (kinda extra) * Facebook * Twitter * Google+ * LinkedIn * Thumblr * Reddit (off by default) * Pinterest (off by default) Usage examples echo $modules->MarkupSocialShareButtons->render(); This outputs a simple UL list with links <ul class='MarkupSocialShareButtons cf'> <li class='mssb-item mssb-facebook mssb-popup'><a href='url'><i>facebook</i></a></li> etc ... </ul> Config Screen See more details and examples on github or modules directory https://github.com/somatonic/MarkupSocialShareButtons http://mods.pw/8j
  14. Hi everyone, Here's a new module that I have been meaning to build for a long time. http://modules.processwire.com/modules/process-admin-actions/ https://github.com/adrianbj/ProcessAdminActions What does it do? Do you have a bunch of admin snippets laying around, or do you recreate from them from scratch every time you need them, or do you try to find where you saw them in the forums, or on the ProcessWire Recipes site? Admin Actions lets you quickly create actions in the admin that you can use over and over and even make available to your site editors (permissions for each action are assigned to roles separately so you have full control over who has access to which actions). Included Actions It comes bundled with several actions and I will be adding more over time (and hopefully I'll get some PRs from you guys too). You can browse and sort and if you have @tpr's Admin on Steroid's datatables filter feature, you can even filter based on the content of all columns. The headliner action included with the module is: PageTable To RepeaterMatrix which fully converts an existing (and populated) PageTable field to either a Repeater or RepeaterMatrix field. This is a huge timesaver if you have an existing site that makes heavy use of PageTable fields and you would like to give the clients the improved interface of RepeaterMatrix. Copy Content To Other Field This action copies the content from one field to another field on all pages that use the selected template. Copy Field Content To Other Page Copies the content from a field on one page to the same field on another page. Copy Repeater Items To Other Page Add the items from a Repeater field on one page to the same field on another page. Copy Table Field Rows To Other Page Add the rows from a Table field on one page to the same field on another page. Create Users Batcher Allows you to batch create users. This module requires the Email New User module and it should be configured to generate a password automatically. Delete Unused Fields Deletes fields that are not used by any templates. Delete Unused Templates Deletes templates that are not used by any pages. Email Batcher Lets you email multiple addresses at once. Field Set Or Search And Replace Set field values, or search and replace text in field values from a filtered selection of pages and fields. FTP Files to Page Add files/images from a folder to a selected page. Page Active Languages Batcher Lets you enable or disable active status of multiple languages on multiple pages at once. Page Manipulator Uses an InputfieldSelector to query pages and then allows batch actions on the matched pages. Page Table To Repeater Matrix Fully converts an existing (and populated) PageTable field to either a Repeater or RepeaterMatrix field. Template Fields Batcher Lets you add or remove multiple fields from multiple templates at once. Template Roles Batcher Lets you add or remove access permissions, for multiple roles and multiple templates at once. User Roles Permissions Batcher Lets you add or remove permissions for multiple roles, or roles for multiple users at once. Creating a New Action If you create a new action that you think others would find useful, please add it to the actions subfolder of this module and submit a PR. If you think it is only useful for you, place it in /site/templates/AdminActions/ so that it doesn't get lost on module updates. A new action file can be as simple as this: <?php namespace ProcessWire; class UnpublishAboutPage extends ProcessAdminActions { protected function executeAction() { $p = $this->pages->get('/about/'); $p->addStatus(Page::statusUnpublished); $p->save(); return true; } } Each action: class must extend "ProcessAdminActions" and the filename must match the class name and end in ".action.php" like: UnpublishAboutPage.action.php the action method must be: executeAction() As you can see there are only a few lines needed to wrap the actual API call, so it's really worth the small extra effort to make an action. Obviously that example action is not very useful. Here is another more useful one that is included with the module. It includes $description, $notes, and $author variables which are used in the module table selector interface. It also makes use of the defineOptions() method which builds the input fields used to gather the required options before running the action. <?php namespace ProcessWire; class DeleteUnusedFields extends ProcessAdminActions { protected $description = 'Deletes fields that are not used by any templates.'; protected $notes = 'Shows a list of unused fields with checkboxes to select those to delete.'; protected $author = 'Adrian Jones'; protected $authorLinks = array( 'pwforum' => '985-adrian', 'pwdirectory' => 'adrian-jones', 'github' => 'adrianbj', ); protected function defineOptions() { $fieldOptions = array(); foreach($this->fields as $field) { if ($field->flags & Field::flagSystem || $field->flags & Field::flagPermanent) continue; if(count($field->getFieldgroups()) === 0) $fieldOptions[$field->id] = $field->label ? $field->label . ' (' . $field->name . ')' : $field->name; } return array( array( 'name' => 'fields', 'label' => 'Fields', 'description' => 'Select the fields you want to delete', 'notes' => 'Note that all fields listed are not used by any templates and should therefore be safe to delete', 'type' => 'checkboxes', 'options' => $fieldOptions, 'required' => true ) ); } protected function executeAction($options) { $count = 0; foreach($options['fields'] as $field) { $f = $this->fields->get($field); $this->fields->delete($f); $count++; } $this->successMessage = $count . ' field' . _n('', 's', $count) . ' ' . _n('was', 'were', $count) . ' successfully deleted'; return true; } } This defineOptions() method builds input fields that look like this: Finally we use $options array in the executeAction() method to get the values entered into those options fields to run the API script to remove the checked fields. There is one additional method that I didn't outline called: checkRequirements() - you can see it in action in the PageTableToRepeaterMatrix action. You can use this to prevent the action from running if certain requirements are not met. At the end of the executeAction() method you can populate $this->successMessage, or $this->failureMessage which will be returned after the action has finished. Populating options via URL parameters You can also populate the option parameters via URL parameters. You should split multiple values with a “|” character. You can either just pre-populate options: http://mysite.dev/processwire/setup/admin-actions/options?action=TemplateFieldsBatcher&templates=29|56&fields=219&addOrRemove=add or you can execute immediately: http://mysite.dev/processwire/setup/admin-actions/execute?action=TemplateFieldsBatcher&templates=29|56&fields=219&addOrRemove=add Note the “options” vs “execute” as the last path before the parameters. Automatic Backup / Restore Before any action is executed, a full database backup is automatically made. You have a few options to run a restore if needed: Follow the Restore link that is presented after an action completes Use the "Restore" submenu: Setup > Admin Actions > Restore Move the restoredb.php file from the /site/assets/cache/AdminActions/ folder to the root of your site and load in the browser Manually restore using the AdminActionsBackup.sql file in the /site/assets/cache/AdminActions/ folder I think all these features make it very easy to create custom admin data manipulation methods that can be shared with others and executed using a simple interface without needing to build a full Process Module custom interface from scratch. I also hope it will reduce the barriers for new ProcessWire users to create custom admin functionality. Please let me know what you think, especially if you have ideas for improving the interface, or the way actions are defined.
  15. Search Corrections Suggests alternative words for a given input word. This can be useful in a website search feature where the given search term produces no results, but an alternative spelling or stem of the term may produce results. The module has two methods intended for public use: findSimilarWords(): this method suggests corrected spellings or similar alternatives for the given word based on words that exist in the website. stem(): this method returns the stem of the given word, which may give a full or partial match for a word within the website. The module doesn't dictate any particular way of using it in a website search feature, but one possible approach is as follows. If a search produces no matching pages you can take the search term (or if multiple terms, split and then loop over each term) and use the module methods to find alternative words and/or the stem word. Then automatically perform a new search using the alternative word(s), and show a notice to the user, e.g. Your search for "begining" produced no matches. Including results for "beginning" and "begin". findSimilarWords() This method creates a list of unique words (the "word list") that exist on the pages and fields that you define, and compares those words to a target word that you give it. The method returns an array of words that are sufficiently similar to the target word. For multi-language sites, the $user language determines which language populates the word list. Similarity The method ranks similar words by calculating the Levenshtein distance from the target word. Where several results have the same Levenshtein distance from the target word these are ordered so that results which have more letters in common with the target word at the start of the result word are higher in the order. Method arguments $target (string) The input word. $selector (string) A selector string to find the pages that the word list will be derived from. $fields (array) An array of field names that the word list will be derived from. $options (array) Optional: an array of options as described below. minWordLength (int) Words below this length will not be included in the word list. Default: 4 lengthRange (int) Words that are longer or shorter than the target word by more than this number will not be included in the word list. Default: 2 expire (int) The word list is cached for this number of seconds, to improve performance. Default: 3600 maxChangePercent (int) When the Levenshtein distance between a word and the target word is calculated, the distance is then converted into a percentage of changed letters relative to the target word. Words that have a higher percentage change than this value are not included in the results. Default: 50 insertionCost (int) This is an optional argument for the PHP levenshtein() function. See the docs for details. Default: 1 replacementCost (int) This is an optional argument for the PHP levenshtein() function. See the docs for details. Default: 1 deletionCost (int) This is an optional argument for the PHP levenshtein() function. See the docs for details. Default: 1 Example of use // The input word that may need correcting $target = 'dispraxia'; // Get the Search Corrections module $sc = $modules->get('SearchCorrections'); // Define a selector string to find the pages that the word list will be derived from $selector = "template=basic-page"; // Define an array of field names that the word list will be derived from $flds = ['title', 'body']; // Optional: override any of the default options $options = ['maxChangePercent' => 55]; // Get an array of similar words that exist in the pages/fields you defined // The return value is in the format $word => $levenshtein_distance $results = $sc->findSimilarWords($target, $selector, $flds, $options); Example result: stem() This method uses php-stemmer to return the stem of the given word. As an example, "fish" is the stem of "fishing", "fished", and "fisher". The returned stem may be the original given word in some cases. The stem is not necessarily a complete word, e.g. the stem of "argued" is "argu". If using the stem in a search you will probably want to use a selector operator that can match partial words. Method arguments $word (string) The input word. $language (string) Optional: the language name in English. The valid options are shown below. Default: english catalan danish dutch english finnish french german italian norwegian portuguese romanian russian spanish swedish Alternatively, you can use the ISO 639 language code for any of the above languages. Example of use // The input word $word = 'fishing'; // Get the Search Corrections module $sc = $modules->get('SearchCorrections'); // Get the stem of the word $stem = $sc->stem($word); https://github.com/Toutouwai/SearchCorrections https://processwire.com/modules/search-corrections/
  16. FieldtypeFormSelect lets you create fields to select from forms created using the pro FormBuilder module. Features: Create select fields that allow for choosing forms when editing pages Fully compatible with FormBuilder, render forms using native methods Choose which forms will be available to choose from, each field is configured individually Choose how form names will be presented in select elements Compatible with FormBuilderHtmx FieldtypeFormSelect lets you create fields like this, configured as desired. Choose which forms will be present. Including forms where names start/end or contain a value allows you to create a form select field once then use form names to help group them together, or add/remove them from form selects 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 edit a field configuration. For example, this field will only allow you to choose forms having names ending with "request", so "customer-support-request" and "consultation-request" will be included, but where forms with names like "newsletter-signup" and "call-to-action" won't. Choose how you would like the form names to be presented in the select element. They can be shown as they are originally named, as spaced words, or as capitalized/spaced words. Rendering in your templates is straightforward <?php $page->select_a_form; // => A form ID, or null if no form has been selected // Render using the native FormBuilder method echo $forms->render($page->select_a_form); // Alternate method. Selected form will be rendered, if no form is selected output is null. echo $page->render('select_a_form'); Form select fields store the ID of the selected form and FieldtypeFormSelect makes use of ProcessWire's built-in field rendering to keep things simple. The fields you create will always be up-to-date with the forms as they currently exist. If a form is deleted that has been selected in one or more fields, those values will be set to null so you won't experience any issues with references to form IDs that no longer exist. Your templates and pages stay free from errors. My primary use is to have a form select field available for blocks created in the RockPageBuilder module by @bernhard. I want each section on the page to contain an option to choose any form that will open in a modal to put the power of choosing forms in the hands of the user. RockPageBuilder is not required, but makes for a powerful example. Contributions and issues are welcome on Github, or stop by here for some help! Install as a ProcessWire module Install via Composer Download from the Github repository Cheers!
  17. This module allows you to automatically rename file (including image) uploads according to a configurable format This module lets you define as many rules as you need to determine how uploaded files will be named and you can have different rules for different pages, templates, fields, and file extensions, or one rule for all uploads. Renaming works for files uploaded via the admin interface and also via the API, including images added from remote URLs. Github: https://github.com/adrianbj/CustomUploadNames Modules Directory: http://modules.processwire.com/modules/process-custom-upload-names/ Renaming Rules The module config allows you to set an unlimited number of Rename Rules. You can define rules to specific fields, templates, pages, and file extensions. If a rule option is left blank, the rule with be applied to all fields/templates/pages/extensions. Leave Filename Format blank to prevent renaming for a specific field/template/page combo, overriding a more general rule. Rules are processed in order, so put more specific rules before more general ones. You can drag to change the order of rules as needed. The following variables can be used in the filename format: $page, $template, $field, and $file. For some of these (eg. $field->description), if they haven't been filled out and saved prior to uploading the image, renaming won't occur on upload, but will happen on page save (could be an issue if image has already been inserted into RTE/HTML field before page save). Some examples: $page->title mysite-{$template->name}-images $field->label $file->description {$page->name}-{$file->filesize}-kb prefix-[Y-m-d_H-i-s]-suffix (anything inside square brackets is is considered to be a PHP date format for the current date/time) randstring[n] (where n is the number of characters you want in the string) ### (custom number mask, eg. 001 if more than one image with same name on a page. This is an enhanced version of the automatic addition of numbers if required) If 'Rename on Save' is checked files will be renamed again each time a page is saved (admin or front-end via API). WARNING: this setting will break any direct links to the old filename, which is particularly relevant for images inserted into RTE/HTML fields. The Filename Format can be defined using plain text and PW $page variable, for example: mysite-{$page->path} You can preserve the uploaded filename for certain rules. This will allow you to set a general renaming rule for your entire site, but then add a rule for a specific page/template/field that does not rename the uploaded file. Just simply build the rule, but leave the Filename Format field empty. You can specify an optional character limit (to nearest whole word) for the length of the filename - useful if you are using $page->path, $path->name etc and have very long page names - eg. news articles, publication titles etc. NOTE - if you are using ProcessWire's webp features, be sure to use the useSrcExt because if you have jpg and png files on the same page and your rename rules result in the same name, you need to maintain the src extension so they are kept as separate files. $config->webpOptions = array( 'useSrcExt' => false, // Use source file extension in webp filename? (file.jpg.webp rather than file.webp) ); Acknowledgments The module config settings make use of code from Pete's EmailToPage module and the renaming function is based on this code from Ryan: http://processwire.com/talk/topic/3299-ability-to-define-convention-for-image-and-file-upload-names/?p=32623 (also see this post for his thoughts on file renaming and why it is the lazy way out - worth a read before deciding to use this module). NOTE: This should not be needed on most sites, but I work with lots of sites that host PDFs and photos/vectors that are available for download and I have always renamed the files on upload because clients will often upload files with horrible meaningless filenames like: Final ReportV6 web version for John Feb 23.PDF
  18. 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, via Composer, 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 the high quality services now available. Inspired by what is possible with ProcessWire, I built Fluency, a third-party translation service integration for ProcessWire. 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. Module Features Translate any multilanguage field while editing any page. Translate fields in Repeater, Repeater Matrix, Table, Fieldset Page, Image descriptions, etc. Translate any file that added in the ProcessWire language pages. It's possible to translate the entire ProcessWire core in ~20 minutes Provide intuitive translation features that your clients and end-users can actually use. Fluency is designed for real-world use by individuals of all skill levels with little to no training. Its ease-of-use helps encourage users to adopt a multilanguage workflow. Start for free, use for free. Translation services supported by Fluency offer generous free tiers that can support regular usage levels. Fluency is, and will always be, free and open source. Use more than one Translation Engine. You may configure Fluency to use either DeepL, Google Cloud Translation, or both by switching between them as desired. AI powered translations that rival humans. DeepL provides the highest levels of accuracy in translation of any service available. Fluency has been used in many production sites around the world and in commercial applications where accuracy matters. Deliver impressive battle-tested translation features your clients can count on. Disable translation for individual fields. Disable translation for multilanguage fields where values aren't candidates for translation such as phone numbers or email addresses Configure translation caching. Caching can be enabled globally so that the same content translated more than once anywhere in ProcessWire doesn't count against your API usage and provides lightning fast responses. Set globally ignored words and text. Configure Fluency to add exclusionary indicators during translation so that specific words or phrases remain untranslated. This works either for specific strings alone, or present in other content while remaining grammatically correct in translation. Choose how translation is handled for fields. Configure Fluency to have buttons for either "Translate from {default language}" on each tab, or "Translate To All Languages" to populate every language for a field from any language to any language you have configured. No language limits. Configure as few or as many languages as you need. 2, 5, 10, 20 language website? Absolutely possible. If the translation service you choose offers a language, you can use it in ProcessWire. When new languages are introduced by third parties, they're ready to use in Fluency. Visually see what fields and language tabs have modified content. Fluency adds an visual indication to each field language tab to indicate which has different content than when opening the edit page. This helps ensure that content updated in one language should be updated in other languages to prevent content divergence between languages. Render language meta tags and ISO codes. Output alt language meta tags, add the current language's ISO code to your <html lang=""> attribute to your templates that are automatically generated from accurate data from the third party translation service. Build a standards-compliant multi-language SEO ready page in seconds with no additional configuration. Render language select elements. - Fluency can generate an unordered list of language links to switch between languages when viewing your pages. You can also embed a <select> element with JS baked in to switch between languages when viewing your pages. Render it without JS to use your own. Manage feature access for users. Fluency provides a permission that can be assigned to user roles for managing who can translate content. Track your translation account usage. View your current API usage, API account limit, and remaining allotment to keep an eye on and manage usage. (Currently only offered by DeepL) Use the global translation tool. Fluency provides translation on each field according to the languages you configure in ProcessWire. Use the global translation tool to translate any content to any language. Use Fluency from your templates and code. All translation features, usage statistics, cache control, and language data are accessible globally from the $fluency object. Perform any operation and get data for any language programmatically wherever you need it. Build custom AJAX powered admin translation features for yourself. Fluency provides a full RESTful API within the ProcessWire admin to allow developers to add new features for ProcessWire applications powered by the same API that Fluency uses. Robust plain-language documentation that helps you get up to speed fast. Fluency is extremely easy to use but also includes extensive documentation for all features both within the admin and for the Fluency programming API via the README.md document. The module code itself is also fully annotated for use with the ProDevTools API explorer. Is and will always be data safe. Adding, upgrading, or removing Fluency does not modify or remove your content. ProcessWire handles your data, Fluency sticks to translating. Full module localization. Translate Fluency itself to any language. All buttons, messages, and UI elements for Fluency will be presented in any language you choose for the ProcessWire admin. Built for expansion. Fluency provides translation services as modular "Translation Engines" with a full framework codebase to make adding new translation services easier and more reliable. Contributions for new translation services are welcome. Fluency is designed and built to provide everything you need to handle incredibly accurate translations and robust tools that make creating and managing multi-language sites a breeze. Built through research on translation plugins from around the web, it's the easiest and most friendly translation implementation for both end users and developers on any CMS/CMF anywhere. Fluency complements the built-in first class language features of ProcessWire. Fluency continues to be improved with great suggestions from the community and real-world use in production applications. Big thanks to everyone who has helped make Fluency better. Contributions, suggestions, and bug reports welcome! 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. 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. 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 You can install Fluency by adding the module to your ProcessWire project using any of the following methods. Method 1: Within ProcessWire using 'Add Module From Directory' and the class name Fluency Method 2: Via Composer with composer require firewire/fluency Method 3: Download from the Github repository and unzip the contents into /site/modules/ Feedback File issues and feature requests here (your feedback and testing is greatly appreciated): https://github.com/SkyLundy/Fluency/issues Thank you! ¡Gracias! Ich danke Ihnen! Merci! Obrigado! Grazie! Dank u wel! Dziękuję! Спасибо! ありがとうございます! 谢谢你
  19. Reactions is a module that collects reactions for pages from site users/visitors based on a click of a reaction button. It's basically the same thing as those "did you find the information you were looking for" thingies you see on some sites. An example of what the buttons might look like: There is also a very simple process module that displays pages along with their reaction counts for each enabled reaction type. GitHub repository: https://github.com/teppokoivula/reactions Modules directory: https://processwire.com/modules/reactions/ Needed this for a project and was kind of in a hurry, so it's not super polished, but seems to work well for basic use cases. One thing that's kind of fun (or scary) about this module is that it modifies the structure of the reactions database table automatically based on active buttons; this is done using ProcessWire's built-in features ? Getting started You can install the module the usual way; clone or download the code, or install via admin. Or via Composer: composer require teppokoivula/reactions The easiest way to define available buttons is via site config: $config->reactions = [ 'reaction_types' => [ 'like' => [ 'title' => 'Like it', 'icon' => '<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M720-120H280v-520l280-280 50 50q7 7 11.5 19t4.5 23v14l-44 174h258q32 0 56 24t24 56v80q0 7-2 15t-4 15L794-168q-9 20-30 34t-44 14Zm-360-80h360l120-280v-80H480l54-220-174 174v406Zm0-406v406-406Zm-80-34v80H160v360h120v80H80v-520h200Z"/></svg>', // optional attributes, either as an associative array or as a string, e.g.: // 'attrs' => [ // 'data-some-attr' => 'value', // ], // 'attrs' => 'data-attr="value"', ], 'love' => [ 'title' => 'Love it', 'icon' => '<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="m480-120-58-52q-101-91-167-157T150-447.5Q111-500 95.5-544T80-634q0-94 63-157t157-63q52 0 99 22t81 62q34-40 81-62t99-22q94 0 157 63t63 157q0 46-15.5 90T810-447.5Q771-395 705-329T538-172l-58 52Zm0-108q96-86 158-147.5t98-107q36-45.5 50-81t14-70.5q0-60-40-100t-100-40q-47 0-87 26.5T518-680h-76q-15-41-55-67.5T300-774q-60 0-100 40t-40 100q0 35 14 70.5t50 81q36 45.5 98 107T480-228Zm0-273Z"/></svg>', ], 'haha' => [ 'title' => 'Haha!', 'icon' => '<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M480-260q68 0 123.5-38.5T684-400H276q25 63 80.5 101.5T480-260ZM312-520l44-42 42 42 42-42-84-86-86 86 42 42Zm250 0 42-42 44 42 42-42-86-86-84 86 42 42ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-400Zm0 320q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Z"/></svg>', ], ], ]; ... though you could also add them programmatically, e.g. if you wanted to manage them via admin: $wire->addHookBefore('Reactions::setReactionTypes', function(HookEvent $event) { $reaction_buttons = $event->wire()->pages->get(1)->reaction_buttons; if ($reaction_buttons->count()) { $reaction_types = []; foreach ($reaction_buttons as $reaction_button) { if (!$reaction_button->title) continue; $reaction_types[$reaction_button->name] = [ 'title' => $reaction_button->title, 'icon' => $reaction_button->icon && $reaction_button->icon instanceof Pageimage ? $reaction_button->icon->filename : null, ]; } if (!empty($reaction_types)) { $event->arguments(0, $reaction_types); } } }); The module has basic styles and scripts bundled in, though you'll have to load them yourself: <link rel="stylesheet" href="<?= $config->urls->Reactions ?>styles/reaction-buttons.css"> <script src="<?= $config->urls->Reactions ?>scripts/reaction-buttons.js"></script> ... and then call the render method to render the buttons in your template file(s): <?= $modules->get('Reactions')->renderReactionButtons() ?> For those interested in doing stuff like displaying something based on the answer, bundled JS triggers an event that you can listen to: document.dispatchEvent(new CustomEvent('reactions-updated', { detail: { pageID: pageID, reaction: reaction, }, }, { bubbles: true }));
  20. --- 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.
  21. Page View Statistic for ProcessWire is a module to log page views of the CMS. The records including some basic information like IP-address, browser, operating system, requested page and originate page. This module doesn't claim to be the best or most accurate. Advantages One of the biggest advantage is that this module doesn't require any external service like Google Analytics or similar. You don't have to modify your templates either. There is also no Javascript or image required. Disadvantages There is only one disadvantage. This module doesn't record visits if the browser loads the page from its browser cache. To prevent the browser from loading the page from its cache, add the following meta tags to the header of your page: <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" /> <meta http-equiv="Pragma" content="no-cache" /> <meta http-equiv="Expires" content="0" /> How to use The records can be accessed via the Setup-menu of the CMS backend. The first dropdown control changes the view mode. Detailed records View mode "Detailed records" shows all visits of the selected day individually with IP-address, browser, operating system, requested page and originate page. Click the update button to see new added records. Cached visitor records View modes other than "Detailed records" are cached visitor counts. Cached visitor records are collected on a daily basis from the detailed records. This approach is new in version 1.0.8 and ensures fast display even with many records. Another advantage is that the detailed records can be deleted while the cache remains. The cache can be updated manually or automatically in a specified time period. Multiple visits from the same IP address on the same day are counted as a single visitor. Upgrade from older versions Cached visitor counts is new in version 1.0.8. If you just upgraded from an older version you might expire a delay or even an error 500 if you display cached visitor counts. The reason for this is that the cache has to be created from the records. This can take longer if your database contains many records. Sometimes it might hit the maximally execution time. Don't be worry about that and keep reloading the page until the cache is completely created. Upgrades in general It seems that the upgrade function don't get called after an upgrade. This might be a bug in ProcessWire. This can lead to an error message ("Unknown column...") if you try to open the statistic page immediately after an upgrade. There are two ways to avoid this error message. Click the "Continue to module settings" button directly after the upgrade or open the Modules page and click the "Refresh" button. Time of view This module can record the time a visitor viewed the page. This feature is deactivated by default. To activate open the module configuration page and activate "Record view time". If activated you will find a new column (S.) in the records which means the time of view in seconds. With every page request, a Javascript code is added directly after the <body> tag. Every time the visitor switches to another tab or closes the tab, this script reports the number of seconds the tab was visible. The initial page request is recorded only as a hyphen (-). Execution time Starting with version 1.1.9 this module records the PHP execution time from the initialization of the module till the HTML output in seconds. Settings You can access the module settings by clicking the Configuration button at the bottom of the records page. The settings page is also available in the menu: Modules->Configure->ProcessPageViewStat. IP2Location This module uses the IP2Location database from: http://www.ip2location.com. This database is required to obtain the country from the IP address. IP2Location updates this database at the begin of every month. The settings of ProcessPageViewStat offers the ability to automatically download the database monthly. Please note, that automatically download will not work if your webspace doesn't allow allow_url_fopen. Dragscroll This module uses DragScroll, a JavaScript available from: http://github.com/asvd/dragscroll. Dragscroll adds the ability in view mode "Day" to drag the records horizontally with the mouse pointer. PhpUserAgent This module uses PhpUserAgent available from: https://github.com/donatj/PhpUserAgent. PhpUserAgent is required to filter out the browser type and platform from the server request. New in version 1.1.0 A new feature in version 1.1.0 offers the possibility to record user names of logged in visitors. Just activate "Record user names" and "Record loggedin user" in the module settings. New in version 1.1.3 A new feature in version 1.1.3 offers an internal WHOIS function. In the module settings you can switch between internal and external WHOIS. New in version 1.1.4 Detailed records can now be exported as CSV-file. The file contains all data of the specified date regardless of the pagination. The button is located at the bottom of the page. New in version 1.1.8 The UserAgentParser was exchanged with PhpUserAgent due to some complaints.
  22. Hey all! This is a module to enhance forms built using the Pro FormBuilder module by providing the ability to submit them in place using AJAX and HTMX. FormBuilderHtmx works in harmony with FormBuilder by handling front-end rendering and AJAX and lets FormBuilder manage form configuration and processing. FormBuilderHtmx provides a drop-in replacement for the $forms->render() method and provides all native features and behavior (and adds a few extra superpowers to boot). Noteworthy features: Zero configuration, install and render AJAX powered FormBuilder forms immediately Render multiple forms on the same page. Supports both multiple instances of the same form or different forms. Each form is processed independently. Non-intrusive, can be used alongside FormBuilder's native rendering methods and does not modify core module behavior Perfect for forms embedded in popups and modals Does not conflict with styling and other JavaScript already in-place, only handles the form submission/response loop Automatically disables the `Submit` button on submission to prevent duplicate requests Provides the ability to add a custom 'spinner' shown when a form is being processed Gives you the ability to add additional HTML attributes to your FormBuilder <form> element. Add additional custom functionality using HTMX attributes, hook into form actions with your JavaScript, or even add AlpineJS directly to your forms. Compatible with FieldtypeFormSelect, let users choose which forms to embed, your code determines how they are rendered Uses HTMX, a stable, powerful, and tiny (14kb gzipped) library, installation documentation available here This module is BYOH (Bring Your Own HTMX) in that the HTMX library is not included or available within this module. This ensures long-term stability by not locking FormBuilderHtmx to external asset versioning. FormBuilderHtmx uses stable core HTMX features so use the library version that works for you and confidently add this module to both new, existing, and future ProcessWire applications. In some instances CSRF protection may need to be disabled to submit forms with this module. Just test your forms and you're good to go. Using this module is truly easy. <!-- Replace the native $forms->render() method with $htmxForms->render() --> <?php $htmxForm = $htmxForms->render('your_form_name') ?> <!-- Use native ProcessWire properties and methods as usual --> <?php echo $htmxForm->styles; echo $htmxForm->scripts; echo $htmxForm; ?> Presto. You can optionally include a helpful 'spinner' or activity animation that will be showed to users while their form request is being processed. Check out these ready-to-go examples you can use in your projects. <style> /* Add these styles to your CSS, the `.htmx-request` must be present as shown here. Be sure to include any CSS your 'spinner' may need, and style everything as desired */ .activity-indicator { display: none; } .htmx-request .activity-indicator, .htmx-request.activity-indicator { display: block; } </style> <!-- Optional second argument matches that of the $forms->render() method for pre-populated values The third argument is the CSS selector matching your 'spinner' element --> <?= $htmxForms->render('your_form_name', [], '#indicator-for-the-form') ?> <div id="indicator-for-the-form" class="activity-indicator"> <span class="spinner"></span> </div> Presto (again) Check out the documentation for detailed usage and other available features. Pull requests and issues filed on Github are welcome, or drop by here to get some help! Install as a ProcessWire module Install using Composer Download from the FormBuilderHtmx Github repository . Cheers!
  23. This module lets you restrict users to a certain branch of the page tree - it can limit editing permissions, as well as the page list view to this branch. http://modules.processwire.com/modules/admin-restrict-branch/ https://github.com/adrianbj/AdminRestrictBranch Restricted View Non-restricted View Note that this module does not add permissions (unlike how PageEditPerUser and PageEditPerRole work), so the user must have template level permissions to edit the pages in the restricted branch. What this does allow though is giving all users/roles editing access for the home template and allowing that to inherit all the way through the page tree and let this module restrict to specific branches. As you can see from the screenshots you can specify how to determine the branch to restrict the user to - either via a matched role name, or via a dedicated page select field on the user's profile. The match role name works like this - if you have a series of branches called: Branch One, Branch Two, etc, users with a role named: branch-one will only have access to Branch One. You can also decide whether to restrict page tree viewing as well and editing privileges (default) or just editing privileges. The Branch Exclusions option is important for things like external PageTable parent branches etc. Main module config settings User specific branch setting on user profile page This module came out of my personal needs as well as this discussion: https://processwire.com/talk/topic/11428-project-design-main-shop-hundreds-of-affiliates/ As always, feedback is very welcome.
  24. Session Info Lists information about active sessions in a similar way to SessionHandlerDB, but for file-based sessions. Only install the module if you are not already using SessionHandlerDB. Installation 1. If you want to be able to see the pages that are being viewed by active sessions then set... $config->sessionHistory = 1; ...in /site/config.php If you have already set $config->sessionHistory to a higher number then you can leave it unchanged: 1 is the minimum needed for use in the Session Info module. 2. Install the Session Info module. A helper module named "Session Extras" will be automatically installed also. 3. If you want to be able to see the IP address and/or user agent for active sessions then visit the module config page for Session Extras and tick the relevant checkboxes. 4. You can now view information about active sessions at Access > Sessions. Screenshots With $config->sessionHistory set to 1 or higher: Additional information is listed when IP address and user agent tracking are enabled in Session Extras: https://github.com/Toutouwai/ProcessSessionInfo https://processwire.com/modules/process-session-info/
  25. 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.
×
×
  • Create New...