Attention:

This is an archive of the old jlleblanc.com site. Most of the content here was created between 2004 and 2010 and built with Joomla. All articles on this site refer to outdated versions of Joomla and some links may be broken. I'm providing this in case anyone still needs it or is interested in a little trip in the time machine.

JUser tutorial for Joomla! 1.5

For every request in Joomla!, there is one user. Information about this user is readily available through the Joomla! framework in the form of an object. To get this object, use the following member function of JFactory:

	$user =& JFactory::getUser();

Getting a reference through getUser() ensures that only one user object is created during any one Joomla! request, saving on memory and processing time. Most of the information about the user is available through public member variables of the user object. This code displays the current user's name, email, user name, user type, and group id:

	echo "<p>Your name is {$user->name}, your email is {$user->email}, and your username is {$user->username}</p>";
	echo "<p>Your usertype is {$user->usertype} which has a group id of {$user->gid}.</p>";

These are the relevant member variables automatically generated on a call to getUser():

  • id - The unique, numerical user id. Use this when referencing the user record in other database tables.
  • name - The name of the user. (e.g. Vint Cerf)
  • username - The login/screen name of the user. (e.g. shmuffin1979)
  • email - The email address of the user. (e.g. crashoverride@hackers.com)
  • password - The encrypted version of the user's password
  • password_clear - Set to the user's password only when it is being changed. Otherwise, remains blank.
  • usertype - The role of the user within Joomla!. (Super Administrator, Editor, etc...)
  • gid - Set to the user's group id, which corresponds to the usertype.
  • block - Set to '1' when the user is set to 'blocked' in Joomla!.
  • registerDate - Set to the date when the user was first registered.
  • lastvisitDate - Set to the date the user last visited the site.
  • guest - If the user is not logged in, this variable will be set to '1'. The other variables will be unset or default values.

In addition to the member variables (which are stored in the database in columns), there are parameters for the user that hold preferences. To get one of these parameters, call the getParam() member function of the user object, passing in the name of the parameter you want along with a default value in case it is blank.

	$user =& JFactory::getUser();
	$language = $user->getParam('language', 'the default');

	echo "<p>Your language is set to {$language}.</p>";

Frequently, you will just want to make sure the user is logged in before continuing. The 'guest' member function will be set to '1' when the current user is not logged in. When the user is authenticated, 'guest' will be set to '0'.

	$user =& JFactory::getUser();

	if ($user->guest) {
		echo "<p>You must login to see the content. I want your email address.</p>";
	} else {
		?>

		<h1>Impromptu leftovers salad that goes well with fish</h1>
		<ul>
			<li>1/2 cup chopped celery</li>
			<li>1/4 cup raisins</li>
			<li>1 teaspoon Extra Virgin Olive Oil</li>
			<li>2 tablespoons of faux Thai lemongrass marinade</li>
			<li>1/4 cup shredded fresh basil</li>
			<li>Sprinkling of dill weed</li>
			<li>Big pinch of kosher salt</li>
			<li>Several lettuce leaves (to taste)</li>
		</ul>

		<p>Wash the lettuce and basil because there's no telling who touched it before you did,
even if the package says "prewashed."
Put them in a bowl; preferably a hand-crafted salad bowl,
but a metallic measuring bowl will also do.
Get out a much smaller bowl and swish around all of the remaining ingredients.
Actually, if you don't want to dirty up a perfectly good and clean bowl,
you can probably just use the first bowl for this step
and dump the greens on top. Toss irregularly. Consume promptly.
Serves two, unless somebody eats a smaller portion.</p>
		<?php
	}

Not all authenticated users are given equal rights. For instance, a Super Administrator may be able to edit anyone's content, while a Publisher may only be able to edit their own. The authorize() member function can be used to determine if the current user has permission to do a certain task. The first parameter is used to identify which component or function we wish to authenticate against. The second represents the task. The third and fourth are optional; they further break the permissions down into record types and ownership respectively.

In Joomla! 1.5, the rights for all of the core components are stored in libraries/joomla/user/authorization.php. These are available to all extensions wherever authentication is required. If the permission scheme of the Content component suits your extension's needs, you can use code similar to the following to determine what functions to give to a specific user.

	$user =& JFactory::getUser();

	if ($user->authorize('com_content', 'edit', 'content', 'all')) {
		echo "<p>You may edit all content.</p>";
	} else {
		echo "<p>You may not edit all content.</p>";
	}

	if ($user->authorize('com_content', 'publish', 'content', 'own')) {
		echo "<p>You may publish your own content.</p>";
	} else {
		echo "<p>You may not publish your own content.</p>";
	}

The permissions for core functions may not be suitable for your extension. If this is the case, you can create your own permissions. You will probably want to add this code in a place where it will always be executed, such as the beginning of the component you are building or in a systemwide plugin. First, you need to get an authorization object using the getACL() member function of JFactory. This works like getUser() in that it only creates one authorization object during any particular Joomla! request. Once you have this object, call the addACL() member function to add permissions. Pass in the name of your component or function, the task name, the string 'users', and the user type (in lowercase) respectively. If you want to also define record sets and ownership, pass those in as an additional two parameters.

Note that in Joomla! 1.5, permissions are not inherited. For example, if you give an Administrator the right to edit content, Super Administrators do not automatically get this right; you must grant it separately.

	$auth =& JFactory::getACL();

	$auth->addACL('com_userinfo15', 'persuade', 'users', 'super administrator');
	$auth->addACL('com_userinfo15', 'persuade', 'users', 'administrator');
	$auth->addACL('com_userinfo15', 'persuade', 'users', 'manager');

	$user =& JFactory::getUser();

	if ($user->authorize('com_userinfo15', 'persuade')) {
		echo "<p>You may persuade the system to do what you wish.</p>";
	} else {
		echo "<p>You are not very persuasive.</p>";
	}

Information about the current user is readily available in any part of your Joomla! extension. You need only fetch the object and access the member variables. You can authorize the user against the core permissions set, or create your own to suit your needs.

An installable component featuring these code snippets is available for download here. Log into the frontend of your site and go to index.php?option=com_userinfo15 to see them in action. Log in with different users to see how the behavior changes. Access it as an unauthenticated user as well to see the difference.

 

Daily Message Component Tutorial for Joomla 1.5

This tutorial is designed to help you build a complete component with a backend and frontend. After reading the tutorial, you should understand how some of the core classes and functions work so that you can use them in your own components. A full, ready to install copy of the component can be downloaded here. This tutorial is designed for Joomla 1.5; a version for 1.0 can be found here.

Different people will understand the functionality of Joomla components in different ways. Developers with significant previous PHP experience may wish to start with dailymessage.php (the file generating the frontend display) and admin.dailymessage.php (generates the backend display). Others will want to start with the XML document which maps out every code source, image, and SQL query.

dailymessage.php

When you click on a link to the Daily Message component from the frontend, the file dailymessage.php in the /components/com_dailymessage folder is executed. You can add any valid PHP code you wish from here, but there are some security measures you should take even if you are not going to be using Joomla!'s libraries.

<?php

defined('_JEXEC') or die();

As with every file of source code in Joomla!, we start with an opening PHP tag. We also use the defined() call to check to make sure that Joomla! is requesting dailymessage.php and that it is not being requested directly. If it is being requested directly, we quit right away.

$db =& JFactory::getDBO();

$db->setQuery("SELECT * FROM #__dailymessage WHERE published = 1 ORDER BY date");
$rows = $db->loadObjectList();

The first thing we want to do is to grab all of the published messages from the database so that we can prepare them for display. To do this, we first get a reference to the database Joomla! is currently connected to. Next, we pass our query into the setQuery() member function. The prefix #__ will be converted to jos_ (or whatever database prefix you chose for your installation) when the query is actually run. To get the rows out, we call the loadObjectList() function which returns an array of row objects. This array gets stored in $rows.

list($begin, $end) = getMessageFormat();

Our component has some configuration that allows the administrator to add bold, underline, and italicize tags around each message. The getMessageFormat() function (defined in this file below) returns an array with the opening and closing tags. We use PHP's list() language construct to extract the two array elements into $begin and $end.

echo '<ul>';

foreach ($rows as $row) {
echo '<li>' . JHTML::date($row->date) . ' ' . $begin . $row->message . $end . '</li>';
}

echo '</ul>';

To list the daily messages, we start by outputting an opening unordered list tag. Then we cycle over each record in the $rows array and output a list item for each. The JHTML::date() function formats the value of $row->date according to the preferences set in Joomla!. The beginning formatting tags are output, followed by the message in $row->message, followed by the ending formatting tags.

