1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
require_once __DIR__ . '/common.inc.php'; |
4
|
|
|
|
5
|
|
|
use Battis\DataUtilities; |
6
|
|
|
use Battis\BootstrapSmarty\NotificationMessage; |
7
|
|
|
|
8
|
|
|
$MANUALLY_CREATED_COURSES_ACCOUNT = 96; |
9
|
|
|
$DEFAULT_TERM = 195; |
10
|
|
|
|
11
|
|
|
/** |
12
|
|
|
* Generate a unique SIS ID |
13
|
|
|
* |
14
|
|
|
* @param string $name |
15
|
|
|
* |
16
|
|
|
* @return string |
17
|
|
|
**/ |
18
|
|
|
function generateSisId($name) |
|
|
|
|
19
|
|
|
{ |
20
|
|
|
return strtolower(preg_replace('/[^a-z0-9\-]+/i', '-', $_REQUEST['prefix'] . |
21
|
|
|
$name . $_REQUEST['suffix']) . (empty($_REQUEST['unique']) ? '' : '.' . |
22
|
|
|
md5(time()))); |
23
|
|
|
} |
24
|
|
|
|
25
|
|
|
define('STEP_INSTRUCTIONS', 1); |
26
|
|
|
define('STEP_RESULT', 2); |
27
|
|
|
|
28
|
|
|
$step = (empty($_REQUEST['step']) ? STEP_INSTRUCTIONS : $_REQUEST['step']); |
29
|
|
|
|
30
|
|
|
switch ($step) { |
31
|
|
|
case STEP_RESULT: |
32
|
|
|
// TODO use $toolbox->explodeNewLines() |
|
|
|
|
33
|
|
|
$courses = array(); |
34
|
|
|
$courseNames = explode("\n", $_REQUEST['courses']); |
35
|
|
|
foreach ($courseNames as $name) { |
36
|
|
|
if (!empty(trim($name))) { |
37
|
|
|
$courses[]['long_name'] = trim($name); |
38
|
|
|
} |
39
|
|
|
} |
40
|
|
|
|
41
|
|
|
if (empty($_REQUEST['account'])) { |
42
|
|
|
$toolbox->smarty_addMessage( |
43
|
|
|
'Account', |
44
|
|
|
'was not selected, defaulting to the <a target=\"_parent\" href="' . $_SESSION[CANVAS_INSTANCE_URL] . '/accounts/' . $MANUALLY_CREATED_COURSES_ACCOUNT . '">Manually-Created Courses</a> account.', |
45
|
|
|
NotificationMessage::WARNING |
46
|
|
|
); |
47
|
|
|
$account = $MANUALLY_CREATED_COURSES_ACCOUNT; |
48
|
|
|
} else { |
49
|
|
|
$account = $_REQUEST['account']; |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
if (empty($_REQUEST['term'])) { |
53
|
|
|
$toolbox->smarty_addMessage( |
54
|
|
|
'Term', |
55
|
|
|
'was not selected, defaulting to the Default Term.', |
56
|
|
|
NotificationMessage::WARNING |
57
|
|
|
); |
58
|
|
|
$term = $DEFAULT_TERM; |
59
|
|
|
} else { |
60
|
|
|
$term = $_REQUEST['term']; |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
$templated = false; |
64
|
|
View Code Duplication |
if (empty($_REQUEST['template'])) { |
|
|
|
|
65
|
|
|
$toolbox->smarty_addMessage( |
66
|
|
|
'Template', |
67
|
|
|
'was not entered, courses are in default configuration.' |
68
|
|
|
); |
69
|
|
|
} else { |
70
|
|
|
$templated = true; |
71
|
|
|
$template = (is_int($_REQUEST['template']) ? $_REQUEST['template'] : "sis_course_id:{$_REQUEST['template']}"); |
72
|
|
|
|
73
|
|
|
/* pull course settings as completely as possible */ |
74
|
|
|
try { |
75
|
|
|
$source = $toolbox->api_get("courses/$template/settings"); |
76
|
|
|
$source = array_merge( |
77
|
|
|
$source->getArrayCopy(), |
78
|
|
|
$toolbox->api_get("courses/$template")->getArrayCopy() |
79
|
|
|
); |
80
|
|
|
|
81
|
|
|
/* save ID and name to create a nice link later */ |
82
|
|
|
$sourceId = $source['id']; |
83
|
|
|
$sourceName = $source['name']; |
84
|
|
|
|
85
|
|
|
/* clear settings that are provided form entry */ |
86
|
|
|
unset($source['id']); |
87
|
|
|
unset($source['sis_course_id']); |
88
|
|
|
unset($source['integration_id']); |
89
|
|
|
unset($source['name']); |
90
|
|
|
unset($source['course_code']); |
91
|
|
|
unset($source['account_id']); |
92
|
|
|
unset($source['enrollment_term_id']); |
93
|
|
|
unset($source['start_at']); |
94
|
|
|
unset($source['end_at']); |
95
|
|
|
unset($source['enrollments']); |
96
|
|
|
|
97
|
|
|
/* why nest this, I mean... really? */ |
98
|
|
|
$source = array('course' => $source); |
99
|
|
|
|
100
|
|
|
/* pull course navigation */ |
101
|
|
|
$tabs = $toolbox->api_get("courses/$template/tabs", [ |
102
|
|
|
'include[]' => 'external' |
103
|
|
|
]); |
104
|
|
|
$navigation = []; |
105
|
|
|
foreach ($tabs as $tab) { |
106
|
|
|
if ($tab['id'] != 'home' && $tab['id'] != 'settings') { |
107
|
|
|
$navigation[$tab['id']] = $tab; |
108
|
|
|
} |
109
|
|
|
} |
110
|
|
|
uasort($navigation, function ($left, $right) { |
111
|
|
|
return $left['position'] - $right['position']; |
112
|
|
|
}); |
113
|
|
|
} catch (Exception $e) { |
114
|
|
|
$toolbox->exceptionErrorMessage($e); |
115
|
|
|
} |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
$csv = DataUtilities::loadCsvToArray('csv'); |
119
|
|
|
if ($csv) { |
120
|
|
|
$courses = array_merge($courses, $csv); |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
if (!empty($courses)) { |
124
|
|
|
foreach ($courses as $course) { |
125
|
|
|
/* build parameter list */ |
126
|
|
|
$params = array(); |
127
|
|
|
|
128
|
|
|
if (!empty($course['course_id'])) { |
129
|
|
|
$params['sis_course_id'] = $course['course_id']; |
130
|
|
|
} else { |
131
|
|
|
$params['sis_course_id'] = generateSisId((empty($course['course_id']) ? $course['long_name'] : $course['course_id'])); |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
if (!empty($course['long_name'])) { |
135
|
|
|
$params['name'] = $course['long_name']; |
136
|
|
|
} |
137
|
|
|
|
138
|
|
View Code Duplication |
if (!empty($course['short_name'])) { |
|
|
|
|
139
|
|
|
$params['course_code'] = $course['short_name']; |
140
|
|
|
} elseif (!empty($params['name'])) { |
141
|
|
|
$params['course_code'] = $params['name']; |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
if (!empty($course['account_id'])) { |
145
|
|
|
$_account = "sis_account_id:{$course['account_id']}"; |
146
|
|
|
} else { |
147
|
|
|
$_account = $account; |
148
|
|
|
} |
149
|
|
|
|
150
|
|
View Code Duplication |
if (!empty($course['term_id'])) { |
|
|
|
|
151
|
|
|
$params['term_id'] = "sis_term_id:{$course['term_id']}"; |
152
|
|
|
} elseif (!empty($term)) { |
153
|
|
|
$params['term_id'] = $term; |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
if (!empty($course['start_at'])) { |
157
|
|
|
$params['start_at'] = $course['start_at']; |
158
|
|
|
} |
159
|
|
|
|
160
|
|
|
if (!empty($course['end_at'])) { |
161
|
|
|
$params['end_at'] = $course['end_at']; |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
/* create course */ |
165
|
|
|
try { |
166
|
|
|
$course = $toolbox->api_post( |
167
|
|
|
"accounts/$_account/courses", |
168
|
|
|
array( |
169
|
|
|
'course' => $params |
170
|
|
|
) |
171
|
|
|
); |
172
|
|
|
|
173
|
|
|
if ($templated) { |
174
|
|
|
/* duplicate course settings */ |
175
|
|
|
$toolbox->api_put("/courses/{$course['id']}", $source); |
176
|
|
|
|
177
|
|
|
/* duplicate course navigation */ |
178
|
|
View Code Duplication |
foreach ($navigation as $id => $tab) { |
|
|
|
|
179
|
|
|
$toolbox->api_put( |
180
|
|
|
"courses/{$course['id']}/tabs/$id", |
181
|
|
|
[ |
182
|
|
|
'position' => $tab['position'], |
183
|
|
|
'visibility' => $tab['visibility'] |
184
|
|
|
] |
185
|
|
|
); |
186
|
|
|
} |
187
|
|
|
|
188
|
|
|
/* duplicate course content */ |
189
|
|
|
$migration = $toolbox->api_post( |
190
|
|
|
"courses/{$course['id']}/content_migrations", |
191
|
|
|
array( |
192
|
|
|
'migration_type' => 'course_copy_importer', |
193
|
|
|
'settings[source_course_id]' => $template |
194
|
|
|
) |
195
|
|
|
); |
196
|
|
|
|
197
|
|
|
$toolbox->smarty_addMessage( |
198
|
|
|
"<a target=\"_parent\" href=\"{$_SESSION[CANVAS_INSTANCE_URL]}/courses/{$course['id']}\">{$course['name']}</a>", |
199
|
|
|
"has been created as a clone of <a target=\"_parent\" href=\"{$_SESSION[CANVAS_INSTANCE_URL]}/courses/$sourceId\">$sourceName</a>. Course content is being <a target=\"_parent\" href=\"{$_SESSION[CANVAS_INSTANCE_URL]}/courses/{$course['id']}/content_migrations\">migrated</a> right now.", |
200
|
|
|
NotificationMessage::GOOD |
|
|
|
|
201
|
|
|
); |
202
|
|
View Code Duplication |
} else { |
|
|
|
|
203
|
|
|
$toolbox->smarty_addMessage( |
204
|
|
|
"<a target=\"_parent\" href=\"{$_SESSION[CANVAS_INSTANCE_URL]}/courses/{$course['id']}\">{$course['name']}</a>", |
205
|
|
|
"has been created.", |
206
|
|
|
NotificationMessage::GOOD |
|
|
|
|
207
|
|
|
); |
208
|
|
|
} |
209
|
|
|
} catch (Exception $e) { |
210
|
|
|
$toolbox->exceptionErrorMessage($e); |
211
|
|
|
} |
212
|
|
|
} |
213
|
|
|
} else { |
214
|
|
|
$toolbox->smarty_addMessage( |
215
|
|
|
'Courses', |
216
|
|
|
'No course names were entered', |
217
|
|
|
NotificationMessage::ERROR |
|
|
|
|
218
|
|
|
); |
219
|
|
|
} |
220
|
|
|
|
221
|
|
|
/* flow into STEP_INSTRUCTIONS */ |
222
|
|
|
|
223
|
|
|
case STEP_INSTRUCTIONS: |
224
|
|
|
default: |
225
|
|
|
$toolbox->smarty_assign('accounts', $toolbox->getAccountList()); |
226
|
|
|
$toolbox->smarty_assign('terms', $toolbox->getTermList()); |
227
|
|
|
|
228
|
|
|
$toolbox->smarty_assign('formHidden', array('step' => STEP_RESULT)); |
229
|
|
|
$toolbox->smarty_display(basename(__FILE__, '.php') . '/instructions.tpl'); |
230
|
|
|
} |
231
|
|
|
|
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: