Commit 0381eb9a authored by Jan Köster's avatar Jan Köster
Browse files

test

parent d5cdf974
Loading
Loading
Loading
Loading
+74 −20
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@
#include <algorithm>
#include <regex>
#include <chrono>
#include <set>
#include <string>
#include <thread>
#include <atomic>
@@ -84,16 +85,19 @@ namespace blogi {
            form.parse(req);

            bool saved = false;
            bool syncNow = false;

            // Collect all form data in one pass before applying
            std::set<std::string> inForm;    // review_in_form_* hidden fields
            std::set<std::string> checked;   // approve_* checkboxes that are checked

            for(const auto &cur : form.urlData()){
                if(cur.key.compare(0, 8, "approve_") == 0) {
                    std::string author = cur.key.substr(8);
                    dbpp::SQL sql;
                    dbpp::DBResult res;
                    sql << "UPDATE google_reviews SET approved=" << (cur.value == "1" ? "true" : "false")
                        << " WHERE author_name='" << author << "';";
                    Args->database[tid]->exec(sql, res);
                    saved = true;
                if(cur.key.compare(0, 15, "review_in_form_") == 0) {
                    inForm.insert(cur.key.substr(15));
                } else if(cur.key.compare(0, 8, "approve_") == 0 && cur.value == "on") {
                    checked.insert(cur.key.substr(8));
                } else if(cur.key == "sync_now") {
                    syncNow = true;
                } else if(cur.key == "google_notify_email") {
                    _notifyEmail = cur.value;
                    setConfig(*Args->database[tid], "GOOGLE_REVIEW_NOTIFY_EMAIL", cur.value);
@@ -116,11 +120,35 @@ namespace blogi {
                }
            }

            // Apply approvals: reset only the reviews that were shown in the form,
            // then mark the checked ones as approved.
            if(!inForm.empty()) {
                std::vector<char> buf;
                for(const auto &author : inForm) {
                    buf.clear();
                    bool isApproved = checked.count(author) > 0;
                    dbpp::SQL sql;
                    dbpp::DBResult res;
                    sql << "UPDATE google_reviews SET approved=" << (isApproved ? "true" : "false")
                        << " WHERE author_name='" << dbpp::SQL::escaped(buf, author.c_str()) << "';";
                    Args->database[tid]->exec(sql, res);
                }
                saved = true;
            }

            json_object *jroot = json_object_new_object();
            json_object_object_add(jroot, "title", json_object_new_string("Google Reviews"));

            if(saved) {
                json_object_object_add(jroot, "message", json_object_new_string("Saved!"));
            if(syncNow) {
                if(!_apiKey.empty() && !_placeId.empty()) {
                    _fetchFromGoogle(tid);
                    json_object_object_add(jroot, "message", json_object_new_string("Synchronisierung abgeschlossen!"));
                } else {
                    json_object_object_add(jroot, "message", json_object_new_string("API Key und Place ID müssen zuerst gespeichert werden."));
                    json_object_object_add(jroot, "message_type", json_object_new_string("error"));
                }
            } else if(saved) {
                json_object_object_add(jroot, "message", json_object_new_string("Gespeichert!"));
                json_object_object_add(jroot, "message_type", json_object_new_string("success"));
            }

@@ -152,27 +180,53 @@ namespace blogi {
            for(int i = 0; i < ncount; ++i) {
                std::string author = res[i][0];
                int rating = atoi(res[i][1]);
                bool approved = atoi(res[i][3]) == 1;
                std::string text = res[i][2] ? res[i][2] : "";
                bool approved = res[i][3] && atoi(res[i][3]) == 1;

                json_object *jf = json_object_new_object();
                std::string key = "approve_" + author;
                json_object_object_add(jf, "name", json_object_new_string(key.c_str()));
                // Hidden sentinel so the form handler knows which reviews were on screen
                json_object *jhidden = json_object_new_object();
                json_object_object_add(jhidden, "name", json_object_new_string(("review_in_form_" + author).c_str()));
                json_object_object_add(jhidden, "type", json_object_new_string("hidden"));
                json_object_object_add(jhidden, "value", json_object_new_string("1"));
                json_object_array_add(jfields, jhidden);

                // Approval checkbox with author, rating and a text excerpt as label
                std::string excerpt = text.size() > 80 ? text.substr(0, 77) + "..." : text;
                std::string label = author + " (" + std::to_string(rating) + "★)";
                if(!excerpt.empty()) label += " – " + excerpt;

                std::string label = "Review by " + author + " (" + std::to_string(rating) + " stars)";
                json_object *jf = json_object_new_object();
                json_object_object_add(jf, "name", json_object_new_string(("approve_" + author).c_str()));
                json_object_object_add(jf, "label", json_object_new_string(label.c_str()));
                json_object_object_add(jf, "type", json_object_new_string("checkbox"));
                if(approved) {
                    json_object_object_add(jf, "value", json_object_new_string("1"));
                    json_object_object_add(jf, "value", json_object_new_string("on"));
                }
                json_object_array_add(jfields, jf);
            }

            json_object_object_add(jform, "fields", jfields);

            json_object_object_add(jform, "submit", json_object_new_string("Save Changes"));
            json_object_object_add(jform, "submit", json_object_new_string("Speichern"));

            json_object_object_add(jroot, "form", jform);

            // Sync Now button (rendered as a separate form below the main form)
            json_object *jsyncform = json_object_new_object();
            json_object_object_add(jsyncform, "method", json_object_new_string("POST"));
            json_object_object_add(jsyncform, "action", json_object_new_string(Args->config->buildurl("settings/google").c_str()));
            json_object *jsyncfields = json_object_new_array();
            {
                json_object *jf = json_object_new_object();
                json_object_object_add(jf, "name", json_object_new_string("sync_now"));
                json_object_object_add(jf, "type", json_object_new_string("hidden"));
                json_object_object_add(jf, "value", json_object_new_string("1"));
                json_object_array_add(jsyncfields, jf);
            }
            json_object_object_add(jsyncform, "fields", jsyncfields);
            json_object_object_add(jsyncform, "submit", json_object_new_string("Jetzt synchronisieren"));
            json_object_object_add(jroot, "sync_form", jsyncform);

            return jroot;
        }

@@ -267,11 +321,11 @@ namespace blogi {
                if (_stop.load()) break;

                if (!_apiKey.empty() && !_placeId.empty())
                    _fetchFromGoogle();
                    _fetchFromGoogle(0);
            }
        }

        void _fetchFromGoogle() {
        void _fetchFromGoogle(int tid) {
            try {
                std::string path = "/maps/api/place/details/json?place_id=" + _placeId
                                 + "&fields=reviews&key=" + _apiKey;
@@ -313,7 +367,7 @@ namespace blogi {
                                timeStr = std::to_string(json_object_get_int64(jtime));

                            if (!author.empty())
                                _processReview(0, author, rating, text, timeStr);
                                _processReview(tid, author, rating, text, timeStr);
                        }
                    }
                }