I saw the use of this module in the photo gallery video and have started using it myself. AWESOME MOD! So far it is working great and I'm able to easily create related nodes. The create links are showing up as expected on the referenced nodes.

How would I generate links when not directly on the node but within the context of the referenced node?

For example... I have three content types... A game, an event (references game), and a discussion (references game). When viewing the game itself I get the create links.

I'm using view page tabs and path aliases along the lines of...
mysite.com/game/[nid] (game node) <-- has both create links
mysite.com/game/[nid]/events (events for game) <-- want create event link
mysite.com/game/[nid]/discuss (discussions for game) <-- want create discussion link

How would I go about accomplishing this?

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

quicksketch’s picture

You can use the Custom Links module to create arbitrary links on your nodes. However, you're asking how to make links not on nodes but on views. In which case you can just type out the HTML for the create links in the view footer. A little hacky, but if you're looking for a better solution you can theme the entire view and put a link down at the bottom in the theme layer. Either approach you take, none of this is really related to the Node Reference URL Widget and probably should be asked elsewhere.

caschbre’s picture

Sorry, I probably wasn't very clear in my initial post.

The Node Reference URL Widget has the option to add links on nodes to create related nodes. For example, when I'm on the game node there are links to create events (node/add/event/[nid]) and create discussions. These are automatically generated by this mod I thought. Those create links include the node id of the game that is being in the link.

So if I'm understanding this correctly, I need to use some PHP to grab the node id and generate the link? I'll ask this in the support forums.

hefox’s picture


$links = nodereference_url_build_all_links($node, $teaser);
if ($links) $output = theme('links', $node);

not the module mainter, but was just looking at it and he now has some DELICIOUS new functions
With node being the node like in game node where ya building links for
$teaser whether or not you're display node as a teaser or not; this is relavent since node reference now have specific full node or teaser visibility settings on the teaser.

If you prefer, http://i.intheclosets.com/node/7 there is a short module that provides the links as a field for views; I've just redone it for the new release of node reference so not sure how stable it is ATM (also has an unrelated field, sorry. Also if receive a php warning, just reload the page in a few minutes I'm working on the site ATM).

hefox’s picture

just re read your post, oops

If you're using advanced views:

What you likely want is a cleaned up verision of below, with replace with event or discussion's machine names since you want one link per area

  $links = array();
  $fields = content_fields(NULL, $object->type);
  foreach ($fields as $field_name => $field) {
    foreach (_nodereference_url_field_instances($field_name) as $target_type => $instance) {
      if ($target_type == '<target type>' && $instance['widget']['type'] == 'nodereference_url') {
        $link_settings = $instance['widget']['node_link'];
        if (($link_settings['teaser'] && $teaser == TRUE) || ($link_settings['full'] && $teaser == FALSE)) {
          if ($link = nodereference_url_build_link($node, $instance, $teaser)) {
            $links[$target_type .'_'. $field_name] = $link;
          }
        }
      }
    }
  }

Otherwise... likely very likely.

$type = <type name>;
$nid = <parent NID, the one going to be referenced>
f (user_access('create ' . $type . ' content')) {
   echo l('link text', 'node/add/'. str_replace('_', '-', $type) .'/'. $nid)
}

Checks user permissions then creates link

Anyhow meant to say up there, can I hijack this topic to ask for views integration? It's related!

c-c-m’s picture

I also want to do the same you are asking for.

I've been reading the two answers (#3 and #4) but didn't understand a word. Did you manage to achieve that?

I guess I will have to add a php content on footer or header of the view, but I do not know what to put, since I do not know php. I guess the answer may be #3, but I didn't understand it. Can anyone explain it a little bit easier?

Thank you very much.

hefox’s picture

Exactly what is your view of, where is it located? How do you know the node ID (node/nid) of the node you want to reference? Ie, is this on the node page?

let's say it's on the node page or sub page.

arg(), retrieves part of the url in format of 0/1/2/3/4. Usually node ID is located at the second place, in this case '1' since it starts at 0.

Let's also assume your content type TYPE (not label) is 'contenttype'. Also, let's assume you're not using advanced views setting for the node reference; if you do then it becomes complicated.


$nid = arg(1) ;
$type = 'contenttype';
if (user_access('create ' . $type . ' content')) { // makes sure the user has permission to create the content type
   echo l('Link title', 'node/add/'. str_replace('_', '-', $type).'/'.$nid) ;
}

should work

caschbre’s picture

Thanks hefox for this bit of code! This is what I've been trying to figure out how to do.

When you reference "advanced views"... what exactly do you mean by that?

hefox’s picture

Inside the fields settings for your node you can ::

a) Pick what content types that can be referenced. (page, story, blog, etc.)
b) Use views to filter on what NODES can be referenced; for example, a view of only nodes where the author is the current user.

B makes the link more complicated since, while the link is the same text wise, it needs to be only displayed for certian nodes. That's what #3 and first part of #4 are talking about.

However you're likely using a so don't need to worry about handling b.

c-c-m’s picture

Thank you very much, hefox your code works perfectly, although unlike the Node Reference URL Widget module there's no way to return back to the previous page (the page whith the view that has your code). Could it be possible to achieve that behaviour as well?

Regards

hefox’s picture

$nid = arg(1) ;
$type = 'contenttype';
if (user_access('create ' . $type . ' content')) { // makes sure the user has permission to create the content type
   echo l('Link title', 'node/add/'. str_replace('_', '-', $type).'/'.$nid, array('query'=> drupal_get_destination())) ;
}

that shopuld do it, adds the current page as destination=
into the url which overrides the default go to node created.

Here is the information about the l function for future reference : http://api.drupal.org/api/function/l
And here's about drupal get destination http://api.drupal.org/api/function/drupal_get_destination/6

hope I didn't typo anything!

caschbre’s picture

Very cool hefox! Thank you very much. This has been helpful especially for someone who doesn't know PHP.
+1 rep! :-)

c-c-m’s picture

That's great now, Hefox! Thank you very much!

caschbre’s picture

So far I've been using this code and it has worked great! I recently came across an instance where my link is showing up for content types that should not have this reference. Basically I need to check if the current node type can be referenced.

I know I could hard-code the types, however as I add new content types that can use this reference I'd hate to have to come back (or forget) to update this code. I was looking through the module code but couldn't quite figure out how to utilize the functions (nodereference_url_build_link ??) that check if the current node can be referenced.

Any ideas?

hefox’s picture

here's a segment of code from a view field I have; haven't touched it in a while but I assume it works. Results an array ($links) that can be used for theme_links if I remember correctly.

    $nid = $values->{$this->aliases['nid']};
     $type = $values->{$this->aliases['type']};
     $node = (object)array('type'=>$type,'nid'=>$nid);
     $field_info = content_fields($this->definition['content_field_name']);
     $links = array();
     foreach(_nodereference_url_field_instances($this->definition['content_field_name']) as $target_type => $instance) {
       $attr=array();
       $field['widget']['node_link']['full'] = true;
       $link = nodereference_url_build_link($node,$instance, FALSE);
       if ($link) $links[] = $link;
     }
caschbre’s picture

I've been going over your latest code (in post #14) trying to understand it. This is a bit more advanced than I'm used to. Where I'm stuck is the $instance parameter for the nodereference_url_build_link function. I don't follow how it is created or what the foreach loop is doing.

Just to clarify what I'm trying to do... I created a block that I want to display on my node pages. That block displays the links to create content to reference the current node. So far my links are created based on if the user can create that content type, but it doesn't check if that content type can is setup to reference the current node.

hefox’s picture

    $field_name = 'field name'; // where field_name is like field_parent or whatever. 
    $node  = menu_get_object();
     $field_info = content_fields($field_name);
     $links = array();
     foreach(_nodereference_url_field_instances($field_name) as $target_type => $instance) {
       $attr=array();
       $field['widget']['node_link']['full'] = true;
       $link = nodereference_url_build_link($node,$instance, FALSE);
       if ($link) $links[] = $link;
     }
   echo theme('links',$links); 

Try something like that. Not sure if menu_get_object will work, if not node_load(nid) (node_load(arg(1)))

caschbre’s picture

Here's what I've got...

<?php
  $field_name = 'field_content_reference';  // guessing field_content_reference... this is my node reference field name
  $node  = node_load(array('nid' => arg(1)));  // I validated this is pulling the right nid
  $field_info = content_fields($field_name);
  $links = array();
  foreach(_nodereference_url_field_instances($field_name) as $target_type => $instance) {
    $attr=array();
    $field['widget']['node_link']['full'] = true;
    $link = nodereference_url_build_link($node,$instance, FALSE);
    if ($link) $links[] = $link;
  }
  echo theme('links',$links);  // I also tried theme_links($links);
?>

The block isn't displaying anything so far. I'm guessing the $field_name is wrong... but I can't figure out what else to use there.

caschbre’s picture

It appears that my $link is coming back as an empty array. The nodereference_url_build_link is not returning anything.

I did a print_r of the $instance and it looks like the following. No idea if that is correct or not though.

Array ( [field_name] => field_content_reference [type_name] => file [display_settings] => Array ( [weight] => -3 [parent] => [label] => Array ( [format] => hidden ) [teaser] => Array ( [format] => hidden [exclude] => 0 ) [full] => Array ( [format] => hidden [exclude] => 0 ) [4] => Array ( [format] => default [exclude] => 0 ) [2] => Array ( [format] => default [exclude] => 0 ) [3] => Array ( [format] => default [exclude] => 0 ) [token] => Array ( [format] => default [exclude] => 0 ) ) [widget_active] => 1 [type] => nodereference [required] => 0 [multiple] => 0 [db_storage] => 1 [module] => nodereference [active] => 1 [locked] => 0 [columns] => Array ( [nid] => Array ( [type] => int [unsigned] => 1 [not null] => [index] => 1 ) ) [referenceable_types] => Array ( [discuss] => discuss [event] => event [news] => news [page] => page [webform] => webform [committee] => 0 [council] => 0 [file] => 0 [other] => 0 [local] => 0 ) [advanced_view] => -- [advanced_view_args] => [widget] => Array ( [node_link] => Array ( [teaser] => 0 [full] => 0 [title] => Add Attachment [hover_title] => Add an attachment to this piece of content. [destination] => node ) [fallback] => leave_blank [label] => Content [weight] => -3 [description] => [type] => nodereference_url [module] => nodereference_url ) )

caschbre’s picture

Figured it out!!!

The line
$field['widget']['node_link']['full'] = true;
should read
$instance['widget']['node_link']['full'] = true;

quicksketch’s picture

Status: Active » Fixed

So the final code was:

  $field_name = 'field_content_reference';  // guessing field_content_reference... this is my node reference field name
  $node  = node_load(array('nid' => arg(1)));  // I validated this is pulling the right nid
  $field_info = content_fields($field_name);
  $links = array();
  foreach(_nodereference_url_field_instances($field_name) as $target_type => $instance) {
    $attr=array();
    $instance['widget']['node_link']['full'] = true;
    $link = nodereference_url_build_link($node,$instance, FALSE);
    if ($link) $links[] = $link;
  }
  echo theme('links',$links);  // I also tried theme_links($links);

I'd note that you could probably shorten this up significantly with something like this:

  $node  = node_load(arg(1));
  $links = nodereference_url_build_all_links($node, FALSE);
  print theme('links', $links);

But this approach might show you more links than you'd want, and it'd only work if the link was configured to show up on the full node view already.

quicksketch’s picture

Version: 6.x-1.2 » 6.x-1.3
FileSize
2.52 KB

I generalized this code into a simpler function for themer use, though it only prints out one link at a time. After applying this patch you can print out a link in your .tpl.php files by using the following:

<?php print nodereference_url_create_link($node, 'field_content_reference', 'story'); ?>

Note that you'll need to replace "field_content_reference" with the field name of your Node Reference field and "story" with the name of the content type that contains the Node Reference field.

I've added this code to CVS and it will be in the 1.4 version.

caschbre’s picture

That's great quicksketch! I did end up adding a bit more to my code to work around #543140 link doesn't take into account og context. I don't think that particular issue is resolved. However here is what my final code looked like and handled group context:

If (module_exists('nodereference_url')) {
  $field_name = 'field_content_reference'; // where field_name is like field_parent or whatever. 
  //  $node  = node_load(array('nid' => arg(1)));
  $node = menu_get_object();
  $field_info = content_fields($field_name);
  $links = array();
  foreach(_nodereference_url_field_instances($field_name) as $target_type => $instance) {
    $attr=array();
    $instance['widget']['node_link']['full'] = true;
    $link = nodereference_url_build_link($node,$instance, FALSE);
    if ($link) {
      $links[] = $link;
    }
    if (module_exists('og') && $group_node = og_get_group_context()) {
      foreach($links as $key => $mylink) {
        $links[$key]['query'] .= '&gids[]=' . $group_node->nid;
      }
    }
  }
  echo theme('links',$links);
}
caschbre’s picture

@quicksketch... one question about your patch. Is the node type (e.g. story) optional? I could see themers wanting to either 1) call out a specific link, or 2) display all links.

quicksketch’s picture

