当两个插件使用相同的库时,如何避免管理帖子屏幕重复

时间:2019-08-28 作者:Jonathan Stegall

我有两个使用WP Logging 班它创建了一个名为Logs的自定义post类型,该类型(至少在我的情况下)仅在admin中可见,例如在/wp admin/edit中。php?s&;post\\u状态=全部(&U);post\\U类型=wp\\U日志。

为了更容易判断哪个插件正在创建日志,我添加了几个挂钩。两个插件使用它们的方式相同。他们所做的是:

将可排序类型列添加到管理帖子屏幕,并将类型字段(WP日志库添加)添加到该屏幕以下是我使用的代码:

// add a sortable Type column to the posts admin
add_filter( \'manage_edit-wp_log_columns\', array( $this, \'type_column\' ), 10, 1 );
add_filter( \'manage_edit-wp_log_sortable_columns\', array( $this, \'sortable_columns\' ), 10, 1 );
add_action( \'manage_wp_log_posts_custom_column\', array( $this, \'type_column_content\' ), 10, 2 );

// filter the log posts admin by log type
add_filter( \'parse_query\', array( $this, \'posts_filter\' ), 10, 1 );
add_action( \'restrict_manage_posts\', array( $this, \'restrict_log_posts\' ) );

/**
 * Add a Type column to the posts admin for this post type
 *
 * @param array $columns
 * @return array $columns
 */
public function type_column( $columns ) {
    $columns[\'type\'] = __( \'Type\', \'form-processor-mailchimp\' );
    return $columns;
}

/**
 * Make the Type column in the posts admin for this post type sortable
 *
 * @param array $columns
 * @return array $columns
 */
public function sortable_columns( $columns ) {
    $columns[\'type\'] = \'type\';
    return $columns;
}

/**
 * Add the content for the Type column in the posts admin for this post type
 *
 * @param string $column_name
 * @param int $post_id
 */
public function type_column_content( $column_name, $post_id ) {
    if ( \'type\' != $column_name ) {
        return;
    }
    // get wp_log_type
    $terms = wp_get_post_terms(
        $post_id,
        \'wp_log_type\',
        array(
            \'fields\' => \'names\',
        )
    );
    if ( is_array( $terms ) ) {
        echo esc_attr( $terms[0] );
    }
}

/**
 * Filter log posts by the taxonomy from the dropdown when a value is present
 *
 * @param object $query
 * @return object $query
 */
public function posts_filter( $query ) {
    global $pagenow;
    $type     = \'wp_log\';
    $taxonomy = \'wp_log_type\';
    if ( is_admin() && \'edit.php\' === $pagenow ) {
        if ( isset( $_GET[\'post_type\'] ) && esc_attr( $_GET[\'post_type\'] ) === $type ) {
            if ( isset( $_GET[ $taxonomy ] ) && \'\' !== $_GET[ $taxonomy ] ) {
                $query->post_type = $type;
                $query->tax_query = array(
                    array(
                        \'taxonomy\' => $taxonomy,
                        \'field\'    => \'slug\',
                        \'terms\'    => esc_attr( $_GET[ $taxonomy ] ),
                    ),
                );
            }
        }
    }
}

/**
 * Add a filter form for the log admin so we can filter by wp_log_type taxonomy values
 *
 * @param object $query
 * @return object $query
 */
public function restrict_log_posts() {
    $type     = \'wp_log\';
    $taxonomy = \'wp_log_type\';
    // only add filter to post type you want
    if ( isset( $_GET[\'post_type\'] ) && esc_attr( $_GET[\'post_type\'] ) === $type ) {
        // get wp_log_type
        $terms = get_terms(
            [
                \'taxonomy\'   => $taxonomy,
                \'hide_empty\' => true,
            ]
        );
        ?>
        <select name="wp_log_type">
            <option value=""><?php _e( \'All log types \', \'form-processor-mailchimp\' ); ?></option>
            <?php
            $current_log_type = isset( $_GET[ $taxonomy ] ) ? esc_attr( $_GET[ $taxonomy ] ) : \'\';
            foreach ( $terms as $key => $term ) {
                printf(
                    \'<option value="%s"%s>%s</option>\',
                    $term->slug,
                    $term->slug == $current_log_type ? \' selected="selected"\' : \'\',
                    $term->name
                );
            }
            ?>
        </select>
        <?php
    }
}
在这种情况下,两个插件之间的代码是相同的。当然,如果在两个插件中都启用了它,问题是它会复制显示。

posts manage screen with two identical type dropdowns, and the type displayed twice in the column

在制作之前,我有没有办法检查一下是否已经添加了这些内容?

我认为这值得一试(在所有的过滤器上,使用doing_action 在所有操作上):

if ( ! doing_filter( \'manage_edit-wp_log_columns\' ) ) {
    add_filter( \'manage_edit-wp_log_columns\', array( $this, \'type_column\' ), 10, 1 );
}
但这并没有改变任何事情。还有什么我可以试穿的吗?

2 个回复
最合适的回答,由SO网友:Tom J Nowell 整理而成

在代码中,添加如下过滤器:

add_action( \'restrict_manage_posts\', array( $this, \'restrict_log_posts\' ) );
它添加了一个如下开头的函数:

public function restrict_log_posts() {
    $type     = \'wp_log\';
    $taxonomy = \'wp_log_type\';
    // only add filter to post type you want
    if ( isset( $_GET[\'post_type\'] ) && esc_attr( $_GET[\'post_type\'] ) === $type ) {
        // get wp_log_type
        $terms = get_terms(
首先,此操作传递post类型,以便通过调整add_action 并使用它传递的第一个参数:

public function restrict_log_posts( $post_type ) {
    $type     = \'wp_log\';
    $taxonomy = \'wp_log_type\';
    // only add filter to post type you want
    if ( \'wp_log\' === $post_type ) {
        // get wp_log_type
        $terms = get_terms(
那么我们可以使用did_action 要仅在第一次运行它,请执行以下操作:

public function restrict_log_posts( $post_type ) {
    if ( did_action( \'restrict_manage_posts\' ) ) {
        return;
    }
....
但这可能没有预期的效果,而且很粗糙。相反,这个动作根本不属于这个类,应该是一个独立的动作。然后,我们只能在尚未定义函数的情况下定义该函数:


if ( !function_exists(\'restrict_logs_by_type\') ) {
    add_action( \'restrict_manage_posts\', \'restrict_logs_by_type\', 10, 1 );
    /**
     * Add a filter form for the log admin so we can filter by wp_log_type taxonomy values
     *
     */
    function restrict_logs_by_type( $post_type ) {
        $type     = \'wp_log\';
        $taxonomy = \'wp_log_type\';
        // only add filter to post type you want
        if ( $type !== $post_type ) {
            return;
        }
        // get wp_log_type
        $terms = get_terms([
                \'taxonomy\'   => $taxonomy,
                \'hide_empty\' => true,
        ]);
        if ( is_wp_error( $terms ) || empty( $terms ) ) {
            // no terms, or the taxonomy doesn\'t exist, skip
            return;
        }

        ?>
        <select name="wp_log_type">
            <option value=""><?php esc_html_e( \'All log types \', \'form-processor-mailchimp\' ); ?></option>
            <?php
            $current_log_type = isset( $_GET[ $taxonomy ] ) ? esc_attr( $_GET[ $taxonomy ] ) : \'\';
            foreach ( $terms as $key => $term ) {
                printf(
                    \'<option value="%s"%s>%s</option>\',
                    esc_attr( $term->slug ),
                    selected( $term->slug, $current_log_type, false ),
                    esc_html( $term->name )
                );
            }
            ?>
        </select>
        <?php
    }
}

注意,我做了一些significant 改进:

我修复了一个主要的安全漏洞,在选项标记中添加了转义selected WP提供的功能我将if检查替换为!==, 让它成为一个守卫。现在,整个函数可以不包含1,并且可读性更强。此外,圈复杂度和NPath复杂度都已降低。该函数现在是独立的,不需要它成为对象或类的一部分。我重命名了该函数以描述它的功能。如果未找到术语,或分类法不存在,此版本将跳过显示下拉列表。如果唯一的项目是“全部”,则没有下拉列表的意义。如果没有这一点,如果没有日志类型或条目,日志屏幕就会崩溃。整个代码段都包装在function_exists 调用,如果函数是由第一个插件加载的,那么第二个插件将不会费心定义和添加它

SO网友:Jonathan Stegall

现在我一直在研究它,我想到了一个可能的解决方案。

// add a filter to check for other plugins that might be filtering the log screen
$are_logs_filtered = apply_filters( \'wp_logging_manage_logs_filtered\', false );
add_filter( \'wp_logging_manage_logs_filtered\', \'__return_true\' );

if ( false === $are_logs_filtered ) {
    // add a sortable Type column to the posts admin
    add_filter( \'manage_edit-wp_log_columns\', array( $this, \'type_column\' ), 10, 1 );
    add_filter( \'manage_edit-wp_log_sortable_columns\', array( $this, \'sortable_columns\' ), 10, 1 );
    add_action( \'manage_wp_log_posts_custom_column\', array( $this, \'type_column_content\' ), 10, 2 );

    // filter the log posts admin by log type
    add_filter( \'parse_query\', array( $this, \'posts_filter\' ), 10, 1 );
    add_action( \'restrict_manage_posts\', array( $this, \'restrict_log_posts\' ) );
}
添加wp_logging_manage_logs_filtered 对于这两个插件,如果在这两个插件上都将其值设置为true,则会导致筛选字段、排序列和列中的内容都只发生一次。

我倾向于认为这是最好的做法,但当然我可能会错过一些东西。

相关推荐

/wp-admin/工作,但网站未加载

我对主题做了一些小的代码更改,只是更改了其中一个模板中的HTML,我的网站停止了工作。我收到“此页面不工作”HTTP错误500,但只有当我访问该网站时,wp admin才能正常工作。以下是我迄今为止所做的尝试,但没有任何效果:1。禁用所有插件2。从WP config打开WP\\U DEBUG和WP\\U DEBUG\\U LOG。php-我没有收到任何错误3。将内存限制增加到512M你知道我还能尝试什么吗?