File indexing completed on 2024-06-23 05:07:02
0001 /* 0002 SPDX-FileCopyrightText: 2008 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "itemlinkhandler.h" 0008 0009 #include "akonadiserver_debug.h" 0010 #include "connection.h" 0011 #include "handlerhelper.h" 0012 #include "storage/collectionqueryhelper.h" 0013 #include "storage/datastore.h" 0014 #include "storage/itemqueryhelper.h" 0015 #include "storage/selectquerybuilder.h" 0016 #include "storage/transaction.h" 0017 0018 #include "private/scope_p.h" 0019 0020 using namespace Akonadi; 0021 using namespace Akonadi::Server; 0022 0023 ItemLinkHandler::ItemLinkHandler(AkonadiServer &akonadi) 0024 : Handler(akonadi) 0025 { 0026 } 0027 0028 bool ItemLinkHandler::parseStream() 0029 { 0030 const auto &cmd = Protocol::cmdCast<Protocol::LinkItemsCommand>(m_command); 0031 0032 const Collection collection = HandlerHelper::collectionFromScope(cmd.destination(), connection()->context()); 0033 if (!collection.isVirtual()) { 0034 return failureResponse(QStringLiteral("Can't link items to non-virtual collections")); 0035 } 0036 0037 /* FIXME BIN 0038 Resource originalContext; 0039 Scope::SelectionScope itemSelectionScope = Scope::selectionScopeFromByteArray(m_streamParser->peekString()); 0040 if (itemSelectionScope != Scope::None) { 0041 m_streamParser->readString(); 0042 // Unset Resource context if destination collection is specified using HRID/RID, 0043 // because otherwise the Resource context is relative to the destination collection 0044 // instead of the source collection (collection context) 0045 if ((mDestinationScope.scope() == Scope::HierarchicalRid || mDestinationScope.scope() == Scope::Rid) && itemSelectionScope == Scope::Rid) { 0046 originalContext = connection()->context()->resource(); 0047 connection()->context()->setResource(Resource()); 0048 } 0049 } 0050 Scope itemScope(itemSelectionScope); 0051 itemScope.parseScope(m_streamParser); 0052 */ 0053 0054 SelectQueryBuilder<PimItem> qb; 0055 ItemQueryHelper::scopeToQuery(cmd.items(), connection()->context(), qb); 0056 0057 /* 0058 if (originalContext.isValid()) { 0059 connection()->context()->setResource(originalContext); 0060 } 0061 */ 0062 0063 if (!qb.exec()) { 0064 return failureResponse(QStringLiteral("Unable to execute item query")); 0065 } 0066 0067 const PimItem::List items = qb.result(); 0068 const bool createLinks = (cmd.action() == Protocol::LinkItemsCommand::Link); 0069 0070 DataStore *store = connection()->storageBackend(); 0071 Transaction transaction(store, createLinks ? QStringLiteral("LINK") : QStringLiteral("UNLINK")); 0072 0073 PimItem::List toLink; 0074 PimItem::List toUnlink; 0075 for (const PimItem &item : items) { 0076 const bool alreadyLinked = collection.relatesToPimItem(item); 0077 bool result = true; 0078 if (createLinks && !alreadyLinked) { 0079 result = collection.addPimItem(item); 0080 toLink << item; 0081 } else if (!createLinks && alreadyLinked) { 0082 result = collection.removePimItem(item); 0083 toUnlink << item; 0084 } 0085 if (!result) { 0086 return failureResponse(QStringLiteral("Failed to modify item reference")); 0087 } 0088 } 0089 0090 if (!transaction.commit()) { 0091 return failureResponse(QStringLiteral("Cannot commit transaction.")); 0092 } 0093 0094 if (!toLink.isEmpty()) { 0095 store->notificationCollector()->itemsLinked(toLink, collection); 0096 } else if (!toUnlink.isEmpty()) { 0097 store->notificationCollector()->itemsUnlinked(toUnlink, collection); 0098 } 0099 0100 return successResponse<Protocol::LinkItemsResponse>(); 0101 }