Basically, I want to send out notifications of a node creation if a user is subscribed to a node that is referenced using the cck node reference. I have a couple content types called Industry and Career, which are nodes I am controlling, and I want users (who can create their own images and video) to be notified when content has been created that references careers or industries that they are subscribed to. Does that make sense? I was looking at the code, and it seems that this might be done through a hook, or through modifying the subscriptions.module around line 189 in the subscriptions_queue function. Can someone point me in the right direction here? Thanks in advance for the help.

Brett

Comments

salvis’s picture

Yes, hook_subscriptions_queue_alter() looks like a good way to do what you want. You'd check your conditions and create {subscriptions_queue} entries yourself for the users that meet your conditions.

Let us know how it goes.

brettev’s picture

Thanks a ton for your help. I have the logic set up, I just need to know what to add to the rows to make sure it works how I think it should.

I should set module="node", but what do I do for field and value? Do I still use the load_args and load_function as the nid and subscriptions_content_node_load like the ones in there are? Also, does is_new = 1 and last_sent = 0? I'm sure these are pretty simple questions, but for all my searching, I can't seem to find what the rows I have in my table are doing there. Shouldn't they be cleared out when the email is sent?

Brett

salvis’s picture

field determines which template (mailkey) you get and which mailvars_function. Try 'nid' and use the nid as value.

Yes, use load_args and load_function as given, unless you want to provide your own load_function() for some reason.

If the post is new, is_new should be 1, if it's only updated or commented, it should be 0. last_sent is copied from the user's {subscriptions_user} entry.

Yes, after cron has run and sent out the notifications, the corresponding entries in {subscriptions_queue} should be gone. All of this is done in subscriptions_cron().

brettev’s picture

This is what I have so far. The first 2 are for nodes that reference them through a single select field, and the second two are for multi selects. Thoughts? Comments? Criticisms?

function sub_by_cckref_subscriptions_queue_alter(&$event) {
	$node = $event['node'];
	$mainindustry = $node->field_main_industry[0]['nid'];
	if (is_numeric($mainindustry) and $mainindustry > 0) {
		//trigger an email to everyone that is subscribed to this main industry
		sub_by_cckref_add_to_queue($event, $node, $mainindustry);
	}
	
	$maincareer = $node->field_main_career[0]['nid'];
	if (is_numeric($maincareer) and $maincareer > 0) {
		//trigger an email to everyone that is subscribed to this main career
		sub_by_cckref_add_to_queue($event, $node, $maincareer);
	}
	
	$industries = $node->field_industry_ref;
	if ($industries) {
		foreach ($industries as $key => $value) {
			if (is_numeric($value) and $value > 0) {
				//trigger an email to everyone that is subscribed to this industry
				sub_by_cckref_add_to_queue($event, $node, $value);
			}
		}
	}
	
	$careers = $node->field_career_ref_reqd;
	if ($careers) {
		foreach ($careers as $key => $value) {
			if (is_numeric($value) and $value > 0) {
				//trigger an email to everyone that is subscribed to this career
				sub_by_cckref_add_to_queue($event, $node, $value);
			}
		}
	}
}

function sub_by_cckref_add_to_queue($event, $node, $noderefid) {
	//find all users subscribed to the mainindustry
	$subusers = db_query("SELECT recipient_uid FROM {subscriptions} WHERE field='nid' AND value=%d ", $noderefid);
	while ($subuser = db_fetch_object($subusers)) {
		$userrow = db_fetch_object(db_query("SELECT name, mail FROM {users} WHERE uid=%d", $subuser->recipient_uid));
		$username = $userrow->name;
		$useremail = $userrow->mail;
		if (is_numeric($subuser->recipient_uid) and $subuser->recipient_uid > 0 and strlen($username) > 0 and strlen($useremail) > 0) {
			$db_query("INSERT INTO {subscriptions_queue} 
				(uid, name, mail, language, module, field, value, author_uid, 
				send_interval, digest, load_args, load_function, is_new, last_sent) 
				VALUES 
				(%d, '%s', '%s', '', 'node', 'nid', %d, %d, 1, -1, %d, 
				'subscriptions_content_node_load', %d, %d)", 
				$subuser->recipient_uid, $username, $useremail, $event['load_args'], 
				$node->uid, $event['load_args'], $event['is_new'], 0);
		}
	}
}
salvis’s picture

You must check that your $event really contains a node. Then use its nid, not load_args as value, and also pass on the load_function that you get, rather than hard-coding it. Finally, as I said before, last_sent should be taken from {subscriptions_user}.

Does it work?

brettev’s picture

Thanks for the hints. I think I fixed them. Does this look a little better? I haven't turned the module on yet, I'm kind of waiting to pass it back and forth with some people first. I'm hoping to turn it on today though.

function sub_by_cckref_subscriptions_queue_alter(&$event) {
	//global $user;
	//if($user->uid == 1) print_r($event);
	if(is_set($event['node'])){
		$node = $event['node'];
		$mainindustry = $node->field_main_industry[0]['nid'];
		if (is_numeric($mainindustry) and $mainindustry > 0) {
			//trigger an email to everyone that is subscribed to this main industry
			sub_by_cckref_add_to_queue($event, $node, $mainindustry);
		}
		
		$maincareer = $node->field_main_career[0]['nid'];
		if (is_numeric($maincareer) and $maincareer > 0) {
			//trigger an email to everyone that is subscribed to this main career
			sub_by_cckref_add_to_queue($event, $node, $maincareer);
		}
		
		$industries = $node->field_industry_ref;
		if ($industries) {
			foreach ($industries as $key => $value) {
				if (is_numeric($value) and $value > 0) {
					//trigger an email to everyone that is subscribed to this industry
					sub_by_cckref_add_to_queue($event, $node, $value);
				}
			}
		}
		
		$careers = $node->field_career_ref_reqd;
		if ($careers) {
			foreach ($careers as $key => $value) {
				if (is_numeric($value) and $value > 0) {
					//trigger an email to everyone that is subscribed to this career
					sub_by_cckref_add_to_queue($event, $node, $value);
				}
			}
		}
	}
}

function sub_by_cckref_add_to_queue($event, $node, $noderefid) {
	//find all users subscribed to the mainindustry
	$subusers = db_query("SELECT recipient_uid FROM {subscriptions} WHERE field='nid' AND value=%d ", $noderefid);
	while ($subuser = db_fetch_object($subusers)) {
		$userrow = db_fetch_object(db_query("SELECT name, mail FROM {users} WHERE uid=%d", $subuser->recipient_uid));
		$username = $userrow->name;
		$useremail = $userrow->mail;
		$lastsent = db_result(db_query("SELECT last_sent FROM {subscriptions_user} WHERE uid=%d", $subuser->recipient_uid));
		if (is_numeric($subuser->recipient_uid) and $subuser->recipient_uid > 0 and strlen($username) > 0 and strlen($useremail) > 0) {
			$db_query("INSERT INTO {subscriptions_queue} 
				(uid, name, mail, language, module, field, value, author_uid, 
				send_interval, digest, load_args, load_function, is_new, last_sent) 
				VALUES 
				(%d, '%s', '%s', '', 'node', 'nid', %d, %d, 1, -1, %d, 
				'%s', %d, %d)", 
				$subuser->recipient_uid, $username, $useremail, $node->nid, 
				$node->uid, $event['load_args'], $event['load_function'] ,$event['is_new'], $lastsent);
		}
	}
}
salvis’s picture

