-
Posts
6,314 -
Joined
-
Last visited
-
Days Won
318
Everything posted by bernhard
-
RockMigrations1 - Easy migrations from dev/staging to live server
bernhard replied to bernhard's topic in Modules/Plugins
That's exactly how I'm developing PW now. Everything related to a pageClass is in the pageClass - even hooks. That's by default not possible because we have no init() or ready() in pageClasses. That's why there is the trigger method: https://github.com/BernhardBaumrock/RockMigrations/blob/88faf3f13844de3e4a8a4ae2968dc45535778659/RockMigrations.module.php#L346-L362 There's also loadClasses here https://github.com/BernhardBaumrock/RockMigrations/blob/88faf3f13844de3e4a8a4ae2968dc45535778659/RockMigrations.module.php#L1851-L1863 Unfortunately that's a little mess. That methods have been quick additions while finding the right way to do it. I didn't know how to use PW's classloader back then and I even didn't know about spl_autoload_register... But it does not matter too much to me right now as long as the pageClass's init() gets called on init() and ready() - if needed - on ready(). Think of it as an autoload pageClass. Not sure about the performance impact of that, but I guess it's minimal. The benefit is that I have everything in one file that belongs together. All hooks, all helper methods for markup output, whatever. No more hook chaos in ready.php, no more problems moving updates from dev to live and of course having all changes documented in GIT ? I guess your approach is a lot more common than mine... that's why migrations get a lot less attraction than they'd deserve in my opinion... -
RockMigrations1 - Easy migrations from dev/staging to live server
bernhard replied to bernhard's topic in Modules/Plugins
I have not had the time to read your post carefully and give an educated answer ? Why not define those changes directly in your code from the very first moment? I know that feels complicated and cumbersome, but you'll need the same things over and over again (mainly being "type", "columnWidth", "label", "tags") and you'll get used to that and in the end be at least as quick as doing it by clicking around the admin. In more complex scenarios you'll likely be even quicker (imagine changing the "columnWidth" of multiple fields to rearrange your setup... that means a lot of clicks... on the dev-setup and then a lot of clicks and brain work to replicate that on production; using code you can simply change all widths, save, refresh). Back to your first post... Yes, that's a good observation. The first approach was inspired by Lostkobrakai's module that has a concept of "one single truth/place for all migrations". I just wanted to make the syntax easier to grasp and use. I see the benefits of that approach. Even more because I have improved a lot as developer and I'm packing almost anything into modules or reusable components. On the other hand, that approach has a huge drawback: You end up with lots of migrations and you can't easily grasp what's going on in the big picture. My new approach is a lot more practical (though might be less technically "correct"): You put your setup into a dedicated migrate() method of your module that represents the state/setup of this module or pageClass. Then you see at one glance all fields, templates and pages that belong to that logical piece of your project and with a single modules refresh you get that setup on your system - and with a git push and refresh you also get that setup on your live system (or any other). There are rare cases where the execution order of migrations is important. But it turned out that this is really rare on the one hand and almost impossible across different logical parts (eg two different modules). And even if that happend... You have the same problem with regular PW modules or any other kind of software dependency issues... In 95% of the cases migrations are all about adding fields, creating pages that hold data, changing parameters (like labels). All that is really as easy as changing properties of the migrate([...]) options array. Sometimes you might realize that you've created a field that you don't need any more. Then I simply use this technique: // in one of your modules or page classes public function cleanup() { $this->rm()->deleteField('myoldfield'); } public function migrate() { $this->cleanup(); $this->rm()->migrate([ 'fields' => [ 'mynewfield1' => [...], 'mynewfield2' => [...], ], 'templates' => [...], ]); } public function rm() { return $this->wire->modules->get('RockMigrations'); } I even use class constands now instead of string values - that has a huge benefit that I get better readability in my code (syntax colors), it's impossible to make typo's and I get code completion wherever I am in my project: You see in this example: The properties that are needed are really easy: label --> just type a string icon --> just choose one of the fontawesome icon-names (I tend to look them up here https://fontawesome.com/v4.7.0/icons/ but I guess ther should also be a plugin for autocomplete?) collapsed state --> autocomplete again ? If I come up with a property that I don't know, I do that manually on that field, look up the property in tracy, apply the code to my module/pageClass, save it, refresh and check if everything works, commit and continue with my work ? PS: In the screenshots above you see a migration that was applied when the fields already existed in the system (I built that before I had the joy of RockMigrations). That's why some other properties are not defined (like type, tags,...). But it shows also how flexible and easy to apply RM can be. One might call it "progressive" ? Does that bring some light into the dark? -
I have not thought about the technical view, but I liked how your example really felt more "PW-ish" (like hooks) than my first approach. But I didn't like that it worked different to normal autoload modules... I came up with this idea that at least for my taste merges best of both worlds: <?php namespace ProcessWire; class FooModule extends WireData implements Module, ConfigurableModule { public static function getModuleInfo() { return [ 'title' => 'FooModule', 'version' => '0.0.1', 'summary' => 'Your module description', 'autoload' => true, 'singular' => true, 'icon' => 'smile-o', 'requires' => [], 'installs' => [], ]; } public function init() { $this->addRoute("/my/custom/{user}/endpoint/{action}", $this, "userEndpoint"); } public function userEndpoint($event) { // get parameters from route and sanitize them // not sure about the syntax? maybe $event->route->get('user', 'int'); $user = $event->api->get('user', 'int'); $action = $event->api->get('action', 'string'); $method = $event->api->method; if($method == 'GET') { // return found data as json $result = $this->wire->pages->findRaw([ 'template' => 'foo', 'user' => $user, ], ["title", "foo", "bar"]); return $this->api->json($result); } elseif($method == 'POST') { // update database // some kind of helper (https status codes etc) // would be nice, but I don't have much experience // with APIs so there might be others to talk to :) $user = $this->wire->users->get($user); $user->setAndSave('action', $action); return $this->api->success("Updated $user's action to $action"); } else { throw new Wire404Exception('Not allowed'); } } } or in init.php: $wire->addRoute("/my/custom/{user}/endpoint/{action}", function($event) { // get parameters from route and sanitize them // not sure about the syntax? maybe $event->route->get('user', 'int'); $user = $event->api->get('user', 'int'); $action = $event->api->get('action', 'string'); $method = $event->api->method; ... });
-
Membership app, Processwire limitations on unique records?
bernhard replied to Kiwi Chris's topic in General Support
I hope I don't bother anybody asking that over and over again ? Have you tried RockMigrations? -
I'd suggest the following: First, disable markup regions to confirm that it works when markup regions are disabled. Then enable markup regions and to this: // replace this include 'pdf.php'; // by that: echo "include PDF here"; Then load your page that should create the PDF and inspect the HTML (right click -> show sourcecode). What does the source code look like?
-
Funding ProcessWire / More community efforts
bernhard replied to pideluxe's topic in Wishlist & Roadmap
If done correctly I think that could be a great plus for ProcessWire! And I'd be happy to be part of such an association ? -
I've had this error sometimes and it was due to a broken pdf (don't know the reason). I don't understand why you want to use markup regions for rendering HTML of the pdf?? Are you trying to render a regular page HTML as PDF?? I don't think that's a good idea. In a regular HTML page you have lots of code that mPDF will at least not understand and in the worst case will break your pdf. So I'd recommend throwing custom HTML to mPDF instead of regular page markup. You'll have a lot more control over your pdf and a lot less troubles.
-
session: configurable module check failed when updating to 2.6.13
bernhard replied to bernhard's topic in General Support
Already reported ? -
And where do you want to store the resized images? I guess you don't want to always create them on the fly?! ?
-
Let's say I wanted to build a ticketing system... And I wanted to have common answers ready to be inserted into my answer to the ticket creator... Do we have solutions for that already? I have done that like this years ago: https://processwire.com/talk/topic/17207-custom-office-management-crmcontrolling-software/?do=findComment&comment=151471 But I thought something like https://processwire.com/talk/topic/18289-processmention-forum-mentions-style-page-link-autocomplete-for-ckeditor/ could be more convenient/versatile... Thx for your input PS: Actually I'm thinking if a solution NOT limited to ckeditor fields wouldn't be better. Why not add this functionality to any text input field you like?!
-
Page Hit Counter – Simple Page View Tracking
bernhard replied to David Karich's topic in Modules/Plugins
I've had a chat with ryan about exactly that topic lately! It seems he liked the idea, so I'll add your conversation to our chat and report back what he says ?- 111 replies
-
- 3
-
- hitcounter
- tracking
- (and 4 more)
-
This is what I wrote ryan lately: And that was his response: Now the topic came up here: https://processwire.com/talk/topic/20668-page-hit-counter-–-simple-page-view-tracking/?do=findComment&comment=211318 As this is getting offtopic in the pagehitcounter thread I suggest to continue discussion here @adrian @David Karich What do you think? Have you ever had the need for a custom endpoint in your projects? How did you solve it? Which issues did you have? Let's collect some examples so that ryan can see "more specifically what we are talking about" ?
-
Same here!
-
RockFinder3 - Combine the power of ProcessWire selectors and SQL
bernhard replied to bernhard's topic in Modules/Plugins
Template: YES, Field: NO It takes permissions from the very first page find operation (that is a $pages->findIDs) and then joins all raw data from the database to those page ids. -
Link to a Custom Admin Process Containing URL Parameters
bernhard replied to jor's topic in Module/Plugin Development
Untested: $wire->addHookAfter("ProcessLogin::getBeforeLoginVars", function(HookEvent $event) { $vars = $event->return; $foo = $this->wire->input->get('foo'); $bar = $this->wire->input->get('bar'); if($foo !== null) $vars['foo'] = $this->wire->sanitizer->text($foo); if($bar !== null) $vars['bar'] = $this->wire->sanitizer->text($bar); $event->return = $vars; }); Make sure to sanitize input properly! -
Link to a Custom Admin Process Containing URL Parameters
bernhard replied to jor's topic in Module/Plugin Development
Thx for pushing me to learn something new ? https://github.com/processwire/processwire/blob/d8945198f4a6a60dab23bd0462e8a6285369dcb9/wire/modules/Process/ProcessLogin/ProcessLogin.module#L848-L864 -
Link to a Custom Admin Process Containing URL Parameters
bernhard replied to jor's topic in Module/Plugin Development
Hallo Jor ? it depends on where/how the dynamic links are created. Eg. if they where created on page creation (eg of a ticket), then you could save the link as meta-data of that page and just provide the ID of that page in the link and then the redirect function could get the real URL from meta-data of that page again. -
Link to a Custom Admin Process Containing URL Parameters
bernhard replied to jor's topic in Module/Plugin Development
You need to create endpoints via ID-only parameters: public function executeRedirect() { $id = $this->wire->input->get('id', 'int'); $url = "/your/default/landingpage"; if($id===1) $url = '/foo/bar/?foo=foo&bar=bar'; elseif($id===2) $url = '/what/so/ever/?bar=foo&foo=bar'; return $this->wire->session->redirect($url); } Then send a link like /your/module/redirect/?id=2 Alternatively you can create one method - executeFoo() and executeBar() - for each endpoint, then you can link to /your/module/foo and /your/module/bar -
RockMigrations1 - Easy migrations from dev/staging to live server
bernhard replied to bernhard's topic in Modules/Plugins
v0.0.30: Working with select options fields got easier today ? $rm->migrate([ 'fields' => [ 'yourfield' => [ 'tags' => 'myTag', 'type' => 'options', 'inputfieldClass' => 'InputfieldRadios', 'optionColumns' => 1, // side by side 'options' => [ 1 => 'Eingangsrechnung', 2 => 'Ausgangsrechnung', ], 'required' => true, 'defaultValue' => 1, ], ], ]); Setting the "options" as array has not been possible until now. -
I've done that too complicated too many times ? $wire->addHookAfter("Pages::saveReady('template=foo,id=0')", function($event) { $event->arguments(0)->status = 1; }); Now create a new "foo" page and it will automatically be published (and also the "temp" status will be removed) ? I need that all the time for backend applications...
- 1 reply
-
- 6
-
how to make ProcessPageEdit-Form non editable for some roles?
bernhard replied to bernhard's topic in General Support
Should have known that 5 years ago ? -
Membership app, Processwire limitations on unique records?
bernhard replied to Kiwi Chris's topic in General Support
Thx @szabesz the problem is, that this will be called every time a page is loaded (I think?). But we want the init() to fire only once for all instances of Contact, so that all hooks only get added once and not multiple times. RockMigrations has a helper for that to trigger init/ready on a pageclass or even trigger it for all classes in a given folder. But I did not investigate a lot in that approach so if there are better solutions (maybe using PWs ClassLoader that I havent really worked with) I'm happy to hear them ? -
[solved] How to listen for pw-panel-closed ?
bernhard replied to bernhard's topic in General Support
It was indeed a typo!!! That explains why it worked in $(document).ready --> I fixed the typo by accident ? Thx @7Studio and happy that my tutorial helped. The pw backend is a great playground ? -
Edit: seems that it works when wrapping the code in $(document).ready(...) - can anybody explain why? Strange one... I have this in a custom JS file in the backend: $(document).on("pw-modal-closed", function(event, ui) { console.log('modal closed, do some magic'); }); console.log('loaded'); I load the page and get "loaded" in the console. I click on a link having class="pw-panel", the panel opens. I close the panel. Nothing in the console ? Any ideas? It should work IMHO: https://github.com/processwire/processwire/blob/d8945198f4a6a60dab23bd0462e8a6285369dcb9/wire/modules/Jquery/JqueryUI/modal.js#L43