Plugin Directory

Changeset 1064687


Ignore:
Timestamp:
01/10/2015 02:46:37 PM (11 years ago)
Author:
aercolino
Message:

Moved Enzymes3::PREFIX to EnzymesOptions::PREFIX.
Introduced Enzymes3::GLOBAL_POST for better documenting calls to EnzymesPlugin::engine()->metabolize().
Introduced Enzymes3::NO_POST for forcing no post in calls to EnzymesPlugin::engine()->metabolize().
Introduced Enzymes3::NO_POST_AUTHOR for getting a handle to a user in calls to EnzymesPlugin::engine()->metabolize().
Renamed Enzymes3::$current_post to Enzymes3::$injection_post.
Formatted code according to a new style where consecutive assignments get aligned and arrays elements get indented only a double size.
Fixed post selection by slug.
Improved differences between the post hosting an injection and the post hosting a field, also considering the new NO_POST and NO_POST_AUTHOR concepts.
Renamed Enzymes3::belongs_to_current_author() to Enzymes3::injection_author_owns().
Fixed null posts.
Implemented backward compatibility with Enzymes version 2. Now Enzymes version 3 will detect the version of an injection and ignore it if coming from version 2. Then version 2 will take on as usual because its filters have the same priority but are added after those from version 3.
Added EnzymesCapabilities::PREFIX, different from the new EnzymesOptions::PREFIX.
Saved the activation date for later determining a meaningful default for Enzymes version of injections. You can force by using =enzymes 2=|.. or =enzymes 3=|.. at the start of a sequence.
All green tests, but need to add some more.

