Лучшая подборка кода для вашего файла 'functions.php'

9 сент. 2010 г., 11:29:00
Просмотры: 169K
Голосов: 346

Как и многие другие, кто сейчас читает этот пост, я изучал различные блоги, форумы и дискуссионные группы, чтобы улучшить свои навыки работы с WordPress. В течение последних 12 месяцев я поставил себе цель заменить использование плагинов добавлением кода непосредственно в файл functions.php.

Хотя я полностью согласен, что плагины очень полезны во многих ситуациях, мой опыт показал, что в 90% случаев использования, даже если плагин существует, его применение может создать ненужные сложности и проблемы совместимости. Кроме того, во многих случаях такие плагины добавляли меню и другие элементы администрирования, которые мне не нужны.

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

Итак, цель этого поста - попытаться привлечь вас, читателей/администраторов/разработчиков, поделиться со мной и другими любыми полезными фрагментами кода, которые вы добавили в файл functions.php вашей темы для расширения или улучшения WordPress без использования плагинов.

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

Я с нетерпением жду всех ваших ответов и, конечно же, буду постоянно добавлять свои новые находки, когда буду их обнаруживать.

Пожалуйста, голосуйте за вопрос и любые ответы, которые вы считаете полезными, нажимая на стрелку вверх слева от вопроса или ответа.

25
Комментарии

Пожалуйста, добавьте также ваши старые, уже существующие находки.

hakre hakre
9 сент. 2010 г. 11:38:16

Привет @NetConstructor: Я обеспокоен этим вопросом, потому что это вопрос типа "Список X", о котором предупреждали представители StackExchange: http://meta.stackexchange.com/questions/57226/should-we-have-a-list-of-x-close-reason Моя главная проблема в том, что когда я думаю о вашем вопросе, я представляю себе почти бесконечное количество ответов, и поэтому я беспокоюсь, что этот вопрос приведёт к сбору случайных ответов, но ничего определённого. Я хочу узнать мнение других, прежде чем (голосовать за) закрытие, так как не хочу быть излишне строгим, просто у меня есть опасения.

MikeSchinkel MikeSchinkel
9 сент. 2010 г. 14:00:40

Мой голос — либо закрыть, либо сделать вики-сообществом

Chris_O Chris_O
9 сент. 2010 г. 15:37:41

Учитывая, что первые 5 ответов были от автора вопроса, и сам вопрос скорее направлен на сбор различных ответов, а не на получение единственного правильного решения, это должно быть сообществом вики.

EAMann EAMann
9 сент. 2010 г. 17:43:16

похоже, что нельзя просто изменить вопрос в вики. Это действительно так?

NetConstructor.com NetConstructor.com
9 сент. 2010 г. 18:31:53

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

Lemon Bacon Lemon Bacon
10 сент. 2010 г. 02:58:46

@NetConstructor.com ... Я преобразовал вопрос в вики, когда писал последний комментарий. Извините, если это вызвало путаницу. Обычно вы (как автор вопроса) можете превратить вопрос в вики в любое время.

EAMann EAMann
10 сент. 2010 г. 03:56:15

@EAMann спасибо... Я искал эту опцию, но не был уверен, где она находится. Возможно, после того как вы преобразовали вопрос, я просто перестал видеть эту опцию?

NetConstructor.com NetConstructor.com
10 сент. 2010 г. 08:37:41

@NetConstructor.com - Точно. Как только вопрос преобразован, он остается вики... опция применяется и исчезает со страницы.

EAMann EAMann
10 сент. 2010 г. 17:23:26

Я считаю это плохим стилем и предпочитаю плагины. а) Они созданы профессиональными разработчиками б) они поддерживаются и легко обновляются. Для небольших кастомных сниппетов я рекомендую плагин Shortcode Exec PHP, который предоставляет очень чистый -- и переносимый -- способ кастомизировать ваш Wordpress.

