编码挑战--JavaScript复活节彩蛋

时间:2010-10-25 作者:EAMann

正如你们中的一些人所知Easter Egg 隐藏在WordPress后期修订系统中,该系统将显示电影中的消息The Matrix 如果你执行了一个特定的操作(如果你不知道,我不会破坏这个惊喜…四处查看修改后的内容,看看你是否能找到它)。我喜欢复活节彩蛋,当我偶然发现它时,这是一个令人激动的发现。

不过,有些人似乎不是真正的粉丝。我有一个客户最近发现这个复活节彩蛋陷入恐慌,因为他们认为有人入侵了他们的博客。他们吓坏了,我的收件箱里堆满了惊慌失措的信息,我的语音邮件配额也被“最大化”了;请帮忙&引用;消息。

这让我相信,当WordPress在某些情况下部署时,一些复活节彩蛋应该关闭,例如,对于高维护客户。输入我对WordPress首次回答代码挑战的想法。

本次挑战的获胜者将获得额外的150点声誉积分

我将选择;“最佳”;10月31日的回答基于:

答案的完整性(代码描述+示例代码+屏幕截图,如果适用)

  • 代码的简单性(但请记住,更短并不总是更好)
  • 关于如何在客户端站点上安装代码的完整描述,任何人只要复制粘贴我已经发布在WP黑客邮件列表上的解决方案,就会被自动取消资格。让游戏开始吧!

  • 3 个回复
    最合适的回答,由SO网友:Denis de Bernardy 整理而成

    下面的插件使用jQuery动态隐藏两个有问题的无线电,并终止版本自我比较。

    <?php
    # Plugin Name: Pest Control
    # Plugin URI: http://www.semiologic.com/
    # Description: Kills the Easter Bunny
    # Version: 1.0
    # Author: Denis de Bernardy
    # License: Public Domain
    
    class PestControl {
        public static function bootstrap() {
            add_action(\'admin_head-revision.php\', array(__CLASS__, \'mixomatosis\'));
            add_action(\'load-revision.php\', array(__CLASS__, \'plague\'));
        }
    
        public static function mixomatosis() {
            echo <<<EOD
    <script type="text/javascript">
    // <![CDATA[
    jQuery(document).ready(function($) {
        var mixomatosis = function() {
            var left = $(\':radio[name=left]:checked\').val(),
                right = $(\':radio[name=right]:checked\').val();
            $(\':radio[name=left], :radio[name=right]\').each(function() {
                var t = $(this);
                switch (true) {
                    case t.attr(\'name\') == \'left\' && t.attr(\'value\') == right:
                    case t.attr(\'name\') == \'right\' && t.attr(\'value\') == left:
                        t.css(\'display\', \'none\');
                        break;
                    default:
                        t.css(\'display\', \'\');
                }
            });
        };
    
        mixomatosis();
        $(\':radio[name=left], :radio[name=right]\').change(mixomatosis);
    });
    // ]]>
    </script>
    EOD;
        }
    
        public static function plague() {
            if ($_GET[\'action\'] == \'diff\' && $_GET[\'left\'] == $_GET[\'right\']) {
                wp_die("Can\'t compare a revision with itself.");
            }
        }
    }
    
    PestControl::bootstrap();
    ?>
    

    SO网友:Jan Fabry

    我的解决方案有两种工作方式:通过修改the list-revisions Javascript file, 如果通过某种方式选择了两个相同的修订版本,它会提供一条真正的错误消息。

    此屏幕截图为您提供了错误消息的快速概述,以及新Javascript的效果。如您所见,不再可能选择同一修订两次。如果你想看到效果,你要么禁用Javascript(注释掉add_action((\'wp_default_scripts\', ... 行)或手动更改URL。

    Comparison of the old and new revision screens

    它是作为插件编写的。对于多站点安装,您可以将其放入mu-plugins, 并让初始化依赖于数据库配置选项。这样,您可以为不同的客户端启用或禁用它。

    欢迎对我的插件编写风格发表评论,我尝试将代码分为三个逻辑块

    主插件文件。此文件切换list-revisions 具有“更安全”版本的Javascript文件,可防止两次选择同一版本。它还检查admin_action_diff 如果两个修订版本相等,则返回带有错误消息的自有页面的操作和快捷方式。新页面已写入ui-identical.php 分离代码和布局。

    <?php
    /*
    Plugin Name: Myxomatosis
    Plugin URI: http://www.monkeyman.be/
    Description: Kill the Easter Bunny and his eggs!
    Version: 1.0
    Author: Jan Fabry
    */
    
    class Myxomatosis
    {
        function __construct()
        {
            add_action(\'admin_action_diff\', array(&$this, \'checkEqualDiff\'));
            add_action(\'wp_default_scripts\', array(&$this, \'loadSafeListRevisions\'), 20);
        }
    
        function checkEqualDiff()
        {
            global $left, $right;
            if (!array_key_exists(\'left\', $_REQUEST) || !array_key_exists(\'right\', $_REQUEST)) {
                return;
            }
            $left = absint($_REQUEST[\'left\']);
            $right = absint($_REQUEST[\'right\']);
    
            if (!$left || !$right || $left != $right) {
                // Nothing wrong, they are not equal
                return;
            }
    
            // They are equal. Set up globals so UI can be included
            // Which globals do I need here?
            global $title, $hook_suffix, $pagenow, $is_iphone, $current_screen, $user_identity, $post, $wp_locale;
    
            $post = get_post($left);
            if ($post->post_parent) {
                $post = get_post($post->post_parent);
            }
    
            require_once(plugin_dir_path(__FILE__) . \'ui-identical.php\');
            exit();
        }
    
        function loadSafeListRevisions(&$scripts)
        {
            $scripts->remove(\'list-revisions\');
            $scripts->add(\'list-revisions\', plugin_dir_url(__FILE__) . \'safe-list-revisions.dev.js\', null, \'20101026\' );
        }
    }
    
    $myxomatosis_instance = new Myxomatosis();
    
    文件ui-identical.php, 在插件目录中。这将创建一个页面,显示两个修订是否相同。将再次显示修订列表。

    <?php
    wp_enqueue_script(\'list-revisions\');
    
    $post_title = \'<a href="\' . get_edit_post_link() . \'">\' . get_the_title() . \'</a>\';
    $h2 = sprintf( __( \'Compare Revisions of &#8220;%1$s&#8221;\' ), $post_title );
    $title = __( \'Revisions\' );
    
    require_once(ABSPATH . \'/wp-admin/admin-header.php\');
    ?>
    <div class="wrap">
        <h2 class="long-header"><?php echo $h2; ?></h2>
    
        <div class="error"><p><?php _e( \'You selected two identical revisions\' ); ?></p></div>
    
    <h2><?php echo $title; ?></h2>
    
    <?php
    
    $args = array( \'format\' => \'form-table\', \'parent\' => true, \'right\' => $right, \'left\' => $left );
    if ( ! WP_POST_REVISIONS || !post_type_supports($post->post_type, \'revisions\') )
        $args[\'type\'] = \'autosave\';
    
    wp_list_post_revisions( $post, $args );
    ?>
    
    </div>
    <?php
    require_once(ABSPATH . \'/wp-admin/admin-footer.php\');
    
    文件safe-list-revisions.dev.js, 在插件目录中。逻辑分为两个循环:一个用于读取当前选中的按钮,另一个用于隐藏和显示其他按钮。这可能比原始版本更简单,并且允许在中间进行一些调整。

    (function(w) {
        var init = function() {
            var pr = document.getElementById(\'post-revisions\'),
            var inputs = pr ? pr.getElementsByTagName(\'input\') : [];
            if (inputs.length <= 2) {
                // Sanity check: if there is only one revision, hide nothing
                // Not that we should get here...
                return;
            }
            // For simplicity, only one click handler is registered on the whole #post-revisions table
            pr.onclick = function() {
                var i, checkCount = 0, side;
                var checkedIdx = {};
                for (i = 0; i < inputs.length; i++) {
                    if (inputs[i].checked) {
                        side = inputs[i].getAttribute(\'name\');
                        checkedIdx[side] = i;
                    }
                }
                if (checkedIdx[\'left\'] + 1 == checkedIdx[\'right\']) {
                    // The same revisions are checked
                    // Move left down (or right up, if left is at the bottom)
                    // There should always be at least two revisions (see sanity check above)
                    if (checkedIdx[\'left\'] + 2 < inputs.length) {
                        checkedIdx[\'left\'] += 2;
                        inputs[checkedIdx[\'left\']].checked = true;
                    } else {
                        checkedIdx[\'right\'] -= 2;
                        inputs[checkedIdx[\'right\']].checked = true;
                    }
                }
                if (checkedIdx[\'left\'] < checkedIdx[\'right\']) {
                    // \'Old\' is newer than \'New\', so switch them
                    // We sometimes get this - don\'t know why
                    var origLeft = checkedIdx[\'left\'];
                    checkedIdx[\'left\'] = checkedIdx[\'right\'] - 1;
                    checkedIdx[\'right\'] = origLeft + 1;
    
                    inputs[checkedIdx[\'left\']].checked = true;
                    inputs[checkedIdx[\'right\']].checked = true;
                }
                // Loop again, hide what we should not see
                // \'left\' buttons should be hidden until we see a checked \'right\' button
                // \'right\' buttons should be visible until we see a checked \'left\' button
                for (i = 0; i < inputs.length; i++) {
                    side = inputs[i].getAttribute(\'name\');
                    if (\'left\' == side) {
                        inputs[i].style.visibility = (i < checkedIdx[\'right\'] ? \'hidden\' : \'visible\');
                    } else if (\'right\' == side) {
                        inputs[i].style.visibility = (checkedIdx[\'left\'] < i ? \'hidden\' : \'visible\');
                    }
                }
            }
            pr.onclick();
        }
        if ( w && w.addEventListener )
            w.addEventListener(\'load\', init, false);
        else if ( w && w.attachEvent )
            w.attachEvent(\'onload\', init);
    })(window);
    

    SO网友:Rarst

    我很欣赏代码如何以一种模糊和僵化的方式将复活节彩蛋包括在内(

    我在管理方面很差劲,所以下面是我的代码,它在我脑海中产生了比回答更多的问题:

    add_filter( \'get_edit_post_link\', \'hijack_revision_easter_egg\' );
    
    function hijack_revision_easter_egg( $input ) {
    
        global $action, $left, $right;
    
    
        if( \'diff\' != $action )
        return $input;
    
        if( $left == $right ) {
    
        $revision = wp_get_post_revision( $left );
    
        if( $revision->post_parent )
            wp_redirect ( site_url( "/wp-admin/revision.php?revision={$left}&action=view" ) );
        else
            wp_redirect( str_replace( \'amp;\', \'\', $input ) );
    
        exit;
        }
    
        return $input;
    }
    
    不知道为什么编码的符号会中断重定向。。。不知道admin_action_ 这应该真正使用的钩子,而不是杂乱无章地钩住无害的get_edit_post_link...

    我试图重定向到修订视图,但对于最新版本,这似乎不可能。

    结束

    相关推荐

    How do you debug plugins?

    我对插件创作还很陌生,调试也很困难。我用了很多echo,它又脏又丑。我确信有更好的方法可以做到这一点,也许是一个带有调试器的IDE,我可以在其中运行整个站点,包括插件?