File indexing completed on 2024-11-24 04:43:49

0001 /*
0002     SPDX-FileCopyrightText: 2015-2021 Krzysztof Nowicki <krissn@op.pl>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "ewsmodifymailjob.h"
0008 
0009 #include <Akonadi/MessageFlags>
0010 
0011 #include <KLocalizedString>
0012 
0013 #include "ewsmailhandler.h"
0014 
0015 #include "ewsresource_debug.h"
0016 
0017 using namespace Akonadi;
0018 
0019 constexpr unsigned ChunkSize = 10;
0020 
0021 EwsModifyMailJob::EwsModifyMailJob(EwsClient &client, const Akonadi::Item::List &items, const QSet<QByteArray> &parts, QObject *parent)
0022     : EwsModifyItemJob(client, items, parts, parent)
0023     , mChunkedJob(ChunkSize)
0024 {
0025 }
0026 
0027 EwsModifyMailJob::~EwsModifyMailJob() = default;
0028 
0029 void EwsModifyMailJob::start()
0030 {
0031     bool doSubmit = false;
0032     EwsId itemId;
0033 
0034     EwsUpdateItemRequest::ItemChange::List itemChanges;
0035     itemChanges.reserve(mItems.size());
0036     for (const Item &item : std::as_const(mItems)) {
0037         itemId = EwsId(item.remoteId(), item.remoteRevision());
0038 
0039         if (mParts.contains("FLAGS")) {
0040             EwsUpdateItemRequest::ItemChange ic(itemId, EwsItemTypeMessage);
0041             QHash<EwsPropertyField, QVariant> propertyHash = EwsMailHandler::writeFlags(item.flags());
0042 
0043             for (auto it = propertyHash.cbegin(), end = propertyHash.cend(); it != end; ++it) {
0044                 EwsUpdateItemRequest::Update *upd;
0045                 if (it.value().isNull()) {
0046                     upd = new EwsUpdateItemRequest::DeleteUpdate(it.key());
0047                 } else {
0048                     upd = new EwsUpdateItemRequest::SetUpdate(it.key(), it.value());
0049                 }
0050                 ic.addUpdate(upd);
0051             }
0052 
0053             itemChanges.append(ic);
0054             doSubmit = true;
0055         }
0056     }
0057 
0058     if (doSubmit) {
0059         mChunkedJob.setItems(itemChanges);
0060         mChunkedJob.start(
0061             [this](const EwsUpdateItemRequest::ItemChange::List::const_iterator &firstChange,
0062                    const EwsUpdateItemRequest::ItemChange::List::const_iterator &lastChange) {
0063                 auto req = new EwsUpdateItemRequest(mClient, this);
0064                 req->addItemChanges(firstChange, lastChange);
0065                 return req;
0066             },
0067             [](EwsUpdateItemRequest *req) {
0068                 return req->responses();
0069             },
0070             [this](unsigned int progress) {
0071                 Q_EMIT reportPercent(progress);
0072             },
0073             [this](bool success, const QString &error) {
0074                 updateItemsFinished(success, error);
0075             });
0076     } else {
0077         emitResult();
0078     }
0079 }
0080 
0081 void EwsModifyMailJob::updateItemsFinished(bool success, const QString &error)
0082 {
0083     if (!success) {
0084         setErrorText(error);
0085         emitResult();
0086         return;
0087     }
0088 
0089     Item::List::iterator it = mItems.begin();
0090     for (const auto &resp : mChunkedJob.responses()) {
0091         if (!resp.isSuccess()) {
0092             setErrorText(i18nc("@info:status", "Item update failed: ") + resp.responseMessage());
0093             emitResult();
0094             return;
0095         }
0096 
0097         /* In general EWS guarantees that the order of response items will match the order of request items.
0098          * It is therefore safe to iterate these in parallel. */
0099         if (it->remoteId() == resp.itemId().id()) {
0100             it->setRemoteRevision(resp.itemId().changeKey());
0101             ++it;
0102         } else {
0103             setErrorText(i18nc("@info:status", "Item out of order while processing update item response."));
0104             emitResult();
0105             return;
0106         }
0107     }
0108     emitResult();
0109 }
0110 
0111 #include "moc_ewsmodifymailjob.cpp"