diff --git a/lib/private/legacy/preferences.php b/lib/private/legacy/preferences.php index 71d0b749f4..060274085f 100644 --- a/lib/private/legacy/preferences.php +++ b/lib/private/legacy/preferences.php @@ -84,14 +84,14 @@ class OC_Preferences{ * @param string $app app * @param string $key key * @param string $value value - * @return bool + * @param string $preCondition only set value if the key had a specific value before + * @return bool true if value was set, otherwise false * * Adds a value to the preferences. If the key did not exist before, it * will be added automagically. */ - public static function setValue( $user, $app, $key, $value ) { - self::$object->setValue( $user, $app, $key, $value ); - return true; + public static function setValue( $user, $app, $key, $value, $preCondition = null ) { + return self::$object->setValue( $user, $app, $key, $value, $preCondition ); } /** diff --git a/lib/private/preferences.php b/lib/private/preferences.php index 0dc5b26810..d1db25bbf0 100644 --- a/lib/private/preferences.php +++ b/lib/private/preferences.php @@ -165,44 +165,56 @@ class Preferences { * @param string $app app * @param string $key key * @param string $value value + * @param string $preCondition only set value if the key had a specific value before + * @return bool true if value was set, otherwise false * * Adds a value to the preferences. If the key did not exist before, it * will be added automagically. */ - public function setValue($user, $app, $key, $value) { + public function setValue($user, $app, $key, $value, $preCondition = null) { // Check if the key does exist $query = 'SELECT COUNT(*) FROM `*PREFIX*preferences`' . ' WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?'; $count = $this->conn->fetchColumn($query, array($user, $app, $key)); $exists = $count > 0; - if (!$exists) { + $affectedRows = 0; + + if (!$exists && $preCondition === null) { $data = array( 'userid' => $user, 'appid' => $app, 'configkey' => $key, 'configvalue' => $value, ); - $this->conn->insert('*PREFIX*preferences', $data); - } else { - $data = array( - 'configvalue' => $value, - ); - $where = array( - 'userid' => $user, - 'appid' => $app, - 'configkey' => $key, - ); - $this->conn->update('*PREFIX*preferences', $data, $where); + $affectedRows = $this->conn->insert('*PREFIX*preferences', $data); + } elseif ($exists) { + $data = array($value, $user, $app, $key); + $sql = "UPDATE `*PREFIX*preferences` SET `configvalue` = ?" + . " WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?"; + + if ($preCondition !== null) { + if (\OC_Config::getValue( 'dbtype', 'sqlite' ) === 'oci') { + //oracle hack: need to explicitly cast CLOB to CHAR for comparison + $sql .= " AND to_char(`configvalue`) = ?"; + } else { + $sql .= " AND `configvalue` = ?"; + } + $data[] = $preCondition; + } + $affectedRows = $this->conn->executeUpdate($sql, $data); } // only add to the cache if we already loaded data for the user - if (isset($this->cache[$user])) { + if ($affectedRows > 0 && isset($this->cache[$user])) { if (!isset($this->cache[$user][$app])) { $this->cache[$user][$app] = array(); } $this->cache[$user][$app][$key] = $value; } + + return ($affectedRows > 0) ? true : false; + } /** diff --git a/tests/lib/preferences.php b/tests/lib/preferences.php index 93c9704f6c..d31b0257ba 100644 --- a/tests/lib/preferences.php +++ b/tests/lib/preferences.php @@ -97,6 +97,42 @@ class Test_Preferences extends PHPUnit_Framework_TestCase { $this->assertEquals('othervalue', $value); } + public function testSetValueWithPreCondition() { + // remove existing key + $this->assertTrue(\OC_Preferences::deleteKey('Someuser', 'setvalueapp', 'newkey')); + + // add new preference with pre-condition should fails + $this->assertFalse(\OC_Preferences::setValue('Someuser', 'setvalueapp', 'newkey', 'newvalue', 'preCondition')); + $query = \OC_DB::prepare('SELECT `configvalue` FROM `*PREFIX*preferences` WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?'); + $result = $query->execute(array('Someuser', 'setvalueapp', 'newkey')); + $row = $result->fetchRow(); + $this->assertFalse($row); + + // add new preference without pre-condition should insert the new value + $this->assertTrue(\OC_Preferences::setValue('Someuser', 'setvalueapp', 'newkey', 'newvalue')); + $query = \OC_DB::prepare('SELECT `configvalue` FROM `*PREFIX*preferences` WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?'); + $result = $query->execute(array('Someuser', 'setvalueapp', 'newkey')); + $row = $result->fetchRow(); + $value = $row['configvalue']; + $this->assertEquals('newvalue', $value); + + // wrong pre-condition, value should stay the same + $this->assertFalse(\OC_Preferences::setValue('Someuser', 'setvalueapp', 'newkey', 'othervalue', 'preCondition')); + $query = \OC_DB::prepare('SELECT `configvalue` FROM `*PREFIX*preferences` WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?'); + $result = $query->execute(array('Someuser', 'setvalueapp', 'newkey')); + $row = $result->fetchRow(); + $value = $row['configvalue']; + $this->assertEquals('newvalue', $value); + + // correct pre-condition, value should change + $this->assertTrue(\OC_Preferences::setValue('Someuser', 'setvalueapp', 'newkey', 'othervalue', 'newvalue')); + $query = \OC_DB::prepare('SELECT `configvalue` FROM `*PREFIX*preferences` WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?'); + $result = $query->execute(array('Someuser', 'setvalueapp', 'newkey')); + $row = $result->fetchRow(); + $value = $row['configvalue']; + $this->assertEquals('othervalue', $value); + } + public function testDeleteKey() { $this->assertTrue(\OC_Preferences::deleteKey('Deleteuser', 'deleteapp', 'deletekey')); $query = \OC_DB::prepare('SELECT `configvalue` FROM `*PREFIX*preferences` WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?'); @@ -165,19 +201,11 @@ class Test_Preferences_Object extends PHPUnit_Framework_TestCase { ) )); $connectionMock->expects($this->once()) - ->method('update') - ->with($this->equalTo('*PREFIX*preferences'), - $this->equalTo( - array( - 'configvalue' => 'v2', - )), - $this->equalTo( - array( - 'userid' => 'grg', - 'appid' => 'bar', - 'configkey' => 'foo', - ) - )); + ->method('executeUpdate') + ->with($this->equalTo("UPDATE `*PREFIX*preferences` SET `configvalue` = ?" + . " WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?"), + $this->equalTo(array('v2', 'grg', 'bar', 'foo')) + ); $preferences = new OC\Preferences($connectionMock); $preferences->setValue('grg', 'bar', 'foo', 'v1');