Updates framework to support automated framework subclasses

All framework classes have been renamed to use the SihnonFramework_ prefix.
The class autoloader now looks for subclasses of the framework classes in the Sihnon_Lib directory, and
automatically creates them if they don't exist. The autoloader correctly creates interfaces and abstract
classes as needed, by using reflection to check the type of the parent class.
All references to classes within the framework now use the Sihnon_ prefix.
The PluginFactory supports multiple scan directories, and will search both the framework and subclass class
tree to find candidate plugins.
This commit is contained in:
2010-10-10 18:32:16 +01:00
parent 676fef1deb
commit 81521eae5f
25 changed files with 145 additions and 90 deletions

View File

@@ -1,17 +0,0 @@
<?php
class Sihnon_BackgroundTask {
protected function __construct() {
}
public static function run($command) {
$pipes = array();
$pid = proc_open($command . ' &', array(), $pipes);
proc_close($pid);
}
};
?>

View File

@@ -1,62 +0,0 @@
<?php
class Sihnon_Cache {
protected $config;
protected $cache_dir;
public function __construct(Sihnon_Config $config) {
$this->config = $config;
$this->cache_dir = $config->get('cache.base_dir');
if (is_dir($this->cache_dir)) {
if ( ! is_writeable($this->cache_dir)) {
throw new Sihnon_Exception_InvalidCacheDir();
}
} else {
if ( ! Sihnon_Main::mkdir_recursive($this->cache_dir)) {
throw new Sihnon_Exception_InvalidCacheDir();
}
}
}
protected function cacheFilename($source_filename) {
return $this->cache_dir . sha1($source_filename);
}
public function exists($source_filename, $ttl = 3600) {
$cache_filename = $this->cacheFilename($source_filename);
// Check to see if the file is cached
if (!file_exists($cache_filename)) {
return false;
}
// Check to see if the cache has expired
if (filemtime($cache_filename) + $ttl < time()) {
// Delete the cached item
unlink($cache_filename);
return false;
}
return true;
}
public function store($source_filename, $content) {
$cache_filename = $this->cacheFilename($source_filename);
return file_put_contents($cache_filename, $content);
}
public function fetch($source_filename, $ttl = 3600) {
$cache_filename = $this->cacheFilename($source_filename);
if (!$this->exists($source_filename)) {
throw new Sihnon_Exception_CacheObjectNotFound($source_filename);
}
return file_get_contents($cache_filename);
}
};
?>

View File

@@ -1,90 +0,0 @@
<?php
class Sihnon_Config {
/**
* Boolean value type
* @var bool
*/
const TYPE_BOOL = 'bool';
/**
* Integer value type
* @var int
*/
const TYPE_INT = 'int';
/**
* Float value type
* @var float
*/
const TYPE_FLOAT = 'float';
/**
* String value type
* @var string
*/
const TYPE_STRING = 'string';
/**
* String List value type; list of newline separated strings
* @var array(string)
*/
const TYPE_STRING_LIST = 'array(string)';
/**
* Backend to be used for this Config object
* @var Sihnon_Config_IPlugin
*/
private $backend;
/**
* Associative array of settings loaded from the database
* @var array(string=>array(string=>string))
*/
private $settings = array();
/**
* Constructs a new instance of the Config class
*
* @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($backend, $options) {
$this->backend = Sihnon_Config_PluginFactory::create($backend, $options);
$this->settings = $this->backend->preload();
}
/**
* Identifies whether the named setting exists
*
* @param string $key Name of the setting
* @return bool
*/
public function exists($key) {
return isset($this->settings[$key]);
}
/**
* Fetches the value of the named setting
*
* @param string $key Name of the setting
*/
public function get($key) {
if (!isset($this->settings[$key])) {
throw new Sihnon_Exception_UnknownSetting($key);
}
switch ($this->settings[$key]['type']) {
case self::TYPE_STRING_LIST:
return array_map('trim', explode("\n", $this->settings[$key]['value']));
default:
return $this->settings[$key]['value'];
}
}
};
?>

View File

@@ -1,29 +0,0 @@
<?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

@@ -1,33 +0,0 @@
<?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

@@ -1,31 +0,0 @@
<?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

@@ -1,27 +0,0 @@
<?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

@@ -1,161 +0,0 @@
<?php
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;
private $dbname;
private $prepared_statements = array();
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);
} catch (PDOException $e) {
throw new Sihnon_Exception_DatabaseConnectFailed($e->getMessage());
}
}
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();
foreach ($this->dbh->query($sql) as $row) {
if (is_array($value_cols)) {
$values = array();
foreach ($value_cols as $value_col) {
$values[$value_col] = $row[$value_col];
}
$results[$row[$key_col]] = $values;
} else {
$results[$row[$key_col]] = $row[$value_col];
}
}
return $results;
}
public function selectList($sql, $bind_params = null) {
if ($bind_params) {
$stmt = $this->dbh->prepare($sql);
foreach ($bind_params as $param) {
$stmt->bindValue(':'.$param['name'], $param['value'], $param['type']);
}
$result = $stmt->execute();
if (!$result) {
list($dummy, $code, $message) = $stmt->errorInfo();
throw new Sihnon_Exception_DatabaseQueryFailed($message, $code);
}
return $stmt->fetchAll();
} else {
$results = array();
$result = $this->dbh->query($sql);
foreach ($result as $row) {
$results[] = $row;
}
return $results;
}
}
public function selectOne($sql, $bind_params = null) {
$rows = $this->selectList($sql, $bind_params);
if (count($rows) != 1) {
throw new Sihnon_Exception_ResultCountMismatch(count($rows));
}
return $rows[0];
}
public function insert($sql, $bind_params = null) {
$stmt = $this->dbh->prepare($sql);
if ($bind_params) {
foreach ($bind_params as $param) {
if (isset($param['type'])) {
$stmt->bindValue(':'.$param['name'], $param['value'], $param['type']);
} else {
$stmt->bindValue(':'.$param['name'], $param['value']);
}
}
}
$result = $stmt->execute();
if (!$result) {
list($code, $dummy, $message) = $stmt->errorInfo();
throw new Sihnon_Exception_DatabaseQueryFailed($message, $code);
}
}
public function update($sql, $bind_params = null) {
$stmt = $this->dbh->prepare($sql);
if ($bind_params) {
foreach ($bind_params as $param) {
if (isset($param['type'])) {
$stmt->bindValue(':'.$param['name'], $param['value'], $param['type']);
} else {
$stmt->bindValue(':'.$param['name'], $param['value']);
}
}
}
$result = $stmt->execute();
if (!$result) {
list($code, $dummy, $message) = $stmt->errorInfo();
throw new Sihnon_Exception_DatabaseQueryFailed($message, $code);
}
}
public function errorInfo() {
return $this->dbh->errorInfo();
}
public function lastInsertId() {
return $this->dbh->lastInsertId();
}
}
?>

View File

@@ -1,24 +0,0 @@
<?php
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 {};
class Sihnon_Exception_NoDatabaseConnection extends Sihnon_Exception_DatabaseException {};
class Sihnon_Exception_DatabaseQueryFailed extends Sihnon_Exception_DatabaseException {};
class Sihnon_Exception_ResultCountMismatch extends Sihnon_Exception_DatabaseException {};
class Sihnon_Exception_ConfigException extends Sihnon_Exception {};
class Sihnon_Exception_UnknownSetting extends Sihnon_Exception_ConfigException {};
class Sihnon_Exception_CacheException extends Sihnon_Exception {};
class Sihnon_Exception_InvalidCacheDir extends Sihnon_Exception_CacheException {};
class Sihnon_Exception_CacheObjectNotFound extends Sihnon_Exception_CacheException {};
class Sihnon_Exception_InvalidPluginName extends Sihnon_Exception {};
?>

View File

@@ -1,113 +0,0 @@
<?php
class Sihnon_ForegroundTask {
const PIPE_STDIN = 0;
const PIPE_STDOUT = 1;
const PIPE_STDERR = 2;
private function __construct() {
}
/**
*
* Code largely taken from user submitted comment on http://php.sihnon.net/manual/en/function.proc-open.php
* @param unknown_type $command
* @param unknown_type $cwd
* @param unknown_type $env
* @param unknown_type $stdin
* @param unknown_type $callback_stdout
* @param unknown_type $callback_stderr
*/
public static function execute($command, $cwd = null, $env = null, $stdin = null, $callback_stdout = null, $callback_stderr = null, $identifier = null) {
$txOff = 0;
$txLen = strlen($stdin);
$stdout = '';
$stdoutDone = FALSE;
$stderr = '';
$stderrDone = FALSE;
$descriptors = array(
self::PIPE_STDIN => array('pipe', 'r'),
self::PIPE_STDOUT => array('pipe', 'w'),
self::PIPE_STDERR => array('pipe', 'w'),
);
$pipes = array();
$process = proc_open($command, $descriptors, $pipes);
stream_set_blocking($pipes[self::PIPE_STDIN], 0); // Make stdin/stdout/stderr non-blocking
stream_set_blocking($pipes[self::PIPE_STDOUT], 0);
stream_set_blocking($pipes[self::PIPE_STDERR], 0);
if ($txLen == 0) {
fclose($pipes[0]);
}
while (true) {
$rx = array(); // The program's stdout/stderr
if (!$stdoutDone) {
$rx[] = $pipes[self::PIPE_STDOUT];
}
if (!$stderrDone) {
$rx[] = $pipes[self::PIPE_STDERR];
}
$tx = array(); // The program's stdin
if ($txOff < $txLen) {
$tx[] = $pipes[self::PIPE_STDIN];
}
$ex = array();
stream_select($rx, $tx, $ex, null, null); // Block til r/w possible
if (!empty($tx)) {
$txRet = fwrite($pipes[self::PIPE_STDIN], substr($stdin, $txOff, 8192));
if ($txRet !== false) {
$txOff += $txRet;
}
if ($txOff >= $txLen) {
fclose($pipes[self::PIPE_STDIN]);
}
}
foreach ($rx as $r) {
if ($r == $pipes[self::PIPE_STDOUT]) {
$chunk = fread($pipes[self::PIPE_STDOUT], 8192);
if (feof($pipes[self::PIPE_STDOUT])) {
fclose($pipes[self::PIPE_STDOUT]); $stdoutDone = true;
}
if ($callback_stdout) {
call_user_func($callback_stdout, $identifier, $chunk);
} else {
$stdout .= $chunk;
}
} else if ($r == $pipes[self::PIPE_STDERR]) {
$chunk = fread($pipes[self::PIPE_STDERR], 8192);
if (feof($pipes[self::PIPE_STDERR])) {
fclose($pipes[self::PIPE_STDERR]); $stderrDone = true;
}
if ($callback_stderr) {
call_user_func($callback_stderr, $identifier, $chunk);
} else {
$stderr .= $chunk;
}
}
}
if (!is_resource($process))
break;
if ($txOff >= $txLen && $stdoutDone && $stderrDone)
break;
}
return array(proc_close($process), $stdout, $stderr);
}
}

View File

@@ -1,11 +0,0 @@
<?php
interface Sihnon_IPlugin {
public static function init();
public static function name();
}
?>

View File

@@ -1,9 +0,0 @@
<?php
interface Sihnon_IPluginFactory {
public static function init();
}
?>

View File

@@ -1,54 +0,0 @@
<?php
class Sihnon_Log {
const LEVEL_DEBUG = 'DEBUG';
const LEVEL_INFO = 'INFO';
const LEVEL_WARNING = 'WARNING';
const LEVEL_ERROR = 'ERROR';
private static $hostname = '';
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($level, $message) {
$this->backend->log($level, time(), 0, self::$hostname, $this->progname, 0, $message);
}
public function debug($message) {
return $this->log(self::LEVEL_DEBUG, $message);
}
public function info($message) {
return $this->log(self::LEVEL_INFO, $message);
}
public function warning($message) {
return $this->log(self::LEVEL_WARNING, $message);
}
public function error($message) {
return $this->log(self::LEVEL_ERROR, $message);
}
public static function initialise() {
self::$hostname = trim(`hostname`);
}
}
Sihnon_Log::initialise();
?>

View File

@@ -1,27 +0,0 @@
<?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

@@ -1,49 +0,0 @@
<?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

