// Dùng trong trường hợp muốn tương tác với hook/action, nhưng không thêm mới markup, ví dụ không thêm mới block nào đó
// Lý do là để có thể mở rộng và xóa khi cần
class Codetot_Layout {
public function init() {
remove_action('codetot_footer', 'codetot_layout_slideout_menu', 10);
}
}
// Function thêm mới cần nên viết ra ngoài và độc lập, không phụ thuộc vào class
function codetot_layout_render_slideout_menu {
the_block('slideout-menu');
}
function codetot_woocommerce_get_product_query($args) {}
function ct_lms_get_course_query($args) {}
function azpet_get_hot_deal_query($args) {}
// _render tức là hiển thị ra
function codetot_layout_render_slideout_menu {
the_block('slideout-menu');
}
// _get tức là lấy ra (không echo)
// _query tức là sẽ trả về WP_Query
function codetot_get_product_query($product_args) {}
// _get tức là lấy ra (không echo)
// _query tức là sẽ trả về array
function codetot_get_product_args() {}
function codetot_get_product_query($query, $posts_per_page = 9) {
// Sẽ không cần
// $_posts_per_page = !empty($post_per_page) ? $posts_per_page : 9;
}
function codetot_get_post_query($custom_post_args) {
$default_args = array(
'post_type' => 'post',
'posts_per_page' => get_option('posts_per_page')
);
// Tương tự array_merge() trong PHP, nhưng được WordPress xử lý nữa rồi
$post_args = wp_parse_args($custom_post_args, $default_args);
return new WP_Query($post_args);
}
- Case thường gặp: có thể có link hoặc không có link.
- Cách xử lý: Tạo 1 biến riêng và set điều kiện cho output ra
<?php
ob_start();
the_block('image', array(
'image' => $image,
'class' => 'image--cover image--square logo-grid__image',
'size' => 'medium'
));
$content = ob_get_clean();
if (!empty($link)) {
printf('<a class="logo-grid__link" href="%1$s">%3$s</a>,
esc_attr($link),
$content
);
} else {
// Không nên echo $content thẳng ra, mà tạo 1 div tương đương tiến hành css cho cả __link lẫn __block
printf('<div class="logo-grid__block">%s</div>, $content);
}
function codetot_get_post_args($categories = []) {
$post_args = array(
'post_type' => 'post',
'posts_per_page' => -1,
);
$tax_query = array();
if (!empty($categories)) {
$tax_query[] = array(
'taxonomy' => 'course_category',
'field' => 'term_id',
'terms' => $categories
);
}
if (count($tax_query) > 1) {
$tax_query['relation'] = 'AND';
}
if (!empty($tax_query)) {
$post_args['tax_query'] = $tax_query;
}
return $post_args;
}
Tài liệu tham khảo: https://developer.wordpress.org/themes/theme-security/data-sanitization-escaping/
Các giá trị thu thập được từ $_GET, $_POST hay từ data người dùng nhập đều cần xử lý qua các function để hạn chế tấn công.
sanitize_email()
sanitize_file_name()
sanitize_html_class()
sanitize_key()
sanitize_meta()
sanitize_mime_type()
sanitize_option()
sanitize_sql_orderby()
sanitize_text_field()
sanitize_title()
sanitize_title_for_query()
sanitize_title_with_dashes()
sanitize_user()
esc_url_raw()
wp_filter_post_kses()
wp_filter_nohtml_kses()
Các function esc_
esc_html()// <h2><?php echo esc_html( $title ); ?></h2>
esc_url() // <img src="<?php echo esc_url( $great_user_picture_url ); ?>" />
esc_js()
esc_attr() // <ul class="<?php echo esc_attr( $stored_class ); ?>"> </ul>
esc_textarea() // <textarea><?php echo esc_textarea( $text ); ?></textarea>
Ngoài ra còn có escape cho các phần language cần dịch:
esc_html__()
esc_html_e()
esc_html_x()
esc_attr__()
esc_attr_e()
esc_attr_x()
Và escape cho post_content:
echo wp_kses_post( $post_content );
Bởi vì chỉ có dữ liệu mới nên được escape/sanitize
, các function chỉ return ra HTML cần loại bỏ các đoạn mã HTML nằm bên trong echo
vì có thể gây hiểu nhầm khi quét code là đoạn có mức độ security cao (do không esc_html
được).
<?php
foreach ($items as $item) : ?>
<li>
<a href="<?php echo esc_url( $item['url']); ?>"><?php echo esc_html( $item['name'] ); ?></a>
</li>
<?php endforeach; ?>
Ngoài ra, khi sử dụng các biến truyền placeholder, ví dụ sprintf()
cũng không truyền HTML vào.
<?php
$time = esc_html__('1 hour', 'theme-prefix');
$views_ago = sprintf(esc_html__('%s ago', 'theme-prefix'), $time);
?>
<?php if ( !empty( $time) ) : ?>
<span><?php echo esc_html( $views_ago ); ?></span>
<?php endif;
function ct_azpet_is_hot_deal_product($start_date, $end_date) {
$now = current_time('Y-m-d H:i:s' );
$time_stamp_now = strtotime($now);
$time_stamp_start = strtotime($start_date);
$time_stamp_end = strtotime($end_date);
// Case 1: both start and end date were filled
if(!empty($start_date) && !empty($end_date) ) {
// Trả về kết quả sớm nhất, không cần if else nhiều điều kiện
return $now > $start_date && $now < $end_date;
}
// If empty end_date but has start_date
if (!empty($start_date) && empty($end_date)) {
return $time_stamp_start < $time_stamp_now;
}
// If empty start_date but has end_date
if (empty($start_date) && !empty($end_date)) {
return $time_stamp_end > $time_stamp_now;
}
return false;
}