I don't see any obvious problems, but that doesn't mean much. I would single-step through this kind of code in a debugger to make sure that it does what I intend, and following the flow of control and inspecting variable values often reveals bugs.

brettev’s picture

here's the working version. tested and awesome!! I had 4 fields I wanted to check against, so those are the 4 top parts.

function sub_by_cckref_subscriptions_queue_alter(&$event) {	
	if($event['module'] == 'node' and $event['action'] == 'insert'){
		$node = $event['node'];				
		$mainindustry = $node->field_main_industry[0][nid];
		if (is_numeric($mainindustry) and $mainindustry > 0) {
			sub_by_cckref_add_to_queue($event, $node, $mainindustry);
		}
		$maincareer = $node->field_main_career[0][nid];
		if (is_numeric($maincareer) and $maincareer > 0) {
			sub_by_cckref_add_to_queue($event, $node, $maincareer);
		}
		$industries = $node->field_industry_ref;
		if (is_array($industries)) {
			foreach ($industries as $value) {
				$value = $value['nid'];
				if (is_numeric($value) and $value > 0) {
					sub_by_cckref_add_to_queue($event, $node, $value);
				}
			}
		}
		$careers = $node->field_career_ref_reqd;
		if (is_array($careers)) {
			foreach ($careers as $value) {
				$value = $value['nid'];
				if (is_numeric($value) and $value > 0) {
					sub_by_cckref_add_to_queue($event, $node, $value);
				}
			}
		}		
	}
}

function sub_by_cckref_add_to_queue($event, $node, $noderefid) {
	$subusers = db_query("SELECT recipient_uid FROM {subscriptions} WHERE field='nid' AND value=%d ", $noderefid);
	while ($subuser = db_fetch_object($subusers)) {
		$userrow = db_fetch_object(db_query("SELECT name, mail FROM {users} WHERE uid=%d", $subuser->recipient_uid));
		$username = $userrow->name;
		$useremail = $userrow->mail;
		$lastsent = db_result(db_query("SELECT last_sent FROM {subscriptions_user} WHERE uid=%d", $subuser->recipient_uid));
		if (is_numeric($subuser->recipient_uid) and $subuser->recipient_uid > 0 and strlen($username) > 0 and strlen($useremail) > 0) {
			db_query("INSERT INTO {subscriptions_queue} (uid, name, mail, language, module, field, value, author_uid, send_interval, digest, load_args, load_function, is_new, last_sent) VALUES (%d, '%s', '%s', '', 'node', 'nid', %d, %d, 1, -1, %d, '%s', %d, %d)", $subuser->recipient_uid, $username, $useremail, $node->nid, $node->uid, $event['load_args'], $event['load_function'] ,$event['is_new'], $lastsent);
		}
	}
}
salvis’s picture

Did you miss the closing tag? Please try to edit #8 and make it readable...

brettev’s picture

fixed

salvis’s picture

Nice work, congratulations!

