Проблемы с кодировкой HTML и отображением изображений в формате WP http XML-ответа


Это мой самый первый WP-плагин. Вероятно, здесь будет больше одного вопроса, и все они связаны, поэтому я собираюсь задать все здесь.

Рабочий тест здесь

Используемый номер отслеживания: lc0614061377

Пример XML-ответа от tracenow.net:

<Consignment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/">
    <consignmentNumber>lc0614061377</consignmentNumber>
    <customerRef/>
    <itemCount>1</itemCount>
    <name>six red squares</name>
    <address1>unit 7b victoria business park</address1>
    <address2>short street</address2>
    <town>SOUTHEND ON SEA</town>
    <county>ESSEX</county>
    <postcode>ss2 5by</postcode>
    <country>United Kingdom</country>
    <recipient>cannon</recipient>
    <status>Delivered</status>
    <collected>0001-01-01T00:00:00</collected>
    <delivered>2014-07-25T10:00:50</delivered>
    <collectionCode/>
    <deliveryCode>Delivered OK</deliveryCode>
    <comments/>
    <created>2014-07-24T15:00:40</created>
    <deliveryLatitude>51.54617</deliveryLatitude>
    <deliveryLongitude>0.712245</deliveryLongitude>
    <deliverySignature>
        http://resources.tracenow.net/signatures/d5dbffb4-0336-44bf-b72c-00fb9aaac759/0a630170-1390-4ca4-b104-5ca4b9b6199f.jpg
    </deliverySignature>
    <deliveryImage>
        http://resources.tracenow.net/images/d5dbffb4-0336-44bf-b72c-00fb9aaac759/6de6c2bd-236b-447d-a106-b1a7bd537645.jpg
    </deliveryImage>
</Consignment>

Это текущее состояние моего кода:

// tracenow.php

<?php
 /*
 Plugin Name: TraceNow Tracking
 Plugin URI: http://www.titandesign.co.uk
 Description: A simple parcel tracking plugin for Codeway TraceNow.
 Version: 4.0
 Author: Richard King
 Author URI: http://www.titandesign.co.uk/
 License: GPL-2.0+
 License URI: http://www.opensource.org/licenses/gpl-license.php 
 */

 wp_enqueue_script( 'my-ajax-handle', plugin_dir_url( __FILE__ ) . 'ajax.js', array( 'jquery' ) );
 wp_enqueue_style( 'my-ajax-handle', plugin_dir_url( __FILE__ ) . 'style.css' );
 wp_localize_script( 'my-ajax-handle', 'the_ajax_script', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );

 // THE TRACKING FUNCTION
 if( !class_exists( 'WP_Http' ) )
include_once( ABSPATH . WPINC. '/class-http.php' );

 function tracking_function(){ 
 //if ( isset( $_POST['consignmentNumber'] ) && '1' == $_POST['consignmentNumber'] ){
    $consignmentNumber = $_POST['consignmentNumber'];
    $url = ('http://services.tracenow.net/TraceNowAccess.asmx/GetConsignment?consignmentNumber=' .($consignmentNumber) .'&externalAccessGuid=d5dbffb4-0336-44bf-b72c-00fb9aaac759');
    $args = array(
                'method' => 'GET',
                'timeout' => 45,
                'redirection' => 5,
                'httpversion' => '1.1',
                'content-type' => 'application/x-www-form-urlencoded',
                'body' => array(),
                'headers' => array(),
                'blocking' => true,
                'cookies' => array(),
                'connection' => 'close',
                );

    $response = wp_remote_get( $url, $args );
    if ( is_wp_error( $response ) ) {
            $error_message = $response->get_error_message();
                 echo "Something went wrong: $error_message";
            } else {
                /*include ('/render_xml_to_html.php');
                        if(function_exists('render_xml_data')){
                            render_xml_data('example_data.xml');
                            }else{
                            echo null;
                        } */
                    echo '<h3>Consignment Details</h3>' . '<pre>' . print_r($response['body'], true) . '</pre>';// this is passed back to the javascript function
                    die();
            } // end if
    //} // end if               
 }

 // THE AJAX ADD ACTIONS
add_action( 'wp_ajax_the_ajax_hook', 'tracking_function' );
add_action( 'wp_ajax_nopriv_the_ajax_hook', 'tracking_function' ); // need this to serve non logged in users

// ADD TRACKING FORM TO THE PAGE

function tracenow_frontend(){
$the_form = '
<form id="theForm" method="POST">
<input id="consignmentNumber" name="consignmentNumber" value="Consignment No" type="text" />
<input name="action" type="hidden" value="the_ajax_hook" /> <!-- this puts the action the_ajax_hook into the serialized form -->
<input id="submit_button" value="Track" type="button" onClick="submit_me();" />
 </form>
 <div id="response_area">
    Your tracking details will appear here
</div>';// END DIV RESPONSE AREA
return $the_form;
}
 add_shortcode("tn_ajax_frontend", "tracenow_frontend");

