You are here

public function Paragraph::search in Search and Replace Scanner 8

Performs the serach operation for the given string/expression.

Parameters

string $field: The field with the matching string (formatted as type:bundle:field).

array $values: An array containing the $form_state values.

Return value

array An array containing the titles of the entity and a snippet of the matching text.

Overrides Entity::search

File

src/Plugin/Scanner/Paragraph.php, line 22

Class

Paragraph
Class Paragraph.

Namespace

Drupal\scanner\Plugin\Scanner

Code

public function search($field, array $values) {
  $title_collect = [];
  list($bundle, $fieldname) = explode(':', $field);
  $query = \Drupal::entityQuery('paragraph');
  $query
    ->condition('type', $bundle);
  if ($values['published']) {
    $query
      ->condition('status', 1);
  }
  $conditionVals = parent::buildCondition($values['search'], $values['mode'], $values['wholeword'], $values['regex'], $values['preceded'], $values['followed']);
  if ($values['language'] !== 'all') {
    $query
      ->condition('langcode', $values['language'], '=');
    $query
      ->condition($fieldname, $conditionVals['condition'], $conditionVals['operator'], $values['language']);
  }
  else {
    $query
      ->condition($fieldname, $conditionVals['condition'], $conditionVals['operator']);
  }
  $entities = $query
    ->execute();
  if (!empty($entities)) {

    // Load the paragraph(s) which match the criteria.
    $paragraphs = \Drupal::entityTypeManager()
      ->getStorage('paragraph')
      ->loadMultiple($entities);

    // Iterate over matched paragraphs to extract information that will be
    // rendered in the results.
    foreach ($paragraphs as $paragraph) {
      if (!empty($paragraph)) {

        // Load the entity the paragraph is referenced in.
        $parentEntity = $paragraph
          ->getParentEntity();
        if (!empty($parentEntity)) {
          $parentEntityType = $parentEntity
            ->getEntityTypeId();

          // In the case of nested relationships we need to find the base
          // entity.
          if ($parentEntityType != 'node') {

            // If child is only nested one level deep.
            if ($parentEntity
              ->getParentEntity()
              ->getEntityTypeId() == 'node') {
              $parentEntity = $parentEntity
                ->getParentEntity();
            }
            else {
              while ($parentEntity
                ->getParentEntity()
                ->getEntityTypeId() != 'node') {
                $parentEntity = $parentEntity
                  ->getParentEntity();
              }
            }
          }
          $id = $parentEntity
            ->id();

          // Get the value of the specified field.
          $paraField = $paragraph
            ->get($fieldname);
          $fieldType = $paraField
            ->getFieldDefinition()
            ->getType();
          if (in_array($fieldType, [
            'text_with_summary',
            'text',
            'text_long',
          ])) {

            // Get the value of the field.
            $fieldValue = $paraField
              ->getValue()[0];

            // Get the parent entity's title.
            $title_collect[$id]['title'] = $parentEntity
              ->getTitle();

            // Find all instances of the term we're looking for.
            preg_match_all($conditionVals['phpRegex'], $fieldValue['value'], $matches, PREG_OFFSET_CAPTURE);
            $newValues = [];

            // Build an array of strings which are displayed in the results
            // with the searched term bolded.
            foreach ($matches[0] as $v) {

              // The offset of the matched term(s) in the field's text.
              $start = $v[1];
              if ($values['preceded'] !== '') {

                // Bolding won't work if starting position is in the middle
                // of a word (non-word bounded searches), therefore we move
                // the start position back as many character as there are in
                // the 'preceded' text.
                $start -= strlen($values['preceded']);
              }
              $replaced = preg_replace($conditionVals['phpRegex'], "<strong>{$v[0]}</strong>", preg_split("/\\s+/", substr($fieldValue['value'], $start), 6));
              if (count($replaced) > 1) {

                // The final index contains the remainder of the text, which
                // we don't care about so we discard it.
                array_pop($replaced);
              }
              $newValues[] = implode(' ', $replaced);
            }
            $title_collect[$id]['field'] = $newValues;
          }
          elseif ($fieldType == 'string') {
            $title_collect[$id]['title'] = $parentEntity
              ->getTitle();
            preg_match($conditionVals['phpRegex'], $paraField
              ->getString(), $matches, PREG_OFFSET_CAPTURE);
            $match = $matches[0][0];
            $replaced = preg_replace($conditionVals['phpRegex'], "<strong>{$match}</strong>", $paraField
              ->getString());
            $title_collect[$id]['field'] = [
              $replaced,
            ];
          }
        }
      }
    }
  }
  return $title_collect;
}