@@ -1,44 +0,0 @@
<?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

@@ -1,27 +0,0 @@
<?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,97 +0,0 @@
<?php
abstract class Sihnon_LogEntry {
protected static $table_name = "";
protected $id;
protected $level;
protected $ctime;
protected $pid;
protected $hostname;
protected $progname;
protected $line;
protected $message;
protected function __construct($id, $level, $ctime, $pid, $hostname, $progname, $line, $message) {
$this->id = $id;
$this->level = $level;
$this->ctime = $ctime;
$this->pid = $pid;
$this->hostname = $hostname;
$this->progname = $progname;
$this->line = $line;
$this->message = $message;
}
public static function fromDatabaseRow($row) {
return new Sihnon_ClientLogEntry(
$row['id'],
$row['level'],
$row['ctime'],
$row['pid'],
$row['hostname'],
$row['progname'],
$row['line'],
$row['message']
);
}
public static function fromId($id) {
$database = Sihnon_Main::instance()->database();
return Sihnon_ClientLogEntry::fromDatabaseRow(
$database->selectOne('SELECT * FROM '.self::$table_name.' WHERE id=:id', array(
array('name' => 'id', 'value' => $id, 'type' => PDO::PARAM_INT)
)
)
);
}
public static function recent($limit = 100) {
$entries = array();
$database = Sihnon_Main::instance()->database();
foreach ($database->selectList('SELECT * FROM '.self::$table_name.' ORDER BY ctime DESC LIMIT :limit', array(
array('name' => 'limit', 'value' => $limit, 'type' => PDO::PARAM_INT)
)) as $row) {
$entries[] = self::fromDatabaseRow($row);
}
return $entries;
}
public function id() {
return $this->id;
}
public function level() {
return $this->level;
}
public function ctime() {
return $this->ctime;
}
public function pid() {
return $this->pid;
}
public function hostname() {
return $this->hostname;
}
public function progname() {
return $this->progname;
}
public function line() {
return $this->line;
}
public function message() {
return $this->message;
}
};
?>

View File

@@ -1,196 +0,0 @@
<?php
class Sihnon_Main {
protected static $instance;
protected $config;
protected $database;
protected $log;
protected $cache;
protected $base_uri;
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);
}
/**
*
* @return Sihnon_Main
*/
public static function instance() {
if (!self::$instance) {
self::$instance = new Sihnon_Main();
self::$instance->init();
}
return self::$instance;
}
/**
*
* @return Sihnon_Config
*/
public function config() {
return $this->config;
}
/**
*
* @return Sihnon_Database
*/
public function database() {
return $this->database;
}
/**
*
* @return Sihnon_Log
*/
public function log() {
return $this->log;
}
/**
*
* @return Sihnon_Cache
*/
public function cache() {
return $this->cache;
}
public function baseUri() {
return $this->base_uri;
}
public function absoluteUrl($relative_url) {
$secure = isset($_SERVER['secure']);
$port = $_SERVER['SERVER_PORT'];
return 'http' . ($secure ? 's' : '') . '://'
. $_SERVER['HTTP_HOST'] . (($port == 80 || ($secure && $port == 443)) ? '' : ':' . $port)
. '/' . $this->base_uri . $relative_url;
}
public static function initialise() {
spl_autoload_register(array('Sihnon_Main','autoload'));
}
public static function autoload($classname) {
// Ensure the classname contains only valid class name characters
if (!preg_match('/^[A-Z][a-zA-Z0-9_]*$/', $classname)) {
throw new Exception('Illegal characters in classname'); // TODO Subclass this exception
}
// Ensure the class to load begins with our prefix
if (!preg_match('/^Sihnon_/', $classname)) {
return;
}
// Special case: All exceptions are stored in the same file
if (preg_match('/^Sihnon_Exception/', $classname)) {
require_once(Sihnon_Lib . 'Sihnon/Exceptions.class.php');
return;
}
// Replace any underscores with directory separators
$filename = Sihnon_Lib . preg_replace('/_/', '/', $classname);
// Tack on the class file suffix
$filename .= '.class.php';
// If this file exists, load it
if (file_exists($filename)) {
require_once $filename;
}
}
/**
* 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 = '';
for ($i=1,$l=count($parts); $i<=$l; $i++) {
$iPath = $parts;
$path = join('/', array_slice($iPath, 0, $i));
if (empty($path)) continue;
if (!file_exists($path)) {
if (!mkdir($path)) return false;
if (!chmod($path, $permissions)) return false;
}
}
return true;
}
public static function issetelse($var, $default = null) {
if (isset($var)) {
return $var;
}
if (is_string($default) && preg_match('/^Sihnon_Exception/', $default) && class_exists($default) && is_subclass_of($default, Sihnon_Exception)) {
throw new $default();
}
return $default;
}
public static function formatDuration($time) {
if (is_null($time)) {
return 'unknown';
}
$labels = array('seconds', 'minutes', 'hours', 'days', 'weeks', 'months', 'years');
$limits = array(1, 60, 3600, 86400, 604800, 2592000, 31556926, PHP_INT_MAX);
$working_time = $time;
$result = "";
$ptr = count($labels) - 1;
while ($ptr >= 0 && $working_time < $limits[$ptr]) {
--$ptr;
}
while ($ptr >= 0) {
$unit_time = floor($working_time / $limits[$ptr]);
$working_time -= $unit_time * $limits[$ptr];
$result = $result . ' ' . $unit_time . ' ' . $labels[$ptr];
--$ptr;
}
return $result;
}
}
Sihnon_Main::initialise();
?>

View File

@@ -1,30 +0,0 @@
<?php
/**
* Base class for all plugins, providing default implementations for
* standard plugin methods.
*
* @class Sihnon_PluginBase
*/
class Sihnon_PluginBase {
/**
* Provides a basic initialisation function that does nothing.
*
*/
public static function init() {
// Nothing to do
}
/**
* Returns the name of this plugin
*
* @return string
*/
public static function name() {
return static::PLUGIN_NAME;
}
}
?>

