From e916b47f12ba0e84ee6b1faed687b920e49633f8 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Tue, 6 May 2014 21:24:06 -0700
Subject: [PATCH] DD-22 : WIP : Implement the modify listing route. Made the
 code more readable and cleared old debug code

---
 indra/newview/llinventorybridge.cpp      |   8 +-
 indra/newview/llmarketplacefunctions.cpp | 172 ++++++++++++++++++++---
 indra/newview/llmarketplacefunctions.h   |  19 ++-
 3 files changed, 162 insertions(+), 37 deletions(-)

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index e9abe6a466d..f68d69b1c35 100755
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -3178,7 +3178,7 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
 	{
         if (depth_nesting_in_marketplace(mUUID) == 1)
         {
-            LLMarketplaceData::instance().setActivation(mUUID,true);
+            LLMarketplaceData::instance().activateListing(mUUID,true);
         }
 		return;
 	}
@@ -3187,7 +3187,7 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
         if (depth_nesting_in_marketplace(mUUID) == 2)
         {
 			LLInventoryCategory* category = gInventory.getCategory(mUUID);
-            LLMarketplaceData::instance().setVersionFolderID(category->getParentUUID(), mUUID);
+            LLMarketplaceData::instance().setVersionFolder(category->getParentUUID(), mUUID);
         }
 		return;
 	}
@@ -3195,7 +3195,7 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
 	{
         if (depth_nesting_in_marketplace(mUUID) == 1)
         {
-            LLMarketplaceData::instance().setActivation(mUUID,false);
+            LLMarketplaceData::instance().activateListing(mUUID,false);
         }
 		return;
 	}
@@ -3204,7 +3204,7 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
         if (depth_nesting_in_marketplace(mUUID) == 2)
         {
 			LLInventoryCategory* category = gInventory.getCategory(mUUID);
-            LLMarketplaceData::instance().setVersionFolderID(category->getParentUUID(), LLUUID::null);
+            LLMarketplaceData::instance().setVersionFolder(category->getParentUUID(), LLUUID::null);
         }
 		return;
 	}
diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp
index 2178ecaaa2e..15c1630a2ae 100755
--- a/indra/newview/llmarketplacefunctions.cpp
+++ b/indra/newview/llmarketplacefunctions.cpp
@@ -104,19 +104,19 @@ LLSD getMarketplaceStringSubstitutions()
 // SLM Responders
 void log_SLM_error(const std::string& request, U32 status, const std::string& reason, const std::string& code, const std::string& description)
 {
-		LL_WARNS("SLM") << request << " request failed. status : " << status << ". reason : " << reason << ". code : " << code << ". description : " << description << LL_ENDL;
+		LL_WARNS("SLM") << "Merov : " << request << " request failed. status : " << status << ", reason : " << reason << ", code : " << code << ", description : " << description << LL_ENDL;
 }
 
 // Merov: This is a temporary hack used by dev while secondlife-staging is down...
 // *TODO : Suppress that before shipping!
-static bool sBypassMerchant = false;
+static bool sBypassMerchant = true;
 
-class LLSLMMerchantResponder : public LLHTTPClient::Responder
+class LLSLMGetMerchantResponder : public LLHTTPClient::Responder
 {
-	LOG_CLASS(LLSLMMerchantResponder);
+	LOG_CLASS(LLSLMGetMerchantResponder);
 public:
 	
-    LLSLMMerchantResponder() {}
+    LLSLMGetMerchantResponder() {}
     
 	virtual void completed(U32 status, const std::string& reason, const LLSD& content) { }
     
@@ -138,12 +138,12 @@ class LLSLMMerchantResponder : public LLHTTPClient::Responder
     }
 };
 
