Can't sanitize select field with WordPress Categories - php

I'm adding a custom field to page that would select a blog category to feature on that page. All the other fields are working fine, so, i'll post code related only to this field. Getting error 500 when loading page editor.
$feat_blog = isset( $values['feat_blog'] ) ? esc_attr( $values['feat_blog'][0] ) : "";
This is the field itself
<select name="feat_blog" id="feat_blog" value="<?php echo $feat_blog; ?>">
<?php $categories = get_categories(); foreach($categories as $category) { ?>
<option value="<?php echo $category->slug ?>"> <?php echo $category->name ?></option>
<?php } ?>
</select>
And sanitization code that's actually causing trouble
if ( isset( $_POST['feat_blog'] )){
$valid_values = array(
categories = get_categories();
foreach($categories as $category) {
echo $category->slug,
}
);
$value = sanitize_text_field( $_POST['feat_blog'] );
if( in_array( $value, $valid_values ) ) {
update_post_meta( $post->ID, 'feat_blog', $value );
}
}

There are quite a few things wrong with your code here...
You are putting ; in an array and attempting to assign a variable there.
You are echoing in an array.
You are running functions inside an array.
You are missing the $ infront of the $categories variable.
if ( isset( $_POST['feat_blog'] )) {
$categories = get_categories();
$valid_values = array();
foreach($categories as $category) {
$valid_values[] = $category->slug;
}
$value = sanitize_text_field( $_POST['feat_blog'] );
if( in_array( $value, $valid_values ) ) {
update_post_meta( $post->ID, 'feat_blog', $value );
}
}
What I did here is I moved the $categories variable declaration outside of the foreach loop and set the $valid_values array BEFORE the loop. If you set it inside the loop it is going to reset every time the loop occurs. You also can't use ; inside of an array as that is intended to close the statement.

Related

Get the first category assigned to a WordPress post but ignore certain categories

My WordPress project has a couple of categories that are used internally only and I don't want them to be picked up on the front end. This causes problems when I want to display the first category assigned to a post.
What I'm trying to do is loop through the assigned categories using get_the_category until I reach a category that is not Uncategorised or Event. I've tried using continue and break without success.
$categories = get_the_category();
if ( ! empty( $categories ) ) {
foreach( $categories as $category ) :
$category_name = $category->cat_name;
if ( $category_name == 'Uncategorised' || $category_name == 'Event' ) continue;
$category = esc_html( $category_name );
break;
endforeach;
}
echo $category;
I expected this to display the first category name that is not Uncategorised or Event as a string, though I've had inconsistent results, with it returning objects and even the unwanted names. Any help would be much appreciated.
Update
I ended up using this:
$categories = get_the_category();
if( $categories ) {
foreach( $categories as $category ) :
$category_name = $category->cat_name;
if ( $category_name == 'Uncategorised' || $category_name == 'Event' ) continue;
$category = esc_html( $category_name );
break;
endforeach;
if( ! is_string( $category ) ) {
$category = null;
}
}
However, I'm pretty sure it could be done in a less verbose way and I'm also unsure about the non-string result which occurs if neither of the two excluded categories are found. I'd still be grateful for some expert opinion.
Your don't break foreach loop correctly:
$categories = get_the_category();
if ( ! empty( $categories ) ) {
$category_ok = '';
foreach( $categories as $key => $category ) :
$category_name = $category->cat_name;
if ( $category_name !== 'Uncategorised' && $category_name !== 'Event' ) {
$category_ok = esc_html( $category_name );
break;
}
endforeach;
}
echo $category_ok;

Adding HTML to PHP loop

I am using the following code to output a list of custom taxonomies:
<?php // Get terms for post
$terms = get_the_terms( $post->ID , 'status' );
// Loop over each item since it's an array
if ( $terms != null ){
foreach( $terms as $term ) {
// Print the name method from $term which is an OBJECT
print $term->slug ;
print $term->name;
// Get rid of the other data stored in the object, since it's not needed
unset($term);
}
}
?>
My question is, how can I add html to this loop? I have tried multiple methods such as:
echo '<button class="filter $term->slug" data-filter="$term->slug">$term->name</button>';
...but this either errors out, or doesn't print the required terms. My desired output of html would be:
<button class="filter term-slug" data-filter="term-slug">term-name</button>
Please try this way. It should work. You need to just print '".$term->name."'like this inside the HTML to identify the object variable.
<?php // Get terms for post
$terms = get_the_terms( $post->ID , 'status' );
// Loop over each item since it's an array
if ( $terms != null ){
foreach( $terms as $term ) {
// Print the name method from $term which is an OBJECT
echo '<button class="filter "'.$term->slug.'"" data-filter="'.$term->slug.'">'".$term->name."'</button>';
// Get rid of the other data stored in the object, since it's not needed
unset($term);
}
}
?>
Rewrite your line as below:-
echo "<button class='filter {$term->slug}' data-filter='{$term->slug}'>$term->name</button>";
Please add below code and check.
<?php
$terms = get_the_terms( $post->ID , 'status' );
if ( $terms != null )
{
foreach( $terms as $term )
{
echo '<button class="filter "'.$term->slug.'"" data-filter="'.$term->slug.'">'".$term->name."'</button>';
unset($term);
}
}
?>

How to display taxonomy parent for selected taxonomy

I want to show on the site the parent of the selected taxonomy. For that I have the above code but the problem with this is that it is showing all the selected taxonomy in a list with now structure.
global $post;
$features = get_the_terms( $post->ID, 'property-feature' );
if ( !empty( $features ) && is_array( $features ) && !is_wp_error( $features ) ) {
?>
<div class="property-features">
<?php
global $inspiry_options;
$property_features_title = $inspiry_options[ 'inspiry_property_features_title' ];
if( !empty( $property_features_title ) ) {
?><h4 class="fancy-title"><?php echo esc_html( $property_features_title ); ?></h4><?php
}
?>
<ul class="property-features-list clearfix">
<?php
foreach( $parent_term as $single_feature ) {
echo '<li>'. $single_feature->name . '</li>';
}
?>
</ul>
</div>
<?php
}
Example:
Parent: option 1, option 2
Parent 2 : option 3, option 4
If I select option 2 and option 3 I want to see
Parent: option 2
Parent 2 : option 3
Updare 2
global $post;
$features = get_the_terms( $post->ID, 'property-feature' );
$featuresss = get_the_terms( $post->ID, 'property-feature' );
// determine the topmost parent of a term
function get_term_top_most_parent($term_id, $taxonomy){
// start from the current term
$parent = get_term_by( 'id', $term_id, $taxonomy);
// climb up the hierarchy until we reach a term with parent = '0'
while ($parent->parent != '0'){
$term_id = $parent->parent;
$parent = get_term_by( 'id', $term_id, $taxonomy);
}
return $parent;
}
// so once you have this function you can just loop over the results returned by wp_get_object_terms
function hey_top_parents($taxonomy, $results = 1) {
// get terms for current post
$terms = wp_get_object_terms( get_the_ID(), $taxonomy );
$y = get_the_terms($terms->term_id, $taxonomy);
// set vars
$top_parent_terms = array();
foreach ( $terms as $term ) {
//get top level parent
$top_parent = get_term_top_most_parent( $term->term_id, $taxonomy );
//check if you have it in your array to only add it once
if ( !in_array( $top_parent, $top_parent_terms ) ) {
$top_parent_terms[] = $top_parent;
}
}
// build output (the HTML is up to you)
foreach( $top_parent_terms as $single_feature ) {
echo '<li>'. $single_feature->name . '</li>';
foreach( $terms as $single ) {
echo '<ul><li>'. $single->name . '</li></ul>';
}
}
//return $top_parent_terms;
}
I managed to display the top parent for the selected taxonomy but now the problem is that I need now to display in the top parent anly the selected taxonomy from that parent
global $post;
$taxonomy = "property-feature";
// determine the topmost parent of a term
function get_term_top_most_parent($term_id, $taxonomy){
// start from the current term
$parent = get_term_by( 'id', $term_id, $taxonomy);
// climb up the hierarchy until we reach a term with parent = '0'
while ($parent->parent != '0'){
$term_id = $parent->parent;
$parent = get_term_by( 'id', $term_id, $taxonomy);
}
return $parent;
}
// so once you have this function you can just loop over the results returned by wp_get_object_terms
function hey_top_parents($taxonomy, $results = 1) {
// get terms for current post
$terms = wp_get_object_terms( get_the_ID(), $taxonomy );
// set vars
$top_parent_terms = array();
foreach ( $terms as $term ) {
//get top level parent
$top_parent = get_term_top_most_parent( $term->term_id, $taxonomy );
//check if you have it in your array to only add it once
if ( !in_array( $top_parent, $top_parent_terms ) ) {
$top_parent_terms[] = $top_parent;
}
}
// build output (the HTML is up to you)
foreach( $top_parent_terms as $single_feature )
{
echo '<li>'. $single_feature->name . '</li>';
foreach( $terms as $single ) {
if( $single_feature->term_id == $single->parent ) {
echo '<ul><li>'. $single->name . '</li></ul>';
}
}
}
//return $top_parent_terms;
}
CHANGES:
1) Moved taxonomy name to variable (used in echo's).
$taxonomy = "property-feature";
2) Added if condition to the code responsible for displaying sub terms.
if( $single_feature->term_id == $single->parent ) {
echo '<ul><li>'. $single->name . '</li></ul>';
}
REMOVED (not used lines of codes):
1)
$features = get_the_terms( $post->ID, 'property-feature' );
$featuresss = get_the_terms( $post->ID, 'property-feature' );
2)
$y = get_the_terms($terms->term_id, $taxonomy);
CONSIDER:
1) Removing $results variable from:
function hey_top_parents($taxonomy, $results = 1) {
it is not used anywhere or maybe should be to determine if results should be returned or displayed by the function.

wp_reset_postdata() doesn't restore the global $post variable

I'm using WP_Query to get posts from a custom post type to use the result in a metabox. Everything works great with my query. But after this query I can't get the other meta values from database.
This is my helper function to get custom field value:
function my_page_get_custom_field( $value ) {
global $post;
$custom_field = get_post_meta( $post->ID, $value, true );
if ( !empty( $custom_field ) )
return is_array( $custom_field ) ? stripslashes_deep( $custom_field ) : stripslashes( wp_kses_decode_entities( $custom_field ) );
return false;
}
Here's my query:
$sliderArgs = array(
'posts_per_page' => -1,
'post_type' => 'slider',
);
$slider = new WP_Query($sliderArgs);
if ($slider->have_posts()) {
?>
<select name="slider" id="slider">
$selectedSlide = my_page_get_custom_field('slider');
while($slider->have_posts()){
$slider->the_post();
$slideID = get_the_ID();
?><option value="<?php echo $slideID; ?>" <?php selected($selectedSlide, $slideID, true); ?>><?php the_title(); ?></option><?php
}
wp_reset_postdata(); ?>
</select>
}
And this is my other custom field which returns empty (there is a value in database and when I try to change it works great but not displaying in input value in admin):
<input type="text" name="meta_title" id="meta_title" value="<?php echo my_page_get_custom_field('meta_title'); ?>">
OK I solved it.
I used get_posts instead of WP_Query. This helped me a lot: https://core.trac.wordpress.org/ticket/18408#comment:5

wordpress, get category names for a custom post type

Is there a better way to get the category names for a custom post type in wordpress?
<?php // get the portfolio categories
$terms = get_the_terms( $post->ID, 'filters' );
if ( $terms && ! is_wp_error( $terms ) ) :
$names = array();
$slugs = array();
foreach ( $terms as $term ) {
$names[] = $term->name;
$slugs[] = $term->slug;
}
$name_list = join( " / ", $names );
$slug_list = join( " category-", $slugs );
endif;
?>
<!-- BEGIN portfolio-item-->
<li class="portfolio-item third column category-<?php echo $slug_list; ?>" data-filter="category-<?php echo $slug_list; ?>">
<?php
$taxonomy = 'filters';
$terms = get_terms($taxonomy);
if ( $terms && !is_wp_error( $terms ) ) :
?>
<ul>
<?php foreach ( $terms as $term ) { ?>
<li><?php echo $term->name; ?></li>
<?php } ?>
</ul>
<?php endif;?>
Or in fuctions.php place this:
function get_the_category_custompost( $id = false, $tcat = 'category' ) {
$categories = get_the_terms( $id, $tcat );
if ( ! $categories )
$categories = array();
$categories = array_values( $categories );
foreach ( array_keys( $categories ) as $key ) {
_make_cat_compat( $categories[$key] );
}
return apply_filters( 'get_the_categories', $categories );
}
and call the function as:
<?php $cat = get_the_category_custompost($post->ID, 'Your Custom Taxonomy'); ?>
My answer seems too simple, but I used this to list the categories from a wordpress plugin called DW Question Answer that has separate categories from the standard wp categories.
I am assuming that Design Wall used custom post types to create the q&a part and taxonomies to create the categories.
<ul>
<?php wp_list_categories('taxonomy=dwqa-question_category&hide_empty=0&orderby=id&title_li=');?>
</ul>
Assuming your custom taxonomy is recipegroups, i have implemented and tested this code in functions.php and i am sure that it will work in plugins too.
$recipeTerms = get_terms(array(
'taxonomy' => 'recipegroups',
));
foreach($recipeTerms as $recipeTerm){
if($recipeTerm->parent==0){
echo "<div class='termsBox'>"; // remove these div's to suit your needs..
$termLink =get_term_link( $recipeTerm );
echo "<a href='$termLink'><div class='termParent'>".$recipeTerm->name."</div></a> ";
$termChilds = get_term_children($recipeTerm->term_id, 'recipegroups' );
foreach($termChilds as $child){
$chTerm = get_term_by( 'id', $child, 'recipegroups');
$termLink =get_term_link( $chTerm );
echo "<a href='$termLink'><div class='top-cat-items'>".$chTerm->name."</div></a>";
}
echo "</div>"; // end of termsBox div
}
}

Categories