// ajax.js
function submit_me(){
        jQuery.post(the_ajax_script.ajaxurl, jQuery('#theForm').serialize()
        ,
        function(response_from_tracking_function){
            jQuery("#response_area").html(response_from_tracking_function);
            }
        );
        jQuery('#theForm').find('input[type=text]').val('Consignment No');      
}

// render_xml_to_html.php
<?php
/*
    Written by Gary Hollands Sept 2010
    This work is available under the terms of the GNU General Public License, http://www.gnu.org/licenses/gpl.html
    render_xml_data is a function that can use XML data and present that data as HTML.
*/
function render_xml_data($path_to_xml_file){
    if (!file_exists($path_to_xml_file)){
        return;
    }else{
        $chars_to_replace = array('[\r]','[\n]','[\t]');
        $xmlstring = trim(preg_replace($chars_to_replace, '', file_get_contents($path_to_xml_file)));
    }
    $xml = new SimpleXMLElement($xmlstring);
    foreach ($xml->consignment as $consign) {
            echo '<div class="consignment">'."\n";
            echo '<h3>'.$consign->consignmentnumber.'</h3>'."\n";
            echo '<p><span class="category">Customer Ref: </span>'.$consign->customerref.'</p>'."\n";
            echo '<p><span class="category">Number of items: </span>'.$consign->itemcount.'</p>'."\n";
            echo '<p><span class="category">Name: </span>'.$consign->name.'</p>'."\n";
            echo '<p><span class="category">Address 1: </span>'.$consign->address1.'</p>'."\n";
            echo '<p><span class="category">Address 2: </span>'.$consign->address2.'</p>'."\n";
            echo '<p><span class="category">Town: </span>'.$consign->town.'</p>'."\n";
            echo '<p><span class="category">County: </span>'.$consign->county.'</p>'."\n";
            echo '<p><span class="category">Postcode: </span>'.$consign->postcode.'</p>'."\n";
            echo '<p><span class="category">Country: </span>'.$consign->country.'</p>'."\n";
            echo '<p><span class="category">Recipient: </span>'.$consign->recipient.'</p>'."\n";
            echo '<p><span class="category">Status: </span>'.$consign->status.'</p>'."\n";
            echo '<p><span class="category">Collected: </span>'.$consign->collected.'</p>'."\n";
            echo '<p><span class="category">Delivered: </span>'.$consign->delivered.'</p>'."\n";
            echo '<p><span class="category">Collection Code: </span>'.$consign->collectioncode.'</p>'."\n";
            echo '<p><span class="category">Delivery Code: </span>'.$consign->deliverycode.'</p>'."\n";
            echo '<p><span class="category">Comments: </span>'.$consign->comments.'</p>'."\n";
            echo '<p><span class="category">Created: </span>'.$consign->created.'</p>'."\n";
            echo '<p><span class="category">Delivery Latitude: </span>'.$consign->deliverylatitude.'</p>'."\n";
            echo '<p><span class="category">Delivery Longitude: </span>'.$consign->deliverylongitude.'</p>'."\n";
            echo '<p><span class="category">Delivery Signature: </span><img src="/'.$consign->deliverysignature.'/"/></p>'."\n";
            echo '<p><span class="category">Delivery Image: </span><img src="/'.$consign->deliveryimage.'/"/></p>'."\n";
            echo '</div><!--end consignment-->'."\n";
    }
}

Ссылка на GitHub Суть

Итак, для начала. Функция отслеживания заключается в работает и возвращает ответ с сервера нормально.

  1. Как мне получить ответ для отображения в виде HTML, который будет отображаться на странице. В данный момент он возвращает XML-текст запроса, который является именно тем, что мне нужно. Мне нужно нацелиться на узлы, которые не являются пустыми, и вернуть их с заголовком. Пример для номера отправления я хочу добавить заголовок 'Consignment No:'. То же самое для address, status, time, GeoLoc и т.д. Я рассматривал возможность использования jQuery и CSS: перед добавлением заголовка. У меня также есть файл render_xml_to_html.php, который, как я предполагал, был правильным методом, однако единственный результат, который я получаю, когда подразумевается, равен 0. Есть какие-нибудь предложения?
  2. В XML-ответе есть ссылки на 2 изображения, но у них нет тега img, классов или идентификаторов, поэтому мне сложно настроить таргетинг на эти файлы изображений. Я попытался настроить таргетинг.jpg, но это просто не сработало. Мне нужно добавить img, src="" и теги alt="", чтобы я мог отображать ссылки на изображения в виде изображений. Помогите, пожалуйста.
  3. Защита плагина: У меня есть попытался добавить wp_nonce в вызов ajax для проверки запроса формы. Я также пытался создать и добавить nonce в функцию отслеживания, но снова получаю ошибку. Это действительно поставило меня в тупик. Сейчас я прочитал так много блогов о добавлении nonce, что я совершенно сбит с толку и мог бы сделать легкий толчок в правильном направлении.
  4. Я хотел бы отправить ответ на страницу под названием результаты. Это существующая страница. Я проверил кодекс, но единственным вариантом, который я смог найти, был addpage, который каждый раз создает новую страницу. Причина: Я хотел бы иметь возможность добавить плагин в качестве виджета.
Author: Richard King, 2014-09-09

1 answers

Регистрация зависимостей

WordPress использует для этого API зависимостей . Это довольно просто: зарегистрируйте и поставьте в очередь скрипт, затем передайте данные, которые вы хотите передать из WP/PHP в JS, используя wp_localize_script(), который добавляет тег <script>, содержащий массив, в ваш DOM (точно до того, как ваш скрипт будет добавлен в него):

add_action( 'wp_enqueue_scripts', function()
{
    $name = 'handle';
    wp_register_script(
        $name,
        plugins_url( 'assets/ajax.js', __FILE__ ),
        [ 'jquery' ],
        filemtime( plugins_dir_path( __FILE__ ).'assets/ajax.js' ),
        true
    );
    wp_enqueue_script( $name );
    wp_localize_script(
        $name,
        "{$name}Obj", // This string is what gives you access to below array
        [
            'ajaxurl'     => esc_url( admin_url( 'admin-ajax.php' ) ),
            '_ajax_nonce' => wp_create_nonce( "{$name}_action" ),
            'action'      => "{$name}_action",
            'data'        => [ /* additional data as array */ ],
        ]
    );
} );

Вы можете заметить, что я использовал wp_create_nonce() и передал атрибут действия вызову по соображениям безопасности (проверка происхождения запроса в вашем обратный вызов).

Как выполнить удаленный запрос и получить XML-данные

При загрузке данных из удаленного запроса следует использовать WP HTTP API, но с функциями более высокого уровня.

Пример плагина, который выполнит запрос и добавит результат под вашим нижним колонтитулом (как для администратора, так и для внешнего интерфейса):

<?php
/** Plugin Name: (#160775) Fetch XML from TraceNow.net - Part 1 */

add_action( 'shutdown', function()
{
    $request  = wp_remote_get( 
        'http://services.tracenow.net/TraceNowAccess.asmx/GetConsignment?'.
        join( '&', [
            'consignmentNumber'  => 'lc0614061377',
            'externalAccessGuid' => 'd5dbffb4-0336-44bf-b72c-00fb9aaac759'
        ],
    );
    $response = wp_remote_retrieve_body( $request, [
        // *additional args
    ] );

    is_wp_error( $response )
        AND wp_send_json_error( $response->get_error_code() ); 

    if ( 
        'OK' !== wp_remote_retrieve_response_message( $response )
        OR 200 !== wp_remote_retrieve_response_code( $response )
    )
        wp_send_json_error( $response );

    var_dump( wp_send_json_success( $response ) );
} );

Это самый простой способ выполнения таких запросов. Как вы можете видеть, я использую JSON. XML исчез из WPs HTTP API, так как некоторые версии, такие как JSON, проще в использовании.

Подсказка: wp_remote_*() принимает второй аргумент, массив аргументов, о которых вы можете прочитать в коде.

Выполнение действия

Независимо от того, включен ли AJAX (см. Архив ajax для получения дополнительной информации) или нет, вам нужна форма.

<form id="asktracenow">
    <input name="consignmentNumber" />
    <input name="submit" value="submit" />
</form>

Теперь, когда эта форма отправляет данные $_POST, вы захотите очистить их, прежде чем использовать в своем URL-адресе. У вас есть несколько вариантов в зависимости от того, как построены данные. Сначала мы просто $cnum = trim( $_POST['consignmentNumber'] ), затем мы проверьте и в случае необходимости очистите его.

if ( false !== filter_var( $cnum, FILTER_VALIDATE_INT ) )
{
    // do stuff with your absolute, positive integer
    // adjust the check to only pass valid data
}

Убедитесь, что вы придаете этому большое значение - вы никогда не знаете, что получите взамен.

Аяксификация вещей

Просто подключайте вещи к действию WP. Подводя итог, это будет выглядеть примерно так.

// Public or private?
add_action( 'wp_ajax_handle_action', function( $data )
{
    check_ajax_referer( $data['action'] );

    # @TODO sanitize data here:
    // filter_var() filter_var_array() and filter_input()
    # @TODO Custom logic here

    // Error?
    if ( is_wp_error( $thing ) )
        wp_send_json_error( $data );

    // Success!
    wp_send_json_success( $data );
} );

Подсказка: Поместите все это в отдельный плагин для разделения проблем и переносимости.

JavaScript AJAX/обработка запросов

Чтобы сделать этот ответ немного более полным, вот ссылка к другому моему ответу, в котором это подробно объясняется и к которому прилагается огромный пример.

 0
Author: kaiser, 2017-04-13 12:37:42