Wordpress custom page template and WP-API - php

My Wordpress site uses custom template pages like this one:
<php
/* 
Template Name : project_costs
/*
get_header ();
// set default vars or user received
require("my_forms.php");
// pull data from db and calculate
require("project_calculation. php");
// create page
require("content. php");
...
My custom page project_costs.php performing the steps :
Receive and set user entered vars from page forms (POST/GET).
Pull data from database.
Do some calculations and changes.
Creates page for user. 
I want to integrate angular.js with the WP-API plugin. The plugin just pulls raw data from database (step 2) and sends it to front end (step 4). So pages and templates not in use as page didn't reload.
I want to pass data to my php class first (step 3), then pass changed data to WP-API.
Is there any function in WP-API to call my PHP file or function? 
Any advice, samples or links would be highly appreciated.
Thanks.

So I'm working on a huge project which includes several API/Angular replacement parts for #WordPress. One file is a custom endpoint-boilerplate.php. It works like a charm so far but any input would be appreciated.
Just follow the structure and use the my_awesome_function to return do anything you'd like. Then the namespace and route from the hook will be available, using data from my_awesome_func.
<?php
/* ------------------------------------------------------------------------ *
A great example of custom endpoints is the PHP in wp-api-menus plugin
* ------------------------------------------------------------------------ */
// hook into rest_api_init and register a new api route
add_action( 'rest_api_init', function () {
register_rest_route(
'custom-endpoint/v2', // namespace
'/author/(?P<id>\d+)', // route
array( // options
'methods' => 'GET',
'callback' => 'my_awesome_func',
// 'args' => array(
// 'context' => array(
// 'default' => 'view',
// ),
// )
)
);
});
function my_awesome_func( $data ) {
$posts = get_posts( array(
'author' => $data['id'],
) );
if ( empty( $posts ) ) {
return null;
}
return $posts[0]->post_title;
}
So your call will then be a get to http://yourproject.com/wp-json/custom-endpoint/v2/author/1

Related

Block users from REST API endpoint while still grabbing data from it

I have created 2 REST API endpoint to store the CPT data and their custom fields:
Archive Data: xyz.com/wp-json/wl/v2/businesses
Single Business data: xyz.com/wp-json/wl/v2/businesses/<ID>
Both these endpoints have been registered with the permission callbacks;
register_rest_route( 'wl/v2', '/businesses', array(
'methods' => WP_REST_Server::READABLE,
'callback' => 'wl_businesses_posts',
'permission_callback' => '__return_true'
));
It is a business directory website where a common dashboard ( xyz.com/dashboard ) for each 'business' client exists and this dashboard page pulls in data for that 'business' from the Single Business data REST API endpoint above and fills the input fields on the page.
There is also another page accessible to the non-logged in visitors( xyz.com/business1 ) that is common for all businesses and is a read-only page where visitors can check that business' details. This page too pulls data from the Single Business data REST API endpoint mentioned above.
What I am trying to accomplish is that no one except the Admin should be able to peep into the Archive Data or the Single Business data endpoints directly which displays that tall JSON data, to avoid stealing info of all the businesses registered with the site. But at the same time, I would want these endpoints to be accessible by the wp_remote_retrieve_body( wp_remote_get( $url ) );code to populate the dashboard and single business info pages.
I tried this code but it obviously also blocks the requests made by the page code to pull and populate data in the pages.
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;
});
I am not necessarily looking for a code, just the direction about how to solve this problem.
------------------------------UPDATE----------------------------:
Like I said, since it is a business directory, even non logged-in users should see the archive pages and single business pages of the CPT. I've learned recently about the 'permission callbacks' in register_rest_route arguments, so how would I pass a custom 'key' argument in the wp_remote_get function and receive and validate it in the permission callback?
Ok I've managed to secure my endpoint by passing a param in the request, and only if it matches in the permission callback of the rest endpoint, then the data is retrieved:
$userData = wp_remote_retrieve_body( wp_remote_get( $url, array(
'body' => array(
'param' => '1'
),
'sslverify' => false,
) ) );
And in the register_rest_route:
'permission_callback' => function( WP_REST_Request $request ) {
if ( '1' == $request->get_param( 'param' ) ) {
return true;
} else {
return false;
}
}
I'm so happy I wont have to use a plugin for this :D

How to add php values to a function in a wordpress dashboard widget?

I am working on a plugin for wordpress - and I am pretty new at this - but I am trying to make dashboard widgets that display feeds from different sources (CNN, The Onion, MOZ, etc.) I have the plugin set up with a custom options pages I got from https://jeremyhixon.com/tool/wordpress-option-page-generator/ and everything seems to work right. My question is - how do I take the values from the options page and add them to my widget code. Here are the specific options:
Feed Label
Feed URL
Number of Articles
/*
* Retrieve this value with:
* $dashboard_feeds_options = get_option( 'dashboard_feeds_option_name' ); // Array of All Options
* $feed_label_0 = $dashboard_feeds_options['feed_label_0']; // Feed Label
* $feed_url_1 = $dashboard_feeds_options['feed_url_1']; // Feed URL
* $number_of_articles_2 = $dashboard_feeds_options['number_of_articles_2']; // Number of Articles
*/
Here is an example of my widget code with The Onion as a feed source
/** START The Onion Dashboard */
add_action( 'wp_dashboard_setup', 'onion_dashboard_add_widgets' );
function onion_dashboard_add_widgets() {
wp_add_dashboard_widget( 'dw_dashboard_widget_onion', __( 'The Onion', 'dw' ), 'dw_dashboard_widget_onion_handler' );
}
function dw_dashboard_widget_onion_handler() {
$feeds = array(
array(
'url' => 'https://www.theonion.com/rss',
'items' =>15,
'show_summary' => 1,
'show_author' => 0,
'show_date' => 1,
),
);
ob_start(); // start output buffering
wp_dashboard_primary_output( 'dw_dashboard_widget_onion', $feeds );
$buffer = ob_get_clean(); // get the buffer without printing the content
// add the target attribute to the a-tag:
$result = str_replace("<a class='rsswidget'",
"<a class='rsswidget' target='_blank'", $buffer);
echo $result;
};
/** END The Onion Dashboard */
To sum it up - how do I take the values entered in the options page into this code to make it easy for someone to add multiple dashboard widgets to their site? As always - thank you in advance for helping me figure this out!
I would useget_option, you can find more on it here: https://developer.wordpress.org/reference/functions/get_option/. The basic idea would be something like this:
// from your plugin
$example_option_value = get_option('example_option_key');
// do something with $example_option_value

WP Admin: Include custom post type archive in link search results

I've been searching for examples of this online and through the WP documentation on filters but I can't find a suitable hook, so apologies for posting a question without a good example of what I'm trying to do!
When you add a link to text or to a button in the editor, you can search for the page/post you want to link to. What you can't search for is a post type archive link.
I want to be able to type the name of a post type into the search box (pictured below), and include the post type archive link in the search results. In this example, I have a post type called members that I'd like to link to.
I find the need to do this a lot, and I always end up just typing /post-type-link into the box and leaving it at that, but I don't think this is an elegant solution and is clunky for users.
I have tried to write some code, but I don't believe I have the right hook:
function include_cpt_search( $query ) {
if ( is_admin() && is_single() ) {
$query->set( 'post_type', array( 'services' ) );
}
return $query;
}
add_filter( 'pre_get_posts', 'include_cpt_search' );
Has anyone done this before? Know of a filter or hook I could work with? Anything really!
The Link format in the RichText toolbar uses the Search REST API endpoint at /wp/v2/search, so although that endpoint doesn't provide a specialized hook for filtering the response, you can use rest_post_dispatch to add custom links to the search results returned via /wp/v2/search.
So in the examples below, I'm checking if the route is /wp/v2/search and if so, then we add the (custom) post type's archive link. Also note that, you should provide an array with the items mentioned here (the LinkControl component used by the Link format).
Basic Example
Includes only the (i.e. one) post type whereby its name matched exactly the search keyword.
add_filter( 'rest_post_dispatch', 'so_62472641', 10, 3 );
function so_62472641( $response, $server, $request ) {
// Don't modify the data if the REST API route is not /wp/v2/search
if ( 'post' !== $request->get_param( 'type' ) ||
'/wp/v2/search' !== $request->get_route() ) {
return $response;
}
// Let's see if there's a post type that matched the search keyword.
$search = $request->get_param( 'search' );
if ( ! $post_type = get_post_type_object( $search ) ) {
return $response;
}
// Now add the post type archive URL, if any, to the response data.
if ( $url = get_post_type_archive_link( $search ) ) {
$data = (array) $response->get_data();
$data[] = [
'id' => 'post_type-' . $search,
'type' => 'Post Type Archive',
'title' => $post_type->label,
'url' => $url,
];
$response->set_data( $data );
}
return $response;
}
Extended Example
Includes all post types whereby the name/label matched the search keyword.
add_filter( 'rest_post_dispatch', 'so_62472641', 10, 3 );
function so_62472641( $response, $server, $request ) {
// Don't modify the data if the REST API route is not /wp/v2/search
if ( 'post' !== $request->get_param( 'type' ) ||
'/wp/v2/search' !== $request->get_route() ) {
return $response;
}
$search = $request->get_param( 'search' );
$post_types = get_post_types( [], 'objects' );
$extra_data = [];
// Let's see if there's a post type that matched the search keyword.
foreach ( $post_types as $obj ) {
if ( $search === $obj->name ||
// look for the search keyword in the post type name/slug and labels (plural & singular)
false !== stripos( "{$obj->name} {$obj->label} {$obj->labels->singular_name}", $search )
) {
if ( $url = get_post_type_archive_link( $obj->name ) ) {
$extra_data[] = [
'id' => 'post_type-' . $obj->name,
'type' => 'Post Type Archive',
'title' => $obj->label,
'url' => $url,
];
}
}
}
// Now add the post type archive links, if any, to the response data.
if ( ! empty( $extra_data ) ) {
$response->set_data( array_merge( (array) $response->get_data(), $extra_data ) );
}
return $response;
}
Sample Output (for the second example above)
Note: The above is a screenshot of a real response, but I deliberately (via PHP) changed the domain name to example.com (i.e. the actual domain name is different).
And the examples were both tried & tested working on WordPress 5.5.1 (latest release as of writing). Also, you can exclude the default post post type, if you want to.
Additional Notes
It should be noted that the examples do not take into account the pagination, which means, if there were 10 post types that matched the search keyword, then they would always be included in the response (on page 1, 2, 3, etc.). So you might want to just use the first example because at least it always includes at most 1 post type only. However, with the second example, you can actually limit the $extra_data to, say, 5 items (per page - but it's up to you on how to distribute the items per page).
You can also use a custom search handler class, e.g. one that extends the default class (WP_REST_Post_Search_Handler) and use the wp_rest_search_handlers hook to add your class to the list. Here's a very basic example...
In your-class.php:
class My_WP_REST_Post_Search_Handler extends WP_REST_Post_Search_Handler {
// ... you'll need to actually write the code on your own..
}
return new My_WP_REST_Post_Search_Handler;
In the theme's functions.php file or somewhere in your plugin:
add_filter( 'wp_rest_search_handlers', 'my_wp_rest_search_handlers' );
function my_wp_rest_search_handlers( $search_handlers ) {
$search_handlers[] = include_once '/path/to/the/your-class.php';
return $search_handlers;
}

How to Create Author archive page for custom post types

My WordPress site uses one default "post" and "books" custom post. I have two different archive page design for different post types (ile. author.php and books-archive.php).
Now, I want to create a custom user profile page with two links, "All Posts by user" and "All books by user". My current user archive page looks like as follows;
xxxxxxx.com/author/nilanchala
Can someone help me how to create two author archive pages filtered by post types? One for "Post" and other for "Books"?
Please do not suggest any plugin.
This is just an example and you should modify it the way you want, we will be using a custom query and rewrite rule to build the url
First thing you need to do is to create rewrite rule for the two custom query you want to display.
example, you have to reset the permalink in order for the new rewrite rule to take effect,
this is better to be created in a class and in a custom plugin so you can simply call flush_rewrite_rules() function
during plugin activation to reset the permalink.
function _custom_rewrite() {
// we are telling wordpress that if somebody access yoursite.com/all-post/user/username
// wordpress will do a request on this query var yoursite.com/index.php?query_type=all_post&uname=username
add_rewrite_rule( "^all-post/user/?(.+)/?$", 'index.php?query_type=all_post&uname=$matches[1]', "top");
}
function _custom_query( $vars ) {
// we will register the two custom query var on wordpress rewrite rule
$vars[] = 'query_type';
$vars[] = 'uname';
return $vars;
}
// Then add those two functions on thier appropriate hook and filter
add_action( 'init', '_custom_rewrite' );
add_filter( 'query_vars', '_custom_query' );
Now that you have build a custom URL you can then load a custom query on that custom url by creating a custom .php file as template and using template_include filter to load the template if the url/request contains query_type=all_post
function _template_loader($template){
// get the custom query var we registered
$query_var = get_query_var('query_type');
// load the custom template if ?query_type=all_post is found on wordpress url/request
if( $query_var == 'all_post' ){
return get_stylesheet_directory_uri() . 'whatever-filename-you-have.php';
}
return $template;
}
add_filter('template_include', '_template_loader');
You should then be able to access yoursite.com/index.php?query_type=all_post&uname=username or yoursite.com/all-post/user/username
and it should display whatever you put on that php file.
Now that you have the custom url and custom php file, you can start creating your custom query inside the php file to query post type based on user_nicename/author_name,
e.g.
<?php
// get the username based from uname value in query var request.
$user = get_query_var('uname');
// Query param
$arg = array(
'post_type' => 'books',
'posts_per_page' => -1,
'orderby' => 'date',
'order' => 'DESC',
'author_name' => $user;
);
//build query
$query = new WP_QUery( $arg );
// get query request
$books = $query->get_posts();
// check if there's any results
if ( $books ) {
echo '<pre>', print_r( $books, 1 ), '</pre>';
} else {
'Author Doesn\'t have any books';
}
I'm not sure why you need to build a custom query for all post as the default author profile loads all the default posts.

Creating custom tab with ultimatemember plugin of wordpress

I've been trying to create a custom tab for my website and am using UltimateMember plugin.
After bit of google I found some code snippet that can help me do it:
First we need to extend main profile tabs
add_filter('um_profile_tabs', 'add_custom_profile_tab', 1000 );
function add_custom_profile_tab( $tabs ) {
$tabs['mycustomtab'] = array(
'name' => 'My custom tab',
'icon' => 'um-faicon-comments',
);
return $tabs;
}
Then we just have to add content to that tab using this action
add_action('um_profile_content_mycustomtab_default', 'um_profile_content_mycustomtab_default');
function um_profile_content_mycustomtab_default( $args ) {
echo 'Hello world!';
}
But my question, to what file should I add this code to achieve what I need. It sounds very numb of me to ask this, but I'm seriously confused.
Thanks for any help.
Let me share my similar experience. First of all in this code :
$tabs['mycustomtab'] = array(
'name' => 'My custom tab',
'icon' => 'um-faicon-comments',
);
You should use always
mycustomtab
as key which I see you've already used. So that's true.
Generally it works out when you put this code in your active theme's functions.php
But if it doesn't work out, consider adding this to core file um-filters-misc.php in the plugin core file folder for ultimate-member. Let me know if it works for you.
Not sure if anyone still needs help on this, but make sure to add a 'custom' key/value like this:
$tabs['mycustomtab'] = array(
'name' => 'My custom tab',
'icon' => 'um-faicon-comments',
'custom' => true // <- needs to be added so it shows up on the profile page
);
The code example in the UltimateMember documentation -specifically for extending the Profile Menu using hooks- doesn't work because the sample code doesn't have that line.
Hi guys thanks for your help... im using this codes and works "good"... if a want to put shotcode the website print "blue screen" error... [ultimatemember form_id="15817"] (if i use "hello word" works perfect..
function um_mycustomtab_add_tab( $tabs ) {
$tabs['mycustomtab'] = array(
'name' => 'Seguimiento',
'icon' => 'um-faicon-pencil',
);
return $tabs;
}
add_filter( 'um_profile_tabs', 'um_mycustomtab_add_tab', 1000 );
// Action
function um_profile_content_mycustomtab_default( $args ) {
echo do_shortcode('[ultimatemember form_id="15817"]'); //this not work
}
add_action( 'um_profile_content_mycustomtab_default', 'um_profile_content_mycustomtab_default');
here some screenshots tests

Categories