Drupal 6 Related Content

Submitted by tomo on January 24, 2013 - 11:09pm

Similar Entries 2 (6.2) - - doesn't work. But version 1 works like a charm. Version 2 spits up an error on array_filter. Looking at the code, my guess is it's related to some new Views plugin code in version 2.

Related Block - - would have been cool too. It's much like Similar Entries. Unfortunately, the search algorithm is way too narrow. At first, I couldn't tell if the module was even working. Then by weening the search terms down to 1 (which means it figures out a single relevant term and then searches for only that) I saw some results, but not on many nodes still.

Relevant Content - - is nice in theory. Currently, it's broken. It's in the middle of a rewrite, but it's looking more and more unlikely that it will ever get rewritten.

Related links - - is not what it seems. It just finds any referenced links in the content and groups them together. Nothing external.

Other modules are term (taxonomy) based. But ideally, you don't need to specify all the relevant terms, and you don't need to explicitly say that two terms are related. There should be a more intelligent way.

Say you have a bunch of blocks and you want them to be displayed on certain nodes of varying content type based on some criteria like the content type and some CCK fields or taxonomy. You can't do this with the stock block visibility settings without writing custom PHP code.

But we can implement it using some existing basic Drupal building blocks: CCK and Views

1. Create a content type called Visibility Block.

You might have a field for content type where the possible values are returned from code which returns an array of the content types (using function node_get_types()).

2. Then for any fields you want to match, you'll have the same fields in this content type. For example, if one of your content types has a textfield and the possible values are 1, 2, 3, then do the same for Visibility Block.

When you create a Visibility Block, you'll have your block content in the body as normal (optionally you could use Block Reference and create blocks like usual and then link to them in the node instead, but I see no point in the extra effort and redirection), then select the conditions for the pseudo-block being visible.

3. Now create a view called Visibility Blocks Viewed. You'll create block displays, one for each content type that you have a Visibility Block set for which may only be one or two of your c-types.

Create an overridden argument each block display for the content type -field- in Visibility Block. You want to match the content type of the viewed node with the field in the Visibility Block, which are not the same type of thing. So you'll need to convert the argument in code.

You'll call menu_get_object() to get the $node because it's better than "$node = node_load(arg(1));". For the chosen c-type for that block display you will check that the implied node's c-type is what ever type you want to show in this block display because you will also check any fields that are specific to this c-type. Use PHP to supply a value since no argument will be passed in, and have the code load the current node and return the type. Then use PHP for the Validator Options and if the c-type doesn't match then you will display empty text. If you have multiple c-types which share CCK fields then you can put them into a single block display.

4. For each content type, in the chosen block display you will create a new argument for each compared against CCK field. You will pick a field from V-block and then use PHP to return a default value of the currently viewed node's field's value. You won't need to do Validation on these arguments.

5. Finally, you may want to limit the number of nodes returned, maybe just one. Now give this block a title and save it and configure its region in the normal block admin.


Why not the normal block visibility settings?

Because there you can't even configure by content type (anymore in D6). You can configure by path glob and by PHP code which overrides the path glob field (including in the database).

So under "Page specific visibility settings", set to "Show if the following PHP code returns TRUE (PHP-mode, experts only).", the field is blocks.pages. Essentially, PHP code works by overriding the pages list.

Why not use Block Page Visibility?

Block Page Visibility ( enables site developers to centralize the display of blocks to a single PHP function. It is an alternative to controlling display via each block's configure form. The more "sometimes on, sometimes off blocks" that a site uses, the more useful this module becomes.

This takes over the visibility settings of all your blocks by calling:

$sql = 'UPDATE blocks SET visibility = 2, pages = CONCAT("<", "?", "php ", "return bpv_is_visible(\'", module, "-", delta, "\'); ", "?", ">") WHERE status=1 AND theme=\'%s\'';

Sometimes it's easier to configure a block by just whether you're logged in, or whether you're on the front page.

This module doesn't give you any finer grained controls. And you have to configure every block in code. You also lose all your current block visibility settings once you install this module. To use this module you have to implement your own bpv_config or bpv_configuration (I think it's a bug that it's looking for bpv_configuration but actually uses bpv_config).

Build your own FAQ in Drupal

Submitted by tomo on October 13, 2012 - 12:15pm

Websites, including Drupal sites, often need Frequently Asked Questions and answers to them. Drupal, as a content management system, should manage your question and answer content intelligently. With all the great modules contributed to Drupal's community you might think there are some good FAQ modules. In my experience, the Drupal FAQ module is too rigid, and therefore unusable for most of my sites. But we can build a FAQ system using basic Drupal building blocks.

What we need: taxonomy, blocks, views, a few lines of PHP (that can be stored in the database - no custom module required)

1. Content type: Create a new content type. CCK is optional here, as you can just use Title as Question and Body as Answer.

2. Vocabulary: Create a new vocabulary called FAQ. Add a few terms if only for testing.

3. Devel Generate: Optional - requires Devel module's devel_generate to generate some test nodes with test questions, answers, and topics. devel_generate can be run from the command line too if you have drush installed - just run "drush genc". Anyways, generate a few dozen nodes, as many nodes as questions you have. It'll be easier to mass edit the questions once the nodes have already been generated.

4. Views: You'll need two views although they can also be two displays of a single view, so let's do that.

a. Create a view, filtered by your FAQ content type (and published or published/admin).

You will add three node fields:
Node: Nid (Nid) [make this field hidden, but its value is used in the rewritten Question field below]
Node: Title (Question)
Node: Body (Answer)

For the Question, rewrite the output to:

<a name="q-[nid]"></a>

You'll have on argument, which is the Term (FAQ vocabulary topic) in the URL.

- Configure Argument Taxonomy: Term
-- Provide default argument
--- Default argument type: Taxonomy Term ID from URL
-- Validator: (Choose your FAQ vocabulary)
-- Argument type: Term name or synonym
-- (Optional) Transform spaces to dashes in URL

Now turn this default view into a page that's not overridden in any way. Set the URL to be something that's NOT your vocabulary name because your URL will conflict with the default taxonomy paths ("taxonomy/term/%" - which Taxonomy sets up path aliases for from each vocabulary with each term - but that page may also be being overridden by a view included by Views by default). So if you want your URLs to be like "/faq/return-policy" then name your Vocabulary like "FAQ Terms" instead of "FAQ".

At this point you should save your new view and be able to go to "/faq/troubleshooting" or whatever. It will give you a list of questions with answers. But usually a FAQ section will also list out all questions at the top with links to answers below. How can we accomplish that?

b. Let's create a new Display that's a Block. Now override the fields and remove the Answer field. Override the display of the Question to:

<a href="#q-[nid]">[title]</a>

Optionally, set a blank title for this field. Then we will have a block that is just a list of questions. But the argument won't work anymore since it's a block. So you need to override the argument "Taxonomy: Term".

- Default argument type:
-- PHP Code
--- return arg(1);

- Validator: Basic validation + Transform dashes in URL to spaces in term name arguments

This will find the term "charity" in the path "/faq/charity" and pass it on.

5. Now that the block is created, you need to make it display. We want to display it on the top of our first view!

This is assuming you have a region in your theme for blocks at the top of content in pages. You could choose another location but it should really appear as the first content you see. But you want this block to appear ONLY on this page! So in block admin, configure the block you just created, and under:

Page specific visibility settings
- Show block on specific pages:
-- [check] Show on only the listed pages.
- Type in "faq/*"

Save the block. Now your question list with links to answers further down the page should be appearing at the top of your FAQ pages!

7. Next, you need a list of your categories. Sadly, there's no easy way for Drupal to do this. Views has a view type for taxonomies which is unfortunately not very powerful and so we can't use it to get links to "/faq/[term]" as it doesn't allow us to rewrite our own links. It allows you to link to term pages but those pages are rendered by either the Taxonomy module or that default view I mentioned earlier. Trying to override those paths with our own view is a mess, probably due to weighting.

Anyways, we can easily create a list of topics with links with a tiny bit of PHP. Create a new block using the Block admin page. In the block body:

$tree = taxonomy_get_tree($vocabulary_id=YOUR_FAQ_VOCABULARY_ID_HERE);
$html = '<ul>';
if ($tree) {
    foreach ($tree as $term) 
        $html .= '<li>' . l($term->name, 'faq/' . str_replace(' ', '-', mb_strtolower($term->name))) . '</li>';
$html .= '</ul>';
return $html;

Again, set this block to only appear on "faq/*" pages. Then configure its location into a sidebar or somewhere and you will be displaying links to each of your FAQ topics and you're done!

Mass editing nodes in Drupal can be a chore. If you just want to edit some attribute and set it to a single value for many different nodes then Views Bulk Operations can help. But you may instead want to make some quick changes to the titles, bodies, and CCK fields of a bunch of nodes of a certain type. The default way would be to open each node in a browser tab, go to their edit forms, and then operate on each one individually. Can we come up with a better way?

Multi Node Edit is a module that sounds like it could help. It promises to give you a page with many node edit forms. Unfortunately, this is not the case. By itself, this module is not usable to users. If you write some code to use it like a library you might be able to create a page with many node edit forms on it.

Recommendation: This module isn't useful to most people. It might be useful if you're writing code for a custom page.

Editview (editview) is the easiest to use, you just build Views and select 'Style' of 'Editview' in one of your displays. It works on the whole display, so all fields become editable. Unfortunately, you can't control this. Some fields shouldn't be editable, and so sometimes they just don't appear at all. Other times you may want to view a field but not edit it. Unfortunately, this isn't possible, even when using Global fields. [This issue is tracked here:]

* In my case, I just wanted to get a link to edit the node. I accomplished this by adding a Node: Path field which shows the path/alias editing form.

Recommendation: Use Editview if you're comfortable with building Views. Then you can construct a view of the fields you want to edit, and make it easy to filter the nodes you want to edit.

Editable Fields (editablefields) - 6.2 doesn't integrate with Views, despite the README. 6.3 does integrate but not the way explained in the README.txt. There is no added View type to choose when creating views. The exported content types used for demonstration don't import either. Most fields aren't editable, but if they are there will be a new checkbox for editable with some options. However, the 6.3 version of the module is still quite buggy so it doesn't work at all.

Recommendation: Avoid Editablefields module for now unless you want to just edit fields in the node display.

Drupal Links in Content

Submitted by tomo on October 11, 2012 - 3:01am

Problem: In your blog posts you have a lot of links to other pages on your site, then one day you decide to change the URL pattern for all nodes on your site, or you change the pattern and slowly update paths to nodes by editing and saving them. Unfortunately, you had hard-coded paths in your content bodies and now they are all leading to 404 pages. What to do?

1) Link checker (linkchecker) module will find the broken links. This is something you may need to use.

2) Path Finder is a module that turns your node links into permalinks with node id (slug) at the front of the URL so that any future change to title which results in a different URL still leads to the same node via the node id. Example:

Of course, this doesn't help you once you already have a bunch of nodes and content linking to them, but it's one strategy to start with. Then if you do change the titles or patterns of your nodes, as long as the node id / slug is still at the beginning of the url, then you won't get any 404 errors, although you'll then have multiple URLs pointing to the same content. So this isn't ideal.

3) Turn on Pathologic: "Pathologic is an input filter which can correct paths in links and images in your Drupal content in situations which would otherwise cause them to “break;” for example, if the URL of the site changes, or the content was moved to a different server. Pathologic is designed to be a simple, set-it-and-forget-it utility. You don't need to enter any special “tags,” path prefixes, or other non-content noise into your content to trigger Pathologic to work; it finds paths it can manage in your content automatically."

4) If you just need to remove a base path (like from all URLs, then URL Replace Filter (url_replace_filter) will suffice.

5) If you need to do more complicated search and replace on URLs, and want to use regular expressions, then use Search and Replace Scanner (scanner).

Finally, use Global Redirect to always have a single canonical path for each piece of content.

Drupal URLs can be pretty long. But practically, there's a limit in the database of 128 characters, even though browsers and web servers can support much longer URLs. With new versions of Path Auto, the schema is checked for alias column size. Then aliases longer than 128 characters are supported. This requires no hacking!

To change this, without just manually altering the length of the column in your database, you can use the following code in your own module:

* Implementation of hook_schema_alter().
function yourmodulename_schema_alter(&$schema) {
  $schema['url_alias']['fields']['dst']['length'] = 255;

Long URLs aren't very human friendly but even the oldest browsers can support URLs more than 2048 characters in length. Browsers support long paths, web servers support them, proxies support them, and mail clients either support them or break around 80 characters anyways. This doesn't mean you should carelessly throw around long URLs, but if you're generating them automatically then you don't need to cut them at an artificially low limit anymore.

How can we store tables or spreadsheets in Drupal content nodes?

Drupal is a Content Management System as well as a Content Management Framework. It's meant for facilitating the creation and editing of content, where content doesn't just mean simple text. CCK allows Drupal site managers to easily enable complex data types for their content. But sometimes it's not so easy to manage lots of simple data in the way that a spreadsheet (meaning Excel or Google Spreadsheet) easily manages many rows and columns of related data.

Sometimes you really want tabular data and you may not know for sure how many rows or columns you'll want beforehand, which is never a problem for Excel or Google Spreadsheet (which is also why sometimes people abuse Excel as a general purpose database). Maybe you are importing spreadsheets or are using spreadsheets with many rows and columns, and only want to use a section of the spreadsheet. Maybe you need to use spreadsheets because you are using formulas and want to do some graphing based on some numbers too. In fact, Excel can do much more. Rather than hoping all of those use cases will make it into a Drupal module anytime soon, wouldn't it be nice if you could just embed a spreadsheet in a node?

There are some modules for attaching tables or tabular data to nodes but in the end the interface can be a bit unwieldy. I discussed building something like a spreadsheet to quickly edit many values and below I present a demonstration.

What is already available that we could use to attach spreadsheets or something similar to nodes?

1. You could: Configure a Google spreadsheet that's either public or somehow accessed via a Google api, perhaps using OAuth2 or just assuming the viewer also has edit access to the spreadsheet. Google already lets you embed spreadsheets including the editable spreadsheet but they don't let you limit the view of the spreadsheet (limiting the view still lets everyone access the whole spreadsheet by changing the URL).

We would also need new nodes to automatically create sheets in the spreadsheet or new spreadsheets altogether and embed them in node edit. This would need to use their APIs since the embeddable Google Spreadsheets require an existing spreadsheet, otherwise this step needs to be done manually for each node - a new Google spreadsheet created per node.

This Redmine Google Docs plugin takes a similar approach and shows how the resulting data could be embedded.

(This might be worth investigating as well.)

2. Another approach would be to take an existing JavaScript or Java spreadsheet that could be embedded. This could be exactly what you want if you need the full functionality of Excel in each node. One such online spreadsheet is ZK Spreadsheet which is written in Java, and would let you have full formula and charting support.

3. Embed a widget like the form below as a CCK field in a node. It would be a new CCK field type where the editing widget is the below spreadsheet-like table and the display widget might be the same thing, an uneditable table, or the raw JSON string representation. In the database, the actual value of the field would be JSON (unless you wanted to use PHP's serialize() which would require POSTing values first instead of just posting the json value). This means you wouldn't relate or compare this field to anything else, as with any serialized data in a database. You could come up with some other schema involving columns and rows to store the table's values for each field in a node but I'm not sure it's worthwhile.

I created this demonstration but haven't turned it into a Drupal module. There is code to dump the edited values into a single JSON value to be stored in the database but the storage would be module-specific.

Get the JavaScript - then combine it with html and CSS, which you also see below.



Importing and Exporting Drupal Taxonomy

Submitted by tomo on August 31, 2011 - 3:10am

There are multiple modules for importing and exporting Drupal taxonomies (Drupal switches between using the term "taxonomy" and "vocabulary" like a clinical schizophrenic). Some use CSV format (, others XML (, and still others use a PHP array (

Some of these modules use the same paths for the export and import pages but they are different modules and aren't compatible. If you have both Taxonomy Export and Taxonomy XML installed at the same time they will conflict.

Except for CSV, the other import/export modules need you to create documents in a rather wordy XML or PHP code format, which can actually be more work than entering the terms in manually. Some people may use taxonomy import/export for only the taxonomy definition rather than terms. It's sometimes unclear what happens if you want to re-import duplicate term names later.

What worked best for me was using Taxonomy Manager which gives you an improved UI for organizing terms within a vocabulary. I wish it made editing the core fields of a taxonomy more ajax-y but what it does provide is an easy way to add multiple terms at once, a textarea for pasting in a list of terms, and a way to select where the new terms will go. So you can paste in all the top level terms, then paste in all the 2nd level children of the 1st term and select the 1st term to indicate they will all go under it. As long as you don't have too many different branches, then this can be done fairly easily.

Syndicate content
© 2010-2014 Saigonist.