Лучшая подборка кода для вашего файла 'functions.php'
Как и многие другие, кто сейчас читает этот пост, я изучал различные блоги, форумы и дискуссионные группы, чтобы улучшить свои навыки работы с WordPress. В течение последних 12 месяцев я поставил себе цель заменить использование плагинов добавлением кода непосредственно в файл functions.php
.
Хотя я полностью согласен, что плагины очень полезны во многих ситуациях, мой опыт показал, что в 90% случаев использования, даже если плагин существует, его применение может создать ненужные сложности и проблемы совместимости. Кроме того, во многих случаях такие плагины добавляли меню и другие элементы администрирования, которые мне не нужны.
Чаще всего я обнаруживал, что, анализируя код плагинов, я мог выделить нужный мне фрагмент кода и жестко закодировать его в моем functions.php
. Это обеспечивало мне именно ту функциональность, которая мне нужна, без необходимости включать лишние элементы.
Итак, цель этого поста - попытаться привлечь вас, читателей/администраторов/разработчиков, поделиться со мной и другими любыми полезными фрагментами кода, которые вы добавили в файл functions.php
вашей темы для расширения или улучшения WordPress без использования плагинов.
Когда вы публикуете ответ, пожалуйста, дайте каждому фрагменту кода название, сообщите, с какой версией WordPress он совместим, включите описание, которое наилучшим образом описывает его функцию, и (если применимо) добавьте ссылку на оригинальный плагин или источник, где вы нашли информацию.
Я с нетерпением жду всех ваших ответов и, конечно же, буду постоянно добавлять свои новые находки, когда буду их обнаруживать.
Пожалуйста, голосуйте за вопрос и любые ответы, которые вы считаете полезными, нажимая на стрелку вверх слева от вопроса или ответа.

Включение пользовательских типов записей в виджет "Прямо сейчас" в админ-панели
Этот код добавит ваши пользовательские типы записей и количество записей каждого типа в виджет "Прямо сейчас" на панели управления.
// ДОБАВЛЕНИЕ ПОЛЬЗОВАТЕЛЬСКИХ ТИПОВ ЗАПИСЕЙ В ВИДЖЕТ 'ПРЯМО СЕЙЧАС'
function wph_right_now_content_table_end() {
$args = array(
'public' => true ,
'show_ui' => true ,
'_builtin' => false
);
$output = 'object';
$operator = 'and';
$post_types = get_post_types( $args , $output , $operator );
foreach( $post_types as $post_type ) {
$num_posts = wp_count_posts( $post_type->name );
$num = number_format_i18n( $num_posts->publish );
$text = _n( $post_type->labels->singular_name, $post_type->labels->name , intval( $num_posts->publish ) );
if ( current_user_can( 'edit_posts' ) ) {
$num = "<a href='edit.php?post_type=$post_type->name'>$num</a>";
$text = "<a href='edit.php?post_type=$post_type->name'>$text</a>";
}
echo '<tr><td class="first b b-' . $post_type->name . '">' . $num . '</td>';
echo '<td class="t ' . $post_type->name . '">' . $text . '</td></tr>';
}
$taxonomies = get_taxonomies( $args , $output , $operator );
foreach( $taxonomies as $taxonomy ) {
$num_terms = wp_count_terms( $taxonomy->name );
$num = number_format_i18n( $num_terms );
$text = _n( $taxonomy->labels->singular_name, $taxonomy->labels->name , intval( $num_terms ));
if ( current_user_can( 'manage_categories' ) ) {
$num = "<a href='edit-tags.php?taxonomy=$taxonomy->name'>$num</a>";
$text = "<a href='edit-tags.php?taxonomy=$taxonomy->name'>$text</a>";
}
echo '<tr><td class="first b b-' . $taxonomy->name . '">' . $num . '</td>';
echo '<td class="t ' . $taxonomy->name . '">' . $text . '</td></tr>';
}
}
add_action( 'right_now_content_table_end' , 'wph_right_now_content_table_end' );

Добавление формы поиска по Codex в заголовок админ-панели
Это простой способ добавить форму поиска по Codex в заголовок админ-панели, в верхнем правом углу рядом с выпадающим меню быстрых ссылок.
/**
* ДОБАВЛЕНИЕ ФОРМЫ ПОИСКА ПО WP CODEX В ЗАГОЛОВОК АДМИН-ПАНЕЛИ
*/
function wp_codex_search_form() {
echo '<form target="_blank" method="get" action="http://wordpress.org/search/do-search.php" class="alignright" style="margin: 11px 5px 0;">
<input type="text" onblur="this.value=(this.value==\'\') ? \'Поиск по Codex\' : this.value;" onfocus="this.value=(this.value==\'Поиск по Codex\') ? \'\' : this.value;" maxlength="150" value="Поиск по Codex" name="search" class="text"> <input type="submit" value="Перейти" class="button" />
</form>';
}
if( current_user_can( 'manage_plugins' )) {
// Для работы необходимо, чтобы число 11 было заменено на 10!
add_filter( 'in_admin_header', 'wp_codex_search_form', 11 );
}

можете ли вы обновить этот код, чтобы он отображался только пользователям с определенной ролью (конкретно администраторам)?

@NetConstructor.com Я изменил его, чтобы показывать, если current_user_can manage_plugins, затем добавить фильтр. Это так просто.

Работает ли это еще в текущей версии WP... У меня не получилось заставить это работать

Новая колонка в медиатеке для повторной привязки изображений
Этот код добавляет новую колонку на страницу Медиатеки, позволяющую повторно привязывать изображения
add_filter("manage_upload_columns", 'upload_columns');
add_action("manage_media_custom_column", 'media_custom_columns', 0, 2);
function upload_columns($columns) {
unset($columns['parent']);
$columns['better_parent'] = "Родитель";
return $columns;
}
function media_custom_columns($column_name, $id) {
$post = get_post($id);
if($column_name != 'better_parent')
return;
if ( $post->post_parent > 0 ) {
if ( get_post($post->post_parent) ) {
$title =_draft_or_post_title($post->post_parent);
}
?>
<strong><a href="<?php echo get_edit_post_link( $post->post_parent ); ?>"><?php echo $title ?></a></strong>, <?php echo get_the_time(__('Y/m/d')); ?>
<br />
<a class="hide-if-no-js" onclick="findPosts.open('media[]','<?php echo $post->ID ?>');return false;" href="#the-list"><?php _e('Привязать снова'); ?></a>
<?php
} else {
?>
<?php _e('(Не привязано)'); ?><br />
<a class="hide-if-no-js" onclick="findPosts.open('media[]','<?php echo $post->ID ?>');return false;" href="#the-list"><?php _e('Привязать'); ?></a>
<?php
}
}

Тематический пользовательский цикл с использованием шорткодов
Аргументы такие же, как у query_posts. Содержимое, заключенное между тегом запроса, является шаблоном.
add_shortcode('query', 'shortcode_query');
function shortcode_query($atts, $content){
extract(shortcode_atts(array( // несколько значений по умолчанию
'posts_per_page' => '10',
'caller_get_posts' => 1,
'post__not_in' => get_option('sticky_posts'),
), $atts));
global $post;
$posts = new WP_Query($atts);
$output = '';
if ($posts->have_posts())
while ($posts->have_posts()):
$posts->the_post();
// эти аргументы будут доступны внутри $content
$parameters = array(
'PERMALINK' => get_permalink(),
'TITLE' => get_the_title(),
'CONTENT' => get_the_content(),
'COMMENT_COUNT' => $post->comment_count,
'CATEGORIES' => get_the_category_list(', '),
// можно добавить больше...
);
$finds = $replaces = array();
foreach($parameters as $find => $replace):
$finds[] = '{'.$find.'}';
$replaces[] = $replace;
endforeach;
$output .= str_replace($finds, $replaces, $content);
endwhile;
else
return; // записи не найдены
wp_reset_query();
return html_entity_decode($output);
}
Использование:
[query post_type=page posts_per_page=5]
Список страниц:
<h5>{TITLE}</h5>
<div>{CONTENT}</div>
<p><a href="{PERMALINK}">{COMMENT_COUNT} комментариев</a></p>
[/query]
(выполнит запрос для 5 страниц)
Вставка предварительно настроенных виджетов в любом месте с помощью шорткодов
(некоторые идеи взяты из http://webdesign.anmari.com/shortcode-any-widget)
add_action('widgets_init', 'create_arbitrary_sidebar');
function create_arbitrary_sidebar(){
register_sidebar(array(
'name' => __('Произвольные виджеты'),
'id' => 'arbitrary',
'description' => sprintf(__('Виджеты из этой области можно добавлять в записи/страницы с помощью шорткодов %1$s или %2$s.'), '[widget ID]', '[widget Name]'),
'before_widget' => '<div class="block"><div class="block-content block-%2$s clear-block" id="instance-%1$s">',
'after_widget' => '</div></div>',
'before_title' => '<h3 class="title">',
'after_title' => '</h3>'
));
}
add_action('in_widget_form', 'widget_shortcodes_info', 10, 3);
function widget_shortcodes_info($widget, $return, $instance){
if(!is_numeric($widget->number)) return; // баг wp-save :( сначала нужно сохранить виджет...
global $wp_registered_widgets;
// получаем активные виджеты из всех сайдбаров
$sidebars_widgets = wp_get_sidebars_widgets();
// готовим совпадения
$matches = array();
foreach($wp_registered_widgets as $i => $w)
if($w['name'] == $widget->name) $matches[] = $w['id'];
// выясняем позицию виджета (номер)
$number = 0;
$is_arbitrary = false;
if(!empty($sidebars_widgets['arbitrary']))
foreach($sidebars_widgets['arbitrary'] as $i => $value):
if(in_array($value, $matches) && !$is_arbitrary) $number = $number +1;
if($value == $widget->id) $is_arbitrary = true;
endforeach;
echo '<div style="background:#eee; padding: 5px;">Для включения этого виджета в записи или страницы используйте один из следующих шорткодов: <br />';
echo '<code>[widget '.substr(md5($widget->id), 0, 8).']</code> <br /> <code>[widget "'.$widget->name.'"'.(($number > 1) ? ' number='.$number : null).']</code></div>';
}
add_shortcode('widget', 'shortcode_widget');
function shortcode_widget($atts){
global $wp_registered_widgets, $wp_registered_sidebars;
extract(shortcode_atts(array(
'number' => false, // учитывается только если первый аргумент - "Имя виджета" (не хэшированный ID)
'title' => true, // показывать заголовки?
'area' => 'arbitrary' // сайдбар для поиска
), $atts));
// получаем первый параметр (предполагаем, что это ID или имя целевого виджета)
if (!empty($atts[0])) $widget = esc_attr($atts[0]); else return;
$sidebar = esc_attr($area);
$number = intval($number);
$callback = false;
$possible_matches = array();
$sidebars_widgets = wp_get_sidebars_widgets();
if((empty($sidebars_widgets[$sidebar]) || empty($wp_registered_widgets)) && (current_user_can('edit_themes')))
return "нет активных виджетов в {$sidebar}";
// предполагаем, что мы получаем хэшированный ID
foreach ($wp_registered_widgets as $i => $w)
if ($widget == substr(md5($w['id']), 0, 8)):
$callback = ($w['callback']);
$widget = $w['id']; // реальный ID виджета
// также сравниваем имена виджетов и создаем массив возможных совпадений
// (используется позже, если совпадение по ID не удалось)
elseif($widget == $w['name']):
$possible_matches[] = $w['id'];
endif;
// ничего не найдено, предполагаем, что это "Имя виджета".
if(!$callback):
$valid_matches = array();
foreach($sidebars_widgets[$sidebar] as $i => $w)
foreach($possible_matches as $id) if($id == $w) $valid_matches[] = $w;
if(!empty($valid_matches)) $widget = $number ? $valid_matches[$number-1] : $widget = $valid_matches[0];
if($widget && isset($wp_registered_widgets[$widget]['callback'])) $callback = $wp_registered_widgets[$widget]['callback'];
endif;
// ура. мы нашли его
if($callback):
ob_start();
$params = array_merge(array(array_merge($wp_registered_sidebars[$sidebar], array('widget_id' => $widget, 'widget_name' => $wp_registered_widgets[$widget]['name']))), (array)$wp_registered_widgets[$widget]['params']);
$classname_ = '';
foreach ((array)$wp_registered_widgets[$widget]['classname'] as $cn)
if (is_string($cn)) $classname_ .= '_'.$cn; elseif (is_object($cn)) $classname_ .= '_'.get_class($cn);
$classname_ = ltrim($classname_, '_');
$params[0]['before_widget'] = sprintf($params[0]['before_widget'], $widget, $classname_);
$params = apply_filters('dynamic_sidebar_params', $params);
if (is_callable($callback)) call_user_func_array($callback, $params);
$output = ob_get_clean();
// удаляем h3 если title = false
if(!$title) $output = preg_replace('#<h3 class="title">(.*?)</h3>#', '', $output);
return $output;
else:
return "экземпляр виджета не найден: ".esc_attr($atts[0]);
endif;
}
Использование:
Поместите виджет в сайдбар "Произвольные виджеты", сохраните его, и вы получите шорткоды :)
Получение значения произвольного поля через шорткоды
add_shortcode('field', 'shortcode_field');
function shortcode_field($atts){
extract(shortcode_atts(array(
'post_id' => NULL,
), $atts));
if(!isset($atts[0])) return;
$field = esc_attr($atts[0]);
global $post;
$post_id = (NULL === $post_id) ? $post->ID : $post_id;
return get_post_meta($post_id, $field, true);
}
Использование:
[field "my_key"]
[field "my_key" post_id=1]
Получение TinyURL ссылки через шорткоды
add_shortcode('tinyurl', 'shortcode_tinyurl');
function shortcode_tinyurl($atts){
extract(shortcode_atts(array(
'url' => get_permalink(),
'title' => '',
'rel' => 'nofollow'
), $atts));
if(!$title) $title = $url;
if (FALSE === ($cache = get_transient('tinyurl_'+md5($url)))):
$cache = wp_remote_retrieve_body(wp_remote_get('http://tinyurl.com/api-create.php?url='.$url));
set_transient('tinyurl_'+md5($url), $cache, 60*60*24); // кэш на 1 день, можно увеличить
endif;
return '<a href="'.esc_url($cache).'" rel="'.esc_attr($rel).'">'.esc_attr($title).'</a>';
}
Использование:
[tinyurl]
[tinyurl url="http://google.com" title="google"]

Установка редактора по умолчанию: WYSIWYG или HTML
function my_default_editor() {
$r = 'tinymce'; // html или tinymce
return $r;
}
add_filter( 'wp_default_editor', 'my_default_editor' );
Вот как удалить HTML-редактор
jQuery(document).ready(function($) {
$("#edButtonHTML").remove();
});
ОБНОВЛЕНО вот еще один способ установить HTML-редактор по умолчанию
add_filter('wp_default_editor', create_function('', 'return "html";'));

подробнее об источнике: http://wpengineer.com/1946/disable-html-editor-wordpress/

Удаление метабокса автора и его параметров с переносом в метабокс публикации
Проверено на: WordPress 3.0.1
Одна из вещей, которая сводит меня с ума — это захламленная админка WordPress. Один из элементов, который я теперь всегда настраиваю с самого начала в файле functions.php — это удаление метабокса автора и опций экрана, а затем добавление этой опции в метабокс публикации. На мой взгляд, это логично и поддерживает порядок. Также это учитывает соответствующие права доступа.
Чтобы добиться этого, просто скопируйте и вставьте следующий код в ваш файл functions.php.
Если вы знаете более удачный способ реализации, поделитесь в комментариях.
ПРИМЕЧАНИЕ: КОД ОБНОВЛЕН ДЛЯ ИСПРАВЛЕНИЯ ОШИБКИ
// ПЕРЕМЕЩЕНИЕ МЕТАБОКСА АВТОРА В МЕТАБОКС ПУБЛИКАЦИИ
add_action( 'admin_menu', 'remove_author_metabox' );
add_action( 'post_submitbox_misc_actions', 'move_author_to_publish_metabox' );
function remove_author_metabox() {
remove_meta_box( 'authordiv', 'post', 'normal' );
}
function move_author_to_publish_metabox() {
global $post_ID;
$post = get_post( $post_ID );
echo '<div id="author" class="misc-pub-section" style="border-top-style:solid; border-top-width:1px; border-top-color:#EEEEEE; border-bottom-width:0px;">Автор: ';
post_author_meta_box( $post );
echo '</div>';
}

Он не добавляет метабокс автора в мой блок публикации. Я предположил, что это из-за отсутствия add_action
для функции move_author_to_publish_box
, поэтому я добавил add_action('admin_menu', 'move_author_to_publish_box');
, но это вызвало "Фатальную ошибку: Вызов undefined function post_author_meta_box()"

И как бы вы добавили автора к публикации? На admin_init или на admin_menu не сработает.

@kaiser -- Я не уверен, что понял ваш вопрос. Этот код просто удаляет метабокс "автор" и помещает опцию выбора автора в метабокс "публикация".

@NetConstructor: Я только что протестировал это вчера (3.0.4), и да, бокс автора исчез, но не переместился в бокс публикации. Глядя на код, я не вижу, как это может работать, потому что функция нигде не вызывается... вы просто добавили remove_author_box() к хуку admin_menu, но не move_author_to_publish_box().

@kaiser -- ты прав, после проверки я заметил эту проблему. Я обновил код в своем ответе, так что просто удалите все, что вы включили из этого ранее, и вставьте полный код выше. Дайте мне знать, если это исправит ситуацию. Проголосуйте за вопрос и ответ, если это решит проблему - CH :)

@CH/NC: Конечно, это работает, даже тестировать не нужно. Голосую за: без проблем. Можно/стоит расширить, чтобы убрать и другой ненужный хлам... (обсуждения, миниатюры записей). Я не буду править ваш ответ, но если у вас будет время, это даже заслуживает отдельного поста в блоге. :)

@kaiser — не совсем понимаю, в чём вы видите ценность этого? Моя цель была просто убрать лишние метабоксы, которые не нужны, например, слаги и авторы.

@you: Нет, я абсолютно вижу пользу. Вы не просто меня недопоняли, а поняли с точностью до наоборот. Я сказал, что это настолько хорошо, что стоит а) расширить на обсуждения и миниатюры и б) написать об этом пост в блоге — что-то вроде «очистка страниц редактирования контента». Прим.: «Без тестирования» означает, что я знаю, что это работает.

@kaiser -- спасибо за комплимент, но я всё ещё не понимаю, как, по-твоему, интеграция обсуждений или миниатюр в метабокс публикации будет полезна пользователям. Я видел пользу только в удалении метабоксов слага и автора, так как логически они должны быть внутри метабокса публикации. Я всё ещё неверно понимаю твою точку зрения?

Быстрое определение сервера и параметров окружения
Если у вас несколько серверов и окружений, таких как разработка, тестирование и продакшен, этот метод может быть очень полезным.
В моей системе окружение определяется по первым 3 буквам имени хоста, но вы легко можете изменить это под свои нужды.
add_action( 'admin_notices', 'report_environment_status', 3 );
// Отображение информации о сервере и окружении
function report_environment_status() {
$server = php_uname('n');
switch (strtolower(substr($server,0,3))) {
case 'pXX':
$msg = "PRODUCTION";
break;
case 'qXX':
$msg = "QA";
break;
case 'dXX':
$msg = "DEVELOPMENT";
break;
default :
$msg = 'UNKNOWN';
}
echo "<div id='update-nag'>";
echo "<b>Вы находитесь в окружении $msg. (Сервер: $server)</b>";
echo "</div>";
}
Это не раз спасало меня от внесения изменений в неправильное окружение.
Вы также можете превратить это в плагин и активировать его для всей сети, чтобы уведомление отображалось на всех сайтах.

Спасибо за этот материал. Не могли бы вы немного подробнее раскрыть эту тему и различные варианты использования? Я думаю, что мне и другим было бы ОЧЕНЬ полезно, если бы вы могли включить любой другой код, который вы используете при работе с разными версиями кода в разработке. Также, если у вас есть удобный способ переноса сайта из разработки в продакшн или миграции с одного домена на другой. Все эти вещи очень полезны. Наконец, используете ли вы какой-либо клиент системы контроля версий при обновлении файлов? Если да, то делаете ли вы что-то особенное для этого?

Пожалуйста, не помечайте это как ответ. Иначе этот список не будет работать.

Исправлено: Удаление стандартных метабоксов WordPress
Это было очень удобно, но содержало некоторые ошибки
// УДАЛЕНИЕ СТАНДАРТНЫХ МЕТАБОКСОВ ИЗ ЭКРАНА ЗАПИСЕЙ
function remove_default_post_screen_metaboxes() {
remove_meta_box( 'postcustom','post','normal' ); // Метабокс "Произвольные поля"
remove_meta_box( 'postexcerpt','post','normal' ); // Метабокс "Цитата"
remove_meta_box( 'commentstatusdiv','post','normal' ); // Метабокс "Комментарии"
remove_meta_box( 'trackbacksdiv','post','normal' ); // Метабокс "Обратные ссылки"
remove_meta_box( 'slugdiv','post','normal' ); // Метабокс "Ярлык"
remove_meta_box( 'authordiv','post','normal' ); // Метабокс "Автор"
}
add_action('admin_menu','remove_default_post_screen_metaboxes');
// УДАЛЕНИЕ СТАНДАРТНЫХ МЕТАБОКСОВ ИЗ ЭКРАНА СТРАНИЦ
function remove_default_page_screen_metaboxes() {
global $post_type;
remove_meta_box( 'postcustom','page','normal' ); // Метабокс "Произвольные поля"
remove_meta_box( 'postexcerpt','page','normal' ); // Метабокс "Цитата"
remove_meta_box( 'commentstatusdiv','page','normal' ); // Метабокс "Комментарии"
remove_meta_box('commentsdiv','page','normal'); // Комментарии
remove_meta_box( 'trackbacksdiv','page','normal' ); // Метабокс "Обратные ссылки"
remove_meta_box( 'slugdiv','page','normal' ); // Метабокс "Ярлык"
remove_meta_box( 'authordiv','page','normal' ); // Метабокс "Автор"
}
add_action('admin_menu','remove_default_page_screen_metaboxes');

Увеличение периода автоматического выхода из системы
Проверено на: WordPress 3.0.1
Используя приведённый ниже код, вы можете увеличить время хранения cookies, благодаря чему авторизованные пользователи останутся в системе дольше:
function keep_me_logged_in_for_1_year( $expirein ) {
return 31556926; // 1 год в секундах
}
add_filter( 'auth_cookie_expiration', 'keep_me_logged_in_for_1_year' );

есть ещё один трюк, который можно использовать, я нашёл его здесь: http://wpengineer.com/2064/stop-wordpress-from-ever-logging-out/

Добавление ссылки "Настройки" для плагинов на странице списка плагинов
Установите ссылку "Настройки" для плагинов на странице плагинов в админке WordPress, чтобы пользователи могли легко перейти к настройкам (код также содержит решение для версий WordPress младше 2.9)
// определения плагина
define( 'FB_BASENAME', plugin_basename( __FILE__ ) );
define( 'FB_BASEFOLDER', plugin_basename( dirname( __FILE__ ) ) );
define( 'FB_FILENAME', str_replace( FB_BASEFOLDER.'/', '', plugin_basename(__FILE__) ) );
function filter_plugin_meta($links, $file) {
/* создаем ссылку */
if ( $file == FB_BASENAME ) {
array_unshift(
$links,
sprintf( '<a href="options-general.php?page=%s">%s</a>', FB_FILENAME, __('Settings', 'Настройки') )
);
}
return $links;
}
global $wp_version;
if ( version_compare( $wp_version, '2.7alpha', '>' ) ) {
add_filter( 'plugin_action_links_' . FB_WM_BASENAME, 'filter_plugin_meta', 10, 2);
} else {
add_filter( 'plugin_action_links', 'filter_plugin_meta', 10, 2 );
}

Я попытался использовать этот код, но похоже, что он не работает на WordPress 3.1. Можете подтвердить и обновить?

@NetConstructor.com Я немного обновил один из своих бесплатных плагинов, на всех моих плагинах это работает нормально

Отлично! Я как раз искал функцию make_clickable()
, чтобы применить её к the_content
! Почему они не сделали это изначально? Это же так просто - достаточно добавить add_filter( 'the_content', 'make_clickable');
. Альтернативно это можно сделать при сохранении записи, используя другой хук

Добавление фильтра шаблонов страниц в список страниц
Проверено на: WP 3.1
Добавляет фильтр шаблонов страниц в список страниц, позволяя просматривать список страниц, использующих определенный шаблон.
class Page_Template_Filter {
private $templates = array();
public function __construct() {
// Если это не админка или пользователь не может редактировать страницы, выходим
if( !is_admin() || !current_user_can('edit_pages') )
return;
add_action( 'parse_query', array( $this, 'pt_parse_query' ) );
add_action( 'restrict_manage_posts', array( $this, 'pt_restrict_manage_posts' ) );
}
public function pt_parse_query( $query ) {
global $pagenow, $post_type;
if( 'edit.php' != $pagenow )
return;
switch( $post_type ) {
case 'post':
break;
case 'page':
$this->templates = get_page_templates();
if( empty( $this->templates ) )
return;
if( !$this->is_set_template() )
return;
$meta_group = array( 'key' => '_wp_page_template', 'value' => $this->get_template() );
set_query_var( 'meta_query', array( $meta_group ) );
break;
}
}
public function pt_restrict_manage_posts() {
if( empty( $this->templates ) )
return;
$this->template_dropdown();
}
private function get_template() {
if( $this->is_set_template() )
foreach( $this->templates as $template ) {
if( $template != $_GET['page_template'] )
continue;
return $template;
}
return '';
}
private function is_set_template() {
return (bool) ( isset( $_GET['page_template'] ) && ( in_array( $_GET['page_template'], $this->templates ) );
}
private function template_dropdown() {
?>
<select name="page_template" id="page_template">
<option value=""> - без шаблона - </option>
<?php foreach( $this->templates as $name => $file ): ?>
<option value="<?php echo $file; ?>"<?php selected( $this->get_template() == $file ); ?>><?php _e( $name ); ?></option>
<?php endforeach;?>
</select>
<?php
}
}
add_action('admin_init', 'load_ptf');
function load_ptf() {
$Page_Template_Filter = new Page_Template_Filter;
}
Для работы требуется WordPress версии не ниже 3.1, хотя meta_query
можно заменить на старые параметры meta_key
и meta_value
для версии 3.0.

Отображать только записи и медиафайлы текущего автора и исправить счетчики в фильтрах.
Протестировано на: WordPress 3.4.1
По умолчанию WordPress позволяет авторам видеть заголовки записей других пользователей, черновики и все медиафайлы, даже если они не могут их редактировать.
Используйте этот код, чтобы отображать только записи и медиафайлы текущего автора.
В отличие от других решений, этот код также исправляет счетчики записей и медиафайлов в фильтрах (Все|Опубликованные|Черновики|Ожидающие|Корзина; Все|Изображения|Видео|Неприкрепленные).
// Показывать только записи и медиафайлы текущего автора
add_action('pre_get_posts', 'query_set_only_author' );
function query_set_only_author( $wp_query ) {
global $current_user;
if( is_admin() && !current_user_can('edit_others_posts') ) {
$wp_query->set( 'author', $current_user->ID );
add_filter('views_edit-post', 'fix_post_counts');
add_filter('views_upload', 'fix_media_counts');
}
}
// Исправление счетчиков записей
function fix_post_counts($views) {
global $current_user, $wp_query;
unset($views['mine']);
$types = array(
array( 'status' => NULL ),
array( 'status' => 'publish' ),
array( 'status' => 'draft' ),
array( 'status' => 'pending' ),
array( 'status' => 'trash' )
);
foreach( $types as $type ) {
$query = array(
'author' => $current_user->ID,
'post_type' => 'post',
'post_status' => $type['status']
);
$result = new WP_Query($query);
if( $type['status'] == NULL ):
$class = ($wp_query->query_vars['post_status'] == NULL) ? ' class="current"' : '';
$views['all'] = sprintf(__('<a href="%s"'. $class .'>Все <span class="count">(%d)</span></a>', 'all'),
admin_url('edit.php?post_type=post'),
$result->found_posts);
elseif( $type['status'] == 'publish' ):
$class = ($wp_query->query_vars['post_status'] == 'publish') ? ' class="current"' : '';
$views['publish'] = sprintf(__('<a href="%s"'. $class .'>Опубликованные <span class="count">(%d)</span></a>', 'publish'),
admin_url('edit.php?post_status=publish&post_type=post'),
$result->found_posts);
elseif( $type['status'] == 'draft' ):
$class = ($wp_query->query_vars['post_status'] == 'draft') ? ' class="current"' : '';
$views['draft'] = sprintf(__('<a href="%s"'. $class .'>Черновик'. ((sizeof($result->posts) > 1) ? "и" : "") .' <span class="count">(%d)</span></a>', 'draft'),
admin_url('edit.php?post_status=draft&post_type=post'),
$result->found_posts);
elseif( $type['status'] == 'pending' ):
$class = ($wp_query->query_vars['post_status'] == 'pending') ? ' class="current"' : '';
$views['pending'] = sprintf(__('<a href="%s"'. $class .'>Ожидающие <span class="count">(%d)</span></a>', 'pending'),
admin_url('edit.php?post_status=pending&post_type=post'),
$result->found_posts);
elseif( $type['status'] == 'trash' ):
$class = ($wp_query->query_vars['post_status'] == 'trash') ? ' class="current"' : '';
$views['trash'] = sprintf(__('<a href="%s"'. $class .'>Корзина <span class="count">(%d)</span></a>', 'trash'),
admin_url('edit.php?post_status=trash&post_type=post'),
$result->found_posts);
endif;
}
return $views;
}
// Исправление счетчиков медиафайлов
function fix_media_counts($views) {
global $wpdb, $current_user, $post_mime_types, $avail_post_mime_types;
$views = array();
$_num_posts = array();
$count = $wpdb->get_results( "
SELECT post_mime_type, COUNT( * ) AS num_posts
FROM $wpdb->posts
WHERE post_type = 'attachment'
AND post_author = $current_user->ID
AND post_status != 'trash'
GROUP BY post_mime_type
", ARRAY_A );
foreach( $count as $row )
$_num_posts[$row['post_mime_type']] = $row['num_posts'];
$_total_posts = array_sum($_num_posts);
$detached = isset( $_REQUEST['detached'] ) || isset( $_REQUEST['find_detached'] );
if ( !isset( $total_orphans ) )
$total_orphans = $wpdb->get_var("
SELECT COUNT( * )
FROM $wpdb->posts
WHERE post_type = 'attachment'
AND post_author = $current_user->ID
AND post_status != 'trash'
AND post_parent < 1
");
$matches = wp_match_mime_types(array_keys($post_mime_types), array_keys($_num_posts));
foreach ( $matches as $type => $reals )
foreach ( $reals as $real )
$num_posts[$type] = ( isset( $num_posts[$type] ) ) ? $num_posts[$type] + $_num_posts[$real] : $_num_posts[$real];
$class = ( empty($_GET['post_mime_type']) && !$detached && !isset($_GET['status']) ) ? ' class="current"' : '';
$views['all'] = "<a href='upload.php'$class>" . sprintf( __('Все <span class="count">(%s)</span>', 'uploaded files' ), number_format_i18n( $_total_posts )) . '</a>';
foreach ( $post_mime_types as $mime_type => $label ) {
$class = '';
if ( !wp_match_mime_types($mime_type, $avail_post_mime_types) )
continue;
if ( !empty($_GET['post_mime_type']) && wp_match_mime_types($mime_type, $_GET['post_mime_type']) )
$class = ' class="current"';
if ( !empty( $num_posts[$mime_type] ) )
$views[$mime_type] = "<a href='upload.php?post_mime_type=$mime_type'$class>" . sprintf( translate_nooped_plural( $label[2], $num_posts[$mime_type] ), $num_posts[$mime_type] ) . '</a>';
}
$views['detached'] = '<a href="upload.php?detached=1"' . ( $detached ? ' class="current"' : '' ) . '>' . sprintf( __( 'Неприкрепленные <span class="count">(%s)</span>', 'detached files' ), $total_orphans ) . '</a>';
return $views;
}

хороший сниппет, единственный недостаток — если в медиатеке нет элементов, он выводит ошибки, потому что результат не является массивом.

Я определил $_num_posts как массив. Это должно исправить ошибки, которые возникают, когда в медиатеке нет элементов.

Я знаю, что прошло довольно много времени, чтобы спрашивать об этом, но я попробовал с моим CPT, и подсчет постов, кажется, не работает, хотя я заменил все tour type на мой CPT.
Также, есть ли способ применить фильтр для терминов в моём CPT?
Кстати, большое спасибо за ваш код.

Отключение XML-RPC для повышения производительности, если он не используется
Проверено на: Wordpress 3.0.1
WordPress использует операцию CURL для проверки поддержки SSL в XML-RPC. Если вы не используете XML-RPC, то можете удалить этот фильтр. Это небольшое повышение производительности (поскольку WP выполняет GET-запрос через cURL по HTTPS-адресу и либо 1) получает сообщение об отказе, либо 2) превышает время ожидания, что может занимать до 5 секунд). В нашем случае это предотвратило таймаут шлюза, когда прокси-сервер завершал работу раньше, чем завершался cURL-запрос, делая XML-RPC непригодным для использования.
// Предотвращает проверку WordPress возможности SSL на domain.com/xmlrpc.php?rsd
remove_filter('atom_service_url','atom_service_url_filter');

Спасибо за предложенный код. Один вопрос: если используется XML-RPC, но без SSL-возможностей, ускорит ли это код работу? Если нет, в каких ситуациях его включение будет полезным?

Коллекция быстрых правок для functions.php
У меня есть несколько отличных модификаций для functions.php
, которые я находил в течение многих лет поисков.
Окончание цитаты (Excerpt)
function new_excerpt_more($more) {
return '...';
}
add_filter('excerpt_more', 'new_excerpt_more');
Замена логотипа в админке WordPress
function new_admin_logo() {
echo '<style type="text/css">#header-logo { background-image: url('.get_bloginfo('template_directory').'/images/admin_logo.png) !important; }</style>';
}
add_action('admin_head', 'new_admin_logo');
Пользовательская иконка для админки WordPress
function admin_favicon() {
echo '<link rel="shortcut icon" type="image/x-icon" href="' . get_bloginfo('template_directory') . '/images/favicon.ico" />';
}
add_action( 'admin_head', 'admin_favicon' );
Пользовательский подвал админки
function custom_admin_footer() {
echo 'Добро пожаловать в мой блог! Больше никаких ссылок на документацию!';
}
add_filter('admin_footer_text', 'custom_admin_footer');

Получение всех произвольных полей глобально
function get_custom_field($key, $echo = FALSE) {
global $post;
$custom_field = get_post_meta( $post->ID, $key, true );
if ( $echo == false )
return $custom_field;
echo $custom_field;
}
Вызов поля одной строкой
<?php get_custom_field('название-произвольного-поля', TRUE); ?>

Возвращаем количество комментариев
Эта функция аналогична count_user_posts()
, но возвращает количество комментариев:
function count_user_comments($id) {
global $wpdb;
$users = $wpdb->get_var("
SELECT COUNT( * ) AS total
FROM $wpdb->comments
WHERE comment_approved = 1
AND user_id = $id");
return $users;
}
Дополнительно: подсчет записей пользователя (включая произвольные типы записей) или комментариев:
function atom_count($user_id, $what_to_count = 'post') {
global $wpdb;
$where = $what_to_count == 'comment' ? "WHERE comment_approved = 1 AND user_id = {$user_id}" : get_posts_by_author_sql($what_to_count, TRUE, $user_id);
$from = "FROM ".(($what_to_count == 'comment') ? $wpdb->comments : $wpdb->posts);
$count = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) {$from} {$where}"));
return $count;
}
Примеры использования:
<?php echo atom_count(1, 'movie'); // выводит количество записей типа 'movie' ?>
<?php echo atom_count(1, 'comment'); // выводит количество комментариев ?>

Счётчик слов в записях
Протестировано на: WordPress 3.0.1
(Первоначально взято из плагина Post Word Count от Nick Momrick)
Добавляет подсчёт общего количества опубликованных слов в нижнюю часть блока "Прямо сейчас" в админ-панели. Полезно, если вы используете блог для таких целей, как NaNoWriMo, или просто хотите отслеживать, насколько продуктивным становится ваш блог.
function post_word_count() {
$count = 0;
$posts = get_posts( array(
'numberposts' => -1,
'post_type' => array( 'post', 'page' )
));
foreach( $posts as $post ) {
$count += str_word_count( strip_tags( get_post_field( 'post_content', $post->ID )));
}
$num = number_format_i18n( $count );
// Этот блок добавит ваш счётчик слов в раздел статистики блока "Прямо сейчас"
$text = _n( 'Слово', 'Слова', $num );
echo "<tr><td class='first b'>{$num}</td><td class='t'>{$text}</td></tr>";
// Эта строка добавит ваш счётчик слов в нижнюю часть блока "Прямо сейчас"
echo '<p>В этом блоге опубликовано всего <strong>' . $num . '</strong> слов!</p>';
}
// добавляем в таблицу статистики контента
add_action( 'right_now_content_table_end', 'post_word_count');
// добавляем в нижнюю часть блока активности
add_action('activity_box_end', 'post_word_count');
Благодарность Rarst за оптимизацию кода без использования запросов!

Спасибо за помощь, Rarst. Обычно я не люблю включать прямые запросы к базе данных в код плагина в function.php
, но, как я уже говорил, это изначально было взято из чужого плагина.

Не за что, я пробовал это давно, и был полный бардак. :) Теперь с прокачанными навыками пришло время сделать всё правильно. Почему оставил старую часть вывода? Думаю, имеет смысл показывать её вместе с остальной статистикой. Кстати, эта версия даёт другое общее количество (по сравнению с explode
), вероятно из-за фильтров по пути при выборке через API.

Разница в количестве постов - результат фильтров... но использование get_posts()
всё равно даст более точное количество слов. Я оставил старую строку вывода просто потому что именно так я её использовал... скорее разница во мнениях, чем что-то ещё... Я добавлю твой пример обратно в статистику, чтобы люди могли выбирать.

Условная загрузка скриптов
Вот способ загружать скрипты только если присутствует определённый шорткод или виджет. источник: Загрузка скриптов только при наличии определённого шорткода или виджета
function has_my_shortcode($posts) {
if ( empty($posts) )
return $posts;
$found = false;
foreach ($posts as $post) {
if ( stripos($post->post_content, '[my_shortcode') )
$found = true;
break;
}
if ($found){
$urljs = get_bloginfo( 'template_directory' ).IMP_JS;
wp_register_script('my_script', $urljs.'myscript.js' );
wp_print_scripts('my_script');
}
return $posts;
}
add_action('the_posts', 'has_my_shortcode');
А вот как загружать скрипты только при наличии определённого виджета
Чтобы загружать скрипт только на странице, где загружен виджет, вам нужно добавить код is_active_widget() в класс виджета. Например, смотрите стандартный виджет "Последние комментарии" (wp-includes/default-widgets.php, строка 602):
class WP_Widget_Recent_Comments extends WP_Widget {
function WP_Widget_Recent_Comments() {
$widget_ops = array('classname' => 'widget_recent_comments', 'description' => __( 'Последние комментарии' ) );
$this->WP_Widget('recent-comments', __('Последние комментарии'), $widget_ops);
$this->alt_option_name = 'widget_recent_comments';
if ( is_active_widget(false, false, $this->id_base) )
add_action( 'wp_head', array(&$this, 'recent_comments_style') );
add_action( 'comment_post', array(&$this, 'flush_widget_cache') );
add_action( 'transition_comment_status', array(&$this, 'flush_widget_cache') );
}

Пользовательские стили для админ-панели
/* Изменение CSS админ-панели WordPress */
function custom_admin_styles() {
echo '<style type="text/css">#wphead{background:#069}</style>';
}
add_action('admin_head', 'custom_admin_styles');
Вы можете добавить любые изменения CSS между тегами <style>.

Удаление префиксов Private и Protected
Эта функция удаляет префиксы "Private:" и "Protected:" из заголовков записей и страниц, помеченных как приватные. Полезно для контента, видимого только зарегистрированным пользователям или определенным группам.
function the_title_trim($title) {
$title = attribute_escape($title);
$findthese = array(
'#Protected:#',
'#Private:#'
);
$replacewith = array(
'', // Чем заменить "Protected:"
'' // Чем заменить "Private:"
);
$title = preg_replace($findthese, $replacewith, $title);
return $title;
}
add_filter('the_title', 'the_title_trim');
ОБНОВЛЕНО: Теперь функция также удаляет префикс Protected:.

Произвольная длина анонса
function excerpt($num) {
$limit = $num+1;
$excerpt = explode(' ', get_the_excerpt(), $limit);
array_pop($excerpt);
$excerpt = implode(" ",$excerpt)."... (<a href='" .get_permalink($post->ID) ." '>Читать далее</a>)";
echo $excerpt;
}
Ограничьте длину отображаемого анонса, добавив в тему: excerpt('20');
Пример: <?php excerpt('22'); ?>
Это ограничит анонс до 22 символов.
Анонс будет прерван текстом ... (Читать далее)

Добавление slug родительской страницы в body_class
/***************************************************************
* Функция body_class_section
* Добавляет slug страницы верхнего уровня в класс body для цветовых разделов
***************************************************************/
add_filter('body_class','body_class_section');
function body_class_section($classes) {
global $wpdb, $post;
if (is_page()) {
if ($post->post_parent) {
$parent = end(get_post_ancestors($current_page_id));
} else {
$parent = $post->ID;
}
$post_data = get_post($parent, ARRAY_A);
$classes[] = 'section-' . $post_data['post_name'];
}
return $classes;
}
Этот фильтр добавляет уникальный класс к тегу body на основе самой верхней родительской страницы текущей страницы. Я использую это для сайтов, где у каждого раздела есть свои цвета или макеты. Лучше всего работает с сайтами, построенными на страницах. Примеры CSS:
.section-about { background: red; }
.section-portfolio { background: blue; }
Ваша тема также должна использовать функцию body_class.
Исправление oEmbed flash-объектов
/***************************************************************
* Функция my_oembed_wmode
* Исправляет window mode для flash-объектов в oEmbed
***************************************************************/
add_filter('embed_oembed_html', 'my_oembed_wmode', 1);
function my_oembed_wmode( $embed ) {
if ( strpos( $embed, '<param' ) !== false ) {
$embed = str_replace( '<embed', '<embed wmode="transparent" ', $embed );
$embed = preg_replace( '/param>/', 'param><param name="wmode" value="transparent" />', $embed, 1);
}
return $embed;
}
У меня были проблемы, когда oEmbed Flash-объекты конфликтовали с выпадающими навигационными меню. Этот фильтр решает проблему, добавляя прозрачный window mode для встраиваемых объектов.
Удаление колонки "комментарии" из списка страниц в админке
/***************************************************************
* Функция custom_pages_columns
* Удаляет колонку "комментарии" из списка страниц (редко используются на страницах)
***************************************************************/
add_filter('manage_pages_columns', 'custom_pages_columns');
function custom_pages_columns($defaults) {
unset($defaults['comments']);
return $defaults;
}
Я почти никогда не использую комментарии на страницах, и это помогает поддерживать порядок в админке WordPress.

Включение числовой пагинации
Протестировано на: WordPress 3.0.1
/* Числовая пагинация ********************************************/
function numeric_pagination ($pageCount = 9, $query = null) {
if ($query == null) {
global $wp_query;
$query = $wp_query;
}
if ($query->max_num_pages <= 1) {
return;
}
$pageStart = 1;
$paged = $query->query_vars['paged'];
// Устанавливаем текущую страницу, если на первой странице
if ($paged == null) {
$paged = 1;
}
// Проверяем, если начало страницы находится посередине текущих видимых страниц, и если да, то корректируем
if ($paged > floor($pageCount / 2)) {
$pageStart = $paged - floor($pageCount / 2);
}
if ($pageStart < 1) {
$pageStart = 1;
}
// Убеждаемся, что начало страницы корректно
if ($pageStart + $pageCount > $query->max_num_pages) {
$pageCount = $query->max_num_pages - $pageStart;
}
?>
<div id="archive_pagination">
<?php
if ($paged != 1) {
?>
<a href="<?php echo get_pagenum_link(1); ?>" class="numbered page-number-first"><span>‹ <?php _e('<< Первая', 'global'); ?></span></a>
<?php
}
// первая страница не видна...
if ($pageStart > 1) {
//echo 'предыдущая';
}
for ($p = $pageStart; $p <= $pageStart + $pageCount; $p ++) {
if ($p == $paged) {
?>
<span class="numbered page-number-<?php echo $p; ?> current-numeric-page"><?php echo $p; ?></span>
<?php } else { ?>
<a href="<?php echo get_pagenum_link($p); ?>" class="numbered page-number-<?php echo $p; ?>"><span><?php echo $p; ?></span></a>
<?php
}
}
// последняя страница не видна
if ($pageStart + $pageCount < $query->max_num_pages) {
//echo "последняя";
}
if ($paged != $query->max_num_pages) {
?>
<a href="<?php echo get_pagenum_link($query->max_num_pages); ?>" class="numbered page-number-last"><span><?php _e('Последняя >>', 'global'); ?> ›</span></a>
<?php } ?>
</div>

В WordPress уже есть функция для создания числовой пагинации, см. http://codex.wordpress.org/Function_Reference/paginate_links

Отображение определенного контента только для авторизованных пользователей
Протестировано на: WordPress 3.0.1
function content_only4logged_in($content) {
// ДЛЯ ВСЕХ АВТОРИЗОВАННЫХ ПОЛЬЗОВАТЕЛЕЙ
if ( is_user_logged_in() &&
!is_null($content) &&
!is_feed()
) {
return $content;
} else {
$content = wp_html_excerpt( $content, 80 );
$content .= ' …';
$content .= __( 'Извините, продолжение этого контента доступно только для авторизованных пользователей.', FB_TEXTDOMAIN );
return $content;
}
}
add_action( 'the_content', 'content_only4logged_in' );
дополнительные возможности и информация в посте http://wpengineer.com/2046/control-the-wordpress-content-via-userrights-or-time/

Сделайте ваши короткие ссылки короче, удалив WWW
Протестировано на: Wordpress 3.0.1
Сделайте ваши короткие ссылки короче, если ваш домен содержит www.
. Источник: scratch99.com:
add_filter('get_shortlink','sjc_alter_shortlink');
function sjc_alter_shortlink($shortlink) {
$shortlink = preg_replace('/^(https?:\/\/)?(www\.)/','$1',$shortlink);
return $shortlink;
}

Необходимо добавить проверку, чтобы убедиться, что строка "www." удаляется только если она находится в самом начале доменной части исходного URL. Простое замещение этой строки в любом месте URL приведёт к ошибкам, если она использовалась в домене типа owww.com (который, кстати, похоже, работает на WordPress) :)

Проверить, содержит ли запись встроенный контент
Проверяет, содержит ли запись встроенный контент (например, видео или другой медиа-контент). Работает внутри цикла, используя ID текущей записи, либо можно передать конкретный ID записи для проверки.
function has_embed( $post_id = false ) {
if( !$post_id ) $post_id = get_the_ID();
else $post_id = absint( $post_id );
if( !$post_id ) return false;
$post_meta = get_post_custom_keys( $post_id );
$post_meta = array_map( 'trim' , $post_meta );
foreach( $post_meta as $meta ) {
if( '_oembed' != substr( $meta , 0 , 7 ) )
continue;
return true;
}
return false;
}
Использовать функцию можно так же, как проверку наличия метки у записи..
if( has_embed() ) {
// выполнить действия, если есть встроенный контент
}
Функция возвращает true, если найден встроенный контент, и false в противном случае.

Интересно, но мне любопытно, зачем это использовать? Какие у этого могут быть применения?

Проверка, есть ли в посте встроенный контент на странице с анонсами — это один из вариантов использования (и именно для этого изначально был написан этот код). Другие возможные сценарии — когда пользователи пишут свои шаблоны тем и хотят реализовать функциональность, зависящую от наличия встроенного контента в посте (или типе записи), без необходимости использовать фильтр для the_content
или множество вызовов get_post_custom_keys
.

Отображение записей разных пользовательских типов записей на главной странице
Добавив следующий код в конец файла functions.php, вы можете настроить WordPress для автоматического отображения записей из разных пользовательских типов записей, которые вы создали. По умолчанию WordPress отображает только записи, принадлежащие стандартному типу "posts".
В приведенном ниже примере вам нужно изменить часть, которая вызывает:
$query->set( 'post_type', array('post', 'page', 'services', 'attachment'));
Замените её на свои собственные пользовательские типы записей, которые вы хотите включить в список результатов на главной странице. В данном случае мы просим WordPress возвращать все записи, принадлежащие стандартным типам "post" и "page", а также включаем наш пользовательский тип записей "services" и стандартный тип WordPress "attachment" (что означает, что любой файл, добавленный в медиатеку, автоматически будет отображаться на главной странице как отдельная запись).
// КАСТОМНЫЙ СПИСОК ЗАПИСЕЙ НА ГЛАВНОЙ СТРАНИЦЕ, ВКЛЮЧАЯ РАЗНЫЕ ТИПЫ ЗАПИСЕЙ
// не забудьте отредактировать типы записей, которые вы хотите включить в список ниже
add_filter( 'pre_get_posts', 'my_homepage_post_list' );
function my_homepage_post_list ( $query ) {
if ( is_home() && false == $query->query_vars['suppress_filters'] )
$query->set( 'post_type', array('post', 'page', 'services', 'attachment'));
return $query;
}
Вы также можете использовать этот кастомный запрос в других местах, например, в кастомной RSS-ленте, добавив следующее:
if (( is_home() && false == $query->query_vars['suppress_filters'] ) || is_feed())

Удаление стандартных полей контактной информации в профиле пользователя и замена их на более полезные
Вторая часть этой функции уже упоминалась выше, но удаление стандартных полей - AIM, Yahoo IM и Jabber/Google Talk - еще нет:
function update_contact_methods( $contactmethods ) {
// Удаляем раздражающие и ненужные стандартные поля
unset($contactmethods['aim']);
unset($contactmethods['jabber']);
unset($contactmethods['yim']);
// Добавляем новые поля
$contactmethods['phone'] = 'Телефон';
$contactmethods['mobile'] = 'Мобильный';
$contactmethods['address'] = 'Адрес';
return $contactmethods;
}
add_filter('user_contactmethods', 'update_contact_methods');
Конечно, вы можете добавить столько полей, сколько вам нужно (см. предыдущие примеры в этой теме) в разделе "Добавляем новые поля"
