How to build a complete customized Site on Drupal? Example: Indymedia

  1. Installed Drupal 5.0.
  2. Created roles "editor" and "admin."
  3. Set access controls.
  4. Enabled "Clean URLs."
  5. Installed contrib modules:
    • akismet is used for fighting spam. However, if you disable IP logging, it won't work. We're looking into other anti-spam modules.
    • content construction kit
    • contemplate
    • [ filefield] (you'll be customizing the node template, and having this module makes it easier to work with the display of file attachments)
    • imagecache
    • imagefield
    • indymedia_cities: This custom module grabs the master list of Independent Media Centers once a day. Then it removes the line breaks from the list, and provides you with a block that links to all the IMCs.
    • taxonomy access control
    • video
  6. Configured imagecache. This module is used to resize submitted images.
  7. Made categories Local, Global, Hidden, Unsorted.
  8. Save the Indymedia favicon to /misc. This is the little picture displayed by some web browsers. You may have to clear the browser's cache to see the new favicon. The /misc directory doesn't seem the best place for this file, but I don't know where else to put it in Drupal 5.0.
  9. Make a block in one of the columns with indymedia_cities.
  10. Take care of IP logging issues; see below.

if (window.showTocToggle) { var tocShowText = "show"; var tocHideText = "hide"; showTocToggle(); }


Configuring modules


CCK


Contemplate


indymedia_cities.module, Worcester variation

<?php
/* $Id$ */

/**
* Tested on Drupal 5.0.
**/

/**
* Implementation of hook_help.
**/
function indymedia_cities_help($section) {
switch ($section) {
case 'admin/modules#description' :
return t('Makes and updates cities list block.');
}
}

/**
* Implementation of hook_block.
**/
function indymedia_cities_block($op = 'list', $delta = 0) {
switch ($op) {
case 'list':
$blocks[0]['info'] = 'Cities List';
return $blocks;
break;
case 'view':
if (user_access('access content')) {
$block['subject'] = t('Global IMC Network');
$block['content'] = variable_get('indymedia_cities_list', t('To be downloaded'));
return $block;
}
break;
}
}

/**
* Implementation of hook_cron.
*
* Checks for updates
**/
function indymedia_cities_cron() {
$uri = 'http://www.indymedia.org/cities.inc';
$refresh = 24 * 60 * 60;

if (variable_get('indymedia_cities_checked', 0)+$refresh < time()) {
if ( ($newlist=file_get_contents($uri)) ) {
$newlist = str_replace("<br />", " | ", $newlist);
variable_set('indymedia_cities_list', $newlist);
variable_set('indymedia_cities_checked', time());
}
}
}

?>


indymedia_cities.info

; $Id$
name = Indymedia Cities
description = Creates a block with all IMCs, without line breaks, once a day


Taxonomy Access Control

  • You may have to log in as an editor and create an article with a tag, then go back into TAC and set the permissions for anonymous and authenticated users regarding tags. This seems like a TAC bug.
  • Use this module to prevent anonymous users from categorizing articles as "global" or "local." All anonymous articles will default to "Incoming," to be sorted by editors into the other categories.


Make Local/Global/Incoming blocks

  • Here's a php snippet from drupal.org that we use to make the "Local" block. This assumes that "Local" is taxonomy category 1.
<?php
/**
* Creates a list of node titles selected from multiple category terms
* in descending chronological order (most recent first).
* Titles link to full node.
*
* To change category terms to select from,
* edit the $taxd_id numbers, retaining the "" marks.
*
* To change the number of node titles, edit the $list_no number.
*
* This snippet is tested with Drupal 4.6.x
*
*/
$taxo_id = "1";
$list_no =6;
$query = "SELECT DISTINCT(n.nid), n.title, n.created FROM {node} n INNER JOIN {term_node} tn ON n.nid = tn.nid WHERE tn.tid in ($taxo_id) AND n.status = 1 ORDER BY n.created DESC LIMIT $list_no";
$sql = db_rewrite_sql($query);
$result = db_query($sql);
$items = array();
while ($anode = db_fetch_object($result)) {
$items[]= l($anode->title, "node/$anode->nid");
}

if(count($items)) {
return theme('item_list',$items) . '<a href="/local">more</a>';
}
?>


URL aliases

  • Make taxonomy/term/1 -> "local"


Making the content type "Article"

  • The default body is annoying, so remove the label for it and it will disappear.


Setting content template

This article was helpful.

  • Default body
<div class="field field-type-image field-field-main-image">
<h3 class="field-label">Main image</h3>
<div class="field-items">
<?php foreach ((array)$field_main_image as $item) { ?>
<div class="field-item"><a href="/drupal/<?php print $node->field_main_image[0]['filepath'] ?>"><?php print $item['view'] ?></a></div>
<?php } ?>
</div>
</div>
  • New body
<p><?php print $node->field_intro[0]['view'] ?>
</p>

<a href="/drupal/<?php print $node->field_main_image[0]['filepath'] ?>"><?php print $node->field_main_image[0]['view'] ?>
<div class="field field-type-image field-field-main-image"></a>

<?php print $node->field_body[0]['view'] ?>

<div class="field field-type-image field-field-more-pictures"><div class="field-items">

<?php
foreach((array)$field_more_pictures as $item) {
print '<div class="field-item"><h3>'.$item['title'].'</h3><a href="/drupal/'.$item['filepath'].'"><img src="/drupal/files/imagecache/article_mainimage/'.$item['filepath'].'" title="'.$item['title'].'" alt="'.$item['alt'].'"></a><p></p></div>';
}
?>

</div></div>

<?php print $node->content['files']['#value'] ?>

</div>
  • New teaser
<p><?php print $node->field_intro[0]['view'] ?>
</p>

/**
* You may have to experiment with the file path below such that the
* resized image links to the original image. It could be that you don't
* want such a link in the teaser.
**/

<a href="/drupal/<?php print $node->field_main_image[0]['filepath'] ?>"><?php print $node->field_main_image[0]['view'] ?>
<div class="field field-type-image field-field-main-image"></a>

/**
* If there is a body or additional pictures, make a link to the full article
**/

<?php if ((strlen($node->field_body[0]['value'])!=0)
||(count($node->field_more_pictures)!=0)) { ?>
<p><a href="/drupal/node/<?php print $node->nid ?>">[Full article]</a></p>
<?php }?>


Making the content type "Front Page Story"

  • This is for editors when they want to write something for the front page, and not have it appear as a teaser.


Disable IP logging

We ended up using a modified version of the 1st technique. Instead of setting all IPs to 0.0.0.0, we set them to a random number. This prevents the spam filter from thinking all content comes from the same IP and blocking it all. Here's the code:

$_SERVER['REMOTE_ADDR'] = sprintf("%d.%d.%d.%d", rand(0,255), rand(0,255), rand(0,255), rand(0,255));


Concern

Does this mean you're submitting IPs to Akismet that are not really spam IPs?


Notes

  • imagecache is what makes thumbnails of submitted images. It won't work if Clean URLs are not turned on. And Clean URLs don't work for me unless I go into .htaccess and uncomment the RewriteBase line. Had to create a directory tree for imagecache inside /files and set the permissions.
  • imagecache is also sensitive to available memory, which can be a pain to configure.

(Source: http://www.worcesteractivist.org/wiki/Building_an_Indymedia_site_on_Drup...)