Raphael Raphael
10 нояб. 2010 г. 11:43:21

хоть и интересно, я считаю что большинство согласится, что при разработке тем лучше держать вещи локализованными в файле functions.php

NetConstructor.com NetConstructor.com
24 нояб. 2010 г. 19:01:50

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

t31os t31os
28 янв. 2011 г. 18:53:26

@t31os — Я отредактировал его, чтобы сохранить единообразие со всеми записями

NetConstructor.com NetConstructor.com
7 февр. 2011 г. 15:53:20

Все ответы, не относящиеся к теме, должны быть удалены. Эта ветка — хороший пример плохих практик программирования.

fuxia fuxia
13 июн. 2011 г. 15:09:56

Я должен не согласиться. Вопрос не был связан с темой. Все соответствующие модификации functions.php приветствуются, и пользователи должны голосовать за/против соответственно.

NetConstructor.com NetConstructor.com
14 июн. 2011 г. 07:56:23

Интересно, что нигде не указано, что файл functions.php находится в директории вашей темы, что приводит к путанице, например: http://wordpress.stackexchange.com/questions/25341/error-after-editing-functions-php

scribu scribu
9 авг. 2011 г. 03:07:10

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

Ian Dunn Ian Dunn
16 янв. 2012 г. 20:49:10

@rarst - Относительно вашего комментария о закрытии этой темы, разве не поэтому она указана в вики сообщества?

User User
19 февр. 2012 г. 15:35:19

@Cor van Noorloos использование статуса сообщества wiki было значительно сокращено и не поощряется сетью. Проще говоря, отговорка "это не очень подходит для вопросов и ответов, но это же wiki сообщества!" больше не работает. Ответы здесь превратились в неупорядоченную и плохо поддерживаемую массу, посещаемую только из-за фактора "вау"/развлечения. По всей сети было много движений, чтобы закрыть подобные вопросы.

Rarst Rarst
19 февр. 2012 г. 15:43:03

@rarst - Понятно. Принял к сведению.

User User
19 февр. 2012 г. 15:55:04

Что касается закрытия этой конкретной "wiki", я голосую за её повторное открытие. Очевидно, что этот wiki-пост чрезвычайно популярен, о чём свидетельствует 30 000 просмотров — это в три раза больше, чем у ЛЮБОГО другого вопроса или wiki на этом сайте, а сама тема получила 119 голосов "за", что вдвое больше, чем у любого другого вопроса или темы. Если вы согласны с её ценностью, пожалуйста, проголосуйте за повторное открытие, нажав на ссылку "reopen".

NetConstructor.com NetConstructor.com
20 февр. 2012 г. 13:12:40

@NetConstructor.com Чистое количество просмотров страниц не является показателем качества. Мы должны поощрять конкретные вопросы с конкретными ответами и хорошие практики программирования. Эта ветка - полная противоположность.

fuxia fuxia
22 февр. 2012 г. 04:44:30

@toscho - именно поэтому это было создано как вики, и данный пост совершенно уместен. Мое замечание относительно просмотров было сделано потому, что очевидно, эта тема в 3 раза популярнее любой другой на этом сайте. Этот сайт популярен именно благодаря таким вопросам, поэтому нет смысла закрывать его. Я не думаю, что это можно оспаривать, если интерес сообщества к подобным темам не имеет значения для администраторов.

NetConstructor.com NetConstructor.com
24 февр. 2012 г. 18:38:34

Добавлю еще один комментарий, основанный на только что сделанных мной расчетах. На этом сайте менее 790 зарегистрированных пользователей с рейтингом "1" или выше. Если предположить, что эта группа представляет тех, кто действительно голосует и/или вносит вклад на сайте (а 790 - весьма справедливая оценка), то 117 человек, проголосовавших за этот вопрос, представляют более 14% всех активных пользователей, которые сочли тему полезной. Пожалуйста, проголосуйте за повторное открытие темы.