function getMessageFormat()
{
$params =& JComponentHelper::getParams('com_dailymessage');

In Joomla!, menu items control the appearance and behavior of a page, as well as the configuration for a component. This function is designed to get the configuration for the current menu item and return an appropriate set of formatting tags. The getParams() member function of JComponentHelper returns a parameters object when we pass in the name of a component (in this case, com_dailymessage). Since we are loading com_dailymessage, we get the parameters set for the current menu item and store them in $params.

	$italic = $params->get('italic', false);
$bold = $params->get('bold', false);
$underline = $params->get('underline', false);

The get() member function of the $params object returns the values for parameter names you pass in. In addition to the names, you can specify a default value for your parameters (in our case, false).

	$begin = '';
$end = '';

if ($italic) {
$begin .= '<i>';
$end = '</i>' . $end;
}

if ($bold) {
$begin .= '<b>';
$end = '</b>' . $end;
}

if ($underline) {
$begin .= '<u>';
$end = '</u>' . $end;
}

Before building our formatting tags, we set $begin and $end as blank strings. We then test each of the variables we just set using $params->get(). If they are set to something other than false or 0, we add the appropriate tags to the $begin and $end strings; the $begin tags are appended, while the $end tags are prepended.

	$format = array($begin, $end);

return $format;

Finally, we set $format to the contents of $begin and $end with a space between, then return $format.

}

admin.dailymessage.php

When you go to the backend and choose Daily Message from the Components menu, the file admin.dailymessage.php in the /administrator/components/com_dailymessage folder is executed. This file can contain any PHP code you desire, but you are probably more interested in generating screens that look like the ones in other components.

<?php

defined('_JEXEC') or die();

We begin with an opening <?php tag and a call to defined(). This particular call makes sure that the code is being executed from within Joomla!. If not, PHP will stop right away. This is to prevent people from running your code outside of Joomla!. Without this line, someone would be able to pull up http://www.yoursite.com/administrator/components/com_dailymessage/admin.dailymessage.php without having to first log into the backend, leaving them free to use the functions you intended only for admins. For this reason, place this line at the top of each one of your files of code.

JTable::addIncludePath(JPATH_COMPONENT.DS.'tables');

This call to the addIncludePath() member function of JTable pulls in all of the files in our directory of database table classes. Any classes contained in these files will be available through JTable. The JPATH_COMPONENT constant is automatically defined by Joomla! to point to the current directory where our component script is running. A directory separator appropriate to the host operating system is defined in DS. Therefore, if our installation of Joomla! was hosted at /var/www on our host, the resulting string in the call to addIncludePath() would be /var/www/administrator/components/com_dailymessage/tables.

require_once(JPATH_COMPONENT.DS.'controller.php');

The logic flow through our backend component will be handled through a controller. Our controller makes it simple to add new functions to the component in an organized, predictable way.

$controller = new DailyMessageController();
$controller->registerDefaultTask('listMessages');

To get the controller started, we assign a new instance of DailyMessageController to $controller. Next, we use the registerDefaultTask() member function to specify which function should be executed when the user either does not choose one or tries to use one that does not exist.

$task = JRequest::getCmd('task');

