I'm writing a custom processor for search api that will search body content of nodes for links to pdfs and extract the content from them to be indexed. It's meant to be able to do the same thing search api attachments can do, it just searches for links inside bodies instead of just grabbing what's in an entity reference or file field. I'm using the drupal 7 search api attachments bf plugin as an example, but with Drupal 8 it's handled a bit differently

I currently have this file in a custom module located in /src/search_api/processor/BodyFieldAttachments.php


namespace Drupal\search_api_attachments_bf\Plugin\search_api\processor;

use Drupal\search_api\Datasource\DatasourceInterface;
use Drupal\search_api\Item\ItemInterface;
use Drupal\search_api\Processor\ProcessorPluginBase;
use Drupal\search_api\Processor\ProcessorProperty;

 * @SearchApiProcessor(
 *     id = "bodyfield_attachments"
 *  label = @Translation("Body Field Attachments")
 *  description = @Translation("Allows file links inside body fields to be indexed")
 * )
class BodyFieldAttachments extends ProcessorPluginBase{
     * {@inheritdoc}
    public function getPropertyDefinitions(DatasourceInterface $datasource = NULL){
        $properties = [];

        return $properties;

     *  {@inheritdoc}
    public function addFieldValues(ItemInterface $item){
        $node = $this->getNode($item->getOriginalObject());
        $body = $node->body->value;
        $files = $this->getFilesFromBody($body);


    protected function getFilesFromBody($text){
        $files = array();
        if (isset($text) && !empty($text)) {
            global $base_url;
            // Parse href attributes in <a> links.
            preg_match_all('/href=[\'"]([^\>\'"]*)[\'"]/', $text, $matches, PREG_SET_ORDER);
            foreach ($matches as $match) {
                // Determine if the file is local. Absolute URL could be local.
                // Beginning double slashes is implicit for the current page's protocol
                // but just apply http.
                if (substr($match[1], 0, 2) == '//') {
                    $url = 'http:' . $match[1];
                elseif (substr($match[1], 0, 1) == '/') {
                    $url = $base_url . $match[1];
                else {
                    $url = $match[1];

                $parse = parse_url($url);
                // Get absolute URL to the file location.
                $path_files = file_create_url('public://');
                if (isset($parse['host']) and $parse['host'] == $_SERVER['HTTP_HOST']) {
                    $uri = 'public://' . str_replace($path_files, '', $url);
                    // Convert back things (such as %20 back to a space).
                    $uri = urldecode($uri);

                    if (file_exists($uri)) {
                        $files_load = file_load_multiple(array(), array('uri' => $uri));
                        $file = reset($files_load);
                        if ($file) {
                            $files[] = (array) $file;
        return $files;

I have search api attachments installed and I do see that it has FilesExtractor class that handles file extraction but I'm not sure how to call upon it from my plugin and get it to use the config that's in place for Search Api attachments. Would I just create an instance of the FilesExtractor class and use one of its methods? Or is there some proper way to tap into it?

1 Answer 1


I was able to use the search api attachments file extractor by extending it.

The FilesExtractor class itself was a processor plugin. So I was able to access all the functionality by using

class BodyFieldAttachments extends 

instead of

class BodyFieldAttachments extends ProcessorPluginBase

Then I could just override the specific functions that need to be overwritten while having access to all the functionality the search api attachment plugin had.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.