@@ -78,6 +78,11 @@ public static function is_tagging_enabled_and_supported(): bool {
78
78
return $ enabledinconfig && $ supportedbyfs ;
79
79
}
80
80
81
+ // TODO unit tests for this functionality
82
+ public static function can_override_existing_tags (): bool {
83
+ return !empty (get_config ('tool_objectfs ' , 'overridetags ' ));
84
+ }
85
+
81
86
/**
82
87
* Gathers the tag values for a given content hash
83
88
* @param string $contenthash
@@ -98,41 +103,6 @@ private static function gather_tags(string $contenthash): array {
98
103
return $ tags ;
99
104
}
100
105
101
- /**
102
- * Returns the tags stored locally in the DB for the given file contenthash
103
- * @param int $objectid
104
- * @return array array of key=>value pairs, the tags for the given file that are stored in the database.
105
- */
106
- public static function query_local_tags (string $ contenthash ): array {
107
- global $ DB ;
108
- $ records = $ DB ->get_records ('tool_objectfs_object_tags ' , ['contenthash ' => $ contenthash ], '' , 'tagkey,tagvalue ' );
109
-
110
- $ tags = [];
111
- foreach ($ records as $ record ) {
112
- $ tags [$ record ->tagkey ] = $ record ->tagvalue ;
113
- }
114
- return $ tags ;
115
- }
116
-
117
- /**
118
- * Synchronises the tags for a given file.
119
- *
120
- * @param string $contenthash file to update tags for
121
- * @param bool $force By default, will not update stored tags unless the gathered tags differ from the locally stored tags. If this is true, it will always store the newest tags.
122
- */
123
- public static function update_tags_if_necessary (string $ contenthash , bool $ force = false ) {
124
- // Gather the exact current and compare against local db.
125
- $ gatheredtags = self ::gather_tags ($ contenthash );
126
- $ localtags = self ::query_local_tags ($ contenthash );
127
-
128
- // Update if forced to, or if what we just gathered is not the same as what is stored in the database.
129
- $ shouldupdate = $ force || self ::are_tags_different ($ gatheredtags , $ localtags );
130
-
131
- if ($ shouldupdate ) {
132
- self ::store_tags ($ contenthash , $ gatheredtags );
133
- }
134
- }
135
-
136
106
/**
137
107
* Updates the local db tag records, and marks object as needing sync to sync local tags to external.
138
108
* @param int $objectid
@@ -141,39 +111,23 @@ public static function update_tags_if_necessary(string $contenthash, bool $force
141
111
private static function store_tags (string $ contenthash , array $ tags ) {
142
112
global $ DB ;
143
113
144
- // Get a lock, since we are modifying the tags in the DB.
145
- $ lock = self ::get_object_tag_lock ($ contenthash );
146
-
147
- if (!$ lock ) {
148
- throw new coding_exception ("Unable to obtain lock for object " . $ contenthash ); // TODO different ex type ?
149
- }
150
-
151
- try {
152
- // Purge any existing tags for this object.
153
- $ DB ->delete_records ('tool_objectfs_object_tags ' , ['contenthash ' => $ contenthash ]);
154
-
155
- // Record time in var, so that they all have the same time.
156
- $ timemodified = time ();
157
-
158
- // Store new records.
159
- $ recordstostore = [];
160
- foreach ($ tags as $ key => $ value ) {
161
- $ recordstostore [] = [
162
- 'contenthash ' => $ contenthash ,
163
- 'tagkey ' => $ key ,
164
- 'tagvalue ' => $ value ,
165
- 'timemodified ' => $ timemodified
166
- ];
167
- }
168
- $ DB ->insert_records ('tool_objectfs_object_tags ' , $ recordstostore );
169
-
170
- // We always mark them needing sync after changing the values.
171
- self ::mark_object_tag_sync_status ($ contenthash , self ::SYNC_STATUS_NEEDS_SYNC );
172
- } catch (Exception $ e ) {
173
- // Failed - release lock and rethrow.
174
- $ lock ->release ();
175
- throw $ e ;
114
+ // Purge any existing tags for this object.
115
+ $ DB ->delete_records ('tool_objectfs_object_tags ' , ['contenthash ' => $ contenthash ]);
116
+
117
+ // Record time in var, so that they all have the same time.
118
+ $ timemodified = time ();
119
+
120
+ // Store new records.
121
+ $ recordstostore = [];
122
+ foreach ($ tags as $ key => $ value ) {
123
+ $ recordstostore [] = [
124
+ 'contenthash ' => $ contenthash ,
125
+ 'tagkey ' => $ key ,
126
+ 'tagvalue ' => $ value ,
127
+ 'timemodified ' => $ timemodified
128
+ ];
176
129
}
130
+ $ DB ->insert_records ('tool_objectfs_object_tags ' , $ recordstostore );
177
131
}
178
132
179
133
/**
@@ -188,15 +142,19 @@ public static function get_objects_needing_sync(int $limit) {
188
142
[$ insql , $ inparams ] = $ DB ->get_in_or_equal ([OBJECT_LOCATION_DUPLICATED , OBJECT_LOCATION_EXTERNAL , OBJECT_LOCATION_ORPHANED ], SQL_PARAMS_NAMED );
189
143
$ inparams ['syncstatus ' ] = self ::SYNC_STATUS_NEEDS_SYNC ;
190
144
145
+ // TODO somehow exclude ones already queued ?
191
146
$ records = $ DB ->get_records_select ('tool_objectfs_objects ' , 'tagsyncstatus = :syncstatus AND location ' . $ insql , $ inparams , '' , 'contenthash ' , 0 , $ limit );
192
147
return array_column ($ records , 'contenthash ' );
193
148
}
194
149
195
150
/**
196
- * Replicates the tags stored locally in the DB for a given object to the external object store.
151
+ * Gathers the tag values for a given object contenthash, stores the values in the DB and then replicates these to the external store.
152
+ * Will mark the object sync status to sync status not required.
197
153
* @param string $contenthash
198
154
*/
199
- public static function replicate_local_to_external_tags_for_object (string $ contenthash ) {
155
+ public static function calculate_tags_store_locally_and_replicate_to_external (string $ contenthash ) {
156
+ // TODO someway to genericise this, so we can call it with and without replicating ,etc...
157
+
200
158
// Take lock, to ensure tags are not updated while we sync them.
201
159
$ lock = self ::get_object_tag_lock ($ contenthash );
202
160
@@ -205,18 +163,24 @@ public static function replicate_local_to_external_tags_for_object(string $conte
205
163
}
206
164
207
165
try {
208
- // TODO refactor so all func use contenthash, no objectid.
209
- // Then also probably remove from DB.
210
- $ tags = self ::query_local_tags ($ contenthash );
211
-
212
- // Get current client.
166
+ // Get current client, ensure it is configured correctly.
213
167
$ client = manager::get_client (manager::get_objectfs_config ());
214
168
215
169
if (empty ($ client )) {
216
170
throw new coding_exception ("No client set, cannot replicate tags " ); // TODO moodle ex ?
217
171
}
218
172
219
- $ client ->set_object_tags ($ contenthash , $ tags );
173
+ // Sanity check, ensure supports object tagging.
174
+ if (!$ client ->supports_object_tagging ()) {
175
+ throw new coding_exception ("Client does not support object tagging " ); // TODO different ex ?
176
+ }
177
+
178
+ // Gather tags from sources & store locally.
179
+ $ gatheredtags = self ::gather_tags ($ contenthash );
180
+ self ::store_tags ($ contenthash , $ gatheredtags );
181
+
182
+ // Replicate to external.
183
+ $ client ->set_object_tags ($ contenthash , $ gatheredtags );
220
184
221
185
// Mark as synced, this stops it from re-syncing in the future.
222
186
self ::mark_object_tag_sync_status ($ contenthash , self ::SYNC_STATUS_SYNC_NOT_REQUIRED );
@@ -226,6 +190,23 @@ public static function replicate_local_to_external_tags_for_object(string $conte
226
190
}
227
191
}
228
192
193
+ /**
194
+ * This should only ever be called as part of uploading an object for the first time.
195
+ */
196
+ public static function calculate_tags_and_store_locally_and_return (string $ contenthash ): array {
197
+ // TODO.
198
+ }
199
+
200
+ private static function should_set_object_tags (string $ contenthash ) {
201
+ // If can override, always return true.
202
+ if (self ::can_override_existing_tags ()) {
203
+ return true ;
204
+ }
205
+
206
+ // Else lookup if object already has tags, or if it even exists.
207
+ // TODO.
208
+ }
209
+
229
210
/**
230
211
* Gets a tag writing lock on the given object, ensuring tags are not written/updated while being synced, for example.
231
212
* @param string $contenthash
@@ -249,17 +230,4 @@ private static function mark_object_tag_sync_status(string $contenthash, int $st
249
230
}
250
231
$ DB ->set_field ('tool_objectfs_objects ' , 'tagsyncstatus ' , $ status , ['contenthash ' => $ contenthash ]);
251
232
}
252
-
253
- /**
254
- * Returns true if the tags given are different. They are different when their keys or values do not match, order does not matter.
255
- * @param array $a array of key=>value where keys and values are both strings
256
- * @param array $b array of key=>value where keys and values are both strings
257
- * @return bool
258
- */
259
- private static function are_tags_different (array $ a , array $ b ): bool {
260
- // Order the keys in both arrays, then do a simple equality check.
261
- ksort ($ a );
262
- ksort ($ b );
263
- return $ a !== $ b ;
264
- }
265
233
}
0 commit comments