如何在短代码中包含其他插件的css文件?

时间:2016-05-17 作者:Lucio Crusca

我编写了一个插件,可以创建一个短代码,以及其他东西。该短代码需要一个post\\u id参数,它提取该帖子的内容,并返回该帖子的过滤内容(例如,它应用所有过滤器,以便完成该内容中的任何其他短代码)。以下是代码的精简版本:

public static function myshortcode($atts = null, $content = "")
{
  global $wp_filter, $merged_filters, $wp_current_filter, $post;

  if (is_array($atts))
    extract($atts, EXTR_OVERWRITE);

  $save_wp_filter = $wp_filter;
  $save_merged_filters = $merged_filters;
  $save_wp_current_filter = $wp_current_filter;
  $post = get_post($post_id);
  setup_postdata($post);
  $content = $post->post_content;
  $content = apply_filters(\'the_content\', $content);        
  $content = str_replace(\']]>\', \']]>\', $content);
  $wp_filter = $save_wp_filter;
  $merged_filters = $save_merged_filters;
  $wp_current_filter = $save_wp_current_filter;

  return $content;
}
除了其他插件短代码无法包含自己的CSS文件(例如,Visual Composer的Ultimate插件有自己的CSS文件要包含,但以这种方式调用时不包含它们)之外,所有这些都很好。我怀疑问题是,当WP为我的短代码执行“the\\u content”钩子(不是我显式调用的钩子,而是WP自己首先调用的钩子,它会导致我的短代码执行)时,在页面中包含CSS文件已经太晚了(例如,<;head>;标记已经关闭),此时Wordpress,有机会只将CSS文件包含到它认为页面需要的插件中(例如,只包含我的插件,因为页面最初只包含我的短代码)。

我可以使用wp\\u enqueue\\u样式显式添加所需的第三方CSS文件,但问题是我想以可移植的方式将它们包括在内。今天的问题是VC的终极插件,明天将是内容蛋或其他东西。最好的解决方案是调用WP的函数,该函数决定页面所需的插件是什么,并调用它们,在执行我的短代码后,将页面的实际内容传递给该函数,而不是在执行我的短代码之前页面的内容。

是否存在此类WP功能?

编辑:

对于评论后的澄清,是的,我的短代码类似于[embed\\u page id=“123”],但我需要它,例如在页面中使用[embed\\u post id=“123”]。没有循环的风险,因为它只用于将帖子嵌入页面,而不用于帖子。最后,是的,嵌入的内容确实包括其他第三方短代码,这些短代码应该自动将它们自己的CSS、JS等放入队列。

在收到答案后编辑:

简而言之,答案是否定的,Wordpress中不存在这样的功能。下面是详细的答案。我想奖励@majick和@cjbj,因为他们给出了广泛而详细的答案,但我必须选择一个。。。

3 个回复
最合适的回答,由SO网友:majick 整理而成

我认为您可以通过在输出标题之前应用内容过滤器来预先运行页面上的短代码来解决这个问题。这应该允许在包含的帖子中运行任何内部短代码,以正确添加任何操作挂钩,从而添加任何所需的样式表/资源。

add_action(\'wp_loaded\',\'maybe_prerun_shortcodes\');
function maybe_prerun_shortcodes() {
    if (is_page()) {
        global $post; 
        if (has_shortcode($post->post_content,\'embed_post\')) {
            $content = apply_filters(\'the_content\',$post->post_content);
        }
    }
}
EDIT 上述操作只会将在嵌入式post中的任何短代码调用中排队的样式表和资源排队(虽然这是更好的做法,但实际上并不经常这样做)它应该适用于这些情况,因为将过滤器应用于当前页面内容将运行嵌入的短代码,然后将过滤器应用于嵌入的帖子(在您现有的函数中)

然而,要获取特定帖子的样式表,您必须获取该特定帖子(这就是为什么iframe方法可以工作的原因,考虑到已经讨论过的问题)

在这种情况下,我建议的解决方法是在加载帖子时存储帖子上加载的样式资源。。。

add_filter(\'style_loader_tag\',\'custom_store_style_tags\',11,2)
function custom_store_style_tags($tag,$handle) {
    global $styletags; $styletags[$handle] = $tag;}
}

add_action(\'wp_footer\',\'custom_save_style_tags\');
function custom_save_style_tags() {
    global $embedstyles;
    if (is_single()) {
        global $styletags, $post; 
        update_post_meta($post->ID,\'styletags\',$styletags);
    } elseif (is_array($embedstyles)) {
        global $styletags;
        foreach ($embedstyles as $handle => $tag) {
            if (!array_key_exists($handle,$styletags)) {echo $tag;}
        }
    }
}
然后,您可以使用快捷码检索要检索的样式标记,上述函数的第二部分将在页脚中输出它们:

public static function myshortcode($atts = null, $content = "")
{
  // EXISTING CODE SNIPPED

  global $embedstyles;
  $embedstyle = get_post_meta($post_id,\'styletags\',true);
  if (is_array($embedstyle)) {
      if (!is_array($embedstyles)) {$embedstyles = array();}
      $embedstyles = array_merge($embedstyle,$embedstyles);
  }

  return $content;
}
您也可以通过script_loader_tag 过滤并简单地更改变量以匹配。。。

当然,仍然有一些可能性body 类可能不是@cjbj所提到的样式的目标。。。或者,一些脚本可能会在页脚中初始化,即使它们已正确排队。

。。。而且它还没有考虑到页面上打印(未排队)的内联样式/脚本。。。但这是一个好的开始。。。取决于你想走多远。

SO网友:cjbj

这可能是一个愚蠢的想法,但可能会奏效:

1让您的短代码爆炸为iframe 带有自定义query_var (tutorial). 像这样:

<iframe src="http://www.example.com/?p=123&my_query_var=content_only"></iframe>
在您的single.php 检测query_var 在这种情况下,跳过视觉页眉、侧边栏和页脚-任何与帖子内容本身无关的内容。

通过这种方式,您可以以通常的方式加载帖子,并避免其他短代码没有完全完成它们应该做的事情的所有问题。

编辑-评论后澄清

这种方法背后的理念是,您不知道第三方插件做什么,甚至可能独立于短代码执行。因此,如果您试图捕捉短代码的功能,您可能仍然会错过一些东西。例如,短代码可能导致生成html 以及包括css 文件,但该插件还可能添加body_class 在此基础上css 视情况而定。没有办法知道。因此,为了确保外部插件/短代码的行为符合预期,最好的方法是让WP加载整个页面。因此iframe.

现在,这就给您带来了一个问题,即您将获得一个完整的页面,包括标题、菜单、侧栏等等。因此,您需要一个只运行the_title()the_content() 也许还有其他部分。在某种程度上,你必须告诉WP你不想这样。WP必须知道是否应该生成正常single.php 或者是赤裸裸的。这就是query_var 进来了。通过将其添加到在短代码中生成的url中,您可以向WP提供一个线索,表明这不是对single.php. 这仍然相对容易,因为您可以设置自定义query_var 只需要几行代码。

如果你想在插件中使用你的短代码,事情就会变得复杂,因为那时你也不知道主题是做什么的。你必须推翻主题,插入你的赤裸裸的骨头single.php. 因为你不知道主题是如何构建的,所以你无法确定帖子的格式是否与主题中的格式相同。你也可以让你的插件分析single.php 并删除不需要的元素,但这是一种猜测。也可能有自定义模板,如single-custompage.php. 因此,如果您遵循此路径,最好包含一个选项页面,允许用户设置页面中包含的帖子样式。

SO网友:Nefro

加载visual compose css

function get_visual_composer_style($id) {
    return \'<style>\' . get_post_meta( $id, \'_wpb_shortcodes_custom_css\', true  ) .                 \'</style>\';
}
基于快捷码加载css

function custom_shortcode_scripts() {
    global $post;
    if( is_a( $post, \'WP_Post\' ) && has_shortcode( $post->post_content, \'custom-shortcode\') ) {
       wp_enqueue_script( \'custom-script\');
    }
}
add_action( \'wp_enqueue_scripts\', \'custom_shortcode_scripts\');