Please upgrade here. These earlier versions are no longer being updated and have security issues.
HackerOne users: Testing against this community violates our program's Terms of Service and will result in your bounty being denied.

This small piece of bootstrap.before code stopped working with 2.5?

edited March 2018 in Vanilla 2.0 - 2.8

The code below changes the anchor for usernames that display next to each post. It's no longer working with 2.5. Any ideas?

    <?php if (!defined('APPLICATION')) exit();
    function UserUrl($User, $Px = '', $Method = '', $Get = FALSE){
        $UserName = GetValue('Name', $User);
        $Result = 'https://www.mywebsite.com/'.$UserName;
        if ($Get)
            $Result .= '?'.http_build_query($Get);
        return $Result;
    }

Comments

  • It seems like that in Vanilla 2.3 /conf/bootstrap.before.php was loaded in bootstrap.php (line 18), but in Vanilla 2.5 they got rid of bootstrap.before, now only bootstrap.early is left.

    Easiest fix is of course to rename bootstrap.before.php to bootstrap.early.php, but I'm a plugin guy so I personally think the best solution is to write a plugin (If all you have is a hammer, everything looks like a nail).

    If you follow the steps detailed here https://docs.vanillaforums.com/developer/addons/addon-quickstart/#1-name-your-addon you can create your own plugin.

    <?php
    
    if (!defined('APPLICATION'))
        die();
    
    $PluginInfo['FunctionOverride'] = array(
        'Name' => 'FunctionOverride',
        'Description' => 'Overrides default Vanilla functions',
        'Version' => '1.0',
        'License' => 'GPL v2',
        'RequiredApplications' => array('Vanilla' => '>=2.5')
    );
    
    class FunctionOverridePlugin extends Gdn_Plugin {
    }
    
    //must be outside class declaration to override Vanilla function!
     function UserUrl($User, $Px = '', $Method = '', $Get = FALSE){
            $UserName = GetValue('Name', $User);
            $Result = 'https://www.mywebsite.com/'.$UserName;
            if ($Get)
                $Result .= '?'.http_build_query($Get);
            return $Result;
     }
    
  • edited March 2018

    Thank you, @Caylus. Sorry but I'm actually mistaken about this. The above bit of code is about changing the anchor for poster's username and this is actually working fine within bootstrap.before. What isn't working is some code that changes the username anchor when posted as a 'mention'. Ironically, this is referenced in bootstrap.early.

    If you can fix below (or ideally combine it into a plugin with your code mentioned earlier), I would happily send another $50 as a thank you.

    Changing username anchor when posted as a mention

    /conf/bootstrap.early

        <?php if (!defined('APPLICATION')) exit();
        Gdn::FactoryInstall('MentionsFormatter', 'CustomMentions', PATH_CONF . '/custommentions.php');
    

    /conf/custommentions.php

    <?php if (!defined('APPLICATION')) exit();
    class CustomMentions {
        public function FormatMentions($Body) {
            return preg_replace(
                   '/(^|[\s,\.>])@(\w{1,50})\b/i', //{3,20}
                   '\1'.Anchor('@\2', 'https://www.mywebsite.com/\\2'),
                   $Body
                );
        }
    
    
    public function getMentions($Mixed) {
    
                 $Formatter = Gdn::Factory('MentionsFormatter');
             if (is_object($Formatter)) {
                return $Formatter->FormatMentions($Mixed);
             }
             // Handle @mentions.
             if(C('Garden.Format.Mentions')) {
                $Mixed = preg_replace(
                   '/(^|[\s,\.>])@(\w{1,50})\b/i', //{3,20}
                   '\1'.Anchor('@\2', '/profile/\\2'),
                   $Mixed
                );
             }
    
             // Handle #hashtag searches
                if(C('Garden.Format.Hashtags')) {
                    $Mixed = preg_replace(
                        '/(^|[\s,\.>])\#([\w\-]+)(?=[\s,\.!?]|$)/i',
                        '\1'.Anchor('#\2', '/search?Search=%23\2&Mode=like').'\3',
                        $Mixed
                    );
                }
    
                // Handle "/me does x" action statements
             if(C('Garden.Format.MeActions')) {
                $Mixed = preg_replace(
                   '/(^|[\n])(\/me)(\s[^(\n)]+)/i',
                   '\1'.Wrap(Wrap('\2', 'span', array('class' => 'MeActionName')).'\3', 'span', array('class' => 'AuthorAction')),
                   $Mixed
                );
             }
    
             return $Mixed;
    
        }
    
    }
    
  • CaylusCaylus ✭✭
    edited March 2018

    Oooh they changed the position where bootstrap.before is included, they didn't get rid of it.
    Sneaky sneaky. It's now included in environment.php, not bootstrap.php.

    But on to your current problem: There seems to be an issue with the Factory thingy.

    Gdn::FactoryInstall('MentionsFormatter', 'CustomMentions', PATH_CONF . '/custommentions.php'); nicely supplies a path to the class, but inside the Factory install function the path to that class is never used.

    Since custommentions.php is never included, the CustomMentions class never exists.

    So three possibilities: a) you simply add a require_once PATH_CONF . '/custommentions.php' to bootstrap.early.php, b) you copy paste the class definition code to bootstrap.early.php, c) you use the following plugin:

    EDIT: You'd have to remove the UserUrl from either this plugin or your bootstrap.before file, otherwise it throws an error because it's twice defined.

    <?php
    if (!defined('APPLICATION'))
        die();
    $PluginInfo['FunctionOverride'] = array(
        'Name' => 'FunctionOverride',
        'Description' => 'Overrides default Vanilla functions',
        'Version' => '1.0',
        'License' => 'GPL v2',
        'RequiredApplications' => array('Vanilla' => '>=2.5')
    );
    class FunctionOverridePlugin extends Gdn_Plugin {
    }
    
    //must be outside class declaration to override Vanilla function!
     function UserUrl($User, $Px = '', $Method = '', $Get = FALSE){
            $UserName = GetValue('Name', $User);
            $Result = 'https://www.mywebsite.com/'.$UserName;
            if ($Get)
                $Result .= '?'.http_build_query($Get);
            return $Result;
     }
    
    class MentionsFormatter {
        public function formatMentions($Body) {
            return preg_replace(
                   '/(^|[\s,\.>])@(\w{1,50})\b/i', //{3,20}
                   '\1'.Anchor('@\2', 'https://www.mywebsite.com/\\2'),
                   $Body
                );
        }
    }
    //placed this function override outside of class definition, because otherwise it wouldn't override the function you wanted to override
    
    function getMentions($Mixed) {
                 $Formatter = Gdn::Factory('MentionsFormatter');
             if (is_object($Formatter)) {
                return $Formatter->FormatMentions($Mixed);
             }
             // Handle @mentions.
             if(C('Garden.Format.Mentions')) {
                $Mixed = preg_replace(
                   '/(^|[\s,\.>])@(\w{1,50})\b/i', //{3,20}
                   '\1'.Anchor('@\2', '/profile/\\2'),
                   $Mixed
                );
             }
             // Handle #hashtag searches
                if(C('Garden.Format.Hashtags')) {
                    $Mixed = preg_replace(
                        '/(^|[\s,\.>])\#([\w\-]+)(?=[\s,\.!?]|$)/i',
                        '\1'.Anchor('#\2', '/search?Search=%23\2&Mode=like').'\3',
                        $Mixed
                    );
                }
                // Handle "/me does x" action statements
             if(C('Garden.Format.MeActions')) {
                $Mixed = preg_replace(
                   '/(^|[\n])(\/me)(\s[^(\n)]+)/i',
                   '\1'.Wrap(Wrap('\2', 'span', array('class' => 'MeActionName')).'\3', 'span', array('class' => 'AuthorAction')),
                   $Mixed
                );
             }
             return $Mixed;
        }
    
  • edited March 2018

    Awesome, thanks. Your require_once fix worked but I couldn't use the plugin as it made the whole forum give a 500 error.

    Did I create the plugin wrong? Please see attached.

    EDIT: I also removed the code from bootstrap.before and bootstrap.early but same 500 error.

  • This is odd again.

    According to the docs, overriding functions declared in functions.general.php at the bottom of a plugin is the preferred method of extending functionality (because it's easy to disable/enable, presumably).

    https://docs.vanillaforums.com/developer/addons/function-overrides/

    But you're right, that works for UserUrl() (which is not located in functions.general.php), but for getMentions it doesn't work (which is located in functions.general.php).

    I'll report an issue on the GitHub, but I fear you might be stuck with declaring the functions in bootstrap.early.php after all.

  • edited March 2018

    Thanks for your help. I'll stick to the non-plugin solution for now then :)

  • R_JR_J Admin

    environment.php loads first, which includes conf/bootstrap.before.php and later on composers autoloader which includes the functions.general.php

    After the environment.php the bootstrap.php is called which includes the plugins: too late for overriding something from functions.general.php.

    I have written a custom mention formatter a few years ago and had to provide a bootstrap.before snippet because of this problem. Although it is a problem, I don't think it is an issue.

  • Ah, so it's probably not something that will be fixed easily. Thanks for the info R_J!

    @w1ckedsick schrieb:
    Thanks for your help. I'll stick to the non-plugin solution for now then :)

    Glad to be of help and thanks for the 50 bucks again :D

Sign In or Register to comment.