configuration file system integration

This commit is contained in:
Nicolas Le Goff
2011-12-28 13:24:26 +01:00
parent 5a0ed13223
commit 42ce345fe8
8 changed files with 419 additions and 71 deletions

View File

@@ -58,7 +58,7 @@ class Core extends \Pimple
$conf = $this->conf; $conf = $this->conf;
$this['EM'] = $this->share(function() use ($conf) $this['EM'] = $this->share(function() use ($conf)
{ {
$doctrine = new Core\Service\Doctrine($conf->getDoctrineConf()); $doctrine = new Core\Service\Doctrine($conf->getDoctrine());
return $doctrine->getEntityManager(); return $doctrine->getEntityManager();
}); });

View File

@@ -11,6 +11,9 @@
namespace Alchemy\Phrasea\Core; namespace Alchemy\Phrasea\Core;
use Alchemy\Phrasea\Core\Configuration\Application;
use Alchemy\Phrasea\Core\Configuration\Parser as ConfigurationParser;
/** /**
* Handle configuration file mechanism of phraseanet * Handle configuration file mechanism of phraseanet
* *
@@ -20,7 +23,6 @@ namespace Alchemy\Phrasea\Core;
*/ */
class Configuration class Configuration
{ {
const MAIN_ENV_NAME = "main";
/** /**
* The environnment name * The environnment name
@@ -29,16 +31,35 @@ class Configuration
protected $environnement; protected $environnement;
/** /**
* The configuration * The finale configuration values as an array
* @var Array * @var Array
*/ */
protected $configuration; protected $configuration = array();
/** /**
* Tell if appli is currently installed * Tell if appli is currently installed
* @var boolean * @var boolean
*/ */
protected $installed; protected $installed = false;
/**
* Class that take care of configuration process
* @var Configuration\Handler
*/
private $configurationHandler;
/**
* Class that take care of configuration specification
* like filepath, extends keywords etc ..
* @var Configuration\Specification
*/
private $configurationSpecification;
/**
* Class that take care of parsing configuration file
* @var Configuration\Parser
*/
private $configurationParser;
/** /**
* *
@@ -46,28 +67,61 @@ class Configuration
*/ */
public function __construct($envName) public function __construct($envName)
{ {
//check whether the main configuration file is present on disk $this->init($envName);
try
{
$specifications = new Configuration\PhraseaConfiguration();
$parser = new Configuration\Parser\Yaml();
$specifications->getConfFileFromEnvName(self::MAIN_ENV_NAME);
$this->installed = true;
$this->environnement = $envName;
$confHandler = new Configuration\EnvironnementHandler($specifications, $parser);
$this->configuration = $confHandler->handle($envName);
}
catch(\Exception $e)
{
$this->installed = false;
} }
/**
* Getter
* @return Configuration\Handler
*/
public function getConfigurationHandler()
{
return $this->configurationHandler;
}
/**
* Setter
* @param Configuration\Handler $configurationHandler
*/
public function setConfigurationHandler(Configuration\Handler $configurationHandler)
{
$this->configurationHandler = $configurationHandler;
}
/**
* Getter
* @return Configuration\Specification
*/
public function getConfigurationSpecification()
{
return $this->configurationSpecification;
}
/**
* Setter
* @param Configuration\Specification $configurationSpecification
*/
public function setConfigurationSpecification(Configuration\Specification $configurationSpecification)
{
$this->configurationSpecification = $configurationSpecification;
}
/**
* Getter
* @return Configuration\Parser
*/
public function getConfigurationParser()
{
return $this->configurationParser;
}
/**
* Setter
* @param type $configurationParser
*/
public function setConfigurationParser($configurationParser)
{
$this->configurationParser = $configurationParser;
} }
/** /**
@@ -85,9 +139,52 @@ class Configuration
* *
* @return Array * @return Array
*/ */
public function getDbalConf() public function getDoctrine()
{ {
return (array) $this->configuration['doctrine']['dbal'] ?: null; $doctrine = $this->get('doctrine'); //get doctrine scope
if (null !== $doctrine)
{
$doctrine["debug"] = $this->isDebug(); //set debug
if (!!$doctrine["log"]['enable'])
{
$logger = $doctrine["log"]["type"];
if (!in_array($doctrine["log"]["type"], $this->getAvailableLogger()))
{
throw new \Exception(sprintf('Unknow logger %s', $logger));
}
$doctrineLogger = $this->get($logger); //set logger
$doctrine["logger"] = $doctrineLogger;
}
}
return null === $doctrine ? array() : $doctrine;
}
/**
* Check if current environnement is on debug mode
* Default to false
* @return boolean
*/
public function isDebug()
{
$phraseanet = $this->getPhraseanet();
return isset($phraseanet["debug"]) ? !!$phraseanet["debug"] : false;
}
/**
* Return the phraseanet scope configurations values
*
* @return Array|null
*/
public function getPhraseanet()
{
$phraseanet = $this->get('phraseanet');
return null === $phraseanet ? array() : $phraseanet;
} }
/** /**
@@ -100,13 +197,21 @@ class Configuration
return $this->installed; return $this->installed;
} }
public function get($key) /**
* Check if key exist in final configuration if yes it returns the value else
* it returns null
*
* @param type $key
* @return Array|null
*/
private function get($key)
{ {
return isset($this->configuration[$key]) ? $this->configuration[$key] : null; return isset($this->configuration[$key]) ? $this->configuration[$key] : null;
} }
/** /**
* Return the configuration * Return the configuration
*
* @return Array|null * @return Array|null
*/ */
public function getConfiguration() public function getConfiguration()
@@ -114,5 +219,61 @@ class Configuration
return $this->configuration; return $this->configuration;
} }
/**
* Return Available logger
*
* @return Array
*/
private function getAvailableLogger()
{
return array('echo', 'monolog');
}
/**
* Return configurationFilePAth
* @return string
*/
public function getConfigurationFilePath()
{
return __DIR__ . '/../../../../config';
}
/**
* Return configurationFileName
* @return string
*/
public function getConfigurationFileName()
{
return 'config.yml';
}
/**
* Init object
* Called in constructor
*/
private function init($envName)
{
$filePath = $this->getConfigurationFilePath();
$fileName = $this->getConfigurationFileName();
try
{
new \SplFileObject(sprintf("%s/%s", $filePath, $fileName));
$this->installed = true;
}
catch (\Exception $e)
{
}
$this->environnement = $envName;
if ($this->installed)
{
$confHandler = new Configuration\Handler(new Application(), new ConfigurationParser\Yaml());
$this->configuration = $confHandler->handle($envName);
}
}
} }

