I have problem with WP shortcodes.
When I am trying to publish a short code it is displayed as text.
Ii looks like this:
enter image description here
I did try:
Shortcode rendering as text not as shortcode should
and may others.
This is my shortcode.php
<?php
/**
* WordPress API for creating bbcode like tags or what WordPress calls
* "shortcodes." The tag and attribute parsing or regular expression code is
* based on the Textpattern tag parser.
*
* A few examples are below:
*
* [shortcode /]
* [shortcode foo="bar" baz="bing" /]
* [shortcode foo="bar"]content[/shortcode]
*
* Shortcode tags support attributes and enclosed content, but does not entirely
* support inline shortcodes in other shortcodes. You will have to call the
* shortcode parser in your function to account for that.
*
* {#internal
* Please be aware that the above note was made during the beta of WordPress 2.6
* and in the future may not be accurate. Please update the note when it is no
* longer the case.}}
*
* To apply shortcode tags to content:
*
* $out = do_shortcode( $content );
*
* #link https://codex.wordpress.org/Shortcode_API
*
* #package WordPress
* #subpackage Shortcodes
* #since 2.5.0
*/
/**
* Container for storing shortcode tags and their hook to call for the shortcode
*
* #since 2.5.0
*
* #name $shortcode_tags
* #var array
* #global array $shortcode_tags
*/
$shortcode_tags = array();
/**
* Add hook for shortcode tag.
*
* There can only be one hook for each shortcode. Which means that if another
* plugin has a similar shortcode, it will override yours or yours will override
* theirs depending on which order the plugins are included and/or ran.
*
* Simplest example of a shortcode tag using the API:
*
* // [footag foo="bar"]
* function footag_func( $atts ) {
* return "foo = {
* $atts[foo]
* }";
* }
* add_shortcode( 'footag', 'footag_func' );
*
* Example with nice attribute defaults:
*
* // [bartag foo="bar"]
* function bartag_func( $atts ) {
* $args = shortcode_atts( array(
* 'foo' => 'no foo',
* 'baz' => 'default baz',
* ), $atts );
*
* return "foo = {$args['foo']}";
* }
* add_shortcode( 'bartag', 'bartag_func' );
*
* Example with enclosed content:
*
* // [baztag]content[/baztag]
* function baztag_func( $atts, $content = '' ) {
* return "content = $content";
* }
* add_shortcode( 'baztag', 'baztag_func' );
*
* #since 2.5.0
*
* #global array $shortcode_tags
*
* #param string $tag Shortcode tag to be searched in post content.
* #param callable $func Hook to run when shortcode is found.
*/
function add_shortcode($tag, $func) {
global $shortcode_tags;
if ( '' == trim( $tag ) ) {
$message = __( 'Invalid shortcode name: Empty name given.' );
_doing_it_wrong( __FUNCTION__, $message, '4.4.0' );
return;
}
if ( 0 !== preg_match( '#[<>&/\[\]\x00-\x20=]#', $tag ) ) {
/* translators: 1: shortcode name, 2: space separated list of reserved characters */
$message = sprintf( __( 'Invalid shortcode name: %1$s. Do not use spaces or reserved characters: %2$s' ), $tag, '& / < > [ ] =' );
_doing_it_wrong( __FUNCTION__, $message, '4.4.0' );
return;
}
$shortcode_tags[ $tag ] = $func;
}
/**
* Removes hook for shortcode.
*
* #since 2.5.0
*
* #global array $shortcode_tags
*
* #param string $tag Shortcode tag to remove hook for.
*/
function remove_shortcode($tag) {
global $shortcode_tags;
unset($shortcode_tags[$tag]);
}
/**
* Clear all shortcodes.
*
* This function is simple, it clears all of the shortcode tags by replacing the
* shortcodes global by a empty array. This is actually a very efficient method
* for removing all shortcodes.
*
* #since 2.5.0
*
* #global array $shortcode_tags
*/
/*function remove_all_shortcodes() {
global $shortcode_tags;
$shortcode_tags = array();
}
*/
/**
* Whether a registered shortcode exists named $tag
*
* #since 3.6.0
*
* #global array $shortcode_tags List of shortcode tags and their callback hooks.
*
* #param string $tag Shortcode tag to check.
* #return bool Whether the given shortcode exists.
*/
function shortcode_exists( $tag ) {
global $shortcode_tags;
return array_key_exists( $tag, $shortcode_tags );
}
/**
* Whether the passed content contains the specified shortcode
*
* #since 3.6.0
*
* #global array $shortcode_tags
*
* #param string $content Content to search for shortcodes.
* #param string $tag Shortcode tag to check.
* #return bool Whether the passed content contains the given shortcode.
*/
function has_shortcode( $content, $tag ) {
if ( false === strpos( $content, '[' ) ) {
return false;
}
if ( shortcode_exists( $tag ) ) {
preg_match_all( '/' . get_shortcode_regex() . '/', $content, $matches, PREG_SET_ORDER );
if ( empty( $matches ) )
return false;
foreach ( $matches as $shortcode ) {
if ( $tag === $shortcode[2] ) {
return true;
} elseif ( ! empty( $shortcode[5] ) && has_shortcode( $shortcode[5], $tag ) ) {
return true;
}
}
}
return false;
}
/**
* Search content for shortcodes and filter shortcodes through their hooks.
*
* If there are no shortcode tags defined, then the content will be returned
* without any filtering. This might cause issues when plugins are disabled but
* the shortcode will still show up in the post or content.
*
* #since 2.5.0
*
* #global array $shortcode_tags List of shortcode tags and their callback hooks.
*
* #param string $content Content to search for shortcodes.
* #param bool $ignore_html When true, shortcodes inside HTML elements will be skipped.
* #return string Content with shortcodes filtered out.
*/
function do_shortcode( $content, $ignore_html = false ) {
global $shortcode_tags;
if ( false === strpos( $content, '[' ) ) {
return $content;
}
if (empty($shortcode_tags) || !is_array($shortcode_tags))
return $content;
// Find all registered tag names in $content.
preg_match_all( '#\[([^<>&/\[\]\x00-\x20=]++)#', $content, $matches );
$tagnames = array_intersect( array_keys( $shortcode_tags ), $matches[1] );
if ( empty( $tagnames ) ) {
return $content;
}
$content = do_shortcodes_in_html_tags( $content, $ignore_html, $tagnames );
$pattern = get_shortcode_regex( $tagnames );
$content = preg_replace_callback( "/$pattern/", 'do_shortcode_tag', $content );
// Always restore square braces so we don't break things like <!--[if IE ]>
$content = unescape_invalid_shortcodes( $content );
// Making your custom string parses shortcode
$string = do_shortcode( $string );
// If your string has a custom filter, add its tag name in an applicable add_filter function
add_filter( 'my_string_filter_hook_tag_name', 'do_shortcode' );
return $content;
}
/**
* Retrieve the shortcode regular expression for searching.
*
* The regular expression combines the shortcode tags in the regular expression
* in a regex class.
*
* The regular expression contains 6 different sub matches to help with parsing.
*
* 1 - An extra [ to allow for escaping shortcodes with double [[]]
* 2 - The shortcode name
* 3 - The shortcode argument list
* 4 - The self closing /
* 5 - The content of a shortcode when it wraps some content.
* 6 - An extra ] to allow for escaping shortcodes with double [[]]
*
* #since 2.5.0
*
* #global array $shortcode_tags
*
* #param array $tagnames List of shortcodes to find. Optional. Defaults to all registered shortcodes.
* #return string The shortcode search regular expression
*/
function get_shortcode_regex( $tagnames = null ) {
global $shortcode_tags;
if ( empty( $tagnames ) ) {
$tagnames = array_keys( $shortcode_tags );
}
$tagregexp = join( '|', array_map('preg_quote', $tagnames) );
// WARNING! Do not change this regex without changing do_shortcode_tag() and strip_shortcode_tag()
// Also, see shortcode_unautop() and shortcode.js.
return
'\\[' // Opening bracket
. '(\\[?)' // 1: Optional second opening bracket for escaping shortcodes: [[tag]]
. "($tagregexp)" // 2: Shortcode name
. '(?![\\w-])' // Not followed by word character or hyphen
. '(' // 3: Unroll the loop: Inside the opening shortcode tag
. '[^\\]\\/]*' // Not a closing bracket or forward slash
. '(?:'
. '\\/(?!\\])' // A forward slash not followed by a closing bracket
. '[^\\]\\/]*' // Not a closing bracket or forward slash
. ')*?'
. ')'
. '(?:'
. '(\\/)' // 4: Self closing tag ...
. '\\]' // ... and closing bracket
. '|'
. '\\]' // Closing bracket
. '(?:'
. '(' // 5: Unroll the loop: Optionally, anything between the opening and closing shortcode tags
. '[^\\[]*+' // Not an opening bracket
. '(?:'
. '\\[(?!\\/\\2\\])' // An opening bracket not followed by the closing shortcode tag
. '[^\\[]*+' // Not an opening bracket
. ')*+'
. ')'
. '\\[\\/\\2\\]' // Closing shortcode tag
. ')?'
. ')'
. '(\\]?)'; // 6: Optional second closing brocket for escaping shortcodes: [[tag]]
}
/**
* Regular Expression callable for do_shortcode() for calling shortcode hook.
* #see get_shortcode_regex for details of the match array contents.
*
* #since 2.5.0
* #access private
*
* #global array $shortcode_tags
*
* #param array $m Regular expression match array
* #return string|false False on failure.
*/
function do_shortcode_tag( $m ) {
global $shortcode_tags;
// allow [[foo]] syntax for escaping a tag
if ( $m[1] == '[' && $m[6] == ']' ) {
return substr($m[0], 1, -1);
}
$tag = $m[2];
$attr = shortcode_parse_atts( $m[3] );
if ( ! is_callable( $shortcode_tags[ $tag ] ) ) {
/* translators: %s: shortcode tag */
$message = sprintf( __( 'Attempting to parse a shortcode without a valid callback: %s' ), $tag );
_doing_it_wrong( __FUNCTION__, $message, '4.3.0' );
return $m[0];
}
if ( isset( $m[5] ) ) {
// enclosing tag - extra parameter
return $m[1] . call_user_func( $shortcode_tags[$tag], $attr, $m[5], $tag ) . $m[6];
} else {
// self-closing tag
return $m[1] . call_user_func( $shortcode_tags[$tag], $attr, null, $tag ) . $m[6];
}
}
/**
* Search only inside HTML elements for shortcodes and process them.
*
* Any [ or ] characters remaining inside elements will be HTML encoded
* to prevent interference with shortcodes that are outside the elements.
* Assumes $content processed by KSES already. Users with unfiltered_html
* capability may get unexpected output if angle braces are nested in tags.
*
* #since 4.2.3
*
* #param string $content Content to search for shortcodes
* #param bool $ignore_html When true, all square braces inside elements will be encoded.
* #param array $tagnames List of shortcodes to find.
* #return string Content with shortcodes filtered out.
*/
function do_shortcodes_in_html_tags( $content, $ignore_html, $tagnames ) {
// Normalize entities in unfiltered HTML before adding placeholders.
$trans = array( '[' => '[', ']' => ']' );
$content = strtr( $content, $trans );
$trans = array( '[' => '[', ']' => ']' );
$pattern = get_shortcode_regex( $tagnames );
$textarr = wp_html_split( $content );
foreach ( $textarr as &$element ) {
if ( '' == $element || '<' !== $element[0] ) {
continue;
}
$noopen = false === strpos( $element, '[' );
$noclose = false === strpos( $element, ']' );
if ( $noopen || $noclose ) {
// This element does not contain shortcodes.
if ( $noopen xor $noclose ) {
// Need to encode stray [ or ] chars.
$element = strtr( $element, $trans );
}
continue;
}
if ( $ignore_html || '<!--' === substr( $element, 0, 4 ) || '<![CDATA[' === substr( $element, 0, 9 ) ) {
// Encode all [ and ] chars.
$element = strtr( $element, $trans );
continue;
}
$attributes = wp_kses_attr_parse( $element );
if ( false === $attributes ) {
// Some plugins are doing things like [name] <[email]>.
if ( 1 === preg_match( '%^<\s*\[\[?[^\[\]]+\]%', $element ) ) {
$element = preg_replace_callback( "/$pattern/", 'do_shortcode_tag', $element );
}
// Looks like we found some crazy unfiltered HTML. Skipping it for sanity.
$element = strtr( $element, $trans );
continue;
}
// Get element name
$front = array_shift( $attributes );
$back = array_pop( $attributes );
$matches = array();
preg_match('%[a-zA-Z0-9]+%', $front, $matches);
$elname = $matches[0];
// Look for shortcodes in each attribute separately.
foreach ( $attributes as &$attr ) {
$open = strpos( $attr, '[' );
$close = strpos( $attr, ']' );
if ( false === $open || false === $close ) {
continue; // Go to next attribute. Square braces will be escaped at end of loop.
}
$double = strpos( $attr, '"' );
$single = strpos( $attr, "'" );
if ( ( false === $single || $open < $single ) && ( false === $double || $open < $double ) ) {
// $attr like '[shortcode]' or 'name = [shortcode]' implies unfiltered_html.
// In this specific situation we assume KSES did not run because the input
// was written by an administrator, so we should avoid changing the output
// and we do not need to run KSES here.
$attr = preg_replace_callback( "/$pattern/", 'do_shortcode_tag', $attr );
} else {
// $attr like 'name = "[shortcode]"' or "name = '[shortcode]'"
// We do not know if $content was unfiltered. Assume KSES ran before shortcodes.
$count = 0;
$new_attr = preg_replace_callback( "/$pattern/", 'do_shortcode_tag', $attr, -1, $count );
if ( $count > 0 ) {
// Sanitize the shortcode output using KSES.
$new_attr = wp_kses_one_attr( $new_attr, $elname );
if ( '' !== trim( $new_attr ) ) {
// The shortcode is safe to use now.
$attr = $new_attr;
}
}
}
}
$element = $front . implode( '', $attributes ) . $back;
// Now encode any remaining [ or ] chars.
$element = strtr( $element, $trans );
}
$content = implode( '', $textarr );
return $content;
}
/**
* Remove placeholders added by do_shortcodes_in_html_tags().
*
* #since 4.2.3
*
* #param string $content Content to search for placeholders.
* #return string Content with placeholders removed.
*/
function unescape_invalid_shortcodes( $content ) {
// Clean up entire string, avoids re-parsing HTML.
$trans = array( '[' => '[', ']' => ']' );
$content = strtr( $content, $trans );
return $content;
}
/**
* Retrieve the shortcode attributes regex.
*
* #since 4.4.0
*
* #return string The shortcode attribute regular expression
*/
function get_shortcode_atts_regex() {
return '/([\w-]+)\s*=\s*"([^"]*)"(?:\s|$)|([\w-]+)\s*=\s*\'([^\']*)\'(?:\s|$)|([\w-]+)\s*=\s*([^\s\'"]+)(?:\s|$)|"([^"]*)"(?:\s|$)|(\S+)(?:\s|$)/';
}
/**
* Retrieve all attributes from the shortcodes tag.
*
* The attributes list has the attribute name as the key and the value of the
* attribute as the value in the key/value pair. This allows for easier
* retrieval of the attributes, since all attributes have to be known.
*
* #since 2.5.0
*
* #param string $text
* #return array|string List of attribute values.
* Returns empty array if trim( $text ) == '""'.
* Returns empty string if trim( $text ) == ''.
* All other matches are checked for not empty().
*/
function shortcode_parse_atts($text) {
$atts = array();
$pattern = get_shortcode_atts_regex();
$text = preg_replace("/[\x{00a0}\x{200b}]+/u", " ", $text);
if ( preg_match_all($pattern, $text, $match, PREG_SET_ORDER) ) {
foreach ($match as $m) {
if (!empty($m[1]))
$atts[strtolower($m[1])] = stripcslashes($m[2]);
elseif (!empty($m[3]))
$atts[strtolower($m[3])] = stripcslashes($m[4]);
elseif (!empty($m[5]))
$atts[strtolower($m[5])] = stripcslashes($m[6]);
elseif (isset($m[7]) && strlen($m[7]))
$atts[] = stripcslashes($m[7]);
elseif (isset($m[8]))
$atts[] = stripcslashes($m[8]);
}
// Reject any unclosed HTML elements
foreach( $atts as &$value ) {
if ( false !== strpos( $value, '<' ) ) {
if ( 1 !== preg_match( '/^[^<]*+(?:<[^>]*+>[^<]*+)*+$/', $value ) ) {
$value = '';
}
}
}
} else {
$atts = ltrim($text);
}
return $atts;
}
/**
* Combine user attributes with known attributes and fill in defaults when needed.
*
* The pairs should be considered to be all of the attributes which are
* supported by the caller and given as a list. The returned attributes will
* only contain the attributes in the $pairs list.
*
* If the $atts list has unsupported attributes, then they will be ignored and
* removed from the final returned list.
*
* #since 2.5.0
*
* #param array $pairs Entire list of supported attributes and their defaults.
* #param array $atts User defined attributes in shortcode tag.
* #param string $shortcode Optional. The name of the shortcode, provided for context to enable filtering
* #return array Combined and filtered attribute list.
*/
function shortcode_atts( $pairs, $atts, $shortcode = '' ) {
$atts = (array)$atts;
$out = array();
foreach ($pairs as $name => $default) {
if ( array_key_exists($name, $atts) )
$out[$name] = $atts[$name];
else
$out[$name] = $default;
}
/**
* Filter a shortcode's default attributes.
*
* If the third parameter of the shortcode_atts() function is present then this filter is available.
* The third parameter, $shortcode, is the name of the shortcode.
*
* #since 3.6.0
* #since 4.4.0 Added the `$shortcode` parameter.
*
* #param array $out The output array of shortcode attributes.
* #param array $pairs The supported attributes and their defaults.
* #param array $atts The user defined shortcode attributes.
* #param string $shortcode The shortcode name.
*/
if ( $shortcode ) {
$out = apply_filters( "shortcode_atts_{$shortcode}", $out, $pairs, $atts, $shortcode );
}
return $out;
}
/**
* Remove all shortcode tags from the given content.
*
* #since 2.5.0
*
* #global array $shortcode_tags
*
* #param string $content Content to remove shortcode tags.
* #return string Content without shortcode tags.
*/
function strip_shortcodes( $content ) {
global $shortcode_tags;
if ( false === strpos( $content, '[' ) ) {
return $content;
}
if (empty($shortcode_tags) || !is_array($shortcode_tags))
return $content;
// Find all registered tag names in $content.
preg_match_all( '#\[([^<>&/\[\]\x00-\x20=]++)#', $content, $matches );
$tagnames = array_intersect( array_keys( $shortcode_tags ), $matches[1] );
if ( empty( $tagnames ) ) {
return $content;
}
$content = do_shortcodes_in_html_tags( $content, true, $tagnames );
$pattern = get_shortcode_regex( $tagnames );
$content = preg_replace_callback( "/$pattern/", 'strip_shortcode_tag', $content );
// Always restore square braces so we don't break things like <!--[if IE ]>
$content = unescape_invalid_shortcodes( $content );
return $content;
}
/**
* Strips a shortcode tag based on RegEx matches against post content.
*
* #since 3.3.0
*
* #param array $m RegEx matches against post content.
* #return string|false The content stripped of the tag, otherwise false.
*/
function strip_shortcode_tag( $m ) {
// allow [[foo]] syntax for escaping a tag
if ( $m[1] == '[' && $m[6] == ']' ) {
return substr($m[0], 1, -1);
}
return $m[1] . $m[6];
}
Please help...
I wanna help but I really dont understand your question.
try change define('WP_DEBUG', true); and see where the problem is.
add_shortcode('check', 'check_scode');
function check_scode($atts){
return '<h1>its working</h1>';
}
add above script test to the bottom of your functions.php in wp-content/themes/your-themes
and put this shortcode
[check]
or with php code, check if your shortcode registered,
if ( ! function_exists( 'check_shortcode' ) ) :
function check_shortcode( $code = '' ) {
global $shortcode_tags;
if ( $code && array_key_exists( $code, $shortcode_tags ) ){
return true;
}
}
endif;
put in the bottom of your functions.php and add this script somewhere,
<?php
if(check_shortcode('gallery_bank')) {
echo '<h1>Shortcode found</h1>';
}else{
echo '<h1>Shortcode <b>not Registered<b></h1>';
}
?>
you should check your theme, search theme check in plugin-install page
Related
This is my code for displaying dropdowns in nav menu. I've found it somewhere in internet and edited. I need to display SVG icon element in parent <li> if has submenu / dropdown menu.
<?php
if ( !class_exists( 'WP_Bootstrap_Navwalker' ) ) {
/**
* WP_Bootstrap_Navwalker class
*
* #package Template
* #subpackage Bootstrap4
*
* #since 1.0.0
* #see https://getbootstrap.com/docs/4.0/components/navbar/
* #extends Walker_Nav_Menu
* #author Javier Prieto
*/
class WP_Bootstrap_Navwalker extends Walker_Nav_Menu {
/**
* Starts the list before the elements are added.
*
* #since WP 3.0.0
*
* #see Walker_Nav_Menu::start_lvl()
*
* #param string $output Used to append additional content (passed by reference).
* #param int $depth Depth of menu item. Used for padding.
* #param stdClass $args An object of wp_nav_menu() arguments.
*/
public function start_lvl( &$output, $depth = 0, $args = array() ) {
if ( isset( $args->item_spacing ) && 'discard' === $args->item_spacing ) {
$t = '';
$n = '';
} else {
$t = "\t";
$n = "\n";
}
$indent = str_repeat( $t, $depth );
// Default class to add to the file.
$classes = array( 'sub-menu menu__list' );
/**
* Filters the CSS class(es) applied to a menu list element.
*
* #since WP 4.8.0
*
* #param array $classes The CSS classes that are applied to the menu `<ul>` element.
* #param stdClass $args An object of `wp_nav_menu()` arguments.
* #param int $depth Depth of menu item. Used for padding.
*/
$class_names = join( ' ', apply_filters( 'nav_menu_submenu_css_class', $classes, $args, $depth ) );
$class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
/*
* The `.dropdown-menu` container needs to have a labelledby
* attribute which points to it's trigger link.
*
* Form a string for the labelledby attribute from the the latest
* link with an id that was added to the $output.
*/
$labelledby = '';
// Find all links with an id in the output.
preg_match_all( '/(<a.*?id=\"|\')(.*?)\"|\'.*?>/im', $output, $matches );
// With pointer at end of array check if we got an ID match.
if ( end( $matches[2] ) ) {
// Build a string to use as aria-labelledby.
$labelledby = 'aria-labelledby="' . esc_attr( end( $matches[2] ) ) . '"';
}
$output .= '<div class="nav-links__submenu nav-links__submenu--type--menu">';
$output .= '<div class="menu menu--layout--classic">';
$output .= "{$n}{$indent}<ul$class_names $labelledby role=\"menu\">{$n}";
}
/**
* Starts the element output.
*
* #since WP 3.0.0
* #since WP 4.4.0 The {#see 'nav_menu_item_args'} filter was added.
*
* #see Walker_Nav_Menu::start_el()
*
* #param string $output Used to append additional content (passed by reference).
* #param WP_Post $item Menu item data object.
* #param int $depth Depth of menu item. Used for padding.
* #param stdClass $args An object of wp_nav_menu() arguments.
* #param int $id Current item ID.
*/
public function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
if ( isset( $args->item_spacing ) && 'discard' === $args->item_spacing ) {
$t = '';
$n = '';
} else {
$t = "\t";
$n = "\n";
}
$indent = ( $depth ) ? str_repeat( $t, $depth ) : '';
$classes = empty( $item->classes ) ? array() : (array) $item->classes;
/*
* Initialize some holder variables to store specially handled item
* wrappers and icons.
*/
$linkmod_classes = array();
$icon_classes = array();
/*
* Get an updated $classes array without linkmod or icon classes.
*
* NOTE: linkmod and icon class arrays are passed by reference and
* are maybe modified before being used later in this function.
*/
$classes = self::separate_linkmods_and_icons_from_classes( $classes, $linkmod_classes, $icon_classes, $depth );
// Join any icon classes plucked from $classes into a string.
$icon_class_string = join( ' ', $icon_classes );
/**
* Filters the arguments for a single nav menu item.
*
* WP 4.4.0
*
* #param stdClass $args An object of wp_nav_menu() arguments.
* #param WP_Post $item Menu item data object.
* #param int $depth Depth of menu item. Used for padding.
*/
$args = apply_filters( 'nav_menu_item_args', $args, $item, $depth );
// Add .dropdown or .active classes where they are needed.
if ( isset( $args->has_children ) && $args->has_children ) {
$classes[] = 'dropdown';
}
if ( in_array( 'current-menu-item', $classes, true ) || in_array( 'current-menu-parent', $classes, true ) ) {
$classes[] = 'active';
}
// Add some additional default classes to the item.
$classes[] = 'menu-item-' . $item->ID;
$classes[] = 'nav-item menu__item';
// Allow filtering the classes.
$classes = apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args, $depth );
// Form a string of classes in format: class="class_names".
$class_names = join( ' ', $classes );
$class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
/**
* Filters the ID applied to a menu item's list item element.
*
* #since WP 3.0.1
* #since WP 4.1.0 The `$depth` parameter was added.
*
* #param string $menu_id The ID that is applied to the menu item's `<li>` element.
* #param WP_Post $item The current menu item.
* #param stdClass $args An object of wp_nav_menu() arguments.
* #param int $depth Depth of menu item. Used for padding.
*/
$id = apply_filters( 'nav_menu_item_id', 'menu-item-' . $item->ID, $item, $args, $depth );
$id = $id ? ' id="' . esc_attr( $id ) . '"' : '';
$output .= $indent . '<li itemscope="itemscope" itemtype="https://www.schema.org/SiteNavigationElement"' . $id . $class_names . '>';
// Initialize array for holding the $atts for the link item.
$atts = array();
/*
* Set title from item to the $atts array - if title is empty then
* default to item title.
*/
if ( empty( $item->attr_title ) ) {
$atts['title'] = ! empty( $item->title ) ? strip_tags( $item->title ) : '';
} else {
$atts['title'] = $item->attr_title;
}
$atts['target'] = ! empty( $item->target ) ? $item->target : '';
$atts['rel'] = ! empty( $item->xfn ) ? $item->xfn : '';
// If the item has children, add atts to the <a>.
if ( isset( $args->has_children ) && $args->has_children && 0 === $depth && $args->depth > 1 ) {
$atts['href'] = '#';
$atts['data-toggle'] = 'dropdown';
$atts['aria-haspopup'] = 'true';
$atts['aria-expanded'] = 'false';
$atts['class'] = 'dropdown-toggle nav-link';
$atts['id'] = 'menu-item-dropdown-' . $item->ID;
} else {
$atts['href'] = ! empty( $item->url ) ? $item->url : '#';
// For items in dropdowns use .dropdown-item instead of .nav-link.
if ( $depth > 0 ) {
$atts['class'] = 'dropdown-item';
}
}
$atts['aria-current'] = $item->current ? 'page' : '';
// Update atts of this item based on any custom linkmod classes.
$atts = self::update_atts_for_linkmod_type( $atts, $linkmod_classes );
// Allow filtering of the $atts array before using it.
$atts = apply_filters( 'nav_menu_link_attributes', $atts, $item, $args, $depth );
// Build a string of html containing all the atts for the item.
$attributes = '';
foreach ( $atts as $attr => $value ) {
if ( ! empty( $value ) ) {
$value = ( 'href' === $attr ) ? esc_url( $value ) : esc_attr( $value );
$attributes .= ' ' . $attr . '="' . $value . '"';
}
}
// Set a typeflag to easily test if this is a linkmod or not.
$linkmod_type = self::get_linkmod_type( $linkmod_classes );
// START appending the internal item contents to the output.
$item_output = isset( $args->before ) ? $args->before : '';
/*
* This is the start of the internal nav item. Depending on what
* kind of linkmod we have we may need different wrapper elements.
*/
if ( '' !== $linkmod_type ) {
// Is linkmod, output the required element opener.
$item_output .= self::linkmod_element_open( $linkmod_type, $attributes );
} else {
// With no link mod type set this must be a standard <a> tag.
$item_output .= '<a' . $attributes . '>';
}
/*
* Initiate empty icon var, then if we have a string containing any
* icon classes form the icon markup with an <i> element. This is
* output inside of the item before the $title (the link text).
*/
$icon_html = '';
if ( ! empty( $icon_class_string ) ) {
// Append an <i> with the icon classes to what is output before links.
$icon_html = '<i class="' . esc_attr( $icon_class_string ) . '" aria-hidden="true"></i> ';
}
/** This filter is documented in wp-includes/post-template.php */
$title = apply_filters( 'the_title', esc_html( $item->title ), $item->ID );
/**
* Filters a menu item's title.
*
* #since WP 4.4.0
*
* #param string $title The menu item's title.
* #param WP_Post $item The current menu item.
* #param stdClass $args An object of wp_nav_menu() arguments.
* #param int $depth Depth of menu item. Used for padding.
*/
$title = apply_filters( 'nav_menu_item_title', $title, $item, $args, $depth );
// If the .sr-only class was set apply to the nav items text only.
if ( in_array( 'sr-only', $linkmod_classes, true ) ) {
$title = self::wrap_for_screen_reader( $title );
$keys_to_unset = array_keys( $linkmod_classes, 'sr-only', true );
foreach ( $keys_to_unset as $k ) {
unset( $linkmod_classes[ $k ] );
}
}
// Put the item contents into $output.
$item_output .= isset( $args->link_before ) ? $args->link_before . $icon_html . $title . $args->link_after : '';
/*
* This is the end of the internal nav item. We need to close the
* correct element depending on the type of link or link mod.
*/
if ( '' !== $linkmod_type ) {
// Is linkmod, output the required closing element.
$item_output .= self::linkmod_element_close( $linkmod_type );
} else {
// With no link mod type set this must be a standard <a> tag.
$item_output .= '</a>';
}
$item_output .= isset( $args->after ) ? $args->after : '';
// END appending the internal item contents to the output.
$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}
/**
* Traverse elements to create list from elements.
*
* Display one element if the element doesn't have any children otherwise,
* display the element and its children. Will only traverse up to the max
* depth and no ignore elements under that depth. It is possible to set the
* max depth to include all depths, see walk() method.
*
* This method should not be called directly, use the walk() method instead.
*
* #since WP 2.5.0
*
* #see Walker::start_lvl()
*
* #param object $element Data object.
* #param array $children_elements List of elements to continue traversing (passed by reference).
* #param int $max_depth Max depth to traverse.
* #param int $depth Depth of current element.
* #param array $args An array of arguments.
* #param string $output Used to append additional content (passed by reference).
*/
public function display_element( $element, &$children_elements, $max_depth, $depth, $args, &$output ) {
if ( ! $element ) {
return; }
$id_field = $this->db_fields['id'];
// Display this element.
if ( is_object( $args[0] ) ) {
$args[0]->has_children = ! empty( $children_elements[ $element->$id_field ] ); }
parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );
}
/**
* Menu Fallback.
*
* If this function is assigned to the wp_nav_menu's fallback_cb variable
* and a menu has not been assigned to the theme location in the WordPress
* menu manager the function with display nothing to a non-logged in user,
* and will add a link to the WordPress menu manager if logged in as an admin.
*
* #param array $args passed from the wp_nav_menu function.
*/
public static function fallback( $args ) {
if ( current_user_can( 'edit_theme_options' ) ) {
// Get Arguments.
$container = $args['container'];
$container_id = $args['container_id'];
$container_class = $args['container_class'];
$menu_class = $args['menu_class'];
$menu_id = $args['menu_id'];
// Initialize var to store fallback html.
$fallback_output = '';
if ( $container ) {
$fallback_output .= '<' . esc_attr( $container );
if ( $container_id ) {
$fallback_output .= ' id="' . esc_attr( $container_id ) . '"';
}
if ( $container_class ) {
$fallback_output .= ' class="' . esc_attr( $container_class ) . '"';
}
$fallback_output .= '>';
}
$fallback_output .= '<ul';
if ( $menu_id ) {
$fallback_output .= ' id="' . esc_attr( $menu_id ) . '"'; }
if ( $menu_class ) {
$fallback_output .= ' class="' . esc_attr( $menu_class ) . '"'; }
$fallback_output .= '>';
$fallback_output .= '<li class="nav-item">' . esc_html__( 'Add a menu', 'wp-bootstrap-navwalker' ) . '</li>';
$fallback_output .= '</ul>';
if ( $container ) {
$fallback_output .= '</' . esc_attr( $container ) . '>';
}
// If $args has 'echo' key and it's true echo, otherwise return.
if ( array_key_exists( 'echo', $args ) && $args['echo'] ) {
echo $fallback_output; // WPCS: XSS OK.
} else {
return $fallback_output;
}
}
}
/**
* Find any custom linkmod or icon classes and store in their holder
* arrays then remove them from the main classes array.
*
* Supported linkmods: .disabled, .dropdown-header, .dropdown-divider, .sr-only
* Supported iconsets: Font Awesome 4/5, Glypicons
*
* NOTE: This accepts the linkmod and icon arrays by reference.
*
* #since 4.0.0
*
* #param array $classes an array of classes currently assigned to the item.
* #param array $linkmod_classes an array to hold linkmod classes.
* #param array $icon_classes an array to hold icon classes.
* #param integer $depth an integer holding current depth level.
*
* #return array $classes a maybe modified array of classnames.
*/
private function separate_linkmods_and_icons_from_classes( $classes, &$linkmod_classes, &$icon_classes, $depth ) {
// Loop through $classes array to find linkmod or icon classes.
foreach ( $classes as $key => $class ) {
/*
* If any special classes are found, store the class in it's
* holder array and and unset the item from $classes.
*/
if ( preg_match( '/^disabled|^sr-only/i', $class ) ) {
// Test for .disabled or .sr-only classes.
$linkmod_classes[] = $class;
unset( $classes[ $key ] );
} elseif ( preg_match( '/^dropdown-header|^dropdown-divider|^dropdown-item-text/i', $class ) && $depth > 0 ) {
/*
* Test for .dropdown-header or .dropdown-divider and a
* depth greater than 0 - IE inside a dropdown.
*/
$linkmod_classes[] = $class;
unset( $classes[ $key ] );
} elseif ( preg_match( '/^fa-(\S*)?|^fa(s|r|l|b)?(\s?)?$/i', $class ) ) {
// Font Awesome.
$icon_classes[] = $class;
unset( $classes[ $key ] );
} elseif ( preg_match( '/^glyphicon-(\S*)?|^glyphicon(\s?)$/i', $class ) ) {
// Glyphicons.
$icon_classes[] = $class;
unset( $classes[ $key ] );
}
}
return $classes;
}
/**
* Return a string containing a linkmod type and update $atts array
* accordingly depending on the decided.
*
* #since 4.0.0
*
* #param array $linkmod_classes array of any link modifier classes.
*
* #return string empty for default, a linkmod type string otherwise.
*/
private function get_linkmod_type( $linkmod_classes = array() ) {
$linkmod_type = '';
// Loop through array of linkmod classes to handle their $atts.
if ( ! empty( $linkmod_classes ) ) {
foreach ( $linkmod_classes as $link_class ) {
if ( ! empty( $link_class ) ) {
// Check for special class types and set a flag for them.
if ( 'dropdown-header' === $link_class ) {
$linkmod_type = 'dropdown-header';
} elseif ( 'dropdown-divider' === $link_class ) {
$linkmod_type = 'dropdown-divider';
} elseif ( 'dropdown-item-text' === $link_class ) {
$linkmod_type = 'dropdown-item-text';
}
}
}
}
return $linkmod_type;
}
/**
* Update the attributes of a nav item depending on the limkmod classes.
*
* #since 4.0.0
*
* #param array $atts array of atts for the current link in nav item.
* #param array $linkmod_classes an array of classes that modify link or nav item behaviors or displays.
*
* #return array maybe updated array of attributes for item.
*/
private function update_atts_for_linkmod_type( $atts = array(), $linkmod_classes = array() ) {
if ( ! empty( $linkmod_classes ) ) {
foreach ( $linkmod_classes as $link_class ) {
if ( ! empty( $link_class ) ) {
/*
* Update $atts with a space and the extra classname
* so long as it's not a sr-only class.
*/
if ( 'sr-only' !== $link_class ) {
$atts['class'] .= ' ' . esc_attr( $link_class );
}
// Check for special class types we need additional handling for.
if ( 'disabled' === $link_class ) {
// Convert link to '#' and unset open targets.
$atts['href'] = '#';
unset( $atts['target'] );
} elseif ( 'dropdown-header' === $link_class || 'dropdown-divider' === $link_class || 'dropdown-item-text' === $link_class ) {
// Store a type flag and unset href and target.
unset( $atts['href'] );
unset( $atts['target'] );
}
}
}
}
return $atts;
}
/**
* Wraps the passed text in a screen reader only class.
*
* #since 4.0.0
*
* #param string $text the string of text to be wrapped in a screen reader class.
* #return string the string wrapped in a span with the class.
*/
private function wrap_for_screen_reader( $text = '' ) {
if ( $text ) {
$text = '<span class="sr-only">' . $text . '</span>';
}
return $text;
}
/**
* Returns the correct opening element and attributes for a linkmod.
*
* #since 4.0.0
*
* #param string $linkmod_type a sting containing a linkmod type flag.
* #param string $attributes a string of attributes to add to the element.
*
* #return string a string with the openign tag for the element with attribibutes added.
*/
private function linkmod_element_open( $linkmod_type, $attributes = '' ) {
$output = '';
if ( 'dropdown-item-text' === $linkmod_type ) {
$output .= '<span class="dropdown-item-text"' . $attributes . '>';
} elseif ( 'dropdown-header' === $linkmod_type ) {
/*
* For a header use a span with the .h6 class instead of a real
* header tag so that it doesn't confuse screen readers.
*/
$output .= '<span class="dropdown-header h6"' . $attributes . '>';
} elseif ( 'dropdown-divider' === $linkmod_type ) {
// This is a divider.
$output .= '<div class="dropdown-divider"' . $attributes . '>';
}
return $output;
}
/**
* Return the correct closing tag for the linkmod element.
*
* #since 4.0.0
*
* #param string $linkmod_type a string containing a special linkmod type.
*
* #return string a string with the closing tag for this linkmod type.
*/
private function linkmod_element_close( $linkmod_type ) {
$output = '';
if ( 'dropdown-header' === $linkmod_type || 'dropdown-item-text' === $linkmod_type ) {
/*
* For a header use a span with the .h6 class instead of a real
* header tag so that it doesn't confuse screen readers.
*/
$output .= '</span>';
} elseif ( 'dropdown-divider' === $linkmod_type ) {
// This is a divider.
$output .= '</div>';
}
return $output;
}
}
}
EDIT: No any idea?
You can do that using CSS and this function in your function.php:
add_filter( 'wp_nav_menu_objects', 'add_menu_parent_class' );
function add_menu_parent_class( $items ) {
$parents = array();
foreach ( $items as $item ) {
//Check if the item is a parent item
if ( $item->menu_item_parent && $item->menu_item_parent > 0 ) {
$parents[] = $item->menu_item_parent;
}
}
foreach ( $items as $item ) {
if ( in_array( $item->ID, $parents ) ) {
//Add "menu-parent-item" class to parents
$item->classes[] = 'menu-parent-item';
}
}
return $items;
}
I don't know which classes you used but something like this should work:
#yourmenuclass ul li.menu-parent-item:before {
content: url(image.file);
}
I need to add a wrapper div around all the content within the author box.
What filter code do I need to change the genesis_author_box into this:
<section class="author-box" itemprop="author" itemscope="" itemtype="https://schema.org/Person">
<div class="author-box-wrap">
<img alt="" src="" srcset="" class="avatar avatar-150 photo" height="150" width="150">
<h4 class="author-box-title">About <span itemprop="name">Author Name</span></h4>
<div class="author-box-content" itemprop="description">Description Text</div>
</div>
</section>
Here is the default Genesis markup:
<section class="author-box" itemprop="author" itemscope="" itemtype="https://schema.org/Person">
<img alt="" src="" srcset="" class="avatar avatar-150 photo" height="150" width="150">
<h4 class="author-box-title">About <span itemprop="name">Author Name</span></h4>
<div class="author-box-content" itemprop="description">Description Text</div>
</section>
Here is the code that assembles the default Genesis markup:
/**
* Echo the the author box and its contents.
*
* The title is filterable via `genesis_author_box_title`, and the gravatar size is filterable via
* `genesis_author_box_gravatar_size`.
*
* The final output is filterable via `genesis_author_box`, which passes many variables through.
*
* #since 1.3.0
*
* #global WP_User $authordata Author (user) object.
*
* #param string $context Optional. Allows different author box markup for different contexts, specifically 'single'.
* Default is empty string.
* #param bool $echo Optional. If true, the author box will echo. If false, it will be returned.
* #return string HTML for author box if `$echo` param is falsy.
*/
function genesis_author_box( $context = '', $echo = true ) {
global $authordata;
$authordata = is_object( $authordata ) ? $authordata : get_userdata( get_query_var( 'author' ) );
$gravatar_size = apply_filters( 'genesis_author_box_gravatar_size', 70, $context );
$gravatar = get_avatar( get_the_author_meta( 'email' ), $gravatar_size );
$description = wpautop( get_the_author_meta( 'description' ) );
// The author box markup, contextual.
if ( genesis_html5() ) {
$title = __( 'About', 'genesis' ) . ' <span itemprop="name">' . get_the_author() . '</span>';
/**
* Author box title filter.
*
* Allows you to filter the title of the author box. $context passed as second parameter to allow for contextual filtering.
*
* #since unknown
*
* #param string $title Assembled Title.
* #param string $context Context.
*/
$title = apply_filters( 'genesis_author_box_title', $title, $context );
$heading_element = 'h1';
if ( 'single' === $context && ! genesis_get_seo_option( 'semantic_headings' ) ) {
$heading_element = 'h4';
} elseif ( genesis_a11y( 'headings' ) || get_the_author_meta( 'headline', (int) get_query_var( 'author' ) ) ) {
$heading_element = 'h4';
}
$pattern = sprintf( '<section %s>', genesis_attr( 'author-box' ) );
$pattern .= '%s<' . $heading_element . ' class="author-box-title">%s</' . $heading_element . '>';
$pattern .= '<div class="author-box-content" itemprop="description">%s</div>';
$pattern .= '</section>';
} else {
$title = apply_filters( 'genesis_author_box_title', sprintf( '<strong>%s %s</strong>', __( 'About', 'genesis' ), get_the_author() ), $context );
$pattern = '<div class="author-box">%s<h1>%s</h1><div>%s</div></div>';
if ( 'single' === $context || get_the_author_meta( 'headline', (int) get_query_var( 'author' ) ) ) {
$pattern = '<div class="author-box"><div>%s %s<br />%s</div></div>';
}
}
$output = sprintf( $pattern, $gravatar, $title, $description );
/**
* Author box output filter.
*
* Allows you to filter the full output of the author box.
*
* #since unknown
*
* #param string $output Assembled output.
* #param string $context Context.
* #param string $pattern (s)printf pattern.
* #param string $context Gravatar.
* #param string $context Title.
* #param string $context Description.
*/
$output = apply_filters( 'genesis_author_box', $output, $context, $pattern, $gravatar, $title, $description );
if ( $echo ) {
echo $output;
return null;
} else {
return $output;
}
My PHP is really rough... Thank you for your help!
Give this a try:
add_filter( 'genesis_author_box', 'my_filter_author_box', 10, 3 );
function my_filter_author_box( $output, $context ) {
$output = preg_replace( '/<section (.+?)>(.+)<\/section>/ms', '<section $1><div class="author-box-wrap">$2</div></section>', $output );
return $output;
}
It may be worth reconsidering why you need to add the inner wrapping div and see if you can work out a better way to style it instead.
I have a custom post type that has a bunch of posts all formatted like so
Artist - Song Title
for example
The Smashing Pumpkins - Quiet
I am trying to put 'Artist' in a variable $artist and 'Song Title' in a variable $song
$artistsong = get_the_title();
$songeach = explode("-", $artistsong);
$artist = $songeach[0];
$song = $songeach[1];
But this does not work. Echo-ing $artist gets the full title
The Smashing Pumpkins - Quiet
and echoing $song does not output anything
This works if I am just starting from plaintext, but not with 'get_the_title()'
$song = "The Smashing Pumpkins - Quiet";
$songeach = explode("-", $song);
$artist = trim($songeach[0]);
$song = trim($songeach[1]);
echo $artist;
//echos 'The Smashing Pumpkins'
echo $song;
//echos 'Quiet'
Is there another way to put the full title into a variable initially other than get_the_title() which does not seem to be working for me, or am I missing something else?
Add this code to your functions.php
function get_the_title_keep_hyphen( $post = 0 ) {
$post = get_post( $post );
$title = isset( $post->post_title ) ? $post->post_title : '';
$id = isset( $post->ID ) ? $post->ID : 0;
if ( ! is_admin() ) {
if ( ! empty( $post->post_password ) ) {
/**
* Filter the text prepended to the post title for protected posts.
*
* The filter is only applied on the front end.
*
* #since 2.8.0
*
* #param string $prepend Text displayed before the post title.
* Default 'Protected: %s'.
* #param WP_Post $post Current post object.
*/
$protected_title_format = apply_filters( 'protected_title_format', __( 'Protected: %s' ), $post );
$title = sprintf( $protected_title_format, $title );
} elseif ( isset( $post->post_status ) && 'private' == $post->post_status ) {
/**
* Filter the text prepended to the post title of private posts.
*
* The filter is only applied on the front end.
*
* #since 2.8.0
*
* #param string $prepend Text displayed before the post title.
* Default 'Private: %s'.
* #param WP_Post $post Current post object.
*/
$private_title_format = apply_filters( 'private_title_format', __( 'Private: %s' ), $post );
$title = sprintf( $private_title_format, $title );
}
}
/**
* Filter the post title.
*
* #since 0.71
*
* #param string $title The post title.
* #param int $id The post ID.
*/
return $title;
}
And use this code in your single.php
$artistsong = get_the_title_keep_hyphen();
$songeach = explode(" - ", $artistsong);
$artist = $songeach[0];
$song = $songeach[1];
See the last line
I change from return apply_filters( 'the_title', $title, $id ); to return $title;
Because apply_filters function change the hyphen from - => –.
It's because of the dash symbol.
Try $songeach = explode("P", $artistsong); and you'll see what I mean. You could try a different character between artist and song title - although probably not ideal.
I have created my own custom word limit function in wordpress. I need a way to ignore the shortcode as part of the word count. I don't want to strip it out but ignore shortcodes as part of the word count. Otherwise if you choose a number say 15 and the shortcode is in any part of that 15 word limit then the page will fatal error.
function my_word_limit($limit) {
$content = explode(' ', get_the_content(), $limit);
if (count($content)>=$limit) {
array_pop($content);
$content = implode(" ",$content).'...';
} else {
$content = implode(" ",$content);
}
$content = apply_filters('the_content', $content);
return $content;
}
This is the shortcode I would be using for example.
[di-video-logged-out]<iframe src="https://www.youtube.com/embed/LEIu8gba634" width="854" height="480"></iframe>[/di-video-logged-out]
Trim content and limit with certain count word
( Keep shortcode on output even content trimmed, you can tweak also if you don't )
Here my approach with use wp_trim_word of the content and filter wp_trim_word. Also, you can use this function wpso36236774_trim_words into such as $post->post_content or get_the_content directly ( without filter ). Usage was commented inside code.
add_filter( 'wp_trim_words', 'wpso36236774_trim_words', 10, 4 );
/* Trims text to a certain number of words.
* #author Jevuska
* #version 1.0.1
*
* Kepp shortcode if exist in text.
* Combination function of strip_shortcodes and wp_trim_words
* Default $num_words = 55
*
** USAGE
** Using directly
** wpso36236774_trim_words( $text, 56 )
** wpso36236774_trim_words( $text, 56, null, false, false, true ) - return array
** Shortcode hidden if $num_words is not set or if set with value = 55 with 4 arguments
**
** Use wp_trim_words
** wp_trim_words( $text, $num_words = 56 )
** Fire wp_trim_words
** Shortcode hidden if $num_words is not set or $num_words = 55
** Position always in bottom
** add_filter( 'wp_trim_words', 'wpso36236774_trim_words', 10, 4 );
*
* #param string $text Text to trim.
* #param int $num_words The number of words to trim the text to. Default 5.
* #param string $more An optional string to append to the end of the trimmed text, e.g. ….
* #param string $original_content The text before it was trimmed.
* #param mix $pos Shortcode Position. You can set 'top' value if using directly
* #param boolean $count Get word count
* #return string The text after the filter witch $num_words
* #return array If using directly and parameter $count set to true
*/
function wpso36236774_trim_words( $text, $num_words = 55, $more = null, $original_content = false, $pos = false, $count = false )
{
if ( null === $more)
$more = ' ' . '[…]';
$shortcode = $strip_shortcode = true;
if ( ! $original_content )
$original_content = $text;
$text = $original_content;
/* Check existing shortcode
*
*/
if ( false === strpos( $text, '[' ) )
$strip_shortcode = false;
global $shortcode_tags;
if ( empty( $shortcode_tags ) || ! is_array( $shortcode_tags ) )
$strip_shortcode = false;
/* Strip content from shortcode
*
*/
if ( $strip_shortcode )
{
preg_match_all( '#\[([^<>&/\[\]\x00-\x20=]++)#', $text, $matches );
$tagnames = array_intersect( array_keys( $shortcode_tags ), $matches[1] );
if ( ! empty( $tagnames ) )
{
$text = do_shortcodes_in_html_tags( $text, true, $tagnames );
$pattern = get_shortcode_regex( $tagnames );
preg_match_all( "/$pattern/", $text, $match );
if ( ! empty( $match[0] ) && is_array( $match[0] ) )
{
$shortcode = '';
$length = count( $match[0] );
for ( $i = 0 ; $i < $length; $i++ )
$shortcode .= do_shortcode( $match[0][ $i ] ); //match shortcode
}
$text = preg_replace_callback( "/$pattern/", 'strip_shortcode_tag', $text );
$text = unescape_invalid_shortcodes( $text );
}
}
/* Hide shortcode
* Base on count function arguments
*
*/
if ( func_num_args() == 1 || ( func_num_args() == 4 && 55 == $num_words ) )
$shortcode = '';
/* Split content into array words
*
*/
$text = wp_strip_all_tags( $text );
/*
* translators: If your word count is based on single characters (e.g. East Asian characters),
* enter 'characters_excluding_spaces' or 'characters_including_spaces'. Otherwise, enter 'words'.
* Do not translate into your own language.
*/
if ( strpos( _x( 'words', 'Word count type. Do not translate!' ), 'characters' ) === 0 && preg_match( '/^utf\-?8$/i', get_option( 'blog_charset' ) ) )
{
$text = trim( preg_replace( "/[\n\r\t ]+/", ' ', $text ), ' ' );
preg_match_all( '/./u', $text, $words_array );
$limit_words_array = array_slice( $words_array[0], 0, $num_words + 1 );
$full_words_array = $words_array[0];
$sep = '';
}
else
{
$limit_words_array = preg_split( "/[\n\r\t ]+/", $text, $num_words + 1, PREG_SPLIT_NO_EMPTY );
$full_words_array = explode( ' ', preg_replace( "/[\n\r\t ]+/", ' ', $text ) );
$sep = ' ';
}
/* Check word count base on $num_words
*
*/
$word_count = count( $full_words_array );
if ( $word_count >= $num_words )
{
array_pop( $limit_words_array );
$text = implode( $sep, $limit_words_array );
$text .= $more;
/* keep shortcode if exists and set position ( top or bottom text )
*
*/
switch( $pos )
{
case 'top' :
$text = $shortcode . $text;
break;
default :
$text .= $shortcode;
break;
}
}
else
{
$text = apply_filters( 'the_content', $original_content );
}
if ( $count )
return array(
'text' => $text,
'count' => $word_count
);
return $text; //output
}
Let me know if any issue about this code. Tweak as you need and I hope this helps.
UPDATE
Fix multiple shortcode
Hide shortcode option base on total argument
Patch $pos for additional shortcode position top and bottom text ( func directly only ). For another positon, you must set class and css for your shortcode.
I've purchased a theme and the blog excerpt works fine on their demo site, but not on my website's blog overview page.
this is the code I found, but this is the wordpress post-template.php
The theme does not have any blog settings which leads me to think it's a wordpress issues?
Hopre someone can help,
Many thanks!
P.S. Php newbie so please explain how I can fix this.
function get_the_excerpt( $deprecated = '' ) {
if ( !empty( $deprecated ) )
_deprecated_argument( __FUNCTION__, '2.3' );
$post = get_post();
if ( empty( $post ) ) {
return '';
}
if ( post_password_required() ) {
return __( 'There is no excerpt because this is a protected post.' );
}
/**
* Filter the retrieved post excerpt.
*
* #since 1.2.0
*
* #param string $post_excerpt The post excerpt.
*/
return apply_filters( 'get_the_excerpt', $post->post_excerpt );
}
/**
* Whether post has excerpt.
*
* #since 2.3.0
*
* #param int|WP_Post $id Optional. Post ID or post object.
* #return bool
*/
function has_excerpt( $id = 0 ) {
$post = get_post( $id );
return ( !empty( $post->post_excerpt ) );
}
/**
* Display the classes for the post div.
*
* #since 2.7.0
*
* #param string|array $class One or more classes to add to the class list.
* #param int|WP_Post $post_id Optional. Post ID or post object.
*/
function post_class( $class = '', $post_id = null ) {
// Separates classes with a single space, collates classes for post DIV
echo 'class="' . join( ' ', get_post_class( $class, $post_id ) ) . '"';
}
By default the_excerpt() return the text in the excerpt field. Though you can use a filter to change what it returns:
add_filter( 'get_the_excerpt', 'my_custom_excerpt' );
It will trigger this function when the_excerpt() will be called:
function my_custom_excerpt($excerpt) {
if(empty($excerpt)) {
return get_custom_excerpt();
} else {
return $excerpt;
}
}
That way a custom excerpt will be used if the excerpt field is empty. Here is the code for get_custom_excerpt (it will do a "smart" ceasure):
function print_excerpt($length)
{
global $post;
$text = $post->post_excerpt;
if ( '' == $text ) {
$text = get_the_content('');
$text = apply_filters('the_content', $text);
$text = str_replace(']]>', ']]>', $text);
}
$text = strip_shortcodes($text);
$text = strip_tags($text, '<a>'); // change this to the tags you want to keep
if (preg_match('/^.{1,'.$length.'}\b/s', $text, $match))
$text = $match[0];
$excerpt = reverse_strrchr($text, array('.','!'), 1, 100);
if($excerpt) {
echo apply_filters('the_excerpt',$excerpt);
} else {
echo apply_filters('the_excerpt',$text.'...');
}
}
function reverse_strrchr($haystack, $needle, $trail, $offset=0)
{
return strrposa($haystack, $needle, $offset) ? substr($haystack, 0, strrposa($haystack, $needle, $offset) + $trail) : false;
}
// strrpos in Array mode
function strrposa($haystack, $needles=array(), $offset=0)
{
if(!is_array($needles))
$needles = array($needles);
foreach($needles as $query) {
if(strrpos($haystack, $query, $offset) !== false)
return strrpos($haystack, $query, $offset);
}
return false;
}