• Как сделать AJAX запрос безопасным?

    @cluberr
    Защита: используем nonce и проверяем права

    Нет острой необходимости проверять AJAX запрос, если он потенциально не опасный. Например, когда он просто получает какие-то данные. Но когда запрос удаляет или обновляет данные, то его просто необходимо дополнительно защитить с помощью nonce кода и проверкой прав доступа.

    Разработчики часто ленятся ставить такую защиту, получая самый неожиданный результат. Недобросовестные пользователи могут каким-либо образом заставить юзера с правами сделать то что им нужно и в итоге навредить сайту над которым вы работали долгие месяцы, годы.

    Существует два вида защиты, которые нужно использовать в AJAX запросах в большинстве случаев.

    1. Код nonce (случайный код)

    Nonce - это уникальная строка, которая создается и используется один раз - одноразовое число. Nonce проверка используется, когда нужно убедится, что запрос был послан с указанного «места».

    В WordPress есть функции wp_create_nonce() и check_ajax_referer() - это базовые функции для создания и последующей проверки nonce кода. С их помощью мы и будем создавать защиту nonce для AJAX запросов.

    Для начала создадим nonce код:

    add_action( 'wp_enqueue_scripts', 'myajax_data', 99 );
    function myajax_data(){
    
    	wp_localize_script('twentyfifteen-script', 'myajax', 
    		array(
    			'url' => admin_url('admin-ajax.php'),
    			'nonce' => wp_create_nonce('myajax-nonce')
    		)
    	);  
    
    }

    twentyfifteen-script это название основного скрипта темы (см. выше), который подключается на сайте с помощью wp_enqueue_script().

    Затем, в AJAX запросе добавим переменную с кодом nonce:

    var ajaxdata = {
    	action     : 'myajax-submit',
    	nonce_code : myajax.nonce
    };
    jQuery.post( myajax.url, ajaxdata, function( response ) {
    	alert( response );
    });

    Теперь, в обработке заброса необходимо проверить nonce код:

    add_action( 'wp_ajax_nopriv_myajax-submit', 'myajax_submit' );
    add_action( 'wp_ajax_myajax-submit', 'myajax_submit' );
    function myajax_submit(){
    	// проверяем nonce код, если проверка не пройдена прерываем обработку
    	check_ajax_referer( 'myajax-nonce', 'nonce_code' );
    	// или так
    	if( ! wp_verify_nonce( $_POST['nonce_code'], 'myajax-nonce' ) ) die( 'Stop!');
    
    	// обрабатываем данные и возвращаем
    	echo 'Возвращаемые данные';
    
    	// не забываем завершать PHP
    	wp_die();
    }

    check_ajax_referer()работает на основе функции wp_verify_nonce() и по сути является её оберткой для AJAX запросов.
    Обратите внимание, что в данном случае Nonce код создается в HTML коде. А это значит, если у вас установлен плагин страничного кэширования, то этот код может и наверняка будет устаревать к моменту очередного AJAX запроса.
    2. Проверка прав доступа

    Тут AJAX запросы будут срабатывать только для пользователей с правом author. Для всех остальных включая неавторизованных пользователей, AJAX запрос вернет ошибку.

    Особенность тут в том, что не авторизованные пользователи тоже должны видеть сообщение об ошибке при AJAX запросе. Для этого нужно обрабатывать запрос для них возвратом ошибки:

    add_action( 'wp_ajax_nopriv_myajax-submit', 'myajax_submit' );
    add_action( 'wp_ajax_myajax-submit', 'myajax_submit' );
    function myajax_submit(){
    	// проверяем nonce код, если проверка не пройдена прерываем обработку
    	check_ajax_referer( 'myajax-nonce', 'nonce_code' );
    
    	// текущий пользователь имеет права автора или выше
    	if( ! current_user_can('publish_posts') )
    		die('Этот запрос доступен пользователям с правом автора или выше.')
    
    	// Делаем что нужно и выводим данные на экран, чтобы вернуть их скрипту
    
    	// Не забываем выходить
    	wp_die();
    }
    Ответ написан
    2 комментария
  • Как оптимизировать сайт на wordpress+visual composer?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Бекенд у вас весьма шустрый:

    bf3ea512b4264ec0a546b7e2a70bafee.jpg

    Это весьма и весьма достойный результат. С сервером и на серверной стороне все в порядке. А теперь узкие места:

    1. Загрузка шрифтов с серверов Google. С вашим шустрым сервером имеет смысл шрифты стянуть себе и отдавать локально. Срежете секунды полторы:

    67053ff4cfef4f458eb6d4723a36a7e2.jpgab83df494f21431284650396046227eb.jpg

    2. Далее, есть проблема с несколькими стилями:

    vcare.uz/wp-content/plugins/js_composer/assets/lib...
    vcare.uz/wp-content/plugins/js_composer/assets/lib...
    vcare.uz/wp-content/plugins/js_composer/assets/lib...

    Они долго грузятся, можете сами в Developer Tools посмотреть. Проблема не только в том, что они долго грузятся, но и в том, что они встают в очередь так как расположены в подвале и из-за использования HTTP/1.1. Можно решить 2мя путями:

    - конкатенация в один файл
    - использование HTTP/2

    В идеале, можно искать баланс между HTTP/2 + выборочная конкатенация.

    3. Файлы

    - new.vcare.uz/wp-content/uploads/2017/08/header-1.j...
    - new.vcare.uz/wp-content/uploads/2017/08/bg-white22...

    С ними 2 проблемы:

    - грузится с поддомена (+ DNS lookup и прочие потери на новый коннект)
    - динамический параметр, который предотвращает кеширование файла на стороне клиента

    Перенесите файл на основной домен и уберите параметр.

    4. Contact Form 7

    7cad4ec44dba469b86e2fbaa7c31558d.jpg

    У вас 7 (!!!) аякс-запросов этот плагин генерит. Я так понимаю, это 7 разных форм на странице. Запросы запускаются достаточно рано в цикле жизни страницы, и блокируют других ресурсов, занимая соединения с сервером. По протоколу HTTP/1.1, насколько я помню, браузер открывает до 6 соединений с сервером. В вашем случае, часть из этих 6 к моменту вызова этих ajax-запросов уже занята, и они встают в очередь друг за другом, вместе с другими ресурсами. Это умножает время ожидания. Переход на HTTP/2 заметно снизит влияние, но желательно избавиться от них вообще. Я бы советовал заменить CF7 на более адекватный плагин. Попробуйте, к примеру, Torro Forms (толковый и бесплатный, еще и с нормальным интерфейсом).

    5. Еще один запрос к admin-ajax.php

    f94caf0158b642b2958aefe1b9825ae5.jpg

    Собственно, он инициирован Visual Composer'ом - это Masonry сетка. Возможно, он у меня дозапустился потому что я начал скролить страницу и докрутил до того места, где он нужен. Возможно, он не запускается по умолчанию и проблемой не является.

    6. Front-end performance (парсинг и рендеринг):

    1691686d9b5f493fb147d10e0da4a894.jpg

    Парсинг скриптов занимает много времени, ибо их много. Но от этого можно избавиться только путем уменьшения их количества, что, возможно, не вариант. А вот второй очень тревожный сигнал - это как раз время ожидания (Idle). Это как раз говорит о невозможности браузера продолжать работу на каких-то этапах из-за того, что он ждет пока прилетят запрошенные ресурсы. Переход на HTTP/2 крайне желателен + замена CF7. Это как раз тот случай, когда HTTP/2 должен дать ощутимый эффект.

    Ну это так, беглый анализ. Посмотрите результаты тестирования тут: https://tools.pingdom.com/#!/2GQ2d/http://vcare.uz/
    Ответ написан
    3 комментария
  • Какой плагин выбрать для фильтра по рубрикам в WP или как научиться самому писать фильтры?

    kumaxim
    @kumaxim
    Web-программист
    Подход в фильтрах только один - использовать кастомный WP_Query.
    В кодексе, вроде бы, неплохо это все объясняется. В качестве примера посмотри плагин Category Sticky Post
    Ответ написан
    2 комментария
  • Wordpress самые популярные записи за последние 3 дня?

    llgruff
    @llgruff
    Scala
    Такой вариант:
    В post_meta сохраняем счётчик просмотров отдельно за 1, 2, 3 день.
    На 4 день затираем данные 1 дня, чтобы не росла таблица.
    При выводе делаем запрос из трех полей для каждой записи, складываем и сравнимаем общее кол-во просмотров за 3 дня.
    Раз в 3 часа или 6/12/24 по крону обновляем блок популярных записей.
    Ответ написан
    2 комментария
  • Как добавить 2 темы под разные устройства в WordPress?

    deniscopro
    @deniscopro Куратор тега WordPress
    WordPress-разработчик, denisco.pro
    Здравствуйте.

    Попробуйте плагин Any Mobile Theme Switcher. С помощью него можно указать разные темы для разных устройств.
    Ответ написан
    Комментировать
  • Как создать произвольные страницы в Wordpress доступные для определенной роли юзеров?

    ksider
    @ksider
    Я сварщик не настоящий
    в в шаблоне кастомной странице сделать проверку роли пользователя, и возвращать контент если тру

    if (current_user_can('user_role')) {
    echo 'кастомная страница';
     }
    else {
    echo 'авторизуйтесь';
    }
    Ответ написан
    Комментировать
  • Какой хук для WordPress можно использовать, для поиска и замены на всём сайте?

    wppanda5
    @wppanda5 Куратор тега WordPress
    WordPress Mедведь
    function wpp_buffer_content($buffer) {
            // переменная $buffer содержит все содержимое страницы и его можно менять
            // например 
           //$buffer = str_replace( 'Витя', 'Alien', $buffer );
            return $buffer;
        }
    
        function wpp_buffer_start() {
            ob_start( 'wpp_buffer_content' );
        }
    
        function wpp_buffer_stop() {
            ob_end_flush();
        }
    
        add_action( 'wp_head', 'wpp_buffer_start' );
        add_action( 'wp_footer', 'wpp_buffer_stop' );
    Ответ написан
    1 комментарий
  • Как лучше организовать импорт вариативного товара в WooCommerce?

    wppanda5
    @wppanda5 Куратор тега WordPress
    WordPress Mедведь
    Я в подобной ситуации сделал так
    f2dc93a888.jpg
    Механизм импорта соответственно писал сам
    Ответ написан
    Комментировать
  • Как создать метабокс только для поста с определённым id?

    deniscopro
    @deniscopro Куратор тега WordPress
    WordPress-разработчик, denisco.pro
    Предполагаю, что как-то так:
    function my_add_meta_boxes_page() {
        global $post;
        if ( $post->ID == 1 ) {
            add_meta_box( $args );
        }
    }
    add_action( 'add_meta_boxes_page', 'my_add_meta_boxes_page' );


    Вариант использования Advanced Custom Fields не рассматривали?
    Ответ написан
    Комментировать
  • Как отправить форму используя AJAX в Wordpress?

    werftgyhj
    @werftgyhj
    js = just sex
    Урл в WP для всех Ajax запросов один /wp-admin/admin-ajax.php
    что бы в аjax обработал нудная функция для этого в свойстве data нужно указать свойство action
    К примеру
    function sendAjaxForm(result_form, ajax_form, url) {
            jQuery.ajax({
                url:     url, //url страницы где обрабатывается отправленная форма
                type:     "POST", //метод отправки
                dataType: "html", //формат данных
                data: {
                     action: myAction,
                     jQuery("#"+ajax_form).serialize()
                 },  
                success: function(response) { //Данные отправлены успешно
                  result = jQuery.parseJSON(response);
                  document.getElementById(result_form).innerHTML =""+result.error;
                },
                error: function(response) { // Данные не отправлены
                  document.getElementById(result_form).innerHTML = "Ошибка. Данные не отправленны.";
        
                }
            });
          }

    и в wp добавляем action
    add_action('wp_ajax_{action}', 'my_action_callback'); //где {action} - тот самый экшн из data а my_action_callback функция которая должна его обработать
    Ответ написан
    Комментировать
  • Wordpress. Подключение защищено не полностью. Как решить?

    alone_lion1987
    @alone_lion1987
    Веб-разработчик
    У вас так происходит, потому что вывод ссылок в html идет по протоколу http:// (просмотрите исходный html-код и поиском пройдитесь по http://, все ссылки там у вас загружаются по http, а нужно по https), поэтому получается такая ситуация. Нужно чтобы система генерировала ссылки по https. Это касается всего, — ссылки для подключения css, js. Ссылки, в контенте, которые уже берутся из бд.

    В этом случае, в шаблоне вашего сайта, если прописаны абсолютные url, советую заменить http на https. Если используете по всюду функции вывода из бд, тогда надо менять в бд. Но лучше попробуйте такой код (если у вас сайт на wordpress). Еще есть встроенная функция, определяющая, какой протокол использует веб-сервер, для отдачи страниц, — is_ssl( ).

    В файл functions.php вставьте:

    add_filter('the_content', 'replace_url_to_https', 30);
    function replace_url_to_https($text)
    {
        $text = preg_replace('~http(://(?:www.)?' . preg_quote($_SERVER['HTTP_HOST']) . ')~', 'https\1', $text);
        return $text;
    }

    Вроде это должно помочь.

    Еще можно запросами к бд попробовать, тогда и код выше не понадобится:

    UPDATE wp_options SET option_value = replace(option_value, 'http://site.ru', 'https://site.ru') WHERE option_name = 'home' OR option_name = 'siteurl';
    
    UPDATE wp_posts SET guid = replace(guid, 'http://site.ru', 'https://site.ru');
    
    UPDATE wp_posts SET post_content = replace(post_content, 'http://site.ru', 'https://site.ru');


    Тут site.ru — ваш домен подставляете. Все абсолютные пути в базе станут с https

    А везде, где ссылки выводятся не через бд, а напрямую хардкорно прописаны где либо http, замените на https://
    Ответ написан
    2 комментария
  • Как сделать кликабельным весь блок li, а не только вложенную в него а?

    Amirez
    @Amirez
    В чем секрет кота Бориса?
    li задай размер, а ссылке width,height:100%
    Ответ написан
    Комментировать
  • Как убрать админ-бар для определенных ролей пользователей?

    llgruff
    @llgruff
    Scala
    Нужно изменить права в вашей функции, т.е. просто administrator заменить на publish_posts.
    Участник и Подписчик не будут видеть. Автор, Редактор, Админ — будут видеть.
    Подробнее current_user_can.
    Ответ написан
    Комментировать
  • Фильтрация в WordPress без указания параметров в ссылке?

    kobyakovdima
    @kobyakovdima
    Любитель экспериментов
    Если objects - это постоянная страница, то все get параметры можно сделать в виде ЧПУ. Об этом подробно расписано тут с примерами.

    А вот код, который решает Вашу проблему:
    add_action('init', 'rewrite_rule_my');
    function rewrite_rule_my(){
    	add_rewrite_tag('%metro%', '([^&]+)');
    	add_rewrite_rule('^(objects)/([^/]*)/?', 'index.php?pagename=$matches[1]&metro=$matches[2]', 'top');
    }

    Вставляется в functions.php. После вставки обязательно идём в админку -> Настройки ЧПУ и просто жмём "Сохранить", чтобы новые правила вступили в силу. В шаблоне страницы objects получаем значение так (3 способа):
    get_query_var('metro') // рекомендуемый
    $wp_query->query_vars['metro']
    $wp_query->query['metro']

    а там уже используете его по назначению.
    Ответ написан
  • Как в wordpress, в меню, сделать ссылку на телефон?

    @vylegzhanin
    В поле URL для телефона:
    tel:89000000000
    В поле URL для почты:
    mailto:mail@site.ru
    Ответ написан
    Комментировать
  • Не переводится админка темы в wordpress, хотя сам сайт перевелся, как быть?

    edalis
    @edalis
    HTML, CSS, JS, Node.js
    Если вы хорошо посмотрели и фразы, находящиеся в админке, не входят в 300 оставшихся непереведенных строк, то это значит, что админка не подготовлена для перевода. Возможен так же вариант, что в теме есть еще файлы перевода, находящиеся в других папках темы. Надо поискать их. Если их нет, то единственный вариант - искать фразы админки в файлах темы и переводить прямо там. Однако, при обновлении темы весь перевод придется делать снова. Хотя, если использовать дочернюю тему, ущерб при обновлении можно свести к минимуму. Но это уже от темы зависит, возможно не получится сделать перевод в файлах дочерней темы.
    Ответ написан
    2 комментария
  • Почему не применяются стили родительской темы в дочерней в Wordpress?

    deniscopro
    @deniscopro Куратор тега WordPress
    WordPress-разработчик, denisco.pro
    Привет.

    Для дочерних стилей нужно использовать функцию get_stylesheet_directory_uri().
    Функция get_template_directory_uri() в данном случае вернет путь к родительской теме.
    Ответ написан
    7 комментариев
  • Как реализовать новости на wordpress?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Новости - это стандартный базовый функционал WordPress, он же "блог". Чтобы он был по адресу /news/, создайте страницу News, зайдите в Настройки - Чтение и установите эту страницу как страницу записей. Потом еще зайдите в настройки постоянных ссылок и замените в произвольной структуре /%postname%/ на /blog/%postname%/, чтобы одна новость была тоже с префиксом.

    Для FAQ подбирайте плагин, или же зарегистрируйте custom post type. Для добавления вопроса - форма (ручками) или плагин по типу Contact Form 7 и надстройка к нему чтобы создавать пост при отправке формы.
    Ответ написан
    Комментировать
  • .htaccess для лучшей оптимизации сайта?

    sim3x
    @sim3x
    Оптимальное значение гзип - 5

    Типичный случай оптимизации - убрать апач и поставить nginx+php-fpm
    Ответ написан
    2 комментария
  • WordPress индексация данных в базе?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    ElasticPress. Для истинных ценителей шаредов Elastic Search есть в виде облачного сервиса.
    Ответ написан
    8 комментариев