NetConstructor.com NetConstructor.com
24 февр. 2012 г. 18:47:01

@NetConstructor.com Обсудите это на Meta, где ваши аргументы будут лучше видны. :)

fuxia fuxia
24 февр. 2012 г. 19:10:14
Показать остальные 20 комментариев
Все ответы на вопрос 30
2
15

Включение пользовательских типов записей в виджет "Прямо сейчас" в админ-панели

Этот код добавит ваши пользовательские типы записей и количество записей каждого типа в виджет "Прямо сейчас" на панели управления.

// ДОБАВЛЕНИЕ ПОЛЬЗОВАТЕЛЬСКИХ ТИПОВ ЗАПИСЕЙ В ВИДЖЕТ 'ПРЯМО СЕЙЧАС'
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' );
26 янв. 2011 г. 16:19:21
Комментарии

В виджете RightNow внезапно появился тип записи "WooFramework Internal Container"! . . . нужно добавить один дополнительный аргумент 'show_ui' => true, и теперь всё в порядке

brasofilo brasofilo
4 апр. 2012 г. 03:37:39

Это точно такая же ситуация, которую я описал выше.

jaredwilli jaredwilli
9 дек. 2012 г. 19:52:30
4
14

Добавление формы поиска по 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 );
}
9 нояб. 2010 г. 05:22:03
Комментарии

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

NetConstructor.com NetConstructor.com
22 февр. 2011 г. 22:19:14

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

jaredwilli jaredwilli
23 февр. 2011 г. 02:56:13

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

Zach Lysobey Zach Lysobey
15 февр. 2012 г. 19:06:32

Я обернул add_filter в этот вызов действия: add_action('plugins_loaded', 'pluginInit');, а затем function pluginInit(){if...add_filter(...)} - я запускаю это в WP 3.4-alpha и пришлось использовать in_admin_footer

brasofilo brasofilo
2 апр. 2012 г. 14:28:28
0
14

Новая колонка в медиатеке для повторной привязки изображений

Этот код добавляет новую колонку на страницу Медиатеки, позволяющую повторно привязывать изображения

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
        }
}
14 нояб. 2010 г. 17:57:56
1
13

Тематический пользовательский цикл с использованием шорткодов

Аргументы такие же, как у 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"]
21 дек. 2010 г. 22:03:19
Комментарии

Лучше использовать Javascript: <a href="javascript:window.open('http://tinyurl.com/api-create.php?url='+location.href"> Получить короткую ссылку </a> (чтобы избежать сотен ненужных запросов открытия страницы (от ботов и т.д.) к TinyUrl...

T.Todua T.Todua
23 янв. 2015 г. 12:22:10
1
12

Установка редактора по умолчанию: 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";'));
16 нояб. 2010 г. 06:56:16
Комментарии

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

bueltge bueltge
17 нояб. 2010 г. 14:44:36
11
11

Удаление метабокса автора и его параметров с переносом в метабокс публикации

Проверено на: 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>';
}
30 сент. 2010 г. 06:06:41
Комментарии

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

matt matt
5 дек. 2010 г. 07:02:43

Какую версию WordPress вы используете?

NetConstructor.com NetConstructor.com
6 дек. 2010 г. 19:21:32

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

kaiser kaiser
1 февр. 2011 г. 09:42:15

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

NetConstructor.com NetConstructor.com
1 февр. 2011 г. 17:07:08

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

kaiser kaiser
1 февр. 2011 г. 20:55:29

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

NetConstructor.com NetConstructor.com
2 февр. 2011 г. 00:29:12

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

kaiser kaiser
2 февр. 2011 г. 01:50:33

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

NetConstructor.com NetConstructor.com
2 февр. 2011 г. 07:11:09

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

kaiser kaiser
2 февр. 2011 г. 08:53:13

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

NetConstructor.com NetConstructor.com
3 февр. 2011 г. 18:05:34

