XF 2.2 Question on extending XF\Pub\Controller\Members

AndrewSimm

Well-known member
I have extended XF\Pub\Controller\Member with the intent of adding the option for moderators to discourage users. When I try and use the same functions used in Admin/Users I am unable to get it to work. If I use the finder and save then it works. What do I need to do to get the below code to work or should I stick with the way I am doing it?

PHP:
<?php

namespace Andrew\ModeratorPanel\XF\Pub\Controller;
use XF\Mvc\FormAction;

class Member extends XFCP_Member
{
    protected function memberSaveProcess(\XF\Entity\User $user)
    {
        $visitor = \XF::visitor();

        if ($visitor->canDiscourageUsers())
        {
            $form = $this->formAction();

            $input = $this->filter([
                'option' => [
                    'is_discouraged' => 'bool'
                ]
            ]);

            $userOptions = $user->getRelationOrDefault('Option');
            $form->setupEntityInput($userOptions, $input['option']);

            /* This works but probably isn't the right way to do it

                $user_id = $user->user_id;

                $input = $this->filter([
                    'option' => [
                        'is_discouraged' => 'bool'
                    ]
                ]);

                $finder = \XF::finder('XF:UserOption');
                $userOption = $finder
                    ->where('user_id',$user_id)
                    ->fetchOne();

                $userOption->is_discouraged = $input['option']['is_discouraged'];
                $userOption->save();
            */
        }

        $response = parent::memberSaveProcess($user);
        return $response;
    }
}
 
Are you trying to create a new moderator tools option to discourage members with one click? Like the following?

1606589067764.png

If this is the case, then I think you can create a new controller action instead of overwriting memberSaveProcess.

Not the complete implementation, but as a starter:

PHP:
public function actionDiscourage(ParameterBag $params)
{
    // Ideally use a modal confirmation box here that will submit the confirmation.. Just like actionBan

    //  This is how I would set the user option
    //  Ideally checking the option first and setting the opposite to provide a Remove Discourage option
    $user = $this->assertViewableUser($params->user_id);
    $userOptions = $user->getRelationOrDefault('Option');
    $userOptions->is_discouraged = true;
    $userOptions->save();

   // Then redirect properly, or success message, etc.
}

Basically, I would use actionBan() and actionBanEdit() methods to do the same thing for discourage.
 
Last edited:
Are you trying to create a new moderator tools option to discourage members with one click? Like the following?

View attachment 240776

If this is the case, then I think you can create a new controller action instead of overwriting memberSaveProcess.

Not the complete implementation, but as a starter:

PHP:
public function actionDiscourage(ParameterBag $params)
{
    // Ideally use a modal confirmation box here that will submit the confirmation.. Just like actionBan

    //  This is how I would set the user option
    //  Ideally checking the option first and setting the opposite to provide a [ICODE]Remove Discourage[/ICODE] option
    $user = $this->assertViewableUser($params->user_id);
    $userOptions = $user->getRelationOrDefault('Option');
    $userOptions->is_discouraged = true;
    $userOptions->save();

   // Then redirect properly, or success message, etc.
}

Basically, I would use actionBan() and actionBanEdit() methods to do the same thing for discourage.
I am currently building this into member/edit, which is why I was adding to memberSaveProcess. In either case, I do like how you skip $form->setupEntityInput($userOptions, $input['option']);

My only question is what I am losing out on by skipping that and using the code below.

PHP:
    protected function memberSaveProcess(\XF\Entity\User $user)
    {
        $visitor = \XF::visitor();

        if ($visitor->canDiscourageUsers())
        {

            $input = $this->filter([
                'option' => [
                    'is_discouraged' => 'bool'
                ]
            ]);

            $userOptions = $user->getRelationOrDefault('Option');
            $userOptions->is_discouraged = $input['option']['is_discouraged'];
            $userOptions->save();

        }

        $response = parent::memberSaveProcess($user);
        return $response;
    }
 
Move $response = parent::memberSaveProcess($user); to the top, and then at the bottom: $response->basicEntitySave($user, $input['option']['is_discouraged']);?

edit: I haven't tested this yet, it's from the top of my head, so... :)
 
Move $response = parent::memberSaveProcess($user); to the top, and then at the bottom: $response->basicEntitySave($user, $input['option']['is_discouraged']);?

edit: I haven't tested this yet, it's from the top of my head, so... :)
Here is what I get when I do that.
Code:
TypeError: Argument 2 passed to XF\Mvc\FormAction::basicEntitySave() must be of the type array, boolean given, called in /var/www/public/src/addons/Andrew/ModeratorPanel/XF/Pub/Controller/Member.php on line 24 in src/XF/Mvc/FormAction.php at line 82
 
Here is what I get when I do that.
Code:
TypeError: Argument 2 passed to XF\Mvc\FormAction::basicEntitySave() must be of the type array, boolean given, called in /var/www/public/src/addons/Andrew/ModeratorPanel/XF/Pub/Controller/Member.php on line 24 in src/XF/Mvc/FormAction.php at line 82
Have your tried $response->basicEntitySave($user, $userOptions? If that doesn't work, then use your code below, however; I would still move the $response = parent::memberSaveProcess($user); to the top. I wish I had more time with this, but it's too close to supper to get into it.
I am currently building this into member/edit, which is why I was adding to memberSaveProcess. In either case, I do like how you skip $form->setupEntityInput($userOptions, $input['option']);

My only question is what I am losing out on by skipping that and using the code below.

PHP:
    protected function memberSaveProcess(\XF\Entity\User $user)
    {
        $visitor = \XF::visitor();

        if ($visitor->canDiscourageUsers())
        {

            $input = $this->filter([
                'option' => [
                    'is_discouraged' => 'bool'
                ]
            ]);

            $userOptions = $user->getRelationOrDefault('Option');
            $userOptions->is_discouraged = $input['option']['is_discouraged'];
            $userOptions->save();

        }

        $response = parent::memberSaveProcess($user);
        return $response;
    }
 
Try:
PHP:
use XF\Entity\User as UserEntity;
...
    protected function memberSaveProcess(UserEntity $user)
    {
        $formAction = parent::memberSaveProcess($user);

        $visitor = \XF::visitor();
        if ($visitor->canDiscourageUsers())
        {
            $input = $this->filter([
                'option' => [
                    'is_discouraged' => 'bool',
                ]
            ]);

            $userOptions = $user->getRelationOrDefault('Option');
            $formAction->setupEntityInput($userOptions, $input['option']); // by calling this you aren't overriding the values set by the parent call, instead you are adding an instruction to the `$formAction` object that you want to set the value of entity to something
        }

        return $formAction;
    }
 
Try:
PHP:
use XF\Entity\User as UserEntity;
...
    protected function memberSaveProcess(UserEntity $user)
    {
        $formAction = parent::memberSaveProcess($user);

        $visitor = \XF::visitor();
        if ($visitor->canDiscourageUsers())
        {
            $input = $this->filter([
                'option' => [
                    'is_discouraged' => 'bool',
                ]
            ]);

            $userOptions = $user->getRelationOrDefault('Option');
            $formAction->setupEntityInput($userOptions, $input['option']); // by calling this you aren't overriding the values set by the parent call, instead you are adding an instruction to the `$formAction` object that you want to set the value of entity to something
        }

        return $formAction;
    }
That works, perfect, thank you so much!
 
Top Bottom