Wed, 26 Feb 2025 00:35:17 -0600
Add find_or_create method to Purple.ContactManager
Testing Done:
Ran the unit test in valgrind.
Bugs closed: PIDGIN-18037
Reviewed at https://reviews.imfreedom.org/r/3846/
--- a/libpurple/purplecontactmanager.c Fri Feb 21 00:03:24 2025 -0600 +++ b/libpurple/purplecontactmanager.c Wed Feb 26 00:35:17 2025 -0600 @@ -677,6 +677,46 @@ return NULL; } +PurpleContact * +purple_contact_manager_find_or_create(PurpleContactManager *manager, + PurpleAccount *account, const char *id, + gboolean *found) +{ + PurpleContact *contact = NULL; + PurpleContact *new_contact = NULL; + GListStore *contacts = NULL; + guint position = 0; + gboolean new_contact_found = FALSE; + + g_return_val_if_fail(PURPLE_IS_CONTACT_MANAGER(manager), NULL); + g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL); + g_return_val_if_fail(!purple_strempty(id), NULL); + + new_contact = purple_contact_new(account, id); + + contacts = g_hash_table_lookup(manager->accounts, account); + if(G_IS_LIST_STORE(contacts)) { + new_contact_found = + g_list_store_find_with_equal_func(contacts, new_contact, + purple_contact_manager_find_with_id_helper, + &position); + } + + if(new_contact_found) { + g_clear_object(&new_contact); + contact = g_list_model_get_item(G_LIST_MODEL(contacts), position); + } else { + purple_contact_manager_add(manager, new_contact); + contact = new_contact; + } + + if(found != NULL) { + *found = new_contact_found; + } + + return contact; +} + void purple_contact_manager_add_person(PurpleContactManager *manager, PurplePerson *person)
--- a/libpurple/purplecontactmanager.h Fri Feb 21 00:03:24 2025 -0600 +++ b/libpurple/purplecontactmanager.h Wed Feb 26 00:35:17 2025 -0600 @@ -156,6 +156,21 @@ PurpleContact *purple_contact_manager_find_with_id(PurpleContactManager *manager, PurpleAccount *account, const gchar *id); /** + * purple_contact_manager_find_or_create: + * @account: the account whose contact to find + * @id: the id of the contact to find + * @found: (out) (optional): a return address for a boolean which will be set to true + * if the contact was found + * + * Looks for a [class@Purple.Contact] that belongs to @account with an id of @id + * or creates a new one. + * + * Returns: (transfer full): The [class@Purple.Contact] that was either found or newly created. + */ +PURPLE_AVAILABLE_IN_3_0 +PurpleContact *purple_contact_manager_find_or_create(PurpleContactManager *manager, PurpleAccount *account, const char *id, gboolean *found); + +/** * purple_contact_manager_add_person: * @manager: The instance. * @person: The [class@Purple.Person to add].
--- a/libpurple/tests/test_contact_manager.c Fri Feb 21 00:03:24 2025 -0600 +++ b/libpurple/tests/test_contact_manager.c Wed Feb 26 00:35:17 2025 -0600 @@ -247,6 +247,39 @@ g_clear_object(&manager); } +static void +test_purple_contact_manager_find_or_create(void) { + PurpleAccount *account = NULL; + PurpleContact *contact1 = NULL; + PurpleContact *contact2 = NULL; + gboolean found; + PurpleContactManager *manager = NULL; + + manager = g_object_new(PURPLE_TYPE_CONTACT_MANAGER, NULL); + + account = purple_account_new("test", "test"); + + found = TRUE; + contact1 = purple_contact_manager_find_or_create(manager, account, "id-1", + &found); + g_assert_true(PURPLE_IS_CONTACT(contact1)); + g_assert_false(found); + contact2 = purple_contact_manager_find_or_create(manager, account, "id-1", + &found); + g_assert_true(found); + g_assert_true(contact1 == contact2); + + /* Cleanup. */ + g_object_unref(contact2); + /* Calling ContactManager.remove so g_assert_finalize doesn't complain about + * weak references. + */ + purple_contact_manager_remove(manager, contact1); + g_assert_finalize_object(contact1); + g_assert_finalize_object(manager); + g_assert_finalize_object(account); +} + /****************************************************************************** * Person Tests *****************************************************************************/ @@ -443,6 +476,8 @@ test_purple_contact_manager_find_with_username); g_test_add_func("/contact-manager/find/with-id", test_purple_contact_manager_find_with_id); + g_test_add_func("/contact-manager/find-or-create", + test_purple_contact_manager_find_or_create); g_test_add_func("/contact-manager/person/add-remove", test_purple_contact_manager_person_add_remove);