miércoles, 24 de septiembre de 2014

Publicar en WordPress desde Microsoft Access via XMLRPC Parte 8

Continuando con los artículos en donde estamos investigando cómo conectar Microsoft Access con WordPress vía XML-RPC, en esta entrega veremos un caso sencillo, pero que puede ser útil: ¿Cómo borrar un post en WordPress? Antes de continuar recomiendo que lean los artículos anteriores:


Para cumplir con lo requerido, trabajaremos con wp.deletePost. Hay que tener en cuenta que el método también sirve para eliminar archivos de la librería de medios.




El código

Function BorrarPostEnWordPress(PostId As String) As String
 
    ' Datos de Autenticación
    CargarConstantes
    txtURL = SITIO
    txtUserName = USUARIO
    txtPassword = PASSWORD
    
    ' Datos del Post
    txtId = PostId
      
    ' ServerXMLHTTP
    Dim objSvrHTTP As ServerXMLHTTP
    Dim strT As String
    Set objSvrHTTP = New ServerXMLHTTP
  
    ' Autenticación
    objSvrHTTP.Open "POST", txtURL, False, CStr(txtUsuario), CStr(txtPassword)
    objSvrHTTP.setRequestHeader "Accept", "application/xml"
    objSvrHTTP.setRequestHeader "Content-Type", "application/xml"

    strT = strT & "<methodCall>"
    
    ' Acción
    strT = strT & "<methodName>wp.deletePost</methodName>"
    
    ' General
    strT = strT & "<params>"
    strT = strT & "<param><value><string>0</string></value></param>"
    strT = strT & "<param><value>" & txtUserName & "</value></param>"
    strT = strT & "<param><value><string>" & txtPassword & "</string></value></param>"
    strT = strT & "<param><value><int>" & txtId & "</int></value></param>"
    strT = strT & "<param>"
    strT = strT & "</param>"
    strT = strT & "</params>"
    strT = strT & "</methodCall>"
    
    ' Publicación
    objSvrHTTP.send strT
    
    ' Debug
    Debug.Print objSvrHTTP.responseText
    'MsgBox objSvrHTTP.responseText
    BorrarPostEnWordPress = resultado(objSvrHTTP.responseText, "EDIT")

End Function


Bibliografía



Hasta la próxima!

martes, 23 de septiembre de 2014

Publicar en WordPress desde Microsoft Access via XMLRPC Parte 7

Continuando con la prueba de conexión entre el mundo de Microsoft Access y WordPress, llegamos al artículo número 7 en donde vamos ahora a sofisticar un poco más nuestra solución para agregar seguridad por usuario en las publicaciones. Recomiendo que lean los 6 artículos previos sobre XMLRPC:

Detalle del requerimiento
  • Se desea asignar seguridad por usuario a cada post y su archivo adjunto
  • Un usuario no puede ver lo de otro
  • Un administrador puede ver todo

Enfoque de la solución

Trabajaremos con el campo autor de cada post / imagen.
  • Al momento de crear un post, le asignamos un autor
  • Agregaremos código en WordPress para controlar si el usuario conectado coincide con el autor

Modificaciones en WordPress - Parte 1 - Plugin de seguridad

Instalaremos un plugin de seguridad que directamente impida el acceso al sitio, si el visitante no está conectado. Usamos "Private Only"



Modificaciones en WordPress - Parte 2 - Query

Vamos a interceptar el query de los posts y las imágenes para evitar que me deje ver archivos / posts que no son de mi autoría a través de un plugin construido por nosotros. Código:


# Muestra los posts sólo si es el autor o es administrador
function seguridad_posts_media($query) {
  if( !current_user_can( 'manage_options' ) ) {
global $user_ID;
$query->set('author', $user_ID );
}
  return $query;
}

add_filter('pre_get_posts', 'seguridad_posts_media');


Modificaciones en WordPress - Parte 3 - Descarga de imágenes

