Jump to content

Robin S

  • Content Count

  • Joined

  • Last visited

  • Days Won


Everything posted by Robin S

  1. v0.1.1 released with support for Repeaters and comma as decimal separator. Thanks @David Karich!
  2. Thanks, will discuss with you over on the PR.
  3. Do you know if there's a way to query some Shopify API to get all the IDs and titles of products that exist in the Shopify store? So that a client only needs to maintain products in Shopify but the PW site could run a cron job where every day it gets all the product IDs and titles and automatically creates pages for them?
  4. This markup actually belongs to InputfieldWrapper rather than individual inputfield renders. There is the InputfieldWrapper::setMarkup method that you can use to customise the markup that is rendered by InputfieldWrapper. See the defaultMarkup property as a starting point for what can be customised: /** * Markup used during the render() method - customize with InputfieldWrapper::setMarkup($array) * */ static protected $defaultMarkup = array( 'list' => "<ul {attrs}>{out}</ul>", 'item' => "<li {attrs}>{out}</li>", 'item_label' => "<label class='InputfieldHeader ui-widget-header{class}' for='{for}'>{out}</label>", 'item_label_hidden' => "<label class='InputfieldHeader InputfieldHeaderHidden ui-widget-header{class}'><span>{out}</span></label>", 'item_content' => "<div class='InputfieldContent ui-widget-content{class}'>{out}</div>", 'item_error' => "<p class='InputfieldError ui-state-error'><i class='fa fa-fw fa-flash'></i><span>{out}</span></p>", 'item_description' => "<p class='description'>{out}</p>", 'item_head' => "<h2>{out}</h2>", 'item_notes' => "<p class='notes'>{out}</p>", 'item_detail' => "<p class='detail'>{out}</p>", 'item_icon' => "<i class='fa fa-fw fa-{name}'></i> ", 'item_toggle' => "<i class='toggle-icon fa fa-fw fa-angle-down' data-to='fa-angle-down fa-angle-right'></i>", // ALSO: // InputfieldAnything => array( any of the properties above to override on a per-Inputifeld basis) ); But this applies to the whole InputfieldWrapper. In terms of making it more targeted you can set markup for individual inputfield types by using the inputfield class name as a key: $wrapper->setMarkup([ 'InputfieldText' => [ 'item' => '<li {attrs}><p>Markup before</p>{out}<p>Markup after</p></li>', ], ]); But you can't target individual inputfields by name or something like that. LoginRegisterPro has a similar setMarkup() method but has the added feature of letting you use "name=some_inputfield_name" as a key: https://processwire.com/store/login-register-pro/docs/#customizing-markup-and-or-class-attributes-html It would be cool if a feature like that was added to the core InputfieldWrapper::setMarkup method.
  5. I can see why it's awkward for your use case, but the getMarkup() and getText() methods are working as per their documentation as I understand it. The argument can be one of two things: "field name" or "markup string with field {name} tags in it". The method has to distinguish between those two possibilities and it does that by looking for the presence of "{" and "}" - if those characters are not found it treats the string as a field name. Basically you're requesting a new feature which is a third possible argument to these methods, namely a string that isn't a field name and doesn't have {name} tags in it. I'm sure Ryan would consider that if you raise it in the requests repo, but given how many existing requests there are you'll probably want to come up with a workaround in the meantime. You could do this... echo $page->getMarkup($modules->get('MyModule')->MyTextFormatSetting) ?: $modules->get('MyModule')->MyTextFormatSetting; echo $page->getText($modules->get('MyModule')->MyTextFormatSetting) ?: $modules->get('MyModule')->MyTextFormatSetting; ...or in the case of getMarkup() the method is hookable so you could do this... $wire->addHookAfter("Page::getMarkup", function(HookEvent $event) { $key = $event->arguments(0); if(!$event->return) $event->return = $key; });
  6. I suggest setting the maxFiles setting of the inputfield dynamically with a hook. There are many different methods you could potentially hook - I don't know if you're talking about Page Edit, ProcessProfile, ProcessUser, or some form on the front-end, and I don't know if by "group" you mean "role". But here is something that you can adapt to suit: $wire->addHookBefore("InputfieldImage::render", function(HookEvent $event) { /* @var InputfieldImage $inputfield */ $inputfield = $event->object; $field = $inputfield->hasField; if(!$field || $field->name !== 'images') return; $user = $event->wire('user'); if($user->hasRole('foo')) { $inputfield->maxFiles = 1; $inputfield->description = 'You may upload a maximum of 1 image.'; } elseif($user->hasRole('bar')) { $inputfield->maxFiles = 2; $inputfield->description = 'You may upload a maximum of 2 images.'; } else { $inputfield->maxFiles = 0; // No limit } });
  7. @maddmac, I tested here inside a repeater and it's working correctly. You might need to clear cached files from your browser to get the updated CKEditor plugins that are included in the module. As far as I know plugins don't get automatic cache busting in CKEditor and I don't know any way to do this manually due to the way external plugins are loaded. If you do a hard refresh in Page Edit it should fix things.
  8. Thanks! I use findIDs() when I'm using the PW API in conjunction with SQL queries where I only need the page IDs in the query. Sometimes I only need a single page ID and so having a getID() makes that simpler and corresponds to the find() and get() methods.
  9. The thing is, it's a risk that's carried by the site developer rather than the module developer. If an autoload module adds scripts and styles to $config->scripts and $config->styles it's your site that's at risk of breaking, not the module. Personally I'd never want to take that risk. The simple solution is to create your own custom FilenameArray in $config that is reserved for front-end usage. This old post from @Soma explains how:
  10. @ryan, great timing on the $pages->has() method - I requested essentially this just the other day: https://github.com/processwire/processwire-requests/issues/358 But the method name has() seems not so intuitive - if you didn't know better you would think this returns a true/false value. I think $pages->getID() would be more intuitive - maybe that could be added as an alias?
  11. As far as I can see this isn't possible/practical. Although the cropper library does allow for "minCropBoxWidth" and "minCropBoxHeight" options these can only be set when the cropper is initialised. To change the options you have to destroy the existing cropper and reinitialise it with complete new options, but the library provides no ability to get the existing options (as supplied by the PW core) before destroying the old cropper. And I don't want to duplicate and maintain ProcessPageEditImageSelect.js to be able to recreate all the options. The options that can be updated dynamically are very limited - only setAspectRatio() and setDragMode() methods are available. If anyone can see a way to set minCropBoxWidth and minCropBoxHeight dynamically then let me know. So as @horst suggested, use CroppableImage instead if you need to set minimum crop sizes.
  12. v0.3.0 released. Adds support for PageListSelect and PageListSelectMultiple inputfield types. Also adds support for PageAutocomplete inputfield type but only when used via a HannaCodeDialog::buildForm hook. From the module readme: @maddmac, I think you must be referring to PageListSelect which is used in InputfieldSelectorSelectID rather than that module as a whole. In v0.3.0 you can now use PageListSelect with HannaCodeDialog, either by setting a "attributename__type=pagelistselect" attribute in the tag settings or by using a HannaCodeDialog::buildForm hook.
  13. That's not how this module works. It's just gives you code completion for fields that belong to the template of the current page - $config is an API variable so is something totally different. But you can add type hints for the API variables that PW makes available to template files in a DocBlock at the top of your template files. More info:
  14. Sorry, I never get to work on multi-language sites here in NZ so I don't know about multi-language features.
  15. As I understand it, PHP_EOL means "the end of line character for the current system". So when the code executes on Windows it equates to "\r\n" and when it executes on *nix it equates to "\n". It's cross-platform when it comes to outputting a line-break character, but not when it comes to looking for line-break characters in user input from Windows and *nix. I usually do this... $lines = explode("\n", str_replace("\r", "", $input)); ...which is faster than regex.
  16. @kunago, I think Croppable Image 3 is probably the best option for a lot of cases (e.g. you don't want the user to create a cropped image smaller than the given pixel dimensions), but inspired by your question I created this module:
  17. Inspired by a recent question. Image Crop Ratios Allows preset aspect ratios to be defined per image field for the ProcessWire image crop tool. The module adds a select dropdown to the crop tool. Choose an aspect ratio and the crop area will be fixed to that ratio. Screencast Installation Install the Image Crop Ratios module. Configuration Default aspect ratios for all image fields can be defined in the module config. Aspect ratios for specific image fields can be defined on the Input tab of the field settings. You can override the ratio settings in template context if needed. Insert a hyphen as the first item in the ratio settings unless you want to force a ratio to be applied to the crop tool. The hyphen represents a blank option that allows a free crop area to be drawn. Usage Click the "Crop" link on the details view of an image thumbnail. Click the "Crop" icon at the top of the editor window. Choose an option from the "Ratio" select dropdown. https://github.com/Toutouwai/ImageCropRatios https://modules.processwire.com/modules/image-crop-ratios/
  18. You could add the datalist to a normal text field using a hook in /site/ready.php: $wire->addHookBefore('InputfieldText::render', function(HookEvent $event) { /* @var InputfieldText $inputfield */ $inputfield = $event->object; $field = $inputfield->hasField; if($field && $field->name === 'my_field') { $inputfield->attr('list', 'my-list'); $inputfield->appendMarkup = <<<EOT <datalist id="my-list"> <option value="One"> <option value="Two"> <option value="Three"> </datalist> EOT; } });
  19. This seems to do the job: $wire->addHookAfter('ProcessPageEdit::buildFormContent', function(HookEvent $event) { /* @var InputfieldWrapper $wrapper */ $wrapper = $event->return; // Do some check on user role if($event->wire('user')->isSuperuser()) { $inputfields = $wrapper->getAll(); foreach($inputfields as $inputfield) { $inputfield->required = 0; } } });
  20. You could use a hook... $wire->addHookBefore('ProcessPageList::find', function(HookEvent $event) { $selector = $event->arguments(0); /* @var Page $page */ $page = $event->arguments(1); if($page->template == 'your_parent_template') { $selector .= ", sort=date, sort=title"; $event->arguments(0, $selector); } }); ...or this module: https://modules.processwire.com/modules/process-page-list-multiple-sorting/
  21. ProCache serves up a cached static HTML file using mod_rewrite rules in .htaccess It checks if... the request method is not POST there is no query string there is no wire_challenge or wires_challenge cookie a cached HTML file exists for the requested URL ...and if all of this is true it serves the HTML file. I recently opened a support topic asking for help using ProCache in conjunction with template cache (my site has a lot of logged-in users that I'd like to serve cached pages to). When Ryan replies over the weekend I'll mention the discussion here and ask if he'd consider improving the template cache using the principle you're experimenting with.
  22. That sounds like a very good enhancement! It would be great to have a solution like this implemented in the core template cache, so it doesn't require any changes to a core file and is available to those not using AIOM+. An important factor is if enough information is known so early in the load process to deliver all the standard template cache features for things like multi-language, URL segments, logged-in users option and cache-disabling GET/POST vars. But a lot of that is knowable from the URL alone so I think your approach should work. If you have time, maybe you could experiment with this separate from AIOM+ and PM Ryan to see if he'd consider adding it to the core? If it works it would add another "selling point" to PW.
  23. Sounds like the effects of a shortcut key combination. Maybe you have the Admin Hot Keys module (or something like it) installed?
  24. Hi @matjazp, I'm not currently a user of this module, but I'm interested in this feature and your comments in the readme: What was the inefficiency you noticed in the core template cache feature and how did you make the AIOM+ cache more efficient? Is there an improvement that could me made to the core template cache that would be worth communicating to @ryan?
  25. Building on @BitPoet's code, here's an alternative way you could add labels to the select options: $wire->addHookBefore('ProcessPageEditLink::execute', function(HookEvent $event) { $input = $event->wire('input'); $page = $event->wire('pages')->get($input->get->id); // Do some check on $page to return early when not applicable $anchors = $input->get->anchors ?: []; $my_anchors = [ 'some_anchor' => 'Some anchor', 'other_anchor' => 'Other anchor', 'third_anchor' => 'Third anchor', ]; $anchors = array_merge($anchors, array_keys($my_anchors)); $input->get->anchors = $anchors; $event->wire()->addHookBefore('InputfieldSelect::render', function(HookEvent $event) use ($my_anchors) { $inputfield = $event->object; if($inputfield->name !== 'link_page_anchor') return; $options = $inputfield->options; $inputfield->options = []; foreach($options as $option) { $anchor_name = ltrim($option, '#'); if(isset($my_anchors[$anchor_name])) {; $inputfield->addOption($option, $my_anchors[$anchor_name]); } else { $inputfield->addOption($option); } } }); });
  • Create New...