From 676fef1deb74d4a91cd7020ab8fa87a878018501 Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Sun, 10 Oct 2010 17:11:44 +0100 Subject: [PATCH] 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. --- private/config.php.dist | 43 +++++++++-- source/lib/Sihnon/Config.class.php | 71 +++---------------- source/lib/Sihnon/Config/IPlugin.class.php | 29 ++++++++ .../Sihnon/Config/Plugin/Database.class.php | 33 +++++++++ .../Sihnon/Config/Plugin/FlatFile.class.php | 31 ++++++++ .../lib/Sihnon/Config/PluginFactory.class.php | 27 +++++++ source/lib/Sihnon/Database.class.php | 34 +++++++-- source/lib/Sihnon/Exceptions.class.php | 3 + source/lib/Sihnon/Log.class.php | 35 ++++----- source/lib/Sihnon/Log/IPlugin.class.php | 27 +++++++ .../lib/Sihnon/Log/Plugin/Database.class.php | 49 +++++++++++++ .../lib/Sihnon/Log/Plugin/FlatFile.class.php | 44 ++++++++++++ source/lib/Sihnon/Log/PluginFactory.class.php | 27 +++++++ source/lib/Sihnon/Main.class.php | 54 ++++++++++---- source/lib/Sihnon/PluginFactory.class.php | 13 ++++ 15 files changed, 408 insertions(+), 112 deletions(-) create mode 100644 source/lib/Sihnon/Config/IPlugin.class.php create mode 100644 source/lib/Sihnon/Config/Plugin/Database.class.php create mode 100644 source/lib/Sihnon/Config/Plugin/FlatFile.class.php create mode 100644 source/lib/Sihnon/Config/PluginFactory.class.php create mode 100644 source/lib/Sihnon/Log/IPlugin.class.php create mode 100644 source/lib/Sihnon/Log/Plugin/Database.class.php create mode 100644 source/lib/Sihnon/Log/Plugin/FlatFile.class.php create mode 100644 source/lib/Sihnon/Log/PluginFactory.class.php diff --git a/private/config.php.dist b/private/config.php.dist index 45705ec..e66f8c2 100644 --- a/private/config.php.dist +++ b/private/config.php.dist @@ -10,23 +10,54 @@ */ define('Sihnon_Lib', '../lib/'); +/** + * Sihnon Database Support + * + * Specifies whether or not to include database support in the Framework + * + * @var bool + */ +define('Sihnon_DatabaseSupport', false); + /** * Sihnon Database Configuration * - * Specifies the absolute or relative path to the Sihnon database configuration file. + * Specifies the absolute or relative path to the Sihnon database configuration file, required when Database support is enabled. * This is a standard ini type file, containing the config required to connect to the database. * * @var string */ -define('Sihnon_DBConfig', '../dbconfig.conf'); +define('Sihnon_DBConfig', '../private/dbconfig.conf'); /** - * Sihnon Log Table - * - * Specifies the name of the database table used to store log entries for this application. + * Sihnon Config Plugin + * + * Specifies the plugin to use for configuration value storage. + * Options include: + * - Database (Requires Database Support to be enabled, and the Sihnon_ConfigTable option set) + * - FlatFile (Requires the Sihnon_ConfigFile option set) * * @var string */ -define('Sihnon_Log_Table', 'logs'); +define('Sihnon_ConfigPlugin', 'FlatFile'); + +/** + * Sihnon Config Table + * + * Specifies the name of the database table thats used for storing configuration values + * when the Database Config Plugin is used. + * + * @var string + */ +define('Sihnon_ConfigTable', 'settings'); + +/** + * Sihnon Config File + * + * Specifies the name of the file used to store configuration values when the FlatFile Config Plugin is used + * + * @var string + */ +define('Sihnon_ConfigFile', '../private/settings.txt'); ?> \ No newline at end of file diff --git a/source/lib/Sihnon/Config.class.php b/source/lib/Sihnon/Config.class.php index bea4c86..8b2218c 100644 --- a/source/lib/Sihnon/Config.class.php +++ b/source/lib/Sihnon/Config.class.php @@ -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(); } /** diff --git a/source/lib/Sihnon/Config/IPlugin.class.php b/source/lib/Sihnon/Config/IPlugin.class.php new file mode 100644 index 0000000..0e9bc20 --- /dev/null +++ b/source/lib/Sihnon/Config/IPlugin.class.php @@ -0,0 +1,29 @@ +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(); + +} + +?> \ No newline at end of file diff --git a/source/lib/Sihnon/Config/Plugin/Database.class.php b/source/lib/Sihnon/Config/Plugin/Database.class.php new file mode 100644 index 0000000..d40faf4 --- /dev/null +++ b/source/lib/Sihnon/Config/Plugin/Database.class.php @@ -0,0 +1,33 @@ +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(); + } + +} + +?> \ No newline at end of file diff --git a/source/lib/Sihnon/Config/Plugin/FlatFile.class.php b/source/lib/Sihnon/Config/Plugin/FlatFile.class.php new file mode 100644 index 0000000..9b90e95 --- /dev/null +++ b/source/lib/Sihnon/Config/Plugin/FlatFile.class.php @@ -0,0 +1,31 @@ +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(); + } + +} + +?> \ No newline at end of file diff --git a/source/lib/Sihnon/Config/PluginFactory.class.php b/source/lib/Sihnon/Config/PluginFactory.class.php new file mode 100644 index 0000000..315f873 --- /dev/null +++ b/source/lib/Sihnon/Config/PluginFactory.class.php @@ -0,0 +1,27 @@ + \ No newline at end of file diff --git a/source/lib/Sihnon/Database.class.php b/source/lib/Sihnon/Database.class.php index 6582273..952e5c3 100644 --- a/source/lib/Sihnon/Database.class.php +++ b/source/lib/Sihnon/Database.class.php @@ -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(); diff --git a/source/lib/Sihnon/Exceptions.class.php b/source/lib/Sihnon/Exceptions.class.php index 1b6e318..ff4b7b3 100644 --- a/source/lib/Sihnon/Exceptions.class.php +++ b/source/lib/Sihnon/Exceptions.class.php @@ -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 {}; diff --git a/source/lib/Sihnon/Log.class.php b/source/lib/Sihnon/Log.class.php index 781dd65..441e44b 100644 --- a/source/lib/Sihnon/Log.class.php +++ b/source/lib/Sihnon/Log.class.php @@ -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) { diff --git a/source/lib/Sihnon/Log/IPlugin.class.php b/source/lib/Sihnon/Log/IPlugin.class.php new file mode 100644 index 0000000..b6fec93 --- /dev/null +++ b/source/lib/Sihnon/Log/IPlugin.class.php @@ -0,0 +1,27 @@ +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); +} + +?> \ No newline at end of file diff --git a/source/lib/Sihnon/Log/Plugin/Database.class.php b/source/lib/Sihnon/Log/Plugin/Database.class.php new file mode 100644 index 0000000..964d3fa --- /dev/null +++ b/source/lib/Sihnon/Log/Plugin/Database.class.php @@ -0,0 +1,49 @@ +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) + ) + ); + } +} + +?> \ No newline at end of file diff --git a/source/lib/Sihnon/Log/Plugin/FlatFile.class.php b/source/lib/Sihnon/Log/Plugin/FlatFile.class.php new file mode 100644 index 0000000..03bb45a --- /dev/null +++ b/source/lib/Sihnon/Log/Plugin/FlatFile.class.php @@ -0,0 +1,44 @@ +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)); + } +} + +?> \ No newline at end of file diff --git a/source/lib/Sihnon/Log/PluginFactory.class.php b/source/lib/Sihnon/Log/PluginFactory.class.php new file mode 100644 index 0000000..6fd8ba1 --- /dev/null +++ b/source/lib/Sihnon/Log/PluginFactory.class.php @@ -0,0 +1,27 @@ + \ No newline at end of file diff --git a/source/lib/Sihnon/Main.class.php b/source/lib/Sihnon/Main.class.php index 3a98ebe..becbfce 100644 --- a/source/lib/Sihnon/Main.class.php +++ b/source/lib/Sihnon/Main.class.php @@ -1,26 +1,37 @@ 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 = ''; diff --git a/source/lib/Sihnon/PluginFactory.class.php b/source/lib/Sihnon/PluginFactory.class.php index 6f623ef..b1e0102 100644 --- a/source/lib/Sihnon/PluginFactory.class.php +++ b/source/lib/Sihnon/PluginFactory.class.php @@ -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();