Jump to content

ryan

Administrators
  • Posts

    16,714
  • Joined

  • Last visited

  • Days Won

    1,515

Everything posted by ryan

  1. I forgot to mention earlier, but I haven't yet experimented with integrating htmx into this. Trying to start simple so right now it's all original PHP/JS. I do plan to experiment with htmx here to see what additional options it'll open up. The current version does however use server side events (SSE) like some of you guys (Ivan, Netcarver, Kongondo) suggested. @Ivan Gretsky Configurable repeater type colors I haven't yet added but will try to do that this coming week.
  2. For anyone that is testing out the live preview feature in the PageAutosave module, if you have any trouble getting it to work, here's a few troubleshooting notes: 1. Try temporarily disabling Tracy debugger on the front-end (if using it). I found that I couldn't have Tracy debugger active on the front-end while using live preview, otherwise neither Tracy or live preview would work. I think the two conflict with each other in some way and I just haven't figured it out yet but will work with it more next week. 2. If using ProCache with HTML minify, try turning that feature off for logged-in users. You can do this in Setup > ProCache > Minify. The reason for this is that HTML minify removes a few technically unnecessary markup tags that live preview may need. I will also be able to find a workaround for this, but just haven't had a chance yet. 3. Make sure your HTML document has <head>, </head>, <body> and </body> tags present in the output. 4. If your page does a lot of its layout with Javascript and isn't working with live preview, go to the PageAutosave module settings and near the bottom are the Live Preview settings. For the "Default live preview update method" choose "Reload/refresh document". 5. If still not working, try enabling the PageAutosave debug mode. You'll find this at the bottom of the PageAutosave module settings. This makes it report verbose javascript console.log messages. Open your javascript console when using live preview and please let me know what messages you get.
  3. @adrian So far I'm not seeing this one. I also backtracked through the code from that line and don't see anything obvious. Do you know what steps are necessary to reproduce it? Also wanted to mention it may be necessary to disable Tracy on the front-end for the live-preview to work. I was running into JS errors from Tracy when trying to use it with live preview, which had the effect of preventing either from working. I think it's because both live preview and Tracy are adding code in the page, and live preview must be doing something that interferes with Tracy's JS. I think I'll be able to figure out a way around it but just wanted to mention it in case you or anyone else were observes it not working when the Tracy bar is active. @Jonathan Lahijani This is fantastic! I'm blown away by it. Amazing work. How did you come up with this video so quickly? (and so well narrated too)
  4. @wbmnfktr Sounds good, those are the boards you are able to view? I've added it to the first one you mentioned (ProFields board). Thanks.
  5. Work has continued on the Page Autosave module this week and several more improvements have been made, compiled into version 2 of the module (now posted in ProDrafts and ProDevTools). The PageAutosave portion has been improved in several ways. For instance, when the page changes elsewhere, autosave disables and displays a message letting the user know about the change. An issue with CKEditor inline fields was also fixed. But the biggest addition to the Page Autosave module was Live Preview. We've got a good discussion going on in last week's post and it helped move things forward with building the live preview feature. It's functional and working well, though it's a start and there's still more to do with it. It's far enough along to begin testing so I've posted it in the ProDevTools and ProDrafts boards. If you don't have access to either of those boards but do to one of the other VIP boards and want to test it out, let me know and I'll add it there too. Since I'm not yet certain whether this module will end up in the core, as a module, or as part of an existing Pro module package, I'm keeping it in the VIP boards at least until it's more production ready. If I find that it adds a lot of value to the core and I can fully support it there, then it'll end up in the core. Here's how the live preview feature works: When live preview is enabled (it is by default), the “View” tab in the top of the page editor supports a live preview option. To see it, hover the “View” tab and it should appear. When you click the live preview link it will open a new window. Drag and size the live preview window so that you can see it at the same time as your page editor, whether side-by-side, above or below, or on another screen. As you make changes in the page editor and they are automatically saved, the live preview window will also update automatically. No development required There is no development required to use live preview, you don't have to insert anything into your template files to start using it. The live preview window updates by re-rendering the page and replacing the entire <body> markup of the page. I found this works well in several places where I tested it and it has the benefit of looking pretty seamless and keeping your scroll position, etc. But it's not going to work everywhere, and it can also lose JS events (though I'm looking into how we can improve that). This might be okay since you are just previewing content and layout, but it's something to keep in mind. If you find the default <body> replacement doesn't work well for your instance, there's a setting in the module configuration where you can tell it to reload/refresh the window for live preview instead. This will pretty much always be reliable, but it also looks like a page refresh, which somewhat reduces the live preview effect. To control and improve performance of live preview There's another option that enables you to have more control over how live preview works while also significantly improving the performance of it. The tradeoff is that you need to add class names in your markup for live preview to recognize and update. When you want live preview to just render and replace the value for the field being edited, you can edit your template file(s) and surround the field value output with a tag having the class name "pw-value-name" where "name" is the name of the field that has its value contained within. This can significantly increase performance as live preview can render and dynamically update just the changed field rather than the entire page. For example, let’s say you had the following markup: <h1><?= $page->title ?></h1> To mark it up for fast live preview, you would add a new class: <h1 class='pw-value-title'><?= $page->title ?></h1> When an update is made to the “title” field in the page editor, live preview will notice the h1.pw-value-title in your markup and it can skip rendering the entire page and instead just render the value of the “title” field for the page, and replace it directly. A few things to note about this: 1. Live preview replaces the “inner HTML” of the element directly with the formatted field value. You should not have any other markup within there, unless it’s part of the field’s formatted value already. 2. The surrounding element (<h1> in the example above) can have any other class names or attributes that you want it to have. Live preview does not replace the tag, only the contents within it. So if you add the pw-value-* class to an existing element that already has other classes or attributes, that’s fine, it's flexible. 3. When you use this option, consider also using it in other places you output the same field value (if there is more than one), otherwise live preview won’t update the ones that aren't identified with the pw-value-* class. So if your $page->title appears elsewhere, like in breadcrumbs (for example) then that breadcrumb instance of the title won’t update, unless it is also marked up with the pw-value-title class. Maybe that is fine for breadcrumbs for it not to update, but it’s just something to be aware of. 4. This pw-value-* option is just for basic text, textarea (including CKEditor) and number fields. Don't use this stuff in repeater, file/image and other more complex fields, as those will always involve generated markup beyond just the field value. For something like a blog post or other article type of page, if you want a 2 minute solution that'll give you the most return, just wrap your $page->body output and call it a day: <div class="pw-value-body"><?= $page->body ?></div> ...that way any changes to your "body" field will update more quickly and without having to re-render the page. What's remaining Like discussed in last week's thread, I'd still like to add support for "pw-field-*" classes. This will be similar to the "pw-value-*" classes, except that it'll enable replacing blocks of generated markup within the element having that class name, rather than just the field value. This'll be useful for people really getting into live preview. But I also kind of think that most people will want to use live preview without having to add anything in their markup, and it works quite well that way too. This is all I worked on this week so no core updates to report (though this may count as core updates if it ends up in the core). Thanks for reading and have a great weekend!
  6. The thing I'm thinking of is that a lot of people don't do this (often me included). Like if we've got a button with id="my-button" that we want to add a click event to, then we add it to $("#my-button").on('click', ...); and that no longer works if the button gets swapped with something from live preview. Of course, it's just a matter of coding the JS in a different way. But before telling people to code things a certain way I like to see if I can find a way to make things work no matter how they've put together their front-end code. For this case (live preview) it's probably not that important though.
  7. @kongondo Thanks, great ideas! Your SSE examples are eye opening. I think I understand a lot of this but not yet all of it, since I'm not deep in htmx yet, so I'll have to return to this once I do. But part of what you covered was the external interface to it that the web developer implements, and I think that's a good place to start, so I'll focus just on that. I understand the benefits of a separate config file, but am not sure how many would go to the effort of maintaining it for live preview. Maybe if PW auto-generates it somehow with functional defaults, it might help. Pros/cons aside, when we need something outside of the defaults, personally I'd rather declare this with markup classes or attributes in a manner similar to how we do for Markup Regions. Maybe I'm lazy, but it's already easy and familiar, and not much new to remember. Like with Markup Regions, ProcessWire can remove the attributes when they aren't needed, so no need for any output downsides. But if I had to declare it separately from the markup, I'd at least like to be able to do it in Setup > Fields > field rather than having to edit a .json file (and maybe this is a good fallback either way). I agree that it's good if the default behavior is to swap the entire <body> / refresh the window. But when we want to declare what gets updated with a live preview, here's an example of one way we could do it. If I wanted a particular section of markup to update automatically when the field "images" changed, I'd like if I could just do something simple like this, where div#gallery is an existing bit of markup a already there, like this: <div id='gallery'> // markup for an image gallery </div> …and I just add a class to that existing markup tag... <div id='gallery' class='pw-field-images'> // markup for an image gallery </div> ...or maybe a custom attribute instead: <div id='gallery' pw-field='images'> <!-- markup for images gallery --> </div> I'm not suggesting to add additional markup, but just an additional class or attribute to existing markup. If that same images field was also used elsewhere in the page, then I could just use that class (or attribute) again, and it would update too: <div id='sidebar-photos' class='pw-field-images'> <!-- markup for the sidebar photos --> </div> One thing I noticed in coding ProDrafts live preview is that field-level granularity often makes little difference in the end result. Replacing larger blocks of markup often is just as effective and visually identical. So I'd want to be able to say "if any of these fields change, update this…": <div id='content' pw-field='title,body,images,sidebar'> ... </div> For fields that already contain markup (like CKEditor), or fields that get rendered from their own /site/templates/fields/* template file, ProcessWire could automatically add the appropriate class by wrapping the value with it (this is similar to what ProDrafts and PageFrontEdit do): <div class='pw-field-body'> <!-- value of $page->body, div wrapper added automatically when live preview --> </div> This enables it to work automatically, without the developer doing anything at all. The only minor downside is that occasionally that can interfere with a CSS/JS selector, like if you are trying to target h1 + p:first-child, where the <p> is part of the CKEditor output but the <h1> isn't. Live preview still works, but the CSS/JS selector no longer matches when live preview is on. It's simple to work around though, and of course only affects output when someone is live previewing. Whether using a separate config file or not, if we use htmx, I think it should be a silent player and the developer wouldn't even need to know anything about how to use it. I'd like to avoid an external config file where I'm having to add 'htmx-attributes' arrays. I don't think we need the level of granularity or features in live preview that would demand the user know this kind of stuff. (Though fine for advanced users if/when needed). The more automatic it is, the more likely one is to use it. I think we'd also like the flexibility of not being dependent upon any particular library in case we ever decide to replace it with something custom. Side note, but one issue I also noticed in coding ProDrafts live preview is that when you update an element that has JS events on it that were added in document.ready, then they no longer work. For instance, an images gallery might have events that make thumbnails open in a lightbox or something. When the images gallery live updates, the lightbox no longer works unless the events were added to the whole document. Does htmx have some magic for this kind of situation?
  8. @Ivan Gretsky That part I know I can handle. It's the front-end JS side of it that I don't know a lot about, yet. I mean this just to suggest the possibility of establishing some sort of guidelines for how a developer might implement selective rendering. I don't know what those guidelines would be, and just use that GET var as an example of how a request might indicate a change for a particular field (named "body"). Trying to communicate that in the simplest example possible. The developer would decide what that meant in terms of output that should be produced. But perhaps this example is too far from the context, I'm still learning how this SSE stuff works. PW can't generate partial markup for anything (outside of the admin at least), so it would be up to the site developer to implement whatever methodology we suggest for this, at least if they want higher performance live updates. From what I can tell, htmx can handle both cases... replacing partial markup, or selecting a part (hx-select) from a larger portion of markup, like the full document. @kongondo Yes you are right, it wouldn't be very practical. But the benefits of selective markup rendering may be enough that it's worthwhile for us to establish some guidelines for supporting selective rendering. Like that ?change=body example earlier, that's what I was trying to communicate there even if it's likely not a good example. The guidelines could be as simple as just letting the site developer know when they can skip over expensive things to render, like primary navigation or footer, etc. Something like if($config->livePreview) { // skip rendering unnecessary primary navigation } else { // render primary navigation } I was actually thinking of "body" as a PW field name, and the developer would decide what that means to the output in terms of what should be replaced. But you guys have a lot more experience with htmx than me so I think my example is likely flying a little blind, as my focus so far as only been on the auto-save part that identifies field changes. I need to start playing with htmx. ? The way that ProDrafts live preview works is by having the editor window communicate to the preview window and notify it when a field changes (JS based window-to-window communication). The preview window does pull a fresh/updated copy of the rendered page, but it attempts to only replace the markup that changed. It does this by having formatted values for fields like "body" include an extra <div> around them that identifies what it is, and then ProDrafts can replace just that element with JS. You can see things as you type in the editor, with a short delay, unless your page is very slow to render. This works well for formatted text fields (which is usually most of what one wants to see in live preview), but it does have to refresh the full document for other things where the site developer may be responsible for more runtime markup related to the field output. @monollonom ProDrafts only reloads the whole frame as a last resort. For most cases it can update just what changed. This is helpful for avoiding a very visible and distracting page refresh. Such page refreshes kind of kill the live-preview effect and can more easily draw your attention away from the content you are working on. I don't know if it'll be necessary to introduce a 3rd party dependency or not (htmx), but it does seem like a good place to start, even if we end up rolling our own later. That's more the domain of ProDrafts, and PagesSnapshots (another module in development). I think any kind of core autosave and live preview will focus on just those features (autosave and live updated view) and making them as good as they can be. It might be that one only wants to use these features for unpublished pages, but I think that's where it is most useful in the first place. If you wanted autosave/live preview on a published page, you could always clone it and then replace the original (or not) when you were done. This is essentially how PagesSnapshots manages drafts.
  9. Thanks for all of the replies, this is great information. It sounds like SSE is the way to go here. I don't have any experience with that yet so am looking forward to learning more. I'm basically repeating what's been said above, but it sounds like htmx has this built in and may be a simple way to get started with it. Since this is a front-end modification (where PW doesn't usually venture into), the more lightweight we can be with it, the better. So we might eventually consider putting together just the functionality that we need for this part, as I know htmx does quite a bit more. But since I know almost nothing about SSE, htmx sounds like a great place to start. Since the front-end comes exclusively from user's template files, I don't think there's a way that ProcessWire can selectively render one thing or another in the page. It has to render the entire page. But it does sound like the actual JS-update part of it could certainly be more selective. For users that want selective server-side rendering of elements, it's certainly possible that we could provide some kind of suggestion that the developer should follow, as a means to increase performance of live preview. For instance, if the URL is /path/to/page/?change=body then the developer might detect $input->get('change') === 'body' and render the markup appropriately. But I think most will just want a drop-in solution that they don't have to code around. And that means how fast it works would have more to do with how efficiently the site is coded and how fast the environment is that it's running is. I don't think this will ever be a "see each character as you type" type of live preview, but I think most of the value of live preview will still be present even with a small delay.
  10. Now that we're in the last couple months of this year, I've been trying to implement a lot of plans that we discussed early in the year. That meant a lot of updates to repeaters in the last couple of weeks (and likely more on the way). But this week, I've been working on another thing we discussed earlier, which is bringing automatic save and live preview capabilities to ProcessWire, independently of ProDrafts, and with full repeater support. In ProcessWire, it's your own code (in template files) that renders the site’s output. ProcessWire delivers a $page to your template file(s), and your template file(s) render it in whatever manner they see fit. In this environment, we need an automatic save capability before we can have a live preview capability. Working on that automatic save capability is what I've been doing this week. I figure that once that is finished, then we'll be able to start developing the live preview capability. I'm glad to report that we now have automatic save fully functional and have tested pretty thoroughly with every Fieldtype/Inputfield I can think of. Unlike in ProDrafts, it also fully supports repeater, repeater matrix, and even nested ones. Actually, it looks like we'll be able to support everything you would want it to. But it's early yet it'll need a lot of testing before its production ready. I've built it into a module called PageAutosave. It requires the latest version of ProcessWire on the dev branch (3.0.189). I'm not yet positive whether this is going to end up as a core module or not. I thought I would gauge interest and see. For now, I'm posting a limited release test version of it in the ProDrafts support board and ProDevTools support board, if anyone is interested in trying it out. The PageAutosave module lets you configure whether you want it enabled for all pages or just for unpublished pages. When needed, you can also optionally choose to limit it to certain templates, certain fields, or certain user roles. Autosave isn't always desirable as it literally means your changes get saved to the $page as you type, so I imagine it's something people might use more for unpublished pages. Autosave is one side of the coin and live preview is the other. The current goal for live preview is to not depend on any particular view or admin interface and instead to just simply have the option of having a window open to a page in the website that detects changes and updates them automatically. So if you had one window open to the page edit screen, and another window viewing the page being edited, you could observe your updates as you made them. Once that is working reliably, we can decide on how best to put an interface around it, and maybe some will also like the option of just having two browser windows open wherever they want them. This won't be the kind of live preview where you'll see every character as you type it, but more likely you'll see updates a second or so after you make them. That's because your edits have to be auto-saved in the page editor, ProcessWire has to call your template file(s) to render the output, and the live preview has to update whatever has changed since the last update. It's that last part of it that I'll need the most help on. Some of you have mentioned htmx as a potential way to accomplish that and I think it looks compelling. And if you know of any other [likely JS-based] tools or technologies that we should also look at, please reply and let us know. I've bumped the core version to 3.0.189 primarily because the PageAutosave module requires updates that are in this version. This version also continues some longer term build out of a couple Fieldtype interface methods across multiple modules, and adds a new 'sorted' JS event that is triggered during sort actions (also used by PageAutosave). But if you aren't going to be installing the PageAutosave module, there's no urgency to update to 3.0.189 if you are on the dev branch and already using 3.0.188. Thanks for reading and have a great weekend!
  11. @adrian @Jonathan Lahijani Consider those warnings to just be strong suggestions. If you want to ignore them, it's likely okay, but for most (including me) I would avoid colliding repeater matrix type names with field names because it's a source of confusion. I think I had also identified a case where it could a problem. I don't remember exactly what it was, but do remember it was possible enough to warrant displaying warnings about it, but unlikely enough to be okay to ignore if everything otherwise works. @wbmnfktr Turns out thats a leftover debugging/development message which is blank because the value it's showing is empty unless you use the images feature. It should only appear when editing the matrix field (Setup > Fields) and is okay to ignore. I'll make sure it's removed in the next update. Thanks.
  12. @Ivan Gretsky Those are already present in Matrix as part of the header label. See the "Item Headers" input for each of the matrix types:
  13. Like last week, this week, updates continued on the core and matrix repeater fields. Repeater and matrix fields can now be configured to use fewer pages. When set, it won't create placeholder pages for repeater items until at least one repeater item exists for a given page and field. This can drastically reduce the number of pages consumed by repeaters in your system, and even more so if you are nesting repeaters. Eventually, this will become the default setting, but for now we are playing it safe and making it optional with a new toggle that you'll find on the Details tab when editing a repeater or matrix field: After enabling the "Use fewer pages..." Setting, the "Find an optionally delete unnecessary pages" checkbox will take care of cleaning up anything that isn't necessary for existing repeaters already in the database. If you have a large site with a lot of repeaters, this could be deleting a lot of now irrelevant stuff, so just be aware of that and backup ahead of time to be safe. Thanks to @Jonathan Lahijani for the idea/suggestion. Also new this week is the ability to copy and paste repeater items, as well as to clone above or below existing items. It handles this by replacing the existing "clone" icon action with a dialog that now lets you choose among various related actions. Among them is the ability to copy/paste from the same page or between different pages. The only requirement is that the repeater (or matrix) items are from the same field. See the video below for an example of how this works: This works with either Repeater or Repeater Matrix fields. But if you want this feature in Repeater Matrix, you'll want to upgrade to ProcessWire 3.0.188 and download the new version posted today (v8 beta) in the ProFields download thread. The ability to copy/paste repeater items was an idea originally from @David Karich and a module he developed called Repeater Matrix Item Duplicator. Thanks for reading and have a great weekend!
  14. @Jonathan Lahijani Thanks, yes your description explains it perfectly. I understand how it works now. Where does one define the preview view? The preview seems like it is prepared for the admin, and presumably is something different than what appears on the front-end. If that's the case, this approach would also work for Repeater Matrix (like with custom preview render files like I mentioned in my previous message). It seems like a lot of work for a developer to set up, but if it's what sometime wants then maybe they don't mind. How does ACF work in this respect? It looks to me like developer-defined admin previews, but I don't know for sure. Then there's the potential where the preview is the literal front-end view of the element (and surrounding document), like you guys mentioned. Since front-end output in PW is entirely up to the developer, I'm not sure how much Repeater Matrix can do here. This would be more of a separate "live preview" option for the entire page rather than something specific to repeaters. PW just renders the whole page, though maybe the developer can implement their own method to selectively render one component or another (alongside the mentioned htmx), but that might be asking a lot of the site developer to implement it. This also requires that the preview be in a separate window or frame, since the full document has to be rendered, at least initially. A tool like htmx is cool and might save time relative to jQuery'ing it. But like ProDrafts preview, the underlying issue of having to render the full document remains. Htmx does have the hx-select to facilitate this, which would likely be better than the homegrown method ProDrafts uses for inline replacement. Though ProDrafts inline replacement at least doesn't require one to code for it, but I'm guessing htmx is more consistent/reliable across a much broader diversity of situations.
  15. @Jonathan Lahijani The png is just an example and it supports any common image extension: gif, png, jpg, svg. I'm cool with a preview option, but just didn't want to mix preview with editor. But a preview that appears above or in a modal or something has potential. We may be able to provide an option for developers to provide their own preview render files, like we do for the preview images. The acf examples look interesting, but admittedly I'm lost in them like a nuclear power plant control room, likely because I'm not so familiar with the wordpress tools. By the way, the option we talked about earlier (repeaters with fewer pages) is now committed in the dev branch and you can enable it by opening the "Repeaters storage" fieldset that appears on the Details tab when editing a Repeater or Matrix field.
  16. @Jonathan Lahijani If I understand what you are asking for correctly, I think it's actually the next item in the class to-do's here -- does this sound like the same thing you are talking about? If so, I've actually reached the next step on that one along with some other updates, and may have it committed this week, so it's definitely on the way.
  17. RepeaterMatrix v7 is now posted in the ProFields download thread. If you grab a copy, please consider it a dev/beta version (test thoroughly before using in production) and note that it also requires the current dev core version (3.0.187).
  18. @nbcommunication Thanks, I was able to duplicate and fix the issue and it is in 3.0.187.
  19. This week we have some very useful new additions to both the core Repeater Fieldtype and the ProFields Repeater Matrix Fieldtype. This post covers all the details along with a couple of brief demonstration videos— https://processwire.com/blog/posts/new-repeater-and-repeater-matrix-features/
  20. @Ivan Gretsky Hooks have already been added for this, and I think they were present in the dev version I posted in the ProFields board a few months back? I don't remember for sure, but I'm trying to make everything hookable so that people can modify the output as needed, and will keep looking for additional opportunities for that as I build in more related features. @teppo Yes there's a renderAddMatrixItemLink() hookable method for this, and it renders a link for one matrix item type, and gets called for each of them. So you could change the output to be anything you want. This is already present, but with the changes being made, chances are another hookable method will be added related to this. @Pete If I understand correctly, this is already there. See the "Matrix types to allow for adding new items" on the "Input" tab when editing your matrix field. This can be configured in template context which enables you to specify some types for one template and other types for another, etc. @mlfct Thanks, I was able to reproduce that here too and have pushed a fix on the dev branch.
  21. It took a little more time this week to wrap up what I was finishing last week (and the week[s] before). But I think it's now at a good spot to move on to something else, and so I started with some Repeater and RepeaterMatrix updates. In Repeater, a new feature was added that's been requested for awhile: the ability to add items anywhere you choose. Previously you could do it only by adding items to the bottom, and then drag them in place. Now you can click insert before/after [icons] in each repeater item header and it will add the new item in place. It is also depth-aware. This is something that I think will also be useful especially for people using repeaters for page builder type contexts. (Note: the feature does not [yet] work if you have all Ajax features turned OFF in your repeater settings). There's a GIF screencast below that shows you how it works. You can click the "insert before" or "insert after" actions and it inserts a new item in place. Alternatively, if you hover either action for a second, it'll show you where it's going to insert an item and you can click either the the item, or the action, to complete the insertion. There's still likely some optimizations and improvements to make in the JS here but so far it seems to be working well. (I made this as a GIF but for some reason IP.Board won't accept it, so here's a YouTube embed instead): Everything in Repeater also gets inherited by RepeaterMatrix, so you'll find this feature there too. But it's not fully functional there just yet. That's because RepeaterMatrix items also have a "type", so I'm working on a new version of RepeaterMatrix that lets you select a type once you've chosen where to insert the item. Another related feature in progress in RepeaterMatrix at the same time is a dropdown/select option for choosing what matrix type you want to add for items. This is an alternative to the current list of links that appears at the bottom. The dropdown also gives you the option of having groups of related types. More on that soon, potentially next week. Thanks for reading and have a great weekend.
  22. This week I kept working on what's been in progress the last couple of weeks. That wasn't really the plan, as I was hoping to move on to other parts of the core. But I found it a took a lot of time to adjust everything to the new code and classes, and to refactor and remove other chunks of code that could either be simplified or removed. So these last few weeks of updates took a lot more time than I expected, and it's one of those things where once I got into it I felt I had to keep working until it was done as well as it could be. That meant getting pretty deep into some core logic. So in hindsight I'm slightly regretting refactoring so much code without major short-term benefits that can make more interesting reading here. And there are perhaps some short-term drawbacks in potentially introducing new bugs, as goes with any new code. But that's how it is sometimes. The good news is that it's a definite improvement in quality and I have no doubt there will be long term benefits especially in terms of improved performance and maintainability. But in any case, I'm glad to be wrapping up these particular updates so that I can move on to other parts of the core and Pro modules, and hopefully I'll have more interesting stuff to write about next time. One small addition you might find useful in these updates is that you can now identify the closest matching page when a 404 occurs. Maybe you want to provide a hint to users that land on a 404 as to what page they might have been looking for. Now you can do this in your 404 page template file: $p = $pages->request()->getClosestPage(); if($p->id > 1) { echo "<p>Were you looking for <a href='$p->url'>$p->title</a>?</p>"; } Like last week I'm not bumping the dev branch core version just yet because I don't want to trigger any upgrade alerts that might prompt people to upgrade immediately. I'd rather focus more on testing and leave these updates to those that are interested in that testing, helping to track down any issues. Thanks in advance for your help with testing these updates. Likewise, thanks for reading, I hope you have a great weekend!
  23. @kongondo It shouldn't have any impact on those files and the same rules apply for when the $page API variable is available. The difference now is that you could potentially call $pages->request()->getPage(); on your own to find out what page it's going to be before the rest of PW knows. I think this probably isn't a common need, but the best example I've been able to think of is that SessionAllow module, which would like to know what the current $page is going to be before it decides whether or not to start a user session. That getPage() method is also hookable, so you could also dictate what the $page API var is going to be if you wanted to. Or you could call $pages->request->setPage($page); before PW calls getPage(). @Ivan Gretsky We couldn't make the getDefault() hookable because usually when code calls that, it's because it literally needs the default language and not one that's been substituted for it. So I think we'd have to focus further in on what you are wanting to do, or what front-end logic you are wanting to change, to see if that could be made hookable. That pageNotAvailableInLanguage() method was added to enable hooking into the logic of what the method describes, but perhaps other types of logic can be made hookable too.
  24. All the updates I mentioned last week are committed on the dev branch today, and it's quite a lot of new code and revised code. There's enough here to justify a couple of version bumps, but I'm leaving it at 3.0.185 temporarily because the ProcessWireUpgrade module will see the version change and some people might upgrade automatically. Because there's so much that's been rewritten, refactored, added and changed here, I'd like it to marinate for a week on the dev branch before it triggers any upgrade notifications. Our dev branch tends to be very stable, and this is one week where there's enough new code that I don't want to call it as-stable-as-usual just yet (though it might very well be). In addition, it's also not totally finished as there's still some redundant code to be removed and stuff that needs to be moved around a bit, though everything should be fully functional as-is. I am running it here on the processwire.com site without any issues, so chances are that all is good, but I always like to be cautious. Below is a summary of what's new and changed. It's a bit technical, and there's nothing here that's all that important to know about, but whether you read on or not, just know that the core is getting even better and faster with updates like these. The core PagePaths module has been refactored and has multi-language support. Previously it only worked on single-language sites. Now multi-language sites can take advantage of potentially significant performance improvements offered by this module. This is one module that is not installed by default, but it's definitely worth installing: Modules > Core > PagePaths. The core LanguageSupportPageNames module has been refactored. Assuming I did it well, you shouldn't notice any difference other than that it's faster. For instance, one of the changes is that it drops its old indexes on the pages table and re-creates them in a different way. I discovered some situations where finding pages by multi-language path was resulting in full pages table scans. Using MySQL “explain” statements I found I could prevent that by reversing the order of the columns in the language-specific indexes, preventing the full table scan and making it many times faster. This could make a big difference on large multi-language sites, but is less likely to be noticed on smaller sites. The LanguageSupportPageNames module also gained a new configuration setting that lets you specify what should happen when a page is accessed at a language it's not available in: throw a 404 or redirect to the default language. The core PagePathHistory module has been refactored. It has a powerful new getPathInfo() method, though it's primarily of interest for internal core use. A new PagesRequest class has been added to the core and it can be accessed from $pages->request(). It primarily focuses on one hookable method: $pages->request()->getPage(). The method accepts no arguments but it analyzes the current request, identifies the page to render, and returns it. Previously this logic was in the ProcessPageView module. The benefit of this method is that you can now determine the page to render much earlier, like during the boot process. Previously the current page wasn't identified until after PW booted and the ProcessPageView module loaded. This will enable [for example] a module such as SessionAllow to decide whether or not to allow sessions based on what page was requested. In addition, this method is hookable, so you could have a module that adds its own logic to identify or change the page that should be rendered. A new PagesPathFinder class has been added to the core and can be accessed from $pages->pathFinder(). Like the PagesRequest class, this new class primarily focuses on one method: $pages->pathFinder()->get($path). The given $path can contain any page path, optionally containing language prefix, URL segments, pagination numbers, or even a previously named version of the path. It will find and validate that path and return an array of information about it. PagesPathFinder does its job very quickly. In fact, it's about 10 times faster (in testing/timing locally) than PW could previously identify this information using existing methods. PagesPathFinder will also take advantage of the PagePaths and/or PagePathHistory modules when appropriate, if they are installed. Below is an example of what the return value would be for path /es/hello/bar/baz/page3 where /es/ is the language prefix, /hello/ is the actual page, /bar/baz/ are the URL segments and /page3 is the pagination number segment. It analyzes everything out and returns a 200 "ok" response if the path is good, or in this case, it's returning a redirect because it detected a Spanish URL with English page name and pagination prefix, and it's suggesting a redirect: $info = $pages->pathFinder()->get('/es/hello/bar/baz/page3'); [ 'request' => '/es/hello/bar/baz/page3', // path that was requested 'response' => 301, // one of 200 (ok), 301 (permRedirect), 302 (tempRedirect), 404 (pageNotFound), 414 (pathTooLong) 'type' => 'permRedirect', // ok, permRedirect, tempRedirect, pagePathError, pageNotFound or pathTooLong 'errors' => [], // array of error messages indexed by error name 'redirect' => '/es/hola/bar/baz/pagina3', // suggested path to redirect to, blank otherwise 'page' => [ // info about page that was matched 'id' => 1237, 'parent_id' => 1232, 'templates_id' => 12, 'status' => 1, 'name' => 'hello' ], 'language' => [ 'name' => 'spanish', // name of language detected 'segment' => 'es', // segment prefix in path (if any) 'status' => 1 // language status where 1 is on, 0 is off ], 'parts' => [ // all the parts of the path identified [ 'type' => 'language', 'value' => 'es', 'language' => 'spanish' ], [ 'type' => 'pageName', 'value' => 'hello', 'language' => 'default' ], [ 'type' => 'urlSegment', 'value' => 'bar', 'language' => '' ], [ 'type' => 'urlSegment', 'value' => 'baz', 'language' => '' ], [ 'type' => 'pageNum', 'value' => 'page3', 'language' => 'default' ] ], 'urlSegments' => [ // URL segments identified in order 'bar', 'baz' ], 'urlSegmentStr' => 'bar/baz', // URL segment string 'pageNum' => 3, // requested pagination number 'pageNumPrefix' => 'page', // prefix used in pagination number 'scheme' => 'https', // blank if no scheme required, https or http if one of those is required 'method' => 'pagesRow', // method(s) that were used to find the page ] While you might never need to use this method yourself, ProcessWire now uses it on every request. And now that this logic is isolated from ProcessPageView and has a dedicated $pages API, it's much more open and we can, for example, more easily apply tests to this logic. I've covered a few updates here but there's more if you feel like digging in the commit log https://github.com/processwire/processwire/commits/dev. Thanks for reading and have a great weekend!
×
×
  • Create New...