-
Posts
1,306 -
Joined
-
Last visited
-
Days Won
13
Everything posted by Juergen
-
Hello @abmcr Why do you not extend the button drop down with your pdf feature instead of adding a new button. BTW: Adding a second save button was the way to go a at the time where PW did not offer the possibility for a drop down button. To get an additional dropdown level for PDF, please put the following piece of code inside your site/templates/init.php or site/templates/ready.php. If the files do not exist by default, you have to create them manually. $wire->addHookAfter('ProcessPageEdit::getSubmitActions', function($event) { $actions = $event->return; $actions[] = [ 'value' => 'value of action, i.e. view, edit, add, etc', 'icon' => 'file-pdf-o', 'label' => 'Pdf', 'class' => 'btn_pdf_plan', ]; $event->return = $actions; }); Only to mention: do not forget to change the value to your needs (fe save in your case). Best regards
-
Hello @ all I am using a lot of hooking of methods and I want to optimize the performance of a module a little. In my case I use the following Hooks inside my modules init() method: public function init() { $this->addHookBefore('Page::render', $this, 'function1'); $this->addHookBefore('Page::render', $this, 'function2'); $this->addHookBefore('Page::render', $this, 'function3'); $this->addHookBefore('Page::render', $this, 'function4'); } As you can see, I am always hooking the same method (Page::render) to run different functions. The functions itself are declared outside of the init() method. My question: Would it have an impact on the performance if I would fe summarize function1 to function4 into one function (see below) or does it not matter? public function init() { $this->addHookBefore('Page::render', $this, 'summarizeFunction'); } protected function summarizeFunction() { $this->function1(); $this->function2(); $this->function3(); $this->function4(); } As you can see, I have only 1 hook left, that hooks into Page::render - not 4 as before. I have not try it, if there would be a significant performance boost or not. I only want to ask some other devs if they have experiences if this could be optimize the performance a little bit or not. Best regards
-
How to hook after field configuration is saved [SOLVED]
Juergen replied to Juergen's topic in Module/Plugin Development
Thanks @Jan Romero What a silly mistake!!! ??You are right: Sure, that was the mistake. I know that it must be $event and not $field, but I have overlooked this silly mistake over and over and I was wondering why it did not work. I have tried it with $event->object and $event->arguments(0).... BTW: Now both Hooks work with $event->arguments(0)!! Thanks for your help!!! Thanks for helping me -
Hello @all I have searched the forum and studied the PHP class files, but I cannot find a way to achieve the following one: I want to run a Hook after the pass field (a system field) is saved. It should also work with other inputfields, but in my case I need to run it especially on the pass field. To clearify: I want to run the Hook if the "Edit field: pass" page is saved. I have tried the following inside the init() function of my module: $this->addHookAfter('Fields::save', $this, 'updateBlacklist'); The appropriate method: protected function updateBlacklist(HookEvent $event): void { $field = $field->object; if ($field->name == 'pass') { $this->wire('session')->message('works'); } } But it does not work. As mentioned by @LostKobrakai at this topic, " Field::save is called when a fieldsettings should be saved", but it seems that nothing happens. Could anyone point me into the right direction?
-
Thanks @flydev I thought that this is called type declaration. I have used this for a while, but I did not knew, that this was called union type. Now I have learnt something new today.? The problem is solved for flashmaster82, we have discussed the issue via PM. The module itself should check if version 8.1 is installed. 'requires' => ['PHP>=8.1.0', 'ProcessWire>=3.0.181'] So it should give you a warning message before the installation process starts.
-
Hello Luigi I found the problem: The blank profile uses markup regions and therefore you have to copy the code of the form between a div with the id "content". Take a look at the code afterwards: <?php namespace ProcessWire; /** * Demonstration of a complex form * You can copy this code to a template to show the form * If you use these classes inside another namespace (fe ProcessWire) like in this case, you have to take care about the namespace in front of the class instances. * Fe you have to use $form = new \FrontendForms\Form('myForm'); or $form = new FrontendForms\Form('myForm'); and not only $form = new Form('myForm'); */ echo '<div id="content">'; echo '<h1>Complex form</h1>'; $form = new \FrontendForms\Form('registration'); $form->setMinTime(8); $form->setMaxTime(3600); $form->setMaxAttempts(5); $form->setErrorMsg('Ouups! There are some errors.'); $form->setSuccessMsg('Congratulation! There are no errors.'); $userdata = new \FrontendForms\FieldsetOpen(); $userdata->setLegend('User data')->append('<p>Please fill out all required fields.</p>'); $form->add($userdata); $singleRadio = new \FrontendForms\InputRadio('single'); $singleRadio->setLabel('Single radio button'); $singleRadio->setAttribute('value', 'single'); $singleRadio->setRule('required'); $singleRadio->setNotes('This field makes no sense'); $form->add($singleRadio); $gender = new \FrontendForms\InputRadioMultiple('gender'); $gender->setLabel('Gender')->setAttribute('class', 'myextralabelclass'); $gender->setDefaultValue('Male'); $gender->addOption('Male', 'Male')->setAttribute('class', 'male'); $gender->addOption('Female', 'Female')->setAttribute('class', 'female'); $gender->addOption('Diverse', 'Diverse')->setAttribute('class', 'diverse'); $gender->getFieldWrapper()->setAttribute('class', 'uk-width-1-1')->removeAttributeValue('class', 'uk-margin'); $form->add($gender); $firstname = new \FrontendForms\InputText('firstname'); $firstname->setLabel('Firstname'); $firstname->setRule('required'); $firstname->getFieldWrapper()->prepend('<div class="uk-child-width-1-2" data-uk-grid>')->removeAttributeValue('class', 'uk-margin'); $form->add($firstname); $lastname = new \FrontendForms\InputText('lastname'); $lastname->setLabel('Lastname'); $lastname->setRule('required'); $lastname->getFieldWrapper()->append('</div>')->removeAttributeValue('class', 'uk-margin'); $form->add($lastname); $street = new \FrontendForms\InputText('street'); $street->setLabel('Street'); $street->setRule('required'); $street->getFieldWrapper()->setAttribute('class', 'uk-width-3-4')->prepend('<div data-uk-grid>')->removeAttributeValue('class', 'uk-margin'); $form->add($street); $number = new \FrontendForms\InputText('number'); $number->setLabel('Number'); $number->setRule('required'); $number->setRule('integer'); $number->getFieldWrapper()->setAttribute('class', 'uk-width-expand')->append('</div>')->removeAttributeValue('class', 'uk-margin'); $form->add($number); $email = new \FrontendForms\InputEmail('email'); $email->setLabel('Email address'); $email->setSanitizer('email'); $email->setRule('required'); $email->setRule('email'); $email->setRule('emailDNS'); $email->getFieldWrapper()->prepend('<div class="uk-child-width-1-3" data-uk-grid>')->removeAttributeValue('class', 'uk-margin'); $form->add($email); $phone = new \FrontendForms\InputTel('phone'); $phone->setLabel('Phone'); $phone->setRule('integer'); $phone->getFieldWrapper()->removeAttributeValue('class', 'uk-margin'); $form->add($phone); $fax = new \FrontendForms\InputText('fax'); $fax->setLabel('Fax'); $fax->setRule('required')->setCustomFieldName('Fax number'); $fax->getFieldWrapper()->append('</div>')->removeAttributeValue('class', 'uk-margin'); $form->add($fax); $birthday = new \FrontendForms\InputDate('birthday'); $birthday->setLabel('My birthday'); $birthday->setRule('required')->setCustomFieldName('The day of my birth'); $birthday->setRule('date'); $form->add($birthday); $children = new \FrontendForms\InputNumber('children'); $children->setLabel('Number of children'); $children->setAttribute('min', '0'); $children->setAttribute('max', '15'); $children->setRule('required')->setCustomMessage('Please enter how much children do you have'); $form->add($children); $userdataClose = new \FrontendForms\FieldsetClose(); $form->add($userdataClose); $interestsOpen = new \FrontendForms\FieldsetOpen(); $interestsOpen->setLegend('My interest'); $form->add($interestsOpen); $interests = new \FrontendForms\InputCheckboxMultiple('interest'); $interests->setLabel('I am interested in'); $interests->setDefaultValue('Web-design'); $interests->addOption('Music', 'Music')->setChecked(); $interests->addOption('Web-design', 'Web-design'); $interests->addOption('Sports', 'Sports')->setChecked(); $interests->addOption('Photography', 'Photography'); $firstname->setRule('required'); $interests->alignVertical(); $form->add($interests); $php = new \FrontendForms\Select('php'); $php->setLabel('My preferred PHP version is'); $php->setDefaultValue('PHP 8'); $php->addOption('PHP 6', 'PHP 6'); $php->addOption('PHP 7', 'PHP 7'); $php->addOption('PHP 8', 'PHP 8'); $form->add($php); $css = new \FrontendForms\SelectMultiple('css'); $css->setLabel('I have knowledge in'); $css->setDefaultValue('Less', 'CSS 1'); $css->addOption('CSS 1', 'CSS 1'); $css->addOption('CSS 2', 'CSS 2'); $css->addOption('CSS 3', 'CSS 3'); $css->addOption('Less', 'Less'); $css->addOption('Sass', 'Sass'); $form->add($css); $interestsClose = new \FrontendForms\FieldsetClose(); $form->add($interestsClose); $accept = new \FrontendForms\InputCheckbox('accept'); $accept->setLabel('I accept the data privacy'); $accept->setRule('accepted')->setCustomMessage('You have to accept the data privacy'); $form->add($accept); $newsletter = new \FrontendForms\InputCheckbox('newsletter'); $newsletter->setLabel('I want to register to the newsletter'); $newsletter->setChecked(); $form->add($newsletter); $button = new \FrontendForms\Button('submit'); $button->setAttribute('value', 'Send'); $form->add($button); if ($form->isValid()) { print_r($form->getValues()); // or do what you want } // render the form echo $form->render(); echo '</div>'; As you can see the form code is between the opening and closing tags of the content container. BTW I have sent you a PM with the new version. Best regards Jürgen
-
I am sorry, that I cannot help you, but I am unable to reproduce the error and without any error messages I have no starting point. As written above, I am working on the improved version, which will be (hopefully) ready to use within the next days. I can inform you if it will be ready to download if you want. Best regards Jürgen
-
Sorry, but I cannot post a possible cause for this behavior here. I have removed all fields and added it step by step to the configuration form again until the form was completed. This time no problem occurs. I cannot reproduce the failure, but I guess there was a JS problem, because the button could not be clicked to submit the form. So the thread will be closed.
-
Thanks @Robin S for your feedback. I have disabled all inputfields on the configuration form except this InputfieldInteger and now it works too. It seems that there will be a combination of fieldsets, other inputfields, whatever that causes this strange behavior. I keep this thread open, until I have found the reason and post it her. Best regards Jürgen
-
Hello @ all, today I have discovered a possible bug on the InputfieldInteger form field with the step attribute. After adding the step attribute the submit button to save the module configuration page does not work anymore. This behavior only occurs if the type of the InputfieldInteger is set to number. If set to text everything works fine. Take a look at https://processwire.com/api/ref/inputfield-integer/ Lets take a look at the code: // this does not work -> input type set to number $integerfield = $this->modules->get('InputfieldInteger'); $integerfield->inputType = 'number'; $integerfield->step = 10; // this works $integerfield = $this->modules->get('InputfieldInteger'); $integerfield->inputType = 'text'; $integerfield->step = 10; I did not get any error message, but as mentioned above, the submission does not take place. If someone could test this on a configurable module and confirm or deny this behavior, before I open a new issue. Best regards Jürgen
-
Please also check in the module configuration settings that in the blacklist of forbidden IDs is not your IP address listed. I can remember that in the old version a Javascript mistake causes that the local IP address was stored inside this field and has to be deleted manually. This was a bug. Currently I am working on an improved version without JS and it works as expected - but this version has to be tested and is not ready to use for the moment. So please check this setting too.
-
Usually not, but in your case it seems that a loop produces the repeats, but I dont know where it is located. I have tried it o a local installation (XAMPP) and it works as expected. So the cause should be somewhere on your side. Can you tell me which of the PW profiles do you use (Uikit, blank profile, blog,...) Do you have the installation locally on XAMPP etc too or is it public reachable, so I can take a look. Best regards
-
Problem using PHP script as image src in ProcessWire
Juergen replied to Juergen's topic in Module/Plugin Development
Thanks @teppo I have thought that this will be the problem. I think I will create an extra folder with the required permissions for this reason. -
Hello @ all I want to create a captcha image for a form, which can be reloaded on demand, if the user cannot read the captcha. The form will be created by a module, that is why this question is inside this category. For this reason I want to create the captcha image on the fly by using a PHP file as image source instead of an image file. // in a template file $path = $config->urls->assets.'files/captchaimage.php'; echo '<img src="'.$path.'" />'; As you can see: the image source is not an image file (fe. captcha.png), it is a PHP file which creates the image on the fly. I have added this file to site/assets/files because this folder can be reached from outside. The captchaimage.php consists of the following code (only for testing purposes): <?php header("Content-Type: image/png");//change the php file to an image $im = @imagecreate(110, 20) or die("Cannot Initialize new GD image stream");//creates an image with the resolution x:110 y:20 $background_color = imagecolorallocate($im, 0, 0, 0);//create a color with RGB $text_color = imagecolorallocate($im, 233, 14, 91); imagestring($im, 1, 5, 5, "A Simple Text String", $text_color);//draws text to the image with the font:1 xpos:5 ypos:5 imagepng($im);//sends the image data to the user imagedestroy($im);//destroys the image from the server ?> This is not the real code for producing the captcha - it is only a simple code to create an image. My problem is, that I cannot output the image on the template. I always get the message, that the image could not be loaded. Can someone point me in the right direction, why this does not work? Thanks in advance
-
New URL hooks do not consider user language
Juergen replied to Juergen's topic in Module/Plugin Development
I found a workaround: Put the user language inside a session variable and call this session variable inside the hook. public function init() { //set language id inside a session variable for later usage in url hook $this->wire('session')->set('userlang', $this->wire('user')->language->id); // Show details about the blocked IP address inside a panel $this->wire->addHook('/detail-view/{ip}', function ($event) { $userLang = $this->wire('session')->get('userlang'); // grab current user lang from session $this->wire('user')->language = $userLang; // here comes the code }); } Not really elegant, but it works. Now translatable strings work as expected. -
New URL hooks do not consider user language
Juergen replied to Juergen's topic in Module/Plugin Development
Maybe could it be the same issue as in this topic? Bug report - Get $user->language in hook Pages::saveReady -
In PW version 3.0.173, new hooks for urls were introduced (ProcessWire 3.0.173 core updates: New URL hooks). The problem is, I am using translatable strings inside the hook, but the language is always default. I can remember there was also a problem within another hook and Ryan mentioned that this is the usual behaviour, because language is always detected before and after the hook but not within. Maybe someone struggles with the same problem and has found a solution to post it here? I need translatable strings inside this hook.
-
Hello I have created a module which contains a MarkupAdminDataTable with a lot of entries of statistic data in the module configuration. Inside this table I have added a "View details" button to each table row (entry). By clicking this button I want to show some log file information about this entry inside the panel. This information will come from a php file, not from an admin page. Therefore I cannot load the content via href attribute. Is it possible to load content inside this panel without creating an admin page and how?
-
Hello, I have a multilang field in my module configuration - it is a text field. // Required hint custom text $requiredText = wire('modules')->get('InputfieldText'); $requiredText->name = 'input_requiredText'; $requiredText->label = $this->_('Hint that all required fields have to be filled out'); $requiredText->value = $this->input_requiredText; // here is the value $reqText = $this->_('This text will be displayed on the form depending on your settings.') . '<br>'; $reqText .= $this->_('If nothing is entered, a default text will be displayed instead.'); $requiredText->description = $reqText; $requiredText->notes = $this->_('Can be overwritten on each form.'); $requiredText->useLanguages = true; // enable multilanguage for this field $requiredText->showIf = "input_requiredHintPosition!=none"; $fieldset1->add($requiredText); The values will be stored as followed inside the db: "input_requiredText":"My custom text","input_requiredText__1012":"Das ist mein Custom Text","input_requiredText__1013":"" I want to output the values depending on the users language on the frontend Question: Is there an easy way to grab this values on the frontend?
-
Great idea @Anonimas I have integrated both. You can change/customize the text for the required fields with setRequiredText() method. $form->setRequiredText('This is my customized text, that you have to fill out all required fields.') I have also added EOT for better readability. Please download and install the module once more. Thanks for your ideas.
-
Hi Anonimas Inspired by your question I have added a new method to add the wrapper div over all form fields (including hidden fields too). $form->setFormElementsWrapper()->setAttribute('class', 'mycustomclass'); By default a unique CSS id will be added, but as you can see in the example above, you can also add a class attribute (or other attributes) too. <form> <div id="formelementswrapper" class="mycustomclass"> .... </div> </form> To use this method, please download version 2.0.9 from GitHub. Alternatively replace the Form.php. This file includes all the changes and additions. BTW could you please tell me, what is the intention for you to wrap all form fields in an extra div? Best regards Jürgen