Jump to content

Jan Romero

  • Posts

  • Joined

  • Last visited

  • Days Won


Jan Romero last won the day on August 16

Jan Romero had the most liked content!

1 Follower

Profile Information

  • Gender
    Not Telling
  • Location

Recent Profile Visitors

14,745 profile views

Jan Romero's Achievements

Sr. Member

Sr. Member (5/6)




Community Answers

  1. If you’re running MySql 8 you can use the row_number window function: update pages p inner join (select id, row_number() over (partition by parent_id order by rand()) - 1 as randomsort from pages where parent_id = :YOUR_PARENT_ID) as r on r.id = p.id set p.sort = r.randomsort There may be faster ways to give consecutive sort numbers to random children, but this runs in the blink of an eye (Adminer says 0.005s for my 986 pages). Repeat until you get the order you like. Make sure you set the parent to “manual drag-and-drop” or you won’t see any effect.
  2. Hi, sounds like you want this: (only without the negating “!” in your case)
  3. This is in the selector docs, right were you would expect it 😉 Granted, the page is pretty long and cluttered when you’re just scrolling through, but it’s great for CTRL+F’ing and the table of contents at the top is very helpful. Mostly “find“ means “I have some criteria, give me any pages that match it” (only those the user may view, by default). “Get” means “I know exactly which page I want, give it to me”. Get gives you one specific page, Find gives you multiple. There is also pages()->findOne() if you only want a single page – the difference here is that this will check if you have access first, while pages()->get() will always give it to you if it exists, even if it’s unpublished or hidden. Anyway, rock on! I’m sure you will be enjoying PW for years to come 🙂
  4. What you’re doing very much hinges on the stability of your products and the order they’re in between rendering the form and processing its submission. If you open the form in your browser and let it sit there for an hour while you or someone else adds, removes or modifies a product, you will update the wrong products when you get back to the form! This is because you’re using the products’ positions in the selector results to identify them. It would be better to use their IDs or their page names because those are much less likely to change. Consider this: <form method="post"> <?php $products = $pages->find("template=product, sort=title"); foreach ($products as $product) { ?> <li> <h3><?=$product->id?>&nbsp;&nbsp;<input type="number" value="<?=$product->amount ?: 0?>" name="product[<?=$product->id?>]" min="0" style="width: 50px;">&nbsp;&nbsp;<?=$product->title?></h3> </li> <?php } ?> <button type="submit" name="submit" value="update" style="width: auto;">Bestand aktualisieren</button> </form> if ($input->post->submit) { $amounts = $input->post->product; $products = $pages->find("template=product, sort=title"); if ($amounts) { foreach ($amounts as $id => $amount) { $products->getPageByID((int)$id)?->setAndSave('amount', $amount); } } } Well, one answer is “because Ryan didn’t program it that way”. You were giving $pages->get() a Page that you already had. It certainly could work, because all the necessary information is there, but the get() method wasn’t programmed for that situation, because if you have the Page object already, why would you need to get it again? You can still do so by converting the Page object to a string (which is always its ID) or just getting its ID explicitly. Because your Page object was named $id, that would have been $pages->get($id->id). Here is an unrelated tip: you can just use single quotes instead of escaping the double quotes, because mercifully both are legal in HTML. You can even mix them in the same tag: <input type="text" value='call me ishmael'/>
  5. Yes, in a file with namespace ProcessWire that will let you use it: $foo = new \stdClass(); You can also put “use \stdClass” at the top if you need it a lot. The same goes for all the other stuff outside PW’s namespace. Often you’ll need \DateTime or \IntlDateFormatter for example. Edit: the technical term is “The Global Space”: https://www.php.net/manual/en/language.namespaces.global.php
  6. Put a backslash in front if you want to use PHP classes, or am I missing something? It’s near impossible to answer your question without knowing why you want to use stdClass. Could well be that ProcessWire has something suitable for your use case, but what is your use case?
  7. Granted, I don’t have much experience with the complex column types (I only just updated after 10 years or so, to get the Page type), but if you primarily use primitive types, ProFields Table has the benefit of being a single SQL join away. So if you’re like me and you sometimes want to do custom queries, that’s pretty cool. Plus, while I have nothing against repeaters, for some things it just feels icky to have the Page overhead. I have a site with playlists, so there’s a table with Artist, Title and some auto-generated normalisation columns for search, for example. Another site manages ”trips“ using a column for the place and two DateTime columns for the duration. I think the need to connect multiple Page references to some metadata like dates is pretty common, and ProFields Table is perfect for that.
  8. if ($input->post->submit) { //it is a mystery to us what this, and since it comes //from the client, it may also be a mystery to you $amounts = $input->post->product; //you’re looking up pages, so this will be a PageArray //with arbitrary numerical indices $products = $pages->find("template=product, sort=title"); if ($amounts) { //apparently we’re assuming the client sent us an //array with meaningful indices foreach ($amounts as $index => $amount) { //because $products is a PageArray, you’re going to //get NULL or a Page object when you access it like //this. In your case probably NULL unless your client //can somehow divine what pages result from the above //selector AND in what order $id = $products[$index]; //because $id is either NULL or a Page, this selector //cannot work. It will work if you put $id in quotes: //– if $id is NULL it will look for nothing and give you // a NullPage. //– if $id is a Page, PHP will call toString() on it, // resulting in its ID, so you’ll just get the same // Page back. //Both paths seem useless though? $pages->get($id)->setAndSave('amount', $amount); } } } This is my understanding from looking at it… Can you explain what $input->post->product contains?
  9. Looks like I subscribed not a moment too soon 😎 ProFields Table is the greatest 👌👌👌
  10. I just stumbled upon this pretty recent article by Ionos, one of the biggest hosting providers in Germany (formerly 1&1, not sure how big they are elsewhere): https://www.ionos.com/digitalguide/hosting/cms/processwire/ It’s in english and includes a comparison to Wordpress (the tabular comparison is kind of broken, though).
  11. Interesting problem. If I understand correctly, you want to have two sources of truth that you need to connect somehow, i.e. the data inside the SVG and data from ProcessWire? I wonder if that’s worthwhile, because what are the chances you’ll want to change something on one side and not the other? To get translatable strings inside the SVG you could always use {placeholders} and populate them with WireTextTools, but as soon as you significantly change a text’s length, you’ll need to touch the SVG anyway, plus you will need to keep the placeholder names in sync. Obviously authoring the SVG is the most annoying part of managing this content, but I don’t see how you would get around it, so maybe try and make it the only part? You could cram everything into the SVG in some standardized way, like predefined classes and data- attributes, then analyze it with JS and build all the toggles dynamically.
  12. I just had this problem as well, using path hook like this: wire()->addHook('/my/path', function($event) { /*…*/ }); In conjunction with a form like this: <form method="POST" action="/my/path/"> ProcessWire redirects the version with the trailing slash to the path matching the hook. I presume the same thing happens with normal pages and url segments as well, depending on the template settings. So if your redirect goes from /action_page to /action_page/ or vice versa, just request the exact url directly.
  13. To limit how many characters can be input, to go the field settings and set "maximum length" in the Input tab to a value greater than 0. You can also do this per template if you switch to a template using the dropdown in the upper right corner. Or you can go to the template settings and click the field there. To shorten the string during output, you can use WireTextTools: WireTextTools::truncate() method - ProcessWire API
  14. Yes, I couldn’t get it to work either, I amended my comment 😅 Bernhard’s snippet has a syntax error, here’s the working code: wire()->addHookAfter('Pages::saveReady(template=foo, id=0, status&'.Page::statusTemp.')', function($event) { $event->arguments(0)->status = 1; }); I also added the status check, because you don’t need this to run for every new page. API-created pages will be published by default, for example. Also I’m not sure I would just set the status to 1, in case PW or some other hook wants to set something else, like Locked or Draft or something. Probably better to just remove the ones you want to remove specifically.
  • Create New...