create shortcode that changes url endpoint - wordpress

I am calling data from an api and looping through it as an array. The problem is that I want to only call one individual profile at a time and have a shortcode for each individual profile. I have created the shortcode function and it does work. However, I have to either call all the profiles in the loop or only one through an if statement. This is obviously not what I want. I want to be able to add: player_number=664 (for example) to the end of the endpoint url.
I have the shortcode working but not as I need it.
function individualPlayer(){
$html .= '<div class="s-players">
<div class="container">';
$responseindividualPlayer = wp_remote_get('http://api-address-hidden-for-security/statsajax.php?action=rankedplayerslist&eventid=5');
$array = json_decode(utf8_encode($responseindividualPlayer['body']),TRUE);
foreach($array as $player){
if($player['Numero'] == 707) {
$html .= '
<p>'.$player['Evento'].'</p>
<p>'.(int)$player['Numero'].'</p>
<p>'.$player['Jugador'].'</p>';
}
}
return $html .'</div></div>';
}
add_shortcode('individualPlayer', 'individualPlayer');
I want to remove the if statement.
The URL gives the event ID followed by ?player_number= then the player number.
I would love to have it [shortcode 'player_number=123'] if that is possible. If it is not possible, could someone please help orient me in the right direction?
Thank you in advance.
Erik Robles

First, you would need to pass the player number as a parameter to the individualPlayer function. This can be accomplished as follows:
function individualPlayer($attrs = []){
# Normalize the case
$attrs = array_change_key_case((array)$attrs, CASE_LOWER);
$playerId = $attrs['playerid'];
Shortcode call:
[individualPlayer playerid="123"]
Next, we need to filter the results to just the player you want. If the API supports filtering by the player number, pass $playerId to the endpoint in the required format. For example, if the API accepts the player id as a query string parameter named pid, we can set up the endpoint as follows:
$responseindividualPlayer = wp_remote_get('http://api-address-hidden-for-security/statsajax.php?action=rankedplayerslist&eventid=5&pid=' . $playerId);
If it does not support API-side filtering, then you will have to do it on your side (loop through the results and pick the record with a matching id).
foreach($array as $player){
if($player['Numero'] == $playerId) {
# etc.

Credit goes to Krzysiek Dróżdż for helping me with this answer.
class Remote_Player_API {
private static $instance;
private $remote_data;
public static function init() {
if ( ! self::$instance ) {
self::$instance = new Remote_Player_API();
}
}
protected function __construct() {
$this->register_shortcodes();
}
protected function get_remote_api_data() {
// you can also use transients here and cache remote responses for some time to optimize API calls even more
if ( ! $this->remote_data ) { // obtain remote data only, if we haven't done it already, so the request will be done only once
$response = wp_remote_get('http://api-address-hidden-for-security/statsajax.php?action=rankedplayerslist&eventid=5');
$this->remote_data = json_decode( utf8_encode( $response['body'] ), TRUE );
}
return $this->remote_data;
}
protected function register_shortcodes() {
add_shortcode( 'individualPlayer', array( $this, 'shortcode_callback_individualPlayer' ) );
}
public function shortcode_callback_individualPlayer( $atts ) {
$atts = shortcode_atts( array(
'player_number' => 0, // you have to pass player_number as attribute
), $atts );
ob_start();
?>
<div class="s-players">
<div class="container">
<?php
foreach ( $this->get_remote_api_data() as $player ) :
if ( $player['Numero'] != $atts['player_number'] ) continue;
?>
<p><?php echo esc_html( $player['Evento'] ); ?></p>
<p><?php echo (int)$player['Numero']; ?></p>
<p><?php echo esc_html( $player['Jugador'] ); ?></p>
<?php endforeach; ?>
</div>
</div>
<?php
return ob_get_clean();
}
}
Remote_Player_API::init();

Related

Get start date from Event Calendar wordpress

I'm working on an event website in Wordpress and I use this plugin: https://theeventscalendar.com/
All the documentation files say that I have to use tribe_get_start_date() to get the event date. So that's what I'm using in my custom loop.
$events = tribe_get_events();
if ( empty( $events ) ) {
echo 'Sorry, nothing found.';
} else foreach ($events as $event) {
echo get_the_title( $event );
echo tribe_get_start_date( null, false, 'j F Y' ):
}
But the function tribe_get_start_date always gives the current date instead of the event date.
What can be the issue?
The ideal situation would be that the loop only shows the 4 upcoming events.
Maybe it is due to you passing null to your tribe_get_start_date function, when you might want to be passing $event.
$events = tribe_get_events();
if ( empty( $events ) ) {
echo 'Sorry, nothing found.';
} else foreach ($events as $event) {
echo get_the_title( $event );
echo tribe_get_start_date( $event, false, 'j F Y' ):
}

wordpress: Display last record of Custom post type on home page

I am a novice developer of WordPress.
I created a custom post type wp_locations to practice.
It has three numeric fields that are entered as <input type="number">: a phone_number; a fax_number and a zip_code
$wp_location_phone = get_post_meta($post->ID,'wp_location_phone',true);
$wp_location_fax = get_post_meta($post->ID,'wp_location_fax',true);
$wp_location_zipcode = get_post_meta($post->ID,'wp_location_zipcode',true);
That works properly and stores the information.
I have a plugin to create the Custom Post Type and save a new record in WordPress.
Now I want to display this record on the home page in a table.
I searched but I could not run any suggestions. Please guide me with an example. Thanks
class wp_simple_location{
private $wp_location_trading_hour_days = array();
public function __construct(){
add_action('init', array($this,'set_location_trading_hour_days')); //sets the default trading hour days (used by the content type)
add_action('init', array($this,'register_location_content_type'));
add_action('add_meta_boxes', array($this,'add_location_meta_boxes'));
add_action('save_post_wp_locations', array($this,'save_location')); //save location
register_activation_hook(__FILE__, array($this,'plugin_activate'));
register_deactivation_hook(__FILE__, array($this,'plugin_deactivate'));
}
//display function used for our custom location meta box*/
public function location_meta_box_display($post){
wp_nonce_field('wp_location_nonce', 'wp_location_nonce_field');
//collect variables
$wp_location_phone = get_post_meta($post->ID,'wp_location_phone',true);
$wp_location_fax = get_post_meta($post->ID,'wp_location_fax',true);
$wp_location_zipcode = get_post_meta($post->ID,'wp_location_zipcode',true);
/*
// information is gathered here in a form. The relevant inputs are:
<input type="number" name="wp_location_phone" id="wp_location_phone" value=" <?php echo $wp_location_phone;"?> />
<input type="number" name="wp_location_fax" id="wp_location_fax" value=" <?php echo $wp_location_fax; ?>"/>
<input type="number" name="wp_location_zipcode" id="wp_location_zipcode" value=" <?php echo $wp_location_zipcode;" ?> />
*/
}
//triggered when adding or editing a location
public function save_location($post_id){
// nonce & autosave checks removed from example as they are irrelevant
//get our phone, email and address fields
$wp_location_phone = isset($_POST['wp_location_phone']) ? sanitize_text_field($_POST['wp_location_phone']) : '';
$wp_location_fax = isset($_POST['wp_location_fax']) ? sanitize_text_field($_POST['wp_location_fax']) : '';
$wp_location_zipcode = isset($_POST['wp_location_zipcode']) ? sanitize_text_field($_POST['wp_location_zipcode']) : '';
//update phone, email and address fields
update_post_meta($post_id, 'wp_location_phone', $wp_location_phone);
update_post_meta($post_id, 'wp_location_fax', $wp_location_fax);
update_post_meta($post_id, 'wp_location_zipcode', $wp_location_zipcode);
//search for our trading hour data and update
foreach($_POST as $key => $value){
//if we found our trading hour data, update it
if(preg_match('/^wp_location_trading_hours_/', $key)){
update_post_meta($post_id, $key, $value);
}
}
do_action('wp_location_admin_save',$post_id);
}
} // end class
Other notes:
The customer post type name is "wp_location" but the slug is "locations":
$args = array(
[...]
'rewrite' => array('slug' => 'locations', 'with_front' => 'true')
);
register_post_type('wp_locations', $args);
A quick Google search for "wp_simple_location" shows that you have taken this example from SitePoint and changed it.
Based on that, I'm going to amend the rest of that example to show you how to create a shortcode you can use.
Assumptions:
I presume the code you posts isn't your from your test site, as it is
not valid (e.g. you are missing many )
I'm also going to assume that you only have 1 location - the
sitepoint example allowed you add many but you appear to have removed
that code
Code:
1. Add back in the get_locations_output function.
You deleted the get_locations_output function, which is how you actually display the information - which is what you want! So you need to add it back into your wp_simple_location class. I have changed it so it should work with your changes
// main function for displaying locations (used for our shortcodes and widgets)
public function get_locations_output(){
//find locations
$location_args = array(
'post_type' => 'wp_locations',
'posts_per_page'=> 999,
'post_status' => 'publish'
);
//output
$html = '';
$locations = get_posts($location_args);
//if we have a location it will be returned in an array, so loop through it
if($locations){
$html .= '<article class="location_list cf">';
//foreach location
foreach($locations as $location){
$html .= '<section class="location">';
//collect location data
$wp_location_id = $location->ID;
$wp_location_phone = get_post_meta($wp_location_id,'wp_location_phone',true);
$wp_location_fax= get_post_meta($wp_location_id,'wp_location_fax',true);
$wp_location_zipcode= get_post_meta($wp_location_id,'wp_location_zipcode',true);
// output details only if any were entered
if($wp_location_phone || $wp_location_fax || $wp_location_zipcode){
$html .= '<table>';
if(!empty($wp_location_phone)){
$html .= '<tr><td>Phone: </td><td>' . $wp_location_phone . '</td></tr>';
}
if(!empty($wp_location_fax)){
$html .= '<tr><td>Fax: </td><td>' . $wp_location_fax. '</td></tr>';
}
if(!empty($wp_location_zipcode)){
$html .= '<tr><td>Zipcode: </td><td>' . $wp_location_zipcode. '</td></tr>';
}
$html .= '</table>';
}
//apply the filter after the main content, before it ends
//(lets third parties hook into the HTML output to output data)
$html = apply_filters('wp_location_after_main_content', $html);
$html .= '</section>';
}
$html .= '</article>';
}
return $html;
} // end function
**2. Create a new class that adds a shortcode to let you include the information in pages **
Note: Proper practice is create the new new class in a separate php file and include it in your wp_simple_location class file, but to keep this example simple, add this to the bottom of the file containing your wp_simple_location class:
class wp_location_shortcode{
//on initialize
public function __construct(){
add_action('init', array($this,'register_location_shortcodes')); //shortcodes
}
//location shortcode
public function register_location_shortcodes(){
add_shortcode('wp_locations', array($this,'location_shortcode_output'));
}
//shortcode display
public function location_shortcode_output($atts, $content = '', $tag){
//get the global wp_simple_locations class
global $wp_simple_locations;
//uses the main output function of the location class
$html = $wp_simple_locations->get_locations_output();
return $html;
}
}
$wp_location_shortcode = new wp_location_shortcode;
**3. Use the shortcode to include the information **
To include the information in any page, you just need to use the following shortcode in the post editor:
[wp_locations]
Note:
You should also clean up your plugin code - for example the code starting //search for our trading hour data and update is not needed as you deleted the hours from the plugin. Also make sure all your php tags are correct!
As I mentioned, I have just changed the SitePoint example to work with your changes, so I haven't tested any of this. If you have any questions it might be a good idea to re-read the SitePoint tutorial because it explains the code in detail.

Use postmeta in wordpress shortcode

Trying to get my post meta from posts using shrotcodes and then displaying it on the content.This is the code that's trying to do this:
$string = '';
$custom_content = get_post_custom($post->ID);
if( $my_query->have_posts() ) {
while ($my_query->have_posts()) : $my_query->the_post();
$content = get_the_content();
$bonus = $custom_content["bonus"];
$string .= $content . $bonus . '<br>';
endwhile;
}
return $string;
It's not working as the custom content returns empty. Whats wrong? Thanks in advance
I don't think you got the shortcode idea, you should read some info about add_shortcode() also you can use get_post_meta() to retriev the metadata from the database.
Here is an example on how you can achieve this but this will only work with the main loop (as default):
<?php
//you can put this code in functions.php or you can build a plugin for it
function metadata_in_content($attr) {
//this is the function that will be triggerd when the code finds the proper shortcode in the content; $attr is the parameter passed throw the shortcode (leave null for now)
global $wpdb, $wp_query;
//we need global $wpdb to query the database and to get the curent post info
if (is_object($wp_query->post)) {
$post_id = $wp_query->post->post_id;// here we save the post id
$metadata = get_post_meta( $post_id, $key, $single ); // here we get the needed meta, make sure you place the correct $key here, also if you don't want to get an array as response pass $single as "true"
return $metadata; // this finally replaces the shortcode with it's value
}
}
add_shortcode('insert_metadata', 'metadata_in_content');
//the above code hooks the metadata_in_content function to the [insert_metadata] shortcode
?>
Now all it's left to do is to place [insert_metadata] in the post content and things should work.

Checkbox array in Wordpress widget?

I'm trying to create a widget that enables user to select which categories will be displayed.
The following is piece of codes I created but the changes of the checkbox state can't be saved. There are only two values : the title and list of selected categories.
function form($instance) {
$instance = (array)$instance;
if( empty($instance['title']) ) $instance['title'] = 'Category';
$selected_categories = (array)$instance['category'];
var_dump($selected_categories);
....
$categories = get_categories( array('exclude'=> 1) );
foreach($categories as $category) : ?>
<div>
<input type="checkbox" name="<?php echo $this->get_field_name('category'); ?>"
value="<?php echo $category->cat_ID; ?>"
<?php echo $category->cat_name; ?>
</div>
<?php endforeach; ?>
}
function update($new_instance, $old_instance) {
$instance = $old_instance;
$instance['title'] = strip_tags($new_instance['title']);
$instance['category'] = $new_instance['category'];
return $instance;
}
I observe the changes through var_dump($selected_categories). The value is always array(size=0) ignoring how many checkbox I checked.
I have no idea how to passing array in $instance variable.
Thanks in advance.
Do you have a validation function that fills the values in the array if they are not set? That is the »update« method of the widget. Perhaps you should add:
'<input name="..." value="..." id="'.$this->get_field_id( 'category' ).'" />';
to your input element.
I spent a lot of time on this exact issue. Searches online on this topic were less than satisfying. I wanted to understand how the Widget extends WP_Widget object works. Like the original post I too wanted to allow my admins to select from a dynamic check list of all post categories. In my website, I'm using this for promos, and I expect to have lots of instances of this puppy. A robust instance storage system is essential for me.
A couple of stupid questions that were bugging me.
1) What's up with the funky label for=.... Category Name /label things I see on each and every example online. (Note 'label' is surrounded by left/right symbols.. can't do that here..) Is that required, or merely somebody copying what's been done before (within the file defaults-widgets.php in the WordPress source code)? Ans: total waste of time. Less is more, code it right.
2) I really really wanted to understand the mechanism of how the system saves a users selections. There appears to be no obvious coding on the backend page to capture the selections. I spent a long time here searching, including attempting to step thru the code on a debugger, with lousy results. I spent a lot of time with var_dump($instance) to understand results. The system works, but I don't really understand why.
My logic in making this system work was to create a single checkbox variable, get that to work. Next step was to create an array of checkbox variables but only use one of them and get that to work. Finally utilize the entire array of checkbox variables. Success.
Code extract follows:
/*Saves the settings. */
function update( $new_instance, $old_instance ){
$args = array(
//your selections here.
);
$categories = get_categories( $args ); // returns an array of category objects
$arrlength=count($categories);
for($x=0;$x<$arrlength;$x++){
$tempArray[$categories[$x]->slug] = '';
}
$instance = $old_instance;
$new_instance = wp_parse_args( (array) $new_instance, $tempArray );
for($x=0;$x<$arrlength;$x++){
$instance[$categories[$x]->slug] = $new_instance[$categories[$x]->slug] ? 1 : 0;
}
return $instance;
}
/*Creates the form for the widget in the admin back-end. */
function form( $instance ){
echo '<p>Choose your categories of interest. Multiple selections are fine.</p> ';
$args = array(
//your selections here. Use same args as update function, duh.
);
$categories = get_categories( $args ); // returns an array of category objects
$arrlength=count($categories);
for($x=0;$x<$arrlength;$x++){
$tempArray[$this->get_field_id($categories[$x]->slug)] = '';
}
$instance = wp_parse_args( (array) $instance, $tempArray );
for($x=0;$x<$arrlength;$x++){
$tempCheckFlag[$categories[$x]->slug] = $instance[$categories[$x]->slug] ? 'checked="checked"' : '';
// could also use 'checked()' function
// Yup, this could be combined with the for loop below,
// listed here seperately to enhance understanding of what's going on.
}
for($x=0;$x<$arrlength;$x++)
{
echo '<p><input class ="checkbox" type="checkbox" value="1" id="'.$this->get_field_id($categories[$x]->slug).'" name="'.$this->get_field_name($categories[$x]->slug).'"'.$tempCheckFlag[$categories[$x]->slug].'>'.$categories[$x]->name.' (Category # '.$categories[$x]->term_id.' )</p>';
}
}
When I need to use the selections in my widget function, I retrieve the admin's selections from the $instance variable.
/* Displays the Widget in the front-end */
function widget( $args, $instance ){
//....
foreach($instance as $key=>$value)
{
if ($value){
$category_array[]=$key;
}
}
// Now I have a simple array of just those categories that had a check mark...
Here is a second solution that uses an array of checkbox.
I solved this problem with a checkbox array in the new version 1.8 of my widget recently updated posts widget.
I use the second form of foreach
foreach (array_expression as $key => $value).
$key allows to obtain a unique id for each checkbox.
Here $id is a number incremented by the foreach itself.
function form($instance) {
$term_taxonomy_id = (isset($instance['term_taxonomy_id']) ? array_map('absint', $instance['term_taxonomy_id']) : array("0"));
<?php
$categ = get_categories();
foreach($categ as $id => $item) :
?>
<br/>
<input type="checkbox"
id="<?php echo $this->get_field_id('term_taxonomy_id') . $id; ?>"
name="<?php echo $this->get_field_name('term_taxonomy_id'); ?>[]"
<?php if (isset($item->term_taxonomy_id)) {
if (in_array($item->term_taxonomy_id,$term_taxonomy_id))
echo 'checked';
};
?>
value="<?php echo $item->term_taxonomy_id; ?>" />
<label for="<?php echo $this->get_field_id('term_taxonomy_id') . $id; ?>" >
<?php echo $item->name ?>
</label>
<?php endforeach; ?>
I stored term_taxonomy_id instead cat_ID, for my plugin, but you can pretty much store cat_ID, it will work as well.
The array data is sanitized by the php function array_map ().The update function is:
function update($new_instance, $old_instance) {
// Par défaut, aucune catégorie n'est exclue
$instance['term_taxonomy_id'] = (isset($new_instance['term_taxonomy_id']) ? array_map( 'absint', $new_instance['term_taxonomy_id']) : array('0'));
For their use in a MySQL query, I implodes it into a set of values:
// écriture de la liste des objects sélectionnées en langage MySQL
if (isset($instance['term_taxonomy_id']))
$selected_object = "('".implode(array_map( 'absint',$instance['term_taxonomy_id']),"','")."')";
else $selected_object = "('0')";

Wordpress Settings API error

Hi I am trying to creating some custom options for a template I am developing but I seem to be getting an error:
Warning: Illegal string offset 'show_header' in C:\xampp\htdocs\wordpress\wp-content\themes\01MyWork\includes\theme-options.php on line 62
This is the line that seems to be throwing the error:
$html = '<input type="checkbox" id="show_header" name="thanathos_theme_display_options[show_header]" value="1" ' . checked(1, $options['show_header'], false) . '/>';
And this is the entire code:
<?php
function thanatos_theme_menu(){
add_theme_page(
"Thanathos Theme Options",
"Thanathos Theme",
"administrator",
"thanathos_theme_options",
"thanathos_theme_display_callback"
);
}
add_action('admin_menu' , 'thanatos_theme_menu');
function thanathos_theme_display_callback(){
?>
<div class="wrap">
<div id="icon-themes" class="icon32"></div>
<h2>Sandbox Theme Options</h2>
<?php settings_errors(); ?>
<!--Create the form that will be used to render our options-->
<form method="post" action="options.php">
<?php settings_fields('thanathos_theme_display_options'); ?>
<?php do_settings_sections( 'thanathos_theme_display_options' ); ?>
<?php submit_button(); ?>
</form>
</div>
<?php
}
add_action('admin_init' , 'thanatos_initializa_theme_options');
function thanatos_initializa_theme_options(){
if( false == get_option( 'thanathos_theme_display_options' ) ) {
add_option( 'thanathos_theme_display_options' );
}
add_settings_section(
'general_settings_section',
'Thanatos Options',
'thanatos_general_options_callback',
'thanathos_theme_display_options'
);
add_settings_field(
'show_header',
'Header',
'thanathos_field_header_callback',
'thanathos_theme_display_options',
'general_settings_section',
array( // The array of arguments to pass to the callback. In this case, just a description.
'Activate this setting to display the header.'
)
);
register_setting('thanathos_theme_display_options', 'thanathos_theme_display_options');
}
function thanatos_general_options_callback(){
echo 'mergem la mare';
}
function thanathos_field_header_callback($args){
// First, we read the options collection
$options = get_option('thanathos_theme_display_options');
// Next, we update the name attribute to access this element's ID in the context of the display options array
// We also access the show_header element of the options collection in the call to the checked() helper function
$html = '<input type="checkbox" id="show_header" name="thanathos_theme_display_options[show_header]" value="1" ' . checked(1, $options['show_header'], false) . '/>';
// Here, we'll take the first argument of the array and add it to a label next to the checkbox
$html .= '<label for="show_header"> ' . $args[0] . '</label>';
echo $html;
}
?>
Yes, that's the problematic part:
if( false == get_option( 'thanathos_theme_display_options' ) ) {
add_option( 'thanathos_theme_display_options' );
}
That's the initial if statement at the beginning of the thanatos_initializa_theme_options() function.
You can find the solution in the very neat Theme Options API tut at http://wp.tutsplus.com/tutorials/theme-development/the-complete-guide-to-the-wordpress-settings-api-part-4-on-theme-options/#post-684925289
Or, more exactly more exactly in this article's comments section.
I'm pasting the Steve Bondy's smart solution here because for some reason making the page scroll to the appropriate comment doesn't work for me (in Chrome at least).
START quote
(...)One little issue I had - I followed along through reordering the code, up to just before adding the Social options. At that point I discovered that the code was broken. I would get an error like
Warning: Illegal string offset 'show_header' in ...\themes\Sandbox\functions.php
Warning: Illegal string offset 'show_content' in ...\themes\Sandbox\functions.php
Warning: Illegal string offset 'show_footer' in ...\themes\Sandbox\functions.php
It turns out that this error was caused by adding 'sandbox_theme_display_options' to the options table without giving it a value. If you change sandbox_initialize_theme_options as follows it will create and initialize the options, avoiding the error experienced by myself and others.
function sandbox_initialize_theme_options() {
// If the theme options don't exist, create them.
if( false == get_option( 'sandbox_theme_display_options' ) ) {
$options = array("show_header" => TRUE, "show_content" => TRUE, "show_footer" => TRUE);
add_option( 'sandbox_theme_display_options', $options);
} // end if
(...)
If the old code has been run the empty 'sandbox_theme_display_options' value must be deleted from the database first. Alternatively, the following code will also detect this case and correct it.
function sandbox_initialize_theme_options() {
// See if the options exist, and initialize them if they don't
$options = get_option( 'sandbox_theme_display_options' );
if( false == $options or $options == "" ) {
$options = array("show_header" => TRUE, "show_content" => TRUE, "show_footer" => TRUE);
update_option( 'sandbox_theme_display_options', $options);
} // end if
(...)
This checks for non-existant or empty options values and initializes the options using update_option instead of add_option.
EOF quote
You are using name="thanathos_theme_display_options[show_header]" in plain HTML. Probably you want to parse by PHP the string [show_header].
You may have to run:
delete_option('thanathos_theme_display_options');
during 'admin_init' if you think you have old plugin information mucking about in the database and need a fresh start.

Resources