-
Posts
695 -
Joined
-
Last visited
-
Days Won
20
Everything posted by Jan Romero
-
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?
-
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.
-
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?
-
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).
-
Dynamic SVG? How might you try to solve this...?
Jan Romero replied to BrendonKoz's topic in General Support
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. -
I just had this problem as well, using a 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.
-
Limit characters or words of textarea on certain template
Jan Romero replied to Martinus's topic in API & Templates
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 -
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.
-
When ProcessPageAdd quick-creates a page, it gives it a temporary status Page::statusTemp that is removed when the page is next saved using the UI. I imagine you need to remove this status in your hook to make the lightning symbol go away. The temporary status is there so pages that were accidentally created can be cleaned up automatically. I would probably hook ProcessPageAdd::processQuickAdd instead of Pages::save: https://github.com/processwire/processwire/blob/master/wire/modules/Process/ProcessPageAdd/ProcessPageAdd.module#L1091 Edit: Can’t get processQuickAdd to work… Maybe because it redirects the hook doesn’t get a chance to run? Still, it should be sufficient to hook into ProcessPageEdit::execute: wire()->addHookBefore('ProcessPageEdit::execute', function(HookEvent $event) { /** @var Page $page */ $page = $event->object->getPage(); //if the page has statusTemp it was probably created by ProcessPageAdd::processQuickAdd if ($page->hasStatus(Page::statusTemp)) { $page->removeStatus(Page::statusTemp); $page->removeStatus(Page::statusUnpublished); $page->save(['quiet' => true, 'noHooks' => true, 'noFields' => true]); wire()->message('Auto-published that for you. You’re welcome.'); } });
-
Well, it’s kind of a broad question. If you’re talking about having different language versions of your pages, ProcessWire comes with built-in support for managing that content. You’ll have to figure out whom to show which language content yourself, though, for example by using the Accept-Language header. If you only need region-specific content and no multi-language, you could abuse ProcessWire’s language system for that, too. If you need both dimensions, you’ll have to figure out how to manage all that content. Do you need everything for every region and language, or maybe just a sprinkle here and there such as “this site is not available in your country thanks to the S. Fischer Verlag GmbH”? I guess the answer is, it’s up to you? ProcessWire doesn’t have a built-in feature that lets you connect content to predefined regions or detects users’ regions for you, but you’ll want to decide these things for yourself anyway. My example used an external service that looks up IP adresses. There are drawbacks to that technique that you may not want. Other options include just asking the user or using the browser’s geolocation API (AFAIK this will only give you coordinates, so again you’ll need to use a service to get the “region”, or calculate it yourself if you’re into geomatics).
-
Wow, I didn’t believe this until I tried it ? However, since you’re only looking for one image, try using get() instead of find(): $image = $p->images->get("videocounter=270"); Or use first() to get the first matching image: $image = $p->images->find("videocounter=270")->first(); Otherwise find() will give you a Pageimages object that potentially holds multiple images, so calling url() on it won’t work.
-
Sure, just copy and paste this to your site $http = new WireHttp(); $region = $http->getJson("http://ip-api.com/json/{$session->getIP()}?fields=city,countryCode"); user()->setLanguage($region['countryCode']); //well… it’s not *this* easy. you’ll have to connect your languages to ISO 3166-1 alpha-2 country codes somehow echo '<marquee><blink>' . sprintf(__('Hot milfs looking to hook up in %s!'), $region['city']) . '</blink></marquee>';
-
There is nothing like this specific to ProcessWire, you can just use any CSS you want. For example this is the first Google hit for “css framework”: https://github.com/troxler/awesome-css-frameworks
-
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.