Obtaining Correct Filepath for files on search results

SomebodySysop - June 11, 2008 - 21:46
Project:Swish-E Indexer
Version:5.x-1.1
Component:Code
Category:bug report
Priority:normal
Assigned:Unassigned
Status:needs review
Description

On Drupal 5.7 system, getting this error when executing search after clicking on "Files" tab:

    * warning: Invalid argument supplied for foreach() in modules/node/node.module on line 521.
    * warning: implode(): Bad arguments. in modules/node/node.module on line 525.
    * user warning: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 query: SELECT n.nid, n.vid, n.type, n.status, n.created, n.changed, n.comment, n.promote, n.sticky, r.timestamp AS revision_timestamp, r.title, r.body, r.teaser, r.log, r.format, u.uid, u.name, u.picture, u.data FROM node n INNER JOIN users u ON u.uid = n.uid INNER JOIN node_revisions r ON r.vid = n.vid WHERE in includes/database.mysql.inc on line 172.

Attached screenshot as well. Correct file is returned, but with these warnings.

Is this some configuration issue on my part? Thanks for any assistance.

AttachmentSize
swishSearchError.jpg75.63 KB

#1

SomebodySysop - June 12, 2008 - 21:29

OK, after a day or so, I believe I have a much better understanding of what's going on. There are three overall problems that I see. I think I should deal with each as a separate issue.

The first appears to be the path of files displayed on the search results. Swish-e indexes files recursively, so all applicable files under the "files" directory are indexed, including subdirectories.

However, on the search results, the swish.module code inserts variable_get('file_directory_path', 'files') as the default path to each file (regardless of it's actual filepath). Therefore, for example, on the file search results screen, files/file1.doc will display the correct link and "Containing node", but files/subdir/file2.doc will not, hence the warning:

warning: Invalid argument supplied for foreach() in modules/node/node.module on line 521.

Now, it appears that each time you also do a _swish_do_index(), you do an _swish_do_update() which populates the swish_fulltext table with all the correct filepaths.

So, my proposed logic for the search results list would be to get the correct filepath for each file from the swish_fulltext table, which will also retrieve the correct node information. The proposed code changes:

<?php
/**
* This will be invoked by the search module.
* Returns the Header, and array of items found, if any.
*/
function swish_search ($op = 'search'$keys = null){
...
      case
'search' :
       
$find = array();
     
$is_public = false;
     
$swish_bin   = variable_get('swish_path', '/usr/local/bin/swish-e');
      if (
variable_get('file_downloads','1') == FILE_DOWNLOADS_PUBLIC) {
       
$is_public = true;
       
$swish_index = getcwd() .'/' . file_directory_path().'/'. 'my_swish_index';
      } else {
       
$swish_index = file_directory_path().'/'. 'my_swish_index';
      }
...
//
// We need to use the basename to retrieve the correct filepath for the file,
// not suppy a default file path
//
         
$text_item = db_fetch_object(db_query("SELECT `fulltext`, nid, filepath from {swish_fulltext} where filepath like '%$basename%'"));
         
$snippet = search_excerpt($keys,$text_item->fulltext);       
//
// I use the filepath from fulltext since it's the one used to get to the actual file.
// I put 'system' in front of the path if the system controls file access (i.e., not 'public').
// Otherwise, I've got to look at the path permissions to determine if the file
// is in a public directory or not.
//
         
if ($is_public) {
           
$dir = str_replace($basename, "", $text_item->filepath);
           
$output = exec('ls -ld ' . $dir);
             
$permission = substr($output, 7, 1);
            if (
$permission == 'r') {
             
$link0 = file_create_url ($text_item->filepath);
            } else {
             
$link0 = 'system/' . $text_item->filepath;
            }
          } else {
           
$link0 = 'system/' . $text_item->filepath;
          } 

         
$find[] = array('link' => $link0, 'title' => $title, 'snippet' => $snippet, 'extra' => $extra, 'node' => node_load($text_item->nid));

        }
      }

      return
$find;
  }
}
?>

If this looks OK and makes sense, I'll happily supply a patch.

#2

SomebodySysop - June 12, 2008 - 17:53

Technical note on my proposed code change:

I know that:

<?php
          $text_item
= db_fetch_object(db_query("SELECT `fulltext`, nid, filepath from {swish_fulltext} where filepath like '%$basename%'"));
?>

should actually look more like:
<?php
          $text_item
= db_fetch_object(db_query("SELECT `fulltext`, nid, filepath from {swish_fulltext} where filepath like '%%s%'", $basename));
?>

The problem is that the latter code does not work. If someone has a more appropriate way to do this, I'd love to see it!

#3

SomebodySysop - June 12, 2008 - 17:54
Title:warning: Invalid argument supplied for foreach() in node/node.module on line 521» Obtaining Correct Filepath for files on search results
Status:active» needs review

#4

yas - June 18, 2008 - 20:43

Hello,

To ensure your process, I suggest the check of $text_item object like this:

<?php
          $text_item
= db_fetch_object(db_query("SELECT `fulltext`, nid, filepath from {swish_fulltext} where filepath like '%$basename%'"));
          if(!isset(
$text_item)) continue;
         
$snippet = search_excerpt($keys,$text_item->fulltext);       
?>

In my case, it happened that a file of $basename is actually existing but there is no result from {swish_fulltext}.

#5

SomebodySysop - June 19, 2008 - 00:03

To answer my question about how to format the query:

<?php
          $text_item
= db_fetch_object(db_query("SELECT * FROM {swish_fulltext} WHERE filepath LIKE '%s'", "%" . "/" . $basename));
?>

This not only insures the correct % character is inserted, but also that files/file.txt doesn't false match files/bigFile.txt. The previous code allowed this to occur.

#6

derbenito - November 6, 2008 - 11:21

Hello. Is there I solution for the problem. I have tried your code-changes but I get still the same error.
Thanx

Ben

#7

SomebodySysop - November 6, 2008 - 17:45

I ended up writing my own version of this module to specifically handle OG based files. I don't know if this will help you, but below is the code I use (successfully):

<?php
          $text_item
= db_fetch_object(db_query("SELECT sf.filepath, f.nid, sf.fulltext, f.filename, fr.description FROM {swishe_fulltext} sf INNER JOIN {files} f ON sf.filepath = f.filepath INNER JOIN {file_revisions} fr ON f.fid = fr.fid WHERE sf.filepath LIKE '%s'", "%" . "/" . $basename));
         
$snippet = search_excerpt($keys,$text_item->fulltext);       
?>

Note that in my code I search the "file" table as well. This is NOT a part of the official Swish-E module code.

 
 

Drupal is a registered trademark of Dries Buytaert.