Глоссарий с гугло-плюшками!

Передо мной стояла задача сделать глоссарий с постами и не только выводить их по первой букве, но и показывать все на карте заданной с помощью модуля wp-geo-mashup. Т.к. брать чужой модуль и доделывать его для гугло-плюшки я не хотел, то с радостью сел за написание своего! А получился у меня не модуль, а всего лишь loop с выводом гуглокарты)

Еще забыл добавить что поиск по мета-информации (custom field) тоже был нужен!
Я опущу создание шаблона для страницы и вывод туда нужной петли, просто напишу код который поместил в отдельный файл.


$temp = $wp_query;
$letter = get_query_var('letter');
$paged = get_query_var('paged');
$wp_query= null;
$wp_query = new WP_Query("posts_per_page=10&post_type=member&paged={$paged}&glossary={$letter}&address={$address}&city={$city}&company_name={$company_name}&orderby=post_title&order=ASC");
if ( have_posts() ) : ?>
<div id="fade">
<div style="display: none;">
<?php echo GeoMashup::map( array('width' => 385, 'height' => 480, 'static' => true)); ?>
</div>
<div>
<ul>
<?php  while ( have_posts() ) : the_post(); ?>
<li>
<span><a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a></span>
<?php if ($website = post_custom('field_website')) : ?>
<a href="<?php echo $website; ?>"><?php echo $website; ?></a>
<?php endif; ?>
</li>
<?php endwhile; ?>
</ul>
</div>
</div>
<?php else : ?>
<span><?php _e("Nothing to found"); ?></span>
<?php endif; ?>
<?php if(function_exists('wp_pagenavi')) { wp_pagenavi(); } ?>
<?php $wp_query = null; $wp_query = $temp; ?>

Скопировав глобальную переменную $wp_query во временную переменную $temp я тем самым просто сохранил ее чтобы потом вернуть на место в конце скрипта, это нужно для того чтобы не разрушать вывод основной информации на странице. Подробнее смотрите как сделать две петли на одной странице: Multiple loops in action.

При создании нового запроса вы увидите массу других параметров, все они нужны =)
Карту мы выводим через статический метод в модуле wp-geo-mashup — GeoMashup::map(), внутри можем задать кучу параметров, все они описаны в документации, см. README в папке с модулем, или страницу документации.
Код для вывода постов и карты готов, теперь приступим к форме для поиска.


<form id="search-company" method="get">
<?php
$company_name =  esc_html( $_GET['company_name'] );
$address = esc_html( $_GET['field_address'] );
$city = esc_html( $_GET['field_city'] );
?>
<div>
<p><?php _e("Введите название и адрес для поиска", 'ru_RU'); ?></p>
<p>
<label for="company_name"><?php _e("Название", 'ru_RU'); ?>:</label>
<input type="text" id="company_name" name="company_name" value="<?php echo $company_name; ?>" />
</p>
<p>
<label for="address"><?php _e("Адрес", 'ru_RU'); ?>:</label>
<input type="text" id="address" name="field_address" value="<?php echo $address; ?>" />
</p>
<p>
<label for="city"><?php _e("Город", 'ru_RU'); ?>:</label>
<input type="text" id="city" name="field_city" value="<?php echo $city; ?>" />
</p>
<p><input type="submit" value="<?php _e("Поиск", 'ru_RU'); ?>" id="searchsubmit" /></p>
</div>
</form>

Форма готова, теперь чтобы заставить ее работать следует добавить в functions.php обработку полей для поиска (помещаем в functions.php):


/**
* Add custom parameter to query. Get all posts by title first leter
* @param $where
* @param $wp_query
* @return string
*/
function htmlandcms_posts_where( $where, &$wp_query ) {
global $wpdb;
if ( $letter = $wp_query->get( 'glossary' ) ) {
$where .= ' AND ' . $wpdb->posts . '.post_title LIKE \'' . esc_sql( like_escape( $letter ) ) . '%\'';
}
if ( $company_name = $wp_query->get( 'company_name' ) ) {
$where .= ' AND ' . $wpdb->posts . '.post_title LIKE \'%' . esc_sql( like_escape( $company_name ) ) . '%\'';
}
if ( $address = $wp_query->get( 'address' ) ) {
$where .= ' AND ' . $wpdb->postmeta . '.meta_key = \'field_address\' AND ' . $wpdb->postmeta . '.meta_value LIKE \'%' . esc_sql( like_escape( $address ) ) . '%\'';
}
if ( $city = $wp_query->get( 'city' ) ) {
$where .= ' AND ' . $wpdb->postmeta . '.meta_key = \'field_city\' AND ' . $wpdb->postmeta . '.meta_value LIKE \'%' . esc_sql( like_escape( $city ) ) . '%\'';
}
return $where;
}
add_filter( 'posts_where', 'htmlandcms_posts_where', 10, 2 );

Тут мы дополняем параметр WHERE в SQL-запросе. Как работают фильтры советую почитать на кодексе, ну или спросить в комментариях, я расскажу.
А дальше мы подключим в запрос базу с мета-информацией поста (т.е. custom fields). Поля address и city заполняются при создании материала, если они в форме заданы то база добавляется в запрос:


function htmlandcms_posts_join($join, &$wp_query) {
global $wpdb;
if ($true = $wp_query->get( 'address' ) || $true = $wp_query->get( 'city' )) {
$join .= ' LEFT JOIN ' . $wpdb->postmeta . ' ON ' . $wpdb->posts . '.ID = ' . $wpdb->postmeta . '.post_id';
}
return $join;
}
add_filter( 'posts_join', 'htmlandcms_posts_join', 10, 2);

Последнее что осталось это сам глоссарий. Не так давно открыл для себя систему виджетов и решил этим воспользоваться. Наследуем класс WP_Widget, выводим список букв с символами (помещаем в functions.php):


class WP_Widget_Glossary extends WP_Widget {
function __construct() {
$widget_ops = array('classname' => 'widget_glossary', 'description' => __( "Posts glossary") );
parent::__construct('glossary', __("Glossary"), $widget_ops);
}

function widget($args, $instance) {
$cache = wp_cache_get('widget_glossary', 'widget');

if (!is_array($cache))
{
$cache = array();
}

if (!isset($args['widget_id']))
{
$args['widget_id'] = $this->id;
}

if ( isset( $cache[ $args['widget_id'] ] ) ) {
echo $cache[ $args['widget_id'] ];
return;
}

ob_start();
extract($args);

?>
<?php echo $before_widget; ?>
<?php if ($title) echo $before_title . $title . $after_title; ?>
<ul>
<?php foreach (range('a', 'z') as $letter) : ?>
<li><a href="<?php echo get_bloginfo('url') . "/glossary/{$letter}"; ?>"><?php echo $letter ?></a></li>
<?php endforeach ?>
</ul>
<?php echo $after_widget; ?>
<?php
$cache[$args['widget_id']] = ob_get_flush();
wp_cache_set('widget_glossary', $cache, 'widget');
}
}

О создании виджетов в WordPress написано очень много статей, как на английском так и на русском, рассказывать уже нечего, если что не понятно то смотрите в код и все поймете! 🙂

Виджет создали, только ссылка на буквы у меня идет: site.ru/glossary/a, заменить на свой адрес.
А чтобы наши пути правильно обрабатывали добавим в functions.php такой код:


// Adding the id var so that WP recognizes it
function htmlandcms_insert_query_vars( $vars ) {
array_push($vars, 'letter');
return $vars;
}
add_filter( 'query_vars','htmlandcms_insert_query_vars' );

Добавили поддержку параметра ‘letter’ при создании запроса класса WP_Query();
Далее добавляем правила обработки путей:


/**
* Rewrite url rules.
* @param $wp_rewrite
*/
function htmlandcms_rewrite_rules( $wp_rewrite ) {
$wp_rewrite->rules = array(
'leden/(\w)/page/?([0-9]{1,})/?$' => $wp_rewrite->index . '?pagename=glossary&letter=' . $wp_rewrite->preg_index( 1 ) . '&paged=' . $wp_rewrite->preg_index( 2 ),
'leden/(\w)/?$' => $wp_rewrite->index . '?pagename=glossary&letter=' . $wp_rewrite->preg_index( 1 )

) + $wp_rewrite->rules;
}
add_action( 'generate_rewrite_rules', 'htmlandcms_rewrite_rules' );

Добавили поддержку путей вида site.ru/glossary, site.ru/glossary/a, и site.ru/glossary/paged/1.
Теперь очистим же кеш правил для обработки путей.


// flush_rules() if our rules are not yet included
function htmlandcms_flush_rules(){
$rules = get_option( 'rewrite_rules' );

if ( ! isset( $rules['(leden)/(\w*)$'] ) ) {
global $wp_rewrite;
$wp_rewrite->flush_rules();
}
}
add_action( 'wp_loaded','htmlandcms_flush_rules' );

Теперь пути обрабатываются верно, осталось дело за малым, а если точнее то осталось вывести наш виджет с буквами от ‘a’ до ‘z’. Выводим виджет в сайдбаре или можем вставить на нужную страницу с помощью кода:


<?php the_widget('WP_Widget_Glossary'); ?>

P,S. Думал на ночь по-быстрому написать маленькую статейку с пару примерами, а она оказалась и не такая уж и маленькая. В общем если будут вопросы то не стесняемся, спрашиваем!

.

 

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *