mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
upload folders to server
This commit is contained in:
parent
65d93d4b6d
commit
67d9104374
@ -139,6 +139,12 @@ bool Database::execQuery(QSqlQuery &query) {
|
||||
return query.exec();
|
||||
}
|
||||
|
||||
QSqlQuery Database::prepare(const QString &sql) {
|
||||
QSqlQuery query(db_);
|
||||
query.prepare(sql);
|
||||
return query;
|
||||
}
|
||||
|
||||
int Database::version() const {
|
||||
if (version_ >= 0) return version_;
|
||||
|
||||
|
@ -22,6 +22,7 @@ public:
|
||||
bool transaction();
|
||||
bool commit();
|
||||
bool execQuery(QSqlQuery &query);
|
||||
QSqlQuery prepare(const QString& sql);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -7,6 +7,9 @@ namespace jop {
|
||||
|
||||
enum Table { UndefinedTable, FoldersTable, NotesTable, ChangesTable };
|
||||
|
||||
// Note "DELETE" is a reserved keyword so we need to use "DEL"
|
||||
enum HttpMethod { UndefinedMethod, HEAD, GET, PUT, POST, DEL, PATCH };
|
||||
|
||||
}
|
||||
|
||||
#endif // ENUM_H
|
||||
|
@ -37,6 +37,18 @@ int BaseModel::count(Table table) {
|
||||
return output;
|
||||
}
|
||||
|
||||
bool BaseModel::load(const QString &id) {
|
||||
QSqlQuery q(jop::db().database());
|
||||
q.prepare("SELECT " + BaseModel::tableFieldNames(table()).join(",") + " FROM " + BaseModel::tableName(table()) + " WHERE id = :id");
|
||||
q.bindValue(":id", id);
|
||||
jop::db().execQuery(q);
|
||||
q.next();
|
||||
if (!jop::db().errorCheck(q)) return false;
|
||||
if (!q.isValid()) return false;
|
||||
|
||||
loadSqlQuery(q);
|
||||
}
|
||||
|
||||
bool BaseModel::save() {
|
||||
bool isNew = this->isNew();
|
||||
|
||||
@ -333,7 +345,10 @@ int BaseModel::Value::toInt() const {
|
||||
}
|
||||
|
||||
QString BaseModel::Value::toString() const {
|
||||
return stringValue_;
|
||||
if (type_ == QMetaType::QString) return stringValue_;
|
||||
if (type_ == QMetaType::Int) return QString::number(intValue_);
|
||||
qCritical("Unreachable");
|
||||
return QString("");
|
||||
}
|
||||
|
||||
QVariant BaseModel::Value::toQVariant() const {
|
||||
|
@ -43,6 +43,7 @@ public:
|
||||
BaseModel(const QSqlQuery& query);
|
||||
QStringList changedFields() const;
|
||||
static int count(jop::Table table);
|
||||
bool load(const QString& id);
|
||||
bool save();
|
||||
bool dispose();
|
||||
|
||||
|
@ -94,3 +94,10 @@ QStringList Change::mergedFields() const {
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
void Change::disposeByItemId(const QString &itemId) {
|
||||
QString sql = QString("DELETE FROM %1 WHERE item_id = :item_id").arg(BaseModel::tableName(jop::ChangesTable));
|
||||
QSqlQuery q = jop::db().prepare(sql);
|
||||
q.bindValue(":item_id", itemId);
|
||||
jop::db().execQuery(q);
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ public:
|
||||
|
||||
static QVector<Change> all(int limit = 100);
|
||||
static QVector<Change> mergedChanges(const QVector<Change> &changes);
|
||||
static void disposeByItemId(const QString& itemId);
|
||||
|
||||
void addMergedField(const QString& name);
|
||||
QStringList mergedFields() const;
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <QSettings>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonParseError>
|
||||
#include <QBuffer>
|
||||
|
||||
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include "synchronizer.h"
|
||||
#include "models/folder.h"
|
||||
#include "models/note.h"
|
||||
#include "models/change.h"
|
||||
|
||||
using namespace jop;
|
||||
|
||||
@ -14,58 +13,54 @@ void Synchronizer::start() {
|
||||
qDebug() << "Starting synchronizer...";
|
||||
|
||||
QVector<Change> changes = Change::all();
|
||||
foreach (Change& change, changes) {
|
||||
changes = Change::mergedChanges(changes);
|
||||
foreach (Change change, changes) {
|
||||
jop::Table itemType = (jop::Table)change.value("item_type").toInt();
|
||||
QString itemId = change.value("item_id").toString();
|
||||
Change::Type type = (Change::Type)change.value("type").toInt();
|
||||
|
||||
qDebug() << itemId << itemType << type;
|
||||
|
||||
if (itemType == jop::FoldersTable) {
|
||||
|
||||
if (type == Change::Create) {
|
||||
|
||||
Folder folder;
|
||||
folder.load(itemId);
|
||||
QUrlQuery data = valuesToUrlQuery(folder.values());
|
||||
api_.put("folders/" + folder.id().toString(), QUrlQuery(), data, "putFolder:" + folder.id().toString());
|
||||
|
||||
} else if (type == Change::Update) {
|
||||
|
||||
Folder folder;
|
||||
folder.load(itemId);
|
||||
QStringList mergedFields = change.mergedFields();
|
||||
QUrlQuery data;
|
||||
foreach (QString field, mergedFields) {
|
||||
data.addQueryItem(field, folder.value(field).toString());
|
||||
}
|
||||
api_.patch("folders/" + folder.id().toString(), QUrlQuery(), data, "patchFolder:" + folder.id().toString());
|
||||
|
||||
} else if (type == Change::Delete) {
|
||||
|
||||
api_.del("folders/" + itemId, QUrlQuery(), QUrlQuery(), "deleteFolder:" + itemId);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// QSqlQuery query;
|
||||
|
||||
// std::vector<Folder> folders;
|
||||
// query = db_.query("SELECT " + Folder::dbFields().join(',') + " FROM folders WHERE synced = 0");
|
||||
// query.exec();
|
||||
|
||||
// while (query.next()) {
|
||||
// Folder folder;
|
||||
// folder.fromSqlQuery(query);
|
||||
// folders.push_back(folder);
|
||||
// }
|
||||
|
||||
// QList<Note> notes;
|
||||
// query = db_.query("SELECT " + Note::dbFields().join(',') + " FROM notes WHERE synced = 0");
|
||||
// query.exec();
|
||||
|
||||
// while (query.next()) {
|
||||
// Note note;
|
||||
// note.fromSqlQuery(query);
|
||||
// notes << note;
|
||||
// }
|
||||
|
||||
// for (size_t i = 0; i < folders.size(); i++) {
|
||||
// Folder folder = folders[i];
|
||||
// QUrlQuery data;
|
||||
// data.addQueryItem("id", folder.id());
|
||||
// data.addQueryItem("title", folder.title());
|
||||
// data.addQueryItem("created_time", QString::number(folder.createdTime()));
|
||||
// data.addQueryItem("updated_time", QString::number(folder.updatedTime()));
|
||||
// api_.put("folders/" + folder.id(), QUrlQuery(), data, "putFolder:" + folder.id());
|
||||
// }
|
||||
|
||||
// return;
|
||||
|
||||
// for (int i = 0; i < notes.size(); i++) {
|
||||
// Note note = notes[i];
|
||||
// QUrlQuery data;
|
||||
// data.addQueryItem("id", note.id());
|
||||
// data.addQueryItem("title", note.title());
|
||||
// data.addQueryItem("body", note.body());
|
||||
// data.addQueryItem("created_time", QString::number(note.createdTime()));
|
||||
// data.addQueryItem("updated_time", QString::number(note.updatedTime()));
|
||||
// api_.put("notes/" + note.id(), QUrlQuery(), data, "putNote:" + note.id());
|
||||
// }
|
||||
QUrlQuery Synchronizer::valuesToUrlQuery(const QHash<QString, Change::Value>& values) const {
|
||||
QUrlQuery query;
|
||||
for (QHash<QString, Change::Value>::const_iterator it = values.begin(); it != values.end(); ++it) {
|
||||
query.addQueryItem(it.key(), it.value().toString());
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
||||
void Synchronizer::api_requestDone(const QJsonObject& response, const QString& tag) {
|
||||
QSqlQuery query;
|
||||
qDebug() << "WebApi: done" << tag;
|
||||
|
||||
QStringList parts = tag.split(':');
|
||||
QString action = tag;
|
||||
QString id = "";
|
||||
@ -75,17 +70,19 @@ void Synchronizer::api_requestDone(const QJsonObject& response, const QString& t
|
||||
id = parts[1];
|
||||
}
|
||||
|
||||
// TODO: check for error
|
||||
|
||||
qDebug() << "Synced folder" << id;
|
||||
|
||||
if (action == "putFolder") {
|
||||
// qDebug() << "Synced folder" << id;
|
||||
// query = db_.query("UPDATE folders SET synced = 1 WHERE id = ?");
|
||||
// query.addBindValue(id);
|
||||
// query.exec();
|
||||
Change::disposeByItemId(id);
|
||||
}
|
||||
|
||||
if (action == "putNote") {
|
||||
// qDebug() << "Done note" << id;
|
||||
// query = db_.query("UPDATE notes SET synced = 1 WHERE id = ?");
|
||||
// query.addBindValue(id);
|
||||
// query.exec();
|
||||
if (action == "patchFolder") {
|
||||
Change::disposeByItemId(id);
|
||||
}
|
||||
|
||||
if (action == "deleteFolder") {
|
||||
Change::disposeByItemId(id);
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <stable.h>
|
||||
#include "webapi.h"
|
||||
#include "database.h"
|
||||
#include "models/change.h"
|
||||
|
||||
namespace jop {
|
||||
|
||||
@ -18,6 +19,7 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
QUrlQuery valuesToUrlQuery(const QHash<QString, BaseModel::Value> &values) const;
|
||||
WebApi& api_;
|
||||
Database& db_;
|
||||
|
||||
|
@ -14,22 +14,24 @@ QString WebApi::baseUrl() const {
|
||||
return baseUrl_;
|
||||
}
|
||||
|
||||
void WebApi::execRequest(QNetworkAccessManager::Operation method, const QString &path, const QUrlQuery &query, const QUrlQuery &data, const QString& tag) {
|
||||
void WebApi::execRequest(HttpMethod method, const QString &path, const QUrlQuery &query, const QUrlQuery &data, const QString& tag) {
|
||||
QueuedRequest r;
|
||||
r.method = method;
|
||||
r.path = path;
|
||||
r.query = query;
|
||||
r.data = data;
|
||||
r.tag = tag;
|
||||
r.buffer = NULL;
|
||||
queuedRequests_ << r;
|
||||
|
||||
processQueue();
|
||||
}
|
||||
|
||||
void WebApi::post(const QString& path,const QUrlQuery& query, const QUrlQuery& data, const QString& tag) { execRequest(QNetworkAccessManager::PostOperation, path, query, data, tag); }
|
||||
void WebApi::get(const QString& path,const QUrlQuery& query, const QUrlQuery& data, const QString& tag) { execRequest(QNetworkAccessManager::GetOperation, path, query, data, tag); }
|
||||
void WebApi::put(const QString& path,const QUrlQuery& query, const QUrlQuery& data, const QString& tag) { execRequest(QNetworkAccessManager::PutOperation, path, query, data, tag); }
|
||||
//void patch(const QString& path,const QUrlQuery& query = QUrlQuery(), const QUrlQuery& data = QUrlQuery(), const QString& tag = "") { execRequest(QNetworkAccessManager::PatchOperation, query, data, tag); }
|
||||
void WebApi::post(const QString& path,const QUrlQuery& query, const QUrlQuery& data, const QString& tag) { execRequest(HttpMethod::POST, path, query, data, tag); }
|
||||
void WebApi::get(const QString& path,const QUrlQuery& query, const QUrlQuery& data, const QString& tag) { execRequest(HttpMethod::GET, path, query, data, tag); }
|
||||
void WebApi::put(const QString& path,const QUrlQuery& query, const QUrlQuery& data, const QString& tag) { execRequest(HttpMethod::PUT, path, query, data, tag); }
|
||||
void WebApi::del(const QString &path, const QUrlQuery &query, const QUrlQuery &data, const QString &tag) { execRequest(HttpMethod::DEL, path, query, data, tag); }
|
||||
void WebApi::patch(const QString &path, const QUrlQuery &query, const QUrlQuery &data, const QString &tag) { execRequest(HttpMethod::PATCH, path, query, data, tag); }
|
||||
|
||||
void WebApi::setSessionId(const QString &v) {
|
||||
sessionId_ = v;
|
||||
@ -53,19 +55,32 @@ void WebApi::processQueue() {
|
||||
|
||||
QNetworkReply* reply = NULL;
|
||||
|
||||
if (r.method == QNetworkAccessManager::GetOperation) {
|
||||
// TODO
|
||||
//manager->get(QNetworkRequest(QUrl("http://qt-project.org")));
|
||||
if (r.method == jop::PATCH) {
|
||||
// TODO: Delete buffer when done
|
||||
QBuffer* buffer = new QBuffer();
|
||||
buffer->open(QBuffer::ReadWrite);
|
||||
buffer->write(r.data.toString(QUrl::FullyEncoded).toUtf8());
|
||||
buffer->seek(0);
|
||||
r.buffer = buffer;
|
||||
reply = manager_.sendCustomRequest(*request, "PATCH", buffer);
|
||||
}
|
||||
|
||||
if (r.method == QNetworkAccessManager::PostOperation) {
|
||||
if (r.method == jop::GET) {
|
||||
reply = manager_.get(*request);
|
||||
}
|
||||
|
||||
if (r.method == jop::POST) {
|
||||
reply = manager_.post(*request, r.data.toString(QUrl::FullyEncoded).toUtf8());
|
||||
}
|
||||
|
||||
if (r.method == QNetworkAccessManager::PutOperation) {
|
||||
if (r.method == jop::PUT) {
|
||||
reply = manager_.put(*request, r.data.toString(QUrl::FullyEncoded).toUtf8());
|
||||
}
|
||||
|
||||
if (r.method == jop::DEL) {
|
||||
reply = manager_.deleteResource(*request);
|
||||
}
|
||||
|
||||
if (!reply) {
|
||||
qWarning() << "WebApi::processQueue(): reply object was not created - invalid request method";
|
||||
return;
|
||||
@ -77,11 +92,13 @@ void WebApi::processQueue() {
|
||||
|
||||
QStringList cmd;
|
||||
cmd << "curl";
|
||||
if (r.method == QNetworkAccessManager::PutOperation) {
|
||||
cmd << "-X" << "PUT";
|
||||
}
|
||||
if (r.method == jop::PUT) cmd << "-X" << "PUT";
|
||||
if (r.method == jop::PATCH) cmd << "-X" << "PATCH";
|
||||
if (r.method == jop::DEL) cmd << "-X" << "DELETE";
|
||||
|
||||
cmd << "--data" << "'" + r.data.toString(QUrl::FullyEncoded) + "'";
|
||||
if (r.method != jop::GET && r.method != jop::DEL) {
|
||||
cmd << "--data" << "'" + r.data.toString(QUrl::FullyEncoded) + "'";
|
||||
}
|
||||
cmd << url;
|
||||
|
||||
qDebug().noquote() << cmd.join(" ");
|
||||
@ -99,6 +116,9 @@ void WebApi::request_finished(QNetworkReply *reply) {
|
||||
qWarning().noquote() << QString(responseBodyBA);
|
||||
} else {
|
||||
response = doc.object();
|
||||
if (!response["error"].isNull()) {
|
||||
qWarning().noquote() << "API error:" << QString(responseBodyBA);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < inProgressRequests_.size(); i++) {
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define WEBAPI_H
|
||||
|
||||
#include <stable.h>
|
||||
#include "enum.h"
|
||||
|
||||
namespace jop {
|
||||
|
||||
@ -12,22 +13,24 @@ class WebApi : public QObject {
|
||||
public:
|
||||
|
||||
struct QueuedRequest {
|
||||
QNetworkAccessManager::Operation method;
|
||||
HttpMethod method;
|
||||
QString path;
|
||||
QUrlQuery query;
|
||||
QUrlQuery data;
|
||||
QNetworkReply* reply;
|
||||
QNetworkRequest* request;
|
||||
QString tag;
|
||||
QBuffer* buffer;
|
||||
};
|
||||
|
||||
WebApi(const QString& baseUrl);
|
||||
QString baseUrl() const;
|
||||
void execRequest(QNetworkAccessManager::Operation method, const QString& path,const QUrlQuery& query = QUrlQuery(), const QUrlQuery& data = QUrlQuery(), const QString& tag = "");
|
||||
void execRequest(HttpMethod method, const QString& path,const QUrlQuery& query = QUrlQuery(), const QUrlQuery& data = QUrlQuery(), const QString& tag = "");
|
||||
void post(const QString& path,const QUrlQuery& query = QUrlQuery(), const QUrlQuery& data = QUrlQuery(), const QString& tag = "");
|
||||
void get(const QString& path,const QUrlQuery& query = QUrlQuery(), const QUrlQuery& data = QUrlQuery(), const QString& tag = "");
|
||||
void put(const QString& path,const QUrlQuery& query = QUrlQuery(), const QUrlQuery& data = QUrlQuery(), const QString& tag = "");
|
||||
//void patch(const QString& path,const QUrlQuery& query = QUrlQuery(), const QUrlQuery& data = QUrlQuery(), const QString& tag = "");
|
||||
void del(const QString& path,const QUrlQuery& query = QUrlQuery(), const QUrlQuery& data = QUrlQuery(), const QString& tag = "");
|
||||
void patch(const QString& path,const QUrlQuery& query = QUrlQuery(), const QUrlQuery& data = QUrlQuery(), const QString& tag = "");
|
||||
void setSessionId(const QString& v);
|
||||
|
||||
private:
|
||||
|
@ -48,7 +48,19 @@ class FoldersController extends ApiController {
|
||||
return static::successResponse($folder);
|
||||
}
|
||||
|
||||
return static::successResponse($folder);
|
||||
if ($request->isMethod('PATCH')) {
|
||||
$data = $this->patchParameters();
|
||||
$folder->fromPublicArray($this->patchParameters());
|
||||
$folder->save();
|
||||
return static::successResponse($folder);
|
||||
}
|
||||
|
||||
if ($request->isMethod('DELETE')) {
|
||||
$folder->delete();
|
||||
return static::successResponse(array('id' => $id));
|
||||
}
|
||||
|
||||
return static::errorResponse('Invalid method');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -126,6 +126,8 @@ class BaseModel extends \Illuminate\Database\Eloquent\Model {
|
||||
return $output;
|
||||
}
|
||||
|
||||
// Note: this is used for both PATCH and PUT requests, so fields not
|
||||
// in the array must not be reset.
|
||||
public function fromPublicArray($array) {
|
||||
foreach ($array as $k => $v) {
|
||||
if ($k == 'rev_id') {
|
||||
|
Loading…
Reference in New Issue
Block a user