MarkE
Members-
Posts
1,047 -
Joined
-
Last visited
-
Days Won
12
Everything posted by MarkE
-
So here's a (hopefully better and working) solution. Add the following as a hook to (i.e. new method for) WireSaveableItems: public function getFreshSaveableItem($event) { $saveables = $event->object; $item = $event->arguments(0); $database = $this->wire()->database; $sql = $saveables->getLoadQuery()->getQuery(); $query = $database->prepare($sql); $query->execute(); $rows = $query->fetchAll(\PDO::FETCH_ASSOC); $newItem = null; if($item) { foreach ($rows as $key => $val) { if ($val['id'] == $item->id) { $row = $rows[$key]; $newItem = $saveables->initItem($row); // there should be only one matching item break; } } } $event->return = $newItem; } This returns the item as it is in the database, so if you call (say) wire('fields')->getFreshSaveableItem($myfield) in a beforeSave hook, you will get the version of $myfield that is in the database - i.e before it is saved and can compare it with the version about to be saved. But if you want to use this, test it out well first! Maybe someone else can come up with something better (or even a PR for the core?!)
-
Just bumping this in case anyone has any ideas. As stated above, my work-round is rather clumsy and inefficient. Surely there must be an easier way?! EDIT: I notice that WireSaveableItems has a hookable method ___saved(Saveable $item, array $changes = array()) but I can't find anything calling it with the $changes parameter set.
-
What software do people like for showing off their modules, websites etc.? I have tried the (free version of) screencast-o-matic and Clipchamp but neither really suits me. The former is a bit simple whereas the latter is rather complex. I'd like to be able to record activity on a screen, pause the recording while I gather my thoughts or segue to a different sequence, add captions (or maybe audio) and cut or append videos. Any suggestions?
-
The description for 'add new tag' in (say) the field setup in the back-end UI reads 'You may use letters, digits or underscore.' It does not mention capital letters. However, if capital letters are included, they seem to get converted to lower case. On the other hand, via the API you can set $field->tags to have values which include capitals and these are then shown correctly in the UI and is maintained correctly in the API. But if you amend other data for the field (say) then the tag is amended to the lower case version. Is this a bug? What should the proper behaviour be? It has certainly caught me out - assigning tags with capitals in the API which work fine for a while until some unrelated part of the field is changed and then the tag no longer matches the original.
-
Thanks for all the tips, @Robin S. However one of the fields I need is a repeater matrix and that doesn't seem to support autojoin. Also, while I could get autojoin to work (for other fields) via the field settings, I couldn't replicate your example in my system - none of the requested ('autojoinable') fields were joined. I am on PW 3.0.206. findRaw() works as documented and gets all the fields and may be usable for my purposes, but that doesn't feel like the right answer. It seems like findJoin might be a bit buggy - I'm not sure @adrian's issue has been resolved. But it may be something strange in my set up.
-
New version seems to do the trick. Thanks @adrian.
-
Thanks @Robin S . Sort of ‘doh’ as I had heard of autojoin, but never used it or looked into it. That post explains everything, although I wonder if some fuller documentation in the API for $page might be helpful. I guess using autojoin is more efficient than getting the page then using getFields().
-
Having used PW for a few years now, I feel that this is a really basic question about something that ought to be obvious to me! So I'm prepared to say 'doh!' If I get a page object via the $page API (or page() or $pages or whatever) it doesn't always seem to have the fields fully populated. For example, here is the 'Field List & Values' display (partial) for a page 'gallery-of-apples', it has 5 fields: If I call $page and dump it, all I get is the title field, but by getting the fields via getFields() and setting them, I get the complete picture - see Tracy console image below: What is going on here? Why don't I get all the fields and values with $page?
-
This is a s lightly obscure issue, but hopefully very easy to deal with. If a page only has one child, then the child doesn't necessarily have a sort attribute. In this case, BatchChildEditor will add a sort attribute and save the page. This seems to me to be unnecessary (and is causing a small problem with a module of mine). Is it possible and reasonable to not set the sort if there is only one child? The relevant code is at the end of the saveChildren() method: $cp->sort = $i; if($cp->isChanged()) { $cp->of(false); $cp->save(); } I think it would need something like: if($this->wire('input')->post->individualChildTitles->count() > 1) { $cp->sort = $i; } if($cp->isChanged()) { $cp->of(false); $cp->save(); } but maybe there is a better solution?
-
Start by putting your html inside the foreaches. As coded you will only pick up the last item in each loop.
-
FWIW I have made a little work-round that saves $template->getExportData() as a session var on 'ready' then compares it with the changed value, hooked in 'saved'. It seems to work, but there must be a less clumsy way. trackChanges etc is not very helpful.
-
Thanks @Jan Romero, but that deals with pages (and the values of their fields). What I am after are the field and template objects themselves.
-
A simple question: Is there any way, when a template or field is saved of getting the previous properties (i.e. before the save)?
-
PW 3.0.209 – Core updates and an AI that knows ProcessWire
MarkE replied to ryan's topic in News & Announcements
Probably because ProcessWire has such a nice well-documented API ?. I played with it a bit and it knows how to build modules, but when I asked it to build an inputfield module, the code was what you might use for an inputfield on a page. I am trying to think of how to educate it with the correct context ?. -
module hCaptcha spam protection for ProcessWire forms
MarkE replied to MoritzLost's topic in Modules/Plugins
Yes. I realised after my last update that was probably the cause and that there is no delay in setting up. Maybe a small update to the module documentation? Anyway a really helpful module and very easy to install in Formbuilder. Thanks a lot! -
module hCaptcha spam protection for ProcessWire forms
MarkE replied to MoritzLost's topic in Modules/Plugins
Hi @MoritzLost. I just installed this and added a field to my form in Formbuilder as per instructions with secret and site keys from hCaptcha, but nothing shows in the form. Any idea what might be wrong? UPDATE It seems to be working now. Maybe it just takes time for a new site to be recognised. -
I have a little home-made pagebuilder that is based on RockFrontend and Tailwind and have a few observations that might (or not) be of interest. Tailwind works really well with Latte. The result is (to my mind) concise and understandable code that is easily encapsulated. I tried some of the plugin components etc. but was generally disappointed. As is usually the case with these things, you get a load of baggage you didn't really want and then you try and customise it slightly and it is not easy. I ended up just building my own components with Latte, Tailwind and a bit of custom vanilla js (with a bit of help from various examples on the www). For example, I built a general-pupose carousel template that can be called via a Latte {include file} with options, e.g.: {include $config->paths->templates . 'motif_layouts/latte_blocks/motif_carousel.latte', imagePages: $page->motif_image_page, modal: true, } and {include $config->paths->templates . 'motif_layouts/latte_blocks/motif_carousel.latte', imagePages: $page->motif_image_page, start: $page->motif_image_page->first, autoCycle: ['speed' => 5000] } My pagebuilder makes extensive use of css grid-area-templates which are not present in Tailwind. I thought this might be a bit of a problem, but was pleasantly surprised that the css file reduced from this: .image-text .has-image { /*grid-area: content;*/ display: grid; grid-template-columns: auto; gap: 20px; grid-template-areas: "image" "text"; } @media (min-width: 500px) { .image-text .has-image:not(.image-right) { /*grid-area: content;*/ display: grid; grid-template-columns: 1fr 5fr; gap: 20px; grid-template-areas: "image text" ".... text"; } .image-text .has-image.image-right { /*grid-area: content;*/ display: grid; grid-template-columns: 5fr 1fr; gap: 20px; grid-template-areas: "text image" "text ...."; } } .image-text .no-image{ /*grid-area: content;*/ display: grid; grid-template-columns: auto; grid-template-areas: "text"; } .image-text img{ grid-area: image; } .image-text div#body{ grid-area: text; } to this: .image-text { --stacked: "image" "text"; --image-left: "image text" ".... text"; --image-right: "text image" "text ...."; --text-only: "text"; } .image-text img{ grid-area: image; } .image-text div[id*='body']{ grid-area: text; } with only a marginal increase in the html (using arbitrary properties and values) and (I think) an increase in clarity: <div n:class= "$imgs > 0 ? '[grid-template-areas:var(--stacked)]' : '[grid-template-areas:var(--text-only)]', ($imgs > 0 && $page->motif_toggle == 0) ? 'sm:[grid-template-areas:var(--image-right)] sm:grid-cols-[5fr_1fr]', ($imgs > 0 && $page->motif_toggle == 1) ? 'sm:[grid-template-areas:var(--image-left)] sm:grid-cols-[1fr_5fr]', grid, gap-5"> Note that you need to include these type of class names in quote marks or Latte gets confused. The bit that worried me most was where I needed styling to be dependent on php variables. Some commentators have said that this presents a problem for Tailwind because it creates the stylesheet before the variables are known. However, the work-round is quite simple, with an in-line style tag to create css vars like this: <style> #gallery-item-{$imgPage->id} { --w: {$imgDisplayWidth|noescape}{$heightArray[1]}; --w2: {$expandWidth|noescape}{$heightArray[1]}; --wh: {$halfWidth|noescape}{$heightArray[1]}; --wq: {$quarterWidth|noescape}{$heightArray[1]}; --h: {$height|noescape}; --h2: {$expandHeight|noescape}; } </style> which then can be used directly: class="w-[var(--w)] hover:w-[var(--w2)]" It may be that there are better ways of doing some of this, but I was pleasantly surprised that each time I looked at a bit of slightly involved css and html and thought 'how the hell am I going to do that in Tailwind?', the answer was much shorter and clearer code. In particular, Latte works well with Tailwind throught the power of the n:class tag.
-
RockFrontend 🔥🚀 The Powerful Toolbox for ProcessWire Frontend Development
MarkE replied to bernhard's topic in RockFrontend
Yes thanks. I think those elements must have dated from the early days of RockFrontend and I never updated that _main.php. So I've re-done it all now as per the latest readme and it all seems fine. -
RockFrontend 🔥🚀 The Powerful Toolbox for ProcessWire Frontend Development
MarkE replied to bernhard's topic in RockFrontend
Aha! I have <script src="<?= urls()->siteModules?>RockFrontend/Alfred.js?m=1660123300"></script> <script src="<?= urls()->siteModules?>RockFrontend/livereload.js?m=1660123300"></script> in my head. I think that was maybe the requirement with an earlier version but no longer needed? -
RockFrontend 🔥🚀 The Powerful Toolbox for ProcessWire Frontend Development
MarkE replied to bernhard's topic in RockFrontend
Thanks @bernhard. I can see in the dev tools elements that (for example) <script>let RockFrontend = {"rootUrl":"\/","defaultVspaceScale":0.66000000000000003}</script> is added, but the error persists. Also, I note that this script is not added if there is no Alfred tag on the page, so will that not always cause an error in Alfred.js (albeit not important)? -
RockFrontend 🔥🚀 The Powerful Toolbox for ProcessWire Frontend Development
MarkE replied to bernhard's topic in RockFrontend
The hook seems to be working OK. RockFrontend is a js variable. Where is it supposed to be set? -
RockFrontend 🔥🚀 The Powerful Toolbox for ProcessWire Frontend Development
MarkE replied to bernhard's topic in RockFrontend
Thanks @bernhard. I did that, but I still get this: Alfred.js?m=1660123300:179 Uncaught ReferenceError: RockFrontend is not defined at Alfred.js?m=1660123300:179:3 at Alfred.js?m=1660123300:282:3 livereload.js?m=1660123300:11 Uncaught ReferenceError: RockFrontend is not defined at startStream (livereload.js?m=1660123300:11:14) at livereload.js?m=1660123300:47:3 -
RockFrontend 🔥🚀 The Powerful Toolbox for ProcessWire Frontend Development
MarkE replied to bernhard's topic in RockFrontend
Hi @bernhard, Any idea why I am getting this error in the dev tools console after installing the latest version? Uncaught ReferenceError: RockFrontend is not defined at RockFrontend.js?m=1660203134:11:12 at RockFrontend.js?m=1660203134:48:3 I updated from an earlier version (I forget which, but about 2 months ago) because font-awsome was not loading properly - I was getting <link rel="stylesheet" href="undefinedwire/templates-admin/styles/font-awesome/css/font-awesome.min.css" type="text/css"> rather than the correct url. Now I don't even get that link. Looks like a similar issue though as the url is given by RockFrontend.rootUrl -
Preventing a page from being moved is not necessarily a straightforward matter of trapping the change in a save hook in the same way as a page edit. A problem occurs if the page is only to be 'blocked' conditionally - when the page path is in some given array, for example. In hooking before page save, the page path is the new page path after the move, rather than before it, so you need to do something like this: // .... In the before page:saveReady hook // $page is the page :) The code below operates when (isset($page->parentPrevious) && $object->parentPrevious != $object->parent) $name = $page->parentPrevious->path . $page->name . '/'; // need the path before it was moved if(in_array($name, $blockedNames)) { // $blockedNames are the ones where we don't want moves // Because this hook operates after the move, we need to reverse the move $page->parent = $page->parentPrevious; // Alternatively, to completely stop the save //$event->replace = true; //$event->return = false; } //... rest of hook This prevents the page being moved, both in the page hierarchy (by dragging) or in the page editor by changing the parent in the settings tab. It is also possible to hook before Page:moveable with something like this /** @var Page $page */ $page = $event->object; $moveable = $event->return; // ... code to set $moveable to false if conditions met $event->return = $moveable; Interestingly, the (not documented?) moveable method is created as a hook by PagePermissions and so is hookable. However, this method appears to catch only the situation where the move is effected by dragging the page in the tree, not when the parent is changed in the settings.