I'm building an art gallery and I need to implement a system that will show a "this image is restricted" placeholder image in place of certain CCK imagefield images if the user is not logged in or if they don't have a certain profile field selected. I use a CCK field to flag certain nodes as containing 'mature' artwork (no p*rn, just artistic nudity). I'm using drupal 6, CCK imagefield, imagecache, views, etc.
I'm looking for an image-level solution, since the nodes need to remain accessible to everyone, only the imagefield image itself is replaced with a placeholder image.
I created a module with a nodeapi function that checks the value of the restricted cck field as well as the profile field and edits the imagefield's filepath to point to a placeholder image accordingly. I've got it working on images that are printed using theme('imagecache'...) in template files. However, this method fails when using views where the row style is anything other than 'node' (e.g. when using row style 'fields' and the imagefield field uses an imagecache preset).
There's got to be a better function to use to implement this sort of image replacement / override. Any ideas?
Comments
Can anyone help me out with
Can anyone help me out with some suggestions?
.
Did you try http://drupal.org/project/imagefield_extended yet?
Haven't tried it myself, so dunno if it actually works, but it seems to have Views integration. So, if you add a checkbox to mark an image as "mature", you can keep it in mind in your theming.
I'd make one function of it in your template.php file, which does pretty much this:
if($checkbox) { $picture = $placeholder; } else { $picture = $somepicture; }
Yeah, didn't feel like writing an actual example out, but you get the gist. Then you can call it from your templates (node template, preprocessing functions, view's row template, ...). You'll still need to replace it in at least your node.tpl file (or preprocess function) and view's row template (or hook_views_pre_render). As far as I know, there's no overlapping functionality. Nodes use the Node API, Views use the Views API. So finding a way that both can call the same function seems to be the best way to go.
I'd probably do it hardcoded
I'd probably do it hardcoded directly in the theme where you want to display the image. Let's say node-your_view.tpl.php
Grab the file you require and before you define its output check if the user is logged in and if the tickbox for mature content has been clicked:
I've got it mostly hardcoded
I've got it mostly hardcoded already, but I've got lots of views and don't want the maintenance headache.
Thanks for the suggestions.
Thanks for the suggestions. I'll have a look at Imagefield Extended.
I looked at hook_views_pre_render but I didn't make any progress. I'm at the edge of my drupal capabilities :)
Hackish attempt
Well, after a few hours I managed to hack together a solution for views output that uses fields.
This probably contains some drupal/php no-no's (don't laugh) and I don't know what the performance implications are with the node_load and profile_load_profile calls.
This is in views-view-field-FIELD_NAME_FID.tpl.php file:
Am I approaching this thing right?
I would still REALLY like to move this functionality into a module or template.php. If anyone can help, give me a shout. It would be appreciated!
.
On itself, it looks ok. Not sure if there's another way, but this'd be more or less what I would've done, too (not saying I'm a reference, just saying that at least to me, it doesn't look that bad ;) )
As you said, node_load and profile_load_profile can get pretty heavy, depending on your site. That depends on how many modules hook into those processes. It's not very recommendable to do that for every single row -- especially the profile_load_profile one, as that'll always give the same results.
The main alternatives you got (as far as I can see):
Profile_load_profile: I'll get to this later on
node_load: Only other option you have here (again, as far as I can see, at least), is making a direct DB call to fetch the value you need. This is, assuming you're familiar with the database, writing SQL queries (ok, it's a very basic query, but still) and if you rename the field, or add it to another content type, you might have to change that query (CCK is an absolutely magnificent module, but its table alters can be a pain in the behind)
Another point of optimalization (although this is just plain nitpicking):
You can replace three lines by one (without losing readability or maintainability):
can be replaced by:
if (strstr($field->options['format'], 'linked')){ //if the format contains string 'linked', add link to nodeThe rest, you've already noticed yourself (eg. adding that "(this will create problems later)" comment)
You're also right about wanting to put that into a separate module or template.php.
To add it in a module, you can use hook_views_pre_render. Just check if it's the correct type, then run a foreach on $view->result (like this:
foreach($view->result as $key => $value) {), make your alterations to $value and reassign $value to $view->result[$key]. This would also allow you to put the profile_load_profile before the loop, meaning it's called just once instead of for every row. In your module, you can also add a configuration form that'll store stuff like view names, replacement image and imagecache prefix, so you don't have them hardcoded, but can change them from the backend if necessary.Great, thanks for the advice
Great, thanks for the advice and replacement code.
Your module suggestions are right on and is what I'm going for, but I think it's above my pay grade atm :)
.
Show your boss what you can do, then you'll rise a pay grade ;)