Stefanowitsch Posted July 26 Share Posted July 26 I have not tried this before. So I would like to ask if it is -practically- possible to include RPB blocks in the search results. As far as I understand - each block is a separate page - so this makes searching a bit tricky. Because how does ProcessWire know where this particular RPB block is located in the frontend - I mean on which page? If I search for "lorem ipsum" (you get the Idea...) will the search result find the page where a RPB block is placed that contains this string? Link to comment Share on other sites More sharing options...
bernhard Posted July 26 Share Posted July 26 Hi @Stefanowitsch What I did is to add a hook at Pages::saved which will save the content of the RPB field to a hidden field which then can be queried via regular selectors. Each block had a dedicated method createIndex() which was called in a loop: $blocks = $page->getFormatted(RockPageBuilder::field_blocks); $index = ''; foreach($blocks as $block) $index .= $block->createIndex(); $page->setAndSave('your_search_index_field', $index); The benefit here is that you can define custom markup for each block, for example a headline block could just return this for a search index: public function createIndex() { return "** {$this->title} **\n"; } Does that help? 2 Link to comment Share on other sites More sharing options...
Stefanowitsch Posted July 26 Author Share Posted July 26 Thanks, bernhard. I will try this out. So basically each block saves it's own content into a hidden field that is part of the "parent" page template. That makes sense, it should work. Link to comment Share on other sites More sharing options...
Stefanowitsch Posted August 11 Author Share Posted August 11 Here's my solution to this. For anybody who might integrate it in a similar way: 1. Create a custom search index field and add it to the page templates that should be included in the search. The idea is that all RockPageBuilder blocks on a page will write "their content" into this field so that when searching for keywords the corresponding page (that includes a block) will be listed 2. Create a method called "createIndex" in each RockPageBuilder block class that you want to include in the search results. For example a simple Textblock would only return its body field: public function createIndex() { return "{$this->body}\n"; } 3 Make use of the Pages::saved Hook in ready.php to save the content of all RockPageBuilder bocks into the search index field: $wire->addHookAfter('Pages::saved', function($event) { $page = $event->arguments(0); $index = ''; // Iterate over all fields on the page foreach($page->fields as $field) { // Check if the field is of the type used by RockPageBuilder if ($field->type instanceof FieldTypeRockPageBuilder) { // Get the formatted content of the field $blocks = $page->getFormatted($field->name); // Further processing of the blocks if needed foreach($blocks as $block) { if (method_exists($block, 'createIndex')) { $index .= $block->createIndex(); } } } } //bd($index); // Save index to custom search index field $page->block_search_cache = $index; $page->save(['noHooks' => true]); }); 4. Inside your search template you can search for pages that contain blocks like this: $matches = $pages->find('block_search_cache%=' . $q); 2 1 Link to comment Share on other sites More sharing options...
FireWire Posted August 25 Share Posted August 25 @Stefanowitsch many thanks for sharing your solution, really helped me out. I modified it a little when implementing. Does the same job but may be a little more optimized. <?php $wire->addHookBefore('Pages::saveReady', function($event) { // ...rest of code here $page->block_search_cache = $index; // By hooking before the saveReady event it's possible to set the search cache field value without calling an extra page save // $page->save(['noHooks' => true]); }); Worked for me and just thought to share. Thanks again! 3 Link to comment Share on other sites More sharing options...
Stefanowitsch Posted August 27 Author Share Posted August 27 On 8/25/2024 at 7:14 PM, FireWire said: @Stefanowitsch many thanks for sharing your solution, really helped me out. I modified it a little when implementing. Does the same job but may be a little more optimized. <?php $wire->addHookBefore('Pages::saveReady', function($event) { // ...rest of code here $page->block_search_cache = $index; // By hooking before the saveReady event it's possible to set the search cache field value without calling an extra page save // $page->save(['noHooks' => true]); }); Worked for me and just thought to share. Thanks again! Okay, so you commented out the save method and used the saveReady hook instead? I will try this out! Saving inside the "saveReady" hook brought me some trouble because I got catched in an endless save-loop. Thats why I used the 'noHooks' option here. Link to comment Share on other sites More sharing options...
bernhard Posted August 27 Share Posted August 27 @Stefanowitsch if you hook into Pages::saveReady then you modify the $page object right before the save happens. For example you can just set $page->title = 'foo' there without saving, because PW saves the page object right after you modified it. If you hook into Pages::saved the save has already happened. In that case you need another $page->save() after you modified anything. Sometimes it's better (or necessary) to use Pages::saved, sometimes you can just use Pages::saveReady to be a little more efficient. 2 Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now