blog_id);
$this->run_site_activation();
restore_current_blog();
} catch (Throwable $e) {
restore_current_blog();
$this->log_error('initialize_new_site', $e);
}
}
public function maybe_run_activation()
{
if (!is_admin()) {
return;
}
try {
$pending = get_option('acadlix_activation_pending');
if (empty($pending) || $pending['plugin'] !== ACADLIX_PLUGIN_BASENAME) {
return;
}
delete_option('acadlix_activation_pending');
if (is_multisite() && !empty($pending['network'])) {
foreach (get_sites(['fields' => 'ids']) as $site_id) {
switch_to_blog($site_id);
$this->run_site_activation();
restore_current_blog();
}
} else {
$this->run_site_activation();
}
} catch (Throwable $e) {
$this->log_error('maybe_run_activation', $e);
}
}
// public function activate($network_wide)
// {
// if (is_multisite() && $network_wide) {
// // Loop through all existing sites
// foreach (get_sites(['fields' => 'ids']) as $site_id) {
// switch_to_blog($site_id);
// $this->run_site_activation();
// restore_current_blog();
// }
// } else {
// $this->run_site_activation();
// }
// }
private function run_site_activation()
{
try {
if (function_exists('acadlix')) {
acadlix()->migration()->createTable();
acadlix()->seeder()->seed();
acadlix()->admin()->option()->createOption();
acadlix()->admin()->userRole()->addCapabilities();
acadlix()->cpt()->register_all_cpts();
acadlix()->schedule()->createSchedules();
acadlix()->integrations()->caches()->clearAll();
}
} catch (Throwable $e) {
$this->log_error('run_site_activation', $e);
}
}
public function deactivate($network_wide)
{
try {
if (is_multisite() && $network_wide) {
foreach (get_sites(['fields' => 'ids']) as $site_id) {
switch_to_blog($site_id);
$this->run_site_deactivation();
restore_current_blog();
}
} else {
$this->run_site_deactivation();
}
} catch (Throwable $e) {
$this->log_error('deactivate', $e);
}
}
public function run_site_deactivation()
{
try {
if (function_exists('acadlix')) {
acadlix()->admin()->userRole()->removeCapabilities();
acadlix()->cpt()->unregister_all_cpts();
acadlix()->schedule()->deleteSchedules();
}
} catch (Throwable $e) {
$this->log_error('run_site_deactivation', $e);
}
}
public function uninstall()
{
try {
if (is_multisite()) {
foreach (get_sites(['fields' => 'ids']) as $site_id) {
switch_to_blog($site_id);
$delete_data = acadlix()->helper()->acadlix_get_option('acadlix_delete_data_on_plugin_uninstall', "no");
if ($delete_data !== "no") {
$this->run_site_uninstall();
}
restore_current_blog();
}
} else {
$delete_data = acadlix()->helper()->acadlix_get_option('acadlix_delete_data_on_plugin_uninstall', "no");
if ($delete_data !== "no") {
$this->run_site_uninstall();
}
}
} catch (Throwable $e) {
$this->log_error('uninstall', $e);
}
}
public function acadlix_delete_site($site)
{
try {
$blog_id = (int) $site->id;
switch_to_blog($blog_id);
if (function_exists('acadlix')) {
acadlix()->migration()->removeTable();
}
restore_current_blog();
} catch (Throwable $e) {
restore_current_blog();
$this->log_error('acadlix_delete_site', $e);
}
}
private function run_site_uninstall()
{
try {
if (function_exists('acadlix')) {
acadlix()->admin()->core()->acadlix_delete_post_type_data();
acadlix()->migration()->removeTable();
acadlix()->admin()->option()->removeOptions();
}
} catch (Throwable $e) {
$this->log_error('run_site_uninstall', $e);
}
}
public function acadlix_load_textdomain()
{
// load_plugin_textdomain('acadlix', false, ACADLIX_PLUGIN_FOLDER_NAME . '/languages/' . acadlix()->versionPath);
}
public function acadlix_check_version_update()
{
if (!current_user_can('manage_options')) {
return;
}
if (acadlix()->isDev) {
return;
}
try {
if (is_multisite() && is_plugin_active_for_network(ACADLIX_PLUGIN_BASENAME)) {
$sites = get_sites(['deleted' => 0]);
foreach ($sites as $site) {
switch_to_blog($site->blog_id);
$this->run_version_update();
restore_current_blog();
}
} else {
$this->run_version_update();
}
} catch (Throwable $e) {
$this->log_error('acadlix_check_version_update', $e);
}
}
public function get_option_name()
{
return acadlix()->pro ? 'acadlix_pro_version' : 'acadlix_version';
}
public function get_current_version()
{
$option_name = $this->get_option_name();
return acadlix()->helper()->acadlix_get_option($option_name);
}
public function run_version_update()
{
$current_version = $this->get_current_version();
if (version_compare($current_version, ACADLIX_VERSION, '==')) {
return;
}
$this->update_version();
acadlix()->helper()->acadlix_update_option($this->get_option_name(), ACADLIX_VERSION);
}
public function update_version()
{
// This method is intentionally left blank. Use run_version_update() to perform the actual update.
}
public function acadlix_check_db_update()
{
if (!current_user_can('manage_options')) {
return;
}
try {
if (is_multisite() && is_plugin_active_for_network(ACADLIX_PLUGIN_BASENAME)) {
$sites = get_sites(['deleted' => 0]);
foreach ($sites as $site) {
switch_to_blog($site->blog_id);
$this->run_db_update();
restore_current_blog();
}
} else {
$this->run_db_update();
}
} catch (Throwable $e) {
$this->log_error('acadlix_check_db_update', $e);
}
}
protected function run_db_update()
{
$installed_ver = (int) acadlix()->helper()->acadlix_get_option('acadlix_db_version') ?: 1;
$updates = [
2 => 'updateV2',
3 => 'updateV3',
4 => 'updateV4',
5 => 'updateV5',
6 => 'updateV6', // update 1.3.0
7 => 'updateV7', // update 1.4.0
8 => 'updateV8', // update 1.5.0
9 => 'updateV9', // update 1.6.0,
10 => 'updateV10', // update 1.6.1,
11 => 'updateV11', // update 1.6.2,
12 => 'updateV12', // update 1.6.3 (pro) 1.0.5 (free),
13 => 'updateV13', // update 1.6.4 (pro) 1.0.6 (free),
14 => 'updateV14', // update 1.6.5 (pro) 1.0.7 (free),
15 => 'updateV15', // update 1.6.8 (pro) 1.0.8 (free),
16 => 'updateV16', // update 1.6.9 (pro) 1.0.9 (free),
17 => 'updateV17', // update 1.7.0 (pro) 1.1.0 (free),
18 => 'updateV18', // update 1.1.2 (free),
19 => 'updateV19', //
20 => 'updateV20',
21 => 'updateV21',
22 => 'updateV22',
23 => 'updateV23',
24 => 'updateV24',
];
foreach ($updates as $version => $method) {
if ($installed_ver < $version && method_exists($this, $method)) {
try {
acadlix()->migration()->createTable();
acadlix()->seeder()->seed();
acadlix()->admin()->option()->createOption();
acadlix()->admin()->userRole()->addCapabilities();
acadlix()->integrations()->caches()->clearAll();
// Run the specific migration method
$this->$method();
// Update version per step so successful migrations aren't re-run
acadlix()->helper()->acadlix_update_option('acadlix_db_version', $this->dbVersion);
} catch (Throwable $e) {
$this->log_error("DB Migration (Version {$version})", $e);
// Break out of loop so subsequent dependent migrations don't run on broken DB state
break;
}
}
}
}
protected function updateV24()
{
}
protected function updateV23()
{
}
protected function updateV22()
{
}
protected function updateV21()
{
}
protected function updateV20()
{
/**
* In this update add student home page module.
*/
flush_rewrite_rules();
}
protected function updateV19()
{
}
protected function updateV18()
{
/**
* In this update add course enrollment module.
*/
if (!get_option('acadlix_free_course_enrollment_update')) {
$orderItems = acadlix()
->model()
->orderItem()
->with('order')
->whereHas('order', function ($query) {
$query->where('status', Order::STATUS_SUCCESS);
})
->whereNull("subscription_id")
->where('type', 'course')
->get();
foreach ($orderItems as $item) {
// Ensure the item has an associated order and valid user/course IDs to prevent errors
if (!$item->order || !$item->order->user_id || !$item->item_id) {
continue;
}
try {
// Use your fluent factory method to safely upsert the record (Scenario A)
$course = acadlix()->model()->course()->find($item->item_id);
if (!$course) {
// Cast IDs to int before interpolation so the message can't carry unescaped/unsafe data
throw new \Exception('Course not found for Order Item ID ' . (int) $item->id . ' with Course ID ' . (int) $item->item_id);
}
$percentage = $course->getCourseCompletionPercentage($item->order->user_id);
$courseSectionContentId = $course->getCurrentCourseContentId($item->order->user_id);
$start_time = acadlix()->model()->userActivityMeta()
->where('user_id', $item->order->user_id)
->where('type', 'course')
->where('type_id', $item->item_id)
->where('meta_key', 'course_start_time')
->first();
acadlix()->model()->courseEnrollment()->enroll(
(int) $item->order->user_id,
(int) $item->item_id, // Assuming item_id stores your course_id
[
'source_type' => 'order',
'source_id' => $item->order_id,
'type' => $item->type,
'item_id' => $item->item_id,
'via' => 'user',
'via_id' => $item->order->user_id,
'course_section_content_id' => $courseSectionContentId, // Use the current course content ID
'started_at' => $start_time ? $start_time->meta_value : null,
'progress_percent' => $percentage, // Use the calculated percentage
]
);
} catch (\Exception $e) {
// Log individual errors so the entire loop doesn't crash if one row has corrupt data
$this->log_error('Acadlix Migration Error for Order Item ID ' . $item->id, $e);
}
}
update_option('acadlix_free_course_enrollment_update', true);
}
}
protected function updateV17()
{
/**
* In this add question sorting.
*/
}
protected function updateV16()
{
/**
* In this update add course student module.
*/
}
protected function updateV15()
{
/**
* In this update add Microsoft Teams module.
*/
}
protected function updateV14()
{
/**
* In this update add course bundle module.
*/
}
protected function updateV13()
{
/**
* In this update add certificate module.
*/
}
protected function updateV12()
{
/**
* In this update add coupon module.
*/
}
protected function updateV11()
{
/**
* In this update add assessment question type.
*/
}
protected function updateV10()
{
/**
* Update for review module
*/
}
protected function updateV9()
{
/**
* In this update add export functionality.
*/
}
protected function updateV8()
{
/**
* In this update modify course statistic
* Add Schedule
*/
$course_statistic = acadlix()->model()->courseStatistic()
->whereNull('course_id')
->get();
foreach ($course_statistic as $statistic) {
$statistic->update([
'course_id' => $statistic->order_item->course_id,
]);
}
acadlix()->schedule()->createSchedules();
}
protected function updateV7()
{
/**
* In this update some user roles.
*/
}
protected function updateV6()
{
/**
* In this update add student module.
*/
}
protected function updateV5()
{
/**
* In this update add multisite functionality.
*/
}
protected function updateV4()
{
/**
* In this update add capabilities for zoom run through addCapabilities function.
*/
}
protected function updateV3()
{
/**
* In this update add column attempted_at in statistic table run through createTable function.
*/
}
protected function updateV2()
{
/**
* In this update also run subject seeder to add default subject.
* Update questions subject_id
*/
$subject = acadlix()->model()->subject()->where('default', 1)->first();
$questions = acadlix()->model()->question()->where('subject_id', null)->get();
if ($questions->count() > 0 && $subject) {
foreach ($questions as $question) {
$question->update([
'subject_id' => $subject->id,
]);
}
}
}
/**
* Safely log errors to debug.log and notify admin gracefully
*/
protected function log_error(string $context, Throwable $e): void
{
$message = sprintf(
'[Acadlix Activator Error] Context: %s | Message: %s | File: %s Line: %d',
$context,
$e->getMessage(),
$e->getFile(),
$e->getLine()
);
error_log($message);
if (is_admin()) {
set_transient(
'acadlix_migration_last_error',
sprintf(
/* translators: 1: error context */
__('A background update step encountered an issue (%s). The site was kept safe.', 'acadlix'),
$context
),
HOUR_IN_SECONDS
);
}
}
}