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.

List User Post Count Dashboard

It is possible to see a list of the amount of post of a user in the dashboard, to block those that have not had any activity,

Thks,

Comments

  • Solved:

    Modify: applications/dashboard/views/user/index.php

    Add:

    <?php echo anchor(t('First Visit'), $this->_OrderUrl('DateFirstVisit')); ?>
    <?php echo anchor(t('Last Visit'), $this->_OrderUrl('DateLastActive')); ?>
    <?php if ($ViewPersonalInfo) : ?>
    <?php echo t('Last IP'); ?>
    <?php endif; ?>

    //Add Column CountComments Header

    <?php echo t('Comments'); ?>

    Modify: applications/dashboard/views/user/users.php

    <?php if ($ViewPersonalInfo) : ?>

    <?php echo htmlspecialchars($User->LastIPAddress); ?>
    <?php endif; ?>

    //Add Column CountComments Content

    <?php echo ($User->CountComments); ?>
  • R_JR_J Ex-Fanboy Munich Admin

    "Modify WhateverCoreFileName" is not a solution, it is a very bad advice. Modify-hacks are gone when you update.

    Instead of this write a plugin or a custom theme and you can make the changes there.

    Ugly hacks are quicker than pretty solutions. If you prefer them, do so, but please don't propagate them.

  • @r_j ok perfect please delete my comment,

    Thks,

  • I understand that modifying the core of any software is not a good solution since the updates erase all changes, there is some way to make this change without writing a plugin, which would be the best, I am new and I want to learn, and sorry if my solution It is not appropriate to delete my comment

    Thks,

    @j_r

  • R_JR_J Ex-Fanboy Munich Admin
    1. Undo your changes.
    2. Create a new folder and file and name them like that: plugins/extendedUserInfo/class.extendeduserinfo.plugin.php
    3. Paste the following code in there:
    <?php
    
    $PluginInfo['extendedUserInfo'] = [
        'Name' => 'Extended User Info',
        'Description' => 'Show additional columns in the user info.',
        'Version' => '0.0.1',
        'MobileFriendly' => true,
        'HasLocale' => true,
        'Author' => 'R_J',
        'License' => 'MIT'
    ];
    
    class ExtendedUserInfoPlugin extends Gdn_Plugin {
        public function userController_userCell_handler($sender, $args) {
            if (!isset($args['User'])) {
                // Print header.
                echo '<th>'.t('Comment Count').'</th>';
            } else {
                // Print user info.
                echo '<td>'.$args['User']->CountComments.'</td>';
            }
        }
    }
    
    
    1. Activate your new "Extended User Info" plugin.
    2. Enjoy.

    Isn't it beautiful how easy Vanilla and clean can be extended? =)

  • phreakphreak Vanilla*APP (White Label) & Vanilla*Skins Shop MVP
    edited August 2017

    @Linc: Wouldn't that be something to be added to the core? I think the comment and discussion count are very important for a professional user handling.

    @R_J: When did this life decide to make you such an enjoyable companion? I extended the code a little to display discussion counts as well.

    <?php
    $PluginInfo['extendedUserInfoPosts'] = [
        'Name' => 'Extended User Info Posts',
        'Description' => 'Show additional columns in the user info.',
        'Version' => '0.0.2',
        'MobileFriendly' => true,
        'HasLocale' => true,
        'Author' => 'R_J',
        'License' => 'MIT'
    ];
    class ExtendedUserInfoPlugin extends Gdn_Plugin {
        public function userController_userCell_handler($sender, $args) {
            if (!isset($args['User'])) {
                // Print header.
                echo '<th>'.t('Discussion Count').'</th>';            
                echo '<th>'.t('Comment Count').'</th>';       
            } else {
                // Print user info.
                echo '<td>'.$args['User']->CountDiscussions.'</td>';            
                echo '<td>'.$args['User']->CountComments.'</td>';        
            }
        }
    }
    

    A sorting option would also be great:
    This doesn't but could something like this work? (Stolen and modified from class.usercontroller.php).

            // Sorting Discussion and Post Counts
            if (in_array($Order, array('CountDiscussions', 'CountComments'))) {
                $Order = 'u.'.$Order;
                $OrderDir = 'desc';
            } else {
                $Order = 'u.Name';
                $OrderDir = 'asc';
            }
    
    • VanillaAPP | iOS & Android App for Vanilla - White label app for Vanilla Forums OS
    • VanillaSkins | Plugins, Themes, Graphics and Custom Development for Vanilla
  • R_JR_J Ex-Fanboy Munich Admin

    No, the fields which could be used for sorting are hard coded:

    • DateInserted
    • DateFirstVisit
    • DateLastActive
    • Name

    You can make it look like it would be possible to sort the results by using that line:
    echo '<th>'.anchor(t('Comment Count'), $this->_OrderUrl('CountComments')).'</th>';
    instead of
    echo '<th>'.t('Comment Count').'</th>';

    But the logic in the UserControllers index method would compare "CountComments" with the first three fields above and, since it does not match, set the default sort order to "Name".

    There is no clean, elegant and obvious way to change that behaviour. There are no events fired where you can take influence on the process of fetching the required user information.

    It is possible to add your own sort options with a "trick", but that would be really ugly. Really, really ugly.

    At first you would need your own theme for that, so that you can override the index view.
    Instead of using your own index view as a view, you would use it like a controller and afterwards load the original index.
    Using the index view as a controller means, that you would do some logical processing here. In fact you would have to do what has been done in the index() method already, up to the point where the user data is fetched. The only difference is, that this time you would accept your sort parameter.

    That approach is a hack and not a solution because it is some kind of dangerous. It would easily be possible that you break the functionality of that method for upcoming versions.
    It also fetches data twice instead of doing it "the right way" on the first go.


    Normally I don't do that, but in this case I think it would be quite "okay", to make a change in the core file, if you know what you are doing!!!
    After an update your forum will be "broken" so that your user list would display a sortable column, but instead of acting like you would expect it, the users would always be sorted by name. But you would be the only person who will notice that behavior and you can make sure that you do not forget that you made a hack.

    Replace echo '<th>'.t('Comment Count').'</th>'; with

    echo '<th>',
        anchor(
            t('Comment Count'),
            $this->_OrderUrl('CountComments'),
            '',
            ['alt' => 'Sorting requires fugly hack']
        ),
        '</th>'
    ;
    

    Then go to the place that you've already found where the is the list of "accepted" fields and add your own like that: if (in_array($Order, array('DateInserted', 'DateFirstVisit', 'DateLastActive', 'CountComments'))) {.

    I guess I will start writing a pull request so that the order fields can be influenced, which would make an elegant solution in the future possible. I really don't like advising people how to hack the source code...

  • LincLinc Detroit Admin

    @phreak said:
    @Linc: Wouldn't that be something to be added to the core? I think the comment and discussion count are very important for a professional user handling.

    I think it would be great to have analysis of activity from your users. I don't think the general users list is where that sort of functionality belongs. If anything, I think the "Last IP" address there should be removed as well. If some day we are able to devise a grand unifying "reputation" metric for a community, I'd consider adding that to the user list. I don't think all-time post count as a standalone metric merits that level of attention.

  • R_JR_J Ex-Fanboy Munich Admin

    @Linc said:
    I don't think all-time post count as a standalone metric merits that level of attention.

    That is a good point. I have been part of a community where a lot of very active users left the field nearly at the same time. I bet some of them still would make it in the top five of all time posters...

  • phreakphreak Vanilla*APP (White Label) & Vanilla*Skins Shop MVP

    I don't think all-time post count as a standalone metric merits that level of attention.

    I didn't mean to have full fledged metrics here. Sometimes it's enough to see which new users didn't take off posting and so can be addressed by a moderator or admin with help (especially when raising a community from the ground).

    Sorting by number of posts could also reveal potential moderators (the last login date is next to the comment count to identify if this is still active). Bots and spammers can easier by detected (one click less) if you got a feeling how their activity is on your boards (starting 3 discussions but doesn't write a comment) and much more.

    This small changes already help and reveal a lot to skilled community managers. Even if it's just a number. So I think it could be helpful to many. Full-fledged community metrics is a totally other topic and some time away of getting realised. So I think it's a good idea to integrate small and helpful hacks. That is why I proposed the idea of moving this to the core.

    I actually would also like to have a traffic light system saying >Active<, >Inactive< and... >Fading away< determined on the numbers of logins in the last month for example.

    • VanillaAPP | iOS & Android App for Vanilla - White label app for Vanilla Forums OS
    • VanillaSkins | Plugins, Themes, Graphics and Custom Development for Vanilla
  • LincLinc Detroit Admin

    What we should do is create a useful metrics system, not slap the lowest common denominator stat in the user list and call it a day. I don't like half-ass "fixes" and they make for bad product design. There appears to be a very straightforward workaround if you really want to use it for now.

  • R_JR_J Ex-Fanboy Munich Admin

    @Linc said:
    I think it would be great to have analysis of activity from your users. I don't think the general users list is where that sort of functionality belongs. If anything, I think the "Last IP" address there should be removed as well. If some day we are able to devise a grand unifying "reputation" metric for a community, I'd consider adding that to the user list. I don't think all-time post count as a standalone metric merits that level of attention.

    Would it make sense to make a PR for the UserController like that?

            $this->EventArguments[Filter'] = &$Filter;
            $this->EventArguments['Order'] = &$Order;
            $this->EventArguments['OrderDir'] = &$OrderDir;
            $this->fireEvent('BeforeGetUsers');
    
            // Get user list
            $this->UserData = $UserModel->search($Filter, $Order, $OrderDir, $Limit, $Offset);
            $this->setData('Users', $this->UserData);
    

    At this point: https://github.com/vanilla/vanilla/blob/release/2.4/applications/dashboard/controllers/class.usercontroller.php#L107-L109

    I don't like "BeforeGet..." in a class other than a model. I thought about "BeforeUserList" but found that to vague

  • LincLinc Detroit Admin
    edited August 2017

    @R_J said:
    Would it make sense to make a PR for the UserController like that?

    It may.

    What would make greater sense is to set a practical goal and plan out how that hook would be used in a way that is both safe and scales adequately. The first things I notice about that hook is that it A] Bypasses the safety filters right above it and B] Is constrained by the existing functionality of UserModel's search() method, so it's threading a needle already.

    I built myself a quick-and-dirty, single-purpose "reputation list" page separate from the main user list.. That's much easier than manipulating that directory page and trying to make it work for all cases.

    The older I get and the longer I do this, the less in favor I am of sticking a hook somewhere and figuring out the details later. Start with the hard work and drill down to exactly your goal (not what's possible) and it's more likely to work out better in the end. :)

  • R_JR_J Ex-Fanboy Munich Admin

    The goal would be to allow sorting on all columns. I understand that from performance reasons it makes sense to allow sorting only on indexed columns and that's why that filter is a good way to restrict users on that.
    But not all Vanilla installations and some admins may be okay with a somehat slower response time.

    Having a table nowadays which is not sortable is somewhat disappointing. Having a table which cannot be sorted by every column but only a few, is not comprehensible for the user.
    By now there is no way to change that shortcomming. So I think there should be a way to circumvent the filter.

  • LincLinc Detroit Admin
    edited August 2017

    @R_J said:
    But not all Vanilla installations and some admins may be okay with a somehat slower response time.

    How to create bad product reputation, a 3-act play:

    1. "I don't mind if my forum is slow / my forum is small enough it won't matter!" the kind-hearted addon developer says. She builds a quick plugin and publishes it in the directory, noting in the description that maybe don't use it on large sites.
    2. Someone with a large site comes along. "I really want this functionality!" he says. Maybe they don't see the warning. Maybe they don't care! "This is critical so I'll take the performance hit," he says.
    3. A user on the large site is trying to use their new special functionaliy. "Gee, Vanilla sure is slow all the time," he says. "Maybe we should think about finding faster software that isn't so frustrating."

    I don't like admins who are OK with bad performance from Frankenstein-ing plugins.

  • R_JR_J Ex-Fanboy Munich Admin

    Thanks for obviously avoiding getting personal, you might have already noticed that I have a crush for Frankenstein-plugins :lol:
    But they show what's possible with Vanilla and I like testing around. I surely admit that using them in a production setting might not be a good idea, though.

    And using that as a base for a discussion isn't suited. You are 100% right with that.


    So what is my goal? I'm really not too sure. But I have an idea...

    What I'm missing in Vanilla is a simple way for developers to provide data in standardized, sortable data-tables/data-lists. I don't see much use for that in the frontend but on many places in the backend: users, plugins, themes, categories, new: tags, posts to moderate etc.
    Also, as written above, I think that sortable tables are a must and if a table already provides the option to sort some fields, it isn't understandable at all why not all fields should be sortable.

    So my idea, my goal would be to be able to provide an interface which behaves the same at all places. Make tables sortable by all columns and enable the user to filter it by all columns. That's what I as a user expect. And that's what I expect from a modern backend.

    Yes, that's what I think would be great.


    But back to the user list: I was asking myself what impact we are talking about, in the end. One second, two seconds, even more? And how much users are "many" users? By looking at one of your commercial forums, I decided to create a test user table with nearly 300k entries (the one that I was looking at had less than 200k)

    As far as I can tell, the only change I'm refering to is the "order by" field in this query:

    select u.*
    from GDN_User u
    where u.Deleted = '0'
    order by u.WhatEver
    limit 30;
    

    First thing I've seen that there is already a non-indexed column allowed in the filter. While ordering by an indexed column always took aroun 0.002 seconds, ordering by DateFirstVisit or CountDiscussions took from 0.16 to 0.36 second, in average 0.2 seconds. Those are no too reliable numbers, only based on some manual reloads (always including a flush tables to empty the query cache).

    So the impact on allowing a sort on each column would be around 0.2 seconds in my scenario. Even ordering them by Attributes (not possible through gui, but the hardest column I would guess) only takes around 0.5 seconds.
    That's not worth a discussion from my point of view.


    But again I'm with you that a dedicated page is better. A page to show the top posters allows taking smart rules into considerations that a simple filter will not provide.
    But my overall goal wasn't to enhance the user page, but to improve lists throughout Vanilla. If I could order plugins, categories, tags etc. I would simply expect to also be able to sort users.

    By the way: my first attempt was to create a PR which would allow sorting by any column, but I stopped when I saw that accepting field names from the GET array would require fetching the tables schema and I felt that would be too much of a change. So I made the question for the fireEvent addition, when my initial question would have been "are you interested in a PR which allows sorting by any column?"

Sign In or Register to comment.