php js css php js css

Scripts

Save Script Run
Attached Artifacts
Title
PHP Code
<?php /** * Deep inspection + demo data generator: AF Courses, Schedules, Units. * Creates 50 realistic courses with future schedules (Term 1-4 2027), * products, schedules and per-week units across levels/age groups. */ $iCoursesTarget = 50; // ---------- 1. Inspect existing data ---------- echo "=== INSPECTION ===\n"; echo "Courses total: " . \Components\AF\Courses::getCount() . "\n"; echo "Schedules total: " . \Components\AF\Courses\Schedules::getCount() . "\n"; echo "Units total: " . \Components\AF\Courses\Units::getCount() . "\n"; echo "Sessions: " . \Components\AF\Courses\Configuration\Sessions::getCount() . "\n"; echo "Levels: " . \Components\AF\Courses\Configuration\Levels::getCount() . "\n"; echo "Products: " . \Components\Commerce\Products::getCount() . "\n\n"; // ---------- 2. Ensure future sessions exist (Term 2-4 2027) ---------- $arrNewSessions = [ ['2027', 'Term 2 2027', '2027-04-19', '2027-06-19'], ['2027', 'Term 3 2027', '2027-07-12', '2027-09-11'], ['2027', 'Term 4 2027', '2027-10-04', '2027-12-04'], ]; $arrSessionIds = [51 => ['2027-02-01', '2027-03-28']]; // existing Term 1 2027 foreach ($arrNewSessions as $arrS) { $arrExisting = \Components\AF\Courses\Configuration\Sessions::getAll([ 'filter' => [['session_name', '=', $arrS[1]], 'AND', ['session_year', '=', $arrS[0]]], 'limit' => 1, ]); if (count($arrExisting)) { $iSid = (int)$arrExisting[0]['session_id']; } else { $iSid = (int)\Components\AF\Courses\Configuration\Sessions::save([ 'session_year' => $arrS[0], 'session_name' => $arrS[1], 'session_start_date' => $arrS[2], 'session_end_date' => $arrS[3], 'session_visible_public' => 1, ]); } $arrSessionIds[$iSid] = [$arrS[2], $arrS[3]]; } echo "Sessions available: " . implode(', ', array_keys($arrSessionIds)) . "\n"; // ---------- 3. Course blueprint builder ---------- $arrTeachers = [1351, 1181, 1052, 1180, 1182]; // Rooms: CBD Campus(2): 7,8,9,23,24 | St Kilda(1): 3,4,5,6 | Online Zooms(17): 19,20,21 $arrRooms = [ 'cbd' => [7, 8, 9, 23, 24], 'stkilda' => [3, 4, 5, 6], 'online' => [19, 20, 21], ]; $arrDayNames = [1 => 'Mon', 2 => 'Tue', 3 => 'Wed', 4 => 'Thu', 5 => 'Fri', 6 => 'Sat', 7 => 'Sun']; $arrFullDayNames = [1 => 'monday', 2 => 'tuesday', 3 => 'wednesday', 4 => 'thursday', 5 => 'friday', 6 => 'saturday', 7 => 'sunday']; $fnCourse = function($arrDef) { return $arrDef; }; // Build 50 course definitions: [group, level, levelName, ageGroup, type, pace, hoursPerClass, timeStart, timeEnd, days, campusKey] $arrCourses = []; // Adults - Standard progression (16) foreach ([ ['A1.1', 2], ['A1.2', 7], ['A1.3', 8], ['A1.4', 9], ['A2.1', 10], ['A2.2', 11], ['A2.3', 12], ['A2.4', 131], ['B1.1', 14], ['B1.2', 15], ['B1.3', 16], ['B2.1', 17], ['B2.2', 18], ['C1', 6], ['C2', 132], ['A2.5', 27], ] as $i => $arrLvl) { $iDay = ($i % 5) + 1; $bEvening = ($i % 2 === 0); $arrCourses[] = [ 'level' => $arrLvl[0], 'level_id' => $arrLvl[1], 'age' => 1, 'type' => 2, 'pace' => 38, 'hpc' => 2.0, 'start' => $bEvening ? '18:00:00' : '09:30:00', 'end' => $bEvening ? '20:00:00' : '11:30:00', 'days' => [$iDay], 'campus' => ($i % 4 === 3) ? 'online' : 'cbd', 'teacher' => $arrTeachers[$i % 5], ]; } // Adults - speciality (8) $arrSpecial = [ ['Conversation B1', 14, 29, 39, 1.5, '18:00:00', '19:30:00', 2], ['Conversation B2', 17, 29, 39, 1.5, '12:00:00', '13:30:00', 4], ['French for Travel A1', 2, 27, 39, 1.5, '17:30:00', '19:00:00', 5], ['Easy Going A2', 10, 30, 39, 1.5, '10:00:00', '11:30:00', 3], ['DELF B2 Prep', 17, 24, 38, 2.0, '17:00:00', '19:00:00', 6], ['Grammar Workshop B1', 14, 16, 44, 6.0, '09:30:00', '15:30:00', 6], ['Pronunciation Workshop A2', 10, 16, 44, 6.0, '09:30:00', '15:30:00', 6], ['TCF Exam Prep', 130, 24, 38, 2.0, '18:00:00', '20:00:00', 1], ]; foreach ($arrSpecial as $i => $a) { $arrCourses[] = [ 'level' => $a[0], 'level_id' => $a[1], 'age' => 1, 'type' => $a[2], 'pace' => $a[3], 'hpc' => $a[4], 'start' => $a[5], 'end' => $a[6], 'days' => [$a[7]], 'campus' => ($i === 7) ? 'online' : 'stkilda', 'teacher' => $arrTeachers[($i + 2) % 5], ]; } // Teens (10) foreach ([['Year 7', 22], ['Year 8', 23], ['Year 9', 24], ['Year 10', 133], ['Year 11', 134], ['Year 12', 135]] as $i => $arrLvl) { $arrCourses[] = [ 'level' => $arrLvl[0], 'level_id' => $arrLvl[1], 'age' => 2, 'type' => ($i % 3 === 0 ? 23 : 2), 'pace' => 38, 'hpc' => 2.0, 'start' => '16:30:00', 'end' => '18:30:00', 'days' => [($i % 4) + 1], 'campus' => ($i % 3 === 2) ? 'online' : 'cbd', 'teacher' => $arrTeachers[($i + 1) % 5], ]; } foreach ([['Teens Conversation A2', 10, 29, 5], ['DELF Junior A2 Prep', 10, 24, 6], ['Taste of French Y9', 24, 23, 3], ['Taste of French Y11', 134, 23, 4]] as $i => $a) { $arrCourses[] = [ 'level' => $a[0], 'level_id' => $a[1], 'age' => 2, 'type' => $a[2], 'pace' => 39, 'hpc' => 1.5, 'start' => '16:45:00', 'end' => '18:15:00', 'days' => [$a[3]], 'campus' => 'stkilda', 'teacher' => $arrTeachers[($i + 3) % 5], ]; } // Children (10) foreach ([['Prep', 136], ['Year 1', 137], ['Year 2', 138], ['Year 3', 139]] as $i => $arrLvl) { $arrCourses[] = [ 'level' => $arrLvl[0], 'level_id' => $arrLvl[1], 'age' => 3, 'type' => 2, 'pace' => 39, 'hpc' => 1.5, 'start' => '10:00:00', 'end' => '11:30:00', 'days' => [6], 'campus' => 'stkilda', 'teacher' => $arrTeachers[$i % 5], ]; } foreach ([['Taste of French Kids 1', 136, 22, 6], ['Taste of French Kids 2', 137, 22, 6], ['Kids Holiday Immersion A1', 2, 25, 2], ['Kids Holiday Immersion A2', 130, 25, 2], ['Kids Conversation B1', 14, 29, 3]] as $i => $a) { $arrCourses[] = [ 'level' => $a[0], 'level_id' => $a[1], 'age' => 3, 'type' => $a[2], 'pace' => 39, 'hpc' => 1.5, 'start' => '13:00:00', 'end' => '14:30:00', 'days' => [$a[3]], 'campus' => ($i > 1 ? 'cbd' : 'stkilda'), 'teacher' => $arrTeachers[($i + 4) % 5], ]; } // Toddlers (4) foreach ([['French Play Group', 21, '09:30:00', '10:15:00'], ['Mum & Me', 19, '10:30:00', '11:15:00'], ['Story Time', 20, '11:30:00', '12:15:00'], ['French Play Group 2', 21, '09:30:00', '10:15:00']] as $i => $a) { $arrCourses[] = [ 'level' => 'Pre-School', 'level_id' => 1, 'age' => 12, 'type' => $a[1], 'pace' => 37, 'hpc' => 0.75, 'start' => $a[2], 'end' => $a[3], 'days' => [($i % 2) + 5], 'campus' => 'stkilda', 'teacher' => $arrTeachers[$i % 5], ]; } // Corporate + Intensive (2) $arrCourses[] = [ 'level' => 'A1.1 Corporate', 'level_id' => 2, 'age' => 4, 'type' => 28, 'pace' => 38, 'hpc' => 2.0, 'start' => '08:00:00', 'end' => '10:00:00', 'days' => [2, 4], 'campus' => 'cbd', 'teacher' => $arrTeachers[0], ]; $arrCourses[] = [ 'level' => 'A1 Intensive', 'level_id' => 1, 'age' => 1, 'type' => 3, 'pace' => 45, 'hpc' => 4.0, 'start' => '09:00:00', 'end' => '13:00:00', 'days' => [1, 2, 3, 4, 5], 'campus' => 'online', 'teacher' => $arrTeachers[1], ]; $arrCourses[] = [ 'level' => 'Conversation A2', 'level_id' => 10, 'age' => 1, 'type' => 29, 'pace' => 39, 'hpc' => 1.5, 'start' => '12:00:00', 'end' => '13:30:00', 'days' => [3], 'campus' => 'stkilda', 'teacher' => $arrTeachers[2], ]; $arrCourses = array_slice($arrCourses, 0, $iCoursesTarget); echo "Course definitions: " . count($arrCourses) . "\n\n"; // ---------- 4. Create courses ---------- $arrSessionKeys = array_keys($arrSessionIds); $iCreated = 0; $arrErrors = []; foreach ($arrCourses as $i => $a) { // Assign sessions round-robin, then a start date inside the session window $iSessionId = $arrSessionKeys[$i % count($arrSessionKeys)]; list($sSessStart, $sSessEnd) = $arrSessionIds[$iSessionId]; $iDayNum = $a['days'][0]; $iOffset = ($i * 7) % 28; // vary start week $oStart = new DateTime($sSessStart); $oStart->modify('+' . $iOffset . ' days'); while ((int)$oStart->format('N') !== $iDayNum) { $oStart->modify('+1 day'); } // 8 weekly classes per schedule $oEnd = clone $oStart; $oEnd->modify('+' . (count($a['days']) * 7) . ' days'); $sCourseCode = $a['level'] . '-' . $arrDayNames[$iDayNum] . '-' . substr(str_replace('-', '', $sSessStart), 0, 8) . '-' . ($i + 1); // Product if (!isset($iBrandId)) { $arrBrand = \Components\Commerce\Products\Brands::getAll(['limit' => 1]); if (count($arrBrand)) { $iBrandId = (int)$arrBrand[0]['product_brand_id']; } else { $iBrandId = (int)\Components\Commerce\Products\Brands::save(['product_brand_title' => 'Alliance Française']); } echo "Using brand: {$iBrandId}\n"; } $fHoursTotal = $a['hpc'] * 8; $fPrice = round(($fHoursTotal * 55) / 10) * 10; $iProductId = 0; $arrProd = \Components\Commerce\Products::getAll(['filter' => [['product_code', '=', $sCourseCode]], 'limit' => 1]); if (count($arrProd)) { $iProductId = (int)$arrProd[0]['product_id']; } else { $iProductId = (int)\Components\Commerce\Products::save([ 'product_title' => $a['level'] . ' ' . $arrDayNames[$iDayNum] . ' ' . ($iSessionId === 51 ? 'Term 1 2027' : '2027'), 'product_price_base' => $fPrice, 'product_code' => $sCourseCode, 'product_brand_id' => $iBrandId ?: 1, 'product_is_offline' => 1, ]); } $arrLocationIds = $arrRooms[$a['campus']]; $iLocationId = $arrLocationIds[$i % count($arrLocationIds)]; $sLocationType = ($a['campus'] === 'online') ? 'remote' : 'internal'; // Skip if the course already exists (idempotent re-run) $arrExistingCourse = \Components\AF\Courses::getAll(['filter' => [['course_code', '=', $sCourseCode]], 'limit' => 1]); if (count($arrExistingCourse)) { echo "Skip (exists): {$sCourseCode}\n"; continue; } // Course $arrCourse = [ 'course_code' => $sCourseCode, 'course_type' => 'collective', 'course_start_date' => $oStart->format('Y-m-d'), 'course_start_time' => $a['start'], 'course_end_date' => $oEnd->format('Y-m-d'), 'course_end_time' => $a['end'], 'course_total_hours' => number_format($fHoursTotal, 2, '.', ''), 'course_objectives' => $a['level'] . ' objectives: develop listening and speaking skills, build core vocabulary and consolidate grammar through interactive activities.', 'session_id' => $iSessionId, 'age_group_id' => $a['age'], 'type_id' => $a['type'], 'pace_id' => $a['pace'], 'product_id' => $iProductId, 'location_ids_cache' => (string)$iLocationId, 'level_ids_cache' => (string)$a['level_id'], 'course_is_day_' . $arrFullDayNames[$iDayNum] => 1, 'course_hidden_in_selector' => 0, 'course_membership_option' => 'hidden', ]; $iCourseId = (int)\Components\AF\Courses::save($arrCourse); if (!$iCourseId) { $arrErrors[] = "Course save failed: {$sCourseCode}"; continue; } // Level link \Components\AF\Courses\Levels::save(['course_id' => $iCourseId, 'level_id' => $a['level_id']]); // Schedule $arrSchedule = [ 'schedule_start_date' => $oStart->format('Y-m-d'), 'schedule_end_date' => $oEnd->format('Y-m-d'), 'schedule_start_time' => $a['start'], 'schedule_end_time' => $a['end'], 'schedule_location_type' => $sLocationType, 'location_id' => $iLocationId, 'teacher_id' => $a['teacher'], 'course_id' => $iCourseId, 'schedule_day' => $a['days'], ]; $iScheduleId = (int)\Components\AF\Courses\Schedules::save($arrSchedule); // Units - one per class occurrence $iUnits = 0; $oUnitDate = clone $oStart; for ($u = 0; $u < 8; $u++) { // step to the next configured weekday while (!in_array((int)$oUnitDate->format('N'), $a['days'])) { $oUnitDate->modify('+1 day'); } \Components\AF\Courses\Units::save([ 'unit_date' => $oUnitDate->format('Y-m-d'), 'unit_start_time' => $a['start'], 'unit_end_time' => $a['end'], 'unit_comment' => ($u === 0 ? 'Introduction and placement' : null), 'unit_billing_status' => 'unpaid', 'unit_location_type' => $sLocationType, 'location_id' => $iLocationId, 'teacher_id' => $a['teacher'], 'schedule_id' => $iScheduleId, 'course_id' => $iCourseId, ]); $iUnits++; $oUnitDate->modify('+1 day'); } $iCreated++; echo sprintf("#%02d course_id=%d sched=%d units=%d %s | %s %s-%s | session %d | lvl %s | product %d \$%.2f\n", $iCreated, $iCourseId, $iScheduleId, $iUnits, $sCourseCode, $oStart->format('d M Y'), $a['start'], substr($a['end'], 0, 5), $iSessionId, $a['level'], $iProductId, $fPrice); \Components\Settings\Developer\Threads::setCurrentProgressStatus("Created {$iCreated} / " . count($arrCourses) . " courses…"); } echo "\n=== SUMMARY ===\n"; echo "Created courses: {$iCreated}\n"; echo "Courses total now: " . \Components\AF\Courses::getCount() . "\n"; echo "Schedules total now: " . \Components\AF\Courses\Schedules::getCount() . "\n"; echo "Units total now: " . \Components\AF\Courses\Units::getCount() . "\n"; if (count($arrErrors)) { echo "Errors:\n" . implode("\n", $arrErrors) . "\n"; } else { echo "No errors.\n"; }

Run Log

▼ Today 4:53am ✗ Error 0.3s
=== INSPECTION ===
Courses total: 279
Schedules total: 249
Units total: 2305
Sessions: 48
Levels: 51
Products: 85

Sessions available: 51, 52, 53, 54
Course definitions: 49

Tried to create product without a brand
#0 /usr/lib/php/Oncord/beta/Framework/Components/DataABC/DataABC.inc.php(4048): Components\Commerce\Products::_save(Array)
#1 /usr/lib/php/Oncord/beta/Framework/functions.inc.php(1281) : eval()'d code(211): Framework\Components\DataABC::save(Array)
#2 /usr/lib/php/Oncord/beta/Framework/functions.inc.php(1281): eval()
#3 /usr/lib/php/Oncord/beta/Components/Settings/Developer/Scripts/Scripts.inc.php(761): evalOuter('\nif (!function_...')
#4 [internal function]: Components\Settings\Developer\Scripts::execute('SRiug5aJoEIbXx1...', '0q0O0LfmB6u1O7f...')
#5 /usr/lib/php/Oncord/beta/Scr/FnCall/FnCall.inc.php(148): call_user_func_array(Array, Array)
#6 /usr/lib/php/Oncord/beta/Scr/OpStatic/OpStatic.inc.php(62): Scr\FnCall->evaluate('\\Components\\Set...')
#7 /usr/lib/php/Oncord/beta/Components/Settings/Developer/Threads/_resources/runner.php(121): Scr\OpStatic->evaluate()
#8 /usr/lib/php/Oncord/beta/Components/Settings/Developer/Threads/_resources/runner.php(160): runCode()
#9 {main}
▶ Today 4:53am ✗ Error 0.1s
▶ Today 4:53am ✗ Error 0.1s
▶ Today 4:53am ✗ Error 0.1s
▶ Today 4:53am ✗ Error 0.1s
▶ Today 4:53am ✓ Completed 5.5s
▶ Today 4:53am ✓ Completed 274.9s