Jump to content

MarkE

Members
  • Posts

    630
  • Joined

  • Last visited

  • Days Won

    6

Posts posted by MarkE

  1. v0.0.12 now available. This fixes a few bugs and also introduces interactive dependent-selects in the config. Now that both the config and the pages have dependent selects, I thought it would be helpful to demo how it all works.

    Firstly, the config. On the details tab, you select the quantity you want to measure and then choose what units you want to be selectable within a page (you can also choose whether to convert automatically, not at all, or to 'ask'):

    You will realise that we ended that demo just saving with no quantity selected. That's because we can use the same field in different template contexts to measure different quantities. So, next, we are going to add our field to a template and choose 'volume' as the quantity:

    Similarly, we can add our field to a different template to measure mass:

    Finally, we can create a page using one of these templates. In this case, it is 'volume' and we have chosen to convert automatically:

    If we had chosen to 'ask', we would have got a confirmation box before doing the conversion.

    All of this is accomplished by the magic of htmx (and of course ProcessWire). The principles behind it are discussed at 

    The actual code has moved on a bit from that post. For instance, I have used css transitions in the config. These work really nicely with htmx:

    
    #Inputfield_unit_set {
      opacity: 1;
      transition: opacity 200ms ease-in;
    }
    
    #Inputfield_unit_set.htmx-swapping {
      opacity: 0.1;
      transition: opacity 100ms ease-out;
    }
    
    #Inputfield_unit_set.htmx-settling {
      opacity: 0.1;
    }

    Now I'm getting the hang of htmx, I really like it 😃

    • Like 4
  2. 35 minutes ago, matjazp said:

    I had that behavior once, a long time ago, don't remember what the culprit was

    Yeah, not the first time for me either. Anyway, I've found the problem now - I'd added a script using

    echo "<script src='{$js}'></script>";

    . I changed that to 

    $this->wire()->config->scripts->append($js);

    and all seems good now.

  3. The dropdown menus in the AdminUI on my dev machine have suddenly stopped working. Also the submit button is wrong - see below:

    As you can see, the drop-down disappears when I try and select from it. It all works OK on the live site and I have done the following:

    • Compared the 'wire' files between the dev and live sites - no corruption or missing files
    • Logged out and back in again
    • Cleared the cache
    • Stopped and restarted Laragon

    Obviously, I have some code on my dev site that is not yet in the live site, but I can't see that it should affect the Admin UI. Nevertheless, I have tried disabling any new js files and that doesn't fix it either. I am also using the exact same database on each site.

    Version is PW 3.0.190 on Windows 10 / Laragon. Any ideas?

  4. All sorted now, I hope. I needed to insert the AsmSelect js (and also that for Toggle, at least on creation of new fields). Not exctly sure why, and I'm sure there is a better solution. Anyway, here is my code if it helps anyone else. (BTW I still need to get it working in modals 😐)

    1. In the module ___getConfigInputfields() method:

    public function ___getConfigInputfields(Field $field): InputfieldWrapper {
    		/* @var $field \ProcessWire\FieldtypeMeasurement */
    		$inputfields = parent::___getConfigInputfields($field);
    		$input = $this->wire('input');
    		if($input->post('quantity')) $field->set('quantity', $input->post('quantity'));
    		$f = $this->modules->get("InputfieldSelect");
    		$quantities = Measurement::getQuantities();
    		$f->label = __("Quantity");
    		$f_name = 'quantity';
    		$f->name = $f_name;
    		$f->columnWidth = 50;
    		$f->description = __("Type of physical quantity to be measured.");
    		$f->notes = __("Save after changing to see the options for units applicable to this quantity.");
    		foreach($quantities as $quantity) {
    			$f->addOption($quantity);
    		}
    		$f->value = $field->get('quantity');
    
    		#### add HTMX to change the units selection ####
    		$adminEditURL = $this->wire('config')->urls->admin . "setup/field/edit/";
    		$adminEdit = "{$adminEditURL}?id={$field->id}&refresh=1";
    		$f->attr([
    			'hx-get' => $adminEdit, // caught by HTMX AJAX LISTENER in hook
    			'hx-target' => "#Inputfield_unit_set", // our element to target with swap
    			'hx-swap' => 'innerHTML', //
    			'hx-trigger' => 'change', //
    			'hx-include' => "[name=quantity]",  // the new quantity
    		]);
    		########## end of hx- attributes ########################
    
    		$f->addClass('no-selectize');
    		$inputfields->append($f);
    
    		$f = $this->modules->get('InputfieldCheckbox');
    		$f->attr('name', 'hide_quantity');
    		$f->label = __('Hide quantity display in the input field.');
    		$f->attr('checked', $field->hide_quantity ? 'checked' : '');
    		$f->columnWidth = 50;
    		$inputfields->append($f);
    
    		$quantity = $field->get('quantity');
    		$fs = $this->unitSet($quantity, $field);
    		$inputfields->append($fs);
    
    		$f = $this->modules->get('InputfieldCheckbox');
    		$f->attr('name', 'show_remark');
    		$f->label = __('Show remark');
    		$f->notes = __("Show a remark entry box (default front-end rendering is as a tooltip).");
    		$f->attr('checked', $field->show_remark ? 'checked' : '');
    		$f->columnWidth = 100;
    		$inputfields->append($f);
    
    		return $inputfields;
    	}

    In the ready() method:

    $this->wire()->addHookAfter('ProcessField::buildEditForm', function(HookEvent $event) {
    			$object = $event->object;
    			$field = $object->getField();
    			if(!$field || !$field->id) {
    				$this->session()->set('newField', true);
    			}
    			##################### HTMX LISTENER #############################
    			$input = wire('input');
    			$ajax = wire('config')->ajax;
    			if($ajax && $input->get('refresh') == 1) {
    				$quantity = $input->get('quantity');
    				$fs = $this->unitSet($quantity, $field);
    				$inputfields = parent::___getConfigInputfields($field);
    				$inputfields->append($fs);
    				/*
    				 * In order to render AsmSelect and Toggle fields, we need to make sure the js and css is present
    				 */
    				// AsmSelect //
    				$js1 = $this->config->urls->modules . "Inputfield/InputfieldAsmSelect/asmselect/jquery.asmselect.js";
    				$out = "<script src='{$js1}'></script>";
    				$js2 = $this->config->urls->modules . "Inputfield/InputfieldAsmSelect/InputfieldAsmSelect.js";
    				$out .= "<script src='{$js2}'></script>";
    				$css1 = $this->config->urls->modules . "Inputfield/InputfieldAsmSelect/asmselect/jquery.asmselect.css";
    				$out .= "<link rel='stylesheet' href='{$css1}'/>";
    				$css2 = $this->config->urls->modules . "Inputfield/InputfieldAsmSelect/InputfieldAsmSelect.css";
    				$out .= "<link rel='stylesheet' href='{$css2}'/>";
    				// Toggle // We only want to add this for new fields as it persists afterwards
    				if($this->session()->get('newField')) {
    					$js3 = $this->config->urls->modules . "Inputfield/InputfieldToggle/InputfieldToggle.js";
    					$out .= "<script src='{$js3}'></script>";
    					$css3 = $this->config->urls->modules . "Inputfield/InputfieldToggle/InputfieldToggle.css";
    					$out .= "<link rel='stylesheet' href='{$css3}'/>";
    					$this->session->remove('newField');
    				}
    				// Finally we can render the html to be swapped into 'unit_set'
    				$out .= $inputfields->render();
    				echo $out;
    				die();
    			}
    		});

    In the module.js file:

    /*
    We need to tell htmx that ProcessWire expects Ajax calls to send "X-Requested-With"
     */
    
    const FieldtypeMeasurement = {
        initHTMXXRequestedWithXMLHttpRequest: function () {
            console.log("initHTMXXRequestedWithXMLHttpRequest - configRequest")
            document.body.addEventListener("htmx:configRequest", (event) => {
                event.detail.headers["X-Requested-With"] = "XMLHttpRequest"
            })
        },
    
        listenToHTMXRequests: function () {
            // before send - Just an example to show you where to hook BEFORE SEND htmx request
            htmx.on("htmx:beforeSend", function (event) {
                console.log("FieldtypeMeasurement - listenToHTMXRequests - event", event);
            })
        },
    }
    
    
    /**
     * DOM ready
     *
     */
    document.addEventListener("DOMContentLoaded", function (event) {
        if (typeof htmx !== "undefined") {
            // CHECK THAT htmx is available
            console.log("HTMX!")
            // init htmx with X-Requested-With
            FieldtypeMeasurement.initHTMXXRequestedWithXMLHttpRequest()
            // just for testing
            FieldtypeMeasurement.listenToHTMXRequests()
        } else {
            console.log("NO HTMX!")
        }
    })

    You also need 

    $this->wire()->config->scripts->append("https://unpkg.com/htmx.org@1.7.0");

    in the module init() method

  5. EDIT NOTE: If you read this comment earlier, I have deleted that content as it was all a red herring.

    I have now found the solution to the second problem:

    In order to populate the form correctly (as well as swapping in the html), we need to catch the new quantity when the field is saved. Saving the field calls getConfigInputFields again so we can simply add these lines in that method iin our module:

    		$input = $this->wire('input');
    		if($input->post('quantity')) $field->set('quantity', $input->post('quantity'));

    The processInput method called from ProcessField as part of the save will then have the correct config fields to process the changes against.

    The problem with the display of AsmSelect fields remains however - as you can see from the image below:

    672094549_MeasurementconfigAsmSelect.jpg.efb817c64e477312d9ee35802c9783d3.jpg

    It is displaying like a multi select, not an AsmSelect. After saving, it displays correctly.

  6. I looked into this further in the context of a Fieldtype module - specifically my FieldtypeMeasurement module. Unfortunately, it proved to be a bit too complex (at least for my tiny brain) to use @Robin S's idea. Instead, I attempted to use htmx (encouraged by my previous efforts with @kongondo's help) and made quite a lot of progress, but not quite enough....

    I thought it would be helpful to share my efforts as a general solution for Fieldtype modules would be nice.

    The basic idea is to specify the hx- attributes in the config InputFields in the module as follows:

    public function ___getConfigInputfields(Field $field): InputfieldWrapper {
    		/* @var $field \ProcessWire\FieldtypeMeasurement */
    		$inputfields = parent::___getConfigInputfields($field);
    
    		$f = $this->modules->get("InputfieldSelect");
    		$quantities = Measurement::getQuantities();
    		$f->label = __("Quantity");
    		$f_name = 'quantity';
    		$f->name = $f_name;
    		$f->columnWidth = 50;
    		$f->description = __("Type of physical quantity to be measured.");
    		foreach($quantities as $quantity) {
    			$f->addOption($quantity);
    		}
    		$f->value = $field->get('quantity');
    
    		#### add HTMX to change the units selection ####
    		$adminEditURL = $this->wire('config')->urls->admin . "setup/field/edit/";
    		$adminEdit = "{$adminEditURL}?id={$field->id}&refresh=1";
    		$f->attr([
    			'hx-get' => $adminEdit, // caught by HTMX AJAX LISTENER in hook
    			'hx-target' => "#Inputfield_unit_set", // our element to target with swap
    			'hx-swap' => 'innerHTML', //
    			'hx-trigger' => 'change', //
    			'hx-include' => "[name=quantity]",  // the new quantity
    		]);
    		########## end of hx- attributes ########################
    
    		$f->addClass('no-selectize');
    		bd($f, 'quantity field');
    		$inputfields->append($f);
    
    ...
    
    		$quantity = $field->get('quantity');
    		$fs = $this->unitSet($quantity, $field);
    		$inputfields->append($fs);
    
    ...
    		
    		return $inputfields;
    	}

    Then in the module's ready() method, add a hook like this:

    		$this->wire()->addHookAfter('ProcessField::buildEditForm', function(HookEvent $event) {
    			##################### HTMX LISTENER #############################
    			$input = wire('input');
    			$ajax = wire('config')->ajax;
    			if($ajax && $input->get('refresh') == 1) {
    				$quantity = $input->get('quantity');
    				$fieldId = $input->get('id');
    				$field = fields()->get("id=$fieldId");
    				$fs = $this->unitSet($quantity, $field);
    				$inputfields = parent::___getConfigInputfields($field);
    				$inputfields->append($fs);
    				echo $inputfields->render();
    				die();
    			}
    		});

    I have omitted the code for unitSet() here, for simplicity, but can show it if needed. Basically, it adds the selector field for units plus a notes field, both of which are dependent on 'quantity'. An important point to note is that the same unitSet() method is called in getConfigInputfields and in the hook.

    What works:

    • The dependent select field ('units') is updated by htmx on a change of quantity, as is the dependent 'notes' field.

    What doesn't work:

    • If I use an AsmSelect field for the 'units' dependent select, selected items are not added as they should be. I have checked that all the required js appears to be loaded, but maybe it is not all available in context. If I switch to a plain Select field, the dependent select appears to operate correctly, but...
    • Selected items (in the dependent 'units' field) are not retained after saving the field - i.e. the selection is emptied. Other dependent and changed fields are saved correctly.

    Re-selecting and saving a second time fixes both these issues, but that rather spoils the whole point of the exercise.

    I am not sure of the reason for these problems, but this is my analysis so far:

    • In saving the field, PW uses the 'form' object built by ProcessField::buildEditForm(). This form is the original form, not taking into account the change of 'quantity'. The hook inserts the new HTML so that everything displays correctly (Asm excepted) but does not update the form. This may account for the second problem (at least) because the 'options' property in the form has the dependent options for the previous quantity, not the newly-selected quantity, so the newly-selected dependent 'units' item is not in the options list.
    • I looked into modifying the form in the hook (after all, it is $event->return), but frankly struggled. I'm not sure whether it was the syntax or protected properties that was preventing me from updating 'form'; in any case, the updated form is not retained as the hook has to 'die' to prevent recursive loading - so setting $event->return has no effect.

    So I'm afraid I've hit a bit of a brick wall and have run out of ideas for now. The module works fine, as is, however - you just have to save after changing quantity and then select the units, but it would be nice to have an interactive solution. I'm hoping there are cleverer/more experienced people out there with better ideas 😄

     

  7. Please note that there is a bug in that the 'in-field' conversion feature is not working properly inside lazy-loaded repeaters. I am looking for a fix for this (any suggestions welcomed 😀).

    EDIT - The problem can be avoided (for existing repeater items) by disabling dynamic loading, but new items will need to be saved before 'in-field' conversion is enabled.

    EDIT 2: Hopefully now all fixed in v0.0.11

  8. 4 hours ago, cst989 said:

    But I might keep an eye out to see what your solution is first!

    I suspect that one of the other suggestions might fit your particular needs best @cst989, but FWIW, here is a very brief outline of my 'spreadsheet' solution:

    • The whole 'sheet' is a page - rendered in the front end.
    • Each column ('stage') can be of multiple types and is a repeater matrix item.
    • Each row is a field. Not all stages have all the fields.
    • The rendering template php loops though the 'stages' within the fields.
    • Some row/column combinations are editable in the front end and may be complex fields in their own right (e.g. repeaters or my FiledtypeMeasurement), so the use of table or matrix  did not fit my need.
    • Users can add new columns as shown. To resequence columns (at the moment) they need to edit the page in the back end.
    • The sheet is responsive and scrollable.

    So, in summary, it is a hand-built solution based on repeater matrix. If you do want to go this route, I can share code snippets.

    • Thanks 1
  9. Thanks for all that @bernhard. I don't want to perpetuate a to-and-fro and would really welcome input from others too. I do want to say that I, for one, appreciate what you have done, even if I decided to go a different route.

    I will take another look in depth at RockMigrations, as it has clearly developed quite a bit since I first looked at it. However, the module info says that it has been archived and that you are working on a new version. Is it better if I wait for that? Also:

    • Is there any documentation of best practices beyond the examples? For example, you mentioned putting migrations inside classes and, in particular, custom page classes, which sounds like a great idea, where it makes sense to do so.
    • I use PhpStorm, which has many of the same features as your IDE. The snippets sound especially useful (Live Templates in PhpStorm). Are they available anywhere? (I note that there is what appears to be an old GitHub repository for some PW snippets, but I'm not sure anyone ported those to PhpStorm either).

    Maybe you can reflect on some of my comments about achieving broader appeal? I well understand that RockMigrations was developed for personal use and that there may be little motivation in meeting other needs (although your contributions to the PW community are already extensive...). Likewise my motivation was to develop something that met my needs. My reason for being concerned about the wider appeal and applicability of a migrations module is to sustain PW as a viable, well-supported and favoured solution, which is ultimately to the benefit of all its users, including me. 

    • Like 4
  10. OK @bernhard, I have now re read https://processwire.com/talk/topic/26565-share-your-pw-dev-setups-tools/?do=findComment&comment=220484 and haven't got much to add to my previous comment. I think a lot boils down to the target 'market' for the migration tool. PW actually has a rather broad user base - from those who want something just a bit more flexible than WP at one end to those who would be equally happy with a plain PHP framework. I have used both WP and CodeIgniter in the past and find PW way better than both. I am not a full-time professional developer - very much a part-time amateur on a few projects. I also hack around in Python from time to time. Consequently I do not instantly remember all the structures, attribute names etc. - the UI helps with all of that.

    My view is that the migration tool (or tools) should cater for the full range of users and not just for the pro developer. My reason for this is (similarly to @MoritzLost) that PW without migrations is not a great solution for anything other than simple 'build and forget' websites which (forgive me 😉) you may as well do in WP. Part-time or more amateur PW users need to maintain and upgrade sites just like full-time pros, but less frequently. You say in the post referenced above that it is much quicker to type the code than use the UI. I am sure that is true for you and your team, but most certainly not for everyone. For example, creating a new field, you enter 'type' => 'text' - well, that's easy, but what are all the other fieldtypes called? I would need to look up their names - the UI gives me a selection drop-down. Have I entered all the necesaary attributes for my new field? I would need some sort of checklist to consider; in the UI it is all presented to you. The IDE helps with methods, for sure, but not with strings, and not with completeness.

    I appreciate it must be difficult to put yourself in the shoes of those less capable and experienced than you, but I think that is required to understand the needs of the wider user group. (I must admit that I don't understand @MoritzLost's problems with RockMigrations as I would have placed him in the super-pro category with you). You can take the view that only the super-pro group is important, but I think that only serves to marginalise PW. In my view, all users (other than those building very simple websites, for which PW is arguably overkill) need a solution to the migration/version issue even if they don't know it yet.

    • Like 2
  11. 10 minutes ago, bernhard said:

    Yes. I was very impressed, but I didn't really understand the context (was this just a demo or a real working tool) and I wasn't clear what your plans were for it (to incorporate in RockMigrations somehow?).

    12 minutes ago, bernhard said:

    Even more, I don't think that it will work. At least not for more complex projects and that's exactly the kind of projects where migrations come into play and what RockMigrations was built for...

    Because? It does seem to be very interactive and maybe that causes problems. With ProcessDbMigrate I very much opted for batch creation of entity specs, which is easier to manage.

    14 minutes ago, bernhard said:

    Yes, I did, but I must confess to not having thought through all the comments made there. The intial part of the post clearly shows implementation on an existing site by just specifying the changes, not the whole description - hence my comment about 'not fully declarative as it assumes a prior state'. I will re-read it more thoroughly.

  12. Thanks for the comments @bernhard. I'll do my best to reply. If, along the way, I demonstrate a misunderstanding about RockMigrations, please accept my apologies and help me to understand better - I have tried to use it but it didn't do what I wanted and I found it very time-consuming to try and get it right (admittedly this was some time ago and it has no doubt developed quite a bit since then). Equally, I would be grateful if you could try out ProcessDbMigrate, or at least read through the help file, and comment on the various pros and cons in order to advance the whole subject.

    14 minutes ago, bernhard said:

    1) Could you (both) please explain what you mean by "declarative config". In detail.

    21 minutes ago, bernhard said:

    Could you please explain what you mean by "RockMigrations is not really declarative".

    A fair request. At its simplest, you could say that it is a (complete or, at least, sufficient) specification of the current state of the entity(ies) in question. Arguably, RockMigrations fits this definition, if you completely specify the entity. However that is time-consuming and it is simpler to just specify the changes (which is not fully declarative as it assumes a certain prior state). With ProcessDbMigrate, I was attempting to produce a declarative definition automatically, rather than having to code it. That might not be enough 'detail' but we can discuss further.

    21 minutes ago, bernhard said:

    Could you please explain why you think "RockMigrations is difficult to implement on existing sites"

    Related to the above: to implement it in a declarative way required me to specify every field and template in full in code, by hand (at least for the migration scope in question). I had already done this via the UI and just wanted to produce the spec automatically from the database.

    25 minutes ago, bernhard said:

    Could you please explain why you think "it is fine if you want to code rather than use the PW Admin UI (*) and if you are doing everything the 'RockMigrations way' from scratch for a site, but I think it sits a little uncomfortably with the PW way of doing things."

    Again, related to the above. There is not much point using the Admin UI to specify the fields etc. if you are going to do it via the API anyway. Many people like the UI and are less proficient at coding (typing, remembering all the structures and formats etc., even if aided by the IDE). Allowing specification via the UI does not mean that 'mouseclicks' need to be recorded - just that the config files need to be generated from the resulting database automatically (or at least programmatically).

    31 minutes ago, bernhard said:

    That's why I think the discussion was not really helpful. It was full of opinionated assumptions and expectations without any noticable efforts in doing research in what we already have

    I hope you were referring to the OP here, not my post, as I did research all the prior migrations tools (even using some of the working bits of the core tools) and put a lot of work into my own solution.

    33 minutes ago, bernhard said:

    which concepts of the available tools work well, which don't, which could work differently (eg. having migration config in YAML rather than in PHP which seemed to be a huge thing for some whereas it absolutely means nothing to me. And: Which would be such an easy thing to implement into RockMigrations if need be...).

    I quite agree. That's why I was suggesting some way of agreeing requirements and then reviewing the best way forward, which may be by adaptation of an existing tool. As regards YAML vs JSON vs PHP, I agree that it is not such a huge thing. After all, the PHP is just an array specification. However, I plumped for JSON as it seemed easier when I was wanting to automatically generate specs from the database. FWIW, my original intention was to generate RockMigrations-style PHP from the database and leverage your existing work, but I struggled with that (I did say I'm not a great tech...). That might still be a good way to go 🙂

    40 minutes ago, bernhard said:

    I'll show why I think your statements are absolutely wrong in my opinion, but I'd be happy to hear your explanations first to get a better feeling of how RockMigrations is being seen by you or maybe also others, as I think that would be valuable feedback.

    In doing so, could you please also address the roll-back issue (added as an edit to my first post). Other requirements that ProcessDbMigrate meets which I think RockMigrations currently does not include database comparison, preview and audit trail. Please read the help file to get a full picture of what it does before commenting on pros and cons.

    • Like 4
  13. I realise that the original post here arose from the context of a comparison of Craft and PW. While it is sometimes helpful to look at other CMSs for inspiration, my fear is that, in this case it clouds the essential point:

    On 3/31/2022 at 3:05 PM, MoritzLost said:

    There's been a lot of talk recently about managing ProcessWire sites in version control systems (git in particular). Currently, this is quite difficult. The most important reason is that most of the site configuration is stored in the database, which you can't track in version control save for a database dump.

    The 'lot of talk' refers to 

    where, indeed, there was a lot of useful discussion of this topic but, unfortunately, not a lot of progress. As I suggested in that discussion:

    On 2/4/2022 at 12:12 AM, MarkE said:

    As to a way forward, I think a collaborative development of requirements and spec would help and then some agreement on who and how to build it. I also really think that a contribution to this discussion from @ryan before proceeding would be most helpful.

    @MoritzLost's wishlist is definitely a contribution to such a collaborative development and I would agree with much of what is said. My chief concern is that it is very aspirational (and also reflective of personal preferences) such that:

    On 3/31/2022 at 3:05 PM, MoritzLost said:

    To be honest, at this point I don't think it's likely to happen

    I think if the aspirations were more limited (at least initially), there might be a better chance of a result. Before reviewing the 'wish list', I would like to firstly consider the range of views then, finally, look at the current state and the way forward.

    Viewpoints

    Both @MoritzLost and I refer to @ryan's views on the topic of migrations and version control, but I do not recall seeing those expressed specifically anywhere. I also note that, in the other thread, @horst gave a "-10" to my suggestion that it was a really important topic. If they do not think it is important, I would really like to hear why.

    My viewpoint: I am not a tech wizard and my needs are quite simple; however, I have built a few sites in PW that make extensive use of its capability as a app-building framework rather than just a simple CMS. It is ideally suited to this purpose... ...except when you need to upgrade the live site. It is impossible to copy the live DB, change and test that then upload, without making it unavailable. Making anything but simple changes to fields and templates carries a high risk of human error.

    Wishlist

    As regards @MoritzLost's wishes:

    On 3/31/2022 at 3:05 PM, MoritzLost said:

    Declarative config. This is the most important thing.

    Absolutely.

    On 3/31/2022 at 3:05 PM, MoritzLost said:

    Better distinction between content and configuration

    That would be helpful.

    The other wishes in the list are either 'nice to haves' or personal preferences (IMHO).

    I would add one other 'wish' at this point:

    "Ability to implement on an already-existing site."

    EDIT: And another 'Roll-back capability'

    Current state

    At the moment the core provides practically nothing. There are some export features but they are incomplete and buggy in places.

    @bernhard's RockMigrations module is a well-developed solution to the problem, but it is not really declarative and I think it is difficult to implement on existing sites. It is fine if you want to code rather than use the PW Admin UI and if you are doing everything the 'RockMigrations way' from scratch for a site, but I think it sits a little uncomfortably with the PW way of doing things.

    For these reasons, I developed 'ProcessDbMigrate' as a POC (This is extensively documented here). In fact it rather exceeded my expectations and achieves the following:

    1. To allow development to take place (in a separate environment on a copy of the live database, or on a test database with the same structure) using the Admin UI. When finished, to permit a declarative approach to defining the migration and implementing it (again in the UI).
    2. To allow testing of the migration in a test environment on a copy of the live database.
    3. To allow roll-back of a migration if installation causes problems (ideally while testing rather than after implementation!).
    4. To provide a record of changes applied.
    5. Optionally, if changes are made directly on the live system (presumably simple, low-risk mods – although not best practice), to allow reverse migration to the development system in a similar fashion.
    6. To provide a database comparison tool which can (if wished) be used to create a draft migration for the differences between the databases.

    I have no pride of authorship here (and I am sure some may think my coding is a bit hacky), but it is a fairly thorough attempt to address the wishes expressed above. It is declarative (using JSON rather than YAML). It deals with the content vs configuration issue by defining a 'scope' for every migration - in other words, it can be used when the distinction between content and configuration is a bit fluid (which is always a potential issue in any CMS). It can be simply implemented on any existing site by installing the module.

    However, ProcessDbMigrate does have some drawbacks. 

    • It introduces quite a few new templates, fields and admin pages which could confuse a user (although they are flagged as 'system').
    • It doesn't completely and accurately model all possible fields and templates so it does need to be tested on the chosen site before implementing. This is partly because it is 'POC' and partly because I couldn't find a definitive model.
    • I know for certain that it does not cope with nested repeater fields.
    • EDIT: plus if you use it to compare a whole database it will probably crash by exceeding memory limits - however, it is more reliable when scoped to genuine configuration matters.

    Way forward

    As I said earlier, I think the way forward should be collaborative. I also think that a module is more practicable, at least initially, than expecting a massive core upgrade; it is also more workable for a collaborative approach.

    I think that a specially moderated thread might be a good start, where the moderator is reasonably unpinionated but sufficiently experienced. 

    Initially, views should be gathered (via a poll? - perhaps @teppo could facilitate this?) as to the need for a migration/version control solution. Then some ranking of the 'wish list' items followed by a selection of a 'doable' set of requirements. The existing solutions could then be compared with this list to assess whether any of them go some way towards meeting the requirements and might be adapted or incorporated (either as code or as a 'leg-up' on the specification).

    Alongside this, we need a complete and accurate published data model of fields, templates and pages. Futhermore, this would need to be kept up-to-date for core changes. Existing modules (particularly Fieldtypes) would need to be reviewed for compliance. @ryan's help with this would be essential.

    No doubt contributors to the thread will have their own views on how to progress things, but a willingness to make tangible contributions would be helpful!

    Conclusion

    Perhaps I have missed the point entirely, in which case, please explain, but my fear is that this discussion will just remain a discussion and it will be left to individuals with the motivation to provide their own solutions which inevitably will reflect their own personal preferences and needs.

    • Like 5
    • Thanks 1
  14. I wonder if FieldtypeMeasurement might help? Only in alpha at the moment so you would need to test well. Create a conversion php file with the calculations (see the help). Data entry would then be net or whatever gross you want, with interactive conversion as required. See the readme for more details. Happy to help if you want to go down this route. Note that both this and @bernhard’s suggestion require a field change, whereas a hook (if it works) might not, so you would need to handle data migration. 

×
×
  • Create New...