Jump to content


  • Posts

  • Joined

  • Last visited

  • Days Won


Posts posted by MarkE

  1. Thanks for the comments @kongondo. As stated, it is POC at the moment so I am very open to suggestions for improvements 🙂 . I have built it with an app in mind, but I wanted to do the fieldtype before proceeding with the app. No doubt using it in anger will result in some changes.

    4 minutes ago, kongondo said:

    Is there a reason you combine magnitudes into pipe-separated values?

    I combined the magnitudes as pipe-separated in order to store them as a string in the DB. I am having second thoughts about this. In fact I am wondering about using arrays and then storing a json in the DB.

    At the moment, the queries don't work with combi fields, but there is a wider issue: if there are a mix of units in the field instances then numerical comparisons are meaningless. Therefore it is necessary to loop through the pages with measurements and convertTo() a common unit, then compare - this deals with combi units at the same time (assuming the common unit is single-valued!). I'm therefore thinking how could I solve that wider problem at the same time as the one you mention?

    5 minutes ago, kongondo said:

    maybe it is prone to errors? Editors need to remember to input a pipe as well as remember what side of the pipe is what measurement.

    Fair point. There is some error checking at the moment, but I still need to catch the exceptions which are generated and provide helpful messages. Hopefully the dropdown indicates the format and editors will soon get the hang of this. Again, I am open to better suggestions - it needs a balance between conciseness and idiocy-proof.

  2. OK - I did this and it seems to work OK. @teppowas rather quick off the mark with the PW weekly report - I still have to add a lot of units and do some tidying (and remove debugging lines in case people don't have Tracy!). I will also add some notes about what I learnt doing this as the existing tutorials (such as @bernhard's) don't seem to cover fieldtypes which use the database.

    Support thread started at 


    • Like 3
  3. EDIT:
    Note that this OP relates to the original version of the module. Version 0.0.12 is now published to the modules library at https://processwire.com/modules/fieldtype-measurement/. As well as many bug fixes and small enhancements, it now also includes an 'in-field' interactive conversion feature and dependent-select in the config. See the readme on the module page for up-to-date details and see this post for a bit of a demo.

    This fieldtype and inputfield bundle was built for storing measurement values within a field, rendering them in a variety of formats and converting them to other units or otherwise modifying them via the API.

    The API consists of a number of predefined functions, some of which include...

    • render() for rendering the measurement object,
    • valueAs() for converting the value to another unit value,
    • convertTo() for converting the whole measurement object to different units, and
    • add() and subtract() for for modifying the stored value by the value (converted as required) in another measurement.

    In the admin the inputfield includes a checkbox (which can be optionally disabled) for converting values on page save. For an example if a value was typed in as centimeters, the unit was changed to metres, and the page saved with this checkbox selected, said value would be automatically converted so that e.g. 170 cm becomes 1.7 m.


    A simple length field using Fieldtype Measurement and Inputfield Measurement.

    Combination units (e.g. feet and inches) are also supported.

    Please note that this module is 'proof of concept' at the moment - there are limited units available and quite a lot of code tidying to do. More units will be added shortly.

    See the GitHub at https://github.com/MetaTunes/FieldtypeMeasurement for full details and updates.

    • Like 7
  4. 4 hours ago, joe_g said:

    2. Streamline replication from live -> staging and -> test, so I can work on a fresh copy of data without having to use phpmyadmin

    Not sure this is strictly a shared server issue. I find that I want to update data structures and settings pages, but don’t want to overwrite user-updated pages so database backup and restore (or phpmyadmin) doesn’t work. That’s why I wrote ProcessDbMigrate - still in alpha but usable provided everything is tested first. Or, if you prefer to do it all in code with the api, rather than in UI, there is RockMigrations

    • Like 2
  5. I found a few more small bugs and have also greatly enhanced the help file, so that it is now available as a pop-out when working in the module. The new version (0.1.3) is at https://github.com/MetaTunes/ProcessDbMigrate. You should be able to replace the files in your ProcessDbMigrate directory with the new ones and 'refresh modules' to upgrade.

    @cjx2240, @antpreand @dotnetic (and anyone else): I'd appreciate your feedback as I am considering releasing this (as alpha) to the modules directory.

  6. I've been looking around for a fieldtype that can handle weights and measures but, rather surprisingly, can't seem to find anything.

    What I have in mind is a field that essentially comprises 2 elements - a (float) value and a (dropdown) measure (e.g. lbs, kg). It would also have an associated standard unit (usually an SI unit, I guess), which might or might not be in the dropdown, and each measure option would have a conversion factor to the standard unit. The value would be stored in the database as standard units. The measure options, standard unit and conversions would be specified in the input/details for the field, along with a default measurement option; these could also be set via API. If a user changes the measurement option in the dropdown, then the value would be amended accordingly (via AJAX).

    Is it possible to use the Combo ProField for this pupose (I don't have ProFields)? 

    Would it be desirable to build a new Fieldtype module for this? Or is there a better way of achieving the same end?

  7. Thanks for the comments @cjx2240. Sorry it has taken so long to reply. I have done quite a bit of work removing various bugs (there were quite a few!). I have also extended the functionality considerably to include a database comparison feature (allows draft migrations to be created based on database differences). There is also the capability to run custom code alongside the migration via hooks. The help file is now (roughly) indexed and available at https://metatunes.github.io/DbMigrate/help.html. The new version (0.1.0) is at https://github.com/MetaTunes/ProcessDbMigrate. You should be able to replace the files in your ProcessDbMigrate directory with the new ones and 'refresh modules' to upgrade.

    Please let me know if any of the snags you hit have persisted after the update (or any new ones encountered) and I will try and resolve them more quickly next time! I'm hoping that this version is a passable 'alpha' as opposed to the previous 'proof of concept' and will look to submit it to the modules directory if it seems sufficiently robust.

    • Like 1
    • Thanks 1
  8. 1 hour ago, ryan said:

    Was this bodyFoot thing querying the database, or doing something memory?

    bodyFoot is just a (CKE) textarea field in a page with template=Availability. It holds a comma-separated list of hosts which are permitted to access the Availability page in site-admin. $host is the name of the site-web host. So all the select is doing is checking that $host is in the list of hosts. I realise that it might have been better to explode the list and then check array membership but, ignoring that for now, I am puzzled by your example - I get "Yes" for both too.

    Examining the (real) situation a bit more, I added some Tracy debugging to the code as follows:

    $host = $config->httpHost;
    bd($host, 'host');
    bd(adminSite()->pages->get("template=Availability")->bodyFoot, 'bodyFoot');
    $adminPage = adminSite()->pages->get("template=Availability, bodyFoot%=$host"); // bodyFoot holds permitted hosts list for PW sites
    bd($adminPage, 'admin page in Prices');
    $availabilityTable = $adminPage->runtime_markup_availability;

    This is the output with the real data (in 3.0.184):


    Replacing the %= by *= in the code results in the following:


    In version 3.0.165, the *= yielded the same result as %=

  9. 5 hours ago, ryan said:

    That I think may be defeating the purpose of making it load on-demand.

    I did wonder if that might be the case. I need to use the setting in both sites, having just set it in site-web, and I thought setting() achieves that whereas adminSite() is not available to the other site. However, it seems I am wrong and that the adminSite() function is available in site-admin when that instance is called from site-web. So I removed the extra line and everything seems to work, thanks!

    5 hours ago, ryan said:

    I think we'd need to look at what is in $host in order to tell. It would also be good to know the full context of that bodyFoot*=$host, for instance is that selector being sent to a $pages API call, or to something else? The biggest difference between *= and %= is that *= matches from the beginning of a word boundary whereas %= matches anywhere in the string. So if you've got an instance where %= is matching and *= isn't, then most likely it's because of that difference.

    bodyFoot was "<p>myText, some more text, ... </p>" and $host was "myText" so your explanantion is spot on and in line with the docs. However, *= worked in 3.0.165 with exactly the same values so it looks like something changed... No worries, it all works now, but I wonder if there might be a problem lurking for others if indeed there was a change.

    • Like 1
  10. On 9/6/2021 at 9:12 AM, MarkE said:

    I really don't know why the above code has been added or what it is trying to achieve?

    The more I look at this, the more it seems to me to be a bug. The current method has the effect of not only removing the namespace, but also failing to add:

    if(!defined("PROCESSWIRE")) die("no direct access");

    to the Hanna code.

    In my case, I have dozens of Hanna codes all just calling one hannaCode() function, so that I can maintain the codes in my IDE rather than the PW UI (much less time-consuming!). The upgrade seems to require me to edit every single Hanna code, which surely ought not to be the intention. I have therefore hacked my TextFormatterHannaCode.module to include the following in getPHP():

    		$php = '<' . '?php';
    		$openPHP = $php;
    		$openPHPNS = "$php namespace ProcessWire;";
    		$firstLine = 'if(!defined("PROCESSWIRE")) die("no direct access");';
    		if(strpos($code, 'namespace') && preg_match('/(namespace\s+ProcessWire(?:;|\s*;))/', $code, $matches)) {
    			$openPHP = $openPHPNS;
    			$code = str_replace($matches[1], '', $code);
    		if(strpos($code, $openPHP) !== 0 && strpos($code, $php) !== 0) {
    			// prepend open PHP tag to code if not already present
    			$code = "$openPHPNS\n$firstLine\n$code"; 
    		} else {
    			// otherwise insert our $firstLine security check
    			$code = str_replace($php, "$openPHPNS\n$firstLine\n", $code);

    This automatically adds the namespace and the 'die' to all Hanna codes and works (so far) for me. Perhaps others ( @adrian, @ryan?) might suggest a better fix or tell me that I've got it all wrong 😉 

    EDIT: I have raised an issue on GitHub for this

  11. On 4/29/2021 at 9:34 AM, Ivan Gretsky said:

    Try adding ProcessWire namespace in you Hanna codes.


    On 4/29/2021 at 2:40 PM, adrian said:

    Try calling the function like:


    I am confused by this. Surely it should not be necessary to both add the namespace in the Hanna code AND call the function \ProcessWire\myFunction()?

    So I looked at the TextFormatterHannaCode.module - getPHP() method and found this:

    		$php = '<' . '?php';
    		$openPHP = $php;
    		$openPHPNS = "$php namespace ProcessWire;";
    		$firstLine = 'if(!defined("PROCESSWIRE")) die("no direct access");';
    		if(strpos($code, 'namespace') && preg_match('/(namespace\s+ProcessWire(?:;|\s*;))/', $code, $matches)) {
    			$openPHP = $openPHPNS;
    			$code = str_replace($matches[1], '', $code);
    		if(strpos($code, $openPHP) !== 0 && strpos($code, $php) !== 0) {
    			// prepend open PHP tag to code if not already present
    			$code = "$openPHP\n$firstLine\n$code"; 
    		} else {
    			// otherwise insert our $firstLine security check
    			$code = str_replace($openPHP, "$openPHP\n$firstLine\n", $code); 

    It seems that the method is removing "namespace ProcessWire;" from the Hanna code. Looking at the cached files shows this to be the case. In other words, adding  "namespace ProcessWire;" to the Hanna code is pointless as \ProcessWire\myfunction() is still going to be needed.

    I really don't know why the above code has been added or what it is trying to achieve?

    • Like 1
  12. 3 hours ago, ryan said:

    So I would replace your setting() call with the following

    I used setting() because I needed to access the object in site-admin* as well as site-web. So I used your code and added:

    if (!setting('admin_site')) setting('admin_site', adminSite());
    3 hours ago, ryan said:

    Next, make sure that your instances are both running the exact same ProcessWire version. 

    Both sites are in the same installation so use the exact same version

    3 hours ago, ryan said:

    You might want to rename your /site/ to /site-admin/  so that there is no /site/ directory which would typically be the primary instance. 

    Done that. Everything works except for the cross-site referencing as reported - I'm still getting a null page returned. (The code reversion problem seems to have been temporary).


    *Note: I need to access the object in site-admin because the availability page is running in site-web - called by

    $availabilityTable = $adminPage->runtime_markup_availability;

    (where $adminPage is the one that is currently being returned as null) but the runtime_markup code is in site-admin and needs to use the site-admin instance of wire(), not the site-web one. (Why is the runtime_markup code in site-admin? Because there can be multiple public websites which may or may not be PW sites and I want them all to use the same code to render the availability table which is defined in the admin site).

    Sorry if it's a bit complicated, but it was all working so well in 3.0.165!


    The above is probably all irrelevant! The problem seems to be to do with the selector bodyFoot*=$host which is finding the correct page in 3.0.165 but not in 3.0.184. Using just "template=Availability" works fine and the found pages have field bodyFoot with the text $host.

    So I changed *= to %= and now it works! I guess at sometime the selector method got changed very slightly, so I will check for other instances of that.

    Anyway I'll keep the changes you suggested @ryan as they are an improvement anyway 🙂 

  13. Just trying to update a multi-instance site to 3.0.184 from 3.0.165 but the cross-linking between the two sites no longer works.

    The two sites are /site/ - essentially the admin site for property bookings - and /site-web/ for the public website and which publishes availability from /site/.

    In /site-web/templates/_init.php I have:

    setting('admin_site', new ProcessWire($config->paths->root . 'site/'));

    and in /site-web/templates/prices.php I have:

    $adminPage = setting('admin_site')->pages->get("template=Availability, bodyFoot*=$host"); // bodyFoot holds permitted hosts list for PW sites
    bd($adminPage, 'admin page in Prices');

    In 3.0.165 $adminPage is the correct Availability page. In 3.0.184 it is a null page. I have tried clearing FileCompiler from cache in both sites, but still get the same result.

    I also did a dump of setting('admin_site') in both versions and it looks identical.

    Is there anything in 3.0.184 that might have changed to cause this? Any other ideas?


    EDIT: Another really weird thing. If I try and edit site-web/templates/_init.php to add debugging then it keeps reverting when reloading - like PW is editing my php file! This only happens with 3.0.184, not 3.0.165. Think I'm losing my mind!

  14. For the benefit of anyone else wanting their module to be comptible with earlier versions of PW, I suggest you use: 

    $tab1 = $this->wire(new InputfieldWrapper());


    $tab1 = $modules->get('InputfieldWrapper');

    Also, do not use plain $tab1 = new InputfieldWrapper(); as the column widths of the contained inputfields will not work properly. Per the PW coding style guide:


    All newly-created objects that are derived from Wire SHOULD have their dependencies injected. In order to do this, pass the new object through the wire() method.


    • Like 2
  15. 49 minutes ago, netcarver said:

    This requires a more recent version of PW than 3.0.165 - I'm currently using 3.0.182.

    Ta. The site is on 3.0.165. @Robin S's module is on 170. Hopefully a new core is out soon and I will move to that.

    However, I am using this in my ProcessDbMigrate module (full alpha release shortly.... 😁) and I have tried to make that compatible with 3.0.148 (even pre page class days). I'm not sure what the best policy is regarding the backwards compatibility of new modules.

  • Create New...