| Server IP : 14.225.216.240 / Your IP : 216.73.216.26 Web Server : nginx/1.20.1 System : Linux localhost.localdomain 5.14.0-596.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Fri Jun 27 16:02:33 UTC 2025 x86_64 User : taidh ( 1001) PHP Version : 8.3.19 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /home/taidh/papacafe.vn/wp-content/themes/papacafe/ |
Upload File : |
<?php
/**
* Papacafe functions and definitions
*
* @link https://developer.wordpress.org/themes/basics/theme-functions/
*
* @package Papacafe
* @since Papacafe 1.0
*/
/**
* Register block styles.
*/
if (! function_exists('papacafe_block_styles')) :
/**
* Register custom block styles
*
* @since Papacafe 1.0
* @return void
*/
function papacafe_block_styles()
{
register_block_style(
'core/details',
array(
'name' => 'arrow-icon-details',
'label' => __('Arrow icon', 'papacafe'),
/*
* Styles for the custom Arrow icon style of the Details block
*/
'inline_style' => '
.is-style-arrow-icon-details {
padding-top: var(--wp--preset--spacing--10);
padding-bottom: var(--wp--preset--spacing--10);
}
.is-style-arrow-icon-details summary {
list-style-type: "\2193\00a0\00a0\00a0";
}
.is-style-arrow-icon-details[open]>summary {
list-style-type: "\2192\00a0\00a0\00a0";
}',
)
);
register_block_style(
'core/post-terms',
array(
'name' => 'pill',
'label' => __('Pill', 'papacafe'),
/*
* Styles variation for post terms
* https://github.com/WordPress/gutenberg/issues/24956
*/
'inline_style' => '
.is-style-pill a,
.is-style-pill span:not([class], [data-rich-text-placeholder]) {
display: inline-block;
background-color: var(--wp--preset--color--base-2);
padding: 0.375rem 0.875rem;
border-radius: var(--wp--preset--spacing--20);
}
.is-style-pill a:hover {
background-color: var(--wp--preset--color--contrast-3);
}',
)
);
register_block_style(
'core/list',
array(
'name' => 'checkmark-list',
'label' => __('Checkmark', 'papacafe'),
/*
* Styles for the custom checkmark list block style
* https://github.com/WordPress/gutenberg/issues/51480
*/
'inline_style' => '
ul.is-style-checkmark-list {
list-style-type: "\2713";
}
ul.is-style-checkmark-list li {
padding-inline-start: 1ch;
}',
)
);
register_block_style(
'core/navigation-link',
array(
'name' => 'arrow-link',
'label' => __('With arrow', 'papacafe'),
/*
* Styles for the custom arrow nav link block style
*/
'inline_style' => '
.is-style-arrow-link .wp-block-navigation-item__label:after {
content: "\2197";
padding-inline-start: 0.25rem;
vertical-align: middle;
text-decoration: none;
display: inline-block;
}',
)
);
register_block_style(
'core/heading',
array(
'name' => 'asterisk',
'label' => __('With asterisk', 'papacafe'),
'inline_style' => "
.is-style-asterisk:before {
content: '';
width: 1.5rem;
height: 3rem;
background: var(--wp--preset--color--contrast-2, currentColor);
clip-path: path('M11.93.684v8.039l5.633-5.633 1.216 1.23-5.66 5.66h8.04v1.737H13.2l5.701 5.701-1.23 1.23-5.742-5.742V21h-1.737v-8.094l-5.77 5.77-1.23-1.217 5.743-5.742H.842V9.98h8.162l-5.701-5.7 1.23-1.231 5.66 5.66V.684h1.737Z');
display: block;
}
/* Hide the asterisk if the heading has no content, to avoid using empty headings to display the asterisk only, which is an A11Y issue */
.is-style-asterisk:empty:before {
content: none;
}
.is-style-asterisk:-moz-only-whitespace:before {
content: none;
}
.is-style-asterisk.has-text-align-center:before {
margin: 0 auto;
}
.is-style-asterisk.has-text-align-right:before {
margin-left: auto;
}
.rtl .is-style-asterisk.has-text-align-left:before {
margin-right: auto;
}",
)
);
}
endif;
add_action('init', 'papacafe_block_styles');
/**
* Enqueue block stylesheets.
*/
if (! function_exists('papacafe_block_stylesheets')) :
/**
* Enqueue custom block stylesheets
*
* @since Papacafe 1.0
* @return void
*/
function papacafe_block_stylesheets()
{
/**
* The wp_enqueue_block_style() function allows us to enqueue a stylesheet
* for a specific block. These will only get loaded when the block is rendered
* (both in the editor and on the front end), improving performance
* and reducing the amount of data requested by visitors.
*
* See https://make.wordpress.org/core/2021/12/15/using-multiple-stylesheets-per-block/ for more info.
*/
wp_enqueue_block_style(
'core/button',
array(
'handle' => 'papacafe-button-style-outline',
'src' => get_parent_theme_file_uri('assets/css/button-outline.css'),
'ver' => wp_get_theme(get_template())->get('Version'),
'path' => get_parent_theme_file_path('assets/css/button-outline.css'),
)
);
}
endif;
add_action('init', 'papacafe_block_stylesheets');
/**
* Register pattern categories.
*/
if (! function_exists('papacafe_pattern_categories')) :
/**
* Register pattern categories
*
* @since Papacafe 1.0
* @return void
*/
function papacafe_pattern_categories()
{
register_block_pattern_category(
'papacafe_page',
array(
'label' => _x('Pages', 'Block pattern category', 'papacafe'),
'description' => __('A collection of full page layouts.', 'papacafe'),
)
);
}
endif;
add_action('init', 'papacafe_pattern_categories');
// News code cua Loc
//Headerrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
add_action('admin_menu', 'add_custom_header_tab');
// Hàm này thêm một mục mới vào menu Appearance trong admin panel của WordPress
function add_custom_header_tab()
{
// Thêm trang con trong Appearance
add_theme_page(
'Custom Header', // Tiêu đề trang hiển thị ở phần đầu của trang
'Custom Header', // Tiêu đề menu hiển thị trong phần Appearance
'edit_theme_options', // Quyền truy cập cần thiết để nhìn thấy mục này (chỉ người dùng có quyền chỉnh sửa giao diện)
'custom-header-tab', // Menu slug (định danh duy nhất của trang)
'custom_header_page_html' // Hàm callback để hiển thị nội dung của trang
);
}
function custom_header_page_html()
{
?>
<h1>Welcome to the Custom Header Page!</h1>
<form method="post" action="options.php">
<?php
// Tạo các trường ẩn cần thiết cho bảo mật và liên kết với option group
settings_fields('custom_header_settings_group');
// Hiển thị các trường cài đặt (nếu có)
do_settings_sections('custom-header-tab');
// Nút submit để lưu các cài đặt
submit_button();
?>
</form>
<?php
}
add_action('admin_init', 'custom_header_settings_init');
function custom_header_settings_init()
{
// Đăng ký cài đặt
register_setting('custom_header_settings_group', 'header1_id');
register_setting('custom_header_settings_group', 'header_logo');
register_setting('custom_header_settings_group', 'header_phone');
// Tạo một section để nhóm các cài đặt của bạn lại (có thể bỏ qua nếu không cần)
add_settings_section(
'custom_header_section', // ID của section
'Custom Header Settings', // Tiêu đề của section
null, // Hàm callback để hiển thị nội dung của section (có thể là null)
'custom-header-tab' // Slug của trang mà bạn muốn hiển thị section này
);
add_settings_field(
'header1_id', // ID của trường
'Header Content', // Nhãn hiển thị của trường
'custom_header_field_callback', // Hàm callback để hiển thị nội dung của trường
'custom-header-tab', // Trang hiển thị
'custom_header_section' // Section mà trường này thuộc về
);
add_settings_field(
'header_logo', // ID của trường
'Header Logo', // Nhãn hiển thị của trường
'header_logo_field_callback', // Hàm callback để hiển thị nội dung của trường
'custom-header-tab', // Trang hiển thị
'custom_header_section' // Section mà trường này thuộc về
);
add_settings_field(
'header_phone', // ID của trường
'Header_phone', // Nhãn hiển thị của trường
'header_phone_field_callback', // Hàm callback để hiển thị nội dung của trường
'custom-header-tab', // Trang hiển thị
'custom_header_section' // Section mà trường này thuộc về
);
}
function custom_header_field_callback()
{
if (function_exists('is_plugin_active') && is_plugin_active('elementor/elementor.php')) {
// Nội dung mặc định trong trình soạn thảo
$content = get_option('header1_id', '');
wp_editor($content, 'header1_id');
} else {
echo '<p>Elementor is not activated. Please activate Elementor to use this feature.</p>';
}
}
function header_logo_field_callback()
{
if (function_exists('is_plugin_active') && is_plugin_active('elementor/elementor.php')) {
// Gọi thư viện media của WordPress
wp_enqueue_media();
$header_logo = get_option('header_logo', '');
echo '<div>
<img id="header-logo-preview" src="' . esc_url($header_logo) . '" style="max-width: 100%; max-height: 200px;" />
<input type="hidden" id="header-logo-url" name="header_logo" value="' . esc_attr($header_logo) . '" />
<button type="button" class="button" id="select-header-logo">Select Image</button>
</div>';
// JavaScript để mở media library và chọn ảnh
echo '<script>
jQuery(document).ready(function($) {
$("#select-header-logo").on("click", function(e) {
e.preventDefault();
var imageFrame;
if (imageFrame) {
imageFrame.open();
return;
}
imageFrame = wp.media({
title: "Select or Upload Image",
button: { text: "Use this image" },
multiple: false
});
imageFrame.on("select", function() {
var attachment = imageFrame.state().get("selection").first().toJSON();
$("#header-logo-url").val(attachment.url);
$("#header-logo-preview").attr("src", attachment.url);
});
imageFrame.open();
});
});
</script>';
} else {
echo '<p>Elementor is not activated. Please activate Elementor to use this feature.</p>';
}
}
function header_phone_field_callback()
{
if (function_exists('is_plugin_active') && is_plugin_active('elementor/elementor.php')) {
// Nội dung mặc định của số điện thoại
$custom_header_phone = get_option('header_phone', '');
echo '<input type="tel" name="header_phone" value="' . esc_attr($custom_header_phone) . '" class="regular-text" />';
} else {
echo '<p>Elementor is not activated. Please activate Elementor to use this feature.</p>';
}
}
function render_header_sections()
{
// Lấy nội dung của các phần footer từ database
$header_sections = [
'header_content' => get_option('header1_id', ''),
'header_logo' => get_option('header_logo', ''),
'header_phone' => get_option('header_phone', ''),
];
?>
<header class="header">
<div class="logo-container">
<img src="<?php echo $header_sections['header_logo']; ?>" alt="Logo" class="logo">
<h1 class="site-title"><?php echo $header_sections['header_content']; ?></h1>
</div>
<div class="contact-info">
<span>Số điện thoại liên hệ: </span>
<a href="<?php echo $header_sections['header_phone']; ?>"><?php echo $header_sections['header_phone']; ?></a>
</div>
<!-- menu -->
<nav class="custom-menu-nav">
<ul>
<?php
// Lấy dữ liệu menu từ database
$menu_items = get_option('custom_menu_items', []);
// Hiển thị các item trong menu
foreach ($menu_items as $item) : ?>
<li>
<a href="<?php echo esc_url($item['href']); ?>">
<?php echo esc_html($item['name']); ?>
</a>
<?php if (!empty($item['submenus'])) : ?>
<ul class="submenu">
<?php foreach ($item['submenus'] as $sub_item) : ?>
<li>
<a href="<?php echo esc_url($sub_item['href']); ?>">
<?php echo esc_html($sub_item['name']); ?>
</a>
</li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</li>
<?php endforeach; ?>
</ul>
</nav>
</header>
<?php
}
//Menuuuuuuuuuuuuuuuuu
function theme_register_menus()
{
register_nav_menus(
array(
'primary-menu' => __('Primary Menu'), // Menu chính
'footer-menu' => __('Footer Menu'), // Menu dưới cùng (tuỳ chọn)
'mobile-menu' => __('Mobile Menu')
)
);
}
add_action('after_setup_theme', 'theme_register_menus');
//load css
function load_assets()
{
//header
// wp_enqueue_style("bootstrap", get_theme_file_uri() . '/assets/css/bootstrap.min.css', array(), "1.0", "all");
//wp_enqueue_style("fontawesome", get_theme_file_uri() . '/assets/css/fontawesome.css', array(), "1.0", "all");
// wp_enqueue_style("venobox", get_theme_file_uri() . '/assets/css/venobox.min.css', array(), "1.0", "all");
// wp_enqueue_style("niceSelect", get_theme_file_uri() . '/assets/css/nice-select.min.css', array(), "1.0", "all");
// wp_enqueue_style("animate", get_theme_file_uri() . '/assets/css/animate.min.css', array(), "1.0", "all");
wp_enqueue_style("swiper", get_theme_file_uri() . '/assets/css/swiper.min.css', array(), "1.0", "all");
// wp_enqueue_style("maincss", get_theme_file_uri() . '/assets/css/main.min.css', array(), "1.0", "all");
//footer
// wp_enqueue_script("bootstrapBundle", get_theme_file_uri() . '/assets/js/bootstrap.bundle.js', array('jquery'), '1.0.0', true);
// wp_enqueue_script("countdown", get_theme_file_uri() . '/assets/js/countdown.js', array('jquery'), '1.0.0', true);
// wp_enqueue_script("imagesloaded", get_theme_file_uri() . '/assets/js/imagesloaded-pkgd.js', array('jquery'), '1.0.0', true);
// wp_enqueue_script("jquery371", get_theme_file_uri() . '/assets/js/jquery-3.7.1.js', array('jquery'), '1.0.0', true);
// wp_enqueue_script("jqueryIsotope", get_theme_file_uri() . '/assets/js/jquery.isotope.js', array('jquery'), '1.0.0', true);
// wp_enqueue_script("mainJs", get_theme_file_uri() . '/assets/js/mainJs', array('jquery'), '1.0.0', true);
// wp_enqueue_script("meanmenu", get_theme_file_uri() . '/assets/js/meanmenu.js', array('jquery'), '1.0.0', true);
// wp_enqueue_script("niceSelect", get_theme_file_uri() . '/assets/js/nice-select.js', array('jquery'), '1.0.0', true);
// wp_enqueue_script("smoothScroll", get_theme_file_uri() . '/assets/js/smooth-scroll.js', array('jquery'), '1.0.0', true);
wp_enqueue_script("swiper", get_theme_file_uri() . '/assets/js/swiper.js', array('jquery'), '1.0.0', true);
wp_enqueue_script("venobox", get_theme_file_uri() . '/assets/js/venobox.js', array('jquery'), '1.0.0', true);
// wp_enqueue_script("waypoints", get_theme_file_uri() . '/assets/js/waypoints.js', array('jquery'), '1.0.0', true);
// wp_enqueue_script("wow", get_theme_file_uri() . '/assets/js/wow.js', array('jquery'), '1.0.0', true);
// CSS từ CDN
wp_enqueue_style("bootstrap", get_theme_file_uri() . '/assets/css/bootstrap.min.css', array(), "1.0", "all");
wp_enqueue_style("fontawesome-cdn", "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css", array(), "6.0.0", "all");
wp_enqueue_style("venobox-cdn", "https://cdnjs.cloudflare.com/ajax/libs/venobox/1.9.1/venobox.min.css", array(), "1.9.1", "all");
wp_enqueue_style("nice-select-cdn", "https://cdnjs.cloudflare.com/ajax/libs/jquery-nice-select/1.1.0/css/nice-select.min.css", array(), "1.1.0", "all");
wp_enqueue_style("animate-cdn", "https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css", array(), "4.1.1", "all");
// wp_enqueue_style("swiper-cdn", "https://unpkg.com/swiper/swiper-bundle.min.css", array(), null, "all");
wp_enqueue_style("main-css", get_theme_file_uri() . '/assets/css/main.css', array(), "1.0", "all");
// JavaScript từ CDN
wp_enqueue_script("bootstrapBundle", get_theme_file_uri() . '/assets/js/bootstrap.bundle.js', array('jquery'), '1.0.0', true);
wp_enqueue_script("jquery-cdn", "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js", array(), '3.7.1', true);
wp_enqueue_script("countdown", get_theme_file_uri() . '/assets/js/countdown.min.js', array('jquery'), '1.0.0', true);
wp_enqueue_script("imagesloaded", get_theme_file_uri() . '/assets/js/imagesloaded-pkgd.js', array('jquery'), '1.0.0', true);
wp_enqueue_script("isotope-cdn", "https://cdnjs.cloudflare.com/ajax/libs/jquery.isotope/3.0.6/isotope.pkgd.min.js", array('jquery'), '3.0.6', true);
// wp_enqueue_script("venobox-cdn", "https://cdnjs.cloudflare.com/ajax/libs/venobox/1.9.1/venobox.min.js", array('jquery'), '1.9.1', true);
wp_enqueue_script("mainJs", get_theme_file_uri() . '/assets/js/main.js', array('jquery'), '1.0.0', true);
wp_enqueue_script("meanmenu", get_theme_file_uri() . '/assets/js/meanmenu.js', array('jquery'), '1.0.0', true);
wp_enqueue_script("nice-select-cdn", "https://cdnjs.cloudflare.com/ajax/libs/jquery-nice-select/1.1.0/js/jquery.nice-select.min.js", array('jquery'), '1.1.0', true);
wp_enqueue_script("smooth-scroll-cdn", "https://cdnjs.cloudflare.com/ajax/libs/smooth-scroll/16.1.3/smooth-scroll.min.js", array('jquery'), '16.1.3', true);
// wp_enqueue_script("swiper-cdn", "https://unpkg.com/swiper/swiper-bundle.min.js", array('jquery'), null, true);
wp_enqueue_script("waypoints-cdn", "https://cdnjs.cloudflare.com/ajax/libs/waypoints/4.0.1/jquery.waypoints.min.js", array('jquery'), '4.0.1', true);
wp_enqueue_script("wow-cdn", "https://cdnjs.cloudflare.com/ajax/libs/wow/1.1.2/wow.min.js", array('jquery'), '1.1.2', true);
}
add_action("wp_enqueue_scripts", "load_assets");
//Footerrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
add_action('admin_menu', 'add_custom_footer_tab');
// Hàm này thêm một mục mới vào menu Appearance trong admin panel của WordPress
function add_custom_footer_tab()
{
// Thêm trang con trong Appearance
add_theme_page(
'Custom Footer', // Tiêu đề trang hiển thị ở phần đầu của trang
'Custom Footer', // Tiêu đề menu hiển thị trong phần Appearance
'edit_theme_options', // Quyền truy cập cần thiết để nhìn thấy mục này (chỉ người dùng có quyền chỉnh sửa giao diện)
'custom-footer-tab', // Menu slug (định danh duy nhất của trang)
'custom_footer_page_html' // Hàm callback để hiển thị nội dung của trang
);
}
function custom_footer_page_html()
{
?>
<h1>Welcome to the Custom Footer Page!</h1>
<form method="post" action="options.php">
<?php
// Tạo các trường ẩn cần thiết cho bảo mật và liên kết với option group
settings_fields('custom_footer_settings_group');
// Hiển thị các trường cài đặt (nếu có)
do_settings_sections('custom-footer-tab');
// Nút submit để lưu các cài đặt
submit_button();
?>
</form>
<?php
}
add_action('admin_init', 'custom_footer_settings_init');
function custom_footer_settings_init()
{
// Đăng ký cài đặt
register_setting('custom_footer_settings_group', 'footer_copyright');
register_setting('custom_footer_settings_group', 'footer_address');
register_setting('custom_footer_settings_group', 'footer_phone');
register_setting('custom_footer_settings_group', 'footer_bc');
register_setting('custom_footer_settings_group', 'footer_gmail');
register_setting('custom_footer_settings_group', 'footer_facebook');
register_setting('custom_footer_settings_group', 'footer_youtube');
register_setting('custom_footer_settings_group', 'footer_instagram');
//Picture
register_setting('custom_footer_settings_group', 'footer_logo');
register_setting('custom_footer_settings_group', 'footer_free_shipping');
register_setting('custom_footer_settings_group', 'footer_free_return');
register_setting('custom_footer_settings_group', 'footer_customer_service');
register_setting('custom_footer_settings_group', 'footer_zalo_logo');
// Tạo một section để nhóm các cài đặt của bạn lại (có thể bỏ qua nếu không cần)
add_settings_section(
'custom_footer_section', // ID của section
'Custom Footer Settings', // Tiêu đề của section
null, // Hàm callback để hiển thị nội dung của section (có thể là null)
'custom-footer-tab' // Slug của trang mà bạn muốn hiển thị section này
);
add_settings_field(
'footer_copyright', // ID của trường
'Copyright: ', // Nhãn hiển thị của trường
'custom_copyright_field_callback', // Hàm callback để hiển thị nội dung của trường
'custom-footer-tab', // Trang hiển thị
'custom_footer_section' // Section mà trường này thuộc về
);
add_settings_field(
'footer_address', // ID của trường
'Address: ', // Nhãn hiển thị của trường
'custom_address_field_callback', // Hàm callback để hiển thị nội dung của trường
'custom-footer-tab', // Trang hiển thị
'custom_footer_section' // Section mà trường này thuộc về
);
add_settings_field(
'footer_phone', // ID của trường
'Phone number: ', // Nhãn hiển thị của trường
'custom_phone_field_callback', // Hàm callback để hiển thị nội dung của trường
'custom-footer-tab', // Trang hiển thị
'custom_footer_section' // Section mà trường này thuộc về
);
add_settings_field(
//bc là viết tắt của business code
'footer_bc', // ID của trường
'Business code: ', // Nhãn hiển thị của trường
'custom_bc_field_callback', // Hàm callback để hiển thị nội dung của trường
'custom-footer-tab', // Trang hiển thị
'custom_footer_section' // Section mà trường này thuộc về
);
add_settings_field(
'footer_gmail', // ID của trường
'Gmail: ', // Nhãn hiển thị của trường
'custom_gmail_field_callback', // Hàm callback để hiển thị nội dung của trường
'custom-footer-tab', // Trang hiển thị
'custom_footer_section' // Section mà trường này thuộc về
);
add_settings_field(
//fb là facebook
'footer_facebook', // ID của trường
'Facebook: ', // Nhãn hiển thị của trường
'custom_facebook_field_callback', // Hàm callback để hiển thị nội dung của trường
'custom-footer-tab', // Trang hiển thị
'custom_footer_section' // Section mà trường này thuộc về
);
add_settings_field(
//fb là youtube
'footer_youtube', // ID của trường
'Youtube: ', // Nhãn hiển thị của trường
'custom_youtube_field_callback', // Hàm callback để hiển thị nội dung của trường
'custom-footer-tab', // Trang hiển thị
'custom_footer_section' // Section mà trường này thuộc về
);
add_settings_field(
//fb là instagram
'footer_instagram', // ID của trường
'Instagram: ', // Nhãn hiển thị của trường
'custom_instagram_field_callback', // Hàm callback để hiển thị nội dung của trường
'custom-footer-tab', // Trang hiển thị
'custom_footer_section' // Section mà trường này thuộc về
);
add_settings_field(
'footer_logo', // ID của trường
'Footer Logo', // Nhãn hiển thị của trường
'footer_logo_field_callback', // Hàm callback để hiển thị nội dung của trường
'custom-footer-tab', // Trang hiển thị
'custom_footer_section' // Section mà trường này thuộc về
);
// Field cho Free Shipping
add_settings_field(
'footer_free_shipping',
'Free Shipping Image',
'footer_free_shipping_field_callback',
'custom-footer-tab',
'custom_footer_section'
);
// Field cho Free Return
add_settings_field(
'footer_free_return',
'Free Return Image',
'footer_free_return_field_callback',
'custom-footer-tab',
'custom_footer_section'
);
// Field cho Customer Service
add_settings_field(
'footer_customer_service',
'Customer Service Image',
'footer_customer_service_field_callback',
'custom-footer-tab',
'custom_footer_section'
);
// Field cho Customer Service
add_settings_field(
'footer_zalo_logo',
'Zalo Image',
'footer_zalo_logo_callback',
'custom-footer-tab',
'custom_footer_section'
);
}
function custom_copyright_field_callback()
{
$custom_copyright = get_option('footer_copyright', '');
echo '<input type="text" name="footer_copyright" value="' . esc_attr($custom_copyright) . '" class="regular-text" />';
}
function custom_address_field_callback()
{
$custom_address = get_option('footer_address', '');
echo '<input type="text" name="footer_address" value="' . esc_attr($custom_address) . '" class="regular-text" />';
}
function custom_phone_field_callback()
{
$custom_phone = get_option('footer_phone', '');
echo '<input type="text" name="footer_phone" value="' . esc_attr($custom_phone) . '" class="regular-text" />';
}
function custom_bc_field_callback()
{
$custom_bc = get_option('footer_bc', '');
echo '<input type="text" name="footer_bc" value="' . esc_attr($custom_bc) . '" class="regular-text" />';
}
function custom_gmail_field_callback()
{
$custom_gmail = get_option('footer_gmail', '');
echo '<input type="email" name="footer_gmail" value="' . esc_attr($custom_gmail) . '" class="regular-text" />';
}
function custom_facebook_field_callback()
{
$custom_facebook = get_option('footer_facebook', '');
echo '<input type="url" name="footer_facebook" value="' . esc_attr($custom_facebook) . '" class="regular-text" />';
}
function custom_youtube_field_callback()
{
$custom_youtube = get_option('footer_youtube', '');
echo '<input type="url" name="footer_youtube" value="' . esc_attr($custom_youtube) . '" class="regular-text" />';
}
function custom_instagram_field_callback()
{
$custom_instagram = get_option('footer_instagram', '');
echo '<input type="url" name="footer_instagram" value="' . esc_attr($custom_instagram) . '" class="regular-text" />';
}
function footer_logo_field_callback()
{
footer_image_field_callback('footer_logo', 'Select Footer Logo');
}
function footer_free_shipping_field_callback()
{
footer_image_field_callback('footer_free_shipping', 'Select Free Shipping Image');
}
function footer_free_return_field_callback()
{
footer_image_field_callback('footer_free_return', 'Select Free Return Image');
}
function footer_customer_service_field_callback()
{
footer_image_field_callback('footer_customer_service', 'Select Customer Service Image');
}
function footer_zalo_logo_callback()
{
footer_image_field_callback('footer_zalo_logo', 'Select Zalo Image');
}
// Hàm chung để tạo field chọn hình ảnh
function footer_image_field_callback($option_name, $button_text)
{
if (function_exists('is_plugin_active') && is_plugin_active('elementor/elementor.php')) {
wp_enqueue_media();
$image_url = get_option($option_name, '');
echo '<div>
<img id="' . $option_name . '-preview" src="' . esc_url($image_url) . '" style="max-width: 100%; max-height: 200px;" />
<input type="hidden" id="' . $option_name . '-url" name="' . $option_name . '" value="' . esc_attr($image_url) . '" />
<button type="button" class="button select-image-button" data-target="' . $option_name . '">' . esc_html($button_text) . '</button>
</div>';
echo '<script>
jQuery(document).ready(function($) {
$(".select-image-button").on("click", function(e) {
e.preventDefault();
var target = $(this).data("target");
var imageFrame;
if (imageFrame) {
imageFrame.open();
return;
}
imageFrame = wp.media({
title: "Select or Upload Image",
button: { text: "Use this image" },
multiple: false
});
imageFrame.on("select", function() {
var attachment = imageFrame.state().get("selection").first().toJSON();
$("#" + target + "-url").val(attachment.url);
$("#" + target + "-preview").attr("src", attachment.url);
});
imageFrame.open();
});
});
</script>';
} else {
echo '<p>Elementor is not activated. Please activate Elementor to use this feature.</p>';
}
}
//widgetttttttttttttttttttttttttt in appearance
function my_custom_theme_widgets_init()
{
register_sidebar(array(
'name' => __('Footer Widget Area', 'textdomain'),
'id' => 'footer-widget-area',
'description' => __('Widget area for footer section of the theme.', 'textdomain'),
'before_widget' => '<div id="%1$s" class="footer-widget %2$s">',
'after_widget' => '</div>',
'before_title' => '<h4 class="footer-widget-title">',
'after_title' => '</h4>',
));
}
add_action('widgets_init', 'my_custom_theme_widgets_init');
//widget area
function my_custom_widget_area()
{
register_sidebar(array(
'name' => __('My Custom Widget Area', 'theme_text_domain'),
'id' => 'custom-widget-area',
'before_widget' => '<div class="custom-widget">',
'after_widget' => '</div>',
'before_title' => '<h3 class="widget-title">',
'after_title' => '</h3>',
));
}
add_action('widgets_init', 'my_custom_widget_area');
//widget list ngang
class Product_List_Widget extends WP_Widget
{
function __construct()
{
parent::__construct(
'product_list_widget', // ID of the widget
__('Product List', 'text_domain'), // Widget name
array('description' => __('Display a list of products', 'text_domain')) // Description
);
}
// Front-end of the widget
public function widget($args, $instance)
{
echo isset($args['before_widget']) ? $args['before_widget'] : '';
?>
<section class="fashion-section pt-100 pb-100">
<div class="container">
<div class="category-top heading-space space-border">
<div class="section-heading mb-0">
<h2 class="section-title">What does Papa havve today?</h2>
</div>
<div class="swiper-arrow">
<div class="swiper-nav custom-swiper-prev" tabindex="0" role="button" aria-label="Previous slide">
<i class="fa-solid fa-angle-left"></i>
</div>
<div class="swiper-nav custom-swiper-next" tabindex="0" role="button" aria-label="Next slide">
<i class="fa-solid fa-angle-right"></i>
</div>
</div>
</div>
<div class="shop-carousel swiper">
<div class="swiper-wrapper">
<?php
// Query WooCommerce products
$args = array(
'post_type' => 'product',
'posts_per_page' => 10
);
$loop = new WP_Query($args);
if ($loop->have_posts()) {
while ($loop->have_posts()) {
$loop->the_post();
global $product;
?>
<div class="swiper-slide">
<div class="shop-item">
<div class="shop-thumb">
<div class="overlay"></div>
<img src="<?php echo get_the_post_thumbnail_url($product->get_id(), 'medium'); ?>" alt="<?php the_title(); ?>" loading="lazy">
<span class="sale">Hot</span>
</div>
<div class="shop-content">
<span class="category">
<?php
$terms = get_the_terms($product->get_id(), 'product_cat');
if ($terms && !is_wp_error($terms)) {
echo esc_html($terms[0]->name);
}
?>
</span>
<h3 class="title">
<a href="<?php echo get_permalink($product->get_id()); ?>">
<?php the_title(); ?>
</a>
</h3>
<span class="price">
<?php echo $product->get_price_html(); ?>
</span>
</div>
</div>
</div>
<?php
}
} else {
echo __('No products found', 'text_domain');
}
wp_reset_postdata();
?>
</div>
</div>
</div>
</section>
<script>
document.addEventListener('DOMContentLoaded', function() {
const swiper = new Swiper('.shop-carousel', {
slidesPerView: 5,
spaceBetween: 30,
loop: true,
navigation: {
prevEl: '.custom-swiper-prev',
nextEl: '.custom-swiper-next',
},
breakpoints: {
320: {
slidesPerView: 1,
spaceBetween: 10,
},
768: {
slidesPerView: 2,
spaceBetween: 20,
},
1024: {
slidesPerView: 5,
spaceBetween: 30,
},
}
});
});
</script>
<?php
echo isset($args['after_widget']) ? $args['after_widget'] : '';
}
// Widget settings form in the dashboard
public function form($instance)
{
// Leaving empty for a simple widget
}
// Save widget settings
public function update($new_instance, $old_instance)
{
$instance = array();
return $instance;
}
}
// Register the widget
function register_product_list_widget()
{
register_widget('Product_List_Widget');
}
add_action('widgets_init', 'register_product_list_widget');
//widget nhieu muc
class Papas_Products_Widget extends WP_Widget
{
function __construct()
{
parent::__construct(
'papas_products_widget', // ID of the widget
__('Papa\'s Products', 'text_domain'), // Widget name
array('description' => __('Display Papa\'s products in categories', 'text_domain')) // Description
);
}
// Front-end of the widget
public function widget($args, $instance)
{
echo isset($args['before_widget']) ? $args['before_widget'] : '';
?>
<section class="papas-products pt-100 pb-100 bg-grey">
<div class="container">
<div class="section-heading text-center">
<h2 class="section-title">Papa's Products</h2>
</div>
<ul id="filter-section" class="project-filter furniture-filter text-center">
<li class="active" data-filter=".papa-cafe">Papa' Cafe</li>
<li data-filter=".arabica">Arabica</li>
<li data-filter=".robusta">Robusta</li>
<li data-filter=".blendar">Blend A&R</li>
<!-- <li data-filter=".nhung-cai-ban">Những cái bàn</li> -->
<li data-filter=".dac-san-3-mien">Đặc sản 3 miền</li>
<li data-filter=".ke-tay-ban-phim">Kê tay bàn phím</li>
<li data-filter="*">All</li>
</ul>
<div class="filter-items row gy-4">
<?php
// Query WooCommerce products
$args = array(
'post_type' => 'product',
'posts_per_page' => 20
);
$loop = new WP_Query($args);
if ($loop->have_posts()) {
while ($loop->have_posts()) {
$loop->the_post();
global $product;
$terms = get_the_terms($product->get_id(), 'product_cat');
$class = '';
if ($terms && !is_wp_error($terms)) {
foreach ($terms as $term) {
$class .= ' ' . strtolower($term->slug);
}
}
?>
<div class="custom-col-xl-2-4 col-lg-3 col-md-6 single-item <?php echo esc_attr($class); ?>">
<div class="ft-shop-item">
<div class="furniture-img">
<img src="<?php echo get_the_post_thumbnail_url($product->get_id(), 'medium'); ?>" alt="<?php the_title(); ?>" loading="lazy">
</div>
<div class="shop-content">
<span class="category">
<?php
if ($terms && !is_wp_error($terms)) {
echo esc_html($terms[0]->name);
}
?>
</span>
<h3 class="title">
<a href="<?php echo get_permalink($product->get_id()); ?>">
<?php the_title(); ?>
</a>
</h3>
<span class="price">
<?php echo $product->get_price_html(); ?>
</span>
</div>
</div>
</div>
<?php
}
} else {
echo __('No products found', 'text_domain');
}
wp_reset_postdata();
?>
</div>
</div>
</section>
<script>
document.addEventListener('DOMContentLoaded', function() {
const filterItems = document.querySelectorAll('#filter-section li');
const products = document.querySelectorAll('.single-item');
const widgetSection = document.querySelector('.papas-products');
// Function to activate filter
function activateFilter(filterValue) {
filterItems.forEach(item => item.classList.remove('active'));
const filterItem = document.querySelector(`#filter-section li[data-filter="${filterValue}"]`);
if (filterItem) {
filterItem.classList.add('active');
}
products.forEach(product => {
if (filterValue === '*' || product.classList.contains(filterValue.substring(1))) {
product.style.display = 'block';
} else {
product.style.display = 'none';
}
});
}
// Event listener for click on filter items
filterItems.forEach(filter => {
filter.addEventListener('click', function() {
const filterValue = this.getAttribute('data-filter');
activateFilter(filterValue);
//history.pushState(null, null, `#papas-products-widget?filter=${filterValue}`);
});
});
// Function to parse the hash value and activate filter
function parseHashAndActivateFilter() {
const urlHash = window.location.hash;
if (urlHash.startsWith('#papas-products-widget')) {
const params = new URLSearchParams(urlHash.split('?')[1]);
const filterValue = params.get('filter');
if (filterValue) {
// Scroll to the widget section
widgetSection.scrollIntoView({
behavior: 'smooth'
});
// Activate the filter
activateFilter(filterValue);
}
}
}
// Check URL hash on page load
parseHashAndActivateFilter();
// Handle hash change events (e.g. browser back button)
window.addEventListener('hashchange', function() {
parseHashAndActivateFilter();
});
});
</script>
<?php
echo isset($args['after_widget']) ? $args['after_widget'] : '';
}
// Widget settings form in the dashboard
public function form($instance)
{
// Leaving empty for a simple widget
}
// Save widget settings
public function update($new_instance, $old_instance)
{
$instance = array();
return $instance;
}
}
//Widget tren cung
class Hero_Section_Widget extends WP_Widget
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct(
'hero_section_widget',
__('Hero Section Widget (Dynamic)', 'text_domain'),
array(
'description' => __('A widget to input text and upload multiple images for a hero section.', 'text_domain')
)
);
}
/**
* Output the widget content on the front-end
*
* @param array $args
* @param array $instance
*/
public function widget($args, $instance)
{
// Extract data
$title = !empty($instance['title']) ? $instance['title'] : '';
$description_1 = !empty($instance['description_1']) ? $instance['description_1'] : '';
$button_url = !empty($instance['button_url']) ? $instance['button_url'] : '#';
// Retrieve images: each line in the textarea corresponds to an image URL
$raw_images = !empty($instance['images']) ? $instance['images'] : '';
// Convert them into an array
$images = array_filter(array_map('trim', explode("\n", $raw_images)));
echo $args['before_widget'];
?>
<section class="hero-section hero-3">
<div class="container">
<div class="row">
<!-- Left section with text content -->
<div class="col-lg-6">
<div class="hero-content-3">
<div class="wow animate__ animate__fadeInLeft mb-20 animated">
<h4>
<span style="font-size:28px">
<strong><?php echo esc_html($title); ?></strong>
</span>
</h4>
<!-- Chỉ còn 1 mô tả -->
<p><em><?php echo nl2br( esc_html($description_1) ); ?></em></p>
</div>
<a class="rr-primary-btn primary-2 wow animate__ animate__zoomIn animated"
data-wow-delay="1s"
href="<?php echo esc_url($button_url); ?>"
style="visibility: visible; animation-delay: 1s; animation-name: zoomIn;">
Khám phá câu chuyện
</a>
</div>
</div>
<!-- Right section with dynamic carousel -->
<div class="col-lg-6 d-flex justify-content-center align-items-center">
<?php if (!empty($images)) : ?>
<div id="hero-carousel-<?php echo $this->id; ?>"
class="carousel slide w-100 wow animate__ animate__fadeInRight animated"
data-bs-ride="carousel">
<div class="carousel-inner">
<?php
$active = 'active';
foreach ($images as $url) :
?>
<div class="carousel-item <?php echo esc_attr($active); ?>">
<img src="<?php echo esc_url($url); ?>"
class="rounded carousel-img"
alt="Slider image"
loading="lazy"
width="1600"
height="1100">
</div>
<?php
// Sau lần đầu tiên, xóa lớp active để không trùng lặp
$active = '';
endforeach;
?>
</div>
<?php if (count($images) > 1) : ?>
<button class="carousel-control-prev" type="button" data-bs-target="#hero-carousel-<?php echo $this->id; ?>" data-bs-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="visually-hidden">Previous</span>
</button>
<button class="carousel-control-next" type="button" data-bs-target="#hero-carousel-<?php echo $this->id; ?>" data-bs-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">Next</span>
</button>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
</div>
</div>
</section>
<?php
echo $args['after_widget'];
}
/**
* Back-end widget form
*
* @param array $instance
* @return void
*/
public function form($instance)
{
// Retrieve or set defaults
$title = !empty($instance['title']) ? $instance['title'] : __('Default Title', 'text_domain');
$description_1 = !empty($instance['description_1']) ? $instance['description_1'] : '';
$button_url = !empty($instance['button_url']) ? $instance['button_url'] : '#';
$images = !empty($instance['images']) ? $instance['images'] : '';
// Title
?>
<p>
<label for="<?php echo esc_attr($this->get_field_id('title')); ?>">
<?php _e('Title:'); ?>
</label>
<input class="widefat"
id="<?php echo esc_attr($this->get_field_id('title')); ?>"
name="<?php echo esc_attr($this->get_field_name('title')); ?>"
type="text"
value="<?php echo esc_attr($title); ?>">
</p>
<!-- Description field -->
<p>
<label for="<?php echo esc_attr($this->get_field_id('description_1')); ?>">
<?php _e('Description:'); ?>
</label>
<textarea class="widefat"
id="<?php echo esc_attr($this->get_field_id('description_1')); ?>"
name="<?php echo esc_attr($this->get_field_name('description_1')); ?>"
rows="5"><?php echo esc_textarea($description_1); ?></textarea>
</p>
<!-- Button URL -->
<p>
<label for="<?php echo esc_attr($this->get_field_id('button_url')); ?>">
<?php _e('Button URL:'); ?>
</label>
<input class="widefat"
id="<?php echo esc_attr($this->get_field_id('button_url')); ?>"
name="<?php echo esc_attr($this->get_field_name('button_url')); ?>"
type="text"
value="<?php echo esc_attr($button_url); ?>">
</p>
<!-- Images Textarea (one URL per line) -->
<p>
<label for="<?php echo esc_attr($this->get_field_id('images')); ?>">
<?php _e('Image URLs (one per line):'); ?>
</label>
<textarea class="widefat"
rows="5"
id="<?php echo esc_attr($this->get_field_id('images')); ?>"
name="<?php echo esc_attr($this->get_field_name('images')); ?>">
<?php echo esc_textarea($images); ?>
</textarea>
</p>
<?php
}
/**
* Save widget form values as they are updated
*
* @param array $new_instance
* @param array $old_instance
* @return array
*/
public function update($new_instance, $old_instance)
{
$instance = array();
$instance['title'] = (!empty($new_instance['title'])) ? strip_tags($new_instance['title']) : '';
$instance['description_1'] = (!empty($new_instance['description_1'])) ? strip_tags($new_instance['description_1']) : '';
$instance['button_url'] = (!empty($new_instance['button_url'])) ? strip_tags($new_instance['button_url']) : '';
// Store the entire textarea directly; each line is an image URL
$instance['images'] = (!empty($new_instance['images']))
? esc_textarea($new_instance['images'])
: '';
return $instance;
}
}
/**
* Register the widget
*/
function register_hero_section_widget()
{
register_widget('Hero_Section_Widget');
}
add_action('widgets_init', 'register_hero_section_widget');
//widget co background
class Custom_CTA_Widget extends WP_Widget
{
// Constructor function
function __construct()
{
parent::__construct(
'custom_cta_widget', // Base ID
__('Custom CTA Widget', 'text_domain'), // Name
array('description' => __('A Custom CTA Widget with image and text input', 'text_domain')) // Args
);
}
// Widget form in the admin panel
public function form($instance)
{
$title1 = !empty($instance['title1']) ? $instance['title1'] : '';
$title2 = !empty($instance['title2']) ? $instance['title2'] : '';
$image_url = !empty($instance['image_url']) ? $instance['image_url'] : '';
?>
<p>
<label for="<?php echo esc_attr($this->get_field_id('title1')); ?>"><?php _e('Title 1:', 'text_domain'); ?></label>
<input class="widefat" id="<?php echo esc_attr($this->get_field_id('title1')); ?>" name="<?php echo esc_attr($this->get_field_name('title1')); ?>" type="text" value="<?php echo esc_attr($title1); ?>">
</p>
<p>
<label for="<?php echo esc_attr($this->get_field_id('title2')); ?>"><?php _e('Title 2:', 'text_domain'); ?></label>
<input class="widefat" id="<?php echo esc_attr($this->get_field_id('title2')); ?>" name="<?php echo esc_attr($this->get_field_name('title2')); ?>" type="text" value="<?php echo esc_attr($title2); ?>">
</p>
<p>
<label for="<?php echo esc_attr($this->get_field_id('image_url')); ?>"><?php _e('Background Image URL:', 'text_domain'); ?></label>
<input class="widefat" id="<?php echo esc_attr($this->get_field_id('image_url')); ?>" name="<?php echo esc_attr($this->get_field_name('image_url')); ?>" type="text" value="<?php echo esc_attr($image_url); ?>">
</p>
<?php
}
// Update widget settings
public function update($new_instance, $old_instance)
{
$instance = array();
$instance['title1'] = (!empty($new_instance['title1'])) ? sanitize_text_field($new_instance['title1']) : '';
$instance['title2'] = (!empty($new_instance['title2'])) ? sanitize_text_field($new_instance['title2']) : '';
$instance['image_url'] = (!empty($new_instance['image_url'])) ? esc_url_raw($new_instance['image_url']) : '';
return $instance;
}
// Display widget in the frontend
public function widget($args, $instance)
{
$title1 = isset($instance['title1']) ? $instance['title1'] : '';
$title2 = isset($instance['title2']) ? $instance['title2'] : '';
$image_url = isset($instance['image_url']) ? $instance['image_url'] : '';
echo $args['before_widget'];
?>
<section class="cta-section" data-background="<?php echo esc_url($image_url); ?>" style="background-image: url('<?php echo esc_url($image_url); ?>');">
<div class="overlay"></div>
<div class="container">
<div class="cta-wrap text-center">
<?php if (!empty($title1)) : ?>
<h2 class="title">
<?php echo esc_html($title1); ?>
</h2>
<?php endif; ?>
<?php if (!empty($title2)) : ?>
<h2 class="title">
<?php echo esc_html($title2); ?>
</h2>
<?php endif; ?>
</div>
</div>
</section>
<?php
echo $args['after_widget'];
}
}
// Register the widget
function register_custom_cta_widget()
{
register_widget('Custom_CTA_Widget');
}
add_action('widgets_init', 'register_custom_cta_widget');
// Register the widget
function register_papas_products_widget()
{
register_widget('Papas_Products_Widget');
}
add_action('widgets_init', 'register_papas_products_widget');
//Quan li nhan xet
function create_customer_reviews_cpt()
{
$labels = array(
'name' => 'Customer Reviews',
'singular_name' => 'Customer Review',
'menu_name' => 'Customer Reviews',
'name_admin_bar' => 'Customer Review',
'add_new' => 'Add New',
'add_new_item' => 'Add New Review',
'new_item' => 'New Review',
'edit_item' => 'Edit Review',
'view_item' => 'View Review',
'all_items' => 'All Reviews',
'search_items' => 'Search Reviews',
'not_found' => 'No reviews found.',
'not_found_in_trash' => 'No reviews found in Trash.',
);
$args = array(
'labels' => $labels,
'public' => false,
'show_ui' => true,
'show_in_menu' => true,
'capability_type' => 'post',
'supports' => array(), // Không hỗ trợ tiêu đề và nội dung
'menu_icon' => 'dashicons-format-chat',
);
register_post_type('customer_review', $args);
}
add_action('init', 'create_customer_reviews_cpt');
function add_customer_reviews_metabox()
{
add_meta_box(
'customer_reviews_details',
'Customer Review Details',
'render_customer_reviews_metabox',
'customer_review',
'normal',
'high'
);
}
add_action('add_meta_boxes', 'add_customer_reviews_metabox');
function render_customer_reviews_metabox($post)
{
wp_nonce_field('save_customer_reviews_details', 'customer_reviews_nonce');
// Lấy giá trị hiện tại nếu có
$name = get_post_meta($post->ID, '_customer_name', true);
$address = get_post_meta($post->ID, '_customer_address', true);
$avatar = get_post_meta($post->ID, '_customer_avatar', true);
$rating = get_post_meta($post->ID, '_customer_rating', true);
?>
<p>
<label for="customer_name">Customer Name:</label>
<input type="text" id="customer_name" name="customer_name" value="<?php echo esc_attr($name); ?>" class="widefat">
</p>
<p>
<label for="customer_address">Customer Address:</label>
<input type="text" id="customer_address" name="customer_address" value="<?php echo esc_attr($address); ?>" class="widefat">
</p>
<p>
<label for="customer_avatar">Avatar:</label><br>
<img id="customer_avatar_preview" src="<?php echo esc_url($avatar); ?>" style="max-width: 150px; display: <?php echo $avatar ? 'block' : 'none'; ?>;" /><br>
<input type="hidden" id="customer_avatar" name="customer_avatar" value="<?php echo esc_attr($avatar); ?>" />
<button type="button" id="customer_avatar_button" class="button">Select Avatar</button>
<button type="button" id="customer_avatar_remove" class="button" style="display: <?php echo $avatar ? 'inline-block' : 'none'; ?>;">Remove Avatar</button>
</p>
<script>
jQuery(document).ready(function($) {
var mediaUploader;
$('#customer_avatar_button').click(function(e) {
e.preventDefault();
if (mediaUploader) {
mediaUploader.open();
return;
}
mediaUploader = wp.media.frames.file_frame = wp.media({
title: 'Choose Avatar',
button: {
text: 'Choose Image'
},
multiple: false
});
mediaUploader.on('select', function() {
var attachment = mediaUploader.state().get('selection').first().toJSON();
$('#customer_avatar').val(attachment.url);
$('#customer_avatar_preview').attr('src', attachment.url).show();
$('#customer_avatar_remove').show();
});
mediaUploader.open();
});
$('#customer_avatar_remove').click(function(e) {
e.preventDefault();
$('#customer_avatar').val('');
$('#customer_avatar_preview').hide();
$('#customer_avatar_remove').hide();
});
});
</script>
<p>
<label for="customer_rating">Rating:</label><br>
<select id="customer_rating" name="customer_rating" class="widefat">
<option value="1" <?php selected($rating, '1'); ?>>1 Star</option>
<option value="2" <?php selected($rating, '2'); ?>>2 Stars</option>
<option value="3" <?php selected($rating, '3'); ?>>3 Stars</option>
<option value="4" <?php selected($rating, '4'); ?>>4 Stars</option>
<option value="5" <?php selected($rating, '5'); ?>>5 Stars</option>
</select>
</p>
<?php
}
function save_customer_reviews_details($post_id)
{
// Kiểm tra nonce để đảm bảo yêu cầu an toàn
if (! isset($_POST['customer_reviews_nonce'])) {
return;
}
if (! wp_verify_nonce($_POST['customer_reviews_nonce'], 'save_customer_reviews_details')) {
return;
}
// Kiểm tra quyền lưu post
if (! current_user_can('edit_post', $post_id)) {
return;
}
// Lưu thông tin tên
if (isset($_POST['customer_name'])) {
update_post_meta($post_id, '_customer_name', sanitize_text_field($_POST['customer_name']));
}
// Lưu thông tin địa chỉ
if (isset($_POST['customer_address'])) {
update_post_meta($post_id, '_customer_address', sanitize_text_field($_POST['customer_address']));
}
// Lưu thông tin avatar
if (isset($_POST['customer_avatar'])) {
update_post_meta($post_id, '_customer_avatar', esc_url_raw($_POST['customer_avatar']));
}
// Lưu thông tin đánh giá số sao
if (isset($_POST['customer_rating'])) {
update_post_meta($post_id, '_customer_rating', sanitize_text_field($_POST['customer_rating']));
}
}
add_action('save_post', 'save_customer_reviews_details');
//widget customer reviews
class Customer_Reviews_Widget extends WP_Widget
{
public function __construct()
{
parent::__construct(
'customer_reviews_widget',
__('Customer Reviews Widget', 'text_domain'),
array('description' => __('A Widget to display customer reviews', 'text_domain'))
);
}
public function widget($args, $instance)
{
echo $args['before_widget'];
$shape_image = !empty($instance['shape_image']) ? $instance['shape_image'] : plugin_dir_url(__FILE__) . 'images/testi-shape.png';
?>
<section class="testimonial-section pt-100 pb-100">
<div class="container">
<div class="section-heading white-content text-center">
<h2 class="section-title">Khách hàng nói gì về chúng tôi</h2>
</div>
<div class="testimonial-carousel swiper swiper-initialized swiper-horizontal swiper-pointer-events">
<div class="swiper-wrapper" aria-live="polite" style="cursor: grab;">
<?php
if (!empty($instance['selected_reviews'])) {
$selected_reviews = $instance['selected_reviews'];
$query_args = array(
'post_type' => 'customer_review',
'post__in' => $selected_reviews,
'orderby' => 'post__in',
'posts_per_page' => count($selected_reviews),
);
$reviews = new WP_Query($query_args);
if ($reviews->have_posts()) :
$delay = 0.1;
while ($reviews->have_posts()) : $reviews->the_post();
$customer_name = get_post_meta(get_the_ID(), '_customer_name', true);
$customer_address = get_post_meta(get_the_ID(), '_customer_address', true);
$customer_avatar = get_post_meta(get_the_ID(), '_customer_avatar', true);
$customer_rating = get_post_meta(get_the_ID(), '_customer_rating', true);
$rating_count = (int) $customer_rating;
?>
<div class="swiper-slide wow animate__ animate__fadeIn animated" data-wow-delay="<?php echo $delay; ?>s" role="group" style="margin-right: 30px;">
<div class="testi-item-wrap">
<div class="testi-item">
<div class="testi-top-content">
<h4 class="title"><?php the_title(); ?></h4>
<ul class="review">
<?php for ($i = 0; $i < $rating_count; $i++) : ?>
<li><i class="fa-solid fa-star"></i></li>
<?php endfor; ?>
<?php for ($i = $rating_count; $i < 5; $i++) : ?>
<li><i class="fa-solid fa-star-o"></i></li>
<?php endfor; ?>
</ul>
</div>
<p><?php the_content(); ?></p>
<div class="shape">
<img src="<?php echo esc_url($shape_image); ?>" alt="shape" loading="lazy" width="50" height="50">
</div>
</div>
<div class="testi-author">
<img src="<?php echo esc_url($customer_avatar); ?>" alt="img" loading="lazy">
<h4 class="name"><?php echo esc_html($customer_name); ?> <span><?php echo esc_html($customer_address); ?></span></h4>
</div>
</div>
</div>
<?php
$delay += 0.1; // Tăng độ trễ để mỗi item có animation delay khác nhau
endwhile;
wp_reset_postdata();
endif;
}
?>
</div>
<span class="swiper-notification" aria-live="assertive" aria-atomic="true"></span>
</div>
</div>
</section>
<?php
echo $args['after_widget'];
}
public function form($instance)
{
$selected_reviews = !empty($instance['selected_reviews']) ? $instance['selected_reviews'] : array();
$shape_image = !empty($instance['shape_image']) ? $instance['shape_image'] : '';
$query_args = array(
'post_type' => 'customer_review',
'posts_per_page' => -1,
'orderby' => 'title',
'order' => 'ASC',
);
$reviews = new WP_Query($query_args);
if ($reviews->have_posts()) :
echo '<p><label for="' . esc_attr($this->get_field_id('selected_reviews')) . '">' . __('Select Reviews to Display:', 'text_domain') . '</label></p>';
echo '<ul>';
while ($reviews->have_posts()) : $reviews->the_post();
$checked = in_array(get_the_ID(), $selected_reviews) ? 'checked="checked"' : '';
?>
<li>
<input type="checkbox" id="<?php echo esc_attr($this->get_field_id('selected_reviews')) . '_' . get_the_ID(); ?>"
name="<?php echo esc_attr($this->get_field_name('selected_reviews')); ?>[]"
value="<?php echo get_the_ID(); ?>"
<?php echo $checked; ?>>
<label for="<?php echo esc_attr($this->get_field_id('selected_reviews')) . '_' . get_the_ID(); ?>"><?php the_title(); ?></label>
</li>
<?php
endwhile;
echo '</ul>';
wp_reset_postdata();
else :
echo '<p>' . __('No reviews found.', 'text_domain') . '</p>';
endif;
// Shape Image Field
?>
<p>
<label for="<?php echo esc_attr($this->get_field_id('shape_image')); ?>"><?php _e('Shape Image URL:', 'text_domain'); ?></label>
<input class="widefat shape-image-url" id="<?php echo esc_attr($this->get_field_id('shape_image')); ?>" name="<?php echo esc_attr($this->get_field_name('shape_image')); ?>" type="text" value="<?php echo esc_url($shape_image); ?>" />
</p>
<?php
}
public function update($new_instance, $old_instance)
{
$instance = array();
$instance['selected_reviews'] = (!empty($new_instance['selected_reviews'])) ? array_map('absint', $new_instance['selected_reviews']) : array();
$instance['shape_image'] = (!empty($new_instance['shape_image'])) ? esc_url_raw($new_instance['shape_image']) : '';
return $instance;
}
}
function register_customer_reviews_widget()
{
register_widget('Customer_Reviews_Widget');
}
add_action('widgets_init', 'register_customer_reviews_widget');
//custome post type: blog
function create_blog_post_type() {
register_post_type('blog',
array(
'labels' => array(
'name' => __('Blogs'),
'singular_name' => __('Blog')
),
'public' => true,
'has_archive' => true,
'rewrite' => array('slug' => 'blogs'),
'supports' => array('title', 'editor', 'thumbnail', 'excerpt', 'author'),
)
);
}
add_action('init', 'create_blog_post_type');