From 69ac8aba99c54e4a3f4a1e7ec10c40d21dece4ea Mon Sep 17 00:00:00 2001 From: Nicolas Le Goff Date: Wed, 11 Jan 2012 12:17:29 +0100 Subject: [PATCH] refactor & add new services --- .../Core/Service/Log/Doctrine/Monolog.php | 54 +++ .../Core/Service/Log/Doctrine/Normal.php | 48 +++ .../Phrasea/Core/Service/Log/Monolog.php | 111 ++++++ .../Phrasea/Core/Service/Orm/Doctrine.php | 370 ++++++++++++++++++ .../Phrasea/Core/Service/ServiceAbstract.php | 58 +++ .../Phrasea/Core/Service/ServiceInterface.php | 32 ++ .../Core/Service/TemplateEngine/Twig.php | 230 +++++++++++ 7 files changed, 903 insertions(+) create mode 100644 lib/Alchemy/Phrasea/Core/Service/Log/Doctrine/Monolog.php create mode 100644 lib/Alchemy/Phrasea/Core/Service/Log/Doctrine/Normal.php create mode 100644 lib/Alchemy/Phrasea/Core/Service/Log/Monolog.php create mode 100644 lib/Alchemy/Phrasea/Core/Service/Orm/Doctrine.php create mode 100644 lib/Alchemy/Phrasea/Core/Service/ServiceAbstract.php create mode 100644 lib/Alchemy/Phrasea/Core/Service/ServiceInterface.php create mode 100644 lib/Alchemy/Phrasea/Core/Service/TemplateEngine/Twig.php diff --git a/lib/Alchemy/Phrasea/Core/Service/Log/Doctrine/Monolog.php b/lib/Alchemy/Phrasea/Core/Service/Log/Doctrine/Monolog.php new file mode 100644 index 0000000000..7a4044b2a4 --- /dev/null +++ b/lib/Alchemy/Phrasea/Core/Service/Log/Doctrine/Monolog.php @@ -0,0 +1,54 @@ +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'; + } + +} \ No newline at end of file diff --git a/lib/Alchemy/Phrasea/Core/Service/Log/Doctrine/Normal.php b/lib/Alchemy/Phrasea/Core/Service/Log/Doctrine/Normal.php new file mode 100644 index 0000000000..b4b74806e4 --- /dev/null +++ b/lib/Alchemy/Phrasea/Core/Service/Log/Doctrine/Normal.php @@ -0,0 +1,48 @@ + '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'; + } + +} + diff --git a/lib/Alchemy/Phrasea/Core/Service/Orm/Doctrine.php b/lib/Alchemy/Phrasea/Core/Service/Orm/Doctrine.php new file mode 100644 index 0000000000..1ea01b3b8c --- /dev/null +++ b/lib/Alchemy/Phrasea/Core/Service/Orm/Doctrine.php @@ -0,0 +1,370 @@ +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'; + } + +} \ No newline at end of file diff --git a/lib/Alchemy/Phrasea/Core/Service/ServiceAbstract.php b/lib/Alchemy/Phrasea/Core/Service/ServiceAbstract.php new file mode 100644 index 0000000000..3900d5c6fc --- /dev/null +++ b/lib/Alchemy/Phrasea/Core/Service/ServiceAbstract.php @@ -0,0 +1,58 @@ +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'; + } +} \ No newline at end of file diff --git a/lib/Alchemy/Phrasea/Core/Service/ServiceInterface.php b/lib/Alchemy/Phrasea/Core/Service/ServiceInterface.php new file mode 100644 index 0000000000..0189b5ab23 --- /dev/null +++ b/lib/Alchemy/Phrasea/Core/Service/ServiceInterface.php @@ -0,0 +1,32 @@ +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 it’s 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'; + } + +} \ No newline at end of file