-
Posts
680 -
Joined
-
Last visited
-
Days Won
18
Everything posted by Jan Romero
-
It’s a PHP feature, it has nothing to do with ProcessWire or its selectors: https://www.php.net/manual/en/language.types.string.php#language.types.string.parsing I just wouldn’t bother with the curlyless syntax.
-
Enclose the variable parts in curly braces: "<p>{$item->vendor->title}</p>" Otherwise it will only evaluate the first property, $item->vendor. Because it’s a page, you get its ID. It’s bugging me that I can’t seem to find any mention of this limitation in the PHP docs. It only says it will “greedily take as many tokens as possible to form a valid variable name”, but apparently it’s not so greedy with sub-properties? Anyway, I simply always use curly braces… Btw, if you use an editor with a language server such as PHP Intelephense, the syntax highlighting will show you the problem:
-
[SOLVED] make locked pages editable for superusers
Jan Romero replied to jploch's topic in General Support
Haven’t thoroughly tested it or anything, but this hook seems to work: wire()->addHookBefore('ProcessPageEdit::execute', function(HookEvent $event) { /** @var Page $page */ $page = $event->object->getPage(); //ProcessPageEdit does roughly this to figure out if it’s dealing with a save request. if it isn’t, we don’t care if (!count($_POST) || (int)input()->post('id') !== $page->id) return; //if the page isn’t locked -> don’t care if (!$page->isLocked()) return; //if it’s locked and we’re a superuser, unlock if (user()->isSuperuser()) { $page->removeStatus(Page::statusLocked); wire()->message('leet hax, you just edited a locked page.'); //You don’t need to re-lock the page here, because the Locked checkbox is //sent with the page edit form, so saving will set it to the desired value } }); I would have hooked processSave directly, but it’s not hookable. Bonus tip: You can change the warning that says “This page is locked for edits” if you put this in the hook: if (user()->isSuperuser()) $event->object->noticeLocked .= ', but I’ll make an exception for you because you’re such a pleasure to be around'; Btw, you can always edit locked pages from the API as a superuser.- 1 reply
-
- 3
-
I did pagination but infinite scroll not working?
Jan Romero replied to kkalgidim's topic in Getting Started
What you’re using there is not the infinite-scroll plugin you mentioned in your original post. It appears to be this bullshit whom I hope I’m not doing injustice when I assert it only pretends to do infinite scrolling and instead just loads everything at once. Typically ”infinite scroll“ means that you load only a couple of items and show them, then when the user has scrolled to the end, you load a couple more, scroll, load, scroll, load etc. To do that you need three things: Your frontend page that loads displays the items An API that delivers the items, where “API” just means a page that uses pagination to know which items to return next A script on 1 that keeps track of which items to request from 2, which runs when the user has scrolled down, loads the items and puts them at the end With a little Javascript it’s easy to write the script (3) yourself, but of course you can use infinite-scroll.com. The important bit is (2), I believe you don’t have that one yet? Here is the simplest way to implement that: <?php namespace Processwire; $results = pages()->find("template=property, limit=9, sort=-date"); //for this to work the page’s template must use pagination (template settings) foreach($results as $l) { ?> <div class="row-eq-height cf-xs-6 cf-sm-6 cf-lg-4 col-xs-6 col-sm-6 col-md-4 prop-i-col"> <div class="prop-i"> <a href="<?php echo $l->url;?>" class="prop-i-img"> <img src="<?php echo $l->images->eq(0)->url;?>" alt=""> </a> </div> </div> <?php } ?> Note that that would be the entire page. It only returns the items themselves, no <html> or <body> or anything, so that they can be inserted into the full page by the javascript. You need to make sure it behaves that way. Stuff you don’t want here may be added automatically if you use prepend/append files, for example. -
ProFields Table: Edit/Delete Specific Item
Jan Romero replied to Carl Booth's topic in General Support
Hi Carl, welcome to the PW forums! Sorry, it’s not clear to me what $award and $tt are in your code? Also, it looks like you’re getting a table row into $opday and then never do anything with it? But yeah, modifying a specific item is described in the module’s readme: $page->of(false); // turn off output formatting, if necessary $award = $page->awards->first(); $award->title = "Most Sustainable Building"; $award->date = "2014-05-01"; $page->save('awards'); (I only have an exceedingly old version, your readme may differ.) Btw, there is a dedicated support board for ProFields, if you have access (I don’t). -
Get children of a page but start at a certain index
Jan Romero replied to Stefanowitsch's topic in API & Templates
Yes, check the input tab in the field settings. -
some questions… first: checking if field exists doesn't work
Jan Romero replied to froot's topic in Module/Plugin Development
You mean MarkupAdminDataTable? https://processwire.com/api/ref/markup-admin-data-table/ Have you tried setting encodeEntities to false? You’ll have to escape the contents yourself, but you’ll be able to use HTML tags. -
Get children of a page but start at a certain index
Jan Romero replied to Stefanowitsch's topic in API & Templates
First of all, listen to Bernhard, but to answer your question, you can get pages by position using the selector "start": https://processwire.com/docs/selectors/#limit The number is the zero-based index of the first element you want. The order will reflect that of the page tree unless you specify the "sort" selector. I haven’t thouroughly checked it out, but you may be interested in the Virtual Parents module: https://github.com/Toutouwai/VirtualParents -
A page’s status is a bit field technically you need to check whether it contains the hidden status. You can do this with ProcessWire selectors using the bitwise AND operator and negating the result: $page->parents('id!=1, !status&1024') Instead of the number 1024 you can also use the named constant: $page->parents('id!=1, !status&' . Page::statusHidden)
-
Does your Earth page use the template "planet" that you set up in Step 2? I imagine this is the problem. Check the page’s settings tab, it’s probably "basic-page". If that’s not the issue, did you use all the same names from the tutorial? ProcessWire auto-detects the template file from Step 1 and uses it for the template in Step 2 if they have the same names (without the .php extension). So your template should be named "planet" and the file in /site/templates/ should be named "planet.php". Although if ProcessWire couldn’t auto-detect the template file, you shouldn’t be able to view the page at all.
-
Hi, welcome to the forums! ProcessWire is very mobile friendly. I can only speak about the Default theme, which works flawlessly on a phone. I’m sure the other stock themes work similarly well or even better. However, it’s your responsibility to make the actual public site you build with ProcessWire mobile friendly yourself. ProcessWire won’t get in the way of doing that, because it doesn’t come with any assumptions about your frontend. I’m not sure I fully understand your question here. There is nothing wrong with setting up links to a separate shop system and ProcessWire will definitely work well for you there, but if you’re planning on building your own web shop, check out Padloper 2:
-
Sorry, I was a bit terse. To be clear, I meant storing your custom path in the $config->paths object, somewhat like this: // config.php (or init.php) $config->paths->set('home_sidebar_timeline', $includes_path . 'home_sidebar_timeline.php'); Then you should be able to get it from anywhere anywhere like this: include $config->paths->home_sidebar_timeline; //or include $config->paths->get('home_sidebar_timeline');
-
I imagine global variables might work, but I would probably but it into $config->paths: https://processwire.com/api/ref/paths/
-
Hi everyone, I’ve come across this phenomenon where WireCache never builds cache entries if they were previously attempted to preload. Just wondering if anyone has any experience with preloading WireCache items? Am I doing something wrong? I’ve described the issue here: https://github.com/processwire/processwire-issues/issues/1604 Here is the code I’m using: cache()->preload([ 'imaginary', 'names' ]); //these don’t exist. //now cache()->preloads is [ 'imaginary' => '', 'names' => '' ] $freshlyGeneratedValue = cache()->get('imaginary', WireCache::expireDaily, function() { return 'so fresh'; //this never happens }); var_dump($freshlyGeneratedValue); // string(0) "" Thanks!
-
Reviewer role: Permission to view unpublished pages?
Jan Romero replied to snck's topic in General Support
Apparently ready.php is too late for direct page views, so I would recommend init.php.- 2 replies
-
- 1
-
- permissions
- user roles
-
(and 1 more)
Tagged with:
-
I dunno, it works for me. I did add names to the inputs, because they wouldn't get serialised without them, but the javascript is the same as yours: Note that action="/ajax-handler/" with the "/" at the beginning will submit the request to "example.com/ajax-handler/" regardless of the original url. If you want to request a relative path, remove the first "/".
- 1 reply
-
- 1
-
I think you don’t need to manually set the Content-Type header if you send a URLSearchParams object: secondAJAXXHR.send(new URLSearchParams(request)); (no support in the old IE though)
-
Help make to work a nested conditional hook (and/or alternatives)
Jan Romero replied to LAPS's topic in General Support
Yeah, you’re right, the piggybacking I mentioned only works with full page saves… Guess you’ll have to call save() after all. You can do so by specifying the noHooks option, so that you don’t call your hook infinite times: $user->setAndSave('title', 'that user who keeps changing their bookmarks', ['noHooks' => true]); You can also hook savedPageOrField(), in which case the names of the changed fields will be in $event->arguments(1). -
Help make to work a nested conditional hook (and/or alternatives)
Jan Romero replied to LAPS's topic in General Support
Do you specifically need to use that nested hooks technique? If you want to update related user fields when a specific field is about to be saved, you can just hook savePageOrFieldReady() and evaluate the changes: wire()->addHookAfter("Pages::savePageOrFieldReady(template=user)", function(HookEvent $event) { $user = $event->arguments(0); if (!$user->isChanged('user_bookmarks')) return; //bookmarks weren’t changed, nothing to do $user->of(false); $user->set('title', 'that user who keeps changing their bookmarks'); }); Note you don’t need to call save() or anything, you’re piggybacking off of the hooked save operation. <-- doesn’t work if the hook was triggered by a field save. Otherwise, did you remove the nested hook according to the example in the docs? -
Help make to work a nested conditional hook (and/or alternatives)
Jan Romero replied to LAPS's topic in General Support
Hi, this works for me: wire()->addHookAfter("User::changed(user_bookmarks)", function(HookEvent $event) { $user = $event->object; // User $old = $event->arguments(1); // old value $new = $event->arguments(2); // new value wire()->addHookAfter("Pages::savedPageOrField($user)", function(HookEvent $event) use($user, $old, $new) { var_dump($user); var_dump($old); var_dump($new); var_dump($event); }); }); Btw there is also savePageOrFieldReady(). Might be of interest if you want to modify the user. -
Help make to work a nested conditional hook (and/or alternatives)
Jan Romero replied to LAPS's topic in General Support
I think you fell victim to one of the classic blunders. SetAndSave() specifically only saves a particular field, and field-saves don’t trigger the saved() hook. Check out savedPageOrField() to catch both types of save operation: https://processwire.com/api/ref/pages/saved-page-or-field -
Solved: Number of rows for description field
Jan Romero replied to pwired's topic in General Support
Must be a mistake in the blog post, I’m pretty sure Ryan meant the “Details” tab: (the screenshot is from 3.0.191, though) -
Yeah, you can probably replace that line with this if($page->id && $page->if('ImportPagesCSVData')) { to make it work on your end. For a permanent solution the module will have to be updated.
-
Feels like one of those Errors that used to be Warnings before PHP 8. Do you have a detailed error message with the line number? Count appears 4 times in the Module, but it should be an easy fix either way to add some null-checks or is_countable(). @ryan
-
There is a lot going on here. You mentioned that visitors (guests or logged-in users?) will be able to subscribe to multiple events at once, but you will likely only want to verify the email once. AFAIK the only way to verify emails is to actually send a secret to the address and have the recipient send it back. So I would do a poor man’s solution somewhat like this: Create one page per recipient that stores the address and a secret token (ProcessWire can generate one for you like this: (new Password())->randomBase64String()) When the user has entered their address and you have created the page, send them a link like https://example.com/verify?mail=myemail@example.com&mytoken=xyIu6yehxXfTelYpqcOdv8 When that link requested, find the recipient and consider them verified if the token matches (i.e. set a checkbox or just delete the token and consider everyone without one verified) Store event subscriptions as multiple page references either on the recipient or on the event, whatever As long as these transactional mails don’t go overboard you should be fine. If you don’t need any personalisation, you might actually send the event reminders as a single email per event, just dumping everyone into BCC. If you’re thinking of growing the business, you will want to go with a dedicated solution such as https://de.sendinblue.com/preise/ (a German company formerly known as Newsletter2Go, should be fine GDPR-wise). Mass mailing is serious business. You don’t want to get blocked by Gmail or something, so above some threshold it’ll be worth shelling out for a service whose business is making sure emails go through. You mentioned you’re on shared hosting. Do you have cron jobs at all? Some shared hosting providers offer something like “cron jobs lite”, where you get a configuration form and the only action you can perform is an HTTP request. In that case you just expose some URL from your site that will send emails upon request.