What files are required to create a theme for dotProject 2.1.2?

Ok, so I want to create a theme for dotProject. I love doing something for open source projects but it is never easy. So much is not documented.

I would imagine that since dotProject is free, it would be worth it to a company to pay for some customization and some really shiny themes. I know another open source project, SquirrellMail, has a lot of themes that can be purchased out there.

So I am going to look at the three themes that come with dotProject by default and determine what it takes to make my own.

Files in a dotProject Theme

So each them appears to have most of the following files (though each theme does not have all files):

  • footer.php
  • header.php
  • images (directory)
  • index.html
  • login.php
  • lostpass.php
  • main.css
  • overrides.php

So the only directory is the images directory. So what images does it usually contain? I usually contains the following files in general. Some contain more, some less. Some similar files with different names. But that gives you a basic idea.

  • dp_icon.gif
  • favicon.ico
  • index.html
  • obj (directory)
  • titlegrad.jpg
  • tabBg.png
  • tabLeft.png
  • tabRight.png
  • tabSelectedBg.png
  • tabSelectedLeft.png
  • tabSelectedRight.png

Again, there is often a directory in images called obj. The obj directory has the following files.

  • index.html
  • tick.gif

Well, that is pretty much it for the file structure of a dotProject theme.

So lets look at the common files and what is in them? However, how should we group them? How about by extension first, then by name:

HTML File (Optional)

There is only one, but it is in each folder, and as I suspected, it is optional.

  1. index.html – Ok, so why are there these random index.html files? They all only contain one line:
    <html><body bgcolor="#FFFFFF"></body></html>
    

    I have to say that these index.html files are for no other reason that to prevent directory browsing, which should probably be done by a security setting in your web server, so these files are completely optional.

CSS File (Required)

There appears to be only one CSS file, but that doesn’t mean you can’t have multiple CSS files in your theme. However, this is probably the most important file for your theme, so obviously it is required.

  1. main.css – This is of course the file that determines all the style information for the web page. Each HTML element has a style and this is where you change it.