View File

@@ -18,7 +18,7 @@ namespace Alchemy\Phrasea\Core\Configuration;
* @license http://opensource.org/licenses/gpl-3.0 GPLv3 * @license http://opensource.org/licenses/gpl-3.0 GPLv3
* @link www.phraseanet.com * @link www.phraseanet.com
*/ */
class PhraseaConfiguration implements ConfigurationSpecification class Application implements Specification
{ {
/** /**
@@ -38,7 +38,12 @@ class PhraseaConfiguration implements ConfigurationSpecification
*/ */
public function getConfFileFromEnvName($name) public function getConfFileFromEnvName($name)
{ {
return new \SplFileObject(sprintf("/%s/config_%s.%s" if($name === self::EXTENDED_MAIN_KEYWORD)
{
return $this->getMainFile();
}
return new \SplFileObject(sprintf("%s/config_%s.%s"
, $this->getConfigurationFilePath() , $this->getConfigurationFilePath()
, $name , $name
, $this->getConfFileExtension()) , $this->getConfFileExtension())
@@ -54,6 +59,12 @@ class PhraseaConfiguration implements ConfigurationSpecification
return __DIR__ . '/../../../../../config'; return __DIR__ . '/../../../../../config';
} }
public function getMainFile()
{
$path = __DIR__ . '/../../../../../config/config.yml';
return new \SplFileObject($path);
}
/** /**
* *
* {@inheritdoc} * {@inheritdoc}

View File

@@ -20,7 +20,7 @@ use \Symfony\Component\Yaml\Yaml;
* @license http://opensource.org/licenses/gpl-3.0 GPLv3 * @license http://opensource.org/licenses/gpl-3.0 GPLv3
* @link www.phraseanet.com * @link www.phraseanet.com
*/ */
class EnvironnementHandler class Handler
{ {
/** /**
* Configuration file specification interface * Configuration file specification interface
@@ -40,7 +40,7 @@ class EnvironnementHandler
* @param ConfigurationSpecification $configSpec * @param ConfigurationSpecification $configSpec
* @param Parser\ParserInterface $parser * @param Parser\ParserInterface $parser
*/ */
public function __construct(ConfigurationSpecification $configSpec, Parser\ParserInterface $parser) public function __construct(Application $configSpec, Parser $parser)
{ {
$this->confSpecification = $configSpec; $this->confSpecification = $configSpec;
$this->parser = $parser; $this->parser = $parser;
@@ -74,7 +74,7 @@ class EnvironnementHandler
} }
catch (\Exception $e) catch (\Exception $e)
{ {
throw \Exception(sprintf("filename %s not found", $file->getPathname())); throw new \Exception(sprintf("filename %s not found", $file->getPathname()));
} }
} }
else else

View File

@@ -9,7 +9,7 @@
* file that was distributed with this source code. * file that was distributed with this source code.
*/ */
namespace Alchemy\Phrasea\Core\Configuration\Parser; namespace Alchemy\Phrasea\Core\Configuration;
/** /**
* A interface to parse configuration file * A interface to parse configuration file
@@ -18,7 +18,7 @@ namespace Alchemy\Phrasea\Core\Configuration\Parser;
* @license http://opensource.org/licenses/gpl-3.0 GPLv3 * @license http://opensource.org/licenses/gpl-3.0 GPLv3
* @link www.phraseanet.com * @link www.phraseanet.com
*/ */
interface ParserInterface interface Parser
{ {
/** /**
* Parse the configuration file $file to an array * Parse the configuration file $file to an array

View File

@@ -19,7 +19,7 @@ use Symfony\Component\Yaml\Yaml as SfYaml;
* @license http://opensource.org/licenses/gpl-3.0 GPLv3 * @license http://opensource.org/licenses/gpl-3.0 GPLv3
* @link www.phraseanet.com * @link www.phraseanet.com
*/ */
class Yaml implements ParserInterface class Yaml implements \Alchemy\Phrasea\Core\Configuration\Parser
{ {
/** /**
* *

View File

@@ -18,12 +18,16 @@ namespace Alchemy\Phrasea\Core\Configuration;
* @license http://opensource.org/licenses/gpl-3.0 GPLv3 * @license http://opensource.org/licenses/gpl-3.0 GPLv3
* @link www.phraseanet.com * @link www.phraseanet.com
*/ */
interface ConfigurationSpecification interface Specification
{ {
/** /**
* Keywords to detect extended file * Keywords to detect extended file
*/ */
const EXTENDED_KEYWORD = 'extends'; const EXTENDED_KEYWORD = 'extends';
/**
* Keywords to detect main file
*/
const EXTENDED_MAIN_KEYWORD = 'main';
/** /**
* Return an array of paths that CAN'T be extended by ONLY one or more of their value * Return an array of paths that CAN'T be extended by ONLY one or more of their value

View File

@@ -9,7 +9,6 @@
* file that was distributed with this source code. * file that was distributed with this source code.
*/ */
namespace Alchemy\Phrasea\Core\Service; namespace Alchemy\Phrasea\Core\Service;
use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Type;
@@ -22,19 +21,135 @@ use Doctrine\DBAL\Types\Type;
*/ */
class Doctrine class Doctrine
{ {
const MEMCACHED = 'memcached';
const ARRAYCACHE = 'array';
const APC = 'apc';
protected $entityManager; protected $entityManager;
public function __construct() public function __construct(Array $doctrineConfiguration)
{ {
require_once __DIR__ . '/../../../../vendor/doctrine2-orm/lib/vendor/doctrine-common/lib/Doctrine/Common/ClassLoader.php'; require_once __DIR__ . '/../../../../vendor/doctrine2-orm/lib/vendor/doctrine-common/lib/Doctrine/Common/ClassLoader.php';
static::loadClasses(); static::loadClasses();
$config = new \Doctrine\ORM\Configuration(); $config = new \Doctrine\ORM\Configuration();
$config->setMetadataCacheImpl(new \Doctrine\Common\Cache\ArrayCache); //debug mode
$debug = isset($doctrineConfiguration["debug"]) ? : false;
//doctrine cache
$cache = !isset($doctrineConfiguration["orm"]["cache"]) ? : $doctrineConfiguration["orm"]["cache"];
//doctrine log configuration
$log = isset($doctrineConfiguration["log"]) ? !!$doctrineConfiguration["log"] : false;
$logEnable = isset($log["enable"]) ? : !!$log["enable"];
//service logger configuration
$logger = !isset($doctrineConfiguration['logger']) ? : $doctrineConfiguration['logger'];
//default query cache & meta chache
$metaCache = $this->getCache();
$queryCache = $this->getCache();
//handle cache
if ($cache && !$debug)
{
//define query cache
$cacheName = isset($cache["query"]) ? $cache["query"] : self::ARRAYCACHE;
$queryCache = $this->getCache($cacheName);
//define metadatas cache
$cacheName = isset($cache["metadata"]) ? $cache["metadata"] : self::ARRAYCACHE;
$metaCache = $this->getCache($cacheName);
}
//Handle logs
if ($logEnable)
{
$loggerService = isset($log["type"]) ? $log["type"] : '';
switch ($loggerService)
{
case 'monolog':
//defaut to main handler
$doctrineHandler = isset($log["handler"]) ? $log["handler"] : 'main';
if(!isset($logger["handlers"]))
{
throw new \Exception("You must specify at least on monolog handler");
}
if (!array_key_exists($doctrineHandler, $logger["handlers"]))
{
throw new \Exception(sprintf('Unknow monolog handler %s'), $handlerType);
}
$handlerName = ucfirst($logger["handlers"][$doctrineHandler]["type"]);
$handlerClassName = sprintf('\Monolog\Handler\%sHandler', $handlerName);
if (!class_exists($handlerClassName))
{
throw new \Exception(sprintf('Unknow monolog handler class %s', $handlerClassName));
}
if (!isset($log["filename"]))
{
throw new \Exception('you must specify a file to write "filename: my_filename"');
}
$logPath = __DIR__ . '/../../../../../logs';
$file = sprintf('%s/%s', $logPath, $log["filename"]);
if ($doctrineHandler == 'rotate')
{
$maxDay = isset($log["max_day"]) ? (int) $log["max_day"] : (int) $logger["max_day"];
$handlerInstance = new $handlerClassName($file, $maxDay);
}
else
{
$handlerInstance = new $handlerClassName($file);
}
$monologLogger = new \Monolog\Logger('query-logger');
$monologLogger->pushHandler($handlerInstance);
if (isset($log["output"]))
{
$output = $log["output"];
}
elseif (isset($logger["output"]))
{
$output = $logger["output"];
}
else
{
$output = null;
}
if (null === $output)
{
$sqlLogger = new \Doctrine\Logger\MonologSQLLogger($monologLogger);
}
else
{
$sqlLogger = new \Doctrine\Logger\MonologSQLLogger($monologLogger, $output);
}
$config->setSQLLogger($sqlLogger);
break;
case 'echo':
default:
$config->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger);
break;
}
}
//set caches
$config->setMetadataCacheImpl($metaCache);
$config->setQueryCacheImpl($queryCache);
//define autoregeneration of proxies base on debug mode
$config->setAutoGenerateProxyClasses($debug);
$chainDriverImpl = new \Doctrine\ORM\Mapping\Driver\DriverChain(); $chainDriverImpl = new \Doctrine\ORM\Mapping\Driver\DriverChain();
@@ -52,21 +167,28 @@ class Doctrine
$config->setProxyNamespace('Proxies'); $config->setProxyNamespace('Proxies');
$dbalConf = isset($doctrineConfiguration["dbal"]) ? $doctrineConfiguration["dbal"] : false;
if (!$dbalConf)
{
// throw new Exception("Unable to read dbal configuration");
require __DIR__ . '/../../../../../config/connexion.inc'; require __DIR__ . '/../../../../../config/connexion.inc';
$connectionOptions = array( $dbalConf = array(
'dbname' => $dbname, 'dbname' => $dbname,
'user' => $user, 'user' => $user,
'password' => $password, 'password' => $password,
'host' => $hostname, 'host' => $hostname,
'driver' => 'pdo_mysql', 'driver' => 'pdo_mysql',
); );
}
$evm = new \Doctrine\Common\EventManager(); $evm = new \Doctrine\Common\EventManager();
$evm->addEventSubscriber(new \Gedmo\Timestampable\TimestampableListener()); $evm->addEventSubscriber(new \Gedmo\Timestampable\TimestampableListener());
$this->entityManager = \Doctrine\ORM\EntityManager::create($connectionOptions, $config, $evm); $this->entityManager = \Doctrine\ORM\EntityManager::create($dbalConf, $config, $evm);
$this->addTypes(); $this->addTypes();
@@ -98,6 +220,18 @@ class Doctrine
); );
$classLoader->register(); $classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader(
'Doctrine\Common\DataFixtures'
, realpath(__DIR__ . '/../../../../vendor/data-fixtures/lib')
);
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader(
'PhraseaFixture'
, realpath(__DIR__ . '/../../../../conf.d/')
);
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader( $classLoader = new \Doctrine\Common\ClassLoader(
'Doctrine\Common' 'Doctrine\Common'
, realpath(__DIR__ . '/../../../../vendor/doctrine2-orm/lib/vendor/doctrine-common/lib') , realpath(__DIR__ . '/../../../../vendor/doctrine2-orm/lib/vendor/doctrine-common/lib')
@@ -129,6 +263,20 @@ class Doctrine
$classLoader->register(); $classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader(
'Doctrine\Logger'
, realpath(__DIR__ . '/../../../../')
);
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader(
'Monolog'
, realpath(__DIR__ . '/../../../../vendor/Silex/vendor/monolog/src')
);
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader( $classLoader = new \Doctrine\Common\ClassLoader(
'Types' 'Types'
, realpath(__DIR__ . '/../../../../Doctrine') , realpath(__DIR__ . '/../../../../Doctrine')
@@ -164,4 +312,28 @@ class Doctrine
return; return;
} }
/**
* Return a cache object according to the $name
*
* @param type $cacheName
*/
private function getCache($cacheName = self::ARRAYCACHE)
{
switch ($cacheName)
{
case self::MEMCACHED:
$cache = new \Doctrine\Common\Cache\MemcacheCache();
break;
case self::APC:
$cache = new \Doctrine\Common\Cache\ApcCache();
break;
case self::ARRAYCACHE:
default:
$cache = new \Doctrine\Common\Cache\ArrayCache();
break;
}
return $cache;
}
} }