I'm using the SignUp module for a convention schedule application I'm writing. What's the best way to allow signups for a node programmatically? Do I just add all the fields "by hand" then node_save? Or is there a function I missed?

Thanks

Comments

Gremdel’s picture

Status: Active » Closed (fixed)

I dug a little deeper into the SignUp code and I think I may have figured this one out. At the very least, it seems to work. Please let me know if there's a better way to do this:

function con_schedule_confirm_booking($id = NULL)
{
  $node = node_load(array('nid' => $id,
                          'type'=>'con_schedule_booking'));
  if (empty($node))
  {
    drupal_set_message("No such booking.");
    drupal_goto('con_schedule/request/approve');
    return;
  }

  $node->field_booking_status[0]['value'] = 2;  // Switch to 'Confirmed'
  $node->signup_enabled = 1;                    // Tells SignUp to insert default values
  node_save($node);
  
  //drupal_set_message(dprint_r($node, TRUE));
  drupal_set_message("<i>$node->title</i> is confirmed.");
  drupal_goto('con_schedule/request/approve');
}

Thanks! Hopefully this will be of some use to someone.

Gremdel’s picture

Status: Closed (fixed) » Active

All right, newish problem: How do I change the maximum number of signups allowed? Here's what I've tried (using above code):

  $node->field_booking_status[0]['value'] = 2;  // Switch to 'Confirmed'
  $node->signup_enabled = 1;                    // Value that tells SignUp to insert default values
  $node->signup_close_signup_limit = "3";//strval($node->field_booking_max_participants[0]['value']);
  node_save($node);

and when that didn't work I tried:

  $node->field_booking_status[0]['value'] = 2;  // Switch to 'Confirmed'
  $node->signup_enabled = 1;                    // Value that tells SignUp to insert default values
  node_save($node);

  node_load($id);
  $node->signup_close_signup_limit = "3";//strval($node->field_booking_max_participants[0]['value']);
  node_save($node);

I've also tried setting them to an integer instead of a string. Any suggestions?

-Thanks

dww’s picture

Title: How to activate a node programmatically? » Add API for manipulating signup node settings
Version: 6.x-2.x-dev » 6.x-1.x-dev
Category: support » task
Priority: Minor » Normal

Re: #1 -- yeah, that's basically it.

However, you have some problems with this code, most seriously, an XSS (cross site scripting) vulnerability:

  drupal_set_message("<i>$node->title</i> is confirmed.");

Not only is it not translatable (and themers will hate you for the raw HTML), this opens you up to XSS via the node title. Instead, you want this:

  drupal_set_message(t('%title is confirmed.', array('%title' => $node->title)));

See http://api.drupal.org/api/function/t/6 for more.

Also, while I'm reviewing your code:

  $node = node_load(array('nid' => $id,
                          'type'=>'con_schedule_booking'));
  if (empty($node))
  {
    ...

There are a couple of issues in here:

1) If you use node_load() like that, the node_load() cache can't be used (so it's much more expensive). If you just try to load via the nid, the node_load cache is used.

2) Code style is wrong on the if (since the { should be on the same line).

So, I'd write this like so:

  $node = node_load($id);
  if (empty($node) || $node->type != 'con_schedule_booking') {
    ...

This assumes $id is an integer. If you can't trust the $id (depends on the caller for safety), you can always cast it to an integer, like so:

  $node = node_load((int)$id);

Re #2: The signup settings themselves aren't handled via node_save() anymore. See #578502: Move signup-related settings from node/N/edit to node/N/signups/settings. So, there's no real API for modifying the signup settings on a node -- it's all form-based, which is evil. My apologies. See signup/includes/node_settings.inc for more, in particular signup_node_settings_form() and signup_node_settings_form_submit(). Ugh.

The simplest way is to do the query yourself:

  db_query("UPDATE {signup} SET forwarding_email = '%s', send_confirmation = %d, confirmation_email = '%s', close_signup_limit = %d, send_reminder = %d, reminder_days_before = %d, reminder_email = '%s' WHERE nid = %d", $values);

But, that's still evil.

Really, there should be an API for this, something like:

/**
 * Save signup node settings for a given node.
 *
 * @param $nid
 *   Integer node ID for the signup-enabled node to save settings for.
 * @param $settings
 *   Array of signup-related settings to save.
 *   [should document all the allowed values here]
 * @return NULL
 *   This function directly saves the settings to the database and returns no value.
 */
function signup_save_node_settings($nid, $settings) {
  ...
}

This function should do the above query, and is what should be called by signup_node_settings_form_submit() to save the values. Then, other callers could use the same function to do the same stuff, without either having to directly touch the DB nor messing around with faking form submissions, etc.

Changing title and metadata about this issue to reflect that this task should be done, it's not just a support request anymore. Patches welcome. ;)

Cheers,
-Derek

p.s. the filtering stuff on drupal.org is messing with the whitespace a bit, so the above is not formatted to match the Drupal coding standards. Don't let that fool you. ;) It should have a leading space before each ' *' and before the ' */'...

Gremdel’s picture

Thanks for all the input, Derek, it's really appreciated. Here's what I've done based on your suggestions (and it seems to work):

function con_schedule_confirm_booking($id = NULL)
{
  $node = node_load((int)$id);
  if (empty($node) || $node->type != 'con_schedule_booking')
  {
    drupal_set_message(t("No such booking."));
    drupal_goto('con_schedule/request/approve');
    return;
  }

  $node->field_booking_status[0]['value'] = 2;  // Switch to 'Confirmed'
  $node->signup_enabled = 1;                    // Value that tells SignUp to insert default values
  node_save($node);

  $query = "UPDATE {signup} SET close_signup_limit=%d WHERE nid=%d";
  db_query($query, array($node->field_booking_max_participants[0]['value'], $id));
  
  drupal_set_message(t('%title is confirmed.', array('%title' =>  $node->title)));
  drupal_goto('con_schedule/request/approve');
}

Thanks again and for going to extra mile to help with drupal in general.

socialnicheguru’s picture

subscribing

socialnicheguru’s picture

@Grendel et all,

I am having the same issue.

I tried doing it in rules, but the value for signup_close_signup_limit is overwritten at some point after I execute the rule. I tried using php execution for it. but that didn't work.

Edit.
I created a php rule and just accessed the database.

The api for signup settings would really help

<?php

$booking_maximum = 1;
$booking_nid = $node_booking->nid;

 if  (module_exists('signup')){
  $query = "UPDATE {signup} SET close_signup_limit=%d WHERE nid=%d";
  db_query($query, array($booking_maximum, $booking_nid));
}
dsm ($node_booking);

?>