1

I'm building a basic D7 module that fetches data from an API and then add it as a certain content type. Problem is, every node_ function is coming back as undefined. node_object_prepare, node_submit, and node_save with this error message:

Call to undefined function node_object_prepare()

The module is bare bones... info file:

name = Social Fetch
description = Fetches feeds from various social media platforms.
package = public-action
version = 1.0
core = 7.x
files[] = social_fetch.module

and the social_fetch.module...

<?php
if(isset($_GET['fetch']))
{
    social_fetch();
}

function social_fetch(){
        $node = new stdClass();
        $node->title = 'test';
        $node->type = "social_boxes";
        node_object_prepare($node); // Sets some defaults. Invokes hook_prepare() and hook_node_prepare().
        $node->language = LANGUAGE_NONE; // Or e.g. 'en' if locale is enabled
        $node->uid = 1; 
        $node->status = 0; //(1 or 0): published or not
        $node->promote = 0; //(1 or 0): promoted to front page
        $node->comment = 0; // 0 = comments disabled, 1 = read only, 2 = read/write
        $node = node_submit($node); // Prepare node for saving
        node_save($node);
}

So much as I knew, node_ was part of the core and wouldn't need any dependencies but I may be wrong. I tried adding this:

module_load_include('inc', 'node', 'node.module');

but that did nothing. also tried loading the bootstrap to see if maybe this was being run before the core loaded, but that did nothing as well.

  require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
  drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

Am I missing something? should this be run in a hook of some kind and if so, which?

Side Note

I am able to achieve what I need by using the db_ methods below. It just seems like an inferior way to do so since I don't actually know the anatomy of a node to know if these are the only things required to make sure the system remains stable. The kind of things the node API would have handled 100%.

      $nid = db_insert('node') 
        ->fields(array(
          'title' => 'test',
          'uid' => 1,
          'type' => 'social_boxes',
          'language' => 'und',
          'status' => 0,
          'comment' => 0,
          'promote' => 0,
          'created' => REQUEST_TIME,
          'changed' => REQUEST_TIME,
        ))
        ->execute();

        if($nid)
        {
            db_update('node') //add vid back into the new node
              ->fields(array(
                'vid' => $nid
              ))
              ->condition('nid', $nid, '=')
              ->execute();

            db_insert('node_revision') 
            ->fields(array(
              'nid' => $nid,
              'vid' => $nid,
              'uid' => 1,
              'title' => $class->getText(),
              'timestamp' => REQUEST_TIME,
              'log' => '',
              'status' => 0,
              'comment' => 0,
              'promote' => 0,
              'sticky' => 0
            ))
            ->execute();
        }
2
  • Try to define hook_menu and in there define a page callback function with your code. When you then browse to your path everything should work as expected. For automatic execution put your code in hook_cron. That can be triggered externally every few minutes.
    – schlicki
    Commented Mar 15, 2016 at 18:11
  • Can you put it in a full example as an answer? Saying something like define hook_menu doesn't really help cause I swear the docs assume you know everything there is to know about drupal. and when I paste the examples they do nothing at all. not even die('lol') runs.
    – Kai Qing
    Commented Mar 15, 2016 at 18:24

2 Answers 2

2

Tty the following in your .modulfe file:

function social_fetch_menu() {
  $items['social_fetch'] = array(
    'title' => 'Fetch',
    'page callback' => 'social_fetch_fetch',
    'access callback' => true,
  );

  return $items;
}

function social_fetch_fetch() {
  $query = drupal_get_query_parameters(); // $query['fetch'] for your $_GET parameter
  // ... your code to save the node
  return 'done';
}

Now clear the caches and go to ../social_fetch in your browser and see what happens.

To check for your fetch parameter on every page load (of not cached pages) do the following:

function social_fetch_init() {
  $query = drupal_get_query_parameters();
  if (isset($query['fetch'])) {
    // add node
  }
}
3
  • Great that worked. so _menu is just called on page load. good to know. Thanks
    – Kai Qing
    Commented Mar 15, 2016 at 18:40
  • It actually is only called when clearing the cache. The cache then holds available paths that can be seen as connections between url paths and your functions. If you then open a url Drupal searches through available paths from its cache abd - if it finds one - calls the corresponding page callback to create the output.
    – schlicki
    Commented Mar 15, 2016 at 18:43
  • 2
    @schlicki Please note that hook_init() is not invoked for cached pages, so not every page load. Commented Mar 15, 2016 at 18:45
3

Never ever call functions from the global scope. You are probably running into a situation where other modules (the node module) are not yet loaded.

<?php
if(isset($_GET['fetch']))
{
    social_fetch();
}

You could try to add your function to hook_boot(), but even then the node module might not be loaded, so you will have to ensure it is loaded manually. drupal_load('module', 'node');

You'll end up with

function social_fetch_boot() {
  if(isset($_GET['fetch'])) {
    drupal_load('module', 'node');
    social_fetch();
  }
}
4
  • This is a great example of my frustration with drupal - I did exactly this, and after you answered. It does not trigger. What exactly is calling social_fetch_boot? and why does it not call that for me? The module directory is called social_fetch. Should there be no underscore there? Is the naming automatic where the system tries to lower case the module name, replace spaces with _ etc?
    – Kai Qing
    Commented Mar 15, 2016 at 18:33
  • Drupal calls your modules functions for you, in the form of hooks, where you replace the word hook with your module shortname. Did you clear the cache? hooks are not scanned until the cache is cleared. Commented Mar 15, 2016 at 18:35
  • Yeah I clear cache on almost all code changes just to be sure. Thanks. Initially I resorted to the global scope because the hooks werent doing anything. using these answers I was able to get this organized in a sane way and use the node_ functions as intended and not the ghetto back alley way.
    – Kai Qing
    Commented Mar 15, 2016 at 18:42
  • Just be very cautious with the global scope. Drupal is not intended to be used like that, and you might get into trouble later. Commented Mar 15, 2016 at 18:47

Your Answer

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

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