PHP Files – (Requirements unknown)

  1. footer.php – By the name, you can tell this script has to do with the footer of your web page.

    There doesn’t seem to be much variation on this file. It seems to usually have the following script:

    <?php
    	echo $AppUI->getMsg();
    ?>
    	</td>
    </tr>
    </table>
    </body>
    </html>
    
  2. header.php – This file is a lot more complex and has over 100 lines in each theme I have looked at. It will take some time to see what is required. It looks like this is actually both the header and the body. The body appears to be formatted with an HTML table instead of using CSS. So here is the code from the default theme.
    <?php /* STYLE/DEFAULT $Id: header.php 5544 2007-11-27 01:04:12Z merlinyoda $ */
    if (!defined('DP_BASE_DIR')) {
    	die('You should not access this file directly');
    }
    $dialog = dPgetParam( $_GET, 'dialog', 0 );
    if ($dialog)
    	$page_title = '';
    else
    	$page_title = ($dPconfig&#91;'page_title'&#93; == 'dotProject') ? $dPconfig&#91;'page_title'&#93; . '&nbsp;' . $AppUI->getVersion() : $dPconfig['page_title'];
    ?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    	   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
    	<meta name="Description" content="dotProject Default Style" />
    	<meta name="Version" content="<?php echo @$AppUI->getVersion();?>" />
    	<meta http-equiv="Content-Type" content="text/html;charset=<?php echo isset( $locale_char_set ) ? $locale_char_set : 'UTF-8';?>" />
    	<title><?php echo @dPgetConfig( 'page_title' );?></title>
    	<link rel="stylesheet" type="text/css" href="./style/<?php echo $uistyle;?>/main.css" media="all" />
    	<style type="text/css" media="all">@import "./style/<?php echo $uistyle;?>/main.css";</style>
    	<link rel="shortcut icon" href="./style/<?php echo $uistyle;?>/images/favicon.ico" type="image/ico" />
    	<?php @$AppUI->loadJS(); ?>
    </head>
    
    <body onload="this.focus();">
    <table width="100%" cellpadding="0" cellspacing="0" border="0">
    <tr>
    	<td><table width="100%" cellpadding="3" cellspacing="0" border="0"><tr>
    	<th background="style/<?php echo $uistyle;?>/images/titlegrad.jpg" class="banner" align="left"><strong><?php
    		echo "<a style='color: white' href='{$dPconfig&#91;'base_url'&#93;}'>$page_title</a>";
    	?></strong></th>
    	<th align="right" width='50'><a href='http://www.dotproject.net/' <?php if ($dialog) echo "target='_blank'"; ?>><img src="style/<?php echo $uistyle;?>/images/dp_icon.gif" border="0" /></a></th>
    	</tr></table></td>
    </tr>
    <?php if (!$dialog) {
    	// top navigation menu
    	$nav = $AppUI->getMenuModules();
    	$perms =& $AppUI->acl();
    ?>
    <tr>
    	<td class="nav" align="left">
    	<table width="100%" cellpadding="3" cellspacing="0">
    	<tr>
    		<td>
    		<?php
    		$links = array();
    		foreach ($nav as $module) {
    			if ($perms->checkModule($module['mod_directory'], 'access')) {
    				$links[] = '<a href="?m='.$module&#91;'mod_directory'&#93;.'">'.$AppUI->_($module['mod_ui_name']).'</a>';
    			}
    		}
    		echo implode( ' | ', $links );
    		echo "\n";
    		?>
    		</td>
    		<td nowrap="nowrap" align="right">
    		<form name="frm_new" method=GET action="./index.php">
    		<table cellpadding="0" cellspacing="0">
    		<tr><td>
    <?php
    	$newItem = array( 0=>'- New Item -' );
    	if ($perms->checkModule( 'companies', 'add' )) $newItem["companies"] = "Company";
    	if ($perms->checkModule( 'contacts', 'add' )) $newItem["contacts"] = "Contact";
    	if ($perms->checkModule( 'calendar', 'add' )) $newItem["calendar"] = "Event";
    	if ($perms->checkModule( 'files', 'add' )) $newItem["files"] = "File";
    	if ($perms->checkModule( 'projects', 'add' )) $newItem["projects"] = "Project";
    
    	echo arraySelect( $newItem, 'm', 'style="font-size:10px" onChange="f=document.frm_new;mod=f.m.options[f.m.selectedIndex].value;if(mod) f.submit();"', '', true);
    
    	echo "        <input type=\"hidden\" name=\"a\" value=\"addedit\" />\n";
    
    //build URI string
    	if (isset( $company_id )) {
    		echo '<input type="hidden" name="company_id" value="'.$company_id.'" />';
    	}
    	if (isset( $task_id )) {
    		echo '<input type="hidden" name="task_parent" value="'.$task_id.'" />';
    	}
    	if (isset( $file_id )) {
    		echo '<input type="hidden" name="file_id" value="'.$file_id.'" />';
    	}
    ?>
    		</td></tr>
    		</table>
    		</form>
    		</td>
    	</tr>
    	</table>
    	</td>
    </tr>
    <tr>
    	<td>
    		<table cellspacing="0" cellpadding="3" border="0" width="100%">
    		<tr>
    			<td width="100%"><?php echo $AppUI->_('Welcome').' '.$AppUI->user_first_name.' '.$AppUI->user_last_name; ?></td>
    			<td nowrap="nowrap">
    				<?php echo dPcontextHelp( 'Help' );?> |
    				<a href="./index.php?m=admin&a=viewuser&user_id=<?php echo $AppUI->user_id;?>"><?php echo $AppUI->_('My Info');?></a> |
    <?php
    	if ($perms->checkModule('calendar', 'access')) {
    		$now = new CDate();
    ?>                              <b><a href="./index.php?m=tasks&a=todo"><?php echo $AppUI->_('Todo');?></a></b> |
    				<a href="./index.php?m=calendar&a=day_view&date=<?php echo $now->format( FMT_TIMESTAMP_DATE );?>"><?php echo $AppUI->_('Today');?></a> |
    <?php } ?>
    				<a href="./index.php?logout=-1"><?php echo $AppUI->_('Logout');?></a>
    			</td>
    		</tr>
    		</table>
    	</td>
    </tr>
    <?php } // END showMenu ?>
    </table>
    
    <table width="100%" cellspacing="0" cellpadding="4" border="0">
    <tr>
    <td valign="top" align="left" width="98%">
    <?php
    	echo $AppUI->getMsg();
    ?>
    
  3. login.php – These all seem to be a login web page and each seem to have almost the exact same code.
    <?php /* STYLE/DEFAULT $Id: login.php 4842 2007-03-17 15:56:19Z caseydk $ */
    if (!defined('DP_BASE_DIR')) {
    	die('You should not access this file directly');
    }
    ?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    	   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
    	<title><?php echo $dPconfig&#91;'page_title'&#93;;?></title>
    	<meta http-equiv="Content-Type" content="text/html;charset=<?php echo isset( $locale_char_set ) ? $locale_char_set : 'UTF-8';?>" />
           	<title><?php echo $dPconfig&#91;'company_name'&#93;;?> :: dotProject Login</title>
    	<meta http-equiv="Pragma" content="no-cache" />
    	<meta name="Version" content="<?php echo @$AppUI->getVersion();?>" />
    	<link rel="stylesheet" type="text/css" href="./style/<?php echo $uistyle;?>/main.css" media="all" />
    	<style type="text/css" media="all">@import "./style/<?php echo $uistyle;?>/main.css";</style>
    	<link rel="shortcut icon" href="./style/<?php echo $uistyle;?>/images/favicon.ico" type="image/ico" />
    </head>
    
    <body bgcolor="#f0f0f0" onload="document.loginform.username.focus();">
    <br /><br /><br /><br />
    <?php //please leave action argument empty ?>
    <!--form action="./index.php" method="post" name="loginform"-->
    <form method="post" action="<?php echo $loginFromPage; ?>" name="loginform">
    <table align="center" border="0" width="250" cellpadding="6" cellspacing="0" class="std">
    <input type="hidden" name="login" value="<?php echo time();?>" />
    <input type="hidden" name="lostpass" value="0" />
    <input type="hidden" name="redirect" value="<?php echo $redirect;?>" />
    <tr>
    	<th colspan="2"><em><?php echo $dPconfig&#91;'company_name'&#93;;?></em></th>
    </tr>
    <tr>
    	<td align="right" nowrap><?php echo $AppUI->_('Username');?>:</td>
    	<td align="left" nowrap><input type="text" size="25" maxlength="255" name="username" class="text" /></td>
    </tr>
    <tr>
    	<td align="right" nowrap><?php echo $AppUI->_('Password');?>:</td>
    	<td align="left" nowrap><input type="password" size="25" maxlength="32" name="password" class="text" /></td>
    </tr>
    <tr>
    	<td align="left" nowrap><a href="http://www.dotproject.net/"><img src="./style/default/images/dp_icon.gif" border="0" alt="dotProject logo" /></a></td>
    	<td align="right" valign="bottom" nowrap><input type="submit" name="login" value="<?php echo $AppUI->_('login');?>" class="button" /></td>
    </tr>
    <tr>
    	<td colspan="2"><a href="#" onclick="f=document.loginform;f.lostpass.value=1;f.submit();"><?php echo $AppUI->_('forgotPassword');?></a></td>
    </tr>
    </table>
    <?php if (@$AppUI->getVersion()) { ?>
    <div align="center">
    	<span style="font-size:7pt">Version <?php echo @$AppUI->getVersion();?></span>
    </div>
    <?php } ?>
    </form>
    <div align="center">
    <?php
    	echo '<span class="error">'.$AppUI->getMsg().'</span>';
    
    	$msg = '';
    	$msg .=  phpversion() < '4.1' ? '<br /><span class="warning">WARNING: dotproject is NOT SUPPORT for this PHP Version ('.phpversion().')</span>' : '';
    	$msg .= function_exists( 'mysql_pconnect' ) ? '': '<br /><span class="warning">WARNING: PHP may not be compiled with MySQL support.  This will prevent proper operation of dotProject.  Please check you system setup.</span>';
    	echo $msg;
    ?>
    </div>
    <center><?php echo "* ".$AppUI->_("You must have cookies enabled in your browser"); ?></center>
    </body>
    </html>
    
  4. lostpass.php – These all seem to be a full web page to provide a lost password interface and each seem to have almost the exact same code.
    <?php /* STYLE/DEFAULT $Id: lostpass.php 4771 2007-02-18 03:06:27Z ajdonnison $ */
    if (!defined('DP_BASE_DIR')) {
    	die('You should not access this file directly');
    }
    ?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    	   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
    	<title><?php echo @dPgetConfig( 'page_title' );?></title>
    	<meta http-equiv="Content-Type" content="text/html;charset=<?php echo isset( $locale_char_set ) ? $locale_char_set : 'UTF-8';?>" />
           	<title><?php echo $dPconfig&#91;'company_name'&#93;;?> :: dotProject Login</title>
    	<meta http-equiv="Pragma" content="no-cache" />
    	<meta name="Version" content="<?php echo @$AppUI->getVersion();?>" />
    	<link rel="stylesheet" type="text/css" href="./style/<?php echo $uistyle;?>/main.css" media="all" />
    	<style type="text/css" media="all">@import "./style/<?php echo $uistyle;?>/main.css";</style>
    	<link rel="shortcut icon" href="./style/<?php echo $uistyle;?>/images/favicon.ico" type="image/ico" />
    </head>
    
    <body bgcolor="#f0f0f0" onload="document.lostpassform.checkusername.focus();">
    <br /><br /><br /><br />
    <?php //please leave action argument empty ?>
    <!--form action="./index.php" method="post" name="loginform"-->
    <form method="post" name="lostpassform">
    <table align="center" border="0" width="250" cellpadding="6" cellspacing="0" class="std">
    <input type="hidden" name="lostpass" value="1" />
    <input type="hidden" name="redirect" value="<?php echo $redirect;?>" />
    <tr>
    	<th colspan="2"><em><?php echo $dPconfig&#91;'company_name'&#93;;?></em></th>
    </tr>
    <tr>
    	<td align="right" nowrap><?php echo $AppUI->_('Username');?>:</td>
    	<td align="left" nowrap><input type="text" size="25" maxlength="20" name="checkusername" class="text" /></td>
    </tr>
    <tr>
    	<td align="right" nowrap><?php echo $AppUI->_('EMail');?>:</td>
    	<td align="left" nowrap><input type="email" size="25" maxlength="64" name="checkemail" class="text" /></td>
    </tr>
    <tr>
    	<td align="left" nowrap><a href="http://www.dotproject.net/"><img src="./style/default/images/dp_icon.gif" width="120" height="20" border="0" alt="dotProject logo" /></a></td>
    	<td align="right" valign="bottom" nowrap><input type="submit" name="sendpass" value="<?php echo $AppUI->_('send password');?>" class="button" /></td>
    </tr>
    </table>
    <?php if (@$AppUI->getVersion()) { ?>
    <div align="center">
    	<span style="font-size:7pt">Version <?php echo @$AppUI->getVersion();?></span>
    </div>
    <?php } ?>
    </form>
    <div align="center">
    <?php
    	echo '<span class="error">'.$AppUI->getMsg().'</span>';
    
    	$msg = '';
    	$msg .=  phpversion() < '4.1' ? '<br /><span class="warning">WARNING: dotproject is NOT SUPPORT for this PHP Version ('.phpversion().')</span>' : '';
    	$msg .= function_exists( 'mysql_pconnect' ) ? '': '<br /><span class="warning">WARNING: PHP may not be compiled with MySQL support.  This will prevent proper operation of dotProject.  Please check you system setup.</span>';
    	echo $msg;
    ?>
    </div>
    </body>
    </html>
    
  5. overrides.php – I will have to analyze this more to see what it is for. The code looks pretty similar in each file, though the files are slightly different lengths.
    <?php /* STYLE/DEFAULT $Id: overrides.php 5725 2008-06-02 16:20:34Z merlinyoda $ */
    
    if (!defined('DP_BASE_DIR')) {
    	die('You should not access this file directly');
    }
    class CTitleBlock extends CTitleBlock_core {
    }
    
    ##
    ##  This overrides the show function of the CTabBox_core function
    ##
    class CTabBox extends CTabBox_core {
    	function show( $extra='', $js_tabs = false ) {
    		GLOBAL $AppUI, $dPconfig, $currentTabId, $currentTabName;
    		$uistyle = ($AppUI->getPref( 'UISTYLE' )
    		            ? $AppUI->getPref( 'UISTYLE' )
    		            : (($dPconfig['host_style']) ? $dPconfig['host_style'] : 'default'));
    		reset( $this->tabs );
    		$s = '';
    
    		// tabbed / flat view options
    		if (@$AppUI->getPref( 'TABVIEW' ) == 0) {
    			$s .= '<table border="0" cellpadding="2" cellspacing="0" width="100%">' . "\n";
    			$s .= "<tr>\n";
    			$s .= '<td nowrap="nowrap">' . "\n";
    			$s .= '<a href="' . $this->baseHRef . 'tab=0">' . $AppUI->_('tabbed') . '</a> : ';
    			$s .= '<a href="' . $this->baseHRef . 'tab=-1">' . $AppUI->_('flat') . '</a>' . "\n";
    			$s .= "</td>\n" . $extra . "\n</tr>\n</table>\n";
    			echo $s;
    		} else {
    			if ($extra) {
    				echo ('<table border="0" cellpadding="2" cellspacing="0" width="100%">'
    				      . "\n<tr>\n" . $extra . "</tr>\n</table>\n");
    			} else {
    				echo '<img src="./images/shim.gif" height="10" width="1" alt="" />' . "\n";
    			}
    		}
    
    		if ($this->active < 0 || @$AppUI->getPref( 'TABVIEW' ) == 2 ) {
    			// flat view, active = -1
    			echo '<table border="0" cellpadding="2" cellspacing="0" width="100%">' . "\n";
    			foreach ($this->tabs as $k => $v) {
    				echo '<tr><td><strong>'.($v[2] ? $v[1] : $AppUI->_($v[1]))."</strong></td></tr>\n";
    				echo '<tr><td>';
    				$currentTabId = $k;
    				$currentTabName = $v[1];
    				include $this->baseInc.$v[0].".php";
    				echo "</td></tr>\n";
    			}
    			echo "</table>\n";
    		} else {
    			// tabbed view
    			$s = '<table width="100%" border="0" cellpadding="0" cellspacing="0">' . "\n";
    			$s .= '<tr><td>' . "\n" .'<table border="0" cellpadding="0" cellspacing="0"><tr>' . "\n";
    
    			if ( count($this->tabs)-1 < $this->active ) {
    				//Last selected tab is not available in this view. eg. Child tasks
    //				$this->active = 0;
    			}
    			foreach( $this->tabs as $k => $v ) {
    				$class = ($k == $this->active) ? 'tabon' : 'taboff';
    				$sel = ($k == $this->active) ? 'Selected' : '';
    				$s .= '<td valign="middle"><img src="./style/' . $uistyle . '/images/tab' . $sel . 'Left.png" id="lefttab_' . $k .'" border="0" alt="" /></td>' . "\n";
    				$s .= '<td id="toptab_'.$k.'" valign="middle" nowrap="nowrap"';
    
    				$s .= (($js_tabs)
    					   ? (' class="' . $class . '"')
    					   : (' background="./style/' . $uistyle . '/images/tab' . $sel . 'Bg.png"'));
    				$s .= '>&nbsp;<a href="';
    
    				if ($this->javascript) {
    					$s .= "javascript:" . $this->javascript . "({$this->active}, $k)";
    				} else if ($js_tabs) {
    					$s .= 'javascript:show_tab(' . $k . ')';
    				} else {
    					$s .= $this->baseHRef.'tab='.$k;
    				}
    
    				$s .='">'.(($v[2]) ? $v[1] : $AppUI->_($v[1])).'</a>&nbsp;</td>' . "\n";
    				$s .= ('<td valign="middle"><img id="righttab_' . $k . '" src="./style/' . $uistyle . '/images/tab'
    					   . $sel . 'Right.png" border="0" alt="" /></td>' . "\n");
    				$s .= '<td class="tabsp"><img src="./images/shim.gif" height="1" width="3" /></td>' . "\n";
    			}
    			$s .= '</tr></table>' . "\n" .'</td></tr>' . "\n";
    			$s .= '<tr><td width="100%" colspan="'.(count($this->tabs)*4 + 1).'" class="tabox">' . "\n";
    			echo $s;
    			//Will be null if the previous selection tab is not available in the new window eg. Children tasks
    			if ( $this->tabs[$this->active][0] != "" ) {
    				$currentTabId = $this->active;
    				$currentTabName = $this->tabs[$this->active][1];
    				if (!$js_tabs)
    					require $this->baseInc.$this->tabs[$this->active][0].'.php';
    			}
    			if ($js_tabs)
    			{
    				foreach( $this->tabs as $k => $v )
    				{
    					echo '<div class="tab" id="tab_'.$k.'">';
    					$currentTabId = $k;
    					$currentTabName = $v[1];
    					require $this->baseInc.$v[0].'.php';
    					echo '</div>';
    					echo ('<script language="JavaScript" type="text/javascript">' . "\n"
    						  . '//<!--' . "\n"
    						  . 'show_tab('.$this->active.');' . "\n"
    						  . '//-->' . "\n"
    						  . '</script>');
    				}
    			}
    			echo '</td></tr>' . "\n" . '</table>' . "\n";
    		}
    	}
    }
    ?>
    

Image files, gif, jpg, png

These are all just images. You can change them if you want. The image type doesn’t have to remain constant. If you do change them, your theme will be noticeably different.

  1. Tab Images – These are images for the tabs you click on at the top of the web page.
    • tabBg.png
    • tabLeft.png
    • tabRight.png
  2. Tab Selected Images – These are images for the tab that is currently selected at the top of the web page.
    • tabSelectedBg.png
    • tabSelectedLeft.png
    • tabSelectedRight.png

    favicon.ico

    This is the icon that shows up in the tool bar of your browser next to the URL.

7 Comments

  1. www.stevadventure.tk

    What files are required to create a theme for dotProject 2.1.2? | Rhyous

  2. drchon.com says:

    drchon.com

    What files are required to create a theme for dotProject 2.1.2? | Rhyous

  3. mouse click the up coming webpage

    What files are required to create a theme for dotProject 2.1.2? | Rhyous

  4. furniture says:

    furniture

    What files are required to create a theme for dotProject 2.1.2? | Rhyous

  5. cornwall castle hotels uk says:

    cornwall castle hotels uk

    What files are required to create a theme for dotProject 2.1.2? | Rhyous

  6. ibiza public holidays 2007

    What files are required to create a theme for dotProject 2.1.2? | Rhyous

  7. Tred says:

    Thanks for the info, yet to test if it works!

Leave a Reply

How to post code in comments?