HackerOne users: Testing against this community violates our program's Terms of Service and will result in your bounty being denied.

Anyone know of an addon to ban users from a discussion?

13567

Comments

  • R_JR_J Ex-Fanboy Munich Admin

    It depends. You can do it like that, but in the end you would need the saveToSerializedColumn method in this case

    If just have created a test table and like to save test data, feel free to do it any way you want.

    Using a model is the safest way for standard tables, though.

    $discussionModel = new DiscussionModel(); // Since we want to save to discussion table...
    $discussionModel->saveToSerializedColumn(
        'Attributes', // The column name
        $sender->RequestArgs[0], // You should find out what this is
        'DiscussionBan', // This serves as a internal key so that we can identify our d
        [1,2,3,4,5]
    ); 
    
  • R_JR_J Ex-Fanboy Munich Admin

    Now that you've saved to the db, use the discussionModel to get the discussion by its id before the form is displayed (in the other part of the if clause).

    Make sure the permission check is working!

    After that get the discussion (look at the DiscussionModel to find the right method) and put a decho($discussion, 'Discussion', true); in that if clause.

  • MikeOlsonMikeOlson
    edited July 2017

    Here is how I am attempting to get the userid's for the usernames submitted but the query is breaking for some reason:

        // Check if usernames sent
        if(isset($_POST['UserNames'])){
            $UserNames = $_POST['UserNames'];
            echo $UserNames."<Br /><br />";
    
        // make array from list of usernames
    
        $UserArray = explode(',', $UserNames); //split string into array seperated by ', '
        foreach($UserArray as $value) //loop over values
        {
            echo "|".$value . "|<br/>"; //print value
    
    
            //if usernames are sent get their userids
            Gdn::sql()->
               ->select('UserID')
               ->from('GDN_User')
               ->where('UserID', $value)
               ->get();
    
                     // populate array with latest id returned
    
        }
    

    My thought is check to see if usernames were submitted, create an array of that, then loop through the array and query for each name ( I will populate to an array for each iteration of querying userid's)

  • Oh some echoing happening there just to see that I have results

  • R_JR_J Ex-Fanboy Munich Admin

    Use the UserModels getID to get the users. It makes use of caching which is an advantage

  • Ok assuming we want to use this function: public function getByUsername($Username)

    How do I call it? And I assume an array f user data will be brought back?

  • MikeOlsonMikeOlson
    edited July 2017

    I am confused can I not call the usermodel and the function getByUsername() like this?

    $UserModel = new UserModel();
    $UserModel->$sender->getByUsername($value);
    
  • R_JR_J Ex-Fanboy Munich Admin

    $something->$anything would never work.
    The dollar sign is for variables. The -> connector is used to call methods of objects.

    I guess $sender is still unclear. When Vanilla calls the method in your plugin, it passes an instance of the current class to your plugin. Since you are using DiscussionController right now, $sender is a DiscussionController object.

    The UserModel is a class with methods. So you would have to call class->method() directly.


    Alright here is some feedback to your code above:

        if(isset($_POST['UserNames'])){
            $UserNames = $_POST['UserNames'];
            echo $UserNames."<Br /><br />";
    

    Vanilla has a form class and you should use it.

    $userNames = $sender->Form->getFormValue('UserNames', false);
    if ($userNames === false) {
        return;
    }
    decho($userNames);
    
    $userArray = explode(',', $userNames);
    decho($userArray);
    

    foreach($UserArray as $value) //loop over values
        {
            echo "|".$value . "|<br/>"; //print value
            //if usernames are sent get their userids
            Gdn::sql()->
               ->select('UserID')
               ->from('GDN_User')
               ->where('UserID', $value)
               ->get();
    

    If you would use decho instead of echo, you would have seen that the result of your query is an object (type dataset).
    What you need is a user object. First you would have to create an instance of the user model and afterwards you can call its method getByUserName.

    Although normally you would write $userModel = new UserModel();, the user model is a special case and you should use $userModel = Gdn::userModel();. The reason is, as far as I understand, that the user model is only instanciated once and the class gdn has a method usermodel which returns the only instance of the user model.
    You don't need to understand that.

    You need an instance of the user model

    $userModel = Gdn::userModel();
    

    Afterwards you can loop through the $userArray

    $userIDs = [];
    foreach ($userArray as $name) {
        $user = $userModel->getByUsername($name);
        $userIDs[] = $user->UserID;
    }
    decho($userIDs);
    
  • I think I got it.

            $UserModel = new UserModel();
            $UserData = $UserModel->getByUsername($value);
    
  • Oh and of course you replied with a much better concept...

  • Something is wrong with this line:

    $userNames = $sender->Form->getFormValue('UserNames', false);
    

    Breaks code.

  • Also decho never seems to return anything for me.

  • R_JR_J Ex-Fanboy Munich Admin

    Look at class.form.php and see what you can find on getFormValue. I have written most of the code by heart and the method might be named differently

  • Yeah I looked at the Git page you linked and you are right it looks correct against that, but it breaks the code for some reason.

    I have this working correctly but it is a kludgey way of doing it.

        if(isset($_POST['UserNames'])){
            $UserNames = $_POST['UserNames'];
            //echo $UserNames;
    
        // make array from list of usernames
        $UserNameArray = explode(',', $UserNames); //split string into array seperated by ', '
    
        // create array to store userids in_array
        $discBanUsers = array();
    
        // Loop the array
        foreach($UserNameArray as $value) //loop over values
        {
        //  echo "|".$value."|<br />";
    
            $UserModel = new UserModel();
            $UserData = $UserModel->getByUsername($value);
                $count = 0;
                foreach($UserData as $field) //loop over user
                    {
                        if($count<1){
                                    echo $value." - ".$field."<br/>";
                                    array_push($discBanUsers, $field);
                        }
                        $count++;
                    }
    
    
            //if usernames are sent get their userids
    
        }
    
        //update the discussion attributes
    
        }
    
  • R_JR_J Ex-Fanboy Munich Admin

    That looks weird and I'm not sure what you are doing... O.o

    UserModel->getByUsername returns an object with information about the user. Roughly said, it contains every column of the GDN_User table as a property.

    So if you have $user = $userModel->getByUsername($name) you have an object that has a property UserID. You can access object properties like that: $user->UserID.

    There is no need to loop through the $UserData variable.
    And you should really name that variable $user since it is the result of a method in the user model which gets a user, not a users data


    And a more general advice: don't do unnecessary work in a loop, work that only needs to be done once, because it will be done again and again and again...

    Check your creation of the user model against that advice :wink:


    I've also checked it: there is no reason why $userNames = $sender->Form->getFormValue('UserNames', false); shouldn't work. Get away from accessing $_POST directly and make the above code snippet work.

    If copy and paste doesn't work, try to type it in manually. "Breaks code" isn't a good description: do you get an error message or a blank page? If it is a blank page you might change your index.php for a short time to show errors so that you get more information (if you change ini_set('display_errors', 0); to ini_set('display_errors', 1); in your index.php, don't forget to revert that change later on!)


    And if decho isn't working for you (which again is strange), try to use var_dump or print_r since both give you more information on your variable.

  • I get a blank page when I try to run it

    If I do a var_dump on just $sender it returns NULL

    here is what the error returned after setting the index display of errors says:

    Fatal error: Call to a member function getFormValue() on null in /home/vfroot/public_html/vfforums/plugins/discussionBan/views/discussionban.php on line 28

  • Hmmm I think I was thinking that it needed to be in the wrong spot.

  • OMG yeah I am an idiot. I get so caught up in thinking about doing things on the form page.

  • R_JR_J Ex-Fanboy Munich Admin

    :mrgreen:

    There should be no logic on the form page at all. Sometimes you have trivial if/else constructs there but all interactions with the model is strongly adviced to happen in the plugin.
    There is this if authenticatedPostback condition, where the most important action has to take place.

    The form, as you can see it in the GitHub repo, is finished. You might want to change the markup or the css a little bit, but that's everything which is left to do.

  • MikeOlsonMikeOlson
    edited July 2017

    Ok moving on to saving (again)...

    Ok I thinkthis is what we are looking for in the serialized comlumn save. I understand that $sender->RequestArgs[0] is the discussionid and i have taken the usernames and gotten an array of userids and then imploded and appended the brackets. I am assuming that we had to create the string for that.

    Here is the code I am using:

                // This will only be run when the user pressed the button.
                $userNames = $sender->Form->getFormValue('UserNames', false);
                if ($userNames === false) {
                    return;
                }
    
                $userArray = explode(',', $userNames);
    
                $userIDs = [];
                foreach ($userArray as $name) {
                    $userModel = new UserModel();
                    $user = $userModel->getByUsername($name);
                    $userIDs[] = $user->UserID;
                }
    
                $userIDs = "[".implode(',', $userIDs)."]"; 
    
                $discussionModel = new DiscussionModel(); // Since we want to save to discussion table...
                $discussionModel->saveToSerializedColumn(
                'Attributes', // The column name
                $sender->RequestArgs[0], // You should find out what this is
                'DiscussionBan', // This serves as a internal key so that we can identify our d
                $userIds
                ); 
    
    
                $sender->informMessage(t("Your changes have been saved."));
    
Sign In or Register to comment.