Location:
enzymes/trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • enzymes/trunk/enzymes.php

    r1063085 r1064687  
    1010*/
    1111
     12
    1213define('ENZYMES_FILENAME', __FILE__);
    13 require 'src/EnzymesPlugin.php';
     14require_once 'src/EnzymesPlugin.php';
    1415
    1516$enzymesPlugin = new EnzymesPlugin();
     17
     18
     19
     20// ---------------------------------------------------------------------------------------------------------------------
     21// The following code will allow old version 2 enzymes sequences to work exactly as they did.
     22require_once 'enzymes.2/enzymes.php';
     23// ---------------------------------------------------------------------------------------------------------------------
  • enzymes/trunk/src/Enzymes3.php

    r1063307 r1064687  
    77class Enzymes3
    88{
    9     const PREFIX = 'enzymes.';
     9    /**
     10     *  When calling the engine directly, for forcing the global post, use one of the following:
     11     * - EnzymesPlugin::engine()->metabolize($content);
     12     * - EnzymesPlugin::engine()->metabolize($content, null);
     13     * - EnzymesPlugin::engine()->metabolize($content, Enzymes3::GLOBAL_POST);
     14     */
     15    const GLOBAL_POST = null;
     16
     17    /**
     18     * When calling the engine directly, for forcing no post at all, use one of the following:
     19     * - EnzymesPlugin::engine()->metabolize($content, Enzymes3::NO_POST);
     20     */
     21    const NO_POST = -1;
     22
     23    /**
     24     * When calling the engine directly, ID of the user to consider the author after forcing no post.
     25     */
     26    const NO_POST_AUTHOR = 1;
    1027
    1128    /**
     
    3350    /**
    3451     * The post which the content belongs to.
     52     * It can be null if the developer forced no post with ->metabolize($content, Enzymes3::NO_POST).
    3553     *
    3654     * @var WP_Post
    3755     */
    38     protected $current_post;
     56    protected $injection_post;
    3957
    4058    /**
     
    187205                'injection'    => '(?<injection>{[$sequence]})',
    188206        );
    189         $result = array();
     207        $result  = array();
    190208        foreach ($grammar as $symbol => $rule) {
    191             $regex = new Ando_Regex($rule);
     209            $regex           = new Ando_Regex($rule);
    192210            $result[$symbol] = $regex->interpolate($result);
    193211        }
     
    201219    function init_e_injection()
    202220    {
    203         $before = new Ando_Regex('(?<before>.*?)');
     221        $before             = new Ando_Regex('(?<before>.*?)');
    204222        $could_be_injection = new Ando_Regex('\{\[(?<could_be_sequence>.*?)\]\}');
    205         $after = new Ando_Regex('(?<after>.*)');
    206         $content = new Ando_Regex('^$before$could_be_injection$after$', '@@s');
     223        $after              = new Ando_Regex('(?<after>.*)');
     224        $content            = new Ando_Regex('^$before$could_be_injection$after$', '@@s');
    207225        $content->interpolate(array(
    208                                       'before'             => $before,
    209                                       'could_be_injection' => $could_be_injection,
    210                                       'after'              => $after,
    211                               ));
     226                'before'             => $before,
     227                'could_be_injection' => $could_be_injection,
     228                'after'              => $after,
     229        ));
    212230        $this->e_injection = $content;
    213231    }
     
    222240        $sequence_valid = new Ando_Regex(Ando_Regex::option_same_name() . '^(?:\|$enzyme)+$', '@@');
    223241        $sequence_valid->interpolate(array(
    224                                              'enzyme' => $this->grammar['enzyme'],
    225                                      ));
     242                'enzyme' => $this->grammar['enzyme'],
     243        ));
    226244        $this->e_sequence_valid = $sequence_valid;
    227245    }
     
    233251    function init_e_sequence_start()
    234252    {
    235         $rest = new Ando_Regex('(?:\|(?<rest>.+))');
     253        $rest           = new Ando_Regex('(?:\|(?<rest>.+))');
    236254        $sequence_start = new Ando_Regex(Ando_Regex::option_same_name() . '^$enzyme$rest?$', '@@');
    237255        $sequence_start->interpolate(array(
    238                                              'enzyme' => $this->grammar['enzyme'],
    239                                              'rest'   => $rest,
    240                                      ));
     256                'enzyme' => $this->grammar['enzyme'],
     257                'rest'   => $rest,
     258        ));
    241259        $this->e_sequence_start = $sequence_start;
    242260    }
     
    250268        $maybe_quoted = new Ando_Regex('(?<before_string>.*?)$string|(?<anything_else>.+)', '@@s');
    251269        $maybe_quoted->interpolate(array(
    252                                            'string' => $this->grammar['string'],
    253                                    ));
     270                'string' => $this->grammar['string'],
     271        ));
    254272        $this->e_string = $maybe_quoted;
    255273    }
     
    268286        $this->e_comment = new Ando_Regex('\/\*.*?\*\/', '@@s');
    269287        // for some reason WP introduces some C2 (hex) chars when writing a post...
    270         $this->e_unbreakable_space = new Ando_Regex('\xC2\xA0', '@@');
    271         $this->e_all_spaces = new Ando_Regex('(?:\s|\xC2\xA0)+', '@@');
     288        $this->e_unbreakable_space           = new Ando_Regex('\xC2\xA0', '@@');
     289        $this->e_all_spaces                  = new Ando_Regex('(?:\s|\xC2\xA0)+', '@@');
    272290        $this->e_escaped_injection_delimiter = new Ando_Regex('\\\\([{[\]}])', '@@');
    273         $this->e_escaped_string_delimiter = new Ando_Regex('\\\\=', '@@');
     291        $this->e_escaped_string_delimiter    = new Ando_Regex('\\\\=', '@@');
    274292    }
    275293
     
    279297        $this->init_grammar();
    280298        $this->init_expressions();
    281         $this->options = new EnzymesOptions(self::PREFIX);
     299        $this->options = new EnzymesOptions();
    282300    }
    283301
     
    293311        array_shift($keys);
    294312        $default = array_fill_keys($keys, '');
    295         $hash = array_merge($default, $hash);
     313        $hash    = array_merge($default, $hash);
    296314    }
    297315
     
    334352        switch (true) {
    335353            case ($post == ''):
    336                 $result = $this->current_post;
     354                $result = $this->injection_post;
    337355                break;
    338356            case ($post[0] == '@'):
    339                 $result = get_page_by_path($slug, OBJECT, 'post');
     357                // We can't use the following API call because we want all post types.
     358                //$result = get_page_by_path($slug, OBJECT, 'post');
     359                global $wpdb;
     360                $post_id = $wpdb->get_var("SELECT `ID` FROM $wpdb->posts WHERE `post_name` = '$slug' LIMIT 1");
     361                $result  = get_post($post_id);
    340362                break;
    341363            case (is_numeric($post)):
     
    475497    function wp_author( $post_object )
    476498    {
    477         $id = $post_object->post_author;
     499        $id     = $post_object->post_author;
    478500        $result = get_user_by('id', $id);
    479501        return $result;
     
    481503
    482504    /**
     505     * True if the current post's author can exercise the capability.
     506     *
     507     * @param string $capability
     508     *
     509     * @return bool
     510     */
     511    protected
     512    function injection_author_can( $capability )
     513    {
     514        if ( is_null($this->injection_post) ) {
     515            $result = user_can(self::NO_POST_AUTHOR, $capability);
     516        } else {
     517            $result = author_can($this->injection_post, $capability);
     518        }
     519        return $result;
     520    }
     521
     522    /**
    483523     * True if the post belongs to the current post's author.
    484524     *
     
    488528     */
    489529    protected
    490     function belongs_to_current_author( $post_object )
    491     {
    492         $result = $this->current_post->post_author == $post_object->post_author;
     530    function injection_author_owns( $post_object )
     531    {
     532        if ( is_null($this->injection_post) ) {
     533            $result = self::NO_POST_AUTHOR == $post_object->post_author;
     534        } else {
     535            $result = $this->injection_post->post_author == $post_object->post_author;
     536        }
    493537        return $result;
    494538    }
     
    507551    {
    508552        if ( author_can($post_object, EnzymesCapabilities::create_dynamic_custom_fields) &&
    509              ($this->belongs_to_current_author($post_object) ||
     553             ($this->injection_author_owns($post_object) ||
    510554              author_can($post_object, EnzymesCapabilities::share_dynamic_custom_fields) &&
    511               author_can($this->current_post, EnzymesCapabilities::use_others_custom_fields))
     555              $this->injection_author_can(EnzymesCapabilities::use_others_custom_fields))
    512556        ) {
    513557            list($result,) = $this->safe_eval($code, $arguments);
     
    536580        preg_match($expression, $post_item, $matches);
    537581        $post_object = $this->wp_post($matches);
    538         $code = $this->wp_post_field($post_object, $matches);
     582        if ( ! $post_object instanceof WP_Post ) {
     583            return null;
     584        }
     585        $code      = $this->wp_post_field($post_object, $matches);
    539586        $arguments = $num_args > 0
    540587                ? $this->catalyzed->pop($num_args)
    541588                : array();
    542         $result = $this->execute_code($code, $arguments, $post_object);
     589        $result    = $this->execute_code($code, $arguments, $post_object);
    543590        return $result;
    544591    }
     
    561608        preg_match($expression, $author_item, $matches);
    562609        $post_object = $this->wp_post($matches);
     610        if ( ! $post_object instanceof WP_Post ) {
     611            return null;
     612        }
    563613        $user_object = $this->wp_author($post_object);
    564         $code = $this->wp_user_field($user_object, $matches);
    565         $arguments = $num_args > 0
     614        $code        = $this->wp_user_field($user_object, $matches);
     615        $arguments   = $num_args > 0
    566616                ? $this->catalyzed->pop($num_args)
    567617                : array();
    568         $result = $this->execute_code($code, $arguments, $post_object);
     618        $result      = $this->execute_code($code, $arguments, $post_object);
    569619        return $result;
    570620    }
     
    592642                break;
    593643            case (strpos($execution, 'hash(') === 0 && $num_args > 0):
    594                 $result = array();
     644                $result    = array();
    595645                $arguments = $this->catalyzed->pop(2 * $num_args);
    596646                for ($i = 0, $i_top = 2 * $num_args; $i < $i_top; $i += 2) {
    597                     $key = $arguments[$i];
    598                     $value = $arguments[$i + 1];
     647                    $key          = $arguments[$i];
     648                    $value        = $arguments[$i + 1];
    599649                    $result[$key] = $value;
    600650                }
     
    625675    {
    626676        if ( author_can($post_object, EnzymesCapabilities::create_dynamic_custom_fields) &&
    627              ($this->belongs_to_current_author($post_object) ||
     677             ($this->injection_author_owns($post_object) ||
    628678              author_can($post_object, EnzymesCapabilities::share_dynamic_custom_fields) &&
    629               author_can($this->current_post, EnzymesCapabilities::use_others_custom_fields))
     679              $this->injection_author_can(EnzymesCapabilities::use_others_custom_fields))
    630680        ) {
    631681            list(, $output) = $this->safe_eval(" ?>$code<?php ");
    632682        } elseif ( author_can($post_object, EnzymesCapabilities::create_static_custom_fields) &&
    633                    ($this->belongs_to_current_author($post_object) ||
     683                   ($this->injection_author_owns($post_object) ||
    634684                    author_can($post_object, EnzymesCapabilities::share_static_custom_fields) &&
    635                     author_can($this->current_post, EnzymesCapabilities::use_others_custom_fields))
     685                    $this->injection_author_can(EnzymesCapabilities::use_others_custom_fields))
    636686        ) {
    637687            $output = $code;
     
    658708                                                 ->expression(true);
    659709        preg_match($expression, $post_item, $matches);
    660         $code = $this->wp_post_field($post_object, $matches);
     710        $code   = $this->wp_post_field($post_object, $matches);
    661711        $output = $this->transclude_code($code, $post_object);
    662712        return $output;
     
    680730        preg_match($expression, $author_item, $matches);
    681731        $user_object = $this->wp_author($post_object);
    682         $code = $this->wp_user_field($user_object, $matches);
    683         $output = $this->transclude_code($code, $post_object);
     732        $code        = $this->wp_user_field($user_object, $matches);
     733        $output      = $this->transclude_code($code, $post_object);
    684734        return $output;
    685735    }
     
    698748    {
    699749        $this->debug_print('transcluding post_attr');
    700         $same_author = $this->belongs_to_current_author($post_object);
     750        $same_author = $this->injection_author_owns($post_object);
    701751        if ( $same_author && author_can($post_object, EnzymesCapabilities::use_own_attributes) ||
    702              ! $same_author && author_can($this->current_post, EnzymesCapabilities::use_others_attributes)
     752             ! $same_author &&
     753             $this->injection_author_can(EnzymesCapabilities::use_others_attributes)
    703754        ) {
    704755            $expression = $this->grammar['post_attr']->wrapper_set('@@')
     
    725776    {
    726777        $this->debug_print('transcluding author_attr');
    727         $same_author = $this->belongs_to_current_author($post_object);
     778        $same_author = $this->injection_author_owns($post_object);
    728779        if ( $same_author && author_can($post_object, EnzymesCapabilities::use_own_attributes) ||
    729              ! $same_author && author_can($this->current_post, EnzymesCapabilities::use_others_attributes)
     780             ! $same_author &&
     781             $this->injection_author_can(EnzymesCapabilities::use_others_attributes)
    730782        ) {
    731783            $expression = $this->grammar['author_attr']->wrapper_set('@@')
     
    733785            preg_match($expression, $author_attr, $matches);
    734786            $user_object = $this->wp_author($post_object);
    735             $result = $this->wp_user_attribute($user_object, $matches);
     787            $result      = $this->wp_user_attribute($user_object, $matches);
    736788        } else {
    737789            $result = null;
     
    757809        /* @var $author_attr string */
    758810        $post_object = $this->wp_post($matches);
     811        if ( ! $post_object instanceof WP_Post ) {
     812            return null;
     813        }
    759814        switch (true) {
    760815            case ($post_item != ''):
     
    795850                ? $before_string
    796851                : $anything_else;
    797         $result = preg_replace($this->e_all_spaces, '', $outside) .
    798                   preg_replace($this->e_unbreakable_space, ' ', $string);  // normal spaces are meaningful in $string
     852        $result  = preg_replace($this->e_all_spaces, '', $outside) .
     853                   preg_replace($this->e_unbreakable_space, ' ', $string);  // normal spaces are meaningful in $string
    799854        return $result;
    800855    }
     
    824879    }
    825880
     881    protected
     882    function default_version()
     883    {
     884        // The injection_post at this point of the execution can be null only in version 3 because
     885        // in version 2 it follows a different path, i.e. it would go straight into the Enzymes class
     886        // by means of a call to the global metabolize() function. --
     887        if ( is_null($this->injection_post) ) {
     888            return 3;
     889        }
     890        // By looking at these dates we can only assume a default version, because another one
     891        // could have been forced by the user right into an injection. --
     892        $result = $this->injection_post->post_modified_gmt <= EnzymesPlugin::activated_on()
     893                ? 2
     894                : 3;
     895        return $result;
     896    }
     897
     898    /**
     899     * @param string $sequence
     900     *
     901     * @return false|string
     902     */
     903    protected
     904    function sequence_version( &$sequence )
     905    {
     906        $result          = $this->default_version();
     907        $forced_2_prefix = '=enzymes.2=|';
     908        $forced_3_prefix = '=enzymes.3=|';
     909        switch (true) {
     910            case (0 === strpos($sequence, $forced_2_prefix)):
     911                $sequence = substr($sequence, strlen($forced_2_prefix));
     912                $result   = 2;
     913                break;
     914            case (0 === strpos($sequence, $forced_3_prefix)):
     915                $sequence = substr($sequence, strlen($forced_3_prefix));
     916                $result   = 3;
     917                break;
     918        }
     919        return $result;
     920    }
     921
    826922    /**
    827923     * Process the enzymes in the matched sequence.
     
    834930    function process( $could_be_sequence )
    835931    {
    836         $sequence = $this->clean_up($could_be_sequence);
     932        $sequence                       = $this->clean_up($could_be_sequence);
    837933        $there_are_only_chained_enzymes = preg_match($this->e_sequence_valid, '|' . $sequence);
    838 //        $this->debug_print($this->e_sequence_valid . '');
    839934        if ( ! $there_are_only_chained_enzymes ) {
    840             $result = '{[' . $could_be_sequence . ']}';  // skip this injection like if it had been escaped...
     935            $result = '{[' . $could_be_sequence . ']}';  // skip this injection AS IS
     936        } elseif ( $this->sequence_version($sequence) == 2 ) {
     937            $result = '{[' . $sequence . ']}';           // skip this injection
     938            // after stripping out the forced version from $sequence, it any
    841939        } else {
    842940            $this->catalyzed = new EnzymesSequence();
    843             $rest = $sequence;
     941            $rest            = $sequence;
    844942            while (preg_match($this->e_sequence_start, $rest, $matches)) {
    845943                $this->default_empty($matches, 'execution', 'transclusion', 'literal', 'str_literal', 'number', 'rest');
     
    890988
    891989    /**
     990     * @param $args
     991     *
     992     * @return array
     993     */
     994    protected
     995    function get_injection_post( $args )
     996    {
     997        list(, $post) = array_pad($args, 2, null);
     998        if ( $post instanceof WP_Post ) {
     999            return array(true, $post);
     1000        }
     1001        if ( $post == self::NO_POST ) {
     1002            return array(true, null);
     1003        }
     1004        // Some filters of ours do not pass the 2nd argument, while others pass a post ID, but
     1005        // 'wp_title' pass a string separator, so we fix this occurrence.
     1006        $post_id = current_filter() == 'wp_title' ? null : $post;
     1007        $post = get_post($post_id);
     1008        if ( is_null($post) ) {
     1009            // Consider this an error, because the developer didn't force no post.
     1010            return array(false, null);
     1011        }
     1012        return array(true, $post);
     1013    }
     1014
     1015    /**
    8921016     * Process the injected sequences in the content we are filtering.
    8931017     *
    894      * @param string       $content
    895      * @param null|WP_Post $default_post
     1018     * @param string $content
    8961019     *
    8971020     * @return array|null|string
    8981021     */
    8991022    public
    900     function metabolize( $content, $default_post = null )
    901     {
    902         $this->current_post = is_object($default_post)
    903                 ? $default_post
    904                 : get_post();
    905         if ( is_null($this->current_post) ) {
     1023    function metabolize( $content )
     1024    {
     1025        $args = func_get_args();
     1026        list($continue, $this->injection_post) = $this->get_injection_post($args);
     1027        if ( ! $continue ) {
    9061028            return $content;
    9071029        }
    908         if ( ! author_can($this->current_post, EnzymesCapabilities::inject) ) {
     1030        if ( ! $this->injection_author_can(EnzymesCapabilities::inject) ) {
    9091031            return $content;
    9101032        }
  • enzymes/trunk/src/EnzymesCapabilities.php

    r1063285 r1064687  
    33class EnzymesCapabilities
    44{
     5    const PREFIX = 'enzymes.';
    56
    67//@formatter:off
  • enzymes/trunk/src/EnzymesOptions.php

    r1063306 r1064687  
    33class EnzymesOptions
    44{
    5     /**
    6      * @var string
    7      */
    8     protected $prefix;
    9 
    10     /**
    11      * @param string $prefix
    12      */
    13     public
    14     function __construct( $prefix = null )
    15     {
    16         $this->prefix = $prefix;
    17     }
     5    const PREFIX = 'Enzymes3.';
    186
    197    /**
     
    2715    function name( $username = null )
    2816    {
    29         $result = $this->prefix . ($username
     17        $result = self::PREFIX . ($username
    3018                        ? $username
    3119                        : 'global_options');
     
    5644    {
    5745        global $wpdb;
    58         $wpdb->query("DELETE FROM `$wpdb->options` WHERE `option_name` LIKE '{$this->prefix}%'");
     46        $prefix = self::PREFIX;
     47        $wpdb->query("DELETE FROM `$wpdb->options` WHERE `option_name` LIKE '{$prefix}%'");
    5948    }
    6049
  • enzymes/trunk/src/EnzymesPlugin.php

    r1063306 r1064687  
    120120
    121121        foreach ($wp_roles->roles as $name => $role) {
    122             if ( 0 === strpos($name, Enzymes3::PREFIX) ) {
     122            if ( 0 === strpos($name, EnzymesCapabilities::PREFIX) ) {
    123123                remove_role($name);
    124124            }
     
    126126
    127127        foreach (EnzymesCapabilities::all() as $cap) {
    128             if ( 0 === strpos($cap, Enzymes3::PREFIX) ) {
     128            if ( 0 === strpos($cap, EnzymesCapabilities::PREFIX) ) {
    129129                $wp_roles->remove_cap('administrator', $cap);
    130130            }
     
    132132    }
    133133
     134    static public
     135    function activated_on() {
     136        $options = self::$options->keysGet(array('activated_on'));
     137        return $options['activated_on'];
     138    }
     139
    134140}
  • enzymes/trunk/tests/test-Enzymes3.php

    r1063285 r1064687  
    168168
    169169        $target_post_id = $this->factory->post->create(array('post_title' => 'This is the target post.'));
    170         $target         = get_post($target_post_id);
    171170
    172171        $enzymes = new Enzymes3();
     
    178177
    179178        // this must return the target post (default)
    180         $enzymes->metabolize('This post has a {[ fake ]} injection.', $target);
     179        $enzymes->metabolize('This post has a {[ fake ]} injection.', $target_post_id);
    181180        $result = $this->call_method('wp_post', array(array()), $enzymes);
    182181        $this->assertEquals($target_post_id, $result->ID);
    183182
    184183        // this must return the target post (numeric)
    185         $enzymes->metabolize('This post has a {[ fake ]} injection.', $target);
     184        $enzymes->metabolize('This post has a {[ fake ]} injection.', $target_post_id);
    186185        $result = $this->call_method('wp_post', array(array('post' => $post->ID)), $enzymes);
    187186        $this->assertEquals($post->ID, $result->ID);
    188187
    189188        // this must return the target post (slug)
    190         $enzymes->metabolize('This post has a {[ fake ]} injection.', $target);
     189        $enzymes->metabolize('This post has a {[ fake ]} injection.', $target_post_id);
    191190        $result = $this->call_method('wp_post', array(
    192191                array(
Note: See TracChangeset for help on using the changeset viewer.