Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


ryan last won the day on May 23

ryan had the most liked content!

Community Reputation

17,598 Excellent

About ryan

  • Rank

Contact Methods

  • Website URL

Profile Information

  • Gender
  • Location
    Atlanta, GA

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. @HMCB Not a lot left to be done for this particular update. Mostly just details as I come across them. For instance, this morning I noticed that FieldtypeMulti needs some of the same updates I applied to Fieldtype, but nothing that's going to change the way it works or how it behaves. So while not particularly urgent, I just want to cover all the related updates while still fresh on the mind.
  2. ProcessWire 3.0.157 on the development branch continues the trend of core refactoring that’s been happening quite a bit in 2020. Rather than doing a rewrite every few years (like some CMS projects) we instead refactor parts as we go, constantly improving and optimizing the core. This works because the core design/architecture is right where it needs to be, even 10 years in. But there’s always still bits of legacy code, and code that can be improved. So in the context of ProcessWire, refactoring means incrementally rewriting code on the inside, without changing its behavior on the outside (other than making it faster and/or more secure). This has been happening regularly over the last 10 years, and will likewise continue happening over the next 10 years and likely beyond. This week the code behind ProcessWire’s core Database and PageFinder classes got a major refactoring. This is some of the most used code in PW, as it handles everything involved in taking a selector and converting it to a database query. But it’s always been a little bit of a pain point for me because it had to build queries in a way that I thought wasn’t ideal, in order to make it possible for lots of different modular parts (mostly Fieldtype modules) to contribute to the query and for PageFinder to put it all together. It was fast and secure, but still one of those parts that felt like a little too much duct tape to me. But considering how crucial the code is, I’ve always been reluctant to make major changes, since it all worked just fine. Spending lots of years thinking about it (on and off), a desire to work out any pain points, and having better tools available (like Phpstorm and Tracy) made it possible to finally massage out this pain point. Some work still remains to be done, but it’s mostly there and I’m feeling good about it. Stuff like this is key for the maintenance and longevity of the core, and involved a lot of time and effort, but makes very little difference to users, even if it makes a lot of difference to me in maintaining the core. It would make a boring blog post for sure—lots of work and changes, but no new toys to show for it. Nevertheless, it has that feeling of a good house cleaning, even if you can't see it from the outside. The scope of changes here means that there may actually be new bugs to work out, so to be on the safe side, consider 3.0.157 to be a little more “beta” than the dev branches usually are. Though I’m running it here on processwire.com and it’s working well. Beyond the fairly major updates to the Database classes, there are also a few new Sanitizer convenience methods that are primarily variations on existing ones, but useful ones for sure. Thanks for reading and have a great weekend!
  3. This week I was back to focusing on the core and got quite a lot done. A lot of GitHub issue reports were resolved, plus several minor tweaks and additions were made in 3.0.156 as well. But the biggest update was the addition of the $pages->parents() API, which is something that I think you’ll likely have zero use for (and why I’m not putting it into a blog post) but something that the core itself will use quite a bit, and is a really nice improvement for the system and its scalability. So if you don’t mind some technical reading, read on. Whenever you call a $page->find() method ($page, not $pages) or use a “has_parent=“ in a selector, ProcessWire joins in a special table for the purpose called pages_parents. It uses this table to keep track of family relationships that aren’t otherwise apparent. For instance, let’s say we have page “g” that lives at path /a/b/c/d/e/f/g/. Page “g” only knows that it has page “f” as its parent. It doesn’t know that page “e” is its grandparent unless or until page “f” is loaded. Once “f” is loaded, then “f” can reveal its parent “e”. It works the same for every relationship down to the root parent “a”. So the pages are like a linked list or blockchain of sorts, where only 1 relationship forward or backward is known per page. The “pages_parents” table fills in this gap, enabling PW to quickly identify these relationships without having to load all the pages in the family. This is particularly useful in performing find() operations that you want to limit to a branch started by a particular parent. It’s the reason why we have both $pages->find() that searches the entire site, and $page->find() that limits the search within the branch started by $page. I haven’t paid much attention to the code behind this pages_parents table because it generally just worked, needing little attention. But I came across a couple of cases where the data in the table wasn’t fully accurate with the page tree, without a clear reason why. Then I became aware of one large scale case from a PW user where it was a huge bottleneck. It involved a large site (250k+ pages) and a recursive clone operation that appeared to involve hundreds of pages. But that operation was taking an unreasonable 10 minutes, so something wasn’t right. It came down to something going on with the pages_parents table. Once I dove into trying to figure out what was going on, I realized that if I was to have any chance of keeping track of it, we needed a dedicated API for managing these relationships and the table that keeps track of them. So that’s what got a lot of attention this week. While still testing here, it does appear initially that the 10 minute clone time has gone down to a few seconds, and everything about this relationship management is now rewritten, optimized and significantly improved. It was a lot of work, but absolutely worth it for PW. Rebuilding the entire table from scratch now takes between 2-3 seconds on a site with 250k pages and 150k relationships. The new API can be accessed from $pages->parents(). This API is really useful to the work that I do here (maintaining the core) but I’ll be honest, it’s probably not useful to most others, so I won’t go into the details here, other than to say I’m happy with it. But if you are interested, there are methods finding all the parents in a site, or a particular branch, and methods for rebuilding the pages_parents table, among others. Maybe more will be added to it later that actually would be useful in the public API, but for now I’ll likely leave it out of our public API docs. The $sanitizer->selectorValue() method also got a full rewrite this week (actually, one the last few weeks). It’s now quite a bit more comprehensive and configurable (see the new method options). The previous version was just fine, and actually still remains — you can use it by specifying [ ‘version’ => 1 ] in the $options argument to the selectorValue() method. But the new version is coded better and covers more edge cases, plus provides a lot more configurability for the times when you need it.
  4. Beluga, I'm not much into carousels either, but also wouldn't claim there's no place for them. There's 1 small carousel on this entire site, and there was also one on the previous iteration of the site—the client has always liked it, and the customers react well to it. I really like this client for a lot of reasons, but one is that they are much more involved than most, know their technology, their product and their audience better than anyone I've worked with. The carousel is not my idea, but I trust and am certain the client knows their customers better than any self proclaimed experts online. I got a kick out of that linked anti-carousel site because it's a bit of a self own by whoever made it—it uses a carousel to make points that we likely would not have bothered to read if they weren't in a carousel. 🙂
  5. Last week I told you guys about how I was working on development of a client’s site and deep diving into the details. Well this week was the same, except perhaps more so. Yesterday we finally launched phase one. There’s still more to do, and still working out some small bugs and such. This is a site I’ve been developing since back in the early versions of ProcessWire 2.x, which I think was nearly a decade ago. In fact, this was one of the first sites running ProcessWire 2.x, if I recall correctly. We’ve been keeping it up-to-date over the years, but this is the first time we’ve done a full front-end redo of the site, essentially starting from scratch on that, and spending a few months on it. But the admin side (fields, templates and page structure) remains roughly the same from where it was 10 years ago, and that’s what we’re going to redo in phase 2 (this year). There’s a lot of fields in this site, so I’m looking forward to really simplifying it with ProFields, repeaters and more — none of these existed when the original site was built. One thing really great about this iteration of the site is that it’s a ProcessWire community collaboration. Pete (our awesome forum administrator) did the design, as well as most of the front-end markup/css for the site. Jan (our awesome system administrator) setup the servers that it runs on, with AWS load balancer setup and everything related to that (he’s also one of the owners of the site). I did the other development stuff (the ProcessWire API side of things), making all the content fill all the markup in the right places, structure and organization, markup regions, search engines, optimization, etc., basically the stuff needed to get it all working in PW. This is the first time that I’ve developed a site where we can run new and old site side-by-side off the same ProcessWire installation. During development, the client could click a checkbox in their user profile and then they’d be using the new site. Behind the scenes, it does this using a fairly new feature in ProcessWire which is: $config->setLocation(‘templates’, ‘site/tpl’); So we had site/tpl/ having the new site templates, while site/templates/ had the old version. So one limitation for this phase 1 is that the old and new sites had to deliver the same exact content, even if the resulting output was very different. This site also uses custom page classes (another new feature), Markup Regions, and ProcessWire’s Functions API, and the Uikit 3 front-end framework. Pete also wrote a nice custom PW module for this site to handle localized weather forecasts — I ran out of time to get it in place yesterday, but that should be there next week hopefully. Yesterday we launched the site and we were finally able to start running it through its paces with live traffic. I thought I was going to be working on the PW core today, but you know that as soon as you launch a new site you always find things that need adjustment and can’t wait, so that was all of today. There’s more optimization work to do, and then there’s phase 2, where we start using ProFields and Repeaters to better isolate a lot of data and be able to implement the rest of Pete’s design in the parts that we weren’t able to in phase 1. This is where things like the current pricing tables (one example of a weak point) start to look really sharp. But I’m also looking forward to taking a little breather and catch up on some serious PW core work, issue reports and module updates over the next few weeks before diving into phase 2 of this site. I didn’t want to share the site quite yet because there’s still some details to take care of and such. But here it is Friday and I’ve got no other ProcessWire news to report, so was feeling a little guilty that I didn’t get more ProcessWire core work done over the last week, due to being focused on developing this site. But this was one of the first sites running ProcessWire, so it's an important one to me. And here it is about 10 years later, still the same installation (templates, fields, page tree) but with a brand new design and running the latest PW, and lots more to come. Tripsite.com
  6. I hope that you all are having a good week and staying healthy. I’ve been very much focused on preparing a new ProcessWire-powered client’s website for launch, hopefully sometime next week. This is a site that’s already pretty well established with the search engines and such, so I’ve been going through all of the pre-launch QA in terms of optimization, SEO accessibility, mobile testing, getting the multi-language translators everything they need to translate, adding ProCache to the picture, and so on. For me this is one of the most fun parts of development, with relentless optimization and having it all come together… but also one of the most time intensive. This is where all the little details surface, things that need improvement become more apparent, and new ideas keep popping up. It’s also where lots of the bugs are discovered and fixed, and where I sometimes have to slap myself on the head for missing one thing or another, but then of course taking care of it. So that’s been most of this week, and I think likely at least half of next week too. But then it’s back to work on the core and modules, covering issue reports and more. I’ve actually been at work on some parts of the core and ProCache this week as well, but not to the point of finishing anything major. So you’ll see some updates on the core this week, and there’s also lots of stuff pending that’s not yet committed, and it’s all work in progress, so stuff to review later. With kids at home I’m still moving at a little slower pace than usual, but starting to get the hang of it, doing well and building momentum. While I don’t have much new to offer in this update, thanks for reading anyway, and I hope that you have a great weekend!
  7. This post covers a few of the bigger updates in ProcessWire 3.0.154 and 3.0.155 on the dev branch. This includes a new function for live replacement of text in core and modules, a new method for creating canonical URLs, and some major upgrades to our $input->urlSegment() method that I think you’ll like! This continues from last week’s post in the ProcessWire support forum about 3.0.154 core updates and includes several new details— https://processwire.com/blog/posts/pw-3.0.155/
  8. @Pete From this side, my wife's job is one that requires her to be on phone/video meetings most of the day, so she's got to lock herself away from us to focus on that, and the kids are mostly with me during the day. I'm good at focused attention, but not great at changing gears, so I'm still learning. My days used to be just coffee and code. Now things are much more diverse, here's a typical day: wakeup, breakfast, coffee, code, kids wakeup, resolve dispute, make breakfast, coffee, code, hear that TV is on, check in to make sure kids are doing school work, turn off TV, say “get back to school work”, try to figure out something with google classroom, worry about whether I'm doing enough to keep kids focused on school, code, get icloud request to approve download of some game on iPad, tell kids to “get back to work”, explain why several times, answer questions about school work, hear music from some game and decide to let it slide, 1 email, cycle power on router because wife says she can't connect to important video call, code, resolve kids dispute, put 1 kid in timeout, legos, clean up spill, 1 email, slack message, cook lunch, coffee, code, worry about whether kids are spending too much time on screens, phone call, reset wifi because daughter says Roblox won't connect, then work a little more, click the "snooze" button on a dozen emails so they return tomorrow, take kids outside to play while I work on house or yard, ride bikes, cook dinner, eat, netflix, cleanup dinner, go to bed, feel thankful to be healthy, sleep well. I'm definitely still adapting here, but I can't complain about the new normal because having everyone under one roof is comforting, especially at times like this. And while it's harder to get work done, it's mostly still getting done and I just feel thankful to be staying busy. Also, knowing there's nowhere to go but home, life is simpler in many ways.
  9. Here’s a brief update on what’s new in the core since last week. Next week I’m going to compile a more complete overview of everything that’s in 3.0.154 (and more) and put it in a blog post. I wanted to do that today, but my kids have needed a lot of help with various things today (and this whole week actually) with all of this online school stuff and I’ve run out of time. We're a few weeks in and school is cancelled for the rest of the year due to the coronavirus (likely the same around the world). I'm still learning how to adapt to kids around all day and needing attention, but overall it's nice to have the family around more even if it is sometimes hard to get work done. So I’ll keep this sort of brief, and get into more details next week. Several updates were made to the core/LanguageFunctions.php (language functions) file, with biggest being the option to programmatically replace translation text (whether multi-language support is installed or not), useful for very easily updating core/module output to say exactly what you want, and without needing to install multi-language modules. No longer do you need to use various hooks to change text in one module or another. Also moved the __('text') configuration options to dedicated functions which makes it more clear to use, as well as much better for documentation purposes: wireLangEntityEncode(), wireLangTranslations(), wireLangReplacements(). You'll see these new functions in our docs by next week. More details and examples of these in action in next week’s blog post. The CKEditor version has been upgraded from 4.12.1 to 4.14.0. To see what’s changed, see the release notes for CKEditor 4.13.0, 4.13.1 and 4.14.0 here. There’s actually quite a lot here in terms of additions and fixes. Note especially the two security related fixes in 4.14.0 (though I think only the first may be applicable to us). While it looks like a rather unlikely combination of factors needs to come together, and with just the right person, it’s good to be aware of nevertheless. Of note is that these particular cases are entirely client side, before PW ever gets to see or filter the content, so this is something that only a CKEditor upgrade can fix. Updated the core Debug class to use PHP 7.3’s recommended hrtime (high resolution time) for debug timers, rather than microtome. This is only available in PHP 7.3 and newer. As far as I can tell it produces identical results to microtome (as far is our timers go) but the PHP documentation page indicates hrtime is what we should now be using, so that’s what we’re going with. I also did a little refactoring and minor improvements in the Debug class as well. Updated ProcessWire’s Inputfield rendering system so that you can customize markup by matching a field by name, and without hooks. This essentially takes part the Inputfield customization system developed for LoginRegisterPro and brings it into the core. This opens up a lot more customizability for those that want it. Various resolutions of GitHub issue reports, with more on the way. The above are just updates from the last week, but there’s plenty more in 3.0.154 as well. See ProcessWire Weekly #309 for details on Image and file field updates, new $database->columnExists() method and new Selectors::getOperators() method, and more. There are also the new expanded file and image properties, as discussed in #308 and the last blog post. Thanks for reading and I hope you all have a great weekend!
  10. Last week I posted in the blog about current projects in progress, and consistent with that, this week I’ve been working primarily on the upgrades to our file/image fields. To start, this focuses on storing additional info in the DB table, including file size, created/modified user info, and for image fields: width and height. This is useful in making these properties searchable from page-finding selectors, but also a necessary pre-requisite to supporting external file systems. A “ratio” floating point property is now available on image fields as well (and also stored in the DB) and this value reflects the width divided by the height. This is a searchable property and will be useful for quickly finding portrait images, landscape images, square images, or any proportion you need to find. If you want to find images that are at least twice as wide as they are tall, then you’d be looking for a “ratio” of 2.0 or larger (“ratio>=2”). If you needed to find perfectly square images (i.e. 300x300) then you’d be looking for a ratio of 1.0. If you needed to find portrait images, then you’d be looking for images with a ratio under 1.0 (or twice as tall as wide would be 0.5). You can figure out what ratio you are looking for just by taking your target width and dividing by your target height. Longer term, combined with the other added properties, the goal is that this will help with finding pages that have images suitable for specific placements, proportions and dimensions. These new properties won’t be useful at first on existing sites because the data just isn’t present in the DB, even if the columns to store them are. They are populated over time whenever the page is saved. But I’m going to enable an option to have it populate all of this automatically whenever the field is even loaded. It’s actually there in the core right now, but I’ve got it disabled so I can test it out on a few more of my installations before others start using it. There were some other upgrades to the core as well, including improvements to the Selector and Selectors classes, addition of a $database->columnExists() method, lots of new (mostly internal) methods in FIeldtypeFile/FieldtypeImage, and some refactoring of the FieldtypeMulti class, among other minor updates. While there were a lot of changes and additions this week, it’s not stuff that you’ll likely be using right away, so I’m going to hold off on bumping the version till next week. Thanks for reading and have a great weekend!
  11. This week we’ve got a few new and interesting core updates in progress, though none quite ready to release just yet. So rather than releasing version 3.0.154 today, I thought we'd instead take a brief look at what’s coming over the next few weeks… https://processwire.com/blog/posts/processwire-updates-and-additions-in-progress/
  12. If one's goal is to get an up or down from an API call, then zero vs. non-zero is functionally and effectively the same thing as boolean. If there's an opportunity to make a method more useful by taking advantage of that fact, then I'll always do it. So yes, you'll find many examples of this in PW. That's always the strategy I've tried to embrace in the PW API and plan to continue going forward. To reiterate what I stated above, the primary purpose of the has() method is not to get an ID—it is instead to check if the system has a page matching the criteria or not, without actually loading the page. Whether the method returns 0 or false makes no difference in telling the caller that the system has no page matching the criteria. Likewise if the page does match the criteria (true vs 1+). Now if you are specifically looking for a getID() function, then yes of course the name "getID" is preferable. I'm happy to add getID() as an alias for times when one might be specifically looking for that particular need. But that's not what I was looking for here. And if anyone else's experience is similar to mine, we will more often be looking to see if the system has any page matching some criteria (whether we want the ID or not). Basically replacing instances where we might have used count() before, with a more efficient alternative. So I feel pretty strongly that the has method name and return value are optimal and consistent here.
  13. I hope everyone here is doing well, staying in, and staying healthy. Our town here is under a “stay at home” order, and it’s now the law that you can’t get within 6 feet of any other person when out walking. So haven’t left the house (other than for walks and bike rides) in about 2 weeks now. Though with the whole family home all the time, it admittedly feels a lot busier than before this Coronavirus stuff, I think because there’s now a lot more people to attend to during the day (especially kids). Not much silence compared to before. 🙂 Not a bad thing, just very different. If we’ve got to spend a few months, or even a year this way, it’ll be alright, so long as the internet keeps working. I’m just thankful to have a job where I’m already used to working this way, as I know many of you do too. It seems that this whole situation is going to move a lot of activity online that previously wasn’t, so I anticipate it’s going to be potentially a very busy and important year for web development. Online communication and content delivery is going to be that much more important for the world, making reliability, scalability and security every bit as important. These are always our focus, but just want to emphasize this even more as we look forward. With a world in temporary disarray, you can count on ProcessWire to be an especially stable and reliable tool that gets even better every week, and our community always a friendly and helpful place. I’ve got several things in progress in the core, but nothing far enough along to write about just yet. I’ve also been putting a lot of work into ProCache this week, which is long due for a version update. The module still has quite a bit of PW 2.x architecture that I don’t think is needed anymore, so I’m refactoring and improving quite a bit, in addition to feature updates. Thanks for reading and I hope that you have a good and safe weekend!
  14. @Robin S The purpose I was focused on for the method is to see if the system has any page that matches the given criteria. An example of the use case appears in the Template class updates here. It verbally makes sense in code for what it's intended for. Usually I'd use a get or count for that, I didn't need any of the extras that $pages->get() or $pages->count() provide, so thought we could eliminate some overhead. Plus I can think several other other cases where the same was true, so the need has resurfaced enough times that it seemed like good method for PW to have. The method returns the ID just because it already has that info either way, and it seemed potentially more useful (and 0|1+ communicate the same thing as false|true). I had also seen where you'd mentioned a getID recently, and since this method already has the page ID, I thought this also seemed like a good opportunity to accommodate that need too. So far I haven't come across a good use case for getID() in my own projects, outside of checking for existence of something (which 'has' seems like a better term for). But it certainly makes sense alongside the existing findIDs() method, though that method is more about accommodating a scale that find() can't. But it sounds like you've had use cases for it which means others likely have too, and that's plenty good reason for me. I'll go ahead and add getID() it as an alias of has(). Depending on what need you are looking to solve, I imagine this will help people to find what they are looking for more easily.
  15. This latest version of the core on the dev branch focuses on comments field updates, significant refactoring/improvements to ProcessWire’s core Template class and PagesLoader class (which is used by the $pages API variable), and we introduce a useful new $pages API method— https://processwire.com/blog/posts/pw-3.0.153/
  • Create New...