Jump to content

Marc

Members
  • Posts

    103
  • Joined

  • Last visited

Posts posted by Marc

  1. On 7/19/2022 at 3:47 PM, bernhard said:

    How would that concept work with multiple languages?

    I haven't given that any thought but I guess it would not be pretty. You'd have to maintain the layout for all languages. You can go to the source tab of the editor and copy/paste it to the other languages so you could take it from there.

  2. I like repeaters for structuring data. For building a layout, not so much. I've seen the demo's on this forum of people using repeaters in creative ways to build a layout, but it never looks very intuitive to me. I've grown to dislike this approach so I've been looking at other content management systems for inspiration. Bolt CMS uses Article Editor, which is a nice (paid) javascript solution that's basically an advanced wysiwyg editor with support for grids and other nice features. I decided to integrate this into Processwire as an inputfield. Here's a demo:

    I created a few plugins for Article Editor that take care of uploaded images, inserting links and Hanna code support for adding dynamic bits to the editor. And the field also works in repeaters. You can pass your CSS to the editor so that the editor preview should look identical to the real page. I am using Bootstrap.

    A bonus of building a page this way is that the whole layout is stored in a single field so there should be fewer requests to the database compared to repeaters.

    Please note that since Article Editor is not free, you need a license to use it.

    I've been working on this module on and off for a while. There are refinements to be made, like perhaps loading the Hanna code previews dynamically (they are currently inserted into the editor after saving the page). Not sure if it would be good enough to release publicly but I thought I'd share it anyway because I'd like to hear if you think this is a nice approach :)

    • Like 19
  3. So the problem is that PW refuses to generate links for localhost:8080? If I add two domains to $config->httpHosts then depending on which domain I open the site on, the backend will generate the correct links. Have you tried setting up the webpack development server with a custom domain on port 80? Like mysite.webpack.ddev.site?

  4. I have played around just a little with Aimeos for Symfony. It is very fast. I have not looked at their API's, but it looks like you can use a JSON API to fetch products on your PW front end and manipulate a basket as well.  It looks like there is an admin API as well for manipulating products, but not orders (maybe I overlooked it). So I think you will end up working in the Processwire CMS for all your regular content and work in the Aimeos backend for everything sales related. Which may or may not be acceptable to you. The benefit is that for the e-commerce side, you have something dedicated and more robust than a pure PW solution.

    Have you looked it Sylius? It is build from the ground up to be extended and modified. Based on Symfony. I have installed and modified it and it looks like a superb e-commerce package to me. It will not be 'easy' to integrate these solutions with PW, however.

    There is also Shopware. This has a beautiful backend plus it comes with pretty solid content management from what I can tell, so you may not even need Processwire.

    I hope this helps a little. Having worked with Padloper for a few extensive e-commerce projects, I would not use it again unless the shop is very basic. So I share your urge to plugin a dedicated e-commerce solution, but it may not make sense.

    • Like 1
  5. 16 hours ago, bernhard said:

    Does it work in the backend? Do you have the latest version (git pull)? It looks like $RockFinder2 api variable is not available for you, but it should (the module is autoload).

    You are correct, RockFinder2 was not available. I installed the module and ignored the TracyDebugger dependency warning. Since it DID successfully install ProcessRockFinder2, I assumed everything was alright. Anyway, I installed the debugger and reinstalled RockFinder2 and now it's up and running. Silly mistake on my part and sorry for bothering you about this!

    I got your example of including the template name working, thanks for your help! I hope you won't mind if I ask you another question. The docs for RockFinder2 briefly mention repeaters, and state that columns musts be defined manually. What exactly do you mean by this? Could you provide an example? With RockFinder1 you can do $finder->addField("repeatername", ["fieldname"]) but this is no longer the case with RockFinder2.

  6. I would like to try this out so I have just downloaded RockFinder2 from github, however even the simplest test won't work for me:

    $rf = new RockFinder2();
    $rf->find("parent=1");
    $rf->addColumns(["title"]);

    Using this on the front end, it generates the error "Uncaught Error: Call to a member function __invoke() on null in /site/modules/RockFinder2/RockFinder2.module.php:746". Also getting this notice: "Trying to get property of non-object in /site/modules/RockFinder2/RockFinder2.module.php on line 801"

    RockFinder1 is working properly.

  7. Is there an efficient way to get the template name or at least the template ID in the RockFinder results? I'm doing a query for all children of a particular page and those children can have different templates and I need to know which template each page has.

    Excellent module btw ?

  8. On 3/29/2019 at 8:32 PM, adrian said:

    I am surprised Enpass (https://www.enpass.io/) hasn't come up - does everyone know something I don't about it ?

    This has been my manager of choice but sadly no longer. Since I put LineageOs on my Android phone (without the Google Play Store) it is impossible to activicate my registered copy of Enpass. I bet you did not know this ? I moved to Bitwarden as a result.

    • Like 1
  9. I want to have a custom page under Settings in the admin that shows a PageTable field. I have it setup as follows:

    • Created a Process module that installs a page under /admin/settings. This page has the admin template and points to my module's process.
    • A page that has a template which holds the PageTable field. This page holds the children of the PageTable.
    • The execute function of the module renders a form that gets the inputfields from the page I mentionend above.

    When I execute the module, a form is successfully rendered with the PageTable field. It looks like this:

    pw-pagetable-1.JPG.0fac4a0d4183eac2d1575317af4f6dfe.JPG

    However, after pressing 'Add New' and saving a new item, the form reloads and I see this:

    pw-pagetable-2.JPG.5f7e99f240931ae024744ff179bb558d.JPG

    The new item is saved but not listed in the field. I also tried this with a repeater field, which has a similar defect. Other types of fields like a text field work fine. When I add the PageTable field to the template of a regular page and edit that page, it works as expected. Only when accessing the field through my Process module's page it does not work correctly. I'm sure there's a fix for this. I think the form does not know what page to link the PageTable entries to perhaps?

  10. 16 minutes ago, LostKobrakai said:

    This is an infinite loop you're causing. You hook after the render of a field named a specific name and in the hook you render another field of the same name, which again triggers your hook to replace and so on. You'd either need to find a hook, which won't be triggered again by what you're doing inside the hook execution (like @Martijn Geerts tried) or you need to find a way to differenciate the first call to your hook from the ones triggered by your code within the hook.

    Thank you for helping me understand this. Now I managed to get it working! I give my replacement field an exta attribute called 'replaced' and the hook is only allowed to do its job if the field does not have that extra attribute. Like this:

    wire()->addHookAfter('Inputfield::render', function($event) {
        if (wire('page')->template != "account") return;
    
        $inputfield = $event->object;
    
        if ($inputfield->attr('name') == "profile_pad_countrycode" && $inputfield->attr('replaced') != "yes") {
            $replacement = $this->modules->get('InputfieldSelect');
            $replacement->label = 'Land code';
            $replacement->attr('name', 'profile_pad_countrycode');
            $replacement->attr('class', 'uk-select');
            $replacement->attr('replaced', 'yes'); // This is essential to prevent a loop. Check for this value when the hook starts.
            $optionsArray = ['test'];
            $replacement->addOptions($optionsArray);
            $event->return = $replacement->render();
        }
    }); 
  11. 17 hours ago, dragan said:

    What's the idea behind it? I don't think that's possible, and certainly not when you're using two completely different types of input fields... perhaps text/textarea might work, but I think it's just a dangerous / adventurous idea...

    The original text field that I want to replace belongs to a third party module. Rather than changing the field properties of that module, I thought I'd tailor that particular field to my needs with a hook.

    I agree this might be a bit dangerous and perhaps I'll end up just changing the module, but it's a fun experiment nonetheless.

     

    14 hours ago, Martijn Geerts said:
    
    // Could you test this???
    wire()->addHookAfter('Field::getInputfield', function (HookEvent $event) {
    	$event->return->inputfield = 'InputfieldSelect';
    });

     

    I gave this a try. It doesn't appear to have any effect. I should use this in addition to my own hook, right? Is this hook supposed to prepare PW for the change in field type?

     

    I did some more testing and even when I try to replace the text field with a new text field (so same field type), it only works as long as the name of the replacement field is not the same as the original (but then you can't save new values using the new field to the old field). When a form gets rendered and it has the replacement field with the same name as the original field, the server hangs and I'll get this fatal error:

    Fatal error: Allowed memory size of 268435456 bytes exhausted

    So at this point I'll rephrase my question: can I replace a field with a new field of the same type and the same name using a hook? Once I get that working, I'll see if I can use a replacement field of another type.

  12. I have a form (outside of the admin) that shows a text field. I want to replace this field with a select field during rendering. The problem is, when I name the replacement field the same as the original, the page stops working. But I'm thinking if I use another name for my replacement field, its value won't be saved to the original field. Here's the hook I'm using in ready.php:

    wire()->addHookAfter('Inputfield::render', function($event) {
        if (wire('page')->template != "account") return;
    
        $inputfield = $event->object;
    
        if ($inputfield->attr('name') == "profile_pad_countrycode") {
            $replacement = $this->modules->get('InputfieldSelect');
            $replacement->label = 'Land code';
            $replacement->attr('name', 'profile_pad_countrycode'); // This is a problem, the form crashes when using this name.
            $replacement->attr('class', 'uk-select');
            $optionsArray = ['test'];
            $replacement->addOptions($optionsArray);
            $event->return = $replacement->render();
        }
    }); 

    Can this way of replacing an inputfield ever work? Or should I abandon this idea?

  13. 15 hours ago, Robin S said:

    I'm a bit confused by your code because it looks like the module doesn't have any config fields, but generally speaking you can get your module config data after it is saved by hooking after Modules::saveConfig (or Modules::saveModuleConfigData if you need to support older versions of PW). You hook will run after the config is saved for any module, but you can use the first argument to compare against your module classname and return early if it doesn't match.

    I did not include the config part of the module because I did not think it would be relevant. But the Modules::saveConfig hook looks like the hook I need, thanks. I tried it out with a simple test but this does nothing when I save the module configuration (it should diplay a message):

    class WireDataSetupWebsite extends WireData implements Module
    {
        public static function getModuleInfo()
        {
            return array(
                "title" => "Website Options",
                "summary" => "Setup options for this website.",
                "author" => "",
                "singular" => true,
                "autoload" => true
            );
        }
    
        public function init()
        {
            $this->addHookAfter('Module::saveConfig', $this, 'test');
        }
        
        public function test(HookEvent $event) {
            $arguments = $event->arguments;
            $this->session->message('this is a test to see if the hook runs');
        }
    
    }

     

  14. I want to build a simple module that holds some settings for my website. The easiest way I see is doing this with a WireData module. So I set one up and it currently holds one field called website_type. When this field is saved, I want to do some stuff with the updated value. How do I hook into the save method? I tried the following, showing a message with the updated value (it shows the current value instead):

    class WireDataSetupWebsite extends WireData implements Module
    {
        public static function getModuleInfo()
        {
            return array(
                "title" => "Website Options",
                "version" => "0.0.1",
                "summary" => "Setup options for this website.",
                "author" => "",
                "singular" => true,
                "autoload" => true
            );
        }
    
        public function init()
        {
            $this->addHookBefore('ProcessModule::executeEdit', $this, 'test');
    
        }
        
        public function test(HookEvent $event) {
            $this->session->message('website type: ' . $this->website_type);
        }
    
    }

     

  15. I have setup a template called 'product-collection'. The edit permissions are set by this template and assigned to a user role called 'editor'. 'Allow edit-related access to inherit to children' is enabled. I have another template called 'product-card' with no permissions specified.  I have setup two pages, a parent page that has template product-collection and a child with product-card.

    The user with the editor role can edit this product-card page just fine, so the edit-related settings work as expected. There is an issue with the pagelister though: once the product-card page is unpublished, the editor can no longer list this page unless he specifically sets a filter to include unpublished pages. This is because the pagelister shows this warning beneath the filters: "Not all specified templates are editable. Only 'include=hidden' is allowed". So while the specified template (product-card) IS editable (because it inherits edit-permissions from its parent), the pagelister does not know this. One way around this is by setting the edit permissions of the product-card template manually instead of by inheriting from the parent. If you do this the warning goes away and unpublished pages are listed without setting a status filter. This behavior seems like a bug to me. What do you think? I'm using the latest development version.

  16. I figured it out, hopefully this might be useful to others as well:

    // Remove current thumbnail first.
    $currentThumb = $page->image_thumb->first();
    $page->image_thumb->delete($currentThumb);
    // Get the image we want to copy.
    $original = $page->image_front;
    $file = $original->getFile($original);
    // Clone that image and append it to the image_thumb field.
    $new = $original->clone($file, array('action' => 'append', 'pagefiles' => $page->image_thumb));
    $page->save();

    I noticed that this does not work if the filename of the file you are trying to clone ends with -0 (e.g. myfile-0.jpg). I think that is a bug which I'll post to GitHub.

    • Like 4
×
×
  • Create New...