diff --git a/library/Class/AdminVar.php b/library/Class/AdminVar.php index d635d59fd253a601e14b0d39c836ed588f83d904..65e2a1ec9219607e36a15037ee9c00df537b44c6 100644 --- a/library/Class/AdminVar.php +++ b/library/Class/AdminVar.php @@ -137,7 +137,8 @@ class Class_AdminVarLoader extends Storm_Model_Loader { 'usergroup-agenda' => $this->_getRendezVousVars(), 'templating' => $this->_getTemplatingVars(), 'identity-providers' => $this->_getIdentityProvidersVars(), - 'drive-checkout' => $this->_getDriveCheckoutVars() + 'drive-checkout' => $this->_getDriveCheckoutVars(), + 'journal' => $this->_getJournalVars(), ]; } @@ -544,6 +545,7 @@ class Class_AdminVarLoader extends Storm_Model_Loader { } + protected function _getIdentityProvidersVars() { return ['ENABLE_IDENTITY_PROVIDERS' => Class_AdminVar_Meta::newOnOff($this->_('Activer la gestion des fournisseurs d\'identité')), @@ -567,6 +569,22 @@ class Class_AdminVarLoader extends Storm_Model_Loader { } + protected function _getJournalVars() { + $stormModels = new Class_AdminVar_JournalStormModels(); + $models = Class_AdminVar_Meta::newMultiInput($this->_('Liste des données à journaliser'), + ['options' => ['fields' => [['name' => 'model', + 'label' => $this->_('Donnée'), + 'type' => 'select', + 'options' => $stormModels->modelsMultioptions()], + ['name' => 'ids', + 'label' => $this->_('Limité aux identifiants (séparés par ; , vide pour ne pas limiter)')]]], + 'value' => $stormModels->defaultValue()]); + + return ['JOURNAL_ENABLE_STORM' => Class_AdminVar_Meta::newOnOff($this->_('Activer la journalisation des modifications en base de données'))->enable(), + 'JOURNAL_STORM_MODELS' => $models]; + } + + public function allVarsValues() { if (null !== static::$_all_vars_values) return static::$_all_vars_values; @@ -1168,8 +1186,6 @@ class Class_AdminVar extends Storm_Model_Abstract { protected $_loader_class = 'Class_AdminVarLoader'; protected $_fixed_id = true; - protected $_before_save_value; - public function getValeur() { return $this->_get('valeur'); @@ -1224,19 +1240,6 @@ class Class_AdminVar extends Storm_Model_Abstract { public function afterSave() { $this->getMeta()->afterSave($this); Class_DigitalResource::getInstance()->enablePluginWith($this->getClef()); - Class_Journal_Type::save($this); - } - - - public function beforeSave() { - $this->_before_save_value = isset($this->_attributes_in_db['valeur']) - ? $this->_attributes_in_db['valeur'] - : null; - } - - - public function getBeforeSaveValue() { - return $this->_before_save_value; } diff --git a/library/Class/AdminVar/JournalStormModels.php b/library/Class/AdminVar/JournalStormModels.php new file mode 100644 index 0000000000000000000000000000000000000000..4518177e8efb0988eed9bd7750d0a2ee048e168f --- /dev/null +++ b/library/Class/AdminVar/JournalStormModels.php @@ -0,0 +1,75 @@ +<?php +/** + * Copyright (c) 2012-2020, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH is free software; you can redistribute it and/or modify + * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by + * the Free Software Foundation. + * + * There are special exceptions to the terms and conditions of the AGPL as it + * is applied to this software (see README file). + * + * BOKEH is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE + * along with BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +class Class_AdminVar_JournalStormModels { + use Trait_Translator; + + const + MODEL_KEY = 'model', + IDS_KEY = 'ids', + IDS_SEPARATOR = ';'; + + public function modelsMultioptions() { + return ['' => $this->_(''), + Class_AdminVar::class => $this->_('Variables'), + Class_Profil::class => $this->_('Profils')]; + } + + + public function defaultValue() { + return json_encode([static::MODEL_KEY => [Class_AdminVar::class], + static::IDS_KEY => ['']]); + } + + + public function isEnabled() { + return ($map = $this->_loadMapping()) + ? array_filter(array_keys($map)) + : false; + } + + + public function modelMatch($model) { + if (!$map = $this->_loadMapping()) + return false; + + if (!array_key_exists(get_class($model), $map)) + return false; + + $ids = array_filter(explode(static::IDS_SEPARATOR, $map[get_class($model)])); + + return !$ids || in_array($model->getId(), $ids); + } + + + protected function _loadMapping() { + if (!$conf = json_decode(Class_AdminVar::getValueOrDefault('JOURNAL_STORM_MODELS'), true)) + return []; + + if (!isset($conf[static::MODEL_KEY]) || !isset($conf[static::IDS_KEY])) + return []; + + return ($map = array_combine($conf[static::MODEL_KEY], $conf[static::IDS_KEY])) + ? $map + : []; + } +} diff --git a/library/Class/Journal.php b/library/Class/Journal.php index c12ad514d3b11cedd523396444bfd73b2baee96a..d859063b91cb9097ce2a744cf8937e7fb6af102d 100644 --- a/library/Class/Journal.php +++ b/library/Class/Journal.php @@ -99,4 +99,14 @@ class Class_Journal extends Storm_Model_Abstract { return (new Storm_Model_Collection($this->getDetails())) ->detect(function($detail) use($type) { return $detail->getType() == $type; }); } + + + public function addDetail($type, $value) { + Class_JournalDetail::newInstance(['type' => $type, + 'value' => $value, + 'journal' => $this]) + ->save(); + + return $this; + } } diff --git a/library/Class/Journal/AdminVarType.php b/library/Class/Journal/AdminVarType.php new file mode 100644 index 0000000000000000000000000000000000000000..76539c777ec875e0684f4bddc216c5327e96162c --- /dev/null +++ b/library/Class/Journal/AdminVarType.php @@ -0,0 +1,59 @@ +<?php +/** + * Copyright (c) 2012-2020, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH is free software; you can redistribute it and/or modify + * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by + * the Free Software Foundation. + * + * There are special exceptions to the terms and conditions of the AGPL as it + * is applied to this software (see README file). + * + * BOKEH is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE + * along with BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +class Class_Journal_AdminVarType extends Class_Journal_Type { + + const + MY_TYPE = 'ADMIN_VAR_SAVE', + ADMINVAR_ID = 'adminvar_id', + CURRENT_USER_ID = 'current_user_id', + PREVIOUS_VALUE = 'previous_value', + NEW_VALUE = 'new_value'; + + + public static function save($model) { + if (!$model) + return; + + if (!$journal = static::_newJournal()) + return; + + $journal->addDetail(static::ADMINVAR_ID, $model->getClef()); + $journal->addDetail(static::CURRENT_USER_ID, + ($user = Class_Users::getIdentity()) ? $user->getId() : '', + $journal); + $journal->addDetail(static::PREVIOUS_VALUE, $model->getPreviousValue()); + $journal->addDetail(static::NEW_VALUE, $model->getValeur()); + + return $journal; + } + + + public function getLabel() { + return $this->_('La variable "%s" a été modifiée de "%s" à "%s" par "%s"', + $this->_getDetailLabel('adminvar_id'), + $this->_getDetailLabel('previous_value'), + $this->_getDetailLabel('new_value'), + $this->_getDetailLabel('current_user_id') + ); + } +} diff --git a/library/Class/Journal/ProfileType.php b/library/Class/Journal/ProfileType.php new file mode 100644 index 0000000000000000000000000000000000000000..c73aa8643f24b6c4ac62a8ed1017722b0a5d6666 --- /dev/null +++ b/library/Class/Journal/ProfileType.php @@ -0,0 +1,83 @@ +<?php +/** + * Copyright (c) 2012-2020, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH is free software; you can redistribute it and/or modify + * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by + * the Free Software Foundation. + * + * There are special exceptions to the terms and conditions of the AGPL as it + * is applied to this software (see README file). + * + * BOKEH is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE + * along with BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +class Class_Journal_ProfileType extends Class_Journal_Type { + + const + MY_TYPE = 'PROFILE_SAVE', + MODEL_ID = 'model_id', + CURRENT_USER_ID = 'current_user_id', + PREVIOUS_VALUE = 'previous_value', + NEW_VALUE = 'new_value', + STACK = 'stack'; + + + public static function save($model) { + if (!$model) + return; + + $current = $model->getRawAttributes(); + $previous = $model->getRawDbAttributes(); + if (!isset($previous['cfg_accueil'])) + return; + + if (!$journal = static::_newJournal()) + return; + + $journal->addDetail(static::MODEL_ID, $model->getId()); + $journal->addDetail(static::CURRENT_USER_ID, + ($user = Class_Users::getIdentity()) ? $user->getId() : '', + $journal); + $journal->addDetail(static::PREVIOUS_VALUE, json_encode(static::_unserialize($previous['cfg_accueil']))); + $journal->addDetail(static::NEW_VALUE, json_encode(static::_unserialize($current['cfg_accueil']))); + + ob_start(); + debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); + $stack = ob_get_contents(); + ob_end_clean(); + $journal->addDetail(static::STACK, $stack); + + return $journal; + } + + + protected static function _unserialize($data) { + try { + $unserialized = ZendAfi_Filters_Serialize::unserialize($data); + } catch (Exception $e) { + $unserialized = []; + } + + if (!$unserialized) + return []; + + return $unserialized; + } + + + public function getLabel() { + return $this->_('Le profil "%s" a été modifié par "%s"', + $this->_getDetailLabel(static::MODEL_ID), + $this->_getDetailLabel(static::CURRENT_USER_ID) + ); + } +} diff --git a/library/Class/Journal/StormObserver.php b/library/Class/Journal/StormObserver.php new file mode 100644 index 0000000000000000000000000000000000000000..1f3fb4f8dec38fd36ca4b3f31ede9d6207032798 --- /dev/null +++ b/library/Class/Journal/StormObserver.php @@ -0,0 +1,66 @@ +<?php +/** + * Copyright (c) 2012-2020, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH is free software; you can redistribute it and/or modify + * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by + * the Free Software Foundation. + * + * There are special exceptions to the terms and conditions of the AGPL as it + * is applied to this software (see README file). + * + * BOKEH is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE + * along with BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +class Class_Journal_StormObserver { + protected $_lock = false; + + public static function register() { + if (!Class_AdminVar::isModuleEnabled('JOURNAL_ENABLE_STORM')) + return; + + if (!(new Class_AdminVar_JournalStormModels)->isEnabled()) + return; + + Storm_Events::getInstance()->register(new static()); + } + + + /** + * @param $event Storm_Event + */ + public function __invoke($event) { + if ($this->_lock || (!$model = $event->getModel())) + return; + + if ($this->_shouldSave($model)) + Class_Journal_Type::save($model); + } + + + protected function _shouldSave($model) { + // lock to dodge cases where reading adminvar would save a model and then infinite loop here + return $this->_withLockDo(function() use($model) + { + return (new Class_AdminVar_JournalStormModels) + ->modelMatch($model); + }); + } + + + protected function _withLockDo($aBlock) { + $this->_lock = true; + $result = $aBlock(); + $this->_lock = false; + + return $result; + } +} diff --git a/library/Class/Journal/Type.php b/library/Class/Journal/Type.php index deda6beb83783cef9b30e85b54c7505cd0af582a..8d84d9ecebaa6580b25a11f04b1592ac6fee732a 100644 --- a/library/Class/Journal/Type.php +++ b/library/Class/Journal/Type.php @@ -24,17 +24,15 @@ class Class_Journal_Type { use Trait_Translator; const - MY_TYPE = 'ADMIN_VAR_SAVE', - ADMINVAR_ID = 'adminvar_id', - CURRENT_USER_ID = 'current_user_id', - PREVIOUS_VALUE = 'previous_value', - NEW_VALUE = 'new_value'; + MY_TYPE = 'UNKNOWN', + MAX_STACK = 100; protected static $_enabled = true; protected $_journal; + /** @category testing */ public static function disable() { static::$_enabled = false; @@ -53,38 +51,55 @@ class Class_Journal_Type { } + /** + * Given a journal, make instance of its type + * + * @param $journal Class_Journal + * @return Class_Journal_Type + */ + public static function newFor($journal) { + $possibles = [Class_Journal_AdminVarType::MY_TYPE => Class_Journal_AdminVarType::class, + Class_Journal_ProfileType::MY_TYPE => Class_Journal_ProfileType::class]; + + return array_key_exists($journal->getType(), $possibles) + ? new $possibles[$journal->getType()]($journal) + : new static($journal); + } + + + /** + * @param $model Storm_Model_Abstract + * @return Class_Journal or null + */ public static function save($model) { - if (!static::_isEnabled()) + if (!$model || !static::_isEnabled()) return; + $map = [Class_AdminVar::class => Class_Journal_AdminVarType::class, + Class_Profil::class => Class_Journal_ProfileType::class]; + $class = get_class($model); + + return array_key_exists($class, $map) + ? call_user_func([$map[$class], 'save'], $model) + : null; + } + + + protected static function _newJournal() { $journal = Class_Journal::newInstance(['type' => static::MY_TYPE]); + if (!$journal->save()) return; - if (!$model) - return $journal; - - static::_newDetail(static::ADMINVAR_ID, $model->getClef(), $journal); - static::_newDetail(static::CURRENT_USER_ID, - ($user = Class_Users::getIdentity()) ? $user->getId() : '', - $journal); - static::_newDetail(static::PREVIOUS_VALUE, $model->getPreviousValue(), $journal); - static::_newDetail(static::NEW_VALUE, $model->getValeur(), $journal); + static::_cleanStack(); return $journal; } - protected static function _newDetail($type, $value, $journal) { - Class_JournalDetail::newInstance(['type' => $type, - 'value' => $value, - 'journal' => $journal]) - ->save(); - } - - - public static function newFor($journal) { - return new static($journal); + protected static function _cleanStack() { + while (static::MAX_STACK < Class_Journal::countBy(['type' => static::MY_TYPE])) + Class_Journal::findFirstBy(['order' => 'created_at'])->delete(); } @@ -94,12 +109,7 @@ class Class_Journal_Type { public function getLabel() { - return $this->_('La variable "%s" a été modifiée de "%s" à "%s" par "%s"', - $this->_getDetailLabel('adminvar_id'), - $this->_getDetailLabel('previous_value'), - $this->_getDetailLabel('new_value'), - $this->_getDetailLabel('current_user_id') - ); + return ''; } diff --git a/library/startup.php b/library/startup.php index 9f9980f2e1b640dfd8e8e466a95fa04147db4453..d155322b44698a214ae47c4a0c5d2904a72916d8 100644 --- a/library/startup.php +++ b/library/startup.php @@ -75,7 +75,8 @@ class Bokeh_Engine { Class_AdminVar::findAll(); - return $this->setupLanguage(); + return $this->setupLanguage() + ->setupStormObservers(); } @@ -145,13 +146,13 @@ class Bokeh_Engine { } - public function loadConfig($config_init_file_path = './config.ini') { + public function loadConfig($config_init_file_path = './config.ini', $allowModifications=false) { // load configuration (local ou production) if(array_isset('REMOTE_ADDR', $_SERVER) and $_SERVER['REMOTE_ADDR'] == '127.0.0.1') $serveur='local'; else $serveur='production'; - $this->_config = new Zend_Config_Ini($config_init_file_path, $serveur); + $this->_config = new Zend_Config_Ini($config_init_file_path, $serveur, $allowModifications); Zend_Registry::set('cfg', $this->_config); $locale = $this->_config->locale @@ -240,6 +241,13 @@ class Bokeh_Engine { Zend_Registry::set('sql', $afi_sql); Zend_Db_Table::getDefaultAdapter()->query('set names "UTF8"'); Zend_Db_Table::getDefaultAdapter()->query('set SQL_MODE = ""'); + + return $this; + } + + + public function setupStormObservers() { + Class_Journal_StormObserver::register(); return $this; } diff --git a/library/storm b/library/storm index 67e32fa4f2114f69c7a3d9b96d9419186cb2e7bf..17d31fdfc59be5319cb5201ac2280dbb9e7c2c5b 160000 --- a/library/storm +++ b/library/storm @@ -1 +1 @@ -Subproject commit 67e32fa4f2114f69c7a3d9b96d9419186cb2e7bf +Subproject commit 17d31fdfc59be5319cb5201ac2280dbb9e7c2c5b diff --git a/tests/application/modules/AbstractControllerTestCase.php b/tests/application/modules/AbstractControllerTestCase.php index f5fd9d5b7e44489324897e7ca4cd1932b971bcb8..852ba6e185c40723962b8825cbe5a16172f1d416 100644 --- a/tests/application/modules/AbstractControllerTestCase.php +++ b/tests/application/modules/AbstractControllerTestCase.php @@ -116,6 +116,8 @@ abstract class AbstractControllerTestCase extends Zend_Test_PHPUnit_ControllerTe $this->_initMockProfil(); + Storm_Events::setInstance(null); + parent::setUp(); Zend_Registry::get('locale')->setLocale('fr'); diff --git a/tests/scenarios/Journal/JournalTest.php b/tests/scenarios/Journal/JournalTest.php index ef2191b55761f217dc91f6e32dbe31b5b4ee75d7..26508d36791bfbeda12cee07416fb55a5e923b7d 100644 --- a/tests/scenarios/Journal/JournalTest.php +++ b/tests/scenarios/Journal/JournalTest.php @@ -20,9 +20,9 @@ */ -abstract class JournalAdminVarTestCase extends Admin_AbstractControllerTestCase { - protected $_storm_default_to_volatile = true; +abstract class JournalTestCase extends Admin_AbstractControllerTestCase { + protected $_storm_default_to_volatile = true; public function setUp() { parent::setUp(); @@ -33,10 +33,13 @@ abstract class JournalAdminVarTestCase extends Admin_AbstractControllerTestCase -class JournalAdminVarPostTest extends JournalAdminVarTestCase { +class JournalAdminVarPostTest extends JournalTestCase { public function setUp() { parent::setUp(); Class_AdminVar::set('FACETTE_GENRE_LIBELLE', ''); + Class_AdminVar::set('JOURNAL_ENABLE_STORM', 1); + (new Bokeh_Engine)->setupStormObservers(); + $this->postDispatch('/admin/index/adminvaredit/cle/FACETTE_GENRE_LIBELLE', ['cle' => 'FACETTE_GENRE_LIBELLE', 'valeur' => "test"]); @@ -84,10 +87,268 @@ class JournalAdminVarPostTest extends JournalAdminVarTestCase { -class JournalIndexActionTest extends JournalAdminVarTestCase { + +class JournalAdminVarPostWithJournalDisabledTest extends JournalTestCase { + public function setUp() { + parent::setUp(); + Class_AdminVar::set('FACETTE_GENRE_LIBELLE', ''); + Class_AdminVar::set('JOURNAL_ENABLE_STORM', '0'); + (new Bokeh_Engine)->setupStormObservers(); + + $this->postDispatch('/admin/index/adminvaredit/cle/FACETTE_GENRE_LIBELLE', + ['cle' => 'FACETTE_GENRE_LIBELLE', + 'valeur' => "test"]); + } + + + /** @test */ + public function journalShouldNotBeCreated() { + $this->assertNull(Class_Journal::find(1)); + } +} + + + + +class JournalAdminVarPostWithJournalEnabledButModelDisabledTest extends JournalTestCase { + public function setUp() { + parent::setUp(); + Class_AdminVar::set('FACETTE_GENRE_LIBELLE', ''); + Class_AdminVar::set('JOURNAL_ENABLE_STORM', 1); + Class_AdminVar::set('JOURNAL_STORM_MODELS', json_encode(['model' => [Class_Profil::class], + 'ids' => ['']])); + (new Bokeh_Engine)->setupStormObservers(); + + $this->postDispatch('/admin/index/adminvaredit/cle/FACETTE_GENRE_LIBELLE', + ['cle' => 'FACETTE_GENRE_LIBELLE', + 'valeur' => "test"]); + } + + + /** @test */ + public function journalShouldNotBeCreated() { + $this->assertNull(Class_Journal::find(1)); + } +} + + + + +abstract class JournalProfileTestCase extends JournalTestCase { + public function setUp() { + parent::setUp(); + + $simple_widgets = ['modules' => ['1' => ['division' => '4', + 'type_module' => 'RECH_SIMPLE', + 'preferences' => []], + '6' => ['division' => '3', + 'type_module' => 'MENU_VERTICAL', + 'preferences' => ['menu' => '5-8']], + '4' => ['division' => '4', + 'type_module' => 'CALENDRIER']]]; + + Class_Profil::getCurrentProfil() + ->setCfgAccueil($simple_widgets) + ->save(); + } +} + + + + +class JournalProfilePostTest extends JournalProfileTestCase { + public function setUp() { + parent::setUp(); + + Class_AdminVar::set('JOURNAL_ENABLE_STORM', 1); + Class_AdminVar::set('JOURNAL_STORM_MODELS', json_encode(['model' => [Class_Profil::class], + 'ids' => ['']])); + (new Bokeh_Engine)->setupStormObservers(); + + $this->postDispatch('/admin/widget/edit-widget/id/6/id_profil/' . Class_Profil::getCurrentProfil()->getId(), + ['menu' => '8']); + } + + + /** @test */ + public function journalShouldBeCreated() { + $this->assertNotNull(Class_Journal::find(1)); + } + + + /** @test */ + public function journalShouldHaveModelIdDetail() { + $this->assertNotNull(Class_JournalDetail::findFirstBy(['type' => 'model_id', + 'value' => Class_Profil::getCurrentProfil()->getId(), + ])); + } + + + /** @test */ + public function journalShouldHaveUserDetail() { + $this->assertNotNull(Class_JournalDetail::findFirstBy(['type' => 'current_user_id', + 'value' => 666, + ])); + } + + + /** @test */ + public function journalShouldHavePreviousValueDetail() { + $this->assertEquals('{"modules":{"1":{"division":"4","type_module":"RECH_SIMPLE","preferences":[]},"6":{"division":"3","type_module":"MENU_VERTICAL","preferences":{"menu":"5-8"}},"4":{"division":"4","type_module":"CALENDRIER"}}}', + Class_JournalDetail::findFirstBy(['type' => 'previous_value']) + ->getValue()); + } + + + /** @test */ + public function journalShouldHaveNewValueDetail() { + $this->assertEquals('{"page_css":"","use_parent_css":"1","modules":{"1":{"division":"4","type_module":"RECH_SIMPLE","preferences":[]},"6":{"type_module":"MENU_VERTICAL","preferences":{"afficher_titre":"1","menu_deplie":"0","new_html":"0","toggle_menu":"0","menu":"8","boite":"","titre":"","profile_id":"2"},"division":"3","id_module":"6","profile_id":"2"},"4":{"division":"4","type_module":"CALENDRIER"}},"sitemap":"1"}', + Class_JournalDetail::findFirstBy(['type' => 'new_value']) + ->getValue()); + } + + + /** @test */ + public function journalShouldHaveStackDetail() { + $this->assertContains('#0 Class_Journal_ProfileType::save()', + Class_JournalDetail::findFirstBy(['type' => 'stack'])->getValue()); + } +} + + + + +class JournalProfilePostJournalDisabledTest extends JournalProfileTestCase { + public function setUp() { + parent::setUp(); + + Class_AdminVar::set('JOURNAL_ENABLE_STORM', '0'); + (new Bokeh_Engine)->setupStormObservers(); + + $this->postDispatch('/admin/widget/edit-widget/id/6/id_profil/' . Class_Profil::getCurrentProfil()->getId(), + ['menu' => '8']); + } + + + /** @test */ + public function journalShouldNotBeCreated() { + $this->assertNull(Class_Journal::find(1)); + } +} + + + + +class JournalProfilePostJournalEnabledModelDisabledTest extends JournalProfileTestCase { public function setUp() { parent::setUp(); + Class_AdminVar::set('JOURNAL_ENABLE_STORM', 1); + (new Bokeh_Engine)->setupStormObservers(); + + $this->postDispatch('/admin/widget/edit-widget/id/6/id_profil/' . Class_Profil::getCurrentProfil()->getId(), + ['menu' => '8']); + } + + + /** @test */ + public function journalShouldNotBeCreated() { + $this->assertNull(Class_Journal::find(1)); + } +} + + + + +class JournalProfilePostEnabledButWithoutMatchingIdTest extends JournalProfileTestCase { + public function setUp() { + parent::setUp(); + + Class_AdminVar::set('JOURNAL_ENABLE_STORM', 1); + Class_AdminVar::set('JOURNAL_STORM_MODELS', json_encode(['model' => [Class_Profil::class], + 'ids' => ['16']])); + (new Bokeh_Engine)->setupStormObservers(); + + $this->postDispatch('/admin/widget/edit-widget/id/6/id_profil/' . Class_Profil::getCurrentProfil()->getId(), + ['menu' => '8']); + } + + + /** @test */ + public function journalShouldNotBeCreated() { + $this->assertNull(Class_Journal::find(1)); + } +} + + + + +class JournalProfilePostEnabledWithMatchingIdTest extends JournalProfileTestCase { + public function setUp() { + parent::setUp(); + + Class_AdminVar::set('JOURNAL_ENABLE_STORM', 1); + Class_AdminVar::set('JOURNAL_STORM_MODELS', + json_encode(['model' => [Class_Profil::class], + 'ids' => ['16;nothing;' . Class_Profil::getCurrentProfil()->getId()]])); + (new Bokeh_Engine)->setupStormObservers(); + + $this->postDispatch('/admin/widget/edit-widget/id/6/id_profil/' . Class_Profil::getCurrentProfil()->getId(), + ['menu' => '8']); + } + + + /** @test */ + public function journalShouldBeCreated() { + $this->assertNotNull(Class_Journal::find(1)); + } +} + + + + +class JournalProfilePostEnabledWithMatchingIdAndMaxStackTest extends JournalProfileTestCase { + public function setUp() { + parent::setUp(); + + Class_AdminVar::set('JOURNAL_ENABLE_STORM', 1); + Class_AdminVar::set('JOURNAL_STORM_MODELS', + json_encode(['model' => [Class_Profil::class], + 'ids' => ['16;nothing;' . Class_Profil::getCurrentProfil()->getId()]])); + (new Bokeh_Engine)->setupStormObservers(); + + foreach(range(0, Class_Journal_Type::MAX_STACK + 10) as $i) + $this->fixture('Class_Journal', + ['id' => 1000 + $i, + 'type' => Class_Journal_ProfileType::MY_TYPE]); + + $this->postDispatch('/admin/widget/edit-widget/id/6/id_profil/' . Class_Profil::getCurrentProfil()->getId(), + ['menu' => '8']); + } + + + /** @test */ + public function journalShouldBeCreated() { + $this->assertNotNull(Class_Journal::find(1111)); + } + + + /** @test */ + public function journalStackShouldRespectMaximum() { + $this->assertEquals(Class_Journal_Type::MAX_STACK, Class_Journal::count()); + } +} + + + + +class JournalIndexActionTest extends JournalTestCase { + public function setUp() { + parent::setUp(); + + Class_AdminVar::set('JOURNAL_ENABLE_STORM', 1); + (new Bokeh_Engine)->setupStormObservers(); + Class_AdminVar::set('FACETTE_GENRE_LIBELLE', 'test'); Class_Users::getIdentity()->setLogin('Harlock'); $this->dispatch('/admin/journal');