-class LLSLMListingsResponder : public LLHTTPClient::Responder
+class LLSLMGetListingsResponder : public LLHTTPClient::Responder
 {
-	LOG_CLASS(LLSLMListingsResponder);
+	LOG_CLASS(LLSLMGetListingsResponder);
 public:
 	
-    LLSLMListingsResponder() {}
+    LLSLMGetListingsResponder() {}
     
     virtual void completedRaw(U32 status,
                               const std::string& reason,
@@ -152,8 +152,7 @@ class LLSLMListingsResponder : public LLHTTPClient::Responder
     {
 		if (!isGoodStatus(status))
 		{
-            std::string error_code = llformat("%d",status);
-            log_SLM_error("Get listings", status, reason, error_code, "");
+            log_SLM_error("Get listings", status, reason, "", "");
             return;
 		}
         
@@ -169,7 +168,9 @@ class LLSLMListingsResponder : public LLHTTPClient::Responder
             log_SLM_error("Get listings", status, "Json parsing failed", reader.getFormatedErrorMessages(), body);
             return;
         }
-        
+
+        llinfos << "Merov : Get listings completedRaw : data = " << body << llendl;
+
         // Extract the info from the Json string
         Json::ValueIterator it = root["listings"].begin();
         
@@ -204,8 +205,7 @@ class LLSLMCreateListingsResponder : public LLHTTPClient::Responder
     {
 		if (!isGoodStatus(status))
 		{
-            std::string error_code = llformat("%d",status);
-            log_SLM_error("Post listings", status, reason, error_code, "");
+            log_SLM_error("Post listings", status, reason, "", "");
             return;
 		}
         
@@ -221,7 +221,9 @@ class LLSLMCreateListingsResponder : public LLHTTPClient::Responder
             log_SLM_error("Post listings", status, "Json parsing failed", reader.getFormatedErrorMessages(), body);
             return;
         }
-        
+
+        llinfos << "Merov : Create listing completedRaw : data = " << body << llendl;
+
         // Extract the info from the Json string
         Json::ValueIterator it = root["listings"].begin();
         
@@ -241,6 +243,64 @@ class LLSLMCreateListingsResponder : public LLHTTPClient::Responder
         }
     }
 };
+
+class LLSLMUpdateListingsResponder : public LLHTTPClient::Responder
+{
+	LOG_CLASS(LLSLMUpdateListingsResponder);
+public:
+	
+    LLSLMUpdateListingsResponder() {}
+    
+    virtual void completedRaw(U32 status,
+                              const std::string& reason,
+                              const LLChannelDescriptors& channels,
+                              const LLIOPipe::buffer_ptr_t& buffer)
+    {
+		if (!isGoodStatus(status))
+		{
+            log_SLM_error("Put listings", status, reason, "", "");
+            return;
+		}
+        
+        LLBufferStream istr(channels, buffer.get());
+        std::stringstream strstrm;
+        strstrm << istr.rdbuf();
+        const std::string body = strstrm.str();
+        
+        Json::Value root;
+        Json::Reader reader;
+        if (!reader.parse(body,root))
+        {
+            log_SLM_error("Put listings", status, "Json parsing failed", reader.getFormatedErrorMessages(), body);
+            return;
+        }
+        
+        llinfos << "Merov : Update listing completedRaw : data = " << body << llendl;
+
+        // Extract the info from the Json string
+        Json::ValueIterator it = root["listings"].begin();
+        
+        while (it != root["listings"].end())
+        {
+            Json::Value listing = *it;
+            
+            int listing_id = listing["id"].asInt();
+            bool is_listed = listing["is_listed"].asBool();
+            std::string folder_uuid_string = listing["inventory_info"]["listing_folder_id"].asString();
+            std::string version_uuid_string = listing["inventory_info"]["version_folder_id"].asString();
+            
+            LLUUID folder_id(folder_uuid_string);
+            LLUUID version_id(version_uuid_string);
+            
+            // Update that listing
+            LLMarketplaceData::instance().setListingID(folder_id, listing_id);
+            LLMarketplaceData::instance().setVersionFolderID(folder_id, version_id);
+            LLMarketplaceData::instance().setActivation(folder_id, is_listed);
+            
+            it++;
+        }
+    }
+};
 // SLM Responders End
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -763,7 +823,6 @@ LLMarketplaceData::LLMarketplaceData() :
  mStatusUpdatedSignal(NULL),
  mDirtyCount(false)
 {
-    mTestCurrentMarketplaceID = 1234567;
     mInventoryObserver = new LLMarketplaceInventoryObserver;
     gInventory.addObserver(mInventoryObserver);
 }
@@ -773,11 +832,6 @@ LLMarketplaceData::~LLMarketplaceData()
 	gInventory.removeObserver(mInventoryObserver);
 }
 
-S32 LLMarketplaceData::getTestMarketplaceID()
-{
-    return mTestCurrentMarketplaceID++;
-}
-
 void LLMarketplaceData::initializeSLM(const status_updated_signal_t::slot_type& cb)
 {
     mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_INITIALIZING;
@@ -786,12 +840,12 @@ void LLMarketplaceData::initializeSLM(const status_updated_signal_t::slot_type&
 		mStatusUpdatedSignal = new status_updated_signal_t();
 	}
 	mStatusUpdatedSignal->connect(cb);
-	LLHTTPClient::get(getSLMConnectURL("/merchant"), new LLSLMMerchantResponder(), LLSD());
+	LLHTTPClient::get(getSLMConnectURL("/merchant"), new LLSLMGetMerchantResponder(), LLSD());
 }
 
 void LLMarketplaceData::getSLMListings()
 {
-	LLHTTPClient::get(getSLMConnectURL("/listings"), new LLSLMListingsResponder(), LLSD());
+	LLHTTPClient::get(getSLMConnectURL("/listings"), new LLSLMGetListingsResponder(), LLSD());
 }
 
 void LLMarketplaceData::createSLMListing(const LLUUID& folder_id)
@@ -819,6 +873,36 @@ void LLMarketplaceData::createSLMListing(const LLUUID& folder_id)
 	LLHTTPClient::postRaw(getSLMConnectURL("/listings"), data, size, new LLSLMCreateListingsResponder(), headers);
 }
 
+void LLMarketplaceData::updateSLMListing(const LLUUID& folder_id, S32 listing_id, const LLUUID& version_id, bool is_listed)
+{
+	LLSD headers = LLSD::emptyMap();
+	headers["Accept"] = "application/json";
+	headers["Content-Type"] = "application/json";
+
+    Json::Value root;
+    Json::FastWriter writer;
+    
+    // Note : we're assuming that sending unchanged info won't break anything server side...
+    root["listing"]["id"] = listing_id;
+    root["listing"]["is_listed"] = is_listed;
+    root["listing"]["inventory_info"]["listing_folder_id"] = folder_id.asString();
+    root["listing"]["inventory_info"]["version_folder_id"] = version_id.asString();
+    
+    std::string json_str = writer.write(root);
+    
+	// postRaw() takes ownership of the buffer and releases it later.
+	size_t size = json_str.size();
+	U8 *data = new U8[size];
+	memcpy(data, (U8*)(json_str.c_str()), size);
+    
+	// Send request
+    std::string url = getSLMConnectURL("/listing/") + llformat("%d",listing_id);
+    llinfos << "Merov : updating listing : " << url << ", data = " << json_str << llendl;
+	LLHTTPClient::putRaw(url, data, size, new LLSLMUpdateListingsResponder(), headers);
+}
+
+// PUT /associate_inventory/:listing_folder_id/:version_folder_id/:listing_id
+
 std::string LLMarketplaceData::getSLMConnectURL(const std::string& route)
 {
     std::string url("");
@@ -847,7 +931,8 @@ void LLMarketplaceData::setSLMStatus(U32 status)
     }
 }
 
-// Creation / Deletion
+// Creation / Deletion / Update
+// Methods publicly called
 bool LLMarketplaceData::createListing(const LLUUID& folder_id)
 {
     if (isListed(folder_id))
@@ -862,6 +947,47 @@ bool LLMarketplaceData::createListing(const LLUUID& folder_id)
     return true;
 }
 
+bool LLMarketplaceData::activateListing(const LLUUID& folder_id, bool activate)
+{
+    // Folder id can be the root of the listing or not so we need to retrieve the root first
+    S32 depth = depth_nesting_in_marketplace(folder_id);
+    LLUUID listing_uuid = nested_parent_id(folder_id, depth);
+    S32 listing_id = getListingID(listing_uuid);
+    if (listing_id == 0)
+    {
+        // Listing doesn't exists -> exit with error
+        return false;
+    }
+    
+    LLUUID version_uuid = getVersionFolderID(listing_uuid);
+
+    // Post the listing update request to SLM
+    updateSLMListing(listing_uuid, listing_id, version_uuid, activate);
+    
+    return true;
+}
+
+bool LLMarketplaceData::setVersionFolder(const LLUUID& folder_id, const LLUUID& version_id)
+{
+    // Folder id can be the root of the listing or not so we need to retrieve the root first
+    S32 depth = depth_nesting_in_marketplace(folder_id);
+    LLUUID listing_uuid = nested_parent_id(folder_id, depth);
+    S32 listing_id = getListingID(listing_uuid);
+    if (listing_id == 0)
+    {
+        // Listing doesn't exists -> exit with error
+        return false;
+    }
+    
+    bool is_listed = getActivationState(listing_uuid);
+    
+    // Post the listing update request to SLM
+    updateSLMListing(listing_uuid, listing_id, version_id, is_listed);
+    
+    return true;
+}
+
+// Methods privately called or called by SLM responders to perform changes
 bool LLMarketplaceData::addListing(const LLUUID& folder_id, S32 listing_id, const LLUUID& version_id, bool is_listed)
 {
     if (isListed(folder_id))
diff --git a/indra/newview/llmarketplacefunctions.h b/indra/newview/llmarketplacefunctions.h
index aa286adcc89..f0a1f2f4b88 100755
--- a/indra/newview/llmarketplacefunctions.h
+++ b/indra/newview/llmarketplacefunctions.h
@@ -164,8 +164,7 @@ class LLMarketplaceData
     void getSLMListings();
     //void getSLMListing();
     void createSLMListing(const LLUUID& folder_id);
-    //void modifySLMListing();
-    //void associateSLMListing();
+    void updateSLMListing(const LLUUID& folder_id, S32 listing_id, const LLUUID& version_id, bool is_listed);
     
     bool isEmpty() { return (mMarketplaceItems.size() == 0); }
     
@@ -175,6 +174,9 @@ class LLMarketplaceData
     
     // Create/Delete Marketplace data set  : each method returns true if the function succeeds, false if error
     bool createListing(const LLUUID& folder_id);
+    bool activateListing(const LLUUID& folder_id, bool activate);
+    bool setVersionFolder(const LLUUID& folder_id, const LLUUID& version_id);
+    
     bool addListing(const LLUUID& folder_id, S32 listing_id, const LLUUID& version_id, bool is_listed);
     bool associateListing(const LLUUID& folder_id, S32 listing_id);
     bool deleteListing(const LLUUID& folder_id);
@@ -191,25 +193,22 @@ class LLMarketplaceData
     bool setVersionFolderID(const LLUUID& folder_id, const LLUUID& version_id);
     bool setActivation(const LLUUID& folder_id, bool activate);
     
+    // Used to flag if count values for Marketplace are likely to have to be updated
     bool checkDirtyCount() { if (mDirtyCount) { mDirtyCount = false; return true; } else { return false; } }
     void setDirtyCount() { mDirtyCount = true; }
     
-    // Merov : Test method while waiting for SLM API
-    S32 getTestMarketplaceID();
-    
 private:
     // SLM Private
     std::string getSLMConnectURL(const std::string& route);
 
-    marketplace_items_list_t mMarketplaceItems;
-    
+    // Handling Marketplace connection and inventory connection
 	U32  mMarketPlaceStatus;
 	status_updated_signal_t *	mStatusUpdatedSignal;
 	LLInventoryObserver* mInventoryObserver;
-    bool mDirtyCount;
+    bool mDirtyCount;   // If true, stock count value will be updating at the next check
     
-    // Merov : This is for test only, waiting for SLM API
-    S32 mTestCurrentMarketplaceID;
+    // The cache of SLM data (at last...)
+    marketplace_items_list_t mMarketplaceItems;
 };
 
 
-- 
GitLab