Jump to content

BitPoet

Members
  • Posts

    1,334
  • Joined

  • Last visited

  • Days Won

    62

Everything posted by BitPoet

  1. A Pageimage instance knows the page it belongs to. See the bottom of the Pagefile documentation (section "Other") for reference. foreach($random_thumbs as $r) { echo "<img src='{$r->url}'> <p>{$r->page->title}</p>"; }
  2. It's very, very bad practice to use sleep() in a server side script, that is why documentation on working around the pecularities of PHP's buffering (and thread execution) is so sparse. sleep() blocks the whole thread it is called in, and under heavier load, it makes servers utterly unresponsive. There also fine differences in buffering behaviour depending on how PHP is executed (mod_php, FastCGI, classic CGI...) The usual solution to situations where you are tempted to call sleep() is to poll until the condition you need to wait for has been reached, either using classic reloads for the current page or with AJAX. Nowadays, websockets are also used to split off parts of the work to different processes and notify the "owning" session of changes of state in the backend.
  3. Simply don't set a name, then PW will take the title you assigned and create a unique name from it by running it through $sanitizer->pageName and appending an incremental suffix if the name has already been taken. There can only be one page with a given name under the same parent. You can read some more about it in this discussion:
  4. That message comes from within PagesEditor::saveField. The only place in the blog module that I am aware of that calls save() on a single page field is in BlogPublishDate. You could try and uninstall that one temporarily to see if it is indeed the culprit. If the error still persists, it's probably triggered by another module or hook.
  5. Use a comma (and perhaps a white space) between your sort properties. $pages->get('/produzenten/')->prod_repeater->sort('prod_objekt, prod_hausnummer') as $produzent
  6. In that case, you should probably check with your hoster whether .htaccess can be used and mod_rewrite is available at all.
  7. There's a mixup of variables in the log output in removeExpiredDirs, namely $path and $pathname in lines 278 and 291 that got switched around. The empty value is output because there's no subdirectory to delete in the temp dir so $pathname never gets a value. Otherwise, the path of the last subdirectory in the loop would be (wrongly) logged. I have opened an issue.
  8. What I have sometimes found helpful in such cases is to bootstrap PW and render the page in question from the command line, i.e. something like php -r 'namepsace ProcessWire; include("index.php"); $p = $pages->get("ID_OR_PATH_OF_YOUR_PAGE"); $p->render();' since PHP CLI is usually a bit more talkative when things go haywire. Might be worth a try.
  9. Running PW on non-standard ports shouldn't be an issue. Did you develop in a subdirectory? If yes, there might be a leftover RewriteBase entry in .htaccess interfering with URL rewrites.
  10. Permissions are much more involved both in the core code and in the database than roles. There are real (e.g. page-edit, always installed), runtime (e.g. page-create, not present in the database) and optional (also called "delegated", e.g. page-publish, used if installed, otherwise replaced with page-edit) permissions. The current implementation of hasPermission also uses the same code path both for global checks and contextual ($page, $template) lookups. Of course, that doesn't prevent implementation of a multi-permissions check per se. BUT. Since code and database are much more involved, running lots of individual permission checks can quickly become a performance killer. IMHO it is in often better to add your own permission (or role) than to run multiple consecutive permission checks in code. I know, that's not a solution, but I'm not aware of a built-in shortcut. Adding a User::hasOnePermission hook method that splits on the pipe symbol and calls $user->hasPermission for each term should be straight-forward though.
  11. First: You know what $event->object is because it is an object of the very class you're hooking onto. In the linked docs, the hook is on Pages::saved, so the event object is an instance of Pages (not a PageArray). In your code, you're hooking Page::price, so $event->object is a Page object. If your hook was InputfieldText::firstWord, it would be an InputfieldText instance. Second: I'd avoid passing $event around to other methods. It kills readability so $event should only be used in the hooks themselves, not in further methods or functions. Yes, you can manipulate arguments. The syntax is in the docs section you linked, in your case it would be $event->arguments(2, $unitprice). But that is mostly meant for before hooks where you want to change the behavior of the original, hooked method. It would be better though to pass all necessary arguments to tierprice and addVat one by one instead of manipulating the "magic thing" that is $event, i.e. something like: $unitprice = $this->tierprice($page, $quantity); Best practice to keep code readable is to use a pattern with a public hook method that decorates your hooked class and a couple of private methods which do the work. <?php /* The usual module stuff... */ public function init() { $this->addHook("Page::price", $this, "hookPrice"); } public function hookPrice(HookEvent $event) { $page = $event->object; $quantity = $event->arguments(0); $vat = $event->arguments(1) ?? false; $unitprice = $this->tierprice($page, $quantity); if($vat) $unitprice = $this->addVat($unitprice); $event->return = true; } private function tierprice($page, $quantity) { /* do whatever calculations and return the result */ } /* ... */
  12. There's an issue with from headers that I still have on the back burner, so I'll take a look at encoding options when I tackle that. Might be a few weeks though, as I'm up to my neck in work since we switched ERP systems at my workplace yesterday.
  13. No need for thanks. I hit my head on that problem a few times myself, so it's pure self-preservation in the long run My approach above, as I figured out just a little too late, won't work out anyway, since it might not be original object that starts the recursion.
  14. That would only catch flat recursion though. The only way to catch deeper nesting I can think of would be to pass the starting object along. Something like this (untested): public function resetTrackChanges($trackChanges = true, $startingObj = null) { parent::resetTrackChanges($trackChanges); if(!$startingObj) $startingObj = $this; foreach($this->data as $key => $value) { if(is_object($value) && $value instanceof Wire && $value !== $startingObj) $value->resetTrackChanges($trackChanges, $startingObj); } return $this; } Of course, that method signature and logic might have to be implemented by all Wire derived classes that implement their own resetTrackChanges method. On second thought, that doesn't help either. You're spot on with keeping track of seen pages outside of recursion. On the other hand, multiple resetTrackChanges calls might happen in the same program run, so there needs to be a mechanism that cleans up the tracking list.
  15. You might find out more if you print out the names ($key) of all properties of type page and their value's (page) ids. There should be some kind of repeating pattern then that leads from subscriber to tester back to subscriber, but their might be (quite) some hops in between.
  16. You can use page.fieldname on the right hand side in your selector, so you need something like this: parent=/hotels/, template=hotel, hotel_country=page.destination_country, sort=title There's a discussion with a similar setup here:
  17. You can find the answer in this thread:
  18. I think your files shouldn't be compiled (or at least the compiled files not used) at all. Does moving the namespace declaration to the very first line of your php files change anything? How you specify the include files' paths might also be relevant if you use different approaches in your class files and templates.
  19. Have you tried adding /*NoCompile*/ to the require_once() inside Master_Order.class.php?
  20. That's what I'm thinking too. I'd like to add a few neat things though before I actively go for more spotlight on it on the web. Auto save is a neat feature but probably not wanted in all scenarios, so I want to make it optional, and another feature I definitely want to get "wired" in is lool's revision history. Currently, it's far too easy to overwrite a perfectly fine document with no way back.
  21. Update: LoolEditor now uses its own simple modal without a title bar since the editor's close button also closes the modal. Things feel a lot smoother now. I think PW is currently the only CMS that integrates LibreOffice for free
  22. Brilliant! I only now got a chance to reply, and you have already changed things around just the way I imagined. I'll take your module on a test drive in our intranet on Monday.
  23. I have only recently started to work on something similar, only streamlined for frontend editing, so kudos for tackling that topic I'm likely going to peek inside the code and steal a few pieces. The only nitpick I have is that the behavior of the replacement option might not be clear to end users. The field should probably be a little more verbose and tell the user that description and/or tags are replaced by those of the selected file, or they might assume it's the other way round. Perhaps a "Replace with" option would be even more intuitive (use the selected file and keep the rest as is). It's how I'd write it as a user story - "I have a file entry on the page with a description and tags and just want to replace the old file with a new one in that entry". Just playing devil's advocate here, as I'm thinking of my 50+ intranet editors who only update their pages a few times every year.
  24. ProcessWire supports that out of the box. See here for a getting started documentation.
  25. Yes, you'll probably have to hook before Pages::trash.
×
×
  • Create New...