When we pass in 'task', the getCmd() member function of JRequest will return the name of the function the user is trying to run. This can appear in the URL (http://www.yoursite.com/administrator/index.php?option=com_dailymessage&task=iwanttorunthistask), be included in the HTTP POST variables, or be otherwise generated by the Joomla! framework.

$controller->execute($task);
$controller->redirect();

With the correct $task in hand, we pass it off to execute() where it is matched up to the name of a function. Finally, we call redirect(). If we executed a $task that did not result in a screen, we need to redirect the browser to another task that does.

controller.php

This file includes a controller based on the JController base class included with Joomla!. It automates the logical flow of our component so we can concentrate on adding new functions as we need them without disturbing older ones. We pass in the task we want to run into execute() and the controller handles the rest.

<?php

defined('_JEXEC') or die();

jimport('joomla.application.component.controller');

Once again, we begin with an opening <?php tag and a check to make sure that _JEXEC has been set. We also use the jimport() function to pull in the code for the JController base class. Joomla! is in the habit of keeping the code in memory to a minimum (to keep performance fast), while providing a large library of functions and classes for you to use where desired.

class DailyMessageController extends JController
{

We declare our DailyMessageController class as an extension of JController. Extending this class provides ours with the registerDefaultTask(), execute(), and redirect() member functions we used in admin.dailymessage.php along with several others. All extensions of JController typically follow the convention of having a name ending in 'Controller', as ours does.

	function __construct()
{
parent::__construct();

The __contstruct() function is called when a new DailyMessageController() is created. (The default behavior of PHP 5 does this by default where PHP 4 does not. Joomla!'s JObject base class adds this behavior to PHP 4). We call the JController constructor so that it can build an inventory of all of the tasks available.

		$this->registerTask('add', 'edit');
$this->registerTask('unpublish', 'publish');

There are two tasks, add and unpublish, that are almost identical in nature to other tasks present in the controller. Instead of writing entirely different functions for these with only minor changes, we use the registerTask() JController member function to tell the controller to call the edit function when we choose 'add' and the publish function when we select 'unpublish'. (While it might seem that unpublishing is the complete opposite of publishing, all we are really doing is changing a number in the database.)

	}

function save()
{
$option = JRequest::getCmd('option');
$this->setRedirect('index.php?option=' . $option);

The save() task will be adding and updating the data for our daily messages in the database. Since it will not normally generate output, we will want to redirect the user back to the main admin screen for our component when we are done saving. As we did with $task, passing 'option' into JRequest::getCmd() will return 'com_dailymessage'. (If we were to later change the name of our component to something else, say com_weeklymessage, this piece of code would return the new name instead.) The setRedirect() member function of JController specifies the URL we want to send the user to after the task is complete.

		$post = JRequest::get('post');

The when we pass 'post' into the get() member function of JRequest, it processes and returns a cleaned copy of the variables in the $_POST array. Using get('post') instead of accessing $_POST provides us with a level of protection against malicious data.

		$row =& JTable::getInstance('DailyMessage', 'Table');

The getInstance() member function of JTable returns a database table object for the table where will will store our data. The name "TableDailyMessage" is assembled by getInstance() as the second parameter is the class name prefix and the first is the suffix.

		if (!$row->bind($post)) {
return JError::raiseWarning(500, $row->getError());
}

if (!$row->store()) {
return JError::raiseWarning(500, $row->getError());
}

We call two member functions of the database table object. Passing an array into bind() matches the keys and values of that array to the member variables of the database table class. Calling store() takes the member variables and executes an SQL statement for either an INSERT or UPDATE statement. If a value is provided for the table key, an UPDATE statement is used; otherwise an INSERT is generated. If either bind() or store() fails, we call the raiseWarning() member function of JError to stop the component and to dump the error to the screen so we can figure out how to fix it.

		$this->setMessage('Message Saved');

Finally, once the data has successfully made it into the database, we use JController's setMessage() member function to store a message to be displayed in the browser after the task is complete. Since the save() task does not produce any output, this message is added as a variable in the URL the browser is redirected to when the $controller->redirect() function is called in controller.php.

	}

function edit()
{
$cid = JRequest::getVar('cid', array(), 'request', 'array');

Similar to the $post variable in the save() task, we want to get an array from the HTTP request and we want Joomla! to make sure the contents are safe. The getVar() member function of JRequest works similar to get(), except that it only retrieves an element from one of the superglobal arrays ($_GET, $_POST, $_REQUEST, etc...). In this instance, we are getting the 'cid' variable. If this does not exist, we want to default to a blank array. We want Joomla! to pull this out of the $_REQUEST superglobal and want to ensure that the data is in fact an array.

		$row =& JTable::getInstance('DailyMessage', 'Table');

As in the save() task, we pull in a database table object for the table where the daily messages are stored.

		if (isset($cid[0])) {
$row->load($cid[0]);
}

Unlike the save() task, we first test to see if one of the records has been chosen by the user. The 'cid' form variable represents the checkboxes you see alongside a listing of records. If the user has checked at least one box, the ID of the first one checked will be present in $cid[0]. We then call the load() member function to get the corresponding record from the database. If no boxes have been checked, we will just have a 'blank' database table object.

		require_once(JPATH_COMPONENT.DS.'admin.dailymessage.html.php');
$option = JRequest::getCmd('option');
HTML_DailyMessage::edit($option, $row);

Since the edit() task will be generating HTML output, we need to pull in the file with the functions that generate it: admin.dailymessage.html.php. Using JPATH_COMPONENT and DS allow us to get a path to our current directory and we just add the filename to the end. The function generating the edit form needs to know which component to point to, so we use JRequest::getCmd() to get the value of 'option'. Finally, we call HTML_DailyMessage::edit(), passing in the name of the component with the row of data (or the blank if one was not loaded) so that the form can be displayed.

	}

function remove()
{
$option = JRequest::getCmd('option');

$this->setRedirect('index.php?option=' . $option);

$db =& JFactory::getDBO();
$cid = JRequest::getVar('cid', array(), 'request', 'array');

The remove() task looks for any IDs found in the 'cid' array and removes the corresponding daily messages from the database. Like the save() task, this task does not produce any direct output, so we capture the component name in $option and set our redirect to go back to the main component screen when the deleting is complete. We get a reference to the live database object as well as a copy of the 'cid' array from the request.

		$count = count($cid);

if ($count)
{

Before attempting to remove records from the database, we first get a count of the number of IDs. If there are none, this entire block is skipped and the browser just redirects back to the main component screen (although the Javascript in the toolbar usually prevents this from happening in the first place).

			$db->setQuery('DELETE FROM #__dailymessage WHERE id IN (' . implode( ',', $cid ) . ')' );

If the IDs are present, we create a query to delete them and pass it into the setQuery() member function of the database object. The constant #__ is automatically turned into your installation's database prefix (usually jos_) when it is run. PHP's implode() function takes our array of IDs and turns it into a comma separated string the database can understand.

			if (!$db->query()) {
JError::raiseWarning( 500, $db->getError() );
}

After the query is set, we call the database object's query() member function which executes that query. If a problem occurs, we stop processing, raise a warning, and display the error from the database for debugging.

			if ($count > 1) {
$s = 's';
} else {
$s = '';
}

$this->setMessage('Message' . $s . ' removed');

If the deletion goes through with no problems, we add a message to be displayed on the main screen stating they were removed. First, we determine whether one or several records were removed and use this to properly pluralize the message. Then we call setMessage() so that the controller can add it to the redirection URL for display.

		}
}

function publish()
{
$option = JRequest::getCmd('option');

$this->setRedirect('index.php?option=' . $option);

$cid = JRequest::getVar('cid', array(), 'request', 'array');

The publish() task gets IDs from the 'cid' array and sets the publishing for these records. This is yet another task that does not produce any direct output, so we set our redirect to go back to the main list screen after we are done. The $cid variable gets set to the 'cid' array from the request.

		if ($this->getTask() == 'publish') {
$publish = 1;
} else {
$publish = 0;
}

The publish() task is set to handle both the 'publish' and 'unpublish' tasks. Because of this, we need to determine which task we are handling and act accordingly. The controller's getTask() member function returns this back to us value back to us. If it is equal to 'publish', we set $publish to 1, otherwise (when it is set to 'unpublish') we set $publish to 0.

		$table =& JTable::getInstance('DailyMessage', 'Table');

$table->publish($cid, $publish);

After getting a database table object for the daily message table, we call JTable's publish() member function. This function takes an array of table key IDs and sets the 'publish' column of the rows with those IDs to the value of the second parameter.

		if (count($cid) > 1) {
$s = 's';
} else {
$s = '';
}

$action = ucfirst($this->getTask()) . 'ed';

$this->setMessage('Message' . $s . ' ' . $action);

Once the publishing or unpublishing is complete, we are ready to redirect the user back to the list of messages. Before doing this, we need to assemble an appropriate message to display at the top of the screen when they land there. First, we count the number of records processed and set $s accordingly for pluralizing the word. Next, we again use the getTask() member function of the controller to get the name of the task we just published, capitalize the first letter, add 'ed' to the end, and store the result in $action. This way, $action will either say 'Published' or 'Unpublished'. Finally, we call the controller's setMessage() function to make it available on redirection.

	}

function listMessages()
{
$option = JRequest::getCmd('option');

$db =& JFactory::getDBO();
$db->setQuery("SELECT * FROM #__dailymessage");
$rows = $db->loadObjectList();

The listMessages() task gets all of the messages from the database, then passes these along to be turned into an admin screen where the messages are listed. First, we get the component name using JRequest::getCmd('option'), because it will be needed to build the form controlling the message list. Next, we get a reference to the current database object and use setQuery() to pass in our SELECT statement. Finally, we use the loadObjectList() member function, which returns all of the records in the database as an array of objects. Each of the objects in the $rows array represent a single row in the database table, with the column values available as public variables.

		require_once(JPATH_COMPONENT.DS.'admin.dailymessage.html.php');
HTML_DailyMessage::listMessages($option, $rows);

Like the edit() task, we include admin.dailymessage.html.php so that we can call up the function for HTML output. Then we pass the current component name and the array of row objects into HTML_DailyMessage::listMessages() for display.

	}
}

admin.dailymessage.html.php

<?php

defined('_JEXEC') or die();

class HTML_DailyMessage
{

As with the other files, we begin with our opening PHP tag, the check to make sure we are in Joomla!, and declare the HTML_DailyMessage class.

	function listMessages($option, &$rows)
{
HTML_DailyMessage::setAllMessagesToolbar();

The listMessages() function takes the current component name as the first parameter, and an array of row objects as the second (using & to pass this array by reference to save memory). We then call the setAllMessagesToolbar() function in this same class to set up our toolbar buttons. Notice that we are not calling $this->setAllMessagesToolbar(), since we are using HTML_DailyMessage statically.

		?>
<form action="index.php" method="post" name="adminForm">

The form wrapping around all message record listings points to index.php (as all requests through Joomla! do) and is named 'adminForm'. Naming the form as such is very important so that the Javascript in Joomla!'s backend can interact with it.

			<table class="adminlist">
<thead>
<tr>
<th width="20">
<input type="checkbox" name="toggle" value="" onclick="checkAll(<?php echo count( $rows ); ?>);" />
</th>
<th nowrap="nowrap" class="title">Message</th>
<th nowrap="nowrap">Date</th>
<th nowrap="nowrap">Published</th>
</tr>
</thead>

Our records are presented in a table, which is assigned the 'adminList' class. This makes the table appear with the same style as other components in the Joomla! backend. Next, we create the header row. The first header column is a checkbox that will allow the user to toggle on or off all of the records on screen at once. We give it the name 'toggle' and assign an onclick event, passing in the total number of rows being displayed on the screen.

				<tbody>

<?php

$k = 0;
for ($i=0, $n=count( $rows ); $i < $n; $i++) {
$row = &$rows[$i];

We begin our loop through the records by first setting $k to 0, which we will use to help us alternate the row styles. Next, we set our for() loop with $i starting at 0 and $n equaling the total number of rows to be displayed. Inside the loop, we set $row to a reference of the object in the array at position $i.

						$published = JHTML::_('grid.published', $row, $i );
$checked = JHTML::_('grid.id', $i, $row->id );

Before outputting the row, we want to build a couple of elements so that we can essentially echo out the rest. The JHTML::_() function allows us to get commonly used HTML from the Joomla! library. To reduce the amount of code in memory, Joomla! only loads the functions for the particular HTML elements we want when we want them. To do this, we pass in the name of the element desired as the first parameter, then all of the other parameters for that element afterwards. The JHTML class does the rest, without the need to call jimport() to pull in the necessary files. For the publishing button, we pass in our $row and the current record number in $i. For the checkbox, we pass in the record number first, then the $row.

						$link = 'index.php?option=' . $option . '&task=edit&cid[]='. $row->id;

We also build the URL for the links to messages using the component name and the id of the $row. The cid[] variable in the URL will match the form variable for the checkbox, it will all look the same to our controller.

						?>
<tr class="<?php echo "row$k"; ?>">
<td align="center">
<?php echo $checked; ?>
</td>
<td>
<a href="/<?php echo $link; ?>" title="Edit Message">
<?php echo $row->message; ?>
</a>
</td>
<td>
<?php echo JHTML::date($row->date); ?>
</td>
<td align="center">
<?php echo $published; ?>
</td>
<?php

Outputting the row is straightforward. First, we start the row and assign the <tr> element with the class 'row$k', where $k is either a 1 or 0. The background of class 'row1' is slightly darker than 'row0', which creates an alternating visual effect. The checkbox and link URL are simply echoed out, as well as the publishing button. The text for the editing URL is the daily message itself, which is found in the $row object's 'message' member variable (just like the 'message' column in the database). The 'date' column in the database is in MySQL date format, which is usually not what we want to display. Passing this through JHTML::date() formats it according to the display preferences of the user.

						$k = 1 - $k;

This line may appear a little odd, but it helps to create the alternating bar visual effect on the table. If $k is set to 0, we subtract it from 1 and end up with 1 for the next cycle through the loop. When $k is already set to 1, we subtract 1 and get back to 0. This way, the rows alternate evenly between row0 and row1.

					}

?>
</tbody>
</table>

<input type="hidden" name="option" value="<?php echo $option; ?>" />
<input type="hidden" name="task" value="" />
<input type="hidden" name="boxchecked" value="0" />
</form>
<?php

After finishing off the table, we need to add a few hidden variables to the form to tie everything together. The 'option' variable identifies our component when the call to Joomla! is made so that we are properly routed. The 'task' variable is what our controller uses to determine which function to call. We set this as a blank at first; the toolbar buttons will be able to fill this in later. Finally, we set a 'boxchecked' variable so that the Javascript can keep track of how many checkboxes are ticked.

	}

function edit($option, &$row)
{
HTML_DailyMessage::setMessageToolbar($row->id);

JHTML::_('behavior.calendar');

The edit() function takes the name of the component as the first parameter and a reference to a database row object as the second. We call the setMessageToolbar() function, passing in the id of the row. This will allow the toolbar to make some slight adjustments depending on whether we are editing an existing record or creating a new one. As in the listMessages() function, we call the JHTML::_() function to pull in some common HTML. The 'behavior.calendar' element will put a <script> tag in the HTML header that will load the Javascript to power a popup calendar in the form.

		?>
<form action="index.php" method="post" name="adminForm">

Just like the list screen, we need to have our form pointing to index.php and named 'adminForm' for Javascript interaction.

			<div class="col100">
<fieldset class="adminform">
<table class="admintable">
<tbody>
<tr>
<td width="20%" class="key">
<label for="message">Message</label>
</td>
<td>
<input class="inputbox" type="text" name="message" id="message" size="40" value="<?php echo $row->message; ?>" />
</td>
</tr>
<tr>
<td width="20%" class="key">
<label for="date">Date</label>
</td>
<td>
<input class="inputbox" type="text" name="date" id="date" size="40" value="<?php echo $row->date; ?>" />
<input type="reset" class="button" value="..." onclick="return showCalendar('date', 'y-mm-dd');" />
</td>
</tr>
<tr>
<td width="20%" class="key">
<label for="published">Published</label>
</td>
<td>
<?php echo JHTML::_('select.booleanlist', 'published', '', $row->published ); ?>
</td>
</tr>
</tbody>
</table>
</fieldset>
</div>

The edit form uses the 'col100', 'adminform', 'admintable', 'key', 'button', and 'inputbox' classes to format the output to look like other forms in the Joomla! admin interface. The 'message' and 'date' variables are directly populated with values from the $row object. Next to the date field, we build a form button and assign an onclick event to it that displays our popup calendar when clicked. Since we pass 'date' into this Javascript function, it will look for the input named 'date' and fill it in with is chosen from the popup. The 'published' field is represented as a radio button, which we generate using JTHML::_('select.booleanlist', ... ),

		<input type="hidden" name="option" value="<?php echo $option; ?>" />
<input type="hidden" name="task" value="" />
<input type="hidden" name="id" value="<?php echo $row->id ?>" />
</form>
<?php

As with the message list, we need a few hidden variables to take care of a few things. We include the 'option' value and a blank 'task' variable as we did before. We also add an 'id' field which is set to the row id, if it exists. If no value is provided here or it does not exist, our code will assume that it is a new record and will add it to the database.

	}

function setMessageToolbar($id)
{
if ($id) {
$newEdit = 'Edit';
} else {
$newEdit = 'New';
}

We called setMessageToolbar() from our edit() function to configure the toolbar for our editing screen. It takes the row $id as the parameter. We use this to determine if we are adding or editing a message and set $newEdit accordingly.

		JToolBarHelper::title($newEdit . ' Message', 'generic.png');
JToolBarHelper::save();
JToolBarHelper::cancel();

The JToolBarHelper member functions add toolbar buttons in the order you call them. The exception to this is the title() function which sets the screen title to the left of the toolbar. Using our $newEdit variable set above, we set this message, then pass in the name of the image we want to use as the icon for the title. After setting the title, we add the 'save' and 'cancel' buttons to the toolbar. When these are clicked, they will set the task variable in the form to 'save' and 'cancel' respectively.

	}

function setAllMessagesToolbar()
{
JToolBarHelper::title('Message Manager', 'generic.png');
JToolBarHelper::publishList();
JToolBarHelper::unpublishList();
JToolBarHelper::deleteList();
JToolBarHelper::editList();
JToolBarHelper::addNew();

Like the toolbar for editing, we set the title first along with an icon. Then we proceed to add buttons for publishing, unpublishing, deleting, editing, and adding, which set task to 'publish', 'unpublish', 'remove', 'edit', and 'add' respectively. The functions names ending in 'List' also check to make sure that at least one of the checkboxes is ticked before submitting the form. Otherwise, a Javascript alert appears.

	}
}

tables/dailymessage.php

<?php

defined( '_JEXEC' ) or die( 'Restricted access' );

class TableDailyMessage extends JTable
{

We start by checking to make sure that we are inside of Joomla!, then declare the TableDailyMessage class as an extension of the JTable class.

	var $id = null;
var $message = null;
var $date = null;
var $published = null;

These four variables match the four columns found in the #__dailymessage table in the database. We begin by setting them to null. This makes it easier for the class to generate SQL UPDATE commands: it can skip over any variable that is still set to null.

	function __construct(&$db)
{
parent::__construct( '#__dailymessage', 'id', $db );

The only method we are defining for TableDailyMessage is __construct(). This is PHP 5's constructor which is emulated under PHP 4 (if you are still running that version). The current database object gets passed in by reference. Right away, we call JTable's original constructor and pass in the name of our table (with the #__ prefix shorthand), the name of the key column, and the database object. Since we have identified the 'id' column as the key, the object will know when to generate UPDATE rather than INSERT statements based on whether 'id' is set. It will also use this key when we call the load() or delete() functions.

		jimport('joomla.utilities.date');
$now = new JDate();
$this->set( 'date', $now->toMySQL() );

We also want to set the current date as the default value for 'date' in the event that none is specified. First, we call jimport() to pull in the date utilities, then create a date object and store it in $now. (This object defaults to the current date and time.) Then we call JTable's set() member function, passing in 'date' (the column we wish to set) and then the date we wish to set it to. The toMySQL() member function of the JDate class takes the date represented in the object and returns a MySQL-formatted copy.

	}
}


dailymessage.xml

<?xml version="1.0" encoding="utf-8"?>
<install type="component" version="1.5.0">

This XML file serves three purposes: identifying our component, guiding the component installation/removal, and providing the configuration parameters that are available when we create a menu link to the component. The first line of this file identifies it as an XML 1.0 document in UTF-8 format. We continue with an opening <install> tag that encloses the rest of the file. We identify the package type as a component and designate that it is intended for Joomla! 1.5.0.

	<name>Daily Message</name>
<author>Joseph LeBlanc</author>
<creationDate>August 2007</creationDate>
<copyright>(C) 2004 - 2007 Joseph L. LeBlanc. All rights reserved.</copyright>
<license>http://www.opensource.org/licenses/mit-license.php MIT</license>
<authorEmail>contact@jlleblanc.com</authorEmail>
<authorUrl>www.jlleblanc.com</authorUrl>
<version>1.5.0</version>
<description>Manages message for dates</description>

The <name>, <author>, <creationDate>, <copyright>, <license>, <authorEmail>, <authorUrl>, <version>, and <description> elements are all used to identify the component within Joomla!. Although in this case the <version> element matches the version attribute on the <install> tag, this element is intended to identify the version of your component (rather than the target Joomla! version).

	<install>
<sql>
<file driver="mysql" charset="utf8">install.mysql.sql</file>
</sql>
</install>

<uninstall>
<sql>
<file driver="mysql" charset="utf8">uninstall.mysql.sql</file>
</sql>
</uninstall>

These tags identify the SQL files to run when installing and uninstalling the component. Joomla! is designed to support multiple database types. If you want to support other databases in addition to MySQL, you will need to add separate SQL files to these sections.

	<files>
<filename>dailymessage.php</filename>
</files>

This section identifies all of the files going into the frontend portion (/components/com_dailymessage) of the component. Daily Message has a very simple frontend, so only dailymessage.php is included.

	<params>
<param name="bold" type="radio" default="0" label="Bold" description="Display messages in bold">
<option value="0">No</option>
<option value="1">Yes</option>
</param>
<param name="italic" type="radio" default="0" label="Italic" description="Display messages in italics">
<option value="0">No</option>
<option value="1">Yes</option>
</param>
<param name="underline" type="radio" default="0" label="Underline" description="Display messages with an underline">
<option value="0">No</option>
<option value="1">Yes</option>
</param>
</params>

When we create a frontend link to the Daily Message component, we want to do some quick configuration. These <param> tags allow us to provide several options. On the link editing screen, these tags will be read and HTML elements will automatically be generated based on them. When the administrator saves the link, the values chosen will be saved along with the menu item; there is no need to create another table or any other place to store this information.

	<administration>
<menu>Daily Message</menu>

Some of the elements of our component are distinctly a part of the backend and should never reach the frontend. We put these within the <administration> tags. To begin, we add a <menu> tag defining the name of the item added to the Components menu. This will give administrators a link to the list screen in backend of the component.

		<files folder="admin">
<filename>install.mysql.sql</filename>
<filename>uninstall.mysql.sql</filename>
<filename>admin.dailymessage.php</filename>
<filename>admin.dailymessage.html.php</filename>
<filename>controller.php</filename>
<filename>LICENSE</filename>
<filename>tables/dailymessage.php</filename>
</files>

The <files> tag encloses a list of files to be copied to /administrator/components/com_dailymessage. Within our .zip file, there is a folder named 'admin' where all of these files are kept. Notice that we are again listing install.mysql.sql and uninstall.mysql.sql: if we do not do this, these files will not be copied and will not get executed. Also, when we list files under subdirectores (like tables/dailymessage.php), these subdirectories will automatically be created under /administrator/components/com_dailymessage.

	</administration>

</install>

These two closing tags finish off the file.

Download a copy of the component here.

   

Page 1 of 6