<?php

/*
** SellaNMS
** $Id: module.php,v 1.29 2006/01/24 07:08:09 sella Exp $
** Copyright (c) 2001 Digital Genesis Software, LLC. All Rights Reserved.
** Released under the GPL Version 2 License.
** http://www.digitalgenesis.com
*/

//include_once("libs/dgsutil/startup.php");

class Module {
	var $dependants = array();
	var $cache_ext = 'html';

	function Module() {
	}

	/**
		This function should be redefined by all subclasses.  This function should
		return true iff the cache file should be re-written and it should return
		false iff the cache file should not be rewritten.
	*/
	function shouldUpdate() {
		return true;
	}

	/**
		This function should be redefined by all subclasses.  This function should
		return the BODY section of the HTML content of the module.
		
	*/
	function getContent($indent) {
		return sprintf("%s->getContent() not defined.", get_class($this));
	}

	function doIt() {
		global $config;

		$ret_val = array();
		$module_name = get_class($this);

		if (!isset($_SESSION[$module_name])) {
			$_SESSION[$module_name] = array();
		}

		$lock_file = sprintf("%s/sella_nms-%s.lock", $config['cacheDir'], $module_name);
		$cache_file = sprintf("%s/sella_nms-%s.%s", $config['cacheDir'], $module_name, $this->cache_ext);

		if (!$this->isLocked($lock_file)) {
			if (!$this->lockModule($lock_file)) {
				return sprintf("Unable to lock module <%s>.", $module_name);
			}

			if ($this->shouldUpdate() || !file_exists($cache_file)) {
				if (!$this->update($cache_file)) {
					return sprintf("Unable to update module <%s>.", $module_name);
				}
			}

			if (!$this->unlockModule($lock_file)) {
				return sprintf("Unable to unlock module <%s>.", $module_name);
			}
		}

		if ($this->isUpdated($cache_file)) {
			${$module_name}['last_execution'] = time();
			if (!in_array($module_name, $config['modules'])) {
				$ret_val[] = sprintf("%s;%s", $module_name, $cache_file);
			} else {
				$ret_val[] = sprintf("body;%s", $cache_file);
			}
		}
		while (list(, $instance) = each($this->dependants)) {
			$dependant_ret_val = $instance->doIt();

			if (is_array($dependant_ret_val)) {
				while (list(, $dependant_name) = each($dependant_ret_val)) {
					if (!in_array($module_name, $config['modules'])) {
						$ret_val[] = sprintf("%s.%s", $module_name, $dependant_name);
					} else {
						$ret_val[] = sprintf("body.%s", $dependant_name);
					}
				}
			} else {
				return $dependant_ret_val;
			}
		}

		return $ret_val;
	}

	function isUpdated($cache_file) {
		$module_name = get_class($this);
		global ${$module_name};

		clearstatcache();
		if (filemtime($cache_file) > ${$module_name}['last_execution']) {
			return true;
		}	
		return false;
	}

	function isLocked($lock_file) {
		global $config;

		if (file_exists($lock_file)) {
			if (time() - filemtime($lock_file) < ($config['interval'] * 4)) {
				return true;
			}
			if ($config['debug']) {
				printf("Warning: Found stale lock file '%s'.", $lock_file);
			}
		}
		return false;
	}

	function update($cache_file) {
		global $config;

		$temp_file = sprintf("%s-temp", $cache_file);


		if (!$fp = fopen($temp_file, "w")) {
			printf("Error: unable to create temporary file <%s>.", $temp_file);
			return false;
		}

		if ($this->cache_ext == 'php') {
			fwrite($fp, "<? include_once('../libs/dgsutil/startup.php'); initSellaNMS(); ?>\n");
		}

		fwrite($fp, "<HTML>\n");
		fwrite($fp, "\t<HEAD>\n");
		$buf = sprintf("\t\t<TITLE>%s %s</TITLE>\n", $config['program'], $config['version']);
		fwrite($fp, $buf);
		fwrite($fp, "\t\t<LINK REL=\"SHORTCUT ICON\" HREF=\"../favicon.ico\">\n");
		$buf = sprintf("\t\t<LINK REL=\"stylesheet\" HREF=\"../common/%s.css\" TYPE=\"text/css\">\n", isset($config['css']) ? $config['css'] : 'default');
		fwrite($fp, $buf);
		fwrite($fp, "\t\t<META HTTP-EQUIV=\"expires\" CONTENT=\"Thu, 1 Jan 1970 00:00:00 GMT\">\n");
		fwrite($fp, "\t</HEAD>\n");

		if (sizeof($this->dependants) == 0) {
			fwrite($fp, "\t<BODY TOPMARGIN=\"0\" LEFTMARGIN=\"0\" MARGINWIDTH=\"0\" MARGINHEIGHT=\"0\">\n");
		}

		fwrite($fp, $this->getContent(2));

		if (sizeof($this->dependants) == 0) {
			fwrite($fp, "\t</BODY>\n");
		}
		fwrite($fp, "</HTML>\n");

		if (!fclose($fp)) {
			if ($config['debug']) {
				printf("Error: Unable to close temporary file '%s' to '%s'.", $temp_file, $cache_file);
			}
			return false;
		}

		if (!rename($temp_file, $cache_file)) {
			if ($config['debug']) {
				printf("Error: Unable to rename temporary file '%s' to '%s'.", $temp_file, $cache_file);
			}
			return false;
		}

		return true;
	}

	function lockModule($lock_file) {
		if (touch($lock_file)) {
			return true;
		}
		return false;
	}

	function unlockModule($lock_file) {
		if (unlink($lock_file)) {
			return true;
		}
		return false;
	}
}

/*
** Local Variables:
** c-basic-offset: 3
** tab-width: 3
** End:
** vim:
** vim: noet ts=3 sw=3
*/

?>
