TinyMCE hook breaks Wordpress media preview in editor - wordpress

I am extending WP editor with custom button.
Problem happens when I use this hook:
add_filter( 'mce_css', 'mytheme_icon_picker' );
This is used to enqueue custom scripts and styles.
Even the empty function leads to media player not being displayed/styled in editor.
This leads me to believe that hooking to mce_css, breaks WP enqueueing media-player assets.
Does anyone know what hook to use, to correctly include custom files without breaking default behavior?

The code you're using is a filter. It must return a value.
http://codex.wordpress.org/Plugin_API/Filter_Reference/mce_css
Your function should append the CSS URL to the existing list of CSS files.
function wpse_icon_picker( $mce_css ) {
if ( ! empty( $mce_css ) ) {
$mce_css .= ',';
}
$mce_css .= 'enter URL to CSS here';
return $mce_css;
}
add_filter( 'mce_css', 'wpse_icon_picker' );

Related

Output certain product page on homepage / WooCommerce shortcode not working properly

I need to output a certain product page on the homepage. add_rewrite_rule doesn't work for homepage for any reason (
there are actually no rewrite rules for the homepage in the database, WordPress seems to use some other functions to
query the homepage):
//works fine
add_rewrite_rule( 'certainproductpage/?$',
'index.php?post_type=product&name=certainproduct',
'top'
);
//does not work
add_rewrite_rule( '', //tried everything like "/", "/?$" etc
'index.php?post_type=product&name=certainproduct',
'top'
);
After spending way too much time looking through wp / wc core code and stackoverflow I came across an alternative. I can
simply add a shortcode in the content of the page I need to be the homepage and a product page at the same
time: [product_page id=815]. Indeed it works great, but only if the shortcode is added in the admin editor or is
stored in the database (post_content). If I try to call the shortcode manually on the page template (
page-certainproductpage.php) then it outputs the product page without some necessary stuff (PayPal, PhotoSwipe and
Gallery js). Weirdly enough, if I keep the shortcode in the content (via Gutenberg / Code Editor) but don't
call the_content and only echo the shortcode then everything works fine:
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
get_header( 'shop' );
//works fine only if the same shortcode is within the certainproductpage's content
echo do_shortcode("[product_page id='815']");
//the_content();
get_footer( 'shop' );
Also when I try to add the shortcode via the_content filter hook before the do_shortcode function is applied in core's
default-filters.php ($priority < 11), then I get only the error:
NOTICE: PHP message: PHP Fatal error: Maximum execution time of 30 seconds exceeded in /var/www/html/wp-includes/functions.php on line 5106
Unfortunately there is no stack trace logged. And the function around line 5107 is wp_ob_end_flush_all which is called on shutdown from default-filters.php
echo do_shortcode(apply_filters('the_content', "[product_page id=815]")); did not help either (same incomplete output as
with echo do_shortcode("[product_page id=815]");)
Also totally weird:
When I compare the string of the content from the editor and the string of the shortcode added programmatically it is
equal!:
add_filter( "the_content", function ( $content ){
$wtf = "<!-- wp:paragraph -->
<p>[product_page id=815]</p>
<!-- /wp:paragraph -->";
$result = $wtf === $content;
?><pre><?php var_dump($result)?></pre><?php
return $content;
}, 1 );
But if I replace return $content with return $wtf - I get the maximimum exucution time exceeded error.
So how can I properly output a product page on the homepage ("/") or how can I get the same result with the shortcode
when applied within the the_content filter as when just adding the shortcode in the (Gutenberg) editor?
Update
Tested it with a simple custom shortcode outputting only a heading tag and it works fine with the_content filter. Also tried it on an absolutely clean site with only WooCommerce and PayPal installed - with the same results. Seems to be a bug on the WooCommerce side. Gonna run it through xDebug some day this week.
Ok, found a bit of a hacky solution. I just check on every page load whether the homepage is currently queried or not. Then I get the page content and check if it already contains the shortcode. If not then the page content gets updated in the database with the shortcode appended.
//it has to be a hook which loads everything needed for the wp_update_post function
//but at the same time has not global $post set yet
//if global $post is already set, the "certainproductpage" will load content not modified by the following code
add_action( "wp_loaded", function () {
//check if homepage
//there seems to be no other simple method to check which page is currently queried at this point
if ( $_SERVER["REQUEST_URI"] === "/" ) {
$page = get_post(get_option('page_on_front'));
$product = get_page_by_path( "certainproduct", OBJECT, "product" );
if ( $page && $product ) {
$page_content = $page->post_content;
$product_id = $product->ID;
$shortcode = "[product_page id=$product_id]";
//add shortcode to the database's post_content if not already done
$contains_shortcode = strpos( $page_content, $shortcode ) > - 1;
if ( ! $contains_shortcode ) {
$shortcode_block = <<<EOT
<!-- wp:shortcode -->
{$shortcode}
<!-- /wp:shortcode -->
EOT;
$new_content = $page_content . $shortcode_block;
wp_update_post( array(
'ID' => $page->ID,
'post_content' => $new_content,
'post_status' => "publish"
) );
}
}
}
} );
I'd recommend one step at a time. First of all, does this work?
add_filter( "the_content", function ( $content ) {
$content .= do_shortcode( '[product_page id=815]' );
return $content;
}, 1 );
This should append a product page to every WordPress page/post.
If it works, then you need to limit it to the homepage only, by using is_front_page() conditional in case it's a static page:
add_filter( "the_content", function ( $content ) {
if ( is_front_page() ) {
$content .= do_shortcode( '[product_page id=815]' );
}
return $content;
}, 1 );
If this works too, then we'll see how to return a Gutenberg paragraph block, but not sure why you'd need that, so maybe give us more context

Custom post template in a plugin erase theme's one

i work with sportpress on Wordpress. I have a custom plugin that add a lot of function to it.
I created a template for the custom post-type of sportpress. They are in my plugin but i don't find how to make them prioritary on theme. The theme isn't a custom'one, so i don't want to delete or modify anything in it.
I have tried several things but theme's file is everytime superior.
Things tried :
naming the file 'single-....php',
filter : add_filter( 'template_include', 'toornament_template' ),
shortcode in theme file (works but not what i want...),
Thanks a lot...
EDIT :
here is what i tried exaclty, it works with another type of post that has no theme template, but not for the one that has single-post template in the theme...
add_filter( 'template_include', 'player_template', 1 );
function player_template( $template ) {
if ( is_singular( 'sp_player' ) && file_exists( plugin_dir_path(__FILE__) . 'templates/player-tpl.php' ) ){
$template = plugin_dir_path(__FILE__) . 'templates/player-tpl.php';
}
return $template;
};

Use my custom CSS just for my WordPress plugin settings page, how?

I'm developing my first WordPress plugin. I need to use a custom CSS for the settings pages that I created for the plugin but when I enqueue my stylesheet file, it affects the whole WordPress backend and not just my plugin's settings page.
Is possible to solve this problem? How?
When you want to add styles or scripts in WordPress you enqueue them using hooks. For the admin side the hook you are looking for is called admin_enqueue_scripts.
You can add something like
/**
* Register and enqueue a custom stylesheet in the WordPress admin.
*/
function wpdocs_enqueue_custom_admin_style() {
wp_register_style( 'custom_wp_admin_css', plugin_dir_url( __FILE__ ) . 'css/woo-solo-api-admin.css', false, '1.0.0' );
wp_enqueue_style( 'custom_wp_admin_css' );
}
add_action( 'admin_enqueue_scripts', 'wpdocs_enqueue_custom_admin_style' );
You just need to be careful to correctly specify the url of the css script you want to enqueue.
Hope this helps.
Oh and https://developer.wordpress.org page is great for finding out about WordPress functionality, core functions, hooks etc.
Also check out the plugin handbook: https://developer.wordpress.org/plugins/
Loads of useful information can be found there :)
EDIT:
admin_enqueue_scripts has a parameter you can use read more
/**
* Register and enqueue a custom stylesheet in the WordPress admin.
*/
function wpdocs_enqueue_custom_admin_style( $hook ) {
if ( $hook === 'edit.php' ) {
wp_register_style( 'custom_wp_admin_css', plugin_dir_url( __FILE__ ) . 'css/woo-solo-api-admin.css', false, '1.0.0' );
wp_enqueue_style( 'custom_wp_admin_css' );
}
}
add_action( 'admin_enqueue_scripts', 'wpdocs_enqueue_custom_admin_style' );
This will load the script only on the edit post screen.
You can see what hook is loaded on your screen by adding
error_log( print_r( $hook, true ) );
In your wpdocs_enqueue_custom_admin_style function before the condition. Enable the debug log in your wp-config.php and you'll get a name of your custom post screen hook.
Alternatively, you could target the $current_screen to match the CPT's screen. This will load the script only on that page.

Use Wordpress Filter to modify value of wp_head output?

I have just started with Worpdress, and see what when creating a custom theme there is an annoying margin at the top of the page, and that is caused by the content output by the wp_head function. Since I need to learn how to use filters, I thought I would use a filter to remove the css for the html and body tags from the wp_head functions.
The question is, how do I do that? Inside the function I use for a filter, how I am able to access the values for the css written out for the html tag in the wp_head function? Have searched by have found no good explanation for this.
You can remove (and add) classes to the <body> tag as long as the theme is using <?php body_class(); ?>
There is a body_class filter hook at the end of get_body_class() in includes/post-template.php
From Codex
apply_filters( 'body_class', array $classes, array $class )
Filters the list of CSS body classes for the current post or page.
Remove a class from the body_class array:
add_filter( 'body_class', function( $classes ) {
if ( isset( $classes['class-to-remove'] ) ) {
unset( $classes['class-to-remove'] );
}
return $classes;
} );
Add specific CSS class by filter:
add_filter( 'body_class', function( $classes ) {
return array_merge( $classes, array( 'class-name' ) );
} );
Styesheets
To remove style sheets, as long as they are registered properly,
function dequeue_some_css() {
wp_dequeue_style('some-css');
wp_deregister_style('some-css');
}
add_action('wp_enqueue_scripts','dequeue_some_css', 100);
Look into wp_dequeue_style and wp_deregister_style
For adding your own style sheets, see wp_enqueue_style and wp_register_style.

Do I have to add_filter() before apply_filters() in Wordpress?

I'm trying to understand Wordpress plugin like:
apply_filters( 'gettext', $translations->translate( $text ), $text, $domain );
I'm looking for all codes in Wordpress, I can't find:
add_filter( 'gettext', ....);
Why there is no add_filter for this plugin? Or I missed something? Same thing like:
do_action('wp_loaded');
I can't find:
add_action('wp_loaded', ....);
apply_filters is like, 'if there are any filters with this name, run the attached callbacks with these parameters'. So if there is no add_filter for that name, it means that there is no filter that's going to be run with the apply_filters call at the moment.
The same goes with do_action and add_action.
I am a beginner in PHP - WordPress stack as well, but this is from my understanding.
The plugins call apply_filters without having any add_filter in their codes is to allow the website users to add custom logic to their plugins. We - the users, can add our own function and use add_filter to register our functions.
For example, this piece of code is from the plugin. Normally, it shows all products but it provides us a way to not show a specific product.
// Plugin's
if (apply_filters( 'plugin_show_products', true, $product->get_id() ) ) {
$this->show_products();
}
So, if we - the users, want to customize a bit. We can add our own function as following (maybe in functions.php)
// Our custom changes
function my_own_changes($boolean, $product_id) {
if ( $product_id === 5 ) return false;
return true;
}
add_filter( 'plugin_show_products', 'my_own_changes', 10, 2 );
This translates to: The plugin will behave normally but for my own site, it will not show the product with ID of 5!
I have come across this type of code in a plugin or theme where the apply_filter is used without necessarily having an existing filter or add_filter
In this case, where the apply_filters is used without a filter you will have to call the function again where you want to run it. For example, in the header of a theme.
The following is an example of apply filters used in a function that is again called in the header.php
if ( ! function_exists( 'header_apply_filter_test' ) ) {
function header_apply_filter_test() {
$filter_this_content = "Example of content to filter";
ob_start();
echo $filter_this_content;
$output = ob_get_clean();
echo apply_filters( 'header_apply_filter_test', $output );//used here
}
}
Now in the header.php file, you would have to call this function since it is not hooked anywhere. So, in this case, to display the output in the header you would call the function like this :
<?php header_apply_filter_test(); ?>
You could as well write this code with a hook and it would do the same thing i.e display the output in the header.
add_filter('wp_head', 'header_apply_filter_test');
if ( ! function_exists( 'header_apply_filter_test' ) ) {
function header_apply_filter_test() {
$filter_this_content = "Example of content to filter";
ob_start();
echo $filter_this_content;
$output = ob_get_clean();
echo $output;
}
}
For this second option, you would still have the capability of using apply_filters anywhere else to call the callback function header_apply_filter_test() since the filter now exists.
So the bottom line in my view is a use case since either approach works!

Resources