summaryrefslogtreecommitdiff
path: root/modules/documentation.module
blob: 8c014e8f9a3b61cae529ed5ba58f391ab2558369 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
<?php

$module = array("page"  => "documentation",
                "admin" => "documentation");

function documentation_module($name, $module) {
  print "<H2>". ucfirst($name) ."</H2>\n";
  if ($module["help"]) $module["help"]();
  else print "<I>No documentation available for module '$name'.</I>\n";
}

function documentation() {
  ?>
  <SMALL><I>$Id$</I></SMALL>

  <H2>Table of contents</H2>
  <UL>
   <LI><A HREF="#c1">Chapter 1: introduction</A></LI>
   <LI><A HREF="#c2">Chapter 2: installation</A></LI>
   <LI><A HREF="#c3">Chapter 3: engine</A></LI>
   <LI><A HREF="#c4">Chapter 4: modules</A></LI>
   <LI><A HREF="#c5">Chapter 5: development</A></LI>
  </UL>

  <H1><A NAME="c1">Chapter 1: introduction</A></H1>

  <P>Drupal is the English pronunciation for the Dutch word 'druppel' which means 'drop'.  Drupal is a fully-featured content management/discussion engine suitable to setup a news-driven community or portal site.  Drupal aims to provide easy installation, excessive configuration and fine-grained maintenance capabilities.  Due to its modular design, drupal is flexible and easy to adapt or extend.</P>
  <P>Drupal is primarily written by Dries Buytaert (dries_at_drop.org) and built after Slash (<A HREF="http://slashcode.com/">http://slashcode.com/</A>) and Scoop (<A HREF="http://scoop.kuro5hin.org/">http://scoop.kuro5hin.org/</A>).  You can download drupal from <A HREF="http://drop.org/module.php?mod=drupal">http://drop.org/module.php?mod=drupal</A>: the source code behind drupal is released under the GNU General Public License (GPL).  Everybody can download, use and modify drupal to suit his or her needs.  Everybody can freely distribute modified or unmodified versions of it, provided that they too are licensed under the GNU GPL.</P>
  <P>Drupal is free software maintained by volunteer effort at a best effort basis so if you are interested in helping out the drupal project in any way, drop me an e-mail.  If you use drupal for commercial projects, you might be able and willing to boost the pace of development by means of fundings or donations, or you can support further development by contracting me or other drupal developers for consulting services related to drupal.</P>

  <H2>Bugreports</H2>

  <P>If you found a bug, mail me and we will fix it provided you include enough diagnostic information for me to go on.  Your bug reports play an essential role in making drupal reliable.</P>
  <P>The first thing I will do when you report a bug is tell you to upgrade to the newest version of drupal, and then see if the problem reproduces. So you'll probably save us both time if you upgrade and test with the latest version before sending in a bug report.</P>

  <H2>Mailing list</H2>

  <P>There is a mailing list (drupal-support_at_drop.org) for people who want to discuss drupal development.  All submissions relevant to that, such as bug reports, enhancement ideas, patches or reports that a patch fixed a bug are appropriate.</P>
  <P>To subscribe to the drupal-support_at_drop.org mailing list, send an e-mail to drupal-support-request_at_drop.org with no subject and put subscribe in the body of your message.  Similarly, "unsubscribe" in the Subject line unsubscribes you, and "help" returns general list help.</P>

  <H1><A NAME="c2">Chapter 2: installation</A></H1>

  <H2>System requirements</H2>

  MySQL:<BLOCKQUOTE><A HREF="http://mysql.com/">http://mysql.com/</A><BR>(development with version 3.22.32)</BLOCKQUOTE>
  PHP4:<BLOCKQUOTE><A HREF="http://php.net/">http://php.net/</A><BR>(development with version 4.0.0 and 4.0.4)</BLOCKQUOTE>
  Apache:<BLOCKQUOTE><A HREF="http://apache.org/">http://apache.org/</A><BR>(development with version 1.3.14)</BLOCKQUOTE>

  <H2>Installation process</H2>

  <P>Here is the procedure for installing drupal on a Linux or Unix system.  This chapter describes the generic installation procedure for drupal as well as detailing some installation instructions for specific configurations.</P>
  <OL>
   <LI>
    <P>Download the distribution tar-ball and unzip it into the directory you want to serve web files from:</P>
    <BLOCKQUOTE>$ tar -zxvf drupal-x.x.x.tar.gz</BLOCKQUOTE>
   </LI>
   <LI>
    <P>We assume that you have some working experience with Apache, MySQL and PHP.  In order to set up your drupal site correctly, you'll first have to get Apache, MySQL and PHP working together.  So if you still need to install Apache, MySQL or PHP, please install them now.  Otherwise, head on to point 3.  The installation of these required packages is beyond the scope of this document but what follows are some brief guidelines to get you started.</P>
    <P>Installing MySQL shouldn't be too much of a burden, when using a Linux distribution that can handle RPMs.  All you have to do is grab the RPMs from the MySQL website.  Please do note that you'll also need the MySQL client RPM, not only the MySQL server one.  Once MySQL has been installed, download Apache and PHP, and unpack them in the same directory.  To install Apache together with PHP and MySQL, follow the "quick install"-instructions in the <CODE>INSTALL</CODE>-file located in your PHP directory.  When configuring PHP do not forget to replace '<I>apache_1.3.x</I>' with your version of Apache.  This may sound silly but it got me twice.</P>
    <P>After the compilation process you have to set the <CODE>DocumentRoot</CODE> in Apache's <CODE>httpd.conf</CODE> to the path of your <CODE>drupal</CODE>-directory.  Make sure your Apache is setup to allow <CODE>.htaccess</CODE> files so drupal can override Apache options from within the drupal directories.  Therefore, set <CODE>AllowOverride</CODE> to "All" instead of "None".  Somewhat down <CODE>httpd.conf</CODE> they ask you to set <CODE>Directory</CODE> to whatever you set <CODE>DocumentRoot</CODE> to. The last thing to do is to add <CODE>index.php</CODE> in <CODE>IfModule mod_dir.c</CODE> behind <CODE>DirectoryIndex</CODE>.  Apache will then look for <CODE>index.php</CODE> in the <CODE>DocumentRoot</CODE> and will display it as its main page.</P>
   </LI>
   <LI>
    <P>Create a MySQL database for your drupal site (if you haven't already):</P>
    <BLOCKQUOTE>$ mysqladmin create <I>&lt;database&gt;</I></BLOCKQUOTE>
    <P>Make sure to consult the MySQL documentation on how to setup the correct access rights and permissions in your MySQL grant tables.</P>
   </LI>
   <LI>
    <P>Once you have a proper database, dump the required tables into your database:</P>
    <BLOCKQUOTE>$ mysql -h <I>&lt;hostname&gt;</I> -u <I>&lt;username&gt;</I> -p<I>&lt;password&gt; &lt;database&gt;</I> < database/database.mysql</BLOCKQUOTE>
   </LI>
   <LI>
    <P>Rename the configuration file <CODE>includes/hostname.conf</CODE> to match your server's hostname:</P>
    <BLOCKQUOTE>$ cp includes/hostname.conf includes/www.yourdomain.com.conf</BLOCKQUOTE>
    <P><CODE>/</CODE>'s and <CODE>:</CODE>'s are translated to <CODE>.</CODE>'s.  So if the URI of your drupal site would be <CODE>http://www.yourdomain.com:80/foo/</CODE> your configuration file should be named <CODE>www.yourdomain.com.80.foo.conf</CODE>.</P>
   </LI>
   <LI>
    <P>Edit your configuration file to set the required settings such as the database options and to customize your site to your likings.</P>
   </LI>
   <LI>
    <P>Launch your browser and point it to http://yourdomain.com/, create an account, log in and head on to http://yourdomain.com/admin.php.  The first user will automatically have administrator permissions.  Play with it for a bit and spend some time getting used to the administration interfaces.</P>
   </LI>
   <LI>
    <P>Optionally (yet recommended for smooth operation) edit the <CODE>.htaccess</CODE> file and set the values of the PHP variables to your likings: <CODE>session.name</CODE>, <CODE>session.cookie_lifetime</CODE>, <CODE>session.gc_maxlifetime</CODE>, <CODE>session.cache_expire</CODE> and <CODE>session.save_path</CODE>.  Check your PHP reference manual for the exact purpose of each variable mentioned.</P>
   </LI>
   <LI>
    <P>Optionally (yet recommended for smooth operation) setup a crontab to periodically visit http://yourdomain.com/cron.php.</P>
    <P>Use a browser like lynx or wget but make sure the process terminates: either use /usr/bin/lynx -source http://yourdomain.com/cron.php or /usr/bin/wget -O /dev/null http://yourdomain.com/cron.php. Take a look at the example scripts in the <CODE>scripts</CODE>-directory and make sure to adjust them to your needs.</P>
    <P>A good crontab-line to run the cron-script once every hour would be:</P>
    <PRE>  00 * * * * /home/www/drupal/scripts/cron-lynx</PRE>
   </LI>
   <LI>
    <P>Optionally create your site's theme or at least customize the existing themes.  To get started, head on to the <CODE>themes</CODE>-directory and make a custom logo for each theme.</P>
   </LI>
   <LI>
    <P>Optionally add and remove modules to customize the functionality of your site.  Adding and removing modules is plain easy.  You can add a module by copying the files into the <CODE>modules</CODE>-directory and you can remove a module by removing a module's file from the <CODE>modules</CODE>-directory.  The drupal engine will then automatically include or exclude this module.  If for some reason, this seems to fail, "manually" rehash the modules list from http://yourdomain.com/admin.php?mod=module.</P>
   </LI>
   <LI>
    <P>If you get it to run, let us know at <A HREF="mailto:info@drop.org">info@drop.org</A> so we can add your site to our list of drupal sites.  If you can't get it to run, you can find support at the drupal site or you can contact us by e-mail at <A HREF="mailto:info@drop.org">info@drop.org</A>.</P>
   </LI>
  </OL>

  <H2>More then one drupal site on one machine</H2>

  <H3>Multiple directories</H3>

  <P>Drupal allows you to setup multiple drupal sites using different directories on top of one physical source tree.  This might be useful if you want to setup multiple sites about different topics (e.g. <CODE>http://yourdomain.com/travel/</CODE> and <CODE>http://yourdomain.com/sport/</CODE>) or if you want to provide users on your system with a personal drupal site (e.g. <CODE>http://yourdomain.com/~joe/</CODE> and <CODE>http://yourdomain.com/~john/</CODE>).  When using Unix/Linux as your host operating system, this can be best accomplished by using symbolic links:</P>
  <PRE>
   $ ls -l includes/*.conf
   -rw-rw-r--    1 drupal   drupal      includes/yourdomain.com.~joe.conf
  </PRE>
  <P>Once you created the configuration file, create a fake directory using symbolic links that matches the URI.  For a drupal site with URI <CODE>http://yourdomain.com/~joe/</CODE> use:</P>
  <BLOCKQUOTE>$ ln -s . ~joe</BLOCKQUOTE>
  <P>If you want Joe to be able to configure his own drupal site, create another symbolic link to make the configuration file <CODE>includes/yourdomain.com.~joe.conf</CODE> available to Joe in his home directory:</P>
  <BLOCKQUOTE>$ ln -s /path-to-drupal/includes/yourdomain.com.joe.conf /home/joe/</BLOCKQUOTE>

  <H3>More than one domain or vhost one machine</H3>

  <H4>Multiple domains using the same database</H4>

  <P>If you want to host multiple domains (or subdomains) on top of the same database (e.g. http://yourdomain.com/ and http://www.yourdomain.com/), simply use symbolic links to setup the required configuration files:</P>
  <BLOCKQUOTE>$ ln -s includes/yourdomain.com.conf includes/www.yourdomain.com.conf</BLOCKQUOTE>
  <PRE>
   $ ls -l includes/*.conf
   -rw-rw-r--    1 drupal   drupal      includes/yourdomain.com.conf
   lrwxrwxrrx    1 drupal   drupal      includes/www.yourdomain.com.conf -> includes/yourdomain.com.conf
  </PRE>

  <H4>Multiple domains or vhosts using different databases</H4>

  <P>Apache supports both IP- and name-based virtual hosts (vhosts).  While running more than one engine (by using vhosts) can be very useful for development and testing purpose, it might even be more interesting for hosting companies.  Therefor, we tried to support vhosts in the best possible way in order to make the life of any administrator easier.  We do so by making it possible to run an unlimited amount of vhosts on the same physical source tree, though by using different configuration files.  Moreover, you can setup multiple configuration files in your <CODE>includes</CODE>-directory.</P>
  <PRE>
   $ ls -l includes/*.conf
   -rw-rw-r--    1 drupal   drupal      includes/www.yourdomain1.com.conf
   -rw-rw-r--    1 drupal   drupal      includes/www.yourdomain2.com.conf
  </PRE>
  <P>The only thing left to be done is to setup the corresponding vhosts in your Apache configuration file.  Note that the <CODE>DocumentRoot</CODE> points to the same source tree twice:</P>
  <PRE>
   NameVirtualHost 127.0.0.1

   &lt;VirtualHost 127.0.0.1&gt;
     DocumentRoot /home/www/drupal
     ServerName www.yourdomain1.com
   &lt;/VirtualHost&gt;

   &lt;VirtualHost 127.0.0.1&gt;
     DocumentRoot /home/www/drupal
     ServerName www.yourdomain2.com
   &lt;/VirtualHost&gt;
  </PRE>

  <H1><A NAME="c3">Chapter 3: engine</A></H1>

  <P>While we in no way consider the design and implementation of the drupal engine to be finished, we feel that our own accompanying intensive experience has given us a fairly stable and well-proven design.  The following provides a brief over-view of the different aspects of drupal's core engine and features.</P>

  <H2>Cron</H2>

  <P>Cron (which stands for chronograph) is a periodic command scheduler: it executes commands at intervals specified in seconds.  It can be used to control the execution of daily, weekly and monthly jobs (or anything with a period of n seconds).   Automating tasks is one of the best ways to keep a system running smoothly, and if most of your administration does not require your direct involvement, cron is an ideal solution.</P>
  <P>Note that cron does not guarantee that the commands will be executed at the specified interval.  However, the engine will make sure that the commands are run at the specified intervals as closely as possible.</P>
  <P>Whenever <CODE>http://yourdomain.com/cron.php</CODE> is accessed, cron will run: it queries the database for the jobs cron controls, and their periods in seconds.  If a certain task wasn't executed in the last n seconds, where n is the period of that job, it will be executed.  It then records the date in the database so it can know when to run it again.  When all the executed commands terminate, cron is done.</P>
  <P>Cron is handy to run daily, weekly and monthly tasks that take care of various "housekeeping chores" such as database maintenance, recalculating settings, periodic mailings, scheduled backups and so on.</P>
  <P>The recommended way to setup drupal's cron system is to setup a Unix/Linux <CODE>crontab</CODE> that frequently visits <CODE>http://yourdomain.com/cron.php</CODE>: the more you visit <CODE>cron.php</CODE>, the more accurate cron will be.  If your hosting company does not allow you to setup <CODE>crontabs</CODE>, you can always ask someone else to setup a <CODE>crontab</CODE> for you.  After all, virtually any Unix/Linux machine with access to the internet can setup a <CODE>crontab</CODE> to frequently visit <CODE>http://yourdomain.com/cron.php</CODE> for you.<P>
  <P>For the <CODE>crontab</CODE> itself, use a browser like <CODE>lynx</CODE> or <CODE>wget</CODE> but make sure the process terminates: either use <CODE>/usr/bin/lynx -source http://yourdomain.com/cron.php</CODE> or <CODE>/usr/bin/wget -O /dev/null http://yourdomain.com/cron.php</CODE>.  Take a look at the example scripts in the <CODE>scripts</CODE>-directory and make sure to adjust them to your needs.</P>
  <P>A good <CODE>crontab</CODE>-line to run the <CODE>cron</CODE>-script once every hour would be:</P>
  <PRE>
    00 * * * * /home/www/drupal/scripts/cron-lynx
  </PRE>

  <H2>Database abstraction</H2>

  <P>The maintenance of all databases is handled by surprisingly simple code.  Access to to the database is done by facilities of drupal's database abstraction layer.  The purpose of drupal's database abstraction layer is to make it possible to run a drupal site on top of different databases like MySQL, Oracle, Postgres and so on.</P>
  <P>However, currently the only supported database is MySQL.  In fact, we haven't even bothered or tried to migrate to another database so our database abstraction layer might even contain undiscovered flaws.  Nevertless, moving to another database shouldn't be much of a problem.</P>
  <P>Take a look at <CODE>includes/database.inc</CODE> to see what database functions are supported.</P>

  <H2>Moderation, collaborative rating</H2>

  <P>We like to experiment with moderation, trust metrics and collaborative filtering.  Why?  To help individuals and communities address the challenges of information overload.</P>
  <P>As each new piece of information competes for attention, people quickly tend to become overwhelmed and seek assistance in identifying the most interesting, worthwhile, valuable or entertaining items.  Not to mention the fact that reader-contributed content and other levels of interactivity tend to become chaotic, bloated and disreputable.</P>
  <P>Therefor, we decided to develop a public system powered by a community that aims to bring quality content to everyone's attention and to filter out all junk: to <I>sort the wheat from the chaff</I>.  The output should be something clean and homogenized featuring quality content, and should slide down the gullet far more easily.</P>

  <H3>Open submission queue</H3>
  <P>Anyone who visits and has some news or some thoughts they'd like to share, can submit new content for consideration.  After someone has submitted something, their story is added to a queue.  All registered users can access this list of pending stories, that is, stories that have been submitted, but do not yet appear on the public front page. Those registered users can vote whether they think the story should be posted or not. When enough people vote to post a story, the story is pushed over the threshold and up it goes on the public page. On the other hand, when too many people voted to drop a story, the story will get trashed.</P>

  <H3>Comment rating</H3>

  <P>Anyone with a user account will be able to moderate comments.  This lets people assign a score to a comment on how good they think the comment is or how visible they think it should be.  When more than one person rates a comment, the overall rating is just a simple average of all ratings.  Comments with high ratings are more visible than comments with a lower rating.  That way, comments that gain the approval of participants will gradually move up through statistical effects and pointless comments will sink into oblivion.</P>
  <P>Hence, the purpose of comment moderation is two-fold:</P>
  <UL>
   <LI>To bring the really good comments to everyone's attention.</LI>
   <LI>To hide or get get rid of spam, flamebait and trolls.</LI>
  </UL>
  <P>In the latter, comment moderation provides a technical solution to a social problem.</P>

  <H2>Modules</H2>

  <P>When developing drupal it became clear that we wanted to have a system which is as modular as possible. A modular design will provide flexibility, adaptability, and continuity which in turn allows people to customize the site to their needs and likings.</P>
  <P>A drupal module is simply a file containing a set of routines written in PHP.  When used, the module code executes entirely within the context of the site.  Hence it can use all the functions and access all variables and structures of the main engine.  In fact, a module is not any different from a regular PHP file: it is more of a notion that automatically leads to good design principles and a good development model. Modularity better suits the open-source development model, because otherwise you can't easily have people working in parallel without risk of interference.</P>
  <P>The idea is to be able to run random code at given places in the engine.  This random code should then be able to do whatever needed to enhance the functionality.  The places where code can be executed are called "hooks" and are defined by a fixed interface.</P>
  <P>In places where hooks are made available, the engine calls each module's exported functions.  This is done by iterating through the <CODE>modules</CODE> directory where all modules must reside.  Say your module is named <CODE>foo</CODE> (i.e. <CODE>modules/foo.module</CODE>) and if there was a hook called <CODE>bar</CODE>, the engine will call <CODE>foo_bar()</CODE> if this was exported by your module.</P>
  <P>Each module has to declare an associative array named <CODE>$module</CODE> that serves as the list of hooks that a module wants to export or carry out.  Each entry in the array contains the name of a hook followed by the name of the exported function.</P>
  <P>In our above example, our associative array <CODE>$module</CODE> would look like:</P>
  <PRE>
    $module = array("bar" => "foo_bar");
  </PRE>
  <TABLE BORDER="1">
   <TR>
    <TH>Hook name</TH>
    <TH>Hook description</TH>
   </TR>
   <TR>
    <TD VALIGN="top"><CODE>admin</CODE></TD>
    <TD VALIGN="top">If a module requires a spot in the administrator section it should implement <CODE>module_admin</CODE>.  The engine will automatically add a link to the administration menus and will call <CODE>module_admin</CODE> when this link is followed.  In order to make virtually any module maintainer's life easier, you don't have to worry about access rights or permissions for that matter.  The engine will only allow privileged users to call exported <CODE>admin</CODE> functions.</TD>
   </TR>
   <TR>
    <TD VALIGN="top"><CODE>block</CODE></TD>
    <TD VALIGN="top">Any module can export a block to be displayed by making the block function return an associative array of blocks.  Each block in the array requires a "subject", "content", "info" and "link" field.</TD>
   </TR>
   <TR>
    <TD VALIGN="top"><CODE>cron</CODE></TD>
    <TD VALIGN="top">Modules that require to schedule some commands to be executed on regular intervals can implement the <CODE>cron</CODE> interface: the engine will then call <CODE>module_cron</CODE> at the appropriate intervals defined by the administrator.  This interface is particularly handy to implement timers or to automate certain tasks like for instance database maintenance, recalculation of settings or parameters, automatic mailings and so on.</TD>
   </TR>
   <TR>
    <TD VALIGN="top"><CODE>help<CODE></TD>
    <TD VALIGN="top">By implementing the help hook, a module can make documentation available to the engine or to other modules.</TD>
   </TR>
   <TR>
    <TD VALIGN="top"><CODE>export</CODE></TD>
    <TD VALIGN="top">The export hook allows a module to export data and to function as a XML/RDF/RSS backend.  All you have to do in your export function is examine the array of strings containing the URI and figure out where you're at.  This hook is typically used to export news headlines, but can be used to export virtually anything ranging from diary entries, reviews, rapports to entire discussions.</TD>
   </TR>
   <TR>
    <TD VALIGN="top"><CODE>page</CODE></TD>
    <TD VALIGN="top">If a module requires its own page it should provide a function named <CODE>module_page</CODE>.  The page can then be publicly accessed via <CODE>http://yourdomain.com/module.php?mod=module</CODE> which will cause the engine to invoke <CODE>module_page</CODE> in order to generate the module's page.</TD>
   </TR>
   <TR>
    <TD VALIGN="top"><CODE>user</CODE></TD>
    <TD VALIGN="top">If a module requires to extend any of the setting pages available to individual users, it should implement the user hook.  The function takes 3 parameters, resp.: <CODE>$username</CODE>, <CODE>$section</CODE> ("user", "site", "content") and <CODE>$operation</CODE> ("edit", "view", "save").</TD>
   </TR>
  </TABLE>
  <P>Even though we aim towards modularity, a basic rule is to avoid defined interfaces.  We are exceptionally careful when it comes down to adding hooks because once you give a hook to developers they will start coding to it and once somebody's using it, you are stuck with it.</P>

  <H2>Theme system</H2>

  <P>Drupal's theme system is simple, elegant, flexible and powerful.  You can accommodate rather major changes in overall appearance and significant structural changes.  Moreover, you control all aspects of your drupal site in terms of colors, mark-up, layout and even the position of most blocks (or boxes).  You can leave blocks out, move them from right to left, up and down until it fits your needs.</P>
  <P>In order to accomplish this, drupal uses a theme class that has a handful of functions. The drupal engine dynamically loads the correct theme class, instantiates it and then calls this class' functions where appropriate.</P>
  <P>Let's illustrate this with an easy example. Say, to generate the main page, the drupal engine would use something like:</P>
  <PRE>
   $theme = new Theme();
   $theme->header();
     // displays the header of a page
   for each $article to be displayed {
     $theme->story($story);
       // displays a themed article or story
   }
   $theme->footer();
     // displays the footer of a page
  </PRE>
  <P>We have similar functions for things like comments (i.e. <CODE>$theme->comment($comment)</CODE>), generic boxes (i.e. <CODE>$theme->box($topic, $body)</CODE>) and so on.  To create your own theme, you simply need to provide a new implementation of these functions.</P>
  <P>This simple and straight-forward approach has proven to be both flexible and fast.  If you want to learn more about the theme system, we recommend you look at the code of the existing themes.  It is pretty straight-forward and doesn't require any further in-depth knowledge about the engine itself.</P>

  <H2>User management</H2>

  <P>Drupal's user management system is capable of handling registrations, confirmation e-mails, account updates, authentication, access rights and user-based permissions among various other things.</P>
  <P>No participant can use his own name or handle to post comments until they sign up and submit their e-mail address.  Those who do not may participate as anonymous users, but they will suffer numerous disadvantages, for example their posts beginning at a lower score.</P>
  <P>In contrast, those with a user account can use their own name or handle and are granted various privileges: the most important are probably the ability to moderate new submissions, to rate comments and to fine-tune the site to their personal liking.</P>
  <P>Registered users need to authenticate by supplying a username and password.  The username and password are kept in your database, where the password is hashed so that no one can read nor use it.  When a username and password needs to be checked the system goes down the list of registered users till it finds a matching username, and then hashes the password that was supplied and compares it to the listed value.  If they match then that means the username and password supplied were correct.</P>
  <P>Once a user authenticated a session is started and until that session is over they won't have to re-authenticate.  To keep track of the individual sessions, drupal relies on PHP's session support.  A visitor accessing your web site is assigned an unique ID, the so-called session ID, which is stored in a cookie.  For security's sake, the cookie does not contain personal information but acts as a key to retrieve the information stored on your server's side.  When a visitor accesses your site, drupal will check whether a specific session ID has been sent with the request.  If this is the case, the prior saved environment is recreated.</P>
  <P>Drupal allows you to control who is allowed to get authenticated and who is not.  To accomplish this, you can ban certain hostnames, IPs, IP-ranges, e-mail address and usernames.  Any user that matches any of the given ban criteria will not be able to authenticate or to register as a new user.</P>
  <P>Authenticated users can themselves select entirely different appearances for the site, utilizing their own preferences for how the pages are structured, how navigation lists and other page components are presented and much more.</P>
  <P>An important feature of drupal is that any user can be granted administrator rights.  The ability to share maintenance responsibility with volunteers from across the globe can be considered valuable for most community-based projects.</P>

  <H1><A NAME="c4">Chapter 4: modules</A></H1>

  <?php
   module_iterate("documentation_module");
  ?>

  <H1><A NAME="c5">Chapter 5: development</A></H1>

  <P>The drupal engine is open source.  It is possible for each and every user to become a contributor.  The fact remains that most drupal users, even those skilled in programming arts, have never contributed to the code even though most of us had days where we thought to ourselves: "I wish drupal could do this or that ...".  Through this page, we hope to make drupal programming more accessible to at least a small percentage of people.</P>
  <P>We use diff and patch for content control even though we distribute our code via CVS.  Why?  Because diff and patch provide an immense amount of control.  Patches can be submitted via e-mail and in plain text; maintainers can read and judge the patch before it ever gets near a tree.  It allows maintainers to look at changes easily without blindly integrating them.</P>

  <H2>CVS</H2>

  <H3>Introduction</H3>

  <P>CVS is a tool to manage software revisions and release control in a multi-developer, multi-directory, multi-group environment.  It comes in very handy to maintain local modifications.</P>
  <P>Thus, CVS helps you if you are part of a group of people working on the same project.  In large software development projects, it's usually necessary for more then one software developer to be modifying modules of the code at the same time.  Without CVS, it is all too easy to overwrite each others' changes unless you are extremely careful.</P>
  <P>In addition, CVS helps to keep track of all changes.  Therefor, the CVS server has been setup to mail all CVS commits to all maintainers.  Thus, it does not require any effort to inform the other people about the work you have done, and by reading the mails everyone is kept up to date.</P>

  <H3>Linux</H3>

  <P>To gain access via (anonymous) CVS use the following steps. In this example it is assumed that you want a copy of the drupal source code.</P>
  <P>1. Install a recent copy of CVS. All you really need is a copy of the CVS client binary. Alternatively you can download the latest CVS source code from <A HREF="http://www.cyclic.com">Cyclic Software</A>.  Don't worry: CVS is free .</P>
  <P>2. Set CVSROOT in your environment:</P>
  <BLOCKQUOTE>$ export CVSROOT=":pserver:anonymous@drop.org:/home/dries/cvs"</BLOCKQUOTE>
  <P>3. Login by running the command:</P>
  <BLOCKQUOTE>$ cvs login</BLOCKQUOTE>
  <P>The required password is 'anonymous' (without the quotes).</P>
  <P>4. To check out the latest drupal sources, run the command:</P>
  <BLOCKQUOTE>$ cvs co drupal</BLOCKQUOTE>
  <P>This will create a directory called <CODE>drupal</CODE> containing the latest drupal source tree.  For the other source code repositories on this system just substitute the correct package name.</P>
  <P>5. Whenever you want to merge in the latest code changes, use the following command from within the <CODE>drupal</CODE> directory:</P>
  <BLOCKQUOTE>$ cvs ci file1 file2 file3</BLOCKQUOTE>
  <P>6. To add binary files like GIFs you have to use:</P>
  <BLOCKQUOTE>$ cvs add <B>-kb</B> file1 file2 file3</BLOCKQUOTE>
  <P>If a binary file accidentically gets added without `-kb', one can use the <I>cvs admin</I> command to recover.  For example:</P>
  <BLOCKQUOTE>$ cvs admin -kb file1 file2 file3<BR>cvs commit file1 file2 file3</BLOCKQUOTE>
  <P>After you did, make sure to check out a fresh copy of the files (if they were broken):</P>
  <BLOCKQUOTE>$ cvs update -A file1 file2 file3</BLOCKQUOTE>

  <H3>Windows</H3>

  <P>A graphical CVS client is available for MS Windows and for Macs.  You can download the latest version from <A HREF="http://www.wincvs.org">http://www.wincvs.org/</A>.</P>
  <P>If you can want to interface the CVS repository just like Linux users do (raw and uncut), then check <A HREF="http://oodt.jpl.nasa.gov/doc/developers-resources/developing/windows/index.html">this site</A>.</P>

  <H3>Additional references</H3>

  <UL>
   <LI><A HREF="http://cvsbook.red-bean.com/">CVS book</A></LI>
   <LI><A HREF="http://www.loria.fr/~molli/cvs/doc/cvs_toc.html">CVS docs</A></LI>
   <LI><A HREF="http://cellworks.washington.edu/pub/docs/cvs/cvs-FAQ/">CVS FAQ</A></LI>
  </UL>

  <H2>Diff and patch</H2>

  <P>Diff is the first command in the set.  It has the simple purpose to create a file called a <I>patch</I> or a <I>diff</I> which contains the differences between two text files or two groups of text files.  diff can write into different formats, although the unified difference format is preferred.  The patches this command generates are much easier to distribute and allow maintainers to see quickly and easily what changed and to make a judgment.</P>
  <P>Patch is diff's complement and takes a patch file generated by diff and applies it against a file or a group of files.</P>
  <P>The actual usage of diff and patch is not complicated.</P>
  <P>At its simplest, a diff command for comparing two files would be:</P>
  <BLOCKQUOTE>$ diff old.txt new.txt > oldnew.patch</BLOCKQUOTE>
  <P>For drupal, we prefer patches in unified format, so we add -u to the command line:</P>
  <BLOCKQUOTE>$ diff -u old.txt new.txt > oldnew.patch</BLOCKQUOTE>
  <P>Generally, however, a comparison of two source trees is often desired.  A possible command to do so is:</P>
  <BLOCKQUOTE>$ diff -ruN old new > oldnew.patch</BLOCKQUOTE>
  <P>Once a patch is generated, the process of patching the file is even simpler.  Based on our examples above, we could do:</P>
  <BLOCKQUOTE>$ patch < oldnew.patch</BLOCKQUOTE>

  <H2>Creating and sending your patches</H2>

  <P>For a person or company who wishes to submit a change, the process can sometimes be daunting if you're not familiar with "the system".  This text is a collection of suggestions which can greatly increase the chances of your change being accepted.</P>
  <P>1. <B>Coding style:</B><BR>If your code deviates too much from the "standard" coding style, it is more likely to be rejected without further review and without comment.</P>
  <P>2. <B>"diff -u":</B><BR>Use "diff -u" or "diff -urN" to create patches: when creating your patch, make sure to create it in "unified diff" format, as supplied by the '-u' argument to diff.  Patches should be based in the root source directory, not in any lower subdirectory.  Make sure to create patches against a "vanilla", or unmodified source tree.</P>
  <P>3. <B>Describe your changes:</B><BR>Describe the technical detail of the change(s) your patch includes and try to be as specific as possible.  Note that we prefer technical reasoning above marketing: give us clear reasons why "this way" is good.  Justify your changes and try to carry enough weight.  It is important to note the version to which this patch applies.</P>
  <P>4. <B>Separate your changes:</B><BR>Separate each logical change into its own patch.  For example, if your changes include both bug fixes and performance enhancements, separate those changes into two or more patches.  If your changes include an API update, and a new module which  uses that new API, separate those into two patches.</P>
  <P>5. <B>Mail or submit the patch:</B><BR>Remember: no MIME, no HTML mail, no links, no compression, no attachments.  Just plain text.</P>
 <?php
 }
?>