Jump to content

MarkE

Members
  • Posts

    921
  • Joined

  • Last visited

  • Days Won

    10

Everything posted by MarkE

  1. Hi @bernhard. Just tried a different module (AppAPI) which is OK. The problem appears to be with your modules. I tried RockMigrations too - on v3.0.200 - both RockMigrations and RockCalculator give this error: ProcessWire: ProcessModule: No page specified
  2. Thanks @bernhard. That's helpful but doesn't work as $f->hasField is null because magnitude is a property of a measurement object field, not a field itself. So I tried the following code - creating a dummy field to hold the rockcalculator property: $f = $this->modules->get("InputfieldText"); if(wire()->modules->isInstalled('RockCalculator')) { $f->attr("data-rockcalculator", 6); //6 digit precision $f->notes = __("Numeric or math formula"); $dummyField = wire()->fields->makeItem(['name' => 'dummyName']); $f->hasField = $dummyField; $f->hasField->rockcalculator = true; bd($f, '$f in rockcalc'); } else { $f->notes = __("Numeric"); $f->precision = 6; $f->attr('type', "number"); $f->attr('step', "any"); } That almost works, in the sense that isEnabled() is true and loadAssets() runs. However the dev tools do not show the js as loaded and the field doesn't work. I've got round the problem by including the following in the init() of my fieldtype module: if(wire()->modules->isInstalled('RockCalculator')) { $rc = $this->wire->modules->get('RockCalculator'); $this->wire->config->scripts->add($rc->m('lib/math.min.js')); $this->wire->config->scripts->add($rc->m('lib/tooltip.js')); $this->wire->config->scripts->add($rc->m($rc->className . '.js')); $this->wire->config->styles->add($rc->m($rc->className . '.css')); } Maybe there is a better way, but at least this seems to work. And your module certainly enhances mine ☺️
  3. This looks a handy little module. I'm hoping to add it as an enhancement to my FieldtypeMeasurement module, which it would complement very nicely. However, I'm scratching my head a bit as to the best way of incorporating it as I really need to embed it within my Inputfield::render() method - i.e. after the hook in your module has fired (?), but I think that's too late. The problem is that my field is an object. The magnitude property (which is where I'd like the calculator) is rendered as a text inputfield. So what I was hoping to do was something like this (where $f will be the inputfield for the magnitude): $f = $this->modules->get("InputfieldText"); if(wire()->modules->isInstalled('RockCalculator')) { // set the rockcalculator here // $f->attr("data-rockcalculator", 6); //6 digit precision $f->notes = __("Numeric or math formula"); } else { $f->notes = __("Numeric"); $f->precision = 6; $f->attr('type', "number"); $f->attr('step', "any"); } However, that doesn't work because the assets aren't loaded. It works OK if I remove the line if(!$this->isEnabled($inputfield)) return; from loadAssets(), but obviously if the module is used elsewhere in the site, that is not a great idea and isEnabled() is not hookable. I could just load the assets separately, I guess. Any suggestions@bernhard
  4. On 3.0.203. No other modules of yours installed, but planning RockFrontend and maybe RockMigrations
  5. Just tried to install a new module (RockCalculator from @bernhard) and got this message. I don't think it's anything to do with his module, so posting here as a general query. Any ideas what might be causing it? (BTW it installed OK by downloading the files manually)
  6. TLDR: Use custom selectors in page field selector: - check_access=role1|role2 ... - to control who can see results - field=[item.id] - to select on id of repeater item containing the page field. ------------ This module extends the capabilities of selectors specified in the 'input' tab of a page reference field, specifically when that field is part of a set of dependent selectors which may be inside a repeater item. The readme also attempts to bring together various existing documentation regarding the use of dependent page selectors and the enhancements that were provided by various PW versions. See https://github.com/MetaTunes/CustomDependSelects for full readme and to download. Please note that this is an initial alpha release. Please test in your own context thoroughly before using. Also note that PW3.0.200 is required and 3.0.203 is preferred.
  7. Actually, I am building a little module to fix it, hopefully ? -Edit: You can now find it here.
  8. Thanks @AndZyk. I am using dependent selects. So it needs check_access=0 in the input tab as you suggest for InputfieldPage to get it. However for dependent selects, ProcessPageSearch is called to populate the options and strips out the 'check_access'. Then, when the options don't include the already-selected item provided by InputfieldPage, it is removed ? I think perhaps I should raise this as an issue or feature request.
  9. Thanks @AndZyk. I had tried check_access, but it didn't work. I found out why - because ProcessPageSearch contains the following: // don't allow setting of check_access property, except for superuser if($lowerName == 'check_access' && !$superuser) continue; So I sort-of hacked it with a hook: wire()->addHookAfter('ProcessPageSearch::findReady', function(HookEvent $event) { $selector = $event->return; $user = wire()->users->getCurrentUser(); if($user->hasRole('webmaster')) $selector = 'check_access=0, ' . $selector; $event->return = $selector; }); which works, but I'm not very happy with it!
  10. Thanks @bernhardfor your detailed response. The best of both worlds would be nice if it makes sense. First I'll do a few more improvements to my module and then try and respond to the request for a working example, before considering the way forward from there.
  11. I have a number of pages which host dependent select fields. The contents of these are drawn from various repeater fields (actually repeaterMatrix, but I don't think that's relevant to the problem) - i.e. they are provided by a selector which is something like "template=repeater_field_name, ...". They all work fine in superuser, but in any non-superuser role, they return an empty result, even if the role has the maximum permissions. It seems like every repeater template needs to specifically permit access to the required roles, because they are all children of 'admin'. Is this so? Is there a shortcut way of doing this (there are a lot of such fields)? Edit: I guess what I would like to do is to set the access to the repeater page to be the same its host page (getForPage) rather than admin. Any ideas?
  12. Confused @bernhard? I’m not sure what is confusing. Did you read the manual? I’m happy to try and clarify if I know where the problem is.
  13. In case you hadn't realised, there is extensive documentation of the module at https://metatunes.github.io/DbMigrate/help.html. So you don't need to install and use the module to get an understanding of what it does. Specifically as regards running code on migrations, see the following sections: https://metatunes.github.io/DbMigrate/help.html#snippets and https://metatunes.github.io/DbMigrate/help.html#hooks. I'm happy to supply a full soup-to-nuts example if it helps, but that will take a little time. Perhaps reading the help file and reviewing this (completed) example might be explanantion enough. (Note that this example does not include ready.php code for uninstalling as I had fully tested everything and was confident I didn't need to write it. If for some reason it was needed, I could have modified ready.php to hook before and after uninstallMigration() in a similar manner). Let me know if you want a fuller example; also if anything in the help file is not clear as I'll gladly improve it.
  14. The new version looks good @bernhard and I am very tempted to give it a proper try. However, I have been using my own ProcessDbMigrate module successfully on a number of projects and it is serving me pretty well (and the change in approach would be quite radical). Although the two are quite different in methodology, there are some similarities in that my json files have similarities to your yaml files (btw, not quite sure what advantages yaml has over json in this context - json has coped so far). My module is still very much alpha as something this complex does need extensive testing and bugs do crop up (as well as the need to extend to handle additional field types etc. - the recent version 0.1.5 has been updated to include FieldtypeRepeaterMatrix). Sometimes I think about re-engineering it to use RockMigrations methods rather than the current native ones, but that does lead to some head-scratching. For example, my module will handle uninstallation of migrations (provided they have not been conflicted by subsequent changes) - I don't see how RockMigrations does this (reverting the code would leave the database unchanged?). Also I can attach hooks to run on installation (and uninstallation) to handle any data changes related to the migrations (e.g. say field 'name' is split into 'first_name' and 'last_name', the code can populate the new fields when the installation is run). I assume that RockMigrations can handle that too (at least for the forward install), but not quite sure how. I know you have commented in the past that you don't like my approach (although I'm not sure of the precise reasons**) but I think it is a valid alternative and I would like to somehow get the best of both worlds. ** I can see that using Git to handle conflicts has some advantages. My module has to include its own conflict management which works but has not been tested in a multi-developer environment. Mind you, I can envisage semantic conflicts that might arise which Git would not spot - separate modules changing the same field for example.
  15. It’s quite difficult to debug code from a few snippets (maybe someone smarter than me can…). I suggest you install the TracyDebugger module and insert some bd() statements to see what is going wrong.
  16. Check out the Options Fieldtype. Sometimes I find a page ref field is better than an Options field - easier to add/change. It depends whether this is something that needs to be flexible or not.
  17. That looks like the way to go to me. There's no way you can hack the Access Roles form as shown in your image, as all the relevant methods are protected an unhookable.
  18. Sorry @jploch, but its not really clear to me what you want this new permission to do and how you want it to operate. Pretty much anything is do-able in PW ?
  19. Not sure exactly what you are wanting to achieve but, if it helps, here is some code I used to hook User::hasPagePermission. Obviously the context is specific to my app (a membership system), but maybe there are some useful ideas. /** * PAGE PERMISSIONS * Allow member users to edit etc. pages relevant to them (access via AIM in My NCOG) **/ wire()->addHookAfter('User::hasPagePermission', function(HookEvent $event) { // Get the object the event occurred on, if needed $user = $event->object; // An 'after' hook can retrieve and/or modify the return value $return = $event->return; // Get values of arguments sent to hook (if needed) $permission = $event->arguments(0); $p = $event->arguments(1); /* Your code here, perhaps modifying the return value */ // Is it a page we need to customise access for? $templates = ['Membership', 'Member', 'Profile', 'Subscription', 'Payment', 'MemberShop', 'Booking', 'NewsItem']; $permissions = ['page-edit', 'page-add']; $currentUser = $this->users->getCurrentUser(); if ($p and in_array($p->template, $templates) and $permission and in_array($permission, $permissions)) { if ($currentUser and $currentUser->isLoggedin()) { $this->log->save('debug', 'In hasPagePermission hook for Page = ' . $p . ', Permission = ' . $permission . '. Current user is ' . $currentUser); if ($currentUser->hasRole('member')) { $email = $currentUser->email; $memberPage = ($email and $email != '') ? $this->pages->get("has_parent=/memberships/, template=Member, email=$email") : null; if ($currentUser->memberOnly != 0) { $return = false; $this->log->save('debug', 'Member only'); } // Member-only users can only access pages as defined below // Admin members will also have their normal permissions if ($memberPage and $memberPage->id) { $membershipPage = $memberPage->parent; $this->log->save('debug', 'Membership page = ' . $membershipPage->id); $profilePage = $membershipPage->id ? $membershipPage->get("template=Profile, include=hidden") : null; $siblings = $memberPage->siblings("template=Member, include=hidden"); // includes member page itself $shops = $membershipPage->id ? $membershipPage->find("template=MemberShop, include=all") : null; $currentSub = $membershipPage->id ? $membershipPage->latestSubscription() : null; $subsPaymentPages = $membershipPage->id ? $membershipPage->find("template=Payment, parent=[template=Subscription], include=hidden") : null; $draftNewsPages = $membershipPage->id ? $memberPage->find("template=NewsItem, include=all") : null; $bookingPages = $membershipPage->id ? $membershipPage->find("template=Booking, include=hidden") : null; $editablePages = new PageArray(); $addablePages = new PageArray(); $editablePages = $editablePages->add($membershipPage)->add($profilePage)->add($siblings)->add($currentSub)->add($shops)->add($subsPaymentPages)->add($draftNewsPages)->add($bookingPages); $addablePages = $addablePages->add($membershipPage)->add($memberPage); // pages where creation of children is allowed $this->log->save('debug', 'Editable pages = ' . $editablePages->implode(', ', 'id')); $this->log->save('debug', 'Addable pages = ' . $addablePages->implode(', ', 'id')); if ($editablePages->has($p) and $permission == 'page-edit') $return = true; if ($addablePages->has($p) and $permission == 'page-add') $return = true; } } $retStr = $return ? 'true' : 'false'; $this->log->save('debug', 'Returning ' . $retStr); } } // Populate back return value, if you have modified it $event->return = $return; });
  20. I guess this is largely a matter of personal preference. My personal preference is for a written description that can be accessed other than just while coding. This means that one can get an at-a-glance overview and dip in for more detail, without having downloaded the module and fired up the IDE. Call me sad, but I sometimes read this stuff sat in an armchair, not at the workstation ?. I gave the example above of the readme for FieldtypeMeasurement. Perhaps the ideal approach is to have all the documentation in PHPDoc. This is pretty much the approach of PW, so that then the help documentation (API ref) can be generated automatically from the code. If that approach is chosen, then a bit more explanation in the PHPDocs would be helpful. For example, the PHPDoc for alfred is /** * ALFRED - A Lovely FRontend EDitor * @return string */ There is no description of the options and their defaults (although these can be seen by inspecting the code). PW PHPDocs tend to include option descriptions. See $pages->find for a (very full) example /** * Given a Selector string, return the Page objects that match in a PageArray. * * - This is one of the most commonly used API methods in ProcessWire. * - If you only need to find one page, use the `Pages::get()` or `Pages::findOne()` method instead (and note the difference). * - If you need to find a huge quantity of pages (like thousands) without limit or pagination, look at the `Pages::findMany()` method. * * ~~~~~ * // Find all pages using template "building" with 25 or more floors * $skyscrapers = $pages->find("template=building, floors>=25"); * ~~~~~ * * #pw-group-retrieval * * @param string|int|array|Selectors $selector Specify selector (standard usage), but can also accept page ID or array of page IDs. * @param array|string $options One or more options that can modify certain behaviors. May be associative array or "key=value" selector string. * - `findOne` (bool): Apply optimizations for finding a single page (default=false). * - `findAll` (bool): Find all pages with no exclusions, same as "include=all" option (default=false). * - `findIDs` (bool|int): 1 to get array of page IDs, true to return verbose array, 2 to return verbose array with all cols in 3.0.153+. (default=false). * - `getTotal` (bool): Whether to set returning PageArray's "total" property (default=true, except when findOne=true). * - `loadPages` (bool): Whether to populate the returned PageArray with found pages (default=true). * The only reason why you'd want to change this to false would be if you only needed the count details from * the PageArray: getTotal(), getStart(), getLimit, etc. This is intended as an optimization for $pages->count(). * Does not apply if $selector argument is an array. * - `cache` (bool): Allow caching of selectors and loaded pages? (default=true). Also sets loadOptions[cache]. * - `allowCustom` (boolean): Allow use of _custom="another selector" in given $selector? For specific uses. (default=false) * - `caller` (string): Optional name of calling function, for debugging purposes, i.e. "pages.count" (default=blank). * - `include` (string): Optional inclusion mode of 'hidden', 'unpublished' or 'all'. (default=none). Typically you would specify this * directly in the selector string, so the option is mainly useful if your first argument is not a string. * - `stopBeforeID` (int): Stop loading pages once page matching this ID is found (default=0). * - `startAfterID` (int): Start loading pages once page matching this ID is found (default=0). * - `lazy` (bool): Specify true to force lazy loading. This is the same as using the Pages::findMany() method (default=false). * - `loadOptions` (array): Optional associative array of options to pass to getById() load options. * @return PageArray|array PageArray of that matched the given selector, or array of page IDs (if using findIDs option). * * Non-visible pages are excluded unless an "include=x" mode is specified in the selector * (where "x" is "hidden", "unpublished" or "all"). If "all" is specified, then non-accessible * pages (via access control) can also be included. * @see Pages::findOne(), Pages::findMany(), Pages::get() * */ I use PHPStorm, not VSCode. It has a structure view similar to VSCode's outline. However, that just lists the method names etc. - I assume VSCode is similar* - so you need to go to the actual code to get the PHPDoc. In any case, you do need to be at the workstation and to have downloaded the module to see this. As I said, I appreciate that this is a personal thing, so please don't take it as a criticism, but you did ask whether a readme would be just as good, to which my answer is The video is very useful to give an introduction, but is longer than it would take to view a readme. Ideally there would be both, but the readme would be more complete, but less wordy (as described above). *PS I downloaded VSCode and I see that the outline does give variables as a drop-down, but not PHPDoc. Perhaps I should investigate it a bit more...
  21. What do you mean? I mean a summary of the functions and methods, including description of the arguments / options, what the method does / returns and any other notes regarding usage. Either a bit like the main PW API ref or what I did for my FieldtypeMeasurement module (not that I'm holding that up as a great example). Similar comment applies to RockMigrations ?
  22. Great video. Really comprehensive (but I had to view it in more than one sitting ? ). I would appreciate a separate guide to the API that one can dip into. And a really great-looking module ?
  23. Methods have parentheses, properties do not. Check the API reference if you are not sure.
×
×
  • Create New...