Jump to content

Juergen

Members
  • Posts

    1,226
  • Joined

  • Last visited

  • Days Won

    10

Everything posted by Juergen

  1. Hi sp1key! The objects are declared at the top of the file (take a look at line 94 and below of the Form.php). // Classes protected $alert; protected $requiredHint; I do not think so, because the classes will (should) be loaded on demand and not all at once, but you are right: it is strange that it makes differences between classes. I will take a closer look today on the issue especially on the autoloader and the paths. I guess the amount of directories should not cause this issue. Best regards
  2. Maybe there could be a problem with new instances without the namespace. I have only tested this module locally and and never on live servers. Thats why I did not recognize that there could be a problem with namespaces. Anyway: I have added the namespace to every new instance of a FrontendForms class on every file inside the module (I hope I have not overlooked a new instance ?). A lot of files were modified - so please download the module once more. I have not bumped up the version number. BTW: I could not find different spellings on the namespaces inside the files. If you have discovered that I have written it in different ways please let me know where. Best regards
  3. Hello! I have replaced my own class loader with the ProcessWire classLoader, which handles namespaces better and here on my windows system and XAMPP it works. Could you please reinstall the module with the new version 2.0.3 and let me know if the problem is gone now. Best regards.
  4. I have created a fresh install with the beginner theme, but I am not able to reproduce your errors. I have integrated the code inside the basic-page and as you can see the form is still there and it works. Here is the complete code of the basic page (templates/basic-page.php): <?php namespace ProcessWire; /** @var Page $page */ include('./_head.php'); // include header markup ?> <div id='content'><?php // output 'headline' if available, otherwise 'title' echo "<h1>" . $page->get('headline|title') . "</h1>"; $form = new \FrontendForms\Form('contactform'); $gender = new \FrontendForms\Select('gender'); $gender->setLabel('Gender'); $gender->addOption('Mister', 'Mister'); $gender->addOption('Miss', 'Miss'); $form->add($gender); $surname = new \FrontendForms\InputText('surname'); $surname->setLabel('Surname'); $surname->setRule('required'); $form->add($surname); $name = new \FrontendForms\InputText('lastname'); $name->setLabel('Last Name'); $name->setRule('required'); $form->add($name); $email = new \FrontendForms\InputText('email'); $email->setLabel('E-Mail'); $email->setRule('required'); $email->setRule('email'); $form->add($email); $subject = new \FrontendForms\InputText('subject'); $subject->setLabel('Subject'); $subject->setRule('required'); $form->add($subject); $message = new \FrontendForms\Textarea('message'); $message->setLabel('Message'); $message->setRule('required'); $form->add($message); $privacy = new \FrontendForms\InputCheckbox('privacy'); $privacy->setLabel('I accept the privacy policy'); $privacy->setRule('required')->setCustomMessage('You have to accept our privacy policy'); $form->add($privacy); $button = new \FrontendForms\Button('submit'); $button->setAttribute('value', 'Send'); $form->add($button); if ($form->isValid()) { print_r($form->getValues()); // do what you want } // render the form echo $form->render(); // output bodycopy echo $page->get('body'); // render navigation to child pages renderNav($page->children); // TIP: Notice that this <div id='content'> section is // identical between home.php and basic-page.php. You may // want to move this to a separate file, like _content.php // and then include('./_content.php'); here instead, on both // the home.php and basic-page.php template files. Then when // you make yet more templates that need the same thing, you // can simply include() it from them. ?></div><!-- end content --> <aside id='sidebar'><?php // rootParent is the parent page closest to the homepage // you can think of this as the "section" that the user is in // so we'll assign it to a $section variable for clarity $section = $page->rootParent; // if there's more than 1 page in this section... if ($section->hasChildren > 1) { // output sidebar navigation // see _init.php for the renderNavTree function renderNavTree($section); } // output sidebar text if the page has it echo $page->get('sidebar'); ?></aside><!-- end sidebar --> <?php include('./_foot.php'); // include footer markup ?> You do not need to integrate something inside the init.php to make it work. I have only integrated the following 2 lines inside the init.php. Here is the complete code of my init.php (templates/_init.php) <?php namespace ProcessWire; /** * Initialization file for template files * * This file is automatically included as a result of $config->prependTemplateFile * option specified in your /site/config.php. * * You can initialize anything you want to here. In the case of this beginner profile, * we are using it just to include another file with shared functions. * */ include_once("./_func.php"); // include our shared functions $frontendforms = new FrontendForms(); $frontendforms->setLang('de'); I use these 2 lines only to make the error messages in german for all pages -> nothing more, but the module works also without these 2 lines. Please check my code against yours and let me know. Best regards
  5. Mysterious, on my setup everything works fine. Please be patient, I will take a deeper look within the next days. Today I am to busy to dig in ;-) Best regards
  6. Hello Christian, thanks for informing me about the error during the installation. I have corrected it on github, so please download version 2.0.2 again to get rid of the warning. The other problem is maybe caused by the namespace: you are not using a namespace (fe. Processwire) in your test.php. Therefore you do not need to add the namespace before the class name. // this should be correct $gender = new Select('gender') // do not write $gender = new /FrontendForms/Select('gender') // this in only necessary if you are using a namespace in this template //you have to correct it on each class instantiation. I have not tried it, because I am always using a namespace in my templates, but this should solve your problem. Please let me know. Best regards
  7. Here is the working code for your form by using translatable strings. You have to set your email address in email section. I have removed it to do not publish it here in the public. $form = new \FrontendForms\Form('contactform'); $form->setSuccessMsg(__('Your message was submitted successfully!')); $form->setErrorMsg(__('Sorry, but there are errors!')); $gender = new \FrontendForms\Select('gender'); $gender->setLabel(__('Title:')); $gender->addOption(__('Mister'), 'Mr.'); $gender->addOption(__('Miss'), 'Ms.'); $gender->setAttribute('class', 'w3-select w3-border w3-margin-bottom'); $form->add($gender); $name = new \FrontendForms\InputText('name'); $name->setLabel(__('Full Name:')); $name->setRule('required'); $name->setAttribute('class', 'w3-input w3-border w3-margin-bottom'); $form->add($name); $email = new \FrontendForms\InputText('email'); $email->setLabel(__('E-Mail:')); $email->setRule('required'); $email->setRule('email'); $email->setAttribute('class', 'w3-input w3-border w3-margin-bottom'); $form->add($email); $address = new \FrontendForms\InputText('address'); $address->setLabel(__('Address:')); $address->setRule('required'); $address->setAttribute('class', 'w3-input w3-border w3-margin-bottom'); $form->add($address); $message = new \FrontendForms\Textarea('message'); $message->setLabel(__('Message:')); $message->setRule('required'); $message->setAttribute('class', 'w3-input w3-border w3-margin-bottom'); $form->add($message); $button = new \FrontendForms\Button('submit'); $button->setAttribute('value', __('Send')); $button->setAttribute('class', 'w3-btn w3-round w3-blue'); $button->addWrapper()->setAttribute('class', 'w3-padding-24 w3-center'); $form->add($button); if ($form->isValid()) { // send an email $m = wireMail(); $m->to('enteryouremailhere'); $m->fromName($form->getValue('gender') . ' ' . $form->getValue('name')); $m->from($form->getValue('email')); // the email address of the sender $m->subject(_('New message from the contact form()')); // the subject of the email $m->bodyHTML($form->getValue('message') . ' <br><br> ' . $form->getValue('address')); // the message text of the email $m->send(); } echo $form->render();
  8. Hello sp1ke This module runs in its own namespace called "Frontendforms". I have added this namespace later and have forgotten to adapt the example codes. So if you are using the namespace "Processwire" or any other namespace you have to add the "FrontendForms" namespace before creating a new instance. // running inside a namespace $gender = new \FrontendForms\Select('gender'); // running outside of a namespace $gender = new Select('gender'); You have to do it on every new instance, otherwise you will get an error message!!!! I have adapted your code with the new namespace and it works. $form = new \FrontendForms\Form('contactform'); $gender = new \FrontendForms\Select('gender'); switch ($curLanguage) { case "English": $gender->setLabel('Title: '); $gender->addOption('Mister', 'Mr.'); $gender->addOption('Miss', 'Ms.'); break; case "Ελληνικά": $gender->setLabel('Τίτλος: '); $gender->addOption('Κύριος', 'Κος'); $gender->addOption('Κυρία', 'Κα'); break; default: $gender->setLabel('Title: '); $gender->addOption('Mister', 'Mr.'); $gender->addOption('Miss', 'Ms.'); break; } $gender->setAttribute('class', 'w3-select w3-border w3-margin-bottom'); $form->add($gender); $name = new \FrontendForms\InputText('name'); switch ($curLanguage) { case "English": $name->setLabel('Full Name: '); $name->setRule('required')->setCustomMessage('This field is required'); break; case "Ελληνικά": $name->setLabel('Ονοματεπώνυμο: '); $name->setRule('required')->setCustomMessage('Το πεδίο είναι απαραίτητο'); break; default: $name->setLabel('Full Name: '); $name->setRule('required')->setCustomMessage('This field is required'); break; } $name->setAttribute('class', 'w3-input w3-border w3-margin-bottom'); $form->add($name); $email = new \FrontendForms\InputText('email'); switch ($curLanguage) { case "English": $email->setLabel('E-Mail: '); $email->setRule('required')->setCustomMessage('This field is required'); break; case "Ελληνικά": $email->setLabel('E-Mail: '); $email->setRule('required')->setCustomMessage('Το πεδίο είναι απαραίτητο'); break; default: $email->setLabel('E-Mail: '); $email->setRule('required')->setCustomMessage('This field is required'); break; } $email->setRule('email'); $email->setAttribute('class', 'w3-input w3-border w3-margin-bottom'); $form->add($email); $address = new \FrontendForms\InputText('address'); switch ($curLanguage) { case "English": $address->setLabel('Address: '); $address->setRule('required')->setCustomMessage('This field is required'); break; case "Ελληνικά": $address->setLabel('Διεύθυνση: '); $address->setRule('required')->setCustomMessage('Το πεδίο είναι απαραίτητο'); break; default: $address->setLabel('Address: '); $address->setRule('required')->setCustomMessage('This field is required'); break; } $address->setAttribute('class', 'w3-input w3-border w3-margin-bottom'); $form->add($address); $message = new \FrontendForms\Textarea('message'); switch ($curLanguage) { case "English": $message->setLabel('Message: '); $message->setRule('required')->setCustomMessage('This field is required'); break; case "Ελληνικά": $message->setLabel('Μήνυμα: '); $message->setRule('required')->setCustomMessage('Το πεδίο είναι απαραίτητο'); break; default: $message->setLabel('Message: '); $message->setRule('required')->setCustomMessage('This field is required'); break; } $message->setAttribute('class', 'w3-input w3-border w3-margin-bottom'); $form->add($message); $button = new \FrontendForms\Button('submit'); $button->setAttribute('value', 'Send'); $button->setAttribute('class', 'w3-btn w3-round w3-blue'); $button->prepend('<div class="w3-padding-24 w3-center">'); $button->append('</div>'); $form->add($button); switch ($curLanguage) { case "English": $form->setSuccessMsg('<p>Your message was submitted successfully!</p>'); $form->setErrorMsg('<p>Sorry, but there are errors!</p>'); break; case "Ελληνικά": $form->setSuccessMsg('<p>To μήνυμα σας στάλθηκε με επιτυχία!</p>'); $form->setErrorMsg('</p>Υπάρχουν λάθη στη συμπλήρωση της φόρμας!</p>'); break; default: $form->setSuccessMsg('<p>Congratulations, your message was submitted successfully!</p>'); $form->setErrorMsg('<p>Sorry, but there are errors!</p>'); break; } if ($form->isValid()) { // send an email $m = wireMail(); $m->to('enteryouremailhere'); $m->fromName($form->getValue('gender').' '.$form->getValue('name')); $m->from($form->getValue('email')); // the email address of the sender //$m->subject($form->getValue('subject')); // the subject of the email $m->bodyHTML($form->getValue('message')); // the message text of the email $mailSent = $m->send(); } echo $form->render(); BTW you use the subject value, inside your mail function, but you do not have an inputfield for your subject. This will not work. $m->subject($form->getValue('subject')); // the subject of the email The new error message I have changed the code of the Frontendforms.module file a little bit to check if a template path is provided. I recommend you download the module once more to get the latest version and replace it with the version you have on your system. Another question: Why are you using a switch statement for your languages? You can use translatable strings instead of a switch statement. Best regards
  9. Ryan will make the processCSV method hookable in the next update ? No problem, I will make sure it is hookable in the next dev branch version 3.0.195. If you'd like feel free to add the 3 underscores to your copy and it'll be present on the next update.
  10. I have found a solution, but you have to hack the core file "ProcessLanguage.php"a little bit. The perfect method to save translations to fields created by a module is to hook after the "processCSV" method of the "ProcessLanguage" class file. Only problem: This method is not hookable by default, so I added 3 underscores to the method name to make it hookable. Goal: I want to add the German labels to the 3 fields created by the module after uploading and saving the translation csv file for this module. The label translations are inside the module translation csv file and I need to save it to the 3 fields. This is the main problem, because this field were created by the module but they are not part of the module, so I have to create/save the translations for this fields in an extra step. They will not be saved by adding the translation file to the module by default. To save the labels of the fields in another language I use the method below: // Define the hook function inside the init method public function init() { $this->addHookAfter('ProcessLanguage::processCSV', $this, 'addTranslationsToFields'); } /** * Method to add translation to the labels of fields created by this module * @param HookEvent */ protected function addTranslationsToFields(HookEvent $event){ // get the language object of the uploaded translation csv file $language = $event->arguments(1); $translation = new LanguageTranslator($language); $fields = ['jk_publish_open', 'jk_publish_from', 'jk_publish_until']; // name of the field to translate the labels foreach($fields as $fieldName){ //grab the field object $field = $this->wire('fields')->get($fieldName); $label = $translation->getTranslation($this, $field->label); $field->set("label{$language->id}", $label); $field->save('label'); } } The 3 fields where I want to add the translations to the labels are called 'jk_publish_open', 'jk_publish_from', 'jk_publish_until'. After uploading the translation csv. file for the module, the translations for the labels will be also added to the extra created fields which are not part of the module. This works like a charme (thanks to the PW LanguageTranslator class). I will try to convince Ryan to make the processCSV method hookable by default. Therefore I have submitted a pull request for making this method hookable by default: Best regards
  11. Hello, I am struggeling with the following problem: I have created a module that creates 2 additional text fields during the module installation. As documented ,on version ProcessWire 3.0.181 and above you can ship your modules with additional translation files inside the languages folder. This works great. My problem is that I want to add the translations for the 2 additional fields too. It works great for the module itself, but I dont know how to save the translations to the field too after installing the language file to a certain language. The workflow should be the following: After importing and saving fe the German csv file, the translations should also be added and stored on the 2 additional fields (fe the Label in German). Unfortunately there is no useable hookable function inside the ProcessLanguage class (https://github.com/processwire/processwire/blob/master/wire/modules/LanguageSupport/ProcessLanguage.module). Does anyone has an idea how to accomplish this? Thanks in advance for hints.
  12. Silly mistake!!! Trait is not a class, so using $this was not a good idea ? // use __('myString'); // and not $this->_('myString'); // inside traits
  13. Hello community, I am struggeling with a problem that translatable strings inside a trait will not display the correct language translation. I use the trait inside a class and include it inside the class like this <?php namespace MyNameSpace; use function ProcessWire\_; class myClass { use activation; public function myMethod() { return $this->function test(); } ] Only to mention : I use a custom namespace. The trait looks like this <?php namespace MyNameSpace; trait activation { public function test() { return $this->_('My text'); } } The problem is that "My text" will not be translated to the other languages independent of the which $user->language is set. Maybe someone has a solution for this problem and could post it here.
  14. Thanks @Zeka I have tried this, but it does not work. It seems the problem is that this method is inside a trait without any reference to a page language. The trait (called activation in my case) will be included inside a class via use activation; and it works - without the exception of the translations. I have some other classes for rendering frontend forms and texts and in this case the translationable strings work. But thank you for your answere.
  15. Hello, I have created a module which sends out emails to users triggered by LazyCron - works well. The emails contain translateable strings and the problem is that the emails will be always sent in the default language and not in the stored user language. Here is my method that sends out the emails: /** * Create WireMail object and send the email with the activation link * @param User $user - the user object * @return bool - returns true on success and false on failure */ protected function sendActivationLinkEmail(User $user): bool { // send an email with the activation link to the user // but check first if activation code (fl_activation) exists inside the database if($user->fl_activation){ $m = wireMail(); $m->to($user->email); $m->from($this->input_email); $m->subject($this->_('Action required to activate your account')); $m->body($this->createActivationLinkEmail($user)); $m->mailTemplate($this->input_emailTemplate); return $m->send(); } return false; } The method is part of a trait that I use. As you can see the subject contains a translateable string. The body text will be created by another method (createActivationLinkEmail) and contains also translateable strings, but you cannot see it here. The emails will be sent, but the text is always in English (default), independant if the user language is English, German or another language. I have tried to add $this->wire('languages')->set($user->language->id); but it does not work. Can someone help me out how to set the language inside this method to send the emails in the user language? Thanks in advance
  16. Hello at all, I am struggeling about a fast method to get all language translation CSV files of fe a module and merge all these files into 1 CSV file. I do not want fe 10 CSV translation files for a module. So I want to merge them all into one. All translation files for a site module are stored in site/assets/idoftheModule/... as json files. These translation files can be downloaded, but they are in json and not CSV format. I know I can do it one by one in the backend, but this is not my goal. Does anyone has done this before and could give me a hint, what ist the best and fastest way to 1) dowload all CSV files of a module at once and 2) merge them all into 1 CSV file. Thanks in advance
  17. Hello @Flashmaster82, There are different ways - the most simple one is to use PWs built in Mail class: Here is a working example (not tested but it should work ;-)) $form = new Form('contactform'); $gender = new Select('gender'); $gender->setLabel('Gender'); $gender->addOption('Mister', '0'); $gender->addOption('Miss', '1'); $form->add($gender); $surname = new InputText('surname'); $surname->setLabel('Surname'); $surname->setRule('required'); $form->add($surname); $name = new InputText('name'); $name->setLabel('Name'); $name->setRule('required'); $form->add($name); $email = new InputText('email'); $email->setLabel('E-Mail'); $email->setRule('required'); $form->add($email); $subject = new InputText('subject'); $subject->setLabel('Subject'); $subject->setRule('required'); $form->add($subject); $message = new Textarea('message'); $message->setLabel('Message'); $message->setRule('required'); $form->add($message); $privacy = new InputCheckbox('privacy'); $privacy->setLabel('I accept the privacy policy'); $privacy->setRule('required')->setCustomMessage('You have to accept our privacy policy'); $form->add($privacy); $button = new Button('submit'); $button->setAttribute('value', 'Send'); $form->add($button); if($form->isValid()){ // send an email $m = wireMail(); $m->to('myEmail@test.com); // enter here the email address where the mail should be sent to - usually it is your email address $m->fromName($form->getValue('gender').' '.$form->getValue('surname').' '.$form->getValue('name')); $m->from($form->getValue('email')); // the email address of the sender $m->subject($form->getValue('subject')); // the subject of the email $m->bodyHTML($form->getValue('message')); // the message text of the email $mailSent = $m->send(); // optional check if there was an error sending the mail // true on success, false on failure if(!$mailSent){ $form->getAlert()->setText('There was an error sending the mail.'); $form->getAlert()->setCSSClass('alert_dangerClass'); } // save the email as page $p = new Page(); // create new page object $p->template = 'email'; // set template -> you have to create the template first by yourself $p->parent = wire('pages')->get('template=contact'); // set the parent page $p->title = $form->getValue('subject'); $p->body = $form->getValue('subject'); $p->save(); } // render the form echo $form->render(); To send an email please check the docs at https://processwire.com/api/ref/wire-mail/ By creating a new page to save the email as a page under the contact form page please take a look at "save the email as page" section in the code above. You have to create the template and the fields for the email template first by yourself. 1) Create a template with fe the name 'email' first 2) Add the fields to the template where you want to store the data of the email (fe surname, name, subject, email address, message,....) 3) You have to set the parent page finding the parent by its template name (in the above example the contact form page uses the template 'contact') 4) Add the mail values to the email template fields and save the page. Best regards
  18. Hello @sp1ke That would be great and could really be a time saver for other Greek people. I would say you send me only the Greek csv file and I will add it on GitHub as el.csv (I guess el is the language code for Greek, am I right?). Thanks and have a nice weekend
  19. Hello @sp1ke An inputfield is a single line input and textarea is a multiline input. ProcessWire provides an extra sanitizer for textareas. Take a look at https://processwire.com/api/ref/sanitizer/textarea/ . Using "sanitizer text" for normal inputfields and "sanitizer textarea" for textareas was my personal choice. These 2 sanitizers will be applied by default - no need for you to do it manually. This is only for security reasons. If you are not satisfied with it, you can disable the sanitizer on each field by using the removeSanitizers() method. Take a look at this example: $surname = new InputText('surname'); $surname->setLabel('Surname'); $surname->setRule('required'); $surename->removeSanitizers();// this line removes the text sanitizer from this inputfield $form->add($surname); In this case the value will not beeing sanitized, but this is not recommended (especially if you are storing values in the database). If you want to add a special sanitizer for an input, you can use all sanitizers that will be shipped with ProcessWire. See a list of all available sanitizers at https://processwire.com/api/ref/sanitizer/ Example: You want to use the following sanitizers from ProcessWire: $sanitizer->alpha(string $value) //Sanitize to ASCII alpha (a-z A-Z) $sanitizer->camelCase(string $value) //Convert string to be all camelCase All you need to do is to use the setSanitizer(name of the sanitizer in ProcessWire) method. $surname = new InputText('surname'); $surname->setLabel('Surname'); $surname->setRule('required'); $surename->removeSanitizers();// this line removes the text sanitizer from this inputfield $surename->setSanitizer('alpha'); // this adds the alpha sanitizer $surename->setSanitizer('camelCase');// this adds the camelCase sanitizer $form->add($surname); Using camelCase sanitizer for the surename makes no sense in real life, so it is only applied as an example ? Hope it will be a little bit clearer.
  20. Hello @sp1ke glad to hear that, but I would recommend you to update your PHP version to at least 7.2+, because object type hinting is only possible with higher PHP versions. Otherwise you will get this error message everytime someone uses object type hinting (like me ;-). Best regards
  21. Hello This is very strange, because I have no problems and the error message will also make no sense. I have installed it on a new install of PW without problems. The problem is the type hinting in this case: The method add() expects an object and the variable $gender in your case is an object - it is an object of the class Select. So there should not be a problem, but you can try the following: // Replace this code in FrontendForms/FormeElements/Form.php line 203 public function add(object $field) // with this code public function add($field) But before removing the type hinting from this method, please try the following: For testing purposes remove the add() method by the select field and take a look if the problem persists with other fields (fe. the name input field). Which version of PHP do you use? Please let me know!
  22. Hello, as introduced in PW 3.0.181 modules can be shipped with translation files. I am trying to hook after the save method of this new functionality, but I could not get it to work. This hook is inside a module: // initialize the hooks public function init() { $this->addHookAfter('ProcessLanguage::save', $this, 'testHook'); } protected function testHook(HookEvent $event) { wire('session')->message('test'); } Nothing happens! Does anyone has an idea how to hook this new functionality. I have also tried it with fe ProcessLanguage::executeDownload but without success. Here is the Github page of the new feature: https://github.com/processwire/processwire/blob/master/wire/modules/LanguageSupport/ProcessLanguage.module
  23. Hello @sp1ke thank you for your issue report. This error was produced by my editor during find and replace process. It is not possible to use $this inside the module info method. I have replaced all translateable strings from __('My string') to $this->_('My string') because using $this is the prefered method inside the class of a module. During these replacements I have overlooked the replacement inside the module info method. I have replaced it on GitHub to: 'summary' => __('Create forms and validate them using the Valitron library.'), So in this case the string is also translateable. Thanks
  24. Problem is solved! I installed a new installation on XAMPP and now it works without problems - I guess there was going something wrong during the developement of the module inside the database. Best regards
  25. I found out that it happens if I use save() method without a parameter that was not set before. If I use for example save('title') and I set the title first, it works. // Works $p->title = 'My title'; $p->save('title'); // Does not work if title was not set before $p->save('title'); // Unfortunately this does not work $p->addStautus(Page::statusUnpublished); $p->save('status'); // and this does no work too $p->addStautus(Page::statusUnpublished); $p->save(); Any hints how to save the status?
×
×
  • Create New...