char == '"' || $char == "'" && $last_found_char == '=' ) {
// Is this the closing quote for an already found attribute assignment?
if ( $found_attribute_assignment && $current_attribute_enclosure == $char ) {
$found_attribute_assignment = false;
$current_attribute_enclosure = null;
} else {
$found_attribute_assignment = true;
$current_attribute_enclosure = $char;
}
} elseif ( $char == ']' ) {
// we've found a shortcode closing tag. But, we need to ensure
// that this ] isn't within the value of a shortcode attribute.
if ( ! $found_attribute_assignment ) {
break; // exit loop - we've found the shortcode.
}
}
$last_found_char = $char;
// Prevent infinite loops in our while(TRUE).
if ( $index == $content_length ) {
break;
}
++$index;
}
// Get the shortcode.
$shortcode = \substr( $content, $start_of_shortcode + 1, --$index - $start_of_shortcode );
$shortcode_replacement = \str_replace(
[ '[', ']' ],
[ '[', ']' ],
$shortcode
);
// Replace the shortcode with one that doesn't have nested shortcodes.
$content = \str_replace(
$shortcode,
$shortcode_replacement,
$content
);
// Calculate the offset for the next loop iteration.
$offset = $index + 1 + \strlen( $shortcode_replacement ) - \strlen( $shortcode );
}
}
\reset( $this->_shortcodes );
return $content;
}
/**
* Deactivates all shortcodes
*/
public function deactivate_all() {
foreach ( \array_keys( $this->_shortcodes ) as $shortcode ) {
$this->deactivate( $shortcode );
}
}
/**
* Parses the content for shortcodes and returns the substituted content
*
* @param $content
* @return string
*/
public function parse_content( $content ) {
$regex = \str_replace( '%d', '(\d+)', $this->_placeholder_text );
if ( $this->is_rest_request() ) {
// Return early if we're in the REST API and shortcodes are disabled.
// Allows other plugins to disable shortcodes in the REST API.
if ( \apply_filters( 'ngg_disable_shortcodes_in_request_api', true ) ) {
return $content;
}
\ob_start();
}
if ( \preg_match_all( "/{$regex}/m", $content, $matches, PREG_SET_ORDER ) ) {
foreach ( $matches as $match ) {
$placeholder = \array_shift( $match );
$id = \array_shift( $match );
$content = \str_replace( $placeholder, $this->execute_found_shortcode( $id ), $content );
}
}
if ( $this->is_rest_request() ) {
// Pre-generating displayed gallery cache by executing shortcodes in the REST API can prevent users
// from being able to add and save blocks with lots of images and no pagination (for example a very large
// basic slideshow or pro masonry / mosaic / tile display).
if ( \apply_filters( 'ngg_disable_shortcodes_in_request_api', false ) ) {
return $content;
}
\ob_start();
}
return $content;
}
public function render_legacy_shortcode( $params, $inner_content ) {
return Renderer::get_instance()->display_images( $params, $inner_content );
}
public function execute_found_shortcode( $found_id ) {
return isset( $this->_found[ $found_id ] )
? $this->render_shortcode(
$this->_found[ $found_id ]['shortcode'],
$this->_found[ $found_id ]['params'],
$this->_found[ $found_id ]['inner_content']
)
: 'Invalid shortcode';
}
/**
* Adds a shortcode
*
* @param $name
* @param $callback
* @param callable|null $transformer
*/
public function add_shortcode( $name, $callback, $transformer = null ) {
$this->_shortcodes[ $name ] = [
'callback' => $callback,
'transformer' => $transformer,
];
if ( $this->is_disabled() ) {
// Because render_shortcode() is a wrapper to several shortcodes it requires the $name parameter and can't be passed directly to add_shortcode()
add_shortcode(
$name,
function ( $params, $inner_content ) use ( $name ) {
return $this->render_shortcode( $name, $params, $inner_content );
}
);
} else {
\add_shortcode( $name, [ $this, $name . '____wrapper' ] );
}
}
/**
* Removes a shortcode
*
* @param $name
*/
public function remove_shortcode( $name ) {
unset( $this->_shortcodes[ $name ] );
$this->deactivate( $name );
}
/**
* De-activates a shortcode
*
* @param $shortcode
*/
public function deactivate( $shortcode ) {
if ( isset( $this->_shortcodes[ $shortcode ] ) ) {
\remove_shortcode( $shortcode );
}
}
public function is_rest_request() {
return \defined( 'REST_REQUEST' ) || \strpos( $_SERVER['REQUEST_URI'], 'wp-json' ) !== false;
}
public function __call( $method, $args ) {
$params = \array_shift( $args );
$inner_content = \array_shift( $args );
$parts = \explode( '____', $method );
$shortcode = \array_shift( $parts );
if ( \doing_filter( 'the_content' ) && ! \doing_filter( 'widget_text' ) ) {
$retval = $this->replace_with_placeholder( $shortcode, $params, $inner_content );
} else { // Widgets don't use placeholders.
return $this->render_shortcode( $shortcode, $params, $inner_content );
}
return $retval;
}
public function render_shortcode( $shortcode, $params = [], $inner_content = '' ) {
if ( isset( $this->_shortcodes[ $shortcode ] ) ) {
$shortcode = $this->_shortcodes[ $shortcode ];
if ( \is_callable( $shortcode['transformer'] ) ) {
$params = \call_user_func( $shortcode['transformer'], $params );
}
$method = ( \is_null( $shortcode['callback'] ) && \is_callable( $shortcode['transformer'] ) ) ? [ $this, 'render_legacy_shortcode' ] : $shortcode['callback'];
$retval = \call_user_func( $method, $params, $inner_content );
} else {
$retval = 'Invalid shortcode';
}
return $retval;
}
/**
* Prevents wptexturize
*
* @param $shortcode
* @param array $params
* @param string $inner_content
* @return mixed|void
*/
public function replace_with_placeholder( $shortcode, $params = [], $inner_content = '' ) {
$id = \count( $this->_found );
$this->_found[ $id ] = [
'shortcode' => $shortcode,
'params' => $params,
'inner_content' => $inner_content,
];
$placeholder = \sprintf( $this->_placeholder_text, $id );
return \apply_filters( 'ngg_shortcode_placeholder', $placeholder, $shortcode, $params, $inner_content );
}
/**
* @return string
*/
public function get_shortcode_regex() {
$keys = \array_keys( $this->_shortcodes );
return '/' . \get_shortcode_regex( $keys ) . '/';
}
}
Foto’s |