Implements Config and Logging plugins, tidies Main

Added Database and Flatfile plugin engines for both Config and Log classes.
Rewrote Main to make use of the new plugins.
Updated config file definitions to make use of plugins.
This commit is contained in:
2010-10-10 17:11:44 +01:00
parent ddd2e62c13
commit 676fef1deb
15 changed files with 408 additions and 112 deletions

View File

@@ -31,25 +31,13 @@ class Sihnon_Config {
* @var array(string)
*/
const TYPE_STRING_LIST = 'array(string)';
/**
* Contents of the dbconfig file
* @var string
*/
private $dbconfig;
/**
* Database object created for the lifetime of this script
* @var Sihnon_Database
* Backend to be used for this Config object
* @var Sihnon_Config_IPlugin
*/
private $database;
private $backend;
/**
* Associative array of connection parameters for the database configuration
* @var array(string=>string)
*/
private $databaseConfig = array();
/**
* Associative array of settings loaded from the database
* @var array(string=>array(string=>string))
@@ -59,56 +47,13 @@ class Sihnon_Config {
/**
* Constructs a new instance of the Config class
*
* @param string $dbconfig Database configuration file contents
* @param string $backend Backend to use for storing and retrieving configuration items
* @param mixed $options Parameters to configure the Config backend
* @return Sihnon_Config
*/
public function __construct($dbconfig) {
$this->dbconfig = $dbconfig;
$this->parseDatabaseConfig();
}
/**
* Parses the contents of the database configuration file so that individual settings can be retrieved.
*
*/
public function parseDatabaseConfig() {
$this->databaseConfig = parse_ini_file($this->dbconfig);
}
/**
* Returns the value of the named item from the database configuration file
*
* @param string $key Name of the setting to retrieve
*/
public function getDatabase($key) {
if (!isset($this->databaseConfig[$key])) {
throw new Sihnon_Exception_DatabaseConfigMissing($key);
}
return $this->databaseConfig[$key];
}
/**
* Sets the database instance used by this object
*
* @param Sihnon_Database $database Database instance
*/
public function setDatabase(Sihnon_Database $database) {
$this->database = $database;
$this->preload();
}
/**
* Loads the entire list of settings from the database
*
*/
private function preload() {
if (!$this->database) {
throw new Sihnon_Exception_NoDatabaseConnection();
}
$this->settings = $this->database->selectAssoc('SELECT name,type,value FROM settings', 'name', array('name', 'value', 'type'));
public function __construct($backend, $options) {
$this->backend = Sihnon_Config_PluginFactory::create($backend, $options);
$this->settings = $this->backend->preload();
}
/**

View File

@@ -0,0 +1,29 @@
<?php
interface Sihnon_Config_IPlugin extends Sihnon_IPlugin {
/**
* Returns a new instance of the Plugin class
*
* @param array(string=>mixed) $options Configuration options for the Plugin object
*/
public static function create($options);
/**
* Loads all the configuration items from the storage backend
*
* @param string $source_filename Filename of the source
* @param bool $scan Request that the source be scanned for content. Defaults to true.
* @param bool $use_cache Request that the cache be used. Defaults to true.
* @return RippingCluster_Source
*/
public function preload();
/**
* Saves the value of all configuration items back into the storage backend
*/
public function save();
}
?>

View File

@@ -0,0 +1,33 @@
<?php
class Sihnon_Config_Plugin_Database extends Sihnon_PluginBase implements Sihnon_Config_IPlugin {
/**
* Name of this plugin
* @var string
*/
const PLUGIN_NAME = "Database";
private $database;
private $table;
protected function __construct($options) {
$this->database = $options['database'];
$this->table = $options['table'];
}
public static function create($options) {
return new self($options);
}
public function preload() {
return $this->database->selectAssoc("SELECT name,type,value FROM {$this->table}", 'name', array('name', 'value', 'type'));
}
public function save() {
throw new Sihnon_Exception_NotImplemented();
}
}
?>

View File

@@ -0,0 +1,31 @@
<?php
class Sihnon_Config_Plugin_FlatFile extends Sihnon_PluginBase implements Sihnon_Config_IPlugin {
/**
* Name of this plugin
* @var string
*/
const PLUGIN_NAME = "FlatFile";
protected $filename;
protected function __construct($options) {
$this->filename = $options['filename'];
}
public static function create($options) {
return new self($options);
}
public function preload() {
return parse_ini_file($this->filename, true);;
}
public function save() {
throw new Sihnon_Exception_NotImplemented();
}
}
?>

View File

@@ -0,0 +1,27 @@
<?php
class Sihnon_Config_PluginFactory extends Sihnon_PluginFactory {
const PLUGIN_DIR = 'Sihnon/Config/Plugin/';
const PLUGIN_PREFIX = 'Sihnon_Config_Plugin_';
const PLUGIN_INTERFACE = 'Sihnon_Config_IPlugin';
public static function init() {
}
public static function create($plugin, $options) {
self::ensureScanned();
if (! self::isValidPlugin($plugin)) {
throw new Sihnon_Exception_InvalidPluginName($plugin);
}
$classname = self::classname($plugin);
return call_user_func(array($classname, 'create'), $options);
}
}
?>

View File

@@ -5,6 +5,12 @@ class Sihnon_Database {
private $config;
private $dbh;
/**
* Associative array of connection parameters for the database configuration
* @var array(string=>string)
*/
private $database_config;
private $hostname;
private $username;
private $password;
@@ -12,13 +18,14 @@ class Sihnon_Database {
private $prepared_statements = array();
public function __construct(Sihnon_Config $config) {
$this->config = $config;
$this->hostname = $this->config->getDatabase('hostname');
$this->username = $this->config->getDatabase('username');
$this->password = $this->config->getDatabase('password');
$this->dbname = $this->config->getDatabase('dbname');
public function __construct($dbconfig) {
$this->database_cconfig = parse_ini_file($dbconfig);
var_dump($this->database_config);
$this->hostname = $this->getDatabaseConfig('hostname');
$this->username = $this->getDatabaseConfig('username');
$this->password = $this->getDatabaseConfig('password');
$this->dbname = $this->getDatabaseConfig('dbname');
try {
$this->dbh = new PDO("mysql:host={$this->hostname};dbname={$this->dbname}", $this->username, $this->password);
@@ -31,6 +38,19 @@ class Sihnon_Database {
public function __destruct() {
$this->dbh = null;
}
/**
* Returns the value of the named item from the database configuration file
*
* @param string $key Name of the setting to retrieve
*/
private function getDatabaseConfig($key) {
if (!isset($this->database_config[$key])) {
throw new Sihnon_Exception_DatabaseConfigMissing($key);
}
return $this->database_config[$key];
}
public function selectAssoc($sql, $key_col, $value_cols) {
$results = array();

View File

@@ -2,6 +2,9 @@
class Sihnon_Exception extends Exception {};
class Sihnon_Exception_NotImplemented extends Sihnon_Exception {};
class Sihnon_Exception_MissingDefinition extends Sihnon_Exception {};
class Sihnon_Exception_DatabaseException extends Sihnon_Exception {};
class Sihnon_Exception_DatabaseConfigMissing extends Sihnon_Exception_DatabaseException {};
class Sihnon_Exception_DatabaseConnectFailed extends Sihnon_Exception_DatabaseException {};

View File

@@ -9,29 +9,22 @@ class Sihnon_Log {
private static $hostname = '';
private $database;
private $config;
private $table;
public function __construct(Sihnon_Database $database, Sihnon_Config $config, $table) {
$this->database = $database;
$this->config = $config;
$this->table = $table;
private $backend;
private $progname;
public function __construct($backend, $options = array(), $progname = '') {
$this->progname = $progname;
$this->backend = Sihnon_Log_PluginFactory::create($backend, $options);
$this->log(self::LEVEL_INFO, "Logging started");
}
public function __destruct() {
$this->log(self::LEVEL_INFO, "Logging shutdown");
}
public function log($severity, $message) {
$this->database->insert("INSERT INTO {$this->table} (level,ctime,pid,hostname,progname,line,message) VALUES(:level, :ctime, :pid, :hostname, :progname, :line, :message)",
array(
array('name' => 'level', 'value' => $severity, 'type' => PDO::PARAM_STR),
array('name' => 'ctime', 'value' => time(), 'type' => PDO::PARAM_INT),
array('name' => 'pid', 'value' => 0, 'type' => PDO::PARAM_INT),
array('name' => 'hostname', 'value' => self::$hostname, 'type' => PDO::PARAM_STR),
array('name' => 'progname', 'value' => 'webui', 'type' => PDO::PARAM_STR),
array('name' => 'line', 'value' => 0, 'type' => PDO::PARAM_INT),
array('name' => 'message', 'value' => $message, 'type' => PDO::PARAM_STR)
)
);
public function log($level, $message) {
$this->backend->log($level, time(), 0, self::$hostname, $this->progname, 0, $message);
}
public function debug($message) {

View File

@@ -0,0 +1,27 @@
<?php
interface Sihnon_Log_IPlugin extends Sihnon_IPlugin {
/**
* Returns a new instance of the Plugin class
*
* @param array(string=>mixed) $options Configuration options for the Plugin object
*/
public static function create($options);
/**
* Records a new entry in the storage backend used by this logging plugin
*
* @param string $level Severity of the log entry
* @param int $ctime Time the log entry was created
* @param int $pid ID of the process that created the log entry
* @param string $hostname Hostname of the system that created the log entry
* @param string $progname Name of the application that created the log entry
* @param int $line Line number of the code that created the log entry
* @param string $message Message to be logged
*/
public function log($level, $ctime, $pid, $hostname, $progname, $line, $message);
}
?>

View File

@@ -0,0 +1,49 @@
<?php
class Sihnon_Log_Plugin_Database extends Sihnon_PluginBase implements Sihnon_Log_IPlugin {
/**
* Name of this plugin
* @var string
*/
const PLUGIN_NAME = "Database";
private $database;
private $table;
protected function __construct($options) {
$this->database = $options['database'];
$this->table = Sihnon_Main::instance()->config()->get('logging.database.table');
}
public static function create($options) {
return new self($options);
}
/**
* Records a new entry in the storage backend used by this logging plugin
*
* @param string $level Severity of the log entry
* @param int $ctime Time the log entry was created
* @param int $pid ID of the process that created the log entry
* @param string $hostname Hostname of the system that created the log entry
* @param string $progname Name of the application that created the log entry
* @param int $line Line number of the code that created the log entry
* @param string $message Message to be logged
*/
public function log($level, $ctime, $pid, $hostname, $progname, $line, $message) {
$this->database->insert("INSERT INTO {$this->table} (level,ctime,pid,hostname,progname,line,message) VALUES(:level, :ctime, :pid, :hostname, :progname, :line, :message)",
array(
array('name' => 'level', 'value' => $level, 'type' => PDO::PARAM_STR),
array('name' => 'ctime', 'value' => $ctime, 'type' => PDO::PARAM_INT),
array('name' => 'pid', 'value' => $pid, 'type' => PDO::PARAM_INT),
array('name' => 'hostname', 'value' => $hostname, 'type' => PDO::PARAM_STR),
array('name' => 'progname', 'value' => $progname, 'type' => PDO::PARAM_STR),
array('name' => 'line', 'value' => $line, 'type' => PDO::PARAM_INT),
array('name' => 'message', 'value' => $message, 'type' => PDO::PARAM_STR)
)
);
}
}
?>

View File

@@ -0,0 +1,44 @@
<?php
class Sihnon_Log_Plugin_FlatFile extends Sihnon_PluginBase implements Sihnon_Log_IPlugin {
/**
* Name of this plugin
* @var string
*/
const PLUGIN_NAME = "FlatFile";
protected $filename;
protected $fp;
protected function __construct($options) {
$this->filename = Sihnon_Main::instance()->config()->get('logging.flatfile.filename');
$this->fp = fopen($this->filename, 'a');
}
public function __destruct() {
fclose($this->fp);
}
public static function create($options) {
return new self($options);
}
/**
* Records a new entry in the storage backend used by this logging plugin
*
* @param string $level Severity of the log entry
* @param int $ctime Time the log entry was created
* @param int $pid ID of the process that created the log entry
* @param string $hostname Hostname of the system that created the log entry
* @param string $progname Name of the application that created the log entry
* @param int $line Line number of the code that created the log entry
* @param string $message Message to be logged
*/
public function log($level, $ctime, $pid, $hostname, $progname, $line, $message) {
$log_entry = implode(',', array($level, $ctime, $pid, $hostname, $progname, $line, $message)) . "\n";
fwrite($this->fp, $log_entry, strlen($log_entry));
}
}
?>

View File

@@ -0,0 +1,27 @@
<?php
class Sihnon_Log_PluginFactory extends Sihnon_PluginFactory {
const PLUGIN_DIR = 'Sihnon/Log/Plugin/';
const PLUGIN_PREFIX = 'Sihnon_Log_Plugin_';
const PLUGIN_INTERFACE = 'Sihnon_Log_IPlugin';
public static function init() {
}
public static function create($plugin, $options) {
self::ensureScanned();
if (! self::isValidPlugin($plugin)) {
throw new Sihnon_Exception_InvalidPluginName($plugin);
}
$classname = self::classname($plugin);
return call_user_func(array($classname, 'create'), $options);
}
}
?>

View File

@@ -1,26 +1,37 @@
<?php
class Sihnon_Main {
private static $instance;
private $config;
private $database;
private $log;
private $cache;
private $base_uri;
protected static $instance;
private function __construct() {
$this->config = new Sihnon_Config(Sihnon_DBConfig);
$this->database = new Sihnon_Database($this->config);
$this->config->setDatabase($this->database);
protected $config;
protected $database;
protected $log;
protected $cache;
protected $base_uri;
$this->log = new Sihnon_Log($this->database, $this->config, Sihnon_Log_Table);
$this->cache = new Sihnon_Cache($this->config);
protected function __construct() {
$this->base_uri = dirname($_SERVER['SCRIPT_NAME']) . '/';
}
protected function init() {
if (Sihnon_DatabaseSupport) {
$this->database = new Sihnon_Database(Sihnon_DBConfig);
}
$this->config = new Sihnon_Config(Sihnon_ConfigPlugin, array(
'database' => $this->database,
'table' => Sihnon_ConfigTable,
'filename' => Sihnon_ConfigFile)
);
$this->log = new Sihnon_Log($this->config->get('logging.plugin'), array(
'database' => $this->database)
);
$this->cache = new Sihnon_Cache($this->config);
}
/**
*
@@ -29,6 +40,7 @@ class Sihnon_Main {
public static function instance() {
if (!self::$instance) {
self::$instance = new Sihnon_Main();
self::$instance->init();
}
return self::$instance;
@@ -111,6 +123,18 @@ class Sihnon_Main {
}
}
/**
* Throws an exception if the requested name has not been defined.
*
* @param string $name Name of the definition to check for the existence of
* @throws Sihnon_Exception_MissingDefinition
*/
public static function ensureDefined($name) {
if (! defined($name)) {
throw new Sihnon_Exception_MissingDefinition($name);
}
}
public static function mkdir_recursive($directory, $permissions=0777) {
$parts = explode('/', $directory);
$path = '';

View File

@@ -4,6 +4,19 @@ abstract class Sihnon_PluginFactory implements Sihnon_IPluginFactory {
static private $validPlugins = array();
/**
* Scan the plugin directory for potential plugins, and load any valid ones found
*
* @param bool $force Rescan the plugin directory even if it has already been scanned before
*/
public static function scan($force = false) {
if ($force || ! isset(self::$validPlugins[get_called_class()])) {
$candidatePlugins = static::findPlugins(static::PLUGIN_DIR);
static::loadPlugins($candidatePlugins, static::PLUGIN_PREFIX, static::PLUGIN_INTERFACE);
}
}
protected static function ensureScanned() {
if (! isset(self::$validPlugins[get_called_class()])) {
static::scan();