Leaderboard
Popular Content
Showing content with the highest reputation on 07/05/2020 in all areas
-
Thanks for your contributions to the community ? Good luck in all that you do - we'll see you around pwFoo ?3 points
-
This week I'm not bumping the version number just yet because I've got lots of work in progress. The biggest thing so far is something I hinted at last week. Basically, I like what the addition of the MySQL query expansion operators have brought (per posts last week and week before), but they also reveal what's lacking: something as simple as a search for "books" still can't directly match the word "book". But that's the most basic example. It's not a limitation of ProcessWire, but just the type of database indexes in general. I think it'd be amazing if ProcessWire had the ability of being really smart about this stuff, able to interpolate not just plurals vs. singulars but related words. In a perfect world, this is what query expansion would do (in addition to what it already does). But the reality is that it involves all kinds of complicated logic, rules and dictionaries; well beyond the scope of even a database. And it can be vastly different depending on the language. So this isn't something we can just add to the core and have it work. On the other hand, I figured maybe we should just put in a hookable method that just pretends the ability was there. Then people could hook it and make it respond with variations of words, according to their needs. The searches that use query expansion could then call this method and use whatever it returns... for when someday the ability is there. So I went ahead and added that hook — WireTextTools::wordAlternates(). And our database-searching class (DatabaseQuerySelectFulltext) now calls upon it, just in case an implementation is available. Well, after getting that hook added and having our class call it, naturally I wanted to test it out. So I got to work on it and came up with this module: WireWordTools. The WireWordTools module provides an API for English word inflection and lemmatisation. And it hooks that new method mentioned above, so that you can install it and immediately have it bring your searches to the next level. While it only helps for English-language searches, maybe we'll be able to add more languages to it, or maybe it'll lead to other modules that do the same thing for other languages. The expanded/alternate words are only used for searches that use the new query expansion operators, which are the ones that have a "+" in them: ~+=, ~|+=, *+=, **+=. They all can return similar results, but are weighted differently. Unlike most operators, where the logic is direct and you can expect them to always behave the same way, these query expansion operators are more subjective, and ones I think we should intend to keep tweaking and improving over time to continually improve the quality of the results they return. Basically, they are geared towards building site search engines, so I think it makes sense for us to pursue anything that makes them better at that, rather than aiming to always have them return the same thing. I am currently testing out the ~|+= operator ("contains any words expand") on our main site search engine here, along with the WireWordTools module. Finally, searching for "books" does match "book" too, and a lot more. More to be done here, but it's a good start hopefully.2 points
-
Step 1: Change your form element’s action attribute to <?php echo $page->url; ?> Step 2: There is no step 2. edit: sorry, I didn’t read the whole thread either. This same answer had actually been posted by Soma two posts ago.2 points
-
Sounds very interesting! Thx for the updates Ryan ? I understand "we" -> "i" but don't understand the pointed 2.. are they wrong or is my english too bad? ?2 points
-
Hi, module isn't maintained or tested anymore. I love PW, but at the moment I don't need / use it. Because of missing time I stopped web development / fun tasks some time ago...2 points
-
Just in case it helps anyone else, after upgrading from PW core 3.0.148 to latest (3.0.161), the ending bracket gets striped from the CDATA element when generating the output for the RSS XML feed. Not sure what has changed or caused this. Changed line 187 from: $description = '<![CDATA[' . $description . ']]'; to: $description = '<![CDATA[' . $description . ']]>'; Thanks.1 point
-
Ah, sorry, you probably want: $traders = $this->pages->find($selector); Regarding the sorting, very good points from @Jan Romero. I'd add that it's not necessarily the case that sorting by relevance would produce results that are particularly useful for users. It'd depend on the nature of the data and so on. If you want to read how it's done, it's described on https://dev.mysql.com/doc/internals/en/full-text-search.html, but it'd be a major project in itself figuring it all out! And one suggestion: if you're not anticipating too many results, it can take an acceptable amount of time to produce a results array, loop through the array adding a sort criterion (such as a relevance score), and then sorting by that criterion.1 point
-
I think this is a bug in ProcessWire. When you use the ~= operator, ProcessWire translates it into MySQL’s select /*[…]*/ match(field_title.data) against('+New York' in boolean mode) as _score_field_title_data1 /*[…]*/ order by _score_field_title_data1 desc The score it uses to sort is generated by the database according to the number of times the string appears in the text (probably more complicated than that, but whatever). The problem is that several results will have the same score, so the order among them is not deterministic. The database just does whatever it wants at that point, so the order may change inbetween queries, even if the queries are the same, but especially if they differ, even just in LIMIT and OFFSET. If you add "sort" to your selector string, ProcessWire will still use the score to sort, but only after your specified fields. What ProcessWire should do is ALWAYS sort by page id at the end, to keep the order deterministic. It might also be nice to make the relevance scores accessible in selector strings, so you could do something like "title|trader~='New York', sort=-title_relevance, sort=-trader_relevance, sort=-modified, sort=-id" Now you could have results in order of textual relevance, and if the relevance is equal, get the most current ones first, or whatever you desire. Obviously the id is a pretty stupid way to sort, but since it’s strictly unique, it’s a stable way to break ties, so I’d always put it last.1 point
-
I was going through the Hanna Code "Readme" in Bitpoet's editorial blog based off kongondo's Blog module and this particular line caught my attention: $f = $modules->InputfieldCheckboxes; $f->name = 'vegetables'; // Set name to match attribute $f->id = 'vegetables'; // Set id to match attribute $f->label = 'Vegetables'; $f->description = 'Please select some vegetables.'; $f->notes = "If you don't eat your vegetables you can't have any pudding.";//<<<<<<<<<<<< $f->addOptions(['Carrot', 'Cabbage', 'Celery'], false); $form->add($f); Very funny... ?1 point
-
Check this out: https://processwire.com/blog/posts/pw-3.0.137/#on-demand-mirroring-of-remote-web-server-files-to-your-dev-environment1 point
-
While working on the comments form of my blog, I thought to add an honeypot field in comments form to reduce spam. ? Honeypot is simply an hidden field added to a form. Honeypot field can have any name and is made invisible normally with a css directive {display: none}. Web users, being unable to see the field, will not fill it, while spam bots majority will not detect its invisibility and will populate the field. Once the form is submitted with a not-empty honeypot field it is very likely we are dealing with spam. ? In this post you can find more details about honeypot technique. While studying FieldtypeComments module and in particular CommentForm.php, to my great surprise ? I realized that PW already supports honeypot for Comments Form. ?? This feature has been introduced with PW 3.0.40. Normally this honeypot field is disabled, so it was enough to understand how to enable it! And as often is the case with PW ... it is super easy. ? If in your profile you are directly working with CommentArray, you will just have to enable honeypot passing it as an option to the renderForm() function of CommentArray class, example below: $comments->renderForm(['requireHoneypotField' => 'email2']); And .. we are done! ?? If you will look at the html of your Comment Form you will see an additional line CommentFormHP, that's the hidden honeypot field. In case you are using the Uikit 3 Site/Blog Profile, the renderForm() function is called in _uikit.php, ukCommentForm() function. If you wish that honeypot field is applied to every comment form of your site, just add the requireHoneypotField option to the list at the function start: ... 'errorMessage' => __('Your comment was not saved due to one or more errors.') . ' ' . __('Please check that you have completed all fields before submitting again.'), requireHoneypotField' => 'email2', // >>>>> ADD THIS LINE ); ... Otherwise if you wish to add honeypot in comment form on selected templates only, do not modify ukCommentForm(), but pass the option requireHoneypotField when calling the function in your template: ukCommentForm($comments, ['requireHoneypotField' => 'email2']); Now that we enabled it, let test if honeypot works. ? In the browser development section let's select the honeypot field and disable css {display:none} to show it. A new field will appear: If the spam bot is going to fill the field with a value and submit the form, an error is returned and comment will not be submitted ? That approach is great as spam comments will not be even saved inside the table field_comments. ? I hope this can be of help if somebody needs to enable this PW comments feature.1 point
-
You could try one or other of include=all and check_access=0 (see https://processwire.com/api/selectors/#access_control) in your selector, which may help with debugging.1 point
-
Or, going completely overboard using recursion, only loading pages to the requested depth: function getAncestors($pg, $level) { $retPages = (new PageArray())->add($pg); if( $level > 0 ) { foreach( $pg->children As $child ) $retPages->add(getAncestors($child, $level - 1)); } return $retPages; }1 point
-
The function seems a little overkill, but why not. After all to get the grandchildren you only need something like $grandchildren = $pages->find("parent=$page->children, sort=-modified, limit=20"); That's already a function right there. One can of course wrap it into a function and play around with it.1 point