What's New

Major upgrades to Campsite are noted by changing the second digit of the version number.  Minor bug fix releases are indicated by changing the third digit (e.g. Major release: 3.3 -> 3.4, minor release: 3.4.1 -> 3.4.2).

Coming soon in version 3.5:

What's new in version 3.4 "Luca":

What's new in version 3.3 "Speedy":

What's new in version 3.2 "David":

What's new in version 3.1 "Tomás":

What's new in version 3.0 "Filip":

Feature List

This list of features is provided as a guide to help you decide if Campsite is the right content management system for your publication.

Languages

The Campsite administration interface has been translated into the following languages (in alphabetical order):

  1. Arabic
  2. Belarusian
  3. Chinese (Simplified)
  4. Chinese (Traditional)
  5. Croatian
  6. Czech
  7. Dutch
  8. English
  9. French
  10. Georgian
  11. German
  12. Korean
  13. Polish
  14. Portuguese
  15. Romanian
  16. Russian
  17. Serbian (Cyrillic)
  18. Serbo-Croatian (Latin)
  19. Spanish
  20. Swedish

Further translations can be added using a tool built into Campsite called the "Localizer".

Content Features

  1. Multi-lingual content: all of the content that you create in Campsite can be translated:

Requirements and Dependencies

In this chapter:

To install the Campsite server, you need to have shell or ftp access to a Linux, FreeBSD or Unix system. Campsite 3.2 is known to work on the following Linux distributions: Ubuntu, Fedora, Mandriva, Debian.


Before installing Campsite, make sure you have the following applications up and running:

1. Apache web server -- your http daemon, serving your web site to the world (http://www.apache.org). You will need version 2.0.x or newer.

For installation instructions, see the Apache web site. Installing Apache will generate the httpd.conf file referred to further down. This file contains all relevant information for Apache to handle the content on your Linux server. The adjustments described below need to be made in order to tell Apache about the procedures for Campsite files and templates.

2. MySQL Database Server - this application handles the Campsite database. You will need MySQL 5.0 or newer.

Two components of MySQL are needed for Campsite:
 * the server
 * client programs

All of those can be found on the MySQL website (http://www.mysql.com).

3. PHP 5.0 or newer - This is needed for Campsite administration interface. PHP is a module for the Apache web server. The followind PHP modules must be installed:

        * php-cli - Command Line Interface module
        * php-mysql - functions for accessing the MySQL database server
        * php-gd - provides a module for handling graphics directly from the PHP scripts

4. Imagemagick - needed for creating thumbnails of images

 

Debian Dependencies

To install and configure all needed Debian 3.1 libraries run the following command at your command prompt:
apt-get install libdbd-mysql-perl mysql-client mysql-common
  mysql-server php5-mysql php5-cli php5-gd imagemagick


Ubuntu Dependencies

To install and configure all needed Ubuntu libraries run the following command at your command prompt (by copying and pasting it into your terminal):

sudo apt-get install build-essential php5-cli php5-mysql
  apache2 libapache2-mod-php5 php5 mysql-server
  imagemagick php5-gd

The file in php.ini may need to be reconfigured for the extensions mysql.so and gd.so. To do this open up the file /etc/php5/apache2/php.ini and find the lines:

extension=mysql.so
extension=gd.so

If these two lines are commented out (ie proceded by semicolons), uncomment them by removing the semicolons.

Installation Steps

In this chapter:

Here is what you need to do to install Campsite:

  1. Configure apache: create an apache virtual host (optional)
  2. Setup your php.ini file
  3. Copy the Campsite package to a directory on your server.
  4. Unarchive it using the command: tar xzvf <Campsite_source>.
  5. Enter Campsite directory:  "cd campsite".
  6. Copy the content of implementation/site directory into the document root directory of the apache virtual host.
  7. Start a browser, point it to the httpSiteName.PNG URL and follow the steps.

Downloading Campsite

The easiest way to download Campsite is to go to our Sourceforge page and download the files direct from there.

Configuring Apache

Create an apache virtual host or use the default apache virtual host. You may skip this step if you wanted to use the apache default host (localhost). Campsite does not work in subdirectories. So you can not work with a local URL like http://localhost/campsite/ - if this is what you want to do, read the hosts part beyond the apache configuration.

Example of virtual host configuration:

<VirtualHost *>
    DocumentRoot /var/www/campsite

    ServerName [site_name]
    ServerAlias [site_alias]
    DirectoryIndex index.php index.html
    <Directory /var/www/campsite>
            Options -Indexes FollowSymLinks MultiViews
            AllowOverride All
            <IfModule mod_access>
                Order allow,deny
                Allow from all
            </IfModule>
    </Directory>
</VirtualHost>

After you create a virtual host do not forget to restart apache.

Enabling the rewrite module under Ubuntu

If you are working on Ubuntu, trying to add the RewriteModule into the apache configuration might create the following error:

Invalid command 'RewriteEngine', perhaps misspelled or defined by a module not included in the server configuration

In which case you need to enable mod_rewrite. Do this by opening a terminal and type:

sudo a2enmod rewrite

You will see in the terminal: Enabling module rewrite. Run '/etc/init.d/apache2 restart' to activate new configuration!

Working on localhost: changing hosts file

If you installed campsite locally, e.g. http://localhost/campsite/, you need to change the hosts file ( sudo vim /etc/hosts ) and duplicate the line which says localhost, adding your [site_name] from the apache conf (see above) there. If you used "campsite" as the [site_name], your hosts file might start like this (Ubuntu 9.10 example):

127.0.0.1       localhost
127.0.0.1       campsite
# The following lines are desirable for IPv6 capable hosts

 Now you can point your browser to http://campsite

Setup your php.ini file

You will need to adjust values in your php.ini file in order for Campsite to work properly. ⁞ On Debian and Ubuntu systems, your "php.ini" file is usually located in "/etc/php5/apache2" directory.

The following directives show what the values should be for each variable in the php.ini file.

Always turn off register_globals because it's a big security hole:
register_globals = Off

Find the "memory_limit" directive and set the amount of memory to at least 32MB:
memory_limit = 32M   

Set maximum size of POST data that PHP will accept to a hig value:
post_max_size = 100M 

Turn off magic quotes:
magic_quotes_gpc = Off

Allow HTTP file uploads:
file_uploads = On

Set the maximum allowed size for uploaded files to a large value so you will be able to upload large attachments:
upload_max_filesize = 100M

Make sure the following extensions are enabled (they are enabled as long the line appears in the php.ini file, and the line does not start with a semi-colon (';')):
extension=gd.so
extension=mysqli.so
extension=mysql.so

 

Upgrading

In this section:

Upgrading from versions 1.x, 2.0.x, 2.1.x, 2.2.x, 2.3.x, 2.4.x and
2.5.x is not supported anymore. You will have to upgrade first to
Campsite 2.6 or 2.7 and then follow the regular procedure.

Upgrading from Campsite 2.6.x and 2.7.x versions:
Repeat the following steps for each instance:

  1. Backup the instance using campsite-backup-instance
  2. Perform a new Campsite 3.3 install
  3. Run the restore backup script from the admin interface

Read INSTALL file and follow the steps; read on Compatibility issues.

Upgrading from Campsite 3.0.x, 3.1.x and 3.2.x:

Drop the new sources over the existing install, open a browser
and make a request for the publication home page: site_1a.png
The upgrade will be performed automatically when you make the first
request to the publication site or to the Campsite admin interface.

 

Compatibility Issues

Since version 3.0 Campsite doesn't support multiple instances anymore. You will have to perform one install for each Campsite instance. However, the install procedure was greatly simplified.

In version 3.0 the template language as modified extensively. The backup restore script will provide an automated conversion of the old template files to the new format. For more details on language changes please read the chapter "Template Language Version 3.0".

The 3.3 template language is fully backward compatible with versions 3.2, 3.1 and 3.0. The 3.3 version only brings additions to the language.

 

Advanced/non-standard installation

In this section:

 

Installing Campsite under Plesk

To install Campsite under the Plesk control panel, follow the instructions in this wiki:

http://wiki.sourcefabric.org/display/CS/Install+Campsite+Under+Plesk


Configuring Campsite to Work Over SSL

This article will explain how to configure apache over an encrypted SSL connection.

  1. Allocate a separate IP address for each Campsite installation you want to run over SSL. You will have to set this IP address to one of your server network interfaces. We don't provide detailed information about network interface configuration process here because it's outside the scope of Campsite. Read 'ifconfig' manual page for more details, search for configuring network interfaces on linux on Google or try this link: http://www.faqs.org/docs/linux_network/x-087-2-iface.html. We will refer to this IP address as [my_IP_address] in the following steps.

  2. Locate the Listen directive in the main apache configuration file and add the following new lines after it if they did not exist already:

    Listen 80

    Listen 443

  3. Locate the NameVirtualHost directive in the main apache configuration file and add the following new lines after it:

    NameVirtualHost [my_IP_address]:80

    NameVirtualHost [my_IP_address]:443

    In case there are duplicate NameVirtualHost directives remove the duplicates.

  4. Generate certificate and key for the SSL virtual host. We don't provide detailed information about this process here because it's outside the scope of Campsite. Read http://httpd.apache.org/docs/2.0/ssl/ssl_faq.html for details. If your apache has SSL module loaded you can skip to: About Configuration and About Certificates. This step will generate at least two files: certificate file, referred here as [certificate_file] and certificate key file, referred here as [certificate_key_file]. Install these two files into your apache certificates directory, referred here as [certificates_directory].

  5. Edit the Campsite virtual host file.

  6. Duplicate the virtual host definition in this file: copy the whole section in between <VirtualHost [...]> and </VirtualHost>, including these tags and paste it at the end of the file.

  7. Edit the first virtual host definition and replace the existing <VirtualHost [...]> tag with:

    <VirtualHost [my_IP_addresss]:80>

  8. Edit the second virtual host definition and replace the existing <VirtualHost [...]> tag with:

    <VirtualHost [my_IP_address]:443>

  9. Edit the second virtual host definition and add the following lines into your virtual host definition:

    SSLEngine on

    SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP

    SSLCertificateFile [certificates_directory]/[certificate_file]

    SSLCertificateKeyFile [certificates_directory]/[certificate_key_file]

Note: When generating the SSL certificate at step 4 make sure you enter the FQDN ("Fully Qualified Domain Name") of the server when OpenSSL prompts you for the "CommonName", i.e. when you generate a CSR for a website which will be later accessed via foodom.png enter "www.foo.dom" here. The FQDN you supply as CommonName must be the same as the value of ServerName in the Campsite instance virtual host.

The following is an example of a fully configured Campsite instance:

- main apache configuration file:

Listen 80
Listen 443
NameVirtualHost 192.168.2.101:80
NameVirtualHost 192.168.2.101:443

- Campsite instance virtual host configuration file:

<VirtualHost 192.168.2.101:80>
        DocumentRoot /var/www/campsite
        ServerName www.mydomain.org
        DirectoryIndex index.php index.html

        <Directory /var/www/campsite>
                Options -Indexes FollowSymLinks MultiView
                AllowOverride All
                <IfModule mod_access>
                        Order allow,deny
                        Allow from all
                </IfModule>
        </Directory>
</VirtualHost>
<VirtualHost 192.168.2.101:443>
        DocumentRoot /var/www/campsite
        ServerName www.mydomain.org
        DirectoryIndex index.php index.html

        <Directory /var/www/campsite>
                Options -Indexes FollowSymLinks MultiViews
                AllowOverride All
                <IfModule mod_access>
                        Order allow,deny
                        Allow from all
                </IfModule>
        </Directory>

        SSLEngine on
        SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP
        SSLCertificateFile /etc/apache2/ssl/server.crt
        SSLCertificateKeyFile /etc/apache2/ssl/server.pem
</VirtualHost>

 

Troubleshooting

In this section you can search for issues or bugs we know about in order to find out how to fix them.

Error creating users: "The user account could not be created"

Since version 2.7 Campsite uses the LiveUser authentication/authorization toolkit. Unfortunately this toolkit has some bugs that may leave the database in an inconsistent state, which will result in the error message "The user account could not be created" being displayed when trying to create a new user. In order to fix the database corruption run the following SQL script against the Campsite database:

DELETE FROM pu
    USING phorum_users AS pu
        LEFT JOIN liveuser_users AS lu ON pu.fk_campsite_user_id = lu.Id
    WHERE lu.Id IS NULL;
DELETE FROM lur
    USING liveuser_userrights AS lur
        LEFT JOIN liveuser_users AS lu ON lur.perm_user_id = lu.Id
    WHERE lu.Id IS NULL;
DELETE FROM lpu
    USING liveuser_perm_users AS lpu
        LEFT JOIN liveuser_users AS lu ON lpu.perm_user_id = lu.Id
    WHERE lu.Id IS NULL;
UPDATE liveuser_users_auth_user_id_seq
  SET id = (SELECT MAX(Id) FROM liveuser_users);
UPDATE liveuser_perm_users_perm_user_id_seq
    SET id = (SELECT MAX(perm_user_id) FROM liveuser_perm_users);

 

"Unable to create the database [db_name]" error message when installing Campsite

Please create a PHP script with the following script, run it and check the error messages:
<?php $dbName = 'my_test'; $dbConn = mysql_connect("localhost", "root", ""); if (!$dbConn) {     echo "Can not connect to MySQL with root user and no password.\n";     echo "ERROR: " . mysql_error($dbConn) . "\n";     exit(1); } $res = mysql_query("CREATE DATABASE `$dbName` CHARACTER SET utf8 COLLATE utf8_bin"); if (!$res) {     echo "Can not create a database. Please verify if you had the privilege "        . "to create a database.\n";     echo "ERROR: " . mysql_error($dbConn) . "\n";     exit(1); } echo "Created database '$dbName'.\n"; ?>

Please make sure you have MySQL 5.0 or newer running, Campsite does not work on older versions.

Another reason could be that the root user may not have the privilege to create a database if connected through a TCP/IP socket. I know it sounds weird but I know a user of Campsite encountered this problem.

Write rights for the apache user

If you get an error like this, you need to change the access rights:

Notice: Campsite error: unable to write to $compile_dir '/var/www/campsite/templates_c'. Be sure $compile_dir is writable by the web server user. in /var/www/campsite/install/classes/CampTemplate.php on line 89

The installer

sets this up automatically in most cases, but in some cases, you will need that the apache user needs write permissions for the following Campsite folders:

  • document root (e.g. /var/vhosts/httpdocs)
  • backup (/path/to/document_root/backup)
  • conf (/path/to/document_root/conf)
  • files (/path/to/document_root/files)
  • images (/path/to/document_root/images)
  • plugins (/path/to/document_root/plugins)
  • templates (/path/to/document_root/templates)
  • template_cache (/path/to/document_root/templates_cache)

 

Backup & Restore

In this chapter:

Backup & Restore in the admin interface

In Campsite Version 3.4 and newer, backup and restore can be managed through the admin interface. A backup contains the database, templates, images, attached files and configuration files.

Select "Backup/Restore" under the pulldown menu "Actions". You will see a page similar to this:

 

campsite_3.4_backuprestore 

You have the possibility to:

#!/usr/bin/php

Campsite Backup Utility
-----------------------
Backup script version: 3.4.0
Backing up campsite
 * Backing up the database...done.
 * Backing up the templates...done.
 * Backing up images...done.
 * Backing up file attachments...done.
 * Backing up configuration files...done.
 * Creating tarball...done.
 * Cleaning up...done.

Backup saved to file:
  /var/www/campsite/backup/backup-campsite-2010-07-14-12-51-43.tar.gz

Creating a backup archive via shell

For backup purposes you can create archives using the following command:
    [campsite_directory]/bin/campsite-backup [--silent] [--default_dir]

The optional arguments are:

The archive file name is backup-campsite-[date_time].tar.gz and contains the whole instance: the database, templates, images, attached files and configuration files.

Restoring a backup archive via shell

Backup archives can be restored by using the "campsite-restore" command. Everything in the instance will be restored from the archive as it was when the backup was created. Changes made since the backup will be lost.

This script will replace existing data installation with that in the backup file. You must run this script from a directory that you have write access to because this script needs to create a temporary directory. Note that your backup database and files will automatically be upgraded if they are older than the currently installed version of Campsite.

Note: For multiple installations of Campsite on a single server, you must run this script from the installation directory where you want to restore the data. For example, if you have installed Campsite in two locations: /var/www/cs1 and /var/www/cs2, and you want to restore the data for the 'foo' installation, you must run /var/www/cs1/bin/campsite-restore, and NOT /var/www/cs2/bin/campsite-restore.

Parameters:

versions 3.0 to 3.3: <backup_file>

versions 3.4 and newer: -b <backup_file>
        Specifies the tarball created by the 'campsite-backup' script. Give the full or relative path to the file.

    [-t <destination_database_name>]
        If this is specified, the script will use the database name specified instead of the one specified in the backup file. This is useful for site-to-site transfer of a website, that is, moving your website from one server to another.

    [-e]
        Use the existing configuration files instead of the ones in the backup file. In other words, the existing config files in the current installation will not be replaced.

    [-f]
        Dont prompt, assume 'yes' to questions.

    [-c <charset>]
        Convert the database data from <charset> to UTF-8.

    [-s]
        Convert the database data from the database server character set
        to UTF-8.

    [-l]
        List all available charsets and exit.



Installing the Demo Templates

We provide a few demo sites to get you started: download them here.

You can find more detailed information on the sample templates for our demo publication "The Custodian" here.

Restore the demo package using the campsite-restore command. For more details read "Restoring a backup archive" in Backup chapter. All demo packages have the following default account: "admin", with password "admn00".

Do not forget to add your site alias to the publication defined in the demo package: Content/Publication menu in the admin interface. For more details read the chapter "Creating a Publication".

Installing on Ubuntu

Installing Campsite on Ubuntu is fairly easy, provided you follow the right steps. Here is what you need to do to install Campsite on Ubuntu 9.10 "Karmic Koala:"

Configure Apache: create an Apache virtual host (optional)

In this case, there are other web apps on the install, so we will put the Campsite install directory in /var/www/localcampsite.

cd /var/www/

and

mkdir localcampsite

The first step was to remove the existing localhost symbolic link which comes pre-installed with Apache:

sudo rm /etc/apache2/sites-enabled/000-default

Set up the virtual host in apache so that it knows to look in our /localcampsite directory by creating a file named localcampsite in /etc/apache2/sites-available:

cd /etc/apache2/sites-available

 and then:

sudo gedit localcampsite

Copy and paste this text into the document (if you're using nano you can paste by using the right click):

NameVirtualHost localhost
<VirtualHost localhost>
     DocumentRoot /var/www/localcampsite
#"localcampsite" can be whatever you want to name your directory
     ServerName localcampsite
#   ServerAlias [site_alias]
     DirectoryIndex index.php index.html
  <Directory /var/www/localcampsite>
     Options -Indexes FollowSymLinks MultiViews
     AllowOverride All
     <IfModule mod_access>
     Order allow,deny
     Allow from all
     </IfModule>
  </Directory>
</VirtualHost>
  

Save and close.

We need to create a symbolic link between sites available and sites enabled:

sudo ln -s /etc/apache2/sites-available/localcampsite /etc/apache2/sites-enabled/

Whenever  you make changes to Apache, you have to restart it:

sudo /etc/init.d/apache2 restart

Setup your php.ini file

You will need to adjust values in your php.ini file in order for Campsite to work properly. On Debian and Ubuntu systems, your "php.ini" file is usually located in "/etc/php5/apache2" directory.

cd /etc/php5/apache2

and then

sudo gedit php.ini

The php.ini file has a lot of different settings. You can use your text editor's "find" function to jump directly to each of these. The following directives show what the values should be for each variable in the php.ini file.

Always turn off register_globals because it's a big security hole:
register_globals = Off

Find the "memory_limit" directive and set the amount of memory to at least 32MB:
memory_limit = 32M   

Set maximum size of POST data that PHP will accept to a hig value:
post_max_size = 100M 

Turn off magic quotes:
magic_quotes_gpc = Off

Allow HTTP file uploads:
file_uploads = On

Set the maximum allowed size for uploaded files to a large value so you will be able to upload large attachments:
upload_max_filesize = 100M

Make sure the following extensions are enabled (they are enabled as long the line appears in the php.ini file, and the line does not start with a semi-colon (';')):
extension=gd.so
extension=mysqli.so
extension=mysql.so

Downloading Campsite

The easiest way to download Campsite for free is to go to our Sourceforge page and download the files direct from there. Although there are Debian packages available, in this case it's just as easy to use the source files.

Once they're downloaded, unarchive the file using this command:

tar xzvf /path/to/your/downloaded/file/<Campsite_source>

 This will create a directory called "campsite." Enter that directory:

cd campsite

6. Copy the content of implementation/site directory into the document root directory of the apache virtual host:

sudo cp -a <path to local campsite/implementatation/site> /var/www/localcampsite

Note that your command cannot have a trailing slash. It's ok to have "localcampsite" instead of having these files in the www root directory. But because we do, we have an additional step of setting up the virtual host.

Change the ownership of everything in the campsite directory file to be www-data:

cd /var/www/localcampsite

and then:

chown -R www-data *

Start a browser, point it to the http://localhost URL and follow the steps in the web page, and you're done!

Installing Campsite from Debian packages

If you want to install Campsite from the .deb packages, download them from:

http://sourceforge.net/projects/campsite/

Here is a little section on trouble shooting, if you experience any problems after the installation:

1. On your local machine: http://campsite/ in the browser doesn't work at all

As "root" create the file: /etc/apache2/sites-available/campsite

with the following content:

<VirtualHost *:80>
    DocumentRoot /var/www/campsite
    ServerName campsite
#    ServerAlias campsite
    DirectoryIndex index.php index.html
    <Directory /var/www/campsite>
            Options -Indexes FollowSymLinks MultiViews
            AllowOverride All
            <IfModule mod_access>
                Order allow,deny
                Allow from all
            </IfModule>
    </Directory>
</VirtualHost>

Open as "root": /etc/hosts

and add the line:

127.0.0.1       campsite

Restart apache:

sudo /etc/init.d/apache2 restart

Empty your browser cache and point your browser again to http://campsite/

2. Pointing your browser to http://campsite/ for installation throws the errors:

Warning: require_once(/var/www/campsite/conf/install_conf.php) [function.require-once]: failed to open stream:
Permission denied in /var/www/campsite/install/classes/CampInstallationBase.php on line 18
Fatal error: require_once() [function.require]: Failed opening required '/var/www/campsite/conf/install_conf.php'
(include_path='.:/usr/share/php:/usr/share/pear') in /var/www/campsite/install/classes/CampInstallationBase.php on line 18

Change the user rights of the campsite folder and subfolder / files to be readable and writeable by apache.

3. Pointing your browser to http://campsite/ for installation throws the errors:

Notice: Campsite error: the $compile_dir '/var/www/campsite/templates_c' does not exist, or is not a directory. in /var/www/campsite/install/classes/CampTemplate.php on line 89

Create the folders "templates" and "templates_c" in the campsite folder, set the rights to readable and writeable for apache.

4. The installation routine shows the error on the first screen:

Cron Jobs Writable ⁞   No
                      You will need to grant permissions to folder
                      /var/www/campsite/install/cron_jobs

If the folder does not exist: create it. And set the rights to readable and writeable for apache.

Installing Campsite on Windows Vista

Tips and tricks for making Campsite install on Vista (not recommended for production servers)

The Campsite content management system is an extremely flexible and powerful tool for news websites. And since the 3.0 version of Campsite, it can be installed under Windows relatively easily. This howto has been written for users of Windows Vista, but the steps should be similar, if not easier, for other versions of Windows as well.

The main advantage of having Campsite installed under Windows is that it greatly simplifies the process of creating and altering site templates; proprietary design and image editing tools such as Photoshop, Illustrator and Dreamweaver run under Windows but not on Linux. Having a local version of Campsite running means that a template designer can easily alter site graphics without having to either use a remote server or reboot into Linux.

NOTE: This howto is not intended for production servers running under Windows.

Prerequisites


To install Campsite under Windows, you will need the Windows versions of the following software packages:
Optional programs:

Installing MySQL under Windows Vista

MySQL has a number of known issues installing under Windows Vista. You must:

To install MySQL Server 5.0.51a in Vista

   1. Disable the UAC in Windows Control Panel->User Accounts
   2. Use mysql-essential-5.0.51a-win32.msi
   3. In the final step uncheck "Configure MySQL Server now"
   4. Download and run Resource Hacker resourcehacker_1.png

   5. Open ...\MySQL Server 5.0\bin\MySQLInstanceConfig.exe with Resource Hacker
   6. Navigate to 24\1\1033
   7. Change <requestedExecutionLevel level="asAdministrator" uiAccess="false"> to <requestedExecutionLevel level="requireAdministrator" uiAccess="false">
   8. Press "Compile script"
   9. Exit Resource Hacker and save the result (overwrite the initial MySQLInstanceConfig.exe)
  10. Now MySQLInstanceConfig.exe should start normally.
  11. Configure the server.
  12. Sometimes the server doesn't start:

a) Check Windows Firewall settings (3306/TCP)
b) Try changing the compability mode for the file ...\MySQL Server 5.0\bin\mysqld-nt.exe to Windows XP-SP2.
  13. That's all.

Go through the MySQL installation process and make a note of your MySQL root password. You will need this later.

Installing Apache 2.2


Apache 2.2 installs without problems using the Windows Installer under Windows Vista. Once installed, it even has a small icon for starting, restarting and stopping Apache which runs in the system tray. The Apache folders are in this directory:

C:/Program Files/Apache Software Foundation/Apache 2.2/htdocs

(This is the equivalent of /var/www/ under Linux)

You will have to change your Apache virtual host configuration. This involves making changes to two files, httpd-vhosts.conf and httpd.conf. You can find httpd.conf in C:/Program Files/Apache Software Foundation/Apache 2.2/conf

and you will find httpd-vhosts.conf in C:/Program Files/Apache Software Foundation/Apache 2.2/conf/extra

Open C:/Program Files/Apache Software Foundation/Apache 2.2/conf/httpd.conf

Make a backup of this file. Give it a name like 'httpd.conf.backup'

Reopen the httpd.conf file. Search for the line that says:
#Virtual Hosts
#Include conf/extra/httpd-vhosts.conf

Remove the # mark from the line to uncomment the Virtual Hosts directive:
#Virtual Hosts
Include conf/extra/httpd/vhosts.conf

In that file you should also make sure that the mod_dir.so and mod_rewrite.so modules are loaded in order for Campsite to work properly:
LoadModule dir_module modules/mod_dir.so
LoadModule rewrite_module modules/mod_rewrite.so

Save and close.

Open the file for virtual hosts under Apache in C:/Program Files/Apache Software Foundation/Apache 2.2/conf/extra/httpd-vhosts.conf

There are a number of directives Campsite needs in order to run. Here is how I set up my Apache virtual host using the name of 'mycampsite' on my local host:

<VirtualHost *:80>
    ServerAdmin webmaster@mycampsite.localhost
    DocumentRoot "C:/Program Files/Apache Software Foundation/Apache 2.2/htdocs/mycampsite"
    ServerName mycampsite.localhost
    ServerAlias www.mycampsite.localhost
    DirectoryIndex index.php
    <Directory "C:/Program Files/Apache Software Foundation/Apache 2.2/htdocs/mycampsite">
        Options -Indexes FollowSymlinks MultiViews
        AllowOverride All
            Order allow,deny
        Allow from all
    </Directory>
    ErrorLog "logs/mycampsite.localhost-error.log"
    CustomLog "logs/mycampsite.localhost-access.log" common
</VirtualHost>

You must make separate virtual hosts for every Campsite instance you want to run.

Editing the Windows system's 'hosts' file


In order for mycampsite.localhost to be visible, you need to tell Windows that you've added this new subdomain to 'localhost'. To do this, you must go to C:/Windows/System32/drivers and edit the file. Or you can go to C:/Windows/System32 and search for 'hosts'.

Your file will look like this in the main part:

127.0.0.1     localhost
::1           localhost

You need to add a line to include your site name (in this case it was 'mycampsite'):

127.0.0.1      localhost
127.0.0.1      mycampsite.localhost
::1            localhost

You may need to restart for this to take effect.

Installing PHP

Installing PHP was fairly straightforward.

Select Apache 2.2 as the version you are using and point it to the Apache configuration directory is located (C:/Program Files/Apache Software Foundation/Apache 2.2/conf).

During the installation process, you will be asked if you want to install PHP extensions. You will need the following:
They are located in the Extensions tree and are not installed by default, so you will have to find them in the tree and select them for installation.

You might need PEAR, so it's a good idea to enable that as well under 'Extras-> PEAR Install'.

If you miss it the first time around, you can always go back and re-enable them by going to Control Panel -> Uninstall -> PHP5 -> Change and this will restart the setup.

Installing Campsite

If you haven't done so already, download the latest version of Campsite: http://sourceforge.net/project/showfiles.php?group_id=66936

Unpack the files using 7-zip.

The Campsite INSTALL file included in the tarball is written for Unix users, and things are a bit different under Windows. For example, you will have to copy the implementation/site folder to your Apache document root. If you did not change anything, the Apache document root will be in this directory: C:/Program Files/Apache Software Foundation/Apache 2.2/htdocs

In a separate window, go to where you unpacked the Campsite 3.1 tar file (in this case the folder was named campsite-3.1.0.tar), open the folder marked 'implementation' and then the folder marked 'site'. Select all the files in implementation/site and copy them.

Go to the Apache document root (C:/Program Files/Apache Software Foundation/Apache 2.2/htdocs) and create a new folder with the name of your Campsite implementation. In this case the folder was named 'mycampsite'. Open that folder and paste the files you copied from the implementation/site folder into your new folder.

Rename the file htaccess to .htaccess and be sure your apache installation is able to read it in order for Campsite to work well on this platform.

If all the other programs (Apache, MySQL, PHP) have been installed correctly, you should be able to start the Campsite web installer by opening this address in your browser:
mycampsite.localhost
follow the steps in the Campsite web installer and you should be on your way.

Once the installation is done, you can open your Campsite administration interface in a browser at this address:
mycampsite.localhost/admin

Notes:

Because this howto is using the MySQL database only for Campsite and only for testing/development, it used the MySQL root username and password. You should use a different username/password if you will be using MySQL for other purposes on your Windows install.

For users of previous versions of Campsite, you have to pay special attention to the last page of the web config. The old default username/password combination of admin/admn00 has changed. Now you set your password on the last page of the web installer so that your username is admin and the password is whatever you set.

Installing Campsite on Mac OS X

Installation using MAMP

Known issues

As for Campsite 3.1.2 and MAMP 1.7.2 the demo templates and database are not installed by wizard during the installation process. If you want to use them, you need to install them manually.

Installing Campsite on FreeBSD

Most FreeBSD admins will find it very easy, as campsite is in FreeBSD ports (www/campsite) and all, you need to do is standard port install:

#cd /usr/ports/www/campsite
#make install clean

Installing Campsite on PHP-CGI shared hosts

Installing Campsite on hosting setups that run PHP as CGI is possible but is not always straightforward.

Given that such setups vary from provider to provider, we have started a wiki that collects installation instructions and issues that may arise in such environments. The wiki can be found here:

http://wiki.sourcefabric.org/display/CS/Install+on+Shared+Hosting+Using+PHP-CGI

Automated tasks

Campsite has tools that perform the following automated tasks:

  1. sending emails to administrative users containing the latest events that took place in Campsite
  2. sending emails to subscribers alerting them when their subscription ends
  3. automatic changing of the status of issues and articles scheduled for certain actions
  4. automatic indexing the article content (update the search engine database)
  5. generating statistics
The automated tasks are scheduled using the crontab utility, run as apache user (www-data on some systems).

1. Sending emails to administrative users containing the latest events that took place in Campsite is managed by the utility events-notifier located in Campsite's bin directory. This utility is scheduled to run every two minutes.

2. Sending emails to subscribers alerting them when their subscription ends is managed by the utility subscription-notifier located in Campsite's bin directory. This utility is scheduled to run every eight hours.

3. Automatic changing of the status of issues and articles scheduled for certain actions (publish/unpublish/show in front page etc.) is managed by the utility campsite-autopublish located in Campsite's bin directory. This utility is scheduled to run every minute.

4. Automatic indexing the article content is managed by the utility campsite-indexer located in Campsite's bin directory. This utility is scheduled to run every four hours.

5. The statistics gathering script is managed by the campsite-statistics utility, located in the Campsite's bin directory. This utility is scheduled to run every four hours.

Setting up a Campsite Replication Server

The Replication Server concept was developed as a part of the Sourcefabric Radio Package project (a complete open source solution for a radio station (see http://wiki.sourcefabric.org/display/CC/Radio+Package).

Facts

Since Internet connectivity is not that good in some places, radio stations need to be able to create stories on their local intranet and then send them to the main web server (outside of the intranet) whenever connectivity is available. All media from the article must be uploaded to the web server.

The following must be synchronized:

 

Campsite Installation

All you need to do is run a normal Campsite installation on both the master and slave servers. The most important thing at this point is to set the same instance name (campsite is the default) for both installations.

Follow the "Installation" section from the Campsite manual to do all of this in a right way.

 

Campsite MySQL database replication

MySQL server has built-in support for replication, meaning that you can have on-the-fly copies of data stored in a main database server --known in this context as a Master server-- in anothers servers --the Slave servers--. Latest releases of MySQL server --5.x-- allow you to create really complex replication scenarios, but this is not our case. All what you need to synchronize two campsite servers is to use a simple MySQL replication scheme, known as Master Master replication.

When using replication, all updates to the tables that are replicated should be performed on the master server.

This way and to be clear, Local Campsite server will be our 'Master 1' and 'Slave 2', and the Online Campsite server will be the 'Slave 1' and 'Master 2'.

We really need to implement this scheme because of the article comments management. More details about this in the section Handling Article Comments at the end of this document.

 

Requirements

MySQL >= 4.1.0

Make sure MySQL versions installed on master and slave are compatibles to do replication. Take a look at http://dev.mysql.com/doc/refman/4.1/en/replication-compatibility.html.

 

Setting up

In general, what we need to do is:

So, here we go.

1- Create an account on the 'Master 1' server that the 'Slave 1' can use to connect.

   mysql>⁞ GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.*
       -> TO 'replication_user'@'slave1server.yourdomain.com'
       -> IDENTIFIED BY 'a_strong_password';

Change 'replication_user', 'slave1server.yourdomain.com' and 'a_strong_password' to whatever you want to use and suit your installation.

2- Create an account on the 'Master 2' server that the 'Slave 2' can use to connect.

   mysql> GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.*
       -> TO 'replication_user'@'slave2server.yourdomain.com'
       -> IDENTIFIED BY 'a_strong_password';

Change 'replication_user', 'slave2server.yourdomain.com' and 'a_strong_password' to whatever you want to use and suit your installation.

3- Add the following lines to the MySQL configuration file on the 'Master 1' and on the 'Master 2' servers. The MySQL configuration file path is usually '/etc/mysql/my.cnf', if you installed MySQL from the standard packages.

   master 1:

   [mysqld]
   server-id = 1
   log-bin

   master-host = master2server.yourdomain.com
   master-port = 3306
   master-user = replication_user
   master-password = a_strong_password

   replicate-do-db = campsite
   replicate-do-table = campsite.ArticleComments
   replicate-wild-do-table = campsite.phorum_%

The value for master-host can be the valid fqdn (fully qualified domain name) or the IP address of your 'Master 2' server.

   master 2:

   [mysqld]
   server-id = 2
   log-bin

   master-host = master1server.yourdomain.com
   master-port = 3306
   master-user = replication_user
   master-password = a_strong_password

   replicate-do-db = campsite
   replicate-ignore-table = campsite.ArticleComments
   replicate-ignore-table = campsite.SystemPreferences
   replicate-wild-ignore-table = campsite.phorum_%

The value for master-host can be the valid fqdn (fully qualified domain name) or the IP address of your 'Master 1' server.

Note all of the above [mysqld] entries are replication specific. You usually have another couple of entries there, but it does not matter for replication purposes.

4- We need to make sure both 'Master 1' and 'Slave 1' will have the same Campsite database at the same status when starting replication.

If you are doing a new installation on both 'Master 1' and 'Slave 1' and you are totally sure that you are installing the same Campsite package and databases are exactly the same, you can skip this step and continue on 4-. If you do not, continue here.

We have got to make a dump of the 'campsite' database from our 'Master 1' server, then we will copy it to the 'Slave 1' server. Let us use the mysqldump utility to do this.

   $ mysqldump campsite > /tmp/campsite_dump.sql --extended-insert \
   > --master-data -u mysql_user -p

You will be prompted to enter the corresponding password for your MySQL user (default user is the current logged in user). Remember, you need to run this command as a MySQL user with the granted privileges required to do this.

This will create a text file --/tmp/campsite_dump.sql-- containing SQL statements to create the 'campsite' database tables with data.

Now, copy/transfer the dump file to the 'Slave 1' server, make sure MySQL is running there. If you already have a 'campsite' database on the 'Slave 1' it is time to drop all of the tables on it --do not forget backing up, maybe you still need it--. Finally, enter something like the following on the 'Slave 1':

   $ mysql campsite < /tmp/campsite_dump.sql -u mysql_user -p

This will execute all of the SQL statements in the dump file, which will include the CREATE and INSERT statements. Once the dumped-up databases are loaded onto the 'Slave 1' server, go to the final step.

5- Restart both mysql 'Master 1' and 'Master 2', then execute the following SQL statement while logged in as root on both of them:

   mysql> START SLAVE;

6- Check replication works

Setting up and getting work this simple kind of replication is quite easy. If you followed the above indications then replication would have to be working well now. However, you can check this by running the SHOW MASTER STATUS command on the masters and SHOW SLAVE STATUS on the slaves. Those commands will give you some information about the current status of both the Master and Slave servers.

If you are experiencing troubles and replication does not work as it should, please take a look at the corresponding section in the MySQL manual and the other links referenced at the end of this document.

 

Syncing Articles-related Files⁞

This Radio Package feature allows you to be able to synchronize Campsite Article-related files between the Local server and the Online server over the Internet. Our goal is to ensure no user intervention is required when the server is restarted (for passwords or keys).

Please note these instructions are specific to Ubuntu Linux versions 4.01 and later. However, it should be run quite well on any *NIX type OS.

 

Requirements

Just simple like this:

 

Setting up⁞

Keep this in mind:

The remote user must have write access to the Campsite instance HTML directory on the remote host. The local user must have read access to the Campsite instance HTML directory on the local host. The default value of this directory is '/var/www/campsite/html'. You can achieve this by adding the remote/local user to the apache group (default is www-data on Debian/Ubuntu and apache on RedHat). On the remote machine you have to run the following command also:

  chmod g+w /path/to/campsite/instance/html/directory/ -R

1- Test whether rsync over ssh works at all.

   $ rsync -avz -e ssh remoteuser@remotehost:/remote/dir /local/dir/

Type the corresponding password when prompted.

2- Configure the Local server.

We need to generate a private/public pair of keys to allow a ssh connection without asking for a password.

   $ cd ~
   $ mkdir .campsite-rsync
   $ ssh-keygen -t dsa -b 1024 -f ~/.campsite-rsync/localhost-rsync-key
   Generating public/private dsa key pair.
   Enter passphrase (empty for no passphrase):
   Enter same passphrase again:
   Your identification has been saved in /home/localuser/.campsite-rsync/localhost-rsync-key.
   Your public key has been saved in /home/localuser/.campsite-rsync/localhost-rsync-key.pub.
   The key fingerprint is:
   2e:28:d9:ec:85:21:e7:ff:73:df:2e:07:78:f0:d0:a0 localuser@localhost

You have got to create an empty passphrase, so just press enter when asked for it to generate the keys. Make sure to do this to avoid no other unauthorized user can read the private key file.

   $ chmod 600 .campsite-rsync/localhost-rsync-key

Now we will put the public key into the 'authorized_keys' file on remotehost (a.k.a. our Online server) specifically the one for remoteuser.

Let us use scp to transfer the file over from localhost to remotehost.

   $ scp .campsite-rsync/localhost-rsync-key.pub remoteuser@remothost:~/

3- Configure the Online server.

SSH'ing over to remotehost. Once we are on /home/remoteuser/ we need to make sure that every directory and file that we need to authorize connections with the transfered key exist.

   $ if [ ! -d .ssh ]; then mkdir .ssh ; chmod 700 .ssh ; fi
   $ mv localhost-rsync-key.pub .ssh/
   $ cd .ssh/
   $ if [ ! -f authorized_keys ]; then touch authorized_keys ; chmod 600 authorized_keys ; fi
   $ cat localhost-rsync-key.pub >> authorized_keys

Now, we can make connections to the Online server from anywhere. We can edit 'authorized_keys' to increase security by adding somethink like this --use your preferred text editor-.

Change the public key, that looks like this:

   ssh-dss AAAB3NzaC1kc3MAAAEBAOy99zr4UZxKVTcVIZOoUdUNa5LWUn4urIdY4bxP4SuLbcJZumIqyrkV
   YmoT0Qk8l1peRvLkpyE/G5TAyKeS0wpxm28mEF2oRcLx5/ItD2hwfm53irUKYAjiaLwHkAtDZyHUQyZiKku
   s4LqZo2eo196diq3UYxebKX3p6N+l10yBvZr8NGxtyf+QVybxaIKw7qcnUEz+jldV3zY/+wyO/LVtuiD0qN
   W6yG2jv4kYf4ENTz5auMdh5rSv9TXVigDV5DGOHhIKMlQ4Oee0tZ6K82S3yq9mhjOm8KXRmEgr+GQaG/4Yg
   dBmhPeKfneAfbHwD41vb0fvMjpxX9zVX+V4EpEAAAAVAOIO/+vd01P/UyC1KRQz9J10VqfRAAABAE/d1adp
   YnBaH2qxpvyom54eDig6wltril7BjxxEkP9HJS1+03MIJLDE0ZZPfxyiZl4n2SzPMp7uxhd0llywud6dIiF
   GMZ2u8YyJcuRs2dEwIz5CyNtGdTks8G8d3nTRhJEwkXexG83c+/RzGFZZW1ZnBwlvkfRedU2dELwV9ofQpV
   lQhnl0H5eM1M2U0O0pLHADp89ViuoKle4hFpBzPQQ4h+j6bVeemlvvZVNilGnEwatEpRrmtMcpet1yZEqFD
   darGlh/+V5MSjALw4f1E4BYWo23r2qBnoZl6+1MP26SDysXJzxAbA1yvmwbCVZFsTsPlyHhasn5cR25z11g
   Ob8AAAEAB0tCrUN5V1LgohyVmlIWBOa4nFle+tEBLIPC5Bbqgm4LVQ3MUBs4CADeaJHGirSC5JuJuyJXPGQ
   JOSpOdLk/q4ZaJp0SlxcVqXGX1hHIlHE7NuqFPc4+TgPETRaPztTvvg5zA0kTo8CP4qeYtcIt+Mm7F4YGir
   ySeMspPN3Xwh7/0rgDrY/t+FwxPmSRKEIWo1Tztx89+u4yb2FHLB8Hku157GHz502P47jhSYgk2WgoKrJhF
   BrhjvKClVBu8oD7OA10nI9ZNGa4j1OfdTUUukGHoGxJhXhkVXR+mPJMRr6AD6dr/oadObF2Fe6itfRq2KYr
   BGA0M4KNE6LH/2RfAQ== holman@mutant

to:

   from="local_IP",command="/home/remoteuser/.campsite-rsync/validate-rsync" ssh-dss
   AAAAB3NzaC1kc3MAAAEBAOy99zr4UZxKVTcVIZOoUdUNa5LWUn4urIdY4bxP4SuLbcJZumIqyrkVYmoT0Qk
   8l1peRvLkpyE/G5TAyKeS0wpxm28mEF2oRcLx5/ItD2hwfm53irUKYAjiaLwHkAtDZyHUQyZiKkus4LqZo2
   eo196diq3UYxebKX3p6N+l10yBvZr8NGxtyf+QVybxaIKw7qcnUEz+jldV3zY/+wyO/LVtuiD0qNW6yG2jv
   4kYf4ENTz5auMdh5rSv9TXVigDV5DGOHhIKMlQ4Oee0tZ6K82S3yq9mhjOm8KXRmEgr+GQaG/4YgdBmhPeK
   fneAfbHwD41vb0fvMjpxX9zVX+V4EpEAAAAVAOIO/+vd01P/UyC1KRQz9J10VqfRAAABAE/d1adpYnBaH2q
   xpvyom54eDig6wltril7BjxxEkP9HJS1+03MIJLDE0ZZPfxyiZl4n2SzPMp7uxhd0llywud6dIiFGMZ2u8Y
   yJcuRs2dEwIz5CyNtGdTks8G8d3nTRhJEwkXexG83c+/RzGFZZW1ZnBwlvkfRedU2dELwV9ofQpVlQhnl0H
   5eM1M2U0O0pLHADp89ViuoKle4hFpBzPQQ4h+j6bVeemlvvZVNilGnEwatEpRrmtMcpet1yZEqFDdarGlh/
   +V5MSjALw4f1E4BYWo23r2qBnoZl6+1MP26SDysXJzxAbA1yvmwbCVZFsTsPlyHhasn5cR25z11gOb8AAAE
   AB0tCrUN5V1LgohyVmlIWBOa4nFle+tEBLIPC5Bbqgm4LVQ3MUBs4CADeaJHGirSC5JuJuyJXPGQJOSpOdL
   k/q4ZaJp0SlxcVqXGX1hHIlHE7NuqFPc4+TgPETRaPztTvvg5zA0kTo8CP4qeYtcIt+Mm7F4YGirySeMspP
   N3Xwh7/0rgDrY/t+FwxPmSRKEIWo1Tztx89+u4yb2FHLB8Hku157GHz502P47jhSYgk2WgoKrJhFBrhjvKC
   VBu8oD7OA10nI9ZNGa4j1OfdTUUukGHoGxJhXhkVXR+mPJMRr6AD6dr/oadObF2Fe6itfRq2KYrBGA0M4KN
   E6LH/2RfAQ== holman@mutant

Note at the beginning of the line. 'local_IP' is the IP address of the Local server, and '/home/remoteuser/.campsite-rsync/validate-rsync' is a script that you can create --on the Online server-- by:

   $ mkdir .campsite-rsync
   $ cd .campsite-rsync
   $ vim validate-rsync   // or your preferred editor

and this is its content:

   #!/bin/sh

   case "$SSH_ORIGINAL_COMMAND" in
   *\&*)
       echo "Rejected"
       ;;
   *\(*)
       echo "Rejected"
       ;;
   *\{*)
       echo "Rejected"
       ;;
   *\;*)
       echo "Rejected"
       ;;
   *\<*)
       echo "Rejected"
       ;;
   *\`*)
       echo "Rejected"
       ;;
   rsync\ --server*)
       $SSH_ORIGINAL_COMMAND
       ;;
   *)
       echo "Rejected"
       ;;
   esac

If 'localhost' has a variable IP address, or shares its address (via NAT or something similar) with hosts you do not trust, omit the 'from="local_IP",' part of the line (including the comma). This way, 'rsync' will be possible from connections using this key.

Make sure that the 'validate-rsync' script is executable by 'remoteuser' on 'remotehost'.

Check you do not allow SSH root access from anywhere, this is always a good security practice. You need to have an entry like this in the SSH daemon configuration file to do that:

   PermitRootLogin no

4- Let us test if all of the stuff above work well. Run the following command on the local server:

   $ rsync -avz -e "ssh -i /home/localuser/.campsite-rsync/localhost-rsync-key" \
         /home/localuser/somefile remoteuser@remotehost:/home/remoteuser/remote_dir

If it does not work, probably it is because of the file permissions, so check them for each file mentioned before.

5- What to transfer.

Files to be synchronized are those contained into 'images', 'files' and 'look' Campsite directories. They will be transfered over from Local server to Online server. We need to create a file on the Local server with the list of directories and files to be sent.

   $ vim /home/localuser/.campsite-rsync/rsync-files-to-sync.txt

This is the content you need to put in:

   images
   files
   look

That is it, make sure each entry is on a new line. Save and close the file.

6- Cron Job setup.

Now we create the cron script 'rsync-campsite-afiles' like this:

  #!/bin/sh

  RSYNC=/usr/bin/rsync
  SSH=/usr/bin/ssh
  KEY=/home/localuser/.campsite-rsync/localhost-rsync-key
  RUSER=remoteuser
  RHOST=remotehost

  LCAMPSITE_WWW_PATH=/path/to/local/campsite/html/instance/dir
  RCAMPSITE_WWW_PATH=/path/to/remote/campsite/html/instance/dir
  FILESFROM=/home/localuser/.campsite-rsync/rsync-files-to-sync.txt

  $RSYNC -razO -e "$SSH -i $KEY" --files-from=$FILESFROM "$LCAMPSITE_WWW_PATH" \
       "$RUSER@$RHOST:$RCAMPSITE_WWW_PATH"

The cron script is easy to understand, all what you need to know about it is:

  RSYNC: The full path to the 'rsync' binary file
  SSH: The full path to the 'ssh' binary file
  KEY: The full path to the SSH private key
  RUSER: The name for the user on the Online server
  RHOST: The hostname for the Online server
  LCAMPSITE_WWW_PATH: The full path to the Campsite instance HTML directory on
                      the local server (the usual value is:
                      /var/www/campsite/html)
  RCAMPSITE_WWW_PATH: The full path to the Campsite instance HTML directory on
                      the remote server (the usual value is:
                      /var/www/campsite/html)
  FILESFROM: The full path to the file containing the files/directories
             name to be synced

Set executable permission on it:

   $ chmod 755 /home/localuser/.campsite-rsync/rsync-campsite-afiles

Finally, we create an entry for this new cron job:

   $ crontab -e

line to insert:

   * * * * * /home/localuser/.campsite-rsync/rsync-campsite-afiles

for a by minute synchronization.

 

Handling Article Comments

If you are setting up a Local and Online servers environment, you need to take care of article comments. Why? Well, static and dynamic pages must be generated by working on the Local server, that is why we need to replicate data over from the Local to the Online server to keep it up to date.

On the other hand, we have got users from all around the world visiting our Website and, hopefully, most of them would like to post comments on the published articles, and they just can do that.

Said that, we will need to be able to replicate those article-comments-related tables back to the Local server.

All the stuff above means that comments management will be enabled in our Local server only whether we are online and able to reach our Online server.

This is what you need to do in order to set up comments replication:

   mysql> GRANT ALL PRIVILEGES ON campsite.* TO 'dbuser'@'localserver' IDENTIFIED BY 'somepassword';

Now, on the Local server:

That is it, Campsite will show whether you are able or not to manage article comments on the Local server.

Finally

Please, run tests enough to check everything works well, after that you will can go in productive =)

 

Resources

Getting Started

Campsite enables you to host multiple, multi-lingual publications on the same web server. The process of setting up a new on-line publication with Campsite can be divided into three steps:

  1. Configuring the publication, and specifying the templates to be used
  2. Establishing the structure of your publication, with issues and sections
  3. Adding content, managing content, and publishing it

This part of the Campsite manual is aimed at editors and journalists working their way through these three steps. It assumes that the web server you will use is already up and running with Campsite, and that templates have been designed for your publication. If you do not yet have your own Campsite server running, you can follow the steps in this manual using the Campsite demonstration server and sample templates provided by Sourcefabric.

The first step begins with logging in to the administration interface of your Campsite server. This is a special interface which is only available to the staff of your publication. Readers who subscribe to your online publication will log in using the home page of your website instead.

By default, the URL you should enter into your web browser for the administration interface is the name of your website, followed by 'admin'. For example:

http://www.example.com/admin/

Your system administrator should already have provided you with a login account name and password. Below the Account name and Password fields, click the drop-down menu to select an interface language other than the default of English, if you wish. Then click the Login button.

Login

Alternatively, the Campsite demonstration server can be found at:

http://campsite-demo.sourcefabric.org/admin/

Please remember that the demonstration server is a public site, so don't enter any private information there. A variety of guest login accounts are set up on this system, and the passwords for these accounts are shown on the login page.

 

How Permissions Change the Interface

The appearance of the Campsite administration interface changes, depending on the permissions that a particular staff member has. Each user sees only the options that he or she has the authority to use. A typical staff user (a section editor or journalist) will only see some of the options available to a fully authorized administrator (such as the publisher, or senior manager).

When you log into the Campsite administration interface, you will see the administration home page. This is completely different from the publication home page that readers and subscribers see. At the top of the screen, you will see the navigation menu, containing the options available to you.

Here is how two typical users would see the navigation menu differently. Firstly, here's how the Actions sub-menu looks when an administrator is logged in:

 Administrator actions menu

 
And this is how the same Actions sub-menu looks when a journalist is logged in:

User actions menu

 

Main Menu

The main Campsite menu contains a link to the administration Home page and up to six sub-menus, depending on the permissions of the user who is logged in. These sub-menus are Content, Actions, Configure, Users, Plugins and Help. The menus shown below are for an administrator user, who has access to all sub-menu options.

Home

On the left hand side is a list of quick links to different selections of articles; for example, articles that you have submitted yourself, or pending articles.

Administrator home 

 

Clicking on any of these links makes a table of the relevant articles appear on the right hand side of the window.

Recently modified articles 

 

Content

Here you can find the publications on the server, reader comments, the image archive, and the Universal List, a place where you can browse all of the articles in the Campsite database. For each available publication, there are quick links to the latest three issues, and a full list of sections within each issue. In the screen shot below, a sample publication called 'the Custodian' has been set up, with two issues in both English and Spanish. Within issue 2 of the English edition, there are six sections shown.

 Content menu

 

Actions

This menu provides quick access to the most commonly used functions, including 'Add new article' and 'Change your password'. 

Actions menu 

 

Configure

Here you can configure the preferences for your publication. Templates are the files which determine how Campsite displays content to readers and subscribers. Article Types describe the format of your articles, while Topics allow you to categorize your articles. The Languages option specifies the languages that journalists have to choose from when creating articles. Countries enables you to specify the name of a country in the local language for each territory. The Localizer allows you to translate the administration interface. Clicking Logs will show you the recent activity of all staff users, including the IP address that they have logged in from.

Configure menu


Users

Here you can add and edit staff users, and manage subscribers. You can also define staff user types, or synchronize user accounts between Campsite and Phorum, a popular web forum system. 

Users menu

 

Plugins

This sub-menu provides access to additional functionality for Campsite, including blog, interview and poll plugins.

Plugins menu 

 

Help

Links you to the on-line version of this manual, as well the latest news and information about Campsite on the Sourcefabric website. You can also send a support request email by clicking on 'Feedback'.

Help menu

 

Creating a Publication

Campsite content is organized in a hierarchical structure, which conforms to the tradition of newspapers and magazines: Publications, Issues, Sections and Articles. Each publication is made up of issues; each issue is in turn made up of sections, which are comprised of articles. A 'breadcrumb trail' of links is present on every screen, which enables quick navigation between different levels of the publishing hierarchy.

For example, after creating a publication named the "Prague Times", by clicking on "Prague Times" in Campsite's list of publications, you enter the list of issues for that newspaper. By clicking the name or number of a particular issue, you enter its list of sections. By clicking the name of a section you enter the article list. By clicking the article title in that list, you can edit the article.

To create a new publication, click Content on the main navigation menu, and then click 'Publications' from the sub-menu. On the Publication List page that appears, click on 'Add new publication'.

Add new publication

If your login account does not have administrator rights, you will not be able to see the 'Add new publication' option. You may need to ask your system administrator to enhance your access rights. Bear in mind, however, that a good administrator would be reluctant to hand over those rights to more than a handful of people. If you are not among those select few, your Publications List will only contain the publications already hosted on your Campsite server.

The Add new publication window has three areas; General attributes and Comments on the left, and Subscription defaults on the right. There's a Save button beneath these areas.

General attributes

General Attributes

Comments

Subscription defaults 

Subscription Defaults

The rest of the fields are related to subscriptions, which you can adjust later if you wish. First, you have to select a time unit for your subscriptions; which could be days, months, weeks or years.

You can set two types of subscriptions: paid and trial. Paid subscriptions have the following properties:

After clicking the Save button, Campsite will confirm that the new publication has been created.

New publication created 

On the right hand side under the "Subscription defaults" fields, there will now be a link "Set subscription settings by country" which will enable you specify different default time periods for individual countries. This link opens the "Subscription Settings by Country" page, which has a link "Set subscription settings for a country".

Subscription by country 

If you follow this link, it opens a page with a drop-down menu for selecting the country in question, plus fields for the default trial and paid subscription lengths.

Set subscription settings

Clicking the Save button returns you to the "Subscription Settings by Country" page, which should now show the setting you have just made.

Subscription settings updated

Creating a New Issue

Once you have successfully created your publication, click on its name in the Publication List (e.g. "Prague Times"). This will lead you to the Issue List, which will be empty to begin with. 

Issue list 

Click on the 'Add new issue' link. If you are creating the very first issue, you will see a page with fields for basic information which you will need to enter.

Add new issue

The Name is the name of the issue in the particular Language you specify in the drop-down box underneath. The Number is a unique identifier for this issue. If this is the first issue you've ever published, then number "1" would be fine. The issue number cannot be changed once it is specified.

If you are planning to add older issues of your publication at a later stage to the same Campsite server, you may consider continuing the series. For example, if you just published issue 154 of the "Prague Times" before moving to Campsite, you should assign number 155 to the first issue you are creating with Campsite.

The URL Name is only useful if you specified the "URL type: short names" option when you created your publication. This name will show up in the reader's browser address bar. For example, if you enter "2011_1" here, the address for the issue might look like this:

http://campsite.example.com/2011_1

Clicking the Save button takes you to the Change Issue Details page, where various options for the issue are set. On the left hand side, there are settings for the default templates for the front page, sections and articles. If you do not have your own templates yet, you can select templates from the 'classic' sample set that are provided with Campsite. Reader polls can also be set up and edited on this side of the page.

Change issue details 

On the right hand side of the Change Issue Details page are boxes which enable you to set the publishing schedule for the issue. An issue can be set to be published at a specific date and time, and unpublished at another date and time.

Issue publishing schedule

Copying a previous issue

If this is not the first issue you've created, you will see a different page after clicking the "Add new issue" link in the Issue List:

Use the structure 

"Use the structure of the previous issue" will be the usual option to choose once you are ready to publish additional issues, because it automatically creates a new issue with the same sections as the preceding one. Clicking this option opens a page which enables you to specify the new issue number.

Copy previous issue 

The sections of the new issue will be empty, so that you can begin to add articles. Before that, the first step is to set the name of the new issue, because this field is not automatically updated: it will start out with the same name as the last issue. After changing the Name field, click the Save button to update the new issue.

Issue details updated 

The previous templates are not copied to the new issue automatically, so the new issue must be linked to at least a template for the front page.

 

Creating a Section

By clicking on the name of an issue in the Issue List, you will enter the Section List. At first, a new issue will have no sections.

 Section List

If you click on the 'Add new section' link, you will see the corresponding page appear.

Add new section 

Here you must specify the Name, section Number, and URL name. While you can change the name of the section later, the section number is set at the time when the new section is added. The URL name will be part of the URL if you are used the "short names" option when you created the publication.

The section Description is optional. This field is useful for displaying content that doesn't change very often. The information in this field will only be displayed on your site if the template you are using supports it. If you would like to make the new section available to all existing subscribers, you should check the box for this option. Then click the Save button.

Your next step is to set the templates for the new section on the Configure Section page.

Configure section 

Here, you may wish to select custom templates for this new section and its articles from the drop-down menus. If you don't have custom templates for specific sections, you can use general section and article templates instead.

 

Creating Articles

The Article List for a particular section can be found by clicking on Content in the main Campsite navigation menu, and following the hierarchy of Publications, Issues and Sections. Alternatively, use the 'breadcrumb trail' of links just below the main navigation menu. You can create a new article by clicking the "Add new article" link at the top of the Article List.

Article list

The "Add new article" page contains three fields for entering basic information about the article you will create.

Add new article

When you click the 'Save' button, you will be taken to the Edit Article page.

Editing Articles

The appearance of the "Edit article" page depends on the article type you are working on. Below, the default "News Article" type is shown. At the top left are the Actions and Status drop-down menus.

Actions menu

Actions menu

The Actions menu contains short-cuts to commonly used functions: 

Status menu

The status drop-down menu indicates the copy flow state of the article.  There are three states that the article can be in:

Language menu

If multiple languages have been configured for the publication, a drop-down menu will enable fast switching between translated versions of the article. If not, the language of the article will be displayed here.

Edit/View buttons

There may be times when you want to view articles rather than edit them. In this case, clicking the "View" button speeds up the page display process. It also enables you to view an article when it is locked by another user on the server.

The editing area

Below the Actions and Status drop-down menus is the editing area for the article. It begins with three buttons; Preview, Save All, and Save and Close. Preview opens a pop-up window showing how the article will appear to the reader once it is published. Save All saves the fields in the edit area without closing the page, whereas Save and Close both saves the page and closes it, unlocking the page for other authorized users to edit further.

Edit article

The "News article" type has the following fields:

Other article types may contain different fields. Whenever you edit any of the fields, you will need to click either the Save All button at the top and bottom of the edit area, or any of the Save buttons to the left of individual fields. If the text content of a field has not been updated since the last save of the article, the individual button displays the label Saved.

Save buttons 

Note that date fields have a fixed syntax of YYYY-MM-DD (four year digits, two month digits and two day digits, in that order). If you enter dates in any other format, you may get incorrect results.

The sidebar

The sidebar

To the right side of the edit area is a vertical bar containing further options for the new article. Click the link to the right of the green cross icon to open a pop-up window for the relevant action. Click the white cross in a red square icon to remove an item or event that was previously attached to the article.

 

 

 

 

Previewing the article

While you are editing the article, you can see what it will look like when it is live on the web site by clicking the Preview button. The layout that readers will see when they visit your web site is controlled by the templates which your system administrator has installed. To be able to preview article and publication layouts, make sure you have configured the issue in question with the appropriate front page and article templates.

At the bottom of the preview window, you can see information from Campsite's template parser. If any problems occur while generating the web pages, the parser will display error messages. These should help you to identify any problems in the template structure, which you should report to your system administrator or template designer. Once you're finished with the preview window, click the icon in the upper corner of the window bar to close it, in the normal way.

Preview errors

Using the TinyMCE Editor

The body field editor in Campsite (a program called 'TinyMCE') allows contributors to perform extensive article formatting from within a web browser. You may be familiar with most of the functions of TinyMCE from using word processors such as Microsoft Word or OpenOffice.org: functions such as bold, italic, underline, and text alignment. Move your mouse over the icons to see a tooltip explaining what they do. Standard formatting keyboard shortcuts also work (e.g. ctrl+b for bold, ctrl+i for italic).

TinyMCE

The editor field you see on your own Campsite installation may look different than the one pictured above, depending on the extent of your user rights. Typically, the editor you'll see is the one that contains all the functionality you need for your site, but if you feel something vital is missing, discuss it with your Campsite system administrator.

There are two Campsite-specific features in the editor. The first is Insert internal link, which allows you to include links to articles within your Campsite publication.

Link icon

Clicking this icon opens a pop-up window with drop-down menus enabling you to select a specific language version of a publication, issue, section and article to link to.

Insert or edit internal link

After you click the Insert button, the internally linked text will be shown in blue and underlined, like a web link.

Internally linked text

 

The second Campsite-specific feature is Campsite Subhead, which allows you to break your text into different pages. (Your templates must be configured to use this option).

Subhead icon 

Enter the text for the subhead into the editing window, select it with the mouse, then click the Campsite Subhead icon. The subhead text will now be shown with a dashed outline.

Campsite subhead text

Managing Content

The "Article List" page is displayed when you enter a particular section via the Content menu, by following the hierarchy of publications, issues and sections. Alternatively, use the breadcrumb trail to jump to the section that you're interested in, and then click the "Go to Articles" link.

Article list

To edit a specific article, simply click on its title, and you will be taken to the "Edit Article" page. A locked article is one that is being edited at that moment, as shown in the list by a padlock icon to the left of its title. Articles that are being edited by other contributors are marked with a pink background, in addition to the padlock icon.

Article list locked

To find out who is editing the article and when it was locked, click on the article title in the list. A page will open with buttons offering the option of unlocking or simply viewing that particular article.

Article locked

Multiple actions 

The Article List allows you to perform other actions besides editing the article, and you can perform these actions on multiple articles at once. To perform an action on one or more articles, click the checkbox to the left of the article number and title. The articles you have selected will be highlighted with an orange background.

Selected articles

Now that you have selected the articles, go to the "Actions..." drop-down menu at the top of the list, and select the action you would like to perform:

Actions menu

For example, if you select "Status: Publish with issue", Campsite will publish the selected articles at the time the issue they are a part of is published. The page will refresh, and a message will display "Article status set to 'Published'".

Articles published 

Some actions will take you to another page, because they require further input from you. The article list also allows you to rearrange articles as they appear on your section page, if your template supports this feature. To move an article's position in the list, use the blue arrow buttons or select the position number from the drop-down menus in the Order column.

Over on the right hand side of the Article List are additional columns which relate to other functions, such as the Campsite user that created the article, and its publishing status. On the far right side of each row in the list is a magnifying glass icon which opens a preview of the article, and a flag icon which opens the "Translate article" page.

Article list right 

The Universal List

Campsite includes another tool which provides an overview of content across all publications on the server. The Universal List is accessed via an entry on the Content menu, and has an interface somewhat like a search engine. You can filter the search options according to a specific publication, issue or section. Once you have set this initial filter, you can then filter by other criteria, such as the author or date of the article.

Universal List


Publishing Articles

An article in Campsite can have one of four different states: New, Submitted, Published, or Publish with issue. When you create an article, the Status: drop-down menu at the top of the editing area is set to New by default. Once your article copy has been drafted and is ready for the editors to see, click on this drop-down menu and change the Status: to Submitted.

Publish status 

After changing the status to Submitted, the page will be reloaded, and a message will indicate that the change in status of the article has been recorded. The editors will be able to see the fresh submission when they log in to Campsite. Articles which are ready for editing are listed in the default Submitted Articles view on the administrator homepage.

Submitted articles 

In addition, if their user accounts have been configured for notifications, an email will be sent to the editors to inform them about the new submission.

Once the editors have made any required changes and are happy with the way the article reads and appears, they can publish the article by changing the drop-down Status: menu to Publish with issue. Again, the page will be reloaded, and a message will indicate that the article's status has changed.

Publish with issue 

When an article status is set to Publish with issue it becomes visible on your public web site, as soon as the issue it belongs to is published. This feature enables co-ordinated publishing of complementary articles when a complete issue is ready for the public. You can check the publication status of a particular issue in the Issue List. If the issue in question has already been published, then new articles can be seen by the public immediately after their status is changed to Publish.

The whole process is fully reversible, so you can unpublish articles on your site (or even change their status to New) as easily as you can publish them. Note that only authorized users are allowed to publish articles, so you will not be able to access this option if your system administrator has not granted you this permission.

Scheduled Articles

You also have the option to publish (or unpublish) an article at a specific date and time in the future.  You can do this from the Edit article page, using the Add Event link in the sidebar:

Add event

 

After clicking on Add Event, a pop-up window will appear with a calendar and a series of three possible actions for the date and time that you choose: Publish/Unpublish, Show on front page/Remove from front page, and Show on section page/Remove from section page.

Schedule action

Choose the date by clicking on the calendar, or enter a date code manually. Then enter the time for the event, and choose one or more actions to perform at the time you have chosen. After you click the Save button, the pop-up window will close, and the event will appear under Publish Schedule in the sidebar of the Edit article page:

Publish schedule

Once the event is created, the actions will be performed automatically for you on the date and at the time you specified. Over on the left hand side of the Edit article page, the Status drop-down menu will change to Published. In advance of the publish event date and time, a clock icon will be shown.

Publish clock

After the event time, the clock icon will disappear and the event will no longer be shown under Publish Schedule in the sidebar.

Publishing an Issue

You can draft and edit articles for a particular issue on your Campsite server without any of the material being available to the public. You can then publish an entire issue all at once, and there are two ways to do it: immediately, or by scheduling the issue to be published at a specific date and time in the future. Note that within an issue, you can publish or unpublish each article individually; for instance, to hide an article even if the issue it belongs to has already been published.

Publishing Immediately

To publish an issue straight away, click the Publish link for the relevant issue and language edition in the Publish Date column of the Issue List.

Issue List

A pop-up dialog will ask you to confirm that you want to publish the issue in question, because this action implies that any articles which are part of the named issue will become available to the public instantly.

Are you sure?

After clicking the OK button, the issue will be published, and the Issue List will be updated with the publication date and time of that particular issue.

Publish date updated 

To reverse the process, click the Unpublish link. Again, a pop-up dialog will ask if you are sure you want to change the issue's status. 

Scheduled Publishing

To schedule an issue to be published automatically at a specific date and time in the future, click on the Schedule link for the issue and language edition you require in the Publish Date column of the Issue List. This will open the Change issue details page, where you can set the date and time for this particular issue to be published. Over on the right hand side of the page are the Issue Publishing Schedule and Schedule a new action boxes.

Schedule a new action 

Click the small calendar icon to the right of the Date: field to select a specific day for publication. Set the time you require, and select either Publish or Unpublish from the drop-down Action menu. Then click the Save button. The Issue Publishing Schedule box will update to display the newly scheduled action.

 Schedule updated

Note that you can also set the issue to be unpublished at a specific date and time in the future as well. This event will be displayed in the Issue Publishing Schedule box.

Unpublish schedule

To cancel a scheduled action, click the corresponding white cross in a red box icon in the Delete column. You will be asked to confirm the deletion.

Delete scheduled action

An event date and time that has already passed will be shown crossed out. If you click on the date/time link for a future event, the Issue Publishing Schedule page will open, and you will be able to edit the event. Click the Save button to confirm the schedule change.

Schedule edit 

Article Comments

Reader comments can be switched on and off for a whole publication, for a particular article type, or for each individual article. You can also take advantage of Campsite's management features to moderate (or bypass moderation for) comments from subscribers, or members of the general public.

Comment settings in the Publication List

To set the default comment setting at the publication level, go to Content on the main navigation menu, and then click Publications. In the Comments enabled column of the Publication List page which appears, publications in which readers can post comments are shown with a green light icon. Click on the Configure icon for the publication you wish to enable or disable comments for.

Configure publication comments

This action opens the Configure publication page. In the Comments section, there is a checkbox labeled Comments enabled? and a variety of options which enable you to fine-tune comment settings.

Configure publication

Comment settings for article types

Perhaps you want to enable comments for all articles of a particular type, for example blog, but not enable them for another type, such as news_article. Click Configure in the main navigation menu, and then click Article Types from the submenu. On the Article Types page which appears, clicking the red or green light icon in the Comments enabled? column toggles the setting for each article type.

Article type comments


After you click on a green light icon, you will be asked if you are sure you want to deactivate comments for that article type.

Comments - are you sure?

 

Comment settings for individual articles

Comments can be enabled or disabled for a number of individual articles at once, using the Article list page. Click Content on the main navigation menu, then use the submenus to navigate to the publication, issue and section that you require. In the Article list page that appears, use the checkboxes in the left side column to select the articles you want to enable or disable comments for. Then use the drop-down Actions menu and click on Toggle: 'Comments'.

Article list toggle comments

Moderating comments

To prevent spam or defamatory posts from appearing in your online publication, it's often necessary to moderate comments from readers before they are published. A CAPTCHA can prevent some automated spam, but it cannot prevent spam being entered into your publication's comment form manually.

Example comment

 

If you have configured your publication so that subscriber or public comments are moderated, the reader will see a message indicating that their comment has been sent for approval before it will be published - or not, as the case may be.

Comment approval 

 

The list of reader comments can be found by clicking Content, then Comments, on the main navigation menu.

Content comments

 

On the left hand side of the Comments page are two tabs; one for New comments, and one for Published comments. The New tab is the default, and beneath this any new comments are listed. The default list length is 20 comments per page. There is a Search field to help you find a specific range of comments, perhaps on a topical subject. Search results can be sorted by Date posted, Article name, Author or Thread, using the drop-down menu to the right of the Search field. The sort direction can be changed by clicking on the blue arrow icon next to the drop-down menu.

New comment list

 

On the right-hand side of the Comments page is an area displaying the text and metadata of the current comment under review, as indicated by a small yellow arrow icon in the comment list.

Comment edit field

 

A row of radio buttons above the comment text enable you to update the New comment's status to Approved, or Delete if it is spam. Alternatively, the comment can be hidden, or the user that made the comment banned from the publication. Clicking the Show article link, next to the magnifying glass icon, enables you to see the comment in the context of the original article. You can also click on the Article link to open the Edit article page for that particular story.

System Preferences

The System Preferences page is accessed via Configure in the main Campsite navigation menu.

Configure system preferences

This page allows you to control some advanced aspects of your Campsite server, so it is recommended that access is reserved for administrators only.

General Settings

The first section of the System Preferences page is for General Settings.

General settings

Here is what each of the options means:

Editor Settings

The second section of the page is for Editor Settings, which refer to image handling.

Editor settings 

The fields in this section enable you to specify the default resize ratio, or default width and height, for images in articles. If the Zoom enabled for images in article content? radio button is set to Yes, readers can enlarge article images in your publication's pages by clicking on them.

External subscription management

The third section down is related to external subscription management software.

External subscription management

If you select the Yes radio button for the Reader subscriptions managed externally? option, the subscription management features in the Campsite administration interface are hidden. The subscription data is still held in the Campsite database, which your systems administrator will have connected to your third-party subscription management software.

Database replication server

The fourth section enables you to set up Campsite to operate on two servers at once, which is a safety feature in case of hardware or network problems. 

Replication server

Selecting the Yes radio button for the option Setting up a Campsite Replication Server? displays four fields:

Using a Campcaster media library

The fifth section enables you to attach media in a Campcaster storage server to articles in your Campsite publication. Once you've installed and configured Campcaster according to the manual at http://en.flossmanuals.net/Campcaster, create a user in the Campcaster administration interface and add it to the Admins group.

Audio attachments

Back in the Campsite System Preferences page, select the Yes radio button for the option Enable Campcaster audioclip attachments? Below, you should enter the host name or IP address of the Campcaster server. The values of the fields Port, XML RPC Path and XML RPC File should already be filled in with the default values. You don't need to edit these default values, unless you have a custom Campcaster configuration.

The last step is to give certain users the right to attach audio clips to articles. You can edit a Staff User Type to enable this, so that all users of this type will receive the right automatically. Alternatively, you can enable this right for individual staff user accounts.

Other options

At the end of the System Preferences page are two further options.

Misc settings 

Finally, the Save button updates your preferences.

Templates

Templates control the look and feel of your Campsite publication. Each publication has a unique template created by your web developer, which should have already been installed by your system administrator. The Campsite administration interface includes a template management and editing tool, which you can find by clicking Configure on the main navigation menu, then Templates.

Configure templates

 

Templates are organized into folders, shown in a box on the left hand side of the page.

Templates page 

 

Clicking on the name of a folder shows the files included in that template.

Classic template

 

In turn, clicking on a file name opens that file in the template editor. This feature enables web developers to make quick changes to templates on a running Campsite system.

Article template editor

 

You should only make changes to the templates if you know what you are doing, because any modifications will have an immediate impact on the appearance of your publication. However, this feature is useful for editing templates on a development server before they are copied to the publication's production server.

Article Types

Article Types specify the information that Campsite will require from the journalists adding a particular kind of article to your publication. For example, a feature story is likely to require more elements than a brief news item. By default, Campsite has one Article Type set up, which is News Article, but you can create as many as you need. To create or manage your Article Types, select Configure, then Article Types from the main navigation menu. This action opens the Article Types page.

Article types menu 

Article Types consist of a sequence of fields, with each field holding a certain kind of data. Currently, there are six kinds of fields available:

Campsite makes a distinction between the Template Name and Display Name for each Article Type and field. The Template Name is limited to letters, numbers, and underscores (no spaces) and is used internally by your Campsite template. The Display Name is the part that the journalist will see, and can be translated into other languages.

Adding a new Article Type

Click the Add new article type link at the top left of the Article Types page.

Article Types

The Add new article type page will appear. The first step is to enter the Template Name of the Article Type you wish to create. In this example, we'll create an Article Type with the template name review_article - note that it has an underscore, instead of a space, between the words review and article.

Article type name
 
After you click the Save button, you will be prompted to enter the Template Name of the first field in the new Article Type. Select one of the six field types available from the drop-down menu, for example Topic. For this particular field type, we'll also have to select a top level element, such as Entertainment / Review.

Add new field
After clicking the Save button, the Article type fields page is shown. The Article Type that you are currently working on is shown in the breadcrumb trail beneath the main navigation menu.

Article field types 

Click on the Show display names link to add a Display Name for this new field. Select the language you require from the Add translation drop-down menu, and enter the display name for the new field in this language. Then click the blue Translate button.

Add translation 

The Article type fields page will now show the Display Name for the field, together with a language code (in brackets) to indicate its translation. Note that the Display Name can contain spaces, or be capitalized differently from the Template Name for the field.

Field translated

Continue to add new fields to this Article Type, until you have all that you need. Then click the link Back to Article Types List, next to the blue arrowhead icon. This action will return you to the Article Types page.

Editing Article Types

You can add translated Display Names for your new Article Type after clicking on the Show display names link in the Article Types List.

Translate type

Article Types are not set in stone; they can evolve as your publication evolves. For example, you can hide old Article Types that are no longer in use. Toggle whether a type is shown by clicking on the colored light icon in the Show/Hide column - green for shown, red for hidden. A pop-up dialog will ask you if you are sure about this action.

Are you sure?

Hiding a type is less dangerous than deleting it; the latter action will remove the associated content from the server. The delete button is a white cross in a red square icon, over on the right side of the page. Use this button with caution!

Delete button 

As usual when carrying out an action that will have an impact on your publication, Campsite will ask you if you are sure.

Are you sure you want to delete?

In the Article Types List there is also a Comments enabled? column, which toggles readers comments on and off for a specific Article Type. For example, you might wish to disable reader comments for all entertainment reviews, but leave them enabled for news articles.

Article types can be renamed, simply by clicking on the Template Name in the Article Types page. Remember that if you change a Template Name, you cannot put spaces into it.

Rename article type

Editing Article Type Fields

On the Article Type Fields page, fields can be renamed, given Display Names, hidden or deleted, just like Article Types. When you have more than one Article Type field, you can re-arrange the order in which the fields show up on the Edit article page by clicking the blue up and down arrows.

Up and down arrows 

To change a field type, for example, from Single-line Text to Multi-line Text with WYSIWYG, click on the corresponding link for that row in the Type column. The Reassign a field type page will open, on which you can select the new type from a drop-down menu. Then click the Save button to return to the Article type fields page.

Reassign field type

After editing article type fields, you could create a new article to test that the updated fields are displayed as expected.

Test fields

Merging Article Types

Campsite enables you to merge two different Article Types so that content in fields from one type (the Source Article Type) is migrated to another (the Destination Article Type). This is a useful process to go through after adding or editing an Article Type, so that all previously written copy matches the new Article Type fields.

On the Article Types page, click the Merge types link. This opens the Merge article type page. Select the source and destination Article Types you wish to merge from the drop-down menus.

Merge step 1

Next, choose the fields of the source which you'd like to merge into fields of the destination.

 Merge step 2

The next screen displays the result of the potential merge. Any source fields which have not been mapped to destination fields are shown in a red font. You may need to create additional fields in the destination Article Type before attempting a merge.

You can cycle through all the articles which will be merged, and preview the changes. Optionally, check the box to Delete the source article type. When you're ready, click the Merge button.

Merge step 3
If there are no articles left belonging to the Source Article Type, Campsite will display a warning message at the first step of the proposed merge.

No articles

Topics

In Campsite, topics are the subject matters assigned by editors and journalists to articles, so that related articles can be identified and displayed together. A topic can have many subtopics; for example: the sports topic could have the subtopics football, basketball, and water polo. An individual article may have several topics or subtopics assigned to it.

To review or create topics, click Configure on the main navigation menu, then click Topics from the sub-menu.

Configure Topics

To add a new top-level topic, select a language from the drop-down menu and enter a word in the Add root topic field. Then click the Add button.

Add root topic

To rename a topic, click the Edit link to the right of the topic or subtopic name. The name row will expand to show the Change topic name field. Update the name, and then click the Save button.

Rename topic 

You can translate topic names so that they appear in the correct language when an author is editing an article. To translate a topic, click the Edit link to display the Add Translation field for that topic name. Select the language you are translating into from the drop-down menu, enter the translation of the topic name, and then click the Translate button.

Translate topic


If you translate a subtopic and its parent has not yet been translated, the parent topic will appear in its original language until you translate it.

To add a subtopic, click the Edit link next to the topic you want to put the subtopic under. Enter a word or two into the Add Subtopic field, then click the Add button.

Add subtopic 

The new subtopic will appear underneath its parent topic.

Subtopic displayed

You can delete a specific topic or subtopic using the blue cross in a white square icon, on the right hand side of its row. However, you cannot delete a topic currently in use by articles, or a topic that has any subtopics remaining. Campsite will remind you if this is the case.

Deleting topic

Languages

While Campsite's default language is English, you are by no means limited to publishing in that language only. Click Configure on the main navigation menu, then Languages from the submenu, to see the languages currently available on the system.

Configure languages

The Language page enables you to configure support for languages that you wish to publish in. The Code column refers to the two-letter ISO 639-1 code name for each language. English, for example, is en, German is de, Spanish is es, Chinese is zh and so on.

Languages list

Click on a name in the Language column to open a page for that language, which enables you to adjust month, day and time name translations. This feature ensures that automatically generated publication dates and times for an article in a particular language are displayed correctly to your international readers.

Edit language


To add another language, click on the Add new language link, next to the green cross icon. You should enter the language name (both in English and in the language itself), and its code (e.g. cy for Welsh).

Add new language 

After entering translations in all the fields, click the Save button at the end of the page. The new language will now be shown on the Languages page.

Language added

You may wish to limit the number of languages configured on your server, in order to spare your editors and journalists from having to navigate long drop-down language menus. To remove a language, click the white cross in a red square icon at the end of each row in the list. You will be asked if you are sure about this action.

Confirm language deletion 

Countries

This page determines how country lists will appear in forms that readers fill in, for example when signing up for an email newsletter. It also enables you to create country lists in different languages. To see the list of country names in the default language, click Configure on the main navigation menu, then Countries on the submenu.

Configure countries 

The Countries page shows an alphabetical list of countries, with the language they are displayed in, and a two-letter ISO 3166-1 country code for each name. Note that the alphabetical sorting is by the country code, rather than by the country name.

Country list

Click on the name of a country to rename it, then click the Save button to return to the country list.

Edit country name 

To translate a specific country name into a particular language, click the Translate link in that country's row in the list. In the Translate country name page, select the target language from the drop-down menu, and enter the translation into the Name field. Then click the Save button.

Translate country name

To find your translated country names later, use the drop-down Language menu at the top of the Country page to select the language you are interested in, and then click the Search button. The search results, if any, will be listed below the Search box.

List country translations

Campsite's list includes almost all known countries by default, but if you have deleted a country and need to put it back, you can do this by clicking on the Add new country link next to the green cross icon. You will be prompted to enter the country's two-letter ISO code, name and language. The drop-down menu will contain as many languages as you have defined in Campsite's Configure - Languages page.

Add new country

Note that the language you are asked to specify is the language in which you are entering a country's name, not the language spoken in the country.

The Localizer

The default language for the Campsite administration interface is English, but you can either use one of the many translations supplied with Campsite, or create your own translation using the built-in Localizer tool. You can also use the Localizer to improve an existing translation, or adapt it for a regional dialect.

The first step is to check that the language you wish to translate into is in the Configure - Languages list. If your target language does not exist yet, you will have to add it to Campsite first. Then, you can open the Localizer by clicking Configure - Localizer on the main navigation menu.

Configure localizer

The Localizer works by enabling you to translate individual 'strings' of text that appear in the Campsite administration interface. There are around 1893 strings in the whole of Campsite, divided into 36 Screens representing the various different pages in the interface. You can complete a localization with a team of translators working together, by tackling one screen each at a time.

The Localizer

Select your source (Translate from) and target (Translate to) languages from the drop-down menus, and then select a Screen, such as Universal List or Article Types. Strings that have not yet been translated are shown in a red font. You can save your work at any time by clicking the disk icon next to one of the input fields. When you have completed your translation, there is a Save button at the end of the page.

Variables in strings

You will encounter strings with a dollar sign in them, e.g. "$1". This means that one or more words will be substituted in place of these characters. For example, the phrase "Signed in: $1", when printed out on the interface, might be: "Signed in: Administrator". In this example, "Administrator" was substituted for "$1".

TinyMCE, the WYSIWYG article editor incorporated into Campsite, can also be localized. The strings in TinyMCE have to be edited manually by your system administrator, which is a task done separately from the Localizer.

Sending a Localization back to the Campsite Team

We actively encourage Campsite users to send us their language localizations. This makes Campsite more useful for people around the world. Even if a similar language localization exists, it may not address your particular needs or regional differences. For example, there may be differences in Spanish between that used in Spain and that used in Guatemala. In that case, you can localize Campsite to your needs and share the localization with other users that speak your language or dialect.

For more information on how to contribute a localization to Campsite, please email contact@sourcefabric.org

Logs

The Campsite administration interface includes a feature which enables you to keep track of who has done what, and when, on your publication's server. You can examine Campsite's log files by clicking Configure on the main navigation menu, then Logs.

Configure logs

 

The default log view displays all recent events on the Campsite server, with 15 listings per page, and the most recent events first. Click the Next link or page number just above the search results box to see previous pages. Like most features in Campsite, the Logs page is multilingual, so you may see log entries in languages other than your own.

Logs page 

To examine the logs selectively, use the Event drop-down menu above the search results box to select a particular action; for example, Add Article. Then click the Search button, and the Logs page will be refreshed to list events corresponding to that action exclusively.

Search logs

User Management

Campsite's user management allows you to control access to the backend and the frontend of your publication(s). Backend users are called Staff users and frontend users are called Subscribers.  You can define roles for your staff members, such as Journalist and Editor.  The interface will change for each user depending on which permissions they have enabled.  For example, a journalist will have a more simple interface than an editor.

Your subscribers are most likely paying for access to your content.  When you edit an article, you have to option to make the article only viewable to subscribers.

IMPORTANT: Initially, the Campsite demo packages have only one user: admin with admn00 password. Make sure to change the password as soon as possible.  Also, do not delete this user as it is needed by the email script which informs Staff users of events in the system. You should set the email address of "admin" after installation because it is used as "Reply-To" address in the notification emails.

 

Creating User Types

A user type is generally defined by the list of the tasks a user is allowed to do in a system. In Campsite, this list of tasks ranges from creating, managing, and editing publications, sections, and articles, to template management and definition of the publishing environment.

To simplify user management, Campsite allows you to create generic user types, which can then be assigned to multiple users, instead of taking care of every single access right for every single user.

Campsite comes "out of the box" with three default user types:

To create your custom user profiles, select 'Users'->'Staff User Types' from the main menu:

 

and then select 'Add new user type'.  Proceed to select the rights that you want included for this type of user.

 

Creating Staff Users

To add a user, select Users->Staff from the main menu:

1129147084_2StaffMainMenu.png

and then choose 'Add new user account'.  You will see this screen:

1129147761_2StaffUserAdd.png

You should specify the full name of the user, user name, password, and choose a predefined user type (i.e. one of the default types or your custom user types).

If you would like to further fine tune the rights assigned to a particular user, go to Users->Staff and click on the user name you wish to edit.

 

Setting up Subscriptions

In this section:

Campsite allows you to control public access to your publication(s) through its built-in subscription module.

[TIP: If you want to have all your content freely accessible, you can bypass this feature by structuring your templates in a special way. For more information see "Creating Templates for your Publication" chapter.]

For now, you should know that all articles you create in your publication(s) are by default available to subscribers only. Publication editors or administrators have the right to make an article accessible to non-subscribers.

The way it works from readers' side is as follows: If a reader tries to access a non-public article, she is informed that she is not allowed to read the article but is provided with an option to subscribe immediately to that article or other articles or the whole publication. A temporary subscription is activated immediately (the duration of that temporary subscription is determined by the value you set for the 'Pay Time', For more information, see "Creating a Publication" chapter). During this period, the reader has a chance to effect the payment and consequently have her subscription extended by the administrator.

The publication's administrator is automatically notified of all new subscriptions by e-mail. Subscribers also receive automatically generated e-mail reminders that their subscription is expiring 14 days before the event.

[NOTE: The text of the subscription-expiry message is hard coded in the current version of Campsite and it reads as follows:

"Dear <reader>,

This is an automatically generated e-mail message. Your <subs_type> subscription (started on <start_date>) to publication <publication> will expire on <date> (in <number> days).

Please enter the site http://<pub_site&gt; to update subscription."

Future versions of Campsite will allow for customization of the message and for its translation into multiple languages.]

Campsite allows you to control access to your site in two ways:

  • Standard UserName:Password pairs, which is suitable for individual users
  • IP Address access, which most institutional subscribers (libraries, universities, NGOs, companies, etc.) tend to prefer

As Campsite handles subscriptions at the publication level, all subscription-related variables are customizable from the Publication Configure screen:

1143209341_3configure_publication.png
 

First you have to select a time unit for your subscriptions; the time unit can be: days, months, weeks and years.

You can set two types of subscriptions: paid and trial. Paid subscriptions have the following properties:

  • Currency: the publication's currency. Even if the subscription request is sent and the currency is changed meanwhile, the information about the user's debt is correctly recorded.
  • Time unit cost per one section:
    • for one language: the price for access to a section in a single language
    • for all languages: the price for access to a section in all available languages
  • Default time period: the default duration of the paid subscription. This value is used whe a reader subscribes through the frontend (site). The period for a certain subscription can be modified however from the administration interface.

You can specify different default time periods for individual countries if you like. To do so, click on "Countries defaults".  You will then have the option to "Add new country", i.e. create subscription preferences for a given country.

 

Username/Password Access

Campsite allows readers to subscribe to one publication at a time. Within a publication itself, the level of subscription is the section. The reader is able to select any section from the list of the publication's sections, and for each of them specify the period of time he would like to have a subscription for.

Before submitting his request, the user (reader) can evaluate the cost of the subscription and change it. At any time later, he can subscribe to additional sections. Once the user has subscribed to a section, he can't increase the period of time for the subscription until payment is done for that section.

Immediately after the completion of the subscription form, the reader has the right to view the site. By default, the reader has seven days to make a payment and have his subscription confirmed by the administrator or else the account is locked.

The authorized person can confirm the payment, so that the subscription remains active after the first 7 days. There are two options in the administration module for that: change the value of the amount that the subscriber has to pay, or change the number of days the subscriber is allowed to surf the publication's site. By default, if this sum is set to 0 (zero), the number of paid days is automatically set to the number of requested days.

The administrator (or any other user who has the rights to manage publications) has 7 days to confirm the payment. The confirmation is made from the main menu, by selecting User and then Subscriptions. The confirmation consists in changing the payment status (from 'no' to 'yes').

 

IP Address Subscriptions

The IP based access can be used to automatically log in users that have known IP addresses that never change. Examples of this are libraries, colleges, schools etc. The IP address-based access works by recognizing a computer as owned by a certain subscriber based on the computer's IP address. Subscribers with IP address-based access will be allowed to accesss the site without being prompted for user names and passwords.


To create an IP-Address subscription, go to the Subscribers screen:

 1129147133_2SubscribersMainMenu.png

You will get to a screen that looks something like this:

1129147118_2SubscriberList.png

 

First create a regular user by clicking on "Add new user account", edit it by clicking on the "Full Name" link in the subscriber list and click on "Add new" link in "User IP access list management" table (see image number 3). The form allows the input of a group of consecutive IP addresses. If necessary, more groups can be added. The start IP address is the smallest address in the group, while the number of addresses sets the size of the group.

1138377639_3add_ip_access_group.png 

For example, if a university library had a group of IP addresses: 120.120.120.0 to 120.120.120.63 then you would fill in:

It is not necessary to add anything to the templates or to inform the users who will be accessing the site through IP address authentication of the existence of this User Name/Password pair.

It is possible to search for users based their IP addresses. In the subscribers list fill in at least one box in the field named "IP address" from left to right. The administration screen will display all readers that have IP addresses matching the input. For example, if we had two clients, one with IP access group: 120.120.120.0:64 (start IP address 120.120.120.0, 64 addresses), the other one with IP access group: 120.120.140.0:64 then we will have the following results:

 

Customizing the Subscription Form

The subscription interface for the user is customizable. Depending on the user's status, several steps must be taken by a user in order to be able to read the publication. There are three possible scenarios:

The template designer can customize all those forms by means of Campsite's template language.

Plugins

Plugins enable your system administrator to add functionality to your Campsite installation without having to write a large amount of code. They can also enable you to make better use of the content and templates already in your Campsite publication. Currently, there are three plugins installed by default with Campsite:
  • Polls: A mechanism for site visitors to vote on a question; the question can be set dynamically and can be multilingual
  • Interviews: Enables on-line interviews for your Campsite publication; users have to refresh the page regularly to get the latest questions and answers
  • Blogs: Enables users to create and post to their own blogs, including comments

Installing new plugins

Plugins can be found on the Campsite SourceForge page. Once they are downloaded to a local hard disk, they can be uploaded to your Campsite instance. Log in to your admin interface and go to Plugins -> Manage Plugins. From there you can select the plugin to be uploaded. Plugins must be uploaded to the Campsite instance as a .tar archive.

Selecting 'Manage Plugins' pulldown menu also provides you with a list of installed plugins; there is a check box to disable the plugin and a red X to delete the plugin from your system. Once a plugin is correctly installed, you will be able to administer it separately from the Plugins pulldown menu.

Plugins require changes to your site's templates, but each plugin also includes sample templates to either copy and paste or to use as a guide to your own templating.

 

Creating Templates For Your Publication

In this chapter:


When implementing Campsite, chances are you will already have a rather clear outline of the structure of your publication online, or - even better - have a running web version already in HTML. Either way, to migrate your publication to Campsite you will have to generate customized templates for your content. Such templates will be incorporating the Campsite tags used to pull information from the database into the HTML page.

The following sections will guide you step by step through the process of generating such templates. Before proceeding, you should layout your site design.  This can be done in many ways, including sketching your design on paper, or using an HTML editor.  However, the design of web pages is outside the scope of this document. 

One of the main goals of Campsite is to offer a fully customizable layout for online publications and at the same time keep the content independent of the layout. This is done by means of templates. Those templates are nothing more than HTML files containing embedded Campsite description-language tags, which creates the link between the view and the content.

Templates are in-between your content database and your audience on the web. Therefore they need to mediate between both. The database needs to understand what information is requested, and the user's browser needs to retrieve a finished HTML page.

The template sets the stage, passing specific environmental information to the database query, such as: "list only articles from current issue and section 'sports'." At the same time, it gives detailed instructions on how content should be displayed in HTML format. This distinction between environment and content is crucial for understanding and building templates. The template language was designed to be usable on different levels of dynamic features: one can make static templates for every issue, section, article or just a few customized templates that generate different views depending on the given parameters.

The following will cover some examples on how to build templates. Further down you can find a complete list of available commands used by Campsite templates.


Template Quickstart Guide: "How do I..."

In this chapter:
  1. How to create a list of the most popular articles in a section
  2. How to create breadcrumbs
  3. How to do article pagination?
  4. How to display the most recently published articles?
  5. How to make a hard-coded link to an article?
  6. How to check if there are any articles in a section?
  7. How to display content based on the day of the weeek or date
  8. How to add an audio player, playing mp3-files attached to an article

 

Dive right in to the template language using the examples provided here.  These examples are meant to answer the most of the basic "getting started" questions laid out as questions in the form of "How do I...<do something>".


If you are looking for more in-depth information on templates, see "Templates In-depth" chapter.

 

1. How to Create a List of the Most Popular Articles in a Section

The following code snippet works insiction or article page and will display links to the most popular articles in this section.

<?
<ul>
{{ list_articles length=5 order="byPopularity desc"}}
<li><a href="{{ uri }}">{{ $campsite->article->name }}</a></li>
{{ /list_articles }}
</ul>
?>

 

2. How to Create Breadcrumbs

The easiest way to make breadcrumbs is following the two level structure of "Home" and "Section" and create something like this:

<?
<a href="{{ uri options="publication" }}">Home</a>
&gt;
<a href="{{ uri options="section" }}">{{ $campsite->section->name }}</a>
?>

This will first display the link to the home page and then the link to the current section where you are. Include this breadcrumb in your section page.

If you run an issue driven magazine, you might even add an additional level to your breadcrumbs: the current issue:

<?
<a href="{{ uri options="publication" }}">Home</a>
&gt;
<a href="{{ uri options="issue" }}">{{ $campsite->issue->name }}</a>
&gt;
<a href="{{ uri options="section" }}">{{ $campsite->section->name }}</a>
?>

 

3. How to do article pagination?

This example will show you how to split an article on multiple pages. We assume the article type is fastnews and has three fields: date (date field type), intro (body field type) and Full_text (body field type). You'll find this example implemented in the Campsite demo package here. The field Full_text is the one that contains the pagination (subheads).

Here is the code:

{{ list_subtitles field_name="Full_text" }}
  <p>
 {{ if $campsite->article->full_text->subtitle_is_current }}
    <b>{{ $campsite->current_list->index }}. {{ $campsite->subtitle->name }}</b>
  {{ else }}
    <a href="{{ uri }}">{{ $campsite->current_list->index }}. {{ $campsite->subtitle->name }}</a>
  {{ /if }}
  </p>
{{ /list_subtitles }}
<p>View subtitle:
{{ if $campsite->article->full_text->has_previous_subtitles }}
  <a href="{{ uri options="previous_subtitle full_text" }}">Previous</a>
{{ else }}
  Previous
{{ /if }}
|
{{ if $campsite->article->full_text->has_next_subtitles }}
  <a href="{{ uri options="next_subtitle full_text" }}">Next</a>
{{ else }}
  Next
{{ /if }}
|
{{ if $campsite->article->full_text->has_next_subtitles || $campsite->article->full_text->has_previous_subtitles }}
  <a href="{{ uri options="all_subtitles full_text" }}">All</a>
{{ else }}
  All
{{ /if }}
</p>
<p>{{ $campsite->article->full_text }}</p>

Lines 1-9 display the list of article subtitles (see "List of Subtitles" in "Template Language Reference" chapter):

Lines 11-27 create links to navigate to the previous or next subtitle (uri options="previous_subtitle full_text", uri options="previous_subtitle full_text"), or to display all subtitles (uri options="all_subtitles full_text").

Line 29 displays the actual article content, in this case the current subtitle ($campsite->article->full_text).

The example given above will make your page look something like this:

1210427881_3article_pagination_1.jpg 

4. How to display the most recently published articles?

This example will show you how to list the most recent news.  It also demonstrates how to display an image that is linked to an article, and how to make a hyperlink to an article.

The example given below will make your page look something like this:

1124982377_1Screenshot_4.png

 

Note: CSS styles have been removed from the example below to make it easier to read, so if you use the code below, it will not look exactly as shown above; the colors will not be there, and the spacing will be a bit different.

 

{{ local }}
{{ set_current_issue }}
{{ unset_section }}

<!-- Display all news articles on the front page, most recent first -->
{{ list_articles length="10" constraints="type is news OnFrontPage is on" order="bydate desc" }}
  {{ if $campsite->current_list->at_beginning }}
    <table width="100%">
  {{ /if }}
       
  <tr>
  <td valign="top" align="left">
      <!-- Article date -->
       {{ $campsite->article->publish_date | camp_date_format:"%M %d, %Y" }}
      <br />

     
<!-- Article Headline -->

     
<a href="{{ uri }}">{{ $campsite->article->name }}</a>
      <br />

     
<!-- Article Intro -->

      {{ $campsite->article->intro }}
      <br />

     
<!-- Read more -->

     
<a href="{{ uri }}"><nobreak>Read
More...</nobreak></a>
    </td>

   
<td valign="top" align="right">
     
<!-- Optional image -->


      {{ if $campsite->article->has_image(1) }}
     
<img src="../{{ uri options="image 1" }}"
border="0">

      {{ /if }}

    </td>
  </tr>
  {{ if $campsite->current_list->at_end }}
    </table>
  {{ /if }}
<!-- END Article -->
{{ /list_articles }}
{{ /local }}

5. How to make a hard-coded link to an article?

To make a hard-coded link to an article, do the following (replacing the values with the values for your particular article).  This will make a link to an "About Us" page:

{{ local }}
{{ set_issue number="1" }}
{{ set_section number="5" }}
{{ set_article name="About Us" }}
<a href="{{ uri }}">About Us</a>
{{ /local }} 

6. How to check if there are any articles in a section?

This example shows you how to do something only if there is at least one article in a section.  In the example below, substitute the name of your article type for "news". This also assumes that publication, issue, and section variables have been set already.

{{ list_articles constraints="type is news OnSection is On }}
    {{ if $campsite->current_list->at_beginning }}
        {{ $campsite->section->name }}
    {{ /if }}
{{ /list_articles }} 

7. How to display content based on the day of the weeek or date 

To invoke a certain action within templates (e.g. display a particular article headline) you can use the following smarty code:

{{ if $smarty.now|date_format:'%l' == 'Monday' }}
{{ $campsite->article->name }}
{{ /if }}

 or in the case of lower case comparison:

{{ if $smarty.now|date_format:'%l'|lower == 'monday'  }}
{{ $campsite->article->name }}
{{ /if }}

Furthermore, you can use all smarty  date_format conversion specifiers for this or similar purpose:

 

8. How to add an audio player, playing mp3-files attached to an article

By using a combination of the list of articles and the uri options, you can create a playlist of files which are attached to an article. This is the code I used:

<?smarty
{{ list_article_attachments }}
 {{ if $campsite->current_list->at_beginning }}
 {{ /if }}
 {{ if $campsite->attachment->extension == "mp3" }}
<div  <param name="movie" value="/templates/radioactive/apps/player_mp3_maxi.swf" />
 <param name="bgcolor" value="#444444"/>
 <param name="FlashVars" value="mp3={{ uri options="articleattachment" }}" />
<!-- player home: http://flash-mp3-player.net/ -->
</object>
 {{ /if }}
{{ /list_article_attachments }}
?> 

Note that there is a special if condition: checking if the attached file is actually an mp3 file. If you want to play with this, you could extend this and e.g. also embed flv video players or other embedded objects according to the mime-type (i.e. ending) of the attached file.

Templating tricks with Smarty

Here are some tricks, using Smarty in the Campsite templates:


Check if the field is totally empty, i.e. no tags or whitespaces either:

{{ if trim(strip_tags($campsite->article->insert)) !== '' }}
                <ul class="articleList sidebar extLinks">
                    <li class="level-4 extLinks">
{{ $campsite->article->insert }}
                    </li>
               </ul>
{{ /if }}

 

Templates In-depth

In this chapter:

 

This section is an in-depth guide to the templates. 

 

Modular structure of templates

A glance at all articles of an online publication reveals that generally there are many layout similarities even across different sections of the publication. Taking advantage of such similarities is what the template structure of Campsite was meant to do. In other words: design features that remain the same for all articles only need to be specified once, e.g. the navigation from an article back to section and home, font type and size, background color and the like.

On the other hand, there are article components that vary between articles. For example, the top of the article might contain some specific logo to indicate which section it belongs to. In such a case, the templates are designed to work in a modular fashion, allowing you to call up templates within templates.

The modular structure of the templates can be illustrated well by the following example: If background color, font size and type are the same for all articles, they will be specified as plain HTML in the template. But differences between sections will be indicated within the structure of the template (see below) indicating "if this article belongs to the politics section, insert such-and-such template here, if it is sports, insert such-and-such, else: just use the following."

Templates can be stacked within each other. A template can be made to call another template and include the layout information at the position where it was called in the main template. The easiest way to illustrate this modular structure is by looking at a usual tree structure of folders on a computer. Starting from general categories, the deeper the structure, the more precise and specific the folder names and information.

The modular structure was introduced to keep redundancy to zero and therefore the layout work minimal. Any design changes need to be made only once in the templates, never even twice, if you make full use of this modularity potential.

 

Building a Navigation Template

As described above, the template structure can be nested, meaning one template can call another template. This, for example, makes a lot of sense for the navigation. To jump between sections, you might only need one navigation template that can be used by all other templates (article, section, home page).

To nest another template within another, use the following Campsite tag:

{{ include file="navigationtemplate.tpl" }}

The 'include' command is Campsite lingo; the name of the template needs to be adjusted to whatever you called it. Let's assume we add this tag in the article template we created earlier, and we can now go on and build the template.

First thing to do when you are building something like the navigation is to take control over the environmental variables. Our navigation needs to follow some standard rules and should not be affected too much by the environmental setting of the current position of the user.

In terms of Campsite lingo, we need to introduce a 'local' tag, which allows us to specify some environmental variables for a local section inside the template. In other words, we can switch off the environmental variables, set our own and then switch them on again. In that way we can use the same template for the navigation for all articles, sections, even issues (not publications, obviously).

In order to make sure you enter the current issue in the navigation bar, set the environment variables to:

{{ local }}{{ set_current_issue }}

Here, 'local' allows you to set the parameters inside a template to the values you want to be specified. Once the parser finds the '/local' tag, it will switch back to the environment variables it arrived with (for example a back issue).

Then the issue parameter is set to 'current'. This is done in order to make sure that the navigation will always jump to the 'section' (or whatever you want) of the current (latest published) issue.

Then you would need to specify which section you would want to link to. This is done with the 'section number' tag.

{{ set_section number="1" }}

The above tag would set the local section parameter to 1, which will be looked up in the Campsite database under section entries (each section is assigned a number when it is created, see chapter "Creating a section" of this manual).

Now we have set all necessary values for the link: we will link to section 1 in the current issue. All we need to do now is create the link to the section, or - to be more precise - the template that is used to build section pages.

<a href="{{ uri options="section" }}">NEWS</a>

This will create an ordinary link, using the anchor tag of HTML. This link will generate the URI for the section 1.

Finally, we need to end the local parameters with the tag:

{{ /local }}

A complete navigation template could look like this:

{{ local }}
{{ set_current_issue }}
{{ set_section number="1" }}
<a href="{{ uri options="section" }}">News</a><br>
{{ set_section number="2" }}
<a href="{{ uri options="section" }}">Politics</a><br>
{{ set_section number="3" }}
<a href="{{ uri options="section" }}">Sport</a><br>
{{ set_section number="4" }}
<a href="{{ uri options="section" }}">Weather</a><br>
{{ /local }}

Make sure that the section numbers assigned correlate with the names of the sections, as you assigned them when building the publication in the first place.

Now we can advance into a more conditional environment, the section pages.

Linking to Issues, Sections, and Articles

When building your navigation template, you will most likely want to link to internal content.  Two statements will help you do this: uri and uripath. You can find the full description at "Displaying the URL" in "Template Language Reference" chapter. These statements help you build a URL.  In the admin interface, you will assign each issue, section, and article a "URL Name".  These names are used to contruct a link like so:

http://test.com/en/may30/news/summer_is_coming

where:

To produce such a link you only have to write the following:

<a href="{{ uri }}">text</a>

This is equivalent to:

<a href="{{ uripath }}?{{ urlparameters }}">text</a>

uripath displays the 'path' part of the URI: /en/may30/news/summer_is_coming. urlparameters displays the rest of the parameters if any. uri combines both these statements. All these statements work for both old style URLs (named template path) and new type of URLs (named short name).

Creating Links to Issues, Sections, etc.

Use language, publication, issue, section and article arguments in order to specify the scope of the link. Suppose we are in the article template and we want to return to the last issue, current issue, section or article page.

<a href="{{ uri options="language" }}">text</a>
will display:

<a href=/en>text</a>

this will redirect us to the last published issue page.

<a href="{{ uri options="publication" }}">text</a>

will display:

<a href=/en>text</a>

this will redirect us to the last published issue page.

Publication argument has the same effect as language because short name URLs do not have the publication parameter in the URI. Instead, the publication is identified by the site name.

<a href="{{ uri options="issue" }}">text</a>

will display:

<a href=/en/may30>text</a>

this will take us to the current issue page.

<a href="{{ uri options="section" }}">text</a>

will display:

<a href=/en/may30/news>text</a>

this will take us to the current section page.

<a href="{{ uri options="article" }}">text</a>

will display:

<a href=/en/may30/summer_is_coming>text</a>

this will take us to the current article page.

Language, publication, issue, section and article arguments cannot be combined.

Creating a Link to a Template

Sometimes we may need to create a link to a template that is not an issue, section or article template; with short name URLs this can be done the following way:

<a href="{{ uri options="template login.tpl" }}">text</a>

will display:

<a href=/en/may30/summer_is_coming?tpl=tpl_id>text</a>

this will display the login.tpl template in the current context of variables (publication, language, issue etc.).

 

Building an Article Template

Building an article template is the easiest option. All you need to do is generate your HTML layout and substitute the dynamic sections (title, author, intro, text...) with the simple tag:

{{ $campsite->article->title }}

The command is 'print article'; the 'title' part varies. This is the name of the variable that you assigned when building the Article Types. So it could also read:

{{ $campsite->article->sportsitemdeck }}

As the rest of the HTML layout remains as it is, a simple template might look like this:

<body>
<h1>{{ $campsite->article->title }}</h1>
<h3>{{ $campsite->article->subtitle }}</h3>
<p><i>Written by {{ $campsite->article->authorname }}
   on the {{ $campsite->article->date }}</i><p>
{{ $campsite->article->text }}
</body>
</html>

The reason we can reduce the templates to such a simple solution is, because Campsite will remember where it comes from and where it is. So by the time the user arrives at one particular article, Campsite knows the publication, the issue, the section, and even the article ID and can simply generate the HTML page from the database by using the environmental variables together with the layout information in the template.

Obviously, your design can be far more advanced than this page. And Campsite can also perform far more advanced functions than this. In order to get a feel for this, let's jump into the next example, building the navigation. (A full list of tag commands can be found at the end of this chapter.)

Building a Section Template

In this article:
<h3

What's New In the Template Language In Version 3.0

In this chapter:

 

Template Engine Structure

The Campsite extension to Smarty will initialize objects that are specific to Campsite: article, section, issue, image etc. These objects are instantiated from meta classes (e.g. MetaArticle, MetaSection etc.) and use method call overloading for allowing the web designer to access object properties (see: http://www.php.net/manual/en/language.oop5.overloading.php). This way we won't expose the core Article, Section etc. objects to the web designer so he/she won't be able to play with the database. These meta classes will only implement the _ _get() method, _ _set() will be empty or throw an error. Meta classes will use the existing classes (Publication, Issue, Section etc.) to retrieve the data. Meta classes will also implement the method "defined()" that returns true if the object instantiated from the class was actually initialized.

The template engine will initialize the $campsite object, which stores the whole Campsite environment (meaning all template parameters, objects, properties etc.). The $campsite object has the following read/write properties:

and the following read-only properties:


Syntax Changes

Conventions

Environment Manipulating Statements

Set/Unset Statements

Old syntax:

1. <!** #statement# #attribute# #value#>⁞
2. <!** #statement# default>
3. <!** #statement# current>
4. <!** #statement# off>

New syntax:

1. {{ set_#statement# #attribute#="#value#" }}
2. {{ set_default_#statement# }}
3. {{ set_current_#statement# }}
4. {{ unset_#statement# }}

Local Statement

Old syntax:

<!** Local>
<!** EndLocal>

New syntax:

{{ local }}
{{ /local }}

Include Statement

We will use the include statement implemented in Smarty.

Exceptions

Old syntax:

1. <!** HTMLEncoding on>
2. <!** HTMLEncoding off>

New syntax:

1. {{ enable_html_encoding }}
2. {{ disable_html_encoding }}

Examples

<!** Article number 125>

changes to:

{{ set_article number="125" }}
<!** Article off>

changes to:

{{ unset_article }}

List Statements

Old syntax:

<!** List [length #value#] [columns #value#] #statement# [#contraints#]
          [order #order_constraints#]>
<!** ForEmptyList>
<!** EndList>

New syntax:

{{ list_#statement#s [name="#value#"] [length="#value#"] [columns="#value#"]
                     [constraints="#constraints#"] [order="#order_constraints#"] }}
{{ if $currentList->empty }}
{{ /if }}
{{ /list_#statement#s }}

Constraints will require a 'Constraint Parser'. The Constraint Parser has the following requirements:

 * constraints can contain variables
 * constraints can contain "&&"(AND) and "||" (OR)
 * constraints can contain parenthesis

Exceptions

Old syntax:

1. <!** List [length #value#] [columns #value#] ArticleAttachment ForCurrentLanguage>
2. <!** List [length #value#] [columns #value#] ArticleAttachment ForAllLanguages>
3. <!** List [length #value#] [columns #value#] Subtitle>

New syntax:

1. {{ list_article_attachments [name="#name#"] [length="#value#"]
                               [columns="#value#"] language="current" }}
2. {{ list_article_attachments [name="#name#"] [length="#value#"]
                               [columns="#value#"] language="all" }}
3. {{ list_subtitles [name="#name#"] [length="#value#"] [columns="#value#"]
                     [articleType="#value#"] field="#value#" }}

In the exception example 3 articleType and field attributes are read from "With" statement from the old template language.

If Statements

General Syntax

Old syntax:

1. <!** If [not] #statement# >
2. <!** If [not] #statement# #attribute# >
3. <!** If [not] #statement# #attribute# #value# >
4. <!** If [not] #statement# #attribute# #value# [#value#]+ >
5. <!** If [not] #statement# #attribute# #operator# #value# >
6. <!** If [not] #statement# #article_type# #attribute# #operator# #value# >

New syntax:

1. {{ if [!] $#statement# }}
2. {{ if [!] $#statement#->#attribute# }}
3. {{ if [!] ($#statement#->#attribute# == "#value#") }}
4. {{ if [!] ($#statement#->#attribute# == "#value#"
              [and $#statement#->#attribute# == "#value#"]+ ) }}
5. {{ if [!] ($#statement#->#attribute# #smarty_corresponding_operator# "#value#") }}
6. {{ if [!] ($#statement#->type->#article_type#->#attribute#
              #smarty_corresponding_operator# "#value#") }}

Exceptions

Old syntax:

1. <!** If [not] Allowed>
2. <!** If [not] Article upload_date #operator# #value# >
3. <!** If [not] Article has_keyword #value# >
4. <!** If [not] Article translated_to #value# >
5. <!** If [not] CurrentSubtitle >
6. <!** If [not] Image #value# >
7. <!** If [not] Login #attribute# >
8. <!** If [not] NextItems >
9. <!** If [not] PreviousItems >
10. <!** If [not] NextSubtitles >
11. <!** If [not] PrevSubtitles >
12. <!** If [not] Search #attribute# >
13. <!** If [not] User #attribute# >
14. <!** If [not] Subtitle number #operator# #value# >

New syntax:

1. {{ if [!] $article->content_accessible }}
2. {{ if [!] $article->creation_date #smarty_corresponding_operator# "#value#" }}
3. {{ if [!] $article->keyword == "#value#" }}
4. {{ if [!] $article->translationLang == "#value#" }}
5. {{ if [!] $article->subtitle->is_current }}
6. {{ if [!] $article->image_number == "#value#" }}
7. {{ if [!] $user->login_#attribute# }}
8. {{ if [!] $current_list->length gt $current_list->last_element->index }}
9. {{ if [!] $current_list->first_element->index gt 1 }}
10. {{ if [!] $current_list->length gt $current_list->last_element->index }}
11. {{ if [!] $current_list->first_element->index gt 1 }}
12. {{ if [!] $article->search#attribute# }}
13. {{ if [!] $user->subscription_#attribute# }}
14. {{ if [!] $article->subtitle->number #smarty_corresponding_operator# "#value#" }}

With Statement

This statement is not used anymore, see example 3 from "List" exceptions.

URL Statements

Old syntax:

<!** #statement# [#option#]+ >

New syntax:

{{ #statement# [options="[#option#]+"] }}

Where #statement# can be one of the following: URIPath, URLParameters, URI, URL, FormParameters?.

Date Statement

Old syntax:

1. <!** Date #attribute# >
2. <!** Date #date_format# >

New syntax:

1. {{ $smarty.now|camp_date_format:"#corresponding_smarty_date_part#" }}
2. {{ $smarty.now|camp_date_format:"#date_format#" }}

Print Statements

Old syntax:

1. <!** Print #statement# #attribute# >
2. <!** Print Article [#article_type#] #attribute# >
3. <!** Print #statement# #attribute# #date_format# >

New syntax:

1. {{ $#statement#->#attribute# }}
2. {{ $article->[type->#article_type#->]#attribute# }}
3. {{ $#statement#->#attribute#|camp_date_format:"#date_format#" }}

Exceptions

1. <!** Print ArticleAttachment #attribute# >
2. <!** Print ArticleComment #attribute# >
3. <!** Print ArticleComment readerEmailObfuscated >
4. <!** Print ArticleComment readerEmailPreviewObfuscated >
5. <!** Print Subtitle name >
6. <!** Print Image [#imageNumber#] #attribute# [#date_format#] >
7. <!** Print List #attribute# >
8. <!** Print Login error >
9. <!** Print Search #attribute# >
10. <!** Print Subscription #attribute# [#date_format#] >
1. {{ $article->attachment->#attribute# }}
2. {{ $article->comment->#attribute# }}
3. {{ $article->comment->reader_email|camp_obfuscate }}
4. {{ $article->comment->reader_email_preview|camp_obfuscate }}
5. {{ $article->subtitle->name }}
6. {{ $article->image[\[#imageNumber#\]]->#attribute#[|camp_date_format:"#date_format#"] }}
7. {{ $current_list->#attribute# }}
8. {{ $user->login->error_message }}
9. {{ $article->search->#attribute# }}
10. {{ $user->subscription->#attribute#[|camp_date_format:"#date_format#"] }}

{{ $article->title }}
{{ $article->type->data->intro }}

Form Statements

Old syntax:

1. <!** #statement# #template_name# #submit_button_name# >
2. <!** ArticleCommentForm #template_name# #submit_button_name# [#preview_button_name#] >
3. <!** Subscription #subscription_type# #template_name# #submit_button_name#
                     [#total_field_name# #evaluate_button_name#] >

New syntax:

1. {{ #statement#_form template="#template_name#" submit_button="#submit_button_name#" }}
2. {{ article_comment_form template="#template_name#" submit_button="#submit_button_name#"
                           [preview_button="#preview_button_name#"] }}
3. {{ subscription_form type="#subscription_type#" template="#template_name#"
                        submit_button="#submit_button_name#"
                        [total_field="#total_field_name#"]
                        [evaluate_field="#evaluate_button_name#"] }}

The statements that match rule 1 are: Login, Search and User.

Edit Statements

Old syntax:

1. <!** Edit #statement# #attribute# >
2. <!** Edit #statement# #attribute# #integer_value# >
3. <!** Edit #statement# #attribute# HTML #html_code# >

New syntax:

1. {{ camp_edit object="#statement#" attribute="#attribute#" }}
2. {{ camp_edit object="#statement#" attribute="#attribute#" }}
3. {{ camp_edit object="#statement#" attribute="#attribute#" html_code="#html_code#" }}

Select Statements⁞

Old syntax:

1. <!** Select #statement# #attribute# >
2. <!** Select User gender #male_name_string# #female_name_string# >

New syntax:

1. {{ camp_select object="#statement#" attribute="#attribute#" }}
2. {{ camp_select object="user" attribute="gender" male_name="#male_name_string#"
                  female_name="#female_name_string#" }}

Template Language Reference

In this chapter:

 

Language Elements; Conventions

In the following sub chapters describing the template language we used the following conventions:

The template language is composed out of:

Any value must be put in between double quotes (""). The double quote (") must be escaped any time it is used in an identifier. E.g.: escaping a value that contains quote:

{{ if $campsite->article->name == "Lucas \"the beast\"" }}

In some statements (usually lists) there is a special parameter named "constraints". This parameter describes conditions that can not be specified in the usual way:

parameter="value"

The constraints are specified in the following way:

constraints="<constraints_list>"

Constraints are built from the following expressions:

Attributes may have no type or one of the following types:

Every type has a list of valid operators that can be used on attributes of that certain type. The operators list corresponding to defined types:

Spaces in values must be escaped with backslash.

E.g.: constraints="topic is Global\ Warming:en"
In this case "Global Warming" is the topic name.

Basic Syntax

In this article:

The Campsite template engine was built upon Smarty so the Campsite template language is actually an extension of the Smarty template language. For details on the Smarty template language please go to this link: http://smarty.net/manual/en/smarty.for.designers.php

All template tags are enclosed within delimiters. By default these are { and }, but they can be changed. In Campsite we use {{ and }}.

For the examples in this manual, we will assume that you are using the default Campsite delimiters. All content outside of delimiters is displayed as static content, or unchanged. When the template engine encounters template tags, it attempts to interpret them, and displays the appropriate output in their place.

The following sub-chapters, which were copied from the Smarty manual, will familiarize you with the Smarty syntax.


Comments

Template comments are surrounded by asterisks, and that is surrounded by the delimiter tags like so:

{{* this is a comment *}}

Comments are NOT displayed in the final output of the template, unlike <!-- HTML comments -->. These are useful for making internal notes in the templates which no one will see ;-)

Example 3-1. Comments within a template

{{* I am a template comment, I don't exist in the compiled output  *}}
<html>
<head>
<title>{{$title}}</title>
</head>
<body>

{{* another single line comment  *}}
<!-- HTML comment that is sent to the browser -->

{{* this multiline
   comment is
   not sent to browser
*}}

{{*********************************************************
Multi line comment block with credits block
  @ author:         bg@example.com
  @ maintainer:     support@example.com
  @ para:           var that sets block style
  @ css:            the style output
**********************************************************}}

{{* The header file with the main logo and stuff  *}}
{{include file='header.tpl'}}


{{* Dev note:  the $includeFile var is assigned in foo.php script  *}}
<!-- Displays main content block -->
{{include file=$includeFile}}

{{* this <select> block is redundant *}}
{{*
<select name="company">
  {{html_options options=$vals selected=$selected_id}}
</select>
*}}

<!-- Show header from affiliate is disabled -->
{{* $affiliate|upper *}}

{{* you cannot nest comments *}}
{{*
<select name="company">
  {{* <option value="0">-- none -- </option> *}}
  {{html_options options=$vals selected=$selected_id}}
</select>
*}}


{{* cvs tag for a template, below the 36 SHOULD be an american currency
. however its converted in cvs.. *}}
{{* &#36;Id: Exp &#36; *}}
{{* $Id: *}}
</body>
</html>

 

Variables

Template variables start with the $dollar sign. They can contain numbers, letters and underscores, much like a PHP variable. You can reference arrays by index numerically or non-numerically. Also reference object properties and methods.

Config file variables are an exception to the $dollar syntax and are instead referenced with surrounding #hashmarks#, or via the $smarty.config variable.

Example 3-2. Variables

{{$foo}}        <-- displaying a simple variable (non array/object)
{{$foo[4]}}     <-- display the 5th element of a zero-indexed array
{{$foo.bar}}    <-- display the "bar" key value of an array, similar to PHP $foo['bar']
{{$foo.$bar}}   <-- display variable key value of an array, similar to PHP $foo[$bar]
{{$foo->bar}}   <-- display the object property "bar"
{{$foo->bar()}} <-- display the return value of object method "bar"
{{#foo#}}       <-- display the config file variable "foo"
{{$smarty.config.foo}} <-- synonym for {{#foo#}}
{{$foo[bar]}}   <-- syntax only valid in a section loop, see {{section}}
{{assign var=foo value='baa'}}{{$foo}} <--  displays "baa", see {{assign}}

Many other combinations are allowed

{{$foo.bar.baz}}
{{$foo.$bar.$baz}}
{{$foo[4].baz}}
{{$foo[4].$baz}}
{{$foo.bar.baz[4]}}
{{$foo->bar($baz,2,$bar)}} <-- passing parameters
{{"foo"}}       <-- static values are allowed

{{* display the server variable "SERVER_NAME" ($_SERVER['SERVER_NAME'])*}}
{{$smarty.server.SERVER_NAME}}

Request variables such as $_GET, $_SESSION, etc are available via the reserved $smarty variable.

See also $smarty, config variables {{assign}} and assign().

 

Functions

Every Smarty tag either prints a variable or invokes some sort of function. These are processed and displayed by enclosing the function and its attributes within delimiters like so: {{funcname attr1='val1' attr2='val2'}}.

Example 3-3. function syntax

{{config_load file='colors.conf'}}

{{include file='header.tpl'}}
{{insert file='banner_ads.tpl' title='Smarty is cool'}}

{{if $logged_in}}
    Welcome, <font color="{{#fontColor#}}">{{$name}}!</font>
{{else}}
    hi, {{$name}}
{{/if}}

{{include file='footer.tpl' ad=$random_id}}

See also register_function()

 

Attributes

Most of the functions take attributes that specify or modify their behavior. Attributes to Smarty functions are much like HTML attributes. Static values don't have to be enclosed in quotes, but it is recommended for literal strings. Variables may also be used, and should not be in quotes.

Some attributes require boolean values (TRUE or FALSE). These can be specified as either unquoted true, on, and yes, or false, off, and no.

Example 3-4. function attribute syntax

{{include file='header.tpl'}}

{{include file='header.tpl' attrib_name='attrib value'}}

{{include file=$includeFile}}

{{include file=#includeFile# title='Smarty is cool'}}

{{html_select_date display_days=yes}}

{{mailto address='smarty@example.com'}}

<select name='company_id'>
  {{html_options options=$companies selected=$company_id}}
</select>

 

Embedding Vars in Double Quotes

Example 3-5. Syntax examples

{{func var="test $foo test"}}       <-- sees $foo
{{func var="test $foo_bar test"}}   <-- sees $foo_bar
{{func var="test $foo[0] test"}}    <-- sees $foo[0]
{{func var="test $foo[bar] test"}}  <-- sees $foo[bar]
{{func var="test $foo.bar test"}}   <-- sees $foo (not $foo.bar)
{{func var="test `$foo.bar` test"}} <-- sees $foo.bar
{{func var="test `$foo.bar` test"|escape}} <-- modifiers outside quotes!

Example 3-6. Practical examples

{{* will replace $tpl_name with value *}}
{{include file="subdir/$tpl_name.tpl"}}

{{* doesn't replace $tpl_name *}}
{{include file='subdir/$tpl_name.tpl'}} <--

{{* must have backticks as it contains a . *}}
{{cycle values="one,two,`$smarty.config.myval`"}}

{{*  same as $module['contact'].'.tpl' in a php script *}}
{{include file="`$module.contact`.tpl"}}

{{*  same as $module[$view].'.tpl' in a php script *}}
{{include file="$module.$view.tpl"}}
See also escape

 

Math

Math can be applied directly to variable values.

Example 3-7. math examples

{{$foo+1}}

{{$foo*$bar}}

{{* some more complicated examples *}}

{{$foo->bar-$bar[1]*$baz->foo->bar()-3*7}}

{{if ($foo+$bar.test%$baz*134232+10+$b+10)}}

{{$foo|truncate:"`$fooTruncCount/$barTruncFactor-1`"}}

{{assign var="foo" value="`$foo+$bar`"}}

See also the {{math}} function for complex equations and {{eval}}.

 

Escaping Smarty Parsing

It is sometimes desirable or even necessary to have Smarty ignore sections it would otherwise parse. A classic example is embedding Javascript or CSS code in a template. The problem arises as those languages use the { and } characters which are also the default delimiters for Smarty.

The simplest thing is to avoid the situation altogether by separating your Javascript and CSS code into their own files and then using standard HTML methods to access them.

Including literal content is possible using {{literal}}..{{/literal}} blocks. Similar to HTML entity usage, you can use {{ldelim}},{{rdelim}} or {{$smarty.ldelim}} to display the current delimiters.

 

Modifiers

Modifiers can be applied to variables, custom functions or strings. To apply a modifier, specify the value followed by a | (pipe) and the modifier name. A modifier may accept additional parameters that affect its behavior. These parameters follow the modifer name and are separated by a : (colon). Also, all php-functions can be used as modifiers implicitly (more below) and modifiers can be combined.

Example 5-1. Modifier examples

{* apply modifier to a variable *}
{$title|upper}

{* modifier with parameters *}
{$title|truncate:40:'...'}

{* apply modifier to a function parameter *}
{html_table loop=$myvar|upper}

{* with parameters *}
{html_table loop=$myvar|truncate:40:'...'}

{* apply modifier to literal string *}
{'foobar'|upper}

{* using date_format to format the current date *}
{$smarty.now|date_format:"%Y/%m/%d"}

{* apply modifier to a custom function *}
{mailto|upper address='smarty@example.com'}

{* using  php's str_repeat *}
{'='|str_repeat:80}

{* php's count *}
{$myArray|@count}

{* php's shuffle on servers's ip *}
{$smarty.server.SERVER_ADDR|shuffle}

(* this will uppercase and truncate the whole array *}
<select name="name_id">
{html_options output=$myArray|upper|truncate:20}
</select>
You can apply any number of modifiers to a variable. They will be applied in the order they are combined, from left to right. They must be separated with a | (pipe) character:
{$articleTitle}
{$articleTitle|upper|spacify}
{$articleTitle|lower|spacify|truncate}
{$articleTitle|lower|truncate:30|spacify}
{$articleTitle|lower|spacify|truncate:30:". . ."}

 

Template Objects

In this article:

The Campsite template engine stores the template environment in an object named 'campsite'. All Campsite properties and objects are attributes of $campsite object.

The $campsite object has the following attributes which are not objects:

  • version: the Campsite version
  • preview: true if the page was displayed in the preview window (by a Campsite staff user)
  • prev_list_empty: true if a list was displayed before querying this attribute and this list was empty

Any Campsite object (e.g.: $campsite->language, $campsite->article) has the following functions:

Returns true when the object has the given property. This function can be used for dynamic article properties too.

E.g.: $campsite->article->has_property("name") will return true.

Returns true if the object variable given as a parameter points to the same data as the current object.

E.g.: {{ if $campsite->article->same_as($campsite->default_article) }} will return true if the current article was the same as the article defined at the beginning of the template. If both were undefined this function returns true.

Language

The "language" object is set at the beginning of the main template based on the request URL. This object can be changed using the set_language function. The language object has the following properties:
If you want to verify whether the current environment language was the same as the initial language compare it to the default_language object:
{{ if $campsite->language == $campsite->default_language }}
...
{{ /if }}

If you want to display parts of your templates in a different language according to the language selected by the user, you can use something similar to the following code. This snippet was used for a bilingual publication. 

{{ if $campsite->language->code == "en" }}archive{{ else }}[trans]archive{{ /if }}

Default Language

The "default_language" object is set at the beginning of the main template based on the request URL and can not be modified. It has the same attributes as the language object (see "Language" in this chapter).

Publication

The "publication" object is set at the beginning of the main template based on the request URL. This object can be changed using the set_publication (see "Set publication" in this chapter) function. The publication object has the following properties:
For more details on these attributes see also "Creating a Publication" chapter.

Default Publication

The "default_publication" object is set at the beginning of the main template based on the request URL and can not be modified. It has the same attributes as the publication object (see "Publication" in this chapter).

Issue

The "issue" object is set at the beginning of the main template based on the request URL. This object can be changed using the set_issue function (see "Set Issue" in this chapter). The issue object has the following properties:

<date_attribute> may be one of the following:

Default Issue

The "default_issue" object is set at the beginning of the main template based on the request URL and can not be modified. It has the same attributes as the issue object (see "Issue" in this chapter).

Section

The "section" object is set at the beginning of the main template based on the request URL. This object can be changed using the set_section function (see "Set Section" in this chapter). The section object has the following properties:

Default Section

The "default_section" object is set at the beginning of the main template based on the request URL and can not be modified. It has the same attributes as the section object (see "Section" in this chapter).

Article

The "article" object is set at the beginning of the main template based on the request URL. This object can be changed using the set_article function (see "Set Article" in this chapter). The article object has the following properties:

Base properties/functions:

Comments related properties/functions:

Accessibility properties/functions:

Attachment related properties/functions:
Statistics properties/functions:
<date_attribute> may be one of the following:

Note regarding the attribute type->[<article_type>->]<article_type_attribute>:

Attributes which are body fields (content) have the following properties:

E.g.: displaying the first paragraph of the dynamic field "content":
$campsite->article->content->first_paragraph

Note regarding the attribute type->[<article_type>->]<article_type_attribute>: Starting with Campsite 2.3.0 the table cell containing the image link in article body fields has the class cs_img and the cell containing the caption text has the class "caption"; this allows the web designer to change the layout of the article images by using a CSS file. The new image link has the following structure:

<table border="0" cellspacing="0" cellpadding="0" class="cs_img" align=left>
  <tr>
    <td align="center">
      <img src="/get_img?NrArticle=143&NrImage=1" border="0"
           hspace="5" vspace="5">
    </td>
  </tr>
  <tr><td align="center" class="caption">Campsite team</td></tr>
</table>

Note regarding the attribute type->[<article_type>->]<article_type_attribute>: Starting with Campsite 2.3.3 the subtitle in the article body fields has the class articlesubhead; this allows the web designer to change the layout of the subtitles by using a CSS file. The subtitle anchor has the following structure:

<span class="articlesubhead">
    <a name="a1.250_s1">Version 2.3.0 - 2.3.1</a>
</span>

The structure of the anchor name is:

a<language_identifier>.<article_number>_s<subtitle_number>

See also:

 

Default Article

The "default_article" object is set at the beginning of the main template based on the request URL and can not be modified. It has the same attributes as the article object.

 

Article Attachment

The "article_attachment" object is usually initialized inside a list of article attachments. It is not initialized at the beginning of the template and can not be initialized by other campsite function. The article attachment object has the following properties:

 

Audio Attachment

The "audio_attachment" object is usually initialized inside a list of audio attachments. It is not initialized at the beginning of the template and can not be initialized by other campsite function. The audio attachment object has the following properties:

 

Article Comment

The "article_comment" object is usually initialized inside a list of article comments. It can be initialized at the beginning of the template from the URL request but can not be initialized by other campsite function. The article comment object has the following properties:


Subtitle

The "subtitle" object is usually initialized inside a list of subtitles. It can be initialized at the beginning of the template from the URL request but can not be initialized by other campsite function. The subtitle object has the following properties:

See also Editing body-type fields: Working with the body field editor ("Using the WYSIWYG Article Editor" chapter).

Image

The "image" object is usually initialized inside a list of article images. It is not initialized at the beginning of the template and can not be initialized by other campsite function. The image object has the following properties:

<date_attribute> may be one of the following:

 

Topic

The "topic" object is usually initialized inside a "List of article topics" or a "List of subtopics". It can be initialized at the beginning of the template from the URL request or by using the "Set topic" campsite function. The topic object has the following properties:

<topic_name_lang_code> = <topic_name>:<language_code>

 

Default Topic

The "default_topic" object is set at the beginning of the main template based on the request URL and can not be modified. It has the same attributes as the "Topic" object.

 

User

The "user" object is set at the beginning of the main template based on the session cookies or if one of the following actions took place: "Login action", "Edit user action". It can not be initialized by other campsite function. The user object has the following properties:

 

Subscription

The "user->subscription" object is set at the beginning of the main template based on the session cookies or if the "Login action" took place. It can not be initialized by other campsite function.The subscription object has the following properties:

 

Template

The "template" object is set at the beginning of the main template based on the request URL. This object can not be changed using campsite functions. The template object has the following properties:


Default Template

The "default_template" object is set at the beginning of the main template based on the request URL and can not be modified. It has the same attributes as the template object (see "Default Template" in this chapter).

 

URL

The URL object follows the changes in the template environment, meaning that every time an object in the environment changed the URL object is updated. It has the following properties:

{{ if !$campsite->url->is_valid }}
    <h3>The requested page was not found.</h3>
    {{ set_language name=`$campsite->publication->default_language->english_name` }}
    {{ set_current_issue }}
{{ else }}
    <!-- display content -->
{{ /if }}
{{ $campsite->url->uri_path }}?{{ $campsite->url->url_parameters }}
<input type="hidden" name="<param_name>" value="<param_value>">
The URL object has the following functions:

 

Default URL

The "default_url" object is set at the beginning of the main template based on the request URL and can not be modified. It has the same attributes as the url object (see "URL" in this chapter).

 

Current List

The "current_list" is defined inside a list statement only. If multiple lists are embedded then the current_list object refers to the most internal list in which the current_list object was used. E.g.:

{{ list_sections }}
    {{ $campsite->current_list->index }} {{* refers to the sections list *}}
    {{ list_articles }}
        {{ $campsite->current_list->index }} {{* refers to the articles list *}}
    {{ /list_articles }}
    {{ $campsite->current_list->index }} {{* refers to the sections list *}}
{{ /list_sections }}
The object has the following properties:

 

Login Action

The "login_action" object is defined when a login action took place. It has the following properties:


Search Articles Action

The "search_articles_action" object is initialized when a search action took place. It has the following properties:


Submit Comment Action

The "submit_comment_action" object is initialized when a comment form was submitted. It has the following properties:


Preview Comment Action

The "preview_comment_action" object is initialized when the preview button was clicked on a comment form. It has the following properties:


Edit User Action

The "edit_user_action" object is initialized when a user add/edit form was submitted. It has the following properties:


Edit Subscription Action

The "edit_subscription_action" object is initialized when a subscription form was submitted. It has the following properties:

 

Environmental Control

In this article:

 

Set Language

Purpose:

Sets the runtime environment language to the one selected by English name. From this statement on the language is the new chosen one. If the name supplied was not valid this variable is not modified.

Syntax:

{{ set_language name="<language_name>" }}

where <language_name> is the English name of selected language.

Constraints:

Can not be used inside any list statement.

See also "set_default_language", "unset_language".

 

Set Default Language

Purpose:

Sets the runtime environment language to the "default_language".

Syntax:

{{ set_default_language }}

Constraints:

Cannot be used inside any list statement.

See also "set_language", and "unset_language".

 

Unset Language

Purpose:

Unset the runtime environment language. After this statement the language object will not be defined anymore.

Syntax:

{{ unset_language }}
Constraints:

Cannot be used inside "list_articles", "list_article_attachments", "list_article_comments", "list_article_comments", "list_article_topics", "list_article_audio_attachments", "list_search_results" and "list_subtitles" statements.

See also "set_language", and "set_default_language".

  

Set Publication

Purpose:

Sets the runtime environment publication to the one selected by the statement constraint. If the statement constraint was not valid the publication is not changed.

Syntax:

{{ set_publication name="<publication_name>" }}

Select the publication having the specified name. If the name supplied was not valid, this parameter is not modified.

{{ set_publication identifier="<publication_identifier>" }}

Select the publication having the specified identifier. The publication identifier is a unique number associated to the publication and is supplied by the administration interface.

Constraints:

Cannot be used inside any list statement.

See also "set_default_publication", "unset_publication".

 

Set Default Publication

Purpose:

Sets the runtime environment publication to the "default_publication".

Syntax:

{{ set_default_publication }}

Constraints:

Cannot be used inside any list statement.

See also "set_publication", "unset_publication".

 

Unset Publication

Purpose:

Unset the runtime environment publication. After this statement the publication object will not be defined anymore.

Syntax:

{{ unset_publication }}
Constraints:

Cannot be used inside any list statement.

See also "set_publication", "set_default_publication".

 

Set Issue

Purpose:

Sets the runtime environment issue to the one selected by the statement constraint. If the statement constraint was not valid the issue is not changed.

Syntax:

{{ set_issue number="<issue_number>" }}

Select the issue having the specified number. If number supplied was not valid this parameter is not changed.

Constraints:

Cannot be used inside any list statement.

See also "set_default_issue", "set_current_issue", "unset_issue".

 

Set Current Issue

Purpose:

Sets the runtime environment issue to the last published issue.

Syntax:

{{ set_current_issue }}

Constraints:

Cannot be used inside any list statement.

See also "set_issue", "set_default_issue", "unset_issue".

 

Set Default Issue

Purpose:

Sets the runtime environment issue to the "default_issue".

Syntax:

{{ set_default_issue }}

Constraints:

Cannot be used inside any list statement.

See also "set_issue", "set_current_issue", "unset_issue".

 

Unset Issue

Purpose:

Unset the runtime environment issue. After this statement the issue object will not be defined anymore.

Syntax:

{{ unset_issue }}
Constraints:

Cannot be used inside any list statements.

See also "set_issue", "set_current_issue", "set_default_issue".

 

Set Section

Purpose:

Sets the runtime environment section to the one selected by the statement constraint. If the statement constraint was not valid the section is not changed.

Syntax:

{{ set_section name="<section_name>" }}

Select the section having the specified name; this has to be written in the language of the context. If the name supplied was not valid this parameter is not modified.

{{ set_section number="<section_number>" }}

Select the section having the specified number; this is not dependent on context language. If the number supplied was not valid this parameter is not modified.

Constraints:

Cannot be used inside "list_sections", "list_articles", "list_article_attachments", "list_article_comments", "list_article_comments", "list_article_topics", "list_article_audio_attachments", "list_search_results" and "list_subtitles" statements.

See also "set_default_section", "unset_section".

 

Set Default Section

Purpose:

Sets the runtime environment section to the "default_section".

Syntax:

{{ set_default_section }}

Constraints:

Cannot be used inside "list_sections", "list_articles", "list_article_attachments", "list_article_comments", "list_article_comments", "list_article_topics", "list_article_audio_attachments", "list_search_results" and "list_subtitles" statements.

See also "set_section", "unset_section".

 

Unset Section

Purpose:

Unset the runtime environment section. After this statement the section object will not be defined anymore.

Syntax:

{{ unset_section }}
Constraints:

Cannot be used inside "list_sections", "list_articles", "list_article_attachments", "list_article_comments", "list_article_comments", "list_article_topics", "list_article_audio_attachments", "list_search_results" and "list_subtitles" statements.

See also "set_section", "set_default_section".

 

Set Article

Purpose:

Sets the runtime environment article to the one selected by the statement constraint. If the statement constraint was not valid the section is not changed.

Syntax:

{{ set_article name="<article_name>" }}

Select the article having the specified name. If the supplied name was not valid this parameter is not be modified.

{{ set_article number="<article_number>" }}

Select the article having the specified number. If the supplied value was not valid this parameter is not be modified.

Constraints:

Cannot be used inside "list_articles", "list_article_attachments", "list_article_comments", "list_article_comments", "list_article_topics", "list_article_audio_attachments", "list_search_results" and "list_subtitles" statements.

See also "set_default_article", "unset_article".

 

Set Default Article

Purpose:

Sets the runtime environment article to the "default_article".

Syntax:

{{ set_default_article }}
Constraints:

Cannot be used inside "list_articles", "list_article_attachments", "list_article_comments", "list_article_comments", "list_article_topics", "list_article_audio_attachments", "list_search_results" and "list_subtitles" statements.

See also "set_article", "unset_article".

 

Unset Article

Purpose:

Unset the runtime environment article. After this statement the article object will not be defined anymore.

Syntax:

{{ unset_article }}
Constraints:

Cannot be used inside "list_articles", "list_article_attachments", "list_article_comments", "list_article_comments", "list_article_topics", "list_article_audio_attachments", "list_search_results" and "list_subtitles" statements.

See also "set_default_article", "unset_article".

 

Set Topic

Purpose:

Sets the runtime environment topic to the one selected by the statement constraint. If the statement constraint was not valid the topic is not changed. Setting the environment topic will change the behavior of articles list: only articles having that topic will be listed.

E.g.:

{{ set_topic name="test:en" }}
{{ list_articles }}
...
{{ /list_articles }}

This will list only articles having the topic 'test'. The topic is automatically appended to the URL parameters so you don't have to set the topic in the current page.

E.g.:

{{ set_topic name"test:en" }}
<a href="{{ uri }}">text</a>

Syntax:

{{ set_topic name="<topic_name_lang_code>" }}
{{ set_topic identifier="<integer_value>" }}

Select the topic having the specified name-language code or identifier. If the supplied value was not valid this variable is not modified. The name must be written in the following format:

<topic_name_lang_code> = <topic_name>:<language_code>

Examples: sport:en, music:en etc. where 'sport' is the topic name and 'en' is the English language code.

Constraints:

Cannot be used inside "list_articles" and "list_article_topics" statements.

See also "set_default_topic", "unset_topic".

 

Set Default Topic

Purpose:

Sets the runtime environment topic to the "default_topic".

Syntax:

{{ set_default_topic }}

Constraints:

Constraints:

Cannot be used inside "list_articles" and "list_article_topics" statements.

See also "set_topic", "unset_topic".

 

Unset Topic

Purpose:

Unset the runtime environment topic. After this statement the topic object will not be defined anymore.

Syntax:

{{ unset_topic }}
Constraints:

Cannot be used inside "list_articles" and "list_article_topics" statements.

See also "set_default_topic", "unset_topic".

 

Unset Comment

Purpose:

Unset the runtime environment comment. After this statement the comment object will not be defined anymore.

Syntax:

{{ unset_comment }}
Constraints:

Cannot be used inside "list_article_comments" statement.

Lists

In this chapter:

List of Languages

Note: this works only in 3.2.1 and newer versions.

Purpose:

Select the list of languages according to the given constraints and current environmental variables. The language variable may not be defined outside list_languages statement; inside the statement however, this variable is defined. The code between "{{list_languages}}" statement and "{{/list_languages}}" is repeated for every language in the list.

Syntax:

{{ list_languages [length="<integer_value>"]
        [columns="<integer_value>"]
        [of_publication="true|false"]
        [of_issue="true|false"]
        [of_article="true|false"]
        [exclude_current="true|false"]
        [order="<order_condition>"] }}
    <list_of_instructions>
{{ /list_languages }}

where:

When none of the three attributes (of_publication, of_issue, of_section) was specified it will list all available languages in Campsite.

<list_of_instructions> may contain any statement except those listed at the end of the page.

<order_condition>= byNumber desc|asc
|byName desc|asc
|byEnglish_Name desc|asc
|byCode desc|asc

Order conditions are self-explanatory.

Inside the List the following environment variable is modified:

The environment is restored after the list ends.

Constraints:

Inside list_issues the following statements are forbidden:

List of Issues

Purpose:

Select the list of issues according to the given constraints and current environmental variables. The publication, language and issue variables may not be defined outside list_issues statement; inside the statement however, all these variables are defined. The code between "{{ list_issues }}" statement and "{{ /list_issues }}" is repeated for every issue in the list.

Syntax:

{{ list_issues [length="<integer_value>"]
        [columns="<integer_value>"]
        [constraints="<list_of_issue_constraints>"]
        [order="<order_condition>"] }}
    <list_of_instructions>
{{ /list_issues }}

where:

<list_of_instructions> may contain any statement except: "set_language", "set_publication", "list_issues", "set_issue".

<list_of_issue_constraints>= [<issue_constraint>] <list_of_issue_constraints>
| <issue_constraint>
<issue_constraint>= number<integer_operator> <integer_value>
|name <string_operator> <string_value>
|publish_date <date_operator> <date_value>
|publish_year <integer_operator> <integer_value>
|publish_month <integer_operator> <integer_value>
|publish_mday <integer_operator> <integer_value>
|<date_constraint>
<date_constraint>= year <integer_operator> <integer_value>
|mon_nr <integer_operator> <integer_value>
|mday <integer_operator> <integer_value>
|yday <integer_operator> <integer_value>
|wday <integer_operator> <integer_value>
|hour <integer_operator> <integer_value>
|min <integer_operator> <integer_value>
|sec <integer_operator> <integer_value>

where year stands for year, mon_nr for month number (1..12), mday for month day (1..31), yday for year day (1..365), wday for week day (1..7), hour for hour, min for minute and sec for second.

Any parameter used in <list_of_issue_constraints> can only be used once.

<order_condition>= byNumber desc|asc
|byName desc|asc
|byDate desc|asc
|byCreationDate desc|asc
|byPublishDate desc|asc

Order conditions are self-explanatory; byDate and byCreationDate are aliases of byPublishDate.

Inside the List the following environment variables are modified:

The environment is restored after the list ends.

Constraints:

Inside list_issues the following statements are forbidden:

list_issues statement can not be used inside any other list statements.

List of Sections

Purpose:

Select the list of sections according to the given constraints and current environmental variables. The publication, language, issue and section variables may not be defined outside list_sections statement; inside the statement however, all these variables are defined. The code between "{{ list_sections }}" statement and "{{ /list_sections }}" is repeated for every section in the list.

Syntax:

{{ list_sections [length="<integer_value>"]
        [columns="<integer_value>"]
        [constraints="<list_of_section_constraints>"] }}
    <list_of_instructions>
{{ /list_sections }}

where:

<list_of_instructions> may contain any statement except: "set_language", "set_publication", "list_issues", "set_issue", "list_section", "set_section".

<list_of_section_constraints>= [<section_constraint>] <list_of_section_constraints>
| <section_constraint>
<section_constraint>= name <string_operator> <string_value>
| number <integer_operator> <integer_value>

Any parameter used in <list_of_section_constraints> can only be used once.

Inside list_sections, the data context is defined by the constraints applied to the current section for every processed line. The data context is restored after the list processing.

Constraints:

Inside list_sections the following statements are forbidden:

list_sections statement cannot be used inside list_articles, list_subtitles, list_search_results statements.

List of Articles

Purpose:

Select the list of articles according to the given constraints and current environmental variables. The publication, language, issue, section and article variables may not be defined outside list_articles statement; inside the statement however, all these variables are defined. The code between "{{ list_articles }}" statement "{{ /list_articles }}" is repeated for every article in the list.

Syntax:

{{ list_articles [length="<integer_value>"]
        [columns="<integer_value>"]
        [constraints="<list_of_article_constraints>"]
        [ignore_issue="true"] [ignore_section="true"]
        [ignore_language="true"]
        [order="<order_condition>"] }}
    <list_of_instructions>
{{ /list_articles }}

where

{{ list_articles length="10" columns="2" order="byPublishDate desc"}}
{{ if $campsite->current_list->column == "1" }}
left column
{{ /if }}
{{ /list_articles }}

<list_of_instructions> may contain any statement except those listed at the end of the page.

<list_of_article_constraints>= [<article_constraint>] <list_of_article_constraints>
| <article_constraint>
<article_constraint>= name <string_operator> <string_value>
|number <integer_operator> <integer_value>
|keyword <string_value>
|OnFrontPage [<switch_operator> <switch_value>]
|OnSection [<switch_operator> <switch_value>]
|upload_date <date_operator> <date_value>
|publish_date <date_operator> <date_value>
|public <switch_operator> <switch_value>
|type <switch_operator> <article_type>
|[<article_type>] <article_type_attribute> <attribute_type_operator> <attribute_type_value>
|matchAllTopics
|matchAnyTopic
|topic is|not <string_value>
|reads <integer_operator> <integer_value>
|author <string_operator> <string_value>
|issue <integer_operator> <integer_value>
|section <integer_operator> <integer_value>
Examples of constraints:
constraints="issue greater 10 issue smaller 20"
constraints="section greater_equal 40 section smaller 60"

Note on author attribute: this works only in 3.2.1 and newer versions.

Note on topics: the topic name must be written in the following format:

<topic_name>:<language_code>

Examples of valid topic names: sports:en, health:en etc.

Note on topics: If a certain topic was defined in the template environment by use of "set_topic" statement or URL parameter the list will change the behavior of articles list: only articles having that topic will be listed.

E.g.:

{{ set_topic name="test:en" }}
{{ list_articles }}
...
{{ /list_articles }}

This will list only articles having the topic 'test'. The topic is automatically appended to the URL parameters so you don't have to set the topic in the current page.

<order_condition>=

byNumber desc|asc
|byName desc|asc
|byDate desc|asc
|byCreationDate desc|asc
|byPublishDate desc|asc
|byLastUpdate desc|asc
|byPopularity desc|asc
|byPublication desc|asc
|byIssue desc|asc
|bySection desc|asc
|byLanguage desc|asc
|bySectionOrder desc|asc
|byComments desc|asc
|byLastComment desc|asc

Note: ByComments and byLastComment only work in Campsite 3.2.2 and newer.

Note: byLastUpdate is implemented in Campsite 3.5 and newer

Inside the list the data context is defined by the constraints applied to the current article for every processed line. The data context is restored after the list processing.

Constraints:

Inside list_articles the following statements are forbidden:

list_articles statement cannot be used inside list_subtitles, list_search_results statements.

List of Article Attachments

Purpose:

Create a list of documents attached to the article currently defined in the template environment. If the article was not set the list is empty. The code between "{{ list_article_attachments }}" statement and "{{ /list_article_attachments }} is repeated for every attachment in the list.

Syntax:

{{ list_article_attachments [length="<integer_value>"]
        [columns="<integer_value>"]
        [language="current"] }}
    <list_of_instructions>
{{ /list_article_attachments }}

where

Inside list_articles the following statements are forbidden:

Inside the list, the current article attachment is set to the current element of the list. The environment context is restored after the list processing.

Example:

{{ list_article_attachments }}
    {{ if $campsite->current_list->at_beginning }}
        <h4>Downloads:</h4>
{{ /if }}
<a href="/attachment/{{ $campsite->attachment->identifier }}">{{ $campsite->attachment->file_name }}</a> ({{ $campsite->attachment->size_kb }}kb)<br/>
{{ /list_article_attachments }}

Here is an example on how to use the attachment list to play a number of MP3-files:

{{ list_article_attachments }}
    {{ if $campsite->attachment->extension == "mp3" }}
        <object type="application/x-shockwave-flash" data="/templates/radioactive/apps/player_mp3_maxi.swf" width="200" height="20">
            <param name="movie" value="/templates/radioactive/apps/player_mp3_maxi.swf" />
            <param name="bgcolor" value="#444444"/>
            <param name="FlashVars" value="mp3={{ uri options="articleattachment" }}" />
            <!-- player home: http://flash-mp3-player.net/ -->
        </object>
    {{ /if }}
{{ /list_article_attachments }}

List of Article Comments

Purpose:

Create a list of comments attached to the article currently defined in the template environment. If the article was not defined the comments list is empty. The code between "{{ list_article_comments }}" statement and "{{ /list_article_commnets }}" is repeated for every comment in the list.

Syntax:

{{ list_article_comments [ignore_language="true|false"]
        [ignore_article="true|false"]
        [length="<integer_value>"]
        [columns="<integer_value>"]
        [order="<order_condition>"] }}
    <list_of_instructions>
{{ /list_article_comments }}

where:

Note on ignore_article: this option will force the list order to date ordering.

Note: ignore_language and ignore_article only work in Campsite 3.2.2 and newer.

 <order_condition>= byDate desc|asc
|default desc|asc

The default order of the comments in the list (if no order condition was specified) is based on the tree structure of the comments as in the following example:

The first element in the list is the first comment that was submitted, second is it's first reply (if exists), first reply of the first reply .. and so on down the tree structure until it finds no other reply, second reply to the root element etc.

If the order by date condition was specified the comments are displayed strictly by their submission date, regardless of the relation they had to the other comments.

Example:
{{ list_article_comments order="byDate desc" }}
    Subject: {{ $campsite->comment->subject }}<br/>
    Posted {{ $campsite->comment->submit_date }}
    by <b>{{ $campsite->comment->reader_email }}</b>
    <br/>
    {{ $campsite->comment->content }}
    <br/>
{{ /list_article_comments }}
Inside list_articles the following statements are forbidden:

List of Article Images

Purpose:

Create a list of images attached to the article currently defined in the template environment. If the article was not defined the list is empty. The code between "{{ list_article_images }}" statement and "{{ /list_article_images }} is repeated for every image in the list.

Syntax:

{{ list_article_images [length="<integer_value>"]
        [columns="<integer_value>"] }}
    <list_of_instructions>
{{ /list_article_images }}

where:

Example:

{{ set_language name="Deutsch" }}
{{ set_publication name="fluter" }}
{{ unset_issue }}
{{ set_section number="67" }}
{{* show image with index number 1 (when attached to article) *}}
{{ list_articles length="3" constraints="type is themaprint" }}
  {{ list_article_images }}
    {{ if $campsite->article->image->article_index == 1 }}
      <img src="../{{ $campsite->article->image->imageurl }}"
      title="{{$campsite->article->name }}">
    {{ /if }}
  {{ /list_article_images }}
{{ /list_articles }}

Inside list_articles the following statements are forbidden:

Inside the list, the current image is set to the current element of the list. The environment context is restored after the list processing.

List of Article Topics

Purpose:

Create a list of topics attached to the article currently defined in the template environment. If the article was not set the list is empty. The topic parameter may not be defined outside list_article_topics statement; inside the statement however, this parameter is defined. The code between "{{ list_article_topics }}" statement and "{{ /list_article_topics }}" is repeated for every topic in the list.

Syntax:

{{ list_article_topics [length="<integer_value>"]
        [columns="<integer_value>"] }}
    <list_of_instructions>
{{ /list_article_topics }}

where:

Inside list_articles the following statements are forbidden:

Inside the list, the current topic is set to the current element of the list. The environment context is restored after the list processing.

List of Article Audio Attachments

Purpose:

Create a list of audio files attached to the article currently defined in the template environment. If the article was not set the list is empty. The code between "{{ list_article_audio_attachments }}" statement and "{{ /list_article_audio_attachments }}" is repeated for every audio attachment in the list. The order of the audio attachments is the same as in the administration interface.

Syntax:

{{ list_article_audio_attachments
        [length="<integer_value>"]
        [columns="<integer_value>"] }}
    <list_of_instructions>
{{ /list_article_audio_attachments }}

where:

Inside list_articles the following statements are forbidden:

Inside the list, the current audio attachment is set to the current element of the list. The environment context is restored after the list processing.

List of Search Results

Purpose:

Create a list of articles that match the search keywords inputted by the reader. The publication, language, issue, section, article variables may not be defined outside list_search_results statement; inside the statement however, all these variables are defined. The code between "{{ list_search_result }}" statement and "{{ /list_search_result }}" is repeated for every article in the list.

Syntax:

{{ list_search_results [length="<integer_value>"]
        [columns="<integer_value>"]
        [order="<order_condition>"] }}
    <list_of_instructions>
{{ /list_search_result }}

where:

<list_of_instructions> may contain any statement except: "set_language", "set_publication".

<order_condition>= byDate desc|asc
|byCreationDate
|byPublishDate
|byNumber desc|asc
|byName desc|asc

Order conditions are self-explanatory; byDate is an alias of byCreationDate. The default order of  articles in the list (if no order condition was set) is: first they are ordered by the publication identifier ascending, then by the issue number descending, then by the section number ascending and by the article order in the section ascending.

Inside the list, the data context is defined by the constraints applied to the current article for every processed line. The data context is restored after the list processing.

Constraints:

Inside list_articles the following statements are forbidden:

List of Subtitles

Purpose:

Create a list of subtitles for the content of the article currently defined in the template environment. The article, if not specified somewhere else, is treated as group of paragraphs. The markup for a new paragraph is the subtitle. The code between "{{ list_subtitles }}" statement and "{{ /list_subtitles }}" is repeated for every subtitle in the list.

Syntax:

{{ list_subtitles [length="<integer_value>"]
        [columns="<integer_value>"] }}
    <list_of_instructions>
{{ /list_subtitles }}

where:

<list_of_instructions> may contain any statement except: "set_language", "set_publication", "list_issues", "set_issue", "list_sections", "set_section", "list_articles", "set_article".

Inside the list, the data context is defined by the constraints applied to the current article for every processed line. The data context is restored after the list processing.

Constraints:

Inside list_articles the following statements are forbidden:

List of Subtopics

Purpose:

Create a list of subtopics of the topic currently set in the template environment. If the topic was not set it will generate the list of root topics. The topic parameter may not be defined outside the list statement; inside the statement however, this parameter is defined. The code between "{{ list_subtopics }}" statement and "{{ /list_subtopics }}" is repeated for every topic in the list.

Syntax:

{{ list_subtopics [length="<integer_value>"]
        [columns="<integer_value>"]
        [order="<order_condition>"] }}
    <list_of_instructions>
{{ /list_subtopics }}

where:

<list_of_instructions> may contain any statement except those listed at the end of the page.

<order_condition>=  byNumber desc|asc
|byName desc|asc

Inside the list, the data context is defined by the constraints applied to the current topic for every processed line. The data context is restored after the list processing.

Constraints:

Inside list_subtopics the following statements are forbidden:

Forms

In this chapter:


Form: Login

Purpose:

Generate the form and data fields for logging in a user.

Syntax:

{{ login_form [template="<template_name>"] submit_button="<button_name>"
              [html_code="<html_code>"]
              [button_html_code="<html_code>"] }}
<list_of_instructions>
{{ /login_form }}

Constraints:

Can not be used inside subscription and user forms. Cannot be used within itself (e.g. login in login).

A simple example of implementing a login form on the front end of your publication:

{{ if ! $campsite->user->logged_in }}
    <p>Login</p>
    {{ if $campsite->login_action->is_error }}
        <p>There was an error logging in: {{ $campsite->login_action->error_message }}</p>
    {{ /if }}
    {{ login_form submit_button="Login" button_html_code="class=\"submitbutton\"" }}
        <p>User ID: {{ camp_edit object="login" attribute="uname" }}</p>
        <p>Password: {{camp_edit object="login" attribute="password" }}</p>
    {{ /login_form }}
{{ else }}
    <p>Welcome {{ $campsite->user->name }}</p>
    <p><a href="?logout=true">Logout</a></p>
{{ /if }}
Attention: the logout requires this code in the head of every page:
{{ if $campsite->url->get_parameter('logout') == 'true' }}
<META HTTP-EQUIV="Set-Cookie" CONTENT="LoginUserId=; path=/">
<META HTTP-EQUIV="Set-Cookie" CONTENT="LoginUserKey=; path=/">
{{ $campsite->url->reset_parameter('logout') }}
<META HTTP-EQUIV="Refresh" content="0;url={{ uri }}">
{{ /if }}

Form: Search

Purpose:

Generate the search form and data fields for searching keywords in published articles. By default the search action is performed in the current publication only.

Syntax:

{{ search_form [template="<template_name>"] submit_button="<button_name>"
               [html_code="<html_code>"]
               [button_html_code="<html_code>"] }}
<list_of_instructions> 
{{ /search_form }}

  • <template_name> is the name of the next template to be requested from search form.
  • <button_name> is the name of the button for submitting the form.
  • html_code: you can insert whatever HTML code you want in the <form> statement; e.g.: {{ user_form .. html_code="id=\"my_id\"" }}
  • button_html_code: you can insert whatever HTML code you want in the button input field statement; e.g.: {{ user_form .. button_html_code="id=\"my_submit_id\"" }}

The list of instructions may contain any instruction allowed in the current context.

Setting the search scope: whether to search in all publications, in the current publication, in the current issue or in the current section. Insert the following field in the search form:

{{ camp_select object="search" attribute="level" }}

Constraints:

Can not be used within itself (e.g. search in search).

 


Form: Comment

Purpose:

Generate the form and default data fields for article comment submit. Inside the form camp_edit statements can be used to generate article comment input fields.

Syntax:

{{ comment_form [template="<template_name>"]
                submit_button="<submit_button_name>"
                [preview_button="<preview_button_name>"]
                [html_code="<html_code>"]
                [button_html_code="<html_code>"] }}
<list_of_instructions>
{{ /comment_form }}
  • <template_name>: the name of the next template to be requested when submitting the comment
  • <submit_button_name>: the name of the button for submitting the comment
  • <preview_button_name>: the name of the button for previewing the comment
  • html_code: you can insert whatever HTML code you want in the <form> statement; e.g.: {{ user_form .. html_code="id=\"my_id\"" }}
  • button_html_code: you can insert whatever HTML code you want in the button input field statement; e.g.: {{ user_form .. button_html_code="id=\"my_submit_id\"" }}

 


Form: User

Purpose:

Generate the form and data fields for adding a new user or editing an existing user data.

Syntax:

{{ user_form submit_button="<button_name>" [template="<template_name>"]
             [html_code="<html_code>"]
             [button_html_code="<html_code>"] }}
<list_of_instructions>
{{ /user_form }}
  • <template_name> is the name of the next template to be requested from user form.
  • <button_name> is the name of the button for submitting the form.
  • html_code: you can insert whatever HTML code you want in the <form> statement; e.g.: {{ user_form .. html_code="id=\"my_id\"" }}
  • button_html_code: you can insert whatever HTML code you want in the button input field statement; e.g.: {{ user_form .. button_html_code="id=\"my_submit_id\"" }}

Constraints:

Can not be used inside subscription and login forms. Can not be used within itself (ex.: user in user).

 


Form: Subscription

Purpose:

Generate the form and default data fields for subscription. Inside this can be used Edit and Select statements to generate fields for every section on issue.

Syntax:

{{ subscription_form type="<subscription_type>" [template="<template_name>"]
                     submit_button="<button_name>"
                     [total="<total_field_name>"]
                     [html_code="<html_code>"]
                     [button_html_code="<html_code>"] }}
<list_of_instructions>
{{ /subscription_form }}
  • <subscription_type> has two values: by_publication and by_section
  • <template_name> is the name of the next template to be requested from subscription form.
  • <button_name> is the name of the button for submitting the form.
  • <total_field_name> is the name of the field where the total payment is written.
  • <evaluate_button_name> is the name of the evaluate button (when pressing this button the total payment is updated in the total field.
  • html_code: you can insert whatever HTML code you want in the <form> statement; e.g.: {{ user_form .. html_code="id=\"my_id\"" }}
  • button_html_code: you can insert whatever HTML code you want in the button input field statement; e.g.: {{ user_form .. button_html_code="id=\"my_submit_id\"" }}

Constraints:

Cannot be used inside user and login forms. Can not be used within itself (ex.: subscription in subscription).

 

Form: Parameters

"formparameters" prints the runtime environment parameters in HTML form format. It prints only data context parameters and can be used to create links.

Syntax:

{{ formparameters [options="<options_list>"] }}
<options_list> = <option>
               | <option> <options_list>
option = fromStart
       | articleComment
where:
  • fromstart: prints the parameters received at the start of template, not the current ones (useful when building site maps)
  • articleComment: inserts the article comment identifier in the parameters list; if no article comment was defined in the template environment no parameter is inserted. This attribute is needed if you want to pass on the current comment id to another page for display purposes.

 

Text Input Fields

Purpose:

Generate an input text field; these fields are used in forms to allow the reader to enter data. These must be used in conjunction with the form statements.

Syntax:

{{ camp_edit object="<object_name>"
             attribute="<attribute_name>"
             [html_code="<HTML_code>"]
             [size ="<field_length>"]
             [columns="<max_columns>"]
             [rows="<max_rows>"] }}

For text input fields, if the size parameter was set the input field size will be set to that value. For text box fields, if the columns/rows parameter was set the box will have the given number of columns/rows.


Note

columns and rows parameters were implemented starting with version 3.2.2.

If the html_code parameter was set the HTML code will be inserted inside the input field.

Example:

{{ camp_edit object="user" attribute="name"
             html_code="id=\"userNameInput\"" }}

will output:

<input type="text" name="f_user_name" size ="50" maxlength="255" id="userNameInput">

 

Edit Login

Purpose:
Generates a text input field for entering a subscriber's login user name or password. Use this to allow a subscriber to login to your site. These statements should be used inside the login form.

Syntax:

{{ camp_edit object="login" attribute="<attribute>"
             [html_code="<HTML_code>"] [size ="<field_length>"] }}

where <attribute> being one of the following:

  • uname: allows login name input
  • password: allows password input

Constraints:

The login edit fields can be used only inside the login form.

 

Edit Search

Purpose:
Generates a text input field so that a user can search for articles on your site. This statement should be used inside the search form.

Syntax:

{{ camp_edit object="search" attribute="<attribute>"
             [html_code="<HTML_code>"] [size ="<field_length>"] }}
with <attribute> being one of the following:
  • keywords: allows search keywords input
  • start_date: select only articles published starting on the selected date
  • end_date: select only articles published up to the selected date
Constraints:
The search edit field can be used only inside the search form.

 

Edit Comment

Purpose:
Generates text fields so that a user can enter a comment. This statement should be used inside the comment form.

Syntax:

{{ camp_edit object="comment" attribute="<attribute>"
             [html_code="<HTML_code>"]
             [size ="<field_length>"]
             [columns="<max_columns>"]
             [rows="<max_rows>"] }}
with <attribute> being one of the following:
  • nickname: a place for the user to type in a nickname
  • reader_email: a place for the user to type in their email address; this field is optional for logged in readers because the email can be read from the subscribers database
  • subject: a place for the user to type in a subject line for their comment
  • content: a place for the user to type in their comment.  
The attributes reader_email, subject and content are mandatory in each Edit Comment form.

Note

columns and rows parameters were implemented starting with version 3.2.2. Constraints:
The comment edit field can be used only inside the comment form.

 

Edit CAPTCHA

Purpose:
Generates a text field allowing the user to input the CAPTCHA code for spam control. This statement should be used inside the comment form.

Syntax:

{{ camp_edit object="captcha" attribute="code"
             [html_code="<HTML_code>"] [size ="<field_length>"] }}

 

Edit User

Purpose:
Generates a text input field for editing the selected user attribute. This statement should be used inside the user form.

Syntax:

{{ camp_edit object="search" attribute="<attribute>"
             [html_code="<HTML_code>"]
             [size ="<field_length>"]
             [columns="<max_columns>"]
             [rows="<max_rows>"] }}
with <attribute> being one of the following:
  • name
  • uname
  • email
  • city
  • str_address
  • state
  • phone
  • fax
  • contact
  • second_phone
  • postal_code
  • employer
  • position
  • how
  • languages
  • field1
  • field2
  • field3
  • field5
  • interests
  • improvements
  • text1
  • text2
  • text3
  • password
  • passwordagain
The parameters (name, uname, email, city...) are fields describing the user's data;  field1-field5, text1-text3 are extra fields for storing extra information of your choosing.

Note

columns and rows parameters were implemented starting with version 3.2.2. Constraints:
The user edit field can be used only inside the user form.

 

Edit Subscription

Purpose:
Generates an input field for editing the subscription time for a certain section. The section must be defined in the template environment. This statement should be used inside the subscription form.

Syntax:

{{ camp_edit object="search" attribute="time"
             [html_code="<HTML_code>"] [size ="<field_length>"] }}
Constraints:
The subscription edit field can be used only inside the subscription form.

 

Option Input Fields

Purpose:

Generate an option input field; these fields are used in forms to allow the reader to enter data. These must be used in conjunction with the form statements.

Syntax:


{{ camp_select object="<object_name>"
               attribute="<attribute_name>"
               [html_code="<HTML_code>"] }}

If the html_code parameter was set the HTML code will be inserted inside the input field.

Example:

{{ camp_select object="user" attribute="country" html_code="id=\"countryId\"" }}

will output a popup list of available countries:

<select name="f_user_country" id="countryId">
...
</select>

 

Select Login

Purpose:
Generates a check box; if checked the user session will be remembered for a period of two weeks so the user will not have to login again. This statement should be used inside the login form.

Syntax:

{{ camp_select object="login" attribute="rememberuser"
               [html_code="<HTML_code>"] }}
Constraints:
The select login field can be used only inside the login form.

 

Select Search

Purpose:

Generates a check box or a popup list for selecting the search mode or the search level respectively. This statement should be used inside the search form.

Syntax:

{{ camp_select object="search" attribute="<attribute>"
               [html_code="<HTML_code>"] }}
with <attribute> being one of the following:
  • mode: if checked the search will return articles that contain all entered keywords; if not checked it will return articles that contain at least one keyword
  • level: allows the reader to select the scope of the search: multiple publications, publication, issue, section.
  • section: select only articles that are in the given section
  • issue: select only articles that are in the given issue

Contraints:

The select search field can be used only inside the search form.

 

Select User

Purpose:
Generates a dropdown list or radio-buttons for selecting values for the given fields. This statement should be used inside the user form.

Syntax:

{{ camp_select object="user" attribute="<attribute>"
               [html_code="<HTML_code>"] }}
with <attribute> being one of the following:
  • gender
  • title
  • country
  • age
  • employertype
  • pref1
  • pref2
  • pref3
  • pref4
The parameters (country, title, gender...) are fields describing the user information; pref1-pref4 are extra fields for storing extra information - the publication administrator sets their meaning. 

Constraints:
The select user field can be used only inside the user form.

 

Select Subscription

Purpose:
Special-purpose input for subscription data.

Syntax:

{{ camp_select object="subscription" attribute="<attribute>"
               [html_code="<HTML_code>"] }}
with <attribute> being one of the following:
  • section: generates a checkbox for selecting the current section in subscription form; use together with "List of Sections" (see also "Creating reader subscriptions through the template language")
  • allLanguages: generates a checkbox allowing the user to choose a subscription to all available languages
  • languages: generates a multiple selection list allowing the user to select individual languages; this selection list is automaticaly deactivated if the user chose to subscribe to all available languages.

Constraints:
The select subscription field can be used only inside the subscription form.

 

CAPTCHA ImageLink

Purpose:

"captcha_image_link" will insert the link for the CAPTCHA image. Use inside an "img" HTML tag as follows:

<img src="../{{ captcha_image_link }}">
Syntax:
{{ captcha_image_link }

 

Images

template block statement: {{ list_images }}

Parameters that can be used in {{ list_images }} statement:

Attributes for the image object

The image template object (see http://en.flossmanuals.net/Campsite/TemplateObjects - Image) has the following new attributes:


Template sample for comments

The following template sample will display the comment form, using CAPTCHA. The comment settings need to be enabled for article and article type, as explained further up in this manual.

{{ if $campsite->article->comments_enabled }}

<div id="comments">
<a name="comments">
  <h3>Comments</h3>
</a>
{{ list_article_comments }}
{{ if $campsite->current_list->at_beginning }}
<a name="commentlist">
  <h4>Previous comments</h4>
</a>
{{ /if }}
  <div class="comment" {{ if $campsite->current_list->at_end }}id="everlast"{{ /if }}>
    <p><strong>{{ $campsite->comment->subject }}</strong></p>
    <p>{{ $campsite->comment->content }}</p>
    <p><em>{{ $campsite->comment->nickname }} | <span>{{ $campsite->comment->submit_date|camp_date_format:"%M %e, %Y" }}</span></em></p>
  </div><!-- /.comment -->
{{ /list_article_comments }}

<a name="commentform">
    <h4>Post a comment</h4>
</a>
{{ if $campsite->submit_comment_action->rejected }}
    <div class="posterror">Your comment has not been accepted.</div>
{{ /if }}

{{ if $campsite->submit_comment_action->is_error }}
    <div class="posterror">{{ $campsite->submit_comment_action->error_message }}
        <span class="posterrorcode">{{ $campsite->submit_comment_action->error_code }}</span>
   </div>
{{ else }}
    {{ if $campsite->submit_comment_action->defined }}
        {{ if $campsite->publication->moderated_comments }}
            <div class="postinformation">Your comments has been passed on to the editors for approval.</div>
        {{ /if }}
    {{ /if }}  
{{ /if }}

{{* if $campsite->comment->defined }}
    <p><strong>{{ $campsite->comment->subject }}
        ({{ $campsite->comment->reader_email|obfuscate_email }}) -
        {{ $campsite->comment->level }}</strong></p>
    <p>{{ $campsite->comment->content }}</p>
{{ /if *}}

{{ if $campsite->user->blocked_from_comments }}
    <div class="posterror">The user you are logged in as, has been blocked from writing comments.</div>
{{ else }}

{{ comment_form submit_button="Send comment" }}
    <div class="form-element">
      <label for="CommentSubject">Name:</label>{{ camp_edit object="comment" attribute="nickname" }}
    </div>
  
    <div class="form-element">
      <label for="CommentEmail">Email (required):</label>{{ camp_edit object="comment" attribute="reader_email" }}
    </div>

    <div class="form-element">
      <label for="CommentNickname">Subject (required):</label>{{ camp_edit object="comment" attribute="subject" }}
    </div>
   
    <div class="form-element">
      <label for="CommentContent">Comment:</label>{{ camp_edit object="comment" attribute="content" }}
    </div>
    {{ if $campsite->publication->captcha_enabled }}
    <div class="form-element clearfix">
      <label for="submitComment">SPAM-protection:</label>
      <img src="../{{ captcha_image_link }}"><br clear="all" />
      <label for="f_captcha_code">Type letters here: </label>{{ camp_edit object="captcha" attribute="code" }}
    </div>
    {{ /if }}
    <div class="form-element">
      <label for="submitComment"></label>
    </div>
{{ /comment_form }}
{{ /if }}

{{ unset_comment }}
{{ if $campsite->comment->defined }}
    <div class="posterror">Error: Your recent comment is still being processed.<div>
{{ /if }}

</div><!-- /#comments -->

{{ /if }}

Somebody Should Set The Title For This Chapter!

Here is a sample template for Search:

Anywhere you want the search form to appear, leading to the search result page, include this:

 {{ search_form template="path/to/search.tpl" submit_button="Search" html_code="class='FORM_suche'" button_html_code=" value='Suche' class='SUBMIT_black'" }}
    {{ camp_edit object="search" attribute="keywords" html_code="id=\"keywords\"" }}
{{ /search_form }}

The "path/to/search.tpl" refers to the relative path of the below template. If it lives in the top folder of your templates, just use "search.tpl" if you have subfolders (e.g. searchfiles), use "searchfiles/search.tpl". Attention: no leading slash!

<h2>Search</h2>
</div>
{{ search_form template="path/to/search.tpl" submit_button="Search" html_code="class='FORM_suchseite'" button_html_code="class='SUBMIT_search'" }}
  <ul class="searchform">
    <li class="searchform">
    <label for="keywords">Search words:</label>
    {{ camp_edit object="search" attribute="keywords" html_code="id=\"keywords\"" }}
    </li>
    <li class="option">
    {{ camp_select object="search" attribute="mode" html_code="id=\"match_all\"" }}
    <label for="match_all">Nur Artikel mit allen W&ouml;rtern anzeigen</label>
    </li>
    <li class="option checkbox"><input type="radio" name="f_search_scope" value="content" id="content" checked>
    <label for="content">Entire article</label></li>
    <li class="option checkbox"><input type="radio" name="f_search_scope" value="title" id="title">
    <label for="title">Only in title</label></li>
    <li class="option"><input type="radio" name="f_search_scope" value="author" id="author">
    <label for="author">Author</li>
  </ul>
 {{ camp_select object="search" attribute="level" }}
  <p>Search in the
    <input type="radio" name="f_search_scope" value="content" id="content" checked>
    <label for="content"><strong>whole content</strong></label>,
    <input type="radio" name="f_search_scope" value="title" id="title">
    <label for="title"><strong>title</strong></label> or
    <input type="radio" name="f_search_scope" value="author" id="author">
    <label for="author"><strong>author</strong></label>
  </p>
  <p>Issue: {{ camp_select object="search" attribute="issue" }}</p>
  <p>Section: {{ camp_select object="search" attribute="section" }}</p>
  <p>Start date: {{ camp_edit object="search" attribute="start_date" }}</p>
  <p>End date: {{ camp_edit object="search" attribute="end_date" }}</p>
  <p>Topic:
    <select name="f_search_topic">
      {{ unset_topic }}
      {{ list_subtopics }}
        <option value="{{ $campsite->topic->identifier }}>">
          {{ $campsite->topic->name }}
        </option>
      {{ /list_subtopics }}
    </select>
  </p>
{{ /search_form }}
<div class="searchresults">
<h2>Search results</h2>
    {{ list_search_results length="24" order="byDate desc" }}
    {{ if $campsite->current_list->at_beginning }}
            <ul class="filmsList">
    {{ /if }}
                <li>
                    <h5><a href="{{ url options="article" }}">{{ $campsite->article->name }}</a></h5>
                    <div><a href="{{ url options="article" }}">{{ $campsite->article->untertitel }}</a></div>
                    <span>(Issue: {{ $campsite->issue->name }}&nbsp;|&nbsp;Section: {{ $campsite->section->name }}
                </li>
       {{ if $campsite->current_list->at_end }}
    </ul>
          <ul class="pagination">
                <li>{{ $campsite->current_list->count }} Artikel</li>
{{ set_current_issue }}
{{ set_default_section }}
{{ unset_article }}
        {{ if $campsite->current_list->has_previous_elements }}
          <li class="previous"><a href="{{ uri options="previous_items template path/to/search.tpl" }}">&laquo;</a></li>
        {{ /if }}
{{ set_current_issue }}
{{ set_default_section }}
{{ unset_article }}
        {{ if $campsite->current_list->has_next_elements }}
          <li class="next"><a href="{{ uri options="next_items template path/to/search.tpl" }}">&raquo;</a></li>
        {{ /if }}
          </ul>
        {{ /if }}
     {{ /list_search_results }}
{{ if $campsite->prev_list_empty }}
                {{ if $campsite->search_articles_action->defined }}
                  <div class="warning">No matches found.</div>
              {{ /if }}
    {{ /if }}
  

How to do article pagination?

This example will show you how to split an article on multiple pages. We assume the article type is fastnews and has three fields: date (date field type), intro (body field type) and Full_text (body field type). You'll find this example implemented in the Campsite demo package here. The field Full_text is the one that contains the pagination (subheads).

Here is the code:

  1. {{ list_subtitles field_name="Full_text" }}
    
  2.   <p>
    
  3.   {{ if $campsite->article->full_text->subtitle_is_current }}
    
  4.     <b>{{ $campsite->current_list->index }}. {{ $campsite->subtitle->name }}</b>
    
  5.   {{ else }}
    
  6.     <a href="{{ uri }}">{{ $campsite->current_list->index }}. {{ $campsite->subtitle->name }}</a>
    
  7.   {{ /if }}
    
  8.   </p>
    
  9. {{ /list_subtitles }}
    
  10. <p>View subtitle:
    
  11. {{ if $campsite->article->full_text->has_previous_subtitles }}
    
  12.   <a href="{{ uri options="previous_subtitle full_text" }}">Previous</a>
    
  13. {{ else }}
    
  14.   Previous
    
  15. {{ /if }}
    
  16. |
    
  17. {{ if $campsite->article->full_text->has_next_subtitles }}
    
  18.   <a href="{{ uri options="next_subtitle full_text" }}">Next</a>
    
  19. {{ else }}
    
  20.   Next
    
  21. {{ /if }}
    
  22. |
    
  23. {{ if $campsite->article->full_text->has_next_subtitles || $campsite->article->full_text->has_previous_subtitles }}
    
  24.   <a href="{{ uri options="all_subtitles full_text" }}">All</a>
    
  25. {{ else }}
    
  26.   All
    
  27. {{ /if }}
    
  28. </p>
    
  29. <p>{{ $campsite->article->full_text }}</p>
    
    
Lines 1-9 display the list of article subtitles (see "List of Subtitles" in "Template Language Reference" chapter):

Lines 11-27 create links to navigate to the previous or next subtitle (uri options="previous_subtitle full_text", uri options="previous_subtitle full_text"), or to display all subtitles (uri options="all_subtitles full_text").

Line 29 displays the actual article content, in this case the current subtitle ($campsite->article->full_text).

The example given above will make your page look something like this:


Article pagination

Note: CSS styles have been removed from the example to make it easier to read, so if you use the code above it will not look exactly as shown; the colors will not be there, and the spacing will be a bit different.

Another way would be to only show the numbers and not display anything if there is no pagination in the field, i.e. it is a normal article. Note: the count of subheads (sub titles) will be one if there is no subheads in the article field.

{{ list_subtitles field_name="Body" }}
{{ if $campsite->current_list->count > 1 }}
    {{ if $campsite->current_list->at_beginning }}
    <div     <ul>
        {{ if $campsite->article->body->has_previous_subtitles }}
        <li><a href="{{ uri options="previous_subtitle body" }}">&laquo;</a></li>
        {{ else }}
        {{ /if }}
    {{ /if }}
    {{ if $campsite->article->body->subtitle_is_current }}
        <li><a     {{ else }}
        <li><a href="{{ uri }}">{{ $campsite->current_list->index }}<!--{{ $campsite->subtitle->name }}--></a></li>
    {{ /if }}
    {{ if $campsite->current_list->at_end }}
        {{ if $campsite->article->body->has_next_subtitles }}
        <li><a href="{{ uri options="next_subtitle body" }}">&raquo;</a></li>
        {{ else }}
        {{ /if }}
    </ul>
    </div>
    {{ /if }}
{{ /if }}
{{ /list_subtitles }}
There might be some fields in the article that you only want to display at the beginning of the article. On the following pages of the pagination you don't want them to show. This is a way to do this:
{{ * print lead only if article pagination is on page one *}}
{{ list_subtitles field_name="Body" }}
    {{ if $campsite->current_list->at_beginning }}
        {{ if $campsite->article->body->has_previous_subtitles }}
        {{ else }}
        <span         {{ /if }}
    {{ /if }}
{{ /list_subtitles }}
As you can see, this is making use of the fact that even without actual pagination (subheads in the text, set with the editor), the article has one subhead in the list: itself.

 

Miscellaneous

In this chapter:

 

Displaying the URL

Purpose:

"uripath" prints only the path part of the URI, the part before the parameters list. If "/en/1/2/3?param1=text" was the full URI, the URI path is "/en/1/2/3".

"urlparameters" prints the runtime environment parameters in URL format.

"uri" prints the complete link URI and it is equivalent to:

{{ uripath }}?{{ urlparameters }}

"url" prints the complete URL in the form: http://[site_alias][uri]. It is equivalent to:

http://{{ $campsite->publication->site }}{{ uri }}


Note

All four statements work for both template path and short URL types. Depending on the URL type the statement displays the proper link.

Note: For publications with short URL type the only way to create links is to use these three statements: either url, uri, uripath or urlparameters. It is not possible to build the URI manually.

Syntax:

{{ url [options="<options_list>"] }}
{{ uri [options="<options_list>"] }}
{{ uripath [options="<options_list>"] }}
{{ urlparameters [options="<options_list>"] }}

where:

<options_list>=

[<option>] <list_of_options>
| <option>

<option>=

fromstart

| reset_issue_list
| reset_section_list
| reset_article_list
| reset_searchresult_list
| reset_subtitle_list
| image [<image_number> [<image_options>]]
| root_level
| language
| publication
| issue
| section
| article
| template <template_name>
| articleAttachment
| articleComment
| audioAttachment
| previous_subtitle <field_name>
| next_subtitle <field_name>
| all_subtitles <field_name>
| previous_items
| next_items

<image_number> is an <integer_value> representing a valid number of article image

<template_name> is a <string value> representing the full path of a valid template

  • fromstart: prints the url corresponding to the received request, before any changes were made to the template runtime environment (useful when building site maps)
  • reset_issue_list: reset list counters for the issues list
  • reset_section_list: reset list counters for the sections list
  • reset_article_list: reset list counters for the articles list
  • reset_searchresult_list: reset list counters for the search results list
  • reset_subtitle_list: reset list counters for the subtitles list
  • image: print image parameters in order to show an image in template; if you use this statement inside the "List of Article Images" statement the image number value is not mandatory. The image options are different depending on the Campsite version:
    •  For versions 3.0-3.3:

    <image_options>=<image_ratio>.

    The "image_ratio" parameter is an integer between 1 and 100. The image will be scaled from 1% of it's size to 100% based on the image ratio parameter.

    •  For versions 3.4 and newer:

    <image_options>=<image_ratio>|width <width>|height <height>.

    The "image_ratio" parameter is the same as above. You can specify image to be resized to the given width or height.

    E.g.: {{ uri options="image 1 width 100 height 100 }}

  • root_level: this link will have all parameters reset: language, publication, issue, section, article, subtitle, lists indexes etc.
  • language: this link will have all parameters above language reset: publication, issue, section, article, subtitle, lists indexes etc.; language parameter remains unchanged
  • publication: this link will have all parameters above publication reset: issue, section, article, subtitle, lists indexes etc.; language and publication parameters remain unchanged
  • issue: this link will have all parameters above issue reset: section, article, subtitle, lists indexes etc.; language, publication and issue parameters remain unchanged
  • section: this link will have all parameters above section reset: article, subtitle, lists indexes etc.; language, publication, issue and section parameters remain unchanged
  • article: this link will have all parameters above article reset: article, subtitle, lists indexes etc.; language, publication, issue, section and article parameters remain unchanged
  • template <template_name>: this link will set the template in the link to <template_name>
  • articleAttachment: displays the link for the current article attached document
  • articleComment: inserts the article comment identifier in the parameters list; if no article comment was defined in the template environment no parameter is inserted. This attribute is needed if you want to pass on the current comment id to another page for display purposes.
  • audioAttachment: displays the link for the current audio file attached to the article
  • previous_subtitle <field_name>: add a parameter to the URI to select the previous subtitle of the given <field_name> for display
  • next_subtitle <field_name>: add a parameter to the URI to select the next subtitle of the given <field_name> for display
  • all_subtitles <field_name>: add a parameter to the URI to select all subtitles of the given <field_name> for display
  • previous_items: add a parameter to the URI to select the previous interval of the current list items for display
  • next_items: add a parameter to the URI to select the next interval of the current list items for display
Constraints:

None.

 

Local

Purpose:

Creates a temporary environment; when leaving the local block the previous template environment (before entering local) is restored.

Syntax:

{{ local }}
<list_of_instructions>
{{ /local }}

The list of instructions may contain any instruction allowed in the current context. If it is used inside a list it must respect the constraints of the list.

Constraints:

None.

 

Logout

There is no template keyword to logout a subscriber. Instead, just put these two lines in your logout.tpl file:

<META HTTP-EQUIV="Set-Cookie" CONTENT="LoginUserId=; path=/">
<META HTTP-EQUIV="Set-Cookie" CONTENT="LoginUserKey=; path=/"> 

Campsite Modifiers

In this chapter:

Truncating UTF8 strings

The "truncate_utf8" modifier behaves exactly like the Smarty truncate modifier except that it works properly on UTF8 strings. See more details on truncate here:

http://www.smarty.net/manual/en/language.modifier.truncate.php

Date Formatting

The "camp_date_format" modifier formats a date string as specified:

{{ <string>|camp_date_format:"<date_attribute>" }}
{{ <string>|camp_date_format:"<date_format>" }}
where:
<date_attribute> may be one of the following:
<date_format> may contain any printable character; escape " (double quotes) in the date formatting with \ (backslash). E.g.: "%M %e, %Y, \"%W\"" will display the the date like this: July 5, 2008, "Saturday".

The following groups of characters have special meaning:
Constraints:
None

 

File Size Formatting

The "camp_filesize_format" modifier formats an integer in Byte specific multiples:

{{ <integer>|camp_filesize_format:"<filesize_format>" }}
<filesize_format> may take one of the following values:

 

Email Obfuscation

The "obfuscate_email" modifier obfuscates a string; the email string is obfuscated not to allow spambot web crawlers to find it.

{{ <email_string>|obfuscate_email }}

Creating an RSS feed for your site

 Step 1) Create your RSS feed.
Create a template named "rss.tpl" and copy and paste the template written below. You will have to adjust the template tags to fit your site.  For example, you should change the channel information such as the title and link, and the tags inside the "<description>" element ("{{ $campsite->article->intro }} {{ $campsite->article->full_text }}").

The PHP code at the beginning and end of the sample below is so that the HTTP header is set to "text/xml" instead of "text/html".

Step 2) Create the link to your RSS feed.
You can do this by using the "URI" keyword:

{{ local }}
{{ unset_issue }}
{{ unset_section }}
<a href="{{ url options="template rss.tpl" }}">RSS Feed</a>
{{ /local }}

If your template is not in the root directory but in a sub folder (in this case the folder named "feeds") you have to specify the URL options as a relative link, e.g.:

{{ local }}
{{ unset_issue }}
{{ unset_section }}
<a href="{{ url options="template feeds/rss.tpl" }}">RSS Feed</a>
{{ /local }}

The following template contains the necessary commands for a valid RSS feed. However, you can alter the list command any way you like to make more than one RSS feed. The following example lists the latest 20 items listed on the front page.

rss.tpl template:

{{ php }}
ob_start();⁞
{{ /php }}
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://purl.org/rss/1.0/"
xmlns:dc="http://purl.org/dc/elements/1.1/">

   <channel rdf:about="http://www.sourcefabric.org">
       <title>Sourcefabric News</title>
       <link>http://www.sourcefabric.org</link>
       <description>Free Software for a Free Press</description>
       <dc:language>en-us</dc:language>
       <items>
         <rdf:Seq>
           {{ local }}
           {{ set_language name="English" }}
           {{ set_current_issue }}
           {{ unset_section }}
           {{ list_articles length="20" constraints="OnFrontPage is on" order="bydate desc" }}
           <rdf:li rdf:resource="{{ url options="article" }}"/>
           {{ /list_articles }}
           {{ /local }}
         </rdf:Seq>
       </items>
   </channel>

   {{ local }}
   {{ set_language name="English" }}
   {{ set_current_issue }}
   {{ unset_section }}
   {{ list_articles length="20" constraints="OnFrontPage is on" order="bydate desc" }}
   <item rdf:about="{{ url options="article" }}">
       <title>{{ $campsite->article->name }}</title>
       <link>{{ url options="article" }}</link>
       <description><![CDATA[{{ $campsite->article->intro }} {{ $campsite->article->full_text }}]]></description>
       <dc:date>{{ $campsite->article->publish_date|camp_date_format:"%Y-%m-%dT%H:%i:%S+01:00" }}</dc:date>
   </item>
   {{ /list_articles }}
   {{ /local }}
</rdf:RDF>

{{ php }}
header("Content-type: text/xml");
$content = ob_get_clean();
echo '<?xml version="1.0" encoding="utf-8"?>';
echo $content;
{{ /php }}
Tips & tricks

If you use XSL, the CDATA sections do not work with Firefox.
If you dont want to use CDATA sections in your RSS, you can strip the HTML from your article this way:
$allowedTags="<rdf:RDF><rdf:Seq><rdf:li><channel><title><link><description><dc:language><dc:date><item><items>";
$content = strip_tags($content, $allowedTags);

Another way to create a link to your RSS feed
Assign the template to a section: create a new section (doesnt matter where), and call it "rss". Configure the section so that its templates are "rss.tpl", and give the section the URL name of "rss". The URL for this section will be the URL to your RSS feed.

 

Changing Templates

It is possible to keep the look for the old issues and at the same time to have a different look for newer issues. There are a few steps you have to take:

  1. Create the new templates in a separate directory

  2. Go to the Issue Configure screen and select the new issue, section and article templates for the issue (e.g. /new/issue.tpl, /new/section.tpl and /new/article.tpl).

  3. Within your templates, make sure to create links to issue, section and article templates by using "uri" (see "Displaying the URL" in "Template Language Reference" chapter) instead of manually writing the link content. In other words, do this:
    <a href="{{ uri }}">link</a>

The Template Cache

To exclude dynamic stuff I've added {{ dynamic }} block. Any code inside dynamic block will be excluded form cache and rendered on each request.

It was first version of template cache handler. It had been working fine but without so many dynamic excluded parts. For given example the cache accelerates just about 2x times than uncached.

That's not fine for me. I'd like more Smile and I've implemented the second template cache handler version with multirendering support. It allows to render included sub-templates by separate rendering process with personal cache settings. The next version contains new function {{ render }}

Full specification:
{{ render file="template_name" [issue=off|issueid] [section=off|sectionid] [article=off|articleid] [params=paremeters] [cache=secs] }}

where

file: template filename
issue: to cache for any issue or for an issue with issueid
section: to cache for any section or for a section with sectionid
article: to cache for any article or for a article with articleid
params: specify additional parameters
cache: overwrite the cache settings in template manager

Let's see on example.
Here is the layout of standard section page.



We need to exclude from caching some dynamic stuff:
1. Most popular list
2. Most commented list
3. External informers
4. Template contains article list pagination.

Let's define some parameters for dynamic stuff:
Most popular article list is defined for issue only.
Most commented article list is defined for all articles in any issue
Informers should be included on each request
Pagination generates links like http://site/en/pub/issue/section/?page=n

Most popular and commented lists should be cached for 600 sec
The main template section.tpl should be cached for 30 days

The cache lifetime for main template can be defined in Template manager:

Most popular list:
{{ render file="most_popular.tpl" section=off cache=600 }}

Most commented list:
{{ render file="most_commented.tpl" issue=off section=off cache=600 }}

Informers:
{{ dynamic }}
{{ php }} inclide 'informer1.php'; {{ php }}
{{ /dynamic }}

Section article list with pagination:
{{ render file="section_list.tpl" params=$campsite->url->get_parameter(page) }}

On article changing or issue publishing/unpublishing the cache manager cleans outdated cached template. Cleaning algorithm based on campsite specific parameters: language, publication, issue, section, article, template, additional params.

 

Using plugins with your templates

Simply installing a plugin is not all you must do. You must still make changes in your site's templates to take advantage of the new features.

Every plugin will be somewhat unique in the features and functionality it provides. Some plugins may be quite complex, and others will be relatively simple. But the vast majority of plugins work with templates in some form or another. Most add new properties that can be used with the templates.

When a new plugin is released, the changes the plugin makes to the template language will also be made available in this section. As an example, we will use the polls plugin as an example of how this all works.

Polls Plugin

In this chapter:

Poll plugin
Plugin Author: Sebastian Goebel
Date: September, 2008

Description: The poll plugin allows users to vote on a topic and then to display the results. From the administrative interface, authorized users can create and delete new polls, change the questions , and add and edit new possible answers.

The polls plugin modifies the templating language in four parts:

  • poll (17 properties)
  • poll answer (8 properties)
  • list of polls
  • list of poll answers

Each of these is discussed in the next few pages.

The general poll object properties are used in your templates for managing such things such as the language the poll will use, the overall number of votes, and the title of the poll.

Frontend/Template Engine

In this article:

Examples of templates using Polls plugin objects

It's usually best to see an example of what it is we're talking about, so here is a sample template that makes use of the polls plugin. This template is called section-polls.tpl. Feel free to copy this and use it as a base for your own polls implementation:

{{ if $included }}
<style>
 .poll_bar {
    border:1px solid #000; 
    background-color: #dfdfdf; 
    height: 20px; 
    vertical-align: center;
    float: left;
}
</style>
<script>
function play(url)
{
    var tag;
    
    if (navigator.appName=="Microsoft Internet Explorer") {
        tag = '<bgsound src="../'+url+'" loop="false">';
    } else {
        tag = '<embed src="../'+url+'" hidden="true" border="0" width="0" height="0" autostart="true" loop="false">';
    }
    $('player_div').innerHTML = tag;    
}
function stop()
{
    $('player_div').innerHTML = '';   
}    
</script>
<div {{ /if }}
{{ poll_form template='poll-form.tpl' submit_button=false ajax=true }} 
       
       
    {{ $campsite->poll->title }}<br>
    {{*
    Question: {{ $campsite->poll->question }}<br>
    Voting Begin: {{ $campsite->poll->date_begin|date_format }}<br>
    Voting End: {{ $campsite->poll->date_end|date_format }}<br>
    *}}
    Votes: {{ $campsite->poll->votes }}<br>
    
    <div    
    {{ list_poll_answers order="byvalue desc" }}
       
         {{ pollanswer_ajax }}
         
              <div               <div                 {{ $campsite->pollanswer->answer }}
                  ({{ $campsite->pollanswer->percentage|string_format:"%d" }})%
             </div>
              
        {{ /pollanswer_ajax }}
        
        <div        {{ list_pollanswer_attachments }}
            {{ if $campsite->attachment->mime_type|substr:0:5 == 'audio' }}
                <a href="javascript: void(0);" onClick="play('{{ uri options="articleattachment" }}')">
                    <img src="..//css/is_shown.png" border="0">
                </a>
                <a href="javascript: void(0);" onClick="stop()">
                    <img src="..//css/unlink.png" border="0">
                </a>
            {{ /if }}
        {{ /list_pollanswer_attachments }}
        
        <div        Give a note: 
        {{ section name=foo start=1 loop=6 }}
            {{ pollanswer_ajax value=$smarty.section.foo.index }}{{ $smarty.section.foo.index }}{{ /pollanswer_ajax }}
        {{ /section }}
        <br>
        
        {{ $campsite->pollanswer->votes }} votes |
        &#216;{{ $campsite->pollanswer->average_value|string_format:"%.1f" }} |
        sum: {{ $campsite->pollanswer->value }}
        
        <div    {{ /list_poll_answers }}
           
{{ /poll_form }}
 
{{ if $included }}
    </div>
    <div id="player_div"></div>
{{ /if }}
The next example of a template is the section page with the poll included. This template is called poll-form.tpl:

{{ include file="html_header.tpl" }}
<table <tr>
  <td valign="top">
    <div id="breadcrumb">
    {{ breadcrumb }}
    </div>
    {{** main content area **}}
    <table    <tr>
      <td>
    {{ if $campsite->poll->defined }}
    
        <h3>Poll Details</h3>
        
        {{ include file='poll-form.tpl' included=true}}
        
        <br>
        <a href="{{ uri options="template section-polls.tpl" }}">All Polls</a>
        
    {{ else }}
       
        <p>
        
        <tr>
            <th align="left">Name</th>
            <th>Voting Begin</th>
            <th>Voting End</th>
            <th>Current</th>
            <th>Allowed/Votes Cast</th>
            <th>Votes</th>
        </tr>  
        <tr><td colspan="6"><hr></td></tr>
        {{ local }}
  
        {{ list_polls name="polls_list" length="10" order='bylastmodified ASC' }}
           <tr align="center">
            <td align="left">
                <a href="{{ uri options="template section-polls.tpl" }}&amp;f_poll_nr={{ $campsite->poll->number }}&amp;f_poll_language_id={{ $campsite->poll->language_id }}">
                    {{ $campsite->poll->name }}
                </a>
            </td>
            <td>{{ $campsite->poll->date_begin|date_format }}</td>
            <td>{{ $campsite->poll->date_end|date_format }}</td>
            <td>{{ if $campsite->poll->is_current }} Y {{ else }} N {{ /if }}</td>
            <td>{{ $campsite->poll->votes_per_user }}/{{ $campsite->poll->user_vote_count }}</td>
            <td>{{ $campsite->poll->votes }}
          </tr>
           
        {{ if  $campsite->current_list->at_end }}
        <tr><td colspan="6"><hr></td></tr>
        <tr>
            <td>{{ $campsite->current_list->count }} Items</td>
            <td colspan="5">
                {{ if $campsite->current_list->has_previous }}
                    <a href="{{ uripath }}?p_polls_list_start={{ $campsite->current_list->previous }}">previous</a>
                {{ else }}
                    previous    
                {{ /if }}
                |
                {{ if $campsite->current_list->has_next }}
                    <a href="{{ uripath }}?p_polls_list_start={{ $campsite->current_list->next }}">next</a>
                {{ else }}
                    next
                {{ /if }}
            </td>
        </tr>
        {{ /if }}
           
        {{ /list_polls }}
        {{ /local }}
    
    {{ /if }}
      
      
      </td>
    </tr>
    </table>
    {{** end main content area **}}
  </td>
  <td valign="top">
    {{ include file="html_rightbar.tpl" }}
  </td>
</tr>
</table>
{{ include file="html_footer.tpl" }}

Poll object properties

Poll object properties

The poll object has following properties:

Poll Answer - object properties

The poll answer object has following properties:

List of Polls - object properties

Purpose:

Select the list of polls according to the given constraints and current environmental variables. The code between "{{ list_polls }}" statement and "{{ /list_polls }}" is repeated for every poll in the list.

Syntax:

{{ list_polls [length="<integer_value>"] [columns="<integer_value>"]
        [constraints="<list_of_poll_constraints>"]
        [item="<item_constraint>"]
        [order="<order_condition>"]>
}}
<list_of_instructions>
{{ /list_polls }}

where:

<list_of_poll_constraints>= [<poll_constraint>] <list_of_poll_constraints>
| <poll_constraint>
<poll_constraint>= number <integer_operator> <integer_value>
| language_id <integer_operator> <integer_value>
| parent_poll_nr <integer_operator> <integer_value>
| is_extended <switch_operator> <switch_value>
| name <string_operator> <string_value>
| votes <integer_operator> <integer_value>
| votes_overall <integer_operator> <integer_value>
| is_current <boolean_operator> <boolean_value>
| <date_constraint>

<date_constraint>=

begin <date_operator> <date_value>
| begin_year <integer_operator> <integer_value>
| begin_month <integer_operator> <integer_value>
| begin_mday <integer_operator> <integer_value>
| end <date_operator> <date_value>
| end_year <integer_operator> <integer_value>
| end_month <integer_operator> <integer_value>
| end_wday <integer_operator> <integer_value>


<item_constraint>= publication
| issue
| section
| article

<order_condition>= bynumber desc|asc
| bylanguage
| bytitle
| byname
| byquestion
| bybegin
| byend
| byanswers
| byvotes
| byvotes_overall
| bypercentage_overall
| bylastmodified








List of Poll Answers - object properties

Purpose: Select the list of poll answers according to the current poll. The code between "{{ list_pollanswers }}" statement and "{{ /list_pollanswers }}" is repeated for every interview in the list.

Syntax:

{{ list_pollanswers [length="<integer_value>"] [columns="<integer_value>"]
        [constraints="<list_of_interview_constraints>"]
        [order="<order_condition>"]>
}}
<list_of_instructions>
{{ /list_pollanswers }}

where:

  • length="<integer_value>": <integer_value> specifies list_length and forces the list to have at most list_length items. If the list contains more items than list_length items the ones not fitting in can be listed using If NextItems/PreviousItems statements.
  • columns="<integer_value>": <integer_value> specifies columns_number and sets an environment variable. This is incremented as if the items would be placed in a table cell. The counting starts from one and the variable is incremented for every new element. When it reaches the maximum value it is reset to one. This is very useful in building tables of data. For details see If List.

<list_of_instructions> may contain any statement except: "set_interview".

<list_of_interview_constraints>= [<interview_constraint>] <list_of_interview_constraints>
| <iinterview_constraint>
<interview_constraint>= id <integer_operator> <integer_value>
| name <string_operator> <string_value>
| language_id <integer_operator> <integer_value>
| moderator_user_id <integer_operator> <integer_value>
| guest_user_id <integer_operator> <integer_value>
| status <string_operator> <string_value>
| <date_constraint>

<date_constraint>=

interview_begin <date_operator> <date_value>
| interview_begin_year <integer_operator> <integer_value>
| interview_begin_month <integer_operator> <integer_value>
| interview_begin_wday <integer_operator> <integer_value>
| interview_end <date_operator> <date_value>
| interview_end_year <integer_operator> <integer_value>
| interview_end_month <integer_operator> <integer_value>
| interview_end_wday <integer_operator> <integer_value>

| questions_begin <date_operator> <date_value>
| questions_begin_year <integer_operator> <integer_value>
| questions_begin_month <integer_operator> <integer_value>
| questions_begin_wday <integer_operator> <integer_value>
| questions_end <date_operator> <date_value>
| questions_end_year <integer_operator> <integer_value>
| questions_end_month <integer_operator> <integer_value>
| questions_end_wday <integer_operator> <integer_value>



<order_condition>= byIdentifier desc|asc
| byName desc|asc
| byTitle desc|asc
| byQuestions_begin desc|asc
| byQuestions_end desc|asc
| byInterview_begin desc|asc
| byInterview_end desc|asc
| byModerator desc|asc
| byGuest desc|asc
| byStatus desc|asc
| byOrder desc|asc

Online Interview Plugin

In this chapter:

 

Description

The Interview-Module allows to plan, manage and publish an interview on your publication website. The Interview can be announced and readers are invited to ask questions, which will be answered by the interview partner. In practice, this module operates a little bit like a forum but with one main protagonist who will reply to all questions posted. There is the possibility to schedule a time frame for the interview, but this is NOT a chat module. It is closer to a FAQ-tool.

Interview

An Interview is stored in the database in two tables. One keeps settings for the interview, and the other records multiple pairs of questions and answers ("interview items") for each interview.

4 User Roles:

  • Reader of your page can visit an interview. If subscribed to the page, he can submit own questions to an interview
  • Guest is the person who answers the questions
  • Moderator have to moderator incoming questions
  • Admin can create new interviews and edit any property

4 Status:
  • Draft: A new interview, which just occurs on the admin screen
  • Pending: The interview is waiting for questions and answers
  • Published: The interview is done, and the results are published on the website
  • Rejected: Used to hide it from the website

Interview Items

Each pair of question and it answer is called interview item. They have similar 4 status stages:
  • Draft: A new question send by an reader, and waiting for moderation (accept/reject)
  • Pending: The question was accepted, and waits to be answered by the guest
  • Published: The answer is given, and the item is ready to be shown on the website.
  • Rejected: If moderator reject item, it will not appear on the guest screen nor on the website
The normal workflow would be:
  1. Admin created interview, status draft
  2. Admin set interview status to pending. If the questions timeframe is current, the interview appears on website and waits for questions. Existing questions can be listed on the website, so other reader can see what already was asked. Answers will not shown yet.
  3. The moderator accept or reject new questions. Spam etc. can be deleted instantly.
  4. Within the interview timeframe, the guest answers the questions. Answered questions automatically get status published.
  5. The admin set the interview status to published, so the questions and answers are shown on the website.

 

Frontend/Template Engine

In this article:

As a template designer, you need to understand which variables can be displayed and how the relate to each other. An interview is composed of two type of objects:

  • Interview: this keeps data about the interview itself, such as title, description, image, moderator, guest, question and answer timeframes
  • Interview item: an item is a pair of one question and one answer. Each interview can contain multiple interview items

 

Interview

The interview object has the following properties:

 

Interview Item

An Interview Item contains an pair of one question and it's answer. For each interview, a certain number of interview items are used.

The Interview Item object has the following properties:

 

List of Interviews

Purpose:

Select the list of interviews according to the given constraints and current environmental variables. The code between "{{ list_interviews }}" statement and "{{ /list_interviews }}" is repeated for every interview in the list.

Syntax:

{{ list_interviews [length="<integer_value>"] [columns="<integer_value>"]
                [constraints="<list_of_interview_constraints>"]
                [order="<order_condition>"]>
}}
<list_of_instructions>
{{ /list_interviews }}

where:

<list_of_instructions> may contain any statement except: "set_interview".

<list_of_interview_constraints>= [<interview_constraint>] <list_of_interview_constraints>
| <iinterview_constraint>
<interview_constraint>= id <integer_operator> <integer_value>
| name
<string_operator> <string_value>
| language_id
<integer_operator> <integer_value>
| moderator_user_id
<integer_operator> <integer_value>
| guest_user_id
<integer_operator> <integer_value>
| status <string_operator> <string_value>
| <date_constraint>

 

<date_constraint>=

interview_begin <date_operator> <date_value>
| interview_begin_year
<integer_operator> <integer_value>
| interview_begin_month
<integer_operator> <integer_value>
| interview_begin_wday
<integer_operator> <integer_value>
|
interview_end <date_operator> <date_value>
| interview_end_year
<integer_operator> <integer_value>
| interview_end_month
<integer_operator> <integer_value>
| interview_end_wday
<integer_operator> <integer_value>

| questions_begin <date_operator> <date_value>
|
questions_begin_year <integer_operator> <integer_value>
|
questions_begin_month <integer_operator> <integer_value>
| questions_begin_wday <integer_operator> <integer_value>
|
questions_end <date_operator> <date_value>
|
questions_end_year <integer_operator> <integer_value>
|
questions_end_month <integer_operator> <integer_value>
|
questions_end_wday <integer_operator> <integer_value>



<order_condition>= byIdentifier desc|asc
| byName desc|asc
| byTitle desc|asc
| byQuestions_begin desc|asc
| byQuestions_end desc|asc
| byInterview_begin desc|asc
| byInterview_end desc|asc
| byModerator desc|asc
| byGuest desc|asc
| byStatus desc|asc
| byOrder desc|asc

 

 

 

 

 

 

 

 

 

List of Interview Items

Purpose:

Select the list of interview items according to the given constraints and current environmental variables. The code between "{{ list_interviews }}" statement and "{{ /list_interviews }}" is repeated for every interview item in the list.

Syntax:

{{ list_interviewitems [length="<integer_value>"] [columns="<integer_value>"]
                [constraints="<list_of_interview_constraints>"]
                [order="<order_condition>"]>
}}
<list_of_instructions>
{{ /list_interviewitems }}

where:

<list_of_instructions> may contain any statement except: "set_interview", "set_interviewitem".

<list_of_interviewitem_constraints>= [<interviewitem_constraint>] <list_of_interviewitem_constraints>
| <iinterviewitem_constraint>
<interviewitem_constraint>= status <string_operator> <string_value>
| questioneer_user_id <integer_operator> <integer_value>
| answer 
<string_operator> <string_value>
| status <string_operator> <string_value>


<order_condition>= byIdentifier desc|asc
| byQuestioneer desc|asc
| byQuestion desc|asc
| byAnswer desc|asc
| byStatus desc|asc
| byOrder desc|asc

 

 

 

 

 

Admin Interface

In this article:

The administration of interviews is seperated into 3 roles:

  1. Admin: Admins can create new interviews, and have access to any action
  2. Moderator: Each interview is assigned to one moderator. His main task is to accept or reject incoming questions.
  3. Guest: Each Interview have one guest assigned, who is reponsible to answer the questions

 

Admin Screen

List of Interviews

The admin screen display an list of interview. There are language and status filters for it, and columns can be ordered by each kind of item.
Following actions can be processed:

Edit Interview

By clicking on an interview's title, an popup form appear which let you edit all interview setting. Here you can adjust:

The Questions timeframe can overlap with interview timeframe.

List of Interview Items

On this screen all items for an selected interview are displayed, and following actions can be processed:

Edit Interview Item

The admin is able to edit the question and answer (e.g. mistypes), and change the status here.

Invitations

Clicking the letter-symbol in the main admin page, will open an window to setup and send invitations to reders which have register themself for this service. An red symbol indicated thet an invitation for this interview was already sent.

The popup screen allows setup of the email parts:

Clicking the "Preview" button will save the settings and displays an preview of the email. Carefully check it before send by clicking button "Invite now".

 

Moderator Screen

Guest Screen

This screen display an list of interviews, which are assigned to the logged-in moderator. There are language and status filters for it, and columns can be ordered by each kind of item.
The only available action is to list interview items.

List of Interview Items

On this screen all items for an selected interview are displayed, and following actions can be made:

Accept/Reject items

To hand over new questions to the guest, they have to be set to status "pending".
If an question should not be answered, but stored in the system, status "rejected" is used.
Items can also be deleted here.

Use the checkboxes for multiple actions.

Edit Interview Item

The moderator is able to edit the question (e.g. mistypes), and change the status on this screen.

 

Guest Screen

List of Interviews

This screen display an list of interviews, which are assigned to the logged-in guest. There are language and status filters for it, and columns can be ordered by each kind of item.
The only available action is to list interview items.

List of Interview Items

On this screen all items for an selected interview are displayed, which are passed by from the moderator. The guest have to pick up those with status "pending" and answer them in the popup. After answering an item, it will automatically get status "published". This does not mean that it occours on the website, just is the interview is also published all published items will occour.

  

Where to go for support

Forum and mailing list: You can visit the Campsite online support forum, and sign up for the mailing list, at http://forum.sourcefabric.org/index.php/f/10/.

This forum is mirrored by the mailing list, so posts on the forum appear on the mailing list and vice versa. You can therefore also post a message there by emailing: campsite-support@lists.sourcefabric.org.

To subscribe to forum updates via mail, please register or login to the forum by clicking the appropriate link. Then click the 'Subscribe' button at the top of each forum page.

Bug reporting: Campsite needs your input to improve. If you think you've found a bug, please visit http://dev.sourcefabric.org and sign in, using the same login and password that you registered for the Campsite forum. Create a bug report by selecting Create Issue, then Campsite, and then Bug. That way, the Campsite team can keep track of your problem and notify you when it has been fixed. You can also suggest improvements and new features for Campsite on that site.

Contact: Finally, when all other avenues have been exhausted, email us directly at contact@sourcefabric.org and we'll try to help!

About this manual

Campsite is being developed by an international community of developers and designers led by Sourcefabric (formerly Campware). 

http://campsite.sourcefabric.org

Copyright (C) 2010 Sourcefabric o.p.s
Copyright (C) 1999-2009 Media Development Loan Fund.

License

All chapters copyright of the authors (see below). Unless otherwise stated all chapters in this manual licensed with GNU General Public License version 2

This documentation is free documentation; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This documentation is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this documentation; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

Authors

This manual has been edited and reworked by Daniel James, based on the collaborative effort at FLOSS Manuals. Thanks to all contributors!

100.gif

Free manuals for free software

General Public License

Version 2, June 1991

Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA

Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.

Preamble

The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too.

When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.

To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.

For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.

We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.

Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.

Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.

The precise terms and conditions for copying, distribution and modification follow.

TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.

1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.

You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.

2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:

a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.

b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.

c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.

In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.

3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:

a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,

b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,

c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.

If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.

4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.

5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.

6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.

7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.

It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.

This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.

8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.

9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.

Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.

10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.

NO WARRANTY

11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

END OF TERMS AND CONDITIONS