This "book", a collection of tips, tricks, articles, and full blown tutorials, is my way of giving back to the community that has helped me so much. It is now and always will be a work in progress. As I learn newer and better ways of doing things and as Drupal itself evolves, I will keep adding more and sometimes go back and revise what's already there.
If you have any questions or comments on anything in this book, please use the support forum as it's much easier for me to keep track of posts than comments.
The following is a list of current articles and tutorials. It links straight to the article/tutorial nodes and doesn't include general info pages or outdated pages:
This isn't much of an article since I'm not doing any how to. I just wanted to say that porting OSWD themes is amazingly easy. I know sepeck's written on this and didn't expect it to be terribly hard, but I was impressed that it took less than 10 minutes. Of course tweaking is needed to make it look right with all modules and such, but it's not bad for 10 minutes of work.
If you're curious, the original theme is here: http://www.oswd.org/design/preview/id/3628 and my super quickie port is in the attached zip.
Edited to add: A bit more work and it now looks like: http://momsclubofholmen.org/
Michelle
Revised Sep 7, 07
Note: Since 6.x is nearly in beta, I should mention that this is being done in 5.x.
When I started work on Coulee Region ONLINE, I planned on writing up a detailed summary of what all went into it to post on the Drupal Showcase forum. As I got more into the project and spent untold hours trying to make my ideas work, often with poor or no documentation, and with a lot of help from the nice folks on IRC, I decided to go beyond that. I am in the process of creating a series of tutorials hits the major points of my site to show you how I did it. While I will try to make the tutorials as useful as possible, they are not drop in solutions. It's expected that you are familiar with Drupal and willing to take the time to research things you don't understand.
This is an ongoing and long term effort so don't expect it to be done anytime soon.
Planned tutorials (in no particular order):
If you'd like to peek at any of this stuff from the user's perspective, please use the dev site. I don't want a bunch of test accounts on my live site. You can play around all you want on the dev site as it will periodically get wiped out with a copy of the live site.
A note about support... I have spent quite a bit of time, far more than I ever expected, answering questions about the user profiles. The thought of multiplying it by several more tutorials is overwhelming. I'm not cutting off support, but I may be more selective in what I answer and will likely take even longer than I have been. I need to balance the time I spent answering questions with getting stuff done on the site. If you have a question that isn't specific to my tutorials, please use the regular Drupal support options as you'll have a lot more people available to answer.
Michelle
I tweaked the forums on CRO quite a bit but it's been too much of a mess of hacks to share. When I decided to copy my changes to the forums here, I realized it was time to clean it up and make it portable. Which has spawned a new module.
You can read the discussion of it here: http://groups.drupal.org/node/7064
This is not even remotely ready for production use; there is still a huge amount of work to be done. I'll be making a project on drupal.org soonish but you can find a very early sneak preview attached.
This section is some early planning pages that I've copied over from the old dev site.
I have been wanting to create a local community site for around 10 years. Back in 1998, I made a Geocities club (later Yahoo Groups) as my first attempt. It failed pretty miserably, unfortunately, but I also didn't put the time into it that I should have. I was never happy with the limitations of using a free host and just couldn't get excited about it.
Since discovering Drupal, my interest has been rekindled. I had a couple other sites I needed to do first and finally have them to the point that they don't need my active attention. That frees up some of my very toddler-limited time to start making this dream a reality.
So why am I telling you this? Well, I thought it might be of interest to others to follow along. This is the first in what will be a series of articles about Coulee Region ONLINE (CRO). I'll tag them with both Drupal and CRO so you can find them easily. When the site is done, I'll go back and turn my articles into handbook pages. I expect this will be a long process, possibly a year or more. So don't expect me to post every day or even every week. But I will post eventually, so drop by now and then to see the progress.
The live site is at http://couleeregiononline.com and the dev site is at http://dev.couleeregiononline.com
Michelle
Being a full time mom to an active toddler, I don't have a lot of time at the computer. But I find myself with a lot of thinking time during the day when driving place to place or watching my son at the park or any of the zillion other things that keeps me from the computer but doesn't take much thought.
Because of this, I tend to do a lot of site design in my head. There's pros and cons with this. One big pro is that I think through what I want and often realize something isn't going to work before I actually implement it. The big con is that it's hard to keep a whole site in my head and I'm sure I've forgotten lots of ideas I had. But, until my son is old enough that I can spend more time on the computer, it's what I have to work with.
He's doing a good job of playing by himself at the moment, so I'm going to write down as many of my daydreams and brainstorms as I can until he comes to fetch me. This will be messy, but I can always refine it later. :)
That's a good start to work with. I'm sure I'll think of more goodies to add as I go along but at least I got a lot of the ideas in my head written down in shorthand so I'll remember them.
The next step is organizing and focusing my brainstorm into concrete specs.
In my last post, I wrote out a quick list of the ideas that have been floating around in my head. Now I need to get organized. My ideas fall into two main categories:
1) Community interaction. I don't want this site to be just a list of links. I want real people talking to each other. I want a living, breathing community. This is my main goal for the site. To that end, I wrote what will likely become my mission statement:
"Coulee Region ONLINE is a community portal for La Crosse, Wisconsin and surrounding communities. While other local portal sites are focused on links and general information, our focus is the people of the community. With forums, chats, blogs, and other interactive features, our goal is to move beyond just giving information and provide a gathering place where people can interact with their neighbors whether they be next door or across the Coulee Region."
2) The other part to my site is informational. I plan to have a ton of information about the communities that make up the Coulee Region. I'll have business links like the other portals do but I also want to add things like local parks and activities. Plus community news, and more. This part of the site will be interactive as well, with people able to add reviews and ratings to each item.
In my next posts, I'll go into detail about each of these options, detailing the functionality and finding out what I need to implement them.
I took a break from writing up specs to indulge myself in going through the contrib modules to see what I might like to use. I set the filter to "all" and copied the links to anything that caught my eye. When I was done, I had roughly 300 modules! Of course, many of these do the same thing as others and some of them aren't maintained anymore. I spent some time organizing them by category but haven't further weeded them. I'm posting the list here for the curious and will post again once I've weeded it down.
[Edit Oct 16: Wow, wish I'd seen this page before trying to organize all of this!]
DISCUSSION
phpfreechat
Forummail
Announcement
Chatbox
Chatroom
Guestbook
Instant messenger
Smileys
Shoutbook
Shoutbox
SpamSpan filter
Survey
YShout AJAX Chat
Live Discussion
poll_inline
Quote
Privatemsg
BLOGGING
Blog Client
Blog Archive
Blog Information
Blogger
Blogroll
Latest and Greatest
USER ENHANCEMENTS
Node Profile
Profile Plus
User Search
Buddylist
Advanced User
Bio
Custom Ranks by Post Count
Karma
imood
USER TOOLS
Bookmarks
Checkmail
TELL A FRIEND
User Referral
Forward
Email This Page
Invite
tellafriend
Send
MULTIMEDIA
Acidfree
audio
Flash gallery
Flash Filter
Gallery
Image
Image Exact Sizes
Image filter
Image Publishing
Imagedrop
Imagemagick
IMCE for TinyMCE
Img_assist
Slideshow
Lightbox V2
Node Image Block
Photobar
Slideshow 2
Video
WebMedia
shazamgallery
Webcam
Flickrstickr
Flickr Module
Flickr Block
Flickr
flickrhood
SITE BUILDING & ADMINISTRATION
Actions
Advanced menu item settings
Contact List & Forms
Content Construction Kit (CCK)
Category
Flatcomments
Forum Access
Extended user status change notifications
Content Templates (Contemplate)
Dynamic Menus
Devel
CustomError
Inactive User
Separate "management" theme for administrative pages
Sanity
microcontent
CONTENT ENTRY & FILTERS
AJAX Spellcheck
Attachment
Authorship Module
Autosave
Bbcode
BBCode Formatting Bar
Comment Upload
FCKeditor
Coolfilter
Excerpt
Embed filter
Edit As New
HTML corrector
Htmlarea
Htmltidy
htmlwrap
Inline
Insert Block
Insert View
Import / Export API
Import-export
Invisimail
quicktags
Remember Filter
webform
Workflow
TinyMCE WYSIWYG Editor
Node Go To
MODERATION
Comment mover
captcha
Flag content
Content Moderator
modr8
Node Moderation
ADVERTISING
AdSense
Banner
Click Thru Tracking
TextLinkAds.com Integration
MAPPING
Carto - opengis web mapping
KML module
Googlemap
GMap Module
Map module
location (API, module)
EVENTS
EventFinder
Event Repeat
Event
Remindme
RSVP
Signup
LINKING
Easylinks
Janode
Links Package
LinksDB
Web Links
Weblink
Delicious
Service links
USER HELP
Help Tip
Favorites
faq
SEARCHING AND SEO
Google Analytics
Google Search
Google Sitemap
Global Redirect
MISC & FUN STUFF
Daylight Savings Reminder
Countdown
Vote up/down Package
FeedButtons
Feedback
Feature
Endorsements Module
Cpanel Integration
helpers
Job Search
Quotes
Recipe
Weather
Postcard
I/O
Syndication
Syndication2
Node import
USER
LoginToboggan
Nodeauthor information
Node Profile
Node Adoption
mypage
Members
Masquerade
Onlinestatus Indicator
Profile Plus
Profile Privacy
Profile visit
Role Assign
Site Profile Directory
Staff Bio
troll
User Badges
User Import
User List
User Maintenance
User Points
User Referral
User Related Content
User Search
User Tags
userlink
UserLists
Usernode
userplus
userposts
userreview
Login Destination
Masquerade
Legal
Remember me
EMAIL & NOTIFICATIONS
Listhandler
Mailhandler
mailman mailing list admin
Mailman Mailing List Management Wrapper
Notify
Subscribe
Subscription
Subscriptions
VOTING & RECCOMENDING
Node Vote
NodeReview
mediumvote
Recommended Posts
Vote up/down Package
Voting
Voting Actions
Voting API
Loves and Hates
Movie Review
Review
PRESENTATION
Nicelinks
Nice Menus
Outgoing links filter
Page title
Paging
Panels
Menu bar
S/P Ajax
S/P Magic Menus
Portal
Print Friendly Pages
Views
s Views Bonus Pack
Views Bookmarks
Views Calc
Views Fusion
Side Content
sIFR
Signwriter
SiteMenu
Superteaser
Switchtheme
Node Queue
Weight
Sections
Planet
ACCESS CONTROL
Path Access
Restricted Text
Taxonomy Access Control
Taxonomy Access Control Lite
STATISTICS
Log Search
Xstatistics
Statistics filtering
Statistics trends
SEARCH & SEO
Pathauto
Node (key)words
Search 404
Search config
Path Redirect
Path Filter
Zeitgeist
TAXONOMY
Taxonomy Breadcrumb
Taxonomy Browser
Taxonomy context
Taxonomy Defaults
Taxonomy Easy Filter
Taxonomy Filter
Taxonomy hide
Taxonomy Multi Editor
Taxonomy Switch
Taxonomy Theme
Primary Term
Tagadelic
As I said before, the main goal of this site is real chat with real people. All other ideas are secondary to this goal. So let's go into detail of what I need to get people talking.
Forums. The forums will be the central place for chat. I plan on using the forum module that comes with Drupal and add some contrib modules and tweaks to get the functionality people are used to from other sites.
Private messaging I'm not a big fan of private messages and prefer to use email, but I know it's something a lot of users like. So I'll add privatemsg for that.
Chatting I'd like to have an IRC like chat going. I thought about interfacing with an actual IRC channel but the various JS offerings look like a much better alternative. I had a look at the demos of YShout AJAX Chat and chatbox but the demo of phpfreechat really impressed me. It's not native Drupal but rather an integration of another OS app. I want to try and avoid that where possible, but I like this one so much better than the others that I'm going to go with it for now. chatroom has potential as a native Drupal solution, but it's not ready yet. I'll keep an eye on it and may change at some point.
WYSIWYG I'm haven't decided, yet, on what, if any, WYSIWYG editor to use. I may leave this decision until I get some users and see what they want. Or maybe start with something simple like BBCode or Quicktags instead of more complex ones like TinyMCE or fckeditor
Voting and reviews
After looking at Webchick's excellent article I've decided to go with userreview for nodes where I want both comments and rates, such as business links. I might also end up using Vote up/down Package if I decide to go for a Digg like structure on some content.
Classifieds
I want to have a place where people can place classified ads. I know I talked with someone who had a custom module for this that they were thinking of releasing, but I can't remember who, now... If I can't track that down, I may just use a combination of CCK and views.
The second part of my general plan is informational. This isn't totally disconnected from the interactive part, of course, but the focus is a little different.
The informational side will consist of these areas:
Communities Each community will have its own page. This page will list general info about that community as well as have a tracker of posts tagged with the community.
Directory. This is sort of like a phone book in that it will list all the area businesses. In addition, it will list parks and other attractions. Since I'm interested in making this site useful more than making money, adding a link will be free, though I'm thinking of offering better positioning for paid links using the sticky option.
Events Local events, including an event calendar. I haven't decided, yet, if I want to use the event module or go with a CCK/views combination.
I'll be using CCK to make a few custom types. Communities, Events and Parks will each get their own type due to the specific details I want recorded. Businesses, restaurants, attractions, and "other" can probably share a content type and just use categories to differentiate. I can't decide what to call this content type... It's one of those niggly things that just keeps eluding me. I'd welcome any suggestions. :)
My original plan was to use the category module primarily because it makes terms into nodes which is perfect for the community pages. After trying it, though, I decided the code just isn't ready for production use. So I've decided to use regular taxonomy. To simulate the terms as nodes functionality, I've added URL aliases to link each community term's page to the proper community landing page. This is a lot more work, but only needs to be done once for each community. I may revisit the category module sometime in the future, but this will work for now.
I've had a lot of people asking about the directory I'm working on here: http://couleeregiononline.com/directory . I plan on doing a tutorial but first I need to finish version 3 of user profiles along with all the other stuff I have to do. So it's going to be a while. In the mean time, here's a few pointers to help those who can't wait:
Hopefully that will help a bit until I can get the tutorial written.
Michelle
Oct 31, 2007 - This tutorial works but I've since found a more elegant way of doing it, so I recommend Rate and Review 2.
Purpose: This tutorial will show you one way of allowing users to rate and review a node all in the same form. This isn't the only way of doing it. If you are looking for a more drop in solution, see http://drupal.org/project/userreview . I went this route because I wanted to use fivestar and I already have CCK and views installed so all I needed was prepopulate.
Skill level: This tutorial is not aimed at beginners. You need to be comfortable with creating content types and theming them.
Support: Please use the support forum if you have questions and I will try to answer if I am able.
Modules needed: CCK, Views, Fivestar (as well as dependencies for those modules)
Note: In order for this to work, you need to make the following change to fivestar_field.inc:
Change
$items[$delta]['target'] = drupal eval($item['target']);
to
$items[$delta]['target'] = eval($item['target']);
The reason for this is that the $node object is not in scope in the evaluated PHP when using drupal_eval but it is with just eval. Hacking a module is uncool, so suggestions to get around that fix are welcome.
If you have a site specific module, add this form_alter code:
<?php
function YOURMODULENAME_form_alter($form_id, &$form) {
switch ($form_id) {
// Only do this for the review type's form
case ('review_node_form'):
//If we are adding a review, we need to grab the parent node ID from the URL
if (arg(1) == "add") {
// Get the parent node's id from the url
$pnid = $_GET['pnid'];
// Set the parentnid field's value
$form['field_parentnid'][0]['value']['#value'] = $pnid;
} else {
// Otherwise, grab the existing parent node ID to redirect to
$pnid = $form['field_parentnid'][0]['value']['#default_value'];
}
// Hide the field
$form['field_parentnid'][0]['value']['#access'] = FALSE;
// On submission, redirect to the parent node
$form['#redirect'] = "node/$pnid";
// This is in case we add more forms later
break;
}
}
?>If you don't already have one and don't know how to make a module, just use the one in the zip.
<?php
$current_rating = votingapi_get_voting_result('node', $nid, 'percent', 'vote', 'average');
$numstars = 5; // Change this to how many stars you want
print theme('fivestar_static', $current_rating->value, $numstars);
?><?php
print l("Add a review","node/add/review",NULL,"pnid=" . $node->nid,NULL,NULL,TRUE);
?><?php
// Retrieve the view
$view = views_get_view('reviews_of_node');
// Build the view into the $reviews variable with paging on and nodes per page set to 20
$reviews = views_build_view('embed', $view, array(strval($node->nid)), true, 20);
// Get the number of reviews
global $pager_total_items;
$numreviews = $pager_total_items[0];
// Print the reviews
print "Number of reviews: $numreviews";
print $reviews
?>Enjoy!
It's likely to be some months before I get to writing this tutorial so I decided to throw up some tidbits. These are offered as is. Please don't ask for support. I'm already behind in supporting forums & profiles and just can't add to that. Don't expect to be able to just drop this in and have it work but, if you have some idea of what you're doing, this may be helpful.
For the top level directory page, I have a vocabulary, Directory Categories, with two levels of terms. The top level is a broad category and the second level narrows it down. I used the panels_by_term view style found when you have both the views bonus pack and the panels module. This is with panels 1 as this was done before panels 2 was around. This is the export of the view, called directory_browse:
<?php
$view = new stdClass();
$view->name = 'directory_browse';
$view->description = 'Browsable directory';
$view->access = array (
);
$view->view_args_php = '// Always use 8 as the augment since that\'s the directory\'s taxonomy
if (!$args[0]) {
$args[0] = 8;
}';
$view->page = TRUE;
$view->page_title = 'Browse Directory';
$view->page_header = '';
$view->page_header_format = '1';
$view->page_footer = '';
$view->page_footer_format = '1';
$view->page_empty = '';
$view->page_empty_format = '1';
$view->page_type = 'panels_threecol_term';
$view->url = 'directory/browse';
$view->use_pager = FALSE;
$view->nodes_per_page = '0';
$view->menu = TRUE;
$view->menu_title = 'Browse directory';
$view->menu_tab = TRUE;
$view->menu_tab_weight = '0';
$view->menu_tab_default = TRUE;
$view->menu_tab_default_parent = NULL;
$view->menu_tab_default_parent_type = 'normal';
$view->menu_parent_tab_weight = '1';
$view->menu_parent_title = 'Directory';
$view->sort = array (
array (
'tablename' => 'node',
'field' => 'sticky',
'sortorder' => 'DESC',
'options' => '',
),
array (
'tablename' => 'node',
'field' => 'title',
'sortorder' => 'ASC',
'options' => '',
),
);
$view->argument = array (
array (
'type' => 'vocid',
'argdefault' => '1',
'title' => '%1',
'options' => '',
'wildcard' => '',
'wildcard_substitution' => '',
),
array (
'type' => 'taxid',
'argdefault' => '6',
'title' => '%1 - %2',
'options' => '9',
'wildcard' => '',
'wildcard_substitution' => '',
),
);
$view->field = array (
array (
'tablename' => 'node',
'field' => 'title',
'label' => '',
'handler' => 'views_handler_field_nodelink',
'options' => 'link',
),
);
$view->filter = array (
);
$view->exposed_filter = array (
);
$view->requires = array(node);
$views[$view->name] = $view;
?>Note the argument code is hardcoded with my vocab ID.
To make the page look how it does takes some heavy theming. You can put this in your template.php:
<?php
// BEGIN Override the browse directory view (panels by term) theming
function phptemplate_views_bonus_panels_byterm_summary_directory_browse($view) {
drupal_add_css(drupal_get_path('module', 'views_bonus') .'/views_bonus.css');
// argument 0 must be a vocabulary ID
$vid = $view->args[0];
// Get the taxonomy tree from the argument to the view
$tree = taxonomy_get_tree($vid);
// group terms with their parent
foreach ($tree as $term) {
$cnt = taxonomy_term_count_nodes($term->tid);
if ($term->depth == 0) {
// Top level category. Add the "all" to the URL to show all subterms when the link is clicked
$txt = array($prefix. l($term->name . " ($cnt)", "taxonomy/term/$term->tid/all"));
$parent_tid = $term->tid;
$groups[$parent_tid]['header'] = $txt;
} else {
// This bit is a pseudo tagadelic for the terms. It takes the number of nodes for a term and divides
// it by 5 and then uses just the whole number part. If a term has at least one node, it gets a 1. If
// a term has more than 25 nodes, it stays at 5. These numbers are then used to add an extra class of
// "sizedterm-N" where N is 0-5 that can be styled in CSS to make the terms look different based on
// the number of nodes in the term.
$sizeclass = floor($cnt/5);
if ($sizeclass == 0 && $cnt > 0) {
$sizeclass = 1;
}
if ($sizeclass > 5) {
$sizeclass = 5;
}
$txt = array('<span class="sizedterm-' . $sizeclass . '">' . l($term->name . " ($cnt)", "taxonomy/term/$term->tid") . '</span>');
$groups[$parent_tid]['rows'][] = $txt;
}
}
// Spread the across 2 columns
$content = array();
$i=0;
foreach ($groups as $group) {
if ($i % 2) {
$section = 'left';
} else {
$section = 'right';
}
// Create a comma separated list of subterms
$subterms = array();
foreach ($group['rows'] as $subterm) {
array_push($subterms, $subterm[0]);
}
$subterms = implode(", ", $subterms);
$content[$section] .= '<div style="display:block;"><h3>' . $group['header'][0] . "</h3>" . $subterms . "</div>";
$i++;
}
return panels_print_layout('twocol', $content);
}
// END Override the browse directory view (panels by term) theming
?>I think this is all the CSS for it but there may be more spread out in my .css file:
.view-summary-directory-browse h3 {
background: #356AA0 url(images/bluegradient-medium.jpg) repeat-x;
color: White;
padding : .25em;
margin-bottom: .25em;
}
.view-summary-directory-browse h3 a {
color: White;
}
.sizedterm-0 {
font-size: .9em;
}
.sizedterm-1 {
font-weight:bold;
font-size: 1.1em;
}
.sizedterm-2 {
font-weight:bold;
font-size: 1.2em;
}
.sizedterm-3 {
font-weight:bold;
font-size: 1.3em;
}
.sizedterm-4 {
font-weight:bold;
font-size: 1.4em;
}
.sizedterm-5 {
font-weight:bold;
font-size: 1.5em;
}
I'll try to throw more tidbits out as time permits. Hopefully that will help someone.
Michelle
Aug 26, 2008: A recent user of this tutorial wrote some updates here.
Note: This tutorial was written before fivestar gained the ability to use comments for rating. It's still useful if you want your reviews to be nodes.
This is a revised version of Rate and review in one step using the node relativity module. (Thanks to greggles for pointing this module out.)
Purpose: This tutorial will show you one way of allowing users to rate and review a node all in the same form. This isn't the only way of doing it. If you are looking for a more drop in solution, see http://drupal.org/project/userreview .
Skill level: This tutorial is not aimed at beginners. You need to be comfortable with creating content types and theming them.
Support: Please use the support forum if you have questions and I will try to answer if I am able.
Modules needed: CCK, Views, Fivestar, and Node Relativity (as well as dependencies for those modules)
Fivestar uses drupal_eval() to determine the target node for the voting widget. Unfortunately, the $node object is not in scope in drupal_eval() and we need to pull the target from the $node object. The fix is to make the following change to fivestar_field.inc:
Change
$items[$delta]['target'] = drupal eval($item['target']);
to
$items[$delta]['target'] = eval($item['target']);
Hacking a module is uncool, so suggestions to get around that fix are welcome.
<?php
$current_rating = votingapi_get_voting_result('node', $nid, 'percent', 'vote', 'average');
$numstars = 5; // Change this to how many stars you want
print theme('fivestar_static', $current_rating->value, $numstars);
?><?php
print l("node/add/review/parent/$node->nid",NULL,NULL,NULL,FALSE,TRUE);
?><?php
// Retrieve the view
$view = views_get_view('reviews_of_node');
// Build the view into the $reviews variable with paging on and nodes per page set to 20
$reviews = views_build_view('embed', $view, array(strval($node->nid)), true, 20);
// Get the number of reviews
global $pager_total_items;
$numreviews = $pager_total_items[0];
// Print the reviews
print "Number of reviews: $numreviews";
print $reviews
?>When submitting the review, it goes to the review view page. It makes more sense to go back to the node being reviewed. If you have already have a site specific module, add this form_alter code:
<?php
function YOURMODULENAME_form_alter($form_id, &$form) {
switch ($form_id) {
// Only do this for the review type's form
case ('review_node_form'):
// On submission, redirect to the parent node
$pnid = arg(4);
$form['#redirect'] = "node/$pnid";
// This is in case we add more forms later
break;
}
}
?>Enjoy!
A big part of any social networking site is the user profiles. Profiles let your users get to know each other and put a face on the anonymous internet. They can be basic, with little more than name, join date, and a few facts, or elaborate and complex. It all depends on the needs of your community. While the core profile module works for simple profiles, no one module will create a complex profile like you find on Myspace and Facebook. Instead, we start with a base module and link other contribs to it.
This section starts with the notes I gathered as I decided which base module build my profiles. Then comes the first and second tutorials. These served the community for a long time and are left for historical purposes, but I don't recommend using them anymore. Version 3 has turned into the Advanced Profile module. There will be tutorials to go with it but the bulk of the work will be done for you so the tutorials will focus on explaining what it's doing and giving ideas for enhancing it.
If you have any questions, please use the issue queue or my support forum. Also, I'd prefer it if people link to this node rather than subpages so people following the link always have the most up to date info.
[Update July 23, 2008: For those on D6, you might want to read this thread and learn about Content Profile, which is shaping up to be the successor to both bio and nodeprofile.]
So you want to pretty up your user profiles? But what module do you use? As with most things in Drupal, there's a lot of options. Of course, I recommend using Advanced Profile for the overall glue, but you still need some place to store the user profile data. This article will run through the pros and cons of each.
Usage:
Download, install, and enable the Bio module.
Setup at admin/user/bio
Add CCK fields as needed
Pros
Cons:
My opinion:
If you only need one node to hold the profile data per user, I reccomend using Bio. It's simple and works well with advanced profile. You can add a lot of other information to the profile panel using advprofile so bio should work for most sites' needs.
Usage:
Install nodeprofile, nodefamily, and subform element modules
Edit the content type you want to use for your profile and tell it that it's a node profile
Edit the options on the new nodeprofile tab that appears
More complex usage can be had by having multiple content types for your profile and using pageroute to hook it all together.
Pros:
Cons:
My opinion:
Nodeprofile is part of an awesome family of modules that let you do complex user profiles. If you need to get fancy with different profiles for different roles or having a wizard like process for the user to fill out multiple nodes in their profile, then this is what you want.
Usage:
Enable the module (it comes with Drupal)
Configure the profile by adding items in categories. Each category will show up on a separate tab of the edit account page.
Pros:
Cons:
My opinion:
I only briefly played with this module but it was a lot better than I was expecting. It's simple to use and has some nice options. If you don't need profiles to be nodes, this looks like a solid option. There are a lot of handbook pages dedicated to customizing it and it can do quite a bit more advanced things than I thought. Not working with views is a big drawback but that will be eliminated in D6 with views 2.
More information:
Profile: extending user account information
Customising the user profile layout
Usage:
The usernode module can be used to create user profiles by adding fields to it with CCK.
Pros:
Cons:
My opinion:
This option is deceptive in that it looks like the best option on the surface if you only need one node profile per user. The trouble is that you are then locked into using the usernode as your profile. If you later decide you want the extra functionality that bio or nodeprofile provide, you're out of luck. The maintainer doesn't reccomend this option and neither do I, but I'm presenting it here for completeness.
What about D6? There's a possibility that bio and nodeprofile may come together for a new and improved module. Interested? See Profiles as nodes in d6 for the discussion.
If you have comments or suggestions for improving this article, feel free to add a comment. Please do not use the comments for support requests.
This is the original tutorial from last May. It has since been replaced by a newer version. See the User Profiles page for details.
Goal: The aim of this tutorial is to walk you through every step you need to create a user profile like this one.
Notes:
Modules needed:
Step 1 - Getting prepared
Step 2 - Creating and configuring the profile content type
Create the content type (see note at end of "Add the fields" section):
Add the fields:
Note: The reason I had you create the content type first and then import into it is that there seems to be a bug with groups not getting created when you create the content type at the same time. You can get around this by doing the import twice if you don't want to manually create the type.
Fix the fields display:
Set the nodeprofile options:
Access control:
Step 3 - Avoiding naming collisions
To avoid having your usernode and nodeprofiles having the same titles, edit the usernode content type (?q=admin/content/types/usernode) and change the autotitle token to something else. I used "Usernode of [author-name]". The user will never see this, but it's nice to make it clear to admins which is which.
Step 4 - Take over the user account view tab
By default, the nodeprofile module will put your user profile as a section on the user account view tab (located at /user/#). This is fine for simple profiles but doesn't look right for a full featured profile. [See screenshots/User-Account-Default-View.jpg]
This step makes the user profile take over the entire view tab. The downside is that you will lose anything that other modules add to this page. If you add a module that normally has a link on the user view page, make sure you provide alternate access to it. If you are fine with the way it displays by default, you can skip this step.
<?php
//function _phptemplate_variables($hook, $vars) {
// if ($hook == 'page') {
if (arg(0) == 'user') {
$vars['tabs'] = str_replace('Edit</a>', 'Edit Account</a>', $vars['tabs']);
}
// return $vars;
// }
//}
?><?php
// Override the display of the nodeprofile to just show the node itself and not the surrounding markup or the tabs.
// Theming of the nodeprofile will be handled separately. Note that this affects it wherever it is displayed and
// not only on the user page.
function phptemplate_nodeprofile_display_box($element, $content) {
$head = isset($element['#title']) ? '<h2 class="nodeprofile-title">'. check_plain($element['#title']) .'</h2>' : '';
return $content;
}
// Override the entire user account view page to not show the categories or to seperate items into divs.
// Note that this is set up to still show everything that is thrown on this page. Getting rid of non-nodeprofile
// sections is done in the node_profile_bonus module by unsetting them but could also be done here by conditionally
// printing them to begin with.
function phptemplate_user_profile($account, $fields) {
foreach ($fields as $category => $items) {
foreach ($items as $item) {
$output .= $item['value'] ;
}
}
// Returning nothing from this function causes the entire page to whitescreen, so let's put something in by default
// A better idea might be to load up some sort of standard thing that has the views and just not the profile fields
if (empty($output)) {
$output = "This user has not filled out a user profile.";
}
return $output;
}
?>Your user account page (?q=user/1) should now look like this: screenshots/User-Account-After-Page-Take-Over.jpg
Step 5 - Taxonomy
My profile uses taxonomy for some of the fields. I did this so you can click on a term and see all the other users with that term. With some coding, the taxonomy is used as though it was a normal CCK field.
Go to Administer > Content management > Categories (?q=admin/content/taxonomy). Create the following vocabularies: Communities, Hobbies, Reading, Music, TV and Movies. Communities is a multi select with the terms entered in via add term. The others are freetagging. Note: If you add these in a different order or choose different vocabularies, you will need to alter the contemplate code and the input form to match.
[DIY - Most people reading this are not going to want preset communities. Feel free to skip that vocab and add it as a normal CCK text field if you want and I'll make notes where you need to delete references to it later.]
Attach each of these vocabularies to your User Profile content type.
Step 6 - Add the views
<?php
function phptemplate_views_view_list_buddylist_of_uid($view, $nodes, $type) {
$fields = _views_get_fields();
$taken = array();
// Set up the fields in nicely named chunks.
foreach ($view->field as $id => $field) {
$field_name = $field['field'];
if (isset($taken[$field_name])) {
$field_name = $field['queryname'];
}
$taken[$field_name] = true<