Несколько Custom_Background - возможно ли это?

27 авг. 2010 г., 20:39:09
Просмотры: 1.07K
Голосов: 3

Возможно ли создать несколько страниц администрирования "custom background" (пользовательский фон)? В текущем проекте мне нужно реализовать 2 разных фона для 2 разных областей сайта, и я хотел бы предоставить клиенту одинаковый интерфейс для настройки обоих фонов (цвет/изображение/повторение и т.д.).

Есть какие-то идеи как это реализовать?

0
Все ответы на вопрос 2
14

Привет @Amit:

Ответ: "Да, это возможно." Следующий вопрос: "А действительно ли вам это нужно?"

Мне показалось забавным попробовать создать плагин для реализации вашего запроса, поэтому я решил проверить, возможно ли это. Конечно, мне удалось заставить его работать, но я опасаюсь, что код плагина настолько тесно связан с существующим кодом WordPress, что может легко сломаться при обновлении ядра.

Этот код обрабатывает всю административную часть, создавая новый пункт меню в разделе "Внешний вид" под названием "Специальный фон". Однако он не предоставляет способа реального использования этого фона - это вторая фаза разработки плагина, которая потребует подключения многих функций из /wp-includes/themes.php, и, честно говоря, не знаю, будет ли у меня возможность написать этот код.

Причина, по которой я остановился на этом этапе - я не знал требований к тому, где должен отображаться специальный фон, а где обычный. Предполагаю, что возможно для выбранных страниц и/или URL-путей?

Тем не менее, вот код плагина (который вы также можете скачать из gist):

<?php
/*
Plugin Name: Special Background
Plugin URI: http://wordpress.stackexchange.com/questions/972/
Description: Пример, показывающий как добавить специальный фон, используя существующую админ-страницу фона в ядре.
Version: 0.1
Author: Mike Schinkel
Author URI: http://mikeschinkel.com/custom-wordpress-plugins/
*/
add_filter('admin_menu','add_special_background_menu_item');
function add_special_background_menu_item() {
    add_theme_page(__('Специальный фон'), __('Специальный фон'),'edit_theme_options','special-background','special_background_admin_page');
}
add_filter('admin_init','add_js_for_special_background');
function add_js_for_special_background() {
    global $custom_background;
    if (is_special_background_page()) {
        wp_enqueue_script('custom-background');
        wp_enqueue_style('farbtastic');
    }
    $hook = 'load-appearance_page_special-background';
    add_action($hook, array(&$custom_background, 'admin_load'));
    add_action($hook, array(&$custom_background, 'take_action'), 49);
    add_action($hook, array(&$custom_background, 'handle_upload'), 49);    
}
add_filter('theme_mod_background_image',      'theme_mod_special_background_image');
add_filter('theme_mod_background_image_thumb','theme_mod_special_background_image_thumb');
add_filter('theme_mod_background_repeat',     'theme_mod_special_background_repeat');
add_filter('theme_mod_background_position_x', 'theme_mod_special_background_position_x');
add_filter('theme_mod_background_attachment', 'theme_mod_special_background_attachment');
add_filter('theme_mod_background_color',      'theme_mod_special_background_color');
function theme_mod_special_background_image($defaults) {
    return theme_mod_special_background_image_attrs('image',$defaults);
}
function theme_mod_special_background_image_thumb($defaults) {
    return theme_mod_special_background_image_attrs('image_thumb',$defaults);
}
function theme_mod_special_background_repeat($defaults) {
    return theme_mod_special_background_image_attrs('repeat',$defaults);
}
function theme_mod_special_background_position_x($defaults) {
    return theme_mod_special_background_image_attrs('position_x',$defaults);
}
function theme_mod_special_background_attachment($defaults) {
    return theme_mod_special_background_image_attrs('attachment',$defaults);
}
function theme_mod_special_background_color($defaults) {
    return theme_mod_special_background_image_attrs('color',$defaults);
}
function theme_mod_special_background_image_attrs($attr,$defaults) {
    if (is_special_background_page()) {
        $mods = get_option( 'mods_' . get_current_theme() );
        $defaults = (!empty($mods["special_background_{$attr}"]) ? $mods["special_background_{$attr}"] : '');
    }
    return $defaults;
}
add_filter('pre_update_option_mods_' . get_current_theme(),'pre_update_option_special_background_image',10,2);
function pre_update_option_special_background_image($newvalue, $oldvalue) {
    static $times_called = 0;
    if (!empty($_POST) && is_special_background_page()) {
        if ((isset($_POST['action']) && $_POST['action']=='save') || isset($_POST['reset-background']) || isset($_POST['remove-background'])) {
            switch ($times_called) {
                case 0:
                    $newvalue = special_background_image_value_swap('image',$newvalue,$oldvalue);
                    break;
                case 1:
                    $newvalue = special_background_image_value_swap('image_thumb',$newvalue,$oldvalue);
                    break;
            }
        } else {
            if ($times_called==0 && isset($_POST['background-repeat'])) {
                $newvalue = special_background_image_value_swap('repeat',$newvalue,$oldvalue);
            }
            if ($times_called==1 && isset($_POST['background-position-x'])) {
                $newvalue = special_background_image_value_swap('position_x',$newvalue,$oldvalue);
            }
            if ($times_called==2 && isset($_POST['background-attachment'])) {
                $newvalue = special_background_image_value_swap('attachment',$newvalue,$oldvalue);
            }
            if ($times_called==3 && isset($_POST['background-color'])) {
            $newvalue = special_background_image_value_swap('color',$newvalue,$oldvalue);
      }
    }
    $times_called++;
  }
  return $newvalue;
}
function special_background_image_value_swap($swap_what,$newvalue,$oldvalue) {
  $newvalue["special_background_{$swap_what}"] = $newvalue["background_{$swap_what}"];
  $newvalue["background_{$swap_what}"] = $oldvalue["background_{$swap_what}"];
  return $newvalue;
}
function special_background_admin_page() {
  global $custom_background;
  if (is_special_background_page()) {
    global $parent_file,$submenu_file,$title;
    $parent_file = 'themes.php';
    $submenu_file = 'themes.php?page=special-background';
    $title = 'Специальный фон';
    require_once(ABSPATH . 'wp-admin/admin-header.php');
    ob_start();
    $custom_background->admin_page();
    $html = ob_get_clean();
    $html = preg_replace('#<h2>([^<]+)</h2>#','<h2>Специальный фон</h2>',$html);
    echo $html;
    include(ABSPATH . 'wp-admin/admin-footer.php');
    exit;
  }
}
function is_special_background_page() {
  global $pagenow;
  return ($pagenow=='themes.php' &&
         isset($_GET['page']) && $_GET['page']== 'special-background');
}

Честно говоря, это слишком много кода для подробного объяснения, но я с радостью отвечу на конкретные вопросы.

28 авг. 2010 г. 08:10:05
Комментарии

Совет: list($var1, $var2) = array($var2, $var1); // меняет значения переменных $var1 и $var2 местами

hakre hakre
28 авг. 2010 г. 09:18:20

Этот плагин я бы определенно завернул в класс.

hakre hakre
28 авг. 2010 г. 09:20:06

@MikeSchinkel: Можешь добавить небольшое описание твоей концепции swap/save? Обычно эти значения модификации темы theme_mod_background_image используются ядром wp для предоставления стандартного заголовка? Что ты делаешь, если в теме нет заголовка? Я думаю о создании объекта-фасада для хуков/опций в своей форке... обновлено: http://codex.wordpress.org/Theme_Modification_API .

hakre hakre
28 авг. 2010 г. 12:06:22

Я сделал форк. http://gist.github.com/554944

hakre hakre
28 авг. 2010 г. 16:11:34

@hakre; спасибо за подсказку про замену. Хотя я с ней знаком. Ты должен понимать, что когда я впервые написал эту функцию, она была гораздо сложнее, и я рефакторил её до текущего состояния, поэтому изначально я не предполагал, что она будет настолько простой. Я также не склонен оборачивать вещи в класс здесь на StackExchange, потому что это усложняет понимание для людей, когда вся инфраструктура класса на месте (тем не менее, это не оптимально; если я использую класс, больше людей испугаются; если я не использую класс, я учу их менее хорошей практике).

MikeSchinkel MikeSchinkel
28 авг. 2010 г. 17:27:49

@hakre - WordPress хранит заголовок в опции под названием mods_{$theme}; моя тема называлась wp30, так что это mods_wp30. Там есть фоновое изображение, миниатюра и цвет. Я просто перехватываю обновление и добавляю свои элементы с другими названиями для специального фона, отсюда и замена, а затем делаю обратное при получении опции. WordPress не предоставляет контекст в set_theme_mod(), что сделало эту задачу гораздо сложнее, чем она должна была быть (я запросил фильтр, может, ты его поддержишь? http://core.trac.wordpress.org/ticket/14721)

MikeSchinkel MikeSchinkel
28 авг. 2010 г. 17:58:57

@hakre - Мне пришлось использовать порядок сохранения, чтобы понять, что именно сохраняется, и это очень пугает, потому что это крайне ненадежно; они добавят что-то в /wp-includes/custom-background.php, и всё сломается! Что касается git, я его не знаю и не готов его изучать. Я понимаю, что форки — это хорошо в git, но я всегда считал форки плохой вещью. Ты хочешь сотрудничать по этому поводу для репозитория на WordPress.org? Если да, то нужно обрабатывать несколько фонов, а не только один.

MikeSchinkel MikeSchinkel
28 авг. 2010 г. 18:01:19

@hakre - Я только что посмотрел твой форк. Это "чистый" код, но он настолько абстрагирован, что его сложно понять. Раньше я писал код таким же образом и даже (буквально) проповедовал этот стиль программирования на своих обучающих курсах для корпоративных, государственных и военных программистов. Но после работы с WordPress я понял, что менее абстрактный код иногда может быть преимуществом, потому что его гораздо легче понять. FYI.

MikeSchinkel MikeSchinkel
28 авг. 2010 г. 18:25:26

О, не настолько абстрактно. Мне просто нравится, когда хуки цепляются за одинаковые имена, а варианты настраиваются в начале класса. Я столкнулся с некоторой путаницей во время рефакторинга твоей базы, поэтому появились эти три класса, которые могут показаться немного избыточными. Последний связан с первым, и его логику можно объединить с классом плагина, но я этого еще не сделал. Другой класс был чем-то, с чем мне хотелось поэкспериментировать, чтобы избавиться от твоих add_filter / кучи глобальных функций → одной глобальной функции. Вот это было абстрактно :D. :P Спасибо за отзыв!

hakre hakre
28 авг. 2010 г. 19:01:20

@MikeSchinkel: Я тоже только начинаю работать с git. У меня нет проблем с форками, думаю, это как создание нового репозитория. Насколько я слышал, в git это работает хорошо, так что давайте пофоркаем немного. Этот gist — отличная панель для вставки кода. Можно видеть, откуда что взято и т.д. Круто. --- Не знаю, есть ли смысл добавлять больше одного фонового изображения в WP. Может быть? Но я думаю, проблема в том, что это не задумано так в ядре, должно быть добавлено какое-то число или ключ для различения между фонами. Наверное, проще просто переписать эту форму и предложить страницы админки.

hakre hakre
28 авг. 2010 г. 19:05:03

@MikeSchinkel: Попробуй перед покупкой :D : http://progit.org/book/

hakre hakre
28 авг. 2010 г. 19:25:49

@hakre: Абстракция — понятие относительное. Хочешь увидеть абстракцию? Почитай мою книгу по программированию! http://mikeschinkel.com/books/ Мне нравится Gist, но я не планирую работать с Git, по крайней мере, до тех пор, пока WordPress не примет его (что, я думаю, маловероятно). Да, иметь несколько фоновых изображений было бы очень логично; представь онлайн-журнал с 5 разделами: один фон для каждого плюс главная страница. И по возможности я стараюсь работать с тем, что есть в WordPress, запрашивая хуки там, где они нужны, а не выбрасывать всё и начинать заново. Это просто моя философия расширения WordPress.

MikeSchinkel MikeSchinkel
28 авг. 2010 г. 20:07:15

Вау! Это работает потрясающе! Я без слов.

Amit Amit
29 авг. 2010 г. 23:18:34

@Amit: Без слов, но печатать-то можешь? :-) Рад, что смог помочь. Я выдохся на этом вопросе, потратил гораздо больше времени, чем ожидал, когда начал отвечать, но если вашему клиенту нужно, чтобы эти фоны отображались созданными, я предлагаю консультации по часам... :)

MikeSchinkel MikeSchinkel
30 авг. 2010 г. 00:13:52
Показать остальные 9 комментариев
5

Технически это возможно (то есть расширить исходный код WordPress), но не по умолчанию. Поэтому я бы ответил "нет". Встроенная функция фоновой темы по умолчанию предназначена только для одной графики.

Но если вы немного подробнее опишете, что именно вы имеете в виду под "2 разными областями", возможно, я смогу предложить что-то интересное помимо этого.

Примечание: Выделено для MikeSchinkel. Плагины расширяют исходный код WordPress.

27 авг. 2010 г. 21:11:10
Комментарии

Ну.. Есть основной сайт (около 20 разделов), а затем есть как бы подсайт под одним из этих разделов, который меняется для этого специального события и требует своих цветов стиля и фонового изображения.

Теоретически, я мог бы сказать клиенту загружать изображение на "главную страницу" каждого раздела и называть его "как-нибудь", но мне нравится функциональность пользовательского фона и его семантическое расположение в CMS.

Amit Amit
27 авг. 2010 г. 21:17:01

ты используешь шаблон для каждого раздела? это может быть точкой для подключения. Или для переопределения с помощью дочерней темы для определенной области (тогда в сумме получится два фоновых изображения, потому что у тебя будет две темы - родительская и дочерняя).

hakre hakre
27 авг. 2010 г. 21:32:28

Маловеры! Ты же должен знать, что нельзя говорить, что что-то невозможно в WordPress! ;-)

MikeSchinkel MikeSchinkel
28 авг. 2010 г. 08:10:49

Я этого не делал. В смысле, это просто куча PHP, которую нужно лишь немного переставить, чтобы всё заработало :)

hakre hakre
28 авг. 2010 г. 09:14:49

Верно. Но не стоит отговаривать людей; где есть желание — найдётся и способ!

MikeSchinkel MikeSchinkel
30 авг. 2010 г. 00:30:16