Configuration: "global" settings are set here.
* See the setConfiguration() method to see how they
* can be set, and the config() and hasConfig() methods to see
* how configuration might be checked.
* - Stream Wrappers: This class can initialize a set of stream
* wrappers which will make certain HPCloud services available
* through the core PHP stream support.
* - Autoloader: It provides a special-purpose autoloader that can
* load the HPCloud classes, but which will not interfere with
* other autoloading facilities.
*
* Configuration
*
* Configuration directives can be merged into the existing confiuration
* using the setConfiguration method.
*
* @code
* '\HPCloud\Transport\CURLTransport',
* // Set the HTTP max wait time to 500.
* 'transport.timeout' => 500,
* );
* Bootstrap::setConfiguration($config);
*
* // Check and get params.
* if (Bootstrap::hasConf('transport.timeout') {
* $to = Bootstrap::conf('transport.timeout');
* }
*
* // Or get a param with a default value:
* $val = Bootstrap::conf('someval', 'default value');
*
* // $val will be set to 'default value' because there
* // is no 'someval' configuration param.
*
* ?>
* @endcode
*
* AUTOLOADING
*
* HPCloud comes with a built-in autoloader that can be called like this:
*
* @code
* Bootstrap::useAutoloader();
* @endcode
*
* @attention
* The structure of the HPCloud file hierarchy is PSR-0 compliant.
* This means that you can use any standard PSR-0 classloader to
* load all of the classes here.
*
* That said, many projects rely upon packages to handle their own
* class loading. To provide this, this package contains a custom
* classloader that will load JUST the HPCloud classes. See
* the Bootstrap::useAutoloader() static method.
*
* See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
*
* STREAM WRAPPERS
*
* Stream wrappers allow you to use the built-in file manipulation
* functions in PHP to interact with other services. Specifically,
* the HPCloud stream wrappers allow you to use built-in file commands
* to access Object Storage (Swift) and other HPCloud services using
* commands like file_get_contents() and fopen().
*
* It's awesome. Trust me.
*
*/
class Bootstrap {
/**
* The directory where HPCloud is located.
*/
public static $basedir = __DIR__;
public static $config = array(
// The transport implementation. By default, we use the PHP stream
// wrapper's HTTP mechanism to process transactions.
//'transport' => '\HPCloud\Transport\PHPStreamTransport',
// This is the default transport while a bug persists in the
// Identity Services REST service.
'transport' => '\HPCloud\Transport\CURLTransport',
);
/**
* An identity services object created from the global settings.
* @var object HPCloud::Services::IdentityServices
*/
public static $identity = NULL;
/**
* Add the autoloader to PHP's autoloader list.
*
* This will add the internal special-purpose
* autoloader to the list of autoloaders that PHP will
* leverage to resolve class paths.
*
* Because HPCloud is PSR-0 compliant, any
* full PSR-0 classloader should be capable of loading
* these classes witout issue. You may prefer to use
* a standard PSR-0 loader instead of this one.
*
* @see https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
*/
public static function useAutoloader() {
spl_autoload_register(__NAMESPACE__ . '\Bootstrap::autoload');
}
/**
* Register stream wrappers for HPCloud.
*
* This register the ObjectStorage stream wrappers, which allow you to access
* ObjectStorage through standard file access mechanisms.
*
* @code
* // Enable stream wrapper.
* Bootstrap::useStreamWrappers();
*
* // Create a context resource.
* $cxt = stream_context_create(array(
* 'tenantid' => '12de21',
* 'account' => '123454321',
* 'secret' => 'f78saf7hhlll',
* 'endpoint' => 'https://identity.hpcloud.com' // <-- not real URL!
* ));
*
* // Get the contents of a Swift object.
* $content = file_get_contents('swift://public/notes.txt', 'r', FALSE, $cxt);
* @endcode
*/
public static function useStreamWrappers() {
$swift = stream_wrapper_register(
\HPCloud\Storage\ObjectStorage\StreamWrapper::DEFAULT_SCHEME,
'\HPCloud\Storage\ObjectStorage\StreamWrapper'
);
$swiftfs = stream_wrapper_register(
\HPCloud\Storage\ObjectStorage\StreamWrapperFS::DEFAULT_SCHEME,
'\HPCloud\Storage\ObjectStorage\StreamWrapperFS'
);
return ($swift && $swiftfs);
}
/**
* Set configuration directives for HPCloud.
*
* This merges the provided associative array into the existing
* configuration parameters (Bootstrap::$config).
*
* All of the HPCloud classes share the same configuration. This
* ensures that a stable runtime environment is maintained.
*
* Common configuration directives:
*
* - 'transport': The namespaced classname for the transport that
* should be used. Example: @code \HPCloud\Transport\CURLTransport @endcode
* - 'transport.debug': The integer 1 for enabling debug, 0 for
* disabling. Enabling will turn on verbose debugging output
* for any transport that supports it.
* - 'transport.timeout': An integer value indicating how long
* the transport layer should wait for an HTTP request. A
* transport MAY ignore this parameter, but the ones included
* with the library honor it.
* - 'account' and 'secret'
* - 'username' and 'password'
* - 'tenantid'
* - 'endpoint': The full URL to identity services. This is used by stream
* wrappers.
*
* @param array $array
* An associative array of configuration directives.
*/
public static function setConfiguration($array) {
self::$config = $array + self::$config;
}
/**
* HPCloud autoloader.
*
* An implementation of a PHP autoload function. Use
* HPCloud::useAutoloader() if you want PHP to automatically
* load classes using this autoloader.
*
* @code
* // Enable the autoloader.
* Bootstrap::useAutoloader();
* @endcode
*
* This is a special-purpose autoloader for loading
* only the HPCloud classes. It will not attempt to
* autoload anything outside of the HPCloud namespace.
*
* Because this is a special-purpose autoloader, it
* should be safe to use with other special-purpose
* autoloaders (and also projects that don't
* rely upon autoloaders).
*
* @param string $klass
* The fully qualified name of the class to be autoloaded.
*/
public static function autoload($klass) {
$components = explode('\\', $klass);
if (empty($components[0])) {
array_shift($components);
}
// This class loader ONLY loads
// our classes. A general purpose
// classloader should be used for
// more sophisticated needs.
if ($components[0] != 'HPCloud') {
return;
}
// We need the path up to, but not including, the root HPCloud dir:
$local_path = substr(self::$basedir, 0, strrpos(self::$basedir, '/HPCloud'));
array_unshift($components, $local_path);
$path = implode(DIRECTORY_SEPARATOR, $components) . '.php';
if (file_exists($path)) {
require $path;
return;
}
}
/**
* Get a configuration option.
*
* Get a configuration option by name, with an optional default.
*
* @param string $name
* The name of the configuration option to get.
* @param mixed $default
* The default value to return if the name is not found.
* @retval mixed
* The value, if found; or the default, if set; or NULL.
*/
public static function config($name = NULL, $default = NULL) {
// If no name is specified, return the entire config array.
if (empty($name)) {
return self::$config;
}
// If the config value exists, return that.
if (isset(self::$config[$name])) {
return self::$config[$name];
}
// Otherwise, just return the default value.
return $default;
}
/**
* Check whether the given configuration option is set.
*
* @code
* if (Bootstrap::hasConfig('transport')) {
* syslog(LOG_INFO, 'An alternate transport is supplied.');
* }
* @endcode
*
* @param string $name
* The name of the item to check for.
* @retval boolean
* TRUE if the named option is set, FALSE otherwise. Note that the value may
* be falsey (FALSE, 0, etc.), but if the value is NULL, this will return
* false.
*/
public static function hasConfig($name) {
return isset(self::$config[$name]);
}
/**
* Get a HPCloud::Services::IdentityService object from the bootstrap config.
*
* A factory helper function that uses the bootstrap configuration to create
* a ready to use HPCloud::Services::IdentityService object.
*
* @param bool $force
* Whether to force the generation of a new object even if one is already
* cached.
* @retval HPCloud::Services::IdentityService
* An authenticated ready to use HPCloud::Services::IdentityService object.
* @throws HPCloud::Exception
* When the needed configuration to authenticate is not available.
*/
public static function identity($force = FALSE) {
// If we already have an identity make sure the token is not expired.
if ($force || is_null(self::$identity) || self::$identity->isExpired()) {
// Make sure we have an endpoint to use
if (!self::hasConfig('endpoint')) {
throw new Exception('Unable to authenticate. No endpoint supplied.');
}
// Neither user nor account can be an empty string, so we need
// to do more checking than self::hasConfig(), which returns TRUE
// if an item exists and is an empty string.
$user = self::config('username', NULL);
$account = self::config('account', NULL);
// Check if we have a username/password
if (!empty($user) && self::hasConfig('password')) {
$is = new IdentityServices(self::config('endpoint'));
$is->authenticateAsUser($user, self::config('password'), self::config('tenantid', NULL), self::config('tenantname', NULL));
self::$identity = $is;
}
// Otherwise we go with access/secret keys
elseif (!empty($account) && self::hasConfig('secret')) {
$is = new IdentityServices(self::config('endpoint'));
$is->authenticateAsAccount($account, self::config('secret'), self::config('tenantid', NULL), self::config('tenantname', NULL));
self::$identity = $is;
}
else {
throw new Exception('Unable to authenticate. No account credentials supplied.');
}
}
return self::$identity;
}
}