Now that I think about it again, it would probably be better to call subscriptions_queue() rather than inserting directly into {subscriptions_queue}. This would give others a chance to hook_subscriptions_queue_alter (you'd get the call, too, and have to be prepared for it, of course) and insulate you a somewhat against changes in the database schema.

greggles’s picture

This is _exactly_ what I need.

@brettev, are you interested in maintaining this as a module on drupal.org? If not, I would like to do so.

brettev’s picture

I would maintain it, but it would have to be made generic and setup with an admin interface. I'm not sure if it would make it to drupal.org as is right now. Would you be interested in making it more generic with an admin page?

greggles’s picture

@brettev - yes, now that I've played with it more I realize that it needs a bit more work in order to be generalized.

I'm not really sure how to make it more generic right now. I've built similar modules and think it is possible, but I'd need to dig into the CCK API again.

aschiwi’s picture

Hi brettev,

I'm hoping to have some questions answered on your code. I am no coder but I think I could take the code you posted to modify and use it for me.

Here is my scenario: People would subscribe to a node of type "one". I want them to be notified when a node of type "two" has been created that references the node they are subscribed to. I think that is what your code does, but I don't know your setup. Could you generalize and comment the top part of your code (in function sub_by_cckref_subscriptions_queue_alter) a little bit, so that I can try and use it for myself?

brettev’s picture

No problem. Happy to help. I've pulled out the 4 checks I had, and just left one of them to simplify things. It should make it easier for you to swap out.

You should leave the bottom function as is, and just modify the $node->field_main_industry[0][nid] to say $node->field_yourfieldname[0][nid].
this only works if it is a single node ref (drop down, not multiselect). The multi select you could pull off my code above.

Does this make sense?

function sub_by_cckref_subscriptions_queue_alter(&$event) {   
    if($event['module'] == 'node' and $event['action'] == 'insert'){
        $node = $event['node'];    //this references the node that is being inserted. In your case, this would be type "two".           
        $mainindustry = $node->field_main_industry[0][nid]; //this is the code that pulls the cck field (node reference), which is what the person is subscribed to (type 'one' for you)
        if (is_numeric($mainindustry) and $mainindustry > 0) { //if this is a valid node reference, trigger subscription notifications to everyone that is subscribed to that type 'one' node
            sub_by_cckref_add_to_queue($event, $node, $mainindustry);
        }
    }
}


/*
 * this function takes the node and the REFERENCED id, 
 * (type one for you) and finds people who are subscribed 
 * to the type 'one' and sends them a notification for the node type 'two'
 */
function sub_by_cckref_add_to_queue($event, $node, $noderefid) {
    $subusers = db_query("SELECT recipient_uid FROM {subscriptions} WHERE field='nid' AND value=%d ", $noderefid); 
    while ($subuser = db_fetch_object($subusers)) {
        $userrow = db_fetch_object(db_query("SELECT name, mail FROM {users} WHERE uid=%d", $subuser->recipient_uid));
        $username = $userrow->name;
        $useremail = $userrow->mail;
        $lastsent = db_result(db_query("SELECT last_sent FROM {subscriptions_user} WHERE uid=%d", $subuser->recipient_uid));
        if (is_numeric($subuser->recipient_uid) and $subuser->recipient_uid > 0 and strlen($username) > 0 and strlen($useremail) > 0) {
            db_query("INSERT INTO {subscriptions_queue} (uid, name, mail, language, module, field, value, author_uid, send_interval, digest, load_args, load_function, is_new, last_sent) VALUES (%d, '%s', '%s', '', 'node', 'nid', %d, %d, 1, -1, %d, '%s', %d, %d)", $subuser->recipient_uid, $username, $useremail, $node->nid, $node->uid, $event['load_args'], $event['load_function'] ,$event['is_new'], $lastsent);
        }
    }
}
aschiwi’s picture

First of all, thank you for your quick help! Second, I didn't get it to work yet, I tried a few thinks but it's not happening. Could you take a look at my code? I changed the name of the module in the function, because I had already named it something else. I changed the name of my field (it happens to be multiselect because I need to prepopulate and hide the field for users) and figured I could leave $industries. In line 3 it now says $node = $event['two'];, which is probably wrong because you didn't tell me to change that to the name of my content type. BUT, writing 'node' instead of 'two' doesn't do it either. I'm sure though that somewhere I would have to put both "one" and "two", so that the module knows which content types I'm referring to?

<?php
function subscriptions_by_noderef_queue_alter(&$event) {  
    if($event['module'] == 'node' and $event['action'] == 'insert'){
        $node = $event['two'];    //this references the node that is being inserted. In your case, this would be type "two".          
        
		$industries = $node->field_noderef_arbeitsschritt_ref;
        if (is_array($industries)) {
            foreach ($industries as $value) {
                $value = $value['nid'];
                if (is_numeric($value) and $value > 0) {
                    subscriptions_by_noderef_add_to_queue($event, $node, $value);
                }
            }
        }
    }
}


/*
* this function takes the node and the REFERENCED id,
* (type one for you) and finds people who are subscribed
* to the type 'one' and sends them a notification for the node type 'two'
*/
function subscriptions_by_noderef_add_to_queue($event, $node, $noderefid) {
    $subusers = db_query("SELECT recipient_uid FROM {subscriptions} WHERE field='nid' AND value=%d ", $noderefid);
    while ($subuser = db_fetch_object($subusers)) {
        $userrow = db_fetch_object(db_query("SELECT name, mail FROM {users} WHERE uid=%d", $subuser->recipient_uid));
        $username = $userrow->name;
        $useremail = $userrow->mail;
        $lastsent = db_result(db_query("SELECT last_sent FROM {subscriptions_user} WHERE uid=%d", $subuser->recipient_uid));
        if (is_numeric($subuser->recipient_uid) and $subuser->recipient_uid > 0 and strlen($username) > 0 and strlen($useremail) > 0) {
            db_query("INSERT INTO {subscriptions_queue} (uid, name, mail, language, module, field, value, author_uid, send_interval, digest, load_args, load_function, is_new, last_sent) VALUES (%d, '%s', '%s', '', 'node', 'nid', %d, %d, 1, -1, %d, '%s', %d, %d)", $subuser->recipient_uid, $username, $useremail, $node->nid, $node->uid, $event['load_args'], $event['load_function'] ,$event['is_new'], $lastsent);
        }
    }
}
?>
brettev’s picture

I'm guessing this should work. You are using a multi select for the field, right?

function subscriptions_by_noderef_queue_alter(&$event) { 
    if($event['module'] == 'node' and $event['action'] == 'insert'){
        $node = $event['node'];    //this should stay 'node' no matter what type you are using.    
       
        $industries = $node->field_noderef_arbeitsschritt_ref;
        if (is_array($industries)) {
            foreach ($industries as $value) {
                $value = $value['nid'];
                if (is_numeric($value) and $value > 0) {
                    subscriptions_by_noderef_add_to_queue($event, $node, $value);
                }
            }
        }
    }
}


/*
* this function takes the node and the REFERENCED id,
* (type one for you) and finds people who are subscribed
* to the type 'one' and sends them a notification for the node type 'two'
*/
function subscriptions_by_noderef_add_to_queue($event, $node, $noderefid) {
    $subusers = db_query("SELECT recipient_uid FROM {subscriptions} WHERE field='nid' AND value=%d ", $noderefid);
    while ($subuser = db_fetch_object($subusers)) {
        $userrow = db_fetch_object(db_query("SELECT name, mail FROM {users} WHERE uid=%d", $subuser->recipient_uid));
        $username = $userrow->name;
        $useremail = $userrow->mail;
        $lastsent = db_result(db_query("SELECT last_sent FROM {subscriptions_user} WHERE uid=%d", $subuser->recipient_uid));
        if (is_numeric($subuser->recipient_uid) and $subuser->recipient_uid > 0 and strlen($username) > 0 and strlen($useremail) > 0) {
            db_query("INSERT INTO {subscriptions_queue} (uid, name, mail, language, module, field, value, author_uid, send_interval, digest, load_args, load_function, is_new, last_sent) VALUES (%d, '%s', '%s', '', 'node', 'nid', %d, %d, 1, -1, %d, '%s', %d, %d)", $subuser->recipient_uid, $username, $useremail, $node->nid, $node->uid, $event['load_args'], $event['load_function'] ,$event['is_new'], $lastsent);
        }
    }
}
aschiwi’s picture

Yes I am using a multiselect field. Not required, because it gets filled in anyways (by prepopulate, not by user). I tried your above code, but still not working yet. Checked my field again, because I am prepopulating the field with (for example) [nid:70] instead of the actual title of the node. I thought that might be it. But then I tried with writing the words in and it was the same. I guess I have to tackle this again tomorrow, probably missing something small...

brettev’s picture

The code is set to work with node reference type fields. It won't work with a text field where you are putting the node id in.

aschiwi’s picture

But it IS a node reference field... I am using the autocomplete kind. To get a node referenced, you can either type in the title of the node or type in [nid:40], "40" standing for whatever the nid is. For some reason I can't remember now, I couldn't get the title information into the nodereference field by using prepopulate. But either way, I tried the code by typing in the actual title of the referenced node and it didn't work. I have to try again today, will let you know what works out for me in the end :-)

aschiwi’s picture

So with some help of a friend I finally managed to do this. It was my mistake, on line 1 I didn't see that it had to be modulename_SUBSCRIPTIONS_queue_alter...
And by the way, it works wether the nodereference field has the title of the referenced node in it OR the nid (in the [nid:1] pattern). We use prepopulate to put the nid in the nodereference field because sometimes the title of a node might be too long for it, and then it wont get referenced right.

Thanks again for your help.

<?php
function sub_by_cckref_subscriptions_queue_alter(&$event) {  
    if($event['module'] == 'node' and $event['action'] == 'insert'){
        $node = $event['node'];    //this references the node that is being inserted. In your case, this would be type "two".          
        $arbeitsschritt = $node->field_noderef_arbeitsschr;
        if (is_array($arbeitsschritt)) {
            foreach ($arbeitsschritt as $value) {
                $value = $value['nid'];
                if (is_numeric($value) and $value > 0) {
                    sub_by_cckref_add_to_queue($event, $node, $value);
                }
            }
        }
		 $aktivitaet = $node->field_noderef_arbeitspaket_v_ak;
        if (is_array($aktivitaet)) {
            foreach ($aktivitaet as $value) {
                $value = $value['nid'];
                if (is_numeric($value) and $value > 0) {
                    sub_by_cckref_add_to_queue($event, $node, $value);
                }
            }
        }        
    }
}


/*
* this function takes the node and the REFERENCED id,
* (type one for you) and finds people who are subscribed
* to the type 'one' and sends them a notification for the node type 'two'
*/
function sub_by_cckref_add_to_queue($event, $node, $noderefid) {
    $subusers = db_query("SELECT recipient_uid FROM {subscriptions} WHERE field='nid' AND value=%d ", $noderefid);
    while ($subuser = db_fetch_object($subusers)) {
        $userrow = db_fetch_object(db_query("SELECT name, mail FROM {users} WHERE uid=%d", $subuser->recipient_uid));
        $username = $userrow->name;
        $useremail = $userrow->mail;
        $lastsent = db_result(db_query("SELECT last_sent FROM {subscriptions_user} WHERE uid=%d", $subuser->recipient_uid));
        if (is_numeric($subuser->recipient_uid) and $subuser->recipient_uid > 0 and strlen($username) > 0 and strlen($useremail) > 0) {
            db_query("INSERT INTO {subscriptions_queue} (uid, name, mail, language, module, field, value, author_uid, send_interval, digest, load_args, load_function, is_new, last_sent) VALUES (%d, '%s', '%s', '', 'node', 'nid', %d, %d, 1, -1, %d, '%s', %d, %d)", $subuser->recipient_uid, $username, $useremail, $node->nid, $node->uid, $event['load_args'], $event['load_function'] ,$event['is_new'], $lastsent);
        }
    }
}
?>
Flying Drupalist’s picture

Hi, is this going to become a module?

brettev’s picture

http://www.brettevanson.com/module/subscriptions-cck-node-reference

I haven't tested it as it is, but it should work. Let me know if it works for you.

salvis’s picture

Hi, is this going to become a module?

I don't understand it well enough to tell whether it's sufficiently general to become a subscriptions/contrib, nor whether brettev wants to contribute it and continue to support it, but I'm certainly open to contributions.

brettev’s picture

I need a few people to use it and post feedback about whether it works for their needs or not. If enough people use it and have a good experience with it, then we can push for include into the subscriptions contrib section.

Brett

Flying Drupalist’s picture

Oh, I'm on 6.6. Can't use this yet. :(

brettev’s picture

I updated the module with a new table name. As far as why it's not showing up in your list, I am not sure. That's a troubleshooting issue, not an issue with this module specifically. Could you have the files in the wrong directory?

Flying Drupalist’s picture

Hi, you must be seeing an old version of my post. I updated it yesterday. I'm on 6.6, and originally I was confused because I couldn't find a checkbox under the subscription category in the module listing, where I assumed it would be. Then I realized that this was a 5.x issue and I couldn't use the module in any case. A 6.x port would be appreciated, sorry for the trouble.

aschiwi’s picture

I didn't try your module but I am using the code you provided here in a custom module. What I just realized is missing from that code is that there are no notifications sent out when the node is updated, which is something I need and added to my code. I looked at the code of your module and I think you don't have 'update' in there either (though I am by no means a coder, maybe I just didn't see).

In line 52 of your module it says

<?php 
if($event['module'] == 'node' and $event['action'] == 'insert') {
?>

The same line is in the code I got from you before and I added the update part so now it looks like this:

<?php 
if($event['module'] == 'node' && (($event['action'] == 'insert') || ($event['action'] == 'update'))) {
?>
parrottvision’s picture

subscribing - would love to see this in 6 as a part of module.

MJH’s picture

This is exactly the functionality I am looking for.
Will this be included in the Drupal 6 version of Subscriptions or will there be an external module?

Is there another "Subscription / Notification" module already working under Drupal 6, that can inform a user subscribed to a node if that node is referenced in another node?

gunzip’s picture

subscribe ;)

gunzip’s picture

well maybe there's a simple way with nodeapi intercepting the insert of a node with a reference field:

function mymodule_nodeapi(&$node, $op, $params = NULL, $page = NULL) {
  switch ($op) {
    case 'insert':
      if (isset($node->field_referred_ref[0]['nid'])) {
        $ref   = node_load($node->field_referred_ref[0]['nid']);
        $event = array(
          'module'        => 'node',
          'uid'           => $ref->uid,
          'load_function' => 'subscriptions_content_node_load',
          'load_args'     => $ref->nid,
          'type'          => 'node',
          'action'        => $op,
          'is_new'        => TRUE,
          'node'          => $ref,
        );
        subscriptions_queue($event);
      }
}

i think this could be merged into the subscriptions_cck nodeapi
(you have to loop through all the nids if you have a multi value field...)

lelizondo’s picture

subscribe

caponey’s picture

i just found this, but do you use this code in template.php, or do you use it in the subscription module, or your own created module?

greggles’s picture

In my opinion, this issue should be marked "fixed" since it kind of is.

There is not really a way to do this generically and I don't think it's a good long term solution. The Notifications/Messaging frameworks are better supported than Subscriptions at this point and any future solutions should be based on that (in my humble opinion...).

salvis’s picture

Indeed I don't see any generic solution either. If anyone has one, I'll certainly be interested.

I'm leaving this issue open as a kind of forum for Subscriptions users to exchange their ideas. If we closed it, someone would probably open a new issue.

The Notifications/Messaging frameworks are better supported than Subscriptions at this point

Well, it took 5 hours to implement #817342: Change weight of the Subscribe fieldset in CCK 'manage fields' page for Subscriptions, after #606454: Change weight of the notifications fieldset in CCK 'manage fields' page had been languishing for over 7 months in the Notifications queue. David Goode then copied my diff, without acknowledgment, and Jose Reyero committed it under David's name: http://drupal.org/cvs?commit=375656 (diff).

I don't have the time or interest to follow the Notifications project. They may have more critical mass, but from what I see of them, these people operate in a way that is not compatible with ours. That's how it was when Jose branched Notifications from Subscriptions, and apparently it's still the same today.

(When comparing the quality of support you should also take into account the 55 open bug reports for Notifications plus 20 for Messaging vs. 0 for Subscriptions.)

keremito’s picture

Hi there,

I would like to do something to update brettev's script for D6. I've downloaded the script from brettev's site (#24), and go through http://drupal.org/node/114774 to convert it to a 6.x module. It's not working now. Install script should use schema api, coder module says. When a referencing node is created system gives error. Before spending more time on,

any ideas? am I totally on a wrong way?

brettev’s picture

post your code and i'll take a peek at it, or send it to me directly

keremito’s picture

Version: 6.x-1.x-dev » 5.x-2.0

Hi brettev,

Thank you very much for your support. install file didnt change, and here is the new module file with minor changes after deadwood.


function sub_by_cckref_menu(){
	$items = array();
	if(!$may_cache){
		$items['admin/settings/sub_by_cckref'] = array(
		  'title'     => 'Administer Subscriptions by CCK Reference',
		  'description'     =>'Set node type for node references',
		  'page callback' => 'drupal_get_form',
		  'page arguments' => array('sub_by_cckref_admin_form'),
		  'access arguments' => array('administer subbycckref'),
		);
	}
	return $items;
}

function sub_by_cckref_perm(){
	return array('administer subbycckref');
}

function sub_by_cckref_admin_form(){
	$form = array();
	
	$info = _content_type_info();
	$options = $info['fields'];
	$options2 = array();

	foreach($options as $option){
		if($option[type] == 'nodereference') $options2[$option[field_name]] = $option[widget][label];
	}	

	$form['sub_by_cck_fieldname'] = array(
		'#type' => 'select',
		'#options' => $options2,
		'#title' => t('Field for subscriptions'),
		'#default_value' => variable_get('sub_by_cck_fieldname', ''),
		'#description' => t("Field name that the people subscribe to"),
	);	

	return system_settings_form($form); 
}

function sub_by_cckref_admin_form_validate($form, &$form_state){
	if(isset($form_state['values']['sub_by_cck_fieldname'])) {
		variable_set('sub_by_cck_fieldname',$form_state['values']['sub_by_cck_fieldname']);
		drupal_set_message(t('Field Name Set: ').$form_state['values']['sub_by_cck_fieldname']);
	}
}

function sub_by_cckref_subscriptions_queue_alter(&$event) {	
	if($event['module'] == 'node' and $event['action'] == 'insert'){
		$node = $event['node'];	
		$fieldname = variable_get('sub_by_cck_fieldname', '');
		$temp1 = $node->$fieldname;	
		$temp2 = $temp1[0][nid];
		if (is_numeric($temp2) and $temp2 > 0) {
			sub_by_cckref_add_to_queue($event, $node, $temp2);
		}
		$temp3 = $node->$fieldname;
		if (is_array($temp3)) {
			foreach ($temp3 as $value) {
				$value = $value['nid'];
				if (is_numeric($value) and $value > 0) {
					sub_by_cckref_add_to_queue($event, $node, $value);
				}
			}
		}		
	}
}

function sub_by_cckref_add_to_queue($event, $node, $noderefid) {
	$subusers = db_query("SELECT recipient_uid FROM {subscriptions} WHERE field='nid' AND value=%d ", $noderefid);
	while ($subuser = db_fetch_object($subusers)) {
		$userrow = db_fetch_object(db_query("SELECT name, mail FROM {users} WHERE uid=%d", $subuser->recipient_uid));
		$username = $userrow->name;
		$useremail = $userrow->mail;
		$lastsent = db_result(db_query("SELECT last_sent FROM {subscriptions_user} WHERE uid=%d", $subuser->recipient_uid));
		if (is_numeric($subuser->recipient_uid) and $subuser->recipient_uid > 0 and strlen($username) > 0 and strlen($useremail) > 0) {
			db_query("INSERT INTO {subscriptions_queue} (uid, name, mail, language, module, field, value, author_uid, send_interval, digest, load_args, load_function, is_new, last_sent) VALUES (%d, '%s', '%s', '', 'node', 'nid', %d, %d, 1, -1, %d, '%s', %d, %d)", $subuser->recipient_uid, $username, $useremail, $node->nid, $node->uid, $event['load_args'], $event['load_function'] ,$event['is_new'], $lastsent);
			//add code here to insert into a db table. this is for the career feed
			db_query("INSERT INTO {subscriptions_cck_node_ref} (nid, title, refid, uid, created) VALUES (%d, '%s', %d, %d, %d)", $node->nid, $node->title, $noderefid, $subuser->recipient_uid, time());
		}
	}
}
brettev’s picture

Well, I made a couple modifications. I'm not 100% sure the subscriptions module hasn't changed its database layout, but there were a couple things in the menu system and the form stuff that I fixed. Anyone else a little more familiar with the subscriptions module could talk to the hook_subscriptions_queue_alter, and the adding the mail to the queue table?


function sub_by_cckref_menu(){
	$items = array();
	$items['admin/settings/sub_by_cckref'] = array(
		'title' =>'Administer Subscriptions by CCK Reference',
		'description' =>'Set node type for node references',
		'page callback' => 'drupal_get_form',
		'page arguments' => array('sub_by_cckref_admin_form'),
		'access arguments' => array('administer subbycckref'),
	);
	return $items;
}

function sub_by_cckref_perm(){
	return array('administer subbycckref');
}

function sub_by_cckref_admin_form(){
	$form = array();
	
	$info = _content_type_info(); //it looks like this is still a valid call
	$options = $info['fields'];
	$options2 = array();
	
	foreach($options as $option){
		if($option[type] == 'nodereference') $options2[$option[field_name]] = $option[widget][label];
	}

	$form['sub_by_cck_fieldname'] = array(
		'#type' => 'select',
		'#options' => $options2,
		'#title' => t('Field for subscriptions'),
		'#default_value' => variable_get('sub_by_cck_fieldname', ''),
		'#description' => t("Field name that the people subscribe to"),
	);
	
	return system_settings_form($form);
}

function sub_by_cckref_admin_form_validate($form, &$form_state){
	if(isset($form['sub_by_cck_fieldname']['#value'])) {
		variable_set('sub_by_cck_fieldname',$form['sub_by_cck_fieldname']['#value']);
		drupal_set_message(t('Field Name Set: ').$form['sub_by_cck_fieldname']['#value']);
	}
}

/*
I have no idea if this is still how the subscriptions module handles their queue_alter function
*/
function sub_by_cckref_subscriptions_queue_alter(&$event) {
	if($event['module'] == 'node' and $event['action'] == 'insert'){
		$node = $event['node'];
		$fieldname = variable_get('sub_by_cck_fieldname', '');
		$temp1 = $node->$fieldname;
		$temp2 = $temp1[0][nid];
		if (is_numeric($temp2) and $temp2 > 0) {
			sub_by_cckref_add_to_queue($event, $node, $temp2);
		}
		$temp3 = $node->$fieldname;
		if (is_array($temp3)) {
			foreach ($temp3 as $value) {
				$value = $value['nid'];
				if (is_numeric($value) and $value > 0) {
					sub_by_cckref_add_to_queue($event, $node, $value);
				}
			}
		}
	}
}

/*
If the subscriptions module hasn't changed its database schema, this should still work i believe.
*/
function sub_by_cckref_add_to_queue($event, $node, $noderefid) {
	$subusers = db_query("SELECT recipient_uid FROM {subscriptions} WHERE field='nid' AND value=%d ", $noderefid);
	while ($subuser = db_fetch_object($subusers)) {
		$userrow = db_fetch_object(db_query("SELECT name, mail FROM {users} WHERE uid=%d", $subuser->recipient_uid));
		$username = $userrow->name;
		$useremail = $userrow->mail;
		$lastsent = db_result(db_query("SELECT last_sent FROM {subscriptions_user} WHERE uid=%d", $subuser->recipient_uid));
		if (is_numeric($subuser->recipient_uid) and $subuser->recipient_uid > 0 and strlen($username) > 0 and strlen($useremail) > 0) {
			db_query("INSERT INTO {subscriptions_queue} (uid, name, mail, language, module, field, value, author_uid, send_interval, digest, load_args, load_function, is_new, last_sent) VALUES (%d, '%s', '%s', '', 'node', 'nid', %d, %d, 1, -1, %d, '%s', %d, %d)", $subuser->recipient_uid, $username, $useremail, $node->nid, $node->uid, $event['load_args'], $event['load_function'] ,$event['is_new'], $lastsent);
			//add code here to insert into a db table. this is for the career feed
			db_query("INSERT INTO {subscriptions_cck_node_ref} (nid, title, refid, uid, created) VALUES (%d, '%s', %d, %d, %d)", $node->nid, $node->title, $noderefid, $subuser->recipient_uid, time());
		}
	}
}
salvis’s picture

Version: 5.x-2.0 » 6.x-1.x-dev

Yes, the hook_subscriptions_queue_alter() should still work in the same way. If you don't NULL the $event, Subscriptions will queue it — don't know whether that's what you want or not.

As for INSERTing into the {subscriptions_queue} table, it would be better to call subscriptions_queue() instead, with an $event of the form as you receive it in hook_subscriptions_queue_alter(). Use devel.module's dpm() to see what it looks like.

keremito’s picture

When I create a referencing node, drupal gives this error;

user warning: Unknown column 'last_sent' in 'field list' query

for this line in sub_by_cckref.module on line 80;

$lastsent = db_result(db_query("SELECT last_sent FROM {subscriptions_user} WHERE uid=%d",

I can hardly understand php and mysql, but when I check the database for
subscriptions, there were a table called subscriptions_last_sent. So should I change that line to;

$lastsent = db_result(db_query("SELECT last_sent FROM {subscriptions_last_sent} WHERE uid=%d",

brettev’s picture

if that table has a last_sent field as well as a uid field, then that query would most likely work. as i haven't been working with subscriptions for quite a while, i'm not 100% sure, but that does seem like it would work

keremito’s picture

Brettev, Salvis,

Thank you very much!

Module is working perfectly now.

I changed the table name as {subscriptions_last_sent}. I also delete the closing tag ("?>").

Besides some "leave a space" kind suggestions, Code review points to line 26 and 55;

"use quotes around a string literal array index, this is not only a style issue, but a known performance problem"

is it something important? and @salvis, I'll think about your suggestion.

The final script is below;

function sub_by_cckref_menu(){
    $items = array();
    $items['admin/settings/sub_by_cckref'] = array(
        'title' =>'Administer Subscriptions by CCK Reference',
        'description' =>'Set node type for node references',
        'page callback' => 'drupal_get_form',
        'page arguments' => array('sub_by_cckref_admin_form'),
        'access arguments' => array('administer subbycckref'),
    );
    return $items;
}

function sub_by_cckref_perm(){
    return array('administer subbycckref');
}

function sub_by_cckref_admin_form(){
    $form = array();
   
    $info = _content_type_info(); //it looks like this is still a valid call
    $options = $info['fields'];
    $options2 = array();
   
    foreach($options as $option){
        if($option[type] == 'nodereference') $options2[$option[field_name]] = $option[widget][label];
    }

    $form['sub_by_cck_fieldname'] = array(
        '#type' => 'select',
        '#options' => $options2,
        '#title' => t('Field for subscriptions'),
        '#default_value' => variable_get('sub_by_cck_fieldname', ''),
        '#description' => t("Field name that the people subscribe to"),
    );
   
    return system_settings_form($form);
}

function sub_by_cckref_admin_form_validate($form, &$form_state){
    if(isset($form['sub_by_cck_fieldname']['#value'])) {
        variable_set('sub_by_cck_fieldname',$form['sub_by_cck_fieldname']['#value']);
        drupal_set_message(t('Field Name Set: ').$form['sub_by_cck_fieldname']['#value']);
    }
}

/*
I have no idea if this is still how the subscriptions module handles their queue_alter function
*/
function sub_by_cckref_subscriptions_queue_alter(&$event) {
    if($event['module'] == 'node' and $event['action'] == 'insert'){
        $node = $event['node'];
        $fieldname = variable_get('sub_by_cck_fieldname', '');
        $temp1 = $node->$fieldname;
        $temp2 = $temp1[0][nid];
        if (is_numeric($temp2) and $temp2 > 0) {
            sub_by_cckref_add_to_queue($event, $node, $temp2);
        }
        $temp3 = $node->$fieldname;
        if (is_array($temp3)) {
            foreach ($temp3 as $value) {
                $value = $value['nid'];
                if (is_numeric($value) and $value > 0) {
                    sub_by_cckref_add_to_queue($event, $node, $value);
                }
            }
        }
    }
}

/*
If the subscriptions module hasn't changed its database schema, this should still work i believe.
*/
function sub_by_cckref_add_to_queue($event, $node, $noderefid) {
    $subusers = db_query("SELECT recipient_uid FROM {subscriptions} WHERE field='nid' AND value=%d ", $noderefid);
    while ($subuser = db_fetch_object($subusers)) {
        $userrow = db_fetch_object(db_query("SELECT name, mail FROM {users} WHERE uid=%d", $subuser->recipient_uid));
        $username = $userrow->name;
        $useremail = $userrow->mail;
        $lastsent = db_result(db_query("SELECT last_sent FROM {subscriptions_last_sent} WHERE uid=%d", $subuser->recipient_uid));
        if (is_numeric($subuser->recipient_uid) and $subuser->recipient_uid > 0 and strlen($username) > 0 and strlen($useremail) > 0) {
            db_query("INSERT INTO {subscriptions_queue} (uid, name, mail, language, module, field, value, author_uid, send_interval, digest, load_args, load_function, is_new, last_sent) VALUES (%d, '%s', '%s', '', 'node', 'nid', %d, %d, 1, -1, %d, '%s', %d, %d)", $subuser->recipient_uid, $username, $useremail, $node->nid, $node->uid, $event['load_args'], $event['load_function'] ,$event['is_new'], $lastsent);
            //add code here to insert into a db table. this is for the career feed
            db_query("INSERT INTO {subscriptions_cck_node_ref} (nid, title, refid, uid, created) VALUES (%d, '%s', %d, %d, %d)", $node->nid, $node->title, $noderefid, $subuser->recipient_uid, time());
        }
    }
}
salvis’s picture

(Leaving out the closing tag messes up the formatting of your post — it's needed here on d.o, but it shouldn't go on your webserver. Please edit your #46 above and add the closing tag.)

Whatever is inside the square brackets, it should be either a number or start with a $ or with a quote. When it starts with a letter, then it's wrong, except if it's a function call, i.e. a word followed by an opening parenthesis (rare).

Having the code in the form of a patch would avoid all formatting problems and make it much easier to comment (using Dreditor).

keremito’s picture

Version: 5.x-2.0 » 6.x-1.x-dev

Sorry, I added the closing tag back.

Ftegg’s picture

Hi
I'm having trouble making this work in D6. Basically, I've downloaded the original module from Brettev's site and updated the code in the .module file to that last script from Keremito (#46). When I go to my site's admin/modules page, I have the message "This version is incompatible with the 6.19 version of Drupal core.". Is there something else that needs to be changed somewhere?

vince.rowe’s picture

Hi there,

You need to edit the modules .info file and add the following lines:

package = "Subscriptions"
dependencies[] = subscriptions
core = 6.x

Ftegg’s picture

Thanks, Vince!

bulat’s picture

I think there is a way to make a generic solution for reference modules.

Not sure if that is applicable for the 6.x but in 7.x there we have function field_info_field_map() that can get us to the list of reference fields (node or entity references have slight variation which I think can be handled in one module). Once that list is there it is easy to check whether module has one of the reference fields and if it does check for subscription in subscriptions table that would match the new node.

In terms of db structure there should be two types of records in subscriptions table for this module to allow two scenarios:
1. Subscribe everybody to Referenced nodes (via specified reference field).
2. Allow users to subscribe to Referenced node (via specified reference field).

Scneario module field value
1 reference my_ref_field my_ref_field
2 reference my_ref_field {nid}
bulat’s picture

Version: 6.x-1.x-dev » 7.x-1.x-dev

Me and @Barinder started a generic reference module for 7.x. It requires minimum code from modules that would need to extend referenced subscriptions for their content types.

Here is the the sample hook implementation that makes it possible to subscribe to new answers for a specific question (see Answers module):

/**
 * Implements hook_subscriptions_reference_info()
 */
function subscriptions_question_subscriptions_reference_info() {
  return array(
    'question_answers' => array(
      'parent' => 'question',
      'child' => 'answer',
      'field' =>  'field_answer_question'),
  );
}

Tried to make it as simple as possible.

So the code fore the subscriptions_reference module goes like this:

<?php

/**
 * @file
 * subscriptoins_reference.module
 */

include_once 'subscriptions_reference.rules.inc';

define('REFERENCE_MODULE', 'node');

/**
 * Implements hook_subscriptions()
 */
function subscriptions_reference_subscriptions($op, $arg0 = NULL, $arg1 = NULL, $arg2 = NULL) {
  $function = '_subscriptions_reference_' . $op;
  if (function_exists($function)) {
    return $function($arg0, $arg1, $arg2);
  }
  switch ($op) {
    case 'queue':
      subscriptions_reference_queue_send($arg0); // $arg0 is $event array.
      return NULL;
    case 'fields': // $arg0 is module.
      if ($arg0 == REFERENCE_MODULE) {
        $fields = array();
        foreach (_available_reference_fields() as $key => $info) {
          $fields[$info['field']] = array(
            'data_function' => 'subscriptions_content_data',
            'subs_mod' => 'subscriptions_content',
            'subs_type' => t('thread'),
            'mailkey' => 'node-type-',
          );
        }
        return $fields;
      }
      break;

    case 'stypes': // @todo where is this used??
      static $stypes = array(); // why is it static?
      foreach (_available_reference_fields() as $key => $info) {
         $stypes[$key] =  array(REFERENCE_MODULE, $info['field']);
      }
      return $stypes;
    case 'stype':
      return (isset($stypes[$arg0]) ? array_merge($stypes[$arg0], array($arg1, $arg2)) : NULL);
  }
  return NULL;
}

/**
 * Sub hook of hook_subscriptions() for $op == 'queue'
 * @param array $event contains event properties 
 * @see subscriptions_reference_node_insert()
 */
function subscriptions_reference_queue_send($event) {
  if ($event['module'] == REFERENCE_MODULE) {
    if (!isset($event['field'])) return; // this is not our event
    $node = $event['node'];
    $field_name = $event['field']; //  
    $ref_nids = field_get_items('node', $node, $event['field']);
    if (!$ref_nids) return; // reference field is empty
    // @todo for entity reference we will want to get 'target_id' field
    $ref_nid = $ref_nids[0]['nid'];
    $subscriptions = subscriptions_get(array(
      'module' => REFERENCE_MODULE,
      'field' => $field_name,
      'value' => $ref_nid,
    ));

    foreach ($subscriptions as $uid => $subscription) {
      $result = db_insert('subscriptions_queue')
          ->fields(array(
            'uid' => $uid,
            // 'name' => $userrow->name, @todo do we need this?
            'language' => '',
            'module' => REFERENCE_MODULE,
            'field' => $field_name,
            'value' => $ref_nid,
            'send_interval' => 1,
            'author_uid' => -1,
            'digest' => -1,
            'load_args' => $event['load_args'],
            'load_function' => $event['load_function'],
            'is_new' => TRUE,)
          )
          ->execute();
    }
  }
}

/**
 * Implements hook_node_insert
 */
function subscriptions_reference_node_insert($node) {

  $field_name = subscriptions_reference_field_name($node, 'child');
  if (!$field_name)
    return;

  $event = array(
    'module' => REFERENCE_MODULE,
    'uid' => $node->uid,
    'load_function' => 'subscriptions_content_load_node',
    'load_args' => $node->nid,
    'type' => 'node',
    'action' => 'insert',
    'is_new' => TRUE,
    'node' => $node,
    'field' => $field_name,
  );

  if (!subscriptions_content_suppress_notifications()) {
    subscriptions_queue($event);
  }
}

/**
 * Implements hook_node_delete().
 */
function subscriptions_reference_node_delete($node) {
  $field_name = subscriptions_reference_field_name($node, 'parent');
  if (!$field_name)
    return;
  subscriptions_delete_for_all_users('node', $field_name, $node->nid);
}

/**
 * Implements _hook_node_options(), subhook of hook_subscriptions().
 *
 * This is called by subscriptions_ui_node_form() in subscriptions_ui.module.
 *
 * @param $account
 * @param $node
 *
 * @see subscriptions_ui_node_form()
 */
function _subscriptions_reference_node_options($account, $node) {
  if (!user_access('subscribe to referenced node')) {
    return NULL;
  }
  $options = array();
  $field_name = subscriptions_reference_field_name($node, 'parent');
  if ($field_name) {
    $options['reference'][] = array(
      'name' => t('Subscribe to this node'),
      'params' => array('module' => REFERENCE_MODULE, 'field' => $field_name, 'value' => $node->nid),
      'link' => 'node/' . $node->nid,
    );
    $options['reference']['weight'] = -4;
  }
  return $options;
}

/**
 * Gets the name of the reference field for the node
 * @param object $node we will check if other nodes expose refs for this node type
 * @param string $op can be either child or parent
 * @return name of the reference field
 */
function subscriptions_reference_field_name($node, $op = 'child') {
  foreach (_available_reference_fields() as $key => $info) {
    if ($info[$op] === $node->type) {
      return $info['field'];
    }
  }
  return FALSE;
}

/**
 * Gets all reference fields from modules that implement subscriptions_reference_info
 */
function _available_reference_fields() {
  // @todo implement cache
  $fields = array();
  foreach (module_implements('subscriptions_reference_info') as $module) {
    $refs_info = module_invoke($module, 'subscriptions_reference_info');
    foreach ($refs_info as $key => $info) {
      $fields[$key] = $info;
    }
  }
  return $fields;
}

/**
 * Implements _hook_types(), subhook of hook_subscriptions().
 *
 * This is called by subscriptions_types() in subscriptions.module.
 *
 * @return array
 *   Returns information about types for Subscriptions module interface.
 * @see subscriptions_types()
 */
function _subscriptions_reference_types() {
  $types = array();

  foreach (_available_reference_fields() as $key => $info) {
    $types[$key] = array(
      'title' => 'Reference ' . $info['child'] . '->' . $info['parent'],
      'page' => 'subscriptions_reference_page_admin',
      'fields' => array(REFERENCE_MODULE, $info['field']),
      'weight' => -20,
      'access' => 'subscribe to referenced node',
      'permission' => array(
        'title' => t('Subscribe to referenced node'),
        'description' => t('Allows user to subscribe to referenced node')
      ),
    );
  }
  return $types;
}

/**
 * Implements hook_disable().
 */
function subscriptions_reference_disable() {
  //  Remove our queue items that have fields 
  //  exposed via hook_subscriptions_reference_info()
  foreach (_available_reference_fields() as $key => $info) {
    db_delete('subscriptions_queue')
        ->condition('module', REFERENCE_MODULE)
        ->condition('field', $info['field'])
        ->execute();
  }
}

/**
 * @TODO: barinder user_access
 */
function subscriptions_reference_subscribe_access() {
  return TRUE;
}

/**
 * Returns a list of reference subscriptions.
 */
function subscriptions_reference_page_admin(array $form, $uid) {
  _subscriptions_module_load_include('subscriptions_reference', 'admin.inc');
  return _subscriptions_reference_form($form, $uid);
}

Here is API with just one hook:

<?php

/**
 * @file
 * subscriptions_reference.api.php
 */

/**
 * Gets attributes of the reference field
 * @return array
 */
function hook_subscriptions_reference_info() {
   return array(
    'reference_id' => array( // should unique accross modules that implement that hook
      'parent' => 'parent_content_type',  // is being referenced
      'child' => 'child_content_type',    // contains the field
      'field' => 'my_reference_field'),   // name of the field
  );
}

Integration with Rules as a bonus:

<?php

/**
 * @file
 * subscriptions_reference.rules.inc
 * Contains rules actions for subscribing to nodes via reference fields
 */

/**
 * Implements hook_rules_action_info() on behalf of the node module.
 */
function subscriptions_reference_rules_action_info() {
  $base = array(
    'type' => 'subscriptions',
    'parameter' => array(
      'node' => array('type' => 'node', 'label' => t('Node')),
      'user' => array('type' => 'user', 'label' => t('User')),
    ),
    'group' => t('Subscriptions'),
    'access callback' => 'subscriptions_reference_subscribe_access',
  );

  // Action subsribe a user to a content
  $items['subscriptions_reference_subscribe_action'] = array(
    'label' => t('Subscribe user to referencing nodes'),
    'base' => 'subscriptions_reference_subscribe',
      ) + $base;

  // Action unsubsribe a user to a content
  $items['subscriptions_reference_unsubscribe_action'] = array(
    'label' => t('Unsubscribe user from referencing nodes'),
    'base' => 'subscriptions_reference_unsubscribe',
      ) + $base;

  return $items;
}

/**
 * Rules subscribe action callback
 */
function subscriptions_reference_subscribe($node, $user) {
  $reference_feild = subscriptions_reference_field_name($node, 'parent');
  if (!$reference_feild)
    return;
  // write subscription to database
  subscriptions_write_subscription(REFERENCE_MODULE, $reference_feild, $node->nid, -1, $user->uid);
}

/**
 * Rules unsubscribe action callback
 */
function subscriptions_reference_unsubscribe($node, $user) {
  $reference_feild = subscriptions_reference_field_name($node, 'parent');
  if (!$reference_feild) return;
  
  db_delete('subscriptions')
      ->condition('module', REFERENCE_MODULE)
      ->condition('field', $reference_feild)
      ->condition('value', $node->nid)
      ->condition('author_uid', -1)  // DEBUG $node->uid,
      ->condition('recipient_uid', $user->uid)
      ->execute();
}

This info file should do:

name = Subscriptions for Referenced Content
description = Allows users to subscribe to referenced content.

core = 7.x

package = Subscriptions
dependencies[] = subscriptions
dependencies[] = subscriptions_mail
dependencies[] = subscriptions_content
dependencies[] = rules

Hopefully somebody will create a separate module from this.

bulat’s picture

I have created a Sandbox project for this, see project application for details - http://drupal.org/node/1990672.

bulat’s picture

Project was promoted to full project - https://drupal.org/project/subscriptions_reference

salvis’s picture

Great news!

I'd love to get some feedback from people using Subscriptions Reference and I'll be happy to add a link on the front page.

mfieraru’s picture

I am trying to use the https://drupal.org/project/subscriptions_reference, I am using the test for now, I first add a Parent node but when I am adding a Child node referencing the Parent node, I am getting this error:

PDOException: SQLSTATE[42000]: Syntax error or access violation: 1064 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 'FROM WHERE (module = 'node') AND (field = 'field_test_parent') AND (value = ' at line 1: SELECT FROM {} WHERE (module = :db_condition_placeholder_0) AND (field = :db_condition_placeholder_1) AND (value = :db_condition_placeholder_2) ; Array ( [:db_condition_placeholder_0] => node [:db_condition_placeholder_1] => field_test_parent [:db_condition_placeholder_2] => 16 ) in subscriptions_get() (line 677 of ****/sites/all/modules/subscriptions/subscriptions.module).

Can you please help me? There's nothing related to this new module online and it would do exactly what I need it to do.

bulat’s picture

Hi @mfieraru, can you please check if patch from comment #2 in  #2035667: Error when creating a child node to a parent which is subscribed to solves it.

mfieraru’s picture

It worked. The patch solved my problem. Thank you a lot,

salvis’s picture

Issue summary: View changes
Status: Active » Closed (outdated)