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

Включение скрытой функции администрирования для отображения всех настроек сайта
Протестировано на: WordPress 3.1 RC3
Этот небольшой фрагмент кода делает довольно интересную вещь. Он добавит дополнительный пункт в меню настроек с ссылкой "Все настройки", которая покажет вам полный список всех настроек, хранящихся в базе данных вашего сайта на WordPress. Приведённый ниже код сделает эту ссылку видимой только для пользователей с правами администратора и скроет её для всех остальных.
// Пользовательская ссылка в меню администрирования для всех настроек
function all_settings_link() {
add_options_page(__('Все настройки'), __('Все настройки'), 'administrator', 'options.php');
}
add_action('admin_menu', 'all_settings_link');

Отлично подходит для разработки! Я часто использую таблицу options для хранения версий БД своих плагинов... Использовать phpMyAdmin для сброса к старой версии БД и тестирования скрипта обновления — это мука... Это сделает процесс намного проще!!!

Изменение логотипа на странице входа и ссылки на него
Проверено на: WordPress 3.0.1
Этот код позволит вам легко изменить логотип на странице входа WordPress, а также ссылку и текст заголовка этого логотипа.
add_filter( 'login_headerurl', 'namespace_login_headerurl' );
/**
* Заменяет URL логотипа на странице входа
*
* @param $url
*/
function namespace_login_headerurl( $url ) {
$url = home_url( '/' );
return $url;
}
add_filter( 'login_headertitle', 'namespace_login_headertitle' );
/**
* Заменяет заголовок логотипа на странице входа
*
* @param $title
*/
function namespace_login_headertitle( $title ) {
$title = get_bloginfo( 'name' );
return $title;
}
add_action( 'login_head', 'namespace_login_style' );
/**
* Заменяет логотип на странице входа
*/
function namespace_login_style() {
echo '<style>.login h1 a { background-image: url( ' . get_template_directory_uri() . '/images/logo.png ) !important; }</style>';
}
РЕДАКТИРОВАНИЕ: Если вы хотите использовать логотип сайта для замены логотипа на странице входа, вы можете использовать следующий код для динамического получения этой информации (проверено на WP3.5):
function namespace_login_style() {
if( function_exists('get_custom_header') ){
$width = get_custom_header()->width;
$height = get_custom_header()->height;
} else {
$width = HEADER_IMAGE_WIDTH;
$height = HEADER_IMAGE_HEIGHT;
}
echo '<style>'.PHP_EOL;
echo '.login h1 a {'.PHP_EOL;
echo ' background-image: url( '; header_image(); echo ' ) !important; '.PHP_EOL;
echo ' width: '.$width.'px !important;'.PHP_EOL;
echo ' height: '.$height.'px !important;'.PHP_EOL;
echo ' background-size: '.$width.'px '.$height.'px !important;'.PHP_EOL;
echo '}'.PHP_EOL;
echo '</style>'.PHP_EOL;
}

Включение пользовательских типов записей в результаты поиска.
// ДОБАВЛЕНИЕ ВОЗМОЖНОСТИ ПОИСКА ПО ПОЛЬЗОВАТЕЛЬСКИМ ТИПАМ ЗАПИСЕЙ
function searchAll( $query ) {
if ( $query->is_search ) { $query->set( 'post_type', array( 'site', 'plugin', 'theme', 'person' )); }
return $query;
}
add_filter( 'the_search_query', 'searchAll' );
Добавление пользовательских типов записей в основную RSS-ленту сайта по умолчанию.
// ДОБАВЛЕНИЕ ПОЛЬЗОВАТЕЛЬСКИХ ТИПОВ ЗАПИСЕЙ В RSS-ЛЕНТУ
function custom_feed_request( $vars ) {
if (isset($vars['feed']) && !isset($vars['post_type']))
$vars['post_type'] = array( 'post', 'site', 'plugin', 'theme', 'person' );
return $vars;
}
add_filter( 'request', 'custom_feed_request' );
Включение пользовательских типов записей в виджет "Прямо сейчас" в админ-панели
Это позволит отображать ваши пользовательские типы записей и количество записей каждого типа в виджете "Прямо сейчас".
// ДОБАВЛЕНИЕ ПОЛЬЗОВАТЕЛЬСКИХ ТИПОВ ЗАПИСЕЙ В ВИДЖЕТ 'ПРЯМО СЕЙЧАС'
function wph_right_now_content_table_end() {
$args = array(
'public' => 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 num b b-' . $post_type->name . '">' . $num . '</td>';
echo '<td class="text 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' );

Относительно последнего фрагмента кода в этом ответе. Это отличное дополнение, так как я добавлял их вручную для каждого типа записи. Единственная проблема, с которой я столкнулся, это то, что данные добавляются после стандартных полей "category" и "tag". Не могли бы вы обновить ваш ответ, чтобы переместить стандартные поля "category" или "tag" ниже или удалить их, чтобы их можно было добавить вручную?

@NetConstructor.com Кажется, я не совсем понимаю ваш запрос. Если я правильно понял, то это будет немного сложнее реализовать, и у меня сейчас нет времени, чтобы разобраться, как это сделать.

Удаление уведомлений об обновлениях для всех пользователей, кроме администратора
Протестировано на: WordPress 3.0.1
Этот код гарантирует, что только пользователь "admin" будет получать уведомления от WordPress о доступных обновлениях.
// УДАЛЕНИЕ УВЕДОМЛЕНИЙ ОБ ОБНОВЛЕНИЯХ WORDPRESS ДЛЯ ВСЕХ ПОЛЬЗОВАТЕЛЕЙ, КРОМЕ АДМИНИСТРАТОРА
global $user_login;
get_currentuserinfo();
if ($user_login !== "admin") { // Замените admin на имя пользователя, который должен получать уведомления
add_action( 'init', create_function( '$a', "remove_action( 'init', 'wp_version_check' );" ), 2 );
add_filter( 'pre_option_update_core', create_function( '$a', "return null;" ) );
}
Измененная версия, которая показывает уведомления только пользователям с правами администратора (а не только пользователю 'admin'):
// УДАЛЕНИЕ УВЕДОМЛЕНИЙ ОБ ОБНОВЛЕНИЯХ WORDPRESS ДЛЯ ВСЕХ ПОЛЬЗОВАТЕЛЕЙ, КРОМЕ АДМИНИСТРАТОРА
global $user_login;
get_currentuserinfo();
if (!current_user_can('update_plugins')) { // Проверяет, может ли текущий пользователь обновлять плагины
add_action( 'init', create_function( '$a', "remove_action( 'init', 'wp_version_check' );" ), 2 );
add_filter( 'pre_option_update_core', create_function( '$a', "return null;" ) );
}

Это далеко не идеальное решение. Оно будет работать только в том случае, если логин администратора по-прежнему стандартный 'admin', что не рекомендуется по соображениям безопасности. Вместо этого следует проверять наличие конкретной capability (прав), которые должны быть у пользователей для просмотра сообщений.

То есть: if (!current_user_can('manage_options')) {...add_filter...} -- Извините за двойной комментарий, я забыл, что нажатие Enter отправляет комментарии)

Именно поэтому я добавил комментарий к коду, где можно изменить имя пользователя администратора. Как бы вы улучшили/переписали этот код?

Лучший способ - убрать global $user_login и get_currentuserinfo() и вместо этого использовать current_user_can в вашем условии if. Это всего 1 строка вместо 3, и это стандартный подход. Вы можете проверить конкретную capability, которая нужна для ДЕЙСТВИЙ с сообщениями, в данном случае это 'update_core' и 'update_plugins'.

Итак: if (!current_user_can('update_plugins')) {/УДАЛИТЬ СООБЩЕНИЯ/}

@Jeremy Clarke так этот код будет правильным способом сделать это? Но если вы хотите разрешить только определенному имени пользователя получать уведомления, будет ли приведенный выше код лучшим вариантом?
if (!current_user_can('update_plugins')) { add_action( 'init', create_function( '$a', "remove_action( 'init', 'wp_version_check' );" ), 2 ); add_filter( 'pre_option_update_core', create_function( '$a', "return null;" )); }

Если вам нужно проверить конкретное имя пользователя, то код из вашего оригинального ответа приемлем, хотя, возможно, есть немного более эффективный способ. Полный код с использованием моего решения будет выглядеть так, как у вас в последнем комментарии. Он такой же, как ваш ответ, но с проверкой current_user_can() вместо $user_login !== 'admin'.

Я отредактировал ответ и добавил версию, использующую current_user_can('update_plugins')

Я только что попробовал код. Но у меня появляется страница с ошибкой при использовании кода. Та же проблема с обоими вариантами кода.

Подключение jQuery из Google CDN
Проверено на: WordPress 3.0.1
// Еще более умное подключение jQuery :)
add_action( 'init', 'jquery_register' );
// Регистрация из Google и для футера
function jquery_register() {
if ( !is_admin() ) {
wp_deregister_script( 'jquery' );
wp_register_script( 'jquery', ( 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js' ), false, null, true );
wp_enqueue_script( 'jquery' );
}
}
Удаление информации о версии WordPress для безопасности
Проверено на: WordPress 3.0.1
// Удаление информации о версии из head и фидов
function complete_version_removal() {
return '';
}
add_filter('the_generator', 'complete_version_removal');
Добавление ссылок "Спам" и "Удалить" к комментариям на фронтенде
Проверено на: WordPress 3.0.1
Это значительно упрощает управление комментариями с фронтенда, добавляя ссылки для пометки как спам и удаления.**
// Ссылки "Спам" и "Удалить" для всех версий WordPress
function delete_comment_link($id) {
if (current_user_can('edit_post')) {
echo '| <a href="'.get_bloginfo('wpurl').'/wp-admin/comment.php?action=cdc&c='.$id.'">удалить</a> ';
echo '| <a href="'.get_bloginfo('wpurl').'/wp-admin/comment.php?action=cdc&dt=spam&c='.$id.'">спам</a>';
}
}
Задержка публикации в RSS-ленте
Проверено на: WordPress 3.0.1
Наконец, мне нравится задерживать публикацию в моих RSS-лентах на 10-15 минут, потому что я всегда нахожу хотя бы пару ошибок в тексте. Другие варианты использования - если вы хотите, чтобы контент был эксклюзивным для вашего сайта в течение дня или недели, прежде чем публиковать его для RSS-читателей.
// Задержка обновления ленты
function publish_later_on_feed($where) {
global $wpdb;
if (is_feed()) {
// Временная метка в формате WordPress
$now = gmdate('Y-m-d H:i:s');
// Значение для задержки; + единица измерения
$wait = '10'; // целое число
// http://dev.mysql.com/doc/refman/5.0/en/date-and-time-functions.html#function_timestampdiff
$device = 'MINUTE'; // MINUTE, HOUR, DAY, WEEK, MONTH, YEAR
// Добавление SQL-синтаксиса к стандартному $where
$where .= " AND TIMESTAMPDIFF($device, $wpdb->posts.post_date_gmt, '$now') > $wait ";
}
return $where;
}
add_filter('posts_where', 'publish_later_on_feed');

источник в моем посте: http://wpengineer.com/320/publish-the-feed-later/ с дополнительной информацией

Вы также можете просто удалить фильтр генератора: remove_action('wp_head', 'wp_generator');

@Derek Perkins - Можешь сделать каждый из этих сниппетов кода отдельным ответом, чтобы за них можно было голосовать независимо?

http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js истекает всего через час. Всегда используйте полную версию, например http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js – она истекает через год.

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

Код "Удаление информации о версии WordPress для безопасности" на самом деле не делает ничего для повышения безопасности вашего сайта. Он даже не предотвращает раскрытие версии WP, используемой на вашем сайте.

Неверно, Джозеф, если версия вашего WordPress раскрыта, люди могут увидеть, используете ли вы устаревшую версию, тем самым подвергая уязвимости. Всегда хорошее решение удалять это из всех установок WordPress. Лично я даже не понимаю, зачем они вообще добавляют эту информацию, так как это ДЕЙСТВИТЕЛЬНО проблема безопасности.

Установите максимальное количество ревизий записей для предотвращения раздувания базы данных.
Протестировано на: WordPress 3.0.1
По умолчанию стоит бесконечное количество, а этот код установит запоминание только последних пяти правок:
/**
* Установка количества ревизий записей, если константа не была задана в wp-config.php
*/
if (!defined('WP_POST_REVISIONS')) define('WP_POST_REVISIONS', 5);
Для справки: на странице Кодекса Редактирование wp-config.php можно найти множество полезных идей по настройке КОНСТАНТ.

Можно ли настроить это для каждого типа записи отдельно?

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

Спасибо, Джереми - Если кто-то еще знает, как это сделать, пожалуйста, напишите здесь.

Инструменты профилирования WordPress
Мне нравится добавлять инструменты профилирования в отдельный файл, который затем подключаю из functions.php по необходимости:
<?php
if ( !defined('SAVEQUERIES') && isset($_GET['debug']) && $_GET['debug'] == 'sql' )
define('SAVEQUERIES', true);
if ( !function_exists('dump') ) :
/**
* dump()
*
* @param mixed $in
* @return mixed $in
**/
function dump($in = null) {
echo '<pre style="margin-left: 0px; margin-right: 0px; padding: 10px; border: solid 1px black; background-color: ghostwhite; color: black; text-align: left;">';
foreach ( func_get_args() as $var ) {
echo "\n";
if ( is_string($var) ) {
echo "$var\n";
} else {
var_dump($var);
}
}
echo '</pre>' . "\n";
return $in;
} # dump()
endif;
/**
* add_stop()
*
* @param mixed $in
* @param string $where
* @return mixed $in
**/
function add_stop($in = null, $where = null) {
global $sem_stops;
global $wp_object_cache;
$queries = get_num_queries();
$milliseconds = timer_stop() * 1000;
$out = "$queries запросов - {$milliseconds}мс";
if ( function_exists('memory_get_usage') ) {
$memory = number_format(memory_get_usage() / ( 1024 * 1024 ), 1);
$out .= " - {$memory}МБ";
}
$out .= " - $wp_object_cache->cache_hits попаданий в кеш / " . ( $wp_object_cache->cache_hits + $wp_object_cache->cache_misses );
if ( $where ) {
$sem_stops[$where] = $out;
} else {
dump($out);
}
return $in;
} # add_stop()
/**
* dump_stops()
*
* @param mixed $in
* @return mixed $in
**/
function dump_stops($in = null) {
if ( $_POST )
return $in;
global $sem_stops;
global $wp_object_cache;
$stops = '';
foreach ( $sem_stops as $where => $stop )
$stops .= "$where: $stop\n";
dump("\n" . trim($stops) . "\n");
if ( defined('SAVEQUERIES') && $_GET['debug'] == 'sql' ) {
global $wpdb;
foreach ( $wpdb->queries as $key => $data ) {
$query = rtrim($data[0]);
$duration = number_format($data[1] * 1000, 1) . 'мс';
$loc = trim($data[2]);
$loc = preg_replace("/(require|include)(_once)?,\s*/ix", '', $loc);
$loc = "\n" . preg_replace("/,\s*/", ",\n", $loc) . "\n";
dump($query, $duration, $loc);
}
}
if ( $_GET['debug'] == 'cache' )
dump($wp_object_cache->cache);
if ( $_GET['debug'] == 'cron' ) {
$crons = get_option('cron');
foreach ( $crons as $time => $_crons ) {
if ( !is_array($_crons) )
continue;
foreach ( $_crons as $event => $_cron ) {
foreach ( $_cron as $details ) {
$date = date('Y-m-d H:m:i', $time);
$schedule = isset($details['schedule']) ? "({$details['schedule']})" : '';
if ( $details['args'] )
dump("$date: $event $schedule", $details['args']);
else
dump("$date: $event $schedule");
}
}
}
}
return $in;
} # dump_stops()
add_action('init', create_function('$in', '
return add_stop($in, "Загрузка");
'), 10000000);
add_action('template_redirect', create_function('$in', '
return add_stop($in, "Запрос");
'), -10000000);
add_action('wp_footer', create_function('$in', '
return add_stop($in, "Отображение");
'), 10000000);
add_action('admin_footer', create_function('$in', '
return add_stop($in, "Отображение");
'), 10000000);
/**
* init_dump()
*
* @return void
**/
function init_dump() {
global $hook_suffix;
if ( !is_admin() || empty($hook_suffix) ) {
add_action('wp_footer', 'dump_stops', 10000000);
add_action('admin_footer', 'dump_stops', 10000000);
} else {
add_action('wp_footer', 'dump_stops', 10000000);
add_action("admin_footer-$hook_suffix", 'dump_stops', 10000000);
}
} # init_dump()
add_action('wp_print_scripts', 'init_dump');
/**
* dump_phpinfo()
*
* @return void
**/
function dump_phpinfo() {
if ( isset($_GET['debug']) && $_GET['debug'] == 'phpinfo' ) {
phpinfo();
die;
}
} # dump_phpinfo()
add_action('init', 'dump_phpinfo');
/**
* dump_http()
*
* @param array $args
* @param string $url
* @return array $args
**/
function dump_http($args, $url) {
dump(preg_replace("|/[0-9a-f]{32}/?$|", '', $url));
return $args;
} # dump_http()
/**
* dump_trace()
*
* @return void
**/
function dump_trace() {
$backtrace = debug_backtrace();
foreach ( $backtrace as $trace )
dump(
'Файл/Строка: ' . $trace['file'] . ', ' . $trace['line'],
'Функция / Класс: ' . $trace['function'] . ', ' . $trace['class']
);
} # dump_trace()
if ( $_GET['debug'] == 'http' )
add_filter('http_request_args', 'dump_http', 0, 2);
?>

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

Вот как это реализовано в моей теме: http://www.semiologic.com/software/sem-reloaded/ — файл /inc/debug.php подключается через /functions.php или /inc/init.php (не могу вспомнить точно).

Улучшение резкости измененных изображений (только JPEG)
Эта функция повышает резкость измененных JPEG изображений. Пример различия:
function ajx_sharpen_resized_files( $resized_file ) {
$image = wp_load_image( $resized_file );
if ( !is_resource( $image ) )
return new WP_Error( 'error_loading_image', $image, $file );
$size = @getimagesize( $resized_file );
if ( !$size )
return new WP_Error('invalid_image', __('Не удалось определить размер изображения'), $file);
list($orig_w, $orig_h, $orig_type) = $size;
switch ( $orig_type ) {
case IMAGETYPE_JPEG:
$matrix = array(
array(-1, -1, -1),
array(-1, 16, -1),
array(-1, -1, -1),
);
$divisor = array_sum(array_map('array_sum', $matrix));
$offset = 0;
imageconvolution($image, $matrix, $divisor, $offset);
imagejpeg($image, $resized_file,apply_filters( 'jpeg_quality', 90, 'edit_image' ));
break;
case IMAGETYPE_PNG:
return $resized_file;
case IMAGETYPE_GIF:
return $resized_file;
}
return $resized_file;
}
add_filter('image_make_intermediate_size', 'ajx_sharpen_resized_files', 900);

если хотите использовать это как плагин: http://wordpress.org/extend/plugins/sharpen-resized-images/

Удаление стандартных метабоксов WordPress
Протестировано на: WordPress 3.0.1
Этот код позволяет удалить определенные метабоксы, которые 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() {
remove_meta_box( 'postcustom','page','normal' ); // Метабокс "Произвольные поля"
remove_meta_box( 'postexcerpt','page','normal' ); // Метабокс "Цитата"
remove_meta_box( 'commentstatusdiv','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');

Согласно этому http://wordpress.stackexchange.com/questions/34030/cant-change-permalink-url-after-hitting-ok-and-update/37779#37779, я бы не скрывал slugdiv таким способом, а использовал бы это https://gist.github.com/1863830 вместо этого

Фильтр для удаления замены "Wordpress" на "WordPress"
Протестировано на: WordPress 3.0.1
Начиная с версии WordPress 3.0 был добавлен фильтр, который автоматически заменяет все вхождения "Wordpress" (с маленькой буквой P) на "WordPress" (с заглавной P) в содержании записей, заголовках записей и тексте комментариев. Некоторые считают это навязчивым, но иногда мне просто нужно использовать неправильное написание WordPress, и этот фильтр оказался несколько раздражающим.
// Удаление раздражающего фильтра для буквы P
if(function_exists('capital_P_dangit')) {
foreach ( array( 'the_content', 'the_title' ) as $filter )
remove_filter( $filter, 'capital_P_dangit', 11 );
remove_filter('comment_text', 'capital_P_dangit', 31 );
}

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

В WordPress 3.0.1 этот фильтр добавляется с приоритетом 11, поэтому вам нужно указать 11
в качестве третьего параметра, чтобы его удалить.

Настройка панели администратора
add_action('wp_dashboard_setup', 'my_custom_dashboard_widgets');
function my_custom_dashboard_widgets() {
global $wp_meta_boxes;
Удаляем эти виджеты панели...
unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_plugins']);
unset($wp_meta_boxes['dashboard']['side']['core']['dashboard_primary']);
unset($wp_meta_boxes['dashboard']['side']['core']['dashboard_secondary']);
Добавляем пользовательский виджет 'Помощь и поддержка'
wp_add_dashboard_widget('custom_help_widget', 'Помощь и поддержка', 'custom_dashboard_help');
}
Содержимое вашего пользовательского виджета
function custom_dashboard_help() {
echo '<p>Lorum ipsum delor sit amet et nunc</p>';
}

Добавление пользовательских полей профиля
Поместите приведённый ниже код в файл functions.php, чтобы добавить пользовательские поля профиля. Редактируйте или добавляйте строки по своему усмотрению.
Не забудьте не удалять строку: return $contactmethods; иначе код не будет работать.
// ПОЛЬЗОВАТЕЛЬСКИЕ ПОЛЯ ПРОФИЛЯ
function my_custom_userfields( $contactmethods ) {
// ДОБАВЛЕНИЕ КОНТАКТНЫХ ПОЛЕЙ
$contactmethods['contact_phone_office'] = 'Рабочий телефон';
$contactmethods['contact_phone_mobile'] = 'Мобильный телефон';
$contactmethods['contact_office_fax'] = 'Рабочий факс';
// ДОБАВЛЕНИЕ ПОЛЕЙ АДРЕСА
$contactmethods['address_line_1'] = 'Адрес (строка 1)';
$contactmethods['address_line_2'] = 'Адрес (строка 2, необязательно)';
$contactmethods['address_city'] = 'Город';
$contactmethods['address_state'] = 'Область';
$contactmethods['address_zipcode'] = 'Почтовый индекс';
return $contactmethods;
}
add_filter('user_contactmethods','my_custom_userfields',10,1);
Для отображения пользовательских полей вы можете использовать один из двух приведённых ниже методов.
Способ 1:
the_author_meta('facebook', $current_author->ID)
Способ 2:
<?php $current_author = get_userdata(get_query_var('author')); ?>
<p><a href="<?php echo esc_url($current_author->contact_phone_office);?>" title="office_phone"> Рабочий телефон</a></p>

Настройка порядка меню в административной панели
Проверено на: WordPress 3.0.1
Этот код позволяет изменить порядок элементов в меню административной панели. Всё, что вам нужно сделать — кликнуть на существующую ссылку в меню админки и скопировать всё, что находится перед URL /wp-admin/. Порядок, указанный ниже, определяет новый порядок элементов в меню администратора.
// НАСТРОЙКА ПОРЯДКА МЕНЮ АДМИНИСТРАТОРА
function custom_menu_order($menu_ord) {
if (!$menu_ord)
return true;
return array(
'index.php', // Ссылка на консоль
'edit.php?post_type=events', // Меню пользовательского типа записей "События"
'edit.php?post_type=news', // Меню пользовательского типа записей "Новости"
'edit.php?post_type=articles',// Меню пользовательского типа записей "Статьи"
'edit.php?post_type=faqs', // Меню пользовательского типа записей "FAQ"
'edit.php?post_type=mentors', // Меню пользовательского типа записей "Наставники"
'edit.php?post_type=testimonials', // Меню пользовательского типа записей "Отзывы"
'edit.php?post_type=services',// Меню пользовательского типа записей "Услуги"
'edit.php?post_type=page', // Стандартное меню для страниц
'edit.php', // Стандартное меню для записей
);
}
add_filter('custom_menu_order', 'custom_menu_order');
add_filter('menu_order', 'custom_menu_order');

Действительно ли существует базовый фильтр с названием custom_menu_order
? Я не смог его найти...

@kaiser задокументировал его здесь http://codex.wordpress.org/Plugin_API/Filter_Reference/custom_menu_order

Функция для изменения длины анонса
Протестировано на: Wordpress 3.0.1
По умолчанию все анонсы ограничены 55 словами. Используя приведенный ниже код, вы можете переопределить эти настройки по умолчанию:
function new_excerpt_length($length) {
return 100;
}
add_filter('excerpt_length', 'new_excerpt_length');
Этот пример изменяет длину анонса до 100 слов, но вы можете использовать тот же метод, чтобы изменить его на любое значение.

@user402... это ограничение по словам или символам? Не могли бы вы показать, как сделать и то, и другое?

@NetConstructor.com Эта функция (и хук excerpt_length
) ограничивают по словам.

Добавление миниатюр в списке записей/страниц
Вы можете добавить этот код в functions.php, чтобы в списке записей и страниц появилась новая колонка с превью миниатюр.
/****** Добавление миниатюр в списке записей/страниц ******/
if ( !function_exists('AddThumbColumn') && function_exists('add_theme_support') ) {
// для записей и страниц
add_theme_support('post-thumbnails', array( 'post', 'page' ) );
function AddThumbColumn($cols) {
$cols['thumbnail'] = __('Миниатюра');
return $cols;
}
function AddThumbValue($column_name, $post_id) {
$width = (int) 35;
$height = (int) 35;
if ( 'thumbnail' == $column_name ) {
// миниатюра в WP 2.9+
$thumbnail_id = get_post_meta( $post_id, '_thumbnail_id', true );
// изображения из галереи
$attachments = get_children( array('post_parent' => $post_id, 'post_type' => 'attachment', 'post_mime_type' => 'image') );
if ($thumbnail_id)
$thumb = wp_get_attachment_image( $thumbnail_id, array($width, $height), true );
elseif ($attachments) {
foreach ( $attachments as $attachment_id => $attachment ) {
$thumb = wp_get_attachment_image( $attachment_id, array($width, $height), true );
}
}
if ( isset($thumb) && $thumb ) {
echo $thumb;
} else {
echo __('Нет');
}
}
}
// для записей
add_filter( 'manage_posts_columns', 'AddThumbColumn' );
add_action( 'manage_posts_custom_column', 'AddThumbValue', 10, 2 );
// для страниц
add_filter( 'manage_pages_columns', 'AddThumbColumn' );
add_action( 'manage_pages_custom_column', 'AddThumbValue', 10, 2 );
}

Отключение пингов на свой же блог
Проверено на: WordPress 3.0.1
// Удаление пингов на собственный блог
function no_self_ping( &$links ) {
$home = get_option( 'home' ); // Получаем URL домашней страницы
foreach ( $links as $l => $link )
if ( 0 === strpos( $link, $home ) ) // Если ссылка ведет на текущий сайт
unset($links[$l]); // Удаляем ее из списка
}
add_action( 'pre_ping', 'no_self_ping' ); // Подключаем функцию к хуку

У меня довольно часто возникает эта проблема. Если я ссылаюсь на другую запись в своем блоге на WordPress, я получаю трекбэк или пингбэк (не помню точно какой) от самого себя. Это раздражает.

Включение сжатия вывода GZIP
Обычно сервер должен быть настроен для автоматического выполнения этого, но многие shared-хостинги этого не делают (вероятно, чтобы увеличить потребление трафика клиентами).
if(extension_loaded("zlib") && (ini_get("output_handler") != "ob_gzhandler"))
add_action('wp', create_function('', '@ob_end_clean();@ini_set("zlib.output_compression", 1);'));

Отображение запросов к БД, затраченного времени и потребления памяти
Протестировано на: WordPress 3.0.1
function performance( $visible = false ) {
$stat = sprintf( '%d запросов за %.3f секунд, использовано %.2fMB памяти',
get_num_queries(),
timer_stop( 0, 3 ),
memory_get_peak_usage() / 1024 / 1024
);
echo $visible ? $stat : "<!-- {$stat} -->" ;
}
Затем добавьте этот код ниже приведенного выше, который автоматически вставит код выше в подвал вашего публичного сайта (убедитесь, что ваша тема вызывает wp_footer
):
add_action( 'wp_footer', 'performance', 20 );
Функцию можно вызывать несколько раз.

Автоматическое извлечение первого изображения из содержимого записи
Проверено на: WordPress 3.0.1
Этот код автоматически извлекает первое изображение, связанное с записью, и позволяет отображать/использовать его при вызове функции getImage.
// АВТОМАТИЧЕСКИ ИЗВЛЕКАЕМ ПЕРВОЕ ИЗОБРАЖЕНИЕ ИЗ ЗАПИСИ
function getImage($num) {
global $more;
$more = 1;
$link = get_permalink();
$content = get_the_content();
$count = substr_count($content, '<img');
$start = 0;
for($i=1;$i<=$count;$i++) {
$imgBeg = strpos($content, '<img', $start);
$post = substr($content, $imgBeg);
$imgEnd = strpos($post, '>');
$postOutput = substr($post, 0, $imgEnd+1);
$postOutput = preg_replace('/width="([0-9]*)" height="([0-9]*)"/', '',$postOutput);;
$image[$i] = $postOutput;
$start=$imgEnd+1;
}
if(stristr($image[$num],'<img')) {
echo '<a href="'.$link.'">'.$image[$num]."</a>";
}
$more = 0;
}

Отлично, но get_the_image тоже отлично справляется с этим. http://wordpress.org/extend/plugins/get-the-image/

Верно, но этот плагин работает иначе и исправляет различные проблемы, которые get_the_image не учитывает

@matt -- В WordPress есть несколько способов добавления изображений к записям, и я думаю, что скрипт get_the_image проверяет только один из них. Этот код сначала проверяет, есть ли у записи featured image (избранное изображение), и если оно есть, использует его. Затем, если избранного изображения нет, он ищет первое изображение, добавленное в контент записи. Если и его нет, то проверяется медиабиблиотека на предмет изображения с наивысшим порядковым номером (по крайней мере, я помню, что порядок был именно таким).

Я предлагаю http://wordpress.org/extend/plugins/auto-post-thumbnail/ Автоматически генерировать Post Thumbnail (Featured Thumbnail) из первого изображения в записи или любом типе пользовательской записи, только если Post Thumbnail не установлен

Отключение стандартных виджетов WordPress
Проверено на: WordPress 3.0.1
// Отключаем все стандартные виджеты WordPress
function unregister_default_wp_widgets() {
unregister_widget('WP_Widget_Pages'); // Виджет страниц
unregister_widget('WP_Widget_Calendar'); // Виджет календаря
unregister_widget('WP_Widget_Archives'); // Виджет архивов
unregister_widget('WP_Widget_Links'); // Виджет ссылок
unregister_widget('WP_Widget_Meta'); // Виджет мета-информации
unregister_widget('WP_Widget_Search'); // Виджет поиска
unregister_widget('WP_Widget_Text'); // Текстовый виджет
unregister_widget('WP_Widget_Categories'); // Виджет категорий
unregister_widget('WP_Widget_Recent_Posts'); // Виджет последних записей
unregister_widget('WP_Widget_Recent_Comments');// Виджет последних комментариев
unregister_widget('WP_Widget_RSS'); // Виджет RSS
unregister_widget('WP_Widget_Tag_Cloud'); // Виджет облака тегов
}
add_action('widgets_init', 'unregister_default_wp_widgets', 1);

Вывод файла шаблона темы, используемого для записи/страницы, в заголовке
add_action('wp_head', 'show_template');
function show_template() {
global $template;
print_r($template);
}
Сокращение стандартного вывода DIV, если ваша тема использует post_class.
Если ваша тема использует что-то вроде:
<div id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
В исходном коде могут появиться очень длинные div, которые могут выглядеть так или даже длиннее:
<div id="post-4" class="post-4 post type-post hentry category-uncategorized category-test category-test-1-billion category-test2 category-test3 category-testing">
Это может действительно загромождать ваш исходный код и в большинстве случаев выглядит излишним, обычно достаточно 3-4 категорий.
Для первого примера мы можем ограничить вывод следующим образом:
// Сокращение слишком длинных выводов div
function category_id_class($classes) {
global $post;
foreach((get_the_category($post->ID)) as $category)
$classes[] = $category->category_nicename;
return array_slice($classes, 0,5);
}
add_filter('post_class', 'category_id_class');
Это ограничивает вывод только первыми 5 значениями, так что приведенный выше пример становится:
<div id="post-4" class="post-4 post type-post hentry category-uncategorized">
Отображение всех записей в архивах категорий, независимо от типа записи: полезно для пользовательских типов записей
function any_ptype_on_cat($request) {
if ( isset($request['category_name']) )
$request['post_type'] = 'any';
return $request;
}
add_filter('request', 'any_ptype_on_cat');
Удаление ненужных элементов панели управления
Это уже было опубликовано, но не включало полный список элементов. Особенно этих раздражающих "входящих ссылок!"
add_action('wp_dashboard_setup', 'my_custom_dashboard_widgets');
function my_custom_dashboard_widgets() {
global $wp_meta_boxes;
// Обзор - комментарии, записи, страницы
unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_right_now']);
// Последние комментарии
unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_recent_comments']);
// Входящие ссылки
unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_incoming_links']);
// Плагины - популярные, новые и недавно обновленные
unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_plugins']);
// Лента блога разработчиков WordPress
unset($wp_meta_boxes['dashboard']['side']['core']['dashboard_primary']);
// Другие новости WordPress
unset($wp_meta_boxes['dashboard']['side']['core']['dashboard_secondary']);
// Быстрая публикация
unset($wp_meta_boxes['dashboard']['side']['core']['dashboard_quick_press']);
// Последние черновики
unset($wp_meta_boxes['dashboard']['side']['core']['dashboard_recent_drafts']);
}
Удаление "прыжков" при клике на "Читать далее"
Вместо этого страница просто загружается с самого верха. Вы знаете, как при клике на "читать далее" страница прыгает к определенному месту, что может быть раздражающим. Этот код загружает страницу нормально, без прыжков!
function remove_more_jump_link($link) {
$offset = strpos($link, '#more-');
if ($offset) {
$end = strpos($link, '"', $offset);
}
if ($end) {
$link = substr_replace($link, '', $offset, $end-$offset);
}
return $link;
}
add_filter('the_content_more_link', 'remove_more_jump_link');
Ограничение пунктов меню АДМИНКИ в зависимости от имени пользователя, замените username на реальное имя пользователя.
function remove_menus()
{
global $menu;
global $current_user;
get_currentuserinfo();
if($current_user->user_login == 'username')
{
$restricted = array(__('Записи'),
__('Медиафайлы'),
__('Ссылки'),
__('Страницы'),
__('Комментарии'),
__('Внешний вид'),
__('Плагины'),
__('Пользователи'),
__('Инструменты'),
__('Настройки')
);
end ($menu);
while (prev($menu)) {
$value = explode(' ',$menu[key($menu)][0]);
if(in_array($value[0] != NULL ? $value[0] : "" , $restricted)) {
unset($menu[key($menu)]);
}
} // end while
} // end if
}
add_action('admin_menu', 'remove_menus');
//альтернативно можно использовать if($current_user->user_login != 'admin'), что, вероятно, более полезно
Стилизация облака тегов
// Настройка облака тегов
add_filter('widget_tag_cloud_args', 'style_tags');
function style_tags($args) {
$args = array(
'largest' => '10',
'smallest' => '10',
'format' => 'list',
);
return $args;
}
Полный список параметров доступен здесь (их много!) http://codex.wordpress.org/Function_Reference/wp_tag_cloud
Изменение интервала обновления виджета RSS по умолчанию
(По умолчанию 6 или 12 часов - я забыл (1800 = 30 минут).
add_filter( 'wp_feed_cache_transient_lifetime', create_function('$fixrss', 'return 1800;') );

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

Я только что использовал код "Ограничение пунктов меню АДМИНИСТРАТОРА на основе имени пользователя, замените имя пользователя на реальное имя пользователя", который отлично работает, но не могли бы вы обновить код, чтобы также показать, как это можно сделать для конкретной "роли пользователя". Я думаю, это было бы очень полезно!

Извините, NetConstructor, я только что увидел ваш комментарий. Для роли пользователя я бы использовал "current_user_can". У меня нет времени проверить это сейчас, но когда у меня будет возможность, я добавлю это.

Удалить уведомление об обновлении ТОЛЬКО для НЕАКТИВНЫХ плагинов
function update_active_plugins($value = '') {
/*
Массив $value содержит список плагинов с отметками времени,
когда последний раз проверялось соответствие версий.
Узел $value->response содержит массив элементов, которые
устарели. Этот узел response используется, например, в меню 'Плагины'
для указания наличия обновлений. Также на странице списка плагинов
для отображения желтого блока под плагином, указывающего на необходимость
действий со стороны пользователя.
*/
if ((isset($value->response)) && (count($value->response))) {
// Получаем список активных плагинов
$active_plugins = get_option('active_plugins');
if ($active_plugins) {
// Здесь мы начинаем сравнивать элементы $value->response
// с списком активных плагинов.
foreach($value->response as $plugin_idx => $plugin_item) {
// Если элемент response не является активным плагином, удаляем его.
// Это предотвратит отображение WordPress уведомлений о необходимости обновления.
if (!in_array($plugin_idx, $active_plugins))
unset($value->response[$plugin_idx]);
}
}
else {
// Если нет активных плагинов, игнорируем неактивные устаревшие.
foreach($value->response as $plugin_idx => $plugin_item) {
unset($value->response);
}
}
}
return $value;
}
add_filter('transient_update_plugins', 'update_active_plugins'); // Хук для версии 2.8.+
//add_filter( 'option_update_plugins', 'update_active_plugins'); // Хук для версии 2.7.x

Удаление избыточной информации и HTML внутри тега <head>
// удаление ненужной информации в заголовке
add_action( 'init', 'remove_header_info' );
function remove_header_info() {
remove_action( 'wp_head', 'rsd_link' ); // RSD (Really Simple Discovery) ссылка
remove_action( 'wp_head', 'wlwmanifest_link' ); // Ссылка на манифест Windows Live Writer
remove_action( 'wp_head', 'wp_generator' ); // Мета-тег с версией WordPress
remove_action( 'wp_head', 'start_post_rel_link' ); // Ссылка на первую запись
remove_action( 'wp_head', 'index_rel_link' ); // Ссылка на индексную страницу
remove_action( 'wp_head', 'adjacent_posts_rel_link' ); // для WordPress < 3.0 (ссылки на соседние записи)
remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head' ); // для WordPress >= 3.0 (ссылки на соседние записи)
}
// удаление дополнительного CSS, который добавляет виджет "Последние комментарии"
add_action( 'widgets_init', 'remove_recent_comments_style' );
function remove_recent_comments_style() {
global $wp_widget_factory;
remove_action( 'wp_head', array(
$wp_widget_factory->widgets['WP_Widget_Recent_Comments'],
'recent_comments_style'
) );
}

Включение отладки ошибок и логирования для использования на рабочих сайтах
Это фрагмент кода, который я написал для использования констант WP_DEBUG, обычно отключенных по умолчанию. Я создал способ не только включить WP_DEBUG для использования на рабочем сайте без негативных последствий, но и задействовал другие константы отладки для принудительного отображения ошибок и создания лог-файла ошибок и уведомлений в директории /wp-content.
Поместите этот код в ваш файл wp-config.php (ПРЕДВАРИТЕЛЬНО СОХРАНИВ РЕЗЕРВНУЮ КОПИЮ НА ВСЯКИЙ СЛУЧАЙ), затем вы можете добавлять параметры ?debug=1, 2 или 3 в конце любого URL на вашем сайте.
?debug=1 = показывает все ошибки/уведомления ?debug=2 = принудительно отображает их ?debug=3 = создает файл debug.log со всеми ошибками в директории /wp-content.
/**
* Написано Джаредом Уильямсом - http://new2wp.com
* @wp-config.php замените константу WP_DEBUG этим кодом
* Включение WP отладки для использования на рабочем сайте
* http://core.trac.wordpress.org/browser/trunk/wp-includes/load.php#L230
* Добавляйте параметр '?debug=#' в конце любого URL на сайте
*
* http://example.com/?debug=1, /?debug=2, /?debug=3
*/
if ( isset($_GET['debug']) && $_GET['debug'] == '1' ) {
// Включение отображения уведомлений во время разработки - E_ALL
define('WP_DEBUG', true);
} elseif ( isset($_GET['debug']) && $_GET['debug'] == '2' ) {
// Должно быть true для работы WP_DEBUG_DISPLAY
define('WP_DEBUG', true);
// Принудительное отображение ошибок
define('WP_DEBUG_DISPLAY', true);
} elseif ( isset($_GET['debug']) && $_GET['debug'] == '3' ) {
// Должно быть true для работы WP_DEBUG_LOG
define('WP_DEBUG', true);
// Логирование ошибок в файл debug.log в директории wp-content
define('WP_DEBUG_LOG', true);
}
Я подробнее рассказываю об этом в гостевом посте для Comluv, если вам интересно: http://comluv.com/dev/enable-debugging-and-logging-for-live-site-usage/
Я все еще работаю над способом защиты этого функционала паролем или, предпочтительно, над реализацией проверки if (current_user_can('manage_themes') и is_logged_in().
Но это уже значительно сложнее.

Автоматическое добавление динамических заголовков для публичных страниц
Протестировано на: WordPress 3.0.1
Использование приведённого ниже кода позволит автоматически создавать динамические заголовки страниц на основе просматриваемых публично страниц/записей.
/* Динамические заголовки **/
// Устанавливает <title> в зависимости от текущей страницы для лучшего форматирования и SEO
// В начале функции необходимо задать переменную $longd с пользовательским текстом
function dynamictitles() {
$longd = __('Введите здесь длинное описание.', 'texdomainstring');
if ( is_single() ) {
wp_title('');
echo ' | '.get_bloginfo('name');
} else if ( is_page() || is_paged() ) {
bloginfo('name');
wp_title('|');
} else if ( is_author() ) {
bloginfo('name');
wp_title(' | '.__('Автор', 'texdomainstring'));
} else if ( is_category() ) {
bloginfo('name');
wp_title(' | '.__('Архив для', 'texdomainstring'));
} else if ( is_tag() ) {
echo get_bloginfo('name').' | '.__('Архив метки', 'texdomainstring');
wp_title('');
} else if ( is_archive() ) {
echo get_bloginfo('name').' | '.__('Архив для', 'texdomainstring');
wp_title('');
} else if ( is_search() ) {
echo get_bloginfo('name').' | '.__('Результаты поиска', 'texdomainstring');
} else if ( is_404() ) {
echo get_bloginfo('name').' | '.__('Ошибка 404 (Страница не найдена)', 'texdomainstring');
} else if ( is_home() ) {
echo get_bloginfo('name').' | '.get_bloginfo('description');
} else {
echo get_bloginfo('name').' | '.($blog_longd);
}
}

Новые роли и возможности — выполняйте только один раз!
Я держу эти штуки под рукой, это правильный способ сделать их без плагина. Они устанавливают одно поле (prefix_user_roles) в базе данных опций, и вам не нужен плагин для их настройки. Обратитесь к странице Codex для получения списка доступных возможностей и их описаний. Вам нужно только раскомментировать один из этих блоков, загрузить любую страницу, а затем снова закомментировать их! Здесь я создаю роль с нужными мне возможностями:
/* Возможности */
// Чтобы добавить новую роль, используя 'international' как короткое имя и
// 'International Blogger' как отображаемое имя в списке пользователей и на странице редактирования:
/*
add_role('international', 'International Blogger', array(
'read' => true, // True разрешает эту возможность, False явно отнимает её.
'edit_posts' => true,
'delete_posts' => true,
'edit_published_posts' => true,
'publish_posts' => true,
'edit_files' => true,
'import' => true,
'upload_files' => true //последний элемент массива не требует запятой!
));
*/
// Чтобы полностью удалить роль или одну из стандартных:
/*
remove_role('international');
*/
Иногда удобнее добавлять/удалять возможности из существующей роли, чем удалять и добавлять роль заново. Опять же, вам нужно только раскомментировать, перезагрузить страницу, а затем снова закомментировать. Это правильно сохранит роль/возможность в таблице опций. (Это позволяет вам, разработчику, контролировать их и убирает накладные расходы громоздких плагинов, делающих то же самое.) Здесь я изменяю роль автора, чтобы он мог удалять свои опубликованные записи (по умолчанию), но даю ему возможность редактировать свои опубликованные записи (что по умолчанию для этой роли невозможно) — используя *add_cap* или *remove_cap*.
/*
$edit_role = get_role('author');
$edit_role->add_cap('edit_published_posts');
$edit_role->remove_cap('delete_published_posts');
*/
Я веду таблицу с сеткой возможностей со страницы Codex для сайтов, которые изменяются таким образом, чтобы помнить, как всё настроено, хотя оставление закомментированного кода в файле functions.php тоже сработает. Не оставляйте эти примеры раскомментированными, иначе запись в базу данных будет происходить при каждой загрузке страницы!

Функции, которые я упомянул выше, записывают данные в поле базы данных options. Комментирование и раскомментирование - правильный подход. Существуют плагины для управления ролями пользователей, но если вы используете упомянутые выше функции, вы не можете оставлять эти функции активными, и вам НЕ нужно настраивать их более одного раза или настраивать их в зависимости от того, обращается ли к чему-то конкретный пользователь. Если вам нужно такое поведение, назначьте этому пользователю конкретную, уникальную роль. И обратитесь к codex - всё, что я написал выше, на 100% правильно, если вы делаете это без плагина.
Почти в каждом случае вам нужно настроить роли пользователей только один раз.

@tomcat23: Для наглядности я обернул это в функцию, которая добавляет роль только если она ещё не существует. Ещё одно замечание: думаю, было бы проще разместить роль где-то в иерархии ролей, получая права доступа из какой-либо встроенной роли, а затем добавляя/удаляя возможности из встроенной роли. Это сделало бы более понятным и легким для запоминания, если её права находятся где-то между, например, администратором и редактором. - Надеюсь, вы не возражаете, что я отредактировал ваш ответ. Если возражаете, пожалуйста, откатите изменения. :)

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

Мало того, ваша функция не делает то же самое, что мой код. Ваша функция оставляет лишнюю проверку get_role('international', которая вообще не нужна! Я использовал этот код для клиента, у которого был сервер на php4 и поэтому он не мог использовать плагин role scoper, который работал только на php5 (и это был единственный плагин, требовавший php5 в их установке). Как разработчик, я увидел, что единственная причина, по которой он им был нужен — это настройка нескольких ролей и изменение некоторых возможностей. И этот код, мой оригинальный ответ здесь, показывает, как это сделать правильно!

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

Для дальнейшего уточнения: вам не нужно оборачивать это в функцию или добавлять проверки админки. add_role(), remove_role(), add_cap() и remove_cap(), как показано в моём оригинальном ответе, не нужно выполнять снова и снова — они просто устанавливают поле в таблице options, которое не нужно перезаписывать постоянно, поэтому ваша обёртка в виде функции ошибочна. Я знаю, вы добавляете действие к after_setup_theme, но установка роли через этот хук не была целью моего ответа. (И вообще, роли обычно не должны поставляться вместе с темами.)

Фух... Как я писал: "Надеюсь, вы не против, что я отредактировал ваш ответ. Если против — пожалуйста, откатите изменения. :)". Вы откатили, объяснили причину, и знаете что? Это нормально. Так что успокойтесь. Но чтобы предложить вам такое же количество объяснений: я всегда оборачиваю код в функции и добавляю его в папку тестовых файлов своей темы. Таким образом, я могу легко тестировать вещи, например, ответы на WA, и быстро добавлять их, если что-то понадобится, так что оборачивание в функцию — это нормально. Кроме того, так проще отключить (только вызов add_action) и разрешить док-комментарии с /**/ вместо многострочных // комментариев. Вот так насчет моего "почему".

@tomcat23 - Обратите внимание, что мы — сообщество, которое поддерживает друг друга, а не бросает вызовы, за исключением академических дискуссий. Как видно из ответа @kaiser, он просто пытался помочь.

@MikeSchinkel Я помню два комментария от @kaiser 1 февраля, поэтому тогда ответил так, как ответил. (Вы модератор, можете проверить, были ли они? Потому что я не думаю, что ошибаюсь, полагая, что он оставил 2 комментария о том, что мой подход ему не нравится.) Я не чувствовал, что мой код или объяснение нуждаются в помощи, и сказал ему об этом 1 февраля. Возвращаюсь спустя время и вижу, что он изменил мой код — мое первое знакомство с "вики"-аспектом этого сайта — и я, по моему мнению, был справедливо раздражен тем, что, пока мой текст и комментарии обсуждают одно, сам код был другим.

Мой ответ соответствует духу исходного вопроса. Это мой полезный код, он хорошо работает для меня, и я не использую его обернутым в функцию. Если бы @kaiser хотел ответить на этот вопрос с кодом, обернутым в функцию и прикрепленным к хуку, он все еще может это сделать.
Еще раз, @kaiser, то, что ты сделал, изменив мой код, но не текст, было вредным для других людей, которые придут сюда, увидят это и обнаружат, что мое обсуждение кода не имеет смысла. Вот почему я считаю, что твой поступок был грубым, и почему я вчера так резко ответил.

@tomcat23 - Уже вода утекла. Все, что я хочу сказать, это то, что я не заинтересован в поиске виноватых, а просто хочу мира для всех в будущем. :)

@MikeSchinkel Да, ты прав.
@kaiser Приношу извинения, если оскорбил тебя.

Пользовательский футер в админке WordPress
// Настройка текста в футере админки
function custom_admin_footer() {
echo 'Добавьте свой пользовательский текст и HTML код для футера здесь';
}
add_filter('admin_footer_text', 'custom_admin_footer');
Я использую это на клиентских сайтах как простую ссылку для связи со мной как разработчиком.

Функция для отключения RSS-лент
Протестировано на: Wordpress 3.0.1
Если вы хотите сделать ваш сайт на WordPress полностью статичным, вы можете отключить RSS-ленты.
Для этого используйте следующую функцию:
function fb_disable_feed() {
wp_die( __('Лента недоступна, пожалуйста, посетите наш <a href="'. get_bloginfo('url') .'">главную страницу</a>!') );
}
add_action('do_feed', 'fb_disable_feed', 1);
add_action('do_feed_rdf', 'fb_disable_feed', 1);
add_action('do_feed_rss', 'fb_disable_feed', 1);
add_action('do_feed_rss2', 'fb_disable_feed', 1);
add_action('do_feed_atom', 'fb_disable_feed', 1);

Источник: http://bueltge.de/wordpress-feeds-deaktivieren/794/ (Frank Bueltge)

Спасибо, Toscho! источник также доступен на английском http://wpengineer.com/287/disable-wordpress-feed/

Изменение сообщения "Howdy" на "Welcome"
С помощью этой функции вы можете настроить сообщение "Howdy" в верхнем правом углу административной панели.
Данная функция использует jQuery для замены сообщения "Howdy" на "Welcome".
/****** Настройка административного сообщения "Howdy" на "Welcome" ******/
$nohowdy = "Welcome";
if (is_admin()) {
add_action('init', 'artdev_nohowdy_h');
add_action('admin_footer', 'artdev_nohowdy_f');
}
// Подгрузка jQuery
function artdev_nohowdy_h() {
wp_enqueue_script('jquery');
}
// Модификация
function artdev_nohowdy_f() {
global $nohowdy;
echo <<<JS
<script type="text/javascript">
//<![CDATA[
var nohowdy = "$nohowdy";
jQuery('#user_info p')
.html(
jQuery('#user_info p')
.html()
.replace(/Howdy/,nohowdy)
);
//]]>
JS;
}
Версия на PHP с использованием фильтра gettext
:
add_filter('gettext', 'change_howdy', 10, 3);
function change_howdy($translated, $text, $domain) {
if (!is_admin() || 'default' != $domain)
return $translated;
if (false !== strpos($translated, 'Howdy'))
return str_replace('Howdy', 'Welcome', $translated);
return $translated;
}

Нельзя ли это уже отредактировать на стороне PHP, чтобы это вообще не выводилось?
