The post Rust: JSON stringify and parse in Node.js appeared first on Justin Silver.
]]>I’m learning Rust for a project to build native modules for use with Node.js and it took me a bit of time to figure out how to parse and stringify JSON using serde_json
and neon_serde
. With Rust still being a relatively new language, the API of both the language and its crates have shifted over time making some of the older examples no longer useful. The solution I came up with using Rust 1.35 and Neon Bindings 0.2 follows.
[package] name = "rust-json" [lib] name = "rust_json" crate-type = ["dylib"] [build-dependencies] neon-build = "0.2.0" [dependencies] neon = "0.2.0" 'neon-serde' = "0.1.1" serde_json = "1.0.39"
#[macro_use] extern crate neon; extern crate neon_serde; extern crate serde_json; use neon::prelude::*; fn stringify(mut cx: FunctionContext) -> JsResult<JsString> { // get the argument as a JsValue (any json type) let value = cx.argument::<JsValue>(0)?; // convert to a serde Value let object: serde_json::Value = neon_serde::from_value(&mut cx, value)?; // convert to a String let string = serde_json::to_string(&object).unwrap(); // return the JsString Ok(cx.string(string)) } fn parse(mut cx: FunctionContext) -> JsResult<JsValue> { // get the argument as a string let string = cx.argument::<JsString>(0)?; // convert from serde Value to serde_json Value let object: serde_json::Value = serde_json::from_str(&string.value()).unwrap(); // now convert to JsValue (any json type) let value = neon_serde::to_value(&mut cx, &object)?; / return the JsValue Ok(value) } register_module!(mut cx, { cx.export_function("stringify", stringify)?; cx.export_function("parse", parse)?; Ok(()) });
Node.js
const native = require('../native'); // more javascript logic here module.exports = native;
You can now import this module as you would any other node module.
const rust = require('rust-json'); // or however you reference your module const stringified = rust.stringify({ test: 123 }); console.log('stringified', stringified); const parsed = rust.parse(stringified); console.log('parsed', parsed);
The post Rust: JSON stringify and parse in Node.js appeared first on Justin Silver.
]]>The post Creating AJAX Functions in WordPress appeared first on Justin Silver.
]]>Adding an AJAX callback to WordPress 2.8+ is pretty simple – you just need to hook in the wp_ajax_(action)
action for admin callbacks, and the wp_ajax_nopriv_(action)
action for front-end callbacks. One caveat however is that the ajaxurl
property (which holds the URL for admin-ajax.php
where the AJAX call is submitted) is not automatically included. You will have to add it manually by adding admin_url( 'admin-ajax.php' )
to make it available on the front-end. The (action)
in the callback matches up with the action: my_action
that should be passed in your AJAX call, for example wp_ajax_my_action
.
// process all my_action for admin only add_action( 'wp_ajax_my_action', 'my_action_callback_function' ); // process my_action for the front-end too admin_url( 'admin-ajax.php' ); add_action( 'wp_ajax_nopriv_my_action', 'my_action_callback_function' );
For versions of WordPress older than 2.8, add an action on init
to handle the AJAX requests. When called the function will attempt to call do_action()
for the key "wp_ajax_" + $_REQUEST['action']
, so if the “action” in the $_REQUEST was “get_post” the resulting key would be “wp_ajax_get_post”. This effectively reproduces the functionality of the wp_ajax_nopriv_(action)
action hook in WordPress 2.8+.
// process all wp_ajax_* calls function core_add_ajax_hook() { /* Theme only, we already have the wp_ajax_ hook firing in wp-admin */ if ( ! defined( 'WP_ADMIN' ) && isset( $_REQUEST['action'] ) ) { do_action( 'wp_ajax_' . $_REQUEST['action'] ); } } add_action( 'init', 'core_add_ajax_hook' );
Now you are free to add as many wp_ajax_* functions as you would like. To continue with the example above, we will create a function for “wp_ajax_get_post”.
This is the PHP function that handles your AJAX callback. Noted that it takes no arguments, and that you will have to grab the values submitted using $_GET
, $_POST
, or the more generic $_REQUEST
(though not really recommended) depending on your HTTP type used.
// get a post by its post.ID function wp_ajax_get_post_callback_function() { // default response $response = array( "success"=>false ); /* get the 'post_id' from the $_REQUEST and sanitize, if post can be loaded set success to true and assign post */ $post_id = filter_input( INPUT_POST, 'post_id', FILTER_SANITIZE_NUMBER_INT ); if ( $post_id && $post = get_post( $post_id, ARRAY_A ) ){ $response = array( "success"=>true, "post"=>$post ); } // set the content type and return json encode response, then exit header( 'Content-type: application/json' ); die( json_encode( $response ) ); } add_action( 'wp_ajax_get_post', 'wp_ajax_get_post_callback_function' );
And now to call this AJAX method using jQuery.
$(document).ready(function(){ // the post id to query var my_post_id = 123; // add a click event to our anchor link that will post the id and get back the post data. $('#anchor').on('click', function(){ $.post( ajaxurl, { action: 'get_post', // the action to pass to the WordPress hook, and then do_action() post_id: my_post_id // the post id to query }, success: function(response){ if (response.success==true){ alert('The post title is ' + response.post.post_title); } } ); } });
This can be triggered by clicking a link like the following.
<a href="#" id="anchor">Click Me</a>
The post Creating AJAX Functions in WordPress appeared first on Justin Silver.
]]>The post Google Analytics for WordPress Fixed appeared first on Justin Silver.
]]>“Unfortunately, an error occurred while connecting to Google”
Google Analytics for WordPress is a great plugin by Yoast to make adding Analytics tracking to your WordPress site easy. All was well until Google updated their authentication and authorization APIs, thus breaking the plugin’s ability to load your Google Analytics accounts and properties using your Google credentials via OpenID
and OAuth
. The error that comes back in this case is "Unfortunately, an error occurred while connecting to Google"
but no additional information on what exactly the problem was. It has been broken for some time now, and although you can enter your UA code manually, I decided to just fix the code in question.
In a nutshell Google updated their URLs and transitioned from an XML interface to a JSON RESTful web service. The changes are pretty straightforward, but now require two calls to Google to get both the Analytics Accounts associated with your username/auth token and a second one to get all of the Analytics Properties (though they can be loaded for all properties at the same time by using ~all in place of the account id in the request.
The file to modify lives under /wp-content/plugins/google-analytics-for-wordpress/googleanalytics.php
. Here is what the code looks like in my version, currently the latest, at 4.2.8. and starts on line 383 and ends on line 435. Replace the code here with the code below it:
// ... Opening code $response = $gdata->get( 'https://www.google.com/analytics/feeds/accounts/default' ); $http_code = wp_remote_retrieve_response_code( $response ); $response = wp_remote_retrieve_body( $response ); if ( $http_code == 200 ) { $options['ga_api_responses'][$token] = array( 'response'=> array( 'code'=> $http_code ), 'body' => $response ); $options['ga_token'] = $token; update_option( 'Yoast_Google_Analytics', $options ); } } if ( isset( $options['ga_api_responses'][$token] ) && is_array( $options['ga_api_responses'][$token] ) && $options['ga_api_responses'][$token]['response']['code'] == 200 ) { $arr = yoast_xml2array( $options['ga_api_responses'][$token]['body'] ); $ga_accounts = array(); if ( isset( $arr['feed']['entry'][0] ) ) { foreach ( $arr['feed']['entry'] as $site ) { $ua = $site['dxp:property']['3_attr']['value']; $account = $site['dxp:property']['1_attr']['value']; if ( !isset( $ga_accounts[$account] ) || !is_array( $ga_accounts[$account] ) ) $ga_accounts[$account] = array(); $ga_accounts[$account][$site['title']] = $ua; } } else { $ua = $arr['feed']['entry']['dxp:property']['3_attr']['value']; $account = $arr['feed']['entry']['dxp:property']['1_attr']['value']; $title = $arr['feed']['entry']['title']; if ( !isset( $ga_accounts[$account] ) || !is_array( $ga_accounts[$account] ) ) $ga_accounts[$account] = array(); $ga_accounts[$account][$title] = $ua; } // ... Closing code
The modified code looks like this:
// ... Opening code // Get all of the Accounts for this oauth token $url = 'https://www.googleapis.com/analytics/v3/management/accounts'; $response = $gdata->get( $url ); $http_code = wp_remote_retrieve_response_code( $response ); $response = wp_remote_retrieve_body( $response ); if ( $http_code == 200 ) { $options['ga_api_responses'][$token] = array( 'acct_response'=> array( 'code'=> $http_code ), 'acct_body' => $response ); // Get all of the properties for this oauth token $url = 'https://www.googleapis.com/analytics/v3/management/accounts/~all/webproperties/'; $response = $gdata->get( $url ); $http_code = wp_remote_retrieve_response_code( $response ); $response = wp_remote_retrieve_body( $response ); if ( $http_code == 200 ) { $options['ga_api_responses'][$token]['response'] = array( 'code'=> $http_code ); $options['ga_api_responses'][$token]['body'] = $response; $options['ga_token'] = $token; update_option( 'Yoast_Google_Analytics', $options ); } } } if ( isset( $options['ga_api_responses'][$token] ) && is_array( $options['ga_api_responses'][$token] ) && $options['ga_api_responses'][$token]['response']['code'] == 200 ) { // Get all of the accounts so we can reference the name by ID $account_info = array(); $json = json_decode( $options['ga_api_responses'][$token]['acct_body'] ); foreach ($json->items as $item) { $account_id = strval($item->id); $account_info[$account_id] = $item->name; } // Get all of the properties in to an array $ga_accounts = array(); $json = json_decode( $options['ga_api_responses'][$token]['body'] ); foreach ($json->items as $item) { $account_id = strval($item->accountId); $account = $account_info[$account_id]; $ua = $item->id; $title = $item->name; // make sure we have an arrary created to hold the properties if ( !isset( $ga_properties[$account] ) || !is_array( $ga_properties[$account] ) ) $ga_accounts[$account] = array(); // Save the property by account for display $ga_accounts[$account][$title] = $ua; } // ... Closing code
The post Google Analytics for WordPress Fixed appeared first on Justin Silver.
]]>