Sure, there’s several files you gotta modify and I will be using demyx
as my namespace.
/web/app/themes/demyx/app/setup.php
Localizing a global array variable that can be accessible anywhere on the frontend. For this example, I’ve included the REST url endpoint and nonce; accessible via demyx.rest
and demyx.nonce
in your .js files.
/**
* Theme assets
*/
add_action('wp_enqueue_scripts', function () {
wp_enqueue_style('sage/main.css', asset_path('styles/main.css'), false, null);
wp_enqueue_script('sage/main.js', asset_path('scripts/main.js'), ['jquery'], null, true);
wp_localize_script('sage/main.js', 'demyx', [
'rest' => home_url() . '/wp-json/demyx/v1',
'nonce' => wp_create_nonce('wp_rest'),
]);
if (is_single() && comments_open() && get_option('thread_comments')) {
wp_enqueue_script('comment-reply');
}
}, 100);
...
/web/app/themes/demyx/.eslintrc.js
Must add your global variable, otherwise webpack will say demyx is not defined
.
module.exports = {
'root': true,
'extends': 'eslint:recommended',
'globals': {
'wp': true,
'demyx': true,
},
...
/web/app/themes/app/rest.php
I like to put specific functionalities of WordPress into their own files.
<?php
namespace App;
use WP_Query;
use WP_Error;
/*
* All of WP REST access is only available to logged in users (aka you)
*/
add_filter('rest_authentication_errors', function($result) {
if (!empty( $result )) {
return $result;
}
if (! is_user_logged_in()) {
return new WP_Error('rest_not_logged_in', 'You are not currently logged in.', array( 'status' => 401));
}
return $result;
});
/*
* REST endpoints
*/
add_action('rest_api_init', function() {
/*
* Custom endpoint
* https://domain.tld/wp-json/demyx/v1/custom
*/
register_rest_route('demyx/v1', '/custom', array(
'methods' => ['GET'],
'callback' => function() {
// Gets data from the ajax request
$get_custom_data = (empty($_GET['custom_data']) ) ? null : sanitize_text_field($_GET['custom_data']);
$data = [];
// Do your wp_query() or custom PHP query here
return $data;
},
'permission_callback' => function () {
// Permission check, returns a boolean
return current_user_can('edit_others_posts');
}
));
});
...
/web/app/themes/demyx/resources/functions.php
Include rest.php into the fold.
/**
* Sage required files
*
* The mapped array determines the code library included in your theme.
* Add or remove files to the array as needed. Supports child theme overrides.
*/
array_map(function ($file) use ($sage_error) {
$file = "../app/{$file}.php";
if (!locate_template($file, true, true)) {
$sage_error(sprintf(__('Error locating <code>%s</code> for inclusion.', 'sage'), $file), 'File not found');
}
}, [
'helpers',
'setup',
'filters',
'admin',
'rest'
]
);
...
/web/app/themes/demyx/resources/assets/scripts/routes/common.js
I’m placing this in common.js
as an example. Feel free to put this any file of your choosing. Probably have to make blog.js
to fire in only blog posts?
export default {
init() {
// JavaScript to be fired on all pages
$.ajax({
url: demyx.rest + '/custom',
method: 'GET',
data: {
custom_data: $('input').val(),
},
beforeSend: function (xhr) {
xhr.setRequestHeader('X-WP-Nonce', demyx.nonce);
},
success: function(data) {
console.log(data);
},
});
},
finalize() {
// JavaScript to be fired on all pages, after page specific JS is fired
},
};
Let me know if I’ve missed anything.