Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation since 10/13/2025 in Posts

  1. ProcessWire’s API is accessible through API variables and it provides multiple ways to access them. There are benefits and drawbacks to each approach and this post aims to cover them all. We also look at how to add your own API variables as well. https://processwire.com/blog/posts/api-variable-best-practices/
    21 points
  2. This is an inputfield module I made as a replacement for InputfieldPageListSelect, due to frustration with it not opening the page structure to the currently selected page. Please note the requirement of ProcessWire >= v3.0.248 when using it as an inputfield for a Page Reference field due to this now fixed core issue. The module doesn't make the PW version a strict requirement in case you just want to replace instances of InputfieldPageListSelect via the bundled ReplacePageListSelect module. Page Tree Select An inputfield for selecting a single page from the page tree. This inputfield is similar to the core InputfieldPageListSelect, but it has the following advantages: It automatically expands the tree to the currently selected page. This avoids having to drill down through the tree when you want to change the selection to a sibling or child of the currently selected page. This was the primary motivation for creating the module. It's faster to navigate through because the whole tree is rendered at once rather than branch by branch. It provides a filter feature to locate pages by title anywhere in the tree. When the tree is filtered you can hover a page title to see the breadcrumb path to the page in a tooltip. It provides buttons to clear the current selection, to restore a changed selection, and to scroll to the selected page. Configuration The following config options are available when using the module as an inputfield for a Page Reference field: Exclude admin pages: excludes pages from the tree that have the admin template (only affects superusers who can otherwise see pages with this template). Exclude pages by template: pages having any of the templates you select here will be excluded from the tree. Descendants of any excluded pages are also excluded. Limit for total pages in the tree: this limit is applied to the selector that finds pages for the tree (default is 5000). Limitations and considerations Performance seems to be reasonable when the tree consists of up to 5000 pages. Your mileage may vary and the module may not be suitable for sites with a very large number of pages (unless excluding pages by template in the inputfield configuration). Pages in the tree show their titles rather than any custom setting defined for the template "List of fields to display in the admin Page List". Page titles are only shown in the default language. The module does not reproduce some of the quirks/features of ProcessPageList such as excluding pages that are hidden and non-editable, and forcing the sort position of special pages like Admin and Trash. ProcessWire >= v3.0.248 is needed for the inputfield to appear as an option in Add Field due to this now fixed core issue. Replacing InputfieldPageListSelect in the ProcessWire admin An autoload module named ReplacePageListSelect is bundled with InputfieldPageTreeSelect. Install the module if you would like to replace all instances of InputfieldPageListSelect in the ProcessWire admin with InputfieldPageTreeSelect. For advanced use cases there are two hookable methods: ReplacePageListSelect::allowReplacement($inputfield): set the event return to false to disable replacement on particular instances of InputfieldPageListSelect. ReplacePageListSelect::getPageTreeSelect($inputfield): set excludeAdminPages, excludeTemplates and limitTotalPages properties on the event return InputfieldPageTreeSelect object when replacing particular instances of InputfieldPageListSelect. https://github.com/Toutouwai/InputfieldPageTreeSelect https://processwire.com/modules/inputfield-page-tree-select/
    16 points
  3. For modules that are not premium/pro modules, I'd love to see if their inclusion in core would be of benefit to the greater community. Many of, for instance, Robin S.'s modules aim to make the interface experience better for the end-user. Even if the code may not be 100% compliant to what the core expects, the very idea of the module may prove useful in improving the total user experience without the need to discover it elsewhere. Some extremely popular modules (ex: Tracy Debugger) may not be directly suited to being added to the core, so thought should be taken over its usefulness to all, not just specific circumstances or groups of people. Alternatively, is there a preferred way to request addition to core via the Feature Requests Github repository?
    6 points
  4. Back to the basics. Great stuff! Most of the forum posts are about new features. But I really enjoy reading about how to use PW, tips and tricks and such. Would love to see more of those and from Ryan himself especially.
    4 points
  5. @Robin S Good question, theoretically it's more efficient to hook to an object directly when it suits your need, though I'm not sure if it is in practice... I've not done any tests to measure. When hooking '$pages' it's called a "local" hook because it's local to just that instance named $pages (and the hooks are stored with the instance), whereas when hooking 'Pages', it's called a "static" hook and it keeps track track of it in the WireHooks class, as it would apply to any current or future instance of the Pages class. But there's only ever one instance of Pages (named $pages) so it doesn't matter in this case. https://processwire.com/api/ref/wire/get-hooks/ Another way of saying it: The $pages->addHook('method') and $wire->addHook('Pages::method') are technically different calls in that $pages->addHook('method') is saying "Hook method in JUST THIS instance of Pages" and $wire->addHook('Pages::method') says "hook method in ALL instances of Pages". While it may not matter in the case of $pages (since only ever one instance), it does matter in cases where there can be multiple instances of the class, such as with the $page class. In that case, you have a choice to make of "do I want to hook JUST THIS $page"... $page->addHook('method', ...); ...or "do I want to hook ALL Page instances" or "do I want to hook ALL BlogPostPage instances", etc. $wire->addHook('Page::method', ...); $wire->addHook('BlogPostPage::method', ...); What's more efficient about local hooks: If hooking just a single $page instance (or other type), then the attached hooks disappear when the $page instance does. When hooking all instances of a class, then that hook sticks around for the entire request, or until manually removed. When a single instance is hooked (local) rather than all instances (static) then ProcessWire only has to consider that hook for the one instance, rather than all instances. So less work. For $pages vs Pages, there's only one of them either way, so it probably doesn't matter much one way or the other in that case.
    3 points
  6. This is great! The filter feature alone is so good! Will save a lot of time. Thank you very much for this fantastic module!
    3 points
  7. Hello community! We would like to share our new module for ProcessWire: ----------------------------------------------------------------------------------------------------------------------------- Asyntai - AI Chatbot Create and launch AI assistant/chatbot for your ProcessWire website in minutes. It talks to your visitors, helps, explains, never misses a chat and can increase conversion rates! All while knowing your website, customized just for you. Your ProcessWire website can now talk. This plugin embeds the Asyntai chatbot on your ProcessWire site and provides a simple admin page to connect your site to Asyntai. Why choose Asyntai? • Increase conversions: Instant, human like replies keep shoppers engaged and buying. • Never miss a chat: The AI replies day and night, even when your team is offline. • Knows your website: Customized just for you; it follows your instructions. • Works in all languages: Automatically detects and answers in the visitor’s language. • Fast responses (1–3s): Keeps customers from bouncing. Installation Download the module from GitHub or from here Copy the module files to /site/modules/Asyntai/ Go to Modules in your ProcessWire admin Click "Refresh" to detect the new module Click "Install" next to "Asyntai - AI Chatbot" Configuration After installation: Go to Modules → Asyntai Click "Get started" to connect your Asyntai account Sign in or create a free account The module will automatically save your connection The chatbot is now live on your site! Don't have an account yet? Create a free Asyntai account at asyntai.com/auth Managing Your Chatbot Once connected, you can manage your chatbot settings, review chat logs, and customize AI responses at: asyntai.com/dashboard Requirements ProcessWire 3.0.0 or higher PHP 7.2 or higher Have a question? Email us at hello@asyntai.com or try our chatbot directly at asyntai.com/ GitHub: https://github.com/asyntai/processwire-Asyntai
    2 points
  8. Great post, thanks @ryan. I remember you saying somewhere that when hooking a $pages method it is more efficient to add the hook to the API variable. So better to do this... $pages->addHookAfter('saveReady', function(HookEvent $event) { // ... }); ...than... $wire->addHookAfter('Pages::saveReady', function(HookEvent $event) { // ... }); Is that still true? And if so, is it just the $pages variable that the advice applies to or is it broader than that?
    2 points
  9. Thanks @ryan, Knew there were different ways to create a PW API variable object. Until I read your blog, I didn't understand the nuances of when, where and which method best suits the context. Like @Ivan Gretsky,
    2 points
  10. 2 points
  11. Yep, I confirm this still works today. However, the website in question is still using an earlier version of ProCache. 😄
    2 points
  12. With anything new that gets designed (a website, operating system, interface), there's always that initial cringe feeling because it's no longer familiar and comfortable, but after a couple weeks, that goes away. I'm developing a new site and using the new Konkat admin theme, which at first felt totally wrong, but now it feels just right (with 1-2 CSS tweaks, like to make repeaters jump out more). My brain is very picky about adjusting to new fonts... Inter in this case. I like the font a lot, but I just need to adjust to it, get used to the curves. Same thing with new versions of Windows when they change the default font. It's kind of like when Facebook went through a few major design changes at during the 5-10 mark and everyone would complain, then everyone got used to it. Anyway, great work. It's grown on me.
    2 points
  13. Hey @gebeer thx for that report! I have pushed your suggested fix on the dev branch of RockFrontend 🙂
    2 points
  14. [Update] Notify existing buyers and update purchases when products gain gated content (v1.0.10) Hi everyone, we’ve extended StripePaymentLinks based on a customer request. Some products evolve over time and later receive gated content (downloads, course pages, etc.). We now handle that case automatically. What it does: When an existing product is later marked as gated and has a stripe product id the module will: Notify existing users via an access email that new gated content is available for something they already own. Update all relevant purchase entries for those users so the meta object and the purchase_lines reflect the actual delivery page (page ID scope), keeping historical purchases consistent with the current site structure and enabling access control. No manual migration needed; it all happens in the background once the product is flagged as requiring access and the corresponding stripe product id is pasted. Available from now on in v1.0.10. Thanks for the request and feedback that led to this improvement! Cheers, Mike
    2 points
  15. Please replace self::getDirContents($path); with self::_getDirContents($path); (underline is missing).
    1 point
  16. Hi @ I have just installed the forked version of this module. I get the below whenever I try to clear cache in the module setting page. Any hints? Fatal Error: Uncaught Error: Call to undefined method AllInOneMinify::getDirContents() in site/modules/AllInOneMinify/AllInOneMinify.module:1216 Fatal Error: Uncaught Error: Call to undefined method AllInOneMinify::getDirContents() in site/modules/AllInOneMinify/AllInOneMinify.module:1216 Thanks. Gideon
    1 point
  17. Today there’s a new version of ProCache (4.0.7) available for download in the ProCache support/upgrades board. Here’s what’s new in this version of ProCache: ProCache has been updated throughout for PHP 8.4 support. Upgraded the SCSS compiler to the latest Leafo SCSSPHP 2.0.1. This version requires PHP 8.2, so ProCache also lets you choose from two older versions if you prefer. Upgraded the LESS compiler to the latest Wikimedia LESS 5.4.1. Past versions can also be selected, including Wikimedia 3.0.0 and Leafo LESS 0.5.0. Upgraded the CSS/JS minifier to the latest available version (1.3.75 latest). Because we had customized the CSS/JS minification quite a bit, the older version (1.0 stable) also remains selectable, just in case there’s anything the older version handles that the new one doesn’t yet. LESS, SCSS and Minifier versions can be selected and changed in the ProCache configuration: Setup > ProCache > JS/CSS. Likewise the ProcessProCache module has a new JS/CSS tab for configuring the settings mentioned above. ProCache now logs LESS/SCSS and Minify status and errors to the JS console (when in debug mode or for a logged-in superuser). ProCache now has a proper API reference page available here: https://processwire.com/api/ref/pro-cache/ Because this is a brand new version with several upgraded libraries, it should be considered beta until it's been out a couple of weeks. Thanks for reading and have a great weekend!
    1 point
  18. Hello @da² Thanks for reporting these issues, I will check this next week. For now I have tried the max file size validator and it has worked in my case, but I guess I must dig a little deeper. Maybe there is a problem especially with zip files and file size calculation.
    1 point
  19. The website, permacultura-cattolica.it, appears to be working as expected right now. It's possible your computer browser's cache is remembering things incorrectly...? Can you try from a different computer (phone?) or browser just to verify? Either that, or you've fixed it, based on @virtualgadjo's suggestions (which sound correct to me).
    1 point
  20. Thank you @Juergen for the fixes. Sorry not to reply before but I have few free time. ^^ I found more issues: File upload is limited to 500 MB: $zipUpload->setRule('allowedFileSize', '524288000'); But I can add a file larger, the form is valid and the upload starts, but then the server is not happy: With module FrontendLoginRegister, in Account Settings I add Language field. I have 2 languages, french and english, french is default. The form displays the 2 languages only if user is actually using french, when using english, only english is listed in the Select field. If user selects english and save, it works. If user selects french it is not saved. I try to investigate the code quickly, only to find that in Select::___renderSelect(), when user is using english, $option->render() returns an empty string for french.
    1 point
  21. Thank you so much, you saved my day.
    1 point
  22. @prestoav, thanks for the compliments 🙂 I forked AIOM primarily to fix issues I was facing, and then it somehow developed into the version with the caching options. I don't use minification of CSS/JS. I think it's enough to use simple preg_replace to remove blanks. It's painful to follow and track issues for all libraries now included in the module (voku html_min, simple_html_dom, symphony css selector, lessmin, cssmin, jsmin, ...). Not worth it for those few percentages. But hey, the module works, even on PHP 8.5. Did you try/test caching options? @David Karich, I didn't change the class name as I wanted to preserve its name and your contribution/authorship of the module. Thanks for the module! I'll PM you.
    1 point
  23. @Jim Bailie This seems like a good question for ChatGPT, at least to get a starting point. I asked it if it could convert .htaccess to nginx and it said: So I uploaded this v1 ProCache ruleset from one of my site (I replaced product key with "xxx" for this example): # PROCACHE vfd31e36cd7ffdab982312621683b6fee RewriteCond %{REQUEST_METHOD} !=POST RewriteCond %{QUERY_STRING} !.*=.* RewriteCond %{HTTP_COOKIE} !^.*(wire_challenge|wires_challenge).*$ RewriteCond %{DOCUMENT_ROOT}/site/assets/ProCache-xxx/$1/index.html -f RewriteRule ^(.*) %{DOCUMENT_ROOT}/site/assets/ProCache-xxx/$1/index.html [L] # /PROCACHE And it gave me this: # PROCACHE vfd31e36cd7ffdab982312621683b6fee equivalent for Nginx location / { # Skip cache if POST request, query string present, or cookie contains wire_challenge / wires_challenge if ($request_method = POST) { break; } if ($query_string != "") { break; } if ($http_cookie ~* "(wire_challenge|wires_challenge)") { break; } # Serve static cached HTML file if it exists if (-f $document_root/site/assets/ProCache-xxx/$uri/index.html) { rewrite ^(.*)$ /site/assets/ProCache-xxx$uri/index.html break; } # Default: pass to ProcessWire (index.php) try_files $uri $uri/ /index.php?$query_string; } # /PROCACHE I have no idea if it's nginx version works or not, but seems like it might be a potentially good way to convert something like this.
    1 point
  24. https://github.com/matjazpotocnik/ProcessWire-AIOM-All-In-One-Minify Note that AIOM+ has a caching component, similar to Procache.
    1 point
  25. [Update] More flexible access mails (v 1.0.11) Just pushed a small update to the module — a few quality-of-life improvements for access mails. What’s new Custom intro text for access mails – There’s a new field called Access Mail Intro Text (optional) access_mail_addon_txt added to your product templates. Whatever you put in there gets prepended to the access mail’s lead text — great for short intros, personal notes, or product-specific instructions. Hookable mail variables – PLMailService adds the hookable method ___alterAccessMailVars($vars, $mod, $user, $links) You can now easily tweak mail content in your ready.php, for example "first purchase vs. repeat purchase": wire()->addHookAfter('PLMailService::alterAccessMailVars', function(\ProcessWire\HookEvent $event) { $vars = (array) $event->arguments(0); $user = $event->arguments(2); // check if this is the user's first purchase $purchaseCount = ($user->hasField('spl_purchases') && $user->spl_purchases) ? $user->spl_purchases->count() : 0; $isFirstPurchase = ($purchaseCount <= 1); if ($isFirstPurchase) { $vars['preheader'] = 'Welcome! Your new access is ready.'; } else { $vars['preheader'] = 'New access added to your account.'; } // Hand back the modified variables $event->return = $vars; }); As always, feedback, ideas, and real-world use cases are more than welcome — especially if you’ve built custom hooks for your own onboarding or mail flows. Cheers, Mike
    1 point
  26. For anyone trying to use this module in PHP 8, after changing the 2x lines mentioned previously in the main module file I was getting the following error at line 314 of /lib/JSMin-2.1.7.php : ord(): Passing null to parameter #1 ($character) of type string is deprecated The line in the file is: if (ord($c) >= self::ORD_SPACE || $c === "\n" || $c === null) { return $c; } Changing it to his solves the issue: if ($c === null || ord($c) >= self::ORD_SPACE || $c === "\n") {return $c;} @David Karich This is a super module and including the three line changes outlined in this thread would be a really nice thing if possible!
    1 point
  27. Wow, that was quick. Thanks. Will wait until it goes into main and then update through module interface.
    1 point
  28. Only 4 years later I found the cause for this. It’s an Apache behaviour: Some Apache configurations are just fine with spaces in URL paths. Some force a 404 status code, no matter what you try to do in your PHP. Might have something to do with ModSecurity module, but I’m not sure. Better be safe: If you can avoid spaces or %20 in URLs, do it!
    1 point
  29. There are quite a few topics with this issue but maybe this specific answer from @Robin S could help? Also, since it seems to be an issue with AJAX, are you seeing any difference if you toggle on (or off) this option?
    1 point
  30. Hello @Juergen, once more thank you very much for your superb support 🙂 In the meantime I found the "Multi-language" section in the documentation as well - sorry I have overlooked this. But the infos you provided above are much appreciated, I will dive into this later on today. Regarding the multi-page form - I need to reconsider this as implementing forms seems to be a challenge for me as a citizen web developer on its own.Maybe the Form Builder plugin can help to achieve this...
    1 point
  31. I have found the issue: This only happens if the ID and name attribute are exactly the same on a single upload field. If there is a difference, everything works as expected, so I have added an additional suffix to the ID attribute of a file upload field to prevent this behavior. display-change.MP4 Now everything should work fine! Module version is updated, so please test if everything works now as expected.
    1 point
  32. Hello @da² I have fixed the 2 bugs with the URL segments (fixes will be in the next update), but I have a question concerning the file upload issue in single upload fields. I have tested it with Firefox without any problems. Take a look at the video. Single file upload.MP4 In my case it works as expected. If I drag and drop more than 1 file only the last file will be taken and only 1 file will be submitted. What browser do you use? Maybe it could be a browser related issue. Best regards Jürgen
    1 point
  33. Off the top of my head, if you require all pages to utilize the unique status, ProcessWire can take care of this for you. You don't ever need to know the path, only the $page->name property, when creating links to pages. That will retain what your client seemingly wants. It may cause issues elsewhere though, if you actually need depth (potentially with URL hooks), or certain modules. I base my response from this short topic:
    1 point
  34. This week we've got several updates to the core on the dev branch. It's primarily focused on small issue fixes and optimizations. Though there's enough since 3.0.251 that I'm bumping the dev branch version to 3.0.252. Next week there won't be any new updates this time next week because I'll be traveling, but will be back right working on the core right after that. Thanks for reading and have a great weekend!
    1 point
  35. With the help of this thread and this StackOverflow response, I think this is working for me with TinyMCE so far: In site/ready.php: $wire->addHookAfter('MarkupHTMLPurifier::initConfig', function(HookEvent $event) { $config = $event->arguments(0); $def = $event->arguments(1); $config->set('HTML.SafeIframe', true); // Allow YouTube and Vimeo $config->set('URI.SafeIframeRegexp', '%^(https?:)?//(www\.youtube(?:-nocookie)?\.com/embed/|player\.vimeo\.com/video/)%'); }); Then, in the PW admin for the textarea field > Input tab > Custom Settings JSON: { "extended_valid_elements": "video,source,iframe[src|width|height|title|frameborder|allow|referrerpolicy|allowfullscreen]" } Note the list of attributes in square brackets after the "iframe". You can use wildcard `[*]` if you want to allow any attribute, though I haven't experimented with that. Finally, clear the HTMLPurifier cache from Tracy Console as described in that GitHub conversation: $purifier = new MarkupHTMLPurifier(); $purifier->clearCache(); This is very fresh, I'm still testing it out, but it seems to work. Might still need to add that bit from SO for the `allowfullscreen`: $def->addAttribute('iframe', 'allowfullscreen', 'Bool');
    1 point
  36. This one's been a long time coming, but this week we launched a site for the UK charity INQUEST who provide support for families involved in state related deaths. This was part of their 40th Anniversary and the site showcases significant milestones and events from their archive over the last 40 years. There's an interactive timeline, case studies and oral histories. Even given the difficult subject matter we're really pleased with the result: Behind the scenes, the modules we used were mostly the usual suspects, Tracy Debugger, ProCache etc. Also RockFrontend specifically for the ajax routing (would love that as a separate module @bernhard ) which we used with HMTX in various places. Not sure we really needed to use HTMX on this one but hey, it is very handy. One module we made use of which we hadn't used before was @Richard Jedlička's PDF fieldtype so that we could generate thumbnails of PDF documents. There are a lot of historical documents on the site and having the thumbnails generated automatically was really handy. The site seems to have gone down really well. And we actually had a launch party - it's been years since that happened... https://history.inquest.org.uk/ Oh, and it does very nicely in Lighthouse and gets A+ in Observatory as well 🙂
    1 point
  37. View website: ID Studio Web Agency We have been working on the ID Studio website for quiet some time using ProcessWire extensively for ourseleves and 90% of all our clients. This post will highlight some features we have implmented and also show off some of the hidden functionality. A quick overview is as follows: Custom web design of course 🙂 Front-end uses Canvas and Three.JS The core objective for us is to get users engaged, reviewing the showcase and services, then getting in touch The showcase and blog have alot of content We hide the ID Lab and About section in the footer but there if folks want to dive in and have the time Development features include: We use the form builder system with some custom modifications 3D tools and management Linking 3D elements to HTML elements Repeater matrix for content panels and lots more, best way is to see it on the video overview below ID-Overview.mp4
    1 point
  38. I have to implement Google Consent v2 together with PrivacyWire for the first time. I tried to summarize the most imporant things and make a quick example. Hope that helps. Improvements welcome. Basically Google wants you to send the user preferences. This way Google can process at least anonymized data if the user denies permissions (and promises to respect privacy). Luckily PrivacyWire gives us the possibility to define a custom js function in the module configuration, which is executed whenever user preferences change. PrivacyWire stores user preferences in localStorage. From there we can fetch this information when needed. So we have to: 1. Integrate Google Tag Manger without modifying the script tag. 2. Set Consent v2 defaults (by default deny every permission): <!-- GOOGLE CONSENT V2 --> <script async src="https://www.googletagmanager.com/gtag/js?id=GTM-ID-HERE"></script> <script> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('consent', 'default', { 'ad_storage': 'denied', 'analytics_storage': 'denied', 'ad_user_data': 'denied', 'ad_personalization': 'denied' }); gtag('js', new Date()); gtag('config', 'GTM-ID-HERE'); </script> <!-- End GOOGLE CONSENT V2 --> 3. Use a function called by PrivacyWire, when user changes preferences. Fetch user preferences from localStorage and send them to Google: function updateConsentFromPrivacyWire() { console.log('update consent from privacy wire...'); const privacyWireData = localStorage.getItem('privacywire'); if (privacyWireData) { try { const consentData = JSON.parse(privacyWireData); const consentPreferences = { // Set Google params based on user preferences 'ad_storage': consentData.cookieGroups.marketing ? 'granted' : 'denied', 'analytics_storage': consentData.cookieGroups.statistics ? 'granted' : 'denied', 'ad_user_data': consentData.cookieGroups.marketing ? 'granted' : 'denied', 'ad_personalization': consentData.cookieGroups.marketing ? 'granted' : 'denied' }; // Update google consent gtag('consent', 'update', consentPreferences); console.log(consentPreferences); } catch (e) { console.error('Error parsing PrivacyWire-Data:', e); } } else { console.warn('No PrivacyWire-Data found in localStorage'); } } // Update consent at pageload document.addEventListener('DOMContentLoaded', updateConsentFromPrivacyWire); 5. This is what the parameters control: ad_storage: Controls whether ad-related cookies and identifiers are stored (e.g., for remarketing). analytics_storage: Controls whether analytics-related cookies are stored (e.g., for Google Analytics tracking). ad_user_data: Controls the collection and use of user data for advertising purposes. ad_personalization: Controls the use of data to personalize ads based on user behavior and preferences. 4. Configure the function name (here updateConsentFromPrivacyWire) in PrivacyWire module settings.
    1 point
  39. 300-600kb are pretty large chunks. I would go with files to keep the DB size down.
    1 point
  40. Some introduction... This module is experimental and there are probably bugs - so treat it as alpha and don't use it on production websites. I started on this module because there have been quite a few requests for "fake" or "invisible" parent functionality and I was curious about what is possible given that the idea sort of goes against the PW page structure philosophy. I'm not sure that I will use this module myself, just because I don't really see a long list of pages under Home (or anywhere else) as untidy or cluttered. I would tend to use Lister Pro when I want to see some set of pages as a self-contained group. But maybe others will find it useful. At the moment this module does not manipulate the breadcrumb menu in admin. So when you are editing or adding a virtual child the real location of the page is revealed in the breadcrumb menu. That's because I don't see the point in trying to comprehensively fool users about the real location of pages - I think it's better that they have some understanding of where the pages really are. But I'm open to feedback on this and it is possible to alter the breadcrumbs if there's a consensus that it would be better that way. Virtual Parents Allows pages in Page List to be grouped under a virtual parent. This module manipulates the page list and the flyout tree menu to make it appear that one or more pages are children of another page when in fact they are siblings of that page. Why would you do that instead of actually putting the child pages inside the parent? Mainly if you want to avoid adding the parent name as part of the URL. For example, suppose you have some pages that you want to be accessed at URLs directly off the site root: yourdomain.com/some-page/. But in the page list you want them to be appear under a parent for the sake of visual grouping or to declutter the page list under Home. Example of how the page structure actually is Example of how the page structure appears with Virtual Parents activated How it works This module identifies the virtual parents and virtual children by way of template. You define a single template as the virtual parent template and one or more templates as the virtual child templates. Anytime pages using the child template(s) are siblings of a page using the parent template, those child pages will appear as children of the virtual parent in the page list and tree menu. You will want to create dedicated templates for identifying virtual parents and virtual children and reserve them just for use with this module. Features Adjusts both page list and tree flyout menu to show the virtual parent/child structure, including the count of child pages. Works everywhere page list is used: Page List Select / Page List Select Multiple (and therefore CKEditor link dialog). Intercepts the "Add page" process in admin, so that when an attempt is made to add a child to a virtual parent, the child is added where it belongs (the next level up) and the template selection is limited to virtual child templates. Intercepts moving and sorting pages in the page list, to ensure only virtual children may be moved/sorted under the virtual parent. Superusers have a toggle switch at the bottom of the page list to easily disable/enable Virtual Parents in order to get a view of what the real page structure is. Usage Install the Virtual Parents module. In the module config, enter pairs of parent/child template names in the form virtual_parent_template=virtual_child_template. If needed you can specify multiple pipe-separated child templates: virtual_parent_template=child_template_1|child_template_2. One pair of template names per line. There is a checkbox in the module config to toggle Virtual Pages on and off, but it's more convenient to use this from the page list. Notes It's important to keep in mind the real location of the virtual child pages. This module is only concerned with adjusting the appearance of page list and tree menu for the sake of visual grouping and tidiness. In all other respects the virtual children are not children of the virtual parent at all. It's recommended to select an icon for the virtual parent template (Advanced tab) so virtual parents are marked out in the page list as being different from normal parent pages. Do not place real children under a virtual parent. There is some protection against this when moving pages in the page list, but when it comes to changing a page's parent via the Settings tab the only protection is common sense. https://github.com/Toutouwai/VirtualParents
    1 point
  41. Hi, well, all this sounds quite normal, when starting an install process, if the htaccess file is named .htaccess the web site will try to work as if it were installed which is not the case in the contrary, wuen the install process is running/finished this file needs to be renamed as .htaccess with the starting period else it won't work as the server won't find it as a genuine .htaccess file il you have a look à the install.php file code, you'll see when the mutation takes place 🙂 have a nice day
    0 points
×
×
  • Create New...