1 /*
2  *  Copyright (C) 2019 Team Kodi
3  *  This file is part of Kodi - https://kodi.tv
4  *
5  *  SPDX-License-Identifier: GPL-2.0-or-later
6  *  See LICENSES/README.md for more information.
7  */
8 
9 #include "SettingsValueXmlSerializer.h"
10 
11 #include "settings/lib/SettingDefinitions.h"
12 #include "settings/lib/SettingSection.h"
13 #include "settings/lib/SettingsManager.h"
14 #include "utils/XBMCTinyXML.h"
15 #include "utils/XMLUtils.h"
16 #include "utils/log.h"
17 
18 static constexpr char SETTINGS_XML_ROOT[] = "settings";
19 
SerializeValues(const CSettingsManager * settingsManager) const20 std::string CSettingsValueXmlSerializer::SerializeValues(
21   const CSettingsManager* settingsManager) const
22 {
23   if (settingsManager == nullptr)
24     return "";
25 
26   CXBMCTinyXML xmlDoc;
27   TiXmlElement rootElement(SETTINGS_XML_ROOT);
28   rootElement.SetAttribute(SETTING_XML_ROOT_VERSION, settingsManager->GetVersion());
29   TiXmlNode* xmlRoot = xmlDoc.InsertEndChild(rootElement);
30   if (xmlRoot == nullptr)
31     return "";
32 
33   const auto sections = settingsManager->GetSections();
34   for (const auto& section : sections)
35     SerializeSection(xmlRoot, section);
36 
37   std::stringstream stream;
38   stream << *xmlDoc.RootElement();
39 
40   return stream.str();
41 }
42 
SerializeSection(TiXmlNode * parent,const std::shared_ptr<CSettingSection> & section) const43 void CSettingsValueXmlSerializer::SerializeSection(
44     TiXmlNode* parent, const std::shared_ptr<CSettingSection>& section) const
45 {
46   if (section == nullptr)
47     return;
48 
49   const auto categories = section->GetCategories();
50   for (const auto& category : categories)
51     SerializeCategory(parent, category);
52 }
53 
SerializeCategory(TiXmlNode * parent,const std::shared_ptr<CSettingCategory> & category) const54 void CSettingsValueXmlSerializer::SerializeCategory(
55     TiXmlNode* parent, const std::shared_ptr<CSettingCategory>& category) const
56 {
57   if (category == nullptr)
58     return;
59 
60   const auto groups = category->GetGroups();
61   for (const auto& group : groups)
62     SerializeGroup(parent, group);
63 }
64 
SerializeGroup(TiXmlNode * parent,const std::shared_ptr<CSettingGroup> & group) const65 void CSettingsValueXmlSerializer::SerializeGroup(TiXmlNode* parent,
66                                                  const std::shared_ptr<CSettingGroup>& group) const
67 {
68   if (group == nullptr)
69     return;
70 
71   const auto settings = group->GetSettings();
72   for (const auto& setting : settings)
73     SerializeSetting(parent, setting);
74 }
75 
SerializeSetting(TiXmlNode * parent,const std::shared_ptr<CSetting> & setting) const76 void CSettingsValueXmlSerializer::SerializeSetting(TiXmlNode* parent,
77                                                    const std::shared_ptr<CSetting>& setting) const
78 {
79   if (setting == nullptr)
80     return;
81 
82   // ignore references and action settings (which don't have a value)
83   if (setting->IsReference() || setting->GetType() == SettingType::Action)
84     return;
85 
86   TiXmlElement settingElement(SETTING_XML_ELM_SETTING);
87   settingElement.SetAttribute(SETTING_XML_ATTR_ID, setting->GetId());
88 
89   // add the default attribute
90   if (setting->IsDefault())
91     settingElement.SetAttribute(SETTING_XML_ELM_DEFAULT, "true");
92 
93   // add the value
94   TiXmlText value(setting->ToString());
95   settingElement.InsertEndChild(value);
96 
97   if (parent->InsertEndChild(settingElement) == nullptr)
98     CLog::Log(LOGWARNING,
99       "CSettingsValueXmlSerializer: unable to write <" SETTING_XML_ELM_SETTING " id=\"{}\"> tag",
100       setting->GetId());
101 }
102