Jump to content

bernhard

Members
  • Posts

    6,674
  • Joined

  • Last visited

  • Days Won

    367

Everything posted by bernhard

  1. Memo to myself and mybe to safe someone else from losing hours trying to understand why a multi-language Inputfield does not render() as expected... Learnings: 1) Inputfield::render() is only hookable for single-language Inputfields! When PW renders a multi-language Inputfield the LanguageSupport module adds a hook that fires after the original Inputfield::render(). This hook calls the render() method for each language and to avoid circular references it does that directly on $inputfield->___render() and not $inputfield->render(): https://github.com/processwire/processwire/blob/51629cdd5f381d3881133baf83e1bd2d9306f867/wire/modules/LanguageSupport/LanguageSupport.module#L445-L453 2) When building a custom Inputfield that supports a multi-language setup it is critical that its render() method is defined with 3 underscores! Otherwise the LanguageSupport hook that adds the markup for the other languages' fields would not fire.
  2. Thank you @ryan this is an awesome update! Really looking forward to replacing lots of hook-chaos by well organized and easy to maintain PageClasses ? ? So far, so ??? BUT: I've put together this quick testing module: <?php namespace ProcessWire; /** * Custom page classes for ProcessWire * * @author Bernhard Baumrock, 07.03.2020 * @license Licensed under MIT * @link https://www.baumrock.com */ class RockPageClasses extends WireData implements Module { public static function getModuleInfo() { return [ 'title' => 'RockPageClasses', 'version' => '0.0.1', 'summary' => 'Custom page classes for ProcessWire', 'autoload' => true, 'singular' => true, 'icon' => 'bolt', 'requires' => [ 'ProcessWire>=3.0.152', // custom page classes update ], 'installs' => [], ]; } public function init() { $this->classLoader->addSuffix('Page', __DIR__ . '/PageClasses/'); $file = $this->classLoader->findClassFile("HomePage"); bd($file); } } Now I deleted the file in /site/classes/HomePage.php and added it to /site/modules/RockPageClasses/PageClasses/HomePage.php and this is the result: Strangely, the file is found but not loaded for the HOME template! Any ideas? I think 95% of my custom classes will live in a folder inside /site/modules ? PS: This is the HomePage class:
  3. Just had to look something up in the Tracy Docs and found their donation button ? So if anybody wants to thank the guys behind Tracy, here's the link: https://nette.org/en/make-donation?to=tracy Can't thank you enough (Adrian and the guys from Nette) for this awesome tool!
  4. Anybody ever had horizontal scrollbars in the PW admin? It's a known issue and I've just pushed a fix for it to the PwQuickFixes module: https://github.com/BernhardBaumrock/PwQuickFixes/commit/4db6b4659692e3888a20ea89752fdce40d4425fe Before: After:
  5. Just wanted to share another use case for $files->url() and $files->path() // old version function mirrorFilesfromLiveServer(HookEvent $event) { $config = $this->wire('config'); $file = $event->return; if ($event->method == 'url') { // convert url to disk path $file = $config->paths->root . substr($file, strlen($config->urls->root)); } if(!is_file($file)) return; This example is taken from this recent post by @gebeer and it would be a lot better to read and maintain with the new methods: // new version function mirrorFilesfromLiveServer(HookEvent $event) { $file = $this->wire('files')->path($event->return); if(!is_file($file) return; In the old version he gets the filename from the $event. He then has to check for the $event->method, because in one case the file is a PATH and in the other it is a URL. That's why he has to modify $file if the method is "url"... And then he does what many of us do in such situations: Use string operations. They are not only ugly but also error prone: Think of different directory separators, missing or doubled slashes (eg /foo/bar//myfile.js or /foo/barmyfile.js). This was all not necessary if we had $files->path() and $files->url() ? See the second example. In one single $files->path() call all the complicated code from example 1 is obsolete. $files->path() returns the path of the file, no matter if it was provided as url or path. So simple, so beautiful.
  6. @porl could you please try if the fork linked above resolves your problem? It has a very active commit log and 72 contributors so that should be a solid choice.
  7. Hi @ryan thank you very much - that will be a tiny but very helpful addition! ? You might be right about it belonging to files instead of config - I really don't care about that. One thing that might be helpful would be a second parameter wheter it should return a trailing slash or not: $less = __DIR__ . "/my/great/file.less"; if(is_file($less)) echo $files->url($less); // /site/templates/my/great/file.less $dir = __DIR__ . "/blocks"; // see comment 2 $blocks = ['file1.php', 'file2.php', 'file3.php']; foreach($blocks as $block) { $file = $files->path($dir, true).$block; // see comment 1 if(!is_file($file)) continue; echo "<link rel='stylesheet' href='{$files->url($file)}'>"; } // comment 1 // see how that is better compared to something like this: $file = "$dir/$block"; // this could fail when $dir is dynamic (eg user input from module config) $file = rtrim($dir, "/")."/".$block; // better, but tedious // and finally, what if somebody used DIRECTORY_SEPARATOR --> it could fail on windows because of the backslash Comment 2: This could also be a relative path, eg $dir = "blocks" (being the blocks folder of the current module). Checking for is_file() can then become tedious as you might have to add $config->paths->whatsoever. $files->path($dir, true) would make sure to return the path with a trailing slash. Or maybe it would be better if the trailing slash was returned by default? I'd really vote for $files->url(...) and $files->path(...) instead of diskPathToUrl/urlToDiskPath; I know one should not be too short in variable/method names, but we already have the equivalents $config->paths and $config->urls that do the same, so I think this would be perfectly reasonable. ? And yes, I think you are right about it being a file tool, therefore we'd better use $files->url(...) instead of $config->url(...) ? Really looking forward to that, thank you again! ---------- Regarding my datetime request: Please disregard this one. First, I didn't know about the WireDateTime at all (Sorry!) and second, the reason why I didn't like PHP's features was that it doesn't provide a nice and easy to understand API. But that's solved when using carbon and that can perfectly be built into a 3rd party module (not bloating the core).
  8. @Gadgetto has fixed it - it also works for me now ? Thx @Jens Martsch - dotnetic
  9. Hi @porl sorry for the delay! It's this one: https://github.com/oyejorge/less.php I see that the repository is archived/read-only. Maybe you want to fork it and I can include the fixed version? Or we can take one of the 186 available forks ? https://github.com/oyejorge/less.php/network/members; maybe https://github.com/wikimedia/less.php ?
  10. Could any of the Windows users please confirm that the installation shows the following error? I think @dragan and @Jens Martsch - dotnetic ?
  11. Hi Ryan, thx for the comments on the Datetime topic. Do you also have some words on $config->urls($path) and $config->paths($url) ?
  12. @d'Hinnisdaël mentioned in the recent new post that there's a library called "carbon" for managing date/times. I've put together a module to include that library into PW for quick testing if anybody is interested: https://github.com/BernhardBaumrock/RockCarbon Using this library handling timezones should be quite straightforward. Dates in the DB could be stored in UTC format and displayed based on the users/systems timezone:
  13. Wow! Well, I just didn't know anything about https://carbon.nesbot.com/ ? Looks like I have to refactor my module once more ? Thx for bringing that to my attention! Difference so far: RockDatetime 19.97KB, Carbon 2.42MB ? Edit2: Just found this: https://try-carbon.herokuapp.com/ Edit: I've put together a quick helper module that loads Carbon into ProcessWire so everybody interested can give it a quick shot eg in the Tracy Console: https://github.com/BernhardBaumrock/RockCarbon
  14. Interesting ? Yeah editUrl() is not hookable! Based on Zekas suggestion maybe something like this: $wire->addHook("Page::_editUrl", function(HookEvent $event) { $page = $event->object; switch($page->template) { case "home": $event->return = $this->pages->get(2)->url."my/custom/edit?id=$page"; break; default: $event->return = $page->editUrl(); } });
  15. v0.0.2: Just added all LESS files in /site/assets/RockSkinUikit to the files to monitor for changes. That means you can have a custom.less file in that folder and you'll get instant LESS support for the whole PW admin ? v0.0.3: I've changed the LESS variable prefix from @tm- to @rs- because I'm using @tm- for my frontend themes and RockLESS was mixing up some variables...
  16. Hey @ryan this sounds great ? Could you please have a look at https://github.com/BernhardBaumrock/RockDatetime and see if that might be something that find its way into the core? I think some solid date and time handling API would be a great addition to PW! RockDatetime was developed because I need it for a new module that I'm working on for dealing with date ranges. See this recent post from today about the latest additions: I'm especially talking about this post: https://processwire.com/talk/topic/23097-previewdiscussion-rockdaterange-fieldtype-inputfield-to-easily-pick-daterange-or-timerange/?do=findComment&comment=198191 It's neither well tested nore complete. But feel free to copy/paste/improve as much as you want ? I think having an API for dates and times would be a very logical addition to the PW API awesomeness ? I'm talking about things like this: // calculating FROM/TO for RockDaterange case 'hour': $from = new RockDatetime("{$obj->date} {$obj->time}:00:00"); if($isTo) $to = $from; else $to = $from->copy()->move("+1 hour"); break; // check if FROM starts at 00:00 on that day if($this->from->equals($this->from->firstOfDay()) ... // show modified date when different from created day $updated = new RockDatetime($page->getUnformatted("modified")); $date = "Zuletzt aktualisiert am ".$updated->format("%d.%m.%Y"); if($updated->sameDay($page->getUnformatted("created"))) $date = ""; // formatting $d = new RockDatetime("25.02.2020 14:00"); echo $d->format(); // 25.02.2020 14:00 echo $d->format("%A, %d.%m.%y (%H:%M Uhr)"); // Dienstag, 25.02.20 (14:00 Uhr) echo $d->format(['time' => "%H|%M|%S"]); // 25.02.2020 14|30|00 On a side note I want to ask you if you please could consider to have a look at this request: https://github.com/processwire/processwire-requests/issues/326 I'm struggling on almost all my module development with proper file path and url handling and I'm doing the implementations over and over again because I don't want to add a module dependency for that. This little thing should really be in the core! We've had some problems with windows/unix file path handling recently and it shows again how important it is to have the right tools at our hands without implementing those things on our own: PS: As I've started to build my first "real" Fieldtype module with custom DB schema I want to say thank you for that awesome piece of software that you've developed here! Unfortunately there are no docs about that and the Events Fieldtype was at least for me not of much help, because it's hard to know where to start and what to add where and at what point of time to make everything work together. But once you get how it works it is really brilliant! I hope I can write a blog post about that some day if there's interest in that. So far I'd just want to express my appreciation ?
  17. RockDatetime is not an Inputfield. It is just a PW module that returns a RockDatetime object you can use for whatever you want. You could use the core InputfieldDatetime though and turn it into a RockDatetime like this: $d = new RockDatetime($page->getUnformatted('datefield')); echo $d->format(); Range input/output is not part of RockDatetime!
  18. It would be very easy to create a RockDatetime field based on the core Datetime field but waking up having a RockDatetime object instead of a timestamp. Maybe you want to experiment with that and create a PR?
  19. THX! Nothing to be sorry about! Was just a suggestion for an improvement ? This looks like a fantastic module. I'm testing ?
  20. I've put huge amounts of work into that module in the last few days. I had to take two steps back to take the next step forward: It turned out, that I needed a more robust and flexible setup when dealing with date ranges. And what I did is - thinking about it now - quite obvious: A RockDaterange now consists of two RockDatetimes. I've put a lot of effort into developing the RockDatetime module. It is already available on Github and has lots of examples and docs in the readme: https://github.com/BernhardBaumrock/RockDatetime Highlights: // calculating FROM/TO for RockDaterange case 'hour': $from = new RockDatetime("{$obj->date} {$obj->time}:00:00"); if($isTo) $to = $from; else $to = $from->copy()->move("+1 hour"); break; // check if FROM starts at 00:00 on that day if($this->from->equals($this->from->firstOfDay()) ... // formatting $d = new RockDatetime("25.02.2020 14:00"); echo $d->format(); // 25.02.2020 14:00 echo $d->format("%A, %d.%m.%y (%H:%M Uhr)"); // Dienstag, 25.02.20 (14:00 Uhr) echo $d->format(['time' => "%H|%M|%S"]); // 25.02.2020 14|30|00 I've also totally rebuilt the date parsing engine! Finding pages using the API $tpl = "template=event"; $pages->find("$tpl,range=2020"); // find all events in 2020 $pages->find("$tpl,range=2020-02"); // find all events in Feb 2020 $pages->find("$tpl,range=2020-02-26"); // find all events on 26. Feb 2020 // other possible selectors $pages->find("$tpl,range=2020-02-10 - 2020-02-20"); $pages->find("$tpl,range=2020-02-10 7:30 - 17:30"); $pages->find("$tpl,range=2020-02-10 7 - 9"); $pages->find("$tpl,range=2020-02-10 12:00 - 2020-02-20 18:00"); // find events in Feb 2020 sorted by range duration $pages->find("$tpl,range=2020-02, sort=-range.duration"); Creating pages using the API $p = new Page(); $p->setAndSave("range", "2020"); // from = 2020-01-01 00:00:00 // _to = 2020-12-31 23:59:59 // to = 2021-01-01 00:00:00 $p->setAndSave("range", "2020-12-24 16:00 - 18:00"); // from = 2020-12-24 16:00:00 // _to = 2020-12-24 17:59:59 // to = 2020-12-24 18:00:00 Formatting in action: // left column echo $range->format(['date' => "%A, %d.%m.%Y", 'time' => '']); // right column echo $range->format(['date' => "%a, %d.%m.%Y"]); Note that the last date does NOT show "07.03.2020 09:00 - 07.03.2020 12:00" - since the event ends on the same day as it starts we don't show that date again. RockDaterange will take care of all those tedious details!
  21. True. At least we got Migrations and RockMigrations now. Why not? Does that feel more like a router? $this->addHookBefore('ProcessPageView::pageNotFound', function($event) { $url = $event->arguments(1); // ensure trailing slashes? if($url[-1] !== "/") $this->session->redirect("$url/"); // prevent pageNotFound to fire $event->replace = true; switch($url) { case: '/my/route1/': return $this->route1(); case: '/my/route2/': return $this->route2(); default: $event->replace = false; } });
  22. I think this is hard to say when we don't know the exact setup. I could think of these options: Prevent uninstall (as you said). Convert the fieldtype (as you said). Move the dependencies out of SnipWire into the Fieldtype. This means SnipWire could not live without the Fieldtype but the Fieldtype could live without SnipWire. Move the helper functions in a separate module that both SnipWire and the Fieldtype can use as a dependency. Maybe static methods are an option? https://www.php.net/manual/en/language.oop5.static.php Though I think you can't access the $wire object in static methods, so that might not be the easiest option, because you can't use all of PW's internal tools.
  23. Ok, thx! So why is that field in the example file? For me as an enduser the experience was: "Oh, wow, that even supports image fields! Let's try it! [uploading] Hm... Doesn't work - maybe another thing that isn't working on Windows due to path issues?" ? PS: When are you planning to merge NEXT into MASTER?
  24. @ukyo showed me this awesome uikit pagebuilder for wordpress: https://demo.yootheme.com/themes/wordpress/2019/balou/wp-admin/customize.php This link might also be interesting for you @Jonathan Lahijani
  25. Finally ? Thank you! Should the images field from the example Dive be working? When I upload an image the field seems to work but when the upload is done, the field resets itself. All other field data is saved correctly. Any ideas?
×
×
  • Create New...