<?php
$page_id = get_option('page_on_front'); // или конкретный ID, например 123
if( have_rows('main-categories', $page_id) ): ?>
<section class="main-categories">
<ul class="main-category-list">
<?php while( have_rows('main-categories', $page_id) ) : the_row(); ?>
<li class="main-category-item">
<a href="<?php the_sub_field('main-category-url'); ?>">
<img src="<?php the_sub_field('main-category-img'); ?>" alt="<?php the_sub_field('main-category-title'); ?>" />
<h3><?php the_sub_field('main-category-title'); ?></h3>
</a>
</li>
<?php endwhile; ?>
</ul>
</section>
<?php endif; ?>
<?php
/**
* Hook: woocommerce_before_single_product_summary.
*
* @hooked woocommerce_show_product_sale_flash - 10
* @hooked woocommerce_show_product_images - 20
*/
do_action( 'woocommerce_before_single_product_summary' );
?>
<div class="summary entry-summary">
<?php
/**
* Hook: woocommerce_single_product_summary.
*
* @hooked woocommerce_template_single_title - 5
* @hooked woocommerce_template_single_rating - 10
* @hooked woocommerce_template_single_price - 10
* @hooked woocommerce_template_single_excerpt - 20
* @hooked woocommerce_template_single_add_to_cart - 30
* @hooked woocommerce_template_single_meta - 40
* @hooked woocommerce_template_single_sharing - 50
* @hooked WC_Structured_Data::generate_product_data() - 60
*/
do_action( 'woocommerce_single_product_summary' );
?>
</div>
<?php
/**
* Hook: woocommerce_after_single_product_summary.
*
* @hooked woocommerce_output_product_data_tabs - 10
* @hooked woocommerce_upsell_display - 15
* @hooked woocommerce_output_related_products - 20
*/
do_action( 'woocommerce_after_single_product_summary' );
?>
</div>
if (isset($query_args['tax_query'])) {
foreach ($query_args['tax_query'] as $key => $tax) {
if ( $tax['taxonomy'] === 'product_visibility') {
unset($query_args['tax_query'][$key]);
}
}
$query_args['tax_query'] = array_values($query_args['tax_query']);
}
add_filter('woocommerce_structured_data_product', 'add_missing_structured_data_fields', 10, 2);
function add_missing_structured_data_fields($markup, $product) {
$reviews = get_comments(array(
'post_id' => $product->get_id(),
'status' => 'approve',
'type' => 'review'
));
if ($reviews) {
$markup['review'] = array();
foreach ($reviews as $review) {
$rating = get_comment_meta($review->comment_ID, 'rating', true);
$markup['review'][] = array(
'@type' => 'Review',
'author' => array(
'@type' => 'Person',
'name' => get_comment_author($review->comment_ID)
),
'datePublished' => get_comment_date('c', $review->comment_ID),
'description' => get_comment_text($review->comment_ID),
'reviewRating' => array(
'@type' => 'Rating',
'ratingValue' => $rating ? $rating : 5,
'bestRating' => 5,
'worstRating' => 1
)
);
}
}
if ($product->get_rating_count() > 0) {
$markup['aggregateRating'] = array(
'@type' => 'AggregateRating',
'ratingValue' => $product->get_average_rating(),
'reviewCount' => $product->get_review_count(),
'bestRating' => '5',
'worstRating' => '1'
);
}
$markup['shippingDetails'] = array(
'@type' => 'OfferShippingDetails',
'shippingRate' => array(
'@type' => 'MonetaryAmount',
'value' => '0',
'currency' => get_woocommerce_currency()
),
'shippingDestination' => array(
'@type' => 'DefinedRegion',
'addressCountry' => 'RU'
)
);
$markup['hasMerchantReturnPolicy'] = array(
'@type' => 'MerchantReturnPolicy',
'applicableCountry' => 'RU',
'returnPolicyCategory' => 'https://schema.org/MerchantReturnFiniteReturnWindow',
'merchantReturnDays' => 14,
'returnMethod' => 'https://schema.org/ReturnByMail',
'returnFees' => 'https://schema.org/FreeReturn'
);
return $markup;
}
add_action('woocommerce_thankyou', 'wpp_auto_complete_free_fully_downloadable_orders');
function wpp_auto_complete_free_fully_downloadable_orders($order_id) {
$order = wc_get_order($order_id);
if (!$order || !in_array($order->get_status(), ['pending', 'on-hold', 'processing'])) {
return;
}
if ($order->get_total() != 0) {
return;
}
$all_downloadable = true;
foreach ($order->get_items() as $item) {
$product = $item->get_product();
if (!$product || !$product->is_downloadable()) {
$all_downloadable = false;
break;
}
}
if ($all_downloadable) {
$order->update_status(
'completed',
'All items are free and downloadable. Order completed automatically.'
);
}
}
<?php
/**
* Plugin Name: Habr Q&A Custom Login Page
* Description: Кастомизация страницы входа WordPress - заменяет логотип на название и описание сайта, скрывает ссылку на главную
* Version: 1.0.0
* Author: WP_Panda
* Author URI: https://wp-panda.pro
* Email: panda@wp-panda.pro
* License: GPL-2.0+
* License URI: http://www.gnu.org/licenses/gpl-2.0.txt
*/
if (!defined('ABSPATH')) {
exit; // Запрет прямого доступа
}
function wpp_habr_custom_login_styles() {
// Убираем стандартный логотип WordPress
add_filter('login_headerurl', function() { return home_url(); });
add_filter('login_headertext', function() { return get_bloginfo('name'); });
// Добавляем свои стили
echo '<style>
#login h1 a {
display: none !important;
}
.login #backtoblog {
display: none !important;
}
</style>';
}
add_action('login_head', 'wpp_habr_custom_login_styles');
function wpp_habr_custom_login_header() {
echo '<div id="login">
<h1>'.esc_html(get_bloginfo('name')).'</h1>
<p style="text-align:center">'.esc_html(get_bloginfo('description')).'</p>';
}
add_action('login_header', 'wpp_habr_custom_login_header');
// Хуки для Contact Form 7
add_action('wpcf7_before_send_mail', 'wpp_limit_cf7_submissions');
add_filter('wpcf7_display_message', 'wpp_block_cf7_form_display', 10, 2);
function wpp_limit_cf7_submissions($contact_form) {
$form_id = $contact_form->id();
$user_ip = $_SERVER['REMOTE_ADDR'];
$user_agent = $_SERVER['HTTP_USER_AGENT'];
// Создаем уникальный ключ для пользователя
$user_key = md5($user_ip . $user_agent);
$option_key = 'cf7_submission_' . $form_id . '_' . $user_key;
// Проверяем, отправлял ли пользователь форму за последние 24 часа
$last_submission = get_option($option_key);
$current_time = time();
if ($last_submission && ($current_time - $last_submission) < 86400) { // 24 часа
// Блокируем отправку
$submission = WPCF7_Submission::get_instance();
if ($submission) {
$submission->add_status('aborted', 'Вы уже отправляли заявку. Пожалуйста, подождите 24 часа.');
}
return false;
}
// Записываем время отправки
update_option($option_key, $current_time, false);
return $contact_form;
}
function wpp_block_cf7_form_display($message, $status) {
if ($status === 'aborted') {
return 'Вы уже отправляли заявку. Пожалуйста, подождите 24 часа перед повторной отправкой.';
}
return $message;
}
function wpp_make_tags_hierarchical() {
$tag_args = get_taxonomy('post_tag');
$tag_args->hierarchical = true;
$tag_args->rewrite['hierarchical'] = true;
}
add_action('init', 'wpp_make_tags_hierarchical', 999);
$categories = get_categories(array(
'orderby' => 'count',
'order' => 'DESC',
'hide_empty' => true
));
$counts = wp_list_pluck($categories, 'count');
$max_count = max($counts);
$min_count = min($counts);
$count_range = ($max_count - $min_count) ? ($max_count - $min_count) : 1;
$normalized = ($category->count - $min_count) / $count_range;
$font_size = 14 + round($normalized * 10, 2);