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

Привет @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');
}
Честно говоря, это слишком много кода для подробного объяснения, но я с радостью отвечу на конкретные вопросы.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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