symphony/lib/toolkit/class.datasourcemanager.php
<?php
/**
* @package toolkit
*/
/**
* The DatasourceManager class is responsible for managing all Datasource objects
* in Symphony. Datasources's are stored on the file system either in the
* `WORKSPACE . /data-sources` folder or provided by an extension in `EXTENSIONS . /./data-sources` folder.
* Datasources are run from the Frontend to commonly output Entries and parameters,
* however there any different types of Datasource that query external sources for data.
* Typically, a Datasource returns XML.
*/
class DatasourceManager implements FileResource
{
/**
* Given the filename of a Datasource, return its handle. This will remove
* the Symphony convention of `data.*.php`
*
* @param string $filename
* The filename of the Datasource
* @return string
*/
public static function __getHandleFromFilename($filename)
{
return preg_replace(array('/^data./i', '/.php$/i'), '', $filename);
}
/**
* Given a name, returns the full class name of an Datasources. Datasources
* use a 'datasource' prefix.
*
* @param string $handle
* The Datasource handle
* @return string
*/
public static function __getClassName($handle)
{
return 'datasource' . $handle;
}
/**
* Finds a Datasource by name by searching the data-sources folder in the
* workspace and in all installed extension folders and returns the path
* to it's folder.
*
* @param string $handle
* The handle of the Datasource free from any Symphony conventions
* such as `data.*.php`
* @return string|boolean
* If the datasource is found, the function returns the path it's folder, otherwise false.
*/
public static function __getClassPath($handle)
{
if (is_file(DATASOURCES . "/data.$handle.php")) {
return DATASOURCES;
} else {
$extensions = Symphony::ExtensionManager()->listInstalledHandles();
if (is_array($extensions) && !empty($extensions)) {
foreach ($extensions as $e) {
if (is_file(EXTENSIONS . "/$e/data-sources/data.$handle.php")) {
return EXTENSIONS . "/$e/data-sources";
}
}
}
}
return false;
}
/**
* Given a name, return the path to the Datasource class
*
* @see DatasourceManager::__getClassPath()
* @param string $handle
* The handle of the Datasource free from any Symphony conventions
* such as `data.*.php`
* @return string
*/
public static function __getDriverPath($handle)
{
return self::__getClassPath($handle) . "/data.$handle.php";
}
/**
* Finds all available Datasources by searching the data-sources folder in
* the workspace and in all installed extension folders. Returns an
* associative array of data sources.
*
* @see toolkit.Manager#about()
* @return array
* Associative array of Datasources with the key being the handle of the
* Datasource and the value being the Datasource's `about()` information.
*/
public static function listAll()
{
$result = array();
$structure = General::listStructure(DATASOURCES, '/data.[\\w-]+.php/', false, 'ASC', DATASOURCES);
if (is_array($structure['filelist']) && !empty($structure['filelist'])) {
foreach ($structure['filelist'] as $f) {
$f = self::__getHandleFromFilename($f);
if ($about = self::about($f)) {
$classname = self::__getClassName($f);
$env = array();
$class = new $classname($env, false);
$about['can_parse'] = method_exists($class, 'allowEditorToParse')
? $class->allowEditorToParse()
: false;
$about['source'] = method_exists($class, 'getSource')
? $class->getSource()
: null;
$result[$f] = $about;
}
}
}
$extensions = Symphony::ExtensionManager()->listInstalledHandles();
if (is_array($extensions) && !empty($extensions)) {
foreach ($extensions as $e) {
if (!is_dir(EXTENSIONS . "/$e/data-sources")) {
continue;
}
$tmp = General::listStructure(EXTENSIONS . "/$e/data-sources", '/data.[\\w-]+.php/', false, 'ASC', EXTENSIONS . "/$e/data-sources");
if (is_array($tmp['filelist']) && !empty($tmp['filelist'])) {
foreach ($tmp['filelist'] as $f) {
$f = self::__getHandleFromFilename($f);
if ($about = self::about($f)) {
$about['can_parse'] = false;
$about['source'] = null;
$result[$f] = $about;
}
}
}
}
}
ksort($result);
return $result;
}
public static function about($name)
{
$classname = self::__getClassName($name);
$path = self::__getDriverPath($name);
if (!General::checkFileReadable($path)) {
return false;
}
require_once($path);
$handle = self::__getHandleFromFilename(basename($path));
$env = array();
$class = new $classname($env, false);
try {
$method = new ReflectionMethod($classname, 'about');
$about = $method->invoke($class);
} catch (ReflectionException $e) {
$about = array();
}
return array_merge($about, array('handle' => $handle));
}
/**
* Creates an instance of a given class and returns it.
*
* @param string $handle
* The handle of the Datasource to create
* @param array $env
* The environment variables from the Frontend class which includes
* any params set by Symphony or Events or by other Datasources
* @param boolean $process_params
* @throws Exception
* @return Datasource
*/
public static function create($handle, array $env = null, $process_params = true)
{
$classname = self::__getClassName($handle);
$path = self::__getDriverPath($handle);
if (!is_file($path)) {
throw new Exception(
__('Could not find Data Source %s.', array('<code>' . $handle . '</code>'))
. ' ' . __('If it was provided by an Extension, ensure that it is installed, and enabled.')
);
}
if (!class_exists($classname)) {
require_once $path;
}
return new $classname($env, $process_params);
}
}