Leaderboard
Popular Content
Showing content with the highest reputation on 05/10/2021 in all areas
-
You have an endless loop happening - you're hooking Pages::saved, and then saving the page inside the hook, which calls Pages::saved, which saves the page, etc. So you need some extra logic to exclude the page you are saving in the hook. In this case you can identify the page you want to exclude by checking if it is locked. if ($page->template == "invoice" && !$page->isLocked()) { //... Alternatively you can hook Pages::saveReady, then you don't need to worry about endless loops because you are hooking just before the page is about to be saved and therefore you don't need to save within the hook itself. $wire->addHookAfter("Pages::saveReady", function($event) { $page = $event->arguments(0); if ($page->template == "invoice") { // lock page if inv_status = paid (1034) or cancelled (1038) if ($page->inv_status == 1034 || $page->inv_status == 1038) { $page->addStatus("locked"); } } });5 points
-
v0.0.63 Thx to the feedback of @wbmnfktr I've made it a lot easier to get started with RockMigrations! The readme has now a dedicated quickstart section: https://github.com/BernhardBaumrock/RockMigrations#quickstart The example that was shipped with RockMigrations was also improved. I removed some complexity and used real world example names (a simple blog setup) instead of "foo" and "bar". This should make it a lot easier to understand ? Also I improved the page name replacements feature introduced lately: Page name replacements now ship with the module. They are saved in a dedicated folder and named "de.txt" for german replacements. If you need any other replacement options just let me know! (maybe @apeisa ? ) $rm->setPagenameReplacements("de"); https://github.com/BernhardBaumrock/RockMigrations/tree/master/replacements2 points
-
Latest version on github is v0.0.12. This fixes a number of bugs and also adds 2 new features: When a migration has been 'locked', so that it can no longer be changed/uninstalled etc., the 'preview' button is replaced with 'review'. The review shows all the changes made by the migration (on the assumption it was properly installed before locking); it is completely derived from the json files (which should be kept unchanged on the system) and therefore is completely independent of the current database state. BTW, the purpose of locking is to prevent inadvertant overwriting of other migrations if there is an overlapping scope (although warning messages are issued if this is a risk). Hopefully it is now (mostly) multi-language enabled. If anyone needs this and finds something is missing, let me know. Obviously you will need to add your own translations ? I've been using the module a fair bit and am pretty happy with it so far. It has been very useful when updating help pages (using @Macrura's excellent AdminHelp module) on the dev system - I can then release them as a consistent batch to the live system. I have also found that it is a good way of migrating language pages as it will migrate the language .json files automatically with the pages - all that's needed is a migration item with selector "template=language".1 point
-
v0.0.56 Today I had some troubles migrating field labels. Changes simply did not show up on the related page edit screen... turned out that some field setting overrides have been activated! Removing them via API is not that simple, so I added the feature to RM: ?1 point
-
Wow. This looks so cool. The creation of fields and templates via the admin might not be for everyone, but I think you can generate the migration file also by hand, right? A feature that has been requested multiple time, is that all changes that you do in the admin should be tracked and added to a migration. I like the basic idea behind it, and think of a hook, that gets triggered after creating a field/template, or making modifications to a field, which automatically or after confirmation modifies or adds a migration file. As you are also running a diff, you might create a migration automatically, to see what changes have been made to templates/fields/contents since the last migration. Then you would just choose which templates/fields/contents should be included in the migration. For example you added a new field, added it to two templates and created a new page with one of the templates. Now your module could run a "Get changes" command, that fetches all differences since the migration and asks which of them you want to integrate. With this behaviour you would not have to remember and "define the affected elements" as in your video. What you think about this approach? I am also happy to have a look at your code and try it out, because I think migrations is a major issue with ProcessWire right now. I am using @bernhards RockMigration atm, but also like your approach. Migrations should be an important part of the core IMHO.1 point
-
For those that like a screencast, I hope this helps (I've broken it down into logical steps): Install the module in your development environment (making sure you have FieldtypeRuntimeOnly installed first). Then open the "Database Migrations" setup page and refresh it. You will see that it has automatically installed a 'bootstrap' migration. Install.mp4 Create a new migration page to hold the scope definition of your new migration - just enter the basic details and save it at this stage. New_migration.mp4 Make the changes you want in the development environment (of course, you may have already done this ? ). We will add a new page and a couple of children. New_pages.mp4 Then a couple of fields (one a page ref with the new page as parent) and a template. Fields_template.mp4 Add a page using the new template. Snafu.mp4 Now go back to the migration page and define the affected elements. Use the preview to see the effect, then "export" the migration if you are happy. Export.mp4 The next step is to install the new migration in the target environment. Sync the code files (including the .json files created by the migration and any new images/files in assets/), install ProcessDbMigrate in the target if necessary and go to the setup page. You can preview the migration before installing it. Install_migration.mp4 If necessary, you can uninstall the migration (and the module), but the code files will remain. Uninstall.mp4 End of show!1 point
-
Great update - working with access control got a lot easier today ?? Access Control ProcessWire has a powerful access control system. When using RM to create new templates and pages it is quite likely that you also want to create roles and define access for those roles on the new templates. The basics of access control can easily be done via RM - for more advanced topics you might need to implement custom solutions. PRs welcome ? Let's say we created an Events calender and we wanted to store all events (tpl event) under one page in the page tree. This page (tpl events) would only allow pages of type event. To manage those events we create a new role on the system called events-manager. $rm->migrate([ 'templates' => [ 'events' => [...], 'event' => [...], ], 'roles' => [ 'events-manager' => [ 'permissions' => ['page-view', 'page-edit'], 'access' => [ 'events' => ['view', 'edit', 'add'], 'event' => ['view', 'edit', 'create'], ], ], ], ]); On more complex setups you can use the API functions that are used under the hood directly. For example sometimes I'm encapsulating parts of the migrations into separate methods to split complexity and keep things that belong together together: /** * Migrate all data-pages * @return void */ public function migrateDatapages() { $rm = $this->rm(); // migrate products (having two custom page classes) // these have their own migrations inside their classes' migrate() method // where we create fields and the template that the class uses $product = new Product(); $product->migrate(); $products = new Products(); $products->migrate(); $rm->setParentChild(Products::tpl, Product::tpl); $rm->setTemplateAccess(Products::tpl, self::role, ["view", "edit", "add"]); $rm->setTemplateAccess(Product::tpl, self::role, ["view", "edit", "create"]); // same goes for all other data pages // ... }1 point
-
The module gets better and better and I love working with it every day ? v0.0.42 has a nice little update to include scripts or styles in the PW backend easily. Why is that great? Because you can organize your files better and have everything in place while still having the ease of use (and you don't need to install any other modules for such simple tasks): Usage: I'm using custom page classes for EVERY page I have in my PW installs. One might think that this is overkill - but I'm wasting so much time on old projects looking for code snippets that are all over the project. Some in ready.php, some in init.php, another story are JavaScript snippets for small GUI tweaks... Not any more ? I have a custom PageClass "Foo" and there I have a method that modifies the page edit form (ProcessPageEdit::buildForm) - this is great for changing field properties like columnWidth or labels etc. on the fly without ever having to fire a migration. If I want to change something for my Foo pages, I head over to my IDE, type "Foo" and get directly to the Foo PageClass. But what about JavaScript? Today I needed a little snippet that populates some fields based on other fields. As easy as that: // in the buildForm hook $rm->addScript(__DIR__."/Foo.js"); Everything is well organized, because I have all my classes in a custom folder (inside a module, but the same would apply for the /site/classes folder): .../myModule/classes |-- Bar.php |-- Foo.js |-- Foo.php '-- Whatsoever.php And the JS file will only be loaded on the page edit screen to prevent overhead. Why not just use $config->scripts->add() you might ask? Good question ? $rm->addScript() will additionally add a cache busting timestamp to the file and it will only include the file if it exists on the system. It will also work on Windows systems, which you might forget to take into account if quickly adding it via $config->scripts->add() and last but not least it will also work on PW instances that are running in a subfolder ? if(!is_file($path)) return; $path = Paths::normalizeSeparators($path); $config = $this->wire->config; $url = str_replace($config->paths->root, $config->urls->root, $path); $m = $timestamp ? "?m=".filemtime($path) : ''; $this->wire->config->scripts->add($url.$m); Happy migrating ?1 point
-
Thx, that helped. The migrate() method was intended to create pages that do not exist in the system (eg pages for a blog). I've made the setPageData method public, so if you want to set page data of the root page, use setPageData instead of migrate(): v0.0.34: https://github.com/BernhardBaumrock/RockMigrations/commit/801ac7ff94edbb7b4e430791874746580d9951111 point
-
Personally I think it's best not to let editors choose font family or font size at all, lest your website ends up looking like a dog's breakfast. But to answer your question, you can use the Custom Config Options in the field settings: https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-font_names https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-fontSize_sizes1 point
-
I know this is a pretty old thread, but every time it comes to creating a Repeater through the API, I get LOST. @thetuningspoon's function illuminates a LOT of what happens behind the scenes when a new Repeater is made through the GUI - but I just keep wishing it was as simple as: $f = new FieldtypeRepeater(); $f->set('name', 'repeaterTest'); $f->add($repeaterField1); $f->add($repeaterField2); $f->save(); Because that isn't technically possible without setting the Fieldgroup or Template that will be used by the Repeater first, right? At the end of the day, I think we should improve the docs for Repeaters (https://processwire.com/api/fieldtypes/repeaters/) to include a section on creating a Repeater from scratch through the API so that this process is more easily understood. I am always referencing several Forum posts and parts of the docs in order to get through the spaghetti - having everything in one place would be great. Otherwise it would be awesome to have some functions as a part of the FieldtypeRepeater Class that cut down on the amount of API calls one needs to make in order to create one of these. Just my 2 cents.1 point