manniru
11/10/2015 - 10:06 PM

JSON Search API for Drupal

JSON Search API for Drupal

<?php
/**
* implements hook_menu
*/
function json_search_menu (){
	$items['json/search/%'] = array(
		'page callback'    => '_json_search',
		'access arguments' => array('access content'),
		'page arguments'   => array(2),
		'type'             => MENU_CALLBACK,
	);
	return $items;
}

// @important this should be only used when you want to disable drupal default search page
/**
* implements hook_init()
*/
function json_search_init(){
}

/**
* custom function to perform and output search results in json
*/
function _json_search( $search_keyword = NULL ){
    $nid_list = array();
    $writerResults = array();
    $storyResults = array();

    $search_keyword = check_plain( $search_keyword ); // Sanitise input

    $server = search_api_server_load('search_server');
    $index = search_api_index_load('writers_index');
    $query = new SearchApiQuery($index);
    
    $query->keys( $search_keyword )
          ->fields( array('title', 'body:value') );

    $srv = new SearchApiDbService($server);
    $result = $srv->search($query);

    foreach ($result['results'] as $result_node) {
        array_push($nid_list, $result_node['id']);
    }

    // Unpublished nodes should be out of the index already
    $nodes = node_load_multiple($nid_list);



    foreach ($nodes as $node) {
        if($node->type === 'writer_story') {
            //Story result
            $entity_reference = _get_entity_field('node', $node, 'field_story_ref_writer');

            $newStoryFound = array(
                'id'            => $node->nid,
                'title'         => $node->title,
                'writerId'      => $entity_reference['#options']['entity']->nid,
                'writerType'    => $entity_reference['#options']['entity']->type,
                'writerName'    => $entity_reference['#title'],
                'body'          => _get_entity_field('node', $node, 'body')['#markup'],
                # 'image'        => null, Add this later...
            );
            
            // Fetch field collection of first image
            $image_collection = _get_entity_field('node', $node, 'field_images_meta', 0)['entity']['field_collection_item'];
            
            // If image exists
            if (!empty( $image_collection )) {
                $field_collection = field_collection_item_load( key( $image_collection ) );    
                $image = _get_entity_field( 'field_collection_item', $field_collection, 'field_writer_story_img', 0);
                
                // Create URL
                $newStoryFound['image'] = file_create_url( $image['#item']['uri'] );

                // For formatted style uncomment next line.
                # $newStoryFound['image'] = image_style_url('thumbnail', $image['#item']['uri']); 
            } 
            
            $newStoryFound['body'] = strip_tags($newStoryFound['body']); // Clean HTML

            $reg_matches = array();
            
            // $reg_pattern = '/(?:^|\.)\K.*?(?=' . $search_keyword . ')[^\.]*\./i'; Old regex

            $reg_pattern = '/[^|\.]*(?='. $search_keyword .')[^\.]*\.(.*?)\./i';
            preg_match($reg_pattern, $newStoryFound['body'], $reg_matches); // Strip sentences containing keyword.
            
            $newStoryFound['body'] = preg_replace('/(' .$search_keyword. ')/i', "<dfn>$1</dfn>", $reg_matches[0]); // Add DFN tags keeping original case.

        	array_push($storyResults, $newStoryFound);
        } 
        else if($node->type === 'writer') {
            //Writer result
            
            $newWriterFound = array(
                'id'                => $node->nid,
                'title'             => $node->title,
                'type'              => $node->type,
                'quote'             => _get_entity_field('node', $node, 'field_writer_quote')['#markup'],
                'firstname'         => _get_entity_field('node', $node, 'field_writer_first_name')['#markup'],
                'surname'           => _get_entity_field('node', $node, 'field_writer_surname')['#markup'],
                # 'backgroundImage' => field_get_default_value('node', $node, 'field_writer_background_image'),
            );

            $image = _get_entity_field('node', $node, 'field_writer_background_image');
            if ( !empty($image['#item']['uri']) && isset($image['#item']['uri']) ) {
                $newWriterFound['backgroundImage'] = file_create_url( $image['#item']['uri'] );
            }
            else {
                $default_image  = file_load( field_info_field('field_writer_background_image')['settings']['default_image'] );
                $newWriterFound['backgroundImage'] = file_create_url( $default_image->uri );
            }

            // Manually filter writers
            if ( strpos(strtolower($newWriterFound['title']), strtolower($search_keyword)) !== false ) {
            	array_push($writerResults, $newWriterFound);
            }
        }
    }
    $cleanedResult = array(
        'writers'   => $writerResults,
        'stories'   => $storyResults,
    );

    drupal_json_output($cleanedResult);
    exit();
}


/**
 * Uses Field API to view and get fields inside nodes with the correct access.
 * @return array|bool Field array if present, false if not.
 */
function _get_entity_field( $entity_type = 'node', &$entity_object, $field_name = NULL, $delta = 0 ) {
    if (!!$field_name) {
        $this_field = field_get_items($entity_type, $entity_object, $field_name);
        return field_view_value($entity_type, $entity_object, $field_name, $this_field[$delta]);
    } 
    else {
        return false;
    }
}