I'm hoping to use rules to automatically create new Biblio entries from a set of PMIDs that will be obtained elsewhere and I'm trying to find a way to use a PHP snippet using the functions already in this modules to create the node and populate the fields. I started with the code already in biblio_pm_form_biblio_node_form_submit but I'm not sure how to get from a BiblioEntrezPubmedArticle to a node that I can save. Or perhaps there is a better way to do this?

Comments

rjerome’s picture

Actually, with a tiny bit of restructuring of the functions "biblio_pm_biblio_import()" and "_biblio_pm_import()" this could be done quite easily. We would just need to move the file reading code from "_biblio_pm_import() to biblio_pm_biblio_import() and pass a list of pmid's to _biblio_pm_import() rather than the file name. Then you could directly call _biblio_pm_import() with your (comma separated) list of PMID's obtained from else where and they would be saved a biblio nodes.

Here are the modifications I would propose...

function biblio_pm_biblio_import($file, $terms = array(), $batch = FALSE, $session_id = NULL, $save = TRUE, $string = FALSE) {
  $nids = array();
  $dups = array();
  $pmids = file($file->uri, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
  if (empty($pmids)) {
    drupal_set_message(t("Could not open PubMed ID file"), 'error');
    return;
  }

  list($nids, $dups) = _biblio_pm_import( $pmids, $terms, $batch, $session_id);

  return array($nids, $dups);
}

function _biblio_pm_import( $pmids, $terms, $batch, $session_id) {
  module_load_include('php', 'biblio_pm', 'EntrezClient');
  module_load_include('php', 'biblio_pm', 'EntrezPubmedArticle');
  $retmax = 100;
  $resmax = count($pmids);
  $start = 0;
  $Eclient = new BiblioEntrezClient;
  $Eclient->post($pmids);
  $Eclient->setReturnMax($retmax);
....
rjerome’s picture

I thought it made sense to restructure the code in as described, so I went ahead and pushed the changes as described above. The one exception being that I renamed the _biblio_pm_import function to biblio_pm_import_ids, and it takes an array of PMID's as the first argument.

presleyd’s picture

Heh, I was just getting on to try this out! Thanks for the quick response!

FYI the rest of my plan is using Pubmed's ability to save a search as an RSS feed and then I'll trigger the rule upon new content in the RSS feed. If I get everything working I'll document it for other people who might have been dependent on Pubmed Integration or Entrez Database Import and looking to move to 7.

presleyd’s picture

Status: Active » Closed (fixed)
presleyd’s picture

Status: Closed (fixed) » Active

The check for duplicates is being done prior to this import. How would it be to check for duplicates here? Or could I call something else to check for duplicates first?

rjerome’s picture

I'm assuming you are calling "biblio_pm_import_ids()" with an array of PMID's?

The duplicate detection is done in "biblio_pm_import_ids()" prior to saving the node and it is only saved if it's not a duplicate. What is the problem you are seeing?

presleyd’s picture

Hmmm let me double check this then.

presleyd’s picture

Sorry don't know what I'm smoking here. It clearly is checking for duplicates before and is indeed working as expected. However, while I'm here how would you feel about being able to pass in an author uid to biblio_pm_import_ids?

I've scratched using Feeds and the RSS for this, the more I think about it its a waste of time. I could just pull the XML from pubmed. I'm thinking of rewriting Pubmed Integration as a vastly simpler module as much of that code is duplicating things that biblio_pm_import_ids does now. All the new module would do is allow you to save Pubmed search strings and hook into cron to pull the XML to get the pmids out to pass to biblio_pm_import_ids().

rjerome’s picture

The way I deal with setting the author UID can be found in the biblio_import() function in the biblio.import.export.inc file. Using the "nids" returned by the import function I just set them all in one go, because even if you set the uid on the node before it is saved it gets reset by the node module to whichever uid is saving the node. Here is the relevant snipet...

  $user = $results['user'];
  $userid = $results['userid'];

  if (user_access('administer biblio') && count($nids) && $user->uid != $userid) {

    db_update('node')
      ->fields(array('uid' => $results['userid']))
      ->condition('nid', $nids, 'IN')
      ->execute();

    db_update('node_revision')
      ->fields(array('uid' => $results['userid']))
      ->condition('nid', $nids, 'IN')
      ->execute();
  }

WRT that modified module you are proposing, maybe that functionality can just be built into the existing biblio_pm.module.

Ron.

presleyd’s picture

That's probably reasonable since it's just a form (or two) and a couple of functions. I've been meaning to figure out the changes to form api in 7 anyway. I don't mind posting a patch here as soon as I get a chance to if you'd like.

ngstigator’s picture

subscribe

presleyd’s picture

I haven't forgotten this, I'm still slowly poking at it. Where do you think the forms should go to enter the search string and search options (number to return, and date back to search)? The past modules just made a new table for to save this info in, does that sound ok still?

I noticed today that the biblio_pm_import_ids function doesn't have an option to initialize the arguments like some of the other functions around it:

function biblio_pm_import_ids($pmids, $terms, $batch, $session_id) {

instead of

function biblio_pm_import_ids($pmids, $terms = array(), $batch = FALSE, $session_id = NULL) {
While I can just pass bogus arguments in, I thought I'd point it out.

sbrow126’s picture

What are the chances that this function/feature will be incorporated in upcoming builds in the near future? I am supporting an academic website which relies on the PubMed Integration module's functions (with some custom coding) to pull back and store the PubMed Data. However, since the PubMed Integration module does not exist on D7 and we are planning to upgrade to D7 in the fall, this would be a highly desirable feature.

In addition, the PubMed Integration Module's developers are noting (on this post: http://drupal.org/node/1128878) that this feature may eliminate the need for their module altogether, so it would be good to know when/if this is in the works so we can plan accordingly.

Thanks.

scor’s picture

@sbrow126 the pubmed integration of the main biblio module for Drupal 7 works pretty well. I use it extensively on two D7 sites (with a bit of custom code). The directions in this issues are really good and it means I'll be able to get rid of some of my custom code.

rjerome’s picture

@sbrow126 (#13) Sorry, maybe I'm a bit thick, but which features of the pubmed integration module are you referring to? If it's the "function biblio_pm_import_ids" bit, that's is already in the biblio_pm module.

presleyd’s picture

@sbrow I am not the maintainer of that module. Biblio imports pubmed articles from a single PMID or list of PMIDs fine. That module just allowed you to submit search terms to Pubmed instead of PMIDs. You can grab the xml from pubmed and extract a list of PMIDs yourself pretty easily. I use the biblio_pm_import_ids as the action from a Rules set (via a small PHP snippet) triggered by cron. The PHP I use is below:

$pmids = array();
include_once "sites/all/modules/biblio/includes/biblio.import.export.inc";
$esearch_url = "http://eutils.ncbi.nih.gov/entrez/eutils/esearch.fcgi?db=pubmed&retmax=99&reldate=30&term=whateverIwanttosearchfrompubmed
$esearch_load = simplexml_load_file($esearch_url);
if (!is_object($esearch_load))
  watchdog("Failed to get retrieve Pubmed entries");
else {
  foreach($esearch_load->xpath("//Id") as $pmid) {
    $pmids[]= (string)$pmid;
  }
}
$nids = biblio_pm_import_ids($pmids, array(), FALSE,NULL);
if(isset($nids[0][0])) {  //there is at least one new publication in the XML
  db_update('node')
    ->fields(array('uid' => 1))
    ->condition('nid', $nids[0], 'IN')
    ->execute();
  db_update('node_revision')
    ->fields(array('uid' => 1))
    ->condition('nid', $nids[0], 'IN')
    ->execute();

I had hoped to make a small module that would remove the need for Rules (and hence replace the old Pubmed Integration module) but I have about 15 Drupal projects floating atm and since I use Rules extensively it's never been a very high priority.

sbrow126’s picture

Thank you. My concern was being able to submit a single PMID that the user would input and retrieve all the necessary Biblio node data from just that. The issue I was having was that we used the PubMed Integration module as a means of facilitating this originally. However, given that there was no updates to the Integration since 2009, my concern was how to get that functionality through D7.

I had to add some custom code to the module itself to get it to work correctly (there was a $global user callin missing so the original function pubmed_integration_import_data and pubmed_integration_load_citation_by_pmid was actually not working properly). There were a few other custom tweaks I had to make to get the PubMed link on a citation to work as well.

The main issue is that I still needed a single PMID to be passed and retrieve a single entry, and as a result the batch process that biblio now uses for the import would still need to be modified, hence my original request. That said, if the current best approach is to modify biblio_pm_import_ids on D7, then that's a simpler solution that upgrading the PubMed Integration module.

The site I am working on allows user to input a single PMID through another module and then using that entry, i created a custom function which would call the citation import process and create a biblio node/citation from it (after validation checks, etc.). So it sounds like on D7 biblio_pm_import_id is the way to go?

rjerome’s picture

Just to be clear, you want to (programmically) pass a PMID and get a node object returned? You don't want the node saved to the database at this point?

This would still be possible, but I would have to write a little helper function to do it.

rjerome’s picture

I've added a helper function to the module which should achieve what you want

You can now do this...

  $node = biblio_pm_fetch_pmid($pmid)

and it will return a "biblio" node object or an empty node object if the pmid is not found.

http://drupalcode.org/project/biblio.git/commit/b9a3788

rjerome’s picture

I've added a helper function to the module which should achieve what you want

You can now do this...

  $node = biblio_pm_fetch_pmid($pmid)

and it will return a "biblio" node object or an empty node object if the pmid is not found.

http://drupalcode.org/project/biblio.git/commit/b9a3788

tonyhrx’s picture

Just on this you had one or two brackets missing

$pmids = array();
include_once "sites/all/modules/biblio/includes/biblio.import.export.inc";
$esearch_url = "http://eutils.ncbi.nih.gov/entrez/eutils/esearch.fcgi?db=pubmed&retmax=99&reldate=30&term=pulmonary+hypertension";
$esearch_load = simplexml_load_file($esearch_url);
if (!is_object($esearch_load)) {
  watchdog("Failed to get retrieve Pubmed entries");
}
else {
  foreach($esearch_load->xpath("//Id") as $pmid) {
    $pmids[]= (string)$pmid;
  }
}
$nids = biblio_pm_import_ids($pmids, array(), FALSE,NULL);
if(isset($nids[0][0])) {

  db_update('node')
    ->fields(array('uid' => 1))
    ->condition('nid', $nids[0], 'IN')
    ->execute();
  db_update('node_revision')
    ->fields(array('uid' => 1))
    ->condition('nid', $nids[0], 'IN')
    ->execute();
    }
tonyhrx’s picture

Further on this: a lot of hosting companies quite sensibly prevent execute(); being stored on a database, so the RUles solution has limited applicability. Module I guess.

presleyd’s picture

I'm not sure what you mean, that execute is part of the Drupal db_update function, not a means to execute shell commands.

liam morland’s picture

Issue summary: View changes
Status: Active » Fixed

If you need further help, please re-open and provide details.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

semmel2000’s picture

Issue tags: +DOI

Would it be also possible to programmatically fetch a node from the DOI of a publication? Similar to

biblio_pm_fetch_pmid($pmid), something like

biblio_doi_fetch_doi($doi)?

liam morland’s picture

Issue tags: -DOI

It would be a new issue to add such a function.

semmel2000’s picture

May I add a new issue request?

liam morland’s picture

Any user can use the "Create a new issue" link on the module issues page. Be aware that this module gets little maintenance, mostly bug fixes. Of course, you could write the patch yourself.