@NC: Нет, ты меня правильно понял. Для меня это не "метабокс публикации", а просто блок в верхнем правом углу для мелких элементов. Я не вижу необходимости иметь отдельный блок для одной строки "добавить миниатюру" или двух чекбоксов из обсуждений. Больше ничего.

kaiser kaiser
3 февр. 2011 г. 19:09:35
Показать остальные 6 комментариев
3
11

Быстрое определение сервера и параметров окружения

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

В моей системе окружение определяется по первым 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>";
}

Это не раз спасало меня от внесения изменений в неправильное окружение.

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

5 нояб. 2010 г. 22:03:12
Комментарии

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

NetConstructor.com NetConstructor.com
5 нояб. 2010 г. 23:28:48

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

hakre hakre
6 нояб. 2010 г. 19:41:34

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

Ian Dunn Ian Dunn
16 янв. 2012 г. 21:01:09
0
10

Исправлено: Удаление стандартных метабоксов 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');
9 нояб. 2010 г. 00:45:36
2
10

Увеличение периода автоматического выхода из системы

Проверено на: 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' );
11 нояб. 2010 г. 14:57:07
Комментарии

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

NetConstructor.com NetConstructor.com
11 нояб. 2010 г. 14:58:14

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

Ian Dunn Ian Dunn
16 янв. 2012 г. 20:58:22
3
10

Добавление ссылки "Настройки" для плагинов на странице списка плагинов

Установите ссылку "Настройки" для плагинов на странице плагинов в админке 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 );
}
15 нояб. 2010 г. 01:07:46
Комментарии

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

NetConstructor.com NetConstructor.com
22 февр. 2011 г. 22:37:19

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

bueltge bueltge
28 февр. 2011 г. 19:23:56

Хотелось бы, чтобы все авторы плагинов делали так (для плагинов, у которых есть страницы настроек, конечно), чтобы такой код не был необходим.

JimmyPena JimmyPena
6 дек. 2011 г. 21:00:37
1
10

Отключение автоматического преобразования URL в ссылки в комментариях WordPress

remove_filter('comment_text', 'make_clickable', 9);
28 дек. 2010 г. 02:14:24
Комментарии

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

fregante fregante
11 янв. 2014 г. 02:57:27
1
10

Добавление фильтра шаблонов страниц в список страниц

Проверено на: 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.

19 мар. 2011 г. 17:52:55
Комментарии

работает безупречно, протестировано в версии 3.4-alpha

brasofilo brasofilo
2 апр. 2012 г. 16:01:27
3
10

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

Протестировано на: 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;
}
26 нояб. 2011 г. 15:11:36
Комментарии

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

chrismccoy chrismccoy
25 февр. 2012 г. 02:38:23

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

Paul Paul
17 авг. 2012 г. 00:02:53

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

Также, есть ли способ применить фильтр для терминов в моём CPT?

Кстати, большое спасибо за ваш код.

Loc_rabbirt Loc_rabbirt
14 февр. 2020 г. 02:06:54
2

Отключение 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');
13 сент. 2010 г. 22:24:19
Комментарии

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

NetConstructor.com NetConstructor.com
14 сент. 2010 г. 05:37:28

Он оказывает минимальное влияние на производительность вызовов XML-RPC, так как больше не требуется проверять поддержку SSL через HTTP-запрос.

gabrielk gabrielk
19 сент. 2010 г. 20:57:49
2

Коллекция быстрых правок для 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');
6 нояб. 2010 г. 23:08:39
Комментарии

спасибо, но эти уже были добавлены.

NetConstructor.com NetConstructor.com
8 нояб. 2010 г. 17:12:18

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

NetConstructor.com NetConstructor.com
26 янв. 2011 г. 16:30:41
2

Получение всех произвольных полей глобально

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); ?>
15 нояб. 2010 г. 07:45:04
Комментарии

Зачем это использовать? В чем преимущество?

matt matt
5 дек. 2010 г. 07:10:33

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

Norcross Norcross
11 дек. 2010 г. 00:44:34
0

Возвращаем количество комментариев

Эта функция аналогична 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'); // выводит количество комментариев ?>

17 нояб. 2010 г. 04:52:13
0

Включение oEmbed в виджетах Текст/HTML

add_filter( 'widget_text', array( $wp_embed, 'run_shortcode' ), 8 );
add_filter( 'widget_text', array( $wp_embed, 'autoembed'), 8 );

Я использую это для виджетов с видео YouTube и контентом из Flickr.

28 дек. 2010 г. 02:07:12
3

Счётчик слов в записях

Протестировано на: 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 за оптимизацию кода без использования запросов!

15 сент. 2010 г. 18:58:01
Комментарии

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

EAMann EAMann
15 сент. 2010 г. 19:56:22

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

Rarst Rarst
15 сент. 2010 г. 20:05:31

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

EAMann EAMann
15 сент. 2010 г. 20:17:22
0

Условная загрузка скриптов

Вот способ загружать скрипты только если присутствует определённый шорткод или виджет. источник: Загрузка скриптов только при наличии определённого шорткода или виджета

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') );
    }
30 сент. 2010 г. 14:57:18
0

Пользовательские стили для админ-панели

/* Изменение CSS админ-панели WordPress */
function custom_admin_styles() {
    echo '<style type="text/css">#wphead{background:#069}</style>';
}
add_action('admin_head', 'custom_admin_styles');

Вы можете добавить любые изменения CSS между тегами <style>.

10 нояб. 2010 г. 20:42:26
0

Удаление префиксов 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:.

3 дек. 2010 г. 20:13:33
0

Произвольная длина анонса

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 символов.

Анонс будет прерван текстом ... (Читать далее)

2 янв. 2011 г. 22:00:51
0

Добавление 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.

21 февр. 2011 г. 21:03:12
1

Включение числовой пагинации

Протестировано на: 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>&lsaquo; <?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'); ?> &rsaquo;</span></a>
<?php } ?>

 </div>
10 сент. 2010 г. 03:04:37
Комментарии

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

t31os t31os
11 нояб. 2010 г. 19:09:23
1

Отображение определенного контента только для авторизованных пользователей

Протестировано на: 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/

17 сент. 2010 г. 11:34:49
Комментарии

У меня не получается отобразить изменённый контент для неавторизованных пользователей... первая часть работает нормально, но если пользователь не вошёл в систему и страница помечена как приватная, я просто получаю обычную 404 ошибку?

gillespieza gillespieza
9 февр. 2011 г. 22:58:07
2

Сделайте ваши короткие ссылки короче, удалив 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;
}
28 сент. 2010 г. 03:53:46
Комментарии

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

Ingve Ingve
29 мая 2012 г. 00:30:34

@Ingve Я исправил, теперь удаляется только начальное www

fregante fregante
11 янв. 2014 г. 03:04:48
2

Проверить, содержит ли запись встроенный контент

Проверяет, содержит ли запись встроенный контент (например, видео или другой медиа-контент). Работает внутри цикла, используя 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 в противном случае.

4 нояб. 2010 г. 19:11:02
Комментарии

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

matt matt
5 дек. 2010 г. 07:08:44

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

t31os t31os
5 дек. 2010 г. 11:34:42
0

Отображение записей разных пользовательских типов записей на главной странице

Добавив следующий код в конец файла 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())
14 нояб. 2010 г. 21:53:13
0

Удаление стандартных полей контактной информации в профиле пользователя и замена их на более полезные

Вторая часть этой функции уже упоминалась выше, но удаление стандартных полей - 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');

Конечно, вы можете добавить столько полей, сколько вам нужно (см. предыдущие примеры в этой теме) в разделе "Добавляем новые поля"

22 дек. 2010 г. 10:46:37