-
Posts
4,931 -
Joined
-
Days Won
321
Everything posted by Robin S
-
how to deal with upper/lowercase in repeater field ->sort()
Robin S replied to cabrooney's topic in General Support
-
I think what you're looking for is the "name" attribute. So if $inputfield is an Inputfield object: $inputfield->name // The name of the input element within the form, which has a suffix when inside a repeater $inputfield->hasField->name // The name of the corresponding field (if the inputfield is associated with a field)
-
how to make ProcessPageEdit-Form non editable for some roles?
Robin S replied to bernhard's topic in General Support
Both. It causes the inputfield to be rendered via renderValue() so there's no input, and even if somebody manually added an input in their browser any processing of the inputfield is prevented. -
Show Modified date of a page in page list in backend
Robin S replied to tires's topic in General Support
The AdminOnSteroids module has a feature that allows formatted dates in Page List via the template settings. See the "Date filter" section in the documentation here. -
Disable a field on the profile edit form
Robin S replied to schwarzdesign's topic in API & Templates
This is the crux of the issue. If the user shouldn't be able to edit a field then you don't want it included in the ProcessProfile form, but as you say this causes issues with inputfield dependencies. My suggestion is: 1. Only include editable fields in ProcessProfile. 2. Remove the showIf condition when the dependent fields appear in ProcessProfile. 3. Implement the same showIf logic to determine which fields are editable in ProcessProfile. Example... In this case I have fields text_1, text_2 and text_3 in the user template. The text_2 and text_3 fields have the showIf condition "text_1=foo". But I don't want the user to be able to edit text_1 in ProcessProfile so I disable that field in the ProcessProfile module settings: In /site/ready.php: $wire->addHookBefore('ProcessProfile::execute', function(HookEvent $event) { /** @var ProcessProfile $pp */ $pp = $event->object; // The fields that have a showIf dependency on a field not editable in ProcessProfile $dependent_fields = ['text_2', 'text_3']; // If dependency condition not met, remove dependent fields from the ProcessProfile editable fields if($event->wire()->user->text_1 !== 'foo') { $pp->profileFields = array_diff($pp->profileFields, $dependent_fields); } // Remove showIf condition from dependent fields $event->wire()->addHookAfter('Field::getInputfield', function(HookEvent $event) use ($dependent_fields) { $inputfield = $event->return; if(!in_array($inputfield->name, $dependent_fields)) return; $inputfield->showIf = ''; }); }); -
how to make ProcessPageEdit-Form non editable for some roles?
Robin S replied to bernhard's topic in General Support
Another way? // Make all field inputfields non-editable in Page Edit $wire->addHookBefore('ProcessPageEdit::execute', function(HookEvent $event) { if(!$event->wire()->user->hasRole('read-only')) return; $event->wire()->addHookAfter('Field::getInputfield', function(HookEvent $event) { $event->return->editable(false); }); }); // Remove the Settings tab $wire->addHookAfter('ProcessPageEdit::buildForm', function(HookEvent $event) { if(!$event->wire()->user->hasRole('read-only')) return; $form = $event->return; $tab = $form->find('id=ProcessPageEditSettings')->first(); $form->remove($tab); $event->object->removeTab('ProcessPageEditSettings'); }); -
Membership app, Processwire limitations on unique records?
Robin S replied to Kiwi Chris's topic in General Support
Getting OT here, but if the page names are publicly accessible anywhere but the email addresses are supposed to be private then you risk leaking the users' emails because base64 encoding is pretty recognisable and easily decoded by anyone. In that case it would be safer to encrypt the email addresses for the name using something like openssl_encrypt(). Also base64 strings can contain characters that are not URL safe so you'd need to replace those, e.g. "+" and "/". -
You can hook the render of a normal text inputfield and use a <datalist> element. Code example here:
-
The core Page Reference inputfields output only a page ID and expect a page ID as input. Possibly you could create your own custom inputfield module that works with a page path instead of an ID. Or here's a hacky solution that involves adding an extra "path" attribute to your Hanna tag... Hook: $wire->addHookAfter('HannaCodeDialog::buildForm', function(HookEvent $event) { // The Hanna tag that is being opened in the dialog $tag_name = $event->arguments(0); // The form rendered in the dialog /* @var InputfieldForm $form */ $form = $event->return; $config = $event->wire()->config; $modules = $event->wire()->modules; if($tag_name === 'select_page') { /* @var InputfieldPageListSelect $f */ $f = $modules->InputfieldPageListSelect; $f->name = 'selected_page'; $f->id = 'selected_page'; $f->label = 'Selected page'; $f->parent_id = 1268; $form->add($f); // Add JS file to Hanna Code Dialog form $js_file = $config->paths->templates . 'hannas/select_page.js'; if(is_file($js_file)) { $js_url = $config->urls->templates . 'hannas/select_page.js?v=' . filemtime($js_file); $form->appendMarkup = "<script src='$js_url'></script>"; } } }); select_page.js $(document).ready(function() { // Must use mousedown instead of click event due to frustrating event propagation issues across PW core // https://github.com/processwire/processwire-issues/issues/1028 $(document).on('mousedown', '.PageListActionSelect a', function(event) { var path; // Adapt unselect label to suit your language if($(this).text() === 'Unselect') { path = ''; } else { path = $(this).closest('.PageListItem').children('.PageListPage').attr('title'); } // Adapt path field ID to suit $('#path').val(path); }); });
-
custom page class: How to use __construct() or similar
Robin S replied to jom's topic in API & Templates
It's too early to access page fields/properties in the constructor. There is a ___loaded() method that's called when the page is loaded and ready. So you could have this: public function ___loaded() { $this->header = $this->title; } -
I don't mind about the sort order if you guys think changing it will be an improvement. Having "Main setup" in the middle seems a bit unusual but not a big deal.
-
custom page class: How to use __construct() or similar
Robin S replied to jom's topic in API & Templates
Page::__construct() takes a Template object as an argument: /** * Create a new page in memory. * * @param Template $tpl Template object this page should use. * */ public function __construct(Template $tpl = null) { if(!is_null($tpl)) { $tpl->wire($this); $this->template = $tpl; } $this->useFuel(false); // prevent fuel from being in local scope $this->parentPrevious = null; $this->templatePrevious = null; $this->statusPrevious = null; } So I think the constructor in your child class should be: public function __construct(Template $tpl = null) { parent::__construct($tpl); $this->header = 'some text'; } -
As long as the user has edit access for the template, you can use "Additional edit permissions and overrides" at Edit Template > Access:
-
In the "Selector string" setting for "Selectable pages" you can use "page" to refer to the current page, but only if you also specify a subfield using dot syntax. In your case you would use page.id to exclude children of a parent: template=item, parent!=page.id Unfortunately I don't think this is documented anywhere.
-
Solution for maintaing different crops of the same image
Robin S replied to joe_g's topic in General Support
I haven't used it, but I think that is what Croppable Image module is intended for: https://processwire.com/modules/croppable-image3/ -
Client-side image resize - EXIF and IPCT metadata loss
Robin S replied to dalibor's topic in General Support
Both client-side and server-side resizing strip the EXIF data. If you are able to get the EXIF data with the server-side option then possibly you are hooking before the resize and might be able to access and save the EXIF data then. But in my opinion PW shouldn't be stripping any data from an uploaded image that is to be the "original" from which variations are derived. There's an open issue about this, with fixes for both client-side and server-side resizing (ImageMagick only): https://github.com/processwire/processwire-issues/issues/1055 Just hoping and waiting for it to be applied to the core...- 2 replies
-
- 1
-
- meta content
- resize
-
(and 1 more)
Tagged with:
-
There's an open GitHub issue about this: https://github.com/processwire/processwire-issues/issues/956 Simplest solution for now is to create a different CKEditor field for use in the repeater.
-
Prevent links to current site from having protocol and host
Robin S replied to DrQuincy's topic in Getting Started
Do you mean that editors are pasting absolute internal links into the link dialog in CKEditor? If so you could try an education approach first, i.e. "Please create internal links via the fields in the link dialog". That way you won't get absolute internal links in the first place. Beyond that you could use a saveReady hook to do a string replacement in the relevant field(s): $pages->addHookAfter('saveReady', function(HookEvent $event) { $page = $event->arguments(0); // Perhaps limit by template as needed if($page->template == 'basic-page') { // Internal links: replace absolute href with relative href $page->body = str_replace('href="https://www.domain.com/', 'href="/', $page->body); } }); -
Styles / Format dropdown in Repeater opens on double click only
Robin S replied to Bike's topic in General Support
Not a solution for you sorry, but I can't reproduce this issue or the other one with the source dialog on a clean PW installation. In such cases the first thing to check is if the issue is reproducible on a clean installation of the latest PW dev version. If it is reproducible then there's a good chance it's a bug and you can create a GitHub issue that describes the steps needed to reproduce the issue. If the issue isn't reproducible on a clean PW installation then it's probably due to a third-party module or some issue with your own code. To isolate the cause you often need to follow a process of elimination. Progressively uninstall modules and remove any customisations you have made until you find the cause. It can be a tedious process but that's just a fact of life when debugging. The Module Disabler panel in Tracy Debugger is an easy way to disable selected modules. -
It looks like PhpStorm doesn't let you override the variable type in a PHPDoc comment when it already knows the type based on the source code. When you get a field value via $page->field_name it is accessed via the __get() magic method, so what PhpStorm is telling you in the case of $this->paymentAmount is actually more accurate than for $payment->paymentAmount, where we are sort of tricking PhpStorm through PHPDoc comments into treating overloaded properties as "real" properties of the Page object. These things aren't fixable issues for the module but are about how your specific IDE understands the code.
-
Where are you typing "$this"? In a template file? If you have a custom Page class HomePage then in your "home.php" template file you put this line at the top: /** @var HomePage $page */ Then you access any fields or methods of the HomePage class from $page. AutoTemplateStubs gives you code assistance for the fields and the HomePage methods. In a template file $this refers to a TemplateFile object. It doesn't give you access to fields or methods of the HomePage class. If you are typing "$this" in the file for a class that extends Page (e.g. HomePage.php) then you are working in file that this module is not designed to support. But PhpStorm automatically gives you code assistance for methods in the class... ...and even though it wasn't something I had in mind when this module was developed (because custom Page classes didn't exist then) you do get assistance for field names too: If this doesn't answer your question please give me more explanation of what you're wanting to do. Maybe screenshots would help.
-
I'm not sure I understand. This module is specifically for code hints in template files - it doesn't do anything for any other files you might have in your site. If you are using custom page classes then see the notes in the readme about that, but again this only has an effect on the template file. When you are editing any other class file, module file, etc then this module isn't going to do anything. But PhpStorm should automatically understand the $this keyword in a class context anyway.
-
There's no built-in option for that, but nearly everything is possible in PW with hooks and some lateral thinking. ? Below is one way you could achieve the goal. In my example I'm using "country" pages under a "countries" parent but the same idea will work for your case of children under the home page. Create a "multiple pages" Page Reference field named "top_pages" and add it to the template of the parent page. The field should be limited to the selection of child pages, so in "Selectable pages" set the "Selector string" option like this: Here "page" is a special keyword that means "the page that is currently being edited". Now edit the parent page and select the child pages you want to be sorted at the top. On the Children tab I have this: So I want the children sorted by title, apart from the children selected in the top_pages field. In /site/ready.php I have the following hooks, which affect the paginated listing of child pages in ProcessPageList: // Before ProcessPageList::find $wire->addHookBefore('ProcessPageList::find', function(HookEvent $event) { $selector_string = $event->arguments(0); $parent = $event->arguments(1); // Return early if the parent page doesn't include the top_pages field, or if the field is empty if(!$parent->hasField('top_pages') || !$parent->top_pages->count) return; // Convert selector string to Selectors object to make it easier to examine and modify $selectors = new Selectors($selector_string); $start = $selectors->get('field=start'); $limit = $selectors->get('field=limit'); // Return early if Selectors object does not conform to what is expected for some reason if(!$start || !$limit) return; // Get start and limit as integers $start_value = (int) $start->value; $limit_value = (int) $limit->value; if($start_value === 0) { // This is the first pagination // Reduce the limit by the count of the top pages $limit->value = $limit_value - $parent->top_pages->count; // Set a custom property on the ProcessPageList object // to indicate that the top pages should be prepended to the children $event->object->add_top_pages = true; } else { // This is not the first pagination // Reduce the start by the count of the top pages $start->value = $start_value - $parent->top_pages->count; } // Set the selector string argument to the string value of $selectors $event->arguments(0, (string) $selectors); }); // After ProcessPageList::find $wire->addHookAfter('ProcessPageList::find', function(HookEvent $event) { $parent = $event->arguments(1); // If there are top pages to add... if($event->object->add_top_pages) { // Prepend the top pages to the children $children = $event->return; $children = $parent->top_pages->add($children); $event->return = $children; // Unset the custom property now that the job is done unset($event->object->add_top_pages); } }); Result: Note: with this approach you must not select more "top pages" than the pagination limit for ProcessPageList (the default is 50).