diff --git a/bin/doctrine b/bin/doctrine index a376777853..bf5c59b5cd 100755 --- a/bin/doctrine +++ b/bin/doctrine @@ -28,6 +28,7 @@ require_once dirname(__FILE__) . '/../lib/Alchemy/Phrasea/Core/Service/Doctrine. try { + $doctrineConf = array(); $doctrine = new Phrasea\Core\Service\Doctrine(); $app = new Application("Phraseanet Doctrine Console", $doctrine->getVersion()); diff --git a/lib/Alchemy/Phrasea/Core.php b/lib/Alchemy/Phrasea/Core.php index 8bd113965d..670a6b6806 100644 --- a/lib/Alchemy/Phrasea/Core.php +++ b/lib/Alchemy/Phrasea/Core.php @@ -58,7 +58,7 @@ class Core extends \Pimple $conf = $this->conf; $this['EM'] = $this->share(function() use ($conf) { - $doctrine = new Core\Service\Doctrine($conf->getDbalConf()); + $doctrine = new Core\Service\Doctrine($conf->getDoctrine()); return $doctrine->getEntityManager(); }); diff --git a/lib/Alchemy/Phrasea/Core/Configuration.php b/lib/Alchemy/Phrasea/Core/Configuration.php index 2d2ad729bc..b5019f4ae4 100644 --- a/lib/Alchemy/Phrasea/Core/Configuration.php +++ b/lib/Alchemy/Phrasea/Core/Configuration.php @@ -11,6 +11,9 @@ namespace Alchemy\Phrasea\Core; +use Alchemy\Phrasea\Core\Configuration\Application; +use Alchemy\Phrasea\Core\Configuration\Parser as ConfigurationParser; + /** * Handle configuration file mechanism of phraseanet * @@ -20,25 +23,43 @@ namespace Alchemy\Phrasea\Core; */ class Configuration { - const MAIN_ENV_NAME = "main"; - + /** * The environnment name * @var string */ protected $environnement; - + /** - * The configuration + * The finale configuration values as an array * @var Array */ - protected $configuration; - + protected $configuration = array(); + /** * Tell if appli is currently installed * @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) { - //check whether the main configuration file is present on disk - 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; - } - + $this->init($envName); + } + + /** + * 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 */ - 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; } - 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 Array|null */ public function getConfiguration() @@ -114,5 +219,61 @@ class 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); + } + } } \ No newline at end of file diff --git a/lib/Alchemy/Phrasea/Core/Configuration/PhraseaConfiguration.php b/lib/Alchemy/Phrasea/Core/Configuration/Application.php similarity index 80% rename from lib/Alchemy/Phrasea/Core/Configuration/PhraseaConfiguration.php rename to lib/Alchemy/Phrasea/Core/Configuration/Application.php index 204d6547cd..5625552aea 100644 --- a/lib/Alchemy/Phrasea/Core/Configuration/PhraseaConfiguration.php +++ b/lib/Alchemy/Phrasea/Core/Configuration/Application.php @@ -18,7 +18,7 @@ namespace Alchemy\Phrasea\Core\Configuration; * @license http://opensource.org/licenses/gpl-3.0 GPLv3 * @link www.phraseanet.com */ -class PhraseaConfiguration implements ConfigurationSpecification +class Application implements Specification { /** @@ -38,7 +38,12 @@ class PhraseaConfiguration implements ConfigurationSpecification */ 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() , $name , $this->getConfFileExtension()) @@ -53,6 +58,12 @@ class PhraseaConfiguration implements ConfigurationSpecification { return __DIR__ . '/../../../../../config'; } + + public function getMainFile() + { + $path = __DIR__ . '/../../../../../config/config.yml'; + return new \SplFileObject($path); + } /** * diff --git a/lib/Alchemy/Phrasea/Core/Configuration/EnvironnementHandler.php b/lib/Alchemy/Phrasea/Core/Configuration/Handler.php similarity index 96% rename from lib/Alchemy/Phrasea/Core/Configuration/EnvironnementHandler.php rename to lib/Alchemy/Phrasea/Core/Configuration/Handler.php index 3bee323db5..6ca9182a86 100644 --- a/lib/Alchemy/Phrasea/Core/Configuration/EnvironnementHandler.php +++ b/lib/Alchemy/Phrasea/Core/Configuration/Handler.php @@ -20,7 +20,7 @@ use \Symfony\Component\Yaml\Yaml; * @license http://opensource.org/licenses/gpl-3.0 GPLv3 * @link www.phraseanet.com */ -class EnvironnementHandler +class Handler { /** * Configuration file specification interface @@ -40,7 +40,7 @@ class EnvironnementHandler * @param ConfigurationSpecification $configSpec * @param Parser\ParserInterface $parser */ - public function __construct(ConfigurationSpecification $configSpec, Parser\ParserInterface $parser) + public function __construct(Application $configSpec, Parser $parser) { $this->confSpecification = $configSpec; $this->parser = $parser; @@ -74,7 +74,7 @@ class EnvironnementHandler } catch (\Exception $e) { - throw \Exception(sprintf("filename %s not found", $file->getPathname())); + throw new \Exception(sprintf("filename %s not found", $file->getPathname())); } } else diff --git a/lib/Alchemy/Phrasea/Core/Configuration/Parser/ParserInterface.php b/lib/Alchemy/Phrasea/Core/Configuration/Parser.php similarity index 87% rename from lib/Alchemy/Phrasea/Core/Configuration/Parser/ParserInterface.php rename to lib/Alchemy/Phrasea/Core/Configuration/Parser.php index 441c51c885..f55c69131c 100644 --- a/lib/Alchemy/Phrasea/Core/Configuration/Parser/ParserInterface.php +++ b/lib/Alchemy/Phrasea/Core/Configuration/Parser.php @@ -9,7 +9,7 @@ * 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 @@ -18,7 +18,7 @@ namespace Alchemy\Phrasea\Core\Configuration\Parser; * @license http://opensource.org/licenses/gpl-3.0 GPLv3 * @link www.phraseanet.com */ -interface ParserInterface +interface Parser { /** * Parse the configuration file $file to an array diff --git a/lib/Alchemy/Phrasea/Core/Configuration/Parser/Yaml.php b/lib/Alchemy/Phrasea/Core/Configuration/Parser/Yaml.php index 4d3feb0958..d461022d50 100644 --- a/lib/Alchemy/Phrasea/Core/Configuration/Parser/Yaml.php +++ b/lib/Alchemy/Phrasea/Core/Configuration/Parser/Yaml.php @@ -19,7 +19,7 @@ use Symfony\Component\Yaml\Yaml as SfYaml; * @license http://opensource.org/licenses/gpl-3.0 GPLv3 * @link www.phraseanet.com */ -class Yaml implements ParserInterface +class Yaml implements \Alchemy\Phrasea\Core\Configuration\Parser { /** * diff --git a/lib/Alchemy/Phrasea/Core/Configuration/ConfigurationSpecification.php b/lib/Alchemy/Phrasea/Core/Configuration/Specification.php similarity index 94% rename from lib/Alchemy/Phrasea/Core/Configuration/ConfigurationSpecification.php rename to lib/Alchemy/Phrasea/Core/Configuration/Specification.php index ab25fa1f34..7f241a7893 100644 --- a/lib/Alchemy/Phrasea/Core/Configuration/ConfigurationSpecification.php +++ b/lib/Alchemy/Phrasea/Core/Configuration/Specification.php @@ -18,12 +18,16 @@ namespace Alchemy\Phrasea\Core\Configuration; * @license http://opensource.org/licenses/gpl-3.0 GPLv3 * @link www.phraseanet.com */ -interface ConfigurationSpecification +interface Specification { /** * Keywords to detect extended file */ 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 diff --git a/lib/Alchemy/Phrasea/Core/Service/Doctrine.php b/lib/Alchemy/Phrasea/Core/Service/Doctrine.php index 425f9dc874..af0e432c1c 100644 --- a/lib/Alchemy/Phrasea/Core/Service/Doctrine.php +++ b/lib/Alchemy/Phrasea/Core/Service/Doctrine.php @@ -9,7 +9,6 @@ * file that was distributed with this source code. */ - namespace Alchemy\Phrasea\Core\Service; use Doctrine\DBAL\Types\Type; @@ -22,19 +21,135 @@ use Doctrine\DBAL\Types\Type; */ class Doctrine { + const MEMCACHED = 'memcached'; + const ARRAYCACHE = 'array'; + const APC = 'apc'; 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'; static::loadClasses(); $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(); @@ -52,24 +167,31 @@ class Doctrine $config->setProxyNamespace('Proxies'); - require __DIR__ . '/../../../../../config/connexion.inc'; + $dbalConf = isset($doctrineConfiguration["dbal"]) ? $doctrineConfiguration["dbal"] : false; - $connectionOptions = array( - 'dbname' => $dbname, - 'user' => $user, - 'password' => $password, - 'host' => $hostname, - 'driver' => 'pdo_mysql', - ); + if (!$dbalConf) + { +// throw new Exception("Unable to read dbal configuration"); + + require __DIR__ . '/../../../../../config/connexion.inc'; + + $dbalConf = array( + 'dbname' => $dbname, + 'user' => $user, + 'password' => $password, + 'host' => $hostname, + 'driver' => 'pdo_mysql', + ); + } $evm = new \Doctrine\Common\EventManager(); $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(); - + return $this; } @@ -77,7 +199,7 @@ class Doctrine { return $this->entityManager; } - + public function getVersion() { return \Doctrine\Common\Version::VERSION; @@ -98,6 +220,18 @@ class Doctrine ); $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( 'Doctrine\Common' , realpath(__DIR__ . '/../../../../vendor/doctrine2-orm/lib/vendor/doctrine-common/lib') @@ -121,19 +255,33 @@ class Doctrine , realpath(__DIR__ . '/../../../../Doctrine') ); $classLoader->register(); - + $classLoader = new \Doctrine\Common\ClassLoader( 'Symfony' , realpath(__DIR__ . '/../../../../vendor/doctrine2-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( @@ -145,23 +293,47 @@ class Doctrine return; } - + protected function addTypes() { - + $platform = $this->entityManager->getConnection()->getDatabasePlatform(); - + Type::addType('blob', 'Types\Blob'); Type::addType('enum', 'Types\Enum'); Type::addType('longblob', 'Types\LongBlob'); 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; + } + } \ No newline at end of file diff --git a/lib/Doctrine/Entities/ValidationParticipant.php b/lib/Doctrine/Entities/ValidationParticipant.php index 654cac9a99..d021731b50 100644 --- a/lib/Doctrine/Entities/ValidationParticipant.php +++ b/lib/Doctrine/Entities/ValidationParticipant.php @@ -38,7 +38,7 @@ class ValidationParticipant /** * @var datetime $reminded */ - private $reminded = false; + private $reminded = null; /** * @var Entities\ValidationData diff --git a/lib/Doctrine/Proxies/EntitiesBasketProxy.php b/lib/Doctrine/Proxies/EntitiesBasketProxy.php index 99fbd0491a..1ed363229c 100644 --- a/lib/Doctrine/Proxies/EntitiesBasketProxy.php +++ b/lib/Doctrine/Proxies/EntitiesBasketProxy.php @@ -192,6 +192,12 @@ class EntitiesBasketProxy extends \Entities\Basket implements \Doctrine\ORM\Prox return parent::hasRecord($record); } + public function getSize() + { + $this->__load(); + return parent::getSize(); + } + public function __sleep() { diff --git a/lib/Doctrine/Repositories/BasketElementRepository.php b/lib/Doctrine/Repositories/BasketElementRepository.php index fb3c33d40c..d52614f9dc 100644 --- a/lib/Doctrine/Repositories/BasketElementRepository.php +++ b/lib/Doctrine/Repositories/BasketElementRepository.php @@ -37,7 +37,7 @@ class BasketElementRepository extends EntityRepository $params = array( 'sbas_id' => $record->get_sbas_id(), - 'record_id' => $record_id->get_record_id() + 'record_id' => $record->get_record_id() ); $query = $this->_em->createQuery($dql); @@ -52,7 +52,7 @@ class BasketElementRepository extends EntityRepository * @param \User_Adapter $user * @return \Entities\BasketELement */ - public function findUserElement($element_id, \User_Adapter $user) + public function findElement($element_id, \User_Adapter $user) { $element = $this->find($element_id); diff --git a/lib/conf.d/PhraseaFixture/Basket/LoadOneBasketEnv.php b/lib/conf.d/PhraseaFixture/Basket/LoadOneBasketEnv.php index d28efd4d07..187be190ad 100644 --- a/lib/conf.d/PhraseaFixture/Basket/LoadOneBasketEnv.php +++ b/lib/conf.d/PhraseaFixture/Basket/LoadOneBasketEnv.php @@ -104,7 +104,7 @@ class LoadOneBasketEnv extends \PhraseaFixture\AbstractWZ implements FixtureInte { $validationParticipant = new \Entities\ValidationParticipant(); - $validationParticipant->setParticipant($participant); + $validationParticipant->setUser($participant); $validationParticipant->setSession($validationSession); diff --git a/lib/conf.d/PhraseaFixture/ValidationParticipant/LoadParticipantWithSession.php b/lib/conf.d/PhraseaFixture/ValidationParticipant/LoadParticipantWithSession.php index 13a11a0078..a4ca44b00a 100644 --- a/lib/conf.d/PhraseaFixture/ValidationParticipant/LoadParticipantWithSession.php +++ b/lib/conf.d/PhraseaFixture/ValidationParticipant/LoadParticipantWithSession.php @@ -43,7 +43,7 @@ class LoadParticipantWithSession extends \PhraseaFixture\AbstractWZ implements F { throw new \LogicException('Fill a user to store a new validation Session'); } - $validationParticipant->setParticipant($this->user); + $validationParticipant->setUser($this->user); if (null === $this->session) { diff --git a/lib/unitTest/Controller/Prod/WorkZoneTest.php b/lib/unitTest/Controller/Prod/WorkZoneTest.php index 023e708654..86ef35951d 100644 --- a/lib/unitTest/Controller/Prod/WorkZoneTest.php +++ b/lib/unitTest/Controller/Prod/WorkZoneTest.php @@ -11,7 +11,6 @@ require_once __DIR__ . '/../../PhraseanetWebTestCaseAuthenticatedAbstract.class.inc'; -use Doctrine\Common\DataFixtures\Loader; use Alchemy\Phrasea\Helper; use Alchemy\Phrasea\RouteProcessor as routeProcessor; @@ -31,6 +30,7 @@ class WorkZoneTest extends PhraseanetWebTestCaseAuthenticatedAbstract { parent::setUp(); $this->client = $this->createClient(); + $this->purgeDatabase(); } public function createApplication() @@ -41,7 +41,7 @@ class WorkZoneTest extends PhraseanetWebTestCaseAuthenticatedAbstract public function testRootGet() { - $this->loadOneWZ(); + $this->insertOneWZ(); $route = "/WorkZone/"; @@ -52,45 +52,4 @@ class WorkZoneTest extends PhraseanetWebTestCaseAuthenticatedAbstract $this->assertEquals(200, $response->getStatusCode()); } - protected function loadOneWZ() - { - try - { - $currentUser = self::$user; - $altUser = self::$user_alt1; - //add one basket - $basket = new PhraseaFixture\Basket\LoadOneBasket(); - $basket->setUser($currentUser); - //add one story - $story = new PhraseaFixture\Story\LoadOneStory(); - $story->setUser($currentUser); - $story->setRecord(self::$record_1); - //add a validation session initiated by alt user - $validationSession = new PhraseaFixture\ValidationSession\LoadOneValidationSession(); - $validationSession->setUser($altUser); - - $loader = new Loader(); - $loader->addFixture($basket); - $loader->addFixture($story); - $loader->addFixture($validationSession); - - $this->insertFixtureInDatabase($loader); - - //add current user as participant - $validationParticipant = new PhraseaFixture\ValidationParticipant\LoadParticipantWithSession(); - $validationParticipant->setSession($validationSession->validationSession); - $validationParticipant->setUser($currentUser); - - $loader = new Loader(); - $loader->addFixture($validationParticipant); - $this->insertFixtureInDatabase($loader); - } - catch (\Exception $e) - { - $this->fail($e->getMessage()); - } - - return; - } - } \ No newline at end of file diff --git a/lib/unitTest/Controller/Prod/basketTest.php b/lib/unitTest/Controller/Prod/basketTest.php index 65fbf08a78..69a215dc62 100644 --- a/lib/unitTest/Controller/Prod/basketTest.php +++ b/lib/unitTest/Controller/Prod/basketTest.php @@ -11,8 +11,6 @@ require_once __DIR__ . '/../../PhraseanetWebTestCaseAuthenticatedAbstract.class.inc'; -use Doctrine\Common\DataFixtures\Loader; -use PhraseaFixture\Basket as MyFixture; use Alchemy\Phrasea\Helper; use Alchemy\Phrasea\RouteProcessor as routeProcessor; @@ -26,14 +24,13 @@ class basketTest extends PhraseanetWebTestCaseAuthenticatedAbstract { protected $client; - protected $loader; protected static $need_records = 2; public function setUp() { parent::setUp(); $this->client = $this->createClient(); - $this->loader = new Loader(); + $this->purgeDatabase(); } public function createApplication() @@ -161,7 +158,7 @@ class basketTest extends PhraseanetWebTestCaseAuthenticatedAbstract $em->flush(); $route = sprintf( - "/baskets/%s/%s/delete/", $basket->getId(), $basket_element->getId() + "/baskets/%s/delete/%s/", $basket->getId(), $basket_element->getId() ); $crawler = $this->client->request('POST', $route); @@ -199,7 +196,7 @@ class basketTest extends PhraseanetWebTestCaseAuthenticatedAbstract $em->flush(); $route = sprintf( - "/baskets/%s/%s/delete/", $basket->getId(), $basket_element->getId() + "/baskets/%s/delete/%s/", $basket->getId(), $basket_element->getId() ); $crawler = $this->client->request( @@ -498,11 +495,11 @@ class basketTest extends PhraseanetWebTestCaseAuthenticatedAbstract */ public function testRemoveBasket() { - $this->insertOneBasketEnv(); + $basket = $this->insertOneBasketEnv(); $em = self::$core->getEntityManager(); /* @var $em \Doctrine\ORM\EntityManager */ - $basket = $em->find("Entities\Basket", 1); + $basket = $em->find("Entities\Basket", $basket->getId()); $em->remove($basket); @@ -542,79 +539,4 @@ class basketTest extends PhraseanetWebTestCaseAuthenticatedAbstract $this->assertEquals(0, $count); } - /** - * - * @return \Entities\Basket - */ - protected function insertOneBasket() - { - $basketFixture = new MyFixture\LoadOneBasket(); - - $basketFixture->setUser(self::$user); - - $this->loader->addFixture($basketFixture); - - $this->insertFixtureInDatabase($this->loader); - - $query = self::$core->getEntityManager()->createQuery( - 'SELECT COUNT(b.id) FROM \Entities\Basket b' - ); - - $count = $query->getSingleScalarResult(); - - $this->assertEquals(1, $count); - - return $basketFixture->basket; - } - - /** - * - * @return \Entities\Basket - */ - protected function insertOneBasketEnv() - { - $em = self::$core->getEntityManager(); - /* @var $em \Doctrine\ORM\EntityManager */ - - $basketFixture = new MyFixture\LoadOneBasketEnv(); - - $basketFixture->setUser(self::$user); - - $basketFixture->addParticipant(self::$user_alt1); - $basketFixture->addParticipant(self::$user_alt2); - - $basketFixture->addBasketElement(self::$record_1); - $basketFixture->addBasketElement(self::$record_2); - - $this->loader->addFixture($basketFixture); - - $this->insertFixtureInDatabase($this->loader); - - $query = $em->createQuery( - 'SELECT COUNT(b.id) FROM \Entities\Basket b' - ); - - $count = $query->getSingleScalarResult(); - - $this->assertEquals(1, $count); - - $query = $em->createQuery( - 'SELECT COUNT(v.id) FROM \Entities\ValidationParticipant v' - ); - - $count = $query->getSingleScalarResult(); - - $this->assertEquals(2, $count); - - $query = $em->createQuery( - 'SELECT COUNT(v.id) FROM \Entities\ValidationSession v' - ); - - $count = $query->getSingleScalarResult(); - - $this->assertEquals(1, $count); - - return $basketFixture->basket; - } - } \ No newline at end of file diff --git a/lib/unitTest/Controller/Prod/storyTest.php b/lib/unitTest/Controller/Prod/storyTest.php index a85608858b..27cd6712cf 100644 --- a/lib/unitTest/Controller/Prod/storyTest.php +++ b/lib/unitTest/Controller/Prod/storyTest.php @@ -26,20 +26,19 @@ class storyTest extends PhraseanetWebTestCaseAuthenticatedAbstract { protected $client; - protected $loader; /** * * @var \record_adapter */ - protected static $story; + protected static $need_story = true; protected static $need_records = 2; public function setUp() { parent::setUp(); $this->client = $this->createClient(); - $this->loader = new Loader(); + $this->purgeDatabase(); } public function createApplication() @@ -47,14 +46,6 @@ class storyTest extends PhraseanetWebTestCaseAuthenticatedAbstract return require __DIR__ . '/../../../Alchemy/Phrasea/Application/Prod.php'; } - public static function tearDownAfterClass() - { - if (self::$story instanceof \record_adapter) - { - self::$story->delete(); - } - } - public function testRootPost() { $route = "/story/"; @@ -133,7 +124,7 @@ class storyTest extends PhraseanetWebTestCaseAuthenticatedAbstract public function testByIds() { - $story = $this->getStory(); + $story = self::$story_1; $route = sprintf("/story/%d/%d/", $story->get_sbas_id(), $story->get_record_id()); @@ -146,7 +137,7 @@ class storyTest extends PhraseanetWebTestCaseAuthenticatedAbstract public function testAddElementsToStory() { - $story = $this->getStory(); + $story = self::$story_1; $route = sprintf("/story/%s/%s/addElements/", $story->get_sbas_id(), $story->get_record_id()); @@ -163,12 +154,12 @@ class storyTest extends PhraseanetWebTestCaseAuthenticatedAbstract $this->assertEquals(302, $response->getStatusCode()); - $this->assertEquals(2, self::$story->get_children()->get_count()); + $this->assertEquals(2, self::$story_1->get_children()->get_count()); } public function testAddElementsToStoryJSON() { - $story = $this->getStory(); + $story = self::$story_1; $route = sprintf("/story/%s/%s/addElements/", $story->get_sbas_id(), $story->get_record_id()); @@ -187,12 +178,12 @@ class storyTest extends PhraseanetWebTestCaseAuthenticatedAbstract $this->assertEquals(200, $response->getStatusCode()); - $this->assertEquals(2, self::$story->get_children()->get_count()); + $this->assertEquals(2, self::$story_1->get_children()->get_count()); } public function testRemoveElementFromStory() { - $story = $this->getStory(); + $story = self::$story_1; $records = array( self::$record_1, @@ -232,13 +223,13 @@ class storyTest extends PhraseanetWebTestCaseAuthenticatedAbstract } $n++; - $this->assertEquals($totalRecords - $n, self::$story->get_children()->get_count()); + $this->assertEquals($totalRecords - $n, self::$story_1->get_children()->get_count()); } } public function testAttachStoryToWZ() { - $story = $this->getStory(); + $story = self::$story_1; $goodRoute = sprintf("/story/%s/%s/attach/", $story->get_sbas_id(), $story->get_record_id()); $badRoute = sprintf("/story/%s/%s/attach/", self::$record_1->get_base_id(), self::$record_1->get_record_id()); @@ -297,7 +288,7 @@ class storyTest extends PhraseanetWebTestCaseAuthenticatedAbstract public function testDetachStoryFromWZ() { - $story = $this->getStory(); + $story = self::$story_1; $route = sprintf("/story/%s/%s/detach/", $story->get_sbas_id(), $story->get_record_id()); //story not yet Attched @@ -350,43 +341,5 @@ class storyTest extends PhraseanetWebTestCaseAuthenticatedAbstract $this->assertEquals(200, $response->getStatusCode()); } - /** - * @return \record_adapter - */ - protected function getStory() - { - if (self::$story instanceof \record_adapter) - return self::$story; - - $collections = self::$core->getAuthenticatedUser() - ->ACL() - ->get_granted_base(array('canaddrecord')); - - $collection = array_shift($collections); - - $crawler = $this->client->request( - 'POST', '/story/', array( - 'base_id' => $collection->get_base_id(), - 'name' => 'test story', - 'description' => 'test_description'), array(), array( - "HTTP_ACCEPT" => "application/json") - ); - - $response = $this->client->getResponse(); - - $response = json_decode($response->getContent()); - - if (!$response->success) - { - $this->fail("Cannot create story"); - } - - $sbasId = $response->story->sbas_id; - $recordId = $response->story->record_id; - - self::$story = new \record_adapter($sbasId, $recordId); - - return self::$story; - } - + } \ No newline at end of file diff --git a/lib/unitTest/PhraseanetPHPUnitAbstract.class.inc b/lib/unitTest/PhraseanetPHPUnitAbstract.class.inc index c77dfeac4a..0563817ced 100644 --- a/lib/unitTest/PhraseanetPHPUnitAbstract.class.inc +++ b/lib/unitTest/PhraseanetPHPUnitAbstract.class.inc @@ -9,18 +9,22 @@ * file that was distributed with this source code. */ +require_once dirname(__FILE__) . "/../../lib/classes/bootstrap.class.php"; + /** * * @package * @license http://opensource.org/licenses/gpl-3.0 GPLv3 * @link www.phraseanet.com */ -require_once dirname(__FILE__) . "/../../lib/bootstrap.php"; -bootstrap::register_autoloads(); + +bootstrap::execute('test'); use Silex\WebTestCase; use Symfony\Component\HttpKernel\Client; use Symfony\Component\HttpFoundation\Response; +use Doctrine\Common\DataFixtures\Loader; +use PhraseaFixture\Basket as MyFixture; abstract class PhraseanetPHPUnitAbstract extends WebTestCase { @@ -32,7 +36,11 @@ abstract class PhraseanetPHPUnitAbstract extends WebTestCase * @var Symfony\Component\HttpKernel\Client */ protected $client; - + /** + * + * @var record_adapter + */ + protected static $story_1; /** * * @var record_adapter @@ -329,6 +337,7 @@ abstract class PhraseanetPHPUnitAbstract extends WebTestCase protected static $updated; protected static $need_records = false; protected static $need_subdefs = false; + protected static $need_story = false; /** * @@ -343,12 +352,22 @@ abstract class PhraseanetPHPUnitAbstract extends WebTestCase * @var \Alchemy\Phrasea\Core */ protected static $core; + + /** + * + * @var \Doctrine\ORM\Tools\SchemaTools + */ + protected $schematTool; + + /** + * Class metadatas + * @var Array + */ + protected $classesMetatdas; public static function setUpBeforeClass() { - self::$core = bootstrap::getCore(); - if (!self::$time_start) self::$time_start = microtime(true); @@ -358,17 +377,6 @@ abstract class PhraseanetPHPUnitAbstract extends WebTestCase $appbox = appbox::get_instance(); if (!self::$updated) { - if (is_file(__DIR__ . '/tests.sqlite')) - { - unlink(__DIR__ . '/tests.sqlite'); - } - - self::$core["EM"] = self::$core->share(function() - { - $doctrine = new \Alchemy\Phrasea\Core\Service\DoctrineTestSQLite(); - return $doctrine->getEntityManager(); - }); - echo "Upgrading tables ...\n"; if (file_exists(Setup_Upgrade::get_lock_file())) unlink(Setup_Upgrade::get_lock_file()); @@ -471,6 +479,14 @@ abstract class PhraseanetPHPUnitAbstract extends WebTestCase self::$collection = $coll; + if (static::$need_story) + { + self::$story_1 = \record_adapter::create( + self::$collection, new system_file(dirname(__FILE__) . '/testfiles/test001.CR2'), false, true + ); + echo "\ngenerate story 01\n"; + } + if (static::$need_records) { if ((static::$need_records === true || static::$need_records >= 1) && !self::$record_1 instanceof record_adapter) @@ -755,10 +771,62 @@ abstract class PhraseanetPHPUnitAbstract extends WebTestCase } } $appbox->get_session()->logout(); + + return; } + /** + * Delete temporay sqlite database + * Create schema using $this->classesMetatdas + * Load DoctrineTestServices + * + * @return + */ + public function __construct() + { + if (null === self::$core) + { + if (is_file(__DIR__ . '/tests.sqlite')) + { + unlink(__DIR__ . '/tests.sqlite'); + } + + self::$core = bootstrap::getCore(); + self::$core["EM"] = self::$core->share(function() + { + $doctrine = new \Alchemy\Phrasea\Core\Service\DoctrineTestSQLite(); + return $doctrine->getEntityManager(); + }); + + $em = self::$core->getEntityManager(); + /* @var $em \Doctrine\ORM\EntityManager */ + + //create schema + $this->schematTool = new \Doctrine\ORM\Tools\SchemaTool($em); + $this->classesMetatdas = array( + $em->getClassMetadata('Entities\Basket') + , $em->getClassMetadata('Entities\BasketElement') + , $em->getClassMetadata('Entities\StoryWZ') + , $em->getClassMetadata('Entities\ValidationData') + , $em->getClassMetadata('Entities\ValidationParticipant') + , $em->getClassMetadata('Entities\ValidationSession') + ); + + $this->schematTool->createSchema($this->classesMetatdas); + } + } + + /** + * Delete all ressources created during the test + */ public function __destruct() { + if (self::$story_1 instanceof record_adapter) + { + echo "."; + self::$story_1->delete(); + self::$story_1 = null; + } if (self::$record_1 instanceof record_adapter) { echo "."; @@ -920,32 +988,23 @@ abstract class PhraseanetPHPUnitAbstract extends WebTestCase { parent::setUp(); - - $em = self::$core["EM"]; - - //create schema - $this->schematTool = new \Doctrine\ORM\Tools\SchemaTool($em); - $this->classesMetatdas = array( - $em->getClassMetadata('Entities\Basket') - , $em->getClassMetadata('Entities\BasketElement') - , $em->getClassMetadata('Entities\StoryWZ') - , $em->getClassMetadata('Entities\ValidationData') - , $em->getClassMetadata('Entities\ValidationParticipant') - , $em->getClassMetadata('Entities\ValidationSession') - ); - $this->schematTool->createSchema($this->classesMetatdas); - $browser = Browser::getInstance(); $browser->setUserAgent(self::USER_AGENT_FIREFOX8MAC); } public function tearDown() { - //drop schema - $this->schematTool->dropSchema($this->classesMetatdas); + $em = self::$core->getEntityManager(); + parent::tearDown(); } + /** + * Insert fixture contained in the specified fixtureLoader + * into sqlLite test temporary database + * + * @param Doctrine\Common\DataFixtures\Loader $fixtureLoader + */ public function insertFixtureInDatabase(Doctrine\Common\DataFixtures\Loader $fixtureLoader) { $purger = new Doctrine\Common\DataFixtures\Purger\ORMPurger(); @@ -953,6 +1012,16 @@ abstract class PhraseanetPHPUnitAbstract extends WebTestCase $executor->execute($fixtureLoader->getFixtures()); } + /** + * Purge sqlLite test temporary database by truncate all existing tables + */ + protected function purgeDatabase() + { + $purger = new Doctrine\Common\DataFixtures\Purger\ORMPurger(); + $executor = new Doctrine\Common\DataFixtures\Executor\ORMExecutor(self::$core->getEntityManager(), $purger); + $executor->execute(array()); + } + protected function assertDateAtom($date) { return $this->assertRegExp('/\d{4}[-]\d{2}[-]\d{2}[T]\d{2}[:]\d{2}[:]\d{2}[+]\d{2}[:]\d{2}/', $date); @@ -964,4 +1033,117 @@ abstract class PhraseanetPHPUnitAbstract extends WebTestCase $browser->setUserAgent($user_agent); } + /** + * Insert one basket entry ans set current authenticated user as owner + * + * @return \Entities\Basket + */ + protected function insertOneBasket() + { + try + { + $basketFixture = new MyFixture\LoadOneBasket(); + + $basketFixture->setUser(self::$user); + + $loader = new Loader(); + $loader->addFixture($basketFixture); + + $this->insertFixtureInDatabase($loader); + + return $basketFixture->basket; + } + catch (\Exception $e) + { + $this->fail('Fail load one Basket : ' . $e->getMessage()); + } + } + + /** + * Create a new basket with current auhtenticated user as owner + * Create a new sessionValidation with the newly created basket + * Set current authenticated user as sessionValidation initiator + * Add 2 records as elments of the newly created basket + * Add 2 participants to the newly created sessionValidation + * + * @return \Entities\Basket + */ + protected function insertOneBasketEnv() + { + try + { + $em = self::$core->getEntityManager(); + /* @var $em \Doctrine\ORM\EntityManager */ + + $basketFixture = new MyFixture\LoadOneBasketEnv(); + + $basketFixture->setUser(self::$user); + + $basketFixture->addParticipant(self::$user_alt1); + $basketFixture->addParticipant(self::$user_alt2); + + $basketFixture->addBasketElement(self::$record_1); + $basketFixture->addBasketElement(self::$record_2); + + $loader = new Loader(); + $loader->addFixture($basketFixture); + + $this->insertFixtureInDatabase($loader); + + return $basketFixture->basket; + } + catch (\Exception $e) + { + $this->fail('Fail load one Basket context : ' . $e->getMessage()); + } + } + + /** + * Load One WZ with + * One basket + * One story + * One ValidationSession & one participant + * @return + */ + protected function insertOneWZ() + { + try + { + $currentUser = self::$user; + $altUser = self::$user_alt1; + //add one basket + $basket = new PhraseaFixture\Basket\LoadOneBasket(); + $basket->setUser($currentUser); + //add one story + $story = new PhraseaFixture\Story\LoadOneStory(); + $story->setUser($currentUser); + $story->setRecord(self::$record_1); + //add a validation session initiated by alt user + $validationSession = new PhraseaFixture\ValidationSession\LoadOneValidationSession(); + $validationSession->setUser($altUser); + + $loader = new Loader(); + $loader->addFixture($basket); + $loader->addFixture($story); + $loader->addFixture($validationSession); + + $this->insertFixtureInDatabase($loader); + + //add current user as participant + $validationParticipant = new PhraseaFixture\ValidationParticipant\LoadParticipantWithSession(); + $validationParticipant->setSession($validationSession->validationSession); + $validationParticipant->setUser($currentUser); + + $loader = new Loader(); + $loader->addFixture($validationParticipant); + $this->insertFixtureInDatabase($loader); + } + catch (\Exception $e) + { + $this->fail('Fail load one WorkingZone : ' . $e->getMessage()); + } + + return; + } + }