refactor & add new services

This commit is contained in:
Nicolas Le Goff
2012-01-11 12:17:29 +01:00
parent b8dd8d4e69
commit 69ac8aba99
7 changed files with 903 additions and 0 deletions

View File

@@ -0,0 +1,54 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2010 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Phrasea\Core\Service\Log\Doctrine;
use Alchemy\Phrasea\Core,
Alchemy\Phrasea\Core\Service,
Alchemy\Phrasea\Core\Service\ServiceAbstract,
Alchemy\Phrasea\Core\Service\ServiceInterface;
use Alchemy\Phrasea\Core\Service\Log\Monolog as ParentLog;
use Doctrine\Logger\MonologSQLLogger;
/**
*
* @package
* @license http://opensource.org/licenses/gpl-3.0 GPLv3
* @link www.phraseanet.com
*/
class Monolog extends ParentLog implements ServiceInterface
{
const JSON_OUTPUT = 'json';
const YAML_OUTPUT = 'yaml';
const VAR_DUMP_OUTPUT = 'normal';
protected $outputs = array(
self::JSON_OUTPUT, self::YAML_OUTPUT, self::VAR_DUMP_OUTPUT
);
public function getService()
{
$output = isset($this->options["output"]) ? $this->options["output"] : self::JSON_OUTPUT;
if (!in_array($output, $this->outputs))
{
throw new \Exception(sprintf('Unknow log output class %s', $output));
}
return new MonologSQLLogger($this->monolog, $output);
}
public function getType()
{
return 'doctrine_monolog';
}
}

View File

@@ -0,0 +1,48 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2010 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Phrasea\Core\Service\Log\Doctrine;
use Alchemy\Phrasea\Core,
Alchemy\Phrasea\Core\Service,
Alchemy\Phrasea\Core\Service\ServiceAbstract,
Alchemy\Phrasea\Core\Service\ServiceInterface;
use Doctrine\DBAL\Logging\EchoSQLLogger;
/**
*
* @package
* @license http://opensource.org/licenses/gpl-3.0 GPLv3
* @link www.phraseanet.com
*/
class Normal extends ServiceAbstract implements ServiceInterface
{
public function __construct($name, Array $options)
{
parent::__construct($name, $options);
}
public function getService()
{
return new EchoSQLLogger();
}
public function getType()
{
return 'echo';
}
public function getScope()
{
return 'log';
}
}

View File

@@ -0,0 +1,111 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2010 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Phrasea\Core\Service\Log;
use Alchemy\Phrasea\Core,
Alchemy\Phrasea\Core\Service,
Alchemy\Phrasea\Core\Service\ServiceAbstract,
Alchemy\Phrasea\Core\Service\ServiceInterface;
/**
*
* @package
* @license http://opensource.org/licenses/gpl-3.0 GPLv3
* @link www.phraseanet.com
*/
class Monolog extends ServiceAbstract implements ServiceInterface
{
const DEFAULT_MAX_DAY = 10;
protected $handlers = array(
'rotate' => 'RotatingFile'
,'stream' => 'Stream'
);
/**
*
* @var \Monolog\Logger
*/
protected $monolog;
public function __construct($name, Array $options)
{
parent::__construct($name, $options);
//defaut to main handler
$handler = isset($options["handler"]) ? $options["handler"] : false;
if (!$handler)
{
throw new \Exception("You must specify at least one monolog handler");
}
if (!array_key_exists($handler, $this->handlers))
{
throw new \Exception(sprintf('Unknow monolog handler %s'), $handlerType);
}
$handlerName = $this->handlers[$handler];
$handlerClassName = sprintf('\Monolog\Handler\%sHandler', $handlerName);
if (!class_exists($handlerClassName))
{
throw new \Exception(sprintf('Unknow monolog handler class %s', $handlerClassName));
}
if (!isset($options["filename"]))
{
throw new \Exception('you must specify a file to write "filename: my_filename"');
}
$logPath = __DIR__ . '/../../../../logs';
$file = sprintf('%s/%s', $logPath, $options["filename"]);
if ($handler == 'rotate')
{
$maxDay = isset($options["max_day"]) ? (int) $options["max_day"] : self::DEFAULT_MAX_DAY;
$handlerInstance = new $handlerClassName($file, $maxDay);
}
else
{
$handlerInstance = new $handlerClassName($file);
}
$channel = isset($options["channel"]) ? $options["channel"] : false;
$monologLogger = new \Monolog\Logger($channel);
$monologLogger->pushHandler($handlerInstance);
$this->monolog = $monologLogger;
}
public function getService()
{
return $this->monolog;
}
public function getType()
{
return 'monolog';
}
public function getScope()
{
return 'log';
}
}

View File

@@ -0,0 +1,370 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2010 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Phrasea\Core\Service\Orm;
use Alchemy\Phrasea\Core,
Alchemy\Phrasea\Core\Service,
Alchemy\Phrasea\Core\Service\ServiceAbstract,
Alchemy\Phrasea\Core\Service\ServiceInterface;
use Doctrine\DBAL\Types\Type,
Doctrine\Common\Cache\AbstractCache;
/**
*
* @package
* @license http://opensource.org/licenses/gpl-3.0 GPLv3
* @link www.phraseanet.com
*/
class Doctrine extends ServiceAbstract implements ServiceInterface
{
const MEMCACHED = 'memcached';
const ARRAYCACHE = 'array';
const APC = 'apc';
protected $outputs = array(
'json', 'yaml', 'normal'
);
protected $loggers = array(
'monolog', 'echo'
);
protected $entityManager;
public function __construct($name, Array $options = array())
{
parent::__construct($name, $options);
static::loadClasses();
$config = new \Doctrine\ORM\Configuration();
$handler = new Core\Configuration\Handler(
new Core\Configuration\Application(),
new Core\Configuration\Parser\Yaml()
);
$phraseaConfig = new Core\Configuration($handler);
/*
* debug mode
*/
$debug = isset($options["debug"]) ? : false;
/*
* doctrine cache
*/
$cache = isset($options["orm"]["cache"]) ? $options["orm"]["cache"] : false;
/*
* default query cache & meta chache
*/
$metaCache = $this->getCache();
$queryCache = $this->getCache();
//Handle logs
$logServiceName = isset($options["log"]) ? $options["log"] : false;
if ($logServiceName)
{
$serviceConf = $phraseaConfig->getService($logServiceName);
$this->handleLogs($config, $logServiceName, $serviceConf->all());
}
//handle cache
$this->handleCache($metaCache, $queryCache, $cache, $debug);
//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();
$driverYaml = new \Doctrine\ORM\Mapping\Driver\YamlDriver(
array(__DIR__ . '/../../../../../conf.d/Doctrine')
);
$chainDriverImpl->addDriver($driverYaml, 'Entities');
$chainDriverImpl->addDriver($driverYaml, 'Gedmo\Timestampable');
$config->setMetadataDriverImpl($chainDriverImpl);
$config->setProxyDir(realpath(__DIR__ . '/../../../../../Doctrine/Proxies'));
$config->setProxyNamespace('Proxies');
$connexion = isset($options["dbal"]) ? $options["dbal"] : false;
if(!$connexion)
{
throw new \Exception("Missing dbal connexion for doctrine");
}
try
{
$dbalConf = $phraseaConfig->getConnexion($connexion)->all();
}
catch(\Exception $e)
{
throw new \Exception(sprintf("Unable to read %s configuration", $connexion));
}
$evm = new \Doctrine\Common\EventManager();
$evm->addEventSubscriber(new \Gedmo\Timestampable\TimestampableListener());
$this->entityManager = \Doctrine\ORM\EntityManager::create($dbalConf, $config, $evm);
$this->addTypes();
return $this;
}
public function getEntityManager()
{
return $this->entityManager;
}
public function getVersion()
{
return \Doctrine\Common\Version::VERSION;
}
protected static function loadClasses()
{
require_once __DIR__ . '/../../../../../vendor/doctrine2-orm/lib/vendor/doctrine-common/lib/Doctrine/Common/ClassLoader.php';
$classLoader = new \Doctrine\Common\ClassLoader(
'Doctrine\ORM'
, realpath(__DIR__ . '/../../../../../vendor/doctrine2-orm/lib')
);
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader(
'Doctrine\DBAL'
, realpath(__DIR__ . '/../../../../../vendor/doctrine2-orm/lib/vendor/doctrine-dbal/lib')
);
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader(
'Doctrine\Common'
, realpath(__DIR__ . '/../../../../../vendor/doctrine2-orm/lib/vendor/doctrine-common/lib')
);
$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(
'Entities'
, realpath(__DIR__ . '/../../../../../Doctrine')
);
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader(
'Repositories'
, realpath(__DIR__ . '/../../../../../Doctrine')
);
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader(
'Proxies'
, realpath(__DIR__ . '/../../../../../Doctrine')
);
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader(
'Symfony'
, realpath(__DIR__ . '/../../../../../vendor/doctrine/orm/lib/vendor')
);
$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(
'Types'
, realpath(__DIR__ . '/../../../../../Doctrine')
);
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader(
'Gedmo'
, __DIR__ . "/../../../../../vendor/doctrine2-gedmo/lib"
);
$classLoader->register();
return;
}
protected function addTypes()
{
$platform = $this->entityManager->getConnection()->getDatabasePlatform();
if (!Type::hasType('blob'))
{
Type::addType('blob', 'Types\Blob');
}
if (!Type::hasType('enum'))
{
Type::addType('enum', 'Types\Enum');
}
if (!Type::hasType('longblob'))
{
Type::addType('longblob', 'Types\LongBlob');
}
if (!Type::hasType('varbinary'))
{
Type::addType('varbinary', 'Types\VarBinary');
}
$platform->registerDoctrineTypeMapping('enum', 'enum');
$platform->registerDoctrineTypeMapping('blob', 'blob');
$platform->registerDoctrineTypeMapping('longblob', 'longblob');
$platform->registerDoctrineTypeMapping('varbinary', 'varbinary');
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;
}
/**
* Handle Cache configuration
*
* @param AbstractCache $metaCache
* @param AbstractCache $queryCache
* @param type $cache
* @param type $debug
*/
private function handleCache(AbstractCache &$metaCache, AbstractCache &$queryCache, $cache, $debug)
{
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 configuration
*
* @param \Doctrine\ORM\Configuration $config
* @param type $log
* @param type $logger
*/
private function handleLogs(\Doctrine\ORM\Configuration &$config, $serviceName, Array $serviceConf)
{
$logType = $serviceConf['type'];
$logService = null;
switch ($logType)
{
case 'monolog':
$logService = Core\ServiceBuilder::build(
$serviceName
, Core\ServiceBuilder::LOG
, $logType
, $serviceConf['options']
, 'doctrine'
);
break;
case 'echo':
default:
$logService = Core\ServiceBuilder::build(
$serviceName
, Core\ServiceBuilder::LOG
, 'normal'
, array()
, 'doctrine'
);
break;
}
if ($logService instanceof Alchemy\Phrasea\Core\Service\ServiceAbstract)
{
$config->setSQLLogger($logService->getService());
}
}
public function getService()
{
return $this->entityManager;
}
public function getType()
{
return 'doctrine';
}
public function getScope()
{
return 'orm';
}
}

View File

@@ -0,0 +1,58 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2010 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Phrasea\Core\Service;
/**
*
* @package
* @license http://opensource.org/licenses/gpl-3.0 GPLv3
* @link www.phraseanet.com
*/
class ServiceAbstract
{
protected $name;
protected $options;
public function __construct($name, Array $options)
{
$this->name = $name;
$this->options = $options;
}
/**
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
*
* @return Array
*/
public function getOptions()
{
return $this->options;
}
/**
*
* @return string
*/
public function getVersion()
{
return 'Unknow';
}
}

View File

@@ -0,0 +1,32 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2010 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Phrasea\Core\Service;
/**
*
* @package
* @license http://opensource.org/licenses/gpl-3.0 GPLv3
* @link www.phraseanet.com
*/
interface ServiceInterface
{
public function getName();
public function getType();
public function getService();
public function getOptions();
public function getScope();
}

View File

@@ -0,0 +1,230 @@
<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2010 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Phrasea\Core\Service\TemplateEngine;
use Alchemy\Phrasea\Core,
Alchemy\Phrasea\Core\Service,
Alchemy\Phrasea\Core\Service\ServiceAbstract,
Alchemy\Phrasea\Core\Service\ServiceInterface;
class Twig extends ServiceAbstract implements ServiceInterface
{
/**
*
* @var \Twig_Environment
*/
protected $twig;
protected $templatesPath = array();
public function __construct($name, Array $options)
{
parent::__construct($name, $options);
$this->options = $this->resolveOptions($options);
$this->templatesPath = $this->resolvePaths();
try
{
$loader = new \Twig_Loader_Filesystem($this->templatesPath);
$this->twig = new \Twig_Environment($loader, $this->options);
$this->loadGlobals();
$this->loadExtensions();
$this->loadFilters();
}
catch (\Exception $e)
{
throw new \Exception(sprintf('Unable to load twig service %s', $e->getMessage()));
}
}
/**
* Load phraseanet global variable
* it' s like any other template variable,
* except that its available in all templates and macros
* @return void
*/
private function loadGlobals()
{
$appbox = \appbox::get_instance();
$session = $appbox->get_session();
$browser = \Browser::getInstance();
$registry = $appbox->get_registry();
$request = new \http_request();
$user = false;
if ($session->is_authenticated())
{
$user = \User_Adapter::getInstance($session->get_usr_id(), $appbox);
}
$core = \bootstrap::getCore();
$eventsmanager = \eventsmanager_broker::getInstance($appbox, $core);
$this->twig->addGlobal('session', $session);
$this->twig->addGlobal('version_number', $core->getVersion()->getNumber());
$this->twig->addGlobal('version_name', $core->getVersion()->getName());
$this->twig->addGlobal('core', $core);
$this->twig->addGlobal('browser', $browser);
$this->twig->addGlobal('request', $request);
$this->twig->addGlobal('events', $eventsmanager);
$this->twig->addGlobal('display_chrome_frame', $registry->is_set('GV_display_gcf') ? $registry->get('GV_display_gcf') : true);
$this->twig->addGlobal('user', $user);
$this->twig->addGlobal('current_date', new \DateTime());
$this->twig->addGlobal('home_title', $registry->get('GV_homeTitle'));
$this->twig->addGlobal('meta_description', $registry->get('GV_metaDescription'));
$this->twig->addGlobal('meta_keywords', $registry->get('GV_metaKeywords'));
$this->twig->addGlobal('maintenance', $registry->get('GV_maintenance'));
$this->twig->addGlobal('registry', $registry);
}
/**
* Load twig extensions
* @return void
*/
private function loadExtensions()
{
$this->twig->addExtension(new \Twig_Extension_Core());
$this->twig->addExtension(new \Twig_Extension_Optimizer());
$this->twig->addExtension(new \Twig_Extension_Escaper());
$this->twig->addExtension(new \Twig_Extensions_Extension_Debug());
// add filter trans
$this->twig->addExtension(new \Twig_Extensions_Extension_I18n());
// add filter localizeddate
$this->twig->addExtension(new \Twig_Extensions_Extension_Intl());
// add filters truncate, wordwrap, nl2br
$this->twig->addExtension(new \Twig_Extensions_Extension_Text());
}
/**
* Load twig filters
* return void
*/
private function loadFilters()
{
$this->twig->addFilter('serialize', new \Twig_Filter_Function('serialize'));
$this->twig->addFilter('sbas_names', new \Twig_Filter_Function('phrasea::sbas_names'));
$this->twig->addFilter('sbas_name', new \Twig_Filter_Function('phrasea::sbas_names'));
$this->twig->addFilter('unite', new \Twig_Filter_Function('p4string::format_octets'));
$this->twig->addFilter('stristr', new \Twig_Filter_Function('stristr'));
$this->twig->addFilter('implode', new \Twig_Filter_Function('implode'));
$this->twig->addFilter('stripdoublequotes', new \Twig_Filter_Function('stripdoublequotes'));
$this->twig->addFilter('phraseadate', new \Twig_Filter_Function('phraseadate::getPrettyString'));
$this->twig->addFilter('format_octets', new \Twig_Filter_Function('p4string::format_octets'));
$this->twig->addFilter('geoname_display', new \Twig_Filter_Function('geonames::name_from_id'));
$this->twig->addFilter('get_collection_logo', new \Twig_Filter_Function('collection::getLogo'));
$this->twig->addFilter('nl2br', new \Twig_Filter_Function('nl2br'));
$this->twig->addFilter('floor', new \Twig_Filter_Function('floor'));
$this->twig->addFilter('bas_name', new \Twig_Filter_Function('phrasea::bas_names'));
$this->twig->addFilter('bas_names', new \Twig_Filter_Function('phrasea::bas_names'));
$this->twig->addFilter('basnames', new \Twig_Filter_Function('phrasea::bas_names'));
$this->twig->addFilter('urlencode', new \Twig_Filter_Function('urlencode'));
$this->twig->addFilter('sbasFromBas', new \Twig_Filter_Function('phrasea::sbasFromBas'));
$this->twig->addFilter('str_replace', new \Twig_Filter_Function('str_replace'));
$this->twig->addFilter('strval', new \Twig_Filter_Function('strval'));
$this->twig->addFilter('key_exists', new \Twig_Filter_Function('array_key_exists'));
$this->twig->addFilter('array_keys', new \Twig_Filter_Function('array_keys'));
$this->twig->addFilter('round', new \Twig_Filter_Function('round'));
$this->twig->addFilter('formatdate', new \Twig_Filter_Function('phraseadate::getDate'));
$this->twig->addFilter('getPrettyDate', new \Twig_Filter_Function('phraseadate::getPrettyString'));
$this->twig->addFilter('prettyDate', new \Twig_Filter_Function('phraseadate::getPrettyString'));
$this->twig->addFilter('prettyString', new \Twig_Filter_Function('phraseadate::getPrettyString'));
$this->twig->addFilter('formatoctet', new \Twig_Filter_Function('p4string::format_octets'));
$this->twig->addFilter('getDate', new \Twig_Filter_Function('phraseadate::getDate'));
$this->twig->addFilter('geoname_name_from_id', new \Twig_Filter_Function('geonames::name_from_id'));
}
/**
* Getter
* @return \Twig_Environment
*/
public function getTwig()
{
return $this->twig;
}
private function getDefaultTemplatePath()
{
$registry = \registry::get_instance();
return array(
'mobile' => array(
$registry->get('GV_RootPath') . 'config/templates/mobile',
$registry->get('GV_RootPath') . 'templates/mobile'
),
'web' => array(
$registry->get('GV_RootPath') . 'config/templates/web',
$registry->get('GV_RootPath') . 'templates/web'
)
);
}
/**
* Set default templates Path
* According to the client device
* @return void
*/
private function resolvePaths()
{
$browser = \Browser::getInstance();
$templatePath = $this->getDefaultTemplatePath();
if ($browser->isTablet() || $browser->isMobile())
{
$paths = $templatePath['mobile'];
}
else
{
$paths = $templatePath['web'];
}
return $paths;
}
/**
* Set configuration options
* @param array $configuration
* @return Array
*/
private function resolveOptions(Array $configuration)
{
$registry = \registry::get_instance();
$options = $configuration;
$options["optimizer"] = !!$options["optimizer"] ? -1 : 0;
$options['cache'] = $registry->get('GV_RootPath') . 'tmp/cache_twig';
$options['charset'] = 'utf-8';
if (!!$options["debug"])
{
unset($options["cache"]);
}
return $options;
}
public function getService()
{
return $this->twig;
}
public function getType()
{
return 'twig';
}
public function getScope()
{
return 'template_engine';
}
}