· 8 years ago · Jul 22, 2018, 12:30 PM
1package org.wordpress.android;
2
3import android.content.ContentValues;
4import android.content.Context;
5import android.database.sqlite.SQLiteDatabase;
6
7import org.wordpress.android.datasets.NotificationsTable;
8import org.wordpress.android.datasets.PeopleTable;
9import org.wordpress.android.datasets.SiteSettingsTable;
10import org.wordpress.android.datasets.SuggestionTable;
11import org.wordpress.android.models.SiteSettingsModel;
12import org.wordpress.android.ui.prefs.AppPrefs;
13import org.wordpress.android.util.AppLog;
14import org.wordpress.android.util.AppLog.T;
15
16import java.io.File;
17import java.io.FileInputStream;
18import java.io.FileOutputStream;
19import java.io.IOException;
20import java.io.InputStream;
21import java.io.OutputStream;
22
23public class WordPressDB {
24 private static final int DATABASE_VERSION = 65;
25
26
27 // Warning if you rename DATABASE_NAME, that could break previous App backups (see: xml/backup_scheme.xml)
28 private static final String DATABASE_NAME = "wordpress";
29 private static final String NOTES_TABLE = "notes";
30 private static final String THEMES_TABLE = "themes";
31
32 // add new table for QuickPress homescreen shortcuts
33 private static final String CREATE_TABLE_QUICKPRESS_SHORTCUTS =
34 "create table if not exists quickpress_shortcuts (id integer primary key autoincrement, "
35 + "accountId text, name text);";
36 private static final String QUICKPRESS_SHORTCUTS_TABLE = "quickpress_shortcuts";
37
38 private static final String DROP_TABLE_PREFIX = "DROP TABLE IF EXISTS ";
39
40 private SQLiteDatabase mDb;
41
42 @SuppressWarnings({"FallThrough"})
43 public WordPressDB(Context ctx) {
44 mDb = ctx.openOrCreateDatabase(DATABASE_NAME, 0, null);
45
46 // Create tables if they don't exist
47 mDb.execSQL(CREATE_TABLE_QUICKPRESS_SHORTCUTS);
48 SiteSettingsTable.createTable(mDb);
49 SuggestionTable.createTables(mDb);
50 NotificationsTable.createTables(mDb);
51
52 // Update tables for new installs and app updates
53 int currentVersion = mDb.getVersion();
54 boolean isNewInstall = (currentVersion == 0);
55
56 if (!isNewInstall && currentVersion != DATABASE_VERSION) {
57 AppLog.d(T.DB, "upgrading database from version " + currentVersion + " to " + DATABASE_VERSION);
58 }
59
60 switch (currentVersion) {
61 case 0:
62 // New install
63 case 1:
64 case 9:
65 case 10:
66 case 11:
67 case 12:
68 case 13:
69 case 14:
70 case 15:
71 // No longer used (preferences migration)
72 case 16:
73 case 17:
74 case 18:
75 case 19:
76 // revision 20: create table "notes"
77 case 20:
78 case 21:
79 // version 23 added CommentTable.java, version 24 changed the comment table schema
80 case 22:
81 case 23:
82 case 24:
83 case 25:
84 // ver 26 "virtually" remove columns 'lastCommentId' and 'runService' from the DB
85 // SQLite supports a limited subset of ALTER TABLE.
86 // The ALTER TABLE command in SQLite allows the user to rename a table or to add a new column to
87 // an existing table. It is not possible to rename a column, remove a column, or add or remove
88 // constraints from a table.
89 case 26:
90 // Drop the notes table, no longer needed with Simperium.
91 mDb.execSQL(DROP_TABLE_PREFIX + NOTES_TABLE);
92 case 27:
93 case 28:
94 // Remove WordPress.com credentials
95 // NOPE: removeWPComCredentials();
96 case 29:
97 case 30:
98 case 31:
99 case 32:
100 case 33:
101 case 34:
102 case 35:
103 // Delete simperium DB - from 4.6 to 4.6.1
104 // Fix an issue when note id > MAX_INT
105 ctx.deleteDatabase("simperium-store");
106 case 36:
107 // Delete simperium DB again - from 4.6.1 to 4.7
108 // Fix a sync issue happening for users who have both wpios and wpandroid active clients
109 ctx.deleteDatabase("simperium-store");
110 case 37:
111 case 38:
112 case 39:
113 case 40:
114 case 41:
115 case 42:
116 case 43:
117 case 44:
118 PeopleTable.createTables(mDb);
119 case 45:
120 case 46:
121 AppPrefs.setVisualEditorAvailable(true);
122 AppPrefs.setVisualEditorEnabled(true);
123 case 47:
124 PeopleTable.reset(mDb);
125 case 48:
126 PeopleTable.createViewersTable(mDb);
127 case 49:
128 // Delete simperium DB since we're removing Simperium from the app.
129 ctx.deleteDatabase("simperium-store");
130 case 50:
131 // fix #5373 - no op
132 case 51:
133 // no op - was SiteSettingsTable.addOptimizedImageToSiteSettingsTable(db);
134 case 52:
135 // no op - was used for old image optimization settings
136 case 53:
137 // Clean up empty cache files caused by #5417
138 clearEmptyCacheFiles(ctx);
139 case 54:
140 // no op - was used for old image optimization settings
141 case 55:
142 SiteSettingsTable.addSharingColumnsToSiteSettingsTable(mDb);
143 case 56:
144 // no op - was used for old video optimization settings
145 case 57:
146 // Migrate media optimization settings
147 SiteSettingsTable.migrateMediaOptimizeSettings(mDb);
148 case 58:
149 // ThemeStore merged, remove deprecated themes tables
150 mDb.execSQL(DROP_TABLE_PREFIX + THEMES_TABLE);
151 case 59:
152 // Enable Aztec for all users
153 AppPrefs.setVisualEditorEnabled(false);
154 AppPrefs.setAztecEditorEnabled(true);
155 case 60:
156 // add Start of Week site setting as part of #betterjetpackxp
157 mDb.execSQL(SiteSettingsModel.ADD_START_OF_WEEK);
158 case 61:
159 // add date & time format site setting as part of #betterjetpackxp
160 mDb.execSQL(SiteSettingsModel.ADD_TIME_FORMAT);
161 mDb.execSQL(SiteSettingsModel.ADD_DATE_FORMAT);
162 case 62:
163 // add timezone and posts per page site setting as part of #betterjetpackxp
164 mDb.execSQL(SiteSettingsModel.ADD_TIMEZONE);
165 mDb.execSQL(SiteSettingsModel.ADD_POSTS_PER_PAGE);
166 case 63:
167 // add AMP site setting as part of #betterjetpackxp
168 mDb.execSQL(SiteSettingsModel.ADD_AMP_SUPPORTED);
169 mDb.execSQL(SiteSettingsModel.ADD_AMP_ENABLED);
170 case 64:
171 // add site icon
172 mDb.execSQL(SiteSettingsModel.ADD_SITE_ICON);
173 }
174 mDb.setVersion(DATABASE_VERSION);
175 }
176
177 public SQLiteDatabase getDatabase() {
178 return mDb;
179 }
180
181 public static void deleteDatabase(Context ctx) {
182 ctx.deleteDatabase(DATABASE_NAME);
183 }
184
185 public boolean addQuickPressShortcut(int blogId, String name) {
186 ContentValues values = new ContentValues();
187 values.put("accountId", blogId);
188 values.put("name", name);
189 boolean returnValue = false;
190 synchronized (this) {
191 returnValue = mDb.insert(QUICKPRESS_SHORTCUTS_TABLE, null, values) > 0;
192 }
193
194 return (returnValue);
195 }
196
197 /*
198 * used during development to copy database to SD card so we can access it via DDMS
199 */
200 protected void copyDatabase() {
201 String copyFrom = mDb.getPath();
202 String copyTo =
203 WordPress.getContext().getExternalFilesDir(null).getAbsolutePath() + "/" + DATABASE_NAME + ".db";
204
205 try {
206 InputStream input = new FileInputStream(copyFrom);
207 OutputStream output = new FileOutputStream(copyTo);
208
209 byte[] buffer = new byte[1024];
210 int length;
211 while ((length = input.read(buffer)) > 0) {
212 output.write(buffer, 0, length);
213 }
214
215 output.flush();
216 output.close();
217 input.close();
218 } catch (IOException e) {
219 AppLog.e(T.DB, "failed to copy database", e);
220 }
221 }
222
223 private void clearEmptyCacheFiles(Context context) {
224 if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
225 File imageCacheDir = new File(android.os.Environment.getExternalStorageDirectory() + "/WordPress/images");
226 File videoCacheDir = new File(android.os.Environment.getExternalStorageDirectory() + "/WordPress/video");
227
228 deleteEmptyFilesInDirectory(imageCacheDir);
229 deleteEmptyFilesInDirectory(videoCacheDir);
230 } else {
231 File cacheDir = context.getApplicationContext().getCacheDir();
232 deleteEmptyFilesInDirectory(cacheDir);
233 }
234 }
235
236 @SuppressWarnings("ResultOfMethodCallIgnored")
237 private void deleteEmptyFilesInDirectory(File directory) {
238 if (directory == null || !directory.exists() || directory.listFiles() == null) {
239 return;
240 }
241
242 for (File file : directory.listFiles()) {
243 if (file != null && file.length() == 0) {
244 file.delete();
245 }
246 }
247 }
248}