-
Posts
17,231 -
Joined
-
Days Won
1,697
Everything posted by ryan
-
@Soma Great to see you back! A couple weeks ago I was just thinking about you and how I wished you were still around here. I've been seeing your amazing paintings on Facebook and figured you had moved on to other things, but thought of sending you a message there, so what a nice surprise to see you here.
-
This week I worked with Claude Code on refactoring the core WireHooks class to improve it in various ways. I do this work because I like to code, so am of course handling that part. But Claude has been very helpful in finding issues as well as reviewing all my code before it gets committed. In this case, Claude found several bugs that are now fixed, and also saved me from introducing more when I added new features. Working with Claude Code reminds me of 1989 when I was in high school learning Turbo Pascal and building a BBS, and getting help from a neighbor and good friend that was doing the same. I learned so much then and now it feels like that time again. But man have things come a long way since then. I asked Claude about helping with the ProcessWire issues and requests GitHub repos, and now it's solving issue reports, replying to them and committing fixes. For simple fixes that involve a line or two, I'm going to let it handle the the whole thing. It's posting under my GitHub account, but it identifies itself as Claude in replies and and in commits. That way it's easy to tell what it does under my account. I had it just cover a couple of issue reports today as a test (see 2195 and 2192), but will be having it do a lot more going forward. Back to the WireHooks class, I asked Claude about writing a commit message for the WireHooks updates, and wow, check this out: Bug fixes in WireHooks: - conditionalArgMatch(): Fix Selector mutation bug where the shared Selector object stored in hook options was permanently mutated after the first call, causing argMatch hooks (e.g. addHook('WireLog::save(=errors)')) to stop matching after their first invocation. - getHooks(): Remove key variable from foreach to prevent shadowing $method param. - getHooks(): Replace array_merge() in loops with direct array append. - addHook(): Prevent 'noAddHooks' option from leaking into stored hook options. - isHookedOrParents(): Use $className string consistently in cache key writes, rather than $class which may be a Wire object. - runHooks(): Scope $useHookReturnValue inside foreach so it resets per hook. - runHooks(): Use strict null comparison ($toObject === null). Bug fixes in HookEvent: - arguments(): Allow setting an argument value to null (use func_num_args() > 1 instead of $value !== null check). - arguments(): Use array_key_exists() instead of isset() for null-correct lookup. - getArgumentNames(): Guard ReflectionMethod instantiation with method_exists() to avoid uncaught ReflectionException for dynamically-added hook methods. - __toString(): Fix argument list building (was appending to string instead of array), add null/bool display, avoid PHP fatal for objects without __toString(). New features in WireHooks: - cancelHooks: Now accepts string values 'before' or 'after' (in addition to boolean true) to cancel only hooks of a given type. For example, a before hook can set $event->cancelHooks = 'after' to cancel remaining after hooks without affecting the hooked method call. - Custom event data carry-forward: Custom data set on a HookEvent (via $event->customKey = $value) is now carried forward to subsequent HookEvent instances within the same runHooks() call. This allows before hooks to pass data to after hooks without using external variables. - getHooks('*'): Supports wildcard method to return all hooks for all objects. Available in debug mode only (uses allStaticHooks/allLocalHooks aggregates). - allStaticHooks: Now tracked alongside allLocalHooks when debug mode is on. - addHooks() comment fix: "If there is a parenthesis" corrected to "no parenthesis". - addHook() exception messages improved with additional context. - runHooks() docblock updated to include 'either' type. - hookTimer() PHPDoc: @param String corrected to lowercase string. New features in HookEvent: - $defaults static property: Defines the canonical set of standard HookEvent fields, used to distinguish custom data from built-in event properties. - $eid property: Each HookEvent instance gets a unique sequential event ID. - set() override: Tracks non-default keys set on the event in $customKeys. - getCustomData(): Returns only the custom (non-default) data set on the event, used internally by runHooks() for the carry-forward feature. - cancelHooks property updated to support bool|string type. Anyway, I know a lot of you here are deep into the AI stuff, and I'm just getting started, so none of this is surprising. But it sure is a pleasure collaborating with Claude Code on this stuff and it brings back that coding wonder and excitement from 1989. Some Claude and Claude Code podcasts I've enjoyed listening to or watching this week include one from AI for Humans Claude is Cooking, Wednesday's AI Daily Brief on How to use Claude's new upgrades, and the Get Educated AI video of how to setup Claude to use your computer and web browser, etc. (though I've not tried this just yet!). Lastly, last week I put together a ProcessWire powered JSON feed of bike tours, and the client prompted that they wanted a map and look what Claude Code did, I'm impressed!
-
- 14
-
-
Most important to me is that I understand everything that goes into the core, and that means that AI is used for ideas and suggestions, but the code is still written by hand. And even then, the suggestions and ideas only end up in the core if they produce a measurable improvement. After testing and benchmarking, sometimes the ideas/suggestions result in an improvement, and just as often they do not. I do the same with pull requests. Coding and re-coding something is how I feel comfortable that I understand it. Perhaps too old-school but I don't think that will ever change. So long as I'm in charge of the core, I need that level of understanding with it. On another project I'm working on with a client (an add-on to their website), we're letting Claude handle the code entirely, with lots of instructions from us, but zero code from us. It's kind of a test and a learning experience, and the client initiated it. We don't know the details of the code, but we do know that the code works quite well. Though I had a peek at its code and found it to be quite solid. What's funny is that in this case, Claude is having me build web services it can pull data from. So I'm giving it instructions, but it's also giving me instructions. 🙂
-
PW 3.0.232 – Core updates + new version modules
ryan replied to ryan's topic in News & Announcements
I think it depends what ProDrafts features you are using. But in general ProDrafts can be installed and uninstalled easily, so having it installed doesn't make any permanent changes to your site or anything. The primary drawback in ProDrafts is repeater support, particularly nested repeaters. -
PW 3.0.232 – Core updates + new version modules
ryan replied to ryan's topic in News & Announcements
I don't have an ETA just yet but this is one of my main projects currently. -
@diogo Thanks, that post is well written and relatable. Interesting comparison with React. I agree with a lot of it, but not really with the AI conclusions. Admittedly, so far I'm not using AI to write code for me, and not sure when/if I will. Instead, I'm using it more as a coding companion. I write the code, and AI looks over everything I do and helps me spot issues and improvements, which it does extremely well. My use of AI so far is very minimal compared to what some others here are doing. But even with this minimal use and understanding, it's clear to me that the world is changed. I don't know about all the other stuff AI is used for, and it wouldn't surprise me if there are some big bubbles. But at least as far as using AI with code (even just as a helper), it is mind blowing, we are in a new world. I think the comparisons to outsourcing and React communicate a lack of experience with AI. But to be fair, I'm also writing about something I don't have a lot of experience with either. I do like this blog and the author's style, looking forward to reading more of his posts.
-
@adrian Thanks for bringing this up. It seemed like x-user came here to troll with an expectation that ProcessWire should ignore and blacklist anything having to do with AI. That doesn't seem realistic. But it did make me wonder, are there any other CMS projects that are taking this approach? It seems unlikely. I imagine we're not too many years away from the point where a CMS project can't compete if it's not involved in the AI space in some way or another. I also think that the AI changes are coming whether we like it or not. So we can either jump on and grow, and make things better, or get left behind, and perhaps get left without a job. If it's only the people that dismiss environmental concerns using AI and voting with their wallets, then there's no incentive for these companies to do better. X-user would make a greater difference to the world by being an AI user that cares and chooses companies based on their values. And I think that's what we all should do. Whereas abandoning anything having to do with AI does nothing to improve the direction of AI and seems a little like self-sabotage. In the future, and with users that care, there will be pressure on AI companies to do things right. For example, when they build that next data center, they will also build a giant solar array or wind farm to power it. Depending on coal and gas plants for electricity is not sustainable, and now it's more costly than solar. Coal and gas is EOL'd. It may be that the power demands of AI push us towards sustainable solutions faster than otherwise, and we need that as quickly as possible. My opinion: We can't dismiss AI and complain. We have to participate and push for better solutions when there are opportunities to do so. If we sit out, there will be no such opportunities. The environmental problems were here long before AI. As I understand, the root of it is power generation. The US (at least) is not solving the power generation problem in a way that can overcome the politics, corruption and outright stupidity. But I also think that it's very likely AI that will be in some way responsible for the solutions for these problems. There are so many problems to solve that are bigger than any of us have answers for. And if there are solutions for these problems, I have no doubt they'll be coming with the help of AI in some fashion. From my perspective blacklisting AI solves nothing and instead is abandoning the problems and giving up.
-
@mattgs This is a very friendly community as a whole. But to be fair, both of you guys posted kind of unfriendly messages. And both of you make good points too. There are some big challenges in the world right now, none of us are perfect, and we've all got to do the best we can, where we can. So I think it's good that you guys have these environmental concerns, and we all should, and it's good to communicate these, share and learn, while also being friendly.
- 18 replies
-
- 18
-
-
@mattgs Like Adrian, I also consider myself very environmentally conscious. I've not spent much time learning AI in part because I thought it was problematic for a lot of reasons. But I don't think we're likely to stop these AI companies so that's why I thought I should try things out with a company that seems to have more ethics than the others. Anthropic seems to have a mission for AI safety and sustainability. I hope it's legit. And as far as I can tell, the other companies don't, which I find concerning. But I'm also not as up-to-speed as you are on the on the issues you brought up, so I'll have to look closer as well as check out the video you mentioned (do you have a link?). I'm also aware that a project like ProcessWire gets executed millions upon millions of times every month (or day?) throughout the world, and every execution consumes energy. So I've always been very interested in optimization and making ProcessWire use as little time and energy as possible to do its work. The updates that we've been focusing on here are aimed directly at that. So perhaps AI is using a little energy to find optimizations and bugs in PW, but that single brief code review session reduces the energy usage of every ProcessWire execution going forward. This is a case where AI is likely saving a lot more energy than it consumes, indirectly by making ProcessWire use less energy. Some of the optimizations and bugs its found have been there since the beginning, and likely would have never been identified otherwise.
- 18 replies
-
- 12
-
-
@teppo Thanks, good to hear the more I use it, the more I'll be blown away. I've been using AI ever since ChatGTP first came out, but primarily just for technical questions and such. For instance, a couple months ago Claude helped me figure out how to reduce static pressure in our HVAC system by rebuilding (DIY) the return plenum and filter rack, and it was super helpful. I posed the same questions to GPT and Gemini but they weren't nearly as helpful. This week is the first that I've gotten into collaboration with the actual code. Adrian showed me all the things Claude Code had recommended for the PageFinder, and I found myself really liking what it had found and suggested... Seemed like we were on the same page, just like with the HVAC work. The other thing is that I've found it a little overwhelming with all these models (GPT, Grok, Gemini, Claude, etc.) with big changes almost weekly, and if these companies were ethical and ones I'd even want to be putting money towards. Then I learned about why they created Anthropic in the first place, and last week heard how they were sticking to their ethics and wouldn't cross their red lines despite government pressure. Sounds like integrity to me, something that is hard to find with big companies. That opened my comfort level and clarified for me that Anthropic's Claude Code was a good place to dive deeper with this stuff.
-
@Peter Knight is that a C2 BikeErg?
-
This week on the dev branch we've got several commits with various core improvements and fixes. @adrian has been using Claude Code to suggest core optimizations (focused mostly on the PageFinder) and so he sent the suggestions to me. (PageFinder is the brains behind the $pages->find() method, and many others). I took the suggestions and coded them into our PageFinder, but didn't want to mess with what was already working well, so put them in a new class named PageFinder2, at least temporarily. If running the latest dev branch, you can enable PageFinder2 by adding the following to your /site/config.php: $config->PageFinder('version', 2); The most significant changes are: using subqueries for subselectors rather than separate independent queries; Reusing PageFinder instances (keeping a pool of typically 1-3 PageFinders rather than creating a new one for each $pages->find() operation); and lots of in_array() calls have been converted to isset() lookups, which should technically be faster (still the case in PHP8?, I'm not sure). There were some other changes as well. Theoretically these changes should make PageFinder even faster than it already is. I did quite a bit of testing and found that for the most part it performs the same as PageFinder v1. But then I came across a rather complex selector that translated to a much faster PageFinder operation, nearly twice as fast, and that convinced me it was worthwhile. While PageFinder v2 is not consistently faster than v1, there are some situations where it can be a lot faster. I'm not totally clear on what those situations are just yet, but I'll be doing more testing. In other situations it also can use a lot fewer queries, though that doesn't necessarily translate to a performance difference. But on the whole, all of Claude's suggestions were quite good, regardless of performance improvements. I was pretty impressed with what Claude Code had suggested, so decided to install it on my computer too. I've found it's particularly good at finding bugs. I'll ask it to do a code review on a core file, and it always has good suggestions. It uses ProcessWire terminology too. For instance it pointed me to an object that wasn't properly "wired to the ProcessWire instance", and that's something you'd only ever hear in ProcessWire land. Claude code also helped with improvements to our DatabaseQuery* classes, PagesVersions module, Wire base class, NullPage class, and minor updates to the PagesLoader* classes. I'm not having it write any code just yet, but am having it suggest where improvements can be made. I like to code. I asked it how it knew so much about ProcessWire, and it said that it stays up-to-date with the forums, the website, API docs, and GitHub repo. Thanks to @adrian and @Jan V. for recommending it to me (Jan V. uses it to manage this webserver), I can see how it's going to be a big help to ProcessWire with its suggestions and ideas, I'm already learning a lot from it. And if you get a chance to try the updated PageFinder, please let me know how it works for you. Thanks for reading and have a great weekend!
- 18 replies
-
- 26
-
-
-
-
ProcessWire and photo-heavy sites go hand-in-hand. But these sites can also present development challenges, especially when cloning a large site. This post goes into detail about techniques you can use to keep lightweight development sites without all the photo/image overhead. https://processwire.com/blog/posts/developing-photo-heavy-sites/
-
- 15
-
-
@maximus Thanks for updating it. I had tried to do so a week or two ago and there were various variables involved in it that I couldn't figure out the source of, so ended up adding it to some version history log, thinking maybe it was pulling from that, but apparently it wasn't. It looks like you replaced the variables with the actual version, which is much simpler.
-
New blog: All about custom page classes in ProcessWire
ryan replied to ryan's topic in News & Announcements
@gebeer That's an excellent summary, thanks! On the core-patterns one, the 'getExcerpt' example probably isn't ideal because it's only returning an excerpt if output formatting is on, otherwise it's returning the entire 'body' field with tags stripped out, which isn't an 'excerpt'. Usually a 'body' field is HTML (TinyMCE, CKE, etc.), so the formatted version would be the same as the unformatted version, unless there's some other formatters being applied on top of it, like TextformatterVideoEmbed, etc. There's an example of a getExcerpt() in the blog post that I think might work better, though I'm sure there are even better examples possible. In the same file, under API wire access, it says that pages() would not work in a Page class. But actually it would work just fine, so long as functions API is enabled. But what's preferable is $this->wire()->pages because it would be guaranteed to be tied to the correct instance (just in case multi-instance, even if rare). For calls like $this->wire('sanitizer') (where API var is in quotes) I'd suggest $this->wire()->sanitizer instead, just because the IDE will know that it's referring to the Sanitizer class, whereas if 'sanitizer' is in quotes then the IDE won't know, or at least it will have to do a lot more work to know. The same goes for any API variable. Lastly, do you think it could link to the blog post also, since that's the source for some of it -- It might help for folks looking for additional info? Thanks! -
New blog: All about custom page classes in ProcessWire
ryan replied to ryan's topic in News & Announcements
@Ivan Gretsky I'm always a little reluctant to make a blanket statement like "avoid markup in page classes", but I'm referring to what I think works best with the projects I work on. The files in /site/templates/ are the view layer, as nearly all code in there is aimed at generating markup/output. Even if something isn't directly generating markup, it's still finding and preparing things for output. Most markup comes from "partials", which are files that I put in /site/templates/parts/, or if exclusive to a particular template, then /site/templates/[template]/. And then I either include() them, or files()->render() them from the site's template files. I primarily use Markup Regions. The _main.php establishes the base markup: <?php namespace ProcessWire; /** @var Page $page **/ ?><!DOCTYPE html> <html> <head id="html-head"> <?php include('./parts/html-head.php');?> </head> <body id="html-body"> <header id="header"> <?php include('./parts/header.php');?> </header> <h1 id="headline"><?=$page->title?></h1> <main id="content"> <?=$page->body?> </main> <aside id="sidebar" pw-optional> </aside> <footer id="footer"> <?php include('./parts/footer.php');?> </footer> </body> </html> Below is a template file for the /products/ page which lists product pages, supports pagination, and uses URL segments for sorting: <?php namespace ProcessWire; // products.php /** @var ProductsPage|CategoryPage $page */ $products = findProducts($page); $body = input()->pageNum === 1 ? $page->body : ''; $headline = $page->get('headline|title'); ?> <h1 id="headline"><?=$headline?></h1> <main id="content"> <?=$body?> <?php include('./parts/sorts.php'); // no expects ?> <?php include('./parts/products-list.php'); // expects $products ?> </main> <aside id="sidebar"> <?php include('./parts/categories-list.php'); // no expects ?> </aside> The category template file works exactly the same way, except that it lists products for the category rather than listing all products. The same code works either way, so "category.php" just includes "products.php": <?php namespace ProcessWire; // category.php include('./products.php'); There's that findProducts() function above in the products.php template file -- I usually have helper functions in a /site/templates/_func.php, /site/templates/_products.php, or /site/templates/products/func.php (assuming exclusive for "products"). Another place would be for the ProductsPage and CategoryPage to have findProducts() methods, but usually I don't want the page classes getting involved with detecting stuff about the current request (sort, pageNum, etc.) so like these in a simple function library file: <?php namespace ProcessWire; // file site/templates/_func.php included by _init.php function getSorts(): array { return [ 'name' => 'A-Z', '-name' => 'Z-A', 'price' => 'Price (low-high)', '-price' => 'Price (high-low)', 'created' => 'Date added (oldest)', '-created' => 'Date added (newest)' ]; } function getSort(): string { $sorts = getSorts(); $sort = input()->urlSegment('sort-(*)'); if(empty($sort)) $sort = 'name'; if(!isset($sorts[$sort])) wire404('Invalid sort'); return $sort; } function findProducts($page, $limit = 20): PageArray { $sort = getSort(); $find = "template=product, sort=$sort, limit=$limit"; if($page instanceof CategoryPage) $find .= ", categories=$page"; return pages()->find($find); } Here's an example of a ./parts/products-list.php file: <?php namespace ProcessWire; // file: parts/products-list.php /** @var PageArray|ProductPage[] $products */ $subhead = $products->getPaginationStr('Products'); $pagination = files()->render('parts/pagination.php', [ 'items' => $products ]); ?> <h3><?=$subhead?></h3> <?=$pagination?> <ul class="products-list"> <?php foreach($products as $product): ? <?php include('./parts/products-item.php'); // expects $product ?> <?php endforeach; ?> </ul> And the parts/products-item.php, though in reality there would likely be more to it: <?php namespace ProcessWire; // file: parts/products-item.php /** @var ProductPage $product */ ?> <li class="products-item"> <h3><?=$product->title?></h3> <p><?=$product->summary?></p> <p><a href="<?=$product->url?>">View Details</a></p> </li> To complete it, here's the parts/sorts.php file: <?php namespace ProcessWire; // file: parts/sorts.php $currentSort = getSort(); $url = page()->url; $sorts = []; foreach(getSorts() as $sort => $label) { if($sort != $currentSort) $label = "<a href='{$url}sort-$sort/'>$label</a>"; $sorts[] = $label; } echo "<p class='sorts'>Sort by: " . implode(' / ', $sorts) . "</p>"; If I start needing to output products in more places in the site, then I'll usually do fewer include()'s and move the rendering to dedicated functions. That way these things render in their own variable namespace and don't bleed variables or overwrite variables in the main rendering. So this would also go in that _func.php (or _products.php or ./products/func.php) mentioned above, and the include() calls in template fiels would be replaced with render...() calls: function renderProducts(PageArray $products): string { return files()->render('parts/products-list.php', [ 'products' => $products ]); } function renderCategories(): string { return files()->render('parts/categories-list.php'); } function renderPagination(PageArray $items) { return files()->render('parts/pagination.php', [ 'items' => $items ]); } So if using render() functions then the <main> with the include('./parts/products-list.php'); would get replaced with this: <main id="content"> <?=$body?> <?=renderProducts($products)?> </main> Ah yes, I hadn't thought about that in a long time. I can't remember if that was implemented yet or not. I'll find out. If not yet implemented I'll have to implement it, it should be fairly simple. -
Everything you need to know about custom page classes, from beginner to advanced. You'll find time saving tips and tricks, pitfalls, best practices, and plenty of examples too— https://processwire.com/blog/posts/custom-page-classes/
- 7 replies
-
- 24
-
-
-
Included are more than 70 issue fixes and 175 commits. Here we’ll zoom in on the numerous new features and improvements to the core for one of our best new versions yet! https://processwire.com/blog/posts/pw-3.0.255/
- 3 replies
-
- 25
-
-
-
Today I’ve merged the dev branch to the main/master branch in preparation for our next official tagged version, which is likely to be 3.0.255. I’ll likely git tag it with the version number early next week. This doesn’t mean that work on the next main/master version is complete. Just that no new issues have appeared that would warrant delaying it any longer. So while there’s still work to do, we’re also at a good point to start getting these updates on the main/master branch. As before, if you run into any issues after upgrading, please report them in the processwire-issues repo. I’ll compile and post a list of all that’s new in 3.0.255+ relative to 3.0.246 within the next week or two so stay tuned. There have been some really nice sites showing up in our sites directory lately. Thank you for those that have been submitting new ProcessWire-powered sites, and please keep it up! It’s great to see such awesome web design and development work.
- 4 replies
-
- 17
-
-
-
@szabesz Thanks, I was able to duplicate that also. I couldn't figure out how to fix it, but @diogo had a look and came up with a solution. It should be on the dev branch now. Please let me know if you still run into the issue.
-
@thei Glad you got it working. It should be possible to use an array for this, but I might be forgetting something about it, as I think it's been a long time since I used one for this. In any case, it's definitely better to use a WireData object (or one derived from it) because ProcessWire can track changes to the properties in the object. Whereas there's no change tracking built into an array.
-
Happy new year! I’m focused right now on getting our next main/master version out, hopefully next week. I’m looking for anything that worked in 3.0.246 but doesn’t in the current dev branch. After this week's commits, I’m not aware of anything remaining that fits that criteria, but if anyone knows of anything please let me know. In addition, if you are aware of any remaining issues with with PHP 8.4 or 8.5 (deprecation notices, etc.) please let me know. In either case, the best place to report is in the processwire-issues repo on GitHub. If it’s something that’s already been reported, then please bump the issue by replying to “bump” to it (or whatever you’d like). Thanks and have a great weekend!
- 2 replies
-
- 14
-
-
-
@thei I think the issue may be that the 'data' column isn't used here, and ProcessWire wants you to use it. So you could perhaps use 'data' as your "date_from" and then add another column called "to" or something, and use that as your "date_to". The only methods that would need to know about "data" and "to" would be those that communicate with the database: getDatabaseSchema(), wakeupValue() and sleepValue(). Everywhere else can refer to date_from and date_to. The wakeupValue would convert "data" and "to" to "date_from" and "date_to", while the sleepValue() would convert "date_from" to "data" and "date_to" to "to" (or whatever column names you decide to use). Example of the Fieldtype portion below: public function getBlankValue(Page $page, Field $field) { return [ 'date_from' => '', 'date_to' => '' ]; } public function getDatabaseSchema(Field $field) : array { $schema = parent::getDatabaseSchema($field); $schema['data'] = 'date default null'; // date_from $schema['to'] = 'date default null'; // date_to $schema['keys']['data'] = 'KEY data (`data`, `to`)'; $schema['keys']['to'] = 'KEY `to` (`to`)'; return $schema; } public function ___sleepValue(Page $page, Field $field, $value) { $value = $this->sanitizeValue($page, $field, $value); // store blank as null in DB if(empty($value['date_from'])) $value['date_from'] = null; if(empty($value['date_to'])) $value['date_to'] = null; // return value ready to store in DB return [ 'data' => $value['date_from'], 'to' => $value['date_to'] ]; } public function ___wakeupValue(Page $page, Field $field, $value) { if(!is_array($value)) return $this->getBlankValue($page, $field); // return value ready for $page->fieldName return [ 'date_from' => "$value[data]", 'date_to' => "$value[to]" ]; } public function sanitizeValue(Page $page, Field $field, $value) { if(!is_array($value)) $value = []; $value = array_merge($this->getBlankValue($page, $field), $value); $dateFrom = $value['date_from']; if($dateFrom) $dateFrom = wireDate('Y-m-d', $dateFrom); $dateTo = $value['date_to']; if($dateTo) $dateTo = wireDate('Y-m-d', $dateTo); return [ 'date_from' => $dateFrom, 'date_to' => $dateTo ]; } Next, I don't think your Inputfield processInput() method will work as-is, so I'd suggest changing it to something like this: public function ___processInput(WireInputData $input) { $value = [ 'date_from' => '', 'date_to' => '' ]; foreach(array_keys($value) as $key) { $date = $input->get($key); $value[$key] = $date ? wireDate('Y-m-d', $date) : ''; } $this->val($value); return $this; } Once you've got it all working, you might consider changing the array value to a WireData value. That will make it so that you only ever have to define the date_from/date_to array once, and it can sanitize itself rather than these other methods.
-
@FireWire I see it says Resolved now, but did you find out how it happened? I looked at the moderation log for the topic and there's no entry where anyone hid or locked the topic. Though I do see an entry where Netcarver fixed the issue. So I'm wondering what broke it in the first place? Maybe a side effect from the recent forum upgrade is the only thing I can guess so far.