@@ -49,27 +49,81 @@ public function get_name() {
49
49
public function execute () {
50
50
global $ DB ;
51
51
52
+ // Get the certificatesperrun, includeinnotvisiblecourses, and certificateexecutionperiod configurations.
53
+ $ certificatesperrun = (int )get_config ('customcert ' , 'certificatesperrun ' );
54
+ $ includeinnotvisiblecourses = (bool )get_config ('customcert ' , 'includeinnotvisiblecourses ' );
55
+ $ certificateexecutionperiod = (int )get_config ('customcert ' , 'certificateexecutionperiod ' );
56
+
57
+ // Get the last processed batch and total certificates to process.
58
+ $ taskprogress = $ DB ->get_record ('customcert_email_task_prgrs ' , ['taskname ' => 'email_certificate_task ' ]);
59
+ $ lastprocessed = $ taskprogress ->last_processed ;
60
+
52
61
// Get all the certificates that have requested someone get emailed.
53
62
$ emailotherslengthsql = $ DB ->sql_length ('c.emailothers ' );
54
63
$ sql = "SELECT c.*, ct.id as templateid, ct.name as templatename, ct.contextid, co.id as courseid,
55
- co.fullname as coursefullname, co.shortname as courseshortname
56
- FROM {customcert} c
57
- JOIN {customcert_templates} ct
64
+ co.fullname as coursefullname, co.shortname as courseshortname
65
+ FROM {customcert} c
66
+ JOIN {customcert_templates} ct
58
67
ON c.templateid = ct.id
59
- JOIN {course} co
60
- ON c.course = co.id
61
- WHERE (c.emailstudents = :emailstudents
62
- OR c.emailteachers = :emailteachers
63
- OR $ emailotherslengthsql >= 3) " ;
64
- if (!$ customcerts = $ DB ->get_records_sql ($ sql , ['emailstudents ' => 1 , 'emailteachers ' => 1 ])) {
68
+ JOIN {course} co
69
+ ON c.course = co.id " ;
70
+
71
+ // Add JOIN with mdl_course_categories to exclude certificates from hidden courses.
72
+ $ sql .= " JOIN {course_categories} cat ON co.category = cat.id " ;
73
+
74
+ // Add conditions to exclude certificates from hidden courses.
75
+ $ sql .= " WHERE (c.emailstudents = :emailstudents
76
+ OR c.emailteachers = :emailteachers
77
+ OR $ emailotherslengthsql >= 3) " ;
78
+
79
+ // Check the includeinnotvisiblecourses configuration.
80
+ if (!$ includeinnotvisiblecourses ) {
81
+ // Exclude certificates from hidden courses.
82
+ $ sql .= " AND co.visible = 1 AND cat.visible = 1 " ;
83
+ }
84
+
85
+ // Add condition based on certificate execution period.
86
+ if ($ certificateexecutionperiod > 0 ) {
87
+ // Include courses with no end date or end date greater than the specified period.
88
+ $ sql .= " AND (co.enddate = 0 OR co.enddate > :enddate) " ;
89
+ $ params ['enddate ' ] = time () - $ certificateexecutionperiod ;
90
+ }
91
+
92
+ // Execute the SQL query.
93
+ if (!$ customcerts = $ DB ->get_records_sql ($ sql , ['emailstudents ' => 1 , 'emailteachers ' => 1 ] + $ params )) {
65
94
return ;
66
95
}
67
96
68
97
// The renderers used for sending emails.
69
98
$ page = new \moodle_page ();
70
99
$ htmlrenderer = $ page ->get_renderer ('mod_customcert ' , 'email ' , 'htmlemail ' );
71
100
$ textrenderer = $ page ->get_renderer ('mod_customcert ' , 'email ' , 'textemail ' );
72
- foreach ($ customcerts as $ customcert ) {
101
+
102
+ // Store the total count of certificates in the database.
103
+ $ totalcertificatestoprocess = count ($ customcerts );
104
+ $ DB ->set_field ('customcert_email_task_prgrs ' , 'total_certificate_to_process ' , $ totalcertificatestoprocess , [
105
+ 'taskname ' => 'email_certificate_task ' ,
106
+ ]);
107
+
108
+ // Check if we need to reset and start from the beginning.
109
+ if ($ lastprocessed >= count ($ customcerts )) {
110
+ $ lastprocessed = 0 ; // Reset to the beginning.
111
+ }
112
+
113
+ if ($ certificatesperrun <= 0 ) {
114
+ // Process all certificates in a single run.
115
+ $ certificates = $ customcerts ;
116
+ } else {
117
+ // Process certificates in batches, starting from the last processed batch.
118
+ $ certificates = array_slice ($ customcerts , $ lastprocessed , $ certificatesperrun );
119
+ }
120
+
121
+ foreach ($ certificates as $ customcert ) {
122
+ // Check if the certificate is hidden, quit early.
123
+ $ fastmoduleinfo = get_fast_modinfo ($ customcert ->courseid )->instances ['customcert ' ][$ customcert ->id ];
124
+ if (!$ fastmoduleinfo ->visible ) {
125
+ continue ;
126
+ }
73
127
// Do not process an empty certificate.
74
128
$ sql = "SELECT ce.*
75
129
FROM {customcert_elements} ce
@@ -111,27 +165,33 @@ public function execute() {
111
165
WHERE ci.customcertid = :customcertid " ;
112
166
$ issuedusers = $ DB ->get_records_sql ($ sql , ['customcertid ' => $ customcert ->id ]);
113
167
114
- // Now, get a list of users who can access the certificate but have not yet.
115
- $ enrolledusers = get_enrolled_users (\context_course::instance ($ customcert ->courseid ), 'mod/customcert:view ' );
116
- foreach ($ enrolledusers as $ enroluser ) {
117
- // Check if the user has already been issued.
118
- if (in_array ($ enroluser ->id , array_keys ((array ) $ issuedusers ))) {
119
- continue ;
120
- }
168
+ // Now, get a list of users who can Manage the certificate.
169
+ $ userswithmanage = get_users_by_capability ($ context , 'mod/customcert:manage ' , 'u.id ' );
121
170
122
- // Now check if the certificate is not visible to the current user.
123
- $ cm = get_fast_modinfo ($ customcert ->courseid , $ enroluser ->id )->instances ['customcert ' ][$ customcert ->id ];
124
- if (!$ cm ->uservisible ) {
125
- continue ;
126
- }
171
+ // Get the context of the Custom Certificate module.
172
+ $ cm = get_coursemodule_from_instance ('customcert ' , $ customcert ->id , $ customcert ->course );
173
+ $ context = \context_module::instance ($ cm ->id );
127
174
128
- // Don't want to email those with the capability to manage the certificate.
129
- if (has_capability ('mod/customcert:manage ' , $ context , $ enroluser ->id )) {
175
+ // Now, get a list of users who can view and issue the certificate but have not yet.
176
+ // Get users with the mod/customcert:receiveissue capability in the Custom Certificate module context.
177
+ $ userswithissue = get_users_by_capability ($ context , 'mod/customcert:receiveissue ' );
178
+ // Get users with mod/customcert:view capability.
179
+ $ userswithview = get_users_by_capability ($ context , 'mod/customcert:view ' );
180
+ // Users with both mod/customcert:view and mod/customcert:receiveissue cabapilities.
181
+ $ userswithissueview = array_intersect_key ($ userswithissue , $ userswithview );
182
+
183
+ $ infomodule = new \core_availability \info_module ($ fastmoduleinfo );
184
+ // Filter who can't access due to availability restriction, from the full list.
185
+ $ userscanissue = $ infomodule ->filter_user_list ($ userswithissueview );
186
+
187
+ foreach ($ userscanissue as $ enroluser ) {
188
+ // Check if the user has already been issued.
189
+ if (in_array ($ enroluser ->id , array_keys ((array )$ issuedusers ))) {
130
190
continue ;
131
191
}
132
192
133
- // Only email those with the capability to receive the certificate.
134
- if (! has_capability ( ' mod/customcert:receiveissue ' , $ context , $ enroluser ->id )) {
193
+ // Don't want to email those with the capability to manage the certificate.
194
+ if (in_array ( $ enroluser ->id , array_keys (( array ) $ userswithmanage ) )) {
135
195
continue ;
136
196
}
137
197
@@ -164,7 +224,7 @@ public function execute() {
164
224
}
165
225
}
166
226
167
- // If there are no users to email we can return early.
227
+ // If there are no users to email, we can return early.
168
228
if (!$ issuedusers ) {
169
229
continue ;
170
230
}
@@ -175,6 +235,7 @@ public function execute() {
175
235
return ;
176
236
}
177
237
238
+ $ issueids = [];
178
239
// Now, email the people we need to.
179
240
foreach ($ issuedusers as $ user ) {
180
241
// Set up the user.
@@ -248,8 +309,21 @@ public function execute() {
248
309
}
249
310
250
311
// Set the field so that it is emailed.
251
- $ DB -> set_field ( ' customcert_issues ' , ' emailed ' , 1 , [ ' id ' => $ user ->issueid ]) ;
312
+ $ issueids [] = $ user ->issueid ;
252
313
}
314
+
315
+ if (!empty ($ issueids )) {
316
+ list ($ sql , $ params ) = $ DB ->get_in_or_equal ($ issueids , SQL_PARAMS_NAMED , 'id ' );
317
+ $ DB ->set_field_select ('customcert_issues ' , 'emailed ' , 1 , 'id ' . $ sql , $ params );
318
+ }
319
+ }
320
+
321
+ // Update the last processed position, if run in batches.
322
+ if ($ certificatesperrun > 0 ) {
323
+ $ newlastprocessed = $ lastprocessed + count ($ certificates );
324
+ $ DB ->set_field ('customcert_email_task_prgrs ' , 'last_processed ' , $ newlastprocessed , [
325
+ 'taskname ' => 'email_certificate_task ' ,
326
+ ]);
253
327
}
254
328
}
255
329
}
0 commit comments