No, the node type is not optional. If a list needs to be created we might need a separate utility function for that, or the themer just has to use the function once per link they want to add (or use a loop).

hefox’s picture

+function nodereference_url_create_link($node, $field_name, $type_name = null, $attributes = array()) {
+  $output = '';
+  if($type_name) {
+   $field = content_fields($field_name, $type_name);
+  $field['widget']['node_link']['full'] = TRUE;
+  if ($link = nodereference_url_build_link($node, $field)) {
+    $options = array();
+    $options['attributes'] = $attributes + (array) $link['attributes'];
+    if ($link['query']) {
+      $options['query'] = $link['query'];
+    }
+    $output = l($link['title'], $link['href'], $options);
+  } else {
+    $links[] = array();
+    foreach(array_keys(node_get_types) as $type_name) {
+      $field = content_fields($field_name, $type_name);
+      $field['widget']['node_link']['full'] = TRUE;
+      if ($link = nodereference_url_build_link($node, $field)) {
+         $link['attributes'] = $attributes + (array) $link['attributes'];
+         $links[] = $link;
        }
     }
     if ($links) $output = theme('links',$output);
     else $output = '';
+ }
+  return $output;
+}

Shrug?

savinsur’s picture

Wouldn't this be simpler?

I am relative noob, so excuse my dumbness, but in views I made a view of an artist. (I have a music site)

a field content [nid] with the following:

re-write the output of this field: "create album"

Output this field as a link: "http://mysite.com/node/add/album/[nid]"

(the url portion is static)

Could I not save as a block that can be referenced when viewing an artist? Using
node-reference-url it works for me when testing within views.

What am I missing that does not respond to the original post in this thread?
Why would I need to hack into the .tpl.php file?

caschbre’s picture

@magpieradio... What some of the code above does is look for any content type that can be referenced in case there is more than one. It also makes sure the user has permission to create the content and only displays the links if they do. The third thing that happens is a check for group context to make sure the appropriate group is (default) checked when creating the new content type.

So in the end we could simply create a link (which I used to do) but for usability, etc. the code goes a long way.

savinsur’s picture

OK, cheers.

Status: Fixed » Closed (fixed)

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

zdean’s picture

So the code from #21 would go in a page or node template...is there a similar code to inject into a view template?

Donaldd’s picture

Version: 6.x-1.3 » 7.x-1.9

I'm using the Drupal 7 version of this module, but when I try to add a link using #21 I get the following error.

Fatal error: Call to undefined function content_fields() in .../nodereference_url/nodereference_url.module on line 210

How can I fix this?

Donaldd’s picture

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

Status: Active » Fixed
FileSize
785 bytes

I'm using the Drupal 7 version of this module, but when I try to add a link using #21 I get the following error.

In a situation like this, you should probably open a new bug report issue, rather than reopening this request (which was originally just a support request). Reopening issues makes tracking changes harder in the future, and it makes it so that when I associate an issue with the commit history, the same issue ends up in multiple commits (and the issue has multiple patches). It makes the whole thing difficult to follow.

Nonetheless, I've committed this patch to the D7 branch which fixes this functionality in Drupal 7. The name of the function was changed (as did the location of the setting), which are both updated in this patch.

Status: Fixed » Closed (fixed)

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

Nathan Tsai’s picture

Issue summary: View changes

For Drupal 7.

You could also create a block display in a view and have two fields:

- NID
- Custom text

Exclude the NID field from display
Put this code for your custom text:
<a href="/node/add/CONTENT-TYPE/[nid]?destination=node/[nid]">The text for the link</a>

CONTENT-TYPE = the machine name of your content type with underscores, "_", being replaced with hyphens, "-".

Example 1:

You have a content type, with the machine name "node_reference_content", that has the node reference field with the widget "Reference from URL". (If the field doesn't have the widget, it won't work). The code for your Custom Text field would be:

<a href="/node/add/node-reference-content/[nid]?destination=node/[nid]">The text for the link</a>

Example 2:

If the URL is aliased and the content type is "basic page", (which has machine name "page"). If the link provided by the module is "/node/add/page/1234?destination=url-alias/title-of-node" the code is:

<a href="/node/add/page/[nid]?destination=node/[nid]">The text for the link</a>

Example 3:

Lastly, if you want the aliased path and you aren't doing this off a subdomain, you could also add the "Path" view field and use this code:

<a href="/node/add/CONTENT-TYPE/[nid]?destination=[path]">The text for the link</a>