Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Try Vanilla Forums Cloud product

Ready to contribute?

Amazing! Sign our contributors' agreement and then join us on GitHub.

Update for critical security issue in PHPMailer included in release Vanilla 2.3.1

Pockets Panel Position Index

edited September 11 in Vanilla 2.3 Help

Hi i used pockets and really works excellent, i have a doubt,

  • With this configuration it works perfectly:

    Page; discussions / Location: Panel /Repeat; After

  • With this configuration it does not work:

    Page; discussions / Location: Panel /Repeat; Index: 4.

I would like the pockets to appear above the online now, attached image.

Comments

  • I have already installed it, but it does not have any documentation how it works, I add the module OnlineNow in Conversations and I put it of last and it does not change anything in the panel,

    Regards,

  • I have read the documentation to order the changes but Pockets is a plugin, and OnlineNow is a module, I still do not understand how to add Pockets in the order.

  • vrijvlindervrijvlinder Papillon-Sauvage MVP

    It works by reordering the modules to what you want. Maybe try the plugin Widgets, it creates modules that can be sorted and you can put anything in them.

  • Thks @vrijvlinder excelent your pluging widgets, create twitter feed and disable css to avoid breaking the css of the boostrap theme,

    Modules Orders:

    config.php

    $Configuration['Modules']['Vanilla']['Panel'] = array('MeModule', 'UserBoxModule', 'GuestModule', 'NewDiscussionModule', 'DiscussionFilterModule', 'SignedInModule', 'Ads', 'CategoriesModule', 'ArticlesModule', 'TagModule', 'TwitterModule', 'OnlineNowModule');

    Regards

    Resolved.

  • @vrijvlinder What would be the best practice to add permission to view by role the modules created with the plugin widgets,

    regards,

  • vrijvlindervrijvlinder Papillon-Sauvage MVP
    edited September 12

    You would need to enact permissions to each module.

    here is an example,check for valid session only moderators can see, if it is not the moderator, it will not be loaded.

    public function AssetTarget() {
         $Session = Gdn::Session();
         if ($Session->CheckPermission('Garden.Moderation.Manage')) {
        return 'Panel'; 
    
    } else { 
    
    return;
     }
    
  • @vrijvlinder it would be great to be able to add, for example, the view permission for each of the roles, edit it in the panel and be able to display the widgets for each role (Admin, Moderator, Member, Guest),

    Regards,

  • vrijvlindervrijvlinder Papillon-Sauvage MVP
    edited September 12

    I think you could do that, it's just a matter of creating all the modules for each role and giving them permissions to check for each role. It can be a bit complicated but I am sure it can be done.

    I can't help you do it at the moment I am too busy, but I am sure @R_J could , he is a wizard ...

    You could check:

    if admin
    if member
    if moderator
    if x role

    Based on who it is the modules would show or not show.

  • edited September 12

    @vrijvlinder I have created the function to see for the widgets addon, in a simple way, so that they are seen by roles, of course it would be interesting to do it by module:

    Code:

    Modify default.php --> addon widget

    $PluginInfo['Widgets'] = array(
         'Name' => 'Widgets',
         'Description' => "This plugin adds modules/widgets you create to the panel . ",
         'Version' => '1.1',
         'RegisterPermissions' => array('Plugins.Widgets.View'), ---> Add Permission for Role.
         'Author' => "VrijVlinder",
         'AuthorEmail' => 'contact@vrijvlinder.com',
         'AuthorUrl' => "http://www.vrijvlinder.com"
    );
    

    Modify class.twittermodule ---> Widget Twetter Feed.

    <?php if (!defined('APPLICATION')) exit();
    
        class TwitterModule extends Gdn_Module {
    
        public function AssetTarget() {
            $Session = Gdn::Session();
            if ($Session->CheckPermission('Plugins.Widgets.View')) { ---> Check Permission for Role.
                return 'Panel';
             }
         } 
    
         public function ToString() {
    
             echo '<div class="Box" id="Twitter"><h4>Twitter Feed</h4>
                 <a class="twitter-timeline" data-lang="es" data-dnt="true" data-theme="dark" data-tweet-limit="1" 
                  href="https://twitter.com/UserTwitter">Tweets by UserTwitter</a> 
                 <script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
             </div>';
         }
    }
    

    Any suggestions, I have tried and it works well,

    Regards,

    vrijvlinder
  • vrijvlindervrijvlinder Papillon-Sauvage MVP

    Yes the simplest way is to obfuscate the plugin entirely based on roles, but I think it would be better to do it by module.

    Since you can create an unlimited amount of modules, it would be better by module.

  • R_JR_J Cheerleader & Troubleshooter Munich Moderator

    That should help: https://open.vanillaforums.com/discussion/comment/225254/#Comment_225254

    Create a plugin called "moduleVisibility" or whatever, add some permissions to the info array like that
    Plugins.ModuleVisibility.Twitter.View

    Then assign this permission to the appropriate roles. In the code do the following checks
    Is that module part of the assets array
    If yes, check if the user has the permission to see it
    If not, unset it

    terabytefrelance
  • edited September 12

    @vrijvlinder @r_j

    It is extremely simple, with the widgets module, and this we can have all the modules in an orderly way and with the permissions as if it were a plugin

    Config Widget Plugin: default.php:

    $PluginInfo['Widgets'] = array(
         'Name' => 'Widgets',
         'Description' => "This plugin adds modules/widgets you create to the panel . ",
         'Version' => '1.1',
         'RegisterPermissions' => array('Plugins.Widgets.Twitter.View', 'Plugins.Widgets.Facebook.View', 
         'Plugins.Widgets.Youtube.View'), ---> Permissions Modules Widgets.
         'Author' => "VrijVlinder",
         'AuthorEmail' => 'contact@vrijvlinder.com',
         'AuthorUrl' => "http://www.vrijvlinder.com"
    );
    

    // Check Permissions: class.twittermodule.php

    public function AssetTarget() {
        $Session = Gdn::Session();
        if ($Session->CheckPermission('Plugins.Widgets.Twitter.View')) {
            return 'Panel';
        }
    } 
    

    Thank you very much indeed, I hope you can modify your plugin so that more people can see it and learn more about Vanilla Forum, that's what makes free software really powerful when they are well thought out.

    vrijvlinder
  • vrijvlindervrijvlinder Papillon-Sauvage MVP

    Awesome work ! Widgets is free to modify as you did to work for you. I made it just to make easier for people to add modules and sort them. You have extended it and that is great !!

    Send me the modified plugin and I will update it to include permission models.

  • R_JR_J Cheerleader & Troubleshooter Munich Moderator
    edited September 13

    @terabytefrelance said:
    @vrijvlinder @r_j

    It is extremely simple, with the widgets module, and this we can have all the modules in an orderly way and with the permissions as if it were a plugin

    Config Widget Plugin: default.php:

    $PluginInfo['Widgets'] = array(
         'Name' => 'Widgets',
         'Description' => "This plugin adds modules/widgets you create to the panel . ",
         'Version' => '1.1',
         'RegisterPermissions' => array('Plugins.Widgets.Twitter.View', 'Plugins.Widgets.Facebook.View', 
         'Plugins.Widgets.Youtube.View'), ---> Permissions Modules Widgets.
         'Author' => "VrijVlinder",
         'AuthorEmail' => 'contact@vrijvlinder.com',
         'AuthorUrl' => "http://www.vrijvlinder.com"
    );
    

    // Check Permissions: class.twittermodule.php

    public function AssetTarget() {
        $Session = Gdn::Session();
        if ($Session->CheckPermission('Plugins.Widgets.Twitter.View')) {
            return 'Panel';
        }
    } 
    

    Thank you very much indeed, I hope you can modify your plugin so that more people can see it and learn more about Vanilla Forum, that's what makes free software really powerful when they are well thought out.

    Going that route you have to alter every plugin/module that you like to take influence on. That is not very flexible, a lot of extra work, it couldn't be packed into a plugin that you could publish and that are only some of the minor concerns.

    Vanilla is very powerful and when you try to change some behaviour, you will see that in most cases there are general solutions which helps plugin authors a lot.

    Instead of changing the module, add the following to a plugin:

        public function base_render_before ($sender) {
            // Check for Panel asset in order to prevent error messages.
            if (!isset($sender->Assets['Panel'])) {
                return;
            }
            // If we need the session more often in makes sense to get it into
            // a variable, otherwise we could have used it directly.
            $session = Gdn::session();
    
            // Check if the twitter module is in the Panel array.
            if (isset($sender->Assets['Panel']['TwitterModule'])) {
                // If yes, check if user has view permissions.
                if (!$session->checkPermission('Plugins.Widgets.Twitter.View')) {
                    // If not, delete it from array so that it will not be rendered.
                    unset($sender->Assets['Panel']['TwitterModule']);
                }
            }
    
            // Repeat the above if-block for the next modules...
    
        }
    

    Now basically the following will happen: all modules are added normally to the Panel, but before the Panel is rendered, you check for the view permissions and remove it from the array of modules which will be rendered afterwards.

    Far more elegant than repeating the if-block would be to loop through an array. You would have to build an array like that:

    $modules = [
        // 'PermissionIdentifier' => 'ModuleName',
        'Twitter' => 'TwitterModule',
        'Facebook' => 'FacebookModule',
        ...
    ];
    

    With such an array you could replace single if blocks with a loop:

            // Loop through all modules.
            foreach ($modules as $permission => $module) {
                // Check if the module is in the panel.
                if (isset($sender->Assets['Panel'][$module])) {
                    // If yes, check if user has view permissions.
                    if (!$session->checkPermission("Plugins.Widgets.{$permission}.View")) {
                        // If not, delete it from array so that it will not be rendered.
                        unset($sender->Assets['Panel'][$module]);
                    }
                }
            }
    

    Now strip those talkative comments:

        public function base_render_before ($sender) {
            if (!isset($sender->Assets['Panel'])) {
                return;
            }
    
            $session = Gdn::session();
    
            $modules = [
                // 'PermissionIdentifier' => 'ModuleName',
                'Twitter' => 'TwitterModule',
                'Facebook' => 'FacebookModule',
                ...
            ];
    
            foreach ($modules as $permission => $module) {
                if (isset($sender->Assets['Panel'][$module])) {
                    if (!$session->checkPermission("Plugins.Widgets.{$permission}.View")) {
                        unset($sender->Assets['Panel'][$module]);
                    }
                }
            }
        }
    

    That would make your code short, maintainable and flexible. All needed actions are done in your own plugin, so that you do not have to alter other files.

    P.S.: the code is untested and I haven't followed this discussion completely, so there might some things to fix with my code, but basically that's the approach I would take if I would like to create "per module permissions"

    terabytefrelancevrijvlinderhgtonight
  • @vrijvlinder @r_j Thanks a lot is a simple but powerful code since everything is done in the plugin for any module to implement in vanilla forum,

    Regards,

  • vrijvlindervrijvlinder Papillon-Sauvage MVP

    Yes,It makes more sense to create a separate plugin that it's only purpose is to allow or disallow views of modules based on roles and permissions.

  • It is possible that instead of writing the name controllers where I want the module to appear, I can define an array with the name controllers for each module and add the module in public function base_render_before ($sender) ?

    Thanks to the collaboration of @r_j testing two solutions, which I will share to add another feature to the plugin widgets of @vrijvlinder.

    Solution 1: default.php

    <?php
    
    if (!defined('APPLICATION')) exit();
    
    // Define the plugin:
    
    $PluginInfo['Widgets'] = array(
        'Name' => 'Widgets',
        'Description' => "This plugin adds modules/widgets you create to the panel . ",
        'RegisterPermissions' => array('Plugins.Widgets.Twitter.View'),
        'Version' => '1.1',
        'Author' => "VrijVlinder",
        'AuthorEmail' => 'contact@vrijvlinder.com',
        'AuthorUrl' => "http://www.vrijvlinder.com"
    );
    
    class Widgets_Plugin extends Gdn_Plugin{
    
        public function __construct(){
        }
    
        public function base_render_before ($sender) {
            $modules = [
                [
                    'ModuleName' => 'TwitterModule',
                    'PermissionKey' => 'Twitter',
                    'Controllers' => [
                        'activitycontroller',
                        'categoriescontroller',
                        'discussioncontroller',
                        'discussionscontroller',
                        'profilecontroller'
                    ]
                ]
                // Other modules here
            ];
    
            $session = Gdn::session();
    
            foreach ($modules as $item) {
                // Maybe another check would be needed here, but as a start that would be sufficient.
    
                if (!isset($sender->Assets['Panel'])) {
                    return;
                }
    
                if (in_array($sender->ControllerName, $item['Controllers'])) {
                    if ($session->checkPermission("Plugin.Widgets.{$item['PermissionKey']}.View")) {
                        $module = new $item['ModuleName']();
                        $sender->addModule($module);
                    }
                }
            }
        }
    
        public function Setup(){
            // Register permissions
    
            // Set initial admininstrator permissions.
            $PermissionModel->Save(array(
                'Role' => 'Administrator',
                'Plugins.Widgets.Twitter.View' => 1
            ));
        }
    
        public function OnDisable(){
            // Deregister permissions (only in 2.1+)
            if(version_compare(APPLICATION_VERSION, '2.1b1', '>=')) {
                $PermissionModel = Gdn::PermissionModel();
                $PermissionModel->Undefine(
                    array(
                        'Plugins.Widgets.Twitter.View'
                    ));
            }
        }
    

    }

  • edited September 13

    Solution 2: default.php

    <?php
    
    if (!defined('APPLICATION')) exit();
    
    // Define the plugin:
    
    $PluginInfo['Widgets'] = array(
        'Name' => 'Widgets',
        'Description' => "This plugin adds modules/widgets you create to the panel . ",
        'RegisterPermissions' => array('Plugins.Widgets.Twitter.View'),
        'Version' => '1.1',
        'Author' => "VrijVlinder",
        'AuthorEmail' => 'contact@vrijvlinder.com',
        'AuthorUrl' => "http://www.vrijvlinder.com"
    );
    
    class Widgets_Plugin extends Gdn_Plugin{
    
        public function __construct(){
        }
    
        public function base_render_before ($sender) {
            $controllers = [
                // ControllerName => Modules for Name Controllers.
                'activitycontroller' => ['Twitter'],
                'categoriescontroller' => ['Twitter'],
                'discussioncontroller' => ['Twitter'],
                'discussionscontroller' => ['Twitter'],
                'profilecontroller' => ['Twitter'],
            ];
    
            if (!array_key_exists($sender->ControllerName, $controllers)) {
                return;
            }
    
            $modules = [
                // Widgest => Class Module Name
                'Twitter' => 'TwitterModule'
            ];
    
            $session = Gdn::session();
    
            foreach ($controllers[$sender->ControllerName] as $item) {
                // do the permission check with "Plugins.Whatever.{$moduleName}.View"
                // attach module with $module = new $modules[$moduleName]();
                if ($session->CheckPermission('Plugins.Widgets.{$item}.View')) {
                    $module = new $modules['Twitter']();
                    $sender->addModule($module);
                }
            }
        }
    
        public function Setup(){
            // Register permissions
            // Set initial admininstrator permissions.
            $PermissionModel->Save(array(
                'Role' => 'Administrator',
                'Plugins.Widgets.Twitter.View' => 1
            ));
        }
    
        public function OnDisable(){
            // Deregister permissions (only in 2.1+)
            if(version_compare(APPLICATION_VERSION, '2.1b1', '>=')) {
                $PermissionModel = Gdn::PermissionModel();
                $PermissionModel->Undefine(
                    array(
                        'Plugins.Widgets.Twitter.View'
                    ));
            }
        }
    }
    

    These two solutions work correctly, which would be the best to implement,

    @vrijvlinder @R_J

    Regards,

  • vrijvlindervrijvlinder Papillon-Sauvage MVP

    It would be great to have settings where one can add the modules to the array via the dashboard.

    terabytefrelance
  • @r_j Good morning, I know that it is possible to insert the module in the head, simply placing:

    return 'Head';

    Now I would like to know how to place it before or after the head, which function would be used and again

    Regards,

  • R_JR_J Cheerleader & Troubleshooter Munich Moderator

    A module is nothing more than a small class with some conventions. One of the conventions is that it has to have a method called toString. If you add the module to an asset, that function is called automatically when this asset is rendered.

    But you do not need to add the module anywhere. You can simply use its toString method anywhere else. Look at how @AjansKartal has done it in his question.

    When you do not use the addModule method, it will not be automatically rendered anywhere.

  • @r_j ok, perfect, I understand, but I do not understand how to call the module in (before head, head, after head),

    Regards,

  • R_JR_J Cheerleader & Troubleshooter Munich Moderator

    There is a plugin called "eventi" which is helpful when trying to find the event you need to hook.

    As far as I understand, the "Head" asset is rendered in the html <head> tag. If you want to add anything in the head tag, a module is the wrong way.

    The head is rendered by module on its own and that module provides some useful functionalities, like adding css files, or adding any tag you like. Maybe you should start a new discussion since this seems to be a complete new topic and describe what you want to add the head.

  • vrijvlindervrijvlinder Papillon-Sauvage MVP
    edited September 14

    No @R_J he does not want to add modules or anything to the document head, he is referring to the asset #Head .

    You can't add it between the #Head and the #Content because that would be the #Body and as far as I know the #Body is not an asset it's a container.

    What I have done to add something there, I used jQuery to append to the #Head
    or use prepend to go before.

    If you target #Body , it will show before the #Head I believe, it was a while ago that I dealt with that.

    terabytefrelance
  • R_JR_J Cheerleader & Troubleshooter Munich Moderator

    It sounds reasonable what you say, @vrijvlinder, but when I look at the template I see this:

    <head>
        {asset name="Head"}
    </head>
    

    So the "Head" asset is in between the head tags.

    You are refering to the html structure and the div IDs

    <body id="{$BodyID}" class="{$BodyClass}">
    <div id="Frame">
        <div class="Head" id="Head">
    ...
        </div>
        <div id="Body">
            <div class="Row">
    ...
                <div class="Column PanelColumn" id="Panel">
                    {module name="MeModule"}
                    {asset name="Panel"}
                </div>
                <div class="Column ContentColumn" id="Content">{asset name="Content"}</div>
            </div>
        </div>
    

    But you are correct with "You can't add it between the #Head and the #Content". I agree that JavaScript would be the only option, if it couldn't be solved with CSS.

    Just one last thought: a custom theme would be a solution, but it isn't always an option. With a custom theme you could insert a {asset name="MyTarget"} which you can address.

    terabytefrelance
  • vrijvlindervrijvlinder Papillon-Sauvage MVP
    edited September 14

    Yes, even though the names are the same they are two different things. asset head is the head of the document .

    The page structure #Head is an asset too but in another context within html structure. I know it's confusing... Head should be called #Top but people would be angry because Headers... :angry:

    <body id="<?php echo $BodyIdentifier; ?>" class="<?php echo $this->CssClass;?>">
       <div id="Frame">
          <div id="Head"><div class="Row">
    
        <div class="Menu">
    

    To do it you could
    a.create a whole new asset called #BetweenHead
    b.add a new div to the template containing that asset
    c.use jQuery to append or prepend sections

    I suffered this truth myself as I wanted to add a module between the Menu and the Body.

    Targeting the #Body , puts it before the body above everything.

Sign In or Register to comment.