Plugin Directory

Changeset 2189055


Ignore:
Timestamp:
11/09/2019 11:04:22 PM (6 years ago)
Author:
Magenta Cuda
Message:

version 1.2

Location:
shortcode-tester/trunk
Files:
1 added
4 edited

Legend:

Unmodified
Added
Removed
  • shortcode-tester/trunk/js/mf2tk_macros_admin.js

    r1524954 r2189055  
    1414    });
    1515    // "Shortcode Tester" evaluate button
    16     divShortcode.find("button#mf2tk-shortcode-tester-evaluate,button#mf2tk-shortcode-tester-evaluate-and-prettify").click(function(){
     16    divShortcode.find("button#mf2tk-shortcode-tester-evaluate,button#mf2tk-shortcode-tester-evaluate-and-prettify,button#mf2tk-shortcode-tester-show-rendered")
     17            .click(function(){
    1718        var permalink=jQuery("#sample-permalink a");
    1819        if(!permalink.length){
    19             window.alert("Error: Permalink not found. Please report this to the developer.");
     20            // Gutenberg
     21            permalink=jQuery("#wp-admin-bar-view a");
     22            if(!permalink.length){
     23                window.alert("Error: Permalink not found. Please report this to the developer.");
     24                return;
     25            }
     26        }
     27        var button=jQuery("button#sct_ix-shortcode-tester");
     28        var nonce;
     29        if(button.length){
     30            nonce=button[0].dataset.nonce;
     31        }else{
     32            // Gutenberg
     33            nonce=mf2tk_macros_admin.shortcode_tester_nonce;
     34        }
     35        var url=permalink[0].href;
     36        var source=jQuery("div#mf2tk-shortcode-tester div#mf2tk-shortcode-tester-area-source textarea").val();
     37        if(this.id==="mf2tk-shortcode-tester-show-rendered"){
     38            var width=640;
     39            var height=480;
     40            var left=window.screen.width/2-width/2;
     41            var top=window.screen.height/2-height/2;
     42            var features="left="+left+",top="+top+",width="+width+",height="+height+",location=0,resizable,scrollbars,menubar=0";
     43            url+="?mc-sct=tpcti_html_eval_post_content&post_content="+encodeURI(source);
     44            window.open(url,"mc-sct-rendered",features);
    2045            return;
    2146        }
    22         var url=permalink[0].href+"?mc-sct=tpcti_eval_post_content"
    2347        var prettify=this.id==="mf2tk-shortcode-tester-evaluate-and-prettify";
    2448        var post_id=jQuery("form#post input#post_ID[type='hidden']").val();
    25         var source=jQuery("div#mf2tk-shortcode-tester div#mf2tk-shortcode-tester-area-source textarea").val();
    26         var button=jQuery("button#sct_ix-shortcode-tester")[0];
     49        url+="?mc-sct=tpcti_eval_post_content";
    2750        jQuery("div#mf2tk-shortcode-tester div#mf2tk-shortcode-tester-area-result textarea").val("Evaluating..., please wait...");
    2851        // Use AJAX to request the server to evaluate the post content fragment
    29         jQuery.post(url,{action:'tpcti_eval_post_content',post_id:post_id,post_content:source,prettify:prettify,nonce:button.dataset.nonce},function(r){
     52        // N.B. - This is not the usual WordPress .../wp-admin/adim-ajax.php AJAX request. The shortcode must be
     53        // evaluated in the context of the web page so this AJAX request is a request for the web page with additional
     54        // query parameters. These query parameters will cause a template redirect to code which will evaluate the
     55        // shortcode in the context of the web page instead of rendering the web page.
     56        jQuery.post(url,{action:'tpcti_eval_post_content',post_id:post_id,post_content:source,prettify:prettify,nonce:nonce},function(r){
    3057            jQuery("div#mf2tk-shortcode-tester div#mf2tk-shortcode-tester-area-result textarea").val(r);
    3158        });
     
    5279    });
    5380    // wire up the "Shortcode Tester" button
    54     jQuery("button#sct_ix-shortcode-tester").click(function(){
     81    function showShortcodeTester(){
    5582        divShortcode.find("button#mf2tk-shortcode-tester-show-both").prop("disabled",true);
    5683        divShortcode.find("button#mf2tk-shortcode-tester-show-source,button#mf2tk-shortcode-tester-show-result").prop("disabled",false);
     
    6087        divPopupOuter.show();
    6188        divShortcode.show();
    62     });
     89    }
     90    var shortcodeTesterButton=jQuery("button#sct_ix-shortcode-tester");
     91    if(shortcodeTesterButton.length){
     92        shortcodeTesterButton.click(showShortcodeTester);
     93    }else{
     94        // Gutenberg
     95        var count=0;
     96        window.setTimeout(function addShortcodeTesterButton(){
     97            var toolbar=jQuery(".edit-post-header-toolbar");
     98            if(toolbar.length){
     99                toolbar.append('<button type="button" aria-label="Test Shortcode" aria-disabled="false" class="components-button components-icon-button sct_ix-shortcode-tester"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"><path d="M8.58 2.39c.32 0 .59.05.81.14 1.25.55 1.69 2.24 1.7 3.97.59-.82 2.15-2.29 3.41-2.29s2.94.73 3.53 3.55c-1.13-.65-2.42-.94-3.65-.94-1.26 0-2.45.32-3.29.89.4-.11.86-.16 1.33-.16 1.39 0 2.9.45 3.4 1.31.68 1.16.47 3.38-.76 4.14-.14-2.1-1.69-4.12-3.47-4.12-.44 0-.88.12-1.33.38C8 10.62 7 14.56 7 19H2c0-5.53 4.21-9.65 7.68-10.79-.56-.09-1.17-.15-1.82-.15C6.1 8.06 4.05 8.5 2 10c.76-2.96 2.78-4.1 4.69-4.1 1.25 0 2.45.5 3.2 1.29-.66-2.24-2.49-2.86-4.08-2.86-.8 0-1.55.16-2.05.35.91-1.29 3.31-2.29 4.82-2.29zM13 11.5c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5.67 1.5 1.5 1.5 1.5-.67 1.5-1.5z"/></svg></button>')
     100                    .find(".sct_ix-shortcode-tester").click(showShortcodeTester).hover(
     101                        function(e){
     102                            // Show tooltip
     103                            var target=jQuery(e.currentTarget);
     104                            var offset=target.offset();
     105                            var tooltip=jQuery(".sct_ix-shortcode_tester_tooltip");
     106                            var style=tooltip[0].style;
     107                            style.left=(offset.left+target.outerWidth()/2)+"px";
     108                            style.top=(offset.top+target.outerHeight()-8)+"px";
     109                            tooltip.show();
     110                        },
     111                        function(e){
     112                            // Hide tooltip
     113                            jQuery(".sct_ix-shortcode_tester_tooltip").hide();
     114                        }
     115                    );
     116            }else{
     117                if(++count<8){
     118                    window.setTimeout(addShortcodeTesterButton,250);
     119                }
     120            }
     121        },250);
     122    }
    63123});
  • shortcode-tester/trunk/readme.txt

    r1524954 r2189055  
    44Tags: shortcode, tool, tester
    55Requires at least: 3.6
    6 Tested up to: 4.6
    7 Stable tag: 1.1.1.1
     6Tested up to: 5.2.4
     7Stable tag: 1.2
    88License: GPLv2 or later
    99License URI: http://www.gnu.org/licenses/gpl-2.0.html
     
    1111
    1212== Description ==
    13 The [Shortcode Tester](https://shortcodetester.wordpress.com/) is a post editor tool for WordPress developers that displays in a popup window the HTML generated by WordPress shortcodes,
     13The Shortcode Tester is a post editor tool for WordPress developers that displays in a popup window the HTML generated by WordPress shortcodes,
    1414i.e. so you can quickly view the generated HTML without having to view the entire post.
    15 Please visit [https://shortcodetester.wordpress.com/](https://shortcodetester.wordpress.com/) for a very quick introduction.
     15Please visit [https://github.com/magenta-cuda/shortcode-tester/blob/master/README.md](https://github.com/magenta-cuda/shortcode-tester/blob/master/README.md) for a very quick introduction.
    1616**This plugin requires at least PHP 5.4.**
    1717
     
    19191. Download the plugin from the WordPress repository.
    20202. Open the 'Plugins' menu item and activate the plugin.
    21 3. Read the tutorial at [https://shortcodetester.wordpress.com/](https://shortcodetester.wordpress.com/).
     213. Read the tutorial at [https://github.com/magenta-cuda/shortcode-tester/blob/master/README.md](https://github.com/magenta-cuda/shortcode-tester/blob/master/README.md).
    2222
    2323== Frequently Asked Questions ==
     
    2727
    2828== Changelog ==
     29
     30= 1.2 =
     31* add support for Gutenberg
    2932
    3033= 1.1.1.1 =
     
    4952== Upgrade Notice ==
    5053
     54= 1.2 =
     55* add support for Gutenberg
     56
    5157= 1.1.1.1 =
    5258* fix major bug where shortcode evaluation was wrong if it was dependent on is_admin() === false
  • shortcode-tester/trunk/shortcode-tester-loader.php

    r1524954 r2189055  
    33/*
    44Plugin Name: Shortcode Tester
    5 Plugin URI:  http://shortcodetester.wordpress.com/
     5Plugin URI:  https://github.com/magenta-cuda/shortcode-tester
    66Description: a simple shortcode tester
    7 Version:     1.1.1.1
     7Version:     1.2
    88Author:      Magenta Cuda
    9 Author URI:  https://profiles.wordpress.org/magenta-cuda/
     9Author URI:  https://github.com/magenta-cuda
    1010License:     GPL2
    1111*/
  • shortcode-tester/trunk/shortcode-tester.php

    r1524954 r2189055  
    3434namespace mc_shortcode_tester {
    3535       
     36    require_once( 'parse-functions.php' );
     37
     38    define( 'START_OF_BODY',    '<!-- ##### ACTION:wp_body_open -->' );
     39    define( 'START_OF_CONTENT', '<!-- ##### FILTER:the_content -->' );   # This is the mark.
     40    define( 'START_OF_SIDEBAR', '<!-- ##### ACTION:get_sidebar -->' );
     41    define( 'START_OF_FOOTER',  '<!-- ##### ACTION:get_footer -->' );
     42
    3643    $construct = function( ) {
    3744
     
    95102                    wp_enqueue_style(  'mf2tk_macros_admin', plugins_url( 'css/mf2tk_macros_admin.css', __FILE__ ) );
    96103                    wp_enqueue_script( 'mf2tk_macros_admin', plugins_url(  'js/mf2tk_macros_admin.js',  __FILE__ ), [ 'jquery' ] );
     104                    wp_localize_script( 'mf2tk_macros_admin', 'mf2tk_macros_admin', [
     105                        'shortcode_tester_nonce' => wp_create_nonce( 'sct_ix-shortcode_tester_nonce' )
     106                    ] );
    97107                } );
    98108
     
    118128        <button id="mf2tk-shortcode-tester-show-result" class="mf2tk-shortcode-tester-button">Show Result Only</button>
    119129        <button id="mf2tk-shortcode-tester-show-both" class="mf2tk-shortcode-tester-button">Show Both</button>
     130        <button id="mf2tk-shortcode-tester-show-rendered" class="mf2tk-shortcode-tester-button">Show Rendered</button>
    120131    </div>
    121132    <div class="sct_ix-shortcode_tester_input_output">
     
    134145    </div>
    135146</div>
     147<!-- for the tooltip use the same classes as React uses for its tooltips -->
     148<div class="components-popover components-tooltip is-bottom is-center sct_ix-shortcode_tester_tooltip" style="display:none;">
     149    <div class="components-popover__content">Shortcode Tester</div>
     150</div>
    136151<!-- end shortcode tester -->
    137152<?php
     
    151166    };   # $construct = function( ) {
    152167
     168    # hide_html_elements() hides top level HTML elements if the HTML element does not contain the mark.
     169
     170    $hide_html_elements = function( $buffer, $start, $length, $mark = NULL, $is_fragment = FALSE ) {
     171        $elements = [ ];
     172        $n        = 0;
     173        # error_log( 'hide_html_elements():$length=' . $length );
     174        # error_log( 'hide_html_elements():substr( $buffer, $length - 16 ) = ' . substr( $buffer, $length - 16 ) );
     175        while ( ( $left_offset = \mc_html_parser\get_start_tag( $buffer, $start, $length ) ) !== FALSE ) {
     176            if ( ++$n > 1024 ) {
     177                # This should not happen. If it does probably a programming error causing an infinite loop.
     178                error_log( 'ERROR:hide_html_elements():Probably in an infinite loop.' );
     179                error_log( 'ERROR:hide_html_elements():                   $start = ' . $start );
     180                error_log( 'ERROR:hide_html_elements():substr( $buffer, $start ) = ' . substr( $buffer, $start ) );
     181                break;
     182            }
     183            # error_log( 'hide_html_elements():$start=' . $start );
     184            $right_offset = \mc_html_parser\get_name( $buffer, $left_offset + 1, $length );
     185            $name         = substr( $buffer, $left_offset + 1, $right_offset - $left_offset );
     186            # error_log( 'hide_html_elements():$name=' . $name );
     187            if ( ( $gt_offset = \mc_html_parser\get_greater_than( $buffer, $right_offset + 1, $length ) ) === FALSE ) {
     188                error_log( 'ERROR:hide_html_elements():Cannot find matching \'>\' for tag beginning with "' . substr( $buffer, $left_offset, 64 ) . '...' );
     189                break;
     190            }
     191            $marked       = FALSE;
     192            if ( ! in_array( $name, [ 'img', 'br', 'hr', 'p' ] ) ) {
     193                # Tag <name> should have a matching end tag </name>.
     194                # error_log( 'hide_html_elements():...>...=' . substr( $buffer, ( $gt_offset + 1 ) - 16, 64 ) );
     195                if ( ( $offset = \mc_html_parser\get_end_tag( $name, $buffer, $gt_offset + 1, $length ) ) === FALSE ) {
     196                    # This should only happen on malformed HTML, i.e. no matching end tag </tag>.
     197                    if ( $is_fragment ) {
     198                        # error_log( 'hide_html_elements():Cannot find matching end tag "</' . $name . '>".' );
     199                        # error_log( 'hide_html_elements(): HTML element begins with: "' . substr( $buffer, $left_offset, 64 ) . '..."' );
     200                        # However, if we are parsing a HTML fragment then this may not be an error as the fragment may not yet be complete.
     201                        # So, ignore this tag and continue.
     202                        $start = $gt_offset + 1;
     203                        continue;
     204                    }
     205                    error_log( 'ERROR:hide_html_elements():Cannot find matching end tag "</' . $name . '>".' );
     206                    error_log( 'ERROR:hide_html_elements(): HTML element begins with: "' . substr( $buffer, $left_offset, 64 ) . '..."' );
     207                    return FALSE;
     208                }
     209                # error_log( 'hide_html_elements():</tag>...=' . substr( $buffer, ( $offset + 1 ) - 16, 64 ) );
     210                if ( ! is_null( $mark ) ) {
     211                    # error_log( 'hide_html_elements():innerHTML = #####'
     212                    #     . substr( $buffer, $gt_offset + 1, ( $offset - ( strlen( $name ) + 1 ) ) - ( $gt_offset + 1 ) ) . '#####' );
     213                    if ( ( $marked = strpos( substr( $buffer, $gt_offset + 1, ( $offset - ( strlen( $name ) + 1 ) ) - ( $gt_offset + 1 ) ), $mark ) )
     214                            !== FALSE ) {
     215                        # TODO: Should also remove siblings of marked.
     216                        # TODO: But, the only sibling seems to be the title which can be easily removed in another way.
     217                    }
     218                }
     219            } else {   # if ( ! in_array( $name, [ 'img', 'br', 'hr', 'p' ] ) ) {
     220                $offset = $gt_offset;
     221            }
     222            if ( ! $marked && ! in_array( $name, [ 'script' ] ) ) {
     223                # Add element to list of elements to hide.
     224                $elements[ ] = (object) [ 'name' => $name, 'left' => $left_offset, 'right' => $gt_offset ];
     225            }
     226            $start = $offset + 1;
     227        }
     228        # Hide elements in reverse order so previous offsets are preserved.
     229        foreach ( array_reverse( $elements ) as $element ) {
     230            # error_log( 'hide_html_elements():$name=' . $element->name );
     231            # error_log( 'hide_html_elements():tag=' . substr( $buffer, $element->left, $element->right - ( $element->left - 1 ) ) );
     232            if ( ( $style_offset = strpos( substr( $buffer, $element->left, $element->right - ( $element->left - 1 ) ), 'style=' ) ) === FALSE ) {
     233                $buffer = substr_replace( $buffer, ' style="display:none;"', $element->right, 0 );
     234            } else {
     235                # Element already has an inline style attribute.
     236                // TODO:
     237            }
     238        }
     239        # error_log( 'hide_html_elements():return=' . "\n#####\n" . $buffer . "/n#####" );
     240        return $buffer;
     241    };
     242
     243    $handle_output_buffering = function( $buffer, $caller, &$ob_state_stack ) {
     244        $ob_state             = end( $ob_state_stack );
     245        $hide_html_elements   = Output_Buffering_State::$hide_html_elements;
     246        $start_of_sidebar_len = strlen( START_OF_SIDEBAR );
     247        $start_of_footer_len  = strlen( START_OF_FOOTER );
     248        # error_log( 'handle_output_buffering():          $caller = ' . $caller );
     249        # error_log( 'handle_output_buffering():$ob_state->caller = ' . $ob_state->caller );
     250        # error_log( 'handle_output_buffering():$ob_state->ender  = ' . ( $ob_state->ender !== NULL ? $ob_state->ender
     251        #                                                                                           : 'end of execution' ) );
     252        # error_log( 'handle_output_buffering():$buffer=' . "\n#####\n" . $buffer . "\n#####" );
     253        if ( $caller === 'wp_body_open' ) {
     254            # ob_end_flush() can be called from multiple hooks - loop_end, get_sidebar, get_footer - or at the end of execution.
     255            # Hence, the buffer may or may not contain sidebars and/or the footer.
     256            if ( strpos( $buffer, START_OF_BODY ) !== 0 ) {
     257                error_log( 'ERROR:handle_output_buffering():unexpected start of body buffer, probably mismatched nested ob_start() output buffers.' );
     258                error_log( 'ERROR:handle_output_buffering():$buffer = "' . substr( $buffer, 64 ) );
     259            }
     260            $sidebar_offset = strpos( $buffer, START_OF_SIDEBAR );
     261            $footer_offset  = strpos( $buffer, START_OF_FOOTER );
     262            # $buffer contains a HTML fragment with embedded mark.
     263            $buffer = $hide_html_elements( $buffer, 0, $sidebar_offset !== FALSE ? $sidebar_offset
     264                                               : ( $footer_offset !== FALSE ? $footer_offset : strlen( $buffer ) ),
     265                                           START_OF_CONTENT, TRUE );
     266/*
     267 * Sidebars are now cleaned in an earlier call to ob_flush().
     268            $offset = 0;
     269            # N.B. There may be multiple sidebars.
     270            while ( ( $offset = strpos( $buffer, START_OF_SIDEBAR, $offset ) ) !== FALSE ) {
     271                $sidebar_offset = strpos( $buffer, START_OF_SIDEBAR, $offset + $start_of_sidebar_len );
     272                $footer_offset  = strpos( $buffer, START_OF_FOOTER,  $offset + $start_of_sidebar_len );
     273                $buffer = $hide_html_elements( $buffer, offset, $sidebar_offset !== FALSE ? $sidebar_offset
     274                                                   : ( $footer_offset !== FALSE ? $footer_offset : strlen( $buffer ) ) );
     275                $offset += $start_of_sidebar_len;
     276            }
     277 */
     278            # This buffer should no longer contain a footer.
     279            # if ( ( $offset = strpos( $buffer, START_OF_FOOTER ) ) !== FALSE ) {
     280            #     $buffer = $hide_html_elements( $buffer, $offset + strlen( START_OF_FOOTER ), strlen( $buffer ) );
     281            # }
     282            # error_log( 'handle_output_buffering():$caller=' . $caller );
     283            # error_log( 'handle_output_buffering():$return=' . "\n#####\n" . $buffer . "\n#####" );
     284        } else if ( $caller === 'get_sidebar' ) {
     285            if ( strpos( $buffer, START_OF_SIDEBAR ) !== 0 ) {
     286                error_log( 'ERROR:handle_output_buffering():unexpected start of sidebar buffer, probably mismatched nested ob_start() output buffers.' );
     287                error_log( 'ERROR:handle_output_buffering():$buffer = "' . substr( $buffer, 64 ) );
     288            }
     289            $start_offset = 0;
     290            # N.B. There may be multiple sidebars.
     291            while ( TRUE ) {
     292                $sidebar_offset = strpos( $buffer, START_OF_SIDEBAR, $start_offset + $start_of_sidebar_len );
     293                $content_offset = strpos( $buffer, START_OF_CONTENT, $start_offset + $start_of_sidebar_len );
     294                $footer_offset  = strpos( $buffer, START_OF_FOOTER,  $start_offset + $start_of_sidebar_len );
     295                $end_offset     = strlen( $buffer );
     296                foreach ( [ $sidebar_offset, $content_offset, $footer_offset ] as $offset ) {
     297                    if ( $offset !== FALSE  && $offset < $end_offset ) {
     298                        $end_offset = $offset;
     299                    }
     300                }
     301                $buffer = $hide_html_elements( $buffer, $start_offset, $end_offset, NULL, TRUE );
     302                if ( strlen( $buffer ) <= $start_of_sidebar_len
     303                    || ( $start_offset = strpos( $buffer, START_OF_SIDEBAR, $start_offset + $start_of_sidebar_len ) ) === FALSE ) {
     304                    break;
     305                }
     306            }
     307            # This buffer should no longer contain a footer.
     308            # if ( ( $offset = strpos( $buffer, START_OF_FOOTER ) ) !== FALSE ) {
     309            #     $buffer = $hide_html_elements( $buffer, $offset + start_of_footer_len, strlen( $buffer ) );
     310            # }
     311        } else if ( $caller === 'get_footer' ) {
     312            if ( strpos( $buffer, START_OF_FOOTER ) !== 0 ) {
     313                error_log( 'ERROR:handle_output_buffering():unexpected start of footer buffer, probably mismatched nested ob_start() output buffers.' );
     314                error_log( 'ERROR:handle_output_buffering():$buffer = "' . substr( $buffer, 64 ) );
     315            }
     316            $buffer = $hide_html_elements( $buffer, 0, strlen( $buffer ) );
     317        }
     318        # Reset $ob_state.
     319        array_pop( $ob_state_stack );
     320        return $buffer;
     321    };
     322
     323    class Output_Buffering_State {
     324        public $on;
     325        public $caller;
     326        public $level;
     327        public $ender;
     328        public static $handle_output_buffering;
     329        public static $hide_html_elements;
     330        function __construct( $caller ) {
     331            $this->on     = TRUE;
     332            $this->caller = $caller;
     333            $this->level  = ob_get_level( );
     334            $this->ender  = NULL;
     335        }
     336    }
     337    Output_Buffering_State::$handle_output_buffering = $handle_output_buffering;
     338    Output_Buffering_State::$hide_html_elements      = $hide_html_elements;
     339
     340   # $alt_template_redirect( ) will try to hide all HTML elements in the post content except the elements containing the mark.
     341
     342    $alt_template_redirect = function( ) {
     343        # Using PHP's output buffering can be tricky since they can easily be incorrectly nested.
     344        # We must call ob_end_flush() only after all calls to ob_start() after our ob_start() have been matched.
     345        # $ob_state will have the state of our output buffering and have references to our output buffering handlers.
     346        $ob_state_stack = [ ];
     347/*
     348        add_action( 'get_header', function ( $name ) {
     349            echo "<!-- ##### ACTION:get_header -->\n";
     350        } );
     351        add_action( 'wp_head', function( ) {
     352            echo "<!-- ##### ACTION:wp_head -->\n";
     353        } );
     354        add_action( 'the_post', function( &$post, &$query ) {
     355            echo "<!-- ##### ACTION:the_post -->\n";
     356        }, 10, 2 );
     357 */
     358        add_filter( 'the_title', function( $title ) {
     359            return '';
     360        } );
     361        add_filter( 'the_content', function( $content ) {
     362            # Insert the mark into the post content and replace $content with $_REQUEST['post_content'].
     363            # This will evaluate $_REQUEST['post_content'] in the context of the post specified by the URL.
     364            # error_log( 'FILTER:the_content():$_REQUEST["post_content"] = ' . $_REQUEST['post_content'] );
     365            return START_OF_CONTENT . "\n" . stripslashes( $_REQUEST['post_content'] );
     366        }, 1 );
     367/*
     368        add_filter( 'the_content', function( $content ) {
     369            return $content;
     370        }, PHP_INT_MAX );
     371 */
     372        add_action( 'loop_end', function( &$query ) use ( &$ob_state_stack ) {
     373            while ( TRUE ) {
     374                $ob_state = empty( $ob_state_stack ) ? NULL : end( $ob_state_stack );
     375                if ( ! is_null( $ob_state ) && $ob_state->on && ob_get_level( ) === $ob_state->level ) {
     376                    # Clean previously emitted content and left sidebars.
     377                    # error_log( 'ACTION:loop_end():ob_end_flush()' );
     378                    $ob_state->ender = 'loop_end';
     379                    ob_end_flush( );
     380                } else {
     381                    break;
     382                }
     383            }
     384            # echo "<!-- ##### ACTION:loop_end -->\n";
     385        }, 10, 1 );
     386        add_action( 'wp_body_open', function( ) use ( &$ob_state_stack ) {
     387            ob_start( function( $buffer ) use ( &$ob_state_stack ) {
     388                $handle_output_buffering = Output_Buffering_State::$handle_output_buffering;
     389                return $handle_output_buffering( $buffer, 'wp_body_open', $ob_state_stack );
     390            } );
     391            array_push( $ob_state_stack, new Output_Buffering_State( 'wp_body_open' ) );
     392            echo START_OF_BODY . "\n";
     393        } );
     394        add_filter( 'get_edit_post_link', function ( $link ) {
     395            return '';
     396        } );
     397/*
     398        add_filter( 'bloginfo', function( $output, $show ) {
     399            echo "<!-- ##### FILTER:bloginfo:[[{$output}]] -->\n";
     400            return $output;
     401        }, 10, 2 );
     402        add_filter( 'has_nav_menu', function( $has_nav_menu, $location ) {
     403            return $has_nav_menu;
     404        }, 10, 2 );
     405 *
     406 * Dangerous to do this as this can insert a HTML comment inside a HTML tag.
     407 *
     408        foreach ( [ 'header_image' ] as $name ) {
     409            add_filter( "theme_mod_{$name}", function( $default ) use ( $name ) {
     410                echo "<!-- ##### FILTER:theme_mod_{$name}:[[{$default}]] -->\n";
     411                return $default;
     412            } );
     413        }
     414 */
     415        add_action( 'get_sidebar', function ( $name ) use ( &$ob_state_stack ) {
     416            # error_log( 'ACTION:get_sidebar():' );
     417            $ob_state = empty( $ob_state_stack ) ? NULL : end( $ob_state_stack );
     418            if ( ! is_null( $ob_state ) && $ob_state->on && ob_get_level( ) === $ob_state->level && $ob_state->caller === 'get_sidebar' ) {
     419                # Clean only a previously emitted sidebar.
     420                # error_log( 'ACTION:get_sidebar():ob_end_flush()' );
     421                $ob_state->ender = 'get_sidebar';
     422                ob_end_flush( );
     423            }
     424            ob_start( function( $buffer ) use ( &$ob_state_stack ) {
     425                $handle_output_buffering = Output_Buffering_State::$handle_output_buffering;
     426                return $handle_output_buffering( $buffer, 'get_sidebar', $ob_state_stack );
     427            } );
     428            array_push( $ob_state_stack, new Output_Buffering_State( 'get_sidebar' ) );
     429            echo START_OF_SIDEBAR . "\n";
     430        } );
     431        add_action( 'get_footer', function ( $name ) use ( &$ob_state_stack ) {
     432            while ( TRUE ) {
     433                $ob_state = empty( $ob_state_stack ) ? NULL : end( $ob_state_stack );
     434                if ( ! is_null( $ob_state ) && $ob_state->on && ob_get_level( ) === $ob_state->level ) {
     435                    # Clean previously emitted content and right sidebars (content should have been handled by ACTION 'loop_end').
     436                    # error_log( 'ACTION:get_footer():ob_end_flush()' );
     437                    $ob_state->ender = 'get_footer';
     438                    ob_end_flush( );
     439                } else {
     440                    break;
     441                }
     442            }
     443            $ob_state = empty( $ob_state_stack ) ? NULL : end( $ob_state_stack );
     444            if ( is_null( $ob_state ) || ! $ob_state->on ) {
     445                ob_start( function( $buffer ) use ( &$ob_state_stack ) {
     446                    $handle_output_buffering = Output_Buffering_State::$handle_output_buffering;
     447                    return $handle_output_buffering( $buffer, 'get_footer', $ob_state_stack );
     448               } );
     449                array_push( $ob_state_stack, new Output_Buffering_State( 'get_footer' ) );
     450                echo START_OF_FOOTER . "\n";
     451            }
     452        } );
     453/*
     454        add_action( 'wp_footer', function( ) {
     455            echo "<!-- ##### ACTION:wp_footer -->\n";
     456        } );
     457        register_shutdown_function( function( ) use ( &$ob_state_stack ) {
     458        } );
     459 */
     460    };   # $alt_template_redirect = function( ) {
     461
    153462    $construct( );
    154 }
     463
     464    if ( ! empty( $_GET[ 'mc-sct' ] ) && $_GET[ 'mc-sct' ] === 'tpcti_html_eval_post_content' ) {
     465        add_filter( 'show_admin_bar', function( $show_admin_bar ) {
     466            return FALSE;
     467        } );
     468        add_action( 'template_redirect', function( ) use ( $alt_template_redirect ) {
     469            $alt_template_redirect( );
     470        } );
     471    }
     472
     473}   # namespace mc_shortcode_tester {
    155474?>
Note: See TracChangeset for help on using the changeset viewer.