You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1320 lines
44 KiB
1320 lines
44 KiB
<?php
|
|
|
|
// require once вместо include использовать!
|
|
// доделать example module и component
|
|
require_once __DIR__ . '/vendor/autoload.php';
|
|
|
|
// Initialize Timber.
|
|
Timber\Timber::init();
|
|
|
|
Timber::$dirname = [
|
|
[
|
|
'modules',
|
|
'templates'
|
|
],
|
|
];
|
|
|
|
use Timber\PostCollection;
|
|
use Timber\Integrations\WooCommerce\Product as TimberProduct;
|
|
|
|
|
|
add_filter( 'timber/integrations', function ( array $integrations ): array {
|
|
$integrations[] = new \Timber\Integrations\WooCommerce\WooCommerceIntegration();
|
|
|
|
return $integrations;
|
|
} );
|
|
|
|
|
|
add_action('timber/init', function() {
|
|
// Инициализируем WooCommerce интеграцию
|
|
if (class_exists('Timber\Integrations\WooCommerce\WooCommerce')) {
|
|
Timber\Integrations\WooCommerce\WooCommerce::init();
|
|
}
|
|
});
|
|
|
|
|
|
|
|
function theme_add_woocommerce_support()
|
|
{
|
|
add_theme_support('woocommerce');
|
|
}
|
|
|
|
add_action('after_setup_theme', 'theme_add_woocommerce_support');
|
|
add_theme_support('post-thumbnails');
|
|
|
|
add_action('after_setup_theme', function() {
|
|
add_theme_support('comments');
|
|
|
|
update_option('default_comment_status', 'open');
|
|
});
|
|
|
|
|
|
|
|
//Подруключение всех ajax controller если запрос сделан по ajax
|
|
|
|
|
|
$modulesDir = __DIR__ . '/modules';
|
|
|
|
// Функция для рекурсивного подключения файлов
|
|
function requireAjaxControllers($baseDir) {
|
|
$modules = glob($baseDir . '/*', GLOB_ONLYDIR);
|
|
|
|
foreach ($modules as $module) {
|
|
$moduleController = $module . '/module-ajax-controller.php';
|
|
if (file_exists($moduleController)) {
|
|
require_once $moduleController;
|
|
}
|
|
|
|
$componentsDir = $module . '/components';
|
|
if (is_dir($componentsDir)) {
|
|
$components = glob($componentsDir . '/*', GLOB_ONLYDIR);
|
|
foreach ($components as $component) {
|
|
$componentController = $component . '/component-ajax-controller.php';
|
|
if (file_exists($componentController)) {
|
|
require_once $componentController;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function requireShortcodes($baseDir) {
|
|
$modules = glob($baseDir . '/*', GLOB_ONLYDIR);
|
|
|
|
foreach ($modules as $module) {
|
|
$componentsDir = $module . '/shortcodes';
|
|
if (is_dir($componentsDir)) {
|
|
// Рекурсивно подключаем все shortcodes.php
|
|
requireShortcodesRecursive($componentsDir);
|
|
}
|
|
}
|
|
}
|
|
|
|
function requireShortcodesRecursive($dir) {
|
|
// Получаем все подпапки в текущем каталоге
|
|
$components = glob($dir . '/*', GLOB_ONLYDIR);
|
|
|
|
foreach ($components as $component) {
|
|
// Проверяем наличие файла shortcode.php в текущей подпапке
|
|
$componentController = $component . '/shortcode.php';
|
|
if (file_exists($componentController)) {
|
|
require_once $componentController;
|
|
}
|
|
|
|
// Рекурсивно вызываем функцию для каждой найденной подпапки
|
|
requireShortcodesRecursive($component);
|
|
}
|
|
}
|
|
|
|
// Пример вызова функции
|
|
|
|
function includeFilesFromFolder($folder) {
|
|
// Проверяем, существует ли папка
|
|
if (is_dir($folder)) {
|
|
// Открываем директорию
|
|
$files = scandir($folder);
|
|
|
|
// Перебираем файлы в директории
|
|
foreach ($files as $file) {
|
|
// Пропускаем текущую и родительскую директории
|
|
if ($file !== '.' && $file !== '..') {
|
|
// Формируем полный путь к файлу
|
|
$filePath = $folder . DIRECTORY_SEPARATOR . $file;
|
|
|
|
// Проверяем, является ли это файлом и имеет ли нужное расширение (например, .php)
|
|
if (is_file($filePath) && pathinfo($filePath, PATHINFO_EXTENSION) === 'php') {
|
|
include_once $filePath; // Подключаем файл
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
throw new Exception("Директория не найдена: $folder");
|
|
}
|
|
}
|
|
|
|
// Подключает модуль из папки /modules/
|
|
function include_module($module_name) {
|
|
// Убедитесь, что имя модуля не пустое
|
|
if (empty($module_name)) {
|
|
return;
|
|
}
|
|
|
|
// Получаем путь к каталогу модуля
|
|
$module_dir = get_template_directory() . '/modules/' . $module_name;
|
|
|
|
|
|
|
|
// Регистрируем стили и скрипты
|
|
add_action('wp_enqueue_scripts', function() use ($module_name, $module_dir) {
|
|
// Подключаем стили
|
|
$css_dir = $module_dir . '/assets/css';
|
|
if (is_dir($css_dir)) {
|
|
$css_files = scandir($css_dir);
|
|
|
|
// Приоритетные файлы
|
|
$priority_files = [
|
|
'normalize.css',
|
|
'gp-style-core.css',
|
|
'gp-style-desktop.css',
|
|
'gp-style-tablet.css',
|
|
'gp-style-mobile.css'
|
|
];
|
|
|
|
// Подключаем приоритетные файлы в заданном порядке
|
|
foreach ($priority_files as $priority_file) {
|
|
$file_path = $css_dir . '/' . $priority_file;
|
|
if (file_exists($file_path)) {
|
|
wp_enqueue_style(
|
|
$module_name . '-' . pathinfo($priority_file, PATHINFO_FILENAME),
|
|
get_template_directory_uri() . '/modules/' . $module_name . '/assets/css/' . $priority_file,
|
|
[],
|
|
filemtime($file_path)
|
|
);
|
|
}
|
|
}
|
|
|
|
// Подключаем остальные CSS-файлы
|
|
foreach ($css_files as $css_file) {
|
|
if (
|
|
pathinfo($css_file, PATHINFO_EXTENSION) === 'css' &&
|
|
$css_file !== '.' &&
|
|
$css_file !== '..' &&
|
|
!in_array($css_file, $priority_files)
|
|
) {
|
|
$file_path = $css_dir . '/' . $css_file;
|
|
wp_enqueue_style(
|
|
$module_name . '-' . pathinfo($css_file, PATHINFO_FILENAME),
|
|
get_template_directory_uri() . '/modules/' . $module_name . '/assets/css/' . $css_file,
|
|
[],
|
|
filemtime($file_path)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Подключаем скрипты
|
|
$js_dir = $module_dir . '/assets/js';
|
|
if (is_dir($js_dir)) {
|
|
$js_files = scandir($js_dir);
|
|
foreach ($js_files as $js_file) {
|
|
if (
|
|
pathinfo($js_file, PATHINFO_EXTENSION) === 'js' &&
|
|
$js_file !== '.' &&
|
|
$js_file !== '..'
|
|
) {
|
|
$file_path = $js_dir . '/' . $js_file;
|
|
wp_enqueue_script(
|
|
$module_name . '-' . pathinfo($js_file, PATHINFO_FILENAME),
|
|
get_template_directory_uri() . '/modules/' . $module_name . '/assets/js/' . $js_file,
|
|
['jquery'],
|
|
filemtime($file_path),
|
|
true
|
|
);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
// Подключаем контроллер модуля
|
|
$module_controller = $module_dir . '/module-controller.php';
|
|
if (file_exists($module_controller)) {
|
|
include_once $module_controller ;
|
|
}
|
|
|
|
}
|
|
|
|
function include_component($module_name, $component_name) {
|
|
// Убедитесь, что имя модуля и компонента не пустые
|
|
if (empty($module_name) || empty($component_name)) {
|
|
return;
|
|
}
|
|
|
|
// Получаем путь к каталогу модуля
|
|
$component_dir = get_template_directory() . '/modules/' . $module_name . '/components/' . $component_name;
|
|
|
|
// Регистрируем стили и скрипты
|
|
add_action('wp_enqueue_scripts', function() use ($module_name, $component_name, $component_dir) {
|
|
// Подключаем стили
|
|
$css_dir = $component_dir . '/assets/css';
|
|
if (is_dir($css_dir)) {
|
|
$css_files = scandir($css_dir);
|
|
|
|
// Приоритетные файлы в нужном порядке
|
|
$priority_files = [
|
|
'gp-style-core.css',
|
|
'gp-style-desktop.css',
|
|
'gp-style-tablet.css',
|
|
'gp-style-mobile.css'
|
|
];
|
|
|
|
// Подключаем приоритетные файлы в заданном порядке
|
|
foreach ($priority_files as $priority_file) {
|
|
$file_path = $css_dir . '/' . $priority_file;
|
|
if (file_exists($file_path)) {
|
|
$handle = "{$module_name}-{$component_name}-" . pathinfo($priority_file, PATHINFO_FILENAME);
|
|
$src = get_template_directory_uri() . "/modules/{$module_name}/components/{$component_name}/assets/css/{$priority_file}";
|
|
wp_enqueue_style($handle, $src, [], filemtime($file_path)); // Используем filemtime для версии
|
|
}
|
|
}
|
|
|
|
// Подключаем остальные CSS-файлы
|
|
foreach ($css_files as $css_file) {
|
|
if (pathinfo($css_file, PATHINFO_EXTENSION) === 'css' && !in_array($css_file, $priority_files)) {
|
|
$file_path = $css_dir . '/' . $css_file;
|
|
$handle = "{$module_name}-{$component_name}-" . pathinfo($css_file, PATHINFO_FILENAME);
|
|
$src = get_template_directory_uri() . "/modules/{$module_name}/components/{$component_name}/assets/css/{$css_file}";
|
|
wp_enqueue_style($handle, $src, [], filemtime($file_path));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Подключаем скрипты
|
|
$js_dir = $component_dir . '/assets/js';
|
|
if (is_dir($js_dir)) {
|
|
$js_files = scandir($js_dir);
|
|
foreach ($js_files as $js_file) {
|
|
if (pathinfo($js_file, PATHINFO_EXTENSION) === 'js') {
|
|
$file_path = $js_dir . '/' . $js_file;
|
|
$handle = "{$module_name}-{$component_name}-" . pathinfo($js_file, PATHINFO_FILENAME);
|
|
$src = get_template_directory_uri() . "/modules/{$module_name}/components/{$component_name}/assets/js/{$js_file}";
|
|
wp_enqueue_script($handle, $src, ['jquery'], filemtime($file_path), true);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
$component_controller = $component_dir . '/component-controller.php';
|
|
if (file_exists($component_controller)) {
|
|
include_once $component_controller ;
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* Регистрируем шаблоны из всех подпапок /templates/
|
|
*/
|
|
add_filter('theme_page_templates', function ($templates) {
|
|
// Путь к папке с шаблонами
|
|
$custom_templates_dir = get_template_directory() . '/templates/';
|
|
|
|
// Ищем ВСЕ PHP-файлы в /templates/ и подпапках
|
|
$all_templates = new RecursiveIteratorIterator(
|
|
new RecursiveDirectoryIterator($custom_templates_dir)
|
|
);
|
|
|
|
foreach ($all_templates as $template_file) {
|
|
// Пропускаем не-PHP файлы и папки
|
|
if ($template_file->isDir() || $template_file->getExtension() !== 'php') {
|
|
continue;
|
|
}
|
|
|
|
// Получаем относительный путь (например, "pages/template-landing.php")
|
|
$relative_path = str_replace($custom_templates_dir, '', $template_file->getPathname());
|
|
|
|
// Формируем имя шаблона (убираем .php и заменяем слэши на дефисы)
|
|
$template_name = str_replace(['/', '.php'], [' - ', ''], $relative_path);
|
|
|
|
// Добавляем в список шаблонов
|
|
$templates['templates/' . $relative_path] = $template_name;
|
|
}
|
|
|
|
return $templates;
|
|
});
|
|
|
|
includeFilesFromFolder(get_template_directory() . '/global-functions');
|
|
|
|
|
|
|
|
// Add the function to the Timber context
|
|
add_filter('timber/context', function($context) {
|
|
$context['template_path'] = get_template_directory_uri();
|
|
$current_url = "http://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
|
$context['current_url'] = htmlspecialchars($current_url);
|
|
return $context;
|
|
});
|
|
|
|
/**
|
|
* Подключает статические CSS и JS файлы из указанной директории
|
|
*
|
|
* @param string $dir_name Название директории в папке /static/
|
|
* @param array $options Дополнительные параметры:
|
|
* - 'css' => false - отключить подключение CSS
|
|
* - 'js' => false - отключить подключение JS
|
|
* - 'version' => string - версия файлов (по умолчанию использует время модификации файла)
|
|
*/
|
|
function enqueue_static_assets($dir_name, $options = []) {
|
|
// Устанавливаем пути к директориям
|
|
$static_dir = get_template_directory() . '/static/' . $dir_name;
|
|
$static_uri = get_template_directory_uri() . '/static/' . $dir_name;
|
|
|
|
// Подключаем CSS файлы
|
|
if (!isset($options['css']) || $options['css'] !== false) {
|
|
$css_dir = $static_dir . '/css/';
|
|
if (file_exists($css_dir)) {
|
|
$css_files = scandir($css_dir);
|
|
foreach ($css_files as $file) {
|
|
if (pathinfo($file, PATHINFO_EXTENSION) === 'css') {
|
|
$handle = $dir_name . '-' . pathinfo($file, PATHINFO_FILENAME);
|
|
$src = $static_uri . '/css/' . $file;
|
|
$ver = isset($options['version']) ? $options['version'] : filemtime($css_dir . $file);
|
|
|
|
wp_enqueue_style(
|
|
$handle,
|
|
$src,
|
|
array(),
|
|
$ver
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Подключаем JS файлы
|
|
if (!isset($options['js']) || $options['js'] !== false) {
|
|
$js_dir = $static_dir . '/js/';
|
|
if (file_exists($js_dir)) {
|
|
$js_files = scandir($js_dir);
|
|
foreach ($js_files as $file) {
|
|
if (pathinfo($file, PATHINFO_EXTENSION) === 'js') {
|
|
$handle = $dir_name . '-' . pathinfo($file, PATHINFO_FILENAME);
|
|
$src = $static_uri . '/js/' . $file;
|
|
$ver = isset($options['version']) ? $options['version'] : filemtime($js_dir . $file);
|
|
$in_footer = strpos($file, 'admin') === 0 ? false : true;
|
|
|
|
wp_enqueue_script(
|
|
$handle,
|
|
$src,
|
|
array(),
|
|
$ver,
|
|
$in_footer
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
add_action('init', function() {
|
|
if (function_exists('wpseo_load_textdomain')) {
|
|
wpseo_load_textdomain();
|
|
}
|
|
if (function_exists('pll_load_textdomain')) {
|
|
pll_load_textdomain();
|
|
}
|
|
add_filter('timber/context', function($context) {
|
|
$context['current_lang'] = pll_current_language();
|
|
return $context;
|
|
});
|
|
}, 1);
|
|
|
|
|
|
$modules_path = get_template_directory() . '/modules/*/editor-blocks/*/editor-block-controller.php';
|
|
foreach (glob($modules_path) as $file) {
|
|
require_once $file; // Подключаем каждый найденный файл
|
|
}
|
|
|
|
|
|
requireShortcodes(get_template_directory() . '/modules');
|
|
|
|
require_once('modules/blog/module-ajax-controller.php');
|
|
require_once('modules/forms/module-ajax-controller.php');
|
|
require_once('modules/shop/module-ajax-controller.php');
|
|
require_once('modules/profile/module-ajax-controller.php');
|
|
|
|
|
|
add_action('wp', 'my_custom_checkout_code');
|
|
function my_custom_checkout_code() {
|
|
if (function_exists('is_checkout') && is_checkout() && !is_order_received_page()) {
|
|
include_component('shop', 'checkout');
|
|
}
|
|
}
|
|
|
|
require_once('modules/author/module-ajax-controller.php');
|
|
|
|
include_module('forms');
|
|
include_module('layout');
|
|
|
|
|
|
class WooProduct extends Timber\Post {
|
|
protected $wc_product;
|
|
|
|
public function __construct ($pid = null) {
|
|
parent::__construct($pid);
|
|
$this->wc_product = wc_get_product($this->ID);
|
|
}
|
|
|
|
public function price() {
|
|
return $this->wc_product->get_price();
|
|
}
|
|
|
|
public function get_price_html() {
|
|
return $this->wc_product->get_price_html();
|
|
}
|
|
|
|
public function get_attr() {
|
|
return $this->wc_product->get_attribute('pa_compound');
|
|
}
|
|
|
|
public function get_test() {
|
|
return 'test';
|
|
}
|
|
|
|
};
|
|
|
|
add_filter('timber/post/classmap', function ($classmap) {
|
|
$custom_classmap = [
|
|
'product' => WooProduct::class,
|
|
];
|
|
return array_merge($classmap, $custom_classmap);
|
|
});
|
|
|
|
//Ajax подгрузка товаров в архиве
|
|
add_action( 'wp_ajax_nopriv_get_products', 'get_products' );
|
|
add_action( 'wp_ajax_get_products', 'get_products' );
|
|
|
|
function get_products() {
|
|
global $post;
|
|
|
|
if (function_exists('WC')) {
|
|
WC();
|
|
}
|
|
|
|
// Потом Timber
|
|
|
|
$context = Timber::context();
|
|
$context['get_page'] = empty($_POST['get_page']) ? 1 : $_POST['get_page'];
|
|
$context['criteria_for_new_product'] = date('Y-m-d', strtotime('-30 days'));
|
|
$context['get_category'] = isset($_POST['get_category']) ? $_POST['get_category'] : NULL;
|
|
$context['get_category_type'] = isset($_POST['get_category_type']) ? $_POST['get_category_type'] : NULL;
|
|
|
|
// Задаем количество постов для подзагрузки Ajax
|
|
$posts_per_page = 12;
|
|
|
|
$args = array(
|
|
'post_type' => 'product',
|
|
'post_status' => 'publish',
|
|
'posts_per_page' => $posts_per_page,
|
|
'paged' => $context['get_page'],
|
|
'has_password' => FALSE
|
|
);
|
|
|
|
$count_args = array(
|
|
'post_type' => 'product',
|
|
'post_status' => 'publish',
|
|
'posts_per_page' => -1,
|
|
'has_password' => FALSE
|
|
);
|
|
|
|
if ($context['get_category'] != NULL) {
|
|
$categories = [
|
|
'tax_query' => array(
|
|
array(
|
|
'taxonomy' => $context['get_category_type'],
|
|
'field' => 'term_id',
|
|
'terms' => array($context['get_category']),
|
|
'operator' => 'IN'
|
|
),
|
|
array(
|
|
'taxonomy' => 'product_visibility',
|
|
'field' => 'slug',
|
|
'terms' => 'exclude-from-catalog',
|
|
'operator' => 'NOT IN'
|
|
)
|
|
)
|
|
];
|
|
$args = array_merge($args, $categories);
|
|
$count_args = array_merge($count_args, $categories);
|
|
}
|
|
|
|
$products = new WP_Query($args);
|
|
$products = new Timber\PostQuery($products, 'Timber\Integrations\WooCommerce\Product');
|
|
|
|
$context['posts'] = $products;
|
|
|
|
$context['count'] = count(Timber::get_posts($count_args));
|
|
|
|
if ($context['count'] <= $context['get_page'] * $posts_per_page) {
|
|
$context['ended'] = true;
|
|
}
|
|
|
|
Timber::render( 'woocommerce/archive-product/archive-product-ajaxload.twig', $context );
|
|
|
|
die();
|
|
}
|
|
|
|
function get_product_info ($id, $type) {
|
|
if (!$id) {
|
|
return '';
|
|
}
|
|
$product = wc_get_product($id);
|
|
if (!$product) {
|
|
return '';
|
|
}
|
|
if ($type == 'price') {
|
|
return $product->get_price();
|
|
} elseif ($type == 'weight') {
|
|
return $product->get_weight() ? $product->get_weight() . ' кг' : '';
|
|
}
|
|
return '';
|
|
}
|
|
|
|
function get_add_to_cart_button ($id) {
|
|
$product = wc_get_product( $id );
|
|
return '<a href="'. $product->add_to_cart_url(). '" value="'. esc_attr( $product->get_id() ) .'"
|
|
class="ajax_add_to_cart add_to_cart_button button button--gradient button--base button--100-perc" data-product_id="'. $id .'">'. pll__('Добавить в корзину') .'</a>';
|
|
}
|
|
|
|
function get_collection_siblings ($term) {
|
|
if (!$term) {
|
|
return [];
|
|
}
|
|
|
|
$args = array(
|
|
'posts_per_page' => -1,
|
|
'post_type' => 'product',
|
|
'order' => 'ASC',
|
|
'order_by' => 'name',
|
|
'tax_query' => [
|
|
[
|
|
'taxonomy' => 'pa_collection',
|
|
'terms' => $term,
|
|
'field' => 'id',
|
|
]
|
|
],
|
|
);
|
|
|
|
$siblings = get_posts($args);
|
|
|
|
$sibl_arr = [];
|
|
|
|
foreach( $siblings as $sibling ) {
|
|
$sibl_arr [] = $sibling;
|
|
}
|
|
|
|
return $sibl_arr;
|
|
}
|
|
|
|
register_sidebar( array(
|
|
'name' => 'Сайдбар для фильтров товаров',
|
|
'id' => 'sidebar_filters',
|
|
'before_widget' => '<div id="%1$s" class="widget %2$s">',
|
|
'after_widget' => '</div>',
|
|
'before_title' => '<h3 class="widget-title">',
|
|
'after_title' => '</h3>',
|
|
) );
|
|
|
|
|
|
// Define encryption secret key
|
|
define('SECRET', 'fT54ehYtt87@q1A');
|
|
|
|
/**
|
|
* Email Validation
|
|
* Validates the format of the provided email via AJAX.
|
|
*/
|
|
add_action('wp_ajax_email_validate', 'email_validate');
|
|
add_action('wp_ajax_nopriv_email_validate', 'email_validate');
|
|
|
|
function email_validate() {
|
|
if (filter_var($_POST['email'], FILTER_VALIDATE_EMAIL) === false) {
|
|
header("Content-Type: application/json");
|
|
echo json_encode(array(
|
|
'status' => 'error',
|
|
'text' => esc_html__('Invalid email format', 'woodmart')
|
|
));
|
|
}
|
|
wp_die();
|
|
}
|
|
|
|
/**
|
|
* Send Verification Code
|
|
* Generates a random code, encrypts it, stores it in a cookie, and sends it via email.
|
|
*/
|
|
add_action('wp_ajax_send_code', 'send_code');
|
|
add_action('wp_ajax_nopriv_send_code', 'send_code');
|
|
|
|
function send_code() {
|
|
$email = $_POST['email'];
|
|
|
|
// Generate a random 4-digit code
|
|
$string = rand(1234, 9999);
|
|
$ciphering = "AES-128-CTR";
|
|
$options = 0;
|
|
$iv = '1234567891011121';
|
|
$encryption = openssl_encrypt($string, $ciphering, SECRET, $options, $iv);
|
|
|
|
// Store encrypted code in a cookie for 5 minutes
|
|
setcookie('login_code', $encryption, time() + 60 * 5, '/');
|
|
|
|
// Prepare email content based on language
|
|
if (function_exists('pll_current_language') && pll_current_language() === 'ru') {
|
|
$subject = "Проверочный код Cosmopet -" . $string;
|
|
$message = "Привет, это Cosmopet.\n
|
|
Держите проверочный код!\n
|
|
" . $string;
|
|
} else {
|
|
$subject = "Cosmopet Verification Code -" . $string;
|
|
$message = "Hello, this is CosmoPet.\n
|
|
Here's your verification code!\n
|
|
" . $string;
|
|
}
|
|
|
|
// Remove email filters for consistent sending
|
|
remove_all_filters('wp_mail_from');
|
|
remove_all_filters('wp_mail_from_name');
|
|
$headers = array(
|
|
'From: Cosmopet <pro@cosmopet.shop>',
|
|
'content-type: text/html; charset=utf-8',
|
|
);
|
|
|
|
// Send email
|
|
wp_mail($email, $subject, $message, $headers);
|
|
|
|
wp_die();
|
|
}
|
|
|
|
/**
|
|
* Check Verification Code
|
|
* Validates the user-entered code, logs in or registers the user.
|
|
*/
|
|
add_action('wp_ajax_check_code', 'check_code');
|
|
add_action('wp_ajax_nopriv_check_code', 'check_code');
|
|
|
|
function check_code() {
|
|
header("Content-Type: application/json");
|
|
|
|
$code = $_POST['code'];
|
|
$email = $_POST['email'];
|
|
|
|
// Generate a random 12-character password
|
|
$alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890@#!()';
|
|
$pass = array();
|
|
$alphaLength = strlen($alphabet) - 1;
|
|
for ($i = 0; $i < 12; $i++) {
|
|
$n = rand(0, $alphaLength);
|
|
$pass[] = $alphabet[$n];
|
|
}
|
|
$pass = implode($pass);
|
|
|
|
// Check if verification code cookie exists
|
|
if (isset($_COOKIE['login_code'])) {
|
|
$string = $_COOKIE['login_code'];
|
|
$ciphering = "AES-128-CTR";
|
|
$options = 0;
|
|
$iv = '1234567891011121';
|
|
$decryption = openssl_decrypt($string, $ciphering, SECRET, $options, $iv);
|
|
|
|
if ($decryption === $code) {
|
|
if (email_exists($email)) {
|
|
// Log in existing user
|
|
$user_id = get_user_by('login', $email)->ID;
|
|
if (empty($user_id)) {
|
|
$user_id = get_user_by('email', $email)->ID;
|
|
}
|
|
wp_set_password($pass, $user_id);
|
|
wp_signon(
|
|
array(
|
|
'user_login' => $email,
|
|
'user_password' => $pass,
|
|
'remember' => 'on',
|
|
)
|
|
);
|
|
|
|
echo json_encode(array(
|
|
'status' => 'success_auth'
|
|
));
|
|
if (function_exists('update_field')) {
|
|
update_field('activated', true, 'user_' . $user_id); // Requires ACF
|
|
}
|
|
exit();
|
|
} else {
|
|
// Register new user
|
|
$user_id = wp_create_user($email, $pass, $email);
|
|
wp_update_user([
|
|
'ID' => $user_id,
|
|
'user_email' => $email
|
|
]);
|
|
|
|
wp_set_auth_cookie($user_id, true);
|
|
echo json_encode(array(
|
|
'status' => 'success_reg'
|
|
));
|
|
if (function_exists('update_field')) {
|
|
update_field('activated', true, 'user_' . $user_id); // Requires ACF
|
|
}
|
|
exit();
|
|
}
|
|
} else {
|
|
echo json_encode(array(
|
|
'status' => 'error',
|
|
'text' => esc_html__('Invalid code', 'woodmart')
|
|
));
|
|
exit();
|
|
}
|
|
} else {
|
|
echo json_encode(array(
|
|
'status' => 'error',
|
|
'text' => esc_html__('The code hasexpired', 'woodmart')
|
|
));
|
|
exit();
|
|
}
|
|
wp_die();
|
|
}
|
|
|
|
/**
|
|
* Logout Redirect
|
|
* Redirects to the homepage after user logout.
|
|
*/
|
|
add_action('wp_logout', 'logout_redirect');
|
|
|
|
function logout_redirect() {
|
|
wp_redirect('/');
|
|
exit();
|
|
}
|
|
|
|
add_filter( 'woocommerce_price_trim_zeros', '__return_true' );
|
|
|
|
function add_comment_like() {
|
|
global $wpdb;
|
|
$table_name = $wpdb->prefix . 'cosmopet_likes';
|
|
$wpdb->show_errors();
|
|
if (!is_user_logged_in()) {
|
|
wp_send_json_error('Необходимо авторизоваться');
|
|
die();
|
|
}
|
|
$comment_id = isset($_POST['comment_id']) ? intval($_POST['comment_id']) : 0;
|
|
$user_id = get_current_user_id();
|
|
if ($comment_id) {
|
|
$comment_exists = get_comment($comment_id);
|
|
if (!$comment_exists) {
|
|
echo '0';
|
|
die();
|
|
}
|
|
$existing_like = $wpdb->get_var($wpdb->prepare(
|
|
"SELECT COUNT(*) FROM $table_name WHERE comment_id = %d AND user_id = %d",
|
|
$comment_id, $user_id
|
|
));
|
|
if (!$existing_like) {
|
|
$result = $wpdb->insert(
|
|
$table_name,
|
|
array(
|
|
'user_id' => $user_id,
|
|
'comment_id' => $comment_id,
|
|
'date_added' => current_time('mysql')
|
|
),
|
|
array('%d', '%d', '%s')
|
|
);
|
|
} else {
|
|
$result = $wpdb->delete(
|
|
$table_name,
|
|
array(
|
|
'user_id' => $user_id,
|
|
'comment_id' => $comment_id
|
|
),
|
|
array('%d', '%d')
|
|
);
|
|
}
|
|
$likes = get_comment_likes_count($comment_id);
|
|
wp_send_json(array(
|
|
'count' => $likes,
|
|
'is_liked' => !$existing_like
|
|
));
|
|
} else {
|
|
wp_send_json(array('count' => 0, 'is_liked' => false));
|
|
}
|
|
die();
|
|
}
|
|
add_action('wp_ajax_add_comment_like', 'add_comment_like');
|
|
|
|
function add_post_like() {
|
|
global $wpdb;
|
|
$table_name = $wpdb->prefix . 'cosmopet_likes';
|
|
if (!is_user_logged_in()) {
|
|
wp_send_json_error('Необходимо авторизоваться');
|
|
die();
|
|
}
|
|
$post_id = isset($_POST['post_id']) ? intval($_POST['post_id']) : 0;
|
|
$user_id = get_current_user_id();
|
|
if ($post_id) {
|
|
$existing_like = $wpdb->get_var($wpdb->prepare(
|
|
"SELECT COUNT(*) FROM $table_name WHERE post_id = %d AND user_id = %d",
|
|
$post_id, $user_id
|
|
));
|
|
if (!$existing_like) {
|
|
$wpdb->insert(
|
|
$table_name,
|
|
array(
|
|
'user_id' => $user_id,
|
|
'post_id' => $post_id,
|
|
'date_added' => current_time('mysql')
|
|
),
|
|
array('%d', '%d', '%s')
|
|
);
|
|
} else {
|
|
$wpdb->delete(
|
|
$table_name,
|
|
array(
|
|
'user_id' => $user_id,
|
|
'post_id' => $post_id
|
|
),
|
|
array('%d', '%d')
|
|
);
|
|
}
|
|
$likes = get_post_likes_count($post_id);
|
|
wp_send_json(array(
|
|
'count' => $likes,
|
|
'is_liked' => !$existing_like
|
|
));
|
|
}
|
|
die();
|
|
}
|
|
add_action('wp_ajax_add_post_like', 'add_post_like');
|
|
|
|
function check_user_likes() {
|
|
global $wpdb;
|
|
$table_name = $wpdb->prefix . 'cosmopet_likes';
|
|
if (!is_user_logged_in()) {
|
|
wp_send_json_error('Необходимо авторизоваться');
|
|
die();
|
|
}
|
|
$user_id = get_current_user_id();
|
|
$liked_posts = $wpdb->get_col($wpdb->prepare(
|
|
"SELECT post_id FROM $table_name WHERE user_id = %d AND post_id > 0",
|
|
$user_id
|
|
));
|
|
$liked_comments = $wpdb->get_col($wpdb->prepare(
|
|
"SELECT comment_id FROM $table_name WHERE user_id = %d AND comment_id > 0",
|
|
$user_id
|
|
));
|
|
$response = array(
|
|
'posts' => $liked_posts,
|
|
'comments' => $liked_comments
|
|
);
|
|
echo json_encode($response);
|
|
die();
|
|
}
|
|
add_action('wp_ajax_check_user_likes', 'check_user_likes');
|
|
|
|
|
|
|
|
function get_post_likes_count($post_id) {
|
|
global $wpdb;
|
|
$table_name = $wpdb->prefix . 'cosmopet_likes';
|
|
$count = $wpdb->get_var($wpdb->prepare(
|
|
"SELECT COUNT(*) FROM $table_name WHERE post_id = %d",
|
|
$post_id
|
|
));
|
|
return $count ? $count : 0;
|
|
}
|
|
|
|
function get_comment_likes_count($comment_id) {
|
|
global $wpdb;
|
|
$table_name = $wpdb->prefix . 'cosmopet_likes';
|
|
$count = $wpdb->get_var($wpdb->prepare(
|
|
"SELECT COUNT(*) FROM $table_name WHERE comment_id = %d",
|
|
$comment_id
|
|
));
|
|
return $count ? $count : 0;
|
|
}
|
|
|
|
function is_user_liked_post($post_id) {
|
|
if (!is_user_logged_in()) {
|
|
return false;
|
|
}
|
|
global $wpdb;
|
|
$table_name = $wpdb->prefix . 'cosmopet_likes';
|
|
$user_id = get_current_user_id();
|
|
$result = $wpdb->get_var($wpdb->prepare(
|
|
"SELECT COUNT(*) FROM $table_name WHERE post_id = %d AND user_id = %d",
|
|
$post_id, $user_id
|
|
));
|
|
return $result > 0;
|
|
}
|
|
|
|
|
|
function is_user_liked_comment($comment_id) {
|
|
if (!is_user_logged_in()) {
|
|
return false;
|
|
}
|
|
global $wpdb;
|
|
$table_name = $wpdb->prefix . 'cosmopet_likes';
|
|
$user_id = get_current_user_id();
|
|
$result = $wpdb->get_var($wpdb->prepare(
|
|
"SELECT COUNT(*) FROM $table_name WHERE comment_id = %d AND user_id = %d",
|
|
$comment_id, $user_id
|
|
));
|
|
return $result > 0;
|
|
}
|
|
|
|
|
|
add_filter('comment_form_logged_in', '__return_empty_string');
|
|
|
|
|
|
// Создание таблицы
|
|
function create_likes_table() {
|
|
global $wpdb;
|
|
$table_name = $wpdb->prefix . 'cosmopet_likes';
|
|
$charset_collate = $wpdb->get_charset_collate();
|
|
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
|
|
id bigint(20) NOT NULL AUTO_INCREMENT,
|
|
user_id bigint(20) NOT NULL,
|
|
post_id bigint(20) DEFAULT '0',
|
|
comment_id bigint(20) DEFAULT '0',
|
|
date_added datetime DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (id),
|
|
KEY post_id (post_id),
|
|
KEY comment_id (comment_id),
|
|
KEY user_id (user_id),
|
|
UNIQUE KEY user_post (user_id, post_id, comment_id)
|
|
) $charset_collate;";
|
|
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
|
|
dbDelta($sql);
|
|
}
|
|
add_action('after_switch_theme', 'create_likes_table');
|
|
|
|
|
|
|
|
add_filter('woocommerce_product_data_tabs', function($tabs) {
|
|
$tabs['composition_tab'] = array(
|
|
'label' => 'Состав',
|
|
'target' => 'composition_product_data',
|
|
'class' => array('composition_tab'),
|
|
'priority' => 60,
|
|
);
|
|
$tabs['feeding_tab'] = array(
|
|
'label' => 'Рекомендации по кормлению',
|
|
'target' => 'feeding_product_data',
|
|
'class' => array('feeding_tab'),
|
|
'priority' => 61,
|
|
);
|
|
$tabs['important_tab'] = array(
|
|
'label' => 'Важно',
|
|
'target' => 'important_product_data',
|
|
'class' => array('important_tab'),
|
|
'priority' => 62,
|
|
);
|
|
return $tabs;
|
|
});
|
|
|
|
|
|
add_action('woocommerce_product_data_panels', function() {
|
|
global $post;
|
|
$composition = get_post_meta($post->ID, '_composition', true);
|
|
echo '<div id="composition_product_data" class="panel woocommerce_options_panel">';
|
|
woocommerce_wp_textarea_input([
|
|
'id' => '_composition',
|
|
'label' => 'Состав',
|
|
'desc_tip' => true,
|
|
'description' => 'Введите состав товара',
|
|
'value' => $composition
|
|
]);
|
|
echo '</div>';
|
|
});
|
|
|
|
|
|
add_action('woocommerce_product_data_panels', function() {
|
|
global $post;
|
|
$feeding = get_post_meta($post->ID, '_feeding_recommendations', true);
|
|
echo '<div id="feeding_product_data" class="panel woocommerce_options_panel">';
|
|
woocommerce_wp_textarea_input([
|
|
'id' => '_feeding_recommendations',
|
|
'label' => 'Рекомендации по кормлению',
|
|
'desc_tip' => true,
|
|
'description' => 'Введите рекомендации по кормлению',
|
|
'value' => $feeding
|
|
]);
|
|
echo '</div>';
|
|
});
|
|
|
|
|
|
add_action('woocommerce_product_data_panels', function() {
|
|
global $post;
|
|
$important = get_post_meta($post->ID, '_important', true);
|
|
echo '<div id="important_product_data" class="panel woocommerce_options_panel">';
|
|
woocommerce_wp_textarea_input([
|
|
'id' => '_important',
|
|
'label' => 'Важно',
|
|
'desc_tip' => true,
|
|
'description' => 'Введите важную информацию',
|
|
'value' => $important
|
|
]);
|
|
echo '</div>';
|
|
});
|
|
|
|
add_action('woocommerce_process_product_meta', function($post_id) {
|
|
if (isset($_POST['_composition'])) {
|
|
update_post_meta($post_id, '_composition', sanitize_textarea_field($_POST['_composition']));
|
|
}
|
|
if (isset($_POST['_feeding_recommendations'])) {
|
|
update_post_meta($post_id, '_feeding_recommendations', sanitize_textarea_field($_POST['_feeding_recommendations']));
|
|
}
|
|
if (isset($_POST['_important'])) {
|
|
update_post_meta($post_id, '_important', sanitize_textarea_field($_POST['_important']));
|
|
}
|
|
});
|
|
// Добавление поля для выбора рекомендуемых товаров
|
|
function register_recommended_products_acf_field() {
|
|
if (function_exists('acf_add_local_field_group')) {
|
|
acf_add_local_field_group(array(
|
|
'key' => 'group_recommended_products',
|
|
'title' => 'Рекомендуемые товары',
|
|
'fields' => array(
|
|
array(
|
|
'key' => 'field_recommended_products',
|
|
'label' => 'Выберите рекомендуемые товары',
|
|
'name' => 'recommended_products',
|
|
'type' => 'relationship',
|
|
'instructions' => 'Выберите товары, которые будут отображаться в секции "вашему питомцу может понравиться"',
|
|
'required' => 0,
|
|
'conditional_logic' => 0,
|
|
'post_type' => array(
|
|
0 => 'product',
|
|
),
|
|
'filters' => array(
|
|
0 => 'search',
|
|
1 => 'taxonomy',
|
|
),
|
|
'return_format' => 'object',
|
|
'min' => '',
|
|
'max' => 8,
|
|
),
|
|
),
|
|
'location' => array(
|
|
array(
|
|
array(
|
|
'param' => 'post_type',
|
|
'operator' => '==',
|
|
'value' => 'product',
|
|
),
|
|
),
|
|
),
|
|
'menu_order' => 0,
|
|
'position' => 'normal',
|
|
'style' => 'default',
|
|
'label_placement' => 'top',
|
|
'instruction_placement' => 'label',
|
|
'hide_on_screen' => '',
|
|
));
|
|
}
|
|
}
|
|
add_action('acf/init', 'register_recommended_products_acf_field');
|
|
|
|
add_action('wp_footer', 'remove_view_cart_button_js');
|
|
function remove_view_cart_button_js() {
|
|
?>
|
|
<script>
|
|
jQuery(document).ready(function($) {
|
|
$(document).on('added_to_cart', function() {
|
|
$('.added_to_cart.wc-forward').remove();
|
|
});
|
|
});
|
|
</script>
|
|
<?php
|
|
}
|
|
|
|
|
|
add_filter( 'script_loader_tag', function ( $tag, $handle, $src ) {
|
|
$module_handles = [
|
|
'shop-single-product-tabs', // для tabs.js
|
|
'shop-single-product-toggle', // для toggle.js
|
|
];
|
|
if ( in_array( $handle, $module_handles ) ) {
|
|
return '<script type="module" src="' . esc_url( $src ) . '"></script>';
|
|
}
|
|
return $tag;
|
|
}, 10, 3 );
|
|
|
|
// Для кнопки "Применить фильтр"
|
|
add_filter('wbw_filter_submit_button_text', 'change_wbw_filter_button_text');
|
|
function change_wbw_filter_button_text($text) {
|
|
return 'Ваш текст'; // Например, "Фильтровать" или "Поиск"
|
|
}
|
|
|
|
// Для кнопки сброса (если есть)
|
|
add_filter('wbw_filter_reset_button_text', 'change_wbw_reset_button_text');
|
|
function change_wbw_reset_button_text($text) {
|
|
return 'Сбросить';
|
|
}
|
|
|
|
|
|
add_action('wp_ajax_get_cart_fragment', 'get_cart_fragment_callback');
|
|
add_action('wp_ajax_nopriv_get_cart_fragment', 'get_cart_fragment_callback');
|
|
|
|
function get_cart_fragment_callback() {
|
|
// Проверяем nonce для безопасности
|
|
check_ajax_referer('woocommerce-cart', 'security', false);
|
|
|
|
// Получаем содержимое корзины
|
|
ob_start();
|
|
wc_get_template('shop/cart-contents.twig', [], '', get_template_directory() . '/templates/');
|
|
$contents = ob_get_clean();
|
|
|
|
// Получаем футер корзины
|
|
ob_start();
|
|
wc_get_template('modal-basket-footer.twig', [], '', get_template_directory() . '/templates/');
|
|
$footer = ob_get_clean();
|
|
|
|
// Получаем данные корзины
|
|
$cart = WC()->cart;
|
|
$count = $cart->get_cart_contents_count();
|
|
$total = $cart->get_total('raw'); // Числовая сумма
|
|
$total_html = wc_cart_totals_order_total_html(); // Форматированная сумма
|
|
|
|
wp_send_json_success([
|
|
'contents' => $contents,
|
|
'footer' => $footer,
|
|
'count' => $count,
|
|
'total' => $total_html,
|
|
'total_raw' => $total
|
|
]);
|
|
}
|
|
|
|
add_action('template_redirect', 'custom_redirect_cart_page');
|
|
function custom_redirect_cart_page() {
|
|
if (is_cart()) {
|
|
wp_redirect(home_url('/'));
|
|
exit;
|
|
}
|
|
}
|
|
|
|
add_action('wp_enqueue_scripts', 'remove_woocommerce_styles_on_checkout', 9999);
|
|
function remove_woocommerce_styles_on_checkout() {
|
|
// Проверяем, что мы на странице чекаута
|
|
if (function_exists('is_checkout') && is_checkout() && !is_order_received_page()) {
|
|
wp_deregister_style('woocommerce-layout');
|
|
wp_deregister_style('woocommerce-smallscreen');
|
|
wp_deregister_style('woocommerce-general');
|
|
|
|
// Дополнительно: отключить другие стили WooCommerce
|
|
wp_dequeue_style('select2');
|
|
wp_deregister_style('select2');
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Добавляем hreflang теги для cosmopet.shop
|
|
add_action('wp_head', 'custom_hreflang_shop', 6);
|
|
function custom_hreflang_shop() {
|
|
// Защищаем от дублирования
|
|
static $hreflang_added = false;
|
|
if ($hreflang_added) {
|
|
return;
|
|
}
|
|
$hreflang_added = true;
|
|
|
|
$current_path = add_query_arg('', $_SERVER['REQUEST_URI']);
|
|
$ru_domain = 'https://cosmopet-test-ru.cp.good-production.xyz';
|
|
$en_domain = 'https://cosmopet-test-ae.cp.good-production.xyz';
|
|
|
|
echo '<link rel="alternate" hreflang="ru-RU" href="' . esc_url($ru_domain . $current_path) . '" />' . "\n";
|
|
echo '<link rel="alternate" hreflang="en-AE" href="' . esc_url($en_domain . $current_path) . '" />' . "\n";
|
|
}
|
|
|
|
add_action('wp_head', 'custom_checkout_padding');
|
|
function custom_checkout_padding() {
|
|
// Проверяем, что это страница Checkout
|
|
if (is_checkout() && !is_admin()) {
|
|
?>
|
|
<style type="text/css">
|
|
main.wrapper {
|
|
padding-top: 100px;
|
|
padding-bottom: 50px;
|
|
}
|
|
</style>
|
|
<?php
|
|
}
|
|
}
|
|
|
|
|
|
// Отправка кода и проверка Email
|
|
add_action( 'wp_ajax_email_activate', 'send_activation_email' );
|
|
add_action( 'wp_ajax_nopriv_email_activate', 'send_activation_email' );
|
|
|
|
function send_activation_email() {
|
|
error_log(123);
|
|
$user = wp_get_current_user();
|
|
$activation_key = sha1($user->user_email . time()); // Generate a unique activation key
|
|
update_field('uuid', $activation_key, 'user_' . get_current_user_id()); // Save the key in user meta
|
|
|
|
$activation_link = home_url("/activate/$activation_key");
|
|
|
|
if(pll_current_language() === 'ru'){
|
|
$subject = "Активация аккаунта COSMOPET -".$string;
|
|
$message = " Остался последний шаг!\n
|
|
Пройдите по ссылке для активации аккаунта:\n
|
|
".$activation_link;
|
|
} else {
|
|
$subject = "Account activation COSMOPET -".$string;
|
|
$message = "Last step!\n
|
|
Follow the link to activate your account\n
|
|
".$activation_link;
|
|
}
|
|
|
|
wp_mail($user->user_email, $subject, $message);
|
|
}
|
|
|
|
|
|
|
|
add_action('init', 'custom_register_activation_endpoint');
|
|
|
|
function custom_register_activation_endpoint() {
|
|
add_rewrite_rule('^activate/([^/]*)/?', 'index.php?activation_key=$matches[1]', 'top');
|
|
add_rewrite_tag('%activation_key%', '([^&]+)');
|
|
}
|
|
|
|
|
|
add_action('template_redirect', 'custom_handle_activation_request');
|
|
|
|
|
|
|
|
add_action('template_redirect', 'custom_handle_activation_request');
|
|
|
|
function get_user_by_acf_field_value($field_value) {
|
|
// Prepare the arguments for WP_User_Query
|
|
$args = array(
|
|
'meta_query' => array(
|
|
array(
|
|
'key' => 'uuid', // Change to your ACF field key
|
|
'value' => $field_value,
|
|
'compare' => '=', // You can use other comparison operators if needed
|
|
),
|
|
),
|
|
);
|
|
|
|
// Execute the query
|
|
$user_query = new WP_User_Query($args);
|
|
|
|
// Check for results
|
|
if (!empty($user_query->get_results())) {
|
|
return $user_query->get_results(); // Returns an array of WP_User objects
|
|
} else {
|
|
return null; // No users found
|
|
}
|
|
}
|
|
|
|
function custom_handle_activation_request() {
|
|
if (get_query_var('activation_key')) {
|
|
$activation_key = sanitize_text_field(get_query_var('activation_key'));
|
|
|
|
$users = get_user_by_acf_field_value($activation_key);
|
|
|
|
if ($users) {
|
|
foreach ($users as $user) {
|
|
$user->set_bio();
|
|
// delete_user_meta($user->ID, 'uuid'); // Clean up the activation key
|
|
update_field('uuid', '', 'user_' . $user->ID);
|
|
update_field('activated', true, 'user_' . $user->ID);
|
|
wp_set_auth_cookie($user->ID);
|
|
wp_redirect('/my-account/'); // Redirect to the homepage or a custom page
|
|
var_dump($user);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|