in 1
if (!preg_match('//is', $htmlString)) {
return $htmlString;
}
$matches = [];
preg_match_all('/(.*?)<\/span>/is', $htmlString, $matches);
if (!empty($matches)) {
// matches[0] are the full string
// matches[1] are the languages
// matches[2] are the strings
foreach ($matches[1] as $id => $match) {
if ($match == $isoCode) {
return $matches[2][$id];
}
}
// Could find the pattern but could not find our language. Return the first language found.
return $matches[2][0];
}
// Could not find pattern. Just return the whole string. We shouldn't get here.
return $htmlString;
}
/**
* Get the print.css file for current theme.
* Only the file path or the file contents when $getFileContents is true.
*/
function api_get_print_css(bool $getFileContents = true, bool $useWebPath = false): string
{
$sysCssPath = api_get_path(SYS_CSS_PATH);
$cssFile = $sysCssPath.'themes/'.api_get_visual_theme().'/print.css';
if (!file_exists($cssFile)) {
$cssFile = $sysCssPath.'print.css';
}
if ($getFileContents) {
return file_get_contents($cssFile);
}
if ($useWebPath) {
return str_replace($sysCssPath, api_get_path(WEB_CSS_PATH), $cssFile);
}
return $cssFile;
}
function api_protect_webservices()
{
if (api_get_configuration_value('disable_webservices')) {
echo "Webservices are disabled. \n";
echo "To enable, add \$_configuration['disable_webservices'] = false; in configuration.php";
exit;
}
}
function api_filename_has_blacklisted_stream_wrapper(string $filename)
{
if (strpos($filename, '://') > 0) {
$wrappers = stream_get_wrappers();
$allowedWrappers = ['http', 'https', 'file'];
foreach ($wrappers as $wrapper) {
if (in_array($wrapper, $allowedWrappers)) {
continue;
}
if (stripos($filename, $wrapper.'://') === 0) {
return true;
}
}
}
return false;
}
/**
* Calculate the percent between two numbers.
*
* @return string
*/
function api_calculate_increment_percent(int $newValue, int $oldValue)
{
if ($oldValue <= 0) {
$result = " - ";
} else {
$result = ' '.round(100 * (($newValue / $oldValue) - 1), 2).' %';
}
return $result;
}
/**
* Erase settings from cache (because of some update) if applicable.
*
* @param int $url_id The ID of the present URL
*/
function api_flush_settings_cache(int $url_id): bool
{
global $_configuration;
$cacheAvailable = api_get_configuration_value('apc');
if (!$cacheAvailable) {
return false;
}
$apcRootVarName = api_get_configuration_value('apc_prefix');
// Delete the APCu-stored settings array, if present
$apcVarName = $apcRootVarName.'settings';
apcu_delete($apcVarName);
if (api_is_multiple_url_enabled() && $url_id === 1) {
// if we are on the main URL of a multi-url portal, we must
// invalidate the cache for all other URLs as well as some
// main settings span multiple URLs
$urls = api_get_access_urls();
foreach ($urls as $i => $row) {
if ($row['id'] == 1) {
continue;
}
$apcVarName = $_configuration['main_database'].'_'.$row['id'].'_settings';
apcu_delete($apcVarName);
}
}
return true;
}
/**
* Decrypt sent data with encoded secret defined in app/config/configuration.php
* in the variable $_configuration['ldap_admin_password_salt'].
*
* @param $encryptedText The text to be decrypted
*/
function api_decrypt_ldap_password(string $encryptedText): string
{
if (!empty(api_get_configuration_value('ldap_admin_password_salt'))) {
$secret = api_get_configuration_value('ldap_admin_password_salt');
} else {
return false;
}
return api_decrypt_hash($encryptedText, $secret);
}
/**
* Decrypt sent hash encoded with secret.
*
* @param $encryptedText The hash text to be decrypted
* @param $secret The secret used to encoded the hash
*
* @return string The decrypted text or false
*/
function api_decrypt_hash(string $encryptedHash, string $secret): string
{
$iv = base64_decode(substr($encryptedHash, 0, 16), true);
$data = base64_decode(substr($encryptedHash, 16), true);
$tag = substr($data, strlen($data) - 16);
$data = substr($data, 0, strlen($data) - 16);
try {
return openssl_decrypt(
$data,
'aes-256-gcm',
$secret,
OPENSSL_RAW_DATA,
$iv,
$tag
);
} catch (\Exception $e) {
return false;
}
}
/**
* Encrypt sent data with secret.
*
* @param $data The text to be encrypted
* @param $secret The secret to use encode data
*
* @return string The encrypted text or false
*/
function api_encrypt_hash($data, $secret)
{
$iv = random_bytes(12);
$tag = '';
$encrypted = openssl_encrypt(
$data,
'aes-256-gcm',
$secret,
OPENSSL_RAW_DATA,
$iv,
$tag,
'',
16
);
return base64_encode($iv).base64_encode($encrypted.$tag);
}
/**
* Replace a specific term by another in all course-related text elements in the database.
* Does not rename directories or replace content of files on disk. Check tests/scripts/replace_course_code.php if
* you are looking for this.
* The replacement can replace bits in larger strings, requiring the search string to be very specific to avoid
* excess replacements.
*
* @return array The number of changes executed in each table
*/
function api_replace_terms_in_content(string $search, string $replace): array
{
$replacements = [
Database::get_course_table(TABLE_QUIZ_TEST) => [
'iid' => ['title', 'description', 'sound'],
],
Database::get_course_table(TABLE_QUIZ_QUESTION) => [
'iid' => ['question', 'description'],
],
Database::get_course_table(TABLE_QUIZ_ANSWER) => [
'iid' => ['answer', 'comment'],
],
Database::get_course_table(TABLE_ANNOUNCEMENT) => [
'iid' => ['title', 'content'],
],
Database::get_course_table(TABLE_ANNOUNCEMENT_ATTACHMENT) => [
'iid' => ['path', 'comment'],
],
Database::get_course_table(TABLE_ATTENDANCE) => [
'iid' => ['name', 'description', 'attendance_qualify_title'],
],
Database::get_course_table(TABLE_BLOGS) => [
'iid' => ['blog_name', 'blog_subtitle'],
],
Database::get_course_table(TABLE_BLOGS_ATTACHMENT) => [
'iid' => ['path', 'comment'],
],
Database::get_course_table(TABLE_BLOGS_COMMENTS) => [
'iid' => ['title', 'comment'],
],
Database::get_course_table(TABLE_BLOGS_POSTS) => [
'iid' => ['title', 'full_text'],
],
Database::get_course_table(TABLE_BLOGS_TASKS) => [
'iid' => ['title', 'description'],
],
Database::get_course_table(TABLE_AGENDA) => [
'iid' => ['title', 'content', 'comment'],
],
Database::get_course_table(TABLE_AGENDA_ATTACHMENT) => [
'iid' => ['path', 'comment', 'filename'],
],
Database::get_course_table(TABLE_COURSE_DESCRIPTION) => [
'iid' => ['title', 'content'],
],
Database::get_course_table(TABLE_DOCUMENT) => [
'iid' => ['path', 'comment'],
],
Database::get_course_table(TABLE_DROPBOX_FEEDBACK) => [
'iid' => ['feedback'],
],
Database::get_course_table(TABLE_DROPBOX_FILE) => [
'iid' => ['title', 'description'],
],
Database::get_course_table(TABLE_DROPBOX_POST) => [
'iid' => ['feedback'],
],
Database::get_course_table(TABLE_FORUM_ATTACHMENT) => [
'iid' => ['path', 'comment', 'filename'],
],
Database::get_course_table(TABLE_FORUM_CATEGORY) => [
'iid' => ['cat_title', 'cat_comment'],
],
Database::get_course_table(TABLE_FORUM) => [
'iid' => ['forum_title', 'forum_comment', 'forum_image'],
],
Database::get_course_table(TABLE_FORUM_POST) => [
'iid' => ['post_title', 'post_text', 'poster_name'],
],
Database::get_course_table(TABLE_FORUM_THREAD) => [
'iid' => ['thread_title', 'thread_poster_name', 'thread_title_qualify'],
],
Database::get_course_table(TABLE_GLOSSARY) => [
'iid' => ['name', 'description'],
],
Database::get_course_table(TABLE_GROUP_CATEGORY) => [
'iid' => ['title', 'description'],
],
Database::get_course_table(TABLE_GROUP) => [
'iid' => ['name', 'description', 'secret_directory'],
],
Database::get_course_table(TABLE_LINK) => [
'iid' => ['description'],
],
Database::get_course_table(TABLE_LINK_CATEGORY) => [
'iid' => ['category_title', 'description'],
],
Database::get_course_table(TABLE_LP_MAIN) => [
'iid' => ['name', 'ref', 'description', 'path', 'content_license', 'preview_image', 'theme'],
],
Database::get_course_table(TABLE_LP_CATEGORY) => [
'iid' => ['name'],
],
Database::get_course_table(TABLE_LP_ITEM) => [
'iid' => ['prerequisite', 'description', 'title', 'parameters', 'launch_data', 'terms'],
],
Database::get_course_table(TABLE_LP_ITEM_VIEW) => [
'iid' => ['suspend_data', 'lesson_location'],
],
Database::get_course_table(TABLE_NOTEBOOK) => [
'iid' => ['title', 'description'],
],
Database::get_course_table(TABLE_ONLINE_LINK) => [
'iid' => ['name'],
],
Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY) => [
'iid' => ['title', 'description'],
],
Database::get_course_table(TABLE_ROLE) => [
'iid' => ['role_name', 'role_comment'],
],
Database::get_course_table(TABLE_STUDENT_PUBLICATION) => [
'iid' => ['title', 'title_correction', 'description'],
],
Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT_COMMENT) => [
'iid' => ['comment', 'file'],
],
Database::get_course_table(TABLE_SURVEY) => [
'iid' => ['title', 'subtitle', 'surveythanks', 'invite_mail', 'reminder_mail', 'mail_subject', 'access_condition', 'form_fields'],
],
Database::get_course_table(TABLE_SURVEY_QUESTION_GROUP) => [
'iid' => ['name', 'description'],
],
Database::get_course_table(TABLE_SURVEY_QUESTION) => [
'iid' => ['survey_question', 'survey_question_comment'],
],
Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION) => [
'iid' => ['option_text'],
],
Database::get_course_table(TABLE_THEMATIC) => [
'iid' => ['content', 'title'],
],
Database::get_course_table(TABLE_THEMATIC_ADVANCE) => [
'iid' => ['content'],
],
Database::get_course_table(TABLE_THEMATIC_PLAN) => [
'iid' => ['description'],
],
Database::get_course_table(TABLE_TOOL_LIST) => [
'iid' => ['description'],
],
Database::get_course_table(TABLE_TOOL_INTRO) => [
'iid' => ['intro_text'],
],
Database::get_course_table(TABLE_USER_INFO_DEF) => [
'iid' => ['comment'],
],
Database::get_course_table(TABLE_WIKI) => [
'iid' => ['title', 'content', 'comment', 'progress', 'linksto'],
],
Database::get_course_table(TABLE_WIKI_CONF) => [
'iid' => ['feedback1', 'feedback2', 'feedback3'],
],
Database::get_course_table(TABLE_WIKI_DISCUSS) => [
'iid' => ['comment'],
],
Database::get_main_table(TABLE_CAREER) => [
'id' => ['name', 'description'],
],
Database::get_main_table(TABLE_MAIN_CHAT) => [
'id' => ['message'],
],
Database::get_main_table(TABLE_MAIN_CLASS) => [
'id' => ['name'],
],
Database::get_main_table(TABLE_MAIN_COURSE_REQUEST) => [
'id' => ['description', 'title', 'objetives', 'target_audience'],
],
'course_type' => [
'id' => ['description'],
],
Database::get_main_table(TABLE_EVENT_EMAIL_TEMPLATE) => [
'id' => ['message', 'subject', 'event_type_name'],
],
Database::get_main_table(TABLE_GRADE_MODEL) => [
'id' => ['name', 'description'],
],
Database::get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY) => [
'id' => ['name', 'description'],
],
Database::get_main_table(TABLE_MAIN_GRADEBOOK_CERTIFICATE) => [
'id' => ['path_certificate'],
],
Database::get_main_table(TABLE_MAIN_GRADEBOOK_EVALUATION) => [
'id' => ['description', 'name'],
],
Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINKEVAL_LOG) => [
'id' => ['name', 'description'],
],
Database::get_main_table(TABLE_MAIN_LEGAL) => [
'id' => ['content', 'changes'],
],
Database::get_main_table(TABLE_MESSAGE) => [
'id' => ['content'],
],
Database::get_main_table(TABLE_MESSAGE_ATTACHMENT) => [
'id' => ['path', 'comment', 'filename'],
],
Database::get_main_table(TABLE_NOTIFICATION) => [
'id' => ['content'],
],
Database::get_main_table(TABLE_PERSONAL_AGENDA) => [
'id' => ['title', 'text'],
],
Database::get_main_table(TABLE_PROMOTION) => [
'id' => ['description'],
],
'room' => [
'id' => ['description'],
],
'sequence_condition' => [
'id' => ['description'],
],
'sequence_method' => [
'id' => ['description', 'formula'],
],
'sequence_rule' => [
'id' => ['description'],
],
'sequence_type_entity' => [
'id' => ['description'],
],
'sequence_variable' => [
'id' => ['description'],
],
Database::get_main_table(TABLE_MAIN_SESSION) => [
'id' => ['description'],
],
Database::get_main_table(TABLE_MAIN_SHARED_SURVEY) => [
'survey_id' => ['subtitle', 'surveythanks', 'intro'],
],
Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION) => [
'question_id' => ['survey_question', 'survey_question_comment'],
],
Database::get_main_table(TABLE_MAIN_SHARED_SURVEY_QUESTION_OPTION) => [
'question_option_id' => ['option_text'],
],
Database::get_main_table(TABLE_MAIN_SKILL) => [
'id' => ['name', 'description', 'criteria'],
],
Database::get_main_table(TABLE_MAIN_SKILL_PROFILE) => [
'id' => ['description'],
],
Database::get_main_table(TABLE_MAIN_SKILL_REL_USER) => [
'id' => ['argumentation'],
],
'skill_rel_user_comment' => [
'id' => ['feedback_text'],
],
Database::get_main_table(TABLE_MAIN_SYSTEM_ANNOUNCEMENTS) => [
'id' => ['content'],
],
Database::get_main_table(TABLE_MAIN_SYSTEM_CALENDAR) => [
'id' => ['content'],
],
Database::get_main_table(TABLE_MAIN_SYSTEM_TEMPLATE) => [
'id' => ['comment', 'content'],
],
Database::get_main_table(TABLE_MAIN_TEMPLATES) => [
'id' => ['description', 'image'],
],
Database::get_main_table(TABLE_TICKET_CATEGORY) => [
'id' => ['description'],
],
Database::get_main_table(TABLE_TICKET_MESSAGE) => [
'id' => ['message'],
],
Database::get_main_table(TABLE_TICKET_MESSAGE_ATTACHMENTS) => [
'id' => ['filename', 'path'],
],
Database::get_main_table(TABLE_TICKET_PRIORITY) => [
'id' => ['description'],
],
Database::get_main_table(TABLE_TICKET_PROJECT) => [
'id' => ['description'],
],
Database::get_main_table(TABLE_TICKET_STATUS) => [
'id' => ['description'],
],
Database::get_main_table(TABLE_TICKET_TICKET) => [
'id' => ['message'],
],
Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT) => [
'id' => ['answer', 'teacher_comment', 'filename'],
],
Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT_RECORDING) => [
'id' => ['teacher_comment'],
],
Database::get_main_table(TABLE_STATISTIC_TRACK_E_DEFAULT) => [
'default_id' => ['default_value'],
],
Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES) => [
'exe_id' => ['data_tracking', 'questions_to_check'],
],
Database::get_main_table(TABLE_STATISTIC_TRACK_E_ITEM_PROPERTY) => [
'id' => ['content'],
],
'track_e_open' => [
'open_id' => ['open_remote_host', 'open_agent', 'open_referer'],
],
Database::get_main_table(TABLE_TRACK_STORED_VALUES) => [
'id' => ['sv_value'],
],
Database::get_main_table(TABLE_TRACK_STORED_VALUES_STACK) => [
'id' => ['sv_value'],
],
Database::get_main_table(TABLE_MAIN_USER_API_KEY) => [
'id' => ['description'],
],
Database::get_main_table(TABLE_USERGROUP) => [
'id' => ['name', 'description', 'picture', 'url'],
],
Database::get_main_table(TABLE_MAIN_BLOCK) => [
'id' => ['name', 'description', 'path'],
],
];
if (api_get_configuration_value('attendance_allow_comments')) {
$replacements['c_attendance_result_comment'] = [
'iid' => ['comment'],
];
}
if (api_get_configuration_value('exercise_text_when_finished_failure')) {
$replacements[Database::get_course_table(TABLE_QUIZ_TEST)]['iid'][] = 'text_when_finished_failure';
}
$changes = array_map(
fn ($table) => 0,
$replacements
);
foreach ($replacements as $table => $replacement) {
foreach ($replacement as $idColumn => $columns) {
$keys = array_map(fn ($column) => "$column LIKE %?%", $columns);
$values = array_fill(0, count($columns), $search);
$result = Database::select(
[$idColumn, ...$columns],
$table,
[
'where' => [
implode(' OR ', $keys) => $values,
],
'order' => "$idColumn ASC",
]
);
foreach ($result as $row) {
$attributes = array_combine(
$columns,
array_map(
fn ($column) => preg_replace('#'.$search.'#', $replace, $row[$column]),
$columns
)
);
try {
Database::update(
$table,
$attributes,
["$idColumn = ?" => $row[$idColumn]]
);
} catch (Exception $e) {
Database::handleError($e);
}
$changes[$table]++;
}
}
}
return $changes;
}