Jump to content


  • Posts

  • Joined

  • Last visited

  • Days Won


da² last won the day on September 5

da² had the most liked content!

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

da²'s Achievements

Full Member

Full Member (4/6)



  1. What do you need to understand? $page->author is a Page Reference field that can list multiple authors pages, so authors are stored in a PageArray, a kind of array dedicated in listing ProcessWire pages. So in your loop, $item is a Page instance using the template "author", and the Page class has a property "title" that corresponds to the title filled in this author's page admin.
  2. It's particular to call a function by a string. 99.99 % of the time you have better to do.
  3. In PW admin, create 2 fields of text (simple text or HTML, with appropriate formatter and editor), "my_page_header_1" and "my_page_header_2", go to the template of this page and add the 2 fields, and finally edit the page and fill the texts.
  4. Maybe with URL rewriting? Like a web server rule to transform URL like /concepts/My_Test_File4$$$.pdf/ to /concepts/?fileName=My_Test_File4$$$.pdf So old links are still working.
  5. Hello, Reading the documentation this is the expected behavior: But you can use get parameter: /concepts/?fileName=My_Test_File4$$$.pdf wire()->input->get->text('fileName'); It's maybe better to use an url encoded PDF name with php urlencode(): /concepts/?fileName=My_Test_File4%24%24%24.pdf urldecode(wire()->input->get->text('fileName'));
  6. Hi, This is called Markup Regions, it's targeted to ease templating (like Twig would do but only in PHP): https://processwire.com/docs/front-end/output/markup-regions/ If you use this, prefer to do it with the pw-region tag as it is better optimized (check the documentation). EDIT: I forgot to mention you can disable Markup Regions in site/config.php with $config->useMarkupRegions = false; Then you may also want to disable $config->prependTemplateFile if this file is no longer necessary. But if you want to use regions, you'll find in documentation that you can prepend/append/replace the _main.php tags with tags in templates, to solve the problem you are facing.
  7. Hi, I'm using the same as you, and already reported it to @ryan, you can see his answer here, it looks like he can do something:
  8. An issue fixed, just need to accept this small pull request. 🙂 https://github.com/processwire/processwire/pull/274
  9. That looks good if online documentation has a note on it. 🙂 Thanks for your commitment. 🙂
  10. OK, thanks for the explanations, I understand better your point of view. Yes this project is 3.0.200 using processInput(), here is the class I used, it's basically just a wrapper over InputfieldForm. Since then, I updated this class, because I saw you updated it in the same way (to make InputfieldForm API easier). abstract class TemplateFormManager { /** @var Inputfield $form */ private $form; private string $submitFieldName; function __construct( array $defaultValues = null, string $formAction = "./", string $method = FormMethod::POST, bool $showSubmit = true, string $submitFieldName = "submit_form" ) { $this->submitFieldName = $submitFieldName; $this->form = modules('InputfieldForm'); $this->buildForm($this->form); $this->applyDefaultValues($defaultValues); if ($showSubmit) $this->addSubmit(); $this->form->action = $formAction; $this->form->method = $method; } function render(): string { return $this->form->render(); } function isSubmitted(): bool { $submitName = $this->form->method == FormMethod::POST ? wire()->input->post($this->submitFieldName) : wire()->input->get($this->submitFieldName); return $submitName != null; } function processInput() { $this->form->processInput( $this->form->method == FormMethod::POST ? wire()->input->post : wire()->input->get ); } function getErrorCount(): int { return count($this->form->getErrors()); } function setError(string $fieldName, string $error) { $field = $this->form->get($fieldName); if (!$field) { throw new InvalidArgumentException("Field '$fieldName' doesn't exist!"); } $field->error($error); } /** * Get value of a Inputfield. */ function __get($fieldName) { $field = $this->form->get($fieldName); if (!$field) { throw new InvalidArgumentException("Field '$fieldName' doesn't exist!"); } return $field->attr('value'); } function getField(string $fieldName): Inputfield { $field = $this->form->get($fieldName); if (!$field) { throw new InvalidArgumentException("Field '$fieldName' doesn't exist!"); } return $field; } protected abstract function buildForm(Inputfield $form); private function applyDefaultValues(?array $values) { if ($values) { foreach ($values as $fieldName => $value) { $field = $this->form->get($fieldName); if (is_a($field, "ProcessWire\InputfieldCheckbox", true)) $field->checked($value); else $field->attr('value', $value); } } } private function addSubmit() { $submit = modules('InputfieldSubmit'); $submit->attr('name', $this->submitFieldName); $submit->value = "Valider"; $this->form->add($submit); } } Next one is my current version (PW 3.0.210), you can look at the execute() method, this is where I use the callback method onValidate() to do extra validation in template file. In the previous version above it was coded in a function executeForm() outside of abstract form class. On getErrorCount() method, I'm smiling at my comment "Strange method that gave me strange bugs, I just understand nothing..." 😆 abstract class AbstractForm { protected readonly InputfieldForm $form; protected readonly string $submitFieldName; public function __construct( array $defaultValues = null, string $formAction = "./", string $method = FormMethod::POST, bool $showSubmit = true, string $submitFieldName = "submit_form" ) { $this->submitFieldName = $submitFieldName; /** @var InputfieldForm $form */ $form = modules('InputfieldForm'); $this->form = $form; $this->buildForm($this->form); if ($showSubmit) $this->addSubmit(); $this->form->populateValues($defaultValues); $this->form->action = $formAction; $this->form->method = $method; } public function render(): string { return $this->form->render(); } public function execute( callable $successCallback = null, callable $validateCallback = null, ): int { if ($this->isSubmitted()) { $this->form->process(); // Check errors managed by form. $errorCount = $this->getErrorCount(); if ($errorCount > 0) return $errorCount; // Do extra validation. if ($validateCallback) $validateCallback($this); // Check errors after our extra validation. $errorCount = $this->getErrorCount(); if ($errorCount > 0) return $errorCount; if ($successCallback) $successCallback($this); } return 0; } /** * Strange method that gave me strange bugs, I just understand nothing... */ public function getErrorCount(): int { return count($this->form->getErrorInputfields()); } public function setError(string $fieldName, string $error): void { $field = $this->form->getChildByName($fieldName); if (!$field) { throw new InvalidArgumentException("Field '$fieldName' doesn't exist!"); } $field->error($error); } /** * Get value of an Inputfield. */ public function __get(string $fieldName): mixed { $value = $this->form->getValueByName($fieldName); if ($value === null) throw new InvalidArgumentException("Field '$fieldName' doesn't exist!"); return $value; } public function setValue(string $fieldName, string $value): void { /** @noinspection PhpUnhandledExceptionInspection */ $field = $this->form->get($fieldName); if (!$field) throw new Error("Field $fieldName it not in form."); $field->attr('value', $value); } protected abstract function buildForm(InputfieldForm $form): void; protected function isSubmitted(): bool { /** @noinspection PhpUnhandledExceptionInspection */ return $this->form->isSubmitted($this->submitFieldName); } private function addSubmit(): void { try { /** @var InputfieldSubmit $submit */ $submit = wire()->modules->get('InputfieldSubmit'); $submit->attr('name', $this->submitFieldName); $submit->value = __("Valider", COMMON_TRANSLATION_DOMAIN); // Traduire dans _commonTranslations.php $this->form->add($submit); } catch (WirePermissionException $e) { throw new Error($e->getMessage()); } } } I use it like that in a template: $onValidate = function (AbstractForm $form): void { // Calling a remote API to valid some data // We got an error $form->setError('fieldName', "Don't do that please"); }; $onSuccess = function (AbstractForm $form): void { // Saving user and redirecting to another page }; // Form default values $currentValues = [ 'foo' => $bar ]; $form = new AccountEditionForm($currentValues); $formErrorCount = $form->execute($onSuccess, $onValidate); Twig::render('account-edition', [ 'form' => $form, 'formErrorCount' => $formErrorCount ]); Thank you. Yes this is often necessary. I'm checking errors that are outside of pure form context. Another user had this same issue since 3.0.210, I'm not alone doing this. 🙂 Sometimes I add the namespace, but just to get cleaner imports. I didn't know there is a relation with template compilation, could you explain what's the problem of having my template compiled by PW? I'm gonna add it in PHPStorm template file, so I don't forget it. EDIT: in fact $config->templateCompile was already false by default.
  11. OK, I don't know if this is possible in PW. I searched in source code for "ORDER BY FIELD" but found nothing. Maybe that could be a PW feature request to add selector for ORDER BY FIELD. You can also do the MySQL request using $database API variable, but then you must do yourself values sanitization, and resolving pages references if any. SELECT * FROM table ORDER BY FIELD(id, 5,3,6,1,4,2);
  12. Could you explain the conditions that justify this sorting? Is it static or dynamic? If static maybe you can solve this by manual sorting in PW admin. Then you use "sort=sort" in your selector. If dynamic the only solution I see actually would be like: $sortedIds = [5872, 5869, 5870, 5871]; // List created dynamically $results = $pages->find('id=' . implode('|', $sortedIds)); $sortedResults = []; foreach ($results as $result) { // echo $result->id . "\n"; $nextId = array_shift($sortedIds); if(!$nextId) break; $sortedResults[] = $results->getPageByID($nextId); } var_dump($sortedResults);
  13. So, except if there's a magic trick I'm not aware of, you have to get the pages in correct order from the resulting PageArray, with your own code.
  14. Sorting is managed with "sort" selector. If you want to sort by reverse id: $pages->find('id=4|2|1', sort='-id');
  • Create New...