Jump to content

da²

Members
  • Posts

    341
  • Joined

  • Last visited

  • Days Won

    3

Everything posted by da²

  1. You can log values with wire()->log->message("foo"), or with a var_dump() followed by an exit(). But here the error message is saying everything: And the code: So maybe the problem comes before this function call, check the parameters values, especially $operator.
  2. If you don't like to use zero as an "empty" value, you can ask for a default value: $input->get('pageId', 'int', -1); But zero is fine since there's no zero ID or zero lang and we can check value easily. $pageId = $input->get('pageId','int'); if ($pageId) ...
  3. Hi, $input->get('pageId','int'); is casting the value to int, so null becomes zero. This is the equivalent of $sanitizer->int(null);
  4. So not all company pages have tools? Why not adding a method CompanyPage::hasTools():bool? if ($companyPage->hasTools()) $companyPage->getTools()->foo(); Yes, methods should always be available.
  5. Watching this cody video made me crazy 😄 , the guy is generating a unit test with AI from the finished implementation! 😬 This is so wrong. We should never write a test from an implementation, tests must be wrote before... because they are meant to validate the implementation. Implementation is a consequence of the tests, not the other way. If an AI generate a test from a wrong implementation, will the test validate the wrong or the expected behavior? 😁 For the fun I asked ChatGPT about this technique: Generating unit tests from the function they are supposed to test might seem efficient for saving time or ensuring that the test covers the existing code, but it has several significant drawbacks. 1. Confirmation Bias: The test may inherit the same errors or biases as the original function. If the function contains a logical error, the test generated from that same logic might not detect it. 2. Lack of Test Case Diversity: A good unit test should verify a function under various conditions, including edge cases or unusual scenarios. If a test is automatically generated from the function, it may not cover all possibilities and might only focus on scenarios the function already handles correctly. 3. Objectivity and Independence: Unit tests are meant to be independent and objective. By generating tests from the function itself, this independence is compromised, which can reduce the tests' ability to identify defects. 4. Lack of Critical Thinking: Manually creating unit tests forces the developer to consider various use cases, possible inputs, and expected outcomes. This helps identify potential flaws in the function's logic. This critical thinking is often lost when tests are generated automatically. 5. Maintenance and Scalability: If the function evolves, the generated tests will also need to be updated. Automatically generated tests may not be as flexible or well-maintained as manually crafted ones. When Can This Technique Be Useful? Initial Generation: For very large projects where tests are nonexistent, generating basic tests can be a starting point before refining them manually. Quick Coverage: In situations where quick coverage is essential, this technique can help, though it should not replace thoughtful and manual testing. Conclusion It is best not to rely solely on this technique. Unit tests should be independent and designed to push the function to its limits, which is difficult to achieve with tests generated from the code they are supposed to test.
  6. And in case using page names is mandatory, the changes are: /** * Values of this enum must be the same as company pages names. */ enum CompanyToolsType:string { case MICROSOFT = "microsoft"; case GOOGLE = "google"; } class CompanyPage extends Page { //public function getTools... public function getToolsType():CompanyToolsType { // TODO Can throw ValueError return CompanyToolsType::from($this->name); } } You can also remove the enum and ask the factory directly with a string, but enum adds a layer of error checking. Same for factory, it can be removed and code moved to CompanyPage, the factory primarily helps with better separation of responsibilities.
  7. Hi, To be clean I wouldn't use the page name. Name purpose is essentially for url management, not for "company"'s one. 🙂 Name can change in the future, but the company associated with the page won't. So I would create, maybe a select options with company names and ID. Or if these tools have properties that need to be stored in PW fields, I would create a tools template and tools page references on the company page. For the code part (using a select options), I don't like using hooks when it's not necessary, hooks make code less clear and harder to maintain on long term. So my approach is like good old classic and verbose OOP. 😄 I wrote this on a simple text editor, so maybe mistakes... /** * Values of this enum must be also set in select options values. */ enum CompanyToolsType:int { case MICROSOFT = 1; case GOOGLE = 2; } interface CompanyTools { public function foo():void; } class MicrosoftTools implements CompanyTools { public function foo():void { echo "I'm a Microsoft tool"; } } class GoogleTools implements CompanyTools { public function foo():void { echo "I'm a Google tool"; } } class CompanyToolsFactory { public static function getTools(CompanyToolsType $type):CompanyTools { return match($type) { CompanyToolsType::MICROSOFT => new MicrosoftTools(), CompanyToolsType::GOOGLE => new GoogleTools(), }; } } /** * @property $companyTypeSelect I don't remember what type it is (Select Options field with single selected value) */ class CompanyPage extends Page { public function getTools():CompanyTools { return CompanyToolsFactory::getTools($this->getToolsType()); } public function getToolsType():CompanyToolsType { // TODO Can throw ValueError return CompanyToolsType::from(intval($this->companyTypeSelect->value)); } }
  8. I understand the idea, this is actually a problem that application might break if this setting change. But instead of adding methods I would remove the setting, no more choice between different return types, only Page|null (and PageArray for multiple). Simplicity... 😁 Obviously it would break actual sites deployed with PW, so maybe for a ProcessWire 4.0... ^^
  9. I use the false value, but I'd prefer a null value, this is more common. Globally I don't really like the NullPage usage in PW API, instead of a null value. Code is a bit less readable, and in both cases you'll end with an error when accessing a property/method on it, if you forgot to check the value. if (!$page) // Faster to write, easier to read if (!$page->id) if ($page instanceof NullPage) NullPage may be necessary in PW core code, but in my usage I don't see any advantage compared to a null value.
  10. I bet $contact is coming from a page reference field that is configured to return false when empty. So if $contact is optional, the code should verify its value before to use it and call renderContactSmall(). For the empty selector, it's necessary to investigate the code that generates it, and log value of variables it's using.
  11. When I need to load a fair amount of data I do custom MySQL queries. findRaw() is very fast too but I don't like to parse its results. Just be careful to sanitize data where needed (all texts at least). The downside is that it takes much more development time. But I become better in MySQL stuff. 😁
  12. If the user have an account: create a form with a select input listing languages, then set the selected language on current user and save. $of = $user->of(false); $user->language = $languages->getLanguage($form->language)->id; $user->save(); $user->of($of); $form->language is my select input, it's the language name. If user has no account, it all depends on how you want to manage languages, common solution is to use language URLs, /de/, /fr/, /en/... https://processwire.com/docs/multi-language-support/multi-language-urls/
  13. You are actually viewing the site with default language. Try this: user()->setLanguage("Tamil"); echo __("Welcome to our website");
  14. Ha, ok, I get it too, that wasn't a PW admin question. ?
  15. Hi, Language packs are not modules, you install them from each language page, accessible from menu Setup > Languages. Then you have a button to import a zip.
  16. @BarryP What is a "loss map"? Are you talking about this "Home" image without src value? Processwire templates are inside the directory site/templates. You probably have a home.php, that is the starting point for the home page display.
  17. I'm not a PHP expert, I use this language since a few years but only intensively since last year. And I just found the spaceship operator <=>. A few days before I implemented an ArrayUtils::floatCompare() because I found bugs in my code where I compared floats like int, because usort callback function return value is an int and I was returning "$float1 - $float2"... followed by the implicit cast to int... not perfect sorting. ? I know I've already read about this 'spaceship.' I remember the name, but probably it wasn't the right time to fully understand its meaning. ^^ Did you know this operator? EDIT : thanks to the moderator who pinned this topic, I owe you a beer! ?
  18. Why? I don't give names, I let PW create it from title.
  19. Is it faster to add START TRANSACTION and COMMIT in the sql file? In my current project I sometimes import 5000 pages using PW API, and with transactions (wire()->database->beginTransaction(); wire()->database->commit();) it is done in 20-30 seconds.
  20. Hi, If your page reference field can contain multiple pages, you should add pages like this: $page->sammelband_verweis->add($matchingPage); Also, for optimization, you should save the page outside of the loop: $of = $page->of(false); foreach ($page->children("include=hidden") as $child) { if (! empty($child->sammelband_text)){ // doing some sanitation to the field's content $SammlungTitel = extractTitleAfterYear($child->sammelband_text); $escapedTitle = $sanitizer->selectorValue($SammlungTitel); $matchingPages = $pages->find("template=publikation, include=hidden, title^=$escapedTitle"); if ($matchingPages->count() > 0) { $matchingPage = $matchingPages->first(); $page->sammelband_verweis->add($matchingPage); } } } $page->save('sammelband_verweis'); $page->of($of);
  21. I've reached the same conclusions when I tried with Profields Table. I use a lot the autocomplete field because the select is not good for hundred of pages. From what I understand, limitation is on both sides: the find() string selector, and the ProcessPageSearch. Just one needs to be improved to solve this limitation. The easier fix is probably ProcessPageSearch: we need a hookable method to replace results, like the getSelectablePages() of InputfieldPage, and like in other hooks we need the page and field from where the request was sent.
  22. I had a look at it, I remember trying to do the same with an autocomplete field except I tried to reference pages from a Profields Table, and never found a correct solution. What you can do is search for repeater items instead of the pages inside items. Or hooking into ProcessPageSearch::findReady to update selector, but it's not clean, I think only solution is to add "id=xxx|xxx|xxx|xxx|xxx|xxx|...." in selector. ? Or maybe hooking into ProcessPageSearch::executeFor and doing your own search. For the hooks you need to know on what page you are, I don't know how. EDIT: Except with a ugly hack, like adding in selector string "name=page.id", and so in ProcessPageSearch::executeFor you can get the page id with $event->return, do a search directly in repeater (like this) and finally format and return results.
  23. @Kiwi Chris Yes, page.vintage refers to the property vintage on the current page. I thought it was your goal, but I missed you are trying to reference item fields in repeater. If I understand good, in your page you have a page reference field with the selector string, and this field must reference the pages that are set in a repeater on the same page? Or is the page reference field inside the repeater too? ?
  24. @Kiwi Chris Try this: productVintage.id=page.vintage.id or: productVintage=page.vintage If you search by title, it would be: productVintage.title=page.vintage.title But I don't see any reason to search by title instead of id.
×
×
  • Create New...