Si bien el paso dos, controlar el acceso, nos falta un detalle. El usuario puede acceder directamente al archivo y descargarlo si conoce un URL como esta:

Para resolver esto tenemos que hacer algo más sofisticado. Modificaremos nuestro .htaccess para que redireccione a una página nuestra los accesos a ese tipo de URLs. Código:


RewriteEngine on
RewriteCond %{REQUEST_FILENAME} -s
RewriteRule ^wp-content/uploads/(.*)$ descargar.php?file=$1 [QSA,L]
# BEGIN WordPress
# END WordPress

Y creamos nuestra página descargar.php para que realice los controles y efectúe la descarga del archivo. Código:


<?php
require_once('wp-load.php');
# Obtener path interno del archivo 
list($basedir) = array_values(array_intersect_key(wp_upload_dir(), array('basedir' => 1)))+array(NULL);
$file =  rtrim($basedir,'/').'/'.str_replace('..', '', isset($_GET[ 'file' ])?$_GET[ 'file' ]:'');

# Obtener id del archivo
$enlace = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$id_archivo =  obtener_id_archivo_desde_url ($enlace);

# Obtener autor del archivo
$post = get_post($id_archivo); 
$autor = $post->post_author;

# Descargar archivo
if ( get_current_user_id() == $autor ) {
header('Content-Type: application/pdf');
readfile ($file);
}
else {
echo "Acceso denegado...";
}

# Función para obtener el ID de un archivo a través de su URL
function obtener_id_archivo_desde_url ( $url ) {
$parsed_url  = explode( parse_url( WP_CONTENT_URL, PHP_URL_PATH ), $url );
$this_host = str_ireplace( 'www.', '', parse_url( home_url(), PHP_URL_HOST ) );
$file_host = str_ireplace( 'www.', '', parse_url( $url, PHP_URL_HOST ) );
if ( ! isset( $parsed_url[1] ) || empty( $parsed_url[1] ) || ( $this_host != $file_host ) ) {
return;
}
global $wpdb;
$attachment = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM {$wpdb->prefix}posts WHERE guid RLIKE %s;", $parsed_url[1] ) );
return $attachment[0];
}
?>


Modificaciones en Access - Parte 1 - Especificar el autor al publicar un post

Es un dato más, veremos que no cambia mucho respecto a lo que veníamos haciendo, pero debemos tener en cuenta que nuestras credenciales deben ser de administrador para poder especificar el autor. Los cambios están resaltados.Código:

Function PublicarEnWordPress(CodigoArchivo As String, NumeroDocumento As String, CodigoCliente As String) As String
    ' Datos de Autenticación
    CargarConstantes
    txtURL = SITIO
    txtUserName = USUARIO
    txtPassword = PASSWORD
    
    ' Datos del Post
    txtTitulo = CodigoCliente & " - " & NumeroDocumento
    txtContenido = "Este es un custom post de ejemplo publicado desde Microsoft Access"
    Dim txtCategorias(1) As String
    txtCategorias(1) = "Uncategorized"
    'txtImagen = "64"
    txtTipoContenido = "proceso"
    txtCliente = CodigoCliente
    txtNumeroCertificado = NumeroDocumento
    txtDocumento = CodigoArchivo
    txtAutor = "3"
      
    ' ServerXMLHTTP
    Dim objSvrHTTP As ServerXMLHTTP
    Dim strT As String
    Set objSvrHTTP = New ServerXMLHTTP
  
    ' Autenticación
    objSvrHTTP.Open "POST", txtURL, False, CStr(txtUsuario), CStr(txtPassword)
    objSvrHTTP.setRequestHeader "Accept", "application/xml"
    objSvrHTTP.setRequestHeader "Content-Type", "application/xml"

    strT = strT & "<methodCall>"
    
    ' Acción
    strT = strT & "<methodName>wp.newPost</methodName>"
    
    ' General
    strT = strT & "<params>"
    strT = strT & "<param><value><string>0</string></value></param>"
    strT = strT & "<param><value>" & txtUserName & "</value></param>"
    strT = strT & "<param><value><string>" & txtPassword & "</string></value></param>"
    strT = strT & "<param>"
    
    strT = strT & "<struct>"
    
    ' Categorías
    strT = strT & "<member><name>categories</name><value><array>"
    strT = strT & "<data>"
    For i = 1 To UBound(txtCategorias)
        strT = strT & "<value>" & txtCategorias(i) & "</value>"
    Next i
    strT = strT & "</data>"
    strT = strT & "</array></value></member>"
    
    ' Título, contenido y fecha
    strT = strT & "<member><name>post_content</name><value><![CDATA[" & txtContenido & "]]></value></member>"
    strT = strT & "<member><name>post_title</name><value>" & txtTitulo & "</value></member>"
    strT = strT & "<member><name>dateCreated</name><value><dateTime.iso8601>" & Format(Now(), "yyyyMMdd") & "T" & Format(Now(), "hh:mm:ss") & "</dateTime.iso8601></value></member>"
    
    ' Imagen destacada
    ' strT = strT & "<member><name>post_thumbnail</name><value><![CDATA[" & txtImagen & "]]></value></member>"
    
    ' Tipo de contenido
    strT = strT & "<member><name>post_type</name><value>" & txtTipoContenido & "</value></member>"
    
    ' Autor
    strT = strT & "<member><name>post_author</name><value>" & txtAutor & "</value></member>"
    
    ' Campos personalizados
    strT = strT & "<member><name>custom_fields</name><value><array><data><value>"
    
    strT = strT & "<struct>"
    strT = strT & "<member><name>key</name><value>cliente</value></member>"
    strT = strT & "<member><name>value</name><value>" & txtCliente & "</value></member>"
    strT = strT & "</struct>"
    
    strT = strT & "<struct>"
    strT = strT & "<member><name>key</name><value>numero_de_certificado</value></member>"
    strT = strT & "<member><name>value</name><value>" & txtNumeroCertificado & "</value></member>"
    strT = strT & "</struct>"
    
    strT = strT & "<struct>"
    strT = strT & "<member><name>key</name><value>documento</value></member>"
    strT = strT & "<member><name>value</name><value>" & txtDocumento & "</value></member>"
    strT = strT & "</struct>"
    
    strT = strT & "</value></data></array></value></member>"
    
    ' Tipo de publicación
    strT = strT & "<member><name>post_status</name><value>publish</value></member>"
    
    strT = strT & "</struct>"
    strT = strT & "</param>"
    strT = strT & "</params>"
    strT = strT & "</methodCall>"
    
    ' Publicación
    objSvrHTTP.send strT
    
    ' Debug
    Debug.Print objSvrHTTP.responseText
    'MsgBox objSvrHTTP.responseText
    PublicarEnWordPress = resultado(objSvrHTTP.responseText, "POST")

End Function


Modificaciones en Access - Parte 2 - Especificar el autor al publicar una imagen

El método para subir imágenes no nos deja especificar el autor. Hay un plugin que encontrarán en el directorio que extiende el método, pero preferí no utilizarlo. La opción es modificar el autor de la imagen luego de subirla, utilizando un método que hasta ahora no hemos utilizado, el método de editar posts. Código:

Function CambiarAutorEnWordPress(PostId As String, NuevoAutor As String) As String
    ' Datos de Autenticación
    CargarConstantes
    txtURL = SITIO
    txtUserName = USUARIO
    txtPassword = PASSWORD
    
    ' Datos del Post
    txtId = PostId
    txtAutor = NuevoAutor
      
    ' ServerXMLHTTP
    Dim objSvrHTTP As ServerXMLHTTP
    Dim strT As String
    Set objSvrHTTP = New ServerXMLHTTP
  
    ' Autenticación
    objSvrHTTP.Open "POST", txtURL, False, CStr(txtUsuario), CStr(txtPassword)
    objSvrHTTP.setRequestHeader "Accept", "application/xml"
    objSvrHTTP.setRequestHeader "Content-Type", "application/xml"

    strT = strT & "<methodCall>"
    
    ' Acción
    strT = strT & "<methodName>wp.editPost</methodName>"
    
    ' General
    strT = strT & "<params>"
    strT = strT & "<param><value><string>0</string></value></param>"
    strT = strT & "<param><value>" & txtUserName & "</value></param>"
    strT = strT & "<param><value><string>" & txtPassword & "</string></value></param>"
    strT = strT & "<param><value><int>" & txtId & "</int></value></param>"
    strT = strT & "<param>"
    
    strT = strT & "<struct>"
    
    ' Autor
    strT = strT & "<member><name>post_author</name><value>" & txtAutor & "</value></member>"
    
    strT = strT & "</struct>"
    strT = strT & "</param>"
    strT = strT & "</params>"
    strT = strT & "</methodCall>"
    
    ' Publicación
    objSvrHTTP.send strT
    
    ' Debug
    Debug.Print objSvrHTTP.responseText
    'MsgBox objSvrHTTP.responseText
    CambiarAutorEnWordPress = resultado(objSvrHTTP.responseText, "EDIT")

End Function


Modificaciones en Access - Parte 3 - Cambio en el análisis del resultado

Un detalle, la edición del post, nos devuelve un valor bool, en función de si pudo o no modificar el post, con lo cual hacemos un pequeño cambio a nuestra función de análisis de resultados: 

Código:

Function resultado(strXML, tipo As String) As String

    Dim error As String
    Dim hayError As Boolean
    error = ""
    hayError = False
    
    Set xmlDoc = CreateObject("MSXML2.DOMDocument")
    xmlDoc.loadXML strXML

    ' Busco errores
    Set elements = xmlDoc.getElementsByTagName("fault")
    For Each el In elements
        error = error & el.Text
        hayError = True
    Next
    
    ' Si no hay errores
    If Not hayError Then
        
        ' POST o MEDIA?
        Dim tipoXML As String
        If tipo = "POST" Then
            tipoXML = "params"
        ElseIf tipo = "EDIT" Then
            tipoXML = "boolean"
        Else
            tipoXML = "string"
        End If
        
        Set elements = xmlDoc.getElementsByTagName(tipoXML)
            
        ' Obtengo el código generado
        resultado = elements(0).Text
    
    ' Si hay errores
    Else
        MsgBox error
        resultado = "-1"
    End If
        
    'MsgBox resultado

End Function


Resultados

Ahora bien, cómo se verá la solución? Si tenemos permisos, nada cambia, si no tenemos permisos, pueden suceder tres cosas:

Caso 1: no estoy conectado



Caso 2: intento acceder a un post sobre el que no tengo permiso


Caso 3: intento acceder directamente a un archivo al que no tengo permiso (esté o no conectado)

Robusto, no? Aquí terminamos por ahora, luego iremos ajustando.
Cualquier duda me consultan. Hasta la próxima!


Bibliografía

Estos son todos los enlaces que me hicieron encontrar la luz en este oscuro camino. Agradezco a los autores y les recomiendo que los visiten.

lunes, 15 de septiembre de 2014

Publicar en WordPress desde Microsoft Access via XMLRPC Parte 6

Continuando con la prueba de conexión entre el mundo de Microsoft Access y WordPress, llegamos al artículo número 6 en donde vamos ahora a realizar un ejemplo completo para unir lo que fuimos investigando en los 5 artículos anteriores de XMLRPC, que recomiendo que leas antes de seguir:
¿En qué consistirá nuestro ejemplo completo?

Lo que buscamos al final del camino es haber creado en WordPress un post personalizado con campos personalizados y un archivo asociado.


