Forum Replies Created

Viewing 5 replies - 1 through 5 (of 5 total)
  • Thread Starter daniilvv

    (@daniilvv)

    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
    }
    Thread Starter daniilvv

    (@daniilvv)

    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
    }
    Thread Starter daniilvv

    (@daniilvv)

    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.

    Thread Starter daniilvv

    (@daniilvv)

    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


    Thread Starter daniilvv

    (@daniilvv)

    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

Viewing 5 replies - 1 through 5 (of 5 total)