custom tax term; set post term issue - wordpress

I am trying to set the post custom taxonomy via two variables (parent Id and child Id) that I've gotten from another function in my plugin file. var's $a and $b
When I manually enter the term ID - everything works fine but when I try to use a variable - to set the term id - it doesn't work
The function for getting the id's in the first code snippet, and trying to save the terms in the second snippet.
//***IF YOU HAVE MODEL GET THE ID
if(!empty($auto_model)){
$auto_model_id = get_term_by( 'slug', $auto_model, $this->tax );
$auto_model_id = $auto_model_id->term_id;
} // end get model id
if ($auto_make_id !== null && $auto_model_id !== null) { // +++++ IF YOU HAVE BOTH
$this->p_id = $auto_make_id; // define variable
$this->c_id = $auto_model_id; // define variable
// set post with both these terms - jump to set post and pass ids to set post
//return $p_id;
return $c_id . $p_id;
}
function cicb_do_things($post_id) { // use this as the final build up before sending to construct
global $auto_make,$auto_model;
$this->makemodel();
$a = $this->p_id;
$b = $this->c_id;
$tag = array( 45 ); // this is how wp wants me to do it; and when I do the wp_set object works great
var_dump ($tag);
echo '<br>';
$tag = array( $a ); // when I put in my variable which is the also 45 - the term does not work
wp_set_object_terms( $post_id, $tag, $this->tax );
}

Related

woocommerce_before_order_object_save hook not work [duplicate]

Hello I'm trying to create a function in the mu-plugins to prevent certain users to change order status from specific order statuses to specific order statuses.
I've been looking everywhere and I have tried many different ways, but nothing seems to work.
Actually the function is running using woocommerce_order_status_changed action hook. The thing is that this hook runs after the order status has already been changed, what's causing an infinite loop.
The most useful hook I found seems to be woocommerce_before_order_object_save.
I found "Add an additional argument to prevent 'woocommerce_order_status_changed' from being called" useful related thread on WooCommerce Github.
I tried using #kloon code snippet solution:
add_filter( 'woocommerce_before_order_object_save', 'prevent_order_status_change', 10, 2 );
function prevent_order_status_change( $order, $data_store ) {
$changes = $order->get_changes();
if ( isset( $changes['status'] ) ) {
$data = $order->get_data();
$from_status = $data['status'];
$to_status = $changes['status'];
// Do your logic here and update statuses with CRUD eg $order->set_status( 'completed' );
// Be sure to return the order object
}
return $order;
}
but $changes variable is always an empty array.
I tried to use wp_insert_post_data Wordpress hook, but when I set:
$data['post_status'] = "some status";
it just prevents the whole update (the whole new data) from being saved.
This is the code I would like to run is:
function($data){
if($data['order_status'] == 'comlpeted' && $data['new_order_status'] == 'proccessing'){
// prevent the order status from being changed
$data['new_order_status'] = $data['order_status'];
}
few more if conditions...
return $data;
}
Any help or advise is appreciated.
Based on #kloon code snippet, I have been able to get the old order status and the new order status. Then I can disable any status change from a specific defined order status to a specific defined order status.
With the following code, specific defined user roles can't change order status from "processing" to "on-hold":
add_filter( 'woocommerce_before_order_object_save', 'prevent_order_status_change', 10, 2 );
function prevent_order_status_change( $order, $data_store ) {
// Below define the disallowed user roles
$disallowed_user_roles = array( 'shop_manager');
$changes = $order->get_changes();
if( ! empty($changes) && isset($changes['status']) ) {
$old_status = str_replace( 'wc-', '', get_post_status($order->get_id()) );
$new_status = $changes['status'];
$user = wp_get_current_user();
$matched_roles = array_intersect($user->roles, $disallowed_user_roles);
// Avoid status change from "processing" to "on-hold"
if ( 'processing' === $old_status && 'on-hold' === $new_status && ! empty($matched_roles) ) {
throw new Exception( sprintf( __("You are not allowed to change order from %s to %s.", "woocommerce" ), $old_status, $new_status ) );
return false;
}
}
return $order;
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.

WordPress prevent delete taxonomy

I would like to prevent that some categories are accidentally deleted. For this I use a meta entry for the category to be protected.
I use the following code for this:
// edit: wrong hook! ** add_action( 'delete_term_taxonomy', 'taxonomy_delete_protection', 10, 1 );
add_action( 'pre_delete_term', 'taxonomy_delete_protection', 10, 1 );
function taxonomy_delete_protection ( $term_id )
{
if (get_term_meta ($term_id, 'delete-protect', true) === true)
{
wp_die('Cannot delete this category');
}
}
Unfortunately, instead of my error message, only "Something went wrong" is displayed. Why?
Edit: The `delete_term_taxonomy` is the wrong hook for my code, because it deleted the meta before i can check the meta entry. `pre_delete_term` does fire before anything happens with the category.
The "Why" is because of the following JavaScript that ships with WordPress:
$.post(ajaxurl, data, function(r){
if ( '1' == r ) {
$('#ajax-response').empty();
tr.fadeOut('normal', function(){ tr.remove(); });
/**
* Removes the term from the parent box and the tag cloud.
*
* `data.match(/tag_ID=(\d+)/)[1]` matches the term ID from the data variable.
* This term ID is then used to select the relevant HTML elements:
* The parent box and the tag cloud.
*/
$('select#parent option[value="' + data.match(/tag_ID=(\d+)/)[1] + '"]').remove();
$('a.tag-link-' + data.match(/tag_ID=(\d+)/)[1]).remove();
} else if ( '-1' == r ) {
$('#ajax-response').empty().append('<div class="error"><p>' + wp.i18n.__( 'Sorry, you are not allowed to do that.' ) + '</p></div>');
tr.children().css('backgroundColor', '');
} else {
$('#ajax-response').empty().append('<div class="error"><p>' + wp.i18n.__( 'Something went wrong.' ) + '</p></div>');
tr.children().css('backgroundColor', '');
}
});
The expected response to this POST request is:
'1' if the term was deleted
'-1' if your user doesn't have permission to delete the term.
For all other cases, "Something went wrong" is displayed.
You are terminating the script early with wp_die, yielding an unexpected response, which comes under "other cases".
There isn't a way to provide a custom error message in the notice box here without writing some JavaScript of your own.
This is my current solution, not perfect but it works.
The "Something went wrong" message show up if you delete the taxonomy with the row action. So i unset the "delete" action so it couldn't be triggered this way.
add_filter ('category_row_actions', 'unset_taxonomy_row_actions', 10, 2);
function unset_taxonomy_row_actions ($actions, $term)
{
$delete_protected = get_term_meta ($term->term_id, 'delete-protect', true);
if ($delete_protected)
{
unset ($actions['delete']);
}
return $actions;
}
Then i hide the "Delete" Link in the taxonomy edit form with css. It's still could be triggered if you inspect the site and it's link, but there is no hook to remove this action otherwise.
add_action( 'category_edit_form', 'remove_delete_edit_term_form', 10, 2 );
function remove_delete_edit_term_form ($term, $taxonomy)
{
$delete_protected = get_term_meta ($term->term_id, 'delete-protect', true);
if ($delete_protected)
{
// insert css
echo '<style type="text/css">#delete-link {display: none !important;}</style>';
}
}
Finally the check before deleting the taxonomy. This should catch all other ways, like the bulk action "delete". I didn't found another way yet to stop the script from deleting the taxonomy.
add_action ('pre_delete_term', 'taxonomy_delete_protection', 10, 1 );
function taxonomy_delete_protection ( $term_id )
{
$delete_protected = get_term_meta ($term_id, 'delete-protect', true);
if ($delete_protected)
{
$term = get_term ($term_id);
$error = new WP_Error ();
$error->add (1, '<h2>Delete Protection Active!</h2>You cannot delete "' . $term->name . '"!');
wp_die ($error);
}
}
This solution provides a way to disable all categories from being deleted by a non Admin. This is for anyone like myself who's been searching.
function disable_delete_cat() {
global $wp_taxonomies;
if(!current_user_can('administrator')){
$wp_taxonomies[ 'category' ]->cap->delete_terms = 'do_not_allow';
}
}
add_action('init','disable_delete_cat');
The easiest solution (that will automatically take care of all different places where you can possibly delete the category/term) and in my opinion the most flexible one is using the user_has_cap hook:
function maybeDoNotAllowDeletion($allcaps, $caps, array $args, $user)
{
if ($args[0] !== 'delete_term') return $allcaps;
// you can skip protection for any user here
// let's say that for the default admin with id === 1
if ($args[1] === 1) return $allcaps;
$termId = $args[2];
$term = get_term($termId);
// you can skip protection for all taxonomies except
// some special one - let's say it is called 'sections'
if ($term->taxonomy !== 'sections') return $allcaps;
// you can protect only selected set of terms from
// the 'sections' taxonomy here
$protectedTermIds = [23, 122, 3234];
if (in_array($termId, $protectedTermIds )) {
$allcaps['delete_categories'] = false;
// if you have some custom caps set
$allcaps['delete_sections'] = false;
}
return $allcaps;
}
add_filter('user_has_cap', 'maybeDoNotAllowDeletion', 10, 4);

Wordpress REST API: Get raw database content

I want to pull data from my event calender. So I added REST API support to my event content type. But my JSON output is with HTML.
Can I not get the raw database data?
I get this: http://astc.dk/wp-json/wp/v2/event/
I put this in my functions.php
add_action( 'init', 'my_event_cpt', 25 );
function my_event_cpt() {
global $wp_post_types;
//be sure to set this to the name of your post type!
$post_type_name = 'event';
if( isset( $wp_post_types[ $post_type_name ] ) ) {
$wp_post_types[$post_type_name]->show_in_rest = true;
// Optionally customize the rest_base or controller class
$wp_post_types[$post_type_name]->rest_base = $post_type_name;
$wp_post_types[$post_type_name]->rest_controller_class = 'WP_REST_Posts_Controller';
}
}

Applying a coupon code programmatically to the cart/order

I've been stuck trying to apply a Drupal commerce coupon for about 2 days now. I have taken care of validating the coupon and currently stumped when I'm trying to redeem it.
So inside my callback function I'm calling:
my_module_coupons_coupon_redeem($coupon);
And inside the redeem function I have:
function my_module_coupons_coupon_redeem($coupon) {
global $user;
$uid = $user->uid;
$order = commerce_cart_order_load($uid);
// Wrap the order for easy access to field data.
$order_wrapper = entity_metadata_wrapper('commerce_order', $order);
// Create the new line item.
$line_item = commerce_coupon_line_item_new($coupon, $order->order_id);
$line_item->commerce_unit_price = array('und' => array(
'0' => array('amount' => 500, 'currency_code' => commerce_default_currency())
));
$line_item_wrapper = entity_metadata_wrapper('commerce_line_item', $line_item);
if (!is_null($line_item_wrapper->commerce_unit_price->value())) {
// Add the base price to the components array.
if (!commerce_price_component_load($line_item_wrapper->commerce_unit_price->value(), 'base_price')) {
$line_item_wrapper->commerce_unit_price->data = commerce_price_component_add(
$line_item_wrapper->commerce_unit_price->value(),
'base_price',
$line_item_wrapper->commerce_unit_price->value(),
TRUE
);
}
}
$line_item_wrapper->commerce_total->data = $line_item_wrapper->commerce_unit_price->data;
//$line_item_wrapper->commerce_product->data = $coupon;
// Save the line item now so we get its ID.
commerce_line_item_save($line_item);
// Add it to the order's line item reference value.
$order_wrapper->commerce_line_items[] = $line_item;
commerce_order_save($order);
}
The coupon line_item is being saved on the DB but when I refresh the cart page I get the following error:
EntityMetadataWrapperException: Unknown data property commerce_product. in EntityStructureWrapper->getPropertyInfo()
Just wondering if this is the correct way of applying coupons without the use of Rules and should I be saving it as a line item in the first place?
Take a look in sites/all/modules/commerce_coupon/oncludes/commerce_coupon.checkout_pane.inc
global $user;
$uid = $user->uid;
$error = '';
// load the cart
$order = commerce_cart_order_load($uid);
// load the coupon from the coupon code
// see MySQL -> your-schema, table: commerce_coupon, column: code
$coupon = commerce_coupon_redeem_coupon_code($code, $order, $error);
// 302 to the cart
drupal_goto('checkout/' . $order->order_id);
I realized this was posted a few years ago, but there was no working answer and I still couldn't find a complete solution for it anywhere.
After you've added the line item you still need to add the commerce coupon reference to the order like so:
$order_wrapper->commerce_coupon_order_reference[] = $coupon;
This way it won't get removed when commerce_coupon_commerce_cart_order_refresh() runs.

Get gravity forms fields

I am using the gravity form on my site. I am working on create the custom report for this I have need gravity form fields name and id based on specific form id.Please let me know how I can do it.
I am using the following function but it is showing all forms info based on it. it is looking very hard to parse it. Please let me know any function so I can get fields name easily.
$forms = RGFormsModel::get_forms_by_id(13);
try this
function get_all_form_fields($form_id){
$form = RGFormsModel::get_form_meta($form_id);
$fields = array();
if(is_array($form["fields"])){
foreach($form["fields"] as $field){
if(isset($field["inputs"]) && is_array($field["inputs"])){
foreach($field["inputs"] as $input)
$fields[] = array($input["id"], GFCommon::get_label($field, $input["id"]));
}
else if(!rgar($field, 'displayOnly')){
$fields[] = array($field["id"], GFCommon::get_label($field));
}
}
}
//echo "<pre>";
//print_r($fields);
//echo "</pre>";
return $fields;
}
It's not that hard to parse:
$fields=array();
foreach ( $forms['fields'] as $field ) {
$fields[]=array($field['id'] => $field['inputName']);
}
P.S. I'm assuming you use Gravity Forms < 1.7 as RGFormsModel::get_forms_by_id is a deprecated function since 1.7
// Get the Form fields
$form = RGFormsModel::get_form_meta($form_id);
// Run through the fields to grab an object of the desired field
$field = RGFormsModel::get_field( $form, $field_id );
I use the above to get a specific field I want to filter the value of. The $field contains an object with all the properties you want.
echo $field->label // Gets the label
echo $field->inputName // Gets the name
echo $field->type // Gets the type
echo $field->cssClass // Gets the CSS Classes as a string
You are able to get the entered value/content of a field by using rgpost() and by referencing the id ($field->id).
// Check the entered value of every field
foreach( $form['fields'] as &$field ) {
// Get the content for the specific field
$fieldContent = rgpost( "input_".$field->id );
// Check the content
if ( $fieldContent == ... ){}
}

Resources