daniilvv
Forum Replies Created
-
I modified the snippet taking into account the class-lp-section-curd.php file, but the values are still not saved
/**
* Рабочее решение для переключателей LearnPress
*/
add_action('admin_footer', 'add_working_section_switchers', 9999);
add_action('save_post_lp_course', 'save_course_section_modes');
function save_course_section_modes($post_id) {
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
if (!current_user_can('edit_post', $post_id)) return;
if (isset($_POST['lp_section_modes'])) {
// Убедимся, что данные очищены перед сохранением
$modes = array();
foreach ($_POST['lp_section_modes'] as $section_id => $mode) {
$modes[sanitize_key($section_id)] = in_array($mode, array('online', 'offline')) ? $mode : 'online';
}
update_post_meta($post_id, '_lp_section_modes', $modes);
}
}
function add_working_section_switchers() {
if (get_post_type() !== 'lp_course') return;
global $post;
$section_modes = get_post_meta($post->ID, '_lp_section_modes', true);
if (!is_array($section_modes)) $section_modes = array();
?>
<script type="text/javascript">
(function() {
'use strict';
console.log('[LP Switchers] Starting reliable version');
// Конфигурация
const config = {
sectionClass: 'section',
headerClasses: [
'section-head',
'section-header',
'section-title',
'section-heading'
],
maxAttempts: 30,
checkInterval: 300,
debug: true
};
// Получаем сохраненные режимы из PHP
const savedModes = <?php echo json_encode($section_modes); ?>;
let modesContainer = null;
// Добавляем стили
const style = document.createElement('style');
style.textContent =<br> .lp-mode-switcher {<br> display: inline-block;<br> margin-left: 15px;<br> position: relative;<br> vertical-align: middle;<br> }<br> .lp-section-mode {<br> appearance: none;<br> -webkit-appearance: none;<br> -moz-appearance: none;<br> padding: 6px 30px 6px 12px;<br> border-radius: 20px;<br> border: 1px solid #ddd;<br> background-color: #f5f5f5;<br> color: #555;<br> font-size: 13px;<br> font-weight: 500;<br> cursor: pointer;<br> transition: all 0.3s ease;<br> box-shadow: 0 1px 2px rgba(0,0,0,0.05);<br> background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e");<br> background-repeat: no-repeat;<br> background-position: right 8px center;<br> background-size: 14px;<br> }<br> .lp-section-mode:hover {<br> border-color: #bbb;<br> background-color: #eee;<br> }<br> .lp-section-mode:focus {<br> outline: none;<br> border-color: #2271b1;<br> box-shadow: 0 0 0 1px #2271b1;<br> }<br> .lp-section-mode option {<br> padding: 8px 12px;<br> background: #fff;<br> }<br> .lp-section-mode[value="online"] {<br> background-color: #e8f5e9;<br> color: #2e7d32;<br> border-color: #c8e6c9;<br> }<br> .lp-section-mode[value="offline"] {<br> background-color: #ffebee;<br> color: #c62828;<br> border-color: #ffcdd2;<br> }<br> .lp-modes-container {<br> display: none;<br> }<br>;
document.head.appendChild(style);
// Функция поиска заголовка секции
function findSectionHeader(section) {
if (!section) return null;
for (const className of config.headerClasses) {
const header = section.getElementsByClassName(className)[0];
if (header) {
if (config.debug) console.log('Found header by class:', className, header);
return header;
}
}
const headings = section.querySelectorAll('h3, h4');
if (headings.length > 0) {
if (config.debug) console.log('Found header by tag:', headings[0]);
return headings[0];
}
const elements = section.children;
for (let i = 0; i < elements.length; i++) {
const el = elements[i];
if (el.textContent && el.textContent.trim() !== '') {
if (config.debug) console.log('Found header by text content:', el);
return el;
}
}
if (config.debug) console.log('Header not found in section:', section);
return null;
}
// Создаем контейнер для скрытых полей
function createModesContainer() {
const postForm = document.getElementById('post') ||
document.querySelector('form#post') ||
document.body;
modesContainer = document.createElement('div');
modesContainer.className = 'lp-modes-container';
modesContainer.style.display = 'none';
postForm.appendChild(modesContainer);
return modesContainer;
}
// Обновляем скрытое поле
function updateHiddenInput(sectionId, value) {
let input = modesContainer.querySelector(input[name="lp_section_modes[${sectionId}]"]);
if (!input) {
input = document.createElement('input');
input.type = 'hidden';
input.name = 'lp_section_modes[' + sectionId + ']';
modesContainer.appendChild(input);
}
input.value = value;
}
// Получаем ID секции
function getSectionId(section) {
// Пытаемся найти data-id в самой секции
if (section.dataset.id) {
return section.dataset.id;
}
// Пытаемся найти data-id во внутренних элементах
const itemsWithId = section.querySelectorAll('[data-id]');
for (let i = 0; i < itemsWithId.length; i++) {
const item = itemsWithId[i];
if (item.dataset.id) {
return item.dataset.id;
}
}
// Если не нашли, генерируем случайный ID
return 'section-' + Math.random().toString(36).substr(2, 8);
}
// Функция добавления переключателя
function addSwitcher(section) {
try {
if (!section) return false;
const header = findSectionHeader(section);
if (!header) {
if (config.debug) console.log('Header not found for section:', section);
return false;
}
if (header.querySelector('.lp-mode-switcher')) {
return false;
}
const sectionId = getSectionId(section);
section.dataset.id = sectionId;
const switcher = document.createElement('div');
switcher.className = 'lp-mode-switcher';
const select = document.createElement('select');
select.className = 'lp-section-mode';
select.name = 'lp_section_modes[' + sectionId + ']';
select.dataset.section = sectionId;
['offline', 'online'].forEach(mode => {
const option = document.createElement('option');
option.value = mode;
option.textContent = mode === 'online' ? 'Онлайн' : 'Офлайн';
select.appendChild(option);
});
// Используем сохраненное значение или значение по умолчанию
select.value = savedModes[sectionId] || 'online';
switcher.appendChild(select);
header.appendChild(switcher);
updateHiddenInput(sectionId, select.value);
select.addEventListener('change', function() {
updateHiddenInput(sectionId, this.value);
});
return true;
} catch (error) {
console.error('[LP Switchers] Error:', error);
return false;
}
}
// Инициализация переключателей
function initSwitchers() {
modesContainer = createModesContainer();
let attempts = 0;
const interval = setInterval(() => {
attempts++;
const sections = document.getElementsByClassName(config.sectionClass);
if (sections.length > 0) {
let addedCount = 0;
Array.from(sections).forEach(section => {
if (addSwitcher(section)) addedCount++;
});
if (addedCount > 0 || attempts >= config.maxAttempts) {
clearInterval(interval);
// Наблюдатель для новых секций
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
mutation.addedNodes.forEach(node => {
if (node.nodeType === 1 && node.classList.contains(config.sectionClass)) {
addSwitcher(node);
}
});
});
});
observer.observe(document.body, {
childList: true,
subtree: true
});
}
} else if (attempts >= config.maxAttempts) {
clearInterval(interval);
}
}, config.checkInterval);
}
// Запуск после полной загрузки
if (document.readyState === 'complete') {
setTimeout(initSwitchers, 500);
} else {
window.addEventListener('load', () => setTimeout(initSwitchers, 500));
}
})();
</script>
<?php
}I added a snippet that adds switches to each section, but I don’t understand why the value of the switches, no matter how hard I try, is not saved for the course and when I restart the editor, it becomes the default
<?php
/**
* Рабочее решение для переключателей LearnPress
*/
add_action('admin_footer', 'add_working_section_switchers', 9999);
add_action('save_post_lp_course', 'save_course_section_modes');
function save_course_section_modes($post_id) {
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
if (!current_user_can('edit_post', $post_id)) return;
if (isset($_POST['lp_section_modes'])) {
update_post_meta($post_id, '_lp_section_modes', $_POST['lp_section_modes']);
}
}
function add_working_section_switchers() {
if (get_post_type() !== 'lp_course') return;
global $post;
$section_modes = get_post_meta($post->ID, '_lp_section_modes', true);
if (!is_array($section_modes)) $section_modes = array();
?>
<script type="text/javascript">
(function() {
'use strict';
console.log('[LP Switchers] Starting reliable version');
// Конфигурация
const config = {
sectionClass: 'section',
headerClasses: [
'section-head',
'section-header',
'section-title',
'section-heading'
],
maxAttempts: 30,
checkInterval: 300,
debug: true
};
// Получаем сохраненные режимы из PHP
const savedModes = <?php echo json_encode($section_modes); ?>;
let modesContainer = null;
// Добавляем стили
const style = document.createElement('style');
style.textContent =<br> .lp-mode-switcher {<br> display: inline-block;<br> margin-left: 15px;<br> position: relative;<br> vertical-align: middle;<br> }<br> .lp-section-mode {<br> appearance: none;<br> -webkit-appearance: none;<br> -moz-appearance: none;<br> padding: 6px 30px 6px 12px;<br> border-radius: 20px;<br> border: 1px solid #ddd;<br> background-color: #f5f5f5;<br> color: #555;<br> font-size: 13px;<br> font-weight: 500;<br> cursor: pointer;<br> transition: all 0.3s ease;<br> box-shadow: 0 1px 2px rgba(0,0,0,0.05);<br> background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e");<br> background-repeat: no-repeat;<br> background-position: right 8px center;<br> background-size: 14px;<br> }<br> .lp-section-mode:hover {<br> border-color: #bbb;<br> background-color: #eee;<br> }<br> .lp-section-mode:focus {<br> outline: none;<br> border-color: #2271b1;<br> box-shadow: 0 0 0 1px #2271b1;<br> }<br> .lp-section-mode option {<br> padding: 8px 12px;<br> background: #fff;<br> }<br> .lp-section-mode[value="online"] {<br> background-color: #e8f5e9;<br> color: #2e7d32;<br> border-color: #c8e6c9;<br> }<br> .lp-section-mode[value="offline"] {<br> background-color: #ffebee;<br> color: #c62828;<br> border-color: #ffcdd2;<br> }<br> .lp-modes-container {<br> display: none;<br> }<br>;
document.head.appendChild(style);
// Функция поиска заголовка секции (должна быть объявлена перед использованием)
function findSectionHeader(section) {
if (!section) return null;
for (const className of config.headerClasses) {
const header = section.getElementsByClassName(className)[0];
if (header) {
if (config.debug) console.log('Found header by class:', className, header);
return header;
}
}
const headings = section.querySelectorAll('h3, h4');
if (headings.length > 0) {
if (config.debug) console.log('Found header by tag:', headings[0]);
return headings[0];
}
const elements = section.children;
for (let i = 0; i < elements.length; i++) {
const el = elements[i];
if (el.textContent && el.textContent.trim() !== '') {
if (config.debug) console.log('Found header by text content:', el);
return el;
}
}
if (config.debug) console.log('Header not found in section:', section);
return null;
}
// Создаем контейнер для скрытых полей
function createModesContainer() {
const postForm = document.getElementById('post') ||
document.querySelector('form#post') ||
document.body;
modesContainer = document.createElement('div');
modesContainer.className = 'lp-modes-container';
modesContainer.style.display = 'none';
postForm.appendChild(modesContainer);
return modesContainer;
}
// Обновляем скрытое поле
function updateHiddenInput(sectionId, value) {
let input = modesContainer.querySelector(input[name="lp_section_modes[${sectionId}]"]);
if (!input) {
input = document.createElement('input');
input.type = 'hidden';
input.name = 'lp_section_modes[' + sectionId + ']';
modesContainer.appendChild(input);
}
input.value = value;
}
// Функция добавления переключателя
function addSwitcher(section) {
try {
if (!section) return false;
const header = findSectionHeader(section);
if (!header) {
if (config.debug) console.log('Header not found for section:', section);
return false;
}
if (header.querySelector('.lp-mode-switcher')) {
return false;
}
const sectionId = section.dataset.id || section.id || 'section-' + Math.random().toString(36).substr(2, 8);
section.dataset.id = sectionId;
const switcher = document.createElement('div');
switcher.className = 'lp-mode-switcher';
const select = document.createElement('select');
select.className = 'lp-section-mode';
select.name = 'lp_section_modes[' + sectionId + ']';
select.dataset.section = sectionId;
['offline', 'online'].forEach(mode => {
const option = document.createElement('option');
option.value = mode;
option.textContent = mode === 'online' ? 'Онлайн' : 'Офлайн';
select.appendChild(option);
});
select.value = savedModes[sectionId] || 'online';
switcher.appendChild(select);
header.appendChild(switcher);
updateHiddenInput(sectionId, select.value);
select.addEventListener('change', function() {
updateHiddenInput(sectionId, this.value);
});
return true;
} catch (error) {
console.error('[LP Switchers] Error:', error);
return false;
}
}
// Инициализация переключателей
function initSwitchers() {
modesContainer = createModesContainer();
let attempts = 0;
const interval = setInterval(() => {
attempts++;
const sections = document.getElementsByClassName(config.sectionClass);
if (sections.length > 0) {
let addedCount = 0;
Array.from(sections).forEach(section => {
if (addSwitcher(section)) addedCount++;
});
if (addedCount > 0 || attempts >= config.maxAttempts) {
clearInterval(interval);
// Наблюдатель для новых секций
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
mutation.addedNodes.forEach(node => {
if (node.nodeType === 1 && node.classList.contains(config.sectionClass)) {
addSwitcher(node);
}
});
});
});
observer.observe(document.body, {
childList: true,
subtree: true
});
}
} else if (attempts >= config.maxAttempts) {
clearInterval(interval);
}
}, config.checkInterval);
}
// Запуск после полной загрузки
if (document.readyState === 'complete') {
setTimeout(initSwitchers, 500);
} else {
window.addEventListener('load', () => setTimeout(initSwitchers, 500));
}
})();
</script>
<?php
}I am not very happy with these additions. So I would like to ask you to tell me which file is responsible for generating the curriculum in the course editor.
on the site if the client buys a course, an account is created for him, which he can log into. And there is a button to cancel the order that has not yet been processed and with a direct bank transfer falls into the hold status. But if you click the button, the site will display a message that the order has been canceled. Although in the WordPress admin panel the order is not canceled



I want to add new fields to the existing program settings. For example, so that in the course editor, when creating a curriculum, the section has an additional setting that allows you to create a special offline section. And when adding lessons to this section, the lessons are not created but are displayed simply as text that would be displayed in the program. I would do it myself, I am interested in this, but I do not understand how to quickly find required code file