So, I created a content type called "Contact" with a cck textfield called "Skypename" (field_skypename). I know that if I write <a href="skype:someskypename?call">Call</a> I get a link that triggers a skype call to someskypename. What I would like to acheive is a block that:
- Appears only when viewing a Contact. No prob here, I just set the Contact node type pathauto settings to /contact, so in the block settings I set it to display only on contact/* paths
- Shows a link to call the viewed Contact if field_skypename is filled.
Some prob here... I'm not familiar with PHP, but I guess I should first pull out filed_skypename from the current node(how?), then check if it is filled(double how?), then build something like:
print: '<a href="skype:'. $node->field_skype[0][value] .'?call">Call</a>';
I know it's a supernoob question, but... help please
p.s. I have Dru 6.10 and CCK 6.X-2.2
Comments
You're almost there
You're definitely on the right track.
PHP has a handy function for checking whether a variable has meaningful content:
empty(foo). You can read about empty() in the PHP documentation, but it returnstrueiffoois unset, null, an empty string, the number 0, an empty array,false, etc. Thus,!empty(foo)will betruewheneverfoohas meaningful content.Try something like this:
The reason to use check_plain is that
$node->field_skype[0][value]presumably contains (or could contain) user input, and you shouldn't print user input directly to output. You should always run it through some function that filters it first. Otherwise, you open security holes in your site.The most Drupalicious way to generate links is with l(), but I don't know how to get it to recognize skype as a protocol.
Thanks for your (very) quick
Thanks for your (very) quick reply!
I think I understood your code and it quite makes sense to me, but I think there's a problem with how Drupal handles
<a>tags. I tried your code in a block, in a Computed field, and on the node's body (PHP input filter always on), but the "Call" link never appears. It's strange because if I just write HTML code<a href="skype:someskypename?call">Call</a>, the link pops up easily... Must dig some more...Oops! Missing quotation marks.
I'll bet the problem is with accessing $node->field_skypename[0]['value'] rather than with the anchor tags. And in fact, now that I'm retyping it, I think I see the problem: we should have (single or double) quotation marks around 'value'. It should be:
If that doesn't work, we'll do some debugging to ensure that $node is defined, etc.
You're right, but it didn't
You're right, but it didn't work either. After some search I found out that the problem is with filter_xss_bad_protocol(), here: http://drupal.org/node/324731, But the two solutions given ther didn't work for me.
That sounds like a more
That sounds like a more difficult problem then. I take it that your code outputs
<a href="skypename?call">Call</a>?I don't know anything about filter_xss_bad_protocol, so you may have to keep searching elsewhere, unless anyone else has any ideas.
The problem shows up only
The problem shows up only when trying to output the link with php. With static html it works... Anyway thank you for your support!
Couldn't replicate the problem
I just tried to create a block with the code above (using a dummy variable instead of $node->field_skypename[0]['value']), and it seems to work fine. The link appears and it opens Skype. I think having the PHP input format gets around the filter issues.
Can you doublecheck the source code for the block and copy and paste it here?
Ok, I tried with these
Ok, I tried with these two:
and:
But still no chance. Maybe is it because I'm on localhost?
Let's try this step by step
Here's what I did:
Once I did that, I went to my home page, and there was a block titled "Call this person on Skype" with my link, fully functional, as its content.
Did you skip any of these steps? What exactly do you see where you're expecting to see the link? Anything?
Tried it, it works
Tried it, it works. So the thing is to pass the variable correctly...
Check for $node
Okay, good.
Let's check that $node is defined before we try to get $skype_name.
Add the following to the end of the block you just created:
If $node is defined, you should see a detailed printout of $node and its contents. If you see '$node is empty', then we'll I'll have some more questions about exactly what you're looking to do on your site.
I get '$node is empty'
I get '$node is empty'.
Progress...
Okay. Well that shows us what the problem is. We've been trying to get $node->field_skypename[0]['value'] when $node isn't defined!
Let's say I create a Contact node with nid 212. If I understand your original post, you want this block to show up only when you're looking at yoursite.com/contact/212. Is that correct? Because if so, we can extract the nid from the path, load the node inside your block, and do whatever we want with it.
That sounds right to me.
That sounds right to me. I don't want the block to show the call link only for a specific node. I would like it to show the current contact's (the node the user is viewing) call link. That means that if I have more contacts, everytime I view one of them, the block should let me call the current one. BTW I'm using pathauto. Is it a problem?
Sounds good
Okay. That all sounds good. Pathauto is not a problem.
One way to solve the problem is by replacing all of the code in your block with the following. I'll explain the code below.
The arg function returns pieces of the path. So,
arg(0)returns the first element in the path, which in your case will be 'contact'. In your case,arg(1)will return the nid of the Contact node that is currently being viewed.This code checks to see that we're looking at a Contact node and that arg(1) is a numeric value. It then tries to load the node with the nid in the path. If that's successful, it tries to get $skype_name from it. If that's successful, it prints the link.
The code is a little ugly because, well, arg() is kind of ugly, but that's okay for now.
Give this a try and tell me if it works. (I have tested it because I don't have the Contact node type set up.)
UPDATE: Oops. There was a typo in the code. (I omitted an opening parenthesis after
check_plain.) It's fixed now.I tried this last code but it
I tried this last code but it still doesn't work...
Let's see: 'contact' is the path I set in pathauto, field_skypename is the name of the cck field, and for the block settings I followed your comments strictly. I have no clue .
Let's debug
Okay. Let's add some extra steps to the code for debugging purposes. We'll try to figure out where it's failing.
Try this:
I know this is frustrating, but we are making progress!
Run that code and tell me what you see.
I get: Error 1. arg(0) is
I get:
Error 1. arg(0) is node and arg(1) is 14
BTW thank for your patience...
Okay. Interesting. And when
Okay. Interesting. And when you look at the address bar in your browser, what do you see? http://localhost/contact/14? Or http://localhost/node/14?
http://localhost/contact/jimb
http://localhost/contact/jimbo , since I had set pathauto to display contacts like this: contact/[title-raw] , and my test contact's title is Jimbo
arg() seems to ignore path aliases
Okay. I didn't realize that you would see contact/jimbo, rather than conctact/212, but that's fine. arg() seems to be ignoring the alias created by pathauto and using the "original" path, which is node/14. Try the workaround I posted and see if that works.
Try this...
Here's a possible workaround:
IT WORKS!!! Wait I'm going to
IT WORKS!!! Wait I'm going to have a little dancing in the streets!!!
Congrats!
Congrats guys, and props to grobemo for his patience and generosity.
Clean version
Fantastic. Sorry I couldn't help you resolve the issue more quickly.
Here's a cleaner version (without the debugging code) for you when you get back from dancing in the streets:
For the record, here's what the code does:
check_plainto protect against malicious code.Among the things that caused us problems in trying to figure this out (and thus things to check if you're having similar problems):
Thank you very much for your
Thank you very much for your help, you've been patient and explained everything in detail. Grazie mille! :)))
What about an array?
Thanks for this. How would you add a field if it had multiple values in an array (I need to add a list of URLs to a block which have been posted in the node using the CCK Link module)?
*
This might get slightly more complicated because you've got links in there, but here's the basic idea:
If you have a field called foo that has multiple values, Drupal stores them in
$node->field_foo[0],$node->field_foo[1], etc. You'll want to loop through those values and add to to your own array. With a simple textfield, you'd do something like this:The catch here is that you want to display links, which are slightly more complicated. You'll need something like this:
This code uses Drupal's l() function, which sanitizes and formats links for you. There's a ternary ( x ? y : z ) operator in there in case titles are optional in your link field. That checks whether the title is non-empty, displaying the title if it's there and the URL if the title is empty.
One final issue
Thank you. Below is the code I ended up using based on this and your previous examples. The node type on which I want the block to show is called 'project' and my CCK links field is called 'field_project_links'. It works, but the block still shows even if there are no links. I checked in Firebug and the first link in the list is still getting printed, even though it is empty.
In the node/add form, the number of links that can be added is set to unlimited and by default there are two fields (with the option to add more). Could this be the issue?
empty($project_links[0]['href']))?
Looks good. Try replacing
if (count($project_links) > 0) {with:I think you're on the right track about what's happening. Drupal creates the node object with (at least) one value in $node->field_project_links, even if the field is empty.
That works, many thanks. I
That works, many thanks. I discovered this can also be done in Views by setting the argument to Node: Nid, default argument to node ID from URL, but I prefer your method. Tangential, but in case anyone else needs it, you can hide the block on the node/edit form if necessary by including the following code in the Block page visibility textfield (from http://drupal.org/node/134425).
But how would you render the
But how would you render the field properly, as defined in the content type display settings?
For example, when the value is a node or user reference, it can be rendered as a view.