Plugin Directory

Changeset 1556450


Ignore:
Timestamp:
12/16/2016 10:56:18 PM (9 years ago)
Author:
goldenapples
Message:

Tagging and relasing version 0.2.0

Location:
speed-bumps
Files:
16 edited
1 copied

Legend:

Unmodified
Added
Removed
  • speed-bumps/tags/0.2.0/Gruntfile.js

    r1204895 r1556450  
    4545        phpcs: {
    4646            application: {
    47                 src: ['inc/**/*.php', 'tests/**/*.php']
     47                src: './',
    4848            },
    4949            options: {
    50                 bin: 'vendor/bin/phpcs',
    51                 standard: 'WordPress-VIP'
     50                bin: "vendor/bin/phpcs --extensions=php --ignore=\"*/vendor/*,*/node_modules/*\"",
     51                standard: "phpcs.ruleset.xml"
    5252            }
    5353        }
  • speed-bumps/tags/0.2.0/README.md

    r1204895 r1556450  
    11# Speed Bumps #
    2 **Contributors:** fusioneng, goldenapples, noppanit 
     2**Contributors:** fusionengineering, goldenapples, noppanit 
    33**Tags:** content, advertising, recirculation 
    4 **Requires at least:** 3.0.1 
    5 **Stable tag:** 0.1.0 
    6 **Tested up to:** 4.3 
     4**Requires at least:** 4.2 
     5**Stable tag:** 0.2.0 
     6**Tested up to:** 4.6 
    77**License:** GPLv2 or later 
    88**License URI:** http://www.gnu.org/licenses/gpl-2.0.html 
     
    114114## Changelog ##
    115115
    116 ### 0.1.0 (July 22, 2015) ###
     116### 0.2.0 (December 15, 2016) ###
     117
     118* Compatability: Remove direct $wp_filter access for WP 4.7 compatability.
     119* Compatability: Fix issues throwing warnings in PHP7.
     120* Feature: Add "last ditch fallback" option for speed bump registration.
     121* Feature: Add filter around speed bump insertion content.
     122* Performance: Unregister speed bumps when global constraints prevent them being inserted.
     123* Performance: Unregister speed bumps after inserting them the maximum number of times.
     124* Performance: Allow speed bump constraint filters to short-circuit other filters at an insertion point, or to skip all remaining insertion points in a document.
     125
     126### 0.1.0 (July 23, 2015) ###
    117127
    118128* Initial release.
    119 * [Full release notes](http://fus.in/1MidK1N)
     129* [Full release notes](http://fusion.net/story/170253/meet-speed-bumps-our-newest-open-source-release/)
  • speed-bumps/tags/0.2.0/inc/constraints/content/class-injection.php

    r1204895 r1556450  
    44use Speed_Bumps\Utils\Comparison;
    55use Speed_Bumps\Utils\Text;
     6use Speed_Bumps;
    67
    78/**
     
    3738
    3839        if ( count( $this_speed_bump_insertions ) >= $args['maximum_inserts'] ) {
    39             $can_insert = false;
     40            $can_insert = Speed_Bumps::return_false_and_remove_all();
    4041        }
    4142
  • speed-bumps/tags/0.2.0/inc/constraints/elements/class-shortcode.php

    r1204895 r1556450  
    22namespace Speed_Bumps\Constraints\Elements;
    33
    4 class Shortcode extends Constraint_Abstract{
     4class Shortcode extends Constraint_Abstract {
    55    public function paragraph_not_contains_element( $paragraph ) {
    66        if ( preg_match_all( '/' . get_shortcode_regex() . '/s', $paragraph, $matches, PREG_SET_ORDER ) ) {
  • speed-bumps/tags/0.2.0/inc/constraints/text/class-minimum-text.php

    r1204895 r1556450  
    22namespace Speed_Bumps\Constraints\Text;
    33
     4use Speed_Bumps\Utils\Comparison;
    45use Speed_Bumps\Utils\Text;
    5 use Speed_Bumps\Utils\Comparison;
     6use Speed_Bumps;
    67
    78/**
     
    4041                if ( isset( $args['minimum_content_length'][ $unit ] ) &&
    4142                    Comparison::content_less_than( $unit, $args['minimum_content_length'][ $unit ], $content ) ) {
    42                     $can_insert = false;
     43                    $can_insert = Speed_Bumps::return_false_and_remove_all();
    4344                }
    4445            }
     
    4748        if ( intval( $args['minimum_content_length'] ) ) {
    4849            if ( Comparison::content_less_than( 'characters', intval( $args['minimum_content_length'] ), $content ) ) {
    49                 $can_insert = false;
     50                $can_insert = Speed_Bumps::return_false_and_remove_all();
    5051            }
    5152        }
     53
     54        // This constraint should only need to be run once. If we've gotten to this point, then the content
     55        // *is* long enough to insert, so this filter can be removed, rather than recalulating on every
     56        // paragraph.
     57        remove_filter( current_filter(), '\\' . __CLASS__ . '::' . __FUNCTION__ );
    5258
    5359        return $can_insert;
  • speed-bumps/tags/0.2.0/languages/speed-bumps.pot

    r1204895 r1556450  
    1 # Copyright (C) 2015 Fusion Engineering
     1# Copyright (C) 2016 Fusion Engineering
    22# This file is distributed under the same license as the Speed-bumps package.
    33msgid ""
    44msgstr ""
    5 "Project-Id-Version: Speed-bumps 0.1.0\n"
    6 "Report-Msgid-Bugs-To: http://wordpress.org/support/plugin/speed-bumps\n"
    7 "POT-Creation-Date: 2015-07-22 18:59:50+00:00\n"
     5"Project-Id-Version: Speed-bumps 0.2.0\n"
     6"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/speed-bumps\n"
     7"POT-Creation-Date: 2016-12-15 22:39:09+00:00\n"
    88"MIME-Version: 1.0\n"
    99"Content-Type: text/plain; charset=utf-8\n"
    1010"Content-Transfer-Encoding: 8bit\n"
    11 "PO-Revision-Date: 2015-MO-DA HO:MI+ZONE\n"
     11"PO-Revision-Date: 2016-MO-DA HO:MI+ZONE\n"
    1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
    1313"Language-Team: LANGUAGE <LL@li.org>\n"
    14 "X-Generator: grunt-wp-i18n 0.5.2\n"
     14"X-Generator: grunt-wp-i18n 0.5.4\n"
    1515"X-Poedit-KeywordsList: "
    1616"__;_e;_x:1,2c;_ex:1,2c;_n:1,2;_nx:1,2,4c;_n_noop:1,2;_nx_noop:1,2,3c;esc_"
  • speed-bumps/tags/0.2.0/readme.txt

    r1204895 r1556450  
    33Tags: content, advertising, recirculation
    44Requires at least: 4.2
    5 Stable tag: 0.1.0
    6 Tested up to: 4.3
     5Stable tag: 0.2.0
     6Tested up to: 4.6
    77License: GPLv2 or later
    88License URI: http://www.gnu.org/licenses/gpl-2.0.html
     
    114114== Changelog ==
    115115
     116= 0.2.0 (December 15, 2016) =
     117
     118* Compatability: Remove direct $wp_filter access for WP 4.7 compatability.
     119* Compatability: Fix issues throwing warnings in PHP7.
     120* Feature: Add "last ditch fallback" option for speed bump registration.
     121* Feature: Add filter around speed bump insertion content.
     122* Performance: Unregister speed bumps when global constraints prevent them being inserted.
     123* Performance: Unregister speed bumps after inserting them the maximum number of times.
     124* Performance: Allow speed bump constraint filters to short-circuit other filters at an insertion point, or to skip all remaining insertion points in a document.
     125
    116126= 0.1.0 (July 23, 2015) =
    117127
  • speed-bumps/tags/0.2.0/speed-bumps.php

    r1204895 r1556450  
    22/*
    33Plugin Name: Speed-bumps
    4 Version: 0.1.0
     4Version: 0.2.0
    55Description: A Plugin to insert a piece of content intelligently.
    66Author: Fusion Engineering
     
    6666     * - and the file containing the class itself will be named `class-{classname}.php`
    6767     */
    68     function spl_autoload($class) {
     68    function spl_autoload( $class ) {
    6969
    7070        // project-specific namespace
     
    8888        if ( file_exists( $file ) ) {
    8989            //Require the file
    90             require($file);
     90            require( $file );
    9191        }
    9292    }
     
    109109     */
    110110    public function insert_speed_bumps( $the_content ) {
     111        global $_wp_filters_backed_up, $wp_filter;
     112        $_wp_filters_backed_up = array();
    111113        $output = array();
    112114        $already_inserted = array();
     
    126128            foreach ( $this->get_speed_bumps() as $id => $args ) {
    127129
    128                 if ( apply_filters( 'speed_bumps_'. $id . '_constraints', true, $context, $args, $already_inserted ) ) {
     130                $speed_bump_filter = sprintf( self::$filter_id, $id );
     131
     132                /**
     133                 * Filter whether a speed bump can be inserted at a given location
     134                 *
     135                 * This filter is dynamically named "speed_bump_{id}_constraints", and is the main logic of
     136                 * this plugin. Returning false from this filter means that the speed bump will not be
     137                 * inserted.
     138                 *
     139                 * @param bool  $can_insert        Whether the speed bump can be inserted here
     140                 * @param array $args              Speed bump rules
     141                 * @param array $context           Current insertion point context
     142                 * @param array $already_inserted  Other speed bumps which have been inserted
     143                 */
     144                if ( apply_filters( $speed_bump_filter, true, $context, $args, $already_inserted ) ) {
    129145
    130146                    $content_to_be_inserted = call_user_func( $args['string_to_inject'], $context, $already_inserted );
    131147
    132                     $output[] = $content_to_be_inserted;
     148                    /**
     149                     * Filter the output of a speed bump.
     150                     *
     151                     * @param string $content_to_be_inserted Output of speed bump
     152                     * @param array  $args                   Speed bump rules
     153                     * @param array  $context                Current insertion point context
     154                     * @param array  $already_inserted       Other speed bumps which have been inserted
     155                     */
     156                    $output[] = apply_filters( 'speed_bumps_content_inserted', $content_to_be_inserted, $args, $context, $already_inserted );
     157
     158                    $already_inserted[] = array(
     159                        'index' => $index,
     160                        'speed_bump_id' => $id,
     161                        'inserted_content' => $content_to_be_inserted,
     162                    );
     163                }
     164
     165                /**
     166                 * Fires after all constraints on a speed bump are completed for an insertion point
     167                 *
     168                 * @param string $speed_bump_filter The speed bump's filter name
     169                 * @param array  $context           Current insertion point context
     170                 */
     171                do_action( 'speed_bumps_constraints_completed', $speed_bump_filter );
     172
     173            } // @codingStandardsIgnoreLine End foreach() loop through filters at insertion point
     174
     175        } // @codingStandardsIgnoreLine End foreach() loop through paragraphs.
     176
     177        // Apply "last ditch" insertion rules for any speed bumps that implement them
     178        $context['last_ditch'] = true;
     179
     180        foreach ( $this->get_speed_bumps() as $id => $args ) {
     181
     182            if ( ! empty( $args['last_ditch_fallback'] ) ) {
     183
     184                if ( is_callable( $args['last_ditch_fallback'] ) ) {
     185                    $can_insert = call_user_func( $args['last_ditch_fallback'], $context, $already_inserted );
     186                } else {
     187                    $inserted = array_filter( $already_inserted, function( $insert ) use ( $id ) { return $insert['speed_bump_id'] === $id; } );
     188                    $can_insert = ( count( $inserted ) < $args['minimum_inserts'] );
     189                }
     190
     191                if ( $can_insert ) {
     192                    $content_to_be_inserted = call_user_func( $args['string_to_inject'], $context, $already_inserted );
     193
     194                    $output[] = apply_filters( 'speed_bumps_content_inserted', $content_to_be_inserted, $args, $context, $already_inserted );
     195
    133196                    $already_inserted[] = array(
    134197                        'index' => $index,
     
    140203        }
    141204
     205        $this->reset_all_speed_bumps();
    142206        return implode( PHP_EOL . PHP_EOL, $output );
    143207    }
     
    163227            // Maximum number of times this can be inserted in a post
    164228            'maximum_inserts' => 1,
     229
     230            // Minimum times this should be inserted, if 'last_ditch_fallback' is true
     231            // (NOTE: this doesn't mean the speed bump will necessarily be inserted this
     232            // number of times; but if it has been inserted fewer times than this at the end
     233            // of the content, a "last ditch" insertion will be processed.)
     234            'minimum_inserts' => 1,
     235            'last_ditch_fallback' => false,
    165236
    166237            // Rules which govern the content as a whole
     
    232303    }
    233304
     305    public function get_speed_bumps_filters() {
     306        $speed_bumps = $this->get_speed_bumps();
     307        $filter_pattern = self::$filter_id;
     308
     309        return array_map(
     310            function( $id ) use ( $filter_pattern ) {
     311                return sprintf( $filter_pattern, $id );
     312            }, array_keys( $speed_bumps )
     313        );
     314    }
     315
    234316    public function get_speed_bump( $id ) {
    235317        return self::$speed_bumps[ $id ];
     
    245327        foreach ( $this->get_speed_bumps() as $id => $args ) {
    246328            $this->clear_speed_bump( $id );
     329        }
     330    }
     331
     332    // Public control structures, which can be called by speed bumps
     333    public static function return_false_and_skip() {
     334        self::skip_current_insertion_point();
     335        return false;
     336    }
     337
     338    public static function return_false_and_remove_all() {
     339        self::remove_current_speed_bump();
     340        return false;
     341    }
     342
     343    public static function return_true_and_skip() {
     344        self::skip_current_insertion_point();
     345        return true;
     346    }
     347
     348    public static function return_true_and_remove_all() {
     349        self::remove_current_speed_bump();
     350        return true;
     351    }
     352
     353    /**
     354     * Prevent the current speed bump from running over the rest of the content.
     355     *
     356     * Removes a speed bump completely. Usually called through
     357     * `return_false_and_remove_all` or `return_true_and_remove_all`.
     358     *
     359     * @uses Speed_Bumps::remove_speed_bump
     360     * @return void
     361     */
     362    public static function remove_current_speed_bump() {
     363        self::remove_speed_bump( current_filter() );
     364    }
     365
     366    /**
     367     * Prevent a speed bump from running over the rest of the content.
     368     *
     369     * Removes a speed bump completely. Usually called through
     370     * `return_false_and_remove_all` or `return_true_and_remove_all`.
     371     *
     372     * @param string $filter_id Filter ID of speed bump to remove
     373     * @return void
     374     */
     375    public static function remove_speed_bump( $filter_id ) {
     376        global $_wp_filters_backed_up, $wp_filter;
     377
     378        if ( in_array( $filter_id, Speed_Bumps()->get_speed_bumps_filters(), true ) ) {
     379            $_wp_filters_backed_up[ $filter_id ] = is_object( $wp_filter[ $filter_id ] ) ? clone $wp_filter[ $filter_id ] : $wp_filter[ $filter_id ];
     380            remove_all_filters( $filter_id );
     381            add_filter( $filter_id, '__return_false' );
     382        }
     383    }
     384
     385    /**
     386     * Skip all remaining constraint checks at the current insertion point.
     387     *
     388     * Removes all constraint checks for a speed bump temporarily, and adds an
     389     * action to reset the speed bump after the current insertion point.
     390     * Usually called from a constraint filter through `return_false_and_skip`
     391     * or `return_true_and_skip`.
     392     *
     393     * Skipping insertion points early when you know that a speed bump can't be
     394     * inserted can improve performance greatly, as otherwise the plugin will
     395     * run all the constraint filters at every paragraph of the content. With
     396     * regex-heavy rules, this can become very slow.
     397     *
     398     * @return void
     399     */
     400    public static function skip_current_insertion_point() {
     401        global $_wp_filters_backed_up, $wp_filter;
     402
     403        $filter_id = current_filter();
     404
     405        if ( isset( $wp_filter[ $filter_id ] )
     406                && in_array( $filter_id, Speed_Bumps()->get_speed_bumps_filters(), true ) ) {
     407
     408            $_wp_filters_backed_up[ $filter_id ] = is_object( $wp_filter[ $filter_id ] ) ? clone $wp_filter[ $filter_id ] : $wp_filter[ $filter_id ];
     409            remove_all_filters( $filter_id );
     410
     411            // Restore the speed bump after the current insertion point has been processed
     412            add_action( 'speed_bumps_constraints_completed', 'Speed_Bumps::restore_speed_bump' );
     413        }
     414    }
     415
     416    /**
     417     * Restore a speed bump that was skipped for an insertion point
     418     *
     419     * Run after all constraint filters have been processed at an insertion
     420     * point. Restores the speed bump which was temporarily removed using
     421     * `remove_current_speed_bump` or `skip_current_insertion_point()`.
     422     *
     423     * @param string Speed bump filter id
     424     */
     425    public static function restore_speed_bump( $speed_bump_filter ) {
     426        global $wp_filter, $_wp_filters_backed_up;
     427
     428        if ( isset( $_wp_filters_backed_up[ $speed_bump_filter ] )
     429                && in_array( $speed_bump_filter, Speed_Bumps()->get_speed_bumps_filters(), true ) ) {
     430
     431            $wp_filter[ $speed_bump_filter ] = $_wp_filters_backed_up[ $speed_bump_filter ];
     432            unset( $_wp_filters_backed_up[ $speed_bump_filter ] );
     433        }
     434
     435        remove_action( 'speed_bumps_constraints_completed', 'Speed_Bumps::restore_speed_bump' );
     436    }
     437
     438    /**
     439     * Restore any filters removed by `remove_current_speed_bump_filters()`.
     440     *
     441     * Run at the end of processing the content, so that more than one content string can be processed in a
     442     * single WP instance.
     443     */
     444    public static function reset_all_speed_bumps() {
     445        global $_wp_filters_backed_up, $wp_filter;
     446
     447        if ( is_array( $_wp_filters_backed_up ) ) {
     448            foreach ( $_wp_filters_backed_up as $hook => $filters ) {
     449                $wp_filter[ $hook ] = $filters;
     450            }
     451            $_wp_filters_backed_up = array();
    247452        }
    248453    }
  • speed-bumps/trunk/Gruntfile.js

    r1204895 r1556450  
    4545        phpcs: {
    4646            application: {
    47                 src: ['inc/**/*.php', 'tests/**/*.php']
     47                src: './',
    4848            },
    4949            options: {
    50                 bin: 'vendor/bin/phpcs',
    51                 standard: 'WordPress-VIP'
     50                bin: "vendor/bin/phpcs --extensions=php --ignore=\"*/vendor/*,*/node_modules/*\"",
     51                standard: "phpcs.ruleset.xml"
    5252            }
    5353        }
  • speed-bumps/trunk/README.md

    r1204895 r1556450  
    11# Speed Bumps #
    2 **Contributors:** fusioneng, goldenapples, noppanit 
     2**Contributors:** fusionengineering, goldenapples, noppanit 
    33**Tags:** content, advertising, recirculation 
    4 **Requires at least:** 3.0.1 
    5 **Stable tag:** 0.1.0 
    6 **Tested up to:** 4.3 
     4**Requires at least:** 4.2 
     5**Stable tag:** 0.2.0 
     6**Tested up to:** 4.6 
    77**License:** GPLv2 or later 
    88**License URI:** http://www.gnu.org/licenses/gpl-2.0.html 
     
    114114## Changelog ##
    115115
    116 ### 0.1.0 (July 22, 2015) ###
     116### 0.2.0 (December 15, 2016) ###
     117
     118* Compatability: Remove direct $wp_filter access for WP 4.7 compatability.
     119* Compatability: Fix issues throwing warnings in PHP7.
     120* Feature: Add "last ditch fallback" option for speed bump registration.
     121* Feature: Add filter around speed bump insertion content.
     122* Performance: Unregister speed bumps when global constraints prevent them being inserted.
     123* Performance: Unregister speed bumps after inserting them the maximum number of times.
     124* Performance: Allow speed bump constraint filters to short-circuit other filters at an insertion point, or to skip all remaining insertion points in a document.
     125
     126### 0.1.0 (July 23, 2015) ###
    117127
    118128* Initial release.
    119 * [Full release notes](http://fus.in/1MidK1N)
     129* [Full release notes](http://fusion.net/story/170253/meet-speed-bumps-our-newest-open-source-release/)
  • speed-bumps/trunk/inc/constraints/content/class-injection.php

    r1204895 r1556450  
    44use Speed_Bumps\Utils\Comparison;
    55use Speed_Bumps\Utils\Text;
     6use Speed_Bumps;
    67
    78/**
     
    3738
    3839        if ( count( $this_speed_bump_insertions ) >= $args['maximum_inserts'] ) {
    39             $can_insert = false;
     40            $can_insert = Speed_Bumps::return_false_and_remove_all();
    4041        }
    4142
  • speed-bumps/trunk/inc/constraints/elements/class-shortcode.php

    r1204895 r1556450  
    22namespace Speed_Bumps\Constraints\Elements;
    33
    4 class Shortcode extends Constraint_Abstract{
     4class Shortcode extends Constraint_Abstract {
    55    public function paragraph_not_contains_element( $paragraph ) {
    66        if ( preg_match_all( '/' . get_shortcode_regex() . '/s', $paragraph, $matches, PREG_SET_ORDER ) ) {
  • speed-bumps/trunk/inc/constraints/text/class-minimum-text.php

    r1204895 r1556450  
    22namespace Speed_Bumps\Constraints\Text;
    33
     4use Speed_Bumps\Utils\Comparison;
    45use Speed_Bumps\Utils\Text;
    5 use Speed_Bumps\Utils\Comparison;
     6use Speed_Bumps;
    67
    78/**
     
    4041                if ( isset( $args['minimum_content_length'][ $unit ] ) &&
    4142                    Comparison::content_less_than( $unit, $args['minimum_content_length'][ $unit ], $content ) ) {
    42                     $can_insert = false;
     43                    $can_insert = Speed_Bumps::return_false_and_remove_all();
    4344                }
    4445            }
     
    4748        if ( intval( $args['minimum_content_length'] ) ) {
    4849            if ( Comparison::content_less_than( 'characters', intval( $args['minimum_content_length'] ), $content ) ) {
    49                 $can_insert = false;
     50                $can_insert = Speed_Bumps::return_false_and_remove_all();
    5051            }
    5152        }
     53
     54        // This constraint should only need to be run once. If we've gotten to this point, then the content
     55        // *is* long enough to insert, so this filter can be removed, rather than recalulating on every
     56        // paragraph.
     57        remove_filter( current_filter(), '\\' . __CLASS__ . '::' . __FUNCTION__ );
    5258
    5359        return $can_insert;
  • speed-bumps/trunk/languages/speed-bumps.pot

    r1204895 r1556450  
    1 # Copyright (C) 2015 Fusion Engineering
     1# Copyright (C) 2016 Fusion Engineering
    22# This file is distributed under the same license as the Speed-bumps package.
    33msgid ""
    44msgstr ""
    5 "Project-Id-Version: Speed-bumps 0.1.0\n"
    6 "Report-Msgid-Bugs-To: http://wordpress.org/support/plugin/speed-bumps\n"
    7 "POT-Creation-Date: 2015-07-22 18:59:50+00:00\n"
     5"Project-Id-Version: Speed-bumps 0.2.0\n"
     6"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/speed-bumps\n"
     7"POT-Creation-Date: 2016-12-15 22:39:09+00:00\n"
    88"MIME-Version: 1.0\n"
    99"Content-Type: text/plain; charset=utf-8\n"
    1010"Content-Transfer-Encoding: 8bit\n"
    11 "PO-Revision-Date: 2015-MO-DA HO:MI+ZONE\n"
     11"PO-Revision-Date: 2016-MO-DA HO:MI+ZONE\n"
    1212"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
    1313"Language-Team: LANGUAGE <LL@li.org>\n"
    14 "X-Generator: grunt-wp-i18n 0.5.2\n"
     14"X-Generator: grunt-wp-i18n 0.5.4\n"
    1515"X-Poedit-KeywordsList: "
    1616"__;_e;_x:1,2c;_ex:1,2c;_n:1,2;_nx:1,2,4c;_n_noop:1,2;_nx_noop:1,2,3c;esc_"
  • speed-bumps/trunk/readme.txt

    r1204895 r1556450  
    33Tags: content, advertising, recirculation
    44Requires at least: 4.2
    5 Stable tag: 0.1.0
    6 Tested up to: 4.3
     5Stable tag: 0.2.0
     6Tested up to: 4.6
    77License: GPLv2 or later
    88License URI: http://www.gnu.org/licenses/gpl-2.0.html
     
    114114== Changelog ==
    115115
     116= 0.2.0 (December 15, 2016) =
     117
     118* Compatability: Remove direct $wp_filter access for WP 4.7 compatability.
     119* Compatability: Fix issues throwing warnings in PHP7.
     120* Feature: Add "last ditch fallback" option for speed bump registration.
     121* Feature: Add filter around speed bump insertion content.
     122* Performance: Unregister speed bumps when global constraints prevent them being inserted.
     123* Performance: Unregister speed bumps after inserting them the maximum number of times.
     124* Performance: Allow speed bump constraint filters to short-circuit other filters at an insertion point, or to skip all remaining insertion points in a document.
     125
    116126= 0.1.0 (July 23, 2015) =
    117127
  • speed-bumps/trunk/speed-bumps.php

    r1204895 r1556450  
    22/*
    33Plugin Name: Speed-bumps
    4 Version: 0.1.0
     4Version: 0.2.0
    55Description: A Plugin to insert a piece of content intelligently.
    66Author: Fusion Engineering
     
    6666     * - and the file containing the class itself will be named `class-{classname}.php`
    6767     */
    68     function spl_autoload($class) {
     68    function spl_autoload( $class ) {
    6969
    7070        // project-specific namespace
     
    8888        if ( file_exists( $file ) ) {
    8989            //Require the file
    90             require($file);
     90            require( $file );
    9191        }
    9292    }
     
    109109     */
    110110    public function insert_speed_bumps( $the_content ) {
     111        global $_wp_filters_backed_up, $wp_filter;
     112        $_wp_filters_backed_up = array();
    111113        $output = array();
    112114        $already_inserted = array();
     
    126128            foreach ( $this->get_speed_bumps() as $id => $args ) {
    127129
    128                 if ( apply_filters( 'speed_bumps_'. $id . '_constraints', true, $context, $args, $already_inserted ) ) {
     130                $speed_bump_filter = sprintf( self::$filter_id, $id );
     131
     132                /**
     133                 * Filter whether a speed bump can be inserted at a given location
     134                 *
     135                 * This filter is dynamically named "speed_bump_{id}_constraints", and is the main logic of
     136                 * this plugin. Returning false from this filter means that the speed bump will not be
     137                 * inserted.
     138                 *
     139                 * @param bool  $can_insert        Whether the speed bump can be inserted here
     140                 * @param array $args              Speed bump rules
     141                 * @param array $context           Current insertion point context
     142                 * @param array $already_inserted  Other speed bumps which have been inserted
     143                 */
     144                if ( apply_filters( $speed_bump_filter, true, $context, $args, $already_inserted ) ) {
    129145
    130146                    $content_to_be_inserted = call_user_func( $args['string_to_inject'], $context, $already_inserted );
    131147
    132                     $output[] = $content_to_be_inserted;
     148                    /**
     149                     * Filter the output of a speed bump.
     150                     *
     151                     * @param string $content_to_be_inserted Output of speed bump
     152                     * @param array  $args                   Speed bump rules
     153                     * @param array  $context                Current insertion point context
     154                     * @param array  $already_inserted       Other speed bumps which have been inserted
     155                     */
     156                    $output[] = apply_filters( 'speed_bumps_content_inserted', $content_to_be_inserted, $args, $context, $already_inserted );
     157
     158                    $already_inserted[] = array(
     159                        'index' => $index,
     160                        'speed_bump_id' => $id,
     161                        'inserted_content' => $content_to_be_inserted,
     162                    );
     163                }
     164
     165                /**
     166                 * Fires after all constraints on a speed bump are completed for an insertion point
     167                 *
     168                 * @param string $speed_bump_filter The speed bump's filter name
     169                 * @param array  $context           Current insertion point context
     170                 */
     171                do_action( 'speed_bumps_constraints_completed', $speed_bump_filter );
     172
     173            } // @codingStandardsIgnoreLine End foreach() loop through filters at insertion point
     174
     175        } // @codingStandardsIgnoreLine End foreach() loop through paragraphs.
     176
     177        // Apply "last ditch" insertion rules for any speed bumps that implement them
     178        $context['last_ditch'] = true;
     179
     180        foreach ( $this->get_speed_bumps() as $id => $args ) {
     181
     182            if ( ! empty( $args['last_ditch_fallback'] ) ) {
     183
     184                if ( is_callable( $args['last_ditch_fallback'] ) ) {
     185                    $can_insert = call_user_func( $args['last_ditch_fallback'], $context, $already_inserted );
     186                } else {
     187                    $inserted = array_filter( $already_inserted, function( $insert ) use ( $id ) { return $insert['speed_bump_id'] === $id; } );
     188                    $can_insert = ( count( $inserted ) < $args['minimum_inserts'] );
     189                }
     190
     191                if ( $can_insert ) {
     192                    $content_to_be_inserted = call_user_func( $args['string_to_inject'], $context, $already_inserted );
     193
     194                    $output[] = apply_filters( 'speed_bumps_content_inserted', $content_to_be_inserted, $args, $context, $already_inserted );
     195
    133196                    $already_inserted[] = array(
    134197                        'index' => $index,
     
    140203        }
    141204
     205        $this->reset_all_speed_bumps();
    142206        return implode( PHP_EOL . PHP_EOL, $output );
    143207    }
     
    163227            // Maximum number of times this can be inserted in a post
    164228            'maximum_inserts' => 1,
     229
     230            // Minimum times this should be inserted, if 'last_ditch_fallback' is true
     231            // (NOTE: this doesn't mean the speed bump will necessarily be inserted this
     232            // number of times; but if it has been inserted fewer times than this at the end
     233            // of the content, a "last ditch" insertion will be processed.)
     234            'minimum_inserts' => 1,
     235            'last_ditch_fallback' => false,
    165236
    166237            // Rules which govern the content as a whole
     
    232303    }
    233304
     305    public function get_speed_bumps_filters() {
     306        $speed_bumps = $this->get_speed_bumps();
     307        $filter_pattern = self::$filter_id;
     308
     309        return array_map(
     310            function( $id ) use ( $filter_pattern ) {
     311                return sprintf( $filter_pattern, $id );
     312            }, array_keys( $speed_bumps )
     313        );
     314    }
     315
    234316    public function get_speed_bump( $id ) {
    235317        return self::$speed_bumps[ $id ];
     
    245327        foreach ( $this->get_speed_bumps() as $id => $args ) {
    246328            $this->clear_speed_bump( $id );
     329        }
     330    }
     331
     332    // Public control structures, which can be called by speed bumps
     333    public static function return_false_and_skip() {
     334        self::skip_current_insertion_point();
     335        return false;
     336    }
     337
     338    public static function return_false_and_remove_all() {
     339        self::remove_current_speed_bump();
     340        return false;
     341    }
     342
     343    public static function return_true_and_skip() {
     344        self::skip_current_insertion_point();
     345        return true;
     346    }
     347
     348    public static function return_true_and_remove_all() {
     349        self::remove_current_speed_bump();
     350        return true;
     351    }
     352
     353    /**
     354     * Prevent the current speed bump from running over the rest of the content.
     355     *
     356     * Removes a speed bump completely. Usually called through
     357     * `return_false_and_remove_all` or `return_true_and_remove_all`.
     358     *
     359     * @uses Speed_Bumps::remove_speed_bump
     360     * @return void
     361     */
     362    public static function remove_current_speed_bump() {
     363        self::remove_speed_bump( current_filter() );
     364    }
     365
     366    /**
     367     * Prevent a speed bump from running over the rest of the content.
     368     *
     369     * Removes a speed bump completely. Usually called through
     370     * `return_false_and_remove_all` or `return_true_and_remove_all`.
     371     *
     372     * @param string $filter_id Filter ID of speed bump to remove
     373     * @return void
     374     */
     375    public static function remove_speed_bump( $filter_id ) {
     376        global $_wp_filters_backed_up, $wp_filter;
     377
     378        if ( in_array( $filter_id, Speed_Bumps()->get_speed_bumps_filters(), true ) ) {
     379            $_wp_filters_backed_up[ $filter_id ] = is_object( $wp_filter[ $filter_id ] ) ? clone $wp_filter[ $filter_id ] : $wp_filter[ $filter_id ];
     380            remove_all_filters( $filter_id );
     381            add_filter( $filter_id, '__return_false' );
     382        }
     383    }
     384
     385    /**
     386     * Skip all remaining constraint checks at the current insertion point.
     387     *
     388     * Removes all constraint checks for a speed bump temporarily, and adds an
     389     * action to reset the speed bump after the current insertion point.
     390     * Usually called from a constraint filter through `return_false_and_skip`
     391     * or `return_true_and_skip`.
     392     *
     393     * Skipping insertion points early when you know that a speed bump can't be
     394     * inserted can improve performance greatly, as otherwise the plugin will
     395     * run all the constraint filters at every paragraph of the content. With
     396     * regex-heavy rules, this can become very slow.
     397     *
     398     * @return void
     399     */
     400    public static function skip_current_insertion_point() {
     401        global $_wp_filters_backed_up, $wp_filter;
     402
     403        $filter_id = current_filter();
     404
     405        if ( isset( $wp_filter[ $filter_id ] )
     406                && in_array( $filter_id, Speed_Bumps()->get_speed_bumps_filters(), true ) ) {
     407
     408            $_wp_filters_backed_up[ $filter_id ] = is_object( $wp_filter[ $filter_id ] ) ? clone $wp_filter[ $filter_id ] : $wp_filter[ $filter_id ];
     409            remove_all_filters( $filter_id );
     410
     411            // Restore the speed bump after the current insertion point has been processed
     412            add_action( 'speed_bumps_constraints_completed', 'Speed_Bumps::restore_speed_bump' );
     413        }
     414    }
     415
     416    /**
     417     * Restore a speed bump that was skipped for an insertion point
     418     *
     419     * Run after all constraint filters have been processed at an insertion
     420     * point. Restores the speed bump which was temporarily removed using
     421     * `remove_current_speed_bump` or `skip_current_insertion_point()`.
     422     *
     423     * @param string Speed bump filter id
     424     */
     425    public static function restore_speed_bump( $speed_bump_filter ) {
     426        global $wp_filter, $_wp_filters_backed_up;
     427
     428        if ( isset( $_wp_filters_backed_up[ $speed_bump_filter ] )
     429                && in_array( $speed_bump_filter, Speed_Bumps()->get_speed_bumps_filters(), true ) ) {
     430
     431            $wp_filter[ $speed_bump_filter ] = $_wp_filters_backed_up[ $speed_bump_filter ];
     432            unset( $_wp_filters_backed_up[ $speed_bump_filter ] );
     433        }
     434
     435        remove_action( 'speed_bumps_constraints_completed', 'Speed_Bumps::restore_speed_bump' );
     436    }
     437
     438    /**
     439     * Restore any filters removed by `remove_current_speed_bump_filters()`.
     440     *
     441     * Run at the end of processing the content, so that more than one content string can be processed in a
     442     * single WP instance.
     443     */
     444    public static function reset_all_speed_bumps() {
     445        global $_wp_filters_backed_up, $wp_filter;
     446
     447        if ( is_array( $_wp_filters_backed_up ) ) {
     448            foreach ( $_wp_filters_backed_up as $hook => $filters ) {
     449                $wp_filter[ $hook ] = $filters;
     450            }
     451            $_wp_filters_backed_up = array();
    247452        }
    248453    }
Note: See TracChangeset for help on using the changeset viewer.