pagebuilder icon indicating copy to clipboard operation
pagebuilder copied to clipboard

What is the best way to perform site search in PageBuilder?

Open pmfx opened this issue 6 years ago • 8 comments

I was wondering what is the best way to make site search when website content heavily depends on PageBuilder?

How to configure AjaxSearch or other snippet to search in PageBuilder and show the search results?

pmfx avatar Mar 08 '18 21:03 pmfx

Good question

mnoskov avatar Mar 09 '18 06:03 mnoskov

I found that AjaxSearch can perform search in custom tables this way:

function pagebuilder_ajaxsearch(&$main, &$joined, $bsf, $fields) {
    global $modx;

    $joined = [
        'tb_name' => $modx->getFullTablename('pagebuilder'),
        'tb_alias' => 'pb',
        'id' => 'id',
        'main' => 'id',
        'join' => 'document_id',
        'searchable' => ['values'],
        'displayed' => ['config', 'values'],
        'concat_separator' => ', ',
        'filters' => [
            ['field' => 'visible', 'oper' => '=', 'value' => '1'],
        ],
    ];
}
[!AjaxSearch? &whereSearch=`content|pagebuilder_ajaxsearch` &ajaxSearch=`0`!]

But results filtered by built in jscropper (because data stored in json format)

mnoskov avatar Mar 09 '18 07:03 mnoskov

Thanks. That was a good clue and I got it working! At least it looks like it is working ;)

Here is what I did:

I've copied AjaxSearch default config file: assets/snippets/ajaxSearch/configs/default.config.php as a assets/snippets/ajaxSearch/configs/pagebuilder.config.php

At the end of this new config file I've added your code and a copy of AjaxSearch strip code (without JS strip):

function pagebuilder_ajaxsearch(&$main, &$joined, $bsf, $fields) {
  global $modx;

  $joined = [
    'tb_name' => $modx->getFullTablename('pagebuilder'),
    'tb_alias' => 'pb',
    'id' => 'id',
    'main' => 'id',
    'join' => 'document_id',
    'searchable' => ['values'],
    'displayed' => ['config', 'values'],
    'concat_separator' => ', ',
    'filters' => [
      ['field' => 'visible', 'oper' => '=', 'value' => '1']
    ],
  ];
}

function pagebuilderStripOutput($text) {
  global $modx;

  if ($text !== '') {
    // stripLineBreaking : replace line breaking tags with whitespace
    $text = preg_replace("'<(br[^/>]*?/|hr[^/>]*?/|/(div|h[1-6]|li|p|td))>'si", ' ', $text);

    // stripTags : Remove MODX sensitive tags
    $modRegExArray[] = '~\[\[(.*?)\]\]~s';
    $modRegExArray[] = '~\[\!(.*?)\!\]~s';
    $modRegExArray[] = '#\[\~(.*?)\~\]#s';
    $modRegExArray[] = '~\[\((.*?)\)\]~s';
    $modRegExArray[] = '~{{(.*?)}}~s';
    $modRegExArray[] = '~\[\*(.*?)\*\]~s';
    $modRegExArray[] = '~\[\+(.*?)\+\]~s';

    foreach ($modRegExArray as $mReg) $text = preg_replace($mReg, '', $text);

    // stripHtml : Remove HTML sensitive tags
    $text = strip_tags($text);
  }
  return $text;
}

The last thing was a snippet call:

[!AjaxSearch? 
&config=`pagebuilder` 
&ajaxSearch=`0` 
&whereSearch=`content|tv|pagebuilder_ajaxsearch` 
&stripOutput=`pagebuilderStripOutput`
!]

pmfx avatar Mar 11 '18 18:03 pmfx

To show extract from PB in AS results you can use this in snippet parameter:

&extract=`1:content,pb_values`

But this may result in showing code like {"richtext":"Lorem ipsum....."}

As a temporary workaround I added this at the end of a "pagebuilderStripOutput" function:

// strip pagebuilder wrappers
$text = str_replace('{"richtext":"', '', $text);
$text = str_replace('"}', '', $text);

But it is not perfect in case other field names are used. Probably can be solved with preg_replace/regex but I'm not that familiar with it.

pmfx avatar Mar 11 '18 20:03 pmfx

While the configuring AjaxSearch is pretty difficult, maybe easiest solution would be to make a copy of PageBuilder values (without JS code) inside "content" field of "site_content" table on every document save event?

With this, there would be no issues with searching or configuring AjaxSearch.

pmfx avatar Mar 20 '18 13:03 pmfx

... and it could be added as a new plugin setting (turned off by default).

pmfx avatar Mar 20 '18 13:03 pmfx

I don't like this solution, we can just end AjaxSearch config to crop all mustaches with regex

mnoskov avatar Mar 21 '18 04:03 mnoskov

Cool, have it working. My mistake was that I didn't add it to the result (landing) page snippet.

fourroses666 avatar Feb 12 '19 09:02 fourroses666