<?php /** * Piwik - free/libre analytics platform * * @link http://piwik.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ use Piwik\Access; use Piwik\Plugin\Settings as PluginSettings; use Piwik\Settings\Setting; use Piwik\Tests\Framework\TestCase\IntegrationTestCase; class CorePluginSettingsTest extends \Piwik\Plugins\ExampleSettingsPlugin\Settings { public function init() { } public function addSetting(Setting $setting) { parent::addSetting($setting); } } /** * Class Core_Plugin_SettingsTest * @group Core * @group PluginSettings */ class Core_Plugin_SettingsTest extends IntegrationTestCase { /** * @var CorePluginSettingsTest */ private $settings; public function setUp() { parent::setUp(); Access::setSingletonInstance(null); $this->settings = $this->createSettingsInstance(); } public function tearDown() { $this->setSuperUser(); if ($this->settings) { $this->settings->removeAllPluginSettings(); } parent::tearDown(); } /** * @expectedException \Exception * @expectedExceptionMessage A setting with name "myname" does already exist for plugin "ExampleSettingsPlugin" */ public function test_addSetting_shouldThrowException_InCaseTwoSettingsHaveTheSameName() { $this->addUserSetting('myname', 'mytitle'); $setting = $this->buildUserSetting('myname', 'mytitle2'); $this->settings->addSetting($setting); } /** * @expectedException \Exception * @expectedExceptionMessage The setting name "myname_" in plugin "ExampleSettingsPlugin" is not valid. Only alpha and numerical characters are allowed */ public function test_addSetting_shouldThrowException_IfTheSettingNameIsNotValid() { $setting = $this->buildUserSetting('myname_', 'mytitle'); $this->settings->addSetting($setting); } public function test_addSetting_shouldAssignDefaultType_IfFieldIsGivenButNoType() { $setting = $this->buildUserSetting('myname', 'mytitle'); $setting->uiControlType = CorePluginSettingsTest::CONTROL_MULTI_SELECT; $this->settings->addSetting($setting); $this->assertEquals(CorePluginSettingsTest::TYPE_ARRAY, $setting->type); } public function test_addSetting_shouldAssignDefaultField_IfTypeIsGivenButNoField() { $setting = $this->buildUserSetting('myname', 'mytitle'); $setting->type = CorePluginSettingsTest::TYPE_ARRAY; $this->settings->addSetting($setting); $this->assertEquals(CorePluginSettingsTest::CONTROL_MULTI_SELECT, $setting->uiControlType); } public function test_addSetting_shouldAddAValidator_IfFieldOptionsAreGiven() { $setting = $this->buildUserSetting('myname', 'mytitle'); $setting->availableValues = array('allowedval' => 'DisplayName', 'allowedval2' => 'Name 2'); $this->settings->addSetting($setting); $this->assertInstanceOf('\Closure', $setting->validate); } public function test_addSetting_shouldAddTheSettings_IfValid() { $setting = $this->addUserSetting('myname', 'mytitle'); $this->assertEquals(array('myname' => $setting), $this->settings->getSettings()); } public function test_addSetting_shouldPassTheStorage_ToTheSetting() { $this->setSuperUser(); $setting = $this->buildUserSetting('myname', 'mytitle', 'myRandomName'); $this->settings->addSetting($setting); $this->settings->setSettingValue($setting, 5); $this->assertSettingHasValue($setting, 5); $this->assertEquals($setting->getValue(), 5); $this->settings->setSettingValue($setting, 'test3434'); $this->assertEquals($setting->getValue(), 'test3434'); } /** * @expectedException \Exception * @expectedExceptionMessage The setting myname2 does not exist */ public function test_setSettingValue_shouldThrowException_IfTryingToSetAValueForNotAvailableSetting() { $this->addUserSetting('myname', 'mytitle'); $setting = $this->buildUserSetting('myname2', 'mytitle2'); $this->settings->setSettingValue($setting, 2); } /** * @expectedException \Exception * @expectedExceptionMessage CoreAdminHome_PluginSettingChangeNotAllowed */ public function test_setSettingValue_shouldThrowException_IfAUserIsTryingToSetASettingWhichNeedsSuperUserPermission() { $this->setUser(); $setting = $this->addSystemSetting('mysystem', 'mytitle'); $this->settings->setSettingValue($setting, 2); } /** * @expectedException \Exception * @expectedExceptionMessage CoreAdminHome_PluginSettingChangeNotAllowed */ public function test_setSettingValue_shouldThrowException_IfAnonymousIsTryingToSetASettingWhichNeedsUserPermission() { $setting = $this->addUserSetting('mysystem', 'mytitle'); $this->settings->setSettingValue($setting, 2); } public function test_setSettingValue_shouldSucceed_IfUserIsTryingToSetASettingWhichNeedsUserPermission() { $this->setUser(); $setting = $this->addUserSetting('mysystem', 'mytitle'); $this->settings->setSettingValue($setting, 2); $this->assertSettingHasValue($setting, 2); } public function test_setSettingValue_shouldSucceed_IfSuperUserTriesToSaveASettingWhichRequiresSuperUserPermission() { $this->setSuperUser(); $setting = $this->addSystemSetting('mysystem', 'mytitle'); $this->settings->setSettingValue($setting, 2); $this->assertSettingHasValue($setting, 2); } public function test_setSettingValue_shouldNotPersistValueInDatabase_OnSuccess() { $this->setSuperUser(); $setting = $this->buildSystemSetting('mysystem', 'mytitle'); $this->settings->addSetting($setting); $this->settings->setSettingValue($setting, 2); // make sure stored on the instance $this->assertSettingHasValue($setting, 2); $this->assertSettingIsNotSavedInTheDb('mysystem', null); } /** * @expectedException \Exception * @expectedExceptionMessage CoreAdminHome_PluginSettingsValueNotAllowed */ public function test_setSettingValue_shouldApplyValidationAndFail_IfOptionsAreSet() { $this->setUser(); $setting = $this->buildUserSetting('mysystem', 'mytitle'); $setting->availableValues = array('allowed' => 'text', 'allowed2' => 'text2'); $this->settings->addSetting($setting); $this->settings->setSettingValue($setting, 'notallowed'); } /** * @expectedException \Exception * @expectedExceptionMessage CoreAdminHome_PluginSettingsValueNotAllowed */ public function test_setSettingValue_shouldApplyValidationAndFail_IfOptionsAreSetAndValueIsAnArray() { $this->setUser(); $setting = $this->buildUserSetting('mysystem', 'mytitle'); $setting->availableValues = array('allowed' => 'text', 'allowed2' => 'text2'); $setting->uiControlType = PluginSettings::CONTROL_MULTI_SELECT; $this->settings->addSetting($setting); $this->settings->setSettingValue($setting, array('allowed', 'notallowed')); } public function test_setSettingValue_shouldApplyValidationAndSucceed_IfOptionsAreSet() { $this->setUser(); $setting = $this->buildUserSetting('mysystem', 'mytitle'); $setting->availableValues = array('allowed' => 'text', 'allowed2' => 'text2'); $setting->uiControlType = PluginSettings::CONTROL_MULTI_SELECT; $this->settings->addSetting($setting); $this->settings->setSettingValue($setting, array('allowed', 'allowed2')); $this->assertSettingHasValue($setting, array('allowed', 'allowed2')); $setting->type = PluginSettings::TYPE_STRING; $this->settings->setSettingValue($setting, 'allowed'); $this->assertSettingHasValue($setting, 'allowed'); } public function test_setSettingValue_shouldCastValue_IfTypeIsSetButNoFilter() { $this->setUser(); // cast to INT $setting = $this->addUserSetting('mysystem', 'mytitle'); $setting->type = PluginSettings::TYPE_INT; $this->settings->setSettingValue($setting, '31xm42'); $this->assertSettingHasValue($setting, 31, 'integer'); // ARRAY $setting->type = PluginSettings::TYPE_ARRAY; $this->settings->setSettingValue($setting, '31xm42'); $this->assertSettingHasValue($setting, array('31xm42'), 'array'); // BOOL $setting->type = PluginSettings::TYPE_BOOL; $this->settings->setSettingValue($setting, '1'); $this->assertSettingHasValue($setting, true, 'boolean'); // FLOAT $setting->type = PluginSettings::TYPE_FLOAT; $this->settings->setSettingValue($setting, '1.21'); $this->assertSettingHasValue($setting, 1.21, 'float'); // STRING $setting->type = PluginSettings::TYPE_STRING; $this->settings->setSettingValue($setting, '31xm42'); $this->assertSettingHasValue($setting, '31xm42'); } public function test_setSettingValue_shouldApplyFilterAndNotCast_IfAFilterIsSet() { $this->setUser(); $setting = $this->buildUserSetting('mysystem', 'mytitle'); $setting->type = PluginSettings::TYPE_INT; $self = $this; $setting->transform = function ($value, $userSetting) use ($self, $setting) { $self->assertEquals('31xm42', $value); $self->assertEquals($setting, $userSetting); return '43939kmf3m3'; }; $this->settings->addSetting($setting); $this->settings->setSettingValue($setting, '31xm42'); // should not be casted to int $this->assertSettingHasValue($setting, '43939kmf3m3', 'string'); } public function test_getSettingValue_shouldReturnUncastedDefaultValue_IfNoValueIsSet() { $this->setUser(); $setting = $this->addUserSetting('mydefaultsystem', 'mytitle'); $setting->type = PluginSettings::TYPE_INT; $setting->defaultValue ='mytestvalue'; // should not be casted to int $this->assertSettingHasValue($setting, 'mytestvalue', 'string'); } /** * @expectedException \Exception * @expectedExceptionMessage The setting myusersetting does not exist */ public function test_getSettingValue_shouldThrowException_IfGivenSettingDoesNotExist() { $setting = $this->buildUserSetting('myusersetting', 'mytitle'); $this->settings->getSettingValue($setting); } /** * @expectedException \Exception * @expectedExceptionMessage CoreAdminHome_PluginSettingReadNotAllowed */ public function test_getSettingValue_shouldThrowException_IfUserHasNotEnoughPermissionToReadValue() { $this->setUser(); $setting = $this->addSystemSetting('myusersetting', 'mytitle'); $this->settings->getSettingValue($setting); } public function test_getSettingValue_shouldReturnValue_IfReadbleByCurrentUserIsAllowed() { $this->setUser(); $setting = $this->addSystemSetting('myusersetting', 'mytitle'); $setting->readableByCurrentUser = true; $this->assertEquals('', $this->settings->getSettingValue($setting)); } public function test_getSettingValue_shouldReturnValue_IfValueExistsAndUserHasPermission() { $this->setUser(); $setting = $this->addUserSetting('myusersetting', 'mytitle'); $setting->type = PluginSettings::TYPE_ARRAY; $this->settings->setSettingValue($setting, array(2,3,4)); $this->assertSettingHasValue($setting, array(2,3,4)); } /** * @expectedException \Exception * @expectedExceptionMessage CoreAdminHome_PluginSettingChangeNotAllowed */ public function test_removeSettingValue_shouldThrowException_IfUserHasNotEnoughUserPermissions() { $setting = $this->addUserSetting('myusersetting', 'mytitle'); $this->settings->removeSettingValue($setting); } /** * @expectedException \Exception * @expectedExceptionMessage CoreAdminHome_PluginSettingChangeNotAllowed */ public function test_removeSettingValue_shouldThrowException_IfUserHasNotEnoughAdminPermissions() { $this->setUser(); $setting = $this->addSystemSetting('mysystemsetting', 'mytitle'); $this->settings->removeSettingValue($setting); } public function test_removeSettingValue_shouldRemoveValue_IfValueExistsAndHasEnoughPermissions() { $this->setUser(); $setting = $this->addUserSetting('myusersetting', 'mytitle'); $this->settings->setSettingValue($setting, '12345657'); $this->assertSettingHasValue($setting, '12345657'); $this->settings->removeSettingValue($setting); $this->assertSettingHasValue($setting, null); } public function test_removeSettingValue_shouldRemoveValue_ShouldNotSaveValueInDb() { $this->setSuperUser(); $setting = $this->addSystemSetting('myusersetting', 'mytitle'); $this->settings->setSettingValue($setting, '12345657'); $this->settings->save(); $this->settings->removeSettingValue($setting); $this->assertSettingHasValue($setting, null); // should still have same value $this->assertSettingIsNotSavedInTheDb('myusersetting', '12345657'); } public function test_getSettingsForCurrentUser_shouldOnlyReturnSettingsHavingEnoughAdminPermissions() { $this->setUser(); $this->addSystemSetting('mysystemsetting1', 'mytitle1'); $this->addSystemSetting('mysystemsetting2', 'mytitle2'); $this->addSystemSetting('mysystemsetting3', 'mytitle3'); $this->addSystemSetting('mysystemsetting4', 'mytitle4'); $userSetting = $this->addUserSetting('myusersetting1', 'mytitle5'); $this->assertEquals(array('myusersetting1' => $userSetting), $this->settings->getSettingsForCurrentUser()); // but all of them should be available via getSettings() $this->assertCount(5, $this->settings->getSettings()); } public function test_getSettingsForCurrentUser_shouldReturnAllSettingsIfEnoughPermissionsAndSortThemBySettingOrder() { $this->skipWhenPhp53(); $this->setSuperUser(); $this->addSystemSetting('mysystemsetting1', 'mytitle1'); $this->addSystemSetting('mysystemsetting2', 'mytitle2'); $this->addUserSetting('myusersetting2', 'mytitle6'); $this->addSystemSetting('mysystemsetting3', 'mytitle3'); $this->addSystemSetting('mysystemsetting4', 'mytitle4'); $this->addUserSetting('myusersetting1', 'mytitle5'); $expected = array('myusersetting2', 'myusersetting1', 'mysystemsetting1', 'mysystemsetting2', 'mysystemsetting3', 'mysystemsetting4'); $this->assertEquals($expected, array_keys($this->settings->getSettingsForCurrentUser())); } public function test_save_shouldSaveAllValues() { $this->setSuperUser(); $this->addSystemSetting('mysystemsetting2', 'mytitle2'); $this->settings->setSettingValue($this->addSystemSetting('mysystemsetting1', 'mytitle1'), '111'); $this->settings->setSettingValue($this->addSystemSetting('mysystemsetting4', 'mytitle4'), '4444'); $this->settings->setSettingValue($this->addUserSetting('myusersetting1', 'mytitle5'), '55555'); $this->addSystemSetting('mysystemsetting3', 'mytitle3'); $this->settings->save(); $verifySettings = $this->createSettingsInstance(); $setting1 = $this->buildSystemSetting('mysystemsetting1', 'mytitle1'); $setting2 = $this->buildSystemSetting('mysystemsetting2', 'mytitle2'); $setting3 = $this->buildSystemSetting('mysystemsetting3', 'mytitle3'); $setting4 = $this->buildSystemSetting('mysystemsetting4', 'mytitle4'); $setting5 = $this->buildUserSetting('myusersetting1', 'mytitle5'); $verifySettings->addSetting($setting1); $verifySettings->addSetting($setting2); $verifySettings->addSetting($setting3); $verifySettings->addSetting($setting4); $verifySettings->addSetting($setting5); $this->assertEquals('111', $verifySettings->getSettingValue($setting1)); $this->assertEquals(null, $verifySettings->getSettingValue($setting2)); $this->assertEquals(null, $verifySettings->getSettingValue($setting3)); $this->assertEquals('4444', $verifySettings->getSettingValue($setting4)); $this->assertEquals('55555', $verifySettings->getSettingValue($setting5)); } public function test_removeAllPluginSettings_shouldRemoveAllSettings() { $this->setSuperUser(); $this->addSystemSetting('mysystemsetting3', 'mytitle3'); $this->addSystemSetting('mysystemsetting4', 'mytitle4'); $this->settings->setSettingValue($this->addSystemSetting('mysystemsetting1', 'mytitle1'), '111'); $this->settings->setSettingValue($this->addSystemSetting('mysystemsetting2', 'mytitle2'), '4444'); $this->settings->setSettingValue($this->addUserSetting('myusersetting1', 'mytitle5'), '55555'); $this->settings->save(); $this->settings->removeAllPluginSettings(); $verifySettings = $this->createSettingsInstance(); $setting1 = $this->buildSystemSetting('mysystemsetting1', 'mytitle1'); $setting2 = $this->buildSystemSetting('mysystemsetting2', 'mytitle2'); $setting3 = $this->buildSystemSetting('mysystemsetting3', 'mytitle3'); $setting4 = $this->buildSystemSetting('mysystemsetting4', 'mytitle4'); $setting5 = $this->buildUserSetting('myusersetting1', 'mytitle5'); $verifySettings->addSetting($setting1); $verifySettings->addSetting($setting2); $verifySettings->addSetting($setting3); $verifySettings->addSetting($setting4); $verifySettings->addSetting($setting5); $this->assertEquals(null, $verifySettings->getSettingValue($setting1)); $this->assertEquals(null, $verifySettings->getSettingValue($setting2)); $this->assertEquals(null, $verifySettings->getSettingValue($setting3)); $this->assertEquals(null, $verifySettings->getSettingValue($setting4)); $this->assertEquals(null, $verifySettings->getSettingValue($setting5)); } /** * @expectedException \Exception * @expectedExceptionMessage checkUserHasSuperUserAccess Fake exception */ public function test_removeAllPluginSettings_shouldThrowException_InCaseUserIsNotSuperUser() { $this->setUser(); $this->settings->removeAllPluginSettings(); } public function test_userSetting_shouldGenerateDifferentKey_ThenSystemSetting() { $this->setSuperUser(); $user = $this->buildUserSetting('myname', 'mytitle'); $system = $this->buildSystemSetting('myname', 'mytitle'); $this->assertNotEquals($user->getKey(), $system->getKey()); $this->assertEquals('myname', $system->getKey()); $this->assertEquals('myname#superUserLogin#', $user->getKey()); } public function test_userSetting_shouldGenerateDifferentKey_ForDifferentUsers() { $this->setSuperUser(); $user1 = $this->buildUserSetting('myname', 'mytitle', 'user1'); $user2 = $this->buildUserSetting('myname', 'mytitle', '_user2_'); $user3 = $this->buildUserSetting('myname', 'mytitle'); $this->assertEquals('myname#user1#', $user1->getKey()); $this->assertEquals('myname#_user2_#', $user2->getKey()); $this->assertEquals('myname#superUserLogin#', $user3->getKey()); } public function test_userSetting_shouldSaveValuesPerUser() { $this->setSuperUser(); $user1Login = 'user1'; $user2Login = '_user2_'; $user3Login = null; // current loggged in user $user = $this->buildUserSetting('myuser', 'mytitle', $user1Login); $this->settings->addSetting($user); $this->settings->setSettingValue($user, '111'); $user->setUserLogin($user2Login); $this->settings->setSettingValue($user, '222'); $user->setUserLogin($user3Login); $this->settings->setSettingValue($user, '333'); $user->setUserLogin($user1Login); $this->assertSettingHasValue($user, '111'); $user->setUserLogin($user2Login); $this->assertSettingHasValue($user, '222'); $user->setUserLogin($user3Login); $this->assertSettingHasValue($user, '333'); $user->setUserLogin($user2Login); $this->settings->removeSettingValue($user); $user->setUserLogin($user1Login); $this->assertSettingHasValue($user, '111'); $user->setUserLogin($user2Login); $this->assertSettingHasValue($user, null); $user->setUserLogin($user3Login); $this->assertSettingHasValue($user, '333'); $this->settings->removeAllPluginSettings(); $user->setUserLogin($user1Login); $this->assertSettingHasValue($user, null); $user->setUserLogin($user2Login); $this->assertSettingHasValue($user, null); $user->setUserLogin($user3Login); $this->assertSettingHasValue($user, null); } /** * @expectedException \Exception * @expectedExceptionMessage You do not have the permission to read the settings of a different user */ public function test_userSetting_shouldThrowException_IfSomeoneTriesToReadSettingsFromAnotherUserAndIsNotSuperuser() { $this->setUser(); $this->buildUserSetting('myname', 'mytitle', 'myRandomName'); } public function test_userSetting_shouldBeAbleToSetLoginAndChangeValues_IfUserHasSuperUserAccess() { $this->setSuperUser(); $setting = $this->buildUserSetting('myname', 'mytitle', 'myRandomName'); $this->settings->addSetting($setting); $this->settings->setSettingValue($setting, 5); $this->assertSettingHasValue($setting, 5); $this->settings->removeSettingValue($setting); $this->assertSettingHasValue($setting, null); } public function test_construct_shouldDetectTheNameOfThePluginAutomatically_IfPluginNameNotGiven() { $setting = new Piwik\Plugins\ExampleSettingsPlugin\Settings(); $this->assertEquals('ExampleSettingsPlugin', $setting->getPluginName()); } private function buildUserSetting($name, $title, $userLogin = null) { return new \Piwik\Settings\UserSetting($name, $title, $userLogin); } private function buildSystemSetting($name, $title) { return new \Piwik\Settings\SystemSetting($name, $title); } private function setSuperUser() { $pseudoMockAccess = new FakeAccess; FakeAccess::$superUser = true; Access::setSingletonInstance($pseudoMockAccess); } private function setUser() { $pseudoMockAccess = new FakeAccess; FakeAccess::$idSitesView = array(1); Access::setSingletonInstance($pseudoMockAccess); } private function addSystemSetting($name, $title) { $setting = $this->buildSystemSetting($name, $title); $this->settings->addSetting($setting); return $setting; } private function addUserSetting($name, $title) { $setting = $this->buildUserSetting($name, $title); $this->settings->addSetting($setting); return $setting; } private function assertSettingHasValue($setting, $expectedValue, $expectedType = null) { $value = $this->settings->getSettingValue($setting); $this->assertEquals($expectedValue, $value); if (!is_null($expectedType)) { $this->assertInternalType($expectedType, $value); } } private function assertSettingIsNotSavedInTheDb($settingName, $expectedValue) { // by creating a new instance... $setting = $this->buildSystemSetting($settingName, 'mytitle'); $verifySettings = $this->createSettingsInstance(); $verifySettings->addSetting($setting); $this->assertEquals($expectedValue, $verifySettings->getSettingValue($setting)); } private function createSettingsInstance() { return new CorePluginSettingsTest('ExampleSettingsPlugin'); } }