39
39
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
40
40
*/
41
41
class data_registry {
42
-
43
- /**
44
- * @var array Inheritance between context levels.
45
- */
46
- private static $ contextlevelinheritance = [
47
- CONTEXT_USER => [CONTEXT_SYSTEM ],
48
- CONTEXT_COURSECAT => [CONTEXT_SYSTEM ],
49
- CONTEXT_COURSE => [CONTEXT_COURSECAT , CONTEXT_SYSTEM ],
50
- CONTEXT_MODULE => [CONTEXT_COURSE , CONTEXT_COURSECAT , CONTEXT_SYSTEM ],
51
- CONTEXT_BLOCK => [CONTEXT_COURSE , CONTEXT_COURSECAT , CONTEXT_SYSTEM ],
52
- ];
53
-
54
42
/**
55
43
* Returns purpose and category var names from a context class name
56
44
*
@@ -83,7 +71,6 @@ public static function var_names_from_context($classname, $pluginname = '') {
83
71
* @return int[]|false[]
84
72
*/
85
73
public static function get_defaults ($ contextlevel , $ pluginname = '' ) {
86
-
87
74
$ classname = \context_helper::get_class_for_level ($ contextlevel );
88
75
list ($ purposevar , $ categoryvar ) = self ::var_names_from_context ($ classname , $ pluginname );
89
76
@@ -104,10 +91,10 @@ public static function get_defaults($contextlevel, $pluginname = '') {
104
91
}
105
92
106
93
if (empty ($ purposeid )) {
107
- $ purposeid = false ;
94
+ $ purposeid = context_instance:: NOTSET ;
108
95
}
109
96
if (empty ($ categoryid )) {
110
- $ categoryid = false ;
97
+ $ categoryid = context_instance:: NOTSET ;
111
98
}
112
99
113
100
return [$ purposeid , $ categoryid ];
@@ -190,69 +177,92 @@ public static function get_subject_scope(\context $context) {
190
177
* @return persistent|false It return a 'purpose' instance or a 'category' instance, depending on $element
191
178
*/
192
179
public static function get_effective_context_value (\context $ context , $ element , $ forcedvalue = false ) {
180
+ global $ DB ;
193
181
194
182
if ($ element !== 'purpose ' && $ element !== 'category ' ) {
195
183
throw new coding_exception ('Only \'purpose \' and \'category \' are supported. ' );
196
184
}
197
185
$ fieldname = $ element . 'id ' ;
198
186
199
- if (empty ($ forcedvalue )) {
200
- $ instance = context_instance::get_record_by_contextid ($ context ->id , false );
201
-
202
- if (!$ instance ) {
203
- // If the instance does not have a value defaults to not set, so we grab the context level default as its value.
204
- $ instancevalue = context_instance::NOTSET ;
205
- } else {
206
- $ instancevalue = $ instance ->get ($ fieldname );
207
- }
187
+ if (!empty ($ forcedvalue ) && ($ forcedvalue === context_instance::INHERIT )) {
188
+ // Do not include the current context when calculating the value.
189
+ // This has the effect that an inheritted value is calculated.
190
+ $ parentcontextids = $ context ->get_parent_context_ids (false );
191
+ } else if (!empty ($ forcedvalue ) && ($ forcedvalue !== context_instance::NOTSET )) {
192
+ return self ::get_element_instance ($ element , $ forcedvalue );
208
193
} else {
209
- $ instancevalue = $ forcedvalue ;
194
+ // Fetch all parent contexts, including self.
195
+ $ parentcontextids = $ context ->get_parent_context_ids (true );
210
196
}
197
+ list ($ insql , $ inparams ) = $ DB ->get_in_or_equal ($ parentcontextids , SQL_PARAMS_NAMED );
198
+ $ inparams ['contextmodule ' ] = CONTEXT_MODULE ;
211
199
212
- // Not set.
213
- if ($ instancevalue == context_instance::NOTSET ) {
214
-
215
- // The effective value varies depending on the context level.
216
- if ($ context ->contextlevel == CONTEXT_USER ) {
217
- // Use the context level value as we don't allow people to set specific instances values.
200
+ if ('purpose ' === $ element ) {
201
+ $ elementjoin = 'LEFT JOIN {tool_dataprivacy_purpose} ele ON ctxins.purposeid = ele.id ' ;
202
+ $ elementfields = purpose::get_sql_fields ('ele ' , 'ele ' );
203
+ } else {
204
+ $ elementjoin = 'LEFT JOIN {tool_dataprivacy_category} ele ON ctxins.categoryid = ele.id ' ;
205
+ $ elementfields = category::get_sql_fields ('ele ' , 'ele ' );
206
+ }
207
+ $ contextfields = \context_helper::get_preload_record_columns_sql ('ctx ' );
208
+ $ fields = implode (', ' , ['ctx.id ' , 'm.name AS modname ' , $ contextfields , $ elementfields ]);
209
+
210
+ $ sql = "SELECT $ fields
211
+ FROM {context} ctx
212
+ LEFT JOIN {tool_dataprivacy_ctxinstance} ctxins ON ctx.id = ctxins.contextid
213
+ LEFT JOIN {course_modules} cm ON ctx.contextlevel = :contextmodule AND ctx.instanceid = cm.id
214
+ LEFT JOIN {modules} m ON m.id = cm.module
215
+ {$ elementjoin }
216
+ WHERE ctx.id {$ insql }
217
+ ORDER BY ctx.path DESC " ;
218
+ $ contextinstances = $ DB ->get_records_sql ($ sql , $ inparams );
219
+
220
+ // Check whether this context is a user context, or a child of a user context.
221
+ // All children of a User context share the same context and cannot be set individually.
222
+ foreach ($ contextinstances as $ record ) {
223
+ \context_helper::preload_from_record ($ record );
224
+ $ parent = \context::instance_by_id ($ record ->id , false );
225
+
226
+ if ($ parent ->contextlevel == CONTEXT_USER ) {
227
+ // Use the context level value for the user.
218
228
return self ::get_effective_contextlevel_value (CONTEXT_USER , $ element );
219
229
}
230
+ }
220
231
221
- $ parents = $ context -> get_parent_contexts ( true );
222
- foreach ( $ parents as $ parent ) {
223
- if ( $ parent -> contextlevel == CONTEXT_USER ) {
224
- // Use the context level value as we don't allow people to set specific instances values.
225
- return self :: get_effective_contextlevel_value ( CONTEXT_USER , $ element );
226
- }
232
+ foreach ( $ contextinstances as $ record ) {
233
+ $ parent = \context:: instance_by_id ( $ record -> id , false );
234
+
235
+ $ checkcontextlevel = false ;
236
+ if ( empty ( $ record -> eleid )) {
237
+ $ checkcontextlevel = true ;
227
238
}
228
239
229
- // Check if we need to pass the plugin name of an activity.
230
- $ forplugin = '' ;
231
- if ($ context ->contextlevel == CONTEXT_MODULE ) {
232
- list ($ course , $ cm ) = get_course_and_cm_from_cmid ($ context ->instanceid );
233
- $ forplugin = $ cm ->modname ;
240
+ if (!empty ($ forcedvalue ) && context_instance::NOTSET === $ forcedvalue ) {
241
+ $ checkcontextlevel = true ;
234
242
}
235
- // Use the default context level value.
236
- list ($ purposeid , $ categoryid ) = self ::get_effective_default_contextlevel_purpose_and_category (
237
- $ context ->contextlevel , false , false , $ forplugin
238
- );
239
243
240
- return self ::get_element_instance ($ element , $ $ fieldname );
241
- }
244
+ if ($ checkcontextlevel ) {
245
+ // Check for a value at the contextlevel
246
+ $ forplugin = empty ($ record ->modname ) ? '' : $ record ->modname ;
247
+ list ($ purposeid , $ categoryid ) = self ::get_effective_default_contextlevel_purpose_and_category (
248
+ $ parent ->contextlevel , false , false , $ forplugin );
242
249
243
- // Specific value for this context instance.
244
- if ($ instancevalue != context_instance::INHERIT ) {
245
- return self ::get_element_instance ($ element , $ instancevalue );
246
- }
250
+ $ instancevalue = $ $ fieldname ;
247
251
248
- // This context is using inherited so let's return the parent effective value.
249
- $ parentcontext = $ context ->get_parent_context ();
250
- if (!$ parentcontext ) {
251
- return false ;
252
+ if (context_instance::NOTSET !== $ instancevalue && context_instance::INHERIT !== $ instancevalue ) {
253
+ // There is an actual value. Return it.
254
+ return self ::get_element_instance ($ element , $ instancevalue );
255
+ }
256
+ } else {
257
+ $ elementclass = "\\tool_dataprivacy \\{$ element }" ;
258
+ $ instance = new $ elementclass (null , $ elementclass ::extract_record ($ record , 'ele ' ));
259
+ $ instance ->validate ();
260
+
261
+ return $ instance ;
262
+ }
252
263
}
253
264
254
- // The forced value should not be transmitted to parent contexts.
255
- return self ::get_effective_context_value ($ parentcontext , $ element );
265
+ throw new coding_exception ('Something went wrong, system defaults should be set and we should already have a value. ' );
256
266
}
257
267
258
268
/**
@@ -264,11 +274,9 @@ public static function get_effective_context_value(\context $context, $element,
264
274
*
265
275
* @param int $contextlevel
266
276
* @param string $element 'category' or 'purpose'
267
- * @param int $forcedvalue Use this value as if this was this context level purpose.
268
277
* @return \tool_dataprivacy\purpose|false
269
278
*/
270
- public static function get_effective_contextlevel_value ($ contextlevel , $ element , $ forcedvalue = false ) {
271
-
279
+ public static function get_effective_contextlevel_value ($ contextlevel , $ element ) {
272
280
if ($ element !== 'purpose ' && $ element !== 'category ' ) {
273
281
throw new coding_exception ('Only \'purpose \' and \'category \' are supported. ' );
274
282
}
@@ -279,39 +287,15 @@ public static function get_effective_contextlevel_value($contextlevel, $element,
279
287
'have a purpose or a category. ' );
280
288
}
281
289
282
- if ($ forcedvalue === false ) {
283
- $ instance = contextlevel::get_record_by_contextlevel ($ contextlevel , false );
284
- if (!$ instance ) {
285
- // If the context level does not have a value defaults to not set, so we grab the context level default as
286
- // its value.
287
- $ instancevalue = context_instance::NOTSET ;
288
- } else {
289
- $ instancevalue = $ instance ->get ($ fieldname );
290
- }
291
- } else {
292
- $ instancevalue = $ forcedvalue ;
293
- }
290
+ list ($ purposeid , $ categoryid ) = self ::get_effective_default_contextlevel_purpose_and_category ($ contextlevel );
294
291
295
- // Not set -> Use the default context level value .
296
- if ($ instancevalue == context_instance::NOTSET ) {
297
- list ( $ purposeid , $ categoryid ) = self :: get_effective_default_contextlevel_purpose_and_category ( $ contextlevel );
292
+ // Note: The $$fieldname points to either $purposeid, or $categoryid .
293
+ if (context_instance:: NOTSET ! == $ $ fieldname && context_instance::INHERIT !== $ $ fieldname ) {
294
+ // There is a specific value set.
298
295
return self ::get_element_instance ($ element , $ $ fieldname );
299
296
}
300
297
301
- // Specific value for this context instance.
302
- if ($ instancevalue != context_instance::INHERIT ) {
303
- return self ::get_element_instance ($ element , $ instancevalue );
304
- }
305
-
306
- if ($ contextlevel == CONTEXT_SYSTEM ) {
307
- throw new coding_exception ('Something went wrong, system defaults should be set and we should already have a value. ' );
308
- }
309
-
310
- // If we reach this point is that we are inheriting so get the parent context level and repeat.
311
- $ parentcontextlevel = reset (self ::$ contextlevelinheritance [$ contextlevel ]);
312
-
313
- // Forced value are intentionally not passed as the force value should only affect the immediate context level.
314
- return self ::get_effective_contextlevel_value ($ parentcontextlevel , $ element );
298
+ throw new coding_exception ('Something went wrong, system defaults should be set and we should already have a value. ' );
315
299
}
316
300
317
301
/**
@@ -320,13 +304,13 @@ public static function get_effective_contextlevel_value($contextlevel, $element,
320
304
* @param int $contextlevel
321
305
* @param int|bool $forcedpurposevalue Use this value as if this was this context level purpose.
322
306
* @param int|bool $forcedcategoryvalue Use this value as if this was this context level category.
323
- * @param string $activity The plugin name of the activity .
307
+ * @param string $component The name of the component to check .
324
308
* @return int[]
325
309
*/
326
310
public static function get_effective_default_contextlevel_purpose_and_category ($ contextlevel , $ forcedpurposevalue = false ,
327
- $ forcedcategoryvalue = false , $ activity = '' ) {
328
-
329
- list ($ purposeid , $ categoryid ) = self ::get_defaults ($ contextlevel , $ activity );
311
+ $ forcedcategoryvalue = false , $ component = '' ) {
312
+ // Get the defaults for this context level.
313
+ list ($ purposeid , $ categoryid ) = self ::get_defaults ($ contextlevel , $ component );
330
314
331
315
// Honour forced values.
332
316
if ($ forcedpurposevalue ) {
@@ -336,37 +320,19 @@ public static function get_effective_default_contextlevel_purpose_and_category($
336
320
$ categoryid = $ forcedcategoryvalue ;
337
321
}
338
322
339
- // Not set == INHERIT for defaults.
340
- if ($ purposeid == context_instance::INHERIT || $ purposeid == context_instance::NOTSET ) {
341
- $ purposeid = false ;
342
- }
343
- if ($ categoryid == context_instance::INHERIT || $ categoryid == context_instance::NOTSET ) {
344
- $ categoryid = false ;
345
- }
346
-
347
- if ($ contextlevel != CONTEXT_SYSTEM && ($ purposeid === false || $ categoryid === false )) {
348
- foreach (self ::$ contextlevelinheritance [$ contextlevel ] as $ parent ) {
323
+ if ($ contextlevel == CONTEXT_USER ) {
324
+ // Only user context levels inherit from a parent context level.
325
+ list ($ parentpurposeid , $ parentcategoryid ) = self ::get_defaults (CONTEXT_SYSTEM );
349
326
350
- list ($ parentpurposeid , $ parentcategoryid ) = self ::get_defaults ($ parent );
351
- // Not set == INHERIT for defaults.
352
- if ($ parentpurposeid == context_instance::INHERIT || $ parentpurposeid == context_instance::NOTSET ) {
353
- $ parentpurposeid = false ;
354
- }
355
- if ($ parentcategoryid == context_instance::INHERIT || $ parentcategoryid == context_instance::NOTSET ) {
356
- $ parentcategoryid = false ;
357
- }
358
-
359
- if ($ purposeid === false && $ parentpurposeid ) {
360
- $ purposeid = $ parentpurposeid ;
361
- }
327
+ if (context_instance::INHERIT == $ purposeid || context_instance::NOTSET == $ purposeid ) {
328
+ $ purposeid = $ parentpurposeid ;
329
+ }
362
330
363
- if ($ categoryid === false && $ parentcategoryid ) {
364
- $ categoryid = $ parentcategoryid ;
365
- }
331
+ if (context_instance::INHERIT == $ categoryid || context_instance::NOTSET == $ categoryid ) {
332
+ $ categoryid = $ parentcategoryid ;
366
333
}
367
334
}
368
335
369
- // They may still be false, but we return anyway.
370
336
return [$ purposeid , $ categoryid ];
371
337
}
372
338
@@ -379,7 +345,6 @@ public static function get_effective_default_contextlevel_purpose_and_category($
379
345
* @return \core\persistent
380
346
*/
381
347
private static function get_element_instance ($ element , $ id ) {
382
-
383
348
if ($ element !== 'purpose ' && $ element !== 'category ' ) {
384
349
throw new coding_exception ('No other elements than purpose and category are allowed ' );
385
350
}
0 commit comments