~ubuntu-branches/ubuntu/wily/gnome-software/wily

« back to all changes in this revision

Viewing changes to src/plugins/gs-plugin-local-ratings.c

  • Committer: Package Import Robot
  • Author(s): Laurent Bigonville
  • Date: 2014-10-11 11:04:58 UTC
  • Revision ID: package-import@ubuntu.com-20141011110458-0qsyec8s0lsjevdv
Tags: upstream-3.14.0
ImportĀ upstreamĀ versionĀ 3.14.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
 
2
 *
 
3
 * Copyright (C) 2013 Richard Hughes <richard@hughsie.com>
 
4
 *
 
5
 * Licensed under the GNU General Public License Version 2
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or modify
 
8
 * it under the terms of the GNU General Public License as published by
 
9
 * the Free Software Foundation; either version 2 of the License, or
 
10
 * (at your option) any later version.
 
11
 *
 
12
 * This program is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 * GNU General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License
 
18
 * along with this program; if not, write to the Free Software
 
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
20
 */
 
21
 
 
22
#include <config.h>
 
23
 
 
24
#include <sqlite3.h>
 
25
#include <stdlib.h>
 
26
 
 
27
#include <gs-plugin.h>
 
28
#include <gs-utils.h>
 
29
 
 
30
struct GsPluginPrivate {
 
31
        gsize                    loaded;
 
32
        gchar                   *db_path;
 
33
        sqlite3                 *db;
 
34
};
 
35
 
 
36
/**
 
37
 * gs_plugin_get_name:
 
38
 */
 
39
const gchar *
 
40
gs_plugin_get_name (void)
 
41
{
 
42
        return "local-ratings";
 
43
}
 
44
 
 
45
/**
 
46
 * gs_plugin_initialize:
 
47
 */
 
48
void
 
49
gs_plugin_initialize (GsPlugin *plugin)
 
50
{
 
51
        /* create private area */
 
52
        plugin->priv = GS_PLUGIN_GET_PRIVATE (GsPluginPrivate);
 
53
        plugin->priv->db_path = g_build_filename (g_get_home_dir (),
 
54
                                                  ".local",
 
55
                                                  "share",
 
56
                                                  "gnome-software",
 
57
                                                  "hardcoded-ratings.db",
 
58
                                                  NULL);
 
59
}
 
60
 
 
61
/**
 
62
 * gs_plugin_get_deps:
 
63
 */
 
64
const gchar **
 
65
gs_plugin_get_deps (GsPlugin *plugin)
 
66
{
 
67
        static const gchar *deps[] = {
 
68
                "appstream",    /* requires the app_id from the pkgname */
 
69
                NULL };
 
70
        return deps;
 
71
}
 
72
 
 
73
/**
 
74
 * gs_plugin_destroy:
 
75
 */
 
76
void
 
77
gs_plugin_destroy (GsPlugin *plugin)
 
78
{
 
79
        g_free (plugin->priv->db_path);
 
80
        sqlite3_close (plugin->priv->db);
 
81
}
 
82
 
 
83
/**
 
84
 * gs_plugin_local_ratings_load_db:
 
85
 */
 
86
static gboolean
 
87
gs_plugin_local_ratings_load_db (GsPlugin *plugin,
 
88
                                 GError **error)
 
89
{
 
90
        const gchar *statement;
 
91
        gboolean ret = TRUE;
 
92
        gchar *error_msg = NULL;
 
93
        gint rc;
 
94
 
 
95
        g_debug ("trying to open database '%s'", plugin->priv->db_path);
 
96
        ret = gs_mkdir_parent (plugin->priv->db_path, error);
 
97
        if (!ret)
 
98
                goto out;
 
99
        rc = sqlite3_open (plugin->priv->db_path, &plugin->priv->db);
 
100
        if (rc != SQLITE_OK) {
 
101
                ret = FALSE;
 
102
                g_set_error (error,
 
103
                             GS_PLUGIN_ERROR,
 
104
                             GS_PLUGIN_ERROR_FAILED,
 
105
                             "Can't open transaction database: %s",
 
106
                             sqlite3_errmsg (plugin->priv->db));
 
107
                goto out;
 
108
        }
 
109
 
 
110
        /* we don't need to keep doing fsync */
 
111
        sqlite3_exec (plugin->priv->db, "PRAGMA synchronous=OFF", NULL, NULL, NULL);
 
112
 
 
113
        /* create table if required */
 
114
        rc = sqlite3_exec (plugin->priv->db, "SELECT * FROM ratings LIMIT 1", NULL, NULL, &error_msg);
 
115
        if (rc != SQLITE_OK) {
 
116
                g_debug ("creating table to repair: %s", error_msg);
 
117
                sqlite3_free (error_msg);
 
118
                statement = "CREATE TABLE ratings ("
 
119
                            "app_id TEXT PRIMARY KEY,"
 
120
                            "rating INTEGER DEFAULT 0);";
 
121
                sqlite3_exec (plugin->priv->db, statement, NULL, NULL, NULL);
 
122
        }
 
123
 
 
124
        /* success */
 
125
out:
 
126
        return ret;
 
127
}
 
128
 
 
129
/**
 
130
 * gs_plugin_local_ratings_sqlite_cb:
 
131
 **/
 
132
static gint
 
133
gs_plugin_local_ratings_sqlite_cb (void *data, gint argc, gchar **argv, gchar **col_name)
 
134
{
 
135
        gint *rating = (gint *) data;
 
136
        *rating = atoi (argv[0]);
 
137
        return 0;
 
138
}
 
139
 
 
140
/**
 
141
 * gs_plugin_local_find_app:
 
142
 */
 
143
static gint
 
144
gs_plugin_local_find_app (GsPlugin *plugin, const gchar *app_id)
 
145
{
 
146
        gchar *statement;
 
147
        gint rating = -1;
 
148
 
 
149
        statement = g_strdup_printf ("SELECT rating FROM ratings WHERE app_id = '%s'", app_id);
 
150
        sqlite3_exec (plugin->priv->db,
 
151
                      statement,
 
152
                      gs_plugin_local_ratings_sqlite_cb,
 
153
                      &rating,
 
154
                      NULL);
 
155
        g_free (statement);
 
156
        return rating;
 
157
}
 
158
 
 
159
/**
 
160
 * gs_plugin_app_set_rating:
 
161
 */
 
162
gboolean
 
163
gs_plugin_app_set_rating (GsPlugin *plugin,
 
164
                          GsApp *app,
 
165
                          GCancellable *cancellable,
 
166
                          GError **error)
 
167
{
 
168
        gboolean ret = TRUE;
 
169
        gchar *error_msg = NULL;
 
170
        gchar *statement = NULL;
 
171
        gint rc;
 
172
 
 
173
        /* already loaded */
 
174
        if (g_once_init_enter (&plugin->priv->loaded)) {
 
175
                ret = gs_plugin_local_ratings_load_db (plugin, error);
 
176
                g_once_init_leave (&plugin->priv->loaded, TRUE);
 
177
 
 
178
                if (!ret)
 
179
                        goto out;
 
180
        }
 
181
 
 
182
        /* insert the entry */
 
183
        statement = g_strdup_printf ("INSERT OR REPLACE INTO ratings (app_id, rating) "
 
184
                                     "VALUES ('%s', '%i');",
 
185
                                     gs_app_get_id (app),
 
186
                                     gs_app_get_rating (app));
 
187
        rc = sqlite3_exec (plugin->priv->db, statement, NULL, NULL, &error_msg);
 
188
        if (rc != SQLITE_OK) {
 
189
                g_set_error (error,
 
190
                             GS_PLUGIN_ERROR,
 
191
                             GS_PLUGIN_ERROR_FAILED,
 
192
                             "SQL error: %s", error_msg);
 
193
                sqlite3_free (error_msg);
 
194
                ret = FALSE;
 
195
                goto out;
 
196
        }
 
197
out:
 
198
        g_free (statement);
 
199
        return ret;
 
200
 
 
201
}
 
202
 
 
203
/**
 
204
 * gs_plugin_refine:
 
205
 */
 
206
gboolean
 
207
gs_plugin_refine (GsPlugin *plugin,
 
208
                  GList **list,
 
209
                  GsPluginRefineFlags flags,
 
210
                  GCancellable *cancellable,
 
211
                  GError **error)
 
212
{
 
213
        gboolean ret = TRUE;
 
214
        gint rating;
 
215
        GList *l;
 
216
        GsApp *app;
 
217
 
 
218
        /* nothing to do here */
 
219
        if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_RATING) == 0)
 
220
                goto out;
 
221
 
 
222
        /* already loaded */
 
223
        if (g_once_init_enter (&plugin->priv->loaded)) {
 
224
                ret = gs_plugin_local_ratings_load_db (plugin, error);
 
225
                g_once_init_leave (&plugin->priv->loaded, TRUE);
 
226
 
 
227
                if (!ret)
 
228
                        goto out;
 
229
        }
 
230
 
 
231
        /* add any missing ratings data */
 
232
        for (l = *list; l != NULL; l = l->next) {
 
233
                app = GS_APP (l->data);
 
234
                if (gs_app_get_id (app) == NULL)
 
235
                        continue;
 
236
                if (gs_app_get_rating (app) != -1)
 
237
                        continue;
 
238
                rating = gs_plugin_local_find_app (plugin, gs_app_get_id (app));
 
239
                if (rating != -1) {
 
240
                        gs_app_set_rating (app, rating);
 
241
                        gs_app_set_rating_confidence (app, 100);
 
242
                        gs_app_set_rating_kind (app, GS_APP_RATING_KIND_USER);
 
243
                        if (rating > 80)
 
244
                                gs_app_add_kudo (app, GS_APP_KUDO_POPULAR);
 
245
                }
 
246
        }
 
247
out:
 
248
        return ret;
 
249
}