Para ello desde MS Access, tendremos un formulario que nos pide tres datos y luego nos indica la URL del post creado, tal como se ve en la siguiente imagen:



Código - Principal

En esta primera parte del código incorporamos la lógica, en donde primero subimos el archivo, y luego el post asociado a ese archivo:

Function CargarDocumentoConMetaDataEnWordPress( _
    Cliente As String, Certificado As String, _
    ArchivoConPath As String, Archivo As String) As String

    Dim CodigoDocumento As String
    Dim CodigoProceso As String
    
    ' Subo un archivo a la librería multimedia de WordPress y obtengo el código publicado
    CodigoDocumento = PublicarMedioEnWordPress(Archivo, ArchivoConPath, "application/pdf")
    
    If CodigoDocumento <> "-1" Then
        ' Subo cun ítem de custom post type, asociando el archivo subido
        CodigoProceso = PublicarEnWordPress(CodigoDocumento, Certificado, Cliente)
        
        If CodigoProceso <> "-1" Then
            ' URL en donde se cargó el post type
            CargarDocumentoConMetaDataEnWordPress = "http://blabla.com/?p=" & CodigoProceso
        Else
            MsgBox "Ocurrió un error al intentar subir un post type"
        End If
    
    Else
        MsgBox "Ocurrió un error al intentar subir un documento"
    End If
    
End Function


Código - Publicación de Imagen / Archivo

Hay algunos cambios resaltados respecto a artículos anteriores, que tienen que ver con el cambio de API a wp y con el análisis del XML devuelto como resultado.

Function PublicarMedioEnWordPress(ArchivoNombre As String, ArchivoConCamino As String, ArchivoTipo As String) As String
    ' Datos de Autenticación
    CargarConstantes
    txtURL = SITIO
    txtUserName = USUARIO
    txtPassword = PASSWORD
    
    ' Datos del Medio
    txtArchivo = ArchivoNombre
    txtTipo = ArchivoTipo
    Dim txtArchivoConPath As String
    txtArchivoConPath = ArchivoConCamino
      
    ' ServerXMLHTTP
    Dim objSvrHTTP As ServerXMLHTTP
    Dim strT As String
    Set objSvrHTTP = New ServerXMLHTTP
  
    ' Autenticación
    objSvrHTTP.Open "POST", txtURL, False, CStr(txtUsuario), CStr(txtPassword)
    objSvrHTTP.setRequestHeader "Accept", "application/xml"
    objSvrHTTP.setRequestHeader "Content-Type", "application/xml"

    strT = strT & "<methodCall>"
    
    ' Acción
    strT = strT & "<methodName>wp.uploadFile</methodName>"
    
    ' General
    strT = strT & "<params>"
    strT = strT & "<param><value><string>0</string></value></param>"
    strT = strT & "<param><value>" & txtUserName & "</value></param>"
    strT = strT & "<param><value><string>" & txtPassword & "</string></value></param>"
    strT = strT & "<param>"
    
    strT = strT & "<struct>"
    
    ' Nombre, Tipo e Imagen
    strT = strT & "<member><name>name</name><value><![CDATA[" & txtArchivo & "]]></value></member>"
    strT = strT & "<member><name>type</name><value><![CDATA[" & txtTipo & "]]></value></member>"
    strT = strT & "<member><name>bits</name><value><base64>" & EncodeFile(txtArchivoConPath) & "</base64></value></member>"
    
    strT = strT & "</struct>"
    strT = strT & "</param>"
    
    strT = strT & "</params>"
    strT = strT & "</methodCall>"

   
    ' Publicación
    objSvrHTTP.send strT

    ' Debug
    Debug.Print objSvrHTTP.responseText
    'MsgBox objSvrHTTP.responseText
    PublicarMedioEnWordPress = resultado(objSvrHTTP.responseText, "MEDIA")

End Function

Public Function EncodeFile(strPicPath As String) As String
    Const adTypeBinary = 1          ' Binary file is encoded

    ' Variables for encoding
    Dim objXML
    Dim objDocElem

    ' Variable for reading binary picture
    Dim objStream

    ' Open data stream from picture
    Set objStream = CreateObject("ADODB.Stream")
    objStream.Type = adTypeBinary
    objStream.Open
    objStream.LoadFromFile (strPicPath)

    ' Create XML Document object and root node
    ' that will contain the data
    Set objXML = CreateObject("MSXml2.DOMDocument")
    Set objDocElem = objXML.createElement("Base64Data")
    objDocElem.DataType = "bin.base64"

    ' Set binary value
    objDocElem.nodeTypedValue = objStream.Read()

    ' Get base64 value
    EncodeFile = objDocElem.Text
    'EncodeFile = Replace(objDocElem.Text, vbLf, "")

    ' Clean all
    Set objXML = Nothing
    Set objDocElem = Nothing
    Set objStream = Nothing

End Function


Código - Análisis de la respuesta

Esto es nuevo respecto a artículos anteriores y sirve para analizar el XML recibido como respuesta con el fin de encontrar el código interno que WordPress asignó a la imagen o post creado:

Function resultado(strXML, tipo As String) As String

    Dim error As String
    Dim hayError As Boolean
    error = ""
    hayError = False
    
    Set xmlDoc = CreateObject("MSXML2.DOMDocument")
    xmlDoc.loadXML strXML

    ' Busco errores
    Set elements = xmlDoc.getElementsByTagName("fault")
    For Each el In elements
        error = error & el.Text
        hayError = True
    Next
    
    ' Si no hay errores
    If Not hayError Then
        
        ' POST o MEDIA?
        Dim tipoXML As String
        If tipo = "POST" Then
            tipoXML = "params"
        Else
            tipoXML = "string"
        End If
        
        Set elements = xmlDoc.getElementsByTagName(tipoXML)
            
        ' Obtengo el código generado
        resultado = elements(0).Text
    
    ' Si hay errores
    Else
        MsgBox error
        resultado = "-1"
    End If
        
    'MsgBox resultado

End Function


Código - Publicación de Custom Post Type

Y finalmente nuestra función para publicar el custom post type, con pocos cambios respecto a artículos anteriores:

Function PublicarEnWordPress(CodigoArchivo As String, NumeroDocumento As String, CodigoCliente As String) As String
    ' Datos de Autenticación
    CargarConstantes
    txtURL = SITIO
    txtUserName = USUARIO
    txtPassword = PASSWORD
    
    ' Datos del Post
    txtTitulo = CodigoCliente & " - " & NumeroDocumento
    txtContenido = "Este es un custom post de ejemplo publicado desde Microsoft Access"
    Dim txtCategorias(1) As String
    txtCategorias(1) = "Uncategorized"
    'txtImagen = "64"
    txtTipoContenido = "proceso"
    txtCliente = CodigoCliente
    txtNumeroCertificado = NumeroDocumento
    txtDocumento = CodigoArchivo
      
    ' ServerXMLHTTP
    Dim objSvrHTTP As ServerXMLHTTP
    Dim strT As String
    Set objSvrHTTP = New ServerXMLHTTP
  
    ' Autenticación
    objSvrHTTP.Open "POST", txtURL, False, CStr(txtUsuario), CStr(txtPassword)
    objSvrHTTP.setRequestHeader "Accept", "application/xml"
    objSvrHTTP.setRequestHeader "Content-Type", "application/xml"

    strT = strT & "<methodCall>"
    
    ' Acción
    strT = strT & "<methodName>wp.newPost</methodName>"
    
    ' General
    strT = strT & "<params>"
    strT = strT & "<param><value><string>0</string></value></param>"
    strT = strT & "<param><value>" & txtUserName & "</value></param>"
    strT = strT & "<param><value><string>" & txtPassword & "</string></value></param>"
    strT = strT & "<param>"
    
    strT = strT & "<struct>"
    
    ' Categorías
    strT = strT & "<member><name>categories</name><value><array>"
    strT = strT & "<data>"
    For i = 1 To UBound(txtCategorias)
        strT = strT & "<value>" & txtCategorias(i) & "</value>"
    Next i
    strT = strT & "</data>"
    strT = strT & "</array></value></member>"
    
    ' Título, contenido y fecha
    strT = strT & "<member><name>post_content</name><value><![CDATA[" & txtContenido & "]]></value></member>"
    strT = strT & "<member><name>post_title</name><value>" & txtTitulo & "</value></member>"
    strT = strT & "<member><name>dateCreated</name><value><dateTime.iso8601>" & Format(Now(), "yyyyMMdd") & "T" & Format(Now(), "hh:mm:ss") & "</dateTime.iso8601></value></member>"
    
    ' Imagen destacada
    ' strT = strT & "<member><name>post_thumbnail</name><value><![CDATA[" & txtImagen & "]]></value></member>"
    
    ' Tipo de contenido
    strT = strT & "<member><name>post_type</name><value>" & txtTipoContenido & "</value></member>"
    
    ' Campos personalizados
    strT = strT & "<member><name>custom_fields</name><value><array><data><value>"
    
    strT = strT & "<struct>"
    strT = strT & "<member><name>key</name><value>cliente</value></member>"
    strT = strT & "<member><name>value</name><value>" & txtCliente & "</value></member>"
    strT = strT & "</struct>"
    
    strT = strT & "<struct>"
    strT = strT & "<member><name>key</name><value>numero_de_certificado</value></member>"
    strT = strT & "<member><name>value</name><value>" & txtNumeroCertificado & "</value></member>"
    strT = strT & "</struct>"
    
    strT = strT & "<struct>"
    strT = strT & "<member><name>key</name><value>documento</value></member>"
    strT = strT & "<member><name>value</name><value>" & txtDocumento & "</value></member>"
    strT = strT & "</struct>"
    
    strT = strT & "</value></data></array></value></member>"
    
    ' Tipo de publicación
    strT = strT & "<member><name>post_status</name><value>publish</value></member>"
    
    strT = strT & "</struct>"
    strT = strT & "</param>"
    strT = strT & "</params>"
    strT = strT & "</methodCall>"
    
    ' Publicación
    objSvrHTTP.send strT
    
    ' Debug
    Debug.Print objSvrHTTP.responseText
    'MsgBox objSvrHTTP.responseText
    PublicarEnWordPress = resultado(objSvrHTTP.responseText, "POST")

End Function


Cambios al sitio en WordPress

Un último detalle. Hemos creado un pequeño plugin en el sitio WordPress para que se puedan visualizar nuestros campos personalizados, tal como muestra la primera imagen de este post. Les dejo el código de ese plugin:

function retornar_ficha_proceso () {

  if ( 'proceso' == get_post_type() ) { 
    
$ficha = '
<table class="ficha_proceso">
<tr>
<td class="ficha_proceso_tit">CLIENTE:</td>
<td class="ficha_proceso_det">' . get_field('cliente') . '</td>
</tr>
<tr>
<td class="ficha_proceso_tit">NÚMERO DE CERTIFICADO:</td>
<td class="ficha_proceso_det">' . get_field('numero_de_certificado') . '</td>
</tr>
<tr>
<td class="ficha_proceso_tit">DOCUMENTO:</td>
<td class="ficha_proceso_det"><a href="' . wp_get_attachment_url(get_field('documento')) . '">' . get_the_title(get_field('documento')) . '</a></td>
</tr>
</table>
          
';          
        return $ficha;
        }
    }

function mostrar_proceso ($content) {

if ( 'proceso' == get_post_type() ) { 
$content = retornar_ficha_proceso();
}

return $content;
}

add_filter('the_content', 'mostrar_proceso', 1);


Esos es todo por ahora, hasta la próxima!!!