I need to create a module that adds a variable to the node create/edit pages.

This variable will control whether or not a specific set of function calls are made on the submit of that create/edit page.

I've tried multiple areas of trying to get help, with no luck. My original help thread is here

I understand how to create a module and have looked over the documentation

What I don't understand is how to use a module to add a section to the node create/edit page, as well as how to add a function that is done on the submit of a new/edited node.

Comments

nedjo’s picture

hook_form_alter allows you to alter (in your case, add to) an existing form. See the implementation in taxonomy.module (taxonomy_form_alter()) for an example of how to attach things to node forms.

hook_nodeapi allows you to respond to node create/update events. In modulename_nodeapi() you'll want something like:


switch ($op) {
  case 'insert';
  case 'update':
    // Do your thing.
   break;
}

ymmatt’s picture

I just updated to 5.1, and based on what nedjo said above I've done loads of research and I want to make sure I have this right:

The most relevant pages that I looked at are here:
Changing the title of a node
Adding your own extra _submit or function ...
The form_set_value function

My concern is that there isn't much documentation yet for 5.x and I don't want to waste time learning the 4.7 when it won't all apply to 5.x

I believe that I need to create a module that uses the following hooks and use the following functions within them:

mymodule_node_form_alter
{
needs to add a checkbox
and its own submit functions using $form['#submit']['my_very_own_form_submit'] = current($form['#submit']);

mymodule_form_set_value
This will allow me to clear the value of the variable after the function has ran (Unless I should do this in the submit function that I added in node_form_alter?

}

and

mymodule_nodeapi
use the switch from above to make the function calls

Is this right?

Also: If I want to have a configurations page so that a person can add their phpbb forum location, as well as username and password for the forum, do I need to create additional tables in the database, or is there a way to put a new variable that is stored in the database?

ymmatt’s picture

OK, I've been able to implement everything, however the section that I added in //do your thing doesn't do my thing. Can you help me figure out what I've done wrong. I've copied my form alter, and my nodeapi code here, it is populated with test data for now:

/**
 * Implementation of hook_form_alter().
 */
function phpbbPostNode_form_alter($form_id, &$form) {
  if (isset($form['#node']) && ($node = $form['#node']) && $form_id == $node->type .'_node_form') {
    if ($node->type == 'interior') {
      $form['postToForum'] = array('#type' => 'checkbox',
	  '#title'		=> t('addTopic'),
	  '#default_value' =>  $node->postToForum,
	  '#description' => t('Check this box to add a link to a new discussion forum'),
	  '#required' =>  FALSE,
	  '#weight' 		=> 1
	  );
    }
    if (is_array($form['phpbbPostNode']) && !empty($form['phpbbPostNode'])) {
      if (count($form['phpbbPostNode']) > 1) { 
        $form['phpbbPostNode'] += array(
          '#type' => 'fieldset',
          '#title' => t('Categories'),
          '#collapsible' => TRUE,
          '#collapsed' => FALSE,
        );
      }
      $form['phpbbPostNode']['#weight'] = -3;
      $form['phpbbPostNode']['#tree'] = TRUE;
    }
  }
}

/**
 * Implementation of nodeapi().
 */
function phpbbPostNode_nodeapi(&$node, $op) {
   switch ($op) {
      case 'insert';
	  case 'update':
         if (($node->type == 'interior') && ($node->postToForum == 'checked')) {
			$phpbb = new curl_phpbb('http://www.mysite.com/forum/');

			// Log in
			$phpbb->phpbbPostNodelogin('user', 'pwd');
			
			// Post a topic
			$body = 'my new body';
			$body .= '[url=http://www.mysite.com/node/9] click here[/url]';
			$subject = 'my new subject';
			$topic = $phpbb->phpbbPostNodenew_topic('1', $body, $subject);
			//echo $topic;
			
			// Log out
			$phpbb->phpbbPostNodelogout();
			$node->postToForum = 0;

		}
		break;
	}
}
Tresler’s picture

Hiya,
If you haven't already have a look at http://api.drupal.org do so soon. you can look up hook_nodeapi on there

If I'm reading this correctly you _only_ want to do this when an existing node is updated, not when a new node is created I *believe* you want a

case 'submit':
  //do something

But check api.drupal.org

Sam Tresler
http://www.treslerdesigns.com
-------------------------------------
"A list of common problems and their solutions can be found in the Troubleshooting FAQ."

ymmatt’s picture

Thank you for your suggestion, I think I have everything in the right place now, however my functioins aren't working correctly.

They work fine outside of drupal, however I think I'm doing something wrong here, maybe a function name interferes with a drupal hook, or function? The original author of this code is Dean Newman written under the GNU/General Public Licence v2.

For some reason the Cookie file is either not created or not written to properly here is the code that should create the cookie file:

function curl_phpbb($phpbb_url, $cookie_name = 'tmpfile.tmp')
	{
		// Check CURL is present
		if ( ! function_exists ( 'curl_init') )
		{
			// Output an error message
			trigger_error('curl_phpbb::error, Sorry but it appears that CURL is not loaded, Please install it to continue.');
			return false;
		}
		if ( empty($phpbb_url) )
		{
			// Output an error message
			trigger_error('curl_phpbb::error, The phpBB location is required to continue, Please edit your script.');
			return false;
		}
		// Set base location
		$this->phpbb_url = $phpbb_url;
		// Create temp file
		$this->cookie_name = $cookie_name;
		
	}


function phpbbPostNodelogin($username, $password)
	{
		global $_SERVER;
	
		// Generate post string
		$post_fields = $this->array_to_http(array(
			'username'	=> $username,
			'password'	=> $password,
			'autologin'	=> 1,
			'redirect'	=> 'index.php',
			'login'		=> 'Log In',
		));
		// Init curl
		$this->curl = curl_init();
		// Set options
		curl_setopt ( $this->curl, CURLOPT_URL, $this->phpbb_url . 'login.php' );
		curl_setopt ( $this->curl, CURLOPT_POST, true );
		curl_setopt ( $this->curl, CURLOPT_POSTFIELDS, $post_fields );
		curl_setopt ( $this->curl, CURLOPT_RETURNTRANSFER, true );
		curl_setopt ( $this->curl, CURLOPT_HEADER, false );
		curl_setopt ( $this->curl, CURLOPT_COOKIE, $this->cookie_name );
		curl_setopt ( $this->curl, CURLOPT_COOKIEJAR, $this->cookie_name );
		curl_setopt ( $this->curl, CURLOPT_COOKIEFILE, $this->cookie_name );
		curl_setopt ( $this->curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT'] );
		// Execute request
		$result = curl_exec ( $this->curl );
		// Error handling
		if ( curl_errno ( $this->curl ) )
		{
			$this->error = array(
				curl_errno($this->curl),
				curl_error($this->curl),
			);
			curl_close ( $this->curl );
			return false;
		}
		// Set Session ID
		$content=file_get_contents($this->cookie_name);
		preg_match('/phpbb2mysql_sid/', $content, $matches, PREG_OFFSET_CAPTURE);
		$offset = $matches[0][1] + strlen($matches[0][0]) + 1;
		$this->sid = substr($content,$offset,32);
		// Close connection
		curl_close ( $this->curl );
		// Return result
		return true;
	}

dwees’s picture

Where are these functions defined in your module? Are they in a separate include file, or did you put them as a new function in the module code itself?

ymmatt’s picture

I put these functions in the module itself.

I found out what was going on, maybe someone else can better explain but here goes:

I think that everything was executing too fast, or out of order, so that the file was unlinked before or while it was attempting to be read by another function. I removed the @unlink($this->cookie_name); and everything works fine

This leaves the tmpfile.tmp file on the server which shouldn't be a problem since its permissions are -rw-r--r--

The latest problem is more than likely with my hook_form_alter implementation. I need the value of the phpbbPostNode_topic to be able to be set and retreived I assume I need to add some variable_set, variable_get calls to my nodeapi, is this true, or is the hook_form_alter implementation wrong? I copied this from the taxonomy module, and I now there is residual code from there that is probably messing this up, but I can't answer that quetion

function phpbbPostNode_form_alter($form_id, &$form) {
  if (isset($form['#node']) && ($node = $form['#node']) && $form_id == $node->type .'_node_form') {
    if ($node->type == 'interior') {
      $form['phpbbPostNode_postToForum'] = array('#type' => 'checkbox',
      '#title'        => t('Add this node to my forum'),
      '#default_value' =>  $node->phpbbPostNode_postToForum,
      '#description' => t('Check this box to add a link to a new discussion forum'),
      '#required' =>  FALSE,
      '#weight'         => -3
      );
      $form['phpbbPostNode_topic'] = array('#type' => 'textfield',
      '#title'        => t('Forum Topic Number'),
      '#default_value' =>  $node->phpbbPostNode_topic,
      '#description' => t('This is the ID nubmer of the related phpbb topic'),
      '#required' =>  FALSE,
      '#weight'         => -2
      );
    }
    if (is_array($form['phpbbPostNode']) && !empty($form['phpbbPostNode'])) {
      if (count($form['phpbbPostNode']) > 1) {
        $form['phpbbPostNode'] += array(
          '#type' => 'fieldset',
          '#title' => t('Categories'),
          '#collapsible' => TRUE,
          '#collapsed' => FALSE,
        );
      }
      $form['phpbbPostNode']['#weight'] = -3;
      $form['phpbbPostNode']['#tree'] = TRUE;
    }
  }
}
ymmatt’s picture

I think what I need to know is how to make these variables exist in the database.

The configuration settings have actually exist in the database, but the variables that I set at node creation/update don't.

This is probably a simple answer, Any Ideas?

newdru’s picture

Did you create YOUR OWN db table to hold your new value(s)?

I only quickly scanned the post but it looks like you are adding a completely new field. And possibly more for user settings. I believe that requires you to create a table with a nid field and the field(s) for your new variable(s). i mean they have to be stored somewhere right. they just can't magically be saved into thin air by drupal. which means you're going to need to implement nodeapi functions that save YOUR form field data to YOUR db on both edits and updates as well as read that data back out into the form for edits of preexisting nodes.. That's what the earlier poster was talking about with nodeapi and update/submit ops.

However, since you are trying to enhance an existing NODE, i'm not so sure you wouldn't want to be using hook_insert and hook_update versus nodeapi.

Either way, I don't see you handling any of those type of functions in any of the code you posted.

fyi, the reason why your config settings exist in the db is because that part is handled automagically by drupal. unless you have some crazy settings (and in your case i actually think you do) the STANDARD drupal settings table is a simple key value table that automatically handles this for you..

i haven't written a module myself but am getting ready to soon.. so i'm not going to be much help outside of what i told you.

good luck

ymmatt’s picture

I was fooled by the automagic of the config setting into thinking that the node variables would be set in the same way.

My guess is that I need to create a module.install file which contains something similar to this but with my variables(taken from gsitemap):

/**
 * Implementation of hook_install().
 */
function phpbbNodePost_install() {
  switch ($GLOBALS['db_type']) {
    case 'mysql':
    case 'mysqli':
      db_query("CREATE TABLE {phpbbNodePost} (
          nid int(10) unsigned primary key,
          last_changed int(11),
          previously_changed int(11),
          last_comment int(11),
          previous_comment int(11),
          priority_override decimal(2,1)
        ) /*!40100 DEFAULT CHARACTER SET utf8 */;
      ");
      break;

    case 'pgsql':
      db_query("CREATE TABLE {phpbbNodePost} (
          nid integer PRIMARY KEY, 
          last_changed integer, 
          previously_changed integer, 
          last_comment integer, 
          previous_comment integer, 
          priority_override real
        );
      ");
      break;
  }
ymmatt’s picture

Ok, so you were right, and the .install file did the trick (after I installed the devel module so I could re-install my module!)

I did have to make a few changes, but the gsitemap module really helped me with mine.

Now I need to be able to get the forum topic number out of the resultant page.

For example I need a regexp that will pull 655 from the line below:
<link rel="prev" href="viewtopic.php?t=655&amp;view=previous" title="View previous topic" />

I currently have this but it returns 0, any ideas as to what I'm doing wrong:

		// Get the Topic ID to Return to the requestee
		preg_match('/viewtopic.php\?t=/', $result, $match, PREG_OFFSET_CAPTURE);
		$offset = $match[0][1] + strlen($match[0][0]);
		$subResult = substr($result,$offset,7);
		preg_match('/&/', $subResult, $match, PREG_OFFSET_CAPTURE);
		$tid = substr($subResult,0,$match[0][1]);
ymmatt’s picture

I've gotten everything working the way I wanted to get it working.

I had to connect to the phpbb database in order to get the correct topic ID and now everything is working the way I wanted it working!

Once I clean everything up I will see what it takes to make it publicly available

newdru’s picture

post it when you're done

ymmatt’s picture

This may be jumping the gun a bit, but I've committed the module to the CVS repository and created the project page.

From what I understand this will take some time before it is available for download, but when it is here is the project page: http://drupal.org/project/phpbbPostNode