Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 06/15/2023 in all areas

  1. If you have the core ProcessPageClone module installed you can copy a page via Page List: But sometimes I don't want to hunt around through Page List to find the page I want to copy, and instead I have found the page via the admin search and have it open in Page Edit. So I used this hook in /site/ready.php to add a "Clone this page" button to the bottom of the Settings tab. // Add a clone button to the Settings tab of Page Edit if this page is allowed to be cloned $wire->addHookAfter('ProcessPageEdit::buildFormSettings', function(HookEvent $event) { $wrapper = $event->return; $modules = $event->wire()->modules; $page = $event->process->getPage(); /** @var ProcessPageClone $ppc */ $ppc = $modules->get('ProcessPageClone'); if($page && $ppc->hasPermission($page)) { /** @var InputfieldButton $f */ $f = $modules->get('InputfieldButton'); $f->value = 'Clone this page'; $f->href = $event->wire()->config->urls->admin . 'page/clone/?id=' . $page->id; $wrapper->add($f); } }); Maybe somebody else has this need and finds this useful.
    2 points
  2. This is what I am using: $this->wire->addHookAfter('ProcessPageEdit::getSubmitActions', function($event) { $page = $event->process->getPage(); if($page->template != "foo") return; $actions = $event->return; unset($actions['next']); $actions['clone'] = [ 'value' => 'clone', 'icon' => 'clone', 'label' => 'Save + create copy', ]; $event->return = $actions; }); $this->wire->addHookAfter('ProcessPageEdit::processSubmitAction', function($event) { $action = $event->arguments(0); // action name, i.e. 'hello' $page = $event->process->getPage(); // Page that was edited/saved if($page->template != 'foo') return; if($action === 'clone') { $copy = $this->wire->pages->clone($page); $copy->title .= ' (copy ' . uniqid() . ')'; $copy->save(); $this->wire->session->redirect($copy->editUrl); } });
    2 points
  3. Also, I want to open the page in Page Edit after it is cloned. Here is a hook for that: // Edit the cloned page after it is created $wire->addHookBefore('ProcessPageClone::execute', function(HookEvent $event) { $event->wire()->addHookBefore('Session::redirect', function(HookEvent $event) { $url = $event->arguments(0); $id = (int) filter_var($url, FILTER_SANITIZE_NUMBER_INT); $redirect_url = $event->wire()->config->urls->admin . 'page/edit/?id=' . $id; $event->arguments(0, $redirect_url); }); });
    2 points
  4. Hey @Cybermano what exactly are you trying to do? If you only want to make the clone unpublished you can add this line before $copy->save(): $copy->addStatus(Page::statusUnpublished); I've some questions and suggestions for improvements on your code (assuming that the only difference to my old post is that the cloned page should be unpublished): Why do you set $page to unpublished during clone and then restore the previous state? That's 2x unnecessary page saves. You are using setAndSave for name + title, but you save() the $copy later anyhow. That means you produce 3 save operations instead of one. Just use $copy->set('name', ...) and same for title and changes will be stored on save() You are using setStatus(). It should be fine but I think it's better to use addStatus() in general unless you really want to force a single status. For example pages can have a "corrupted" status and that will be removed on setStatus() but will be kept when using addStatus() - please anybody correct me if I'm wrong ?
    1 point
  5. OK. I will re-enable this in a future Padloper version. Meanwhile, I'll send you a PM with a suggestion for an interim solution. Thanks.
    1 point
  6. Thanks for your replies, dear people! I am going to take a look at the suggested JS libraries / frameworks and see what's most suitable for the application. Your descriptions of Alpine and htmx's features were very helpful. It sounds like Alpine would be something I could learn quite easily, but htmx's SEO advantage might be something I end up liking very much. One last question though: do module developers usually supply the JS code with the module, or do module devs tend to lean on a CDN? Performance and footprint is less important to me, but I like the idea of having the module work "out of the box" without requiring code from a CDN, and offering alternate solutions for client who want custom designs for everything.
    1 point
  7. Process modules as per @bernhard’s post are the main tool. If you don’t feel confident with that (and do have a try, it’s not that hard) then I suggest you avoid a custom solution. I really like HTMX for that. There are quite a few forum posts about it.
    1 point
  8. You don't need composer for RockForms. But if you are building some intranet-like app as @dotnetic mentioned the most efficient way is to stay in the PW backend. To understand the backend better you can read my blog post here: https://processwire.com/talk/topic/17709-how-to-create-custom-admin-pages-aka-processmodules-yes-its-that-simple/ But creating a complex app with lots of calculations is not an easy task - so if composer is out of your league I'm not sure if it's a good idea to take over such a project. Maybe it's better to build on an existing solution as @Jim Bailie mentioned. But that's of course your decision ? Just wanted to mention that you can achieve anything you want with PW and with the PW backend, but it's definitely more complex than using composer. And your comment about PW needing a page title does not sound like you know a lot about hooks or the inner workings of PW. It's of course your decision, just be aware that if you price it with a flat rate then you might end up with a lot more work than you'd expect ?
    1 point
  9. Are we talking about the page with ID 2 in which you changed the name/URL? It might throw you out of the backend but accessing the new name/url should end in the regular ProcessWire backend as usual. Just tried it and all links are working. Maybe clearing all compiled files or deleting local cookies might help in your case.
    1 point
  10. You can also build the whole application in the admin and have all of ProcessWire´s form validation and possibilities there, like dependend showing and hiding of form fields. I have built several projects for example a job application management system. room management. E-Commerce site with management from order to production inside of the admin. Some of my edit pages even have AJAX calculation fields in them. PDF and chart generation is another thing. I use the edit form of pages to manage different stuff. I also use CustomPageClasses to modify the forms inside of the admin. It depends, if the forms should be customer facing (to the public) or are they just for your client?
    1 point
  11. I've built a commercial module RockForms that can be of huge help here. It uses https://doc.nette.org/en/forms which is the only library on earth that I know where you define all rules from within PHP and get the same exact validation rules also on the client side for live validation. You have tons of options regarding validation and you can even create nested validation rules: https://doc.nette.org/en/forms/validation The drawback of using Nette Forms is that it makes it very hard to customise the created markup of your forms to your needs. That's where RockForms jumps in. Also it integrates everything very well with PW and creates pages from submitted forms, provides hookable methods to do custom stuff at custom events and handles redirects to prevent double form submissions etc.; Basically it handles all the tedious things for you that you'd have to think of upfront or that you have to fix later if you didn't think of them ? A simple form could look like this: // create form with a unique name $form = new RockForm("demo"); // field setup $form ->addText("forename", "Enter your first name") ->setRequired("We need your first name to show it!"); $form ->addText("surname", "Enter your given name"); $form ->addSubmit("submit", "Submit your name"); // render output if ($form->showSuccess($values)) { $name = $values->forename; if($values->surname) $name .= " " . $values->surname; echo "<strong>Thank you for submitting the form, $name!</strong>"; } else { echo $form->render(); } Or for more complex forms you can define everything in OOP style. Extensive docs are in the works and provide live examples that you can play around with: https://www.baumrock.com/modules/rockforms/docs/ Compared to FormBuilder the module does not (yet) have a UI to build forms. That's done in code, but it seems that this is what you want anyhow?! Single Site License will be 49€ - if you are interested write me a PM ?
    1 point
  12. Another follow-up video: Is anyone here using ProcessWire with React, Vue, Svelte or any other JS framework?
    1 point
  13. Hello everyone! Recently I wrote these scripts for TracyDebugger console in order to make work with RepeaterMatrix easier and faster. I want to present them to the community. Show relationship between all types, names and labels. $repeaterMatrixModule = $modules->get('FieldtypeRepeaterMatrix'); $fieldName = 'content_blocks'; $repeaterMatrixField = $fields->get($fieldName); $typesArray = []; foreach($repeaterMatrixModule->getMatrixTypes() as $matrixName => $matrixType) { $typesArray[$matrixName] = $matrixType . ' ' . $repeaterMatrixModule->getMatrixTypeLabel($matrixType, $repeaterMatrixField); } db($typesArray); Show all pages which have specific type in field (repeater_matrix) with this name: $repeaterMatrixModule = $modules->get('FieldtypeRepeaterMatrix'); $typeName = 'block_text'; $fieldName = 'content_blocks'; $repeaterMatrixField = $fields->get($fieldName); $typeId = $repeaterMatrixModule->getMatrixTypeByName($typeName, $repeaterMatrixField); $typeLabel = $repeaterMatrixModule->getMatrixTypeLabel($typeId, $repeaterMatrixField); $pagesWithType = $pages->find("{$fieldName}.type={$typeName}"); db($pagesWithType); db($typeLabel, 'Name of type'); This list can be continued as soon as I'll invent more scripts.
    1 point
  14. Thanks for sharing. Your 2nd example can also be written like this $fieldName = 'content_product'; $typeName = 'product_downloads'; $pagesWithType = $pages->find("{$fieldName}.type={$typeName}"); db($pagesWithType); No need for looping through all pages. find() accepts the subselector .type. Only drawback with my solution: you don't get the label for the type. Actually when trying your example, $typeId returned false and $typeName returned null $repeaterMatrix = $modules->get('FieldtypeRepeaterMatrix'); $typeId = $repeaterMatrix->getMatrixTypeByName('product_downloads'); db($typeId, '$typeId'); // returns false $typeName = $repeaterMatrix->getMatrixTypeLabel($typeId); db($typeName, '$typeName'); // returns null Which version of Repeater Matrix are you using?
    1 point
×
×
  • Create New...