View File

@@ -1,80 +0,0 @@
<?php
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();
}
}
protected static function isValidPlugin($plugin) {
return isset(self::$validPlugins[get_called_class()][$plugin]);
}
public static function getValidPlugins() {
static::ensureScanned();
return array_keys(self::$validPlugins[get_called_class()]);
}
protected static function findPlugins($directory) {
$plugins = array();
$iterator = new Sihnon_Utility_ClassFilesIterator(new Sihnon_Utility_VisibleFilesIterator(new DirectoryIterator(Sihnon_Lib . $directory)));
foreach ($iterator as /** @var SplFileInfo */ $file) {
$plugin = preg_replace('/.class.php$/', '', $file->getFilename());
$plugins[] = $plugin;
}
return $plugins;
}
protected static function loadPlugins($plugins, $prefix, $interface) {
self::$validPlugins[get_called_class()] = array();
foreach ($plugins as $plugin) {
$fullClassname = $prefix . $plugin;
if ( ! class_exists($fullClassname, true)) {
continue;
}
if ( ! in_array($interface, class_implements($fullClassname))) {
continue;
}
// Initialise the plugin
call_user_func(array($fullClassname, 'init'));
self::$validPlugins[get_called_class()][$plugin] = $fullClassname;
}
}
public static function classname($plugin) {
static::ensureScanned();
if ( ! self::isValidPlugin($plugin)) {
throw new Sihnon_Exception_InvalidPluginName($plugin);
}
return self::$validPlugins[get_called_class()][$plugin];
}
}
?>

View File

@@ -1,9 +0,0 @@
<?php
class Sihnon_Utility_ClassFilesIterator extends FilterIterator {
public function accept() {
return preg_match('/.class.php$/i', $this->current()->getFilename());
}
}
?>

View File

@@ -1,9 +0,0 @@
<?php
class Sihnon_Utility_VisibleFilesIterator extends FilterIterator {
public function accept() {
return !(substr($this->current()->getFilename(), 0, 1) == '.');
}
}
?>

View File

@@ -1,9 +0,0 @@
<?php
class Sihnon_Utility_VisibleFilesRecursiveIterator extends RecursiveFilterIterator {
public function accept() {
return !(substr($this->current()->getFilename(), 0, 1) == '.');
}
}
?>