Fix so save() and delete() update in-memory tags cache (T133) - fixes duplicated tags issue
This commit is contained in:
parent
c269544adc
commit
f575dace67
3 changed files with 160 additions and 30 deletions
|
@ -38,6 +38,7 @@ class kolab_storage_config
|
||||||
private $folders;
|
private $folders;
|
||||||
private $default;
|
private $default;
|
||||||
private $enabled;
|
private $enabled;
|
||||||
|
private $tags;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -175,7 +176,26 @@ class kolab_storage_config
|
||||||
$object['type'] = $type;
|
$object['type'] = $type;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $folder->save($object, self::FOLDER_TYPE . '.' . $object['type'], $object['uid']);
|
$status = $folder->save($object, self::FOLDER_TYPE . '.' . $object['type'], $object['uid']);
|
||||||
|
|
||||||
|
// on success, update cached tags list
|
||||||
|
if ($status && is_array($this->tags)) {
|
||||||
|
$found = false;
|
||||||
|
unset($object['_formatobj']); // we don't need it anymore
|
||||||
|
|
||||||
|
foreach ($this->tags as $idx => $tag) {
|
||||||
|
if ($tag['uid'] == $object['uid']) {
|
||||||
|
$found = true;
|
||||||
|
$this->tags[$idx] = $object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$found) {
|
||||||
|
$this->tags[] = $object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return !empty($status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -199,8 +219,19 @@ class kolab_storage_config
|
||||||
}
|
}
|
||||||
|
|
||||||
$folder = $this->find_folder($object);
|
$folder = $this->find_folder($object);
|
||||||
|
$status = $folder->delete($uid);
|
||||||
|
|
||||||
return $folder->delete($uid);
|
// on success, update cached tags list
|
||||||
|
if ($status && is_array($this->tags)) {
|
||||||
|
foreach ($this->tags as $idx => $tag) {
|
||||||
|
if ($tag['uid'] == $uid) {
|
||||||
|
unset($this->tags[$idx]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -122,12 +122,14 @@ class kolab_storage_folder extends kolab_storage_folder_api
|
||||||
*/
|
*/
|
||||||
public function get_resource_uri()
|
public function get_resource_uri()
|
||||||
{
|
{
|
||||||
if (!empty($this->resource_uri))
|
if (!empty($this->resource_uri)) {
|
||||||
return $this->resource_uri;
|
return $this->resource_uri;
|
||||||
|
}
|
||||||
|
|
||||||
// strip namespace prefix from folder name
|
// strip namespace prefix from folder name
|
||||||
$ns = $this->get_namespace();
|
$ns = $this->get_namespace();
|
||||||
$nsdata = $this->imap->get_namespace($ns);
|
$nsdata = $this->imap->get_namespace($ns);
|
||||||
|
|
||||||
if (is_array($nsdata[0]) && strlen($nsdata[0][0]) && strpos($this->name, $nsdata[0][0]) === 0) {
|
if (is_array($nsdata[0]) && strlen($nsdata[0][0]) && strpos($this->name, $nsdata[0][0]) === 0) {
|
||||||
$subpath = substr($this->name, strlen($nsdata[0][0]));
|
$subpath = substr($this->name, strlen($nsdata[0][0]));
|
||||||
if ($ns == 'other') {
|
if ($ns == 'other') {
|
||||||
|
@ -604,7 +606,8 @@ class kolab_storage_folder extends kolab_storage_folder_api
|
||||||
* @param array $object The array that holds the data of the object.
|
* @param array $object The array that holds the data of the object.
|
||||||
* @param string $type The type of the kolab object.
|
* @param string $type The type of the kolab object.
|
||||||
* @param string $uid The UID of the old object if it existed before
|
* @param string $uid The UID of the old object if it existed before
|
||||||
* @return boolean True on success, false on error
|
*
|
||||||
|
* @return mixed False on error or IMAP message UID on success
|
||||||
*/
|
*/
|
||||||
public function save(&$object, $type = null, $uid = null)
|
public function save(&$object, $type = null, $uid = null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,7 +9,7 @@ class kolab_storage_config_test extends PHPUnit_Framework_TestCase
|
||||||
'date' => 'Mon, 20 Apr 2015 15:30:30 UTC',
|
'date' => 'Mon, 20 Apr 2015 15:30:30 UTC',
|
||||||
'subject' => 'Archived',
|
'subject' => 'Archived',
|
||||||
);
|
);
|
||||||
private $url_personal = 'imap:///user/john.doe%40example.org/Archive/9?message-id=%3C1225270%40example.org%3E&date=Mon%2C+20+Apr+2015+15%3A30%3A30+UTC&subject=Archived';
|
private $url_personal = 'imap:///user/$user/Archive/9?message-id=%3C1225270%40example.org%3E&date=Mon%2C+20+Apr+2015+15%3A30%3A30+UTC&subject=Archived';
|
||||||
|
|
||||||
private $params_shared = array(
|
private $params_shared = array(
|
||||||
'folder' => 'Shared Folders/shared/Collected',
|
'folder' => 'Shared Folders/shared/Collected',
|
||||||
|
@ -29,36 +29,54 @@ class kolab_storage_config_test extends PHPUnit_Framework_TestCase
|
||||||
);
|
);
|
||||||
private $url_other = 'imap:///user/lucy.white%40example.org/Mailings/378?message-id=%3C22448899%40example.org%3E&date=Tue%2C+14+Apr+2015+14%3A14%3A30+%2B0200&subject=Happy+Holidays';
|
private $url_other = 'imap:///user/lucy.white%40example.org/Mailings/378?message-id=%3C22448899%40example.org%3E&date=Tue%2C+14+Apr+2015+14%3A14%3A30+%2B0200&subject=Happy+Holidays';
|
||||||
|
|
||||||
|
|
||||||
public static function setUpBeforeClass()
|
public static function setUpBeforeClass()
|
||||||
{
|
{
|
||||||
require_once __DIR__ . '/../../libkolab/libkolab.php';
|
$rcube = rcmail::get_instance();
|
||||||
|
$rcube->plugins->load_plugin('libkolab', true, true);
|
||||||
|
|
||||||
$rcube = rcube::get_instance();
|
if ($rcube->config->get('tests_username')) {
|
||||||
$rcube->user = null;
|
$authenticated = $rcube->login(
|
||||||
|
$rcube->config->get('tests_username'),
|
||||||
$lib = new libkolab($rcube->plugins);
|
$rcube->config->get('tests_password'),
|
||||||
$lib->init();
|
$rcube->config->get('default_host'),
|
||||||
|
false
|
||||||
// fake some session data to make storage work without an actual IMAP connection
|
|
||||||
$_SESSION['username'] = 'john.doe@example.org';
|
|
||||||
$_SESSION['imap_delimiter'] = '/';
|
|
||||||
$_SESSION['imap_namespace'] = array(
|
|
||||||
'personal' => array(array('','/')),
|
|
||||||
'other' => array(array('Other Users/','/')),
|
|
||||||
'shared' => array(array('Shared Folders/','/')),
|
|
||||||
'prefix' => '',
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!$authenticated) {
|
||||||
|
throw new Exception('IMAP login failed for user ' . $rcube->config->get('tests_username'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for defult groupware folders and clear them
|
||||||
|
$imap = $rcube->get_storage();
|
||||||
|
$folders = $imap->list_folders('', '*');
|
||||||
|
|
||||||
|
foreach (array('Configuration') as $folder) {
|
||||||
|
if (in_array($folder, $folders)) {
|
||||||
|
if (!$imap->clear_folder($folder)) {
|
||||||
|
throw new Exception("Failed to clear folder '$folder'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new Exception("Default folder '$folder' doesn't exits in test user account");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new Exception('Missing test account username/password in config-test.inc.php');
|
||||||
|
}
|
||||||
|
|
||||||
|
kolab_storage::setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_001_build_member_url()
|
function test_001_build_member_url()
|
||||||
{
|
{
|
||||||
$rcube = rcube::get_instance();
|
$rcube = rcube::get_instance();
|
||||||
$this->assertEquals('john.doe@example.org', $rcube->get_user_name());
|
$email = $rcube->get_user_email();
|
||||||
|
$personal = str_replace('$user', urlencode($email), $this->url_personal);
|
||||||
|
|
||||||
// personal namespace
|
// personal namespace
|
||||||
$url = kolab_storage_config::build_member_url($this->params_personal);
|
$url = kolab_storage_config::build_member_url($this->params_personal);
|
||||||
$this->assertEquals($this->url_personal, $url);
|
$this->assertEquals($personal, $url);
|
||||||
|
|
||||||
// shared namespace
|
// shared namespace
|
||||||
$url = kolab_storage_config::build_member_url($this->params_shared);
|
$url = kolab_storage_config::build_member_url($this->params_shared);
|
||||||
|
@ -71,8 +89,12 @@ class kolab_storage_config_test extends PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
function test_002_parse_member_url()
|
function test_002_parse_member_url()
|
||||||
{
|
{
|
||||||
|
$rcube = rcube::get_instance();
|
||||||
|
$email = $rcube->get_user_email();
|
||||||
|
$personal = str_replace('$user', urlencode($email), $this->url_personal);
|
||||||
|
|
||||||
// personal namespace
|
// personal namespace
|
||||||
$params = kolab_storage_config::parse_member_url($this->url_personal);
|
$params = kolab_storage_config::parse_member_url($personal);
|
||||||
$this->assertEquals($this->params_personal['uid'], $params['uid']);
|
$this->assertEquals($this->params_personal['uid'], $params['uid']);
|
||||||
$this->assertEquals($this->params_personal['folder'], $params['folder']);
|
$this->assertEquals($this->params_personal['folder'], $params['folder']);
|
||||||
$this->assertEquals($this->params_personal['subject'], $params['params']['subject']);
|
$this->assertEquals($this->params_personal['subject'], $params['params']['subject']);
|
||||||
|
@ -109,6 +131,80 @@ class kolab_storage_config_test extends PHPUnit_Framework_TestCase
|
||||||
$this->assertEquals($params['uid'], $params_['uid']);
|
$this->assertEquals($params['uid'], $params_['uid']);
|
||||||
$this->assertEquals($params['folder'], $params_['folder']);
|
$this->assertEquals($params['folder'], $params_['folder']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test relation/tag objects creation
|
||||||
|
* These objects will be used by following tests
|
||||||
|
*/
|
||||||
|
function test_save()
|
||||||
|
{
|
||||||
|
$config = kolab_storage_config::get_instance();
|
||||||
|
$tags = array(
|
||||||
|
array(
|
||||||
|
'category' => 'tag',
|
||||||
|
'name' => 'test1',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'category' => 'tag',
|
||||||
|
'name' => 'test2',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'category' => 'tag',
|
||||||
|
'name' => 'test3',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'category' => 'tag',
|
||||||
|
'name' => 'test4',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($tags as $tag) {
|
||||||
|
$result = $config->save($tag, 'relation');
|
||||||
|
|
||||||
|
$this->assertTrue(!empty($result));
|
||||||
|
$this->assertTrue(!empty($tag['uid']));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests "race condition" in tags handling (T133)
|
||||||
|
*/
|
||||||
|
function test_T133()
|
||||||
|
{
|
||||||
|
$config = kolab_storage_config::get_instance();
|
||||||
|
|
||||||
|
// get tags
|
||||||
|
$tags = $config->get_tags();
|
||||||
|
$this->assertCount(4, $tags);
|
||||||
|
|
||||||
|
// create a tag
|
||||||
|
$tag = array(
|
||||||
|
'category' => 'tag',
|
||||||
|
'name' => 'new',
|
||||||
|
);
|
||||||
|
$result = $config->save($tag, 'relation');
|
||||||
|
$this->assertTrue(!empty($result));
|
||||||
|
|
||||||
|
// get tags again, make sure it contains the new tag
|
||||||
|
$tags = $config->get_tags();
|
||||||
|
$this->assertCount(5, $tags);
|
||||||
|
|
||||||
|
// update a tag
|
||||||
|
$tag['name'] = 'new-tag';
|
||||||
|
$result = $config->save($tag, 'relation');
|
||||||
|
$this->assertTrue(!empty($result));
|
||||||
|
|
||||||
|
// get tags again, make sure it contains the new tag
|
||||||
|
$tags = $config->get_tags();
|
||||||
|
$this->assertCount(5, $tags);
|
||||||
|
$this->assertSame('new-tag', $tags[4]['name']);
|
||||||
|
|
||||||
|
// remove a tag
|
||||||
|
$result = $config->delete($tag['uid']);
|
||||||
|
$this->assertTrue(!empty($result));
|
||||||
|
|
||||||
|
// get tags again, make sure it contains the new tag
|
||||||
|
$tags = $config->get_tags();
|
||||||
|
$this->assertCount(4, $tags);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue