So, i've built myself an enqueue'd stylesheet concatenator, while it works, what I've found is that the "dependencies" seem to be out of order... in this instance, I deregister and dequeue my "custom" stylesheet, register and enqueue my concatenated stylesheet, and then "re" register and "re" enqueue my custom style sheet using the concatenated handle as the dependency for it... and it always loads before the concatenated stylesheet.
Any ideas why this may be happenning? In my child-theme, I am enqueing "custom" at the default priority, in the parent theme, is where I am performing the concatenation, and my action has the highest possibly priority.
The Code:
protected function concatenate_css( $_cache_time ) {
add_action( 'wp_enqueue_scripts', function( ) use ( $_cache_time ) {
// need our global
global $wp_styles;
// our css string holder
$_css_string = '';
// path to the theme
$_theme_path = get_stylesheet_directory( );
// uri to the theme
$_theme_uri = get_stylesheet_directory_uri( );
// new file path
$_new_css = $_theme_path . '/style.concat.css';
// force the order based on the dependencies
$wp_styles -> all_deps( $wp_styles -> queue );
// setup our exclusions
$_exclude = array( 'custom', 'concatcss', );
// loop through everything in our global
foreach( $wp_styles -> queue as $_hndl ) {
// get the source from the hanlde
$_path = $wp_styles -> registered[$_hndl]->src;
// if we have a "custom" handle, we do not want to process it, so ... skip it
// we also do want to process any source that is not set
if( ! in_array( $_hndl, $_exclude ) && $_path ) {
// we also only want to do this for local stylehseets
if ( strpos( $_path, site_url( ) ) !== false ) {
$_path = ABSPATH . str_replace( site_url( ), '', $_path );
// now that we have everything we need, let's hold the contents of the file in a string variable, while concatenating
$_css_string .= file_get_contents( $_path ) . PHP_EOL;
// now remove the css from queue
wp_dequeue_style( $_hndl );
// and deregister it
wp_deregister_style( $_hndl );
}
}
}
// dequeue and deregsiter any "custom" style
wp_dequeue_style( 'custom' );
wp_deregister_style( 'custom' );
// now write out the new stylesheet to the theme, and enqueue it
// check the timestamp on it, versus the number of seconds we are specifying to see if we need to write a new file
if( file_exists( $_new_css ) ) {
$_ftime = filemtime( $_new_css ) + ( $_cache_time );
$_ctime = time( );
if( ( $_ftime <= $_ctime ) ) {
file_put_contents( $_new_css, $_css_string );
}
} else {
file_put_contents( $_new_css, $_css_string );
}
wp_register_style( 'concatcss', $_theme_uri . '/style.concat.css', array( ), null );
wp_enqueue_style( 'concatcss' );
// requeue and reregister our custom stylesheet, using this concatenated stylesheet as it's dependency
wp_register_style( 'custom', $_theme_uri . '/css/custom.css?_=' . time( ), array( 'concatcss' ), null );
wp_enqueue_style( 'custom' );
}, PHP_INT_MAX );
}
Screenshot of the page source
Just register your concatenated script, but don't enqueue it.
wp_register_style( 'concatcss', $_theme_uri . '/style.concat.css', array( ), null );
// requeue and reregister our custom stylesheet, using this concatenated stylesheet as it's dependency
wp_enqueue_style( 'custom', $_theme_uri . '/css/custom.css?_=' . time( ), array( 'concatcss' ), null );
Related
I can't figure out what I'm doing wrong! I want the function to return a freshly-created variable with a true/false value that I can use to see if we've got the file or not.
// Check to make sure external files are available
function checklink ( $link, $checkname ) {
$try_url = #fopen( $link,'r' );
if( $try_url !== false ) { return $$checkname; }
}
var_dump( checklink( 'https://code.jquery.com/jquery-3.3.1.min.js', 'jqueryOK' ) ); // NULL
I've tried setting $checkname to true or false, adding an extra line to give it a value before return ... PHP 'knows' there is a variable $jqueryOK but says it's undefined.
What am I missing?
UPDATE
Decided to share the outcome, as this is often an overlooked thing in Wordpress - and am changing the title to reflect the task.
// Check to make sure external files are available
function checklink ($link) {
return( bool )#fopen( $link, 'r' );
}
function thatwomanuk_external_scripts()
{
if ($GLOBALS['pagenow'] != 'wp-login.php' && !is_admin()) {
// jquery
$link = 'https://code.jquery.com/jquery-3.3.1.min.js';
if( checklink( $link ) ) { // true - otherwise, Wordpress will load its own
wp_deregister_script('jquery'); // remove jQuery v1
wp_register_script('jquery', $link, array(), '3.3.1', true); // add jQuery v3
wp_enqueue_script('jquery');
wp_script_add_data( 'jquery', array( 'integrity', 'crossorigin' ), array( 'sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=', 'anonymous' ) );
}
// google fonts
$link = 'https://fonts.googleapis.com/css?family=Raleway:300,400,400i,500|Ubuntu:300,400,400i,500&subset=latin-ext';
$fallback = get_template_directory_uri() . '/fonts/thatwoman-fonts-min.css';
if( checklink( $link ) ) {
wp_enqueue_style( 'custom-google-fonts', $link, false );
} else {
wp_enqueue_style( 'custom-google-fonts', $fallback, false );
}
// touch events library
$link = 'https://cdnjs.cloudflare.com/ajax/libs/jquery-touch-events/1.0.5/jquery.mobile-events.js';
$fallback = get_template_directory_uri() . '/js/lib/jquery.mobile-events.min.js';
if( checklink( $link ) ) {
wp_register_script('thatwoman-touch-events', $link, array( 'jquery' ), '1.0.5', true);
} else {
wp_register_script('thatwoman-touch-events', $fallback, array( 'jquery' ), '1.0.5', true);
}
wp_enqueue_script('thatwoman-touch-events');
}
}
add_action( 'wp_enqueue_scripts', 'thatwomanuk_external_scripts' );
Thanks to #u_mulder for making me see sense.
You should simplify your function to:
// Check to make sure external files are available
function checklink ($link) {
return (bool)#fopen( $link,'r');
}
After that in your code:
$link1Available = checklink($link1);
$link2Available = checklink($link2);
// etc
Or as an array:
$links = ['link1', 'link2', 'link3'];
$linksAvailable = [];
foreach ($links as $link) {
$linksAvailable[$link] = checklink($link);
}
If you just want to have a local fallback for a CDN loaded js file, you can use wp_scripts()->add_inline_script() which was added in 4.5, to add a js check if the library was loaded, see my detailed answer on wordpress.stackexchange here.
The short version:
You can use wp_scripts()->add_inline_script(), which will append a js script to an enqueued script, no questions asked, no code problems checked (there is a wrapper function wp_add_inline_script that does checks but does not permit </script> tags, even encoded).
This is a working example
function _enqueue_my_scripts() {
// the normal enqueue
wp_enqueue_script( 'jquery-cdn', 'https://code.jquery.com/jquery-3.3.1.min.js' );
// our custom code which will check for the existance of jQuery (in this case)
wp_scripts()->add_inline_script( 'jquery-cdn',
"window.jQuery || document.write('<script src=\"".get_template_directory_uri() ."/js/jQuery.js\">\\x3C/script>')", 'after');
}
add_action('wp_enqueue_scripts', '_enqueue_my_scripts', 100);
which will give you
<script type='text/javascript' src='https://code.jquery.com/jquery-3.3.1.min.js'></script>
<script type='text/javascript'>
window.Swiper || document.write('<script src="http://localhost/wordpress/wp-content/themes/wp-theme/js/jQuery.js">\x3C/script>')
</script>
in your HTML.
Replace 'window.jQuery' and '/js/jQuery.js' according to your needs but don't touch the rest of the line as it is meant to pass through the correct line to the HTML.
You have double $$ sign in return statement:
if( $try_url !== false ) { return $$checkname; }
I am using wordpress 4.9.5 and I am en-queuing in my functions.php my styles as the following:
function enqueue_parent_theme_style()
{
if ( is_page( 'product builder' ) || is_page('shopping products')) {
$parentStyle = 'parent-style';
//css
wp_enqueue_style($parentStyle, get_template_directory_uri() . '/style.css');
wp_enqueue_style('bootstrap-4.0.0', get_stylesheet_directory_uri() . '/css/bootstrap.min.css', array($parentStyle));
wp_enqueue_style('dataTables', '//cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css', array($parentStyle) );
wp_enqueue_style('dataTables-1.10.16', get_stylesheet_directory_uri() . '/css/dataTables.bootstrap4.min.css', array($parentStyle));
//js
wp_enqueue_script('font-awesome', 'https://use.fontawesome.com/releases/v5.0.10/js/all.js', NULL, '1.0', true);
wp_enqueue_script('main-shopping-product-js', get_theme_file_uri('/js/scripts-bundled.js'), NULL, '1.0', true);
wp_localize_script('main-shopping-product-js', 'shoppingproductData', array(
'root_url' => get_site_url(),
'nonce' => wp_create_nonce('wp_rest')
));
}
}
add_action('wp_enqueue_scripts', 'enqueue_parent_theme_style');
As you can see I only want to load my child css/javascript on two child pages, product builder and shopping products. My css/javascript works on these two pages:
On my two child pages the theme's css and javascript is working perfectly fine. However, when I go back to my main theme pages, the css and javascript is broken.
The pages look like the following:
Any suggestions what I am doing wrong?
Update
My browser console shows the following:
The problem was with the style.css, which was in the if condition:
if ( is_page( 'product builder' ) || is_page('shopping products')) {
$parentStyle = 'parent-style';
//css
wp_enqueue_style($parentStyle, get_template_directory_uri() . '/style.css');
The style.css file contains all css rules( menu part, too ), which construct the pages layouts. Moving out from condition that part will load style.css file in all pages:
function enqueue_parent_theme_style()
{
$parentStyle = 'parent-style';
//css
wp_enqueue_style($parentStyle, get_template_directory_uri() . '/style.css');
if (is_page('product builder') || is_page('shopping products')) {
wp_enqueue_style('bootstrap-4.0.0', get_stylesheet_directory_uri() . '/css/bootstrap.min.css', array($parentStyle));
wp_enqueue_style('dataTables', '//cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css', array($parentStyle));
wp_enqueue_style('dataTables-1.10.16', get_stylesheet_directory_uri() . '/css/dataTables.bootstrap4.min.css', array($parentStyle));
//js
wp_enqueue_script('font-awesome', 'https://use.fontawesome.com/releases/v5.0.10/js/all.js', NULL, '1.0', true);
wp_enqueue_script('main-shopping-product-js', get_theme_file_uri('/js/scripts-bundled.js'), NULL, '1.0', true);
wp_localize_script('main-shopping-product-js', 'shoppingproductData', array(
'root_url' => get_site_url(),
'nonce' => wp_create_nonce('wp_rest')
));
}
}
add_action('wp_enqueue_scripts', 'enqueue_parent_theme_style');
I have a script problem with a plugin and I have to deactivate a JS script from a certain page, the script is in functions.php
wp_enqueue_script( "helper-js", JS_PATH . 'helper.js', array( 'jquery' ), get_bloginfo('version') , true );
And I am trying to exclude it from single-room.php
You'd have to wrap the enqueue in a condition that checks the filename, something like
if ( basename( get_page_template() ) !== 'single-room.php') {
wp_enqueue_script( "helper-js", JS_PATH . 'helper.js', array( 'jquery' ), get_bloginfo('version') , true );
}
unable to add contents in pages like about us ,courses,contact us..while adding the content error is displaying
Warning: Cannot modify header information - headers already sent by (output started at /home/phptraining/public_html/wp-content/themes/health-center-lite/functions.php:95) in /home/phptraining/public_html/wp-admin/post.php on line 235
and
Warning: Cannot modify header information - headers already sent by (output started at /home/phptraining/public_html/wp-content/themes/health-center-lite/functions.php:95) in /home/phptraining/public_html/wp-includes/pluggable.php on line 1196
functions.php
<?php /**Includes reqired resources here**/
define('WEBRITI_TEMPLATE_DIR_URI',get_template_directory_uri());
define('WEBRITI_TEMPLATE_DIR',get_template_directory());
define('WEBRITI_THEME_FUNCTIONS_PATH',WEBRITI_TEMPLATE_DIR.'/functions');
define('WEBRITI_THEME_OPTIONS_PATH',WEBRITI_TEMPLATE_DIR_URI.'/functions/theme_options');
require( WEBRITI_THEME_FUNCTIONS_PATH . '/menu/default_menu_walker.php' ); // for Default Menus
require( WEBRITI_THEME_FUNCTIONS_PATH . '/menu/webriti_nav_walker.php' ); // for Custom Menus
require( WEBRITI_THEME_FUNCTIONS_PATH . '/commentbox/comment-function.php' ); //for comments
require( WEBRITI_THEME_FUNCTIONS_PATH . '/widget/custom-sidebar.php' ); //for widget register
//content width
if ( ! isset( $content_width ) ) $content_width = 900;
//wp title tag starts here
function hc_head( $title, $sep )
{ global $paged, $page;
if ( is_feed() )
return $title;
// Add the site name.
$title .= get_bloginfo( 'name' );
// Add the site description for the home/front page.
$site_description = get_bloginfo( 'description' );
if ( $site_description && ( is_home() || is_front_page() ) )
$title = "$title $sep $site_description";
// Add a page number if necessary.
if ( $paged >= 2 || $page >= 2 )
$title = "$title $sep " . sprintf( _e( 'Page', 'helth' ), max( $paged, $page ) );
return $title;
}
add_filter( 'wp_title', 'hc_head', 10,2 );
add_action( 'after_setup_theme', 'hc_setup' );
function hc_setup()
{ // Load text domain for translation-ready
load_theme_textdomain( 'health', WEBRITI_THEME_FUNCTIONS_PATH . '/lang' );
add_theme_support( 'post-thumbnails' ); //supports featured image
// This theme uses wp_nav_menu() in one location.
register_nav_menu( 'primary', __( 'Primary Menu', 'health' ) );
// theme support
$args = array('default-color' => '000000',);
add_theme_support( 'custom-background', $args );
add_theme_support( 'automatic-feed-links');
require_once('theme_setup_data.php');
require( WEBRITI_THEME_FUNCTIONS_PATH . '/theme_options/option_pannel.php' ); // for Custom Menus
// setup admin pannel defual data for index page
$health_center_lite_theme=theme_data_setup();
function hc_custom_excerpt_length( $length ) { return 50; }
add_filter( 'excerpt_length', 'hc_custom_excerpt_length', 999 );
function hc_new_excerpt_more( $more ) { return '';}
add_filter('excerpt_more', 'hc_new_excerpt_more');
$current_theme_options = get_option('hc_lite_options'); // get existing option data
if($current_theme_options)
{ $hc_lite_theme_options = array_merge($health_center_lite_theme, $current_theme_options);
update_option('hc_lite_options',$hc_lite_theme_options);
}
else
{ add_option('hc_lite_options',$health_center_lite_theme); }
}
/******** health center js and cs *********/
function hc_scripts()
{ // Theme Css
wp_enqueue_style('health-responsive', WEBRITI_TEMPLATE_DIR_URI . '/css/media-responsive.css');
wp_enqueue_style('health-font', WEBRITI_TEMPLATE_DIR_URI . '/css/font/font.css');
wp_enqueue_style('health-bootstrap', WEBRITI_TEMPLATE_DIR_URI . '/css/bootstrap.css');
wp_enqueue_style('health-font-awesome', WEBRITI_TEMPLATE_DIR_URI . '/css/font-awesome-4.0.3/css/font-awesome.min.css');
wp_enqueue_script('health-menu', WEBRITI_TEMPLATE_DIR_URI .'/js/menu/menu.js',array('jquery'));
wp_enqueue_script('health-bootstrap_min', WEBRITI_TEMPLATE_DIR_URI .'/js/bootstrap.min.js');
}
add_action('wp_enqueue_scripts', 'hc_scripts');
if ( is_singular() ){ wp_enqueue_script( "comment-reply" ); }
// Read more tag to formatting in blog page
function hc_content_more($more)
{ global $post;
return ' Read More<i class='fa fa-long-arrow-right'></i>";
}
add_filter( 'the_content_more_link', 'hc_content_more' );
?>
<?php
/**
* Register Widget Area.
*
*/
function wpgyan_widgets_init() {
register_sidebar( array(
'name' => 'Header Sidebar',
'id' => 'header_sidebar',
'before_widget' => '<div>',
'after_widget' => '</div>',
'before_title' => '<h2 class="rounded">',
'after_title' => '</h2>',
) );
}
add_action( 'widgets_init', 'wpgyan_widgets_init' );
?>
This has nothing to do with functions.php sending headers. Rather, it has to do with output having started (in the functions file) before headers are sent (by other WordPress scripts). What you'll see, if you look on line 95, is the following:
?>
<?php
That blank line between the closing and opening PHP tags is the cause of the error. Instead, you should get rid of both of those tags, so that your code becomes:
add_filter( 'the_content_more_link', 'hc_content_more' );
/**
* Register Widget Area.
*
*/
function wpgyan_widgets_init() {
While you're at it, also delete the last line of your functions.php file (the closing ?> PHP tag). It's unnecessary here.
This error is not specific to wordpress. This is a standard error of PHP. This problem is occurring because you are trying to modify headers after an output is generated in that page like php echo or some html is rendered.
I hope this helps you.
I have a WordPress Admin page where you can add a "listing" within this Admin Page I have added many fields which transfer variables over to the listing page which is created/updated. Within this admin page I am trying to take the string after the last "&" in the url which is manually enter in the url before loading the page
see code below:
$url = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$id = substr( $url, strrpos( $url, '&' )+1 );
NOW the code below here is called when the ABOVE admin page is submitted to update the "listing" what I need to do is somehow get the variable $id to pass through to this function and be used again within the submit code. Both of these functions are within functions.php so somehow it should be easy to do this!
This may not be "Wordpress Specific" but is a Wordpress Specific situation where I had this code working on a non-wordpress site. Please help!
$dirname = "../wp-content/themes/Explorable/".$id."/";
$images = glob($dirname."*.jpg");
// Open a known directory, and proceed to read its contents
foreach($images as $image) {
$imageNameLong = substr($image, -14);
$imageName = substr($imageNameLong,0 , -4);
if ( isset( $_POST[$imageName.'links'] ) )
update_post_meta( $post_id, '_'.$imageName.'links', sanitize_text_field( $_POST[$imageName.'links'] ) );
else
delete_post_meta( $post_id, '_'.$imageName.'links' );
if ( isset( $_POST[$imageName.'heading'] ) )
update_post_meta( $post_id, '_'.$imageName.'heading', sanitize_text_field( $_POST[$imageName.'heading'] ) );
else
delete_post_meta( $post_id, '_'.$imageName.'heading' );
};