I'd like to add a query variable to all queries coming from a certain domain.
For example, mydomain.com and proxydomain.com both show the same WordPress site, but for users visiting via proxydomain.com, I'd like to be able to handle their queries differently.
Additionally, I'd like to apply some different CSS styles for visitors coming through proxydomain.com.
I was thinking I could check for the query_var and apply classes based on the presence of that variable.
This is the code to add to your functions.php file:
add_filter( 'body_class', 'domain_as_body_class' );
function domain_as_body_class( $classes ) {
$classes[] = sanitize_title( $_SERVER['SERVER_NAME'] );
return $classes;
}
It adds the sanitized domain of your site (i.e. mydomain-com or proxydomain-com) as class of the body tag of your pages, so you can target the relative class for custom styles.
Update
For the queries you could add a function again in functions.php like:
function is_proxydomain() {
return 'proxydomain.com' == $_SERVER['SERVER_NAME'];
}
And then use it when needed on a query:
if( is_proxydomain() ) {
$args = array(
// arguments for proxydomain.com
);
} else {
$args = array(
// arguments for mydomain.com
);
}
$query = new WP_Query( $args );
I like the answer of d79 for the first part.
For the queries, I think it would be better to extend WP_Query class ( i.e. WP_Query_Custom ) and have one copy for each domain. Then you can load the file you need based on the domain in the functions.php file, and so you don't need to change in the future your calls everywhere you use WP_Query_Custom, even if you need to add more domains and different versions of WP_Query_Custom.
//in functions.php
$mydomain = str_replace('.', '_', $_SERVER['SERVER_NAME']);
require_once("path/to/my/classes/$mydomain/WP_Query_Custom.php");
//In each path/to/my/classes/$mydomain/WP_Query_Custom.php
class WP_Query_Custom extends WP_Query {
function __construct( $args = array() ) {
// Force these args
$args = array_merge( $args, array(
'post_type' => 'my_custom_post_type',
'posts_per_page' => -1, // Turn off paging
'no_found_rows' => true // Optimize query for no paging
) );
add_filter( 'posts_where', array( $this, 'posts_where' ) );
parent::__construct( $args );
// Make sure these filters don't affect any other queries
remove_filter( 'posts_where', array( $this, 'posts_where' ) );
}
function posts_where( $sql ) {
global $wpdb;
return $sql . " AND $wpdb->term_taxonomy.taxonomy = 'my_taxonomy'";
}
}
The example class is copied from extending WP_Query
Related
Issue: How should I go for a conditional "move to trash" action? It means that delete a particular post only when a certain condition is met. Otherwise, prompt user that this can't be done.
Things I've tried: I am calling a function on pre_trash_hook and checking my condition. But I'm not sure how to stop WordPress from not moving forward with further "move to trash" action. Here's the code for reference.
public function register_pre_trash_handler( $product_post_type, $product_comparator_type_meta_key ) {
$this->product_post_type = $product_post_type;
$this->product_comparator_type_meta_key = $product_comparator_type_meta_key;
add_filter( "pre_trash_post", array( $this, "safe_comparator_trash_cb" ), 10, 2 );
}
public function safe_comparator_trash_cb( $should_trash, $post ) {
$product_posts = get_posts( array(
"post_type" => $this->product_post_type,
"meta_key" => $this->product_comparator_type_meta_key,
"meta_value" => $post->ID
) );
if ( ! empty( $product_posts ) ) { // this is the condition. If products exist, don't move the comparator to trash
$should_trash = null;
}
}
FYI, not a big fan of PHP and never used it other than tinkering WordPress themes.
Try with wp_trash_post hook.
add_action('wp_trash_post', 'prevent_from_trash');
public function prevent_from_trash($post_id) {
if (! empty( $product_posts )) { // your condition
wp_redirect(get_home_url() . "/wp-admin/edit.php?post_type=" . $custom_post_type);
die();
}
}
This solution only prevents trashing the post but does not gives any warning, nor notice that it does not want to trash the post.
I have previously used a solution described here: remove_action From PHP Class for removing an action in the WooCommerce membership plugin.
However, the solution no longer works, as WooComemerce have changed the code behind the membership plugin.
So this is the new code.
Main woocommerce-memberships.php
public function includes() {
// load post types
require_once( $this->get_plugin_path() . '/includes/class-wc-memberships-post-types.php' );
// load user messages helper
require_once( $this->get_plugin_path() . '/includes/class-wc-memberships-user-messages.php' );
// load helper functions
require_once( $this->get_plugin_path() . '/includes/functions/wc-memberships-functions.php' );
// init general classes
$this->rules = $this->load_class( '/includes/class-wc-memberships-rules.php', 'WC_Memberships_Rules' );
$this->plans = $this->load_class( '/includes/class-wc-memberships-membership-plans.php', 'WC_Memberships_Membership_Plans' );
$this->emails = $this->load_class( '/includes/class-wc-memberships-emails.php', 'WC_Memberships_Emails' );
$this->user_memberships = $this->load_class( '/includes/class-wc-memberships-user-memberships.php', 'WC_Memberships_User_Memberships' );
$this->capabilities = $this->load_class( '/includes/class-wc-memberships-capabilities.php', 'WC_Memberships_Capabilities' );
$this->member_discounts = $this->load_class( '/includes/class-wc-memberships-member-discounts.php', 'WC_Memberships_Member_Discounts' );
$this->restrictions = $this->load_class( '/includes/class-wc-memberships-restrictions.php', 'WC_Memberships_Restrictions' );
Main instance
function wc_memberships() {
return WC_Memberships::instance();
}
From included class-wc-memberships-restrictions.php file
/**
* Returns the general content restrictions handler.
*
* #since 1.9.0
*
* #return null|\WC_Memberships_Posts_Restrictions
*/
public function get_posts_restrictions_instance() {
if ( ! $this->posts_restrictions instanceof WC_Memberships_Posts_Restrictions ) {
$this->posts_restrictions = wc_memberships()->load_class( '/includes/frontend/class-wc-memberships-posts-restrictions.php', 'WC_Memberships_Posts_Restrictions' );
}
return $this->posts_restrictions;
}
Then in class-wc-memberships-posts-restrictions.php
public function __construct() {
// decide whether attempting to access restricted content has to be redirected
add_action( 'wp', array( $this, 'handle_restriction_modes' ) );
// restrict the post by filtering the post object and replacing the content with a message and maybe excerpt
add_action( 'the_post', array( $this, 'restrict_post' ), 0 );
How do i remove the 'the_post' action?
So far i have the following in functions.php theme file:
function weteach_remove_actions(){
if(is_singular( 'post' )) {
if( function_exists( 'wc_memberships' ) ){
remove_action( 'the_post', array( wc_memberships()->restrictions, 'restrict_post' ));
}
}
return;
}
add_action( 'the_post', 'weteach_remove_actions', 1 );
Which gives me a "blank-page"-error.
Could you tell us what the error message was? My guess is that restrictions and post_restrictions aren't the same property and so you aren't finding the restrict_post method in the right class.
Edited now that I have looked at Memberships, this seems to work for me:
function so_41431558_remove_membership_post_restrictions(){
if( function_exists( 'wc_memberships' ) && version_compare( WC_Memberships::VERSION, '1.9.0', '>=' ) && is_singular( 'post' ) ){
remove_action( 'the_post', array( wc_memberships()->get_restrictions_instance()->get_posts_restrictions_instance(), 'restrict_post' ), 0 );
}
}
add_action( 'wp_head', 'so_41431558_remove_membership_post_restrictions', 1 );
Your add_action attempt is happening on priority 1, which is after the function has already run the Memberships method on priority 0, so even if the rest of your code was correct it would be too late.
So 1. I think we need to go to an earlier hook.
And 2. I think we need to use the new method for accessing the post restrictions class instance.
edited to add
and 3. I've switched to a direct version compare condition
and 4. I misread where the get_posts_restrictions_instance() method was... it is accessed via wc_memberships()->get_restrictions_instance()->get_posts_restrictions_instance()
I have a review plugin that overrides the comment form in a specific posttype.
Now I'm trying to seperate the reviews and comments.
My first step is to remove the filter that modifies the current comment template and use that filter inside a second comment form.
The plugin uses this code (simplified)
final class DM_Reviews {
public function hooks() {
do_action_ref_array( 'dm_reviews_before_setup_actions', array( &$this ) );
add_filter( 'comment_form_defaults', array( $this, 'reviews_form' ) );
do_action_ref_array( 'dm_reviews_after_setup_actions', array( &$this ) );
}
public function review_form( $args ) {
$form = 'plugin code to modify form';
return wp_parse_args( $form, $args );
}
}
In my child theme's function.php file, I tried to use this but it didn't worked.
global $DM_Reviews;
remove_filter( 'comment_form_defaults', array($DM_Reviews, 'reviews_form'),1 );
WP Codex
If someone can put me in the right direction on how to solve it, it would help me a lot.
I think you can achieve this goal, using one of the following solutions depending on the way this plugin instantiates the class:
if( class_exists('DM_Reviews' ) ){
//This should work in whatever case, not tested
remove_filter('comment_form_defaults', array( 'DM_Reviews', 'reviews_form'));
//or Instantiating a new instance, not tested
remove_filter('comment_form_defaults', array( new DM_Reviews(), 'reviews_form'));
//or Targeting the specific instance, not tested
remove_filter('comment_form_defaults', array( DM_Reviews::get_instance(), 'reviews_form'));
}
Hope it helps, let me know if you get stuck.
for me remove_filter didn't work from function.php i wanted to remove a specific behavior of a plugin so what i did :
add_action( 'init', 'remove_filters' );
function remove_filters(){
global $wp_filter;
unset( $wp_filter["_filter_name"]);
}
Try this :
$instance = DM_Reviews::this();
remove_filter('comment_form_defaults', array( $instance, 'reviews_form'));
I previously made a post here: How do I sort by a custom field without manually creating a new page?
However, I believe I asked the wrong question (and I may still be asking the wrong question). Actually think I may need a complex query that will display posts ordered by a meta value. The site is using a theme called "AgentPress". I believe passing params via the URL bar may be too simplistic for what I need.
Honestly I like the way the current category pages display (formatting, etc.), I simply need to "short-circuit" the process so that any category/archive page is sorted by the meta_key for the "property price" as opposed to the date of entry. If there is a simple, more "WordPress-y" mechanism for doing this, I'm all ears. Please be explicit about where to place the code, etc.
FYI, at this point it's clear that passing "order=ASC" and "order=DESC" in the URL works. However, it seems that nothing I do with "meta_key" or anything related has any effect.
Thanks in advance.
You can add a filter on pre_get_posts hook.
Put this code in functions.php (in your theme dir) :
add_filter('pre_get_posts', 'pre_get_posts_hook' );
function pre_get_posts_hook($wp_query) {
if (is_category() || is_archive())
{
$wp_query->set( 'orderby', 'meta_value_num' );
$wp_query->set( 'meta_key', 'price' );
$wp_query->set( 'order', 'ASC' );
return $wp_query;
}
}
You can use meta_value instead of meta_value_num (available with v2.8), but I assume that price is a numeric value.
If you find you lose your navigation menu, I updated #soju's answer as follows:
add_filter('pre_get_posts', 'pre_get_posts_hook' );
function pre_get_posts_hook($wp_query) {
if ( is_archive() && $wp_query->is_main_query() ) { //edited this line
$wp_query->set( 'orderby', 'meta_value_num' );
$wp_query->set( 'meta_key', 'price' );
$wp_query->set( 'order', 'ASC' );
return $wp_query;
}
}
Then the filter won't affect your nav menu
I believe you will find this functionality under a class called PostsOrderedByMetaQuery that extends WP_Query and accepts new arguments 'orderby_meta_key' and 'orderby_order'
class PostsOrderedByMetaQuery extends WP_Query {
var $posts_ordered_by_meta = true;
var $orderby_order = 'ASC';
var $orderby_meta_key;
function __construct($args=array()) {
add_filter('posts_join',array(&$this,'posts_join'),10,2);
add_filter('posts_orderby',array(&$this,'posts_orderby'),10,2);
$this->posts_ordered_by_meta = true;
$this->orderby_meta_key = $args['orderby_meta_key'];
unset($args['orderby_meta_key']);
if (!empty($args['orderby_order'])) {
$this->orderby_order = $args['orderby_order'];
unset($args['orderby_order']);
}
parent::query($args);
}
function posts_join($join,$query) {
if (isset($query->posts_ordered_by_meta)) {
global $wpdb;
$join .=<<<SQL
INNER JOIN {$wpdb->postmeta} postmeta_price ON postmeta_price.post_id={$wpdb->posts}.ID
AND postmeta_price.meta_key='{$this->orderby_meta_key}'
SQL;
}
return $join;
}
function posts_orderby($orderby,$query) {
if (isset($query->posts_ordered_by_meta)) {
global $wpdb;
$orderby = "postmeta_price.meta_value {$this->orderby_order}";
}
return $orderby;
}
}
You would call it like this:
$thirtydays = date('Y/m/d', strtotime('+30 days'));
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$query = new PostsOrderedByMetaQuery(array
(
'post_type' => array('post', 'real-estate'),
'meta_key' => 'Time Available',
'meta_compare' => '<=',
'meta_value' => $thirtydays,
'paged' => $paged,
'orderby_meta_key' => 'Price',
'orderby_order' => 'DESC',
));
foreach($query->posts as $post)
{
echo " {$post->post_title}\n";
}
You can copy the PostsOrderedByMetaQuery class to your theme's functions.php file, or you can use it within a .php file of a plugin you may be writing.
I'm trying to mod a wordpress plugin to take custom categories. So when the random_post_link is called, I can add the custom category by using random_post_link('Random Link',3). 3 being the category name.
How does the plugin below create a new object of class Random_Post_Link? I thought you created new objects by doing something like:
$a = new random_post_link;
But I don't see that in the plugin. I think it creates the new object in the init function by using a hook:
add_action('init', array(CLASS, 'jump'));
If that's the case, how can I add parameter to jump function?
I think I know how add_action works, the second parameter should be the function name, how does
" array(CLASS, 'jump')" work?
Here's the full code for the plugin:
function random_post_link($text = 'Random Post',$the_cat = 36) {
printf('%s', get_random_post_url(), $text);
$the_category = $the_cat;
}
function get_random_post_url() {
return trailingslashit(get_bloginfo('url')) . '?' . Random_Post_Link::query_var;
}
class Random_Post_Link {
const query_var = 'random';
const name = 'wp_random_posts';
public $the_category;
function init() {
add_action('init', array(__CLASS__, 'jump'));
// Fire just after post selection
add_action('wp', array(__CLASS__, 'manage_cookie'));
}
// Jump to a random post
function jump() {
if ( ! isset($_GET[self::query_var]) )
return;
$args = apply_filters('random_post_args', array(
'post__not_in' => self::read_cookie(),
));
$args = array_merge($args, array(
'orderby' => 'rand',
'cat' => $the_category,
'showposts' => 1,
));
$posts = get_posts($args);
if ( empty($posts) ) {
self::update_cookie(array());
unset($args['post__not_in']);
$posts = get_posts($args);
}
if ( empty($posts) )
wp_redirect(get_bloginfo('url'));
$id = $posts[0]->ID;
wp_redirect(get_permalink($id));
die;
}
// Collect post ids that the user has already seen
function manage_cookie() {
if ( ! is_single() )
return;
$ids = self::read_cookie();
$id = $GLOBALS['posts'][0]->ID;
if ( count($ids) > 200 )
$ids = array($id);
elseif ( ! in_array($id, $ids) )
$ids[] = $id;
self::update_cookie($ids);
}
private function read_cookie() {
return explode(' ', #$_COOKIE[self::name]);
}
private function update_cookie($ids) {
setcookie(self::name, trim(implode(' ', $ids)), 0, '/');
}
}
Random_Post_Link::init();
Some WordPress authors use the Class structure in PHP to basically reduce global vars. The class is meant as a 'singleton' of sorts, and so it isn't usually instantiated (that code calls Random_Post_Link::init(); at the bottom instead). The class functions are treated as Class members, not instance members, sort of like Math.max() in other languages, for example.
The __CLASS__ php keyword is simply a token for the current class, so when passed, the callable becomes Random_Post_Link::method() or array( 'Random_Post_Link', 'method' )
If you need to unhook, try remove_action( 'init', array( 'Random_Post_Link, 'jump' ) );
(Also note, that methods used that way should be declared static function jump() {...})
P.S. To further clarify:
http://php.net/manual/en/language.types.callable.php
The array('class', 'function') syntax is a PHP thing, while WordPress actions expect a